0x protocol分析之挂单以及take Limit Order

0x protocol分析之take Limit Order

关于0x是什么的问题这里就不再啰嗦,基本的概念有很多解释的文档,这里主要展示了limit order 的挂单和吃单流程。
0xprotocol的流程概述
0x中一些问题的解释

0x 限价单挂单吃单流程

0x的市价单的交互官方文档写的比较清楚,操作起来也比较简单 。这里主要记录一下限价单的挂单和吃单。

挂单

  1. 按格式准备一个订单
    OX中限价的订单的数据结构
 struct LimitOrder {
        IERC20TokenV06 makerToken;
        IERC20TokenV06 takerToken;
        uint128 makerAmount;
        uint128 takerAmount;
        uint128 takerTokenFeeAmount;
        address maker;
        address taker;
        address sender;
        address feeRecipient;
        bytes32 pool;
        uint64 expiry;
        uint256 salt;
    }
const order = new utils.LimitOrder({
    "makerToken": "0xc778417e063141139fce010982780140aa0cd5ab",
    "takerToken": "0xf8db576976096d5f19c21ab12115d7a2aa7c77cc",
    "makerAmount": "1",
    "takerAmount": "1000000000000000",
    "maker": "0xD993d1049bd38eDBe12f8F6c9cdB716970B778D2",
    "taker": "0x0000000000000000000000000000000000000000",
    "pool": "0x0000000000000000000000000000000000000000000000000000000000000000",
    "expiry": "1627240945",
    "salt": "1626940945557",
    "chainId": 3,
    "verifyingContract": "0xdef1c0ded9bec7f1a1670819833240f027b25eff",
    "takerTokenFeeAmount": "0",
    "sender": "0x0000000000000000000000000000000000000000",  
    "feeRecipient": "0x0000000000000000000000000000000000000000",
    "signature":{
      "v": 28,
      "r": "0x921d18a7b4eaf9ce5227031f872dd54a73237e5eb90d81da3da05465f16f9b4f",
      "s": "0x524904cac050c9ae8f5999cc0f96415d1422dc5b36bb7fbe11d8522cc6b28365",
      "signatureType": 2
    }
  });

其中 signature 字段是订单的签名,签名的创建有多种方式
其一是通过 @0x/protocol-utils提供的工具签名 文档地址

yarn add @0x/protocol-utils
var Web3 = require('web3');
const utils = require('@0x/protocol-utils');
const contractAddresses = require("@0x/contract-addresses");
var infuranKey = "";
var web3 = new Web3("https://ropsten.infura.io/v3/"+infuranKey);

const privateKey = "私钥"
const maker = "0xcC2847AB347A4752a233e20b7E4410e138f096F6";
const makeToken= "0xc778417e063141139fce010982780140aa0cd5ab" 
const takeToken= "0xf8db576976096d5f19c21ab12115d7a2aa7c77cc";
const makerAmount = "1000"
const takerAmount = "1000"
const CHAIN_ID = 3;
const NULL_ADDRESS = "0x0000000000000000000000000000000000000000";
const addresses = contractAddresses.getContractAddressesForChainOrThrow(
    CHAIN_ID
);


main()
  .then(() => process.exit(0))
  .catch(error => {
    console.error(error);
    process.exit(1);
  });
  
async function main() {
    await sign();
}

async function sign() {
    console.log(`CHAIN_ID = ${CHAIN_ID}, ETH = ${addresses.etherToken}, exchange = ${addresses.exchangeProxy}`);
    // 订单组装
    const order = new utils.LimitOrder({ // or utils.RfqOrder
        makerToken : makeToken,
        takerToken : takeToken,
        makerAmount: makerAmount,
        takerAmount: takerAmount,
        maker: maker,
        taker: NULL_ADDRESS,
        pool: "0x0000000000000000000000000000000000000000000000000000000000000000",
        expiry: "2014956123",
        salt: "6",
        chainId: CHAIN_ID,
        verifyingContract: `${addresses.exchangeProxy}`,
        takerTokenFeeAmount: "0",
        sender: NULL_ADDRESS,  
        feeRecipient: NULL_ADDRESS,
    });
    
    // 签名
    const signature = await order.getSignatureWithKey(privateKey, utils.SignatureType.EIP712);
    
    console.log(signature)
    if(await postOrder(order,signature)){
        console.log("发布成功")
        return;
    }
    console.log("发布失败")
}

