From a662c179449441ced12fb7b119780080bd3912dc Mon Sep 17 00:00:00 2001 From: chrisli30 Date: Mon, 8 Jun 2026 18:48:44 -0700 Subject: [PATCH] fix: guard buildTokensFromData against duplicate chainId in PER_CHAIN Addresses Copilot review on #14: the tokens-aggregator refactor dropped duplicate protection, so a chain listed twice in PER_CHAIN would silently overwrite the first chain's entries (wrong Tokens.SYMBOL[chainId], no error at module load). Now throws fast pointing at the duplicate. Patch changeset; no API change. Co-Authored-By: Claude Opus 4.8 (1M context) --- .changeset/tokens-duplicate-chainid-guard.md | 7 +++++++ src/tokens/index.ts | 17 +++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 .changeset/tokens-duplicate-chainid-guard.md diff --git a/.changeset/tokens-duplicate-chainid-guard.md b/.changeset/tokens-duplicate-chainid-guard.md new file mode 100644 index 0000000..0be3a5f --- /dev/null +++ b/.changeset/tokens-duplicate-chainid-guard.md @@ -0,0 +1,7 @@ +--- +"@avaprotocol/protocols": patch +--- + +Guard `buildTokensFromData` against a duplicate `chainId` in `PER_CHAIN`. + +If the same chain were listed twice (a copy-paste in the array, or two chain modules reporting the same `chainId`), the flatten would silently overwrite the first chain's entries and produce a wrong `Tokens.SYMBOL[chainId]` map with no error at module load. It now throws fast pointing at the duplicate. diff --git a/src/tokens/index.ts b/src/tokens/index.ts index 2562408..9ff88ec 100644 --- a/src/tokens/index.ts +++ b/src/tokens/index.ts @@ -69,8 +69,13 @@ const PER_CHAIN: ReadonlyArray { const merged: Record> = Object.create(null); + const seenChainIds = new Set(); for (const [chainId, chainTokens] of PER_CHAIN) { + if (seenChainIds.has(chainId)) { + throw new Error( + `[@avaprotocol/protocols] chainId ${chainId} appears more than once in PER_CHAIN — ` + + `each chain must be listed exactly once. Merge the duplicate entries.`, + ); + } + seenChainIds.add(chainId); for (const [symbol, entry] of Object.entries(chainTokens)) { if (!Object.prototype.hasOwnProperty.call(merged, symbol)) { merged[symbol] = Object.create(null);