📂 Reference > Packages

# Adapter

Table of Contents

The airnode-adapter (opens new window) package has multiple responsibilities. It is used for building requests from an Oracle Integration Specification (OIS), executing them, parsing the responses, but also converting and encoding them for on chain use.

It is an internal dependency of Airnode, but can also be used standalone as an API.

# Installation

You can install @api3/airnode-adapter by adding it to the package.json file in your project.

npm install --save @api3/airnode-adapter
# or by
yarn add @api3/airnode-adapter
1
2
3

You shouldn't need to use the adapter package directly. However, you might want to use its API to double check the conversion or encoding behavior for which you can install this package and verify your assumptions.

# Conversion

While the adapter package has many responsibilities, many of those can be treated as implementation details. On the other hand, there are a few important behaviors to be noted when converting the response values based on the target type and making the response transaction on chain.

Altogether, the response cycle consists of multiple steps

  1. A successful API call is made and Airnode receives a response value.
  2. The value to be converted is extracted from the response using the _path from the OIS object.
  3. This extracted value is converted to the target type. Conversions are performed internally by the castValue(value, type) function.
  4. The converted value is encoded to the native solidity type based on the _type from the OIS object. Encoding is performed internally by the encodeValue(value, type) function.

If any of the steps above fail, an error is thrown. This will fail the given API request and the error reason can be found in the logs.

The rest of this section covers the conversion logic for all of the supported types.

# int256 or uint256

Converting any of the values in the following example will result in an error:

const ERROR_VALUES = [
  null,
  undefined,
  Infinity,
  NaN,
  '', // empty string
  'randomstring',
  [], // arrays of any kind
  {}, // objects of any kind
];
1
2
3
4
5
6
7
8
9
10

There are a few special strings and boolean values that are convertible to int256 or uint256:

const SPECIAL_INT_VALUES = [false, 'false', true, 'true'];
const values = SPECIAL_INT_VALUES.map((v) => adapter.castValue(v, 'int256'));
console.log(values);
// [0, 0, 1, 1];
1
2
3
4
5

Number strings and numbers will attempt to be converted to BigNumbers (opens new window). The value will also be multiplied by the value of the _times parameter if it is present.

const VALID_INT_VALUES = ['123.456', 7777];
const values = VALID_INT_VALUES.map((v) => adapter.castValue(v, 'uint256'));
console.log(values);
// [new BigNumber(123.456), new BigNumber(7777)];
1
2
3
4
5

Conversion for int256 and uint256 is the same - this means that -123 can be converted to uint256. However, an error will be thrown while encoding.

Flooring

Beware that any floating point number will be floored. This is necessary, because floating point numbers are not valid in solidity. To mitigate precision loss, you can use the _times parameter that is sufficiently large.

For example, if the API response is a USD currency, you might want to use _times: "100" to convert the value to cents.

# bool

Converting values in the example are all considered false.

const FALSE_BOOLEAN_VALUES = [0, '0', false, 'false', undefined, null];
const values = FALSE_BOOLEAN_VALUES.map((v) => {
  return adapter.castValue(v, 'bool');
});
console.log(values);
// [false, false, false, false, false, false];
1
2
3
4
5
6
7
8

All other values are converted to true.

# bytes32

There is no conversion for bytes32 - the value is expected to be a valid hex string representing the encoded 32 bytes value. This means that the encoding must be implemented on the API side. If you want to delegate the encoding to Airnode, see the documentation for string32.

For example, let's say the API wants to encode the following string simple string with length 13. Its encoding is 0x73696d706c6520737472696e6700000000000000000000000000000000000000. This is the value that should be sent as a response to Airnode request, together with the 0x prefix.

You can use ethers (opens new window) to encode these on the API side

const value = 'simple string';
const encoded = ethers.utils.formatBytes32String(value);
console.log(encoded); // 0x73696d706c6520737472696e6700000000000000000000000000000000000000
1
2
3

# address

There is no conversion for address - the value is expected to be a string representing a valid address. Valid examples are:

# bytes

There is no conversion for bytes - the value is expected to be a valid hex string representing the encoded value. This means that the encoding to bytes must be implemented on the API side. If you want to send a string, see the documentation for string.

For example, let's say the API wants to encode the following string this is an example string that is a bit longer. Its encoding is 0x7468697320697320616e206578616d706c6520737472696e672074686174206973206120626974206c6f6e676572. This is the value that should be sent as a response to Airnode request, together with the 0x prefix.

You can use ethers (opens new window) to encode these on the API side

const value = 'this is an example string that is a bit longer';
const encodedValue = ethers.utils.hexlify(ethers.utils.toUtf8Bytes(value));
console.log(encodedValue); // 0x7468697320697320616e206578616d706c6520737472696e672074686174206973206120626974206c6f6e676572
1
2
3

# string

You can pass any value to convert it to string - with the exception of arrays and objects, which will throw an error. All other values will be converted to string and before encoded on chain using the string type.

const values = [
  -1,
  0,
  777.89,
  null,
  'simple string',
  'this is an example string that is a bit longer',
];
// ["-1", "0", "777.89", "null", "simple string", "this is an example string that is a bit longer"]
const mappedValues = values.map((v) => {
  return adapter.castValue(v, 'string');
});
1
2
3
4
5
6
7
8
9
10
11
12
13

# string32

You can pass any value to convert it to string - with the exception of arrays and objects, which will throw an error.

However, there is one exception, if the stringified value contains more than 31 characters it will be trimmed down to only the first 31 characters during conversion.

For example, if the API response is the following string this is an example string that is a bit longer with length 46. It will be first trimmed to 31 characters, string this is an example string that and afterwards converted to 0x7468697320697320616e206578616d706c6520737472696e6720746861742000.

You can use ethers (opens new window) to decode the values off chain using the following snippet

const encoded =
  '0x7468697320697320616e206578616d706c6520737472696e6720746861742000';
const decoded = ethers.utils.parseBytes32String(encoded);
console.log(decoded); // "this is an example string that "
1
2
3
4

# Arrays

Conversion of arrays depends on the primitive type. All values of the array (or nested array) will be converted according to the rules of the primitive type.

For example:

  • int256[] - has primitive type int256. All elements of this array follow the int256 rules.
  • string32[7][][5] - is a multidimensional array, where some dimensions are fixed and some not. This is irrelevant though, and all the elements are converted based on string32 rules.
Last Updated: 5/15/2022, 11:04:51 AM