搭建限价单应用#
在本指南中,我们将通过欧易 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);
})();
