天天看點

在Solidity合約中調用Chainlink預言機

在這個教程中,我們将學習如何搜尋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實作一個回調函數以執行響應:

在Solidity合約中調用Chainlink預言機

我們不能簡單地使用任意預言機,因為每個預言機都被配置為執行特定的任務,這具體取決于其支援的擴充卡。為了找到滿足要求的高品質預言機,我們必須使用像

Chainlink Market

之類的清單服務。

2、用Chainlink Market搜尋符合需求的預言機

Chainlink的預言機清單服務有助于我們找到滿足要求的預言機。流行的API通常具有預配置的對某些端點的請求的預言機實作,這會使我們的開發更加容易。在Chainlink Market首頁搜尋欄中鍵入“ CoinGecko”,我們可以确認是否有預言機已經實作了所需的CoinGecko端點:

在Solidity合約中調用Chainlink預言機

如上圖所示,我們的确得到了一些結果!

“節點”部分列出了符合搜尋字元串的預言機節點。這可能意味着它們支援從CoinGecko API檢索資料的作業。在可用的三個節點中,Omniscience-Ropsten已驗證(帶圓圈),這表明了其可信度。此外它還有數量最高的運作作業(Jobs)。

向下滾動,我們可以在作業(Jobs)标題下看到ETH-USD CoinGecko。這看起來很完美,因為它似乎準确描述我們想要檢索的資料,并使用經過驗證的節點。單擊該連結可以檢視該作業的更多資訊:

在Solidity合約中調用Chainlink預言機

上圖顯示了預言機節點的詳細資訊。在左側(紅色矩形内)是Oracle的鍊上位址。如果要使用此oracle,則需要記下該位址。在螢幕的右側是三個頁籤:擴充卡、資料源和作業。單擊作業(Jobs)并滾動,直到找到ETH-USD CoinGecko。單擊該連結以顯示工作資訊頁面:

在Solidity合約中調用Chainlink預言機

上圖顯示了作業資訊頁面,在該頁面中可以檢視其在請求時工作的詳細資訊。突出顯示了作業ID和運作此作業的成本(這些也需要記下)。頁面右側是“任務清單”。這是作業在被調用時執行操作的清單。

每個任務使用一個被支援的擴充卡,逐個建立任務鍊。讓我們周遊清單中的每個任務,以找出作業

如何擷取所需的資料:

2.1 HTTP GET請求

[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-XEhjkfHd-1595382259128)(contract-oracle/http-get.png)]

第一個任務是使用HTTP GET調用CoinGecko API。我們可以從參數中的URL确認它發出了正确的CoinGecko請求。

這将傳回JSON響應結果。

2.2 JSON響應解析

在Solidity合約中調用Chainlink預言機

由于任務1傳回JSON,是以下一個任務需要對其進行解析以便通路我們需要的目标資料。任務2使用JSON Parse擴充卡通過提供的路徑周遊傳回的JSON對象。例如,任務2路徑中的目标資料将位于以下JSON結構中:

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

2.3 相乘計算

在Solidity合約中調用Chainlink預言機

我們已經從JSON結果中得到了價格,但這還沒有處理完。由于Solidity無法處理小數,是以任務3将價格乘以100,000,000以確定可以将其表示為整數。

2.4 ETH Int256

在Solidity合約中調用Chainlink預言機

然後,任務4将結果轉換為編碼的int256。

2.5 ETH交易

在Solidity合約中調用Chainlink預言機

最後,任務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按鈕,你應該會看到價格:

在Solidity合約中調用Chainlink預言機

4、結論

Chainlink預言機是強大的工具,可實作外部世界與區塊鍊之間的互操作性。諸如Chainlink Market之類的清單服務是一種有用的目錄服務,用于查找最适合需求的預言機。

在本教程示例中,我們找到了一個滿足需求的預言機作業,該作業已經配置為從目标服務請求資料。

預言機還支援接受GET請求URL作為參數并從中擷取資料的作業。這意味着你可以使用Chainlink預言機從任何外部API檢索資料。

原文連結:

用ChainLink通路區塊鍊外部資料 — 彙智網