Prerequisites
- A wallet on the source chain with testnet USDC (or any supported asset)
tokenInapproval to the source-chain bridge contract (addresses in supported chains)- The recipient registered via
POST /recipient/registerat least once (generates their stealth keys) - An ECIES library for the language you’re using
1. Register the recipient (first time only)
2. Approve the bridge contract
The sender must approvetokenIn to the bridge on the source chain for amountIn + reward:
3. Call createIntent on source chain
This publishes the public solver-facing offer. The contract also emits an encrypted blob in the same event recoverable only by the relayer’s key, the on-chain recovery anchor.
4. Fetch the relayer’s ECIES public key
5. Encrypt the recipient bundle and store it
The bundle contains the actual recipient address(es) and per-recipient amounts on the destination chain. Sum of amounts must be ≤minAmountOut.
6. Track the intent to completion
PollGET /intent-details/:intentId until status === "completed":
What happens under the hood
After step 5, the relayer:- Batches your intent with other live intents that share the same token pair + chain pair
- Broadcasts to solvers in plaintext: rate, token pair, total batch amount, available fees. No sender or recipient info.
- When a solver bids to fill some portion of the batch, re-encrypts your recipient bundle to that solver’s keypair
- Solver delivers to the stealth address(es) on the destination chain
- Relayer settles on source chain (releases the solver’s reward)
Recipient side
The recipient’s funds land at a Safe at a fresh stealth address on the destination chain. To sweep:- Recipient registers if they haven’t already (step 1 above)
- Lists their stealth balances via
GET /recipient/addresses - Derives the stealth key for a specific delivery via
POST /recipient/derive-stealth-key - Signs a Safe tx and calls
POST /recipient/relay-proxy, the relayer broadcasts and pays gas
Error handling
Common failure modes:| Where | What | How to fix |
|---|---|---|
createIntent revert | Insufficient allowance / balance | Approve enough before calling |
createIntent revert | Invalid destination chain ID | Use a chain from supported chains |
POST /store-recipients 400 | Intent ID doesn’t exist on-chain | Wait for createIntent tx to mine before calling |
POST /store-recipients 400 | ECIES decryption failure | Re-fetch /ecies-pubkey; ensure your library uses the same curve format |
Intent stays pending past auction | No solver took the offer | Retry with a higher reward or a more liquid chain pair |
| Intent expires | auctionDuration elapsed with no winner | User is refunded via BridgeIntentV2 escape; funds are safe |
Try it on testnet
Five-minute version of this guide.