在Solidity合约中调用Chainlink预言机

简介: 在这个教程中,我们将学习如何搜索Chainlink Market以找到满足需求的Chainlink预言机(Oracle),以及如何编写Solidity智能合约实现通过预言机访问区块链外部数据(例如货币价格)的功能。

在这个教程中,我们将学习如何搜索Chainlink Market以找到满足需求的Chainlink预言机(Oracle),以及如何编写Solidity智能合约实现通过预言机访问区块链外部数据(例如货币价格)的功能。

用自己熟悉的语言学习 以太坊DApp开发Java | Php | Python | .Net / C# | Golang | Node.JS | Flutter / Dart

由于区块链生态系统的本质,从链上的智能合约直接访问链下数据是不可能的。但是,Chainlink为区块链预言机提供了一个平台,这些预言机充当链上和链外数据之间的桥梁。预言机使智能合约能够从区块链外部获取数据。

可以将每个预言机节点配置为执行各种任务,具体取决于其支持的适配器。其中一些适配器包括HTTP GET,HTTP POST,JSON Parse,Multiply等的实现。

1、Chainlink预言机简介

假设我们要创建一个智能合约,该合约将根据CoinGecko上的以太坊美元价格做出不同的响应。我们知道智能合约没有办法调用外部HTTP API,但是oracle节点可以。

通过请求-响应周期处理,智能合约就可以从oracle节点请求数据,该节点被配置为执行HTTP GET请求,并为oracle实现一个回调函数以执行响应:
在这里插入图片描述

我们不能简单地使用任意预言机,因为每个预言机都被配置为执行特定的任务,这具体取决于其支持的适配器。为了找到满足要求的高质量预言机,我们必须使用像Chainlink Market之类的清单服务。

2、用Chainlink Market搜索符合需求的预言机

Chainlink的预言机列表服务有助于我们找到满足要求的预言机。流行的API通常具有预配置的对某些端点的请求的预言机实现,这会使我们的开发更加容易。在Chainlink Market主页搜索栏中键入“ CoinGecko”,我们可以确认是否有预言机已经实现了所需的CoinGecko端点:

在这里插入图片描述

如上图所示,我们的确得到了一些结果!

“节点”部分列出了符合搜索字符串的预言机节点。这可能意味着它们支持从CoinGecko API检索数据的作业。在可用的三个节点中,Omniscience-Ropsten已验证(带圆圈),这表明了其可信度。此外它还有数量最高的运行作业(Jobs)。

向下滚动,我们可以在作业(Jobs)标题下看到ETH-USD CoinGecko。这看起来很完美,因为它似乎准确描述我们想要检索的数据,并使用经过验证的节点。单击该链接可以查看该作业的更多信息:

在这里插入图片描述

上图显示了预言机节点的详细信息。在左侧(红色矩形内)是Oracle的链上地址。如果要使用此oracle,则需要记下该地址。在屏幕的右侧是三个选项卡:适配器、数据源和作业。单击作业(Jobs)并滚动,直到找到ETH-USD CoinGecko。单击该链接以显示工作信息页面:

在这里插入图片描述

上图显示了作业信息页面,在该页面中可以查看其在请求时工作的详细信息。突出显示了作业ID和运行此作业的成本(这些也需要记下)。页面右侧是“任务列表”。这是作业在被调用时执行操作的列表。
每个任务使用一个被支持的适配器,逐个创建任务链。让我们遍历列表中的每个任务,以找出作业
如何获取所需的数据:

2.1 HTTP GET请求

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XEhjkfHd-1595382259128)(contract-oracle/http-get.png)]

第一个任务是使用HTTP GET调用CoinGecko API。我们可以从参数中的URL确认它发出了正确的CoinGecko请求。
这将返回JSON响应结果。

2.2 JSON响应解析

在这里插入图片描述

由于任务1返回JSON,因此下一个任务需要对其进行解析以便访问我们需要的目标数据。任务2使用JSON Parse适配器通过提供的路径遍历返回的JSON对象。例如,任务2路径中的目标数据将位于以下JSON结构中:

{ 
  “ market_data”:
    { 
      “ current_price”:
        { 
          “ usd”:“ PRICE_HERE” 
        } 
    } 
}

2.3 相乘计算

在这里插入图片描述

我们已经从JSON结果中得到了价格,但这还没有处理完。由于Solidity无法处理小数,因此任务3将价格乘以100,000,000以确保可以将其表示为整数。

2.4 ETH Int256

在这里插入图片描述

然后,任务4将结果转换为编码的int256。

2.5 ETH交易

在这里插入图片描述

最后,任务5创建一个以太坊交易,以将结果发送回原始合约。

