DEX API

Build bridge applications#

In this guide, we’ll show you how to do a cross-chain swap using USDT on the Ethereum chain for USDC on the Arbitrum chain as an example provided by OKX DEX. This process includes:

  • Set up your environment
  • Check allowance
  • Check approval parameters and send the approved transaction
  • Get the toChainId list that can be traded through fromChainId, and select one of the chains as the destination chain
  • Get the token list through toChainId and select one of the tokens as the destination token
  • Request the /quote endpoint and get the quote data, also retrieving the bridge ID
  • Request the /build-tx endpoint and send the cross-chain swap transaction
  • Get the transaction status
Note
This example uses the Ethereum chain network; however, the same method also supports horizontal expansion, which increases the capacity and throughput of a chain by adding nodes. At the same time, it allows the writing and execution of smart contracts, providing more possibilities for developing applications.

1. Set up your environment#

Import the necessary Node.js libraries and set your environment variables as well as define helper functions and assembly parameters Node.js Environment Settings.

2. Check allowance#

Taking ETH chain as an example#

  • This demo is in JavaScript
  1. Connect to an Ethereum node: You need to ensure that you have connected to an available Ethereum node. You can use web3.js or other Ethereum development libraries to connect to the node. In the code, you need to specify the node's HTTP or WebSocket endpoint.
  2. Obtain a token contract instance: Using the contract address and ABI of the token, you need to create an instance of the token contract. You can use the web3.eth.Contract in web3.js to achieve this. Pass the contract address and ABI as arguments to the contract instance.
  3. Query the authorized amount: Query the authorized allowance by calling the allowance function of the contract instance. This function requires two parameters: the owner's address and the authorized party's address (spenderAddress). You can query the authorized allowance by providing these two addresses during the call.
  4. The spenderAddress can refer to the dexTokenApproveAddress from Here in the Response interface.。
const { Web3 } = require('web3');
// Connect to an Ethereum node
const web3 = new Web3('https://xxxxx');
// token address and  ABI
const tokenAddress = '0xxxxxxxxx';
// user address
const ownerAddress = '0xxxxxxxx';
// ETH dex token approval address
const spenderAddress = '0x40aa958dd87fc8305b97f2ba922cddca374bcd7f';


const tokenABI = [
    {
        "constant": true,
        "inputs": [
            {
                "name": "_owner",
                "type": "address"
            },
            {
                "name": "_spender",
                "type": "address"
            }
        ],
        "name": "allowance",
        "outputs": [
            {
                "name": "",
                "type": "uint256"
            }
        ],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
    }
];


// Create token contract instance
const tokenContract = new web3.eth.Contract(tokenABI, tokenAddress);
// Query token approve allowance function
async function getAllowance(ownerAddress, spenderAddress) {
    try {
        const allowance = await tokenContract.methods.allowance(ownerAddress, spenderAddress).call();
        console.log(`Allowance for ${ownerAddress} to ${spenderAddress}: ${allowance}`);
    } catch (error) {
        console.error('Failed to query allowance:', error);
    }
}

getAllowance(ownerAddress, spenderAddress).then(r => console.log(r));

2.2 Get allowance amount#

Note
Get allowance amount. If allowanceAmount < fromTokenAmount, check out step 3. If allowanceAmount > fromTokenAmount, check out step 3 to increase the allowance amount, or go directly to step 4.
const { data: allowanceData } = await getAllowanceData();
const allowanceAmount = allowanceData?.[0]?.allowanceAmount;

3. Check approval parameters and send the approved transaction#

Note
Since allowanceAmount < fromTokenAmount, we need to approve this token.

3.1 Define approval parameters#

Next, define the parameters for the transaction approval you want to perform.

const getApproveTransactionParams = {
  chainId: fromChainId,
  tokenContractAddress: fromTokenAddress,
  userWalletAddress,
  approveAmount: fromTokenAmount,
};

3.2 Define helper functions#

Define helper functions to interact with the DEX API.

const approveTransaction = async () => {
  const { apiRequestUrl, path } = getAggregatorRequestUrl(
    '/approve-transaction',
    getApproveTransactionParams
  );

  return fetch(apiRequestUrl, {
    method: 'get',
    headers: headersParams,
  })
    .then((res) => res.json())
    .then((res) => {
      return res;
    });
};

3.3 Get the transaction approval tx and send the approved transaction#

if (parseFloat(allowanceAmount) < parseFloat(fromTokenAmount)) {
  const { data } = await approveTransaction(allowanceAmount);
  let allowanceParams = {
    ...{ data: data[0].data }, // You can modify the data content you want in accordance with the Web3 official website
  };
  const { rawTransaction } = await web3.eth.accounts.signTransaction(
    allowanceParams,
    privateKey
  );
  await web3.eth.sendSignedTransaction(rawTransaction);
}

4. Get the toChainId list that can be traded through fromChainId, and select one of the chains as the destination chain#

4.1 Define the parameters to get a tradable destination chain#

Next, define the parameters to get the tradable toChainId list through fromChainId.

const toChainListParams = {
  chainId: fromChainId,
};

