Approving Non-Native Tokens

This section is only applicable to transfers of non-native tokens on EVM Compactible Chains. Non-native tokens include governance tokens, wrapped tokens, stablecoins, and oracle tokens.

If you are executing a transfer with a non-native token, our Swing Contract requires the right allowance limit to spend/withdraw funds (denominated in non-native tokens) from the designated wallet address. Depending on the non-native token amount you are looking to transfer, you want to call our /approve endpoint with a limit greater than or equal to the amount you are transferring.

You can use the /allowance endpoint to determine if you have already approved a sufficient limit to allow your non-native token transfer. Importantly, the allowance limit is specific to the token, chain and bridge. So you must approve an allowance limit every time for every unique transfer combination of token, chain or bridge.

Checking Allowance Limit

We can query our /allowance endpoint in the following manner to get the allowance limit.

The full API reference for our /allowance endpoint can be found in the API reference section.

Making a Request

URL: https://swap.prod.swing.xyz/v0/transfer/allowance

Query Parameters:

PropertyExampleDescription
fromChainethereumSource Chain slug
fromAddress0x018c15DA1239B84b08283799B89045CD476BBbBbSender's wallet address
tokenAddress0x0000000000000000000000000000000000000000Source Token Address
tokenSymbolETHSource Token slug
toTokenAddress0x0000000000000000000000000000000000000000Destination Token Address.
toTokenSymbolUSDCDestination Token slug
toChainpolygonDestination Chain slug
projectIdreplugYour project's ID
bridgeopenoceanselected bridge/route to execute transaction
contractCallfalseIndicate contract call allowance limit
const getAllowance = async () => {
  const result = await axios.get(
    'https://swap.prod.swing.xyz/v0/transfer/allowance',
    {
      fromChain: 'ethereum',
      tokenSymbol: 'ETH',
      tokenAddress: '0x0000000000000000000000000000000000000000',
      bridge: 'openocean',
      fromAddress: '0x018c15DA1239B84b08283799B89045CD476BBbBb',
      toChain: 'polygon',
      toTokenSymbol: 'USDC',
      toTokenAddress: '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359',
      projectId: 'replug',
    },
  );
  return result.data.allowance;
};

This will always only return the allowance limit for that specific token, on the specific chain for that specific bridge:

{
  "allowance": "1000000"
}

Requesting Approval Calldata

If you need to approve a higher allowance limit, you can query our /approve endpoint in the following manner

The full API reference for our /approve endpoint can be found in the API reference section.

Making a Request

URL: https://swap.prod.swing.xyz/v0/transfer/approve

Query Parameters:

PropertyExampleDescription
tokenAmount1000000000000000000Amount of the source token being sent (in wei for ETH).
fromChainethereumSource Chain slug
fromAddress0x018c15DA1239B84b08283799B89045CD476BBbBbSender's wallet address
fromTokenAddress0x0000000000000000000000000000000000000000Source Token Address
tokenSymbolETHSource Token slug
toTokenAddress0x0000000000000000000000000000000000000000Destination Token Address.
toTokenSymbolUSDCDestination Token slug
toChainpolygonDestination Chain slug
projectIdreplugYour project's ID
bridgeopenoceanselected bridge/route to execute transaction
contractCallfalseIndicate contract call allowance limit
const getApprovalCallData = async () => {
  const result = await axios.get(
    'https://swap.prod.swing.xyz/v0/transfer/approve',
    {
      fromChain: 'ethereum',
      tokenSymbol: 'ETH',
      tokenAddress: '0x0000000000000000000000000000000000000000',
      bridge: 'openocean',
      fromAddress: '0x018c15DA1239B84b08283799B89045CD476BBbBb',
      toChain: 'polygon',
      toTokenSymbol: 'USDC',
      toTokenAddress: '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359',
      tokenAmount: 100000000,
      projectId: 'replug',
    },
  );
  return result.data;
};

It is important to note that executing an approval is optional and only required for Non-Native swap/bridge transactions.

An approval is required only if the allowance limit from the /allowance enpdoint is less than or equal to the tokenAmount supplied in the quote.

Since approve is a contract-level function, Swing only returns the necessary call-data that will need to be signed and executed by the local wallet (ie. Metamask, Coinbase Wallet, WalletConnect, etc).

