如何用Hashflow进行市场制作和交易?

337 阅读8分钟

近年来,DeFi交易者的数量不断增加,这使得更多的去中心化交易所(DEX)也被带入市场。

Web3对主要行业的影响越来越大,交易行业也不例外。我们已经看到了中心化交易所的不足之处,如缺乏透明度、不安全、金融排他性和隐私,这为DEX提供了需求。

DEX是一种没有经纪商或第三方等任何中介的加密货币交换方式。他们遵循与集中式交易所不同的方法,依靠智能合约来处理点对点的交易。

该商业模式侧重于其用户的隐私,交易是匿名进行的,尽管交易细节存储在区块链上。

我们在市场上有很多DEX平台,如Coinbase和Binance,但在这篇文章中,我们将重点介绍Hashflow。

我们将看看交易者如何通过Hashflow代币与针尖相连,它的工作方式与其他平台不同,如何进行市场制作,以及如何进行交易。

什么是Hashflow,其目标是什么?

首先,Hashflow以其无桥跨链互换而闻名,这意味着它具有高度的互操作性,零滑点,没有MEV。

之所以能做到这一点,是因为Hashflow确保做市商在报价上签字,所以在交易过程中保持不变。

流动性提供商和交易商与Hashflow上的专业做市商相连,其核心功能为其做市商提供了更好的灵活性--无滑点、抗MEV、更好的报价和更便宜的交易费都是它的优势。

上述这些都是由于Hashflow使用的架构,即基于池的架构才得以实现。

Hashflow如何工作

从交易开始,用户需要将他的钱包连接到Hashflow,输入一个他们想交易的数字,然后向他们显示一个报价。

如果用户接受,则提交订单,该交易被验证并添加到Hashflow网络(或区块链)中。在另一端,有做市商市场,处理用户已经接受的价格报价的发布。

然后,做市商签署交易,并在没有滑点的情况下执行(无论用户提交的是什么订单,都会成立)。与其他DEX不同的是,Hashflow通常有AMM(自动做市商)来处理做市和使用Lazy Liquidity Provision在链上进行资产定价,传统上就像订单簿机制。

定价是在链外完成的,但交易是在链上执行的。

Hashflow是在2021年,并已大幅增长,由于其优化的气体费用和零滑点,提供了最好的价格。截至本文发表时,Hashflow目前支持无桥跨链互换,这使得你在EVM兼容的链上发起互换,预计未来将包括Solana整合、智能订单路由、无气交易、限价订单和Hashverse。

总之,Hashflow是一个DeFi协议,作为一个运行在以太坊区块链上的去中心化的交易所。

Hashflow代币

Hashflow提供其名为HFT(Hashflow代币)的代币,这是2021年12月22日部署在以太坊链上的ERC-20。随着10亿单位的HFT供应,Hashflow以这种方式分配这种加密货币。19%给核心团队;25%给早期投资者;56%给生态系统。还有6.75%将给早期用户作为奖励。

Hashflow Allocation

Hashflow NFT,也被称为Hashbots,将用于未来发布的Hashverse中。NFT持有者将获得与NFT价值相符的HFT,因为每个NFT都会有一个HFT值。而Hashflow表示,四年后,5%的HFT将被发放给社区。

如何进行市场制作

市场标的在Hashflow和整个市场中基本上都很重要。他们是流动性提供者,通过购买和出售资产使市场发挥作用。这并不意味着他们可以马上在任何时候买入和卖出,但他们总是处于待命状态,随时准备购买和出售。

在大多数去中心化的交易所中,做市商是自动的,智能合约被部署在AMM(自动做市商)中寻找市场对,但它们容易受到攻击,同时也有点滞后,因为价格报价是在链上处理的。

在Hashflow中,做市商是公司、机构或个人,他们被赋予了利用其专业性做出这些市场决定的特权,而这是在链外完成的,这又减少了前面提到的气体费用和滑点。

为了在Hashflow上做市场,我们将遵循以下步骤。作为做市商与Hashflow的整合非常简单。

连接到WebSocket

你需要从Hashflow的API连接到WebSocket,就像你在下面第10行看到的那样。而且你可能需要在Telegram或Discord上联系团队,以便被加入到允许的做市商名单中。

