Bungee Provider
The Bungee Protocol provider enables cross-chain token transfers using the Bungee bridge infrastructure, supporting both onchain transactions (native ETH or via BungeeInbox, default) and gasless permit2 flows (ERC20).
Status: Active (mainnet)
API Access
Bungee offers three integration tiers, each with a different base URL and authentication method:
| Tier | Endpoint | Authentication | Rate Limit | Use Case |
|---|---|---|---|---|
| Public Sandbox | https://public-backend.bungee.exchange/ | None | Very limited | Testing only |
| Dedicated Backend | https://dedicated-backend.bungee.exchange/ | API Key (x-api-key) | 20 RPS (extendable) | Production backends |
| Frontend / Direct | https://backend.bungee.exchange/ | Whitelisted domains | 100 RPM | Frontends, dApps, wallets |
The SDK uses the public sandbox by default — createCrossChainProvider("bungee") works with no setup but is rate-limited and intended for integration testing only. For production, upgrade to Dedicated (server-to-server) or Frontend (browser) and pass the matching tier in the config.
See Bungee's API access docs for how to request a key or whitelist your domains.
Configuration
| Field | Type | Required | Description |
|---|---|---|---|
tier | BungeeApiTier | No | API tier: "sandbox", "dedicated", or "frontend" (default: "sandbox") |
baseUrl | string | No | Custom API base URL. Overrides the URL derived from tier |
providerId | string | No | Custom provider identifier (default: "bungee") |
apiKey | string | No | API key for dedicated backend (sent via x-api-key header) |
affiliateId | string | No | Affiliate ID for tracking (sent via affiliate header) |
feeBps | string | No | Convenience fee in basis points (e.g. "50" for 0.5%) |
feeTakerAddress | string | No | Address to receive the convenience fee. Required when feeBps is set |
submissionModes | string[] | No | Transaction submission modes: "user-transaction" (onchain) and/or "gasless" (permit2). Defaults to ["user-transaction"] |
slippage | string | No | Default slippage tolerance (e.g. "0.5" for 0.5%) |
refuel | boolean | No | Enable native gas refueling on the destination chain |
["user-transaction"] onlysubmissionModes defaults to ["user-transaction"]. To enable the gasless permit2 flow, explicitly opt in:
createCrossChainProvider("bungee", {
submissionModes: ["user-transaction", "gasless"],
});
When both modes are configured, quotes are fetched in parallel and the aggregator handles either order type seamlessly, so opting in has no extra cost. For Bungee, adding "gasless" enables the permit2 signature flow for ERC-20 tokens — the user signs a permit2 message instead of sending an onchain transaction.
Notes:
baseUrloverrides the URL derived fromtier.feeBpsandfeeTakerAddressmust be set together. The fee is deducted from the output amount.slippagesets the default tolerance for all quotes. If not set, Bungee uses its own default.refueltops up native gas on the destination chain so the user can transact immediately after bridging.
Creating the Provider
Public Sandbox (Default)
import { createCrossChainProvider } from "@wonderland/interop-cross-chain";
const bungeeProvider = createCrossChainProvider("bungee");
Dedicated Backend
import { BungeeApiTier, createCrossChainProvider } from "@wonderland/interop-cross-chain";
const bungeeProvider = createCrossChainProvider("bungee", {
tier: BungeeApiTier.Dedicated,
apiKey: "your-api-key",
affiliateId: "your-affiliate-id",
});
Custom Base URL
import { createCrossChainProvider } from "@wonderland/interop-cross-chain";
const bungeeProvider = createCrossChainProvider("bungee", {
baseUrl: "https://my-proxy.example.com",
});
Getting Quotes
Default (Onchain)
ERC20 transfers use the onchain BungeeInbox flow by default. The quote returns a transaction step:
const quotes = await bungeeProvider.getQuotes({
user: "0xYourAddress",
input: {
chainId: 10, // Optimism
assetAddress: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", // USDC
amount: "1000000", // 1 USDC
},
output: {
chainId: 8453, // Base
assetAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC
},
});
const quote = quotes[0];
With submissionModes (Gasless)
Use the gasless permit2 signature flow instead of onchain transactions. The quote returns a signature step:
const bungeeProvider = createCrossChainProvider("bungee", {
submissionModes: ["gasless"],
});
const quotes = await bungeeProvider.getQuotes({
user: "0xYourAddress",
input: {
chainId: 8453, // Base
assetAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // USDC
amount: "1000000",
},
output: {
chainId: 10, // Optimism
assetAddress: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85", // USDC
},
});
const quote = quotes[0];
With Convenience Fee
Charge an affiliate fee deducted from the output amount:
const bungeeProvider = createCrossChainProvider("bungee", {
feeBps: "50", // 0.5%
feeTakerAddress: "0xYourFeeReceiverAddress",
});
const quotes = await bungeeProvider.getQuotes({
user: "0xYourAddress",
input: {
chainId: 10,
assetAddress: "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
amount: "1000000",
},
output: {
chainId: 8453,
assetAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
},
});
const quote = quotes[0];
// quote.metadata.bungeeAutoRoute.affiliateFee contains the fee details
With Slippage
Set a custom slippage tolerance for quotes:
const bungeeProvider = createCrossChainProvider("bungee", {
slippage: "0.5", // 0.5% tolerance
});
With Refuel
Enable native gas refueling so the user receives a small amount of native token on the destination chain:
const bungeeProvider = createCrossChainProvider("bungee", {
refuel: true,
});
With Custom Base URL
Override the tier URL with a custom endpoint:
const bungeeProvider = createCrossChainProvider("bungee", {
tier: BungeeApiTier.Dedicated,
baseUrl: "https://public-backend.bungee.exchange", // overrides dedicated URL
});
Fees
After getting a quote, you can inspect the standardized fee breakdown via quote.fees:
const quote = quotes[0];
console.log(quote.fees?.originGas); // origin chain gas estimate
See the API reference for the full QuoteFees type.
Executing Transactions
Bungee quotes can return either a transaction step (onchain via BungeeInbox, default) or a signature step (permit2/gasless via submissionModes: ["gasless"]). Use getSignatureSteps and getTransactionSteps to handle both:
import { getSignatureSteps, getTransactionSteps } from "@wonderland/interop-cross-chain";
const sigSteps = getSignatureSteps(quote.order);
const txSteps = getTransactionSteps(quote.order);
if (sigSteps.length > 0) {
// Permit2 flow: sign + submit
const step = sigSteps[0];
const { signatureType, ...typedData } = step.signaturePayload;
const signature = await walletClient.signTypedData(typedData);
await bungeeProvider.submitOrder(quote, signature);
} else if (txSteps.length > 0) {
// Onchain flow: send transaction directly
const step = txSteps[0];
await walletClient.sendTransaction({
to: step.transaction.to,
data: step.transaction.data,
value: step.transaction.value ? BigInt(step.transaction.value) : undefined,
});
}
Approvals
Access approval information from the order checks:
const allowances = quote.order.checks?.allowances ?? [];
for (const { spender, tokenAddress, required } of allowances) {
// Approve token spend if needed
}
Tracking
Bungee uses API-based tracking. The SDK polls the status endpoint at a 5-second interval:
GET /api/v1/bungee/status?requestHash=<orderId>
No extra RPC URLs are needed — tracking is handled entirely through the Bungee API.
Next Step
See a complete working example: Execute Intent
References
- Bungee Protocol Documentation
- Bungee API Access — request production API keys
- API Reference — full type definitions for quotes, fees, and orders
- Concepts — how intent-based transfers work