This commit is contained in:
Xavier Fiechter 2024-11-29 15:24:45 +01:00
parent 37b2a1b988
commit b0b88a156a
10 changed files with 69 additions and 204 deletions

View file

@ -38,7 +38,6 @@ def bg_runner(proxy_task, task=None, loop=None, *args, **kwargs):
task = task_qs[0]
if func is None:
raise BackgroundTaskError("Function is None, can't execute!")
print("bg_runner, loop {}".format(loop))
kwargs['loop'] = loop
func(*args, **kwargs)
@ -96,8 +95,6 @@ class Tasks(object):
return _decorator
def run_task(self, task_name, loop, args=None, kwargs=None):
print("run_task loop {}".format(loop))
# task_name can be either the name of a task or a Task instance.
if isinstance(task_name, Task):
task = task_name
task_name = task.task_name

View file

@ -9,11 +9,10 @@ from finances.models import OutputStat, HistoricalPrice
import logging
logger = logging.getLogger('labelbase')
async def interact(conn, server_info, method, utxo):
try:
await conn.connect(server_info, "s", use_tor=server_info.is_onion,
disable_cert_verify=True, short_term=True)
disable_cert_verify=True, short_term=True)
txid, index = utxo.split(":")
try:
txn = await conn.RPC(method, txid, True)
@ -43,10 +42,8 @@ async def interact_addr(conn, server_info, method, addr):
hextx = await conn.RPC(method, addr)
if hextx is not None:
return hextx
else:
print("Failed to fetch transaction.")
except ElectrumErrorResponse as ex:
print(ex)
logger.error(ex)
finally:
conn.close()
@ -58,167 +55,92 @@ def is_valid_output_ref(ref):
return False
def checkup_label(label_id, loop):
def checkup_label(label_id, loop):
if label_id and loop:
try:
elem = Label.objects.get(id=label_id)
output = OutputStat.objects.filter(user=elem.labelbase.user,
type_ref_hash=elem.type_ref_hash,
network=elem.labelbase.network).last()
if not output:
output = OutputStat(user=elem.labelbase.user,
type_ref_hash=elem.type_ref_hash,
network=elem.labelbase.network, value=0)
output = OutputStat.objects.filter(
user=elem.labelbase.user,
type_ref_hash=elem.type_ref_hash,
network=elem.labelbase.network
).last()
if elem.type == "output" and is_valid_output_ref(elem.ref) and \
(output.spent is not True or output.confirmed_at_block_time == 0):
if not output:
output = OutputStat(
user=elem.labelbase.user,
type_ref_hash=elem.type_ref_hash,
network=elem.labelbase.network,
value=0,
spent=None,
confirmed_at_block_height=0,
confirmed_at_block_time=0
)
logger.debug(f"Output before processing: {output.output_metrics_dict()}")
if elem.type == "output" and is_valid_output_ref(elem.ref) and (
output.spent is not True or output.confirmed_at_block_time == 0
):
# Determine server info based on network
if elem.labelbase.is_mainnet:
electrum_hostname = elem.labelbase.user.profile.electrum_hostname or "electrum.emzy.de"
electrum_hostname = elem.labelbase.user.profile.electrum_hostname or "fulcrum.sethforprivacy.com"
electrum_ports = elem.labelbase.user.profile.electrum_ports or "s50002"
elif elem.labelbase.is_testnet:
electrum_hostname = elem.labelbase.user.profile.electrum_hostname_test or "testnet.qtornado.com"
electrum_ports = elem.labelbase.user.profile.electrum_ports_test or "s51002"
server_info = ServerInfo(electrum_hostname, electrum_hostname, ports=(electrum_ports))
else:
raise ValueError("Unknown network type.")
server_info = ServerInfo(electrum_hostname, electrum_hostname, ports=(electrum_ports))
conn = StratumClient()
utxo = elem.ref
utxo_data = {}
# Fetch transaction details
utxo_resp = loop.run_until_complete(interact(conn, server_info, "blockchain.transaction.get", utxo))
if utxo_resp:
txid, index, address, value, blocktime, utxo_data = utxo_resp
if utxo_data:
#output.next_input_attributes = utxo_data
output.set_next_input_attributes(utxo_data)
logger.debug(f"Transaction {txid} fetched with blocktime {blocktime}")
if blocktime:
HistoricalPrice.get_or_create_from_api(None, timestamp=blocktime)
output.confirmed_at_block_time = blocktime
output.confirmed_at_block_height = txn.get('height', 0)
# Fetch all unspents for the address
try:
unspents = loop.run_until_complete(interact_addr(conn, server_info, "blockchain.address.listunspent", address))
except:
conn.last_error = None # reset error if needed
conn.last_error = None
unspents = loop.run_until_complete(interact_addr(conn, server_info, "blockchain.scripthash.listunspent", address))
utxo_value = 0
utxo_height = 0
logger.debug(f"Unspents for address {address}: {unspents}")
if unspents:
for unspent in unspents:
if unspent.get('tx_hash') == txid and \
unspent.get('tx_pos') == int(index) and \
unspent.get('height') > 0 and \
unspent.get('value') > 0: # Output is confirmed, but not spent yet
output.spent = False
utxo_value = unspent.get('value')
utxo_height = unspent.get('height')
utxo_found = False
for unspent in unspents:
if unspent.get('tx_hash') == txid and unspent.get('tx_pos') == int(index):
output.spent = False
output.value = unspent.get('value', 0)
output.confirmed_at_block_height = unspent.get('height', 0)
utxo_found = True
break
if not utxo_found:
output.spent = True
logger.warning(f"UTXO {txid}:{index} not found in unspent outputs.")
else:
logger.error(f"Failed to fetch transaction details for {utxo}")
output.network = elem.labelbase.network
if utxo_height:
output.confirmed_at_block_height = utxo_height
if blocktime:
output.confirmed_at_block_time = blocktime
if utxo_value:
output.value = utxo_value
elif value:
output.value = value
break
#
elif conn.last_error:
output.last_error = conn.last_error
else:
output.last_error = {}
logger.warning(f"Unknown error occurred for UTXO {utxo}")
output.last_error = {"error": "Unknown issue"}
logger.debug(f"Output after processing (before save): {output.output_metrics_dict()}")
output.save()
try:
conn.close()
except:
pass
output.refresh_from_db()
logger.debug(f"Output after saving: {output.output_metrics_dict()}")
conn.close()
except Exception as e:
logger.error("Error processing label {}: {}".format(label_id, e))
logger.error(f"Error processing label {label_id}: {e}")
else:
if not label_id:
logger.error("Can't get label_id! {}".format(label_id))
if not loop:
logger.error("Can't get loop!")
def checkup_label_buggy(label_id, loop):
if label_id and loop:
elem = Label.objects.get(id=label_id)
output = OutputStat.objects.filter(user=elem.labelbase.user,
type_ref_hash=elem.type_ref_hash,
network=elem.labelbase.network).last()
if not output:
output = OutputStat(user=elem.labelbase.user,
type_ref_hash=elem.type_ref_hash,
network=elem.labelbase.network, value=0)
#print("Using OutputStat id {}".format(output))
#print("elem.type {} {} {} {}".format(elem.type, is_valid_output_ref(elem.ref), elem.ref, output.spent))
if elem.type == "output" and is_valid_output_ref(elem.ref) and \
(output.spent is not True or output.confirmed_at_block_time == 0):
electrum_hostname = elem.labelbase.user.profile.electrum_hostname
if not electrum_hostname:
electrum_hostname = "electrum.emzy.de"
electrum_ports = elem.labelbase.user.profile.electrum_ports
if not electrum_ports:
electrum_ports = "s50002"
server_info = ServerInfo(electrum_hostname, electrum_hostname, ports=((electrum_ports)))
conn = StratumClient()
assert elem.type_ref_hash
utxo = elem.ref
tx_hash, tx_pos = elem.ref.split(":")
utxo_resp = loop.run_until_complete(interact(conn, server_info, "blockchain.transaction.get", utxo))
blocktime = 0
if utxo_resp:
txid, index, address, value, blocktime = utxo_resp
if blocktime:
#print("Found blocktime {} for label id {}.".format(blocktime, label_id))
HistoricalPrice.get_or_create_from_api(None, timestamp=blocktime)
try:
unspents = loop.run_until_complete(interact_addr(conn, server_info, "blockchain.address.listunspent", address))
except:
conn.last_error = None # reset error if needed
unspents = loop.run_until_complete(interact_addr(conn, server_info, "blockchain.scripthash.listunspent", address))
unspent_utxo = False
utxo_value = 0
utxo_height = 0
if unspents:
for unspent in unspents:
if unspent.get('tx_hash') == tx_hash and \
unspent.get('tx_pos') == int(tx_pos) and \
unspent.get('height') > 0 and \
unspent.get('value') > 0:
unspent_utxo = True
utxo_value = unspent.get('value')
utxo_height = unspent.get('height')
break
if output:
output.network = elem.labelbase.network
if utxo_height:
output.confirmed_at_block_height = utxo_height
if blocktime:
output.confirmed_at_block_time = blocktime
if utxo_value:
output.value = utxo_value
elif value: # take value from TX
output.value = value
if unspent_utxo:
output.spent = False
else:
output.spent = True
output.last_error = {}
elif conn.last_error:
# Damn...
output.last_error = conn.last_error
else:
output.last_error = {}
output.save()
try:
conn.close()
except:
pass
else:
if not label_id:
logger.error("Can't get label_id! {}".format(label_id))
if not loop:
logger.error("Can't get loop!")
logger.error(f"Invalid input: label_id={label_id}, loop={loop}")

