Skip to content
This repository was archived by the owner on Jul 9, 2024. It is now read-only.

Commit 262c02d

Browse files
committed
Prepare config format & validation for beaconSets section #163
1 parent 5853690 commit 262c02d

File tree

2 files changed

+63
-10
lines changed

2 files changed

+63
-10
lines changed

config/airseeker.example.json

+27-8
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,23 @@
55
"level": "INFO"
66
},
77
"beacons": {
8-
"0x924b5d4cb3ec6366ae4302a1ca6aec035594ea3ea48a102d160b50b0c43ebfb5": {
8+
"0xbc80cbd7a8b8180e11d189a8334814a44a69c4d083b31305ecf67a3a3ea0fd9a": {
99
"airnode": "0xA30CA71Ba54E83127214D3271aEA8F5D6bD4Dace",
10-
"templateId": "0xea30f92923ece1a97af69d450a8418db31be5a26a886540a13c09c739ba8eaaa",
10+
"templateId": "0x5fadf775c50d6ec9641b9d07ab3a9ca9d92aaf64d27ea54529fb7d8ebc72e713",
11+
"fetchInterval": 20
12+
},
13+
"0x717d60cb328ef7ea138ae1b31c78a03fe6caa1a05568b1649e89cd924321b732": {
14+
"airnode": "0xA30CA71Ba54E83127214D3271aEA8F5D6bD4Dace",
15+
"templateId": "0x32ee5c344877c40260b6010bb91f85f39b5a9a0f6690d4c6888af90f5613d854",
1116
"fetchInterval": 20
1217
}
1318
},
14-
"beaconSets": {},
19+
"beaconSets": {
20+
"0x786c4a7929a666c77ba5d4d3ce7ed61f2ba9885525f0a7577f014641568926fe": [
21+
"0xbc80cbd7a8b8180e11d189a8334814a44a69c4d083b31305ecf67a3a3ea0fd9a",
22+
"0x717d60cb328ef7ea138ae1b31c78a03fe6caa1a05568b1649e89cd924321b732"
23+
]
24+
},
1525
"chains": {
1626
"1": {
1727
"contracts": {
@@ -82,9 +92,13 @@
8292
]
8393
},
8494
"templates": {
85-
"0xea30f92923ece1a97af69d450a8418db31be5a26a886540a13c09c739ba8eaaa": {
86-
"endpointId": "0x13dea3311fe0d6b84f4daeab831befbc49e19e6494c41e9e065a09c3c68f43b6",
87-
"parameters": "0x3173737373730000000000000000000000000000000000000000000000000000746f00000000000000000000000000000000000000000000000000000000000055534400000000000000000000000000000000000000000000000000000000005f74797065000000000000000000000000000000000000000000000000000000696e7432353600000000000000000000000000000000000000000000000000005f70617468000000000000000000000000000000000000000000000000000000726573756c7400000000000000000000000000000000000000000000000000005f74696d65730000000000000000000000000000000000000000000000000000313030303030300000000000000000000000000000000000000000000000000066726f6d000000000000000000000000000000000000000000000000000000004554480000000000000000000000000000000000000000000000000000000000"
95+
"0x5fadf775c50d6ec9641b9d07ab3a9ca9d92aaf64d27ea54529fb7d8ebc72e713": {
96+
"endpointId": "0x18a60ee2138d98b5f968b7177a8a537515e3db46d0712b8dd311625e6c2335c4",
97+
"parameters": "0x317373737373730000000000000000000000000000000000000000000000000070616972000000000000000000000000000000000000000000000000000000006274635f757364000000000000000000000000000000000000000000000000005f706174680000000000000000000000000000000000000000000000000000007061796c6f61642e7677617000000000000000000000000000000000000000005f74797065000000000000000000000000000000000000000000000000000000696e7432353600000000000000000000000000000000000000000000000000005f74696d6573000000000000000000000000000000000000000000000000000031303030303030303030303030303030303030000000000000000000000000006c6f6f6b6261636b506572696f640000000000000000000000000000000000003500000000000000000000000000000000000000000000000000000000000000696e636c75646543726f737352617465730000000000000000000000000000007472756500000000000000000000000000000000000000000000000000000000"
98+
},
99+
"0x32ee5c344877c40260b6010bb91f85f39b5a9a0f6690d4c6888af90f5613d854": {
100+
"endpointId": "0x18a60ee2138d98b5f968b7177a8a537515e3db46d0712b8dd311625e6c2335c4",
101+
"parameters": "0x317373737373730000000000000000000000000000000000000000000000000070616972000000000000000000000000000000000000000000000000000000006574685f757364000000000000000000000000000000000000000000000000005f706174680000000000000000000000000000000000000000000000000000007061796c6f61642e7677617000000000000000000000000000000000000000005f74797065000000000000000000000000000000000000000000000000000000696e7432353600000000000000000000000000000000000000000000000000005f74696d6573000000000000000000000000000000000000000000000000000031303030303030303030303030303030303030000000000000000000000000006c6f6f6b6261636b506572696f640000000000000000000000000000000000003500000000000000000000000000000000000000000000000000000000000000696e636c75646543726f737352617465730000000000000000000000000000007472756500000000000000000000000000000000000000000000000000000000"
88102
}
89103
},
90104
"triggers": {
@@ -93,7 +107,12 @@
93107
"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": {
94108
"beacons": [
95109
{
96-
"beaconId": "0x924b5d4cb3ec6366ae4302a1ca6aec035594ea3ea48a102d160b50b0c43ebfb5",
110+
"beaconId": "0xbc80cbd7a8b8180e11d189a8334814a44a69c4d083b31305ecf67a3a3ea0fd9a",
111+
"deviationThreshold": 0.1,
112+
"heartbeatInterval": 86400
113+
},
114+
{
115+
"beaconId": "0x717d60cb328ef7ea138ae1b31c78a03fe6caa1a05568b1649e89cd924321b732",
97116
"deviationThreshold": 0.1,
98117
"heartbeatInterval": 86400
99118
}
@@ -105,7 +124,7 @@
105124
"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC": {
106125
"beacons": [
107126
{
108-
"beaconId": "0x924b5d4cb3ec6366ae4302a1ca6aec035594ea3ea48a102d160b50b0c43ebfb5",
127+
"beaconId": "0x717d60cb328ef7ea138ae1b31c78a03fe6caa1a05568b1649e89cd924321b732",
109128
"deviationThreshold": 0.2,
110129
"heartbeatInterval": 86400
111130
}

src/validation.ts

+36-2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export const logSchema = z.object({
1717

1818
export const evmAddressSchema = z.string().regex(/^0x[a-fA-F0-9]{40}$/);
1919
export const evmBeaconIdSchema = z.string().regex(/^0x[a-fA-F0-9]{64}$/);
20+
export const evmBeaconSetIdSchema = z.string().regex(/^0x[a-fA-F0-9]{64}$/);
2021
export const evmTemplateIdSchema = z.string().regex(/^0x[a-fA-F0-9]{64}$/);
2122
export const evmEndpointIdSchema = z.string().regex(/^0x[a-fA-F0-9]{64}$/);
2223
export const emptyObjectSchema = z.object({}).strict();
@@ -44,8 +45,22 @@ export const beaconsSchema = z.record(evmBeaconIdSchema, beaconSchema).superRefi
4445
});
4546
});
4647

47-
// TODO: Will be refined once we start supporting beacon sets
48-
export const beaconSetsSchema = emptyObjectSchema;
48+
export const beaconSetsSchema = z
49+
.record(evmBeaconSetIdSchema, z.array(evmBeaconIdSchema))
50+
.superRefine((beaconSets, ctx) => {
51+
Object.entries(beaconSets).forEach(([beaconSetId, beacons]) => {
52+
// Verify that config.beaconSets.<beaconSetId> is valid
53+
// by deriving the hash of the beaconIds in the array
54+
const derivedBeaconSetId = ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['bytes32[]'], [beacons]));
55+
if (derivedBeaconSetId !== beaconSetId) {
56+
ctx.addIssue({
57+
code: z.ZodIssueCode.custom,
58+
message: `Beacon set ID "${beaconSetId}" is invalid`,
59+
path: [beaconSetId],
60+
});
61+
}
62+
});
63+
});
4964

5065
export const latestGasPriceOptionsSchema = z
5166
.object({
@@ -168,6 +183,23 @@ const validateBeaconsReferences: SuperRefinement<{ beacons: Beacons; gateways: G
168183
});
169184
};
170185

186+
const validateBeaconSetsReferences: SuperRefinement<{ beacons: Beacons; beaconSets: BeaconSets }> = (config, ctx) => {
187+
Object.entries(config.beaconSets).forEach(([beaconSetId, beacons]) => {
188+
beacons.forEach((beaconId, index) => {
189+
// Verify that config.beaconSets.<beaconSetId>.[beaconId] is
190+
// referencing a valid config.beacons.<beaconId> object
191+
const beacon = config.beacons[beaconId];
192+
if (isNil(beacon)) {
193+
ctx.addIssue({
194+
code: z.ZodIssueCode.custom,
195+
message: `Beacon ID "${beaconId}" is not defined in the config.beacons object`,
196+
path: ['beaconSets', beaconSetId, index],
197+
});
198+
}
199+
});
200+
});
201+
};
202+
171203
const validateBeaconUpdatesReferences: SuperRefinement<{
172204
beacons: Beacons;
173205
chains: Chains;
@@ -212,6 +244,7 @@ export const configSchema = z
212244
})
213245
.strict()
214246
.superRefine(validateBeaconsReferences)
247+
.superRefine(validateBeaconSetsReferences)
215248
.superRefine(validateBeaconUpdatesReferences);
216249
export const encodedValueSchema = z.string().regex(/^0x[a-fA-F0-9]{64}$/);
217250
export const signatureSchema = z.string().regex(/^0x[a-fA-F0-9]{130}$/);
@@ -223,6 +256,7 @@ export const signedDataSchema = z.object({
223256
export type Config = z.infer<typeof configSchema>;
224257
export type Beacon = z.infer<typeof beaconSchema>;
225258
export type Beacons = z.infer<typeof beaconsSchema>;
259+
export type BeaconSets = z.infer<typeof beaconSetsSchema>;
226260
export type Chain = z.infer<typeof chainSchema>;
227261
export type Chains = z.infer<typeof chainsSchema>;
228262
export type GasOracleConfig = z.infer<typeof gasOracleSchema>;

0 commit comments

Comments
 (0)