Smart Contracts on any blockchain can gain the ability to connect to any API by integrating with Chainlink oracles. We’ve already seen massive growth of API and off-chain data use in solidity with Chainlink entering the space as an Ethereum oracle. Chainlink is well known as the leading provider of Price Reference Data, which currently secures over $1B USD in DeFi value. While this is an important functionality that empowers a multitude of DeFi platforms users know and love, that alone does not revolutionize the capabilities of smart contracts.

Chainlink was designed with a much broader goal in mind, to be the standard data middleware layer for smart contracts, unlocking their true capability of affecting the external world. To accomplish this, Chainlink gives Solidity and other blockchain developers a framework to interact with any external API and this guide aims to show you how to do so today, live on the Ethereum Mainnet.

The first concept to introduce is adapters. Adapters are the data manipulation functions that every Chainlink node supports by default. Through these adapters, all developers have a standard interface for making data requests and node operators have a standard for serving that data. These adapters include functionality such as HTTP GET, HTTP POST, Compare, Copy, etc. Adapters are your dApp’s connection to the external world’s data.

For example, here are the parameters for the HttpGet adapter:

  • get: takes a string containing the URL to make a GET request to.
  • headers: takes an object containing keys as strings and values as arrays of strings.
  • queryParams: takes a string or array of strings for the URL's query parameters.
  • extPath: takes a slash-delimited string or array of strings to be appended to the job's URL.

For your smart contract to interact with these adapters, we need to introduce another element, requests. All contracts that inherit from ChainlinkClient can create a Chainlink.Request struct that allows developers to form a request to a Chainlink node. Submitting this request requires some basic fields such as the address of the node you wish to use as your oracle, the job ID, and the agreed upon fee. In addition to those default fields, you must add your desired adapter parameters to the request struct like so:

// Set the URL to perform the GET request on
request.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD");

In this way, requests are flexible and can be formulated to fit a variety of situations involving getting, posting, and manipulating any API since the requests can contain any of the adapter functions. For more information on the construction of a request and the functions needed to submit it and receive a response within your ChainlinkClient contract, please see our full HTTP GET request example.

For certain common requests, a node operator may already have an existing oracle job configured and in this case, the request becomes much simpler. Rather than building a request struct with the necessary adapters, the default request struct is all you need to create. No additional adapter parameters are needed, the oracle you choose will know how to respond based on the jobId provided when creating the request struct.

An example of this is given below, taken from the full CoinGecko API Consumer Example.

Chainlink.Request memory req = buildChainlinkRequest(jobId, address(this),
this.fulfillEthereumPrice.selector);
sendChainlinkRequestTo(oracle, req, fee);

Chainlink Market can be used to search through existing nodes and the jobs they support in order to find the job ID you require.

But what if you have some especially complex use case for your smart contract that falls outside of the default adapter functions? What if you need to perform some advanced manipulation of the API data? Maybe it’s not the raw API data you wish to submit to your contract but rather metadata generated by statistical analysis of multiple data points. Maybe you can do your manipulation of the data on-chain with the default adapters but want to reduce gas costs. Perhaps you simply don’t want your API request on chain due to using a credentialed source and don’t want to specify those credentials on-chain or in the oracle job spec. This is where External Adapters come in.

Connect blockchain smart contracts to any API



External adapters are the “whatever data you need, we can handle it” of Chainlink. Since they are pieces of code that exist off-chain with the Chainlink node, they can be written in any language of your choice and perform whatever functionality you can think up so long as the data input and output adheres to the adapter’s JSON specification. External adapters act as the interface between the Chainlink node and external data, letting the node operator know how to request and receive the JSON response that is then consumed on-chain.

Defining this interface specification off-chain through an external adapter opens up vast possibilities: you can now store your API credentials off-chain in any manner you see fit, data can be manipulated any way you can code up in the language of your choosing, and all this happens without using any gas. In a sense, external adapters are like a layer 2 oracle, packaging up data outside the blockchain with speed and low cost and putting it into one tidy JSON format to be verifiably committed on-chain by the Chainlink node.

External adapters are a large part of what makes Chainlink such a versatile oracle middleware. Contract developers are free to implement these adapters as needed or they can choose from existing adapters on the Chainlink Market. If you are a smart contract developer looking to create an external adapter, Chainlink only requires you to specify the JSON interfaces for the data request and the return data; in-between those two interfaces is where developers are free to create and manipulate the data to fit their precise use case. As a node operator, in order to support the external adapter and handle the additional requests, you must create a bridge for it in your node UI and add the adapter’s bridge name to your supported tasks.

Chainlink Node Operator
{
"initiators": [
{ "type": "runLog" }
],
"tasks": [
{ "type": "randomNumber" },
{ "type": "copy",
"params": {"copyPath": ["details", "current"]}},
{ "type": "multiply",
"params": {"times": 100 }},
{ "type": "ethuint256" },
{ "type": "ethtx" }
]
}

Chainlink is striving to give blockchain and smart contract developers the tools to empower their smart contracts with real world data, exactly how they need it. Chainlink’s design incorporating both direct calls to any API through default adapters and extensible external adapters, gives developers a flexible platform to create as they see fit, with any data they might need. If you’re a smart contract developer looking to increase the utility of your smart contract with external data or simply wish to learn more about Chainlink, please check out the resource listed below.

Want to try it out? Follow our example walkthrough, and easily deploy your first smart contract that interacts with off-chain data.

If you’re developing a product that could benefit from Chainlink oracles or would like to assist in the open-source development of the Chainlink network, visit the developer documentation or join the technical discussion on Discord.

Website | Twitter I Reddit | YouTube | Telegram | Events | GitHub | Price Feeds | DeFi