Search
With your own Oracle contract, you can use your own node to fulfill requests. This guide will show you how to deploy your own Oracle contract and add jobs to your node so that it can provide data to smart contracts.
Chainlink nodes can fulfill requests from open or unauthenticated APIs without the need for External Adapters as long as you've added the jobs to the node. For these requests, requesters supply the URL to the open API that they want each node to retrieve. The Chainlink node will use tasks to fulfill the request.
Some APIs require authentication by providing request headers for the operator's API key, which the Chainlink node supports. If you would like to provide access to an API that requires authentication, you must create a job that is specific for that API either using an external adapter or by using the parameters of the HTTP task.
Before you begin this guide, complete the following tasks to make sure you have all of the tools that you need:
Regular
type. You can obtain test ETH from several faucets.Your node works with several different types of addresses. Each address type has a specific function:
Operator.sol
or Oracle.sol
that are deployed to a blockchain. Do not fund these addresses with native blockchain tokens such as ETH. When you make API call requests, the funds pass through this contract to interact with your Chainlink node. This will be the address that smart contract developers point to when they choose a node for an API call.Operator.sol
or Oracle.sol
contract addresses. If you're on OCR, this is the wallet address that receives LINK tokens.Go to Remix and open the Oracle.sol
smart contract. The contents of this file will be very minimal.
On the Compile tab, click the Compile button for Oracle.sol
. Remix automatically selects the compiler version and language from the pragma
line unless you select a specific version manually.
On the Deploy and Run tab, configure the following settings:
Select "Injected Provider" as your Environment. The Javascript VM environment cannot access your oracle node.
Select the "Oracle" contract from the Contract menu.
Copy the LINK token contract address for the network you are using and paste it into the address_link
field next to the Deploy button. Use one of the following network addresses:
0x326C977E6efc84E512bB9C30f76E30c160eD06FB
0x514910771AF9Ca656af840dff83E8264EcF986CA
Click Deploy. MetaMask prompts you to confirm the transaction.
MetaMask doesn't pop up?
If MetaMask does not prompt you and instead displays the error below, disable "Privacy Mode" in MetaMask. You can do this by clicking on your unique account icon at the top-right, then go to the Settings. Privacy Mode will be a switch near the bottom.
Error: Send transaction failed: Invalid address. If you use an injected provider, please check it is properly unlocked.
After you deploy the contract, a link to Etherscan displays at the bottom. Open that link in a new tab to keep track of the transaction.
If the transaction is successful, a new address displays in the Deployed Contracts section.
Keep note of the Oracle contract address. You need it later for your consuming contract.
Find the address for your Chainlink node and add it to the Oracle contract.
In the Chainlink Operator GUI for your node, find and copy the address at the bottom of the Keys page in the Account addresses section.
In Remix, call the setFulfillmentPermission
function with the address of your node, a comma, and the value true
, as the input parameters. This allows your node to fulfill requests to your oracle contract.
Click the setFulfillmentPermission
function to run it. Approve the transaction in MetaMask and wait for it to confirm on the blockchain.
You can add jobs to your Chainlink node in the Chainlink Operator GUI. The ATestnetConsumer.sol consumer contract expects the price value in Uint256
. Use the following Job example:
# THIS IS EXAMPLE CODE THAT USES HARDCODED VALUES FOR CLARITY.
# THIS IS EXAMPLE CODE THAT USES UN-AUDITED CODE.
# DO NOT USE THIS CODE IN PRODUCTION.
type = "directrequest"
schemaVersion = 1
name = "Get > Uint256"
# Optional External Job ID: Automatically generated if unspecified
# externalJobID = "b1d42cd5-4a3a-4200-b1f7-25a68e48aad8"
contractAddress = "YOUR_ORACLE_CONTRACT_ADDRESS"
maxTaskDuration = "0s"
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_cbor [type="cborparse" data="$(decode_log.data)"]
fetch [type="http" method=GET url="$(decode_cbor.get)"]
parse [type="jsonparse" path="$(decode_cbor.path)" data="$(fetch)"]
multiply [type="multiply" input="$(parse)" times=100]
encode_data [type="ethabiencode" abi="(uint256 value)" data="{ \\"value\\": $(multiply) }"]
encode_tx [type="ethabiencode"
abi="fulfillOracleRequest(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes32 data)"
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}"
]
submit_tx [type="ethtx" to="YOUR_ORACLE_CONTRACT_ADDRESS" data="$(encode_tx)"]
decode_log -> decode_cbor -> fetch -> parse -> multiply -> encode_data -> encode_tx -> submit_tx
"""
In the Chainlink Operator GUI on the Jobs tab, click New Job.
Paste the job specification from above into the text field.
Replace YOUR_ORACLE_CONTRACT_ADDRESS
with the address of your deployed oracle contract address from the previous steps. Replace YOUR_ORACLE_CONTRACT_ADDRESS
for both the attribute contractAddress
and also attribute to
for the submit_tx
step in the observationSource
part of the job specification. This address not the same as the ACCOUNT_ADDRESS
from your Chainlink node.
Click Create Job. If the node creates the job successfully, a notice with the job number appears.
Click the job number to view the job details. You can also find the job listed on the Jobs tab in the Node Operators UI.
In the job Definition tab, find the externalJobID
value. Save this value because you will need it later to tell your consumer contract what job ID to request from your node.
If you're going through this guide on Ethereum mainnet, the ATestnetConsumer.sol
contract will still work. However, understand that you're sending real LINK to yourself. Be sure to practice on the test networks multiple times before attempting to run a node on mainnet.
After you add jobs to your node, you can use the node to fulfill requests. This section shows what a requester does when they send requests to your node. It is also a way to test and make sure that your node is functioning correctly.
Note that setChainlinkToken(0x326C977E6efc84E512bB9C30f76E30c160eD06FB)
is configured for Goerli. Fetch the Link token address for the network you are deploying into from the Link token contracts page.
On the Compiler tab, click the Compile button for ATestnetConsumer.sol
.
On the Deploy and Run tab, configure the following settings:
Click Deploy. MetaMask prompts you to confirm the transaction.
Ensure that your Chainlink Node is sufficiently funded with ETH to execute the callbacks to your oracle contract.
Fund the contract by sending LINK to the contract's address. See the Fund your contract page for instructions. The address for the ATestnetConsumer
contract is on the list of your deployed contracts in Remix.
After you fund the contract, create a request. Input your oracle contract address and the job ID for the Get > Uint256
job into the requestEthereumPrice
request method without dashes. The job ID is the externalJobID
parameter, which you can find on your job's definition page in the Node Operators UI.
Click the transact button for the requestEthereumPrice
function and approve the transaction in Metamask. The requestEthereumPrice
function asks the node to retrieve uint256
data specifically from https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD.
After the transaction processes, you can see the details for the complete the job run the Runs page in the Node Operators UI.
In Remix, click the currentPrice
variable to see the current price updated on your consumer contract.
Now that you have a working consumer contract, you can use that same ATestnetConsumer
contract to obtain other types of data. The ATestnetConsumer.sol consumer contract has a requestEthereumLastMarket
function that requests more detailed data from https://min-api.cryptocompare.com/data/pricemultifull?fsyms=ETH&tsyms=USD. Returning this type of data requires another job.
# THIS IS EXAMPLE CODE THAT USES HARDCODED VALUES FOR CLARITY.
# THIS IS EXAMPLE CODE THAT USES UN-AUDITED CODE.
# DO NOT USE THIS CODE IN PRODUCTION.
type = "directrequest"
schemaVersion = 1
name = "Get > Bytes32"
# Optional External Job ID: Automatically generated if unspecified
# externalJobID = "b1d42cd5-4a3a-4200-b1f7-25a68e48aad8"
contractAddress = "YOUR_ORACLE_CONTRACT_ADDRESS"
maxTaskDuration = "0s"
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_cbor [type="cborparse" data="$(decode_log.data)"]
fetch [type="http" method=GET url="$(decode_cbor.get)"]
parse [type="jsonparse" path="$(decode_cbor.path)" data="$(fetch)"]
encode_data [type="ethabiencode" abi="(bytes32 value)" data="{ \\"value\\": $(parse) }"]
encode_tx [type="ethabiencode"
abi="fulfillOracleRequest(bytes32 requestId, uint256 payment, address callbackAddress, bytes4 callbackFunctionId, uint256 expiration, bytes32 data)"
data="{\\"requestId\\": $(decode_log.requestId), \\"payment\\": $(decode_log.payment), \\"callbackAddress\\": $(decode_log.callbackAddr), \\"callbackFunctionId\\": $(decode_log.callbackFunctionId), \\"expiration\\": $(decode_log.cancelExpiration), \\"data\\": $(encode_data)}"
]
submit_tx [type="ethtx" to="YOUR_ORACLE_CONTRACT_ADDRESS" data="$(encode_tx)"]
decode_log -> decode_cbor -> fetch -> parse -> encode_data -> encode_tx -> submit_tx
"""
Add the Get > Bytes32
job to your node like you did for the first job.
In the new job's definition page, find the externalJobID
.
Input your oracle contract address and the job ID for the Get > Bytes32
job into the requestEthereumLastMarket
request method without dashes.
Click the transact button for the requestEthereumLastMarket
function and approve the transaction in Metamask.
After the transaction processes, you can see the details for the complete the job run the Runs page in the Node Operators UI.
In Remix, click the lastMarket
variable. The value is in bytes that you can convert to a string outside of the smart contract later.
Jobs can do more than just retrieve data and put it on chain. You can write your own jobs to accomplish various tasks. See the v2 Jobs page to learn more.
You can withdraw LINK from the Oracle contract. In Remix under the list of deployed contracts, click on your Oracle contract and find the withdraw
function in the function list. Note that the testnet consumer contract also has a withdraw
function that is different.
Paste the address you want to withdraw to, and specify the amount of LINK that you want to withdraw. Then, click withdraw
. Confirm the transaction in MetaMask when the popup appears.