4.2 Define helper functions#

Define helper functions to interact with the DEX API.

const getSupportedChain = async () => {
  const { apiRequestUrl, path } = getCrossChainBaseUrl(
    '/supported/chain',
    toChainListParams
  );
  return fetch(apiRequestUrl, {
    method: 'get',
    headers: headersParams,
  })
    .then((res) => res.json())
    .then((res) => {
      return res;
    });
};

4.3 Get the supported destination chains and select the Arbitrum chain.#

You can also select one of the other chains as the destination chain based on the list.

const { data: supportedChainList } = await getSupportedChain();
const selectChainItem = supportedChainList.find((item) => {
  return item.chainName === 'Arbitrum';
});
toChainId = selectChainItem?.chainId;

5. Get the token list through toChainId, and select one of the tokens as the destination token#

5.1 Define the parameters for getting a list of tradable destination tokens#

Next, define the parameters to get a list of tradable tokens through toChainId.

const toChainTokenListParams = {
  chainId: toChainId,
};

5.2 Define helper functions#

Define helper functions to interact with the DEX API.

const getToChainTokenList = async () => {
  const { apiRequestUrl, path } = getAggregatorRequestUrl(
    '/all-tokens',
    toChainTokenListParams
  );
  return fetch(apiRequestUrl, {
    method: 'get',
    headers: headersParams,
  })
    .then((res) => res.json())
    .then((res) => {
      return res;
    });
};

5.3 Get the tradable token list and select USDC.#

You can also select another token as the destination token.

const { data: toChainTokenList } = await getToChainTokenList();
const selectToChainToken = toChainTokenList.find((item) => {
  return item.tokenSymbol === 'USDC';
});
toTokenAddress = selectToChainToken?.tokenContractAddress;

6. Request the /quote endpoint and get the quote data, also retrieving the bridge ID#

6.1 Define quote parameters#

Next, define the parameters to get basic information of the quote and the router list.

const quoteParams = {
  fromChainId,
  toChainId,
  fromTokenAddress,
  toTokenAddress,
  amount: fromTokenAmount,
  slippage,
};

6.2 Define helper functions#

Define helper functions to interact with the DEX API.

const getQuote = async () => {
  const { apiRequestUrl, path } = getCrossChainBaseUrl('/quote', quoteParams);
  return fetch(apiRequestUrl, {
    method: 'get',
    headers: headersParams,
  })
    .then((res) => res.json())
    .then((res) => {
      return res;
    });
};

6.3 Get the quote information and select a router as the transaction router#

const { data: quoteData } = await getQuote();
bridgeId = quoteData[0]?.routerList[0]?.router?.bridgeId;

7. Request the /build-tx endpoint and send the cross-chain swap transaction#

7.1 Define cross-chain swap parameters#

Next, define the parameters to get the tx information of the cross-chain swap.

const swapParams = {
  fromChainId: fromChainId,
  toChainId: toChainId,
  fromTokenAddress,
  toTokenAddress,
  amount: fromTokenAmount,
  slippage,
  userWalletAddress,
  bridgeId,
};

7.2 Define helper functions#

Define helper functions to interact with the DEX API.

const getSwapData = async () => {
  const { apiRequestUrl, path } = getCrossChainBaseUrl('/build-tx', swapParams);
  return fetch(apiRequestUrl, {
    method: 'get',
    headers: headersParams,
  })
    .then((res) => res.json())
    .then((res) => {
      return res;
    });
};

7.3 Request the /build-tx endpoint to get the tx information and send the cross-chain swap transaction#

const { data: swapData } = await getSwapData();
const swapDataTxInfo = swapData[0].tx;
const nonce = await web3.eth.getTransactionCount(userWalletAddress, 'latest');
// You can obtain the latest nonce and process the hexadecimal numbers starting with 0x according to your needs
let signTransactionParams = {
  data: swapDataTxInfo.data,
  gasPrice: swapDataTxInfo.gasPrice,
  to: swapDataTxInfo.to,
  value: swapDataTxInfo.value,
  nonce,
};
const { rawTransaction } = await web3.eth.accounts.signTransaction(
  signTransactionParams,
  privateKey
);
const chainTxInfo = await web3.eth.sendSignedTransaction(rawTransaction);
transactionTx = chainTxInfo;

8. Get the transaction status#

8.1 Define query parameters#

Next, define the parameters, mainly the source chain hash address.

const getCheckStatusParams = {
  hash: transactionTx,
};

8.2 Define helper functions#

Define helper functions to interact with the DEX API.

const checkTransactionStatus = async () => {
  const { apiRequestUrl, path } = getCrossChainBaseUrl(
    '/status',
    getCheckStatusParams
  );
  return fetch(apiRequestUrl, {
    method: 'get',
    headers: headersParams,
  })
    .then((res) => res.json())
    .then((res) => {
      return res;
    });
};

8.3 Get the transaction status#

Note
You can also add a polling method to get order status in real time. Here is an example of a single query.
const { data: statusInfo } = await checkTransactionStatus();
console.log(statusInfo?.data[0]?.detailStatus);