@api3/commons 0.7.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,78 +1,24 @@
1
1
  import { ethers } from 'ethers';
2
+ import type { Address, Hex, Mnemonic } from './schema';
2
3
  export declare const PROTOCOL_IDS: {
3
- RRP: string;
4
- PSP: string;
5
- RELAYED_RRP: string;
6
- RELAYED_PSP: string;
7
- AIRSEEKER: string;
4
+ readonly RRP: "1";
5
+ readonly PSP: "2";
6
+ readonly RELAYED_RRP: "3";
7
+ readonly RELAYED_PSP: "4";
8
+ readonly AIRSEEKER: "5";
8
9
  };
9
- /**
10
- * An interface that reflects the structure of a Template
11
- */
12
- export interface Template {
13
- airnode: string;
14
- encodedParameters: string;
15
- endpointId: string;
16
- }
17
- /**
18
- * Derives a template ID from the input parameters
19
- *
20
- * @param airnode an Airnode address
21
- * @param encodedParameters encoded parameters, see the airnode/abi package's encode function
22
- * @param endpointId An endpointID (see deriveEndpointId)
23
- */
24
- export declare const deriveTemplateId: ({ airnode, encodedParameters, endpointId }: Template) => string;
25
- /**
26
- * Derives an endpoint ID
27
- *
28
- * @param oisTitle the OIS title
29
- * @param endpointName the endpoint name
30
- */
10
+ export type ProtocolId = (typeof PROTOCOL_IDS)[keyof typeof PROTOCOL_IDS];
11
+ export declare const deriveTemplateIdV0: (airnode: Address, endpointId: Hex, encodedParameters: Hex) => string;
12
+ export declare const deriveTemplateIdV1: (endpointId: Hex, encodedParameters: Hex) => string;
31
13
  export declare const deriveEndpointId: (oisTitle: string, endpointName: string) => string;
32
- /**
33
- * Derives an airnode address's xpub, required for allowing signed data consumers to verify authenticity
34
- *
35
- * @param airnodeMnemonic the airnode's mnemonic
36
- */
37
- export declare const deriveAirnodeXpub: (airnodeMnemonic: string) => string;
38
- /**
39
- * Derives a wallet path from a sponsor address, used for calculating a sponsor wallet.
40
- *
41
- * @param sponsorAddress an EVM-compatible address
42
- * @param protocolId an API application protocol ID
43
- */
44
- export declare function deriveWalletPathFromSponsorAddress(sponsorAddress: string, protocolId: string): string;
45
- /**
46
- * Encodes/formats a string as a hex-encoded bytes32 string.
47
- *
48
- * @param input the input string
49
- */
14
+ export declare const deriveAirnodeXpub: (airnodeMnemonic: Mnemonic) => string;
15
+ export declare function deriveWalletPathFromSponsorAddress(sponsorAddress: Address, protocolId: ProtocolId): string;
50
16
  export declare const toBytes32String: (input: string) => string;
51
- /**
52
- * Decodes a hex-encoded bytes32 string to a normal string.
53
- *
54
- * @param input the input hex string
55
- */
56
- export declare const fromBytes32String: (input: string) => string;
57
- /**
58
- * Derives a sponsor wallet, given a mnemonic and dapiName.
59
- *
60
- * @param sponsorWalletMnemonic the sponsor wallet mnemonic
61
- * @param dapiName the dapi name
62
- */
63
- export declare const deriveSponsorWallet: (sponsorWalletMnemonic: string, dapiName: string) => ethers.Wallet;
64
- /**
65
- * Derives the ID of a single beacon
66
- *
67
- * @param airnodeAddress the airnode address of the provider that supplies the data used to update this beacon
68
- * @param templateId the templateId of the template used to generate the data used to update this beacon
69
- */
70
- export declare const deriveBeaconId: (airnodeAddress: string, templateId: string) => string;
71
- /**
72
- * Derives the ID of a set of beacons.
73
- * By convention beacon IDs are sorted alphabetically - the ordering impacts the resulting hash.
74
- *
75
- * @param beaconIds an ordered array of beacon ids
76
- */
77
- export declare const deriveBeaconSetId: (beaconIds: string[]) => string;
17
+ export declare const fromBytes32String: (input: Hex) => string;
18
+ export declare const deriveSponsorWallet: (airnodeMnemonic: Mnemonic, dapiName: string, protocolId: ProtocolId) => ethers.Wallet;
19
+ export declare const deriveBeaconId: (airnodeAddress: Address, templateId: Hex) => string;
20
+ export declare const deriveBeaconSetId: (beaconIds: Hex[]) => string;
21
+ export declare const deriveHdNodeFromXpub: (xpub: string) => ethers.utils.HDNode;
22
+ export declare const verifyAirnodeXpub: (airnodeXpub: string, airnodeAddress: Address) => ethers.utils.HDNode;
23
+ export declare function deriveSponsorWalletAddress(airnodeXpub: string, sponsorAddress: Address, protocolId: ProtocolId, airnodeAddress?: Address): string;
78
24
  //# sourceMappingURL=derivation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"derivation.d.ts","sourceRoot":"","sources":["../../src/blockchain-utilities/derivation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAIhC,eAAO,MAAM,YAAY;;;;;;CAMxB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,+CAAgD,QAAQ,WACsB,CAAC;AAE5G;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,aAAc,MAAM,gBAAgB,MAAM,WACsC,CAAC;AAE9G;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,oBAAqB,MAAM,WAC0C,CAAC;AAEpG;;;;;GAKG;AACH,wBAAgB,kCAAkC,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,UAU5F;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe,UAAW,MAAM,WAA4C,CAAC;AAE1F;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,UAAW,MAAM,WAA2C,CAAC;AAE3F;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,0BAA2B,MAAM,YAAY,MAAM,kBAWlF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,mBAAoB,MAAM,cAAc,MAAM,WACa,CAAC;AAEvF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,cAAe,MAAM,EAAE,WACoC,CAAC"}
