Ecosystem 6.2.3
16 June 2026
This release has upgrade notes. Read them before updating — they describe behaviour changes that need your attention.
Ecosystem v6.2.3
Release Date: June 16, 2026 Tags: CRITICAL FIXES, ECO DEPOSITS, TESTNET SUPPORT, TRANSACTION PROVIDERS, ETHERSCAN V2, MONERO WITHDRAWALS
Overview
Version 6.2.3 fixes a critical bug where ECO native deposits were never credited on any testnet (BSC testnet / tBNB, ETH Sepolia, etc.). The multi-provider transaction lookup ignored the configured network and always queried mainnet, so a confirmed testnet deposit returned "0 transactions" forever and the user wallet was never credited (the funds were only visible on the block explorer / master wallet). This release makes every transaction provider network-aware, migrates the Etherscan provider to the Etherscan V2 multichain API (the legacy per-chain V1 hosts were deprecated), network-scopes the transaction cache, and adds diagnostics that make the queried network visible in the logs.
This release also hardens the Monero (XMR) stack end-to-end. It closes two fund-loss defects on the withdrawal retry path (a double-spend and a refund-after-send), makes the backend authoritative over the wallet-rpc → daemon connection (the -38 "no connection to daemon" failure that blocked all XMR sync), removes the wallet-close race that produced -13 "No wallet file", fixes the admin master-wallet balance always reading 0, and turns transiently-locked funds into a graceful hold-and-retry instead of a hard failure.
Update Instructions
Then clear any stale cached transaction lookups (per-network cache, 30 min TTL):
redis-cli --scan --pattern 'wallet:*:transactions:*' | xargs -r redis-cli delUpgrade Notes
- Set the network per chain: native and token deposit monitoring follow
{CHAIN}_NETWORK(e.g.BSC_NETWORK="testnet",ETH_NETWORK="sepolia"). This selects the RPC, explorer and chain id together — set it to the network you intend to operate, and make sure the matching{CHAIN}_{NETWORK}_RPC(_WSS)endpoints are configured. - Restart required on a network change: RPC and provider instances are cached per chain and network and are only rebuilt on process restart. Restart the backend after changing any
{CHAIN}_NETWORKvalue, then clear the cached transaction lookups as shown above. {CHAIN}_EXPLORER_API_KEY: set this to the API key only, not a full URL. A single Etherscan V2 key works across all supported EVM chains and testnets.- Monero daemon connection: the backend now pushes the daemon connection to
monero-wallet-rpcitself, so wallet-rpc no longer needs--daemon-address/--daemon-loginat launch. Make sureXMR_DAEMON_RPC_URLpoints at the intended daemon (stagenet default port38081, mainnet18081) and thatXMR_RPC_USER/XMR_RPC_PASSWORDmatch the daemon's--rpc-login. SetXMR_NETWORK(mainnet/stagenet/testnet) to the network you intend to operate, and restart the backend after changing it.
Changed
Deposit Diagnostics
- Changed provider lookups to log the resolved network and chain id, so it is obvious from the logs which network was queried. A "0 transactions" symptom can now be read directly as a wrong-network lookup rather than being indistinguishable from an empty result.
Explorer API Key Hardening
- Changed the explorer key handling to tolerate a pasted URL. Operators following the Etherscan V2 migration docs sometimes paste a whole example URL into
{CHAIN}_EXPLORER_API_KEY; the bare key is now extracted from it, and an obviously malformed value is ignored with a warning instead of breaking the request.
Monero Locked-Funds Handling
- Changed a withdrawal against still-locked funds to hold as PENDING and be retried, instead of failing outright. Monero locks received outputs for roughly ten blocks (~20 minutes) at the protocol level regardless of the platform's confirmation count, so a freshly credited deposit can show a balance with nothing unlocked. The hold has a bounded maximum wait, the unlocked-balance pre-check now accounts for the admin profit being spent from the same unlocked funds, and a "not enough unlocked money" response is treated as this transient case rather than a hard failure.
- Changed the relayed transfer to a single attempt, because it cannot safely be repeated. If the response is lost to a timeout or a reset connection, the withdrawal is marked TIMEOUT for manual review and is not refunded, matching the SOL and EVM handling. The harmless refresh warning that accompanied it was demoted to debug to cut log noise.
Fixed
Testnet deposits were never credited because providers ignored the network
- Fixed the fallback transaction providers hardcoding mainnet chain identifiers and ignoring the network they were given, so on a testnet they queried mainnet, "succeeded" with 0 transactions, and short-circuited any further fallback. Every provider now resolves its identifier from the configured chain id:
- Moralis derives the chain from the chain id (BSC mainnet 56, BSC testnet 97, ETH Sepolia 11155111) instead of a symbol-to-mainnet map.
- Covalent maps chain ids to slugs, including testnets.
- Ankr maps chain ids to slugs and fails for networks its indexer does not serve, such as BSC testnet, so the lookup falls through instead of returning mainnet data.
- NodeReal is restricted to BSC and ETH mainnet and fails for any other network.
- Fixed a provider that cannot serve the requested network reporting success with empty results. It now fails, so the lookup falls through to a provider that can serve the network, or to the deposit RPC block-scan backstop.
Etherscan V1 endpoints were deprecated
- Fixed explorer lookups still using the legacy per-chain hosts, which Etherscan deprecated in 2025 and now rejects. Lookups use the V2 multichain endpoint with a unified API key, which also restores the mainnet explorer lookups for BSC, Polygon and others that were about to break.
- Fixed custom and Blockscout chains (MO, RSK) being at risk of being routed to Etherscan — they keep using their own explorer host.
A Monero withdrawal could be broadcast twice
- Fixed a Monero withdrawal never being checked for having already been sent before it was broadcast. Two independent retry drivers could target the same transaction — a locked-funds self-requeue that bypassed the withdrawal queue's pending-to-processing guard, and the five-minute reconciliation watchdog — so once funds unlocked, both could broadcast a second on-chain transaction and send the customer's coins twice. The handler now stops if the withdrawal is already completed or already carries a transaction hash, the self-requeue is gone, and the watchdog is the single retry authority.
A Monero withdrawal could be refunded after the coins had been sent
- Fixed a late failure on one execution track being able to mark an already-broadcast withdrawal as failed and refund the customer, handing back coins that had genuinely been sent. Failure writes are now guarded, and both the fail and the refund paths re-read the withdrawal and refuse to act on one that already carries a transaction hash.
The transaction cache served the wrong network
- Fixed the cache key for a wallet's transactions carrying no network, so an empty mainnet result could be served for up to 30 minutes after switching a chain to testnet, and the reverse — masking real deposits. The active network is now part of the cache key.
Monero wallet-rpc could not reach the daemon
- Fixed all XMR deposits, withdrawals and balance reads being blocked when
monero-wallet-rpcwas started without daemon details, or with the wrong network's. Every refresh failed with-38 "no connection to daemon"even though the backend itself could reach the daemon. The backend now sets the daemon connection on wallet-rpc at startup fromXMR_DAEMON_RPC_URLandXMR_RPC_USER/XMR_RPC_PASSWORD, and self-heals by re-pointing wallet-rpc and retrying once whenever a refresh hits a daemon error — which covers wallet-rpc starting before the daemon, daemon restarts, and a wallet-rpc launched with no daemon flags at all.
A Monero wallet close raced the next operation
- Fixed a Monero withdrawal closing its wallet outside the serialised single-wallet queue, so the cleanup raced the next operation's open — producing
-13 "No wallet file"warnings and closing the wrong wallet. The close now runs while the wallet lock is held, as every other wallet operation does.
The Monero master wallet balance always read zero
- Fixed the balance being read from the wallet's stale on-disk cache — zero for a wallet created before its deposit arrived — because it was read after a fixed two-second sleep with no refresh. The admin master-wallet screen therefore showed
0while the daemon saw the funds. The balance is now refreshed, with a bounded timeout, before it is read.