The admin console
Every screen under Admin → Ecosystem — the custody overview, chain diagnostics, master and custodial wallets, the private ledger, unspent outputs, markets and tokens — and the permission each one needs.
Enabling the extension adds an Ecosystem entry to the admin navigation. It
opens at /admin/ecosystem and carries four groups.
Overview /admin/ecosystem
Blockchains
Requirements /admin/ecosystem/blockchain
Custom EVM Chains /admin/ecosystem/custom-chain
Wallets
Master Wallets /admin/ecosystem/wallet/master
Custodial Wallets /admin/ecosystem/wallet/custodial
UTXO /admin/ecosystem/utxo
Ledgers /admin/ecosystem/ledger
Trading
Markets /admin/ecosystem/market
Tokens /admin/ecosystem/tokenOverview — the custody console
This is not a statistics page. It answers one question in three parts, and every figure on it comes from a single server-side aggregate rather than arrays counted in the browser.
Can we pay people? Per asset, what customers are owed — the sum of balance and in-order across ECO wallets — against what the platform records itself as holding for them, minus the part of that record the withdrawal engine has already spoken for. Each asset is rated covered, partial or unbacked, and the page rolls those up as a count of assets rather than one money figure, because the payload carries no price feed and adding BTC to USDT would be a lie with two decimals on it.
Is anything stuck? The ECO withdrawal pipeline by status, with the rows the automatic recovery deliberately refuses to touch broken out separately. Those are the ones that wait for a human forever, so they get their own count and a link straight into the queue.
Is any chain degraded? Per chain: whether its RPC is configured, whether its extension is enabled, whether it still holds custody, whether its gas payer has a balance, and what its last stored diagnostics run said.
The masthead also carries the vault state. A green Vault Active badge means key material can be decrypted; an Initiate Vault button means it cannot, and clicking it opens the passphrase prompt.
The deduction for committed balance is clamped at zero. A net-negative private ledger says the platform's records understate what an address holds — a bookkeeping discrepancy, not spendable coins — so it is never counted as extra cover. The page may under-state coverage. It will not over-state it.
Blockchains → Requirements
The per-chain configuration and diagnostics console, covered in detail in Supported blockchains. Two things worth repeating here.
It distinguishes required from optional keys, and names the condition
that promotes an optional key to required — for example, BTC_NODE_USER is
optional until BTC_NODE=node. It also flags keys that are dead: read by no
code path, present in shipped .env files, and safe to remove. Cargo-culted
values are a real source of confusion and this page is the authority on which
ones matter.
The live test is stricter than a connectivity check. It reports readiness per platform flow — deposits, withdrawals, transaction history — and a chain whose RPC answers perfectly still fails if the vault is locked or the master wallet is missing, because a customer still cannot get their money out.
Blockchains → Custom EVM Chains
Add, edit, enable and delete operator-defined EVM chains. The create form has a test action that probes the candidate RPC, WebSocket, chain ID and explorer before you commit the row. Use it — a chain saved with a mismatched chain ID will fail at provider construction later, further from the cause.
Wallets → Master Wallets
One row per chain: chain, currency, address, balance, status. Create, view, enable and disable. Balances are live reads cached for one minute in Redis.
Disabling a wallet is an operational lever with teeth: the diagnostics treat a disabled master wallet the same as a missing one and downgrade the chain's withdrawal readiness to failed. That is the correct way to stop signing on a chain you no longer trust.
Wallets → Custodial Wallets
The shared EVM contracts that receive non-permit token deposits. Each row shows
its master wallet, address, chain, network and status — ACTIVE, INACTIVE or
SUSPENDED. The two transfer actions sweep native coin or a token out of a
contract, which is how you rebalance gas or recover funds from a contract you
are retiring.
Deploy more of these when deposits start failing with "All custodial wallets are currently in use": the count of contracts is your concurrency limit for non-permit deposits.
Wallets → UTXO
Every unspent output the platform tracks on Bitcoin, Litecoin, Dogecoin and
Dash, with amount, script, status (UNSPENT, LOCKED, SPENT) and source
(DEPOSIT, CHANGE, CONSOLIDATION, SYNC).
This is a diagnostic screen, not a routine one. You come here when a UTXO
withdrawal reports that it is uneconomical, to see whether the wallet's inputs
are genuinely too fragmented, or when a payout is stuck to check whether its
inputs are still LOCKED against a transaction that never completed.
Wallets → Ledgers
The private ledger — offchainDifference per wallet, index, currency and
network. A positive value is balance the platform still records at an address
but has already paid away from it.
It matters because the withdrawal engine subtracts it before it will source a payout, and the overview subtracts it before reporting coverage. If an asset shows as under-covered on the overview but the raw record looks fine, this is the screen that explains the gap.
Trading → Markets and Tokens
Covered in Tokens and markets. Both are standard data tables with create, view, edit, status toggle and delete.
The token table is also where the holders view lives, and where fees, limits and precision are edited after creation.
Order maintenance
Ecosystem orders are visible from the core's finance section at
/admin/finance/order/ecosystem, and the addon adds a maintenance endpoint of
its own.
The corrupted rows this cleans up are an artefact of ScyllaDB's upsert
behaviour: a partial write creates a ghost row with a valid primary key and null
everything else. Run it with dryRun: true first — it will tell you how many it
found without deleting anything.
Permissions
backend/seeders/20240402234643-permissions.js writes 41 permission rows
whose key contains ecosystem, and 41 is what you count in Admin → Roles. Only
26 of them are enforced on an admin API route — those are the keys that
decide whether a request succeeds, and they are the right-hand column below.
Seven more are page gates and nothing else: an access.ecosystem.* key exported
from a permission.ts beside the screen, which decides whether the page opens
but guards no endpoint. The remaining eight are wired to table buttons the code
switches off, so granting them changes nothing — the order desk
and the private ledger name their share of them.
They all ship ungranted — a newly enabled addon is reachable by Super Admin only until an operator grants its keys. See Permissions for how the key format maps to screens.
| Area | Opens the screen | Enforced on the API |
|---|---|---|
| Console | access.ecosystem |
access.ecosystem |
| Vault | — | manage.ecosystem.kms |
| Blockchains | view.ecosystem.blockchain (list), access.ecosystem.blockchain (one chain) |
view.ecosystem.blockchain, edit.ecosystem.blockchain |
| Master wallets | access.ecosystem.master.wallet |
view…, create…, edit… |
| Custodial wallets | access.ecosystem.custodial.wallet |
access…, view…, create…, edit… |
| UTXO | access.ecosystem.utxo |
view.ecosystem.utxo, create.ecosystem.utxo, edit.ecosystem.utxo |
| Private ledger | access.ecosystem.private.ledger |
view.ecosystem.private.ledger, edit.ecosystem.private.ledger |
| Tokens | access.ecosystem.token |
view.ecosystem.token, create…, edit…, delete… |
| Markets | access.ecosystem.market |
view.ecosystem.market, create…, edit…, delete… |
| Orders | access.ecosystem.order |
view.ecosystem.order, manage.ecosystem.order |
The two columns are not alternatives, and neither implies the other. A role with
view.ecosystem.master.wallet and no access.ecosystem.master.wallet can read
the wallets through the API but cannot open the screen; grant only the access key
and the page opens onto a table whose first request 403s. Grant them in pairs.
The token and market create and edit pages also carry their matching
create. / edit. key as a page gate, so those four are checked twice.
The gate is compiled into a route manifest at build time and the running process holds it in memory. Granting a key in the UI is not enough on its own — restart the API process for it to take effect.
Note that edit.ecosystem.blockchain covers both enabling a licensed chain and
creating custom EVM chains. It is effectively "may change which chains this
platform custodies", and should be granted narrowly.
POST /api/admin/ecosystem/wallet/custodial/{id}/transfer/native and its /token
sibling carry access.ecosystem.custodial.wallet — not an edit. or manage.
key. That is why access… appears in the API column above, and it means anyone
who can open the Custodial Wallets screen can sweep coin and tokens out of a
contract. Treat that access key as a spend permission, because that is what it is.
Related
- Operations — cron jobs, engine placement, repair scripts
- Blockchains — the diagnostics console in depth
- Troubleshooting — what to do when a screen tells you something is wrong