Monero Blockchain
Private XMR custody for the Ecosystem addon — why Monero needs a long-running wallet RPC and a fully synced daemon of your own, how its one-wallet-file-per-user model differs from every other chain the platform custodies, and why every backend process takes turns on that one wallet RPC.
The Monero Blockchain addon adds XMR to Ecosystem's custody set: per-user deposit addresses, confirmation-aware deposit crediting, and signed withdrawals, all through your own Monero infrastructure.
That last clause is the whole story. Every other chain Ecosystem supports reads
from somebody else's node — an RPC provider, an explorer API, a public cluster.
Monero has no such thing, by design. There is no public API that will tell you
which transactions belong to an address, because on Monero nobody can compute
that without the wallet's view key. So the addon does not talk to a service. It
talks to your monerod and your monero-wallet-rpc, both of which you
install, run and keep alive yourself.
Budget for that before you buy. A synced Monero node is a permanent ~250 GB of SSD and two daemons that must be running whenever the platform is.
What it requires
| Requirement | Why | If it is missing |
|---|---|---|
| Bicrypto core — v6.7.9 or later for Monero 6.2.1 | Everything. The addon also loads shared helpers that only exist from that core release | The extension cannot be enabled. On a core older than that, the addon's code does not load and the diagnostics report it as not installed — see Troubleshooting |
| Ecosystem addon — v6.5.3 or later for Monero 6.2.1 | Wallets, deposits, withdrawals, markets — Monero is a chain inside Ecosystem, not a standalone product. From v6.5.3 its withdrawal queue also refuses, on its own, to refund a withdrawal whose relay was claimed | Nothing to plug into |
| A licence for this product | Product ID 54578959. Activation writes lic/54578959.lic |
The status toggle refuses with 403 |
monerod, fully synchronised |
Wallet sync (through the wallet RPC), fee estimation, confirmations, broadcasting | Down: no deposit is detected; a new withdrawal is refused on the form before anything is debited ("Failed to withdraw: Failed to estimate Monero fee: …"); a withdrawal already queued fails and is refunded. Reachable by the wallet RPC but not by the backend: deposits keep crediting, and withdrawals fail as above. Still synchronising: deposits appear only as it catches up, and a withdrawal that reaches its relay ends in manual review |
monero-wallet-rpc, started with --wallet-dir |
Wallet creation, balances, transfers — every operation | Down: no deposit is detected, and new withdrawals are still accepted and debited — the request needs only the daemon — then each fails with "Wallet RPC is not responding. Please ensure monero-wallet-rpc is running on …" and is refunded. Down when the service starts in a process: the chain is also marked inactive there, and wallet creation, balance reads and history refuse until it answers |
| Redis — the platform's own | The session lock every backend process takes before it touches the wallet RPC | No wallet-rpc session starts: deposits are not checked and withdrawals wait |
| The Ecosystem vault, unlocked | The wallet mnemonic is encrypted before it is stored | Address generation fails |
Note what is not in that list: ScyllaDB. Ecosystem needs it for order books and candles, so you will have it, but Monero deposits, balances and withdrawals do not touch it.
Monero is not like the other chains
Read this section before you read anything else. Almost every operational surprise on this chain traces back to one of these four facts.
There is one wallet file per user wallet. On EVM chains a single master
wallet's HD material derives an unlimited number of addresses and one provider
watches them all. Monero has no such derivation here. When a user first opens
the XMR deposit page, the platform calls create_wallet on monero-wallet-rpc
with the ECO wallet's UUID as the filename, re-opens the file to confirm what it
read, and stores the resulting address and mnemonic. The master wallet is a
wallet file too, named master_wallet. Your --wallet-dir therefore grows by
one wallet file per customer who has ever looked at the XMR deposit page.
Subaddresses are not used. Every wallet operates on account_index: 0 and
its primary address. There is no create_address call anywhere in the product.
The address a user is shown is a standard mainnet address beginning with 4.
Every backend process takes turns on one wallet RPC. monero-wallet-rpc can
have only one wallet open at a time, and it answers every wallet call from
whichever wallet is open. The default deployment runs two backend processes that
both use it — the web process (live deposit checks, new withdrawals as they are
requested, admin balance reads) and the cron process (the background deposit
scanner, the withdrawal watchdog with every retry and any withdrawal still
waiting after three minutes, the dormant-wallet
refresh). So each operation is one session — open, prove,
work, close — under a cluster-wide Redis lock, and the sessions queue. On top of
the lock, every session proves the wallet it is talking to: the address
get_address returns must be exactly the one on record, before every read and
every spend, and every incoming transfer must be paid to that wallet. A session
that finds anything else refuses instead of crediting or sending. This is the
single biggest difference in feel — Monero operations are measured in seconds
to minutes, not milliseconds, and they queue. It also means two rules for you:
restart the web and cron processes together, and never drive the live wallet
RPC by hand. Deposits and confirmations has the details.
The daemon is your explorer. Confirmation counts, fee estimates and sync
state all come from monerod, and so does every broadcast. A daemon that is down
or still synchronising does not degrade the chain gracefully. Deposits silently
stop arriving. A new withdrawal needs the daemon at the moment the customer
submits it — the request prices itself with a fee estimate first — so with the
daemon down the form refuses and nothing is debited. And a daemon that answers
but reports synchronized: false refuses to broadcast, which leaves a
withdrawal that got as far as its relay in manual review rather than failed —
see Withdrawals.
XMR is the only asset
Monero has no token layer, so there is exactly one Ecosystem token row on this
chain and its contractType is NATIVE. You create it through the token
import flow with a blank contract, not the deploy flow — see
Tokens and markets.
There are no custodial wallets on Monero either. Custodial contracts exist only for EVM tokens that cannot pay their own gas; XMR deposits always go to the user's own wallet address regardless of how the token row is flagged.
The token row's network label is checked against XMR_NETWORK (mainnet
when unset), as on every other chain: a row labelled for another network, or not
labelled at all, is not offered, and XMR disappears from the deposit currency
list. Give the row the network XMR_NETWORK names — mainnet on mainnet — and
spell it identically in both places, in lowercase: this comparison is exact,
letter for letter and case for case. XMR_NETWORK="MAINNET" still validates
withdrawals as mainnet, but it no longer matches a row labelled mainnet. The
same mismatch can also happen through the daemon — see
Configuring the RPC connection.
Three gates, checked in order
Activation is not a single switch. When the Monero service starts in a process, it evaluates:
- Licence.
lic/54578959.licmust be a licence this server can read — it has to decode here, not merely exist. The file is read each time this gate runs. - Database row.
ecosystem_blockchainwhereproductId = 54578959must havestatus = true. It shipsfalse. - Wallet RPC reachability. A
get_versioncall againstXMR_WALLET_RPC_URL. If it throws, the chain is marked inactive, and wallet creation, balance reads and transaction history refuse with "Chain 'Monero' is not active."
While the chain is inactive, every use of the service runs the gates again, so operations resume once the fault is fixed.
The gates guard less than "inactive" suggests. Wallet creation, balance and history reads, background scans and pool-backing sends check them. Live deposit checks do not, and neither do withdrawals — not when the request is made, and not when the handler sends it.
Switching the chain off is not a stop button. The status toggle writes the
ecosystem_blockchain row and nothing else. A process whose Monero service is
already active never reads that row again until it restarts, and because no part
of a withdrawal reads it, XMR withdrawals are accepted, debited and sent with the
chain switched off, before a restart and after one. To refuse new withdrawal
requests, disable the XMR token instead — see
Withdrawals.
The daemon check is deliberately not a gate — an unreachable monerod logs a
warning and the chain stays nominally active. That is a trap, not a kindness:
the chain looks enabled while no deposit can be detected. Always confirm the
daemon separately.
The backend does not point the wallet RPC at a daemon when it starts: that call,
set_daemon, acts on whichever wallet happens to be open. Start
monero-wallet-rpc with --daemon-address, and with --daemon-login when
monerod requires an RPC login. When a session's refresh fails with a daemon
error, the backend re-points that session's wallet at the daemon it last got an
answer from itself — XMR_DAEMON_RPC_URL on a single-daemon install, or the
entry of the XMR_<NETWORK>_RPC list that last answered — with the credentials
from XMR_RPC_USER / XMR_RPC_PASSWORD, and retries once.
Where to go next
Build the node, write the systemd units, wait out the sync, activate the licence and create the master wallet.
The environment variables, the session lock, HTTP Digest auth, the daemon the wallet RPC syncs against, the network match, and the two keys that are read by nothing.
How a wallet file becomes a credited balance, the one wallet RPC every process shares, the identity checks, the six-confirmation rule, and the monitor lifecycle.
Where the network fee comes from, the 90-second wait for the wallet RPC, locked outputs, the pre-relay claim, and why an unknown relay outcome is never refunded.
Every key the runtime reads, its default, the lock timings, and what breaks without them.
Sync and daemon faults, the session lock, identity refusals, wallet-open failures, stuck deposits, deferred and held withdrawals.
Related
- Supported blockchains — how licensed non-EVM chains are enabled, and the other three.
- Master wallets and the vault — the encryption that protects every mnemonic this addon creates.
- Deposit wallets and custody — the ECO wallet and address map this chain writes into.