================================================================ AIPP — Ayoun Instant Payments Platform : sandbox demo ================================================================ [1] Setup: participants and aliases ------------------------------------- ZANACO bank ZM Zambia National Commercial Bank MTN-ZM mno ZM MTN Mobile Money Zambia AIRTEL-MW mno MW Airtel Money Malawi ZM directory: jaweed@zanaco.zm, mary@zanaco.zm, chanda@mtn.zm, qr:shoprite-manda-hill MW directory: grace@airtel.mw => ledger events: 13 [2] (a) Online alias payment ZM -> ZM: jaweed@zanaco.zm pays chanda@mtn.zm ZMW 250 ------------------------------------------------------------------------------------ status=completed state=COMPLETE txn=txn-9311343d5740 latency=0.683 ms risk: score=15 action=allow reasons=['new_device'] retry with same idempotency key -> same txn (True), replay=True balance ZANACO-0001 9750 balance MTN-26096 3250 => ledger events: 24 [3] (b) Request-to-pay: Shoprite (QR) collects ZMW 180 from mary@zanaco.zm, Mary approves ------------------------------------------------------------------------------------------- collect col-cf31583a29 status=pending approved -> payment txn-24bdae5404a9 status=completed latency=0.54 ms; collect status=approved balance ZANACO-0002 2320 balance MTN-55501 680 => ledger events: 37 [4] (c) Cross-border ZM -> MW: jaweed@zanaco.zm pays grace@airtel.mw ZMW 1000 ------------------------------------------------------------------------------- foreign resolution returns only a RoutingToken: {'alias': 'grace@airtel.mw', 'country': 'MW', 'participant_id': 'AIRTEL-MW', 'account_token': '5bed67ae420c38c2c8e6625722d390eeb85e213c5ee23ce7a0750261049591db', 'masked_name': 'G*** P***'} status=completed scheme=TCIB settle_ccy=ZAR latency=0.662 ms fx: 1000 ZMW -> 66390.82 MWK @ 66.390815 balance ZANACO-0001 8750 balance OPERATOR:xb-suspense:TCIB 1000 => ledger events: 49 [5] (d) Offline: Chanda loads ZMW 500 of tokens, goes offline, pays two devices --------------------------------------------------------------------------------- registered dev-chanda-phone -> chanda@mtn.zm (cert signed by operator) registered dev-shoprite-pos -> qr:shoprite-manda-hill (cert signed by operator) registered dev-mary-phone -> mary@zanaco.zm (cert signed by operator) minted 6 tokens: ['200', '120', '100', '50', '20', '10']; wallet=500 balance MTN-26096 2750 balance OPERATOR:offline-suspense 500 --- network off: the following uses only local signature checks --- Chanda -> Shoprite POS 120: 1 token(s) verified offline by the POS Chanda -> Mary 80: 3 token(s) verified offline by Mary's phone Chanda wallet left: 300 | Shoprite holding: 120 | Mary holding: 80 --- network back on: Shoprite and Mary redeem --- Shoprite redeemed 120 (accepted 1, rejected 0) Mary redeemed 80 (accepted 3, rejected 0) balance MTN-26096 2750 balance MTN-55501 800 balance ZANACO-0002 2400 balance OPERATOR:offline-suspense 300 => ledger events: 67 [6] (e) Double-spend: Chanda re-signs an already spent token to a second payee -------------------------------------------------------------------------------- Mary's phone accepted serial 36ff0da3... offline (signatures are valid) redeem result: credited=0 rejected=[{'serial': '36ff0da3-89a5-4afe-ab7a-4733eddfa60c', 'reason': 'DoubleSpend: 36ff0da3-89a5-4afe-ab7a-4733eddfa60c'}] DoubleSpendDetected events: 1; device suspended: True risk engine view of device: suspended=True trust=0 => ledger events: 69 [7] (f) Fraud: mule pattern — 8 payers fund one alias within a minute, then it fans out ----------------------------------------------------------------------------------------- payer0 -> mule 150: completed score=15 action=allow ['new_device'] payer1 -> mule 150: completed score=15 action=allow ['new_device'] payer2 -> mule 150: completed score=15 action=allow ['new_device'] payer3 -> mule 150: completed score=15 action=allow ['new_device'] payer4 -> mule 150: completed score=15 action=allow ['new_device'] payer5 -> mule 150: completed score=45 action=allow ['new_device', 'payee_fan_in:6_distinct_payers'] payer6 -> mule 150: completed score=45 action=allow ['new_device', 'payee_fan_in:7_distinct_payers'] payer7 -> mule 150: completed score=45 action=allow ['new_device', 'payee_fan_in:8_distinct_payers'] mule -> jaweed 1100: status=denied score=85 action=deny reasons: ['new_device', 'mule_fan_in_then_fan_out:8_payers_in_window'] compensation: none needed (denied before any funds were reserved) balance MTN-77777 1200 => ledger events: 180 [8] (g) Settlement cycle: multilateral net positions ------------------------------------------------------ MTN-ZM net 1250 OPERATOR net 1300 ZANACO net -2550 sum of positions = 0 pacs.009 cyc-d5c68ce1-001: AIPP-SETTLEMENT -> MTN-ZM 1250 ZMW on 2026-10-07 pacs.009 cyc-d5c68ce1-002: AIPP-SETTLEMENT -> OPERATOR 1300 ZMW on 2026-10-07 pacs.009 cyc-d5c68ce1-003: ZANACO -> AIPP-SETTLEMENT 2550 ZMW on 2026-10-07 => ledger events: 181 [9] (h) Ledger integrity -------------------------- checkpoint signed at seq 181, head 34cb028400923401... ledger.verify() -> True tampering event #22 in memory: amount 250 -> 999999 ledger.verify() -> False => ledger events: 181 Done.