搭建跨链应用#
在本指南中,我们将通过欧易 DEX 提供的一个示例来展示如何进行跨链兑换,使用 Ethereum 链上的 USDT 兑换 Arbitrum 链上的 USDC。这个过程包括:
- 设置你的环境
- 检查授权额度
- 检查授权交易参数并发起授权交易
- 通过 fromChainId 拿到可以交易的 toChainId 列表,并选择其中一条链作为目标链
- 通过 toChainId 拿到该链的币种列表,并且选择其中一个代币作为目标链币种
- 请求询价接口,拿到询价数据,主要目的是为了获取跨链桥 ID
- 请求跨链兑换接口,发起交易
- 查询交易状态
1. 设置你的环境#
导入必要的 Node.js 库并设置你的环境变量以及定义辅助函数和组装参数 Node.js 环境设置
2. 检查授权额度#
以 ETH chain 举例#
Demo 为 JavaScript 语言
连接到以太坊节点:您需要确保您已经连接到一个可用的以太坊节点。您可以使用 web3.js 或其他以太坊开发库来连接到节点。在代码中,您需要指定节点的 HTTP 或 WebSocket 端点。获取代币合约实例:使用代币的合约地址和 ABI,您需要创建一个代币合约的实例。您可以使用 web3.js 的 web3.eth.Contract 方法来实现这一点,将合约地址和 ABI 作为参数传递给合约实例。查询授权额度:通过调用合约实例的 allowance 函数来查询授权额度。该函数需要两个参数:拥有者的地址和被授权者的地址。您可以通过在调用时提供这两个地址来查询授权额度。- spenderAddress 地址可以参考 此处 接口 Response 中的 dexTokenApproveAddress。
js
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));
- 下文的 allowanceAmount 代表真实的链上授权额度
2.2 获取授权数量#
提示
获取授权数量。如果 allowanceAmount < fromTokenAmount,请查看步骤 3,如果 allowanceAmount >= fromTokenAmount,你可以选择使用步骤 3 增加授权数量,或者直接进行步骤 4。
js
const { data: allowanceData } = await getAllowanceData();
const allowanceAmount = allowanceData?.[0]?.allowanceAmount;
3. 检查授权交易参数并发起授权交易#
提示
由于 allowanceAmount < fromTokenAmount,我们需要对该币种进行授权。
3.1 定义授权交易参数#
接下来,定义你要执行授权交易的参数。
js
const getApproveTransactionParams = {
chainId: fromChainId,
tokenContractAddress: fromTokenAddress,
userWalletAddress,
approveAmount: fromTokenAmount,
};
3.2 定义辅助函数#
定义一个辅助函数,用于与 DEX API 进行交互。
js
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 获取授权交易 tx 并且发送授权交易#
js
if (parseFloat(allowanceAmount) < parseFloat(fromTokenAmount)) {
const { data } = await approveTransaction(allowanceAmount);
let allowanceParams = {
...{ data: data[0].data }, // You can modify the data content you want according to the web3 official website
};
const { rawTransaction } = await web3.eth.accounts.signTransaction(
allowanceParams,
privateKey
);
await web3.eth.sendSignedTransaction(rawTransaction);
}
4. 通过 fromChainId 拿到可以交易的 toChainId 列表,并选择其中一条链作为目标链#
4.1 定义获取支持的目标链参数#
接下来,定义参数,并通过 fromChainId 拿到对应的 toChainId 列表。
js
const toChainListParams = {
chainId: fromChainId,
};
4.2 定义辅助函数#
定义一个辅助函数,用于与 DEX API 进行交互。
js
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 获取支持的目标链列表并选择 Arbitrum 链,你也可以根据列表选择其他链作为目标链#
js
const { data: supportedChainList } = await getSupportedChain();
const selectChainItem = supportedChainList.find((item) => {
return item.chainName === 'Arbitrum';
});
toChainId = selectChainItem?.chainId;
5. 通过 toChainId 拿到该链的币种列表,并且选择其中一个代币作为目标链币种#
5.1 定义获取可交易币种参数#
接下来,定义参数,并通过 toChainId 拿到可交易的币种列表。
js
const toChainTokenListParams = {
chainId: toChainId,
};
5.2 定义辅助函数#
定义一个辅助函数,用于与 DEX API 进行交互。
js
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 获取币种列表并选择 USDC 币种,你也可以根据列表选择其他币种作为目标链币种#
js
const { data: toChainTokenList } = await getToChainTokenList();
const selectToChainToken = toChainTokenList.find((item) => {
return item.tokenSymbol === 'USDC';
});
toTokenAddress = selectToChainToken?.tokenContractAddress;
6. 请求询价接口,拿到询价数据,主要目的是为了获取跨链桥 ID#
6.1 定义询价参数#
接下来,定义参数,用来拿到询价的基础信息和路径列表信息。
js
const quoteParams = {
fromChainId,
toChainId,
fromTokenAddress,
toTokenAddress,
amount: fromTokenAmount,
slippage,
};
6.2 定义辅助函数#
定义一个辅助函数,用于与 DEX API 进行交互。
js
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 获取询价信息,并选择一条路径作为交易路径#
js
const { data: quoteData } = await getQuote();
bridgeId = quoteData[0]?.routerList[0]?.router?.bridgeId;
7. 请求跨链兑换接口,发起交易#
7.1 定义跨链兑换参数#
接下来,定义参数,并获取跨链兑换的 tx 信息。
js
const swapParams = {
fromChainId: fromChainId,
toChainId: toChainId,
fromTokenAddress,
toTokenAddress,
amount: fromTokenAmount,
slippage,
userWalletAddress,
bridgeId,
};
7.2 定义辅助函数#
定义一个辅助函数,用于与 DEX API 进行交互。
js
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 请求跨链兑换接口拿到 tx 信息,发起上链交易#
js
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. 查询交易状态#
8.1 定义查询参数#
接下来,定义参数,主要为源链 Hash 地址信息。
js
const getCheckStatusParams = {
hash: transactionTx,
};
8.2 定义辅助函数#
定义一个辅助函数,用于与 DEX API 进行交互。
js
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 获取交易状态#
提示
你也可以增加轮询的方式获取实时订单状态,这里为单次查询的例子。
js
const { data: statusInfo } = await checkTransactionStatus();
console.log(statusInfo?.data[0]?.detailStatus);
目录
- 1. 设置你的环境2. 检查授权额度以 ETH chain 举例2.2 获取授权数量3. 检查授权交易参数并发起授权交易3.1 定义授权交易参数3.2 定义辅助函数3.3 获取授权交易 tx 并且发送授权交易4. 通过 fromChainId 拿到可以交易的 toChainId 列表,并选择其中一条链作为目标链4.1 定义获取支持的目标链参数4.2 定义辅助函数4.3 获取支持的目标链列表并选择 Arbitrum 链,你也可以根据列表选择其他链作为目标链5. 通过 toChainId 拿到该链的币种列表,并且选择其中一个代币作为目标链币种5.1 定义获取可交易币种参数5.2 定义辅助函数5.3 获取币种列表并选择 USDC 币种,你也可以根据列表选择其他币种作为目标链币种6. 请求询价接口,拿到询价数据,主要目的是为了获取跨链桥 ID6.1 定义询价参数6.2 定义辅助函数6.3 获取询价信息,并选择一条路径作为交易路径7. 请求跨链兑换接口,发起交易7.1 定义跨链兑换参数7.2 定义辅助函数7.3 请求跨链兑换接口拿到 tx 信息,发起上链交易8. 查询交易状态8.1 定义查询参数8.2 定义辅助函数8.3 获取交易状态
