# 保留参数
保留参数是OIS对象的一部分,是endpoints
字段(Airnode 终端节点)的一部分,值得深入解释。 它们是OIS对象中Airnode定义的节点的一部分,但不映射到操作参数(API参数)。 它们被Airnode用于特殊目的。
请求者可以通过引用包含参数的模板来传递请求参数,或者作为AirnodeRrp.sol的请求制作方法的一个参数。 在这两种情况下,这些参数都会使用AirnodeRrp ABI进行编码。 作为OIS对象的一部分,有两种类型的参数:
# _type
标志着 API 响应在执行前将被编码为何种 Solidity 类型。
对大多数常见的 Solidity 类型 (opens new window)提供支持,但不支持以下类型。
- 自定义位的整数类型--如
uint32
或uint8
- 固定点十进制数字--如
fixed128x18
或ufixed128x18
- 自定义固定大小的字节--例如
byte4
- 元组--例如
(int256, string)
在支持的实体类型的基础上,还支持一些为特殊目的而创建的 "人工" 类型,否则就很难或无法表示。
你也可以为一个单一的API调用编码多个值--但这影响到所有的保留参数,并在下面的编码多个值部分进行解释。
# 转换和编码行为
在API响应值被编码以便在链上使用之前,它被解析和转换。 任何给定类型的转换行为在适配器包文档中都有深入解释。
然后,转换后的值由ethers ABI Coder (opens new window)使用以下方式进行内部编码
ethers.utils.defaultAbiCoder.encode([solidityType], [value]);
# 支持的原始值
int256
uint256
bool
bytes32
address
bytes
string
# string32 (在链上编码为 bytes32
)
string32
是一种不被solidity支持的人工类型。 它被编码为bytes32
,为少于32个字符的值提供了一个比普通string
类型更便宜的选择。
::warning 局限性
虽然使用string32
更有效率,但在链上从bytes32
解码原始字符串既困难又昂贵。
还要记住,这种类型只能对短于32个字符的字符串进行编码。 如果值更长,它将被修剪,只有前31个字符会被编码。
:::
# timestamp (在链上编码为 uint256
)
timestamp
是一个人造的类型,不被solidity支持。 它被编码为uint256
,并指定了事务被编码时的UNIX时间戳值。 你可以在链上使用这个值来检查Airnode响应的 "新鲜度"。 这在某些情况下可能是有用的,因为Airnode不能保证一个特定的交易何时会在链上被开采。
当使用timestamp
类型时,相应的_path
和_times
变量必须是空字符串或不提供。
# 数组
除了上面定义的基元以及我们创建的所有 "人工 "类型之外,你可以自由地将数组与上述任何类型一起使用。 多维数组也被支持。 Solidity 允许你定义固定大小的数组,这对编码来说更省gas,你也可以使用这些数组。
举例
int256[]
- 正整数数组uint256[8]
- 有8个元素的无符号整数数组int256[] []
- 2维整数数组string32[]
- 是一个string32
值的数组,在链上将被编码为byte32[]
string[2][][3]
- 3维字符串数组,其中第一维包含3个元素,第二维不受限制地包含许多元素,最后一维只有2个元素。 注意,与C语言相比,这个定义是逆向读取 (opens new window)的
# _path
假设API响应将是一个JSON对象,使用点符号来定义用于满足请求的字段。 例如,如果API返回,
{
"field1": {
"fieldA": [
"valueA1",
"valueA2"
],
"fieldB: "valueB"
},
"field2": {
"fieldZ": "valueZ"
}
}
2
3
4
5
6
7
8
9
10
11
12
那么_path
为 field1.fieldA.1
,其响应将是 valueA2
。
如果响应是一个迭代值(即不是JSON对象),并且_path
没有提供或为空字符串(需要对多个值进行编码),Airnode将使用API响应本身来完成请求。
::warning 小心分隔符
确保API响应的路径中的键不包含.
,因为它将被错误地认为是一个分隔符。
{
"strange.key": "123"
}
2
3
定义为 "sange.key"
的_path
将无法工作。 作为变通方法,你可以转义分隔符。
:::
# 转义分隔符
在少数情况下,当API响应的_path
包含,
或.
(逗号或点)时,事情会变得有点复杂。 这些符号在解析保留参数时有非常特殊的意义,如果它们被视为字面意义,就需要转义。 例如,如果API提供者的响应看起来像下面这样
{
"very,strange.key": "123"
}
2
3
那么你需要转义这些符号,在这种情况下_path="very//,strange\\.key"
。
# _times
如果_type
是int256
或uint256
,并且提供了一个有效的_times
参数,Annode在完成请求前将API返回的值与_times
参数相乘。 例如,如果API返回:
{
"data": "1.238",
"apiVersion": "1.0.4"
}
2
3
4
而保留的参数是
_type: int256
_path: data
_times: "100"
2
3
该请求将以123
的值实现。 请注意,这个数字会乘100
,然后被向下取整。 这是因为乘法的结果在之后被转换为int256
。
请确保将_times
参数作为字符串传递。 Airnode将在内部把这个字符串转换为数字。 你也可以将空字符串""
传递给_times
参数--这与不提供_times
参数的效果相同。 然而,在对多个数值进行编码时,这一点很重要。
_times
参数还可以与数组和多维数组一起使用。 API响应数组的所有元素在被编码之前都将被乘上一个数。
# 多值编码
Solidity支持解码和 "解构" 多个值。 例如
function decodeMultipleParameters(bytes calldata data)
public
pure
returns (string memory str, uint256 num, address addr)
{
(str, num, addr) = abi.decode(data, (string, uint256, address));
}
2
3
4
5
6
7
上面的例子演示了分别对string
、uint256
和address
的三个值进行链上解码。 你可以指示Airnode使用保留参数对这些值进行编码,用,
(逗号)来分隔这些值。 例如,使用以下保留参数的组合
{
_type: 'string,uint256,address',
_path: 'pathToString,pathToFloat,pathToAddress',
_times: ',10000,'
}
2
3
4
5
Airnode将把保留的参数按,
分割成 "分割值",并确保它们都包含相同数量的参数。 它将提取并转换每个 "分割值"。 注意,一个""
(空字符串)用于指定某个保留参数不应该用于某个 "分割值"。
例如,让我们假设API响应看起来像这样
{
"pathToString": "some string",
"pathToFloat": "1234.567",
"pathToAddress": "0xe021...08a74"
}
2
3
4
5
Airnode将分别提取和转换每个 "分割值"
_type="string"
,_path="pathToString
"和__times=""
的组合结果是一些"string"
_type="uint256"
,_path="pathToFloat"
和__times="10000"
的组合结果为12345670
- 结合
_type="address"
,_path="pathToAddress"
和__times=""
结果是"0xe021...8a74"
所有这些值然后一起被编码为单字节值,可以在链上发送。 你可以使用测试网关来检查原始API响应,投票结果和最终的编码值。