Search code examples
ethereumsoliditychainlink

Chainlink Core Adapter Path Issue: httpGet uint256 returning 0 from treasury.gov API


I am trying to connect to an API with Chainlink to get a uint from the URL in the request bellow. Problem is, every time the "volume" value comes back 0. I have a feeling the issue is one of two things:

  1. The oracle doesn't like accessing arrays. I've tried "data[0]" as well as "data.0". Both work jsonPath which is on the Docs page.
  2. The API is returning a string instead of a number (as the number is wrapped in quotes). I've tried a bytes32 job as well to only get back 0x0. Also other StackOverflow posts show oracles reading string numbers as numbers.

The following snippets of code are the only changes made to the "deploy on remix" code shown here in Chainlink Docs: https://docs.chain.link/docs/make-a-http-get-request.

request.add("get", "https://api.fiscaldata.treasury.gov/services/api/fiscal_service/v2/accounting/od/avg_interest_rates?sort=-record_date");

request.add("path", "data.0.avg_interest_rate_amt");

The contracts are being deployed on Kovan through Remix/Metamask with plenty of link funding the contract. What could I be doing wrong?


Solution

  • There are a couple of issues:

    1. The response is too large so the node just stops at the HttpGet task. I've tested it on my node and here's the exact error I'm getting: HTTP response too large, must be less than 32768 bytes. If you can influence this, that would be great. Otherwise, you'll need to have your own node that will return a shorter response that matches the above limitations.

    2. The result should have only whole numbers, Solidity doesn't understand decimal points, instead, it uses WEI. That's why you need to multiply the result by at least 100, 10^18 is a standard so I'd go with that. The following piece should work for you:

        function requestData(string memory _id, string memory _field) public {
            Chainlink.Request memory request = buildChainlinkRequest(jobId, address(this), this.fulfillData.selector);
            request.add("get", "https://api.fiscaldata.treasury.gov/services/api/fiscal_service/v2/accounting/od/avg_interest_rates?sort=-record_date");
            string[] memory path = new string[](3);
            path[0] = "data";
            path[1] = _id;
            path[2] = _field;
            request.addStringArray("path", path);
            int timesAmount = 10**18;
            request.addInt("times", timesAmount);
            sendChainlinkRequestTo(oracle, request, fee);
        }
    

    I also added _id and _field as function arguments to query any field of any object. Note, this will only work if you can figure out how to get a shorter response.