Quickstart

This section of the documentation will be focused on teaching you how to effortlessly bridge and swap your digital assets by example using the Swing API.

Our cross-chain APIs are robust and enables you to do any of the following:

  • Fetch a list of chains and tokens.
  • Perform same chain and cross chain swaps.
  • Perform same chain and cross chain deposits/staking.

Our APIs also support cross-chain operations between multiple blockchains of different architectures, enabling developers to bridge their assets between the EVM and BTC chains, for example.

Steps: Executing a Bridge & Swap

The full API reference for our /quote, /allowance, /approve, /send and /status endpoints can be found in the API reference section.

Due to compliance reasons, to give your users the best user experience and to prevent failed transactions, we advise you to notify your users whether they're connecting from a restricted jurisdiction or not. Learn more here.

Bridge and Swap by example (Quick Copy and Paste Tutorial)

Let's get you started by demonstrating how you can quickly build up a transaction and send it over to Swing using a short example!

For our example, we're going to be bridging some USDC from the Ethereum network over to the MATIC on the Polygon network. For our API request client, we will be using axios for querying the Swing API.

Step 1: Gather transaction info

Before beginning a transaction, we must gather the source and destination chain information. Below are the list of parameter definitions that the Swing API accepts:

KeyExampleDescription
fromChainethereumThe blockchain where the transaction originates.
fromTokenAddress0x0000000000000000000000000000000000000000Source Token Address
fromUserAddress0x018c15DA1239B84b08283799B89045CD476BBbBbSender's wallet address
tokenSymbolETHSource Token slug
toTokenAddress0x0000000000000000000000000000000000000000Destination Token Address.
toChainpolygonDestination Source slug
toTokenAmount1000000000000000000Amount of the destination token being received.
toTokenSymbolMATICDestination Chain slug
toUserAddress0x018c15DA1239B84b08283799B89045CD476BBbBbReceiver's wallet address
tokenAmount1000000000000000000Amount of the source token being sent (in wei for ETH).
typeswapType of transaction.
projectIdreplugYour project's ID
routeSee Requesting a Quote pageSelected Route from /quote endpoint

Sample payload:

const transferParams = {
  fromChain: 'ethereum',
  fromTokenAddress: '0x0000000000000000000000000000000000000000',
  fromUserAddress: '0x018c15DA1239B84b08283799B89045CD476BBbBb',
  tokenSymbol: 'ETH',
  toTokenAddress: '0x0000000000000000000000000000000000000000',
  toChain: 'polygon',
  tokenAmount: '100000000000',
  toTokenSymbol: 'MATIC',
  toUserAddress: '0x018c15DA1239B84b08283799B89045CD476BBbBb',
  projectId: 'replug',
};

Step 2: Get a quote

Once we have our source and destination chain details, we have to request a qoute from Swing via the /qoute endpoint.

// Quote Payload
const quoteParams = {
  fromChain: 'ethereum',
  fromTokenAddress: '0x0000000000000000000000000000000000000000',
  fromUserAddress: '0x018c15DA1239B84b08283799B89045CD476BBbBb',
  tokenSymbol: 'ETH',
  toTokenAddress: '0x0000000000000000000000000000000000000000',
  toChain: 'polygon',
  tokenAmount: '100000000000',
  toTokenSymbol: 'MATIC',
  toUserAddress: '0x018c15DA1239B84b08283799B89045CD476BBbBb',
  projectId: 'replug',
};
 
const quotes = await axios.get(
  `https://swap.prod.swing.xyz/v0/transfer/quote`,
  {
    params: quoteParams,
  },
);

The quote contains a list of possible routes that can swap or bridge a user's assets. Each route includes the total amount of tokens a wallet holder must bridge, as well as the fees required for the transaction to go through.

The first item in the quotes array will always be the cheapest route, hence the term "Best Route".

const bestRoute = quotes.data.routes[0];
 
const toAmount = bestRoute.quote.amount;
const bridgeFee = bestRoute.quote.fees.find(
  (fee) => fee.type === 'bridge',
).amount;
const gasFee = bestRoute.quote.fees.find((fee) => fee.type === 'gas').amount;

The response schema for the quote endpoint can be found on the Request a Quote page.

Step 3: Get spender allowance limit (Optional)

Next, we have to verify if the wallet holder has already authorized Swing to access the transaction amount specified in the quote.

const allowanceParams = {
  bridge: bestRoute.quote.integration,
  fromAddress: '0x018c15DA1239B84b08283799B89045CD476BBbBb',
  fromChain: 'ethereum',
  toChain: 'polygon',
  tokenAddress: '0x0000000000000000000000000000000000000000',
  tokenSymbol: 'ETH',
  toTokenSymbol: 'MATIC',
  toTokenAddress: '0x0000000000000000000000000000000000000000',
  projectId: 'replug',
};
 
const checkAllowance = await axios.get(
  `https://swap.prod.swing.xyz/v0/transfer/allowance`,
  {
    params: allowanceParams,
  },
);

This endpoint return a property that holds the approved allownace called allowance:

{
  "allowance": "1000000"
}

Step 4: Get & Sign approval callData (Optional)

Next, we have to determine whether an approval is required. To do that, we have to check if the allowance from the /allowance endpoint is less than or equal to the tokenAmount specified in the quoteParams. If the allowance amount is less than or equal to the tokenAmount, then we must execute an approval to continue.

