Fulfilling Requests

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.

Requirements

Before you begin this guide, complete the following tasks to make sure you have all of the tools that you need:

Address Types

Your node works with several different types of addresses. Each address type has a specific function:

  • Node address: This is the address for your Chainlink node wallet. The node requires native blockchain tokens at all times to respond to requests. For this example, the node uses ETH. When you start a Chainlink node, it automatically generates this address. You can find this address on the Node Operator GUI under Keys > Account addresses.
  • Oracle contract address: This is the address for contracts like 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.
  • Admin wallet address: This is the address that owns your Operator.sol or Oracle.sol contract addresses. If you’re on OCR, this is the wallet address that receives LINK tokens.

Deploy your own Oracle contract

  1. Go to Remix and open the Oracle.sol smart contract. The contents of this file will be very minimal.

  2. 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.

  3. 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

    The Deploy & Run transaction window showing Injected Web 3 selected and the address for your MetaMask wallet.

  4. Click Deploy. MetaMask prompts you to confirm the transaction.

  5. 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.

    Remix Pending Transaction Message

  6. If the transaction is successful, a new address displays in the Deployed Contracts section.

    Screenshot showing the newly deployed contract.

  7. Keep note of the Oracle contract address. You need it later for your consuming contract.

Add your node to the Oracle contract

Find the address for your Chainlink node and add it to the Oracle contract.

  1. 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. Node UI Account Addresses

  2. 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.

    A screenshot showing all of the fields for the deployed contract in Remix.

  3. Click the setFulfillmentPermission function to run it. Approve the transaction in MetaMask and wait for it to confirm on the blockchain.

Add a job to the node

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)" allowUnrestrictedNetworkAccess="true"]
    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
"""
  1. In the Chainlink Operator GUI on the Jobs tab, click New Job.

    The new job button.

  2. Paste the job specification from above into the text field.

    The new job page with TOML format for a new job pasted.

  3. 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.

  4. Click Create Job. If the node creates the job successfully, a notice with the job number appears.

    A screenshot showing that the job is created successfully.

  5. 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.

  6. 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.

Create a request to your node

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.

  1. Open ATestnetConsumer.sol in Remix.

  2. 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.

  3. On the Compiler tab, click the Compile button for ATestnetConsumer.sol.

  4. On the Deploy and Run tab, configure the following settings:

    • Select “Injected Provider” as your environment.
    • Select “ATestnetConsumer” from the Contract menu.
  5. Click Deploy. MetaMask prompts you to confirm the transaction.

  6. Ensure that your Chainlink Node is sufficiently funded with ETH to execute the callbacks to your oracle contract.

  7. 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.

  8. 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.

    Screenshot of the requestEthereumPrice function with the oracle address and job ID specified.

  9. 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.

  10. After the transaction processes, you can see the details for the complete the job run the Runs page in the Node Operators UI.

  11. In Remix, click the currentPrice variable to see the current price updated on your consumer contract.

    A screenshot of the currentPrice button

Retrieving other types of data

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)" allowUnrestrictedNetworkAccess="true"]
    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
"""
  1. Add the Get > Bytes32 job to your node like you did for the first job.

  2. In the new job’s definition page, find the externalJobID.

  3. Input your oracle contract address and the job ID for the Get > Bytes32 job into the requestEthereumLastMarket request method without dashes.

    Screenshot of the requestEthereumLastMarket function with the oracle address and job ID specified.

  4. Click the transact button for the requestEthereumLastMarket function and approve the transaction in Metamask.

  5. After the transaction processes, you can see the details for the complete the job run the Runs page in the Node Operators UI.

  6. In Remix, click the lastMarket variable. The value is in bytes that you can convert to a string outside of the smart contract later.

    A screenshot of the lastMarket button

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.

Remix Click Withdraw Button

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.

Whats Next

Stay updated on the latest Chainlink news