I've altered the chainlink APIconsumer example to read a JSON file which contains data that I wish to bring into and store in the smart contract
pragma solidity ^0.6.0;
import "https://raw.githubusercontent.com/smartcontractkit/chainlink/develop/evm-contracts/src/v0.6/ChainlinkClient.sol";
contract APIConsumer is ChainlinkClient {
string public Name;
address private oracle;
bytes32 private jobId;
uint256 private fee;
/**
* Network: Kovan
* Oracle: Chainlink - 0x2f90A6D021db21e1B2A077c5a37B3C7E75D15b7e
* Job ID: Chainlink - 50fc4215f89443d185b061e5d7af9490
* Fee: 0.1 LINK
*/
constructor() public {
setPublicChainlinkToken();
oracle = 0x2f90A6D021db21e1B2A077c5a37B3C7E75D15b7e;
jobId = "50fc4215f89443d185b061e5d7af9490";
fee = 0.1 * 10 ** 18; // 0.1 LINK
}
/**
* Create a Chainlink request to retrieve API response, find the target price
* data, then multiply by 100 (to remove decimal places from price).
*/
function requestAthleteData() 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://1e68b62e-578e-4390-bf43-6b70a92a23b6.mock.pstmn.io/get");
// Set the path to find the desired data in the API response, where the response format is:
// {"USD":243.33}
request.add("path", "Name");
// Multiply the result by 100 to remove decimals
// request.addInt("times", 100);
// Sends the request
return sendChainlinkRequestTo(oracle, request, fee);
}
/**
* Receive the response in the form of uint256
*/
function fulfill(bytes32 _requestId, string memory _name) public recordChainlinkFulfillment(_requestId)
{
Name = _name;
}
}
This is the data its trying to read: https://1e68b62e-578e-4390-bf43-6b70a92a23b6.mock.pstmn.io/get
[ { "Name": "Tom", "Birthday": "2021-07-01", "Nationality": "SA", "Address": "123 st st" } ]
It has no problems deploying but then when I call the function 'requesttAthletedata' it processes it but doesn't return anything. Am I missing a step somewhere? Or is it a problem with the code?
First, change the _name
argument in fulfill()
to bytes32.
Second, change your request path to this:
request.add("path", "0.Name");
Chainlink cannot currently write strings to a smart contract, only bytes32 which can then be converted into a string. Also, your JSON object was within an array (at the first index) which is why we need to specify "0.Name" as the JSON path.
Third, if you want to convert the bytes32 to a string within the smart contract, you will need to do it within the fulfill()
method.
Your final code should look like this:
pragma solidity ^0.6.0;
import "@chainlink/contracts/src/v0.6/ChainlinkClient.sol";
contract test is ChainlinkClient {
string public Name;
address private oracle;
bytes32 private jobId;
uint256 private fee;
/**
* Network: Kovan
* Oracle: Chainlink - 0x2f90A6D021db21e1B2A077c5a37B3C7E75D15b7e
* Job ID: Chainlink - 50fc4215f89443d185b061e5d7af9490
* Fee: 0.1 LINK
*/
constructor() public {
setPublicChainlinkToken();
oracle = 0x2f90A6D021db21e1B2A077c5a37B3C7E75D15b7e;
jobId = "50fc4215f89443d185b061e5d7af9490";
fee = 0.1 * 10 ** 18; // 0.1 LINK
}
/**
* Create a Chainlink request to retrieve API response, find the target price
* data, then multiply by 100 (to remove decimal places from price).
*/
function requestAthleteData() 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://1e68b62e-578e-4390-bf43-6b70a92a23b6.mock.pstmn.io/get");
// Set the path to find the desired data in the API response, where the response format is:
// {"USD":243.33}
request.add("path", "0.Name");
// Multiply the result by 100 to remove decimals
// request.addInt("times", 100);
// Sends the request
return sendChainlinkRequestTo(oracle, request, fee);
}
/**
* Receive the response in the form of uint256
*/
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 fulfill(bytes32 _requestId, bytes32 _name) public recordChainlinkFulfillment(_requestId)
{
string memory stringName = bytes32ToString(_name);
Name = stringName;
}
}