简体   繁体   English

如何使用 Chainlink api 调用从 api 返回的 json 检索字符串值

[英]How do I use a Chainlink api call to retrieve a string value from json returne by api

I am trying to use a chainlink request to make an api call, then update the volume variable with the result of the api call.我正在尝试使用 chainlink 请求进行 api 调用,然后使用 api 调用的结果更新 volume 变量。

The api call should retrieve a string. api 调用应检索一个字符串。 After deploying and funding the smart contract it seems I am able to make the api call successfully (although I'm not sure about this).在部署智能合约并为其提供资金后,我似乎能够成功拨打 api 电话(尽管我对此不确定)。 The problem is the volume variable isn't updating.问题是 volume 变量没有更新。

I adapted the code from a chainlink tutorial .我改编了chainlink 教程中的代码。 The original tutorial code works, to my mind the changes I made should also work.原始教程代码有效,在我看来我所做的更改也应该有效。 Can anyone help with this?有人能帮忙吗?

 // SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol"; /** * Request tes.net LINK and ETH here: https://faucets.chain.link/ * Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: https://docs.chain.link/docs/link-token-contracts/ */ /** * THIS IS AN EXAMPLE CONTRACT WHICH USES HARDCODED VALUES FOR CLARITY. * PLEASE DO NOT USE THIS CODE IN PRODUCTION. */ contract APIConsumer is ChainlinkClient { using Chainlink for Chainlink.Request; string public volume; address private oracle; bytes32 private jobId; uint256 private fee; /** * Network: Kovan * Oracle: 0xc57B33452b4F7BB189bB5AfaE9cc4aBa1f7a4FD8 (Chainlink Devrel * Node) * Job ID: d5270d1c311941d0b08bead21fea7747 * Fee: 0.1 LINK */ constructor() { setPublicChainlinkToken(); oracle = 0xF405B99ACa8578B9eb989ee2b69D518aaDb90c1F; jobId = "c51694e71fa94217b0f4a71b2a6b565a"; fee = 0.1 * 10 ** 18; // (Varies by.network and job) } /** * Create a Chainlink request to retrieve API response, find the target * data, then multiply by 1000000000000000000 (to remove decimal places from data). */ function requestVolumeData() public returns (bytes32 requestId) { Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfill.selector); // Set the URL to perform the GET request on request.add("get", "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD"); // Set the path to find the desired data in the API response, where the response format is: // {"RAW": // {"ETH": // {"USD": // { // "VOLUME24HOUR": xxx.xxx, // } // } // } // } request.add("path", "RAW.ETH.USD.MARKET"); // // Multiply the result by 1000000000000000000 to remove decimals // int timesAmount = 10**18; // request.addInt("times", timesAmount); // Sends the request return sendChainlinkRequestTo(oracle, request, fee); } /** * Receive the response in the form of uint256 */ function fulfill(bytes32 _requestId, bytes32 _volume) public recordChainlinkFulfillment(_requestId) { volume = bytes32ToString(_volume); } function bytes32ToString(bytes32 _bytes32) public pure returns (string memory) { uint8 i = 0; while(i < 32 && _bytes32[i];= 0) { i++; } bytes memory bytesArray = new bytes(i); for (i = 0; i < 32 && _bytes32[i];= 0; i++) { bytesArray[i] = _bytes32[i]; } return string(bytesArray); } // function withdrawLink() external {} - Implement a withdraw function to avoid locking your LINK in the contract }

To return a string, you actually have to return a bytes32 and cast it to a string on-chain.要返回一个字符串,您实际上必须返回一个bytes32并将其转换为链上的字符串。

You can use something like this, to turn a bytes32 to string:您可以使用类似这样的方法将 bytes32 转换为字符串:

function bytes32ToString(bytes32 _bytes32) public pure returns (string memory) {
        uint8 i = 0;
        while(i < 32 && _bytes32[i] != 0) {
            i++;
        }
        bytes memory bytesArray = new bytes(i);
        for (i = 0; i < 32 && _bytes32[i] != 0; i++) {
            bytesArray[i] = _bytes32[i];
        }
        return string(bytesArray);
    }

Here is one working example with AviationStack.这是 AviationStack 的一个工作示例。 Replace the <access_key> with your access_key, in the API URL.在 API URL 中将<access_key>替换为您的 access_key。

//SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

import '@chainlink/contracts/src/v0.8/ChainlinkClient.sol';
import '@chainlink/contracts/src/v0.8/ConfirmedOwner.sol';

/**
 * Request testnet LINK and ETH here: https://faucets.chain.link/
 * Find information on LINK Token Contracts and get the latest ETH and LINK faucets here: https://docs.chain.link/docs/link-token-contracts/
 */

/**
 * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.
 * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
 * DO NOT USE THIS CODE IN PRODUCTION.
 */

contract AviationGenericLargeResponse is ChainlinkClient, ConfirmedOwner {
    using Chainlink for Chainlink.Request;

    // variable bytes(arbitrary-length raw byte data) returned in a single oracle response
    bytes public data;
    string public flightStatus;

    bytes32 private jobId;
    uint256 private fee;

    event RequestFulfilled(bytes32 indexed requestId, bytes indexed data);
    /**
     * @notice Initialize the link token and target oracle
     * @dev The oracle address must be an Operator contract for multiword response
     *
     *
     * Goerli Testnet details:
     * Link Token: 0x326C977E6efc84E512bB9C30f76E30c160eD06FB
     * Oracle: 0xCC79157eb46F5624204f47AB42b3906cAA40eaB7 (Chainlink DevRel)
     * jobId: 7da2702f37fd48e5b1b9a5715e3509b6
     *
     */
    constructor() ConfirmedOwner(msg.sender) {
        setChainlinkToken(0x326C977E6efc84E512bB9C30f76E30c160eD06FB);
        setChainlinkOracle(0xCC79157eb46F5624204f47AB42b3906cAA40eaB7);
        jobId = '7da2702f37fd48e5b1b9a5715e3509b6';
        fee = (1 * LINK_DIVISIBILITY) / 10; // 0,1 * 10**18 (Varies by network and job)
    }

    /**
     * @notice Request variable bytes from the oracle
     */
    function requestBytes() public {
        Chainlink.Request memory req = buildChainlinkRequest(jobId, address(this), this.fulfillBytes.selector);
        req.add(
            'get',
            'http://api.aviationstack.com/v1/flights?access_key=a6656fabf7fbe4fde6e4061f5be7042a&flight_number=611&airline_name=Qantas&flight_status=landed&limit=1'
        );
        req.add('path', 'data,0,flight_status');
        sendChainlinkRequest(req, fee);
    }


    /**
     * @notice Fulfillment function for variable bytes
     * @dev This is called by the oracle. recordChainlinkFulfillment must be used.
     */
    function fulfillBytes(bytes32 requestId, bytes memory bytesData) public recordChainlinkFulfillment(requestId) {
        emit RequestFulfilled(requestId, bytesData);
        data = bytesData;
        flightStatus = string(data);
    }

    /**
     * Allow withdraw of Link tokens from the contract
     */
    function withdrawLink() public onlyOwner {
        LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress());
        require(link.transfer(msg.sender, link.balanceOf(address(this))), 'Unable to transfer');
    }
}

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

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