Why real-time and provable
Two properties make onchain monitoring different from a nightly batch screen:- Sanctions lists change without warning. When OFAC adds an address, you cannot wait for tomorrow’s redeploy. A dynamic table lets you push a new address to a running pipeline and start flagging within seconds.
- Regulators want the “why,” not just the “what.” Compose traces every external call with inputs and outputs and can run in a Trusted Execution Environment that attests the exact code executed. Each freeze, alert, or SAR trigger comes with a verifiable record.
How it works
Prerequisites
- The Turbo CLI extension installed and logged in.
- A Postgres database and a Goldsky secret. This database also backs the dynamic-table watchlist, so you can keep it inside your own compliance boundary.
- The stablecoin/TIP-20 contract addresses you settle in. Confirm the Tempo dataset name in the Datasource explorer.
Step 1: Screen transfers against a live watchlist
The watchlist lives in a dynamic table. The pipeline checks both counterparties of every transfer against it withdynamic_table_check().
aml-screening.yaml
Step 2: React to a sanctions update in seconds
This is the capability that batch systems cannot match. When a new address must be watched, insert it into the dynamic table from any Postgres client - no redeploy, no re-sync:Step 3: Monitor issuer-level enforcement
TIP-20’s compliance controls emit their own events. Decode them fromraw_logs to keep a real-time view of every policy change and blocked transfer - the issuer-side counterpart to your own screening.
Decoding happens in two steps - one transform defines decoded, the next filters on it - because Flink SQL can’t reference a column alias in the WHERE of the same query.
policy-events.yaml
TransferPolicyUpdate- the token’s whitelist/blacklist policy (TIP-403) changed.TransferBlocked- a transfer was redirected by receive-policy enforcement.BurnBlocked- tokens were removed from a policy-restricted address.PauseStateUpdate- the token was paused or unpaused.
Step 4: Attest every decision with Compose
A flag is not a decision. Route each hit to a Compose task that verifies against your KYC/sanctions provider and records the outcome. Running the task in a TEE produces an attestation that the exact screening logic ran, which is what makes the decision defensible.src/tasks/screen-transfer.ts
case_management webhook in Step 1, or directly from an onchain event trigger. Every run is traceable step by step in the CLI and UI.
Business outcomes
- Minutes, not days, to enforce a sanctions change - the watchlist updates a running pipeline in seconds.
- Defensible decisions - TEE attestations and full execution traces answer “how did you decide?” with a record, not a reconstruction.
- Data stays in your boundary - the watchlist and flagged-transfer tables live in your database, easing residency and retention obligations.
- One surveillance layer across chains and tokens - the same pipeline pattern covers TIP-20 on Tempo and standard stablecoins on any supported chain.