// 发布订单
async function postOrder(order,signature) {
    const signedOrder = { ...order, signature };
    // console.log(signedOrder);
    const resp = await fetch("https://ropsten.api.0x.org/sra/v4/order", {
        method: "POST",
        body: JSON.stringify(signedOrder),
        headers: {
        "Content-Type": "application/json"
        }
    });

    if (resp.status === 200) {
        console.log("Successfully posted order to SRA");
        return true;
    } else {
        const body = await resp.json();
        console.log(
        `ERROR(status code ${resp.status}): ${JSON.stringify(body, undefined, 2)}`
        );
        return false;
    }  
}


通过另外一种方式,提供的工具做的签名可以完成挂单
sign地址

  1. 将生成好的订单 作为body参数 通过api 发布出去,请求为post请求

  2. 发布后可以通过api根据某些参数查询出来, 查询api


吃单

  1. maker 要把maketToken approve 给[0x相关的合约] 0xFbB2a5B444aA89a4054883A4D23FBA45BFc6840A
  2. taker也要 takerToken approve 给合约
  3. 注意take吃单要支付 70k*gasPrice的protocol fee
  4. 0x 合约中一些方法的解析
orderParam 订单参数
["0xf8db576976096d5f19c21ab12115d7a2aa7c77cc","0xc778417e063141139fce010982780140aa0cd5ab",1000,1,0,"0xcc2847ab347a4752a233e20b7e4410e138f096f6","0x0000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000",2014956256,0]  
signParam  签名参数  
[2,28,"0xd447dc3ef38cf18e82e34e2bffb78d2c8e7175881ae6b881a005a956b0f964ba","0x2a2b6dfd811a90d1dd72b830f09f9dcd6db2f9224b343dd4d4d8b33543c24cf8"]  
  1. getLimitOrderHash(orderParam) 获取限价单的订单hash
    return orderHash
  2. getLimitOrderInfo(orderParam) 获取限价的信息
    返回的是一个结构体,分别是订单hash,订单状态,已经订单中已经被吃掉的数量
    return struct OrderInfo {
        bytes32 orderHash;
        OrderStatus status;
        uint128 takerTokenFilledAmount;
    }
    
    其中订单的状态分别有以下几种
    enum OrderStatus {
        INVALID,
        FILLABLE,
        FILLED,
        CANCELLED,
        EXPIRED
    }
    

可以购买的订单的状态是 1 FILLABLE,购买完了的是 2 FILLED

  1. getLimitOrderRelevantState(orderParam,signParam) 这方法是获取限价单的一些状态, 这个会展示出当前的订单还有多少数量可以买的
    返回有三个参数 分别是
    OrderInfo的结构体,这个上面已经提过
    actualFillableTakerTokenAmount 实际可以购买的数量,
    isSignatureValid 挂单者的签名是否正确
    其中 实际actualFillableTakerTokenAmount>0,isSignatureValid=true才可以购买成功.

  2. fillLimitOrder(orderParam,signParam,takerAmount) 吃单
    上述的查询可以说都是为了这个方法的填入正确的参数做准备。
    检查完上面的状态都没问题,将订单参数呵呵签名参数填入,再填上一个合适的takerAmount的数量(<=actualFillableTakerTokenAmount)
    另外注意发送交易的时候 要支付 70K*gasPrice的protocol费。
    正常情况下发送交易,就可以完成吃单操作。


OK,以上就是使用0x 协议完成的挂单吃单的流程。

如果想详细分析token的流转,可以分析下面这个
吃单的一个交易hash

如果有问题,可以留言交流。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值