I am trying to fetch data from an api which gives multiple response in single call and I am doing this using chainlink external API calls.
In my smart contract i have use array of struct to store requested data after request fulfil by Operator contract. I had also created my own job spec [TOML File] by running node locally on my system.
Now my error occur inside job spec file when i request for data.
For better understanding i have provided my smart contract code and job code also there is a screen shot of error that occur when execution while fetch populating fetch data into struct formate of fulfillMultipleParameters(bytes32 requestId,Trade[] memory _prices)
Screen shot of error
Node Operator Job Spec TOML File
schemaVersion = 1
name = "Multiple_Array_of_Struct_Datas_1"
forwardingAllowed = true
maxTaskDuration = "0s"
contractAddress = "0x2D470Df5823edefe6941F8F737660661e47f62af"
minContractPaymentLinkJuels = "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_log -> decode_cbor
decode_cbor [type="cborparse" data="$(decode_log.data)"]
fetch [type="http" method=GET url="$(decode_cbor.url)" allowunrestrictednetworkaccess="true"]
decode_cbor -> fetch
path1_parse [type="jsonparse" path="$(decode_cbor.path1)" data="$(fetch)" ]
path2_parse [type="jsonparse" path="$(decode_cbor.path2)" data="$(fetch)"]
path3_parse [type="jsonparse" path="$(decode_cbor.path3)" data="$(fetch)"]
path4_parse [type="jsonparse" path="$(decode_cbor.path4)" data="$(fetch)"]
path5_parse [type="jsonparse" path="$(decode_cbor.path5)" data="$(fetch)"]
fetch -> path1_parse
fetch -> path2_parse
fetch -> path3_parse
fetch -> path4_parse
fetch -> path5_parse
path5_parse -> encode_mwr
path4_parse -> encode_mwr
path3_parse -> encode_mwr
path2_parse -> encode_mwr
path1_parse -> encode_mwr
encode_mwr [type="ethabiencode"
abi="(bytes32 requestId, Trade[] _prices)"
data="{\\"requestId\\": $(decode_log.requestId), \\"_prices\\": [[ $(path1_parse)], [$(path2_parse)], [$(path3_parse)], [$(path4_parse)], [$(path5_parse)]]}"
]
encode_tx [type="ethabiencode"
abi="fulfillOracleRequest2(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes calldata data)"
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_mwr)}"
]
submit_tx [type="ethtx" to="0x2D470Df5823edefe6941F8F737660661e47f62af" data="$(encode_tx)" from="[\\"0x761Cd84957ecD0344E6C01a02A7cAe479D07B838\\"]"]
encode_mwr -> encode_tx -> submit_tx
"""
Smart Contract Code
pragma solidity ^0.8.7;
import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol";
import "@chainlink/contracts/src/v0.8/ConfirmedOwner.sol";
import "@openzeppelin/contracts/utils/Strings.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 MultiWordConsumer is ChainlinkClient, ConfirmedOwner {
using Chainlink for Chainlink.Request;
struct Trade{
string price;
}
bytes32 private jobId;
uint256 private fee;
// multiple params returned in a single oracle response
Trade[] public trades;
event RequestMultipleFulfilled(
bytes32 indexed requestId,
Trade[] indexed prices
);
/**
* @notice Initialize the link token and target oracle
* @dev The oracle address must be an Operator contract for multiword response
*
*
* Sepolia Testnet details:
* Link Token: 0x779877A7B0D9E8603169DdbD7836e478b4624789
* Oracle: 0x6090149792dAAeE9D1D568c9f9a6F6B46AA29eFD (Chainlink DevRel)
* jobId: 53f9755920cd451a8fe46f5087468395
*
*/
constructor() ConfirmedOwner(msg.sender) {
setChainlinkToken(0x779877A7B0D9E8603169DdbD7836e478b4624789);
setChainlinkOracle(0x2D470Df5823edefe6941F8F737660661e47f62af); // Operator Contract Address
jobId = "3464b5f4c3f74b66a22f881506d2aae5"; //3464b5f4-c3f7-4b66-a22f-881506d2aae5
fee = (1 * LINK_DIVISIBILITY) / 10; // 0,1 10**18 (Varies by network and job)
}
/**
* @notice Request mutiple parameters from the oracle in a single transaction
*/
function requestMultipleParameters() public {
Chainlink.Request memory req = buildChainlinkRequest(
jobId,
address(this),
this.fulfillMultipleParameters.selector
);
req.add(
"url",
"https://api3.binance.com/api/v3/trades?symbol=BTCUSDT&limit=5"
);
for(uint i=0; i<5; i++){
string memory strindex = Strings.toString(i);
uint index = i + 1;
string memory pathindex = Strings.toString(index);
req.add(string.concat("path",pathindex), string.concat(strindex,",price"));
}
// req.add("path2", "1,price");
// req.add("path3", "2,price");
// req.add("path4", "3,price");
// req.add("path5", "4,price");
sendChainlinkRequest(req, fee); // MWR API.
}
/**
* @notice Fulfillment function for multiple parameters in a single request
* @dev This is called by the oracle. recordChainlinkFulfillment must be used.
*/
function fulfillMultipleParameters(
bytes32 requestId,
Trade[] memory _prices
) public recordChainlinkFulfillment(requestId) {
emit RequestMultipleFulfilled(
requestId,
_prices
);
for(uint i = 0; i< _prices.length; i++){
trades.push(_prices[i]);
}
}
function viewprice() public view returns(Trade[] memory ){
return trades;
}
/**
* 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"
);
}
}```