Blockchain使用 ChainlinkClient.sol v0.8.0 時找不到錯誤成員
使用 ChainlinkClient.sol v0.8.0 時找不到錯誤成員add
我正在嘗試使用 Chainlink
APIConsumer
範例,並且我正在導入v0.8/ChainlinkClient.sol
文件。在編譯APIConsumer
契約時,我遇到了錯誤。錯誤
TypeError: Member "add" not found or not visible after argument-dependent lookup in struct Chainlink.Request memory. --> contracts/APIConsumer.sol:44:9: | 44 | request.add("get", "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD"); | ^^^^^^^^^^^
使用時沒有顯示任何錯誤
v0.6/ChainlinkClient.sol
。契約
APIConsumer.sol
//SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol"; /** * @notice reference link for Polygon-Chainlink API's integration * https://docs.matic.network/docs/develop/oracles/chainlink/ */ contract APIConsumer is ChainlinkClient { uint256 public volume; address private oracle; bytes32 private jobId; uint256 private fee; /** * Network: Matic Mumbai Testnet * Oracle: 0x58bbdbfb6fca3129b91f0dbe372098123b38b5e9 * Job ID: da20aae0e4c843f6949e5cb3f7cfe8c4 * LINK address: 0x326C977E6efc84E512bB9C30f76E30c160eD06FB * Fee: 0.01 LINK */ constructor() { //setPublicChainlinkToken; setChainlinkToken(0x326C977E6efc84E512bB9C30f76E30c160eD06FB); //oracle = 0x58bbdbfb6fca3129b91f0dbe372098123b38b5e9; oracle = 0x58BBDbfb6fca3129b91f0DBE372098123B38B5e9; jobId = "da20aae0e4c843f6949e5cb3f7cfe8c4"; fee = 0.01 * 10 ** 18; // 0.01 LINK } /** * 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: request.add("path", "RAW.ETH.USD.VOLUME24HOUR"); // 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, uint256 _volume) public recordChainlinkFulfillment(_requestId) { volume = _volume; } }
v0.8/ChainlinkClient.sol
從 複製它
node_modules
。// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./Chainlink.sol"; import "./interfaces/ENSInterface.sol"; import "./interfaces/LinkTokenInterface.sol"; import "./interfaces/OperatorInterface.sol"; import "./interfaces/PointerInterface.sol"; import { ENSResolver as ENSResolver_Chainlink } from "./vendor/ENSResolver.sol"; /** * @title The ChainlinkClient contract * @notice Contract writers can inherit this contract in order to create requests for the * Chainlink network */ contract ChainlinkClient { using Chainlink for Chainlink.Request; uint256 constant internal LINK_DIVISIBILITY = 10**18; uint256 constant private AMOUNT_OVERRIDE = 0; address constant private SENDER_OVERRIDE = address(0); uint256 constant private ORACLE_ARGS_VERSION = 1; uint256 constant private OPERATOR_ARGS_VERSION = 2; bytes32 constant private ENS_TOKEN_SUBNAME = keccak256("link"); bytes32 constant private ENS_ORACLE_SUBNAME = keccak256("oracle"); address constant private LINK_TOKEN_POINTER = 0xC89bD4E1632D3A43CB03AAAd5262cbe4038Bc571; ENSInterface private ens; bytes32 private ensNode; LinkTokenInterface private link; OperatorInterface private oracle; uint256 private requestCount = 1; mapping(bytes32 => address) private pendingRequests; event ChainlinkRequested( bytes32 indexed id ); event ChainlinkFulfilled( bytes32 indexed id ); event ChainlinkCancelled( bytes32 indexed id ); /** * @notice Creates a request that can hold additional parameters * @param specId The Job Specification ID that the request will be created for * @param callbackAddress The callback address that the response will be sent to * @param callbackFunctionSignature The callback function signature to use for the callback address * @return A Chainlink Request struct in memory */ function buildChainlinkRequest( bytes32 specId, address callbackAddress, bytes4 callbackFunctionSignature ) internal pure returns ( Chainlink.Request memory ) { Chainlink.Request memory req; return req.initialize(specId, callbackAddress, callbackFunctionSignature); } /** * @notice Creates a Chainlink request to the stored oracle address * @dev Calls `chainlinkRequestTo` with the stored oracle address * @param req The initialized Chainlink Request * @param payment The amount of LINK to send for the request * @return requestId The request ID */ function sendChainlinkRequest( Chainlink.Request memory req, uint256 payment ) internal returns ( bytes32 ) { return sendChainlinkRequestTo(address(oracle), req, payment); } /** * @notice Creates a Chainlink request to the specified oracle address * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to * send LINK which creates a request on the target oracle contract. * Emits ChainlinkRequested event. * @param oracleAddress The address of the oracle for the request * @param req The initialized Chainlink Request * @param payment The amount of LINK to send for the request * @return requestId The request ID */ function sendChainlinkRequestTo( address oracleAddress, Chainlink.Request memory req, uint256 payment ) internal returns ( bytes32 requestId ) { return rawRequest(oracleAddress, req, payment, ORACLE_ARGS_VERSION, oracle.oracleRequest.selector); } /** * @notice Creates a Chainlink request to the stored oracle address * @dev This function supports multi-word response * @dev Calls `requestOracleDataFrom` with the stored oracle address * @param req The initialized Chainlink Request * @param payment The amount of LINK to send for the request * @return requestId The request ID */ function requestOracleData( Chainlink.Request memory req, uint256 payment ) internal returns ( bytes32 ) { return requestOracleDataFrom(address(oracle), req, payment); } /** * @notice Creates a Chainlink request to the specified oracle address * @dev This function supports multi-word response * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to * send LINK which creates a request on the target oracle contract. * Emits ChainlinkRequested event. * @param oracleAddress The address of the oracle for the request * @param req The initialized Chainlink Request * @param payment The amount of LINK to send for the request * @return requestId The request ID */ function requestOracleDataFrom( address oracleAddress, Chainlink.Request memory req, uint256 payment ) internal returns ( bytes32 requestId ) { return rawRequest(oracleAddress, req, payment, OPERATOR_ARGS_VERSION, oracle.requestOracleData.selector); } /** * @notice Make a request to an oracle * @param oracleAddress The address of the oracle for the request * @param req The initialized Chainlink Request * @param payment The amount of LINK to send for the request * @param argsVersion The version of data support (single word, multi word) * @return requestId The request ID */ function rawRequest( address oracleAddress, Chainlink.Request memory req, uint256 payment, uint256 argsVersion, bytes4 funcSelector ) private returns ( bytes32 requestId ) { requestId = keccak256(abi.encodePacked(this, requestCount)); req.nonce = requestCount; pendingRequests[requestId] = oracleAddress; emit ChainlinkRequested(requestId); bytes memory encodedData = abi.encodeWithSelector( funcSelector, SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent req.id, req.callbackAddress, req.callbackFunctionId, req.nonce, argsVersion, req.buf.buf); require(link.transferAndCall(oracleAddress, payment, encodedData), "unable to transferAndCall to oracle"); requestCount += 1; } /** * @notice Allows a request to be cancelled if it has not been fulfilled * @dev Requires keeping track of the expiration value emitted from the oracle contract. * Deletes the request from the `pendingRequests` mapping. * Emits ChainlinkCancelled event. * @param requestId The request ID * @param payment The amount of LINK sent for the request * @param callbackFunc The callback function specified for the request * @param expiration The time of the expiration for the request */ function cancelChainlinkRequest( bytes32 requestId, uint256 payment, bytes4 callbackFunc, uint256 expiration ) internal { OperatorInterface requested = OperatorInterface(pendingRequests[requestId]); delete pendingRequests[requestId]; emit ChainlinkCancelled(requestId); requested.cancelOracleRequest(requestId, payment, callbackFunc, expiration); } /** * @notice Sets the stored oracle address * @param oracleAddress The address of the oracle contract */ function setChainlinkOracle( address oracleAddress ) internal { oracle = OperatorInterface(oracleAddress); } /** * @notice Sets the LINK token address * @param linkAddress The address of the LINK token contract */ function setChainlinkToken( address linkAddress ) internal { link = LinkTokenInterface(linkAddress); } /** * @notice Sets the Chainlink token address for the public * network as given by the Pointer contract */ function setPublicChainlinkToken() internal { setChainlinkToken(PointerInterface(LINK_TOKEN_POINTER).getAddress()); } /** * @notice Retrieves the stored address of the LINK token * @return The address of the LINK token */ function chainlinkTokenAddress() internal view returns ( address ) { return address(link); } /** * @notice Retrieves the stored address of the oracle contract * @return The address of the oracle contract */ function chainlinkOracleAddress() internal view returns ( address ) { return address(oracle); } /** * @notice Allows for a request which was created on another contract to be fulfilled * on this contract * @param oracleAddress The address of the oracle contract that will fulfill the request * @param requestId The request ID used for the response */ function addChainlinkExternalRequest( address oracleAddress, bytes32 requestId ) internal notPendingRequest(requestId) { pendingRequests[requestId] = oracleAddress; } /** * @notice Sets the stored oracle and LINK token contracts with the addresses resolved by ENS * @dev Accounts for subnodes having different resolvers * @param ensAddress The address of the ENS contract * @param node The ENS node hash */ function useChainlinkWithENS( address ensAddress, bytes32 node ) internal { ens = ENSInterface(ensAddress); ensNode = node; bytes32 linkSubnode = keccak256(abi.encodePacked(ensNode, ENS_TOKEN_SUBNAME)); ENSResolver_Chainlink resolver = ENSResolver_Chainlink(ens.resolver(linkSubnode)); setChainlinkToken(resolver.addr(linkSubnode)); updateChainlinkOracleWithENS(); } /** * @notice Sets the stored oracle contract with the address resolved by ENS * @dev This may be called on its own as long as `useChainlinkWithENS` has been called previously */ function updateChainlinkOracleWithENS() internal { bytes32 oracleSubnode = keccak256(abi.encodePacked(ensNode, ENS_ORACLE_SUBNAME)); ENSResolver_Chainlink resolver = ENSResolver_Chainlink(ens.resolver(oracleSubnode)); setChainlinkOracle(resolver.addr(oracleSubnode)); } /** * @notice Ensures that the fulfillment is valid for this contract * @dev Use if the contract developer prefers methods instead of modifiers for validation * @param requestId The request ID for fulfillment */ function validateChainlinkCallback( bytes32 requestId ) internal recordChainlinkFulfillment(requestId) // solhint-disable-next-line no-empty-blocks {} /** * @dev Reverts if the sender is not the oracle of the request. * Emits ChainlinkFulfilled event. * @param requestId The request ID for fulfillment */ modifier recordChainlinkFulfillment( bytes32 requestId ) { require(msg.sender == pendingRequests[requestId], "Source must be the oracle of the request"); delete pendingRequests[requestId]; emit ChainlinkFulfilled(requestId); _; } /** * @dev Reverts if the request is already pending * @param requestId The request ID for fulfillment */ modifier notPendingRequest( bytes32 requestId ) { require(pendingRequests[requestId] == address(0), "Request is already pending"); _; } }
您需要
using Chainlink for Chainlink.Request;
在契約聲明之後添加該行,如下所示:contract APIConsumer is ChainlinkClient { using Chainlink for Chainlink.Request; uint256 public volume; address private oracle; bytes32 private jobId; uint256 private fee;