View file

@ -11,9 +11,6 @@ from jsonfield import JSONField
import json
from django.contrib.auth.models import User
from shared.encryption import get_fernet_key, cipher_suite
import logging
logger = logging.getLogger('labelbase')
@ -54,9 +51,11 @@ class OutputStat(models.Model):
self.next_enc_input_attrs = encrypted_data.decode('utf-8')
def next_input_attributes(self):
encrypted_data = self.next_enc_input_attrs.encode('utf-8')
decrypted_data = cipher_suite.decrypt(encrypted_data)
return json.loads(decrypted_data.decode('utf-8'))
if self.next_enc_input_attrs:
encrypted_data = self.next_enc_input_attrs.encode('utf-8')
decrypted_data = cipher_suite.decrypt(encrypted_data)
return json.loads(decrypted_data.decode('utf-8'))
return json.loads("{}")
MAINNET = 'mainnet'
TESTNET = 'testnet'
@ -207,13 +206,11 @@ class OutputStat(models.Model):
network=network).last()
if cached_data:
print("found cached data {} for type_ref_hash {}, created {}".format(cached_data, type_ref_hash, created))
return cached_data, False
def get_value_and_spent(txid, vout):
mempool_api = MempoolAPI()
res0 = mempool_api.get_transaction(txid)
print("res0 {}".format(res0))
vouts = res0.get("vout", [])
if vouts:
value = vouts[int(vout)].get("value", 0)
@ -291,17 +288,18 @@ class HistoricalPrice(models.Model):
mempool_endpoint = user.profile.mempool_endpoint
else:
mempool_endpoint = "https://mempool.space"
url = f"{mempool_endpoints}/api/v1/historical-price?timestamp={timestamp}"
url = f"{mempool_endpoint}/api/v1/historical-price?timestamp={timestamp}"
response = requests.get(url)
api_response = response.json()
except Exception as ex:
logger.error(ex, exc_info=True)
try:
from threadlocals.threadlocals import get_current_request
request = get_current_request()
if request:
messages.error(request, "<strong>Connection Error:</strong> Could not connect to Mempool to retrieve historical price.")
except Exception as ex2:
logger.error(ex, exc_info=True)
logger.error(ex2, exc_info=True)
return None, None
try:
obj, created = cls.objects.get_or_create(timestamp=timestamp, defaults={

View file

@ -833,7 +833,6 @@ class LabelUpdateView(UpdateView):
return "label_derive_addresses.html"
elif action == 'output-details':
return "label_edit_output_details.html"
return "label_edit_update.html"
def get_context_data(self, **kwargs):

View file

@ -1,8 +1,5 @@
from django.contrib.auth.models import User
from messages_extends.models import Message
from messages_extends import constants
"""
DEBUG = 10
@ -40,14 +37,3 @@ def notify_error_persistent(username, message):
def notify_error(username, message):
notify_user(username, message, level=constants.ERROR)
"""
{% for message in messages %}
<div class="alert {% if message.tags %} alert-{{ message.tags }} {% endif %}">
{# close-href is used because href is used by bootstrap to closing other divs #}
<a class="close" data-dismiss="alert"{% if message.pk %} close-href="{% url message_mark_read message.pk %}"{% endif %}>×</a>
{{ message }}
</div>
{% endfor %}
"""

View file

@ -255,7 +255,7 @@
<li class="nav-item ">
<a class="nav-link" href="{% url "donate" %}"><span data-feather="heart" class="align-text-bottom"></span> Donate</a>
<li>
<li class="nav-item ">
<a class="nav-link" href="https://labelbase.space/newsletter/"><span data-feather="mail" class="align-text-bottom"></span> Newsletter</a>
<li>
@ -608,13 +608,6 @@
loadChat(false);
{% endif %}
});
</script>
</body>
</html>

View file

@ -22,6 +22,7 @@
<p class="fs-6 text-muted">
<strong>Mainnet: </strong>
<ul>
<li>fulcrum.sethforprivacy.com / s50002</li>
<li>electrum.emzy.de / s50002</li>
<li>electrum.blockstream.info / s50002</li>
</ul>

View file

@ -2,7 +2,6 @@
{% load bootstrap %}
{% load i18n %}
{% block label_edit_content %}
<!--
{{  res_tx|safe }}
@ -29,8 +28,5 @@
</pre>
{% endif %}
{% endif %}
{% endblock %}

View file

@ -188,8 +188,6 @@ function getPopoverContent(index) {
}
*/
var content = '<div class="popover-content">';
content += '<div><strong>Label:</strong> ' + window.records[index].label + '</div>';
content += '<div><strong>Output:</strong> ' + window.records[index].ref + '</div>';
@ -204,9 +202,6 @@ function getPopoverContent(index) {
content += '<div><strong>Performance:</strong> ' + window.records[index].performance + '%</div>';
content += '<div><strong>Spent:</strong> ' + window.records[index].spent + '</div>';
content += '<div><strong>Spendable:</strong> ' + window.records[index].spendable + '</div>';
content += '</div>';
return content;
}
@ -294,25 +289,9 @@ NO LABELBASE
<script>
{% addtoblock "js" %}
$(document).ready(function () {
$('[data-toggle="popover"]').popover()
});
{% endaddtoblock %}
</script>
{% endblock %}

View file

@ -49,13 +49,7 @@
<p style="padding-top: 2.1em;">
{% url 'registration' as reg_url %}
<strong>First time here?</strong> Let's <a href="{{ reg_url }}">get started</a>.
</p>
<p style="padding-top: .1em;">
<strong>Having problems logging in?</strong> If your credentials are not functioning as expected, it is possible that your account is hosted our <a href="https://legacy.labelbase.space/">legacy system</a>.
</p>
{% endif %}
{% block 'backup_tokens' %}