TrustFlow is a programmable payment rail on Sui: atomic PTB settlement, wallet-native receipts, and public settlement, private evidence. Escrowed stablecoins become conditional payment workflows: fund, submit, approve, split, pay, receipt, and verify in one Sui-native flow.
Why Sui: programmable transaction blocks make the hero "approve → fee
split → pay worker → mint receipt" a single atomic, composable call;
object-owned capabilities (ClientCap / ApproverCap / ResolverCap) give
authorization without an admin key; Seal gives policy-gated evidence
decryption keyed to on-chain dispute state, so the demo stays true to public
settlement, private evidence.
# 0. clone + install JS deps (root of the repo)
pnpm install
# 1. Move unit tests — 46 tests across 4 packages (needs the Sui CLI)
sui move test --path move/trustflow_core # 22 tests
sui move test --path move/trustflow_payment_router # 7 tests
sui move test --path move/trustflow_evidence # 13 tests
sui move test --path move/trustflow_defi_router # 4 tests
# 2. E2E lifecycle test — publishes trustflow_core into a throwaway
# localnet (TestContainers: Postgres + Sui) and drives the full
# create -> fund -> submit -> approve_and_settle -> dispute ->
# resolve_partial flow with real object/event/balance assertions.
# REQUIRES Docker running.
cd integration-tests && pnpm testTypecheck only (no Docker needed): cd integration-tests && npx tsc --noEmit.
The 22 trustflow_core tests and the npx tsc --noEmit typecheck were
observed green while building this. The full E2E suite needs Docker; it has
not been run in a Docker-less environment — see "Verifiability caveat" below.
Chain id 4c78adac. Publisher
0x010030a0afc40b6d8fe99cee368cab5652baa0d36b7be60a9b017d5228c0bdfd.
Website testing URL:
https://trustflow-dapp-testing.vega-fi.workers.dev
Judge starting point:
/admin, with
direct access to /admin?tab=payments, /escrow/[id], /receipt/[id], and
/disputes/[id].
| Package | Package ID | Suiscan |
|---|---|---|
trustflow_core |
0xa42cdd37cc9d560aee5f9e58e5e660de0c076857b7c9f0eff1c76274adce06f4 |
view |
trustflow_payment_router |
0xdc3d82b2c29882e040d2110975a94cfbb15b8775cc14dfa7b2f22f92eca78a0e |
view |
trustflow_evidence |
0xb292ad1e22dc93c0aaed18c9b3a969732dd57b8912009b0ff40ed216d6fc88b9 |
view |
trustflow_defi_router |
0x9e9f987f000a68aed21199c0621b711972b099f0c9749caaf1d91218067d2c64 |
view |
The full deploy record (upgrade caps, init objects, publish history) lives in
deployments.json. To verify against testnet directly,
point a wallet/SDK at these IDs and replay the lifecycle from
dapp/src/lib/sui/ptb/*.ts. The E2E suite instead publishes fresh into a
hermetic localnet so CI never depends on testnet liveness.
┌──────────────────────────┐
│ dapp/ (Next.js + dApp │
│ Kit, PTB builders in │
│ lib/sui/ptb/*.ts) │
└────────────┬─────────────┘
│ one signature
▼
HERO PTB ──► trustflow_payment_router::settlement::approve_and_settle
└─ thin re-export of ─┐
▼
┌─────────────────────── trustflow_core ───────────────────────┐
│ escrow milestone dispute receipt role_cap events │
│ create → fund → submit_milestone → approve_and_settle │
│ └─ open_dispute → resolve_* │
│ fee split (bps) · PaymentReceipt mint · MilestoneSettled │
└───────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
trustflow_evidence trustflow_defi_router Walrus + Seal
evidence_pointer deepbook_swap_router (sealed evidence
nautilus_attestation strategy_adapter blobs; seal_approve
seal_policy (seal_approve) mock_savings_pool gates decryption on
(DeFi payout — scaffold) dispute state)
Hero PTB (single atomic tx, see dapp/src/lib/sui/ptb/approveAndSettle.ts):
approve milestone → assert cap binds to escrow → compute platform fee →
split Balance<CoinType> into fee + net → transfer net to worker → fee to
treasury → mint + transfer PaymentReceipt → emit MilestoneSettled.
| Package | Unit tests | Notes |
|---|---|---|
trustflow_core |
22 | Full lifecycle + threat-model abort cases (cap forgery, double-release, dispute-decision binding). Verified green. |
trustflow_payment_router |
7 | Fee-policy binding + settlement re-exports. |
trustflow_evidence |
13 | Evidence pointers, Nautilus attestation, Seal access policy. |
trustflow_defi_router |
4 | DeepBook swap router + mock savings pool (scaffold). |
| Total | 46 | + 1 multi-step E2E lifecycle test (integration-tests/test/trustflow-lifecycle.test.ts). |
Counts verified by grep -c '#\[test\]' against each
move/<pkg>/tests/*.move.
- Live & on testnet:
trustflow_core(full escrow/milestone/dispute lifecycle, fee split, receipts, events — the audited, hardened path),trustflow_payment_router(fee-policy-bound settlement entrypoints),trustflow_evidence(evidence_pointer,nautilus_attestation, and a realseal_policy::seal_approveentry that gates Seal decryption on dispute state). - Scaffold:
trustflow_defi_router—deepbook_swap_routerandstrategy_adapterare published and compile, but the DeepBook payout-route step in the hero PTB is intentionally stubbed (mock_savings_poolstands in for a real yield venue). Honest status: the DeFi payout leg is wired but not yet executing real swaps.
- Script:
plans/pitch/demo-script-v2-hero-first.md - Demo-day runbook:
scripts/DEMO_RUNBOOK.md - Seed testnet state:
pnpm run seed:demo --network testnet --dry-run, thenpnpm run seed:demo --network testnet - Export Judge Console env after seeding:
pnpm run seed:demo:env --network testnet - Walkthrough video: (to be recorded — placeholder)
move/ trustflow_core · _payment_router · _evidence · _defi_router
dapp/ Next.js frontend + lib/sui/ptb PTB builders
integration-tests/ TestContainers E2E (localnet publish + lifecycle test)
publish/ Move publish scripts (deploy / unsigned bytes for KMS)
deployments.json Testnet package IDs + publish history
plans/pitch/ Demo scripts
The single weakest link: the E2E suite was typecheck-verified, not
run, in the build environment (no Docker → TestContainers can't start a
localnet). The Move-level guarantees are independently proven (22/22
trustflow_core unit tests observed passing, including the exact fee-split
and partial-dispute math the E2E re-asserts), so a judge with Docker can run
cd integration-tests && pnpm test to close the loop. The E2E adds
end-to-end RPC/event/balance assertions on top of that proven Move logic
rather than being the sole source of correctness.