Lesson 11 gave you the write path and the read path. Now meet the full cast — six services, each with exactly one job — and see how a single subscription threads through all of them.
Why this, now? To lead Gateway you must know which service owns which decision — so that when something breaks, or a change is proposed, you know where it lives and who is accountable. The decomposition isn't arbitrary: the seams are cut around two things — the chain boundary and trust/custody. Learn the seams and the system stops being a list of repos and becomes a system you can reason about.
The cast, by job
Six services touch the blockchain world. Group them by role and the design reveals itself:
Service
Its one job
Role
connector (TS)
The only writer — executes chain actions via Fireblocks
Chain I/O (the edge)
listener (TS)
The only reader — watches chains, normalizes events
token-service (Express)
The token lifecycle brain — subscribe/redeem/dividend, escrow, DvP
Orchestration
asset-adapter (Spring)
The deployment state-machine — drives multi-step deploys
Two seams explain the whole split: the chain boundary (connector/listener isolate all chain I/O so nothing else touches a node) and custody/trust (mna-service owns wallet/key provisioning; recon independently verifies). Orchestration sits safely in the middle, never touching a chain or a key directly.
Deep cut 1 — token-service: the lifecycle brain
This is where business rules live. It exposes the REST surface (subscribe, redeem, dividend, orders), enforces whitelist/KYC and per-wallet limits, and — the key idea — models escrow as the mint/burn point:
Escrow = the moment of mint/burn. A subscription escrow is the mint point: when subscription funds are escrowed and conditions met, new tokens are minted (shares created). A redemption escrow is the burn point: tokens are burned as the investor exits. This is the Lesson 8 "issuance mints, redemption burns" invariant, realised as escrow state.
It also integrates DvP (Delivery-vs-Payment) settlement with the FundNode orchestrator — the security leg (tokens) and the cash leg settle atomically, so no one delivers without receiving (Lesson 8's atomicity-across-two-worlds problem). And it learns that chain actions succeeded two ways: the listener's TRANSFER_EVENT_SUBSCRIPTION, and Fireblocks webhooks — which it JWS-verifies.
JWS-verified webhooks. Fireblocks cryptographically signs every webhook (detached JWS). token-service verifies that signature before trusting the callback — proving the "your transaction signed" message genuinely came from Fireblocks and wasn't spoofed by an attacker hitting the endpoint.1Never trust an unsigned webhook that moves money.
Deep cut 2 — asset-adapter: deployment as a state machine
Deploying a token isn't one transaction — it's a workflow: deploy the ERC20F proxy, deploy the AllowList, grant roles (CONTRACT_ADMIN, BURNER, ACCESS_LIST_ADMIN), link whitelist→token. asset-adapter drives this as an explicit state machine (per-chain deployment.yml) and processes inbound MINT_SUPPLY/BURN_SUPPLY/TRANSFER/CLONE events into distribution records.
Why a state machine? Because the steps are multi-transaction, asynchronous, and individually fallible. A state machine makes the workflow resumable and idempotent — if step 3 of 4 fails, you retry from step 3, not step 1. This pairs with the connector's SHA-512 idempotency keys (Lesson 11): the orchestration knows where it is, the executor won't double-apply.
Deep cut 3 — mna-service: custody provisioning + maker-checker
mna-service owns everything about wallets and their binding to tokens: it provisions Fireblocks vaults, generates addresses, manages FIREBLOCKS vs BYO (bring-your-own) wallets, handles gas auto-fuel/seeding (a wallet needs native gas to transact — the service tops it up), and binds token↔wallet. Critically, every wallet/token op is maker-checker:
Maker-checker (the four-eyes principle). One person (maker) proposes a sensitive action; a different person (checker) approves it before it executes. In Gateway this surfaces as a 202 + changeRequestId — the request is accepted as pending approval, not done. It's mandated for regulated operators (SOX, PCI-DSS, FINRA 3110) and defends against both honest error and a single rogue actor.2This is segregation of duties enforced in code.
Deep cut 4 — recon-service: the integrity net
recon reconciles on-chain settlement (transaction_out, distributionOut) against the off-chain ledger and flags MATCHED / UNMATCHED. It's the assurance layer that catches drift — including drift caused by the listener's in-memory checkpoint gap (Lesson 11). Remember the limit: recon detects discrepancies; it does not prevent them. It's the smoke alarm, not the sprinkler.
How a subscription threads through the cast
1. Dashboard FE ─REST▶ token-service: check whitelist/KYC + limits;
open subscription escrow (= MINT point)
2. token-service ─enqueue▶ Service Bus ─▶ connector3. connector ─▶ Fireblocks (signs MINT) ─▶ CHAIN [idempotency key]
4. listener ◀─ mintTo / Transfer event ◀─ CHAIN
normalize ▶ DB + TRANSFER_EVENT_TOPIC
5. token-service ◀─ event / JWS webhook ─ confirm escrow, settle DvP leg
6. recon ─ match transaction_out vs ledger ▶ MATCHED
Notice every service plays its one part and hands off: rules & escrow (token-service) → execution (connector→Fireblocks) → observation (listener) → confirmation (token-service) → assurance (recon). No service reaches outside its lane. That is the design.
The Marketnode lens & interview angles
Know the owner of every decision. "Where do per-wallet limits live?" → token-service. "Who can approve a new minting wallet?" → mna-service maker-checker. "Why didn't my balance update?" → listener/recon. Leading means routing issues to the right lane fast.
Maker-checker and JWS-verified webhooks are non-negotiable in regulated finance — if a candidate proposes an auto-approved wallet creation or trusts an unsigned webhook that triggers a mint, that's a fail.
Interview probe: "Trace a subscription from the UI click to a confirmed holding — name each service and its job." A strong hire narrates the six-step handoff; a weak one collapses it to "the backend mints a token."
Interview probe: "Why is deployment modelled as a state machine rather than a single function?" Listen for multi-step, async, resumable, idempotent.
Retrieve it (don't peek)
From memory. Interleaves Lessons 8 & 11.
1. In Gateway, what does a subscription escrow in token-service represent on-chain?
Correct. Subscription escrow = mint point (shares created); redemption escrow = burn point (shares destroyed). It's the Lesson 8 issuance/redemption invariant modelled as escrow state.
Reconsider. Burning is redemption escrow. A subscription is an investor buying in → new shares → it's the mint point.
2. Why does token-service JWS-verify Fireblocks webhooks before acting on them?
Correct. Fireblocks signs every webhook (detached JWS); verifying the signature proves authenticity and integrity. An unsigned webhook that triggers a mint is an attack vector.
Reconsider. It's not compression, conversion, or retries. The signature proves the callback is authentically from Fireblocks — essential before acting on a money-moving message.
3. A new minting wallet is created and the API returns 202 + changeRequestId. What does that mean?
Correct. 202 + changeRequestId = accepted as a pending change awaiting a checker's approval (four-eyes). Segregation of duties enforced in code — mandated for regulated operators.
Reconsider. It's not done, failed, or queued on-chain. 202 + changeRequestId signals a maker-checker pending approval — a second person must approve before it executes.
I'm your teacher — ask me. Want to go deep next on the ERC20F/ERC20MN01 + AllowList token design (L13), the multi-chain model (L14 — EVM events vs XRPL/Stellar trustlines vs Solana), or have me map which service to look in for a given bug/change as a triage cheat-sheet? Just ask.