How it works
- The engine enters a state
- If the state has an action, it executes it
- Based on the action’s resolution mode, it either advances immediately or waits
- When the next state is reached, the cycle repeats
- When a terminal state is reached, the settlement is complete
Transition rules
The engine enforces strict transition rules:- Only transitions explicitly defined in the template are allowed
- No state can be skipped
- No client can force a state jump
- Every transition is recorded as an event with a timestamp and trigger source
Action handlers
The engine delegates work to registered action handlers:| Action Type | Provider | What It Does |
|---|---|---|
compliance_check | internal | Screens all parties via LSEG World-Check and CipherOwl |
await_confirmation | internal | Pauses until all counterparties confirm participation |
register_escrow | escrow | Registers the settlement on the escrow smart contract |
monitor_deposits | escrow | Watches for on-chain deposits via webhooks |
execute_escrow | escrow | Triggers atomic swap on the escrow contract |
rollback_escrow | escrow | Returns deposits to original owners |
lock_assets | fireblocks | Locks assets via Fireblocks custody |
release_assets | fireblocks | Releases locked assets |
initiate_payment | fireblocks | Initiates fiat/stablecoin payment |
finalize | internal | Marks settlement as complete |
noop | internal | No-op, advances immediately |
Concurrency safety
The engine uses database-level locking (SELECT ... FOR UPDATE) to prevent race conditions:
- Only one engine instance processes a settlement at a time
- Concurrent webhook deliveries and poller runs are safely serialized
- Idempotent processing means duplicate triggers are harmless
Error handling
When an action fails:- The error is logged with full context
- The settlement remains in its current state (no partial transitions)
- The engine can retry on the next trigger (webhook, poller, or manual)
- If
timeout_atis reached, the settlement transitions toTIMED_OUT