前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用Multicall 加速 DeFi查询调用

使用Multicall 加速 DeFi查询调用

作者头像
Tiny熊
发布2021-01-14 16:18:51
1.6K0
发布2021-01-14 16:18:51
举报

背景介绍

有时,从区块链获取数据的成本可能会非常高,不管是从请求花费的时间还是从发送的请求数量上来说,都是这样。如果我们想同时获取大量数据,用来在仪表板上显示或进行分析,我们必须调用合约的不同函数或者用不同参数调用相同函数, 这些都可能会导致查询时间很长。另外,当我们使用像Infura[4]这样的节点提供商,也很容易达到发送请求数量的限额。

什么是 Multicall?

Multicall[5]是一个 npm 软件包,可将多个 HTTP 调用分为一个组。用这个方式,之前想从n个不同的请求中获取的数据,现在可以在发送 HTTP 请求之前对它们进行分组,然后进发送一个请求,从而缩短了请求响应时间,并降低了 eth_call 调用的次数。

用测试了解运作方式

为了了解这种机制的工作原理以及相对于传统方法是否确实有所改进,我们将通过一个对比测试来验证。分别在不使用 Multicall 和使用 Multicall 的情况下,对每个函数调用n次, 然后分析结果。为此,我们通过调用函数 getAccountLiquidity 来查询 Compound 协议。我们将使用 1,000 个不同的地址来获取所有地址的信息。

创建项目

安装依赖

为了进行测试,先创建一个 Node 项目,并将安装依赖项:ethers.js[6] 用于与区块链交互、money-legos[7]则用来以更简单的方式引用 ABI 和合约,以及 Multicall 软件包。

使用以下命令创建项目:

代码语言:javascript
复制
npm init -y

然后,安装了上述提到的依赖项:

代码语言:javascript
复制
npm install -S @studydefi/money-legos ethers ethers-multicall

导入依赖

对比测试的两种情况,我们都必须使用引入公共依赖项进行实例化并以此与区块链连接。引入方式如下(import.js):

代码语言:javascript
复制
const { ethers } = require("ethers");
const { ALCHEMY_URL } = require('./config')
const compound = require("@ studydefi/money-legos/compound");
const { accounts } = require("./accounts");
const { Contract, Provider } = require('ethers-multicall');
const provider = new ethers.providers.JsonRpcProvider(ALCHEMY_URL);

并创建一个用来显示结果和执行时间的函数,如下所示(calculatetime.js):

代码语言:javascript
复制
const calculateTime = async () => {
  const startDate = new Date();
  const result = await getLiquidity()
  const endDate = new Date();
  const milliseconds = (endDate.getTime() - startDate.getTime());
  console.log(`Time to process in milliseconds: $ {milliseconds}`)
  console.log(`Time to process in seconds: $ {milliseconds / 1000}`)
  const callsCount = Object.keys(result).length;
  console.log(`Number of entries in the result: $ {callsCount}`);
}

calculatetime.js

调用合约

常规循环调用

先使用传统方法进行测试,我们将遍历 1,000 个的地址数组(在map循环中),逐个获取每个查询的结果,执行方法如下:

代码语言:javascript
复制
const getLiquidity = () => {
  const compoundContract = new ethers.Contract(
  compound.comptroller.address,
  compound.comptroller.abi,
  provider
  )

  return Promise.all(accounts.map(account => {
  let data
  try {
     data = compoundContract.getAccountLiquidity(account.id)
  } catch (error) {
     console.log(`Error getting the data $ {error}`)
  }
     return data
  }))
}

上面实例化 compound comptroller 合约,并在每个地址上调用流动性函数。

使用 Multicall 调用

使用 Multicall 调用时,调用函数必须稍作更改,形式如下:

代码语言:javascript
复制
const getLiquidity = async () => {
  const ethcallProvider = new Provider(provider);
  await ethcallProvider.init();

  const compoundContract = new Contract(
    compound.comptroller.address,
    compound.comptroller.abi,
  )

  const contractCalls = accounts.map(account => compoundContract.getAccountLiquidity(account.id))
  const results = await ethcallProvider.all(contractCalls);
  return results
}

利用 Multicall 包中的ProviderContract类。首先,初始化 provider,并传递web3、合约地址及其合约 ABI。

创建完成后,执行则和之前类似。在map里,调用帐户流动性函数。但是现在它不会发送到网络,而是将它们分组到一个数组中。创建此数组后,将调用创建好的 Multicall Providerall函数,并进行网络调用。

对比分析结果

要查看是否确实有重大改进,只需要对比两个调用消耗的时间。

传统循环方法消耗的时间:

代码语言:javascript
复制
Time to process in milliseconds: 124653
Time to process in seconds: 124.653
Number of entries in the result: 1000

使用 Multicall 调用

代码语言:javascript
复制
Time to process in milliseconds: 9591
Time to process in seconds: 9.591
Number of entries in the result: 1000

结论

通过结果对比,发现使用 Multicall 调用时间的减少是非常可观的,从 124 秒减少到 9.5,花费的时间减少大约十倍。

另外,如果比较eth_call RPC 调用的数量,同样是非常明显的减少,从一千个减少到只有一个。

因此,如果我们依赖第三方的节点提供商,而在该提供商中对 API 的调用是有限额,则这一点也同样重要。


本翻译由 Cell Network[8] 赞助支持。

来源:https://medium.com/better-programming/speed-up-your-defi-queries-using-multicall-d4cf652d8ab6

参考资料

[1]

登链翻译计划: https://github.com/lbc-team/Pioneer

[2]

翻译小组: https://learnblockchain.cn/people/412

[3]

Tiny 熊: https://learnblockchain.cn/people/15

[4]

Infura: https://infura.io/

[5]

Multicall: https://github.com/cavanmflynn/ethers-multicall#readme

[6]

ethers.js: https://docs.ethers.io/v5/

[7]

money-legos: https://money-legos.studydefi.com/#/

[8]

Cell Network: https://www.cellnetwork.io/?utm_souce=learnblockchain

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-01-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 深入浅出区块链技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景介绍
    • 什么是 Multicall?
    • 用测试了解运作方式
    • 创建项目
      • 安装依赖
        • 导入依赖
        • 调用合约
          • 常规循环调用
          • 使用 Multicall 调用
          • 对比分析结果
          • 结论
            • 参考资料
            相关产品与服务
            区块链
            云链聚未来,协同无边界。腾讯云区块链作为中国领先的区块链服务平台和技术提供商,致力于构建技术、数据、价值、产业互联互通的区块链基础设施,引领区块链底层技术及行业应用创新,助力传统产业转型升级,推动实体经济与数字经济深度融合。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档