Skip to main content

Overview

The GetExactOutputRoutes endpoint retrieves available token routes for exact output swaps. Given a destination token, it returns all source tokens that can be swapped to achieve that exact output amount. This is essential for building UIs where users specify exactly how much they want to receive.

Use Cases

  • Build “I want to receive exactly X tokens” interfaces
  • Find which source tokens can route to a specific destination
  • Payment flows where exact amounts are required
  • Invoice payments requiring precise token amounts
  • DeFi integrations with fixed deposit amounts

Request Parameters

Required Fields

  • destinationChainId (number): The chain ID of the destination token
  • destinationTokenAddress (string): The token address to receive

Optional Fields

  • originChainId (number): Filter routes by source chain
  • originTokenAddress (string): Filter to routes from a specific token
  • ownerAddress (string): User’s wallet address (for balance-aware filtering)

Response

The response includes:
  • tokens (TokenInfo[]): Array of source tokens that can route to the destination

TokenInfo Object Structure

Each token object contains:
  • chainId (number): Chain where the token exists
  • address (string): Token contract address
  • name (string): Token name
  • symbol (string): Token symbol
  • decimals (number): Token decimals
  • supportsBridging (boolean, optional): Whether the token supports cross-chain bridging
  • logoUri (string, optional): URL to token logo
  • featured (boolean): Whether this is a featured/popular token
  • featureIndex (number): Sort order for featured tokens

Examples

Find Source Tokens for USDC on Base

const response = await fetch('https://trails-api.sequence.app/rpc/Trails/GetExactOutputRoutes', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Access-Key': 'YOUR_API_KEY'
  },
  body: JSON.stringify({
    destinationChainId: 8453, // Base
    destinationTokenAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' // USDC on Base
  })
});

const { tokens } = await response.json();

console.log('Tokens that can swap to USDC on Base:');
tokens.forEach(token => {
  console.log(`- ${token.symbol} on chain ${token.chainId}`);
});

Filter by Source Chain

const response = await fetch('https://trails-api.sequence.app/rpc/Trails/GetExactOutputRoutes', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Access-Key': 'YOUR_API_KEY'
  },
  body: JSON.stringify({
    destinationChainId: 8453, // Base
    destinationTokenAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC
    originChainId: 1 // Only show routes from Ethereum mainnet
  })
});

const { tokens } = await response.json();

console.log('Ethereum tokens that can swap to USDC on Base:');
tokens.forEach(token => {
  console.log(`- ${token.symbol}: ${token.address}`);
});

Build Payment Source Selector

import { useEffect, useState } from 'react';

interface TokenInfo {
  chainId: number;
  address: string;
  name: string;
  symbol: string;
  decimals: number;
  logoUri?: string;
  featured: boolean;
}

interface PaymentSourceSelectorProps {
  targetChainId: number;
  targetTokenAddress: string;
  userAddress: string;
  onSelect: (token: TokenInfo) => void;
}

export const PaymentSourceSelector = ({
  targetChainId,
  targetTokenAddress,
  userAddress,
  onSelect
}: PaymentSourceSelectorProps) => {
  const [tokens, setTokens] = useState<TokenInfo[]>([]);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch('https://trails-api.sequence.app/rpc/Trails/GetExactOutputRoutes', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Access-Key': 'YOUR_API_KEY'
      },
      body: JSON.stringify({
        destinationChainId: targetChainId,
        destinationTokenAddress: targetTokenAddress,
        ownerAddress: userAddress
      })
    })
      .then(res => res.json())
      .then(({ tokens }) => {
        // Sort featured tokens first
        const sorted = tokens.sort((a: TokenInfo, b: TokenInfo) => {
          if (a.featured && !b.featured) return -1;
          if (!a.featured && b.featured) return 1;
          return 0;
        });
        setTokens(sorted);
        setLoading(false);
      });
  }, [targetChainId, targetTokenAddress, userAddress]);

  if (loading) return <div>Loading payment options...</div>;

  return (
    <div>
      <h3>Pay with:</h3>
      {tokens.map(token => (
        <button
          key={`${token.chainId}-${token.address}`}
          onClick={() => onSelect(token)}
        >
          {token.logoUri && <img src={token.logoUri} alt={token.symbol} />}
          {token.symbol} (Chain {token.chainId})
        </button>
      ))}
    </div>
  );
};

Check Specific Route Availability

const response = await fetch('https://trails-api.sequence.app/rpc/Trails/GetExactOutputRoutes', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Access-Key': 'YOUR_API_KEY'
  },
  body: JSON.stringify({
    destinationChainId: 8453,
    destinationTokenAddress: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
    originChainId: 42161, // Arbitrum
    originTokenAddress: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831' // USDC on Arbitrum
  })
});

const { tokens } = await response.json();

if (tokens.length > 0) {
  console.log('Route is available!');
} else {
  console.log('No direct route found');
}

When to Use Exact Output

Use GetExactOutputRoutes when:
  • User needs to receive a specific amount (e.g., paying a $100 invoice)
  • Protocol requires exact deposit amounts
  • NFT purchases with fixed prices
  • Subscription payments with fixed amounts
Use GetExactInputRoutes when:
  • User wants to spend a specific amount
  • “Swap all” functionality
  • User specifies how much to send
For the best UX, combine this with GetTokenPrices to show users the estimated cost in USD for each source token option.

Next Steps