The /approval endpoint returns an unsigned callData that we must sign using a wallet like MetaMask or Coinbase Wallet.

if (checkAllowance.allowance < quoteParams.tokenAmount) {
  const approvalParams = {
    bridge: bestRoute.quote.integration,
    fromAddress: '0x018c15DA1239B84b08283799B89045CD476BBbBb',
    fromChain: 'ethereum',
    toChain: 'polygon',
    tokenAmount: '100000000000',
    tokenAddress: '0x0000000000000000000000000000000000000000',
    tokenSymbol: 'ETH',
    toTokenSymbol: 'MATIC',
    toTokenAddress: '0x0000000000000000000000000000000000000000',
    projectId: 'replug',
  };
 
  const approve = await axios.get(
    `https://swap.prod.swing.xyz/v0/transfer/approve`,
    {
      params: approvalParams,
    },
  );
 
  const provider = new ethers.providers.Web3Provider(window.ethereum); // using MetaMask Wallet
  const signer = provider.getSigner();
 
  const txResponse = await signer?.sendTransaction({
    data: sendTransaction.tx.data,
    from: sendTransaction.tx.from,
    to: sendTransaction.tx.to,
    value: sendTransaction.tx.value,
    gasLimit: sendTransaction.tx.gas,
  }); // <- `txResponse` contains the `txHash` of our transaction. You will need this later for getting a transaction's status.
 
  const receipt = await txResponse?.wait();
}

The response schema for the quote endpoint can be found on the Approving Non-Native Tokens page.

Step 5: Send transaction to Swing using the bestRoute via the /send

The /send endpoint will return an unsigned transaction callData that we will have to sign using a user's wallet:

const sendParams = {
  fromUserAddress: '0x018c15DA1239B84b08283799B89045CD476BBbBb',
  toUserAddress: '0x018c15DA1239B84b08283799B89045CD476BBbBb',
  tokenSymbol: 'ETH',
  fromTokenAddress: '0x0000000000000000000000000000000000000000',
  fromChain: 'ethereum',
  toTokenSymbol: 'MATIC',
  toTokenAddress: '0x0000000000000000000000000000000000000000',
  toChain: 'polygon',
  tokenAmount: '100000000000',
  route: bestRoute.route,
  projectId: 'replug',
};
 
const send = await axios.post(
  'https://swap.prod.swing.xyz/v0/transfer/send',
  {
    sendParams,
  },
  {
    headers: { 'Content-Type': 'application/json' },
  },
);

The unsigned callData will be returned in the tx object in the response

{
  "tx": {
    "from": "0x018c15DA1239B84b08283799B89045CD476BBbBb",
    "to": "0x39E3e49C99834C9573c9FC7Ff5A4B226cD7B0E63",
    "data": "0x301a3720000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
    "value": "0x0e35fa931a0000",
    "gas": "0x065749"
  }
}

Step 6: Sign transaction using a wallet using ethers.js and MetaMask

Pass the tx details to ether's sendTransaction function to sign the transaction and send it over to the network

const provider = new ethers.providers.Web3Provider(window.ethereum); // using MetaMask Wallet
const signer = provider.getSigner();
 
const txResponse = await signer.sendTransaction({
  data: sendTransaction.tx.data,
  from: sendTransaction.tx.from,
  to: sendTransaction.tx.to,
  value: sendTransaction.tx.value,
  gasLimit: sendTransaction.tx.gas,
}); // <- `txResponse` contains the `txHash` of our transaction. You will need this later for getting a transaction's status.
 
const receipt = await txResponse?.wait();

Executing this will bring up a MetaMask wallet prompt for the wallet holder to approve. The transaction officially begins once the wallet holder has approved the transaction.

Step 7: Check Transaction Status

After the transaction has been mined and a block created, you can check for a transaction's status via the /status endpoint by using the id property from the /send endpoint and our transaction's txHash:

const status = await axios.get(
  `https://swap.prod.swing.xyz/v0/transfer/status`,
  {
    params: {
      txHash: txResponse.txHash,
      id: sendTransaction.id,
    },
  },
);

Native Vs. Non-Native Bridge/Swaps

Native tokens are the fundamental currency of a blockchain. They are integral to the blockchain's protocol and are used for various purposes, including transactions and paying fees. For example, on the Bitcoin blockchain, the native token is Bitcoin (BTC), and on the Ethereum blockchain, it’s Ether (ETH).

Smart Contract tokens like ERC20 tokens, on the other hand, are not native to the blockchain but are a type of fungible Smart Contract based token standard used primarily on EVM-compatible blockchains.

Why this matters?

When sending a transaction involving an ERC20 token on the source chain, it is important to understand that if the transaction requires a smart contract to transfer tokens on behalf of the wallet holder, the wallet holder must first grant approval to that smart contract. This approval allows the smart contract to access and manage a specified amount of tokens from the user's wallet.

Native tokens, unlike ERC20 tokens, do not require any approval processes because they are the primary currency of the blockchain. This means that transactions involving native tokens can be executed directly without the need for a smart contract approval step.

Examples/Starter Projects

You can check out our examples and starter projects with our API integrated, which you can use as references to build your apps here.