1
+ {"version":3,"file":"derivation.d.ts","sourceRoot":"","sources":["../../src/blockchain-utilities/derivation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEvD,eAAO,MAAM,YAAY;;;;;;CAMf,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAE1E,eAAO,MAAM,kBAAkB,YAAa,OAAO,cAAc,GAAG,qBAAqB,GAAG,WACe,CAAC;AAE5G,eAAO,MAAM,kBAAkB,eAAgB,GAAG,qBAAqB,GAAG,WACa,CAAC;AAExF,eAAO,MAAM,gBAAgB,aAAc,MAAM,gBAAgB,MAAM,WACsC,CAAC;AAE9G,eAAO,MAAM,iBAAiB,oBAAqB,QAAQ,WACwC,CAAC;AAEpG,wBAAgB,kCAAkC,CAAC,cAAc,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,UAQjG;AAED,eAAO,MAAM,eAAe,UAAW,MAAM,WAA4C,CAAC;AAE1F,eAAO,MAAM,iBAAiB,UAAW,GAAG,WAA2C,CAAC;AAExF,eAAO,MAAM,mBAAmB,oBAAqB,QAAQ,YAAY,MAAM,cAAc,UAAU,kBAStG,CAAC;AAEF,eAAO,MAAM,cAAc,mBAAoB,OAAO,cAAc,GAAG,WACe,CAAC;AAEvF,eAAO,MAAM,iBAAiB,cAAe,GAAG,EAAE,WAEuC,CAAC;AAE1F,eAAO,MAAM,oBAAoB,SAAU,MAAM,wBAA8C,CAAC;AAEhG,eAAO,MAAM,iBAAiB,gBAAiB,MAAM,kBAAkB,OAAO,KAAG,OAAO,KAAK,CAAC,MAQ7F,CAAC;AAEF,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,OAAO,EACvB,UAAU,EAAE,UAAU,EACtB,cAAc,CAAC,EAAE,OAAO,UAKzB"}
@@ -1,8 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.deriveBeaconSetId = exports.deriveBeaconId = exports.deriveSponsorWallet = exports.fromBytes32String = exports.toBytes32String = exports.deriveWalletPathFromSponsorAddress = exports.deriveAirnodeXpub = exports.deriveEndpointId = exports.deriveTemplateId = exports.PROTOCOL_IDS = void 0;
3
+ exports.deriveSponsorWalletAddress = exports.verifyAirnodeXpub = exports.deriveHdNodeFromXpub = exports.deriveBeaconSetId = exports.deriveBeaconId = exports.deriveSponsorWallet = exports.fromBytes32String = exports.toBytes32String = exports.deriveWalletPathFromSponsorAddress = exports.deriveAirnodeXpub = exports.deriveEndpointId = exports.deriveTemplateIdV1 = exports.deriveTemplateIdV0 = exports.PROTOCOL_IDS = void 0;
4
4
  const ethers_1 = require("ethers");
5
- const schema_1 = require("./schema");
6
5
  exports.PROTOCOL_IDS = {
7
6
  RRP: '1',
8
7
  PSP: '2',
@@ -10,38 +9,15 @@ exports.PROTOCOL_IDS = {
10
9
  RELAYED_PSP: '4',
11
10
  AIRSEEKER: '5',
12
11
  };
13
- /**
14
- * Derives a template ID from the input parameters
15
- *
16
- * @param airnode an Airnode address
17
- * @param encodedParameters encoded parameters, see the airnode/abi package's encode function
18
- * @param endpointId An endpointID (see deriveEndpointId)
19
- */
20
- const deriveTemplateId = ({ airnode, encodedParameters, endpointId }) => ethers_1.ethers.utils.solidityKeccak256(['address', 'bytes32', 'bytes'], [airnode, endpointId, encodedParameters]);
21
- exports.deriveTemplateId = deriveTemplateId;
22
- /**
23
- * Derives an endpoint ID
24
- *
25
- * @param oisTitle the OIS title
26
- * @param endpointName the endpoint name
27
- */
12
+ const deriveTemplateIdV0 = (airnode, endpointId, encodedParameters) => ethers_1.ethers.utils.solidityKeccak256(['address', 'bytes32', 'bytes'], [airnode, endpointId, encodedParameters]);
13
+ exports.deriveTemplateIdV0 = deriveTemplateIdV0;
14
+ const deriveTemplateIdV1 = (endpointId, encodedParameters) => ethers_1.ethers.utils.solidityKeccak256(['bytes32', 'bytes'], [endpointId, encodedParameters]);
15
+ exports.deriveTemplateIdV1 = deriveTemplateIdV1;
28
16
  const deriveEndpointId = (oisTitle, endpointName) => ethers_1.ethers.utils.keccak256(ethers_1.ethers.utils.defaultAbiCoder.encode(['string', 'string'], [oisTitle, endpointName]));
29
17
  exports.deriveEndpointId = deriveEndpointId;
30
- /**
31
- * Derives an airnode address's xpub, required for allowing signed data consumers to verify authenticity
32
- *
33
- * @param airnodeMnemonic the airnode's mnemonic
34
- */
35
18
  const deriveAirnodeXpub = (airnodeMnemonic) => ethers_1.ethers.utils.HDNode.fromMnemonic(airnodeMnemonic).derivePath("m/44'/60'/0'").neuter().extendedKey;
36
19
  exports.deriveAirnodeXpub = deriveAirnodeXpub;
37
- /**
38
- * Derives a wallet path from a sponsor address, used for calculating a sponsor wallet.
39
- *
40
- * @param sponsorAddress an EVM-compatible address
41
- * @param protocolId an API application protocol ID
42
- */
43
20
  function deriveWalletPathFromSponsorAddress(sponsorAddress, protocolId) {
44
- schema_1.addressSchema.parse(sponsorAddress);
45
21
  const sponsorAddressBN = ethers_1.ethers.BigNumber.from(sponsorAddress);
46
22
  const paths = [];
47
23
  for (let i = 0; i < 6; i++) {
@@ -51,47 +27,39 @@ function deriveWalletPathFromSponsorAddress(sponsorAddress, protocolId) {
51
27
  return `${protocolId}/${paths.join('/')}`;
52
28
  }
53
29
  exports.deriveWalletPathFromSponsorAddress = deriveWalletPathFromSponsorAddress;
54
- /**
55
- * Encodes/formats a string as a hex-encoded bytes32 string.
56
- *
57
- * @param input the input string
58
- */
59
30
  const toBytes32String = (input) => ethers_1.ethers.utils.formatBytes32String(input);
60
31
  exports.toBytes32String = toBytes32String;
61
- /**
62
- * Decodes a hex-encoded bytes32 string to a normal string.
63
- *
64
- * @param input the input hex string
65
- */
66
32
  const fromBytes32String = (input) => ethers_1.ethers.utils.parseBytes32String(input);
67
33
  exports.fromBytes32String = fromBytes32String;
68
- /**
69
- * Derives a sponsor wallet, given a mnemonic and dapiName.
70
- *
71
- * @param sponsorWalletMnemonic the sponsor wallet mnemonic
72
- * @param dapiName the dapi name
73
- */
74
- const deriveSponsorWallet = (sponsorWalletMnemonic, dapiName) => {
34
+ const deriveSponsorWallet = (airnodeMnemonic, dapiName, protocolId) => {
75
35
  // Take first 20 bytes of dapiName as sponsor address together with the "0x" prefix.
76
36
  const sponsorAddress = ethers_1.ethers.utils.getAddress(dapiName.slice(0, 42));
77
- const sponsorWallet = ethers_1.ethers.Wallet.fromMnemonic(sponsorWalletMnemonic, `m/44'/60'/0'/${(deriveWalletPathFromSponsorAddress(sponsorAddress, exports.PROTOCOL_IDS.AIRSEEKER), exports.PROTOCOL_IDS.AIRSEEKER)}`);
37
+ const sponsorWallet = ethers_1.ethers.Wallet.fromMnemonic(airnodeMnemonic, `m/44'/60'/0'/${deriveWalletPathFromSponsorAddress(sponsorAddress, protocolId)}`);
78
38
  return sponsorWallet;
79
39
  };
80
40
  exports.deriveSponsorWallet = deriveSponsorWallet;
81
- /**
82
- * Derives the ID of a single beacon
83
- *
84
- * @param airnodeAddress the airnode address of the provider that supplies the data used to update this beacon
85
- * @param templateId the templateId of the template used to generate the data used to update this beacon
86
- */
87
41
  const deriveBeaconId = (airnodeAddress, templateId) => ethers_1.ethers.utils.solidityKeccak256(['address', 'bytes32'], [airnodeAddress, templateId]);
88
42
  exports.deriveBeaconId = deriveBeaconId;
89
- /**
90
- * Derives the ID of a set of beacons.
91
- * By convention beacon IDs are sorted alphabetically - the ordering impacts the resulting hash.
92
- *
93
- * @param beaconIds an ordered array of beacon ids
94
- */
95
- const deriveBeaconSetId = (beaconIds) => ethers_1.ethers.utils.keccak256(ethers_1.ethers.utils.defaultAbiCoder.encode(['bytes32[]'], [beaconIds]));
43
+ const deriveBeaconSetId = (beaconIds) =>
44
+ // By convention beacon IDs are sorted alphabetically - the ordering impacts the resulting hash.
45
+ ethers_1.ethers.utils.keccak256(ethers_1.ethers.utils.defaultAbiCoder.encode(['bytes32[]'], [beaconIds]));
96
46
  exports.deriveBeaconSetId = deriveBeaconSetId;
47
+ const deriveHdNodeFromXpub = (xpub) => ethers_1.ethers.utils.HDNode.fromExtendedKey(xpub);
48
+ exports.deriveHdNodeFromXpub = deriveHdNodeFromXpub;
49
+ const verifyAirnodeXpub = (airnodeXpub, airnodeAddress) => {
50
+ // The xpub is expected to belong to the hardened path m/44'/60'/0' so we must derive the child default derivation
51
+ // path m/44'/60'/0'/0/0 to compare it and check if xpub belongs to the Airnode wallet.
52
+ const hdNode = (0, exports.deriveHdNodeFromXpub)(airnodeXpub);
53
+ if (airnodeAddress !== hdNode.derivePath('0/0').address) {
54
+ throw new Error(`xpub does not belong to Airnode: ${airnodeAddress}`);
55
+ }
56
+ return hdNode;
57
+ };
58
+ exports.verifyAirnodeXpub = verifyAirnodeXpub;
59
+ function deriveSponsorWalletAddress(airnodeXpub, sponsorAddress, protocolId, airnodeAddress) {
60
+ const hdNode = airnodeAddress ? (0, exports.verifyAirnodeXpub)(airnodeXpub, airnodeAddress) : (0, exports.deriveHdNodeFromXpub)(airnodeXpub);
61
+ const derivationPath = deriveWalletPathFromSponsorAddress(sponsorAddress, protocolId);
62
+ return hdNode.derivePath(derivationPath).address;
63
+ }
64
+ exports.deriveSponsorWalletAddress = deriveSponsorWalletAddress;
97
65
  //# sourceMappingURL=derivation.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"derivation.js","sourceRoot":"","sources":["../../src/blockchain-utilities/derivation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"derivation.js","sourceRoot":"","sources":["../../src/blockchain-utilities/derivation.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,14 @@
1
1
  import { z } from 'zod';
2
- /**
3
- * A Zod validation schema that represents an EVM-compatible address.
4
- */
5
- export declare const addressSchema: z.ZodString;
6
- /**
7
- * A Zod validation schema that represents an EVM-compatible hash, which includes beacon IDs and template IDs.
8
- */
9
- export declare const idSchema: z.ZodString;
2
+ export declare const hexSchema: z.ZodString;
3
+ export type Hex = `0x${string}`;
4
+ export declare const addressSchema: z.ZodEffects<z.ZodString, `0x${string}`, string>;
10
5
  export type Address = z.infer<typeof addressSchema>;
11
- export type Id = z.infer<typeof idSchema>;
6
+ export declare const keccak256HashSchema: z.ZodEffects<z.ZodString, `0x${string}`, string>;
7
+ export type Keccak256Hash = z.infer<typeof keccak256HashSchema>;
8
+ export declare const chainIdSchema: z.ZodEffects<z.ZodString, string, string>;
9
+ export type ChainId = z.infer<typeof chainIdSchema>;
10
+ export declare const ethUnitsSchema: z.ZodUnion<[z.ZodLiteral<"wei">, z.ZodLiteral<"kwei">, z.ZodLiteral<"mwei">, z.ZodLiteral<"gwei">, z.ZodLiteral<"szabo">, z.ZodLiteral<"finney">, z.ZodLiteral<"ether">]>;
11
+ export type EthUnits = z.infer<typeof ethUnitsSchema>;
12
+ export declare const mnemonicSchema: z.ZodEffects<z.ZodString, string, string>;
13
+ export type Mnemonic = z.infer<typeof mnemonicSchema>;
12
14
  //# sourceMappingURL=schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/blockchain-utilities/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,eAAO,MAAM,aAAa,aAAwE,CAAC;AAEnG;;GAEG;AACH,eAAO,MAAM,QAAQ,aAAqE,CAAC;AAE3F,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AACpD,MAAM,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/blockchain-utilities/schema.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,SAAS,aAAoE,CAAC;AAE3F,MAAM,MAAM,GAAG,GAAG,KAAK,MAAM,EAAE,CAAC;AAEhC,eAAO,MAAM,aAAa,kDAQxB,CAAC;AAEH,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD,eAAO,MAAM,mBAAmB,kDAGC,CAAC;AAElC,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,aAAa,2CAGoD,CAAC;AAE/E,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAEpD,eAAO,MAAM,cAAc,2KAQzB,CAAC;AAEH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,eAAO,MAAM,cAAc,2CAEwD,CAAC;AAEpF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC"}
@@ -1,13 +1,36 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.idSchema = exports.addressSchema = void 0;
3
+ exports.mnemonicSchema = exports.ethUnitsSchema = exports.chainIdSchema = exports.keccak256HashSchema = exports.addressSchema = exports.hexSchema = void 0;
4
+ const promise_utils_1 = require("@api3/promise-utils");
5
+ const ethers_1 = require("ethers");
4
6
  const zod_1 = require("zod");
5
- /**
6
- * A Zod validation schema that represents an EVM-compatible address.
7
- */
8
- exports.addressSchema = zod_1.z.string().regex(/^0x[\dA-Fa-f]{40}$/, 'Must be a valid EVM address');
9
- /**
10
- * A Zod validation schema that represents an EVM-compatible hash, which includes beacon IDs and template IDs.
11
- */
12
- exports.idSchema = zod_1.z.string().regex(/^0x[\dA-Fa-f]{64}$/, 'Must be a valid EVM hash');
7
+ exports.hexSchema = zod_1.z.string().regex(/^0x[\dA-Fa-f]+$/, 'Must be a valid hex string');
8
+ exports.addressSchema = zod_1.z.string().transform((value, ctx) => {
9
+ const goParseAddress = (0, promise_utils_1.goSync)(() => ethers_1.ethers.utils.getAddress(value));
10
+ if (!goParseAddress.success) {
11
+ ctx.addIssue({ code: zod_1.z.ZodIssueCode.custom, message: 'Invalid EVM address' });
12
+ return zod_1.z.NEVER;
13
+ }
14
+ return goParseAddress.data;
15
+ });
16
+ exports.keccak256HashSchema = zod_1.z
17
+ .string()
18
+ .regex(/^0x[\dA-Fa-f]{64}$/, 'Must be a valid EVM keccak256 hash')
19
+ .transform((val) => val);
20
+ exports.chainIdSchema = zod_1.z
21
+ .string()
22
+ .regex(/^\d+$/, 'Must be a valid chain ID')
23
+ .refine((chainId) => Number(chainId) > 0, 'Chain ID must be greater than 0');
24
+ exports.ethUnitsSchema = zod_1.z.union([
25
+ zod_1.z.literal('wei'),
26
+ zod_1.z.literal('kwei'),
27
+ zod_1.z.literal('mwei'),
28
+ zod_1.z.literal('gwei'),
29
+ zod_1.z.literal('szabo'),
30
+ zod_1.z.literal('finney'),
31
+ zod_1.z.literal('ether'),
32
+ ]);
33
+ exports.mnemonicSchema = zod_1.z
34
+ .string()
35
+ .refine((mnemonic) => ethers_1.ethers.utils.isValidMnemonic(mnemonic), 'Invalid mnemonic');
13
36
  //# sourceMappingURL=schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/blockchain-utilities/schema.ts"],"names":[],"mappings":";;;AAAA,6BAAwB;AAExB;;GAEG;AACU,QAAA,aAAa,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,oBAAoB,EAAE,6BAA6B,CAAC,CAAC;AAEnG;;GAEG;AACU,QAAA,QAAQ,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,oBAAoB,EAAE,0BAA0B,CAAC,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/blockchain-utilities/schema.ts"],"names":[],"mappings":";;;AAAA,uDAA6C;AAC7C,mCAAgC;AAChC,6BAAwB;AAEX,QAAA,SAAS,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,iBAAiB,EAAE,4BAA4B,CAAC,CAAC;AAI9E,QAAA,aAAa,GAAG,OAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IAC/D,MAAM,cAAc,GAAG,IAAA,sBAAM,EAAC,GAAG,EAAE,CAAC,eAAM,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;IACpE,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;QAC3B,GAAG,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAC,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC,CAAC;QAC9E,OAAO,OAAC,CAAC,KAAK,CAAC;KAChB;IAED,OAAO,cAAc,CAAC,IAAW,CAAC;AACpC,CAAC,CAAC,CAAC;AAIU,QAAA,mBAAmB,GAAG,OAAC;KACjC,MAAM,EAAE;KACR,KAAK,CAAC,oBAAoB,EAAE,oCAAoC,CAAC;KACjE,SAAS,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAU,CAAC,CAAC;AAIrB,QAAA,aAAa,GAAG,OAAC;KAC3B,MAAM,EAAE;KACR,KAAK,CAAC,OAAO,EAAE,0BAA0B,CAAC;KAC1C,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,iCAAiC,CAAC,CAAC;AAIlE,QAAA,cAAc,GAAG,OAAC,CAAC,KAAK,CAAC;IACpC,OAAC,CAAC,OAAO,CAAC,KAAK,CAAC;IAChB,OAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACjB,OAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACjB,OAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACjB,OAAC,CAAC,OAAO,CAAC,OAAO,CAAC;IAClB,OAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;IACnB,OAAC,CAAC,OAAO,CAAC,OAAO,CAAC;CACnB,CAAC,CAAC;AAIU,QAAA,cAAc,GAAG,OAAC;KAC5B,MAAM,EAAE;KACR,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,eAAM,CAAC,KAAK,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,kBAAkB,CAAC,CAAC"}
@@ -1,4 +1,4 @@
1
- import { type Method, type AxiosError, type AxiosResponse } from 'axios';
1
+ import { type Method, type AxiosError } from 'axios';
2
2
  export interface Request {
3
3
  readonly method: Method;
4
4
  readonly url: string;
@@ -8,7 +8,7 @@ export interface Request {
8
8
  readonly body?: unknown;
9
9
  }
10
10
  export interface ErrorResponse {
11
- readonly axiosResponse: Pick<AxiosResponse, 'data' | 'headers' | 'status'> | undefined;
11
+ readonly response: unknown;
12
12
  readonly message: string;
13
13
  readonly code: string | undefined;
14
14
  }
@@ -17,11 +17,13 @@ interface ExecuteRequestSuccess<T> {
17
17
  success: true;
18
18
  errorData: undefined;
19
19
  data: T;
20
+ statusCode: number;
20
21
  }
21
22
  interface ExecuteRequestError {
22
23
  success: false;
23
24
  errorData: ErrorResponse;
24
25
  data: undefined;
26
+ statusCode: number | undefined;
25
27
  }
26
28
  export type ExecuteRequestResult<T> = ExecuteRequestError | ExecuteRequestSuccess<T>;
27
29
  export declare function executeRequest<T>(request: Request): Promise<ExecuteRequestResult<T>>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AACA,OAAc,EAAE,KAAK,MAAM,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAKhF,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC,GAAG,SAAS,CAAC;IACvF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,eAAO,MAAM,qBAAqB,UAAW,UAAU,KAAG,aAOzD,CAAC;AAEF,UAAU,qBAAqB,CAAC,CAAC;IAC/B,OAAO,EAAE,IAAI,CAAC;IACd,SAAS,EAAE,SAAS,CAAC;IACrB,IAAI,EAAE,CAAC,CAAC;CACT;AACD,UAAU,mBAAmB;IAC3B,OAAO,EAAE,KAAK,CAAC;IACf,SAAS,EAAE,aAAa,CAAC;IACzB,IAAI,EAAE,SAAS,CAAC;CACjB;AAED,MAAM,MAAM,oBAAoB,CAAC,CAAC,IAAI,mBAAmB,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;AAErF,wBAAsB,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAiB1F"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AACA,OAAc,EAAE,KAAK,MAAM,EAAE,KAAK,UAAU,EAAsB,MAAM,OAAO,CAAC;AAIhF,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,eAAO,MAAM,qBAAqB,UAAW,UAAU,KAAG,aAOzD,CAAC;AAEF,UAAU,qBAAqB,CAAC,CAAC;IAC/B,OAAO,EAAE,IAAI,CAAC;IACd,SAAS,EAAE,SAAS,CAAC;IACrB,IAAI,EAAE,CAAC,CAAC;IACR,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,UAAU,mBAAmB;IAC3B,OAAO,EAAE,KAAK,CAAC;IACf,SAAS,EAAE,aAAa,CAAC;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,MAAM,oBAAoB,CAAC,CAAC,IAAI,mBAAmB,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;AAErF,wBAAsB,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAwB1F"}
@@ -6,12 +6,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.executeRequest = exports.extractAxiosErrorData = void 0;
7
7
  const promise_utils_1 = require("@api3/promise-utils");
8
8
  const axios_1 = __importDefault(require("axios"));
9
- const pick_1 = __importDefault(require("lodash/pick"));
10
9
  const DEFAULT_TIMEOUT_MS = 10_000;
11
10
  const extractAxiosErrorData = (error) => {
12
11
  // Inspired by: https://axios-http.com/docs/handling_errors
13
12
  return {
14
- axiosResponse: error.response ? (0, pick_1.default)(error.response, ['data', 'status']) : undefined,
13
+ response: error.response?.data,
15
14
  message: error.message,
16
15
  code: error.code,
17
16
  };
@@ -27,10 +26,16 @@ async function executeRequest(request) {
27
26
  params: queryParams,
28
27
  timeout,
29
28
  }));
30
- if (!goAxios.success)
31
- return { success: false, errorData: (0, exports.extractAxiosErrorData)(goAxios.error), data: undefined };
29
+ if (!goAxios.success) {
30
+ return {
31
+ success: false,
32
+ errorData: (0, exports.extractAxiosErrorData)(goAxios.error),
33
+ data: undefined,
34
+ statusCode: goAxios.error.status,
35
+ };
36
+ }
32
37
  const response = goAxios.data;
33
- return { success: true, errorData: undefined, data: response.data };
38
+ return { success: true, errorData: undefined, data: response.data, statusCode: response.status };
34
39
  }
35
40
  exports.executeRequest = executeRequest;
36
41
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":";;;;;;AAAA,uDAAyC;AACzC,kDAAgF;AAChF,uDAA+B;AAE/B,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAiB3B,MAAM,qBAAqB,GAAG,CAAC,KAAiB,EAAiB,EAAE;IACxE,2DAA2D;IAC3D,OAAO;QACL,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAA,cAAI,EAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;QACpF,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;KACA,CAAC;AACrB,CAAC,CAAC;AAPW,QAAA,qBAAqB,yBAOhC;AAeK,KAAK,UAAU,cAAc,CAAI,OAAgB;IACtD,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,EAAE,EAAE,WAAW,GAAG,EAAE,EAAE,OAAO,GAAG,kBAAkB,EAAE,GAAG,OAAO,CAAC;IAEpG,MAAM,OAAO,GAAG,MAAM,IAAA,kBAAE,EAAwC,KAAK,IAAI,EAAE,CACzE,IAAA,eAAK,EAAC;QACJ,GAAG;QACH,MAAM;QACN,OAAO;QACP,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,WAAW;QACnB,OAAO;KACR,CAAC,CACH,CAAC;IACF,IAAI,CAAC,OAAO,CAAC,OAAO;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAA,6BAAqB,EAAC,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAClH,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAE9B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;AACtE,CAAC;AAjBD,wCAiBC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":";;;;;;AAAA,uDAAyC;AACzC,kDAAgF;AAEhF,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAiB3B,MAAM,qBAAqB,GAAG,CAAC,KAAiB,EAAiB,EAAE;IACxE,2DAA2D;IAC3D,OAAO;QACL,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,IAAI;QAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC;AACJ,CAAC,CAAC;AAPW,QAAA,qBAAqB,yBAOhC;AAiBK,KAAK,UAAU,cAAc,CAAI,OAAgB;IACtD,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,EAAE,EAAE,WAAW,GAAG,EAAE,EAAE,OAAO,GAAG,kBAAkB,EAAE,GAAG,OAAO,CAAC;IAEpG,MAAM,OAAO,GAAG,MAAM,IAAA,kBAAE,EAAwC,KAAK,IAAI,EAAE,CACzE,IAAA,eAAK,EAAC;QACJ,GAAG;QACH,MAAM;QACN,OAAO;QACP,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,WAAW;QACnB,OAAO;KACR,CAAC,CACH,CAAC;IACF,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE;QACpB,OAAO;YACL,OAAO,EAAE,KAAK;YACd,SAAS,EAAE,IAAA,6BAAqB,EAAC,OAAO,CAAC,KAAK,CAAC;YAC/C,IAAI,EAAE,SAAS;YACf,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM;SACjC,CAAC;KACH;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAE9B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;AACnG,CAAC;AAxBD,wCAwBC"}
@@ -1,2 +1,3 @@
1
1
  export * from './blockchain-utilities';
2
+ export * from './http';
2
3
  //# sourceMappingURL=universal-index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"universal-index.d.ts","sourceRoot":"","sources":["../src/universal-index.ts"],"names":[],"mappings":"AACA,cAAc,wBAAwB,CAAC"}
1
+ {"version":3,"file":"universal-index.d.ts","sourceRoot":"","sources":["../src/universal-index.ts"],"names":[],"mappings":"AACA,cAAc,wBAAwB,CAAC;AACvC,cAAc,QAAQ,CAAC"}
@@ -16,4 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  // NOTE: Only export modules which work in both Node.js and browser environments.
18
18
  __exportStar(require("./blockchain-utilities"), exports);
19
+ __exportStar(require("./http"), exports);
19
20
  //# sourceMappingURL=universal-index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"universal-index.js","sourceRoot":"","sources":["../src/universal-index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iFAAiF;AACjF,yDAAuC"}
1
+ {"version":3,"file":"universal-index.js","sourceRoot":"","sources":["../src/universal-index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iFAAiF;AACjF,yDAAuC;AACvC,yCAAuB"}
package/package.json CHANGED
@@ -1,11 +1,10 @@
1
1
  {
2
2
  "name": "@api3/commons",
3
- "version": "0.7.1",
3
+ "version": "0.9.0",
4
4
  "keywords": [],
5
5
  "license": "MIT",
6
6
  "engines": {
7
- "node": "^18.14.0 || ^20.10.0",
8
- "pnpm": "^8.8.0"
7
+ "node": ">=18.14.0"
9
8
  },
10
9
  "files": [
11
10
  "dist",
@@ -6,20 +6,24 @@ import {
6
6
  deriveBeaconSetId,
7
7
  deriveEndpointId,
8
8
  deriveSponsorWallet,
9
- deriveTemplateId,
9
+ deriveSponsorWalletAddress,
10
+ deriveTemplateIdV0,
11
+ deriveTemplateIdV1,
10
12
  deriveWalletPathFromSponsorAddress,
11
13
  fromBytes32String,
12
14
  PROTOCOL_IDS,
13
15
  toBytes32String,
16
+ verifyAirnodeXpub,
14
17
  } from './derivation';
18
+ import type { Address } from './schema';
15
19
 
16
- describe('deriveWalletPathFromSponsorAddress', () => {
20
+ describe(deriveWalletPathFromSponsorAddress.name, () => {
17
21
  it('converts address to derivation path', () => {
18
22
  const sponsorAddress = '0x8A45eac0267dD0803Fd957723EdE10693A076698';
19
23
  const res = deriveWalletPathFromSponsorAddress(sponsorAddress, PROTOCOL_IDS.AIRSEEKER);
20
24
  expect(res).toBe('5/973563544/2109481170/2137349576/871269377/610184194/17');
21
25
 
22
- const randomAddress = ethers.utils.getAddress(ethers.utils.hexlify(ethers.utils.randomBytes(20)));
26
+ const randomAddress = ethers.utils.getAddress(ethers.utils.hexlify(ethers.utils.randomBytes(20))) as Address;
23
27
  const randomPath = deriveWalletPathFromSponsorAddress(randomAddress, PROTOCOL_IDS.AIRSEEKER);
24
28
  expect(res).not.toStrictEqual(randomPath);
25
29
  });
@@ -45,103 +49,184 @@ describe('deriveWalletPathFromSponsorAddress', () => {
45
49
  });
46
50
 
47
51
  it('throws if address is an empty string', () => {
48
- const sponsorAddress = '';
52
+ const sponsorAddress = '' as Address;
49
53
  expect(() => deriveWalletPathFromSponsorAddress(sponsorAddress, PROTOCOL_IDS.AIRSEEKER)).toThrow(
50
54
  expect.objectContaining({ name: expect.stringContaining('Error') })
51
55
  );
52
56
  });
57
+ });
53
58
 
54
- it('throws if address is invalid', () => {
55
- let sponsorAddress = '7dD0803Fd957723EdE10693A076698';
56
- expect(() => deriveWalletPathFromSponsorAddress(sponsorAddress, PROTOCOL_IDS.AIRSEEKER)).toThrow(
57
- expect.objectContaining({ name: expect.stringContaining('Error') })
59
+ describe(deriveSponsorWallet.name, () => {
60
+ it('derives a sponsor wallet', () => {
61
+ const dapiName = ethers.utils.formatBytes32String('BTC/ETH');
62
+ const sponsorWallet = deriveSponsorWallet(
63
+ 'test test test test test test test test test test test junk',
64
+ dapiName,
65
+ '1'
58
66
  );
59
67
 
60
- sponsorAddress = ethers.utils.hexlify(ethers.utils.randomBytes(4));
61
- expect(() => deriveWalletPathFromSponsorAddress(sponsorAddress, PROTOCOL_IDS.AIRSEEKER)).toThrow(
62
- expect.objectContaining({ name: expect.stringContaining('Error') })
63
- );
68
+ expect(sponsorWallet.address).toBe('0x4f86228e0Bc58829Cd77547224291bb8d212174D');
69
+ });
64
70
 
65
- sponsorAddress = ethers.utils.hexlify(ethers.utils.randomBytes(32));
66
- expect(() => deriveWalletPathFromSponsorAddress(sponsorAddress, PROTOCOL_IDS.AIRSEEKER)).toThrow(
67
- expect.objectContaining({ name: expect.stringContaining('Error') })
68
- );
71
+ it('throws deriving a sponsor wallet due to an invalid DApi name', () => {
72
+ const dapiName = 'invalid dapi name';
73
+ const throwingFn = () =>
74
+ deriveSponsorWallet('test test test test test test test test test test test junk', dapiName, '5');
75
+
76
+ expect(throwingFn).toThrow(expect.objectContaining({ name: expect.stringContaining('Error') }));
69
77
  });
70
78
 
71
- describe('blockchain utilities', () => {
72
- it('derives a sponsor wallet', () => {
73
- const dapiName = ethers.utils.formatBytes32String('BTC/ETH');
74
- const sponsorWallet = deriveSponsorWallet(
75
- 'test test test test test test test test test test test junk',
76
- dapiName
79
+ it('derives the same sponsor wallet as Airnode', () => {
80
+ function deriveSponsorWalletAirnode(masterHDNode: ethers.utils.HDNode, sponsorAddress: Address): ethers.Wallet {
81
+ const sponsorWalletHdNode = masterHDNode.derivePath(
82
+ `m/44'/60'/0'/${deriveWalletPathFromSponsorAddress(sponsorAddress, '1')}`
77
83
  );
84
+ return new ethers.Wallet(sponsorWalletHdNode.privateKey);
85
+ }
86
+ const mnemonic = 'achieve climb couple wait accident symbol spy blouse reduce foil echo label';
87
+ const hdNode = ethers.utils.HDNode.fromMnemonic(mnemonic);
78
88
 
79
- expect(sponsorWallet.address).toBe('0x1e6f0dfb1775f5032f12f56a01526351eD3F07aF');
80
- });
89
+ // https://github.com/api3dao/airnode/blob/a4c17c28c8b31c9fb13d2828764b89f1063b702f/packages/airnode-node/src/evm/wallet.test.ts#L25
90
+ const expectedSponsorWallet = deriveSponsorWalletAirnode(hdNode, '0x06f509f73eefba36352bc8228f9112c3786100da');
91
+ const actualSponsorWallet = deriveSponsorWallet(mnemonic, '0x06f509f73eefba36352bc8228f9112c3786100da', '1');
81
92
 
82
- it('throws deriving a sponsor wallet due to an invalid DApi name', () => {
83
- const dapiName = 'invalid dapi name';
84
- const throwingFn = () =>
85
- deriveSponsorWallet('test test test test test test test test test test test junk', dapiName);
93
+ expect(actualSponsorWallet.address).toBe(expectedSponsorWallet.address);
94
+ expect(actualSponsorWallet.address).toBe('0x228A54F33E46fbb32a62ca650Fcc9eD3C730511d');
95
+ });
96
+ });
86
97
 
87
- expect(throwingFn).toThrow(expect.objectContaining({ name: expect.stringContaining('Error') }));
88
- });
98
+ describe(deriveAirnodeXpub.name, () => {
99
+ it(`derives an airnode's xpub from a mnemonic`, () => {
100
+ const xpub = deriveAirnodeXpub('test test test test test test test test test test test junk');
89
101
 
90
- it(`derives an airnode's xpub from a mnemonic`, () => {
91
- const xpub = deriveAirnodeXpub('test test test test test test test test test test test junk');
102
+ expect(xpub).toBe(
103
+ 'xpub6Ce9NcJvTk36xtLSrJLZqE7wtgA5deCeYs7rSQtreh4cj6ByPtrg9sD7V2FNFLPnf8heNP3FGkeV9qwfzvZNSd54JoNXVsXFYSYwHsnJxqP'
104
+ );
105
+ });
106
+ });
92
107
 
93
- expect(xpub).toBe(
94
- 'xpub6Ce9NcJvTk36xtLSrJLZqE7wtgA5deCeYs7rSQtreh4cj6ByPtrg9sD7V2FNFLPnf8heNP3FGkeV9qwfzvZNSd54JoNXVsXFYSYwHsnJxqP'
95
- );
96
- });
108
+ describe(deriveEndpointId.name, () => {
109
+ it(`derives an endpoint ID`, () => {
110
+ const endpointId = deriveEndpointId('weather', 'temperature');
97
111
 
98
- it(`derives an endpoint ID`, () => {
99
- const endpointId = deriveEndpointId('weather', 'temperature');
112
+ expect(endpointId).toBe('0x5a82d40e44ecd3ef0906e9e82c1a20f2f4ffe4f613ac70f999047496a9cd4635');
113
+ });
114
+ });
100
115
 
101
- expect(endpointId).toBe('0x5a82d40e44ecd3ef0906e9e82c1a20f2f4ffe4f613ac70f999047496a9cd4635');
102
- });
116
+ describe(deriveTemplateIdV0.name, () => {
117
+ it(`it derives a template ID V0`, () => {
118
+ const templateId = deriveTemplateIdV0(
119
+ '0x4E95C31894a89CdC4288669A6F294836948c862b',
120
+ '0x5a82d40e44ecd3ef0906e9e82c1a20f2f4ffe4f613ac70f999047496a9cd4635',
121
+ '0x6466726f6d63455448'
122
+ );
103
123
 
104
- it(`it derives a template ID`, () => {
105
- const templateId = deriveTemplateId({
106
- airnode: '0x4E95C31894a89CdC4288669A6F294836948c862b',
107
- endpointId: '0x5a82d40e44ecd3ef0906e9e82c1a20f2f4ffe4f613ac70f999047496a9cd4635',
108
- encodedParameters: '0x1234',
109
- });
124
+ expect(templateId).toBe('0x25ea8b12135e4b8d49960ef9e0f967b7c0ccad136b955fbb7fbeb76da27d60b0');
125
+ });
126
+ });
110
127
 
111
- expect(templateId).toBe('0x7655363f294273f84bcc7c47d79858cf46f21951deee92746d9f17a69ac0b0c0');
112
- });
128
+ describe(deriveTemplateIdV1.name, () => {
129
+ it('derives templateId for V1', () => {
130
+ const expectedTemplateIdV1 = deriveTemplateIdV1(
131
+ '0x2f3a3adf6daf5a3bb00ab83aa82262a6a84b59b0a89222386135330a1819ab48',
132
+ '0x6466726f6d63455448'
133
+ );
113
134
 
114
- it('derives a beacon ID', () => {
115
- const beaconId = deriveBeaconId(
116
- '0xc52EeA00154B4fF1EbbF8Ba39FDe37F1AC3B9Fd4',
117
- '0x457a3b3da67e394a895ea49e534a4d91b2d009477bef15eab8cbed313925b010'
118
- );
135
+ expect(expectedTemplateIdV1).toBe('0xe5d99287b5a870c3453bc0b42769c6f37cf4a3143890e9c34753181171fac842');
136
+ });
137
+ });
138
+
139
+ describe(deriveBeaconId.name, () => {
140
+ it('derives a beacon ID', () => {
141
+ const beaconId = deriveBeaconId(
142
+ '0xc52EeA00154B4fF1EbbF8Ba39FDe37F1AC3B9Fd4',
143
+ '0x457a3b3da67e394a895ea49e534a4d91b2d009477bef15eab8cbed313925b010'
144
+ );
145
+
146
+ expect(beaconId).toBe('0xf5c140bcb4814dfec311d38f6293e86c02d32ba1b7da027fe5b5202cae35dbc6');
147
+ });
148
+ });
149
+
150
+ describe(deriveBeaconSetId.name, () => {
151
+ it(`derives a beacon set ID`, () => {
152
+ const beaconSetId = deriveBeaconSetId([
153
+ '0x0e30ed302a3c8eeaa0053caf5fbd0825c86ce1767584d12c69c310f0068b1176',
154
+ '0x496092597aef79595df1567412c6ddefd037f63a5a1572702dd469f62f31f469',
155
+ '0x84c1da28b2f29f0a2b0ff360d537d405d1cd69249fcf5f32ae9c2298cee6da12',
156
+ '0xe8655dc68f2b765c5e6d4a042ba7ba8606cf37e1c8c96676f85364ec5bfe9163',
157
+ '0xf5c140bcb4814dfec311d38f6293e86c02d32ba1b7da027fe5b5202cae35dbc6',
158
+ ]);
159
+
160
+ expect(beaconSetId).toBe('0x33bf380fd5b06a317a905b23eaf5c61ef0a9b4a20589a1bf1d13133daca34b0e');
161
+ });
162
+ });
163
+
164
+ describe(toBytes32String.name, () => {
165
+ it('encodes a string as a bytes32 string', () => {
166
+ const formattedString = toBytes32String('test string');
167
+
168
+ expect(formattedString).toBe('0x7465737420737472696e67000000000000000000000000000000000000000000');
169
+ });
170
+ });
171
+
172
+ describe(fromBytes32String.name, () => {
173
+ it('decodes a bytes32 string to a normal string', () => {
174
+ const formattedString = fromBytes32String('0x7465737420737472696e67000000000000000000000000000000000000000000');
175
+
176
+ expect(formattedString).toBe('test string');
177
+ });
178
+ });
119
179
 
120
- expect(beaconId).toBe('0xf5c140bcb4814dfec311d38f6293e86c02d32ba1b7da027fe5b5202cae35dbc6');
121
- });
180
+ describe(verifyAirnodeXpub.name, () => {
181
+ it('does not throw for valid xpub/airnode combination', () => {
182
+ expect(() =>
183
+ verifyAirnodeXpub(
184
+ 'xpub6CvZvZuFtPUtNirE36eMqYu8pRa1CEQuDon9tT4G8fisU3jj38Sn53TxdHb1SUvWiwVjJ68ytPZf45gnPM7Kg4g4CNTdyjJMevDQ1wk4tYD',
185
+ '0x02F5BD238B866c36f7d7b144D2889fB5e594474e'
186
+ )
187
+ ).not.toThrow();
188
+ });
122
189
 
123
- it(`derives a beacon set ID`, () => {
124
- const beaconSetId = deriveBeaconSetId([
125
- '0x0e30ed302a3c8eeaa0053caf5fbd0825c86ce1767584d12c69c310f0068b1176',
126
- '0x496092597aef79595df1567412c6ddefd037f63a5a1572702dd469f62f31f469',
127
- '0x84c1da28b2f29f0a2b0ff360d537d405d1cd69249fcf5f32ae9c2298cee6da12',
128
- '0xe8655dc68f2b765c5e6d4a042ba7ba8606cf37e1c8c96676f85364ec5bfe9163',
129
- '0xf5c140bcb4814dfec311d38f6293e86c02d32ba1b7da027fe5b5202cae35dbc6',
130
- ]);
190
+ it('throws when the xpub is invalid', () => {
191
+ expect(() =>
192
+ verifyAirnodeXpub(
193
+ 'xpub6CvZvZuFtPUtNirE36eMqYu8pRa1CEQuDon9tT4G8fisU3jj38Sn53TxdHb1SUvWiwVjJ68ytPZf45gnPM7Kg4g4CNTdyjJMevDQ1wk4tYD',
194
+ '0xDdfd47366cA427e75C26c9F3364EE37b33e1DD38'
195
+ )
196
+ ).toThrow('xpub does not belong to Airnode: 0xDdfd47366cA427e75C26c9F3364EE37b33e1DD38');
197
+ });
198
+ });
131
199
 
132
- expect(beaconSetId).toBe('0x33bf380fd5b06a317a905b23eaf5c61ef0a9b4a20589a1bf1d13133daca34b0e');
133
- });
200
+ describe(deriveSponsorWalletAddress, () => {
201
+ it('derives the sponsor wallet address and verifies airnode address', () => {
202
+ const sponsorWalletAddress = deriveSponsorWalletAddress(
203
+ 'xpub6CvZvZuFtPUtNirE36eMqYu8pRa1CEQuDon9tT4G8fisU3jj38Sn53TxdHb1SUvWiwVjJ68ytPZf45gnPM7Kg4g4CNTdyjJMevDQ1wk4tYD',
204
+ '0xE9232cde1f37B029dfbB403f79429f912D7405F3',
205
+ '1',
206
+ '0x02F5BD238B866c36f7d7b144D2889fB5e594474e'
207
+ );
134
208
 
135
- it('encodes a string as a bytes32 string', () => {
136
- const formattedString = toBytes32String('test string');
209
+ expect(sponsorWalletAddress).toBe('0xDdfd47366cA427e75C26c9F3364EE37b33e1DD38');
210
+ });
137
211
 
138
- expect(formattedString).toBe('0x7465737420737472696e67000000000000000000000000000000000000000000');
139
- });
212
+ it('derives the sponsor wallet without xpub verifification', () => {
213
+ const sponsorWalletAddress = deriveSponsorWalletAddress(
214
+ 'xpub6CvZvZuFtPUtNirE36eMqYu8pRa1CEQuDon9tT4G8fisU3jj38Sn53TxdHb1SUvWiwVjJ68ytPZf45gnPM7Kg4g4CNTdyjJMevDQ1wk4tYD',
215
+ '0xE9232cde1f37B029dfbB403f79429f912D7405F3',
216
+ '1'
217
+ );
140
218
 
141
- it('decodes a bytes32 string to a normal string', () => {
142
- const formattedString = fromBytes32String('0x7465737420737472696e67000000000000000000000000000000000000000000');
219
+ expect(sponsorWalletAddress).toBe('0xDdfd47366cA427e75C26c9F3364EE37b33e1DD38');
220
+ });
143
221
 
144
- expect(formattedString).toBe('test string');
145
- });
222
+ it('verifies that xpub is valid when airnode address is provided', () => {
223
+ expect(() =>
224
+ deriveSponsorWalletAddress(
225
+ 'xpub6CvZvZuFtPUtNirE36eMqYu8pRa1CEQuDon9tT4G8fisU3jj38Sn53TxdHb1SUvWiwVjJ68ytPZf45gnPM7Kg4g4CNTdyjJMevDQ1wk4tYD',
226
+ '0xE9232cde1f37B029dfbB403f79429f912D7405F3',
227
+ '1',
228
+ '0xA143283e75c8e0a3174d51e6ccA38B334E1D6b12'
229
+ )
230
+ ).toThrow('xpub does not belong to Airnode: 0xA143283e75c8e0a3174d51e6ccA38B334E1D6b12');
146
231
  });
147
232
  });
@@ -1,6 +1,6 @@
1
1
  import { ethers } from 'ethers';
2
2
 
3
- import { addressSchema } from './schema';
3
+ import type { Address, Hex, Mnemonic } from './schema';
4
4
 
5
5
  export const PROTOCOL_IDS = {
6
6
  RRP: '1',
@@ -8,53 +8,23 @@ export const PROTOCOL_IDS = {
8
8
  RELAYED_RRP: '3',
9
9
  RELAYED_PSP: '4',
10
10
  AIRSEEKER: '5',
11
- };
11
+ } as const;
12
12
 
13
- /**
14
- * An interface that reflects the structure of a Template
15
- */
16
- export interface Template {
17
- airnode: string;
18
- encodedParameters: string;
19
- endpointId: string;
20
- }
13
+ export type ProtocolId = (typeof PROTOCOL_IDS)[keyof typeof PROTOCOL_IDS];
21
14
 
22
- /**
23
- * Derives a template ID from the input parameters
24
- *
25
- * @param airnode an Airnode address
26
- * @param encodedParameters encoded parameters, see the airnode/abi package's encode function
27
- * @param endpointId An endpointID (see deriveEndpointId)
28
- */
29
- export const deriveTemplateId = ({ airnode, encodedParameters, endpointId }: Template) =>
15
+ export const deriveTemplateIdV0 = (airnode: Address, endpointId: Hex, encodedParameters: Hex) =>
30
16
  ethers.utils.solidityKeccak256(['address', 'bytes32', 'bytes'], [airnode, endpointId, encodedParameters]);
31
17
 
32
- /**
33
- * Derives an endpoint ID
34
- *
35
- * @param oisTitle the OIS title
36
- * @param endpointName the endpoint name
37
- */
18
+ export const deriveTemplateIdV1 = (endpointId: Hex, encodedParameters: Hex) =>
19
+ ethers.utils.solidityKeccak256(['bytes32', 'bytes'], [endpointId, encodedParameters]);
20
+
38
21
  export const deriveEndpointId = (oisTitle: string, endpointName: string) =>
39
22
  ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['string', 'string'], [oisTitle, endpointName]));
40
23
 
41
- /**
42
- * Derives an airnode address's xpub, required for allowing signed data consumers to verify authenticity
43
- *
44
- * @param airnodeMnemonic the airnode's mnemonic
45
- */
46
- export const deriveAirnodeXpub = (airnodeMnemonic: string) =>
24
+ export const deriveAirnodeXpub = (airnodeMnemonic: Mnemonic) =>
47
25
  ethers.utils.HDNode.fromMnemonic(airnodeMnemonic).derivePath("m/44'/60'/0'").neuter().extendedKey;
48
26
 
49
- /**
50
- * Derives a wallet path from a sponsor address, used for calculating a sponsor wallet.
51
- *
52
- * @param sponsorAddress an EVM-compatible address
53
- * @param protocolId an API application protocol ID
54
- */
55
- export function deriveWalletPathFromSponsorAddress(sponsorAddress: string, protocolId: string) {
56
- addressSchema.parse(sponsorAddress);
57
-
27
+ export function deriveWalletPathFromSponsorAddress(sponsorAddress: Address, protocolId: ProtocolId) {
58
28
  const sponsorAddressBN = ethers.BigNumber.from(sponsorAddress);
59
29
  const paths = [];
60
30
  for (let i = 0; i < 6; i++) {
@@ -64,53 +34,47 @@ export function deriveWalletPathFromSponsorAddress(sponsorAddress: string, proto
64
34
  return `${protocolId}/${paths.join('/')}`;
65
35
  }
66
36
 
67
- /**
68
- * Encodes/formats a string as a hex-encoded bytes32 string.
69
- *
70
- * @param input the input string
71
- */
72
37
  export const toBytes32String = (input: string) => ethers.utils.formatBytes32String(input);
73
38
 
74
- /**
75
- * Decodes a hex-encoded bytes32 string to a normal string.
76
- *
77
- * @param input the input hex string
78
- */
79
- export const fromBytes32String = (input: string) => ethers.utils.parseBytes32String(input);
80
-
81
- /**
82
- * Derives a sponsor wallet, given a mnemonic and dapiName.
83
- *
84
- * @param sponsorWalletMnemonic the sponsor wallet mnemonic
85
- * @param dapiName the dapi name
86
- */
87
- export const deriveSponsorWallet = (sponsorWalletMnemonic: string, dapiName: string) => {
39
+ export const fromBytes32String = (input: Hex) => ethers.utils.parseBytes32String(input);
40
+
41
+ export const deriveSponsorWallet = (airnodeMnemonic: Mnemonic, dapiName: string, protocolId: ProtocolId) => {
88
42
  // Take first 20 bytes of dapiName as sponsor address together with the "0x" prefix.
89
- const sponsorAddress = ethers.utils.getAddress(dapiName.slice(0, 42));
43
+ const sponsorAddress = ethers.utils.getAddress(dapiName.slice(0, 42)) as Address;
90
44
  const sponsorWallet = ethers.Wallet.fromMnemonic(
91
- sponsorWalletMnemonic,
92
- `m/44'/60'/0'/${
93
- (deriveWalletPathFromSponsorAddress(sponsorAddress, PROTOCOL_IDS.AIRSEEKER), PROTOCOL_IDS.AIRSEEKER)
94
- }`
45
+ airnodeMnemonic,
46
+ `m/44'/60'/0'/${deriveWalletPathFromSponsorAddress(sponsorAddress, protocolId)}`
95
47
  );
96
48
 
97
49
  return sponsorWallet;
98
50
  };
99
51
 
100
- /**
101
- * Derives the ID of a single beacon
102
- *
103
- * @param airnodeAddress the airnode address of the provider that supplies the data used to update this beacon
104
- * @param templateId the templateId of the template used to generate the data used to update this beacon
105
- */
106
- export const deriveBeaconId = (airnodeAddress: string, templateId: string) =>
52
+ export const deriveBeaconId = (airnodeAddress: Address, templateId: Hex) =>
107
53
  ethers.utils.solidityKeccak256(['address', 'bytes32'], [airnodeAddress, templateId]);
108
54
 
109
- /**
110
- * Derives the ID of a set of beacons.
111
- * By convention beacon IDs are sorted alphabetically - the ordering impacts the resulting hash.
112
- *
113
- * @param beaconIds an ordered array of beacon ids
114
- */
115
- export const deriveBeaconSetId = (beaconIds: string[]) =>
55
+ export const deriveBeaconSetId = (beaconIds: Hex[]) =>
56
+ // By convention beacon IDs are sorted alphabetically - the ordering impacts the resulting hash.
116
57
  ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(['bytes32[]'], [beaconIds]));
58
+
59
+ export const deriveHdNodeFromXpub = (xpub: string) => ethers.utils.HDNode.fromExtendedKey(xpub);
60
+
61
+ export const verifyAirnodeXpub = (airnodeXpub: string, airnodeAddress: Address): ethers.utils.HDNode => {
62
+ // The xpub is expected to belong to the hardened path m/44'/60'/0' so we must derive the child default derivation
63
+ // path m/44'/60'/0'/0/0 to compare it and check if xpub belongs to the Airnode wallet.
64
+ const hdNode = deriveHdNodeFromXpub(airnodeXpub);
65
+ if (airnodeAddress !== hdNode.derivePath('0/0').address) {
66
+ throw new Error(`xpub does not belong to Airnode: ${airnodeAddress}`);
67
+ }
68
+ return hdNode;
69
+ };
70
+
71
+ export function deriveSponsorWalletAddress(
72
+ airnodeXpub: string,
73
+ sponsorAddress: Address,
74
+ protocolId: ProtocolId,
75
+ airnodeAddress?: Address
76
+ ) {
77
+ const hdNode = airnodeAddress ? verifyAirnodeXpub(airnodeXpub, airnodeAddress) : deriveHdNodeFromXpub(airnodeXpub);
78
+ const derivationPath = deriveWalletPathFromSponsorAddress(sponsorAddress, protocolId);
79
+ return hdNode.derivePath(derivationPath).address;
80
+ }
@@ -1,8 +1,10 @@
1
- import { addressSchema, idSchema } from './schema';
1
+ import { addressSchema, hexSchema, keccak256HashSchema, chainIdSchema, ethUnitsSchema, mnemonicSchema } from './schema';
2
2
 
3
- describe('schema', () => {
4
- it('validates a valid address', () => {
5
- expect(() => addressSchema.parse('0x8A45eac0267dD0803Fd957723EdE10693A076698')).not.toThrow();
3
+ describe('addressSchema', () => {
4
+ it('validates a valid address and returns its checksum', () => {
5
+ expect(addressSchema.parse('0x8a45eac0267dd0803fd957723ede10693a076698')).toBe(
6
+ '0x8A45eac0267dD0803Fd957723EdE10693A076698'
7
+ );
6
8
  });
7
9
 
8
10
  it('throws for an invalid address', () => {
@@ -10,14 +12,70 @@ describe('schema', () => {
10
12
  expect.objectContaining({ name: 'ZodError' })
11
13
  );
12
14
  });
15
+ });
13
16
 
17
+ describe('keccak256HashSchema', () => {
14
18
  it('validates a valid ID', () => {
15
- expect(() => idSchema.parse('0x3528e42b017a5fbf9d2993a2df04efc3ed474357575065a111b054ddf9de2acc')).not.toThrow();
19
+ expect(() =>
20
+ keccak256HashSchema.parse('0x3528e42b017a5fbf9d2993a2df04efc3ed474357575065a111b054ddf9de2acc')
21
+ ).not.toThrow();
16
22
  });
17
23
 
18
24
  it('throws for an invalid ID', () => {
19
- expect(() => idSchema.parse('0xA3528e42b017a5fbf9d2993a2df04efc3ed474357575065a111b054ddf9de2acc')).toThrow(
25
+ expect(() =>
26
+ keccak256HashSchema.parse('0xA3528e42b017a5fbf9d2993a2df04efc3ed474357575065a111b054ddf9de2acc')
27
+ ).toThrow(expect.objectContaining({ name: 'ZodError' }));
28
+ });
29
+ });
30
+
31
+ describe('hexSchema', () => {
32
+ it('validates a valid hex string', () => {
33
+ expect(() => hexSchema.parse('0x3528e42b017a5fbf9d2993a2df04efc3ed474357575065a111b054ddf9de2acc')).not.toThrow();
34
+ });
35
+
36
+ it('throws for an invalid hex string', () => {
37
+ expect(() => hexSchema.parse('3528e42b017a5fbf9d2993a2df04efc3ed474357575065a111b054ddf9de2acc')).toThrow(
20
38
  expect.objectContaining({ name: 'ZodError' })
21
39
  );
22
40
  });
23
41
  });
42
+
43
+ describe('chainIdSchema', () => {
44
+ it('validates a valid chain ID', () => {
45
+ expect(() => chainIdSchema.parse('1')).not.toThrow();
46
+ });
47
+
48
+ it('throws for an invalid chain ID', () => {
49
+ expect(() => chainIdSchema.parse('0')).toThrow(expect.objectContaining({ name: 'ZodError' }));
50
+ });
51
+ });
52
+
53
+ describe('ethUnitsSchema', () => {
54
+ it('validates a valid unit', () => {
55
+ expect(() => ethUnitsSchema.parse('wei')).not.toThrow();
56
+ expect(() => ethUnitsSchema.parse('kwei')).not.toThrow();
57
+ expect(() => ethUnitsSchema.parse('mwei')).not.toThrow();
58
+ expect(() => ethUnitsSchema.parse('gwei')).not.toThrow();
59
+ expect(() => ethUnitsSchema.parse('szabo')).not.toThrow();
60
+ expect(() => ethUnitsSchema.parse('finney')).not.toThrow();
61
+ expect(() => ethUnitsSchema.parse('ether')).not.toThrow();
62
+ });
63
+
64
+ it('throws for an invalid unit', () => {
65
+ expect(() => ethUnitsSchema.parse('wei2')).toThrow(expect.objectContaining({ name: 'ZodError' }));
66
+ });
67
+ });
68
+
69
+ describe('mnemonicSchema', () => {
70
+ it('validates a valid mnemonic', () => {
71
+ expect(() =>
72
+ mnemonicSchema.parse('destroy manual orange pole pioneer enemy detail lady cake bus shed visa')
73
+ ).not.toThrow();
74
+ });
75
+
76
+ it('throws for an invalid mnemonic', () => {
77
+ expect(() =>
78
+ mnemonicSchema.parse('destroy manual orange pole pioneer enemy detail lady cake bus shed WTF')
79
+ ).toThrow(expect.objectContaining({ name: 'ZodError' }));
80
+ });
81
+ });
@@ -1,14 +1,51 @@
1
+ import { goSync } from '@api3/promise-utils';
2
+ import { ethers } from 'ethers';
1
3
  import { z } from 'zod';
2
4
 
3
- /**
4
- * A Zod validation schema that represents an EVM-compatible address.
5
- */
6
- export const addressSchema = z.string().regex(/^0x[\dA-Fa-f]{40}$/, 'Must be a valid EVM address');
5
+ export const hexSchema = z.string().regex(/^0x[\dA-Fa-f]+$/, 'Must be a valid hex string');
7
6
 
8
- /**
9
- * A Zod validation schema that represents an EVM-compatible hash, which includes beacon IDs and template IDs.
10
- */
11
- export const idSchema = z.string().regex(/^0x[\dA-Fa-f]{64}$/, 'Must be a valid EVM hash');
7
+ export type Hex = `0x${string}`; // Not using z.infer<typeof hexSchema> because the inferred type is just `string`.
8
+
9
+ export const addressSchema = z.string().transform((value, ctx) => {
10
+ const goParseAddress = goSync(() => ethers.utils.getAddress(value));
11
+ if (!goParseAddress.success) {
12
+ ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'Invalid EVM address' });
13
+ return z.NEVER;
14
+ }
15
+
16
+ return goParseAddress.data as Hex;
17
+ });
12
18
 
13
19
  export type Address = z.infer<typeof addressSchema>;
14
- export type Id = z.infer<typeof idSchema>;
20
+
21
+ export const keccak256HashSchema = z
22
+ .string()
23
+ .regex(/^0x[\dA-Fa-f]{64}$/, 'Must be a valid EVM keccak256 hash')
24
+ .transform((val) => val as Hex);
25
+
26
+ export type Keccak256Hash = z.infer<typeof keccak256HashSchema>;
27
+
28
+ export const chainIdSchema = z
29
+ .string()
30
+ .regex(/^\d+$/, 'Must be a valid chain ID')
31
+ .refine((chainId) => Number(chainId) > 0, 'Chain ID must be greater than 0');
32
+
33
+ export type ChainId = z.infer<typeof chainIdSchema>;
34
+
35
+ export const ethUnitsSchema = z.union([
36
+ z.literal('wei'),
37
+ z.literal('kwei'),
38
+ z.literal('mwei'),
39
+ z.literal('gwei'),
40
+ z.literal('szabo'),
41
+ z.literal('finney'),
42
+ z.literal('ether'),
43
+ ]);
44
+
45
+ export type EthUnits = z.infer<typeof ethUnitsSchema>;
46
+
47
+ export const mnemonicSchema = z
48
+ .string()
49
+ .refine((mnemonic) => ethers.utils.isValidMnemonic(mnemonic), 'Invalid mnemonic');
50
+
51
+ export type Mnemonic = z.infer<typeof mnemonicSchema>;
@@ -11,12 +11,9 @@ describe(extractAxiosErrorData.name, () => {
11
11
  } as any as AxiosResponse);
12
12
 
13
13
  expect(extractAxiosErrorData(axiosError)).toStrictEqual({
14
- axiosResponse: {
15
- data: 'error data',
16
- status: 500,
17
- },
18
- code: '500',
14
+ response: 'error data',
19
15
  message: 'error message',
16
+ code: '500',
20
17
  });
21
18
  });
22
19
  });
@@ -33,10 +30,11 @@ describe(executeRequest.name, () => {
33
30
  expect(response).toStrictEqual({
34
31
  data: undefined,
35
32
  errorData: {
36
- axiosResponse: undefined,
33
+ response: undefined,
37
34
  code: 'ECONNREFUSED',
38
35
  message: expect.any(String), // The message is empty in node@20, but "connect ECONNREFUSED ::1:9999" on node@18
39
36
  },
37
+ statusCode: undefined,
40
38
  success: false,
41
39
  });
42
40
  });
package/src/http/index.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { go } from '@api3/promise-utils';
2
2
  import axios, { type Method, type AxiosError, type AxiosResponse } from 'axios';
3
- import pick from 'lodash/pick';
4
3
 
5
4
  const DEFAULT_TIMEOUT_MS = 10_000;
6
5
 
@@ -14,7 +13,7 @@ export interface Request {
14
13
  }
15
14
 
16
15
  export interface ErrorResponse {
17
- readonly axiosResponse: Pick<AxiosResponse, 'data' | 'headers' | 'status'> | undefined;
16
+ readonly response: unknown;
18
17
  readonly message: string;
19
18
  readonly code: string | undefined;
20
19
  }
@@ -22,21 +21,23 @@ export interface ErrorResponse {
22
21
  export const extractAxiosErrorData = (error: AxiosError): ErrorResponse => {
23
22
  // Inspired by: https://axios-http.com/docs/handling_errors
24
23
  return {
25
- axiosResponse: error.response ? pick(error.response, ['data', 'status']) : undefined,
24
+ response: error.response?.data,
26
25
  message: error.message,
27
26
  code: error.code,
28
- } as ErrorResponse;
27
+ };
29
28
  };
30
29
 
31
30
  interface ExecuteRequestSuccess<T> {
32
31
  success: true;
33
32
  errorData: undefined;
34
33
  data: T;
34
+ statusCode: number;
35
35
  }
36
36
  interface ExecuteRequestError {
37
37
  success: false;
38
38
  errorData: ErrorResponse;
39
39
  data: undefined;
40
+ statusCode: number | undefined;
40
41
  }
41
42
 
42
43
  export type ExecuteRequestResult<T> = ExecuteRequestError | ExecuteRequestSuccess<T>;
@@ -54,8 +55,15 @@ export async function executeRequest<T>(request: Request): Promise<ExecuteReques
54
55
  timeout,
55
56
  })
56
57
  );
57
- if (!goAxios.success) return { success: false, errorData: extractAxiosErrorData(goAxios.error), data: undefined };
58
+ if (!goAxios.success) {
59
+ return {
60
+ success: false,
61
+ errorData: extractAxiosErrorData(goAxios.error),
62
+ data: undefined,
63
+ statusCode: goAxios.error.status,
64
+ };
65
+ }
58
66
  const response = goAxios.data;
59
67
 
60
- return { success: true, errorData: undefined, data: response.data };
68
+ return { success: true, errorData: undefined, data: response.data, statusCode: response.status };
61
69
  }
@@ -1,2 +1,3 @@
1
1
  // NOTE: Only export modules which work in both Node.js and browser environments.
2
2
  export * from './blockchain-utilities';
3
+ export * from './http';