Cross-Chain Bridging
The CoW Protocol SDK provides seamless cross-chain token transfers through integration with multiple bridge providers. This enables you to swap tokens across different blockchain networks in a single transaction.
Installation
npm install @cowprotocol/sdk-bridging
Basic Usage
Initialize the BridgingSdk
import {
SupportedChainId,
BridgingSdk,
QuoteBridgeRequest,
OrderKind,
assertIsBridgeQuoteAndPost,
} from '@cowprotocol/sdk-bridging'
import { EthersV6Adapter } from '@cowprotocol/sdk-ethers-v6-adapter'
import { JsonRpcProvider, Wallet } from 'ethers'
// Configure the adapter
const provider = new JsonRpcProvider('YOUR_RPC_URL')
const wallet = new Wallet('YOUR_PRIVATE_KEY', provider)
const adapter = new EthersV6Adapter({ provider, signer: wallet })
// Initialize bridging SDK
const bridging = new BridgingSdk(adapter, options)
Get a Cross-Chain Quote
const parameters: QuoteBridgeRequest = {
// Cross-chain orders are always SELL orders (BUY not supported yet)
kind: OrderKind.SELL,
// Sell token (and source chain)
sellTokenChainId: SupportedChainId.ARBITRUM_ONE,
sellTokenAddress: '0xfff9976782d46cc05630d1f6ebab18b2324d6b14',
sellTokenDecimals: 18,
// Buy token (and target chain)
buyTokenChainId: SupportedChainId.BASE,
buyTokenAddress: '0x0625afb445c3b6b7b929342a04a22599fd5dbb59',
buyTokenDecimals: 18,
// Amount to sell
amount: '120000000000000000',
signer: adapter.signer,
// Optional parameters
appCode: 'YOUR_APP_CODE',
}
// Get a quote (and the post callback) for a cross-chain swap
const quoteResult = await sdk.getQuote(parameters)
// Assert that the quote result is of type BridgeQuoteAndPost
// (type for cross-chain quotes, as opposed to QuoteAndPost for single-chain quotes).
assertIsBridgeQuoteAndPost(quoteResult)
const { swap, bridge, postSwapOrderFromQuote } = quoteResult
// Display all data related to the swap (costs, amounts, appData including the bridging hook, etc.)
console.log('Swap info', swap)
// Display all data related to the bridge (costs, amounts, provider info, hook, and the bridging quote)
console.log('Bridge info', bridge)
// Get the buy amount after slippage in the target chain
const { buyAmount } = bridge.amountsAndCosts.afterSlippage
if (confirm(`You will get at least: ${buyAmount}, ok?`)) {
const orderId = await postSwapOrderFromQuote()
console.log('Order created, id: ', orderId)
}
Cross-chain orders are always SELL orders. BUY orders are not yet supported for cross-chain swaps.
Multi-Provider Quotes
Get Quotes from All Providers
The getMultiQuotes() method allows you to get quotes from multiple bridge providers simultaneously:
import { MultiQuoteRequest } from '@cowprotocol/sdk-bridging'
const multiQuoteRequest: MultiQuoteRequest = {
quoteBridgeRequest: parameters, // Same parameters as above
providerDappIds: ['provider1', 'provider2'], // Optional: specify which providers to query
advancedSettings: {
slippageBps: 100, // 1% slippage tolerance
},
options: {
totalTimeout: 15000, // 15 seconds total timeout
providerTimeout: 8000, // 8 seconds per provider timeout
}
}
// Get quotes from all providers
const results = await bridgingSdk.getMultiQuotes(multiQuoteRequest)
results.forEach((result) => {
if (result.quote) {
console.log(`Quote from ${result.providerDappId}:`, result.quote)
} else {
console.log(`Error from ${result.providerDappId}:`, result.error?.message)
}
})
Progressive Quote Results
Receive quotes progressively as each provider responds:
const progressiveResults: MultiQuoteResult[] = []
const multiQuoteRequest: MultiQuoteRequest = {
quoteBridgeRequest: parameters,
options: {
// Receive quotes as they arrive
onQuoteResult: (result) => {
progressiveResults.push(result)
if (result.quote) {
console.log(`✅ Quote received from ${result.providerDappId}`)
// Update UI immediately with the new quote
displayQuoteInUI(result)
} else {
console.log(`❌ Error from ${result.providerDappId}: ${result.error?.message}`)
}
},
totalTimeout: 20000, // 20 seconds total timeout
providerTimeout: 5000 // 5 seconds per provider timeout
}
}
// This will return all results once completed (or timed out)
const finalResults = await bridgingSdk.getMultiQuotes(multiQuoteRequest)
console.log(`Received ${finalResults.filter(r => r.quote).length} successful quotes out of ${finalResults.length} providers`)
Best Quote Selection
Use getBestQuote() to get only the best quote from all available providers:
// Get the best quote from all available providers
const bestQuote = await bridgingSdk.getBestQuote({
quoteBridgeRequest: parameters,
providerDappIds: ['provider1', 'provider2'], // Optional: specify which providers to query
advancedSettings: {
slippageBps: 100, // 1% slippage tolerance
},
options: {
totalTimeout: 15000, // 15 seconds total timeout
providerTimeout: 8000, // 8 seconds per provider timeout
}
})
if (bestQuote?.quote) {
console.log(`Best quote from ${bestQuote.providerDappId}:`, bestQuote.quote)
const { buyAmount } = bestQuote.quote.bridge.amountsAndCosts.afterSlippage
console.log(`You will receive: ${buyAmount} tokens`)
} else if (bestQuote?.error) {
console.log('All providers failed, first error:', bestQuote.error.message)
}
Progressive Best Quote Updates
let currentBest: MultiQuoteResult | null = null
const bestQuote = await bridgingSdk.getBestQuote({
quoteBridgeRequest: parameters,
options: {
// Called whenever a better quote is found
onQuoteResult: (result) => {
currentBest = result
console.log(`🚀 New best quote from ${result.providerDappId}!`)
if (result.quote) {
const buyAmount = result.quote.bridge.amountsAndCosts.afterSlippage.buyAmount
console.log(`Better quote found: ${buyAmount} tokens`)
// Update UI immediately with the new best quote
updateBestQuoteInUI(result)
}
},
totalTimeout: 20000, // 20 seconds total timeout
providerTimeout: 5000 // 5 seconds per provider timeout
}
})
console.log('Final best quote:', bestQuote)
Use getBestQuote() when you only need the single best quote. Use getMultiQuotes() when you need to display all available options to users.
Provider Management
Get Available Providers
// Get all active providers
const providers = bridgingSdk.getAvailableProviders()
providers.forEach((provider) => {
console.log(`Provider: ${provider.info.name}`)
console.log(`Dapp ID: ${provider.info.dappId}`)
console.log(`Networks: ${provider.info.supportedChains.join(', ')}`)
})
Filter Active Providers
// Initially, all configured providers are available
const allProviders = bridgingSdk.getAvailableProviders()
console.log(`Total providers: ${allProviders.length}`)
// Filter to use only specific providers
bridgingSdk.setAvailableProviders(['across', 'hop-protocol'])
// Now only the specified providers will be used
const filteredProviders = bridgingSdk.getAvailableProviders()
console.log(`Active providers: ${filteredProviders.length}`)
// Reset to use all providers again
bridgingSdk.setAvailableProviders([])
const resetProviders = bridgingSdk.getAvailableProviders()
console.log(`Reset to all providers: ${resetProviders.length}`)
Timeout Configuration
The multi-quote methods support two types of timeouts:
const results = await bridgingSdk.getMultiQuotes({
quoteBridgeRequest: parameters,
options: {
// Global timeout: Maximum time to wait for all providers to complete
totalTimeout: 30000, // 30 seconds (default)
// Individual provider timeout: Maximum time each provider has to respond
providerTimeout: 15000, // 15 seconds (default)
onQuoteResult: (result) => {
// Handle progressive results
console.log(`Received result from ${result.providerDappId}`);
}
}
});
How timeouts work:
providerTimeout: Each provider has this amount of time to complete their quote request. If exceeded, that provider returns a timeout error.
totalTimeout: The total time to wait for all providers. After this time, any remaining providers are marked as timed out.
- Providers that complete within their individual timeout but after the global timeout will still be included in the final results.
Comparison Table
| Feature | getBestQuote() | getMultiQuotes() |
|---|
| Returns | Single best result | Array of all results |
| Progressive Callbacks | Only for better quotes | For all results (success & error) |
| Error Handling | Returns first error if all fail | Returns all errors in array |
| Performance | Optimized for best result only | Returns complete data set |
| Use Case | When you only need the best quote | When you need to compare all options |
Error Handling
try {
const quoteResult = await bridgingSdk.getQuote(parameters)
assertIsBridgeQuoteAndPost(quoteResult)
const { swap, bridge, postSwapOrderFromQuote } = quoteResult
// Post the order
const orderId = await postSwapOrderFromQuote()
console.log('Order created:', orderId)
} catch (error) {
if (error.message.includes('No available providers')) {
console.error('No bridge providers available for this route')
} else if (error.message.includes('timeout')) {
console.error('Quote request timed out')
} else {
console.error('Failed to get cross-chain quote:', error)
}
}
Next Steps