Route swaps (or multi-hop swaps) allow you to trade between two assets by routing the transaction through one or more intermediary pools. This is useful when there’s no direct liquidity pool for a specific asset pair but a path exists through other pools.
The Flashnet SDK simplifies this process by allowing you to define a series of “hops” that make up the desired route.
The maximum number of hops allowed in a single route swap is 4.
Simulating a Route Swap
Before executing, it’s crucial to simulate the route swap to get an estimate of the expected output, price impact, and fees.
async function simulateRouteSwap() {
try {
const simulation = await client.simulateRouteSwap({
hops: [
{
poolId: "btc-usdb-pool-id",
assetInAddress: "bitcoin-pubkey",
assetOutAddress: "usdb-pubkey",
},
{
poolId: "usdb-eur-pool-id",
assetInAddress: "usdb-pubkey",
assetOutAddress: "eur-pubkey",
},
],
amountIn: "10000000", // 0.1 BTC
maxRouteSlippageBps: "100", // 1%
});
console.log('Expected final output amount:', simulation.outputAmount);
console.log('Total price impact %:', simulation.totalPriceImpactPct);
console.log('Hop breakdown:', simulation.hopBreakdown);
return simulation;
} catch (error) {
console.error('Route swap simulation failed:', error);
}
}
The simulation provides a breakdown for each hop, allowing you to see how the swap progresses at each stage.
Executing a Route Swap
To execute the swap, you provide the same hop structure along with slippage parameters. The SDK handles the transfer to the first pool and the subsequent routing automatically.
async function executeRouteSwap() {
try {
// First, simulate to get an expected output
const simulation = await client.simulateRouteSwap({
hops: [
{ poolId: "btc-usdb-pool-id", assetInAddress: "bitcoin-pubkey", assetOutAddress: "usdb-pubkey" },
{ poolId: "usdb-eur-pool-id", assetInAddress: "usdb-pubkey", assetOutAddress: "eur-pubkey" },
],
amountIn: "10000000", // 0.1 BTC
maxRouteSlippageBps: "100",
});
if (!simulation) {
throw new Error("Simulation failed, cannot execute.");
}
// Set a minimum amount out based on simulation to protect against slippage
const minAmountOut = (BigInt(simulation.outputAmount) * 99n / 100n).toString(); // 1% tolerance
const response = await client.executeRouteSwap({
hops: [
{
poolId: "btc-usdb-pool-id",
assetInAddress: "bitcoin-pubkey",
assetOutAddress: "usdb-pubkey",
},
{
poolId: "usdb-eur-pool-id",
assetInAddress: "usdb-pubkey",
assetOutAddress: "eur-pubkey",
},
],
initialAssetAddress: "bitcoin-pubkey",
inputAmount: "10000000",
maxRouteSlippageBps: "100", // 1%
minAmountOut: minAmountOut,
});
console.log('Route swap successful!');
console.log('Final amount out:', response.outputAmount);
console.log('Final transfer ID:', response.finalOutboundTransferId);
} catch (error) {
console.error('Route swap execution failed:', error);
}
}
Integrator Fees
You can also specify integrator fees for the entire route or for individual hops.
async function executeRouteSwapWithFees() {
const minAmountOut = "950000"; // calculated from simulation
await client.executeRouteSwap({
hops: [
{
poolId: "btc-usdb-pool-id",
assetInAddress: "bitcoin-pubkey",
assetOutAddress: "usdb-pubkey",
hopIntegratorFeeRateBps: 20, // 0.2% fee for this specific hop
},
{
poolId: "usdb-eur-pool-id",
assetInAddress: "usdb-pubkey",
assetOutAddress: "eur-pubkey",
},
],
initialAssetAddress: "bitcoin-pubkey",
inputAmount: "10000000",
maxRouteSlippageBps: "100",
minAmountOut: minAmountOut,
integratorFeeRateBps: 10, // 0.1% fee for any hop that doesn't have a specific fee
integratorPublicKey: "your-integrator-pubkey",
});
}
Next Steps