3、编写合约调用预言机

现在,让我们写一个请求预言机服务的合约。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))
        }
    }
}    

上面的ExampleOracleClient合约,利用预言机向CoinGecko请求以太坊的最新美元价格。让我们逐行说明:

  • 第7行:节点详细信息页面找到的预言机地址
  • 第8和9行:前面找到的作业ID和价格
  • 第11行: currentPrice是由执行请求的预言机填充的字段。
  • 第19行: setPublicChainlinkToken()是ChainlinkClient合同中提供的功能,用于设置当前网络上LINK令牌的地址。
  • 第22–25行: requestEthereumPrice()使用oracle地址、作业ID、价格和回调函数构建Chainlink请求。然后调用sendChainlinkRequestTo(),它使用父ChainlinkClient合同提供的另一个功能来请求数据。
  • 第27行: Oracle用于完成请求的回调函数
  • 第32行:使所有者能够从合约中提取LINK令牌的功能
  • 第37行:用于构建请求的辅助功能实现

尝试将此合约粘贴到Remix IDE中并部署到Ropsten测试网。部署后,向其地址发送一些Ropsten LINK(可以在此处找到Ropsten LINK Faucet)。当该交易成功完成后,单击requestEthereumPrice方法按钮。稍等一会儿后,单击currentPrice按钮,你应该会看到价格:

在这里插入图片描述

4、结论

Chainlink预言机是强大的工具,可实现外部世界与区块链之间的互操作性。诸如Chainlink Market之类的清单服务是一种有用的目录服务,用于查找最适合需求的预言机。

在本教程示例中,我们找到了一个满足需求的预言机作业,该作业已经配置为从目标服务请求数据。
预言机还支持接受GET请求URL作为参数并从中获取数据的作业。这意味着你可以使用Chainlink预言机从任何外部API检索数据。


原文链接:用ChainLink访问区块链外部数据 — 汇智网

目录
相关文章
|
算法 Python
合约/现货量化交易/合约交易/秒合约系统开发dapp技术搭建/Python代码规则示例
合约/现货量化交易/合约交易/秒合约系统开发dapp技术搭建/Python代码规则示例
|
23小时前
|
机器学习/深度学习 监控 API
合约量化/秒合约/永续合约对冲系统开发技术规则及源码示例
合约量化、秒合约、永续合约对冲系统的开发涉及策略编写、数据处理、交易执行、风险管理等关键技术。量化策略基于市场数据和机器学习,实现自动交易;秒合约强调高速交易和风险控制;永续合约通过资金费率机制平衡多空持仓。系统需具备高效的数据处理能力和实时监控功能,以确保交易的稳定性和安全性。
|
4月前
|
前端开发 API 区块链
合约交易丨秒合约丨永续合约丨合约跟单系统开发指南步骤
合约交易、秒合约、永续合约和合约跟单系统的开发基本要素和指南如下:
|
算法 机器人
秒合约期权机器人开发/秒合约系统/币币合约/技术开发应用
秒合约期权机器人开发/秒合约系统/币币合约/技术开发应用
|
6月前
|
存储 监控 关系型数据库
BRC20铭文合约NFT铸造交易平台系统开发稳定版/方案详细/步骤逻辑/源码指南
网络拓扑结构:设计一个稳定且高性能的网络拓扑结构对于BRC20铭文智能合约跨链系统的成功运行至关重要。
|
存储 供应链 安全
秒合约|现货合约|合约跟单系统开发(源码部署)
Web3.0的优势主要在于其将数据的存储和交互方式进行了彻底的改进
|
算法 测试技术 区块链
合约交易所开发指南:合约交易所搭建基本原理和步骤实现
合约交易所是基于区块链技术构建的去中心化交易平台。它使用智能合约来管理交易和资产。 智能合约开发环境:在进行合约交易所的开发之前,使用开发环境是很重要的。常见的开发环境包括Truffle、Embark、Builder等。这些开发环境提供了一些有用的命令和工具,如编译合约、部署合约、调试合约、运行单元测试等。
|
存储 安全 区块链
波场链合约交易所系统模型合约开发解决方案
address private _owner; mapping (address => bool) private _pausedUsers; event Log交易撮合(uint256 amount, address user, address trader); event Log资产变动(address from, address to, uint256 amount);
|
区块链
DAPP/LP代币智能合约分红合约系统开发代码逻辑分析
// DAPP代币的智能合约分红 function distributeTokenProceeds(address recipient, uint amount) public { require(recipient != address(0), "Recipient cannot be zero address");
|
区块链
以太坊竞猜合约开发源码规则
以太坊竞猜合约开发源码规则