{
  "data": "0x095ea7b30000000000000000000000008ea23242...",
  "to": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
  "from": "0x184AbEfBdCa24Ce0Dd964a74f6d5E69CE44D9579",
  "fromChain": {
    "chainId": 1,
    "slug": "ethereum",
    "name": "Ethereum",
    "protocolType": "evm"
  }
}

It's important to note that the token approval process is only available for EVM Compatible chains. Meaning that the source chain you supply to the /approve must be an EVM chain. To determine if a chain is EVM-compatible, check its type property, which is returned when you call the /chains endpoint.

{
  "id": "42161",
  "slug": "arbitrum",
  "name": "Arbitrum One",
  "logo": "https://raw.githubusercontent.com/polkaswitch/info/logo.png",
  "type": "evm", // Determines the chain's type. Other types include: "solana" | "bitcoin" | "ibc" | "multiversx"
  "tokenExplorer": "https://arbiscan.io/tokens/{address}",
  "txExplorer": "https://arbiscan.io/tx/{txHash}",
  "rpcUrl": "https://arb-mainnet.g.alchemy.com/v2/eyH6eI33QZYXEx7g4cZFnlBlP6AEVGWZ",
  "singleChainSwap": true,
  "singleChainStaking": true,
  "nativeToken": {
    "symbol": "ETH",
    "decimals": 18,
    "logo": "https://raw.githubusercontent.com/eth.jpg",
    "address": "0x0000000000000000000000000000000000000000",
    "chain": "arbitrum"
  }
}

Skipping this check will result in the /approval endpoint returning an error to the user:

{
  "statusCode": 400,
  "message": "Non-evm is not supported for approval method: solana",
  "error": "Bad Request"
}

Requesting Approval Calldata for Contract Calls

If you need to approve a higher allowance limit for a Contract call transaction, you can set the contractCall API parameter to true

Making a Request

URL: https://swap.prod.swing.xyz/v0/transfer/approve

Query Parameters:

PropertyExampleDescription
contractCallfalseIndicate contract call operation
const getApprovalCallData = async () => {
  const result = await axios.get(
    'https://swap.prod.swing.xyz/v0/transfer/approve',
    {
      fromChain: 'ethereum',
      tokenSymbol: 'ETH',
      tokenAddress: '0x0000000000000000000000000000000000000000',
      bridge: 'openocean',
      fromAddress: '0x018c15DA1239B84b08283799B89045CD476BBbBb',
      toChain: 'polygon',
      toTokenSymbol: 'USDC',
      toTokenAddress: '0x3c499c542cef5e3811e1192ce70d8cc03d5c3359',
      tokenAmount: 100000000,
      contractCall: true,
    },
  );
  return result.data;
};

Since approve is a contract-level function, Swing only returns the necessary call-data that will need to be signed and executed by the local wallet (ie. Metamask, Coinbase Wallet, WalletConnect, etc).

{
  "data": "0x095ea7b30000000000000000000000008ea23242...",
  "to": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
  "from": "0x184AbEfBdCa24Ce0Dd964a74f6d5E69CE44D9579",
  "fromChain": {
    "chainId": 1,
    "slug": "ethereum",
    "name": "Ethereum",
    "protocolType": "evm"
  }
}

It's important to note that the token approval process is only available for EVM Compatible chains. Meaning that the source chain you supply to the /approve must be an EVM chain. To determine if a chain is EVM-compatible, check its type property, which is returned when you call the /chains endpoint.

{
  "id": "42161",
  "slug": "arbitrum",
  "name": "Arbitrum One",
  "logo": "https://raw.githubusercontent.com/polkaswitch/info/logo.png",
  "type": "evm", // Determines the chain's type. Other types include: "solana" | "bitcoin" | "ibc" | "multiversx"
  "tokenExplorer": "https://arbiscan.io/tokens/{address}",
  "txExplorer": "https://arbiscan.io/tx/{txHash}",
  "rpcUrl": "https://arb-mainnet.g.alchemy.com/v2/eyH6eI33QZYXEx7g4cZFnlBlP6AEVGWZ",
  "singleChainSwap": true,
  "singleChainStaking": true,
  "nativeToken": {
    "symbol": "ETH",
    "decimals": 18,
    "logo": "https://raw.githubusercontent.com/eth.jpg",
    "address": "0x0000000000000000000000000000000000000000",
    "chain": "arbitrum"
  }
}

Skipping this check will result in the /approval endpoint returning an error to the user:

{
  "statusCode": 400,
  "message": "Non-evm is not supported for approval method: solana",
  "error": "Bad Request"
}