近年来,DeFi交易者的数量不断增加,这使得更多的去中心化交易所(DEX)也被带入市场。
Web3对主要行业的影响越来越大,交易行业也不例外。我们已经看到了中心化交易所的不足之处,如缺乏透明度、不安全、金融排他性和隐私,这为DEX提供了需求。
DEX是一种没有经纪商或第三方等任何中介的加密货币交换方式。他们遵循与集中式交易所不同的方法,依靠智能合约来处理点对点的交易。
该商业模式侧重于其用户的隐私,交易是匿名进行的,尽管交易细节存储在区块链上。
我们在市场上有很多DEX平台,如Coinbase和Binance,但在这篇文章中,我们将重点介绍Hashflow。
我们将看看交易者如何通过Hashflow代币与针尖相连,它的工作方式与其他平台不同,如何进行市场制作,以及如何进行交易。
- 什么是Hashflow,其目标是什么?
- Hashflow如何工作
- Hashflow代币
- 如何进行市场交易
- 连接到WebSocket
- 创建一个池子
- 接收RFQ并回复报价
- 支持签署报价单
- 获得第一个签署的RFQ
什么是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 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之后,你需要连接到你的钱包,以创建一个提供报价的资金池。
要做到这一点,请使用此链接,并填写你的资金池名称、签名人地址,最后确定你的资金池是公开的还是私有的。完成这个过程后,你应该得到一个类似这样的页面。

收到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的关键方面--即它提供了无桥跨链互换和链外市场决策;也就是说,报价是在没有自动做市商的情况下完成的。