docs
Handle Response

Handling API Responses in Oracle Requests

When interacting with off-chain APIs via an Oracle in a smart contract, it’s important to properly handle how the response is processed. This guide will walk through how to use jsonResponsePath to dynamically specify the path to the desired data within a JSON response from an API.

Overview

In a decentralized environment, once an Oracle request is made, the response needs to be processed and relayed back to the smart contract. This process often involves navigating through a structured JSON response returned by an external API.

To handle this, we use jsonResponsePath, which allows us to specify the key or path where the relevant data is located within the JSON response.

This is especially useful when the response is complex or nested, as it gives us the ability to extract specific values.

Setting jsonResponsePath in Requests

Here’s how you can define the jsonResponsePath within your smart contract when sending a request to an Oracle.

Example: Sending a GET Request

function exampleSendRequestGET(uint256 fulfillGasUsed) external payable nonReentrant {
    uint256 gasCost = gasCostFulfill(fulfillGasUsed);
    require(
        msg.value > gasCost,
        "ETH sent is less than gas cost for the callback"
    );
 
    string memory url = "http://api.example.com/data";
    OracleRequest.Request memory req;
 
    req.url = url; // Define the API endpoint
    req.method = "GET"; // Specify the HTTP method
    req.jsonResponsePath = "data.clientId"; // Path to extract from JSON response
 
    bytes memory requestData = req.encodeCBOR();
    uint256 requestId = _sendRequest(requestData, fulfillGasUsed);
 
    // Store any relevant information about the request, such as the requestId
}

How It Works:

  • req.jsonResponsePath: This is where we specify the path within the JSON response where the data we need is located. In this case, we are extracting the clientId from a nested JSON object, i.e., "data.clientId".

For example, if the API response looks like this:

{
  "data": {
    "clientId": 12345,
    "clientName": "John Doe"
  }
}

In this case the path data.clientId will return 12345.

Handling Arrays in JSON Response

If the API response contains an array, and you need to access a specific index, you can modify the jsonResponsePath to point to the exact index within the array.

For example, consider the following API response:

{
  "data": {
    "clientId": [111, 222, 333, 444, 555],
    "clientName": "John Doe"
  }
}

If you need to extract the value at index 3 from the clientId array (which is 444 in this case), you can set the jsonResponsePath like this:

req.jsonResponsePath = "data.clientId[3]";
  • data.clientId: This navigates to the clientId array within the JSON structure.
  • [3]: Specifies the index of the array element you want to retrieve. In this case, it's the 4th element (444), since array indices start at 0.

By specifying the path in this format, the Oracle will extract the correct value from the array and return it to your contract.

Or consider this other API response example:

[
    { "clientId": 111, "clientName": "John Doe" },
    { "clientId": 222, "clientName": "Jane Doe" },
    { "clientId": 333, "clientName": "Sam Smith" },
    { "clientId": 444, "clientName": "Alex Johnson" }
]

If you need to extract the clientId value from the object at index 3 (which is 444 in this case), you can set the jsonResponsePath like this:

req.jsonResponsePath = "[3].clientId";
  • [3]: This specifies the index of the object in the array from which you want to retrieve the clientId. In this case, it's the 4th object (444), since array indices start at 0.
  • .clientId: This accesses the clientId property of the specified object.

Allowed Responses from Oracle

  • uint256
  • boolean
  • string
  • float

Handle float Responses

To accept float-type responses, the procedure will be as follows: In the request object of your contract, you must specify allowFloatResponse

req.allowFloatResponse = true

Note: VERY IMPORTANT: If you pass req.allowFloatResponse=true, both floats and uints will be multiplied by the oracle by 10**18 before returning the response. This will apply to both uint256 and floats.