在 Ton 链上搭建兑换应用#
搭建单链应用#
在本指南中,我们将用一个示例来展示如何通过欧易 DEX 提供的 API 在 Ton 上用 Ton 兑换 JETTON,这个过程中的步骤包括:
- 设置你的环境
- 请求询价接口,获取询价数据
- 请求兑换接口,发起交易
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,
})]
});
}