'Chainlink: Contract cannot retrieve large-response data type from external adapter
I tried to use the large-response
type to fulfil the request but somehow it does not show up in my contract I tried to fulfil the status
value, and the job works completely as shown in my chainlink node but it does not change the status
value, it stays 0x
as it is. So, I wonder that is my contract or job spec wrong?
This is my contract
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol";
contract APIConsumer is ChainlinkClient {
using Chainlink for Chainlink.Request;
bytes public status;
string public statusString;
address private oracle;
bytes32 private jobId;
uint256 private fee;
event RequestFulfilled(bytes32 indexed requestId,bytes indexed data);
/**
* Network: Kovan
* Oracle: 0xc57B33452b4F7BB189bB5AfaE9cc4aBa1f7a4FD8 (Chainlink Devrel
* Node)
* Job ID: d5270d1c311941d0b08bead21fea7747
* Fee: 0.1 LINK
*/
constructor() {
setPublicChainlinkToken();
oracle = 0xDFE5e6C5C624724384b55719b7da79d3EbB60057;
fee = 1 * 10 ** 18; // (Varies by network and job)
}
function requesData(string memory _jobId) public returns (bytes32 requestId)
{
Chainlink.Request memory request = buildChainlinkRequest(stringToBytes32(_jobId), address(this), this.fulfill.selector);
// Set the URL to perform the GET request on
request.add("trackingNo", "HF123456789DL");
return sendChainlinkRequestTo(oracle, request, fee);
}
/**
* Receive the response in the form of uint256
*/
function fulfill(bytes32 _requestId, bytes memory bytesData) public recordChainlinkFulfillment(_requestId)
{
emit RequestFulfilled(_requestId, bytesData);
status = bytesData;
statusString = string(status);
}
// function withdrawLink() external {} - Implement a withdraw function to avoid locking your LINK in the contract
// function getStatus() public view returns (string memory) {
// return bytes32ToString(status);
// }
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 stringToBytes32(string memory source)
public
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))
}
}
}
This is my job spec.
type = "directrequest"
schemaVersion = 1
name = "Halffin-Data-EA-Create-Tracking8"
externalJobID = "3f706a6b-efdd-44ac-8167-f880a6ca63ac"
maxTaskDuration = "0s"
contractAddress = "0xDFE5e6C5C624724384b55719b7da79d3EbB60057"
minIncomingConfirmations = 0
observationSource = """
decode_log [type=ethabidecodelog
abi="OracleRequest(bytes32 indexed specId, address requester, bytes32 requestId, uint256 payment, address callbackAddr, bytes4 callbackFunctionId, uint256 cancelExpiration, uint256 dataVersion, bytes data)"
data="$(jobRun.logData)"
topics="$(jobRun.logTopics)"]
decode_cbor [type=cborparse data="$(decode_log.data)"]
fetch [type=bridge name="halffin-data" requestData="{\\"id\\": $(jobSpec.externalJobID), \\"data\\": { \\"trackingNo\\": $(decode_cbor.trackingNo)}}"]
parse [type=jsonparse path="data,tracking,slug" data="$(fetch)"]
encode_data [type=ethabiencode abi="(bytes value)" data="{ \\"value\\": $(parse) }"]
encode_tx [type=ethabiencode
abi="fulfillOracleRequest(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes data)"
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}"
]
submit_tx [type=ethtx to="0xDFE5e6C5C624724384b55719b7da79d3EbB60057" data="$(encode_tx)"]
decode_log -> decode_cbor -> fetch -> parse -> encode_data -> encode_tx -> submit_tx
"""
- These are logs from completed job
fetch
"{\"jobRunID\":\"3f706a6b-efdd-44ac-8167-f880a6ca63ac\",\"data\":{\"tracking\":{\"id\":2,\"slug\":\"halffin-logistics\",\"tracking_number\":\"HF123456789DL\"},\"result\":null},\"result\":null}"
name: halffin-data
requestData: {"id": $(jobSpec.externalJobID), "data": { "trackingNo": $(decode_cbor.trackingNo)}}
parse
"halffin-logistics"
path: data,tracking,slug
data: $(fetch)
encode_data
"0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001168616c6666696e2d6c6f67697374696373000000000000000000000000000000"
abi: (bytes value)
data: { "value": $(parse) }
encode_tx
"0x728853aa63b008d8b908b2d431b9ea703268ba10e60ab40603941ec91a2955278f219c1e0000000000000000000000000000000000000000000000000de0b6b3a7640000000000000000000000000000136e61cdeae727926aa768574e2f979c724d6cad7c1de7e1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000062586d6800000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001168616c6666696e2d6c6f67697374696373000000000000000000000000000000"
abi: fulfillOracleRequest(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes data)
data: {"requestId": $(decode_log.requestId), "payment": $(decode_log.payment), "callbackAddress": $(decode_log.callbackAddr), "callbackFunctionId": $(decode_log.callbackFunctionId), "expiration": $(decode_log.cancelExpiration), "data": $(encode_data)}
submit_tx
"{\"logs\": [], \"root\": \"0x\", \"status\": \"0x0\", \"gasUsed\": \"0x5c49\", \"blockHash\": \"0x5b55db677b2776bb637fdb9ba2077e7db21de8e8beba60fb79e1384ae51f39a8\", \"logsBloom\": \"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\", \"blockNumber\": \"0x1d94cd5\", \"contractAddress\": \"0x0000000000000000000000000000000000000000\", \"transactionHash\": \"0xc5371c5ce1692b39835e44fb61c47d2deeeb509f71e32fccb0c5d42eec3be443\", \"transactionIndex\": \"0x1\", \"cumulativeGasUsed\": \"0x39418\"}"
to: 0xDFE5e6C5C624724384b55719b7da79d3EbB60057
data: $(encode_tx)
In case, you might wonder why I use the large-response
data type. I followed this link
Solution 1:[1]
The contractAddress
specified in the (Get > Large bytes)
must be pointed at operator.sol
not oracle.sol
. (Get > Uint256)
is pointed at oracle.sol
. Oracle.sol
is not meant to handle Large bytes, nor multi-variable Uint256 output.
Here is the code to deploy the current version of operator.sol
on remix to then obtain the correct contractAddress
to the associated job-spec within the chainlink node GUI.
// SPDX-License-Identifier: MIT
pragma solidity ^0.7.0;
import "@chainlink/contracts/src/v0.7/Operator.sol";
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Matt - Block-Farms.io |