const PING_PONG_INTERVAL_MS = 30000;
const PING_PONG_GRACE_PERIOD_MS = 1000;

function getWebsocketConnection(
  marketMakerName,
  onMessageCallBack,
  onCloseCallback,
  onHeartbeatCallback,
) {
  const ws = new WebSocket(`${process.env.HASHFLOW_WS_API}/maker/v1`, {
    headers: { marketmaker: marketMakerName, }
  });
  const heartbeat = () => {
    if (ws.pingTimeout) {
      clearTimeout(ws.pingTimeout);
    }
    ws.pingTimeout = setTimeout(() => {
      ws.terminate();
    }, PING_PONG_INTERVAL_MS + PING_PONG_GRACE_PERIOD_MS);

    onHeartbeatCallback();
  }
  ws.on('open', heartbeat);
  ws.on('ping', heartbeat);
  ws.on('message', message => onMessageCallBack(message));

  ws.on('close', () => {
    if (ws.pingTimeout) {
      clearTimeout(ws.pingTimeout);
    }
    setTimeout(() => {
      ws.removeAllListeners();
      onCloseCallback();
    }, 5000);
  });

  ws.on('error', err => {});

  ws.on('unexpected-response', (_, res) => {
    let message = '';
    res.on('data', (chunk) => {
      message += chunk;
    });
    res.on('end', () => {
      if (res.statusCode === 401) {
        logger.error(`WS access not authorized. ${message}`);
      } else {
        logger.error(`Unexpexted response from server: [${res.statusCode}] ${message}.`);
      }
      ws.close()
    });
  });
  return ws;
}

而Hashflow则与你相连,如下图所示:

// TODO: Replace this with your market maker name (once added to the backend)
const MARKET_MAKER_NAME = 'TestMM';
// TODO: Set true if you want to MM on 1inch, etc – and have signed legal agreements
const SUPPORT_AGGREGATORS = false;
const levelsInterval = SUPPORT_AGGREGATORS 
  ? setInterval(() => publishPriceLevels(mainSocket), 1000)
  : undefined;
const onMessageCallback = message => processMessage(mainSocket, message);
const onHeartbeatCallback = () => {
  for (const networkId of Object.keys(SUPPORTED_PAIRS)) {
    sendMessage(mainSocket, 'subscribeToTrades', { networkId, pool: POOL });
  }
};
const onCloseCallback = () => {
  if (SUPPORT_AGGREGATORS) {
    clearInterval(levelsInterval);
  }
  mainSocket = connectToHashflow();
};

const connectToHashflow = () => {
  return getWebsocketConnection(
    MARKET_MAKER_NAME,
    onMessageCallback,
    onCloseCallback,
    onHeartbeatCallback,
  );
}
let mainSocket = connectToHashflow();

与团队联系后,'TestMM'被替换为你的。你也应该参考这个示例代码库,看看如何从Hashflow连接到WebSocket。

创建一个资金池

在连接到WebServer之后,你需要连接到你的钱包,以创建一个提供报价的资金池。

要做到这一点,请使用此链接,并填写你的资金池名称、签名人地址,最后确定你的资金池是公开的还是私有的。完成这个过程后,你应该得到一个类似这样的页面。

MIB Pool

收到RFQ并回复报价

现在到了有趣的部分;当用户想要交易时,Hashflow会收到来自用户的报价请求,然后服务器会将数据提供给指定的做市商。

{
  "messageType": "rfq",
  "message": {
    // This is a unique RFQ ID -- you need to use this when sending back a quote.
    "rfqId": string,

    // This will be something like: hashflow, 1inch. This is useful
    // since 1inch charge fees for their trades
    "source": string,

    // 1 for ETH L1
    "networkId": number,

    // Base token (the token the trader sells).
    "baseToken": string,  // contract address
    "baseTokenName": string,  // token name (e.g. USDC, ETH, ...)
    "baseTokenNumDecimals": number,  // token decimals (e.g. DAI: 18, USDC: 6)

    // Quote token (the token the trader buys).
    "quoteToken": string,  // contract address
    "quoteTokenName": string,  // token name (e.g. USDC, ETH, ...)
    "quoteTokenNumDecimals": number,  // token decimals (e.g. DAI: 18, USDC: 6)


    // Exactly one of the following fields will be present in the RFQ.
    // If baseTokenAmount is present, quoteTokenAmount needs to be filled by the quote.
    // If quoteTokenAmount is present, baseTokenAmount needs to be filled by the quore.
    // Amounts are in decimals, e.g. "1000000" for 1 USDT.
    "baseTokenAmount": ?string,
    "quoteTokenAmount": ?string,

    // The trader wallet address that will swap with the contract. This can be a proxy
    // contract (e.g. 1inch)
    "trader": string,

    // The wallet address of the actual trader (e.g. end user wallet for 1inch).
    // This is helpful in order to understand user behavior.
    // If effectiveTrader is not present, you can assume that trader == effectiveTrader.
    "effectiveTrader": ?string,
  }
}

而根据你在代码库中实现的逻辑,报价也会以这种格式返回给用户。

{
  "messageType": "quote",
  "message": {
    "rfqId": string,  // This should be the same rfqId that was sent by the server
    "pool": string,  // This should be the contract address of the pool.

    // This is optional. If using an EOA (externally owned account), this should 
    // contain the wallet address of the EOA. 
    // The EOA needs to have allowance set to the Pool.
    "eoa": ?string,

    // Same as RFQ
    "baseToken": string,
    "quoteToken": string,

    // Amounts are in decimals.
    "baseTokenAmount": string,
    "quoteTokenAmount": string,

    // Set this to "0" for private pool / EOA trading.
    "fees": string,

    // The unix timestamp when the quote expires, in seconds.
    "quoteExpiry": number,
  }
}

支持签署报价单

只有在用户没有提供特定的做市商时才会发生这种情况,在这种情况下,Hashflow会向所有做市商提出报价请求,并挑选出最好的一个。

当挑选出最好的报价后,我们会发送一个signQuote 消息类型给做市商,让他们签名(从他们那里得到一个签名)。该请求也是这种格式。

  "messageType": "signQuote",
  "message": {
    // The RFQ ID that generated the quote.
    "rfqId": string,
    "networkId": number,  // The chain ID (e.g. 1 for Ethereum mainnet)
    "quoteData": {
      "txid": string,  // Unique identifier of the quote -- different from the RFQ ID.

      "pool": string,
      "eoa": string,

      "baseToken": string,
      "quoteToken": string,

      "baseTokenAmount": string,
      "quoteTokenAmount": string,

      "fees": string,

      "quoteExpiry": number,

      // The account that will be executing the swap. For 1inch, this is the 1inch proxy.
      "trader": string,
      // Trader actually executing the swap, if different from 'trader'.
      "effectiveTrader": ?string,

      // The following parameter is internal to hashflow contracts.
      // It is leveraged to mitigate quote replay.
      "nonce": number
    }
  }
}

获得第一个签名的RFQ

你可以测试一下你的WebServer,看看你是否能从它那里得到一份签名的RFQ,方法是向Hashflow的staging API发出请求,并以下列主体参数为样本。

POST https://api-staging.hashflow.com/taker/v1/quote/signedRfq


{
    "networkId": 42,  // 42 is Kovan, 1 is Mainnet
    "source": "hashflow", 
    "baseToken": "0x07de306ff27a2b630b1141956844eb1552b956b5",  // USDT (Kovan)
    "quoteToken": "0xa0a5ad2296b38bd3e3eb59aaeaf1589e8d9a29a9",  // WBTC (Kovan)
    "trader": "0x2150DD462B496bd5e4A37b5411c13319427BE83E",
    "baseTokenAmount": "1000000",
    "marketMaker": "TestMM"  // don't forget to change this
}

一旦你得到回应,那么你的做市商就被设定了。你还应该参考文档中的更多边缘案例。

总结

在这篇文章中,我们重点解读了Hashflow、其用户和做市商之间的联系以及Hashflow的关键方面--即它提供了无桥跨链互换和链外市场决策;也就是说,报价是在没有自动做市商的情况下完成的。