@rhinestone/shared-configs 1.7.16 → 1.8.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.
@@ -0,0 +1,295 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createChainFactsClient = createChainFactsClient;
7
+ const chains_json_1 = __importDefault(require("../configs/chains.json"));
8
+ const chainFactsKey_1 = require("./generated/chainFactsKey");
9
+ const packageVersion_1 = require("./generated/packageVersion");
10
+ const bundledChainRegistry = chains_json_1.default;
11
+ const DEFAULT_FETCH_TIMEOUT_MS = 5_000;
12
+ const BUNDLED_SNAPSHOT = {
13
+ chains: bundledChainRegistry,
14
+ source: "bundled",
15
+ version: null,
16
+ };
17
+ // Registry keys are chain ids consumers index by directly, so they must be
18
+ // canonical positive integers — no leading zeros, which would let "01" and "1"
19
+ // both address chain 1.
20
+ const CHAIN_ID_KEY = /^[1-9][0-9]*$/;
21
+ function isObject(value) {
22
+ return typeof value === "object" && value !== null && !Array.isArray(value);
23
+ }
24
+ // Enough to tell chain facts from some other JSON that happens to be keyed by
25
+ // chain id (the mainnets/providers blobs are, so a misconfigured URL would
26
+ // otherwise be accepted), and no more.
27
+ //
28
+ // Exhaustive field and enum validation runs once at build time, in yeet's
29
+ // generator (scripts/validation.ts), where the data and the type unions ship in
30
+ // the same version. Repeating it here would be both redundant and wrong: an
31
+ // unknown settlement layer at build time means the unions need updating, but at
32
+ // read time it just means an older consumer is reading a newer artifact, which
33
+ // has to keep working — that's the whole point of the project. Integrity and
34
+ // provenance are the artifact signature's job.
35
+ function looksLikeChainEntry(value) {
36
+ return (isObject(value) &&
37
+ typeof value.name === "string" &&
38
+ Array.isArray(value.tokens));
39
+ }
40
+ function isChainRegistry(value) {
41
+ if (!isObject(value))
42
+ return false;
43
+ const entries = Object.entries(value);
44
+ return (entries.length > 0 &&
45
+ entries.every(([id, entry]) => CHAIN_ID_KEY.test(id) && looksLikeChainEntry(entry)));
46
+ }
47
+ // Both sides are release versions produced by the same pipeline, so a numeric
48
+ // x.y.z comparison is enough; a pre-release suffix (-alpha.N) is ignored, since
49
+ // pre-release tags never publish to the facts CDN.
50
+ //
51
+ // Returns false when either version is unparseable rather than treating it as
52
+ // stale: an odd version string is a pipeline bug to observe, not a reason to
53
+ // stop taking chain updates, and the signature already establishes provenance.
54
+ function isOlderRelease(candidate, baseline) {
55
+ const parse = (v) => {
56
+ const parts = v.split("-")[0].split(".");
57
+ if (parts.length !== 3)
58
+ return null;
59
+ const nums = parts.map((p) => Number(p));
60
+ return nums.every((n) => Number.isInteger(n) && n >= 0) ? nums : null;
61
+ };
62
+ const a = parse(candidate);
63
+ const b = parse(baseline);
64
+ if (!a || !b)
65
+ return false;
66
+ for (let i = 0; i < 3; i += 1) {
67
+ if (a[i] !== b[i])
68
+ return a[i] < b[i];
69
+ }
70
+ return false;
71
+ }
72
+ // ── Signature verification ───────────────────────────────────────────────────
73
+ const P256_COORDINATE_BYTES = 32;
74
+ function base64ToBytes(base64) {
75
+ // atob, not Buffer: available in browsers, Node >= 16, Bun and Deno alike.
76
+ const binary = atob(base64.replace(/\s+/g, ""));
77
+ const bytes = new Uint8Array(binary.length);
78
+ for (let i = 0; i < binary.length; i += 1)
79
+ bytes[i] = binary.charCodeAt(i);
80
+ return bytes;
81
+ }
82
+ /**
83
+ * Converts a DER/ASN.1 ECDSA signature to the fixed-width r‖s form WebCrypto
84
+ * requires.
85
+ *
86
+ * KMS `Sign` with ECDSA_SHA_256 returns DER — `30 <len> 02 <rlen> r 02 <slen> s`,
87
+ * ~70-72 bytes and variable — while `crypto.subtle.verify` expects exactly 64
88
+ * bytes of raw r‖s for P-256. Passing DER through does NOT throw; it just
89
+ * returns false for every signature. So this conversion is the difference
90
+ * between a working verifier and one that silently rejects every legitimate
91
+ * artifact (confirmed empirically before writing it).
92
+ *
93
+ * Each INTEGER is minimally encoded and signed, so r/s may carry a leading 0x00
94
+ * when the high bit is set, or be shorter than 32 bytes when leading zeroes were
95
+ * dropped. Both normalise to a left-padded 32 bytes.
96
+ */
97
+ function derToRawEcdsaSignature(der) {
98
+ let offset = 0;
99
+ const nextByte = () => {
100
+ if (offset >= der.length)
101
+ throw new Error("signature truncated");
102
+ return der[offset++];
103
+ };
104
+ if (nextByte() !== 0x30)
105
+ throw new Error("signature is not a DER SEQUENCE");
106
+ // Sequence length: short form, or long form (0x80 | number-of-length-bytes).
107
+ let sequenceLength = nextByte();
108
+ if (sequenceLength & 0x80) {
109
+ const lengthBytes = sequenceLength & 0x7f;
110
+ sequenceLength = 0;
111
+ for (let i = 0; i < lengthBytes; i += 1) {
112
+ sequenceLength = (sequenceLength << 8) | nextByte();
113
+ }
114
+ }
115
+ if (offset + sequenceLength !== der.length) {
116
+ throw new Error("DER sequence length does not match signature length");
117
+ }
118
+ const readCoordinate = () => {
119
+ if (nextByte() !== 0x02)
120
+ throw new Error("expected a DER INTEGER");
121
+ const length = nextByte();
122
+ if (offset + length > der.length) {
123
+ throw new Error("DER INTEGER overruns the signature");
124
+ }
125
+ let bytes = der.subarray(offset, offset + length);
126
+ offset += length;
127
+ while (bytes.length > 0 && bytes[0] === 0x00)
128
+ bytes = bytes.subarray(1);
129
+ if (bytes.length > P256_COORDINATE_BYTES) {
130
+ throw new Error("DER INTEGER wider than the P-256 coordinate size");
131
+ }
132
+ const padded = new Uint8Array(P256_COORDINATE_BYTES);
133
+ padded.set(bytes, P256_COORDINATE_BYTES - bytes.length);
134
+ return padded;
135
+ };
136
+ const r = readCoordinate();
137
+ const s = readCoordinate();
138
+ const raw = new Uint8Array(P256_COORDINATE_BYTES * 2);
139
+ raw.set(r, 0);
140
+ raw.set(s, P256_COORDINATE_BYTES);
141
+ return raw;
142
+ }
143
+ async function verifyArtifactSignature(publicKeyBase64, signatureBase64, payloadBytes) {
144
+ const key = await crypto.subtle.importKey("spki", base64ToBytes(publicKeyBase64), { name: "ECDSA", namedCurve: "P-256" }, false, ["verify"]);
145
+ return crypto.subtle.verify({ name: "ECDSA", hash: "SHA-256" }, key, derToRawEcdsaSignature(base64ToBytes(signatureBase64)), payloadBytes);
146
+ }
147
+ /**
148
+ * Reads chain facts remote-first, falling back to the registry bundled with
149
+ * this package at publish time. Reads never throw — a failed or malformed
150
+ * fetch leaves the previous tier in place, so callers always get a usable
151
+ * registry. `getSnapshot().source` reports which tier served it, so consumers
152
+ * can alert on having run bundled for longer than expected.
153
+ */
154
+ function createChainFactsClient(options = {}) {
155
+ const { onError } = options;
156
+ // Explicit null means "disable"; omitted (or undefined) means "take the
157
+ // published default". `??` alone cannot express that — it treats null and
158
+ // undefined alike — so null is checked first.
159
+ const remoteUrl = options.remoteUrl === null
160
+ ? null
161
+ : (options.remoteUrl ?? chainFactsKey_1.CHAIN_FACTS_LATEST_URL);
162
+ const publicKey = options.publicKey === null
163
+ ? null
164
+ : (options.publicKey ?? chainFactsKey_1.CHAIN_FACTS_PUBLIC_KEY);
165
+ const fetchTimeoutMs = options.fetchTimeoutMs ?? DEFAULT_FETCH_TIMEOUT_MS;
166
+ let snapshot = BUNDLED_SNAPSHOT;
167
+ // A caller's logging hook must never break the never-throws contract.
168
+ function report(error, phase) {
169
+ try {
170
+ onError?.(error, phase);
171
+ }
172
+ catch (hookError) {
173
+ console.error("[chainFactsClient] onError callback threw", hookError);
174
+ }
175
+ }
176
+ async function fetchRemote() {
177
+ if (!remoteUrl)
178
+ return null;
179
+ if (!publicKey) {
180
+ // Fail closed rather than reading unverified: the payload checks are only
181
+ // structural, so without a key there is nothing establishing that these
182
+ // facts came from the release pipeline.
183
+ report(new Error("remoteUrl is set but publicKey is not — refusing to read chain facts unverified; serving bundled"), "config");
184
+ return null;
185
+ }
186
+ // The timeout must cover the body reads as well as the headers — otherwise a
187
+ // remote that stalls mid-body is unbounded.
188
+ const controller = new AbortController();
189
+ const timeout = setTimeout(() => controller.abort(), fetchTimeoutMs);
190
+ let payloadBytes;
191
+ let signatureBase64;
192
+ try {
193
+ const get = async (url) => {
194
+ const response = await fetch(url, { signal: controller.signal });
195
+ if (!response.ok) {
196
+ throw new Error(`chain facts fetch failed for ${url}: ${response.status} ${response.statusText}`);
197
+ }
198
+ return response;
199
+ };
200
+ // Detached signature, fetched in parallel with the artifact it covers.
201
+ const [payloadResponse, signatureResponse] = await Promise.all([
202
+ get(remoteUrl),
203
+ get(`${remoteUrl}.sig`),
204
+ ]);
205
+ payloadBytes = new Uint8Array(await payloadResponse.arrayBuffer());
206
+ signatureBase64 = await signatureResponse.text();
207
+ }
208
+ catch (error) {
209
+ report(error, "fetch");
210
+ return null;
211
+ }
212
+ finally {
213
+ clearTimeout(timeout);
214
+ }
215
+ // Verify before parsing, over the exact bytes served. Nothing downstream
216
+ // touches the payload until the signature checks out.
217
+ try {
218
+ const verified = await verifyArtifactSignature(publicKey, signatureBase64, payloadBytes);
219
+ if (!verified)
220
+ throw new Error("signature did not verify");
221
+ }
222
+ catch (error) {
223
+ report(error, "verify");
224
+ return null;
225
+ }
226
+ let body;
227
+ try {
228
+ body = JSON.parse(new TextDecoder().decode(payloadBytes));
229
+ }
230
+ catch (error) {
231
+ report(error, "parse");
232
+ return null;
233
+ }
234
+ if (!isObject(body) ||
235
+ typeof body.version !== "string" ||
236
+ !isChainRegistry(body.chains)) {
237
+ report(new Error("chain facts payload has no version or an unusable chains registry"), "parse");
238
+ return null;
239
+ }
240
+ // A signature proves provenance, not freshness: a previous release's
241
+ // artifact stays validly signed forever. So if the CDN publish fails while
242
+ // the npm publish succeeds, a consumer that bumps gets a bundled registry
243
+ // newer than `latest.json` — and a valid remote snapshot would otherwise
244
+ // override it, hiding the change behind a *successful* read.
245
+ //
246
+ // Compared by VERSION, not by chain-id set: an artifact can carry every
247
+ // chain id and still be older, because a facts change is often a new token,
248
+ // quoter, or native-token detail on an EXISTING chain. Both versions come
249
+ // from the same release pipeline — the artifact version IS the package
250
+ // version — so comparing them is meaningful rather than an assumption about
251
+ // arbitrary strings. Equal is accepted: that is the steady state.
252
+ const chains = body.chains;
253
+ if (isOlderRelease(body.version, packageVersion_1.PACKAGE_VERSION)) {
254
+ report(new Error(`chain facts ${body.version} is older than this package's bundled registry (${packageVersion_1.PACKAGE_VERSION}) — treating as stale and keeping bundled data`), "stale");
255
+ return null;
256
+ }
257
+ return { version: body.version, chains };
258
+ }
259
+ async function fetchAndInstall() {
260
+ const payload = await fetchRemote();
261
+ if (!payload)
262
+ return false;
263
+ snapshot = {
264
+ chains: payload.chains,
265
+ source: "remote",
266
+ version: payload.version,
267
+ };
268
+ return true;
269
+ }
270
+ // Concurrent refreshes share one fetch. Without this, overlapping calls can
271
+ // install out of order — A reads v1, B reads v2 and installs it, then A
272
+ // resolves and puts v1 back — which would hide a newly added chain from a
273
+ // running service until some later refresh happened to win. A periodic timer
274
+ // plus an on-demand refresh is enough to hit that, so it is not theoretical.
275
+ // Serialising also avoids fetching the same artifact twice.
276
+ //
277
+ // This orders installs within a process; it does not make the artifact
278
+ // monotonic across CloudFront edges, where a later read can legitimately
279
+ // return an older `latest.json`. That is inherent to a CDN and self-corrects
280
+ // on the next refresh; ruling it out would need an ordering assumption about
281
+ // version strings that the format does not currently guarantee.
282
+ let inFlight = null;
283
+ return {
284
+ refresh() {
285
+ if (!inFlight) {
286
+ inFlight = fetchAndInstall().finally(() => {
287
+ inFlight = null;
288
+ });
289
+ }
290
+ return inFlight;
291
+ },
292
+ getSnapshot: () => snapshot,
293
+ getChainRegistry: () => snapshot.chains,
294
+ };
295
+ }
@@ -1,4 +1,4 @@
1
- import type { PegGroup, ProviderName, SettlementLayer, SupportedChain, SwapQuoter, SwapQuoterConfig, VmType } from "./types";
1
+ import type { ChainNetwork, ChainStack, PegGroup, ProviderName, SettlementLayer, SupportedChain, SwapQuoter, SwapQuoterConfig, VmType } from "./types";
2
2
  interface Token {
3
3
  /** EVM: 0x-prefixed hex. SVM: base58 SPL mint. TVM: base58 (T-prefixed). */
4
4
  address: string;
@@ -19,6 +19,10 @@ interface NativeToken {
19
19
  interface Chain {
20
20
  name: string;
21
21
  vmType: VmType;
22
+ /** Whether this chain is a mainnet or a testnet. */
23
+ network: ChainNetwork;
24
+ /** Execution stack, for consumers that must synthesise a viem `Chain`. */
25
+ stack: ChainStack;
22
26
  /** CAIP-2 chain identifier; populated for non-eip155 chains only. */
23
27
  caip2?: string;
24
28
  /** True for virtual chains (e.g. HyperCore) that settle on another chain. */
@@ -1 +1 @@
1
- {"version":3,"file":"chains.d.ts","sourceRoot":"","sources":["../../src/chains.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE7H,UAAU,KAAK;IACb,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,WAAW;IACnB,oFAAoF;IACpF,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,KAAK;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,WAAW,CAAC;IACzB,kBAAkB,EAAE,WAAW,CAAC;IAChC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC;CAClE;AAED,QAAA,MAAM,MAAM,EAAE,MAAM,CAAC,cAAc,EAAE,KAAK,CAuyCzC,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,CAAC;AAClB,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"chains.d.ts","sourceRoot":"","sources":["../../src/chains.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEvJ,UAAU,KAAK;IACb,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,UAAU,WAAW;IACnB,oFAAoF;IACpF,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,KAAK;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,OAAO,EAAE,YAAY,CAAC;IACtB,0EAA0E;IAC1E,KAAK,EAAE,UAAU,CAAC;IAClB,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,WAAW,CAAC;IACzB,kBAAkB,EAAE,WAAW,CAAC;IAChC,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,SAAS,EAAE,YAAY,EAAE,CAAC;IAC1B,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC;CAClE;AAED,QAAA,MAAM,MAAM,EAAE,MAAM,CAAC,cAAc,EAAE,KAAK,CAw1CzC,CAAC;AAEF,OAAO,EAAE,MAAM,EAAE,CAAC;AAClB,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC"}
@@ -9,6 +9,7 @@ const chains = {
9
9
  "decimals": 18,
10
10
  "symbol": "ETH"
11
11
  },
12
+ "network": "mainnet",
12
13
  "settlementLayers": [
13
14
  "ACROSS",
14
15
  "ECO",
@@ -18,6 +19,7 @@ const chains = {
18
19
  "RHINO",
19
20
  "CCTP"
20
21
  ],
22
+ "stack": "vanilla",
21
23
  "swapQuoterConfig": {},
22
24
  "swapQuoters": [
23
25
  "1inch",
@@ -79,6 +81,7 @@ const chains = {
79
81
  "decimals": 18,
80
82
  "symbol": "ETH"
81
83
  },
84
+ "network": "mainnet",
82
85
  "settlementLayers": [
83
86
  "ACROSS",
84
87
  "ECO",
@@ -88,6 +91,7 @@ const chains = {
88
91
  "RHINO",
89
92
  "CCTP"
90
93
  ],
94
+ "stack": "op-stack",
91
95
  "swapQuoterConfig": {},
92
96
  "swapQuoters": [
93
97
  "1inch",
@@ -157,6 +161,7 @@ const chains = {
157
161
  "decimals": 18,
158
162
  "symbol": "BNB"
159
163
  },
164
+ "network": "mainnet",
160
165
  "settlementLayers": [
161
166
  "ACROSS",
162
167
  "ECO",
@@ -164,6 +169,7 @@ const chains = {
164
169
  "RHINO",
165
170
  "CCTP"
166
171
  ],
172
+ "stack": "vanilla",
167
173
  "swapQuoters": [
168
174
  "1inch",
169
175
  "0x",
@@ -215,11 +221,13 @@ const chains = {
215
221
  "decimals": 18,
216
222
  "symbol": "XDAI"
217
223
  },
224
+ "network": "mainnet",
218
225
  "settlementLayers": [
219
226
  "RELAY",
220
227
  "NEAR",
221
228
  "RHINO"
222
229
  ],
230
+ "stack": "vanilla",
223
231
  "swapQuoters": [
224
232
  "1inch",
225
233
  "velora"
@@ -253,6 +261,7 @@ const chains = {
253
261
  "decimals": 18,
254
262
  "symbol": "ETH"
255
263
  },
264
+ "network": "mainnet",
256
265
  "settlementLayers": [
257
266
  "ACROSS",
258
267
  "ECO",
@@ -261,6 +270,7 @@ const chains = {
261
270
  "RHINO",
262
271
  "CCTP"
263
272
  ],
273
+ "stack": "op-stack",
264
274
  "swapQuoterConfig": {},
265
275
  "swapQuoters": [
266
276
  "1inch",
@@ -322,6 +332,7 @@ const chains = {
322
332
  "decimals": 18,
323
333
  "symbol": "POL"
324
334
  },
335
+ "network": "mainnet",
325
336
  "settlementLayers": [
326
337
  "ACROSS",
327
338
  "ECO",
@@ -331,6 +342,7 @@ const chains = {
331
342
  "RHINO",
332
343
  "CCTP"
333
344
  ],
345
+ "stack": "vanilla",
334
346
  "swapQuoterConfig": {},
335
347
  "swapQuoters": [
336
348
  "1inch",
@@ -384,11 +396,13 @@ const chains = {
384
396
  "decimals": 18,
385
397
  "symbol": "MON"
386
398
  },
399
+ "network": "mainnet",
387
400
  "settlementLayers": [
388
401
  "ACROSS",
389
402
  "RELAY",
390
403
  "CCTP"
391
404
  ],
405
+ "stack": "vanilla",
392
406
  "swapQuoters": [
393
407
  "0x"
394
408
  ],
@@ -443,12 +457,14 @@ const chains = {
443
457
  "decimals": 18,
444
458
  "symbol": "S"
445
459
  },
460
+ "network": "mainnet",
446
461
  "settlementLayers": [
447
462
  "ECO",
448
463
  "RELAY",
449
464
  "RHINO",
450
465
  "CCTP"
451
466
  ],
467
+ "stack": "vanilla",
452
468
  "swapQuoterConfig": {},
453
469
  "swapQuoters": [
454
470
  "1inch",
@@ -483,12 +499,14 @@ const chains = {
483
499
  "decimals": 18,
484
500
  "symbol": "HYPE"
485
501
  },
502
+ "network": "mainnet",
486
503
  "settlementLayers": [
487
504
  "ACROSS",
488
505
  "ECO",
489
506
  "RELAY",
490
507
  "CCTP"
491
508
  ],
509
+ "stack": "vanilla",
492
510
  "swapQuoters": [
493
511
  "0x"
494
512
  ],
@@ -531,7 +549,9 @@ const chains = {
531
549
  "decimals": 18,
532
550
  "symbol": "HYPE"
533
551
  },
552
+ "network": "mainnet",
534
553
  "settlementLayers": [],
554
+ "stack": "vanilla",
535
555
  "swapQuoters": [],
536
556
  "tokens": [
537
557
  {
@@ -559,10 +579,12 @@ const chains = {
559
579
  "decimals": 18,
560
580
  "symbol": "ETH"
561
581
  },
582
+ "network": "mainnet",
562
583
  "settlementLayers": [
563
584
  "ACROSS",
564
585
  "RELAY"
565
586
  ],
587
+ "stack": "op-stack",
566
588
  "swapQuoters": [],
567
589
  "tokens": [
568
590
  {
@@ -617,10 +639,12 @@ const chains = {
617
639
  "decimals": 18,
618
640
  "symbol": "ETH"
619
641
  },
642
+ "network": "mainnet",
620
643
  "settlementLayers": [
621
644
  "ACROSS",
622
645
  "RELAY"
623
646
  ],
647
+ "stack": "vanilla",
624
648
  "swapQuoters": [
625
649
  "1inch",
626
650
  "0x"
@@ -670,6 +694,7 @@ const chains = {
670
694
  "decimals": 18,
671
695
  "symbol": "ETH"
672
696
  },
697
+ "network": "mainnet",
673
698
  "settlementLayers": [
674
699
  "ACROSS",
675
700
  "ECO",
@@ -678,6 +703,7 @@ const chains = {
678
703
  "RHINO",
679
704
  "CCTP"
680
705
  ],
706
+ "stack": "op-stack",
681
707
  "swapQuoterConfig": {},
682
708
  "swapQuoters": [
683
709
  "1inch",
@@ -729,6 +755,7 @@ const chains = {
729
755
  "decimals": 18,
730
756
  "symbol": "XPL"
731
757
  },
758
+ "network": "mainnet",
732
759
  "settlementLayers": [
733
760
  "ACROSS",
734
761
  "ECO",
@@ -736,9 +763,11 @@ const chains = {
736
763
  "OFT",
737
764
  "RHINO"
738
765
  ],
766
+ "stack": "vanilla",
739
767
  "swapQuoterConfig": {},
740
768
  "swapQuoters": [
741
- "0x"
769
+ "0x",
770
+ "fynd"
742
771
  ],
743
772
  "tokens": [
744
773
  {
@@ -770,9 +799,11 @@ const chains = {
770
799
  "decimals": 18,
771
800
  "symbol": "XPL"
772
801
  },
802
+ "network": "testnet",
773
803
  "settlementLayers": [
774
804
  "ECO"
775
805
  ],
806
+ "stack": "vanilla",
776
807
  "swapQuoters": [],
777
808
  "tokens": [
778
809
  {
@@ -812,6 +843,7 @@ const chains = {
812
843
  "decimals": 18,
813
844
  "symbol": "ETH"
814
845
  },
846
+ "network": "mainnet",
815
847
  "settlementLayers": [
816
848
  "ACROSS",
817
849
  "ECO",
@@ -821,6 +853,7 @@ const chains = {
821
853
  "RHINO",
822
854
  "CCTP"
823
855
  ],
856
+ "stack": "vanilla",
824
857
  "swapQuoterConfig": {},
825
858
  "swapQuoters": [
826
859
  "1inch",
@@ -882,6 +915,7 @@ const chains = {
882
915
  "decimals": 18,
883
916
  "symbol": "AVAX"
884
917
  },
918
+ "network": "mainnet",
885
919
  "settlementLayers": [
886
920
  "ACROSS",
887
921
  "RELAY",
@@ -889,6 +923,7 @@ const chains = {
889
923
  "RHINO",
890
924
  "CCTP"
891
925
  ],
926
+ "stack": "vanilla",
892
927
  "swapQuoters": [
893
928
  "1inch",
894
929
  "0x",
@@ -955,11 +990,13 @@ const chains = {
955
990
  "decimals": 18,
956
991
  "symbol": "ETH"
957
992
  },
993
+ "network": "testnet",
958
994
  "settlementLayers": [
959
995
  "ACROSS",
960
996
  "ECO",
961
997
  "CCTP"
962
998
  ],
999
+ "stack": "op-stack",
963
1000
  "swapQuoters": [],
964
1001
  "tokens": [
965
1002
  {
@@ -1016,11 +1053,13 @@ const chains = {
1016
1053
  "decimals": 18,
1017
1054
  "symbol": "ETH"
1018
1055
  },
1056
+ "network": "testnet",
1019
1057
  "settlementLayers": [
1020
1058
  "ACROSS",
1021
1059
  "ECO",
1022
1060
  "CCTP"
1023
1061
  ],
1062
+ "stack": "vanilla",
1024
1063
  "swapQuoters": [],
1025
1064
  "tokens": [
1026
1065
  {
@@ -1067,10 +1106,12 @@ const chains = {
1067
1106
  "decimals": 18,
1068
1107
  "symbol": "ETH"
1069
1108
  },
1109
+ "network": "mainnet",
1070
1110
  "settlementLayers": [
1071
1111
  "RELAY",
1072
1112
  "RHINO"
1073
1113
  ],
1114
+ "stack": "vanilla",
1074
1115
  "swapQuoters": [],
1075
1116
  "tokens": [
1076
1117
  {
@@ -1127,11 +1168,13 @@ const chains = {
1127
1168
  "decimals": 18,
1128
1169
  "symbol": "ETH"
1129
1170
  },
1171
+ "network": "testnet",
1130
1172
  "settlementLayers": [
1131
1173
  "ACROSS",
1132
1174
  "ECO",
1133
1175
  "CCTP"
1134
1176
  ],
1177
+ "stack": "vanilla",
1135
1178
  "swapQuoters": [],
1136
1179
  "tokens": [
1137
1180
  {
@@ -1178,11 +1221,13 @@ const chains = {
1178
1221
  "decimals": 18,
1179
1222
  "symbol": "ETH"
1180
1223
  },
1224
+ "network": "testnet",
1181
1225
  "settlementLayers": [
1182
1226
  "ACROSS",
1183
1227
  "ECO",
1184
1228
  "CCTP"
1185
1229
  ],
1230
+ "stack": "op-stack",
1186
1231
  "swapQuoters": [],
1187
1232
  "tokens": [
1188
1233
  {
@@ -1230,12 +1275,14 @@ const chains = {
1230
1275
  "decimals": 6,
1231
1276
  "symbol": "TRX"
1232
1277
  },
1278
+ "network": "mainnet",
1233
1279
  "settlementLayers": [
1234
1280
  "RELAY",
1235
1281
  "OFT",
1236
1282
  "NEAR",
1237
1283
  "RHINO"
1238
1284
  ],
1285
+ "stack": "vanilla",
1239
1286
  "swapQuoters": [],
1240
1287
  "tokens": [
1241
1288
  {
@@ -1270,6 +1317,7 @@ const chains = {
1270
1317
  "decimals": 9,
1271
1318
  "symbol": "SOL"
1272
1319
  },
1320
+ "network": "mainnet",
1273
1321
  "settlementLayers": [
1274
1322
  "RELAY",
1275
1323
  "OFT",
@@ -1277,6 +1325,7 @@ const chains = {
1277
1325
  "RHINO",
1278
1326
  "CCTP"
1279
1327
  ],
1328
+ "stack": "vanilla",
1280
1329
  "swapQuoters": [],
1281
1330
  "tokens": [
1282
1331
  {