@rhinestone/shared-configs 1.7.15 → 1.7.17
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.
- package/dist/configs/chains.json +27 -1
- package/dist/scripts/__tests__/validation.test.js +132 -10
- package/dist/scripts/generate.js +25 -5
- package/dist/scripts/validation.d.ts +32 -2
- package/dist/scripts/validation.d.ts.map +1 -1
- package/dist/scripts/validation.js +269 -1
- package/dist/src/__tests__/chainFactsClient.test.d.ts +2 -0
- package/dist/src/__tests__/chainFactsClient.test.d.ts.map +1 -0
- package/dist/src/__tests__/chainFactsClient.test.js +460 -0
- package/dist/src/chainFactsClient.d.ts +57 -0
- package/dist/src/chainFactsClient.d.ts.map +1 -0
- package/dist/src/chainFactsClient.js +295 -0
- package/dist/src/chains.d.ts +3 -1
- package/dist/src/chains.d.ts.map +1 -1
- package/dist/src/chains.js +27 -1
- package/dist/src/generated/abis.d.ts +4 -0
- package/dist/src/generated/abis.d.ts.map +1 -1
- package/dist/src/generated/abis.js +82 -0
- package/dist/src/generated/chainFactsKey.d.ts +5 -0
- package/dist/src/generated/chainFactsKey.d.ts.map +1 -0
- package/dist/src/generated/chainFactsKey.js +19 -0
- package/dist/src/generated/contracts.d.ts.map +1 -1
- package/dist/src/generated/contracts.dev.d.ts.map +1 -1
- package/dist/src/generated/contracts.dev.js +5 -0
- package/dist/src/generated/contracts.js +5 -0
- package/dist/src/generated/packageVersion.d.ts +3 -0
- package/dist/src/generated/packageVersion.d.ts.map +1 -0
- package/dist/src/generated/packageVersion.js +6 -0
- package/dist/src/index.d.ts +6 -3
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +6 -1
- package/dist/src/types.d.ts +13 -1
- package/dist/src/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/configs/chains.json
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
"decimals": 18,
|
|
7
7
|
"symbol": "ETH"
|
|
8
8
|
},
|
|
9
|
+
"network": "mainnet",
|
|
9
10
|
"settlementLayers": [
|
|
10
11
|
"ACROSS",
|
|
11
12
|
"ECO",
|
|
@@ -72,6 +73,7 @@
|
|
|
72
73
|
"decimals": 18,
|
|
73
74
|
"symbol": "ETH"
|
|
74
75
|
},
|
|
76
|
+
"network": "mainnet",
|
|
75
77
|
"settlementLayers": [
|
|
76
78
|
"ACROSS",
|
|
77
79
|
"ECO",
|
|
@@ -146,6 +148,7 @@
|
|
|
146
148
|
"decimals": 18,
|
|
147
149
|
"symbol": "BNB"
|
|
148
150
|
},
|
|
151
|
+
"network": "mainnet",
|
|
149
152
|
"settlementLayers": [
|
|
150
153
|
"ACROSS",
|
|
151
154
|
"ECO",
|
|
@@ -200,6 +203,7 @@
|
|
|
200
203
|
"decimals": 18,
|
|
201
204
|
"symbol": "XDAI"
|
|
202
205
|
},
|
|
206
|
+
"network": "mainnet",
|
|
203
207
|
"settlementLayers": [
|
|
204
208
|
"RELAY",
|
|
205
209
|
"NEAR",
|
|
@@ -233,6 +237,7 @@
|
|
|
233
237
|
"decimals": 18,
|
|
234
238
|
"symbol": "ETH"
|
|
235
239
|
},
|
|
240
|
+
"network": "mainnet",
|
|
236
241
|
"settlementLayers": [
|
|
237
242
|
"ACROSS",
|
|
238
243
|
"ECO",
|
|
@@ -298,6 +303,7 @@
|
|
|
298
303
|
"decimals": 18,
|
|
299
304
|
"symbol": "POL"
|
|
300
305
|
},
|
|
306
|
+
"network": "mainnet",
|
|
301
307
|
"settlementLayers": [
|
|
302
308
|
"ACROSS",
|
|
303
309
|
"ECO",
|
|
@@ -356,6 +362,7 @@
|
|
|
356
362
|
"decimals": 18,
|
|
357
363
|
"symbol": "MON"
|
|
358
364
|
},
|
|
365
|
+
"network": "mainnet",
|
|
359
366
|
"settlementLayers": [
|
|
360
367
|
"ACROSS",
|
|
361
368
|
"RELAY",
|
|
@@ -411,6 +418,7 @@
|
|
|
411
418
|
"decimals": 18,
|
|
412
419
|
"symbol": "S"
|
|
413
420
|
},
|
|
421
|
+
"network": "mainnet",
|
|
414
422
|
"settlementLayers": [
|
|
415
423
|
"ECO",
|
|
416
424
|
"RELAY",
|
|
@@ -447,6 +455,7 @@
|
|
|
447
455
|
"decimals": 18,
|
|
448
456
|
"symbol": "HYPE"
|
|
449
457
|
},
|
|
458
|
+
"network": "mainnet",
|
|
450
459
|
"settlementLayers": [
|
|
451
460
|
"ACROSS",
|
|
452
461
|
"ECO",
|
|
@@ -490,6 +499,7 @@
|
|
|
490
499
|
"decimals": 18,
|
|
491
500
|
"symbol": "HYPE"
|
|
492
501
|
},
|
|
502
|
+
"network": "mainnet",
|
|
493
503
|
"settlementLayers": [],
|
|
494
504
|
"swapQuoters": [],
|
|
495
505
|
"tokens": [
|
|
@@ -517,6 +527,7 @@
|
|
|
517
527
|
"decimals": 18,
|
|
518
528
|
"symbol": "ETH"
|
|
519
529
|
},
|
|
530
|
+
"network": "mainnet",
|
|
520
531
|
"settlementLayers": [
|
|
521
532
|
"ACROSS",
|
|
522
533
|
"RELAY"
|
|
@@ -571,6 +582,7 @@
|
|
|
571
582
|
"decimals": 18,
|
|
572
583
|
"symbol": "ETH"
|
|
573
584
|
},
|
|
585
|
+
"network": "mainnet",
|
|
574
586
|
"settlementLayers": [
|
|
575
587
|
"ACROSS",
|
|
576
588
|
"RELAY"
|
|
@@ -620,6 +632,7 @@
|
|
|
620
632
|
"decimals": 18,
|
|
621
633
|
"symbol": "ETH"
|
|
622
634
|
},
|
|
635
|
+
"network": "mainnet",
|
|
623
636
|
"settlementLayers": [
|
|
624
637
|
"ACROSS",
|
|
625
638
|
"ECO",
|
|
@@ -675,6 +688,7 @@
|
|
|
675
688
|
"decimals": 18,
|
|
676
689
|
"symbol": "XPL"
|
|
677
690
|
},
|
|
691
|
+
"network": "mainnet",
|
|
678
692
|
"settlementLayers": [
|
|
679
693
|
"ACROSS",
|
|
680
694
|
"ECO",
|
|
@@ -684,7 +698,8 @@
|
|
|
684
698
|
],
|
|
685
699
|
"swapQuoterConfig": {},
|
|
686
700
|
"swapQuoters": [
|
|
687
|
-
"0x"
|
|
701
|
+
"0x",
|
|
702
|
+
"fynd"
|
|
688
703
|
],
|
|
689
704
|
"tokens": [
|
|
690
705
|
{
|
|
@@ -711,6 +726,7 @@
|
|
|
711
726
|
"decimals": 18,
|
|
712
727
|
"symbol": "XPL"
|
|
713
728
|
},
|
|
729
|
+
"network": "testnet",
|
|
714
730
|
"settlementLayers": [
|
|
715
731
|
"ECO"
|
|
716
732
|
],
|
|
@@ -748,6 +764,7 @@
|
|
|
748
764
|
"decimals": 18,
|
|
749
765
|
"symbol": "ETH"
|
|
750
766
|
},
|
|
767
|
+
"network": "mainnet",
|
|
751
768
|
"settlementLayers": [
|
|
752
769
|
"ACROSS",
|
|
753
770
|
"ECO",
|
|
@@ -814,7 +831,9 @@
|
|
|
814
831
|
"decimals": 18,
|
|
815
832
|
"symbol": "AVAX"
|
|
816
833
|
},
|
|
834
|
+
"network": "mainnet",
|
|
817
835
|
"settlementLayers": [
|
|
836
|
+
"ACROSS",
|
|
818
837
|
"RELAY",
|
|
819
838
|
"NEAR",
|
|
820
839
|
"RHINO",
|
|
@@ -882,6 +901,7 @@
|
|
|
882
901
|
"decimals": 18,
|
|
883
902
|
"symbol": "ETH"
|
|
884
903
|
},
|
|
904
|
+
"network": "testnet",
|
|
885
905
|
"settlementLayers": [
|
|
886
906
|
"ACROSS",
|
|
887
907
|
"ECO",
|
|
@@ -939,6 +959,7 @@
|
|
|
939
959
|
"decimals": 18,
|
|
940
960
|
"symbol": "ETH"
|
|
941
961
|
},
|
|
962
|
+
"network": "testnet",
|
|
942
963
|
"settlementLayers": [
|
|
943
964
|
"ACROSS",
|
|
944
965
|
"ECO",
|
|
@@ -986,6 +1007,7 @@
|
|
|
986
1007
|
"decimals": 18,
|
|
987
1008
|
"symbol": "ETH"
|
|
988
1009
|
},
|
|
1010
|
+
"network": "mainnet",
|
|
989
1011
|
"settlementLayers": [
|
|
990
1012
|
"RELAY",
|
|
991
1013
|
"RHINO"
|
|
@@ -1042,6 +1064,7 @@
|
|
|
1042
1064
|
"decimals": 18,
|
|
1043
1065
|
"symbol": "ETH"
|
|
1044
1066
|
},
|
|
1067
|
+
"network": "testnet",
|
|
1045
1068
|
"settlementLayers": [
|
|
1046
1069
|
"ACROSS",
|
|
1047
1070
|
"ECO",
|
|
@@ -1089,6 +1112,7 @@
|
|
|
1089
1112
|
"decimals": 18,
|
|
1090
1113
|
"symbol": "ETH"
|
|
1091
1114
|
},
|
|
1115
|
+
"network": "testnet",
|
|
1092
1116
|
"settlementLayers": [
|
|
1093
1117
|
"ACROSS",
|
|
1094
1118
|
"ECO",
|
|
@@ -1137,6 +1161,7 @@
|
|
|
1137
1161
|
"decimals": 6,
|
|
1138
1162
|
"symbol": "TRX"
|
|
1139
1163
|
},
|
|
1164
|
+
"network": "mainnet",
|
|
1140
1165
|
"settlementLayers": [
|
|
1141
1166
|
"RELAY",
|
|
1142
1167
|
"OFT",
|
|
@@ -1176,6 +1201,7 @@
|
|
|
1176
1201
|
"decimals": 9,
|
|
1177
1202
|
"symbol": "SOL"
|
|
1178
1203
|
},
|
|
1204
|
+
"network": "mainnet",
|
|
1179
1205
|
"settlementLayers": [
|
|
1180
1206
|
"RELAY",
|
|
1181
1207
|
"OFT",
|
|
@@ -2,18 +2,74 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const bun_test_1 = require("bun:test");
|
|
4
4
|
const validation_1 = require("../validation");
|
|
5
|
-
|
|
5
|
+
const index_1 = require("../../src/index");
|
|
6
|
+
const nativeToken = { address: "0x0", symbol: "ETH", decimals: 18 };
|
|
7
|
+
/** A structurally complete entry, so semantic tests don't trip structural checks. */
|
|
8
|
+
function validChain(overrides = {}) {
|
|
9
|
+
return {
|
|
10
|
+
name: "Ethereum",
|
|
11
|
+
vmType: "evm",
|
|
12
|
+
network: "mainnet",
|
|
13
|
+
nativeToken,
|
|
14
|
+
wrappedNativeToken: { ...nativeToken, symbol: "WETH" },
|
|
15
|
+
tokens: [{ ...nativeToken, balanceSlot: null, approvalSlot: null }],
|
|
16
|
+
settlementLayers: ["ACROSS", "ECO", "RELAY"],
|
|
17
|
+
swapQuoters: ["0x"],
|
|
18
|
+
...overrides,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function errorsFor(chain) {
|
|
22
|
+
return (0, validation_1.validateChainConfig)({ "1": chain }).issues.filter((i) => i.severity === "error");
|
|
23
|
+
}
|
|
24
|
+
(0, bun_test_1.describe)("validateChainConfig — structure", () => {
|
|
25
|
+
// The real generated registry is the thing this actually has to accept; if
|
|
26
|
+
// the checks drift stricter than the generator, the build breaks on good data.
|
|
27
|
+
(0, bun_test_1.it)("accepts the real generated chain registry", () => {
|
|
28
|
+
const result = (0, validation_1.validateChainConfig)(index_1.chainRegistry);
|
|
29
|
+
const errors = result.issues.filter((i) => i.severity === "error");
|
|
30
|
+
(0, bun_test_1.expect)(errors).toEqual([]);
|
|
31
|
+
(0, bun_test_1.expect)(result.hasErrors).toBe(false);
|
|
32
|
+
});
|
|
33
|
+
(0, bun_test_1.it)("rejects a key that is not a canonical chain id", () => {
|
|
34
|
+
const result = (0, validation_1.validateChainConfig)({ "01": validChain() });
|
|
35
|
+
(0, bun_test_1.expect)(result.hasErrors).toBe(true);
|
|
36
|
+
(0, bun_test_1.expect)(result.issues[0].message).toContain("canonical chain id");
|
|
37
|
+
});
|
|
38
|
+
bun_test_1.it.each([
|
|
39
|
+
["a missing name", { name: undefined }],
|
|
40
|
+
["an unknown vmType", { vmType: "wasm" }],
|
|
41
|
+
["a non-object nativeToken", { nativeToken: "0x0" }],
|
|
42
|
+
["a nativeToken missing decimals", { nativeToken: { address: "0x0", symbol: "ETH" } }],
|
|
43
|
+
["tokens not an array", { tokens: {} }],
|
|
44
|
+
["a token missing its slots", { tokens: [nativeToken] }],
|
|
45
|
+
["a token with a bad pegGroup", {
|
|
46
|
+
tokens: [{ ...nativeToken, balanceSlot: null, approvalSlot: null, pegGroup: "GBP" }],
|
|
47
|
+
}],
|
|
48
|
+
["an unknown settlement layer", { settlementLayers: ["ACROSS", "TELEPORT"] }],
|
|
49
|
+
["an unknown swap quoter", { swapQuoters: ["mystery-dex"] }],
|
|
50
|
+
["a malformed swapQuoterConfig", { swapQuoterConfig: { "0x": { slug: 5 } } }],
|
|
51
|
+
["a swapQuoterConfig for an unknown quoter", { swapQuoterConfig: { nope: {} } }],
|
|
52
|
+
["a non-boolean virtual flag", { virtual: "true" }],
|
|
53
|
+
["a missing network", { network: undefined }],
|
|
54
|
+
["an unknown network", { network: "devnet" }],
|
|
55
|
+
])("rejects %s", (_label, overrides) => {
|
|
56
|
+
(0, bun_test_1.expect)(errorsFor(validChain(overrides)).length).toBeGreaterThan(0);
|
|
57
|
+
});
|
|
58
|
+
(0, bun_test_1.it)("names the offending value so the build failure is actionable", () => {
|
|
59
|
+
const [error] = errorsFor(validChain({ settlementLayers: ["TELEPORT"] }));
|
|
60
|
+
(0, bun_test_1.expect)(error.message).toContain("TELEPORT");
|
|
61
|
+
(0, bun_test_1.expect)(error.message).toContain("src/types.ts");
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
(0, bun_test_1.describe)("validateChainConfig — reachability", () => {
|
|
6
65
|
(0, bun_test_1.it)("returns no issues for chains with multiple settlement layers", () => {
|
|
7
|
-
const
|
|
8
|
-
"1": { name: "Ethereum", settlementLayers: ["ACROSS", "ECO", "RELAY"], tokens: [] },
|
|
9
|
-
};
|
|
10
|
-
const result = (0, validation_1.validateChainConfig)(chains);
|
|
66
|
+
const result = (0, validation_1.validateChainConfig)({ "1": validChain() });
|
|
11
67
|
(0, bun_test_1.expect)(result.issues).toHaveLength(0);
|
|
12
68
|
(0, bun_test_1.expect)(result.hasErrors).toBe(false);
|
|
13
69
|
});
|
|
14
70
|
(0, bun_test_1.it)("returns error for chain with zero settlement layers", () => {
|
|
15
71
|
const chains = {
|
|
16
|
-
"100": { name: "Gnosis", settlementLayers: []
|
|
72
|
+
"100": validChain({ name: "Gnosis", settlementLayers: [] }),
|
|
17
73
|
};
|
|
18
74
|
const result = (0, validation_1.validateChainConfig)(chains);
|
|
19
75
|
(0, bun_test_1.expect)(result.issues).toHaveLength(1);
|
|
@@ -24,7 +80,7 @@ const validation_1 = require("../validation");
|
|
|
24
80
|
});
|
|
25
81
|
(0, bun_test_1.it)("returns warning for chain with single settlement layer", () => {
|
|
26
82
|
const chains = {
|
|
27
|
-
"100": { name: "Gnosis", settlementLayers: ["RELAY"]
|
|
83
|
+
"100": validChain({ name: "Gnosis", settlementLayers: ["RELAY"] }),
|
|
28
84
|
};
|
|
29
85
|
const result = (0, validation_1.validateChainConfig)(chains);
|
|
30
86
|
(0, bun_test_1.expect)(result.issues).toHaveLength(1);
|
|
@@ -32,11 +88,18 @@ const validation_1 = require("../validation");
|
|
|
32
88
|
(0, bun_test_1.expect)(result.issues[0].message).toContain("RELAY");
|
|
33
89
|
(0, bun_test_1.expect)(result.hasErrors).toBe(false);
|
|
34
90
|
});
|
|
91
|
+
(0, bun_test_1.it)("skips the reachability check for virtual chains", () => {
|
|
92
|
+
const chains = {
|
|
93
|
+
"1337": validChain({ name: "HyperCore", virtual: true, settlementLayers: [] }),
|
|
94
|
+
};
|
|
95
|
+
const result = (0, validation_1.validateChainConfig)(chains);
|
|
96
|
+
(0, bun_test_1.expect)(result.issues).toHaveLength(0);
|
|
97
|
+
});
|
|
35
98
|
(0, bun_test_1.it)("handles mixed chains correctly", () => {
|
|
36
99
|
const chains = {
|
|
37
|
-
"1":
|
|
38
|
-
"100": { name: "Gnosis", settlementLayers: ["RELAY"]
|
|
39
|
-
"999": { name: "Broken", settlementLayers: []
|
|
100
|
+
"1": validChain(),
|
|
101
|
+
"100": validChain({ name: "Gnosis", settlementLayers: ["RELAY"] }),
|
|
102
|
+
"999": validChain({ name: "Broken", settlementLayers: [] }),
|
|
40
103
|
};
|
|
41
104
|
const result = (0, validation_1.validateChainConfig)(chains);
|
|
42
105
|
(0, bun_test_1.expect)(result.issues).toHaveLength(2);
|
|
@@ -91,3 +154,62 @@ const validation_1 = require("../validation");
|
|
|
91
154
|
(0, bun_test_1.expect)(output).toContain("Gnosis (100)");
|
|
92
155
|
});
|
|
93
156
|
});
|
|
157
|
+
(0, bun_test_1.describe)("classifyChainNetworks", () => {
|
|
158
|
+
const providers = { providers: ["DRPC"] };
|
|
159
|
+
(0, bun_test_1.it)("stamps the network from whichever map holds the chain id", () => {
|
|
160
|
+
const { chains, issues } = (0, validation_1.classifyChainNetworks)({ "1": validChain(), "11155111": validChain({ name: "Sepolia" }) }, { "1": providers }, { "11155111": providers });
|
|
161
|
+
(0, bun_test_1.expect)(chains["1"].network).toBe("mainnet");
|
|
162
|
+
(0, bun_test_1.expect)(chains["11155111"].network).toBe("testnet");
|
|
163
|
+
(0, bun_test_1.expect)(issues).toEqual([]);
|
|
164
|
+
});
|
|
165
|
+
(0, bun_test_1.it)("overwrites any network the jsonnet happens to carry, so the maps stay the one source", () => {
|
|
166
|
+
const { chains } = (0, validation_1.classifyChainNetworks)({ "1": validChain({ network: "testnet" }) }, { "1": providers }, {});
|
|
167
|
+
(0, bun_test_1.expect)(chains["1"].network).toBe("mainnet");
|
|
168
|
+
});
|
|
169
|
+
// The silent-miss case this guard exists for: an unclassified chain would
|
|
170
|
+
// otherwise reach the signed artifact with no way for a consumer to place it.
|
|
171
|
+
(0, bun_test_1.it)("errors when a chain is in neither network map", () => {
|
|
172
|
+
const { chains, issues } = (0, validation_1.classifyChainNetworks)({ "1": validChain() }, {}, {});
|
|
173
|
+
(0, bun_test_1.expect)(issues).toHaveLength(1);
|
|
174
|
+
(0, bun_test_1.expect)(issues[0].severity).toBe("error");
|
|
175
|
+
(0, bun_test_1.expect)(issues[0].chainId).toBe("1");
|
|
176
|
+
(0, bun_test_1.expect)(issues[0].message).toContain("neither");
|
|
177
|
+
(0, bun_test_1.expect)(chains["1"].network).toBeUndefined();
|
|
178
|
+
});
|
|
179
|
+
(0, bun_test_1.it)("errors when a chain is in both network maps", () => {
|
|
180
|
+
const { issues } = (0, validation_1.classifyChainNetworks)({ "1": validChain() }, { "1": providers }, { "1": providers });
|
|
181
|
+
(0, bun_test_1.expect)(issues).toHaveLength(1);
|
|
182
|
+
(0, bun_test_1.expect)(issues[0].severity).toBe("error");
|
|
183
|
+
(0, bun_test_1.expect)(issues[0].message).toContain("both");
|
|
184
|
+
});
|
|
185
|
+
(0, bun_test_1.it)("warns when a network map lists a chain the registry does not define", () => {
|
|
186
|
+
const { issues } = (0, validation_1.classifyChainNetworks)({ "1": validChain() }, { "1": providers, "999999": providers }, {});
|
|
187
|
+
(0, bun_test_1.expect)(issues).toHaveLength(1);
|
|
188
|
+
(0, bun_test_1.expect)(issues[0].severity).toBe("warning");
|
|
189
|
+
(0, bun_test_1.expect)(issues[0].chainId).toBe("999999");
|
|
190
|
+
(0, bun_test_1.expect)(issues[0].message).toContain("absent from the chain registry");
|
|
191
|
+
});
|
|
192
|
+
// The artifact is signed over these exact bytes, so the serialisation has to
|
|
193
|
+
// stay canonical rather than depending on where the field was spliced in.
|
|
194
|
+
(0, bun_test_1.it)("keeps entry keys sorted so the generated JSON stays canonical", () => {
|
|
195
|
+
const { chains } = (0, validation_1.classifyChainNetworks)({ "1": validChain() }, { "1": providers }, {});
|
|
196
|
+
const keys = Object.keys(chains["1"]);
|
|
197
|
+
(0, bun_test_1.expect)(keys).toEqual([...keys].sort());
|
|
198
|
+
(0, bun_test_1.expect)(keys).toContain("network");
|
|
199
|
+
});
|
|
200
|
+
(0, bun_test_1.it)("classifies the real registry with no issues", () => {
|
|
201
|
+
// Round-trips the shipped registry through its own maps: every real chain
|
|
202
|
+
// must land in exactly one, which is what makes the field derivable at all.
|
|
203
|
+
const mainnets = Object.fromEntries(Object.entries(index_1.chainRegistry)
|
|
204
|
+
.filter(([, c]) => c.network === "mainnet")
|
|
205
|
+
.map(([id]) => [id, providers]));
|
|
206
|
+
const testnets = Object.fromEntries(Object.entries(index_1.chainRegistry)
|
|
207
|
+
.filter(([, c]) => c.network === "testnet")
|
|
208
|
+
.map(([id]) => [id, providers]));
|
|
209
|
+
const { chains, issues } = (0, validation_1.classifyChainNetworks)(index_1.chainRegistry, mainnets, testnets);
|
|
210
|
+
(0, bun_test_1.expect)(issues).toEqual([]);
|
|
211
|
+
(0, bun_test_1.expect)(Object.keys(mainnets).length).toBeGreaterThan(0);
|
|
212
|
+
(0, bun_test_1.expect)(Object.keys(testnets).length).toBeGreaterThan(0);
|
|
213
|
+
(0, bun_test_1.expect)(Object.keys(chains)).toHaveLength(Object.keys(index_1.chainRegistry).length);
|
|
214
|
+
});
|
|
215
|
+
});
|
package/dist/scripts/generate.js
CHANGED
|
@@ -88,7 +88,7 @@ function renderChains(chainRegistry, mainnets, testnets) {
|
|
|
88
88
|
}
|
|
89
89
|
return [
|
|
90
90
|
"// Auto-generated by scripts/generate.ts. Do not edit manually.",
|
|
91
|
-
'import type { PegGroup, ProviderName, SettlementLayer, SupportedChain, SwapQuoter, SwapQuoterConfig, VmType } from "./types";',
|
|
91
|
+
'import type { ChainNetwork, PegGroup, ProviderName, SettlementLayer, SupportedChain, SwapQuoter, SwapQuoterConfig, VmType } from "./types";',
|
|
92
92
|
"",
|
|
93
93
|
"interface Token {",
|
|
94
94
|
" /** EVM: 0x-prefixed hex. SVM: base58 SPL mint. TVM: base58 (T-prefixed). */",
|
|
@@ -112,6 +112,8 @@ function renderChains(chainRegistry, mainnets, testnets) {
|
|
|
112
112
|
"interface Chain {",
|
|
113
113
|
" name: string;",
|
|
114
114
|
" vmType: VmType;",
|
|
115
|
+
" /** Whether this chain is a mainnet or a testnet. */",
|
|
116
|
+
" network: ChainNetwork;",
|
|
115
117
|
" /** CAIP-2 chain identifier; populated for non-eip155 chains only. */",
|
|
116
118
|
" caip2?: string;",
|
|
117
119
|
" /** True for virtual chains (e.g. HyperCore) that settle on another chain. */",
|
|
@@ -354,14 +356,26 @@ async function generate() {
|
|
|
354
356
|
const output = runJsonnet(yeetRoot);
|
|
355
357
|
await (0, promises_1.mkdir)(configsDir, { recursive: true });
|
|
356
358
|
await (0, promises_1.mkdir)(generatedDir, { recursive: true });
|
|
357
|
-
|
|
359
|
+
// Stamp mainnet/testnet onto each entry before anything is written, so the
|
|
360
|
+
// registry that reaches configs/chains.json — and from there the published
|
|
361
|
+
// facts artifact and the read-client's bundled fallback — carries the
|
|
362
|
+
// classification rather than leaving it implicit in the network maps.
|
|
363
|
+
const { chains: classifiedChains, issues: classificationIssues } = (0, validation_1.classifyChainNetworks)(output.chains, output.mainnets, output.testnets);
|
|
364
|
+
await (0, promises_1.writeFile)(node_path_1.default.join(configsDir, "chains.json"), `${JSON.stringify(classifiedChains, null, 2)}\n`);
|
|
358
365
|
await (0, promises_1.writeFile)(node_path_1.default.join(configsDir, "mainnets.json"), `${JSON.stringify(output.mainnets, null, 2)}\n`);
|
|
359
366
|
await (0, promises_1.writeFile)(node_path_1.default.join(configsDir, "testnets.json"), `${JSON.stringify(output.testnets, null, 2)}\n`);
|
|
360
367
|
await (0, promises_1.writeFile)(node_path_1.default.join(configsDir, "providers.json"), `${JSON.stringify(output.providers, null, 2)}\n`);
|
|
361
368
|
await (0, promises_1.writeFile)(node_path_1.default.join(configsDir, "oft.json"), `${JSON.stringify(output.oft, null, 2)}\n`);
|
|
362
369
|
await (0, promises_1.writeFile)(node_path_1.default.join(configsDir, "oft-programs.json"), `${JSON.stringify(output.oftProgramIds ?? {}, null, 2)}\n`);
|
|
363
|
-
// Validate chain configuration
|
|
364
|
-
|
|
370
|
+
// Validate chain configuration. Classification problems are reported in the
|
|
371
|
+
// same pass so one run surfaces everything wrong with the registry, rather than
|
|
372
|
+
// failing on the partition and hiding the rest.
|
|
373
|
+
const structural = (0, validation_1.validateChainConfig)(classifiedChains);
|
|
374
|
+
const validationResult = {
|
|
375
|
+
issues: [...classificationIssues, ...structural.issues],
|
|
376
|
+
hasErrors: structural.hasErrors ||
|
|
377
|
+
classificationIssues.some((issue) => issue.severity === 'error'),
|
|
378
|
+
};
|
|
365
379
|
const validationOutput = (0, validation_1.formatValidationIssues)(validationResult);
|
|
366
380
|
if (validationOutput) {
|
|
367
381
|
console.log('\nChain config validation:');
|
|
@@ -371,7 +385,13 @@ async function generate() {
|
|
|
371
385
|
if (validationResult.hasErrors) {
|
|
372
386
|
throw new Error('Chain configuration has errors — see above');
|
|
373
387
|
}
|
|
374
|
-
await (0, promises_1.writeFile)(node_path_1.default.join(sharedConfigsRoot, "src", "chains.ts"), `${renderChains(
|
|
388
|
+
await (0, promises_1.writeFile)(node_path_1.default.join(sharedConfigsRoot, "src", "chains.ts"), `${renderChains(classifiedChains, output.mainnets, output.testnets)}\n`);
|
|
389
|
+
// Stamp the package version so the read-client knows how fresh its BUNDLED
|
|
390
|
+
// registry is, and can refuse a remote artifact from an older release. The
|
|
391
|
+
// release workflow bumps package.json before building for exactly this
|
|
392
|
+
// reason — see shared-configs-publish.yml.
|
|
393
|
+
const packageVersion = JSON.parse(await (0, promises_1.readFile)(node_path_1.default.join(sharedConfigsRoot, "package.json"), "utf8")).version;
|
|
394
|
+
await (0, promises_1.writeFile)(node_path_1.default.join(generatedDir, "packageVersion.ts"), `// Auto-generated by scripts/generate.ts. Do not edit manually.\nconst PACKAGE_VERSION = "${packageVersion}";\n\nexport { PACKAGE_VERSION };\n`);
|
|
375
395
|
await (0, promises_1.writeFile)(node_path_1.default.join(generatedDir, "networks.ts"), `${renderNetworks(output.networks)}\n`);
|
|
376
396
|
const prodAddrConfig = runOrchestratorFile(yeetRoot, "prod", output.chainNames);
|
|
377
397
|
const stagingAddrConfig = runOrchestratorFile(yeetRoot, "staging", output.chainNames);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
export type SettlementLayer = 'ACROSS' | 'ECO' | 'RELAY' | 'OFT';
|
|
1
|
+
export type SettlementLayer = 'ACROSS' | 'ECO' | 'RELAY' | 'OFT' | 'NEAR' | 'RHINO' | 'CCTP';
|
|
2
|
+
export type ChainNetwork = 'mainnet' | 'testnet';
|
|
2
3
|
export interface ChainData {
|
|
3
4
|
name: string;
|
|
4
5
|
settlementLayers: SettlementLayer[];
|
|
@@ -6,6 +7,9 @@ export interface ChainData {
|
|
|
6
7
|
symbol: string;
|
|
7
8
|
[key: string]: unknown;
|
|
8
9
|
}>;
|
|
10
|
+
/** Whether this chain is a mainnet or a testnet. Stamped by
|
|
11
|
+
* `classifyChainNetworks`, not authored in the jsonnet. */
|
|
12
|
+
network?: ChainNetwork;
|
|
9
13
|
/** Virtual chains (e.g. HyperCore) settle on another chain and have no
|
|
10
14
|
* direct settlement layers of their own — excluded from reachability checks. */
|
|
11
15
|
virtual?: boolean;
|
|
@@ -24,9 +28,35 @@ export interface ValidationResult {
|
|
|
24
28
|
hasErrors: boolean;
|
|
25
29
|
}
|
|
26
30
|
/**
|
|
27
|
-
*
|
|
31
|
+
* Stamps every chain with its mainnet/testnet classification, derived from which
|
|
32
|
+
* network map its chain id appears in.
|
|
33
|
+
*
|
|
34
|
+
* Why this exists: the split is otherwise implicit in *which file* an id lands in
|
|
35
|
+
* (configs/mainnets.json vs configs/testnets.json). The package surfaces it as
|
|
36
|
+
* `mainnetChains` / `MainnetNetwork`, but configs/chains.json — the registry the
|
|
37
|
+
* facts artifact publishes and the read-client bundles — carried no trace of it.
|
|
38
|
+
* So a consumer reading facts at runtime could not tell which environment a chain
|
|
39
|
+
* belonged to, which is exactly what the orchestrator's mainnet/testnet registry
|
|
40
|
+
* gating keys off: a CDN-added chain would arrive unclassifiable.
|
|
41
|
+
*
|
|
42
|
+
* Derived rather than authored per chain in the jsonnet, so it cannot drift from
|
|
43
|
+
* the membership it describes — "is this a testnet" keeps one source, the network
|
|
44
|
+
* maps.
|
|
45
|
+
*
|
|
46
|
+
* Lives in this module rather than generate.ts because the partition it relies on
|
|
47
|
+
* is a build-time invariant that has to fail the build, and generate.ts runs its
|
|
48
|
+
* generator on import, so nothing declared there is testable.
|
|
49
|
+
*/
|
|
50
|
+
export declare function classifyChainNetworks(chains: ChainRegistry, mainnets: Record<string, unknown>, testnets: Record<string, unknown>): {
|
|
51
|
+
chains: ChainRegistry;
|
|
52
|
+
issues: ValidationIssue[];
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Validates a chain registry for structural and configuration problems.
|
|
28
56
|
*
|
|
29
57
|
* Checks performed:
|
|
58
|
+
* - Structure: chain-id keys, and every field of every entry against the
|
|
59
|
+
* shapes and unions declared in src/types.ts (error)
|
|
30
60
|
* - Orphaned chains: chains with no settlement layers (error)
|
|
31
61
|
* - Single-layer fragility: chains with exactly one settlement layer (warning)
|
|
32
62
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../scripts/validation.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,
|
|
1
|
+
{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../scripts/validation.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GACvB,QAAQ,GACR,KAAK,GACL,OAAO,GACP,KAAK,GACL,MAAM,GACN,OAAO,GACP,MAAM,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC;AAEjD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,MAAM,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,CAAC;IAC1D;+DAC2D;IAC3D,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB;oFACgF;IAChF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAqJD,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAEtD,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;CACpB;AAiBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAChC;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,CAwEtD;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,gBAAgB,CAiE3E;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAWvE"}
|