Large Responses
This guide explains how to make an HTTP GET request to an external API from a smart contract, using Chainlink's Request & Receive Data cycle and then receive large responses.
Example
This example shows how to:
- Call an API and fetch the response that is an arbitrary-length raw byte data.
IPFS is a decentralized file system for storing and accessing files, websites, applications, and data. For this example, we stored in IPFS a JSON file that contains arbitrary-length raw byte data. To check the response, directly paste the following URL in your browser: https://ipfs.io/ipfs/QmZgsvrA1o1C8BGCrx6mHTqR1Ui1XqbCrtbMVrRLHtuPVD?filename=big-api-response.json
Alternatively, run the following command in your terminal:
curl -X 'GET' \
'https://ipfs.io/ipfs/QmZgsvrA1o1C8BGCrx6mHTqR1Ui1XqbCrtbMVrRLHtuPVD?filename=big-api-response.json' \
-H 'accept: application/json'
The response should be similar to the following:
{
"image": "0x68747470733a2f2f697066732e696f2f697066732f516d5358416257356b716e3259777435444c336857354d736a654b4a4839724c654c6b51733362527579547871313f66696c656e616d653d73756e2d636861696e6c696e6b2e676966"
}
Fetch the value of image. To consume an API, your contract must import ChainlinkClient.sol. This contract exposes a struct named Chainlink.Request
, which your contract can use to build the API request. The request must include the following parameters:
- Link token address
- Oracle address
- Job id
- Request fee
- Task parameters
- Callback function signature
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol";
import "@chainlink/contracts/src/v0.8/shared/access/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 GenericLargeResponse 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 image_url;
bytes32 private jobId;
uint256 private fee;
/**
* @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: 7da2702f37fd48e5b1b9a5715e3509b6
*
*/
constructor() ConfirmedOwner(msg.sender) {
setChainlinkToken(0x779877A7B0D9E8603169DdbD7836e478b4624789);
setChainlinkOracle(0x6090149792dAAeE9D1D568c9f9a6F6B46AA29eFD);
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",
"https://ipfs.io/ipfs/QmZgsvrA1o1C8BGCrx6mHTqR1Ui1XqbCrtbMVrRLHtuPVD?filename=big-api-response.json"
);
req.add("path", "image");
sendChainlinkRequest(req, fee);
}
event RequestFulfilled(bytes32 indexed requestId, bytes indexed data);
/**
* @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;
image_url = 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"
);
}
}
To use this contract:
-
Open the contract in Remix.
-
Compile and deploy the contract using the Injected Provider environment. The contract includes all the configuration variables for the Sepolia testnet. Make sure your wallet is set to use Sepolia. The constructor sets the following parameters:
- The Chainlink Token address for Sepolia by calling the
setChainlinkToken
function. - The Oracle contract address for Sepolia by calling the
setChainlinkOracle
function. - The
jobId
: A specific job for the oracle node to run. In this case, the data is a bytes data type, so you must call a job that calls an API and returns bytes. We will be using a generic GET>bytes job that can be found here.
- The Chainlink Token address for Sepolia by calling the
-
Fund your contract with 0.1 LINK. To learn how to send LINK to contracts, read the Fund Your Contracts page.
-
Call the
data
andimage_url
functions to confirm that thedata
andimage_url
state variables are not set. -
Run the
requestBytes
function. This builds theChainlink.Request
using the correct parameters:- The
req.add("get", "<url>")
request parameter provides the oracle node with the url where to fetch the response. - The
req.add('path', 'image')
request parameter tells the oracle node how to parse the response.
- The
-
After few seconds, call the
data
andimage_url
functions. You should get non-empty responses.
Response Types
Make sure to choose an oracle job that supports the data type that your contract needs to consume. Multiple data types are available such as:
uint256
- Unsigned integersint256
- Signed integersbool
- True or False valuesstring
- Stringbytes32
- Strings and byte values. If you need to return a string, usebytes32
. Here's one method of convertingbytes32
tostring
. Currently, any return value must fit within 32 bytes. If the value is bigger than that, make multiple requests.bytes
- Arbitrary-length raw byte data
Setting the LINK token address, Oracle, and JobId
The setChainlinkToken
function sets the LINK token address for the network you are deploying to. The setChainlinkOracle
function sets a specific Chainlink oracle that a contract makes an API call from. The jobId
refers to a specific job for that node to run.
Each job is unique and returns different types of data. For example, a job that returns a bytes32
variable from an API would have a different jobId
than a job that retrieved the same data, but in the form of a uint256
variable.
Check the Find Existing Jobs page to learn how to find a job suitable to your use case.