从 Chainlink 获取去中心化数据是否有比通过节点进行单独的多个 API 调用更简单的方法?
Is there a simpler way to get decentralized data from Chainlink than doing separate multiple API calls through nodes?
我想在我正在 Remix 中测试的 solidity 项目中获取以美元为单位的 ETH 的喂价数据。我使用 Chainlink 请求数据作为指导,以便我的数据可以分散。
现在,我向具有不同 URL 的不同节点发出 3 个 chainlink 请求,然后计算三个响应的中值以获得去中心化价格。看起来这是一种相当乏味的方法,有没有更简单的方法来做到这一点?
function requestEthereumPrice(address _address, bytes32 job_id, string url)
public
onlyOwner
{
Chainlink.Request memory req = buildChainlinkRequest(stringToBytes32(JOB_ID), address(this), this.fulfill.selector);
req.add("get", url);
req.add("path", "USD");
req.addInt("times", 100);
sendChainlinkRequestTo(_address, req, ORACLE_PAYMENT);
}
function multipleData() public{
requestEthereumPrice(ORACLE_ADDRESS, JOB_ID);
requestEthereumPrice(ORACLE2_ADDRESS, JOB2_ID);
requestEthereumPrice(ORACLE3_ADDRESS, JOB3_ID);
}
function fulfill(bytes32 _requestId, uint256 _price)
public
// Use recordChainlinkFulfillment to ensure only the requesting oracle can fulfill
recordChainlinkFulfillment(_requestId)
{
currentPriceList[index] = _price;
index = (index + 1) & 3
currentPrice = median();
}
欢迎来到 Stack Overflow!
您的方法是最“蛮力”的方法,很有效。但是,目前有两种方法可以改善这一点。
1。使用 reference data contracts
参考数据合约是一种合约,它具有多个受信任的去中心化 Chainlink 节点,将来自不同数据提供商的价格更新发送到区块链上的一个参考点,供任何人查询。您的特定货币对 ETH/USD
是当前支持的货币对之一。获取该数据的代码如下所示:
pragma solidity ^0.6.0;
import "github.com/smartcontractkit/chainlink/evm-contracts/src/v0.6/dev/AggregatorInterface.sol";
contract ReferenceConsumer {
AggregatorInterface internal ref;
// Use 0xF79D6aFBb6dA890132F9D7c355e3015f15F3406F as the address of the ETH/USD pair
constructor(address _aggregator) public {
ref = AggregatorInterface(_aggregator);
}
function getLatestAnswer() public view returns (int256) {
return ref.latestAnswer();
}
function getLatestTimestamp() public view returns (uint256) {
return ref.latestTimestamp();
}
您可以在其中找到当前支持的供稿列表 feeds documentation or the slightly nicer looking page of their feeds explorer。
2。使用预协调器合约
如果你想要一个盒装解决方案,数字 1 很好,但是,也许你不同意 Chainlink 的节点选择,并且想要你自己的实现(这增加了去中心化!)。您的解决方案是选择自己的节点网络的一种方式。
预协调器合约允许您像上面那样制作一个普通的 buildChainlinkRequest
,但会为您将其散布到多个节点。要创建它,首先要部署一个合约:
pragma solidity ^0.5.0;
import "github.com/smartcontractkit/chainlink/evm-contracts/src/v0.5/PreCoordinator.sol";
然后您可以从合约中调用 createServiceAgreement
,它采用参数 uint256 _minResponses, address[] _oracles, address[]_jobIds, uint256[] _payments
。您可以使用 remix 来部署它们。
一旦您从预协调器合约部署了服务协议,它就会为您提供一个服务协议 ID。您可以通过检查日志或查看类似 etherscan 的内容并转到 topic 1
查看 ID 来找到此 ID。这是一个 example.
一旦你有了预协调器的地址和服务协议,你就可以使用预协调器合约的地址作为oracle地址,并在jobId处使用服务协议。这意味着您可以通过以下方式调用大量节点:
function requestEthereumPrice(address precoordinator_address, bytes32 service_agreement, string url)
public
onlyOwner
{
Chainlink.Request memory req = buildChainlinkRequest(service_agreement, address(this), this.fulfill.selector);
req.add("get", url);
req.add("path", "USD");
req.addInt("times", 100);
sendChainlinkRequestTo(precoordinator_address, req, ORACLE_PAYMENT);
}
我想在我正在 Remix 中测试的 solidity 项目中获取以美元为单位的 ETH 的喂价数据。我使用 Chainlink 请求数据作为指导,以便我的数据可以分散。
现在,我向具有不同 URL 的不同节点发出 3 个 chainlink 请求,然后计算三个响应的中值以获得去中心化价格。看起来这是一种相当乏味的方法,有没有更简单的方法来做到这一点?
function requestEthereumPrice(address _address, bytes32 job_id, string url)
public
onlyOwner
{
Chainlink.Request memory req = buildChainlinkRequest(stringToBytes32(JOB_ID), address(this), this.fulfill.selector);
req.add("get", url);
req.add("path", "USD");
req.addInt("times", 100);
sendChainlinkRequestTo(_address, req, ORACLE_PAYMENT);
}
function multipleData() public{
requestEthereumPrice(ORACLE_ADDRESS, JOB_ID);
requestEthereumPrice(ORACLE2_ADDRESS, JOB2_ID);
requestEthereumPrice(ORACLE3_ADDRESS, JOB3_ID);
}
function fulfill(bytes32 _requestId, uint256 _price)
public
// Use recordChainlinkFulfillment to ensure only the requesting oracle can fulfill
recordChainlinkFulfillment(_requestId)
{
currentPriceList[index] = _price;
index = (index + 1) & 3
currentPrice = median();
}
欢迎来到 Stack Overflow!
您的方法是最“蛮力”的方法,很有效。但是,目前有两种方法可以改善这一点。
1。使用 reference data contracts
参考数据合约是一种合约,它具有多个受信任的去中心化 Chainlink 节点,将来自不同数据提供商的价格更新发送到区块链上的一个参考点,供任何人查询。您的特定货币对 ETH/USD
是当前支持的货币对之一。获取该数据的代码如下所示:
pragma solidity ^0.6.0;
import "github.com/smartcontractkit/chainlink/evm-contracts/src/v0.6/dev/AggregatorInterface.sol";
contract ReferenceConsumer {
AggregatorInterface internal ref;
// Use 0xF79D6aFBb6dA890132F9D7c355e3015f15F3406F as the address of the ETH/USD pair
constructor(address _aggregator) public {
ref = AggregatorInterface(_aggregator);
}
function getLatestAnswer() public view returns (int256) {
return ref.latestAnswer();
}
function getLatestTimestamp() public view returns (uint256) {
return ref.latestTimestamp();
}
您可以在其中找到当前支持的供稿列表 feeds documentation or the slightly nicer looking page of their feeds explorer。
2。使用预协调器合约
如果你想要一个盒装解决方案,数字 1 很好,但是,也许你不同意 Chainlink 的节点选择,并且想要你自己的实现(这增加了去中心化!)。您的解决方案是选择自己的节点网络的一种方式。
预协调器合约允许您像上面那样制作一个普通的 buildChainlinkRequest
,但会为您将其散布到多个节点。要创建它,首先要部署一个合约:
pragma solidity ^0.5.0;
import "github.com/smartcontractkit/chainlink/evm-contracts/src/v0.5/PreCoordinator.sol";
然后您可以从合约中调用 createServiceAgreement
,它采用参数 uint256 _minResponses, address[] _oracles, address[]_jobIds, uint256[] _payments
。您可以使用 remix 来部署它们。
一旦您从预协调器合约部署了服务协议,它就会为您提供一个服务协议 ID。您可以通过检查日志或查看类似 etherscan 的内容并转到 topic 1
查看 ID 来找到此 ID。这是一个 example.
一旦你有了预协调器的地址和服务协议,你就可以使用预协调器合约的地址作为oracle地址,并在jobId处使用服务协议。这意味着您可以通过以下方式调用大量节点:
function requestEthereumPrice(address precoordinator_address, bytes32 service_agreement, string url)
public
onlyOwner
{
Chainlink.Request memory req = buildChainlinkRequest(service_agreement, address(this), this.fulfill.selector);
req.add("get", url);
req.add("path", "USD");
req.addInt("times", 100);
sendChainlinkRequestTo(precoordinator_address, req, ORACLE_PAYMENT);
}