搭建限价单应用#
在本指南中,我们将通过欧易 DEX 提供一个用例来进行限价单下单。这个过程包括:
- 设置你的环境
- 检查授权额度
- 创建订单
- 取消订单
1. 设置你的环境#
导入必要的 Node.js 库并设置你的环境变量以及定义辅助函数和组装参数 Node.js 环境设置
2. 检查授权额度#
2.1 请参考查询授权额度教程#
- 下文的 allowanceAmount 代表真实的链上授权额度
2.2 获取授权数量#
获取数量。如果 allowanceAmount !== '0'
,请查看步骤 4。如果 allowanceAmount === '0'
,请查看步骤 5。
const { data: allowanceData } = await getAllowanceData();
const allowanceAmount = allowanceData?.[0]?.allowanceAmount;
3. 创建订单#
提示
如果 allowanceAmount 大于零,则表示已执行批准操作,可以直接创建订单。
3.1 离线签名#
采用 EIP712 结构化签名,签名时钱包将显示订单结构化内容。
const ethers = require('ethers');
// Build domain data
const domainData = {
name: 'OKX LIMIT ORDER',
version: '2.0',
chainId: 1, // The chainId of the ETH mainnet
verifyingContract: '0x2ae8947FB81f0AAd5955Baeff9Dcc7779A3e49F2' // LimitOrder contract address
};
// Define the limit order type
const Order = [
{ name: "salt", type: "uint256" },
{ name: "makerToken", type: "address" },
{ name: "takerToken", type: "address" },
{ name: "maker", type: "address" },
{ name: "receiver", type: "address" },
{ name: "allowedSender", type: "address" },
{ name: "makingAmount", type: "uint256" },
{ name: "takingAmount", type: "uint256" },
{ name: "minReturn", type: "uint256" },
{ name: "deadLine", type: "uint256" },
{ name: "partiallyAble", type: "bool" }
];
const orderData = {
salt: 1702979522,
makerToken: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
takerToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
maker: "0x5F73e69237eB5bA3544273D165907447bF6a0AA7",
receiver: "0x5F73e69237eB5bA3544273D165907447bF6a0AA7",
allowedSender: "0x0000000000000000000000000000000000000000",
makingAmount: 1000000,
takingAmount: 1000000,
minReturn: 1000000,
deadLine: 1703254942,
partiallyAble: true
}
// Build EIP-712 messages
const message = {
domain: domainData,
types: { Order },
value: orderData,
};
// Create an Ethereum signature wallet
const privateKey = '<YOUR_PRIVATE_KEY>';
const wallet = new ethers.Wallet(privateKey);
(async () => {
// Calculate the EIP-712 orderHash
const orderHash = ethers.utils._TypedDataEncoder.hash(message.domain,
message.types,
message.value);
console.log("Order data:", orderData);
console.log("Order Hash:", orderHash);
// Sign the message with the privatekey
const signature =
await wallet._signTypedData(
message.domain,
message.types,
message.value
);
console.log("Order signature:", signature);
})();
3.2 定义参数#
const limitOrderRequestParams = { orderHash,orderData,chainId, signature };
3.3 下单#
const resp = await fetch(apiBaseUrl +"/limit-order/save-order", {
method: "POST",
body: JSON.stringify(limitOrderRequestParams),
headers: headersParams,
});
4. 取消订单#
const ethers = require('ethers');
// 示例限价单数据
const orderData = {
salt: 1700110500, //随机数盐,作为幂等标识,(传入当前时间戳)
makerToken: "0xMakerTokenAddress", //兑入币种地址
takerToken: "0xTakerTokenAddress", //兑出币种地址
maker: "0xMakerAddress", //用户钱包地址
receiver: "0xTakerAddress", //用户指定收款地址
allowedSender: "0xAllowedSender", //用户指定交易对方地址
makingAmount: 2000, //兑入币种数量
takingAmount: 1000, //兑出币种数量
minReturn: 950, //最少兑出币种数量,用于滑点控制
deadLine: 1700120500, //订单超时时间戳
partiallyAble: false //是否支持部分成交
};
// 连接到以太坊节点
const provider = new ethers.providers.JsonRpcProvider("https://mainnet.infura.io/v3/your_infura_project_id");
// 合约地址和 ABI
const contractAddress = "0x2ae8947FB81f0AAd5955Baeff9Dcc7779A3e49F2"; // LimitOrder合约地址
const contractABI = [
{
"inputs": [
{
"components": [
{
"internalType": "uint256",
"name": "salt",
"type": "uint256"
},
{
"internalType": "address",
"name": "makerToken",
"type": "address"
},
{
"internalType": "address",
"name": "takerToken",
"type": "address"
},
{
"internalType": "address",
"name": "maker",
"type": "address"
},
{
"internalType": "address",
"name": "receiver",
"type": "address"
},
{
"internalType": "address",
"name": "allowedSender",
"type": "address"
},
{
"internalType": "uint256",
"name": "makingAmount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "takingAmount",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "minReturn",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "deadLine",
"type": "uint256"
},
{
"internalType": "bool",
"name": "partiallyAble",
"type": "bool"
}
],
"internalType": "struct OrderLibV2.Order",
"name": "_order",
"type": "tuple"
}
],
"name": "cancelOrder",
"outputs": [
{
"internalType": "uint256",
"name": "orderRemaining",
"type": "uint256"
},
{
"internalType": "bytes32",
"name": "orderHash",
"type": "bytes32"
}
],
"stateMutability": "nonpayable",
"type": "function"
}
];
// 使用合约 ABI 和地址创建合约实例
const contract = new ethers.Contract(contractAddress, contractABI, provider);
// 使用私钥创建钱包
const privateKey = "your_private_key";
const wallet = new ethers.Wallet(privateKey, provider);
// 撤销订单
async function cancelOrder(orderData) {
const tx = await contract.connect(wallet).cancelOrder(orderData);
await tx.wait;
console.log("txhash:", tx.hash);
}
// 交互示例
(async () => {
await cancelOrder(orderData);
})();