Permissions
All thirty-four Swap permission keys, the console each one opens, and the four that let a delegate move revenue, commit operator capital or change what a user signs against.
Thirty-four keys, all seeded by the platform's permissions seeder, all beginning
dex. They follow the standing convention: the admin path with / as . and
- as _. /admin/dex/chain is access.dex.chain; the read and write keys
on the same screen are view.dex.chain and edit.dex.chain.
Two different gates enforce them, and both have to pass:
- The
access.key gates reaching the screen at all. It is whatfrontend/middlewares/permissions.jsonmatches the URL against, and it is what the megamenu entry carries. - The
view./create./edit./delete.keys are declared on each backend route and on the DataTable's ownpermissionsprop. They are what actually decide whether a request succeeds.
A role holding access.dex.chain and not edit.dex.chain can open the chain
console, read every row, and have every save refused.
The eleven access keys, and the thirteen screens
| Key | Opens |
|---|---|
access.dex |
The overview dashboard, /admin/dex. Also the megamenu entry for the whole console |
access.dex.provider |
/admin/dex/provider — aggregator activation and credentials |
access.dex.chain |
/admin/dex/chain, and /admin/dex/requirements, and /admin/dex/wallet |
access.dex.token |
/admin/dex/token — the curated token catalogue |
access.dex.pair |
/admin/dex/pair — the featured markets |
access.dex.pool |
/admin/dex/pool and /admin/dex/pool/{id} |
access.dex.position |
/admin/dex/position and /admin/dex/position/{id} |
access.dex.swap |
/admin/dex/swap — swap history |
access.dex.quote |
/admin/dex/quote — the quote log |
access.dex.fee |
/admin/dex/fee and /admin/dex/fee/accrual |
access.dex.settings |
/admin/dex/settings |
Three of those cover more than one screen on purpose:
- Requirements and Wallets sit under
access.dex.chain. Requirements is the diagnosis half of the same decision the chain console is the fix half of, and a separate key would let a role reach the fix and not the diagnosis. Wallets edits nothing the chain console does not already edit — the fee recipient is adexChaincolumn — so minting a separate wallet key would be a second gate on one decision, and the two would eventually be granted differently. - The pool and position detail screens share their list's key. Without that,
the detail path matched nothing in the manifest and fell back to the broad
access.admin, so a role scoped to the Swap console could open the register and not any row in it. - The fee accrual ledger shares
access.dex.fee. It is the same screen's detail view.
Read
Ten view. keys. Each is declared on the list endpoint behind its console.
| Key | Covers |
|---|---|
view.dex.chain |
GET /api/admin/dex/chain, the requirements report, and the fee-wallet report |
view.dex.provider |
The aggregator registry and its readiness columns |
view.dex.token |
The token catalogue |
view.dex.pair |
The market list, and pool discovery (POST .../pair/discover, which only returns candidates) |
view.dex.pool |
The pool register, one pool, and the create/seed transaction plan |
view.dex.position |
Positions, one position, and the position analytics |
view.dex.swap |
Swap history |
view.dex.quote |
The quote log |
view.dex.fee |
The revenue console, the accrual ledger, and the on-chain reconciliation scan |
view.dex.settings |
Reading the settings screen |
Two POST routes deliberately sit on a view. key because they write nothing:
pair discovery returns candidate pools, and POST /api/admin/dex/revenue/reconcile
scans the chain and reports. Neither is audited, because an audit log full of
probes buries the writes that matter.
Write
Seven edit. keys, three create. and three delete..
| Key | Allows |
|---|---|
edit.dex.chain |
The chain PUT, the live network probe on Requirements, and creating a Solana fee token account |
edit.dex.provider |
Switching an aggregator on or off and reordering priority |
edit.dex.token |
Status, listing and risk edits; the on-chain decimals() probe; an on-demand re-screen |
edit.dex.pair |
The pair edit dialog and the pair status switch |
edit.dex.pool |
Everything about a registered pool except registering one: verify, refresh, seed, withdraw, acknowledge, status |
edit.dex.fee |
Recording a sweep |
edit.dex.settings |
Saving the settings screen |
create.dex.token |
Adding one token, and the bulk token-list import |
create.dex.pair |
Adding a market |
create.dex.pool |
Registering a pool, and the create-verification that follows it |
delete.dex.token |
Soft-deleting a token row |
delete.dex.pair |
Deleting a market |
delete.dex.pool |
Deleting a pool row |
Chains and providers have no create. or delete. key at all — both
registries are code, so the console configures rows it cannot make or destroy.
Positions have no edit. key either: a position is opened by a receipt and
closed by a receipt, and nothing on that screen may write one.
create.dex.token, delete.dex.token, create.dex.pair and delete.dex.pair
are real, enforced keys, but the Tokens and Pairs consoles both ship with create
and delete switched off — a token is added by the probing POST or the list
importer, and delisting is listing: DENYLISTED rather than a delete, because
historic swaps resolve their token through that row.
So those four are reachable through the API only. Granting them changes nothing a delegate can do from the admin panel; withholding them does not take a button away from anyone.
The four keys to treat as privileged
edit.dex.chain — where your revenue lands, and which endpoints are trusted
This is the one to reason about the way you would reason about a
withdrawal-approval permission. It writes dexChain.feeRecipient, which is the
only address the integrator fee on that chain is paid to — there is no
global fallback and no second approval step. A holder can point every future
swap fee on Ethereum at an address you do not control, and nothing about the
saved row looks wrong afterwards.
It also writes both RPC fields — including the server-side override, which is never returned to a browser and can be pointed at any endpoint.
What it does not reach is the router allowlist. That list is the static code
list, plus every registered AMM deployment, plus
dexChain.metadata.extraRouters[] — and metadata is written by no admin route
in this addon. The chain PUT accepts six columns and ignores everything else, so
holding this key cannot add a contract address to the list that is checked
against the to and the approval spender of a quote before a user is asked to
sign it. Changing that list is a direct database edit today.
Two mitigations exist and neither is a substitute for granting the key
carefully: feeRecipientUpdatedAt is stamped only when the address actually
changes, so "when did our revenue destination move" is answerable; and the
audit trail records the zero-fee acknowledgement in words rather than as a
boolean.
edit.dex.fee — the key that credits your books
The revenue console shows accrued, swept and on-chain figures. Reading them
takes view.dex.fee. Recording a sweep — POST /api/admin/dex/revenue/sweep
— takes edit.dex.fee, and that is the action that starts the settlement chain:
the covered accruals move to SWEEP_SUBMITTED, and the settlement cron waits for
the recorded transaction to confirm and then books an adminProfit row.
The platform holds no key here and signs nothing; the route records a transfer
the operator made themselves. But an incorrect record is a credit to your own
books against a transaction that did not carry what it claims, so grant it to
whoever is accountable for revenue rather than to everyone with
access.dex.fee.
create.dex.pool and edit.dex.pool — the operator's own capital
These two are the only keys in the addon that let somebody commit your money.
Registering a pool is inert. edit.dex.pool is not: it covers the seed
verification and the withdraw verification, which is to say the whole of taking
and unwinding a market position.
Seeding is not a configuration change. The operator holds the impermanent loss and becomes the counterparty to everyone who trades against the pool, and on a V2 pool the LP fee can never be withdrawn as revenue at all. See Direct pools and Liquidity positions.
dexPoolRiskAckRequired (on by default, Super Admin only) means a seed with no
current, unrevoked acknowledgement is refused; switching it off removes the
dialog but not the record — the seed still writes an attributed waiver naming
the admin who allowed it.
edit.dex.settings — and the five keys it does not reach
Saving the Swap settings screen takes edit.dex.settings. Five settings are
protected and need the Super Admin role, resolved server-side on every
request, in addition to the permission:
| Protected key | What it governs |
|---|---|
dexEnabled |
Whether the swap surface exists at all |
dexAllowlistMode |
Whether curation is the allowlist or something looser |
dexKycRequired |
Whether swapping requires a verified account |
dexDirectPoolsEnabled |
Whether a swap may be filled from a pool you seeded |
dexPoolRiskAckRequired |
Whether seeding requires the risk acknowledgement |
A payload touching any of them from a caller without the role is refused with a 403 and nothing is saved — the whole change, not just the protected key, so a save is never half-applied.
Admin → System → Settings carries dexEnabled, dexAllowlistMode and
dexKycRequired. It has never carried dexDirectPoolsEnabled or
dexPoolRiskAckRequired. Those two are editable from the Swap settings screen's
Liquidity tab and nowhere else, and only by a Super Admin.
dexEnabled is a special case in the other direction: the Swap settings screen
refuses to load while the switch is off, so that screen can never be the place
it is turned on. Use the platform settings screen for that.
What none of these keys does
Nothing here affects what a customer can do. Connecting a wallet, quoting and swapping are gated by the master switch, the token allowlist, the geo list and — where you switched it on — KYC. These keys control the admin side only.
There is also no key that moves funds, reverses a swap or signs anything, because no such route exists. The most a holder of every key on this page can do is stop offering new swaps.
See Roles and permissions for how keys are attached to roles, and The admin surfaces for what each console answers.