diff --git a/tools/usdt-bridge/src/main.rs b/tools/usdt-bridge/src/main.rs index 83f1e705..0b30ff7f 100644 --- a/tools/usdt-bridge/src/main.rs +++ b/tools/usdt-bridge/src/main.rs @@ -1085,7 +1085,25 @@ async fn process_deposit_block( .map(Into::<[u8; 32]>::into) .map_err(|e| format!("bad custody_multisig_pezkuwi config: {e:?}")); match owner_bytes { - Ok(owner_bytes) => Some(execute_wusdt_auto_payout(client, keypair, config.pezkuwi_wusdt_asset_id, owner_bytes, dest_bytes, net_amount).await), + Ok(owner_bytes) => { + let first = execute_wusdt_auto_payout(client, keypair, config.pezkuwi_wusdt_asset_id, owner_bytes, dest_bytes, net_amount).await; + // A cached signing client's WS connection can die silently between + // uses (same failure class as the listener's live subscription - + // see LIVE_SUBSCRIPTION_STALL_TIMEOUT's doc) with no error until the + // next real use - retry once against a genuinely fresh connection + // before falling back to manual review, rather than requiring a + // full process restart to recover auto-pay. + let result = if first.is_err() { + warn!(" ⚠️ Auto-pay attempt failed ({:?}) - retrying once with a fresh connection", first.as_ref().err()); + match PezkuwiSigningClient::::from_insecure_url(&config.pezkuwi_rpc).await { + Ok(fresh_client) => execute_wusdt_auto_payout(&fresh_client, keypair, config.pezkuwi_wusdt_asset_id, owner_bytes, dest_bytes, net_amount).await, + Err(_) => first, + } + } else { + first + }; + Some(result) + } Err(reason) => { warn!(" ⚠️ Auto-pay skipped: {reason}"); None } } } @@ -1457,7 +1475,22 @@ async fn process_withdrawal_block( .map(Into::<[u8; 32]>::into) .map_err(|e| format!("bad custody_multisig_polkadot config: {e:?}")); match owner_bytes { - Ok(owner_bytes) => Some(execute_usdt_auto_payout(client, keypair, config.polkadot_usdt_asset_id, owner_bytes, dest_bytes, net_amount).await), + Ok(owner_bytes) => { + let first = execute_usdt_auto_payout(client, keypair, config.polkadot_usdt_asset_id, owner_bytes, dest_bytes, net_amount).await; + // Same reconnect-and-retry as the wUSDT leg - see its comment. This + // exact failure ("Connection reset by peer... restart required") + // was observed live twice on this leg before this fix. + let result = if first.is_err() { + warn!(" ⚠️ Auto-pay attempt failed ({:?}) - retrying once with a fresh connection", first.as_ref().err()); + match OnlineClient::::from_url(&config.polkadot_rpc).await { + Ok(fresh_client) => execute_usdt_auto_payout(&fresh_client, keypair, config.polkadot_usdt_asset_id, owner_bytes, dest_bytes, net_amount).await, + Err(_) => first, + } + } else { + first + }; + Some(result) + } Err(reason) => { warn!(" ⚠️ Auto-pay skipped: {reason}"); None } } }