samples/http/recipe-cross-chain.sh.
The API may change until launch. Every change is listed in the Changelog.
Before you begin
You needbash, curl, jq and openssl, and an API key with Read quotes, Submit orders and Read orders (Authentication).
The key also needs:
- Venue trading and request signing. A move TetraFi executes for you from an organisation wallet granted to the key is a Basic trade, so the key needs the venue trading scope, its signing secret and venue trading switched on (Trading on your venue accounts).
- An organisation wallet granted to it. A workspace owner, or an admin who manages credentials, grants the key the organisation wallets it may use, signed in with a second factor (Give a key organisation wallets).
- Funds on the chain you sell from. The organisation wallet that sells must hold the USDC you move and gas on that chain: it sends the transactions itself.
1
Find the chains USDC is on
GET /api/v1/assets lists every deployment of each asset. The chains of USDC’s native variant are the chains you can move it between. The script prints them and checks that both of your chains are among them.Output on test networks (shortened)
eip155:11155111), Optimism Sepolia (eip155:11155420), Base Sepolia (eip155:84532) and Solana devnet. In production you see main networks, such as Base (eip155:8453).Without TETRAFI_FROM_CHAIN and TETRAFI_TO_CHAIN, the script takes the first two chains listed, which may not be where your wallet holds USDC.2
Quote the move
POST /api/v1/quotes with the same asset on both sides, each side pinned to its chain, and filters.locations set to ["crossChain"] so only moves between the two chains are quoted (Chains and routes).Pick a quote whose next is order: TetraFi executes it from an organisation wallet, so your key can order it. Its tradingSource names the wallet it trades from (financialAccountId and network), and fundingModel says how the move is funded (Wallets and accounts). The quote’s eta is how long delivery is expected to take.Output on test networks (shortened)
sources. amountBelowMinimum comes with a detail naming the least you can move.You can send one live quote request every 3 seconds. The script waits details.retryAfter once when it gets 429 QUOTE_RATE_LIMITED.3
Place the order
POST /api/v1/orders with the quote id and an Idempotency-Key header you generate and keep. A retry with the same key and body returns the first answer instead of moving the funds twice (Idempotency).A bridge that TetraFi trades from your organisation wallet executes within your limit: an order on a quote whose minReceiveRequired is true must carry minReceive, the least you accept to receive (Orders). Without it, the order is refused with 400 MIN_RECEIVE_REQUIRED and nothing is sent. Cross-chain quotes from such a venue are usually indicative, and the script sends minReceive whenever the quote asks for it: the quoted amount less 50 basis points. Change that with TETRAFI_SLIPPAGE_BPS.The script places the order only when you set TETRAFI_PLACE_ORDER=1.kind, quoteId and operation. A Basic trade’s operation holds the connectionId and operationId you read its status with:Output (shortened)
4
Follow it until it ends
The order answers as soon as it is accepted. A move executed from an organisation wallet answers On test networks, a move from Base Sepolia to Ethereum Sepolia finished about two and a half minutes after the order.
"kind": "basicTrade"; read it at its statusUrl every 10 seconds until terminal is true (Order status).While the funds are on their way, the status can read working or outcomeUnknown. Neither is a failure: keep reading, and never place a new order for it. When next says wait, read again after its retryAfter.Output (shortened)
5
Confirm it arrived
The venue trade’s own detail is under To confirm arrival independently, check the receiving wallet’s balance on the destination chain in the app. Keep reading the order status if the trade or its money movement is not yet final.
operation: executionStatus for the trade and settlementStatus for any later money movement. When the venue reports amounts, dispatch.inputSpent is what you paid and dispatch.outputReceived is what you received. A missing or null amount is unknown, not zero. dispatch.venueOrderId, when present, is the venue’s native order id.bounds.sell.amount is the most the trade spends, every fee charged in it included, and bounds.buy.amount the least it delivers: the limits you accepted, not the amounts that settled. The public response does not document delivery transaction hashes or your organisation wallet’s transaction steps.Output (shortened)
Run the whole script
Output
If no quote can be ordered
When no quote’snext is order, the script stops and its summary lists why, venue by venue:
Output (shortened)
In the app
On the Trade page, open Advanced filters and set Route to Cross-chain, with a from chain and a to chain.Next steps
Wallets and accounts
Choose which organisation wallet trades or receives with source and deliverTo.
Order status
Every status a trade can read, and how often to poll.