Reference · Gateway

Gateway Architecture Map

Defining decision: frontends never touch a chain (no wallet/signing). One service writes (connector), one reads (listener), all keys in Fireblocks. The chain is the slow async edge. Web3 is a backend concern; the UI is orchestration + monitoring.

End-to-end flow

WRITE: Dashboard FE ─REST▶ token-service/asset-adapter ─Bus▶ connectorFireblocksCHAIN
READ:  CHAIN ─events▶ listener ▶ DB + TRANSFER_EVENT_TOPIC ▶ token-service ▶ recon

Chains & custody

NetworksEVM (Ethereum, Polygon, Avalanche), XRPL, Stellar, Solana (Token-2022) — main+test
Custody/signingFireblocks (@fireblocks/ts-sdk); keys never leave vaults (MPC/TSS)
EVM libraryviem
RPCAlchemy / QuickNode / Blockdaemon (per-network from DB)
Token standardERC20F & ERC20MN01 (proxy + impl) + separate AllowList contract; native on XRP/XLM/SOL

The four blockchain-touching services

ServiceRole
connector (TS)Only writer. Consumes DEPLOY/CHAIN_ACTION queues; deploy, MINT, BURN, TRANSFER, DIVIDEND, trustlines, Solana freeze. Per-chain handlers; SHA-512 idempotency; writes transaction_out.
listener (TS)Only reader. Per-chain event subscriptions → normalize to ChainEvent (TRANSFER/WHITELIST) → DB + TRANSFER_EVENT_TOPIC.
token-service (Express)REST token lifecycle: subscribe/redeem/dividend/orders. Whitelist/KYC + limits. Escrow (subscribe=mint, redeem=burn). DvP with FundNode. Fireblocks webhooks (JWS-verified).
asset-adapter (Spring)Deployment state-machine (per-chain deployment.yml); processes MINT_SUPPLY/BURN_SUPPLY/TRANSFER/CLONE into distribution records.
mna-service (NestJS)Provisions Fireblocks vaults/addresses; FIREBLOCKS vs BYO wallets; gas auto-fuel; token↔wallet binding. Maker-checker on every op.
recon-serviceReconciles on-chain (transaction_out, distributionOut) vs off-chain ledger → MATCHED/UNMATCHED.

Frontends (UI only)

dashboard (Next.js): issuance forms, manage (subscribe/redeem/transfer/mint/burn/whitelist), monitor (tx history, holder registry, explorer links), holdings. Uses bignumber.js + mnxp; no raw web3. admin (React/Vite): wallet/network lifecycle, maker-checker (202 + changeRequestId). Only web3 use: viem getAddress/isAddress for checksum validation.

6.5 target architecture

connector + token-service + asset-adapter + gatekeeper collapse into gateway-backend (already has src/infra/blockchain/ with the same Fireblocks/viem handlers). Only listener and recon stay separate. "The blockchain client" becomes an in-process module.

Inherited risks to track

Listener checkpoint: resume-from-block is in-memory only — no persistent checkpoint. Long downtime ⇒ missed events ⇒ DB drifts from chain. recon detects but doesn't prevent. Best practice: persistent sync table (block# + hash) + reorg handling.