简体   繁体   English

测试已完成的 chainlink oracle 请求 ethers/hardhat 的最佳实践是什么?

[英]What is best practice for for testing fulfilled chainlink oracle requests ethers/hardhat?

I am using hardhat with ethers on rinkeby to test a smart contract that makes aa get request to a local chainlink node.我在 rinkeby 上使用带以太币的 hardhat 来测试智能合约,该智能合约向本地 chainlink 节点发出 aa get 请求。 I can observe on the node dashboard that the request is fulfilled.我可以在节点仪表板上观察到请求已完成。

I am struggling to write a test that waits for the 2nd fulfillment transaction to be confirmed.我正在努力编写等待确认第二个履行交易的测试。

I see similar tests in the SmartContractKit/chainlink repo tests我在SmartContractKit/chainlink 回购测试中看到了类似的测试

 it("logs the data given to it by the oracle", async () => {
  const tx = await oc.connect(roles.oracleNode).fulfillOracleRequest(...convertFufillParams(request, response));
  const receipt = await tx.wait();

  assert.equal(2, receipt?.logs?.length);
  const log = receipt?.logs?.[1];

  assert.equal(log?.topics[2], response);
});

I fail to see that this would wait for the fulfilled transaction at all.我看不出这会等待完成的交易。 In the consumer.sol this function calls there is an event RequestFulfilled, that is emit, but it doesn't seem like this test is listening to it.在 consumer.sol 这个 function 调用中有一个事件 RequestFulfilled,也就是 emit,但是这个测试好像没有在监听它。

Another example I found, ocean protocol request test , accomplishes this by creating a mapping of request id's, an accessor, and a while loop in the test the polls until the request id is found.我发现的另一个示例ocean protocol request test通过创建请求 ID 的映射、访问器和测试轮询中的 while 循环来完成此操作,直到找到请求 ID。

 it("create a request and send to Chainlink", async () => {
  let tx = await ocean.createRequest(jobId, url, path, times);
  request = h.decodeRunRequest(tx.receipt.rawLogs[3]);
  console.log("request has been sent. request id :=" + request.id)

  let data = 0
  let timer = 0
  while(data == 0){
    data = await ocean.getRequestResult(request.id)
    if(data != 0) {
      console.log("Request is fulfilled. data := " + data)
    }
    wait(1000)
    timer = timer + 1
    console.log("waiting for " + timer + " second")
  }

});

This makes sense, and I see how it works.这是有道理的,我知道它是如何工作的。 However I would like to avoid creating a mapping, and accessor when I imagine there has got to be a more optimal way.但是,当我认为必须有一种更优化的方法时,我想避免创建映射和访问器。

You'd want to look at the hardhat-starter-kit to see examples of working with Chainlink/oracle API responses.您需要查看hardhat-starter-kit以查看使用 Chainlink/oracle API 响应的示例。

For unit tests, you'd want to just mock the API responses from the Chainlink node.对于单元测试,您只想模拟来自 Chainlink 节点的 API 响应。

For integration tests (for example, on a tes.net) you'd add some wait parameter for a return.对于集成测试(例如,在 tes.net 上),您需要为返回添加一些等待参数。 In the sample hardhat-starter-kit, it just waits x number of seconds, but you could also code your tests to listen for events to know when the oracle has responded.在示例 hardhat-starter-kit 中,它只等待 x 秒,但您也可以编写测试代码以侦听事件以了解 oracle 何时响应。 This does use events to get the requestId, however, you actually don't have to make a the event yourself, as the Chainlink core code already has this.这确实使用事件来获取 requestId,但是,您实际上不必自己创建事件,因为 Chainlink 核心代码已经有了这个。

    it('Should successfully make an external API request and get a result', async () => {
      const transaction = await apiConsumer.requestVolumeData()
      const tx_receipt = await transaction.wait()
      const requestId = tx_receipt.events[0].topics[1]

      //wait 30 secs for oracle to callback
      await new Promise(resolve => setTimeout(resolve, 30000))

      //Now check the result
      const result = await apiConsumer.volume()
      console.log("API Consumer Volume: ", new web3.utils.BN(result._hex).toString())
      expect(new web3.utils.BN(result._hex)).to.be.a.bignumber.that.is.greaterThan(new web3.utils.BN(0))
    })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM