DEX API

在 Ton 链上搭建兑换应用#

搭建单链应用#

在本指南中,我们将用一个示例来展示如何通过欧易 DEX 提供的 API 在 Ton 上用 Ton 兑换 JETTON,这个过程中的步骤包括:

  1. 设置你的环境
  2. 请求询价接口,获取询价数据
  3. 请求兑换接口,发起交易

1. 设置你的环境#

# --------------------- npm package ---------------------
npm install @ton/ton @ton/crypto @ton/core buffer @orbs-network
const cryptoJS = require('crypto-js'); // Import encryption modules for subsequent encryption calculations
const { TonClient, WalletContractV4, internal } = require("@ton/ton");
const { toNano, Cell } = require("@ton/core");
const { mnemonicToPrivateKey } = require("@ton/crypto");
const { getHttpEndpoint } = require("@orbs-network/ton-access");
// --------------------- environment variable ---------------------
const apiBaseUrl = 'https://www.okx.com/api/v5/dex/aggregator';
const chainId = '607';
// Native token contract address
const fromTokenAddress = 'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c';
// JETTON token contract address
const toTokenAddress = 'EQAQXlWJvGbbFfE8F3oS8s87lIgdovS455IsWFaRdmJetTon';
// your wallet address
const user = 'UQDoI2kiSNQZxxxxxxxxxxxx6lM2ZSxKkEw3k1'
const fromAmount = '1000000'
// user wallet private key
const privateKey = 'xxxxx';
// open api Secret key
const secretkey = 'xxxxx'
// Get the current time
const date = new Date();

// --------------------- util function ---------------------
function getAggregatorRequestUrl(methodName, queryParams) {
    return apiBaseUrl + methodName + '?' + (new URLSearchParams(queryParams)).toString();
}

// Check https://www.okx.com/zh-hans/web3/build/docs/waas/rest-authentication for api-key

const headersParams = {
    'Content-Type': 'application/json',
    // The api Key obtained from the previous application
    'OK-ACCESS-KEY': 'xxxxx',
    'OK-ACCESS-SIGN': cryptoJS.enc.Base64.stringify(
    // The field order of headersParams should be consistent with the order of quoteParams.
    // example : quote  ==>   cryptoJS.HmacSHA256(date.toISOString() + 'GET' + '/api/v5/dex/aggregator/quote?amount=1000000&chainId=607&toTokenAddress=EQAQXlWJvGbbFfE8F3oS8s87lIgdovS455IsWFaRdmJetTon&fromTokenAddress=EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c', secretKey)
        cryptoJS.HmacSHA256(date.toISOString() + 'GET' + '/api/v5/dex/aggregator/xxx/xxx/xxx', secretKey)
    ),
    // Convert the current time to the desired format
    'OK-ACCESS-TIMESTAMP': date.toISOString(),
    // The password created when applying for the key
    'OK-ACCESS-PASSPHRASE': 'xxxxxxx',
};
提示

暂不支持额外接收地址。

2. 请求询价接口,拿到询价数据#

2.1 定义询价参数#

  • 接下来,定义询价参数,获取询价的基础信息和路径列表信息。
const quoteParams = {
  amount: fromAmount,
  chainId: chainId,
  toTokenAddress: toTokenAddress,
  fromTokenAddress: fromTokenAddress,
};

2.2 定义辅助函数#

  • 定义一个辅助函数,用于与 DEX API 进行交互。
const getQuote = async () => {
  const apiRequestUrl = getAggregatorRequestUrl('/quote', quoteParams);
  return fetch(apiRequestUrl, {
    method: 'get',
    headers: headersParams,
  })
    .then((res) => res.json())
    .then((res) => {
      return res;
    });
};

3. 请求兑换接口,发起交易#

3.1 定义兑换参数#

  • 接下来,定义参数,并获取兑换的 tx 信息。
const swapParams = {
  chainId: 1,
  fromTokenAddress: fromTokenAddress,
  toTokenAddress: toTokenAddress,
  amount: '1000000',
  slippage: '0.03',
  userWalletAddress: user
};

3.2 定义辅助函数#

定义一个辅助函数,用于与 DEX 批准交易 API 进行交互。

const getSwapData = async () => {
  const apiRequestUrl = getAggregatorRequestUrl('/swap', swapParams);
  return fetch(apiRequestUrl, {
    method: 'get',
    headers: headersParams,
  })
    .then((res) => res.json())
    .then((res) => {
      return res;
    });
};

3.3 请求兑换接口拿到 tx 信息,发起上链交易#

let tx = {
          "data": "te6cckEBBAEAwAABsA+KfqUAALgW1FkYQkBfXhAIAK3+NxydEq8Qc4csyQ7botOnBqxp3L54Fn7Zof9EjDx5ADoI2kiSNQZdnOIVsRSLrVMtiBySHg0Lt6lM2ZSxKkEwyC592wEBAZ8RMwAAAvrwgIALyzu3/eo7h8wFCa+0XsOg6z0IG/43fUuMnumWS8xS91AD0F/w35CTWUxTWRjefoV+400KRA2jX51X4ezIgmUUY/0AX5sDCAIBAQwDABgAAAABAAAAAAAAA+cKUcDO",
          "from": "UQDoI2kiSNQZdnOIVsRSLrVMtiBySHg0Lt6lM2ZSxKkEw3k1",
          "gas": "80234000",
          "gasPrice": "5000",
          "maxPriorityFeePerGas": "",
          "minReceiveAmount": "25062412",
          "to": "UQBXp1W7_UJWvsBrbaO8s-9i8O53s7hNNeZ0XqEEz12i0oDS",
          "value": "440000000"
}
// This is the response of the /swap endpoint

async function sendTx() {

    const endpoint = await getHttpEndpoint();
    const client = new TonClient({ endpoint });

    const mnemonic = ['range', 'xxxxxx']; //   Your mnemonic words  Decimal conversion
    const keyPair = await mnemonicToPrivateKey(mnemonic);

    const wallet = WalletContractV4.create({workchain: 0, publicKey: keyPair.publicKey});

    const contract = client.open(wallet)


    let seqno = await contract.getSeqno();
    const body = Cell.fromBase64(tx.data);
    const value = tx.value / Math.pow(10, 9); // Decimal conversion
    const to = tx.to;

    await contract.sendTransfer({
        seqno,
        secretKey: keyPair.secretKey,
        messages: [internal({
            value: toNano(value),
            to,
            body: body,
        })]
    });
}