exchange.IO("bridge.*", ...)
Bridge tokens from Solana to EVM chains through bridges aggregated by LI.FI: list chains and tokens, quote, simulate, send and track progress.
exchange.IO(k)
exchange.IO(k, chain)
exchange.IO(k, params)
exchange.IO(k, signature)
exchange.IO(k, signature, options)
exchange.IO(k, key)Examples
-
List the supported chains and find USDC on Arbitrum (read-only).
javascriptfunction main() { var chains = exchange.IO("bridge.chains") if (!chains) { Log("Query failed:", GetLastError()) return } Log(chains.length, "chains:", chains.slice(0, 8).map(function(c) { return c.key }).join(",")) var tokens = exchange.IO("bridge.tokens", "arb") || [] var usdc = tokens.filter(function(t) { return t.symbol == "USDC" })[0] Log("USDC on Arbitrum:", usdc ? usdc.address : "not found") } -
Quote bridging 50 USDC to Arbitrum and simulate it (read-only).
javascriptvar TO = "" // your recipient address on Arbitrum (0x...) function main() { if (!TO) { Log("Set TO to your address on the destination chain first") return } var q = exchange.IO("bridge.quote", {toChain: "arb", fromToken: "USDC", toToken: "USDC", amount: 50, toAddress: TO}) if (!q) { Log("Quote failed:", GetLastError()) return } Log("via", q.toolName, "receive", q.toAmount, "at least", q.toAmountMin, "in about", q.executionDuration, "s") q.feeCosts.forEach(function(f) { Log("fee", f.name, f.amount, f.token, f.included ? "included" : "extra") }) var sim = exchange.IO("bridge.simulate", q) Log("Simulation:", sim ? "passed, compute units " + sim.unitsConsumed : GetLastError()) } -
Full flow: quote → simulate → send → poll the progress.
javascriptvar TO = "" // your recipient address on Base (0x...) function main() { if (!TO) { Log("Set TO to your address on the destination chain first") return } var params = {toChain: "base", fromToken: "USDC", toToken: "USDC", amount: 20, toAddress: TO} var q = exchange.IO("bridge.quote", params) if (!q || !exchange.IO("bridge.simulate", q)) { Log("Quote or simulation failed:", GetLastError()) return } var r = exchange.IO("bridge.send", q) if (!r) { Log("Send failed:", GetLastError()) return } Log("Sent", r.txHash, "expected", r.toAmount, "USDC") while (true) { Sleep(20 * 1000) var s = exchange.IO("bridge.status", r.txHash, {toChain: "base", bridge: r.tool}) if (!s) { continue } LogStatus(_D(), s.status, s.substatus || "") if (s.status == "DONE" || s.status == "FAILED" || s.status == "INVALID") { Log("Result", s.status, s.substatus, "received", s.receiving ? s.receiving.amount : "-") break } } }
Returns
| Type | Description |
array / object / bool / null value |
|
Arguments
| Name | Type | Required | Description |
k | string | Yes | The command: |
chain | string / number | No | The chain |
params | object | No | The bridge parameters |
signature | string | No | For |
options | object | No |
|
key | string | No | For |
See Also
Jupiter exchange.IO exchange.IO("receipt") exchange.IO("slippage") exchange.IO("token") exchange.CreateOrder
Remarks
Flow
bridge.quote for a quote → bridge.simulate to simulate → bridge.send to send → bridge.status every 10 to 30 seconds until DONE or FAILED.
Quotes and transactions come from LI.FI (aggregating Across, Stargate, CCTP, deBridge, Mayan, Relay, NEAR Intents and other bridges); LI.FI returns a serialized Solana transaction, which the docker signs with this wallet (refusing one this wallet does not sign), simulates and broadcasts through the Solana node. Requests carry the integrator tag integrator=fmz and no extra fee; fees such as LIFI Fixed Fee in a quote belong to LI.FI and the bridges and are already counted in toAmount.
Bridge parameters
| Key | Required | Description |
|---|---|---|
toChain | yes | Destination chain: a chain ID, a LI.FI chain key (such as arb) or a name (such as Arbitrum or Base, case-insensitive). It cannot be Solana (this chain; swap on the same chain with exchange.CreateOrder()) |
fromToken | yes | A token on Solana: a name in the token table or a mint address |
toToken | yes | A token on the destination chain: a name or address resolved by LI.FI to its canonical token (USDC on Arbitrum is native USDC, not USDC.e) |
amount | yes | The amount of fromToken in token units; digits beyond the token's decimals are dropped |
toAddress | yes | The recipient on the destination chain (an 0x address, checked for format); all destinations are EVM chains where this wallet has no address, so it must be given |
slippage | no | Slippage ratio, [0, 0.5), defaults to the exchange.IO("slippage") value |
order | no | CHEAPEST or FASTEST |
allowBridges, denyBridges | no | Use only, or never, these bridges (LI.FI bridge names, an array or comma-separated) |
Unknown keys are errors. Given a bridge.quote result, the quote is redone from its request (the parameters as given).
Results
bridge.chains:[{id, key, name, chainType, nativeToken}],chainTypebeingEVMorSVM, cached for an hour.bridge.tokens:[{symbol, address, decimals, name, priceUSD}], cached for an hour.bridge.quote:{tool, toolName, fromChain, toChain, toChainName, fromToken, toToken, fromAmount, toAmount, toAmountMin, fromAmountRaw, toAmountRaw, toAmountMinRaw, fromAmountUSD, toAmountUSD, slippage, toAddress, feeCosts, gasCosts, executionDuration, approvalAddress, steps, transactionId, request}: amounts in token units (*Rawin the smallest unit);toAmountMinis the amount guaranteed after slippage;feeCostsis[{name, amount, token, amountUSD, percentage, included}](fees withincludedfalseare paid on top);gasCostsestimates source-chain gas;executionDurationis the expected time in seconds;approvalAddressisnullon Solana;stepslists the steps (crossbridges,swapswaps,protocolis LI.FI's fee).bridge.simulate: re-quotes, signs with this wallet and runssimulateTransaction(with signature verification) without broadcasting; returns thebridge.quoteresult plussimulated(true),unitsConsumedandsignature. A failed simulation is an error whose message gives the reason (AccountNotFoundmeans the wallet has no SOL) and the wallet balance.bridge.send: re-quotes → checks the balance → signs → simulates → broadcasts, without waiting for confirmation; returns{txHash, tool, fromChain, toChain, toChainName, fromToken, toToken, fromAmount, toAmount, toAmountMin, toAddress, transactionId},txHashbeing the source-chain signature, whose stateexchange.IO("receipt")returns. Quotes move; the new quote at sending applies.bridge.status: LI.FI's/status, returning{status, substatus, substatusMessage, tool, sending, receiving, fromAddress, toAddress, explorer, bridgeExplorer}:statusisNOT_FOUND,INVALID,PENDING,DONEorFAILED; whenDONE,substatusisCOMPLETED(delivered as quoted),PARTIAL(a different token arrived) orREFUNDED(returned to the source chain);sendingandreceivingare{txHash, txLink, chainId, amount, amountRaw, token, timestamp}. Right after broadcasting LI.FI may not have indexed the transfer and returnsNOT_FOUND; keep polling.bridge.apiKey: sets the LI.FI API key (headerx-lifi-api-key, for this exchange object only, never echoed) and returns whether a key is set (a boolean).
Rate limits and risks
- Without an API key LI.FI rate-limits by outgoing IP:
/quote75 times per two hours (bridge.quote,bridge.simulateandbridge.sendeach use one), other endpoints 100 per minute, shared by the strategies on one docker; with a key, 100 per minute. A rate-limited call fails withrate limited (HTTP 429 …). - Bridging is asynchronous: when
bridge.sendreturns only the source transaction has been broadcast; delivery takes seconds to tens of minutes (see the quote'sexecutionDuration), so pollbridge.statusto confirm. - Funds sent to a wrong address cannot be recovered; bridge contracts and cross-chain messaging carry each bridge's own security risk; the destination wallet needs gas to use what arrives. Test with a small amount first.