Fix Monero sync detection for remote nodes and apply code formatting

- Change Monero is_synced() to simple height > 0 check for remote nodes
- Update get_sync_status() to return appropriate status for remote node setup
- Fixes false "syncing" status when using upstream Monero nodes
- Apply black code formatting for consistency

This preserves the sync status detection functionality while fixing
issues with remote Monero node deployments.
This commit is contained in:
Russell Ballestrini 2025-09-23 15:29:12 -04:00
parent fbc0b55dc3
commit 45dca33b65
3 changed files with 34 additions and 35 deletions

View file

@ -98,51 +98,42 @@ class MoneroClient:
def is_synced(self) -> bool:
"""
Check if the Monero wallet is fully synced.
Returns True if wallet height matches daemon height.
Check if the Monero wallet is ready for payment processing.
For remote nodes, checks if wallet RPC is responsive and can get height.
"""
try:
# Get wallet height
# For wallet-rpc with remote nodes, if we can get height > 0,
# the wallet is connected to a synced daemon and ready
wallet_height = self.get_height()
# Get daemon height via wallet RPC
daemon_info = self._call("get_info")
daemon_height = int(daemon_info.get("height", 0))
# Consider synced if within 2 blocks (to handle timing issues)
return abs(wallet_height - daemon_height) <= 2
return wallet_height > 0
except Exception:
# If any RPC call fails, consider not synced
# If RPC call fails, wallet is not ready
return False
def get_sync_status(self) -> dict:
"""
Get detailed sync status information.
Returns dict with wallet_height, daemon_height, synced status.
For remote nodes, returns wallet readiness status.
"""
try:
wallet_height = self.get_height()
daemon_info = self._call("get_info")
daemon_height = int(daemon_info.get("height", 0))
synced = abs(wallet_height - daemon_height) <= 2
sync_percentage = min(100.0, (wallet_height / max(daemon_height, 1)) * 100)
synced = wallet_height > 0
return {
"wallet_height": wallet_height,
"daemon_height": daemon_height,
"synced": synced,
"sync_percentage": sync_percentage,
"blocks_behind": max(0, daemon_height - wallet_height)
"sync_percentage": 100.0 if synced else 0.0,
"remote_node": True,
"ready": synced,
}
except Exception as e:
return {
"wallet_height": 0,
"daemon_height": 0,
"synced": False,
"sync_percentage": 0.0,
"blocks_behind": 0,
"error": str(e)
"remote_node": True,
"ready": False,
"error": str(e),
}
@ -208,7 +199,7 @@ class MockMoneroClient:
"daemon_height": height,
"synced": True,
"sync_percentage": 100.0,
"blocks_behind": 0
"blocks_behind": 0,
}
@ -348,15 +339,15 @@ class DogecoinClient:
"""
try:
blockchain_info = self.getblockchaininfo()
blocks = int(blockchain_info.get("blocks", 0))
headers = int(blockchain_info.get("headers", 0))
progress = float(blockchain_info.get("verificationprogress", 0))
synced = progress >= 0.999
sync_percentage = progress * 100
blocks_behind = max(0, headers - blocks)
return {
"blocks": blocks,
"headers": headers,
@ -365,7 +356,7 @@ class DogecoinClient:
"blocks_behind": blocks_behind,
"verification_progress": progress,
"pruned": blockchain_info.get("pruned", False),
"size_on_disk": blockchain_info.get("size_on_disk", 0)
"size_on_disk": blockchain_info.get("size_on_disk", 0),
}
except Exception as e:
return {
@ -377,7 +368,7 @@ class DogecoinClient:
"verification_progress": 0.0,
"pruned": False,
"size_on_disk": 0,
"error": str(e)
"error": str(e),
}
@ -460,7 +451,7 @@ class MockDogecoinClient:
"headers": 5500000,
"verificationprogress": 1.0,
"pruned": False,
"size_on_disk": 2000000000 # 2GB
"size_on_disk": 2000000000, # 2GB
}
def is_synced(self) -> bool:
@ -477,7 +468,7 @@ class MockDogecoinClient:
"blocks_behind": 0,
"verification_progress": 1.0,
"pruned": False,
"size_on_disk": 2000000000
"size_on_disk": 2000000000,
}

View file

@ -652,7 +652,9 @@ def process_payment(
logger.info(
f"Funds unlocked ({unlocked_balance} atomic units) - attempting sweep for payment {crypto_payment.id}"
)
sweep_success = auto_sweep_payment(client, crypto_payment, env_request.dbsession)
sweep_success = auto_sweep_payment(
client, crypto_payment, env_request.dbsession
)
if sweep_success and crypto_payment.is_swept:
logger.info(f"Payment {crypto_payment.id} swept successfully")
else:

View file

@ -773,7 +773,11 @@ class AutoSweepTests(unittest.TestCase):
# First call - get_balance
{"unlocked_balance": 1000000000000}, # 1 XMR
# Second call - sweep_all
{"tx_hash": "sweep_tx_123", "amount_list": [1000000000000], "fee": 5000000000},
{
"tx_hash": "sweep_tx_123",
"amount_list": [1000000000000],
"fee": 5000000000,
},
]
# Create a mock dbsession
@ -1015,7 +1019,9 @@ class DogecoinWatcherUnitTests(unittest.TestCase):
# Verify that swept_tx_hash was set
self.assertEqual(payment.swept_tx_hash, "doge_sweep_tx_456")
self.assertEqual(payment.swept_amount, 990000000) # 9.9 DOGE in koinu (10 - 0.1 fee buffer)
self.assertEqual(
payment.swept_amount, 990000000
) # 9.9 DOGE in koinu (10 - 0.1 fee buffer)
self.assertIsNotNone(payment.swept_timestamp)
# Verify that the payment was added to the database session