How it works
The swipe
A card authorization that sells shielded STRK, pays a merchant in USDC and records the settlement - as one transaction, so no intermediate state is ever exposed.
The naive version of this is three steps: withdraw from the pool, swap, then pay. Every one of those steps publishes something, and between them your value sits in the open. Sealed does it in a single privacy_invoke, so there is no in-between to observe and no leg that can succeed while another fails.
What happens in that one transaction
The authorization arrives
An issuer webhook posts the authorization. It is HMAC-signed; a tampered signature is rejected with 401 before anything touches a chain. This is a Lithic sandbox issuer, not a production card network.
Policy decides, before money moves
The
CardProgramcontract holds the per-swipe cap, the daily cap and the blocked categories. A blocked merchant is refused here and never reaches settlement. The daily spend counter is read back from the contract after the transaction, not tracked in the server's memory.The pool withdraws exactly what the swipe costs
One withdrawal covers the merchant payment plus anything else the same invoke is doing. The amount that leaves is the amount needed, not a rounded-up float.
The converter sells STRK for USDC just in time
The JIT converter holds calldata quoted live from Ekubo and routed through a pinned AVNU router. It converts only at settlement, so no idle USDC balance sits around advertising what you are about to spend.
The merchant is paid, the change re-shields
Payment out, change back into the pool, one atomic step. The receipt carries
AuthorizationSettled, and the replay map plus the daily spend total are readable on chain afterwards.
Why repeat swipes do not chain
Paying the same merchant twice from the same identity links those two payments to each other, whatever else is hidden. The shadow-account anonymizer derives a per-merchant identity so two visits do not share an address. Identities are deterministic per nonce, so the app can find them again without storing a map.
What the merchant and the chain each see
| Party | Sees | Does not see |
|---|---|---|
| The merchant | A card number and an amount in USDC | Your balance, your other activity, your Starknet address |
| A chain observer | That the pool was touched and a USDC payment was made | Which notes were spent, or what remains |
| The hosted account operator | Every swipe it settles, in full | Nothing about your self-custody wallet notes |
The third row is the one people skip. It has its own page.
What the tests actually hold
- A tampered HMAC returns 401, so a forged authorization cannot settle.
- A policy-blocked merchant does not settle, verified against the deployed contract.
- A repeated authorization id returns confirmed and does not settle twice - replay protection lives in the contract's own map, not in a server-side set.
- The settlement event parser is held by a mutation test: reading
keys[1]instead ofkeys[0]turns it red. A parser test that passes either way proves nothing, so this one was checked by breaking it.