由于区块链生态系统的性质,从链上智能合约中访问链外数据是不可能的。然而,Chainlink为区块链oracle提供了一个平台,区块链oracle是网络上充当链上和链下数据之间桥梁的节点。oracle使智能合约能够从外部世界检索数据。
每个oracle节点都可以配置为执行范围广泛的任务,具体取决于它支持的适配器。其中一些适配器包括httpget、httppost、JSON Parse、Multiply等的实现。
如何使用Chainlink Oracle
注意:在此示例中,我们使用的是Ropsten测试网。
假设我们要创建一个智能合约,该合约以以太坊的美元价格为准,这是根据受欢迎的价格分析网站CoinGecko的报道得出的。我们知道,我们的智能合约没有本地方法可以调用外部HTTP API,但是oracle节点可以。
使用请求和响应周期,我们的智能合约可以从oracle节点请求数据,该节点被配置为执行HTTP GET请求,并为oracle实现回调函数以响应。
图1:请求和接收数据流
我们不能简单地使用任何Oracle,因为每个Oracle被配置为执行特定的任务,具体取决于它们支持的适配器。为了找到适合我们需求的高品质Oracle,我们必须使用诸如Chainlink Market之类的挂牌服务进行搜索。
Chainlink market
列表服务使我们能够找到可以满足我们要求的Oracle。常用的API通常具有预先配置的对某些端点的请求的oracle实现,这使我们的开发更加容易。我们可以通过转到Chainlink Market主页并在搜索栏中键入“ CoinGecko”来确定所需的CoinGecko端点是否已由Oracle实施。
图2:Chainlink Market搜索“ CoinGecko”
如图2所示,我们得到了一些结果!
Nodes部分列出了已返回搜索字符串结果的oracle节点。这可能意味着它们支持从coingeckoapi检索数据的作业,在可用的三个节点中,Omniscience-Ropsten已验证(带圆圈),表明了它的可靠性。它的作业运行次数也最多。
向下滚动,我们可以在Jobs标题下看到ETH-USD CoinGecko。这看起来很完美,因为它似乎可以准确描述我们要检索的内容,并使用经过验证的节点。
图3显示了节点详细信息页面,该页面为我们提供了有关Oracle节点的更多信息。在左侧(红色矩形内)是oracle的链上地址。如果要使用此oracle,则需要记下该地址。
在屏幕的右侧是三个选项卡:Adapters, Feeds和Jobs。点击Jobs并滚动直到找到ETH-USD CoinGecko。单击该链接以显示工作信息页面。
图4向我们显示了jobs信息页面,在该页面中,我们可以查看有关jobs要求的详细信息。突出显示了作业ID和运行此作业的成本(也记下这些)。
页面右侧是“任务列表”。这是作业被调用时执行的操作的列表。每个任务使用一个受支持的适配器,一个接一个地创建一个任务链。让我们遍历列表中的每个任务,以找出作业如何获取所需的数据:
1.HTTP GET Request
第一个任务是使用HTTP GET调用CoinGecko API。我们可以从参数中的URL确认它发出了正确的CoinGecko请求。这将返回JSON响应主体。
2. JSON Parse
由于任务1返回JSON,因此下一个任务需要解析它以访问目标数据。任务2使用JSON Parse适配器通过提供的路径遍历返回的JSON对象。例如任务2路径中的目标数据将位于以下JSON结构中:
{
"market_data":
{
"current_price":
{
"usd": "PRICE_HERE"
}
}
}
3. Multiply
我们已经从JSON中获取了价格,但还没有完全准备好。由于Solidity不能处理小数,任务3将价格乘以100000000,以确保它可以表示为整数。
4. ETH Int256
然后任务4将结果转换为编码的int256。
5. ETH Transaction
最后任务5创建一个以太坊事务,将结果发送回原始合约。
智能合约编写
现在我们已经选择了一个可以满足请求的Oracle,让我们写一个可以提出请求的合约。Chainlink提供了一个名为ChainlinkClient的父合约,我们将对其进行扩展以简化请求和响应周期。
pragma solidity 0.6.0;
import "https://github.com/smartcontractkit/chainlink/evm-contracts/src/v0.6/ChainlinkClient.sol";
import "https://github.com/smartcontractkit/chainlink/evm-contracts/src/v0.6/vendor/Ownable.sol";
contract ExampleOracleClient is ChainlinkClient, Ownable {
address constant private ORACLE = 0x83dA1beEb89Ffaf56d0B7C50aFB0A66Fb4DF8cB1;
string constant private JOB_ID = "93547cb3c6784ec08a366be6211caa24";
uint256 constant private ORACLE_PAYMENT = 1 * LINK / 10;
uint256 public currentPrice;
event RequestEthereumPriceFulfilled(
bytes32 indexed requestId,
uint256 indexed price
);
constructor() public Ownable() {
setPublicChainlinkToken();
}
function requestEthereumPrice() public onlyOwner {
Chainlink.Request memory req = buildChainlinkRequest(stringToBytes32(JOB_ID), address(this), this.fulfillEthereumPrice.selector);
sendChainlinkRequestTo(ORACLE, req, ORACLE_PAYMENT);
}
function fulfillEthereumPrice(bytes32 _requestId, uint256 _price) public recordChainlinkFulfillment(_requestId) {
emit RequestEthereumPriceFulfilled(_requestId, _price);
currentPrice = _price;
}
function withdrawLink() public onlyOwner {
LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress());
require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer");
}
function stringToBytes32(string memory source) private pure returns (bytes32 result) {
bytes memory tempEmptyStringTest = bytes(source);
if (tempEmptyStringTest.length == 0) {
return 0x0;
}
assembly { // solhint-disable-line no-inline-assembly
result := mload(add(source, 32))
}
}
}
图5向我们展示了ExampleOracleClient合约。它具有使用通过Chainlink Market找到的Oracle向CoinGecko请求以太坊的最新美元价格的功能。让我们逐行浏览:
第7行:节点详细信息页面上的图3中找到的Oracle地址
第8和9行:图4中找到的工作ID和价格
第11行:currentPrice是将由执行请求的oracle填充的字段。
第19行:setPublicChainlinkToken()是ChainlinkClient父合约中可用的函数,该函数设置当前网络上LINK令牌的地址。
第22–25行:requestEthereumPrice()使用Oracle地址,作业ID,价格和回调函数构建Chainlink请求。然后它使用sendChainlinkRequestTo()请求数据,这是父ChainlinkClient合约提供的另一个功能。
第27行:Oracle用于完成请求的回调函数
第32行:使所有者能够从合约中提取LINK令牌的函数
第37行:用于构建请求的实用程序功能
尝试将此合约粘贴到Remix IDE中并部署到Ropsten测试网。部署后,将一些Ropsten LINK发送到其地址(您可以在此处找到Ropsten LINK水龙头)。然后当该事务成功完成后,在您可用的功能列表中单击requestEthereumPrice。几秒钟/分钟后,单击currentPrice按钮,您应该会看到一个价格!
结论
Chainlink oracle是强大的工具,可实现外部世界与区块链之间的互操作性。诸如Chainlink Market之类的清单服务是一种有用的目录服务,用于查找最适合您的智能合约需求的Oracle。
在我们的示例中,我们发现了一个oracle作业,该作业已配置为从目标终端请求数据。如果这样的工作不存在,或者您找不到它,也可以。Oracle还支持接受GET请求URL作为参数并从中获取数据的作业。这意味着您可以使用Chainlink oracle从任何外部API检索数据。