Making requests¶
Request types¶
You have two types of requests at your disposal. You can use either an instant request, which should fulfill as fast as possible or schedule a delayed request, performed at a specific point of time in the future.
Instant requests¶
To perform instant request you need to call request(string _url)
method in Oracle
contract passing as its only parameter an url wrapped in a format type you want to get back. More about format types in Response formats section.
Delayed requests¶
To perform request, which will be executed in the future you need to call delayedRequest(string url, uint delay)
method in Oracle
contract passing as it’s first parameter wrapped url and amount of time you need to wait before execution.
The delay parameter can be given in two ways: as a unix timestamp or as a relative number of seconds. Using both options you can delay a request for a maximum of 2 years from now.
Request sources¶
Currently we support following request sources:
- open REST api
- random data
In the future we plan to implement:
- IPFS
- closed APIs
Response formats¶
For REST api responses, we support JSON, XML and HTML formats. In the future we plan to support also raw binary data.
JSON format¶
To parse and select response in a JSON format use the json() wrapper. You can also query response following JsonPath.
Note
json(...)
wrapper is treated as $
in JsonPath. Omit it when constructing request. In order to fetch sth
parameter from response make following request
json(...).sth
(instead of json(...)$.sth
).
Example request
json(https://api.coindesk.com/v1/bpi/currentprice.json).chartName
Example response
value: "Bitcoin"
error: 0
Example request with error
json(https://api.coindesk.com/v1/bpi/currentprice.json).sth
Example response with error
value: ""
error: 4004
XML format¶
To parse and select response in a XML format use the xml() wrapper. You can also query response following XPath.
Note
To make selected response a valid well-formed XML if the result is an array of nodes they are wrapped in a <resultlist>
tag.
Moreover if any of these results is a raw value it’s also wrapped in a <result>
tag.
Example request
xml(http://samples.openweathermap.org/data/2.5/weather?q=London&mode=xml&appid=b6907d289e10d714a6e88b30761fae22)string(/current/temperature/@value)
Example response
value: "280.15"
error: 0
HTML format¶
To parse and select response from HTML site use the html() wrapper. You can also query response following XPath.
Example request
html(https://www.w3schools.com)/html/head/title/text()
Example response
value: "W3Schools Online Web Tutorials"
error: 0
ENCRYPTED url fragments¶
For all URL datasources (XML, HTML, JSON) it is also possible to encrypt entirety, part or parts of your query using encrypted() tag. You might want to do that if you wouldn’t like some parts of your URL to be visible to everyone on blockchain. An obvious example would be using some API key as a parameter to your REST query. In order to pass part of your query secretly, simply encrypt it using Gardener public key and wrap it in encrypted() tag. Gardener will decrypt it using its private key and then process it as usual. Any assymetric encryption implementation may be used as long as it produces a stringified version of a following object: {iv, ephemPublicKey, ciphertext, mac} . We recommend using https://www.npmjs.com/package/eth-crypto as shown below.
Example request encryption
import EthCrypto from ‘eth-crypto’;
const gardenerPublicKey = ‘9c691b945b14656b98edbf4d3657290c65cad377bca44da4d54e88cd2bbdefb2e063267b06183029fea5017567653c0fb6c4e3426843381ad7e09014b2d384cf’ // if you want to create it programmatically, derive it from Gardener address or Gardener private key if you are owner of the instance const cipher = await EthCrypto.encryptWithPublicKey(gardenerPublicKey, ‘SECRET_DATA’); constEncryptedSecret = EthCrypto.cipher.stringify(cipher);
Example request
json(https://api.coindesk.com/v1/bpi/historical/close.json?currency=encrypted(c317e44653b8cc3e3ca7f6d9686711c60269a5fd41490868ad8b9cc054836af9d074670241860036e3534fddd6dd73995f14c211da51478025ffb45d9f53b8abb7e681700d13c0d58c0a441fdfd5c6dc57810b451c607338c0851cdc8066421968)).disclaimer
json(https://api.coindesk.com/v1/bpi/historical/close.json?currency=encrypted(c317e44653b8cc3e3ca7f6d9686711c60269a5fd41490868ad8b9cc054836af9d074670241860036e3534fddd6dd73995f14c211da51478025ffb45d9f53b8abb7e681700d13c0d58c0a441fdfd5c6dc57810b451c607338c0851cdc8066421968)&someOtherParam=encrypted(someOtherEncryptedValue)).disclaimer
Example response
value: "This data was produced from the CoinDesk Bitcoin Price Index. BPI value data returned as EUR."
error: 0
RANDOM datasource¶
Random numbers can be generated using either random.org service or a dedicated SGX application. This is configurable by setting SGX_ENABLED in your .env file to either true or false. There are many benefits of generating random numbers using SGX. We haven’t fully leveraged this exciting technology, but after we do, every number will be securely and verifiably generated with the ONLY Third Trusted Party being Intel. That’s right, you don’t even have to trust whoever hosts a Gardener instance! This is further explained in our article: https://medium.com/gardeneroracle/random-number-generation-in-gardener-1660e5c25e00 . You are also read up about Intel SGX technical details, this is a good starting point: https://software.intel.com/en-us/sgx Using SGX requires a specific hardware and OS (is your environment compatible? check it here https://github.com/ayeks/SGX-hardware) as well as SGX PSW installed. If you don’t feel like doing that, you are welcome to use a random.org source which can be considered a less secure but easy to use fallback option.
Note
In order to switch between SGX and random.org way of generating random numbers, use SGX_ENABLED in your .env file.
To generate a random value use the random() wrapper with inclusive upper and lower bounds specified. Both of these bounds should be integers. For random.org acceptable bounds are [-1000000000,1000000000] while for SGX they are defined by 8-byte long datatype: [-9223372036854775808, 9223372036854775807]
Example requests
random(10,20)
random(-2,33)
random(-124354325432,-34325253)
Example response
value: 13
error: 0
value: -2
error: 0
value: -9532532335
error: 0
Response error codes¶
When your requests can be fulfilled succesfully you would get value with error code equals to 0. Any non zero error code means that the request failed to process. Any three-digit code is standard HTTP status code, proxied from the HTTP client. Four-digit errors come from the Gardener server and are listed in the table below.
Error name | Error code | Description |
---|---|---|
INVALID_URL | 1000 | Text between type(…) wrapper isn’t valid url |
INVALID_CONTENT_TYPE | 1001 | This response format wrapper isn’t supported |
INVALID_ENCRYPTION | 1002 | Invalid encrypted data. This probably means your data was not encrypted using Gardener public key. |
INVALID_SELECTOR | 4000 | The selector isn’t valid JsonPath or XmlPath |
NO_MATCHING_ELEMENTS_FOUND | 4004 | No elements found for given selector |
INTERNAL_SERVER_ERROR | 5000 | Unhandled error happens inside Gardener Server |