bal-electrum-plugin/willexecutors.py
bitcoinafterlife b23eee0e44 stauts fix'd
2025-04-16 07:03:31 -04:00

204 lines
7.4 KiB
Python

import json
from datetime import datetime
from functools import partial
from aiohttp import ClientResponse
from electrum.network import Network
from electrum import constants
from electrum.logging import get_logger
from electrum.gui.qt.util import WaitingDialog
from electrum.i18n import _
from .balqt.baldialog import BalWaitingDialog
from . import util as Util
DEFAULT_TIMEOUT = 5
_logger = get_logger(__name__)
def get_willexecutors(bal_plugin, update = False,bal_window=False,force=False,task=True):
willexecutors = bal_plugin.config_get(bal_plugin.WILLEXECUTORS)
for w in willexecutors:
initialize_willexecutor(willexecutors[w],w)
bal=bal_plugin.DEFAULT_SETTINGS[bal_plugin.WILLEXECUTORS]
for bal_url,bal_executor in bal.items():
if not bal_url in willexecutors:
_logger.debug("replace bal")
willexecutors[bal_url]=bal_executor
if update:
found = False
for url,we in willexecutors.items():
if is_selected(we):
found = True
if found or force:
if bal_plugin.config_get(bal_plugin.PING_WILLEXECUTORS) or force:
ping_willexecutors = True
if bal_plugin.config_get(bal_plugin.ASK_PING_WILLEXECUTORS) and not force:
ping_willexecutors = bal_window.window.question(_("Contact willexecutors servers to update payment informations?"))
if ping_willexecutors:
if task:
bal_window.ping_willexecutors(willexecutors)
else:
bal_window.ping_willexecutors_task(willexecutors)
return willexecutors
def is_selected(willexecutor,value=None):
if not willexecutor:
return False
if not value is None:
willexecutor['selected']=value
try:
return willexecutor['selected']
except:
willexecutor['selected']=False
return False
def get_willexecutor_transactions(will, force=False):
willexecutors ={}
for wid,willitem in will.items():
if willitem.get_status('VALID'):
if willitem.get_status('COMPLETE'):
if not willitem.get_status('PUSHED') or force:
if willexecutor := willitem.we:
url=willexecutor['url']
if willexecutor and is_selected(willexecutor):
if not url in willexecutors:
willexecutor['txs']=""
willexecutor['txsids']=[]
willexecutor['broadcast_status']= _("Waiting...")
willexecutors[url]=willexecutor
willexecutors[url]['txs']+=str(willitem.tx)+"\n"
willexecutors[url]['txsids'].append(wid)
return willexecutors
def only_selected_list(willexecutors):
out = {}
for url,v in willexectors.items():
if is_selected(willexecutor):
out[url]=v
def push_transactions_to_willexecutors(will):
willexecutors = get_transactions_to_be_pushed()
for url in willexecutors:
willexecutor = willexecutors[url]
if is_selected(willexecutor):
if 'txs' in willexecutor:
push_transactions_to_willexecutor(willexecutors[url]['txs'],url)
def send_request(method, url, data=None, *, timeout=10):
network = Network.get_instance()
if not network:
raise ErrorConnectingServer('You are offline.')
_logger.debug(f'<-- {method} {url} {data}')
headers = {}
headers['user-agent'] = 'BalPlugin'
headers['Content-Type']='text/plain'
try:
if method == 'get':
response = Network.send_http_on_proxy(method, url,
params=data,
headers=headers,
on_finish=handle_response,
timeout=timeout)
elif method == 'post':
response = Network.send_http_on_proxy(method, url,
body=data,
headers=headers,
on_finish=handle_response,
timeout=timeout)
else:
raise Exception(f"unexpected {method=!r}")
except Exception as e:
_logger.error(f"exception sending request {e}")
raise e
else:
_logger.debug(f'--> {response}')
return response
async def handle_response(resp:ClientResponse):
r=await resp.text()
try:
r=json.loads(r)
r['status'] = resp.status
r['selected']=is_selected(willexecutor)
r['url']=url
except:
pass
return r
class AlreadyPresentException(Exception):
pass
def push_transactions_to_willexecutor(willexecutor):
out=True
try:
_logger.debug(f"willexecutor['txs']")
if w:=send_request('post', willexecutor['url']+"/"+constants.net.NET_NAME+"/pushtxs", data=willexecutor['txs'].encode('ascii')):
willexecutor['broadcast_status'] = _("Success")
_logger.debug(f"pushed: {w}")
if w !='thx':
_logger.debug(f"error: {w}")
raise Exception(w)
else:
raise Exception("empty reply from:{willexecutor['url']}")
except Exception as e:
_logger.debug(f"error:{e}")
if str(e) == "already present":
raise AlreadyPresentException()
out=False
willexecutor['broadcast_status'] = _("Failed")
return out
def ping_servers(willexecutors):
for url,we in willexecutors.items():
get_info_task(url,we)
def get_info_task(url,willexecutor):
w=None
try:
_logger.info("GETINFO_WILLEXECUTOR")
_logger.debug(url)
w = send_request('get',url+"/"+constants.net.NET_NAME+"/info")
willexecutor['url']=url
willexecutor['status'] = w['status']
willexecutor['base_fee'] = w['base_fee']
willexecutor['address'] = w['address']
if not willexecutor['info']:
willexecutor['info'] = w['info']
_logger.debug(f"response_data {w['address']}")
except Exception as e:
_logger.error(f"error {e} contacting {url}: {w}")
willexecutor['status']="KO"
willexecutor['last_update'] = datetime.now().timestamp()
return willexecutor
def initialize_willexecutor(willexecutor,url,status=None,selected=None):
willexecutor['url']=url
if not status is None:
willexecutor['status'] = status
willexecutor['selected'] = is_selected(willexecutor,selected)
def get_willexecutors_list_from_json(bal_plugin):
try:
with open("willexecutors.json") as f:
willexecutors = json.load(f)
for w in willexecutors:
willexecutor=willexecutors[w]
willexecutors.initialize_willexecutor(willexecutor,w,'New',False)
bal_plugin.config.set_key(bal_plugin.WILLEXECUTORS,willexecutors,save=True)
return h
except Exception as e:
_logger.error(f"errore aprendo willexecutors.json: {e}")
return {}
def check_transaction(txid,url):
_logger.debug(f"{url}:{txid}")
try:
w = send_request('post',url+"/searchtx",data=txid.encode('ascii'))
return w
except Exception as e:
_logger.error(f"error contacting {url} for checking txs {e}")
raise e