Search
This guide explains how to make an HTTP GET request to an external API, that returns a json array, from a smart contract, using Chainlink's Request & Receive Data cycle and then receive the needed data from the array.
Prerequisites
You should be familiar with the Chainlink Basic Request Model. If you are new to developing smart contracts on Ethereum, see the Getting Started guide to learn the basics.
Topics
This example shows how to:
Coingecko GET /coins/markets/ API returns a list of coins and their market data such as price, market cap, and volume. To check the response, you can directly paste the following URL in your browser https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=false
or run this command in your terminal:
curl -X 'GET' \
'https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=100&page=1&sparkline=false' \
-H 'accept: application/json'
The response should be similar to the following:
[
{
"id": "bitcoin",
"symbol": "btc",
"name": "Bitcoin",
"image": "https://assets.coingecko.com/coins/images/1/large/bitcoin.png?1547033579",
"current_price": 42097,
"market_cap": 802478449872,
...
},
{
...
}
]
Fetch the id of the first element. 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:
Note on Funding Contracts
Making a GET request will fail unless your deployed contract has enough LINK to pay for it. Learn how to Acquire testnet LINK and Fund your contract.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;
import '@chainlink/contracts/src/v0.8/ChainlinkClient.sol';
import '@chainlink/contracts/src/v0.8/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 FetchFromArray is ChainlinkClient, ConfirmedOwner {
using Chainlink for Chainlink.Request;
string public id;
bytes32 private jobId;
uint256 private fee;
event RequestFirstId(bytes32 indexed requestId, string id);
/**
* @notice Initialize the link token and target oracle
*
* Goerli Testnet details:
* Link Token: 0x326C977E6efc84E512bB9C30f76E30c160eD06FB
* Oracle: 0xCC79157eb46F5624204f47AB42b3906cAA40eaB7 (Chainlink DevRel)
* jobId: 7d80a6386ef543a3abb52817f6707e3b
*
*/
constructor() ConfirmedOwner(msg.sender) {
setChainlinkToken(0x326C977E6efc84E512bB9C30f76E30c160eD06FB);
setChainlinkOracle(0xCC79157eb46F5624204f47AB42b3906cAA40eaB7);
jobId = '7d80a6386ef543a3abb52817f6707e3b';
fee = (1 * LINK_DIVISIBILITY) / 10; // 0,1 * 10**18 (Varies by network and job)
}
/**
* Create a Chainlink request to retrieve API response, find the target
* data which is located in a list
*/
function requestFirstId() public returns (bytes32 requestId) {
Chainlink.Request memory req = buildChainlinkRequest(jobId, address(this), this.fulfill.selector);
// Set the URL to perform the GET request on
// API docs: https://www.coingecko.com/en/api/documentation?
req.add('get', 'https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&per_page=10');
// Set the path to find the desired data in the API response, where the response format is:
// [{
// "id": "bitcoin",
// "symbol": btc",
// ...
// },
//{
// ...
// .. }]
// request.add("path", "0.id"); // Chainlink nodes prior to 1.0.0 support this format
req.add('path', '0,id'); // Chainlink nodes 1.0.0 and later support this format
// Sends the request
return sendChainlinkRequest(req, fee);
}
/**
* Receive the response in the form of string
*/
function fulfill(bytes32 _requestId, string memory _id) public recordChainlinkFulfillment(_requestId) {
emit RequestFirstId(_requestId, _id);
id = _id;
}
/**
* 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 Goerli testnet. Make sure your wallet is set to use Goerli. The constructor sets the following parameters:
setChainlinkToken
function.setChainlinkOracle
function.jobId
: A specific job for the oracle node to run. In this case, the id is a string data type, so you must call a job that calls an API and returns a string. We will be using a generic GET>string job that can be found here.Fund your contract with 0.1 LINK. To learn how to send LINK to contracts, read the Fund Your Contracts page.
Call the id
function to confirm that the id
state variable is not set.
Run the requestFirstId
function. This builds the Chainlink.Request
using the correct parameters. The req.add("path", "0,id")
request parameter tells the oracle node to fetch the id at index 0 of the array returned by the GET request. It uses JSONPath expression with comma(,) delimited string for nested objects, for example: '0,id'
.
After few seconds, call the id
function. You should get a non-empty response: bitcoin
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, use bytes32
. Here's one method of converting bytes32
to string
. Currently, any return value must fit within 32 bytes. If the value is bigger than that, make multiple requests.bytes
- Arbitrary-length raw byte dataThe 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.