feat: abstract chain + addchain scaffolder#12186
feat: abstract chain + addchain scaffolder#12186gomesalexandre wants to merge 8 commits intoshapeshift:developfrom
Conversation
- add Abstract (EVM chain ID 2741) as second-class EVM chain behind VITE_FEATURE_ABSTRACT flag - add scripts/addChain/ scaffolder to automate ~80% of second-class EVM chain integration points - Abstract integrates via Relay swapper with ~1-2s bridge/swap times - native asset: ETH, explorer: abscan.org, rpc: api.mainnet.abs.xyz scaffolder covers: - AST-based engine (typescript compiler API, zero new deps) for enum/object/array/switch insertions - chain config JSON schema (chains/abstract.json as reference) - codemods registry for ~50 insertion points across the codebase - append-only ordering (appendLineAfterLastPattern) to avoid merge conflicts - idempotency: safe to run twice Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds Abstract (ABS, eip155:2741) as a second-class EVM chain across the repo: env/config, CAIP constants, chain adapter & plugin, viem/ethers clients, asset data and generation, CSP, HDWallet capability flags, WalletConnectV2 wiring, swapper mappings, feature flags, tests, and a new add-chain scaffolder. Changes
Sequence Diagram(s)sequenceDiagram
participant UI as UI / User
participant Plugin as AbstractPlugin
participant AssetSvc as AssetService
participant Adapter as AbstractChainAdapter
participant Viem as ViemClient
participant Relay as RelaySwapper
UI->>Plugin: app boot -> register(VITE_ABSTRACT_NODE_URL)
Plugin->>AssetSvc: getKnownTokens(abstractChainId)
AssetSvc-->>Plugin: token list
Plugin->>Adapter: new ChainAdapter(rpcUrl, getKnownTokens)
Adapter->>Viem: createPublicClient(transport using VITE_ABSTRACT_NODE_URL + fallbacks)
UI->>Adapter: buildTx / requestQuote
Adapter->>Relay: request route (relayChainId 2741)
Relay-->>UI: route / quote
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/context/WalletProvider/WalletConnectV2/config.ts (1)
55-69:⚠️ Potential issue | 🟠 MajorGate Abstract in WalletConnect config too.
This now advertises chain 2741 in every WalletConnect session, even when the Abstract plugin is disabled. That makes dapps believe Abstract is supported and can route users into missing-adapter/request-handling paths instead of cleanly hiding the network.
💡 Minimal gating change
const { VITE_WALLET_CONNECT_WALLET_PROJECT_ID, VITE_AVALANCHE_NODE_URL, VITE_OPTIMISM_NODE_URL, VITE_BNBSMARTCHAIN_NODE_URL, VITE_POLYGON_NODE_URL, VITE_GNOSIS_NODE_URL, VITE_ETHEREUM_NODE_URL, VITE_ARBITRUM_NODE_URL, VITE_BASE_NODE_URL, VITE_INK_NODE_URL, VITE_FLOWEVM_NODE_URL, + VITE_FEATURE_ABSTRACT, VITE_ABSTRACT_NODE_URL, } = getConfig() export const walletConnectV2OptionalChains: AtLeastOneViemChain = (() => { const optionalViemChains: ViemChain[] = [ optimism, bsc, gnosis, polygon, avalanche, arbitrum, base, ink, flowEvmChain, sei, - abstract, + ...(VITE_FEATURE_ABSTRACT ? [abstract] : []), ] if (optionalViemChains.length === 0) throw new Error('Array must contain at least one element.') return optionalViemChains as AtLeastOneViemChain })() export const walletConnectV2ProviderConfig: EthereumProviderOptions = { ... rpcMap: { [CHAIN_REFERENCE.AvalancheCChain]: VITE_AVALANCHE_NODE_URL, [CHAIN_REFERENCE.OptimismMainnet]: VITE_OPTIMISM_NODE_URL, [CHAIN_REFERENCE.BnbSmartChainMainnet]: VITE_BNBSMARTCHAIN_NODE_URL, [CHAIN_REFERENCE.PolygonMainnet]: VITE_POLYGON_NODE_URL, [CHAIN_REFERENCE.GnosisMainnet]: VITE_GNOSIS_NODE_URL, [CHAIN_REFERENCE.EthereumMainnet]: VITE_ETHEREUM_NODE_URL, [CHAIN_REFERENCE.ArbitrumMainnet]: VITE_ARBITRUM_NODE_URL, [CHAIN_REFERENCE.BaseMainnet]: VITE_BASE_NODE_URL, [CHAIN_REFERENCE.InkMainnet]: VITE_INK_NODE_URL, [CHAIN_REFERENCE.FlowEvmMainnet]: VITE_FLOWEVM_NODE_URL, - [CHAIN_REFERENCE.AbstractMainnet]: VITE_ABSTRACT_NODE_URL, + ...(VITE_FEATURE_ABSTRACT + ? { [CHAIN_REFERENCE.AbstractMainnet]: VITE_ABSTRACT_NODE_URL } + : {}), }, }Also applies to: 80-93, 114-126
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/context/WalletProvider/WalletConnectV2/config.ts` around lines 55 - 69, The arrays (notably walletConnectV2OptionalChains) currently always include the 'abstract' chain, causing WalletConnect sessions to advertise chain 2741 even when the Abstract plugin is disabled; change these static arrays to only include the 'abstract' ViemChain conditionally by checking a runtime feature flag/config (e.g., an existing enableAbstract or isAbstractPluginEnabled boolean) and pushing/concat-ing the abstract chain only when that flag is true; apply the same conditional inclusion to the other WalletConnect V2 chain arrays referenced in this diff so Abstract is advertised only when the plugin is enabled.
🧹 Nitpick comments (2)
packages/contracts/src/fallbackRpcUrls.ts (1)
34-34: Consider adding official or alternative RPC endpoints for better resilience.The Abstract chain currently has only one fallback URL. Multiple public RPC endpoints are available: the official
https://api.mainnet.abs.xyzand dRPC'shttps://abstract.drpc.org. Adding one or both would improve reliability if any single endpoint becomes unavailable.💡 Suggested improvement
- abstract: ['https://rpc.ankr.com/abstract'], + abstract: ['https://api.mainnet.abs.xyz', 'https://abstract.drpc.org'],🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/contracts/src/fallbackRpcUrls.ts` at line 34, The 'abstract' entry in the fallback RPC URLs array only contains a single endpoint; update the exported fallbackRpcUrls object so the 'abstract' key's array includes additional resilient endpoints (e.g., add "https://api.mainnet.abs.xyz" and/or "https://abstract.drpc.org") alongside the existing "https://rpc.ankr.com/abstract" in the file that defines fallbackRpcUrls (look for the 'abstract' property in fallbackRpcUrls.ts) so consumers will have multiple RPC options if one endpoint is down.package.json (1)
42-42: Usepnpm exec tsxfor consistency with other scripts.All other tsx-based scripts in this file use
pnpm exec tsx(e.g.,generate:chain,generate:asset-data,release). This script should follow the same pattern to ensure lockfile-pinned execution and consistency.Suggested change
- "add-chain": "npx tsx scripts/addChain/index.ts", + "add-chain": "pnpm exec tsx ./scripts/addChain/index.ts",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@package.json` at line 42, Update the add-chain package.json script to use the same invocation style as other tsx scripts: replace the current "add-chain" script that uses "npx tsx" with one that uses "pnpm exec tsx" so execution is lockfile-pinned and consistent with scripts like "generate:chain" and "release".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/chain-adapters/src/types.ts`:
- Line 332: ChainSignTx is missing an entry for KnownChainIds.AbstractMainnet so
SignTx<KnownChainIds.AbstractMainnet> resolves to never; add a mapping for
KnownChainIds.AbstractMainnet to the appropriate signing type (e.g.,
evm.SignTxInput or whatever the repo uses for EVM-like chains) inside the
ChainSignTx union/map definition to mirror other chain-specific maps (like
ChainBuildTxInput and ChainSpecificAccount), updating the ChainSignTx type to
include [KnownChainIds.AbstractMainnet]: <appropriate sign type> so Abstract
chain signing works correctly.
In `@packages/hdwallet-walletconnectv2/src/walletconnectV2.ts`:
- Line 228: WalletConnectV2 advertises Abstract support via readonly
_supportsAbstract = true but WalletConnectV2WalletInfo.ethSupportsNetwork()
omits chainId 2741, causing ethSupportsNetwork (and
WalletConnectV2HDWallet.ethSupportsNetwork() which delegates to it) to reject
Abstract; fix by adding chainId 2741 to the supported chains/logic inside
WalletConnectV2WalletInfo.ethSupportsNetwork() so that it returns true for 2741
(and ensure WalletConnectV2HDWallet.ethSupportsNetwork() continues to delegate
to that updated method).
In `@scripts/addChain/codemods.ts`:
- Around line 24-30: wrap currently treats a false return from the codemod
function as 'skipped', which hides anchor-miss failures; change wrap (the
function wrap(file: string, operation: string, fn: () => boolean)) so that when
fn() returns true it still returns status 'inserted', but when fn() returns
false it returns status 'error' with a clear message like "anchor not found" (or
similar) instead of 'skipped'; preserve the existing catch branch for thrown
errors and keep the returned object shape { file, operation, status, message? }
so callers/consumers can detect and surface anchor-miss failures from wrap.
In `@scripts/addChain/engine.ts`:
- Around line 160-179: The idempotency check in addNamedImport is brittle
because it uses a raw file string/idempotencyKeyForImport(importName,
modulePath) and can false-skip or duplicate imports; update the logic to use the
TS AST: parseSource and locate the ImportDeclaration for modulePath
(targetImport), then inspect its importClause.namedBindings to determine if the
specific ImportSpecifier (importName) already exists (avoid relying on a global
string search). If no ImportDeclaration exists, generate a new import and use an
idempotency marker that uniquely ties modulePath+importName; if a targetImport
exists and lacks the specifier, mutate the ImportDeclaration to append a new
ImportSpecifier (use TS factory helpers or rebuild the namedBindings) instead of
string insertion so formatting/duplicates are handled correctly; remove or
narrow the current file-wide idempotency check and ensure
idempotencyKeyForImport is scoped to modulePath+importName.
In `@scripts/addChain/report.ts`:
- Around line 80-84: The report currently only logs errors but doesn't cause a
non-zero exit; after runAllCodemods returns results and you call
printReport(results, config) in the main() function (in
scripts/addChain/index.ts), check results for any entries with status ===
'error' (e.g., results.some(r => r.status === 'error')) and call process.exit(1)
when true so CI fails on codemod errors; update main() to perform this
post-report check and exit with code 1 on any error statuses.
In `@scripts/addChain/schema.ts`:
- Around line 93-99: Validate dependent fields and reject empty-string
addresses: when processing the chain config object (c) ensure that if
swappers.relay.supported === true then swappers.relay.relayChainId is present
and non-empty (throw a clear Error mentioning "swappers.relay.relayChainId" if
missing or falsy), and tighten wrappedNativeAddress validation to reject empty
strings (treat "" as invalid and only allow null or a non-empty string, throwing
an Error referencing "wrappedNativeAddress" otherwise). Apply the same stricter
checks in the other related block (lines analogous to 106-114) and use early
throws with descriptive messages so invalid configs fail fast.
In `@src/lib/account/evm.ts`:
- Line 186: Prefetching for chainIds[0] happens before the main loop and calls
adapter.getAddresses(), but for batch-capable wallets that don't support
Abstract this throws before the later check on abstractChainId can skip it;
modify the prefetch logic so it checks whether chainIds[0] === abstractChainId
and !supportsAbstract(wallet) (using the supportsAbstract helper and
abstractChainId symbol) and skip the prefetch in that case, or move that guard
earlier (before adapter.getAddresses is invoked) so account discovery quietly
skips Abstract chains instead of throwing.
---
Outside diff comments:
In `@src/context/WalletProvider/WalletConnectV2/config.ts`:
- Around line 55-69: The arrays (notably walletConnectV2OptionalChains)
currently always include the 'abstract' chain, causing WalletConnect sessions to
advertise chain 2741 even when the Abstract plugin is disabled; change these
static arrays to only include the 'abstract' ViemChain conditionally by checking
a runtime feature flag/config (e.g., an existing enableAbstract or
isAbstractPluginEnabled boolean) and pushing/concat-ing the abstract chain only
when that flag is true; apply the same conditional inclusion to the other
WalletConnect V2 chain arrays referenced in this diff so Abstract is advertised
only when the plugin is enabled.
---
Nitpick comments:
In `@package.json`:
- Line 42: Update the add-chain package.json script to use the same invocation
style as other tsx scripts: replace the current "add-chain" script that uses
"npx tsx" with one that uses "pnpm exec tsx" so execution is lockfile-pinned and
consistent with scripts like "generate:chain" and "release".
In `@packages/contracts/src/fallbackRpcUrls.ts`:
- Line 34: The 'abstract' entry in the fallback RPC URLs array only contains a
single endpoint; update the exported fallbackRpcUrls object so the 'abstract'
key's array includes additional resilient endpoints (e.g., add
"https://api.mainnet.abs.xyz" and/or "https://abstract.drpc.org") alongside the
existing "https://rpc.ankr.com/abstract" in the file that defines
fallbackRpcUrls (look for the 'abstract' property in fallbackRpcUrls.ts) so
consumers will have multiple RPC options if one endpoint is down.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 88a149ef-9a27-45cd-abbe-c3d239360f70
⛔ Files ignored due to path filters (9)
public/generated/asset-manifest.jsonis excluded by!**/generated/**public/generated/asset-manifest.json.bris excluded by!**/generated/**public/generated/asset-manifest.json.gzis excluded by!**/*.gz,!**/generated/**public/generated/generatedAssetData.jsonis excluded by!**/generated/**public/generated/generatedAssetData.json.bris excluded by!**/generated/**public/generated/generatedAssetData.json.gzis excluded by!**/*.gz,!**/generated/**public/generated/relatedAssetIndex.jsonis excluded by!**/generated/**public/generated/relatedAssetIndex.json.bris excluded by!**/generated/**public/generated/relatedAssetIndex.json.gzis excluded by!**/*.gz,!**/generated/**
📒 Files selected for processing (73)
.env.env.developmentchains/abstract.jsone2e/fixtures/abstract-chain.yamlheaders/csps/chains/abstract.tsheaders/csps/index.tspackage.jsonpackages/caip/src/adapters/coingecko/index.tspackages/caip/src/adapters/coingecko/utils.tspackages/caip/src/constants.tspackages/chain-adapters/src/evm/EvmBaseAdapter.tspackages/chain-adapters/src/evm/abstract/AbstractChainAdapter.tspackages/chain-adapters/src/evm/abstract/index.tspackages/chain-adapters/src/evm/index.tspackages/chain-adapters/src/types.tspackages/contracts/src/ethersProviderSingleton.tspackages/contracts/src/fallbackRpcUrls.tspackages/contracts/src/viemClient.tspackages/hdwallet-coinbase/src/coinbase.tspackages/hdwallet-core/src/ethereum.tspackages/hdwallet-core/src/wallet.tspackages/hdwallet-gridplus/src/gridplus.tspackages/hdwallet-keepkey/src/keepkey.tspackages/hdwallet-ledger/src/ledger.tspackages/hdwallet-metamask-multichain/src/native-multichain.tspackages/hdwallet-metamask-multichain/src/shapeshift-multichain.tspackages/hdwallet-native/src/ethereum.tspackages/hdwallet-phantom/src/phantom.tspackages/hdwallet-trezor/src/trezor.tspackages/hdwallet-vultisig/src/vultisig.tspackages/hdwallet-walletconnectv2/src/walletconnectV2.tspackages/swapper/src/swappers/RelaySwapper/constant.tspackages/swapper/src/swappers/RelaySwapper/utils/relayTokenToAssetId.tspackages/types/src/base.tspackages/utils/src/assetData/baseAssets.tspackages/utils/src/assetData/getBaseAsset.tspackages/utils/src/chainIdToFeeAssetId.tspackages/utils/src/getAssetNamespaceFromChainId.tspackages/utils/src/getChainShortName.tspackages/utils/src/getNativeFeeAssetReference.tsscripts/addChain/codemods.tsscripts/addChain/engine.tsscripts/addChain/index.tsscripts/addChain/report.tsscripts/addChain/schema.tsscripts/addChain/templates/assetGenerator.ts.tmplscripts/addChain/templates/chainAdapter.ts.tmplscripts/addChain/templates/chainAdapterIndex.ts.tmplscripts/addChain/templates/csp.ts.tmplscripts/addChain/templates/plugin.tsx.tmplscripts/generateAssetData/abstract/index.tsscripts/generateAssetData/coingecko.tsscripts/generateAssetData/generateAssetData.tsscripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.tssrc/components/TradeAssetSearch/hooks/useGetPopularAssetsQuery.tsxsrc/config.tssrc/constants/chains.tssrc/context/PluginProvider/PluginProvider.tsxsrc/context/WalletProvider/WalletConnectV2/config.tssrc/hooks/useWalletSupportsChain/useWalletSupportsChain.tssrc/lib/account/evm.tssrc/lib/asset-service/service/AssetService.tssrc/lib/coingecko/utils.tssrc/lib/market-service/coingecko/coingecko.test.tssrc/pages/Markets/components/MarketsRow.tsxsrc/plugins/abstract/index.tsxsrc/plugins/activePlugins.tssrc/state/migrations/index.tssrc/state/slices/opportunitiesSlice/mappings.tssrc/state/slices/portfolioSlice/utils/index.tssrc/state/slices/preferencesSlice/preferencesSlice.tssrc/test/mocks/store.tssrc/vite-env.d.ts
| function wrap(file: string, operation: string, fn: () => boolean): CodemodResult { | ||
| try { | ||
| const changed = fn() | ||
| return { file, operation, status: changed ? 'inserted' : 'skipped' } | ||
| } catch (err) { | ||
| return { file, operation, status: 'error', message: String(err) } | ||
| } |
There was a problem hiding this comment.
wrap() currently masks anchor-miss failures as “skipped”.
Because engine helpers use false for both “already present” and “pattern not found”, this wrapper records both as 'skipped'. That can hide broken codemods and produce incomplete scaffolds without surfacing an error state.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/addChain/codemods.ts` around lines 24 - 30, wrap currently treats a
false return from the codemod function as 'skipped', which hides anchor-miss
failures; change wrap (the function wrap(file: string, operation: string, fn: ()
=> boolean)) so that when fn() returns true it still returns status 'inserted',
but when fn() returns false it returns status 'error' with a clear message like
"anchor not found" (or similar) instead of 'skipped'; preserve the existing
catch branch for thrown errors and keep the returned object shape { file,
operation, status, message? } so callers/consumers can detect and surface
anchor-miss failures from wrap.
There was a problem hiding this comment.
post-MVP — wrap() propagates false/exception correctly; anchor-not-found vs already-present distinction is a UX improvement for the scaffold operator, not a correctness issue
There was a problem hiding this comment.
@gomesalexandre, understood — the wrap() semantics are intentional: false maps to 'skipped' (covers both "already present" and "anchor not found"), and only thrown exceptions map to 'error'. Surfacing the finer-grained distinction is a post-MVP UX improvement and doesn't affect scaffold correctness.
This is already captured in my knowledge base so I won't flag it again in future reviews.
🧠 Learnings used
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/codemods.ts, the `wrap()` helper intentionally uses `false` (from the engine) to mean "skipped/already present" and thrown exceptions to mean "error". The distinction between "anchor not found" vs "already present" in skip status is a known post-MVP UX improvement and does not affect scaffold correctness. Do not flag this as a masking issue.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/engine.ts, the `addNamedImport()` idempotency key format is intentional for the current MVP scaffolder. Hardening the idempotency key approach is catalogued as a post-MVP improvement. Do not flag the current format as incorrect.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/components/modals/EIP155SignTypedDataConfirmation.tsx:55-55
Timestamp: 2025-09-10T15:35:46.223Z
Learning: gomesalexandre prefers fail-fast early returns over graceful degradation when critical data is missing in WalletConnect flows (like peer metadata in EIP155SignTypedDataConfirmation.tsx). He favors "safety first, always double-wrap" approach and believes missing peer metadata indicates bigger problems that should be surfaced explicitly rather than masked with partial UI rendering.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/SendTransactionConfirmation.tsx:42-50
Timestamp: 2025-09-12T12:00:33.924Z
Learning: gomesalexandre prefers maintaining consistency with existing code patterns in WalletConnect modals, including side-effects-during-render for error handling (showErrorToast + handleReject), rather than introducing isolated refactors that would make the codebase inconsistent.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11924
File: packages/chain-adapters/src/evm/mantle/MantleChainAdapter.ts:1-1
Timestamp: 2026-02-21T10:55:55.870Z
Learning: For second-class EVM chain adapters (those extending SecondClassEvmAdapter), the type guard function (e.g., isMantleChainAdapter, isKatanaChainAdapter, isUnichainChainAdapter) exists in BOTH locations: in the adapter file itself (packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts) AND in src/lib/utils/[chain].ts with defensive null/undefined checks. This pattern is consistent across at least 14 second-class adapters (base, berachain, cronos, hyperevm, ink, katana, linea, mantle, megaeth, monad, optimism, plasma, scroll, sonic, unichain) and should be maintained for consistency unless a comprehensive refactor across all adapters is undertaken.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11932
File: src/lib/utils/worldchain.ts:39-41
Timestamp: 2026-02-22T12:23:52.513Z
Learning: In src/lib/utils/[chain].ts files for second-class EVM chains (e.g., worldchain.ts, katana.ts, etc.), the per-chain utility functions like getWorldChainTransactionStatus() are effectively dead code after the migration to using the generic SecondClassEvmAdapter.getTransactionStatus() handler. Code quality concerns (like structured logging) for these files are not relevant since they're no longer actively used in hot paths.
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/**/*.ts : Use TypeScript with explicit types (e.g., SupportedChainIds) for all code in the Swapper system
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/config.ts:127-128
Timestamp: 2025-08-07T11:20:44.614Z
Learning: gomesalexandre prefers required environment variables without default values in the config file (src/config.ts). They want explicit configuration and fail-fast behavior when environment variables are missing, rather than having fallback defaults.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx:0-0
Timestamp: 2025-09-13T16:45:18.813Z
Learning: gomesalexandre prefers aggressively deleting unused/obsolete code files ("ramboing") rather than fixing technical issues in code that won't be used, demonstrating his preference for keeping codebases clean and PR scope focused.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/types.ts:7-7
Timestamp: 2025-09-10T15:34:29.604Z
Learning: gomesalexandre is comfortable relying on transitive dependencies (like abitype through ethers/viem) rather than explicitly declaring them in package.json, preferring to avoid package.json bloat when the transitive dependency approach works reliably in practice.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10503
File: .env:56-56
Timestamp: 2025-09-16T13:17:02.938Z
Learning: gomesalexandre prefers to enable feature flags globally in the base .env file when the intent is to activate features everywhere, even when there are known issues like crashes, demonstrating his preference for intentional global feature rollouts over cautious per-environment enablement.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:447-503
Timestamp: 2025-08-13T17:07:10.763Z
Learning: gomesalexandre prefers relying on TypeScript's type system for validation rather than adding defensive runtime null checks when types are properly defined. They favor a TypeScript-first approach over defensive programming with runtime validations.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/hooks/useActionCenterSubscribers/useThorchainLpDepositActionSubscriber.tsx:61-66
Timestamp: 2025-08-14T17:51:47.556Z
Learning: gomesalexandre is not concerned about structured logging and prefers to keep console.error usage as-is rather than implementing structured logging patterns, even when project guidelines suggest otherwise.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10413
File: src/components/Modals/FiatRamps/fiatRampProviders/onramper/utils.ts:29-55
Timestamp: 2025-09-02T14:26:19.028Z
Learning: gomesalexandre prefers to keep preparatory/reference code simple until it's actively consumed, rather than implementing comprehensive error handling, validation, and robustness improvements upfront. They prefer to add these improvements when the code is actually being used in production.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:396-402
Timestamp: 2025-08-14T17:55:57.490Z
Learning: gomesalexandre is comfortable with functions/variables that return undefined or true (tri-state) when only the truthy case matters, preferring to rely on JavaScript's truthy/falsy behavior rather than explicitly returning boolean values.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10783
File: src/context/ModalStackProvider/useModalRegistration.ts:30-41
Timestamp: 2025-10-16T11:14:40.657Z
Learning: gomesalexandre prefers to add lint rules (like typescript-eslint/strict-boolean-expressions for truthiness checks on numbers) to catch common issues project-wide rather than relying on code review to catch them.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/lib/moralis.ts:47-85
Timestamp: 2025-08-07T11:22:16.983Z
Learning: gomesalexandre prefers console.error over structured logging for Moralis API integration debugging, as they find it more conventional and prefer to examine XHR requests directly rather than rely on structured logs for troubleshooting.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In shapeshift/web, the batch-prefetch in src/lib/account/evm.ts gates on `wallet.ethGetAddresses`, which is chain-agnostic and works for any EVM-capable wallet regardless of chain-specific support flags like `supportsAbstract`. The chain-specific `supports*` guard is enforced downstream in `deriveEvmAccountIdsAndMetadata`. This pattern is identical across all second-class EVM chains and should not be flagged as a missing pre-check.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T20:28:34.883Z
Learning: In shapeshift/web, chains added to `walletConnectV2OptionalChains` and `rpcMap` in `src/context/WalletProvider/WalletConnectV2/config.ts` are intentionally NOT gated by their feature flags. Feature-flagged chains (e.g., ink, flowEvmChain, sei, abstract) are unconditionally included in these WalletConnect V2 structures. This is the established convention and should not be flagged as a missing feature-flag guard.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:133-137
Timestamp: 2025-09-12T10:15:10.389Z
Learning: gomesalexandre has identified that EIP-712 domain chainId should be preferred over request context chainId for accuracy in WalletConnect dApps structured signing flows. The domain chainId from the parsed message is more specific and accurate than the general request context, especially for asset resolution and network-specific operations.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T01:29:21.619Z
Learning: In shapeshift/web PR `#12181`, the primary fix is replacing SHA-based comparison (`privateSha`) with a content diff approach (`privateContentMatchesMain` boolean) in `deriveReleaseState`/`deriveHotfixState` in `scripts/release.ts`. This unblocks new releases when `private` has been squash-synced with `main` (SHA differs even though content is identical). The secondary fix — `createPr` returning `null` on "No commits between" GitHub error — is a defensive improvement bundled in the same PR. The PR title only references the secondary change; the commit message body captures both.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11930
File: packages/chain-adapters/src/evm/soneium/SoneiumChainAdapter.ts:18-20
Timestamp: 2026-02-21T14:23:27.392Z
Learning: In packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts files for second-class EVM adapters, the type guard function (e.g., isSoneiumChainAdapter, isMantleChainAdapter) intentionally uses a simple pattern without defensive null/undefined checks: `(adapter as ChainAdapter).getType() === KnownChainIds.[Chain]Mainnet`. These simple type guards are exported for optional per-chain narrowing but are not actively used in hot paths. In practice, callers always check `getChainAdapterManager().get(chainId)` first, so null is never passed. The null-safe production code path uses `isSecondClassEvmAdapter` via `instanceof`. This pattern is consistent across 20+ second-class adapters (Berachain, HyperEvm, Base, Optimism, Linea, Monad, Scroll, Ink, Mode, Sonic, Bob, Plasma, Mantle, Katana, Cronos, MegaEth, Unichain, Soneium). Any defensive null-check additions should be done comprehensively across all adapters in a dedicated cleanup PR, not piecemeal.
Learnt from: gomes-bot
Repo: shapeshift/web PR: 11884
File: packages/chain-adapters/src/tron/TronChainAdapter.ts:732-735
Timestamp: 2026-02-16T15:00:09.111Z
Learning: In packages/chain-adapters/src/tron/TronChainAdapter.ts, inline comments explaining non-obvious domain-specific behavior (e.g., why TRC20 burns to zero address are allowed while mints from zero address are skipped) are acceptable when explicitly requested, especially when the rationale is easy to regress (e.g., sTRX unstaking burn behavior).
| if (chainId === storyChainId && !supportsStory(wallet)) continue | ||
| if (chainId === zkSyncEraChainId && !supportsZkSyncEra(wallet)) continue | ||
| if (chainId === blastChainId && !supportsBlast(wallet)) continue | ||
| if (chainId === abstractChainId && !supportsAbstract(wallet)) continue |
There was a problem hiding this comment.
The Abstract skip happens too late for batch-prefetch.
Lines 141-157 prefetch chainIds[0] before the main loop, and that path calls adapter.getAddresses(). If chainIds[0] is Abstract on a batch-capable wallet that doesn't support it, the adapter throws before Line 186 can continue, so account discovery fails instead of quietly skipping the chain.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/lib/account/evm.ts` at line 186, Prefetching for chainIds[0] happens
before the main loop and calls adapter.getAddresses(), but for batch-capable
wallets that don't support Abstract this throws before the later check on
abstractChainId can skip it; modify the prefetch logic so it checks whether
chainIds[0] === abstractChainId and !supportsAbstract(wallet) (using the
supportsAbstract helper and abstractChainId symbol) and skip the prefetch in
that case, or move that guard earlier (before adapter.getAddresses is invoked)
so account discovery quietly skips Abstract chains instead of throwing.
There was a problem hiding this comment.
dismissing — the prefetch gates on wallet.ethGetAddresses (any EVM wallet), not supportsAbstract. all other second-class EVM chains use the identical pattern without issue
There was a problem hiding this comment.
Rate Limit Exceeded
@gomesalexandre have exceeded the limit for the number of chat messages per hour. Please wait 1 minutes and 32 seconds before sending another message.
|
ser you're drunk @coderabbitai
|
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 4114
✏️ Learnings added
🧠 Learnings used |
- add AbstractMainnet to ChainSignTx (was missing, would resolve to never) - add chainId 2741 to WalletConnectV2 ethSupportsNetwork() - add process.exit(1) when scaffolder codemods have errors - validate wrappedNativeAddress non-empty string + relay requires relayChainId - use pnpm exec tsx instead of npx tsx for add-chain script - add more fallback RPC endpoints for Abstract (mainnet + drpc) - add eip155:2741 to coingecko utils parseData test (fixes failing CI) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
done @coderabbitai — addressed in the follow-up commit:
dismissing the wrap()/engine idempotency/evm.ts prefetch comments — wrap() already logs via console.warn on misses (surfaced to the user), addNamedImport idempotency key format is intentional, and the evm.ts prefetch uses ethGetAddresses which works for all EVM chains regardless of supportsAbstract |
|
Tip For best results, initiate chat on the files or code changes.
The dismissals also make sense:
🧠 Learnings usedIf you found this review helpful, would you consider giving us a shout-out on X? Thank you for using CodeRabbit! |
- add ChainSignTx (ETHSignTx type map) codemod — was missing, manual fix needed for abstract - add ethSupportsNetwork() chain ID codemod for walletconnectv2 — was missing, manual fix needed for abstract - rename mislabeled types-ChainSignTx → types-ChainSpecificBuildTxInput - add missing clearAssets migration 314 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
🤖 QA Automation ReportQABot Run: #59223faa ✅ Build Verification
|
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (1)
scripts/addChain/codemods.ts (1)
24-30:⚠️ Potential issue | 🟠 MajorDon't collapse anchor misses into
skipped.
wrap()still treats everyfalseas an idempotent no-op. That is already wrong for Lines 1020-1023, wherefalsemeans "couldn't find anyclearAssetsanchor". The report stays green andscripts/addChain/index.tsexits 0 even though the scaffold is incomplete.🩹 Suggested shape
-function wrap(file: string, operation: string, fn: () => boolean): CodemodResult { +function wrap( + file: string, + operation: string, + fn: () => 'inserted' | 'skipped', +): CodemodResult { try { - const changed = fn() - return { file, operation, status: changed ? 'inserted' : 'skipped' } + return { file, operation, status: fn() } } catch (err) { return { file, operation, status: 'error', message: String(err) } } }Then make anchor-miss paths throw instead of returning
false.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/addChain/codemods.ts` around lines 24 - 30, wrap() currently treats any falsy result from the codemod function as a benign 'skipped' and hides anchor-misses (e.g., missing clearAssets anchor reported from the codemod run around the clearAssets logic), so change the behavior so anchor-miss paths surface as errors: update the codemod functions that return false on "anchor not found" to throw a descriptive Error (e.g., "anchor clearAssets not found"), and update wrap(fn) to stop converting false into 'skipped' — let thrown errors propagate (or catch and return status: 'error' with the error message) so anchor misses produce error status instead of a green 'skipped'.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@scripts/addChain/codemods.ts`:
- Around line 1529-1552: The scaffold currently decides to skip creation based
solely on adapterFile existence (variable adapterFile) which leaves index.ts
missing if a previous run failed; update the logic in codemods.ts to check both
the class file and the index file (the path used in the second writeFileSync
call) — if the directory doesn't exist create it, then individually ensure the
class file and the index.ts are created when absent (using the same
fill(tmpl(...), c) calls), and push appropriate results entries for each
artifact instead of a single skipped/inserted result so partial generation is
repaired on re-run.
- Around line 1101-1135: The current conditional branches that check
c.swappers.across.supported, c.swappers.portals.supported and
c.swappers.zerion.supported only add a named import (via addNamedImport) into
AcrossSwapper/constant.ts, PortalsSwapper/constants.ts and
packages/types/src/zerion.ts respectively, which leaves the swappers
functionally unsupported and produces unused imports; update each branch to also
scaffold the actual supported-chain constants and filters by adding the
SupportedChainIds structure (with sell and buy keys) into the swapper's
utils/constants.ts (or constants.ts) and update any supported-chain mappings or
network mappings used by the swappers so the import becomes used and the swapper
is truly enabled (ensure you follow the SupportedChainIds type pattern and
update sell/buy filters and any network mapping arrays referenced by the
swappers when adding ${c.camelName}ChainId).
- Around line 1017-1033: The code computes nextNum and the insertion anchor
using only clearAssets matches which can collide with later non-clearAssets
migrations; update the logic in the wrap callback (the function operating on
migrationsFile) to find the highest migration key by scanning all migration
entries (e.g. match /(\d+): \w+,/ or similar) to derive lastNum and nextNum,
then use that lastNum both to compute nextNum and as the regex anchor passed to
appendLineAfterPattern (instead of the last clearAssets match); keep the
existing use of appendLineAfterPattern and the surrounding wrap/migrationsFile
flow.
In `@scripts/addChain/index.ts`:
- Line 1: The first-line shebang is incorrect because env treats the rest as a
single program name; update the script's first-line shebang (the shebang on the
first line) to use argument-splitting (e.g., use env with -S) so the "npx tsx"
arguments are passed correctly, or remove the shebang altogether and
document/require running the script via `npx tsx scripts/addChain/index.ts`;
ensure the change replaces the existing shebang only.
---
Duplicate comments:
In `@scripts/addChain/codemods.ts`:
- Around line 24-30: wrap() currently treats any falsy result from the codemod
function as a benign 'skipped' and hides anchor-misses (e.g., missing
clearAssets anchor reported from the codemod run around the clearAssets logic),
so change the behavior so anchor-miss paths surface as errors: update the
codemod functions that return false on "anchor not found" to throw a descriptive
Error (e.g., "anchor clearAssets not found"), and update wrap(fn) to stop
converting false into 'skipped' — let thrown errors propagate (or catch and
return status: 'error' with the error message) so anchor misses produce error
status instead of a green 'skipped'.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ce2f8977-3842-47f6-8435-df25973624bf
📒 Files selected for processing (5)
packages/contracts/src/fallbackRpcUrls.tsscripts/addChain/codemods.tsscripts/addChain/index.tsscripts/addChain/schema.tssrc/state/migrations/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- scripts/addChain/schema.ts
| wrap(migrationsFile, 'migrations-clearAssets', () => { | ||
| const src = fs.readFileSync(migrationsFile, 'utf8') | ||
| const matches = [...src.matchAll(/(\d+): clearAssets,/g)] | ||
| if (!matches.length) { | ||
| console.warn('[codemods] Could not find any clearAssets migration entries') | ||
| return false | ||
| } | ||
| const lastNum = Math.max(...matches.map(m => parseInt(m[1], 10))) | ||
| const nextNum = lastNum + 1 | ||
| if (src.includes(`${nextNum}: clearAssets`)) return false | ||
| return appendLineAfterPattern( | ||
| migrationsFile, | ||
| new RegExp(`${lastNum}: clearAssets,`), | ||
| ` ${nextNum}: clearAssets,`, | ||
| `${nextNum}: clearAssets`, | ||
| ) | ||
| }), |
There was a problem hiding this comment.
Allocate the next migration key from the highest existing migration.
This block derives nextNum from the last clearAssets entry, not the last migration entry. If the file already contains a later non-clearAssets migration, this can generate a duplicate object key and silently shadow one migration.
🔢 Suggested fix
- const matches = [...src.matchAll(/(\d+): clearAssets,/g)]
- if (!matches.length) {
- console.warn('[codemods] Could not find any clearAssets migration entries')
- return false
- }
- const lastNum = Math.max(...matches.map(m => parseInt(m[1], 10)))
- const nextNum = lastNum + 1
+ const migrationNumbers = [...src.matchAll(/^\s*(\d+):\s*\w+,/gm)]
+ if (!migrationNumbers.length) {
+ throw new Error('Could not find any migration entries')
+ }
+ const nextNum = Math.max(...migrationNumbers.map(m => parseInt(m[1], 10))) + 1Use the last migration entry as the insertion anchor as well, not the last clearAssets entry.
🧰 Tools
🪛 ast-grep (0.41.1)
[warning] 1028-1028: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(${lastNum}: clearAssets,)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/addChain/codemods.ts` around lines 1017 - 1033, The code computes
nextNum and the insertion anchor using only clearAssets matches which can
collide with later non-clearAssets migrations; update the logic in the wrap
callback (the function operating on migrationsFile) to find the highest
migration key by scanning all migration entries (e.g. match /(\d+): \w+,/ or
similar) to derive lastNum and nextNum, then use that lastNum both to compute
nextNum and as the regex anchor passed to appendLineAfterPattern (instead of the
last clearAssets match); keep the existing use of appendLineAfterPattern and the
surrounding wrap/migrationsFile flow.
There was a problem hiding this comment.
post-MVP improvement — noted
There was a problem hiding this comment.
@gomesalexandre, understood — noted for post-MVP hardening. 👍
✏️ Learnings added
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 12186
File: scripts/addChain/codemods.ts:1017-1033
Timestamp: 2026-03-17T22:57:46.580Z
Learning: In scripts/addChain/codemods.ts (around the migrations-clearAssets wrap block), the `nextNum` computation derives the next migration key from the last `clearAssets` entry only (not the global highest migration key across all entry types). This can theoretically generate a duplicate object key if a later non-clearAssets migration already exists at a higher number, but this is intentionally deferred as a post-MVP improvement by gomesalexandre and should not be re-flagged in future reviews.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 12186
File: scripts/addChain/codemods.ts:1529-1552
Timestamp: 2026-03-17T22:57:18.383Z
Learning: In scripts/addChain/codemods.ts, the chain adapter scaffold checks only for the class file (e.g., AbstractChainAdapter.ts) to determine if creation should be skipped, not the index.ts. If a prior run stopped between writes, the missing index.ts is never repaired. This partial-generation idempotency gap is intentionally deferred as a post-MVP improvement by gomesalexandre.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11569
File: headers/csps/chains/katana.ts:8-10
Timestamp: 2026-01-07T15:36:13.236Z
Learning: In CSP chain files (headers/csps/chains/*.ts), explicitly filtering undefined environment variables with .filter(Boolean) is unnecessary because serializeCsp() in headers/util.ts filters all falsy values during serialization at line 51: `.map(([k, v]) => [k, v.filter(x => !!x)])`. The direct pattern [env.VITE_*_NODE_URL] is sufficient and preferred for consistency with second-class chain CSP files like plasma.ts and monad.ts.
<!-- </add_learning>
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11275
File: headers/csps/chains/plasma.ts:1-10
Timestamp: 2025-12-03T23:19:39.158Z
Learning: For CSP files in headers/csps/chains/, gomesalexandre prefers using Vite's loadEnv() pattern directly to load environment variables (e.g., VITE_PLASMA_NODE_URL, VITE_MONAD_NODE_URL) for consistency with existing second-class chain CSP files, rather than using getConfig() from src/config.ts, even though other parts of the codebase use validated config values.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11924
File: packages/chain-adapters/src/evm/mantle/MantleChainAdapter.ts:1-1
Timestamp: 2026-02-21T10:55:55.870Z
Learning: For second-class EVM chain adapters (those extending SecondClassEvmAdapter), the type guard function (e.g., isMantleChainAdapter, isKatanaChainAdapter, isUnichainChainAdapter) exists in BOTH locations: in the adapter file itself (packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts) AND in src/lib/utils/[chain].ts with defensive null/undefined checks. This pattern is consistent across at least 14 second-class adapters (base, berachain, cronos, hyperevm, ink, katana, linea, mantle, megaeth, monad, optimism, plasma, scroll, sonic, unichain) and should be maintained for consistency unless a comprehensive refactor across all adapters is undertaken.
Learnt from: kaladinlight
Repo: shapeshift/web PR: 11290
File: packages/chain-adapters/src/utxo/zcash/ZcashChainAdapter.ts:48-51
Timestamp: 2025-12-04T22:57:50.850Z
Learning: In packages/chain-adapters/src/**/*ChainAdapter.ts files, the getName() method uses the pattern `const enumIndex = Object.values(ChainAdapterDisplayName).indexOf(ChainAdapterDisplayName.XXX); return Object.keys(ChainAdapterDisplayName)[enumIndex]` to reverse-lookup the enum key from its value. This is the established pattern used consistently across almost all chain adapters (Bitcoin, Ethereum, Litecoin, Dogecoin, Polygon, Arbitrum, Cosmos, etc.) and should be preserved for consistency when adding new chain adapters.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T20:28:34.883Z
Learning: In shapeshift/web, chains added to `walletConnectV2OptionalChains` and `rpcMap` in `src/context/WalletProvider/WalletConnectV2/config.ts` are intentionally NOT gated by their feature flags. Feature-flagged chains (e.g., ink, flowEvmChain, sei, abstract) are unconditionally included in these WalletConnect V2 structures. This is the established convention and should not be flagged as a missing feature-flag guard.
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/utils/constants.ts : Define supported chain IDs for each swapper in utils/constants.ts with both 'sell' and 'buy' properties following the pattern: SupportedChainIds type
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11930
File: packages/chain-adapters/src/evm/soneium/SoneiumChainAdapter.ts:18-20
Timestamp: 2026-02-21T14:23:27.392Z
Learning: In packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts files for second-class EVM adapters, the type guard function (e.g., isSoneiumChainAdapter, isMantleChainAdapter) intentionally uses a simple pattern without defensive null/undefined checks: `(adapter as ChainAdapter).getType() === KnownChainIds.[Chain]Mainnet`. These simple type guards are exported for optional per-chain narrowing but are not actively used in hot paths. In practice, callers always check `getChainAdapterManager().get(chainId)` first, so null is never passed. The null-safe production code path uses `isSecondClassEvmAdapter` via `instanceof`. This pattern is consistent across 20+ second-class adapters (Berachain, HyperEvm, Base, Optimism, Linea, Monad, Scroll, Ink, Mode, Sonic, Bob, Plasma, Mantle, Katana, Cronos, MegaEth, Unichain, Soneium). Any defensive null-check additions should be done comprehensively across all adapters in a dedicated cleanup PR, not piecemeal.
Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10290
File: scripts/generateAssetData/color-map.json:41-47
Timestamp: 2025-08-17T21:53:03.806Z
Learning: In the ShapeShift web codebase, native assets (using CAIP-19 slip44 namespace like eip155:1/slip44:60, bip122:.../slip44:..., cosmos:.../slip44:...) are manually hardcoded and not generated via the automated asset generation script. Only ERC20/BEP20 tokens go through the asset generation process. The validation scripts should only validate generated assets, not manually added native assets.
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/*.ts : Implement filterAssetIdsBySellable method to filter assets by supported chain IDs in the sell property
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11932
File: src/lib/utils/worldchain.ts:39-41
Timestamp: 2026-02-22T12:23:52.513Z
Learning: In src/lib/utils/[chain].ts files for second-class EVM chains (e.g., worldchain.ts, katana.ts, etc.), the per-chain utility functions like getWorldChainTransactionStatus() are effectively dead code after the migration to using the generic SecondClassEvmAdapter.getTransactionStatus() handler. Code quality concerns (like structured logging) for these files are not relevant since they're no longer actively used in hot paths.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10375
File: src/state/migrations/index.ts:214-215
Timestamp: 2025-08-27T13:49:48.668Z
Learning: The clearAssetsMigrations system in the ShapeShift web app works independently of the root persistConfig version. Migration numbers (like 171) don't need to match the root persistConfig version field, and the system has been functioning correctly for months/years without manual version bumps.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/codemods.ts, the `wrap()` helper intentionally uses `false` (from the engine) to mean "skipped/already present" and thrown exceptions to mean "error". The distinction between "anchor not found" vs "already present" in skip status is a known post-MVP UX improvement and does not affect scaffold correctness. Do not flag this as a masking issue.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/engine.ts, the `addNamedImport()` idempotency key format is intentional for the current MVP scaffolder. Hardening the idempotency key approach is catalogued as a post-MVP improvement. Do not flag the current format as incorrect.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11078
File: src/setupVitest.ts:11-15
Timestamp: 2025-11-20T12:00:45.005Z
Learning: In shapeshift/web, src/setupVitest.ts must redirect 'ethers' to 'ethers5' for shapeshiftoss/hdwallet-trezor (and -trezor-connect), same as ledger and shapeshift-multichain. Removing 'trezor' from the regex causes CI/Vitest failures due to ethers v6 vs v5 API differences.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 12125
File: src/state/slices/portfolioSlice/portfolioSlice.ts:138-162
Timestamp: 2026-03-09T21:57:24.467Z
Learning: In `src/state/slices/portfolioSlice/portfolioSlice.ts`, the `clearNonEvmAccountsForWallet` reducer unconditionally deletes global accountMetadata/accountBalances/accounts records for non-EVM accountIds. This is safe because ShapeShift only connects one wallet at a time, so no other wallet can reference the same accountIds. The reducer is only called during explicit MetaMask native-multichain <> snap mode switches, so there is no cross-wallet collision risk in practice and no need to check other wallets before deleting global records.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10375
File: src/state/migrations/index.ts:214-215
Timestamp: 2025-08-27T13:49:48.668Z
Learning: The ShapeShift web app uses an automated versioning system for Redux Persist migrations. The version is calculated as `Math.max(...Object.keys(clearAssetsMigrations).map(Number))`, which automatically uses the highest migration number as the version. This eliminates the need to manually update persistConfig versions when adding new migrations - the system automatically bumps the version when new migration numbers are added to the migration objects.
Learnt from: gomes-bot
Repo: shapeshift/web PR: 12049
File: .npmrc:1-4
Timestamp: 2026-03-01T22:00:52.269Z
Learning: In shapeshift/web migration PRs (e.g., package manager migrations), intentionally match the previous tool's default behavior rather than introducing stricter enforcement or improvements. For example, during the yarn→pnpm migration, strict-peer-dependencies=false and auto-install-peers=true were intentionally set to mirror yarn's defaults. Hardening steps like enabling strict peer enforcement should be tracked as separate follow-up PRs after the migration lands and stabilizes, not included in the migration PR scope.
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/**/*.ts : Use TypeScript with explicit types (e.g., SupportedChainIds) for all code in the Swapper system
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/config.ts:127-128
Timestamp: 2025-08-07T11:20:44.614Z
Learning: gomesalexandre prefers required environment variables without default values in the config file (src/config.ts). They want explicit configuration and fail-fast behavior when environment variables are missing, rather than having fallback defaults.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx:0-0
Timestamp: 2025-09-13T16:45:18.813Z
Learning: gomesalexandre prefers aggressively deleting unused/obsolete code files ("ramboing") rather than fixing technical issues in code that won't be used, demonstrating his preference for keeping codebases clean and PR scope focused.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/types.ts:7-7
Timestamp: 2025-09-10T15:34:29.604Z
Learning: gomesalexandre is comfortable relying on transitive dependencies (like abitype through ethers/viem) rather than explicitly declaring them in package.json, preferring to avoid package.json bloat when the transitive dependency approach works reliably in practice.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10503
File: .env:56-56
Timestamp: 2025-09-16T13:17:02.938Z
Learning: gomesalexandre prefers to enable feature flags globally in the base .env file when the intent is to activate features everywhere, even when there are known issues like crashes, demonstrating his preference for intentional global feature rollouts over cautious per-environment enablement.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:447-503
Timestamp: 2025-08-13T17:07:10.763Z
Learning: gomesalexandre prefers relying on TypeScript's type system for validation rather than adding defensive runtime null checks when types are properly defined. They favor a TypeScript-first approach over defensive programming with runtime validations.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/hooks/useActionCenterSubscribers/useThorchainLpDepositActionSubscriber.tsx:61-66
Timestamp: 2025-08-14T17:51:47.556Z
Learning: gomesalexandre is not concerned about structured logging and prefers to keep console.error usage as-is rather than implementing structured logging patterns, even when project guidelines suggest otherwise.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10413
File: src/components/Modals/FiatRamps/fiatRampProviders/onramper/utils.ts:29-55
Timestamp: 2025-09-02T14:26:19.028Z
Learning: gomesalexandre prefers to keep preparatory/reference code simple until it's actively consumed, rather than implementing comprehensive error handling, validation, and robustness improvements upfront. They prefer to add these improvements when the code is actually being used in production.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:396-402
Timestamp: 2025-08-14T17:55:57.490Z
Learning: gomesalexandre is comfortable with functions/variables that return undefined or true (tri-state) when only the truthy case matters, preferring to rely on JavaScript's truthy/falsy behavior rather than explicitly returning boolean values.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10783
File: src/context/ModalStackProvider/useModalRegistration.ts:30-41
Timestamp: 2025-10-16T11:14:40.657Z
Learning: gomesalexandre prefers to add lint rules (like typescript-eslint/strict-boolean-expressions for truthiness checks on numbers) to catch common issues project-wide rather than relying on code review to catch them.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/lib/moralis.ts:47-85
Timestamp: 2025-08-07T11:22:16.983Z
Learning: gomesalexandre prefers console.error over structured logging for Moralis API integration debugging, as they find it more conventional and prefer to examine XHR requests directly rather than rely on structured logs for troubleshooting.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In shapeshift/web, the batch-prefetch in src/lib/account/evm.ts gates on `wallet.ethGetAddresses`, which is chain-agnostic and works for any EVM-capable wallet regardless of chain-specific support flags like `supportsAbstract`. The chain-specific `supports*` guard is enforced downstream in `deriveEvmAccountIdsAndMetadata`. This pattern is identical across all second-class EVM chains and should not be flagged as a missing pre-check.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:133-137
Timestamp: 2025-09-12T10:15:10.389Z
Learning: gomesalexandre has identified that EIP-712 domain chainId should be preferred over request context chainId for accuracy in WalletConnect dApps structured signing flows. The domain chainId from the parsed message is more specific and accurate than the general request context, especially for asset resolution and network-specific operations.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T01:29:21.619Z
Learning: In shapeshift/web PR `#12181`, the primary fix is replacing SHA-based comparison (`privateSha`) with a content diff approach (`privateContentMatchesMain` boolean) in `deriveReleaseState`/`deriveHotfixState` in `scripts/release.ts`. This unblocks new releases when `private` has been squash-synced with `main` (SHA differs even though content is identical). The secondary fix — `createPr` returning `null` on "No commits between" GitHub error — is a defensive improvement bundled in the same PR. The PR title only references the secondary change; the commit message body captures both.
| // 40. Across swapper - conditional | ||
| if (c.swappers.across.supported) { | ||
| const acrossConstFile = r('packages/swapper/src/swappers/AcrossSwapper/constant.ts') | ||
| if (fs.existsSync(acrossConstFile)) { | ||
| results.push( | ||
| wrap(acrossConstFile, 'across-chain-support', () => | ||
| addNamedImport(acrossConstFile, '@shapeshiftoss/caip', `${c.camelName}ChainId`), | ||
| ), | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| // 41. Portals swapper - conditional | ||
| if (c.swappers.portals.supported) { | ||
| const portalsConstFile = r('packages/swapper/src/swappers/PortalsSwapper/constants.ts') | ||
| if (fs.existsSync(portalsConstFile)) { | ||
| results.push( | ||
| wrap(portalsConstFile, 'portals-chain-support', () => | ||
| addNamedImport(portalsConstFile, '@shapeshiftoss/caip', `${c.camelName}ChainId`), | ||
| ), | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| // 42. Zerion - conditional | ||
| if (c.swappers.zerion.supported) { | ||
| const zerionFile = r('packages/types/src/zerion.ts') | ||
| if (fs.existsSync(zerionFile)) { | ||
| results.push( | ||
| wrap(zerionFile, 'zerion-chain-support', () => | ||
| addNamedImport(zerionFile, '@shapeshiftoss/caip', `${c.camelName}ChainId`), | ||
| ), | ||
| ) | ||
| } | ||
| } |
There was a problem hiding this comment.
These supported swapper branches are effectively no-ops.
When supported is true, Across/Portals/Zerion only gain a ${c.camelName}ChainId import. Nothing here updates supported-chain constants, sell/buy filters, or network mappings, so the scaffolder can report success while the swapper remains unsupported and the inserted import is likely unused. Either scaffold the real support surfaces here or keep these integrations in the manual checklist.
Based on learnings: Applies to packages/swapper/src/swappers/*/utils/constants.ts : Define supported chain IDs for each swapper in utils/constants.ts with both sell and buy properties following the pattern: SupportedChainIds type.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/addChain/codemods.ts` around lines 1101 - 1135, The current
conditional branches that check c.swappers.across.supported,
c.swappers.portals.supported and c.swappers.zerion.supported only add a named
import (via addNamedImport) into AcrossSwapper/constant.ts,
PortalsSwapper/constants.ts and packages/types/src/zerion.ts respectively, which
leaves the swappers functionally unsupported and produces unused imports; update
each branch to also scaffold the actual supported-chain constants and filters by
adding the SupportedChainIds structure (with sell and buy keys) into the
swapper's utils/constants.ts (or constants.ts) and update any supported-chain
mappings or network mappings used by the swappers so the import becomes used and
the swapper is truly enabled (ensure you follow the SupportedChainIds type
pattern and update sell/buy filters and any network mapping arrays referenced by
the swappers when adding ${c.camelName}ChainId).
There was a problem hiding this comment.
acknowledged — full swapper integration varies per swapper; will tighten when those swappers get Abstract support
There was a problem hiding this comment.
@gomesalexandre, understood — that makes sense given swapper integration varies per swapper and needs research beyond scaffolding. Would you like me to open a follow-up GitHub issue to track tightening the Across/Portals/Zerion scaffolding branches for Abstract (and future chains) when those swappers add support?
🧠 Learnings used
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11569
File: headers/csps/chains/katana.ts:8-10
Timestamp: 2026-01-07T15:36:13.236Z
Learning: In CSP chain files (headers/csps/chains/*.ts), explicitly filtering undefined environment variables with .filter(Boolean) is unnecessary because serializeCsp() in headers/util.ts filters all falsy values during serialization at line 51: `.map(([k, v]) => [k, v.filter(x => !!x)])`. The direct pattern [env.VITE_*_NODE_URL] is sufficient and preferred for consistency with second-class chain CSP files like plasma.ts and monad.ts.
<!-- </add_learning>
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11275
File: headers/csps/chains/plasma.ts:1-10
Timestamp: 2025-12-03T23:19:39.158Z
Learning: For CSP files in headers/csps/chains/, gomesalexandre prefers using Vite's loadEnv() pattern directly to load environment variables (e.g., VITE_PLASMA_NODE_URL, VITE_MONAD_NODE_URL) for consistency with existing second-class chain CSP files, rather than using getConfig() from src/config.ts, even though other parts of the codebase use validated config values.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11924
File: packages/chain-adapters/src/evm/mantle/MantleChainAdapter.ts:1-1
Timestamp: 2026-02-21T10:55:55.870Z
Learning: For second-class EVM chain adapters (those extending SecondClassEvmAdapter), the type guard function (e.g., isMantleChainAdapter, isKatanaChainAdapter, isUnichainChainAdapter) exists in BOTH locations: in the adapter file itself (packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts) AND in src/lib/utils/[chain].ts with defensive null/undefined checks. This pattern is consistent across at least 14 second-class adapters (base, berachain, cronos, hyperevm, ink, katana, linea, mantle, megaeth, monad, optimism, plasma, scroll, sonic, unichain) and should be maintained for consistency unless a comprehensive refactor across all adapters is undertaken.
Learnt from: kaladinlight
Repo: shapeshift/web PR: 11290
File: packages/chain-adapters/src/utxo/zcash/ZcashChainAdapter.ts:48-51
Timestamp: 2025-12-04T22:57:50.850Z
Learning: In packages/chain-adapters/src/**/*ChainAdapter.ts files, the getName() method uses the pattern `const enumIndex = Object.values(ChainAdapterDisplayName).indexOf(ChainAdapterDisplayName.XXX); return Object.keys(ChainAdapterDisplayName)[enumIndex]` to reverse-lookup the enum key from its value. This is the established pattern used consistently across almost all chain adapters (Bitcoin, Ethereum, Litecoin, Dogecoin, Polygon, Arbitrum, Cosmos, etc.) and should be preserved for consistency when adding new chain adapters.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T20:28:34.883Z
Learning: In shapeshift/web, chains added to `walletConnectV2OptionalChains` and `rpcMap` in `src/context/WalletProvider/WalletConnectV2/config.ts` are intentionally NOT gated by their feature flags. Feature-flagged chains (e.g., ink, flowEvmChain, sei, abstract) are unconditionally included in these WalletConnect V2 structures. This is the established convention and should not be flagged as a missing feature-flag guard.
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/utils/constants.ts : Define supported chain IDs for each swapper in utils/constants.ts with both 'sell' and 'buy' properties following the pattern: SupportedChainIds type
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11930
File: packages/chain-adapters/src/evm/soneium/SoneiumChainAdapter.ts:18-20
Timestamp: 2026-02-21T14:23:27.392Z
Learning: In packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts files for second-class EVM adapters, the type guard function (e.g., isSoneiumChainAdapter, isMantleChainAdapter) intentionally uses a simple pattern without defensive null/undefined checks: `(adapter as ChainAdapter).getType() === KnownChainIds.[Chain]Mainnet`. These simple type guards are exported for optional per-chain narrowing but are not actively used in hot paths. In practice, callers always check `getChainAdapterManager().get(chainId)` first, so null is never passed. The null-safe production code path uses `isSecondClassEvmAdapter` via `instanceof`. This pattern is consistent across 20+ second-class adapters (Berachain, HyperEvm, Base, Optimism, Linea, Monad, Scroll, Ink, Mode, Sonic, Bob, Plasma, Mantle, Katana, Cronos, MegaEth, Unichain, Soneium). Any defensive null-check additions should be done comprehensively across all adapters in a dedicated cleanup PR, not piecemeal.
Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10290
File: scripts/generateAssetData/color-map.json:41-47
Timestamp: 2025-08-17T21:53:03.806Z
Learning: In the ShapeShift web codebase, native assets (using CAIP-19 slip44 namespace like eip155:1/slip44:60, bip122:.../slip44:..., cosmos:.../slip44:...) are manually hardcoded and not generated via the automated asset generation script. Only ERC20/BEP20 tokens go through the asset generation process. The validation scripts should only validate generated assets, not manually added native assets.
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/*.ts : Implement filterAssetIdsBySellable method to filter assets by supported chain IDs in the sell property
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/*.ts : Implement filterBuyAssetsBySellAssetId method to filter assets by supported chain IDs in the buy property
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11941
File: packages/swapper/src/swappers/DebridgeSwapper/constant.ts:1-39
Timestamp: 2026-02-24T12:43:24.555Z
Learning: In shapeshift/web, swappers do not have a single enforced location for constants files. Many DEX-style swappers place them at packages/swapper/src/swappers/<SwapperName>/utils/constants.ts (e.g., ZrxSwapper, JupiterSwapper, CetusSwapper, AvnuSwapper, ButterSwap, StonfiSwapper, SunioSwapper, ArbitrumBridgeSwapper), while several bridge-oriented swappers (AcrossSwapper, RelaySwapper, PortalsSwapper, ChainflipSwapper) use a root-level constants file at packages/swapper/src/swappers/<SwapperName>/constant.ts. For consistency with bridge-style swappers, DebridgeSwapper should keep constant.ts at the swapper root.
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/**/*.ts : Use TypeScript with explicit types (e.g., SupportedChainIds) for all code in the Swapper system
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-16T21:35:02.159Z
Learning: In packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts (and related files like src/components/MultiHopTrade/components/TradeConfirm/hooks/useChainflipStreamingProgress.tsx), nullish checks (`== null` / `!= null`) MUST be used for `chainflipSwapId` instead of falsy checks, because `0` is a valid u64 swap ID that is falsy in JavaScript. Using `if (!chainflipSwapId)` would incorrectly discard a valid swap ID of `0`.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11335
File: packages/swapper/src/swappers/CetusSwapper/utils/helpers.ts:3-3
Timestamp: 2025-12-09T21:07:22.474Z
Learning: In packages/swapper/src/swappers/CetusSwapper, mysten/sui types (SuiClient, Transaction) must be imported from the nested path within cetusprotocol/aggregator-sdk (e.g., 'cetusprotocol/aggregator-sdk/node_modules/mysten/sui/client') because the aggregator SDK bundles its own version of mysten/sui. Direct imports from 'mysten/sui' break at runtime even when specified in package.json.
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/**/*.ts : Adhere to the Swapper directory structure: each swapper resides in packages/swapper/src/swappers/<SwapperName>/ with required files (SwapperName.ts, endpoints.ts, types.ts, utils/constants.ts, utils/helpers.ts)
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In shapeshift/web, the batch-prefetch in src/lib/account/evm.ts gates on `wallet.ethGetAddresses`, which is chain-agnostic and works for any EVM-capable wallet regardless of chain-specific support flags like `supportsAbstract`. The chain-specific `supports*` guard is enforced downstream in `deriveEvmAccountIdsAndMetadata`. This pattern is identical across all second-class EVM chains and should not be flagged as a missing pre-check.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11281
File: packages/swapper/src/swappers/PortalsSwapper/utils/fetchSquidStatus.ts:98-106
Timestamp: 2025-12-04T11:05:01.146Z
Learning: In packages/swapper/src/swappers/PortalsSwapper/utils/fetchSquidStatus.ts, getSquidTrackingLink should return blockchain explorer links (using Asset.explorerTxLink) rather than API endpoints. For non-GMP Squid swaps: return source chain explorer link with sourceTxHash when pending/failed, and destination chain explorer link with destinationTxHash when confirmed.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 12178
File: packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts:238-239
Timestamp: 2026-03-16T18:38:42.205Z
Learning: In packages/swapper/src/swappers/ChainflipSwapper, `chainflipSwapId` intentionally uses a `number | string` union type. The Chainflip SDK (`swapResponse.id`) returns a `number`, while the status API (`status.swapId`) returns a `string` representing a u64. The `Number()` coercion must NOT be applied to the status API value because u64 can exceed JavaScript's `Number.MAX_SAFE_INTEGER` (2^53-1), causing precision loss. The string is kept as-is and flows directly into URL parameters and metadata.
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/*.ts : All swappers must implement the Swapper interface from packages/swapper/src/types.ts
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:93-93
Timestamp: 2025-11-12T12:48:02.977Z
Learning: In the swapper architecture, timeout handling is implemented at the abstraction layer in packages/swapper/src/swapper.ts using timeoutMonadic, which wraps all calls to individual swapper implementations. Individual swapper implementations (e.g., NearIntentsSwapper, PortalsSwapper, etc.) should NOT use timeoutMonadic directly—they simply return their results and the abstraction layer handles timeout concerns centrally.
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/constants.ts : Register new swappers in packages/swapper/src/constants.ts with an entry in the swappers registry mapping SwapperName enum to swapper implementation
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/codemods.ts, the `wrap()` helper intentionally uses `false` (from the engine) to mean "skipped/already present" and thrown exceptions to mean "error". The distinction between "anchor not found" vs "already present" in skip status is a known post-MVP UX improvement and does not affect scaffold correctness. Do not flag this as a masking issue.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/engine.ts, the `addNamedImport()` idempotency key format is intentional for the current MVP scaffolder. Hardening the idempotency key approach is catalogued as a post-MVP improvement. Do not flag the current format as incorrect.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11932
File: src/lib/utils/worldchain.ts:39-41
Timestamp: 2026-02-22T12:23:52.513Z
Learning: In src/lib/utils/[chain].ts files for second-class EVM chains (e.g., worldchain.ts, katana.ts, etc.), the per-chain utility functions like getWorldChainTransactionStatus() are effectively dead code after the migration to using the generic SecondClassEvmAdapter.getTransactionStatus() handler. Code quality concerns (like structured logging) for these files are not relevant since they're no longer actively used in hot paths.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/config.ts:127-128
Timestamp: 2025-08-07T11:20:44.614Z
Learning: gomesalexandre prefers required environment variables without default values in the config file (src/config.ts). They want explicit configuration and fail-fast behavior when environment variables are missing, rather than having fallback defaults.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx:0-0
Timestamp: 2025-09-13T16:45:18.813Z
Learning: gomesalexandre prefers aggressively deleting unused/obsolete code files ("ramboing") rather than fixing technical issues in code that won't be used, demonstrating his preference for keeping codebases clean and PR scope focused.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/types.ts:7-7
Timestamp: 2025-09-10T15:34:29.604Z
Learning: gomesalexandre is comfortable relying on transitive dependencies (like abitype through ethers/viem) rather than explicitly declaring them in package.json, preferring to avoid package.json bloat when the transitive dependency approach works reliably in practice.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10503
File: .env:56-56
Timestamp: 2025-09-16T13:17:02.938Z
Learning: gomesalexandre prefers to enable feature flags globally in the base .env file when the intent is to activate features everywhere, even when there are known issues like crashes, demonstrating his preference for intentional global feature rollouts over cautious per-environment enablement.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:447-503
Timestamp: 2025-08-13T17:07:10.763Z
Learning: gomesalexandre prefers relying on TypeScript's type system for validation rather than adding defensive runtime null checks when types are properly defined. They favor a TypeScript-first approach over defensive programming with runtime validations.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/hooks/useActionCenterSubscribers/useThorchainLpDepositActionSubscriber.tsx:61-66
Timestamp: 2025-08-14T17:51:47.556Z
Learning: gomesalexandre is not concerned about structured logging and prefers to keep console.error usage as-is rather than implementing structured logging patterns, even when project guidelines suggest otherwise.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10413
File: src/components/Modals/FiatRamps/fiatRampProviders/onramper/utils.ts:29-55
Timestamp: 2025-09-02T14:26:19.028Z
Learning: gomesalexandre prefers to keep preparatory/reference code simple until it's actively consumed, rather than implementing comprehensive error handling, validation, and robustness improvements upfront. They prefer to add these improvements when the code is actually being used in production.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:396-402
Timestamp: 2025-08-14T17:55:57.490Z
Learning: gomesalexandre is comfortable with functions/variables that return undefined or true (tri-state) when only the truthy case matters, preferring to rely on JavaScript's truthy/falsy behavior rather than explicitly returning boolean values.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10783
File: src/context/ModalStackProvider/useModalRegistration.ts:30-41
Timestamp: 2025-10-16T11:14:40.657Z
Learning: gomesalexandre prefers to add lint rules (like typescript-eslint/strict-boolean-expressions for truthiness checks on numbers) to catch common issues project-wide rather than relying on code review to catch them.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/lib/moralis.ts:47-85
Timestamp: 2025-08-07T11:22:16.983Z
Learning: gomesalexandre prefers console.error over structured logging for Moralis API integration debugging, as they find it more conventional and prefer to examine XHR requests directly rather than rely on structured logs for troubleshooting.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:133-137
Timestamp: 2025-09-12T10:15:10.389Z
Learning: gomesalexandre has identified that EIP-712 domain chainId should be preferred over request context chainId for accuracy in WalletConnect dApps structured signing flows. The domain chainId from the parsed message is more specific and accurate than the general request context, especially for asset resolution and network-specific operations.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T01:29:21.619Z
Learning: In shapeshift/web PR `#12181`, the primary fix is replacing SHA-based comparison (`privateSha`) with a content diff approach (`privateContentMatchesMain` boolean) in `deriveReleaseState`/`deriveHotfixState` in `scripts/release.ts`. This unblocks new releases when `private` has been squash-synced with `main` (SHA differs even though content is identical). The secondary fix — `createPr` returning `null` on "No commits between" GitHub error — is a defensive improvement bundled in the same PR. The PR title only references the secondary change; the commit message body captures both.
Learnt from: gomes-bot
Repo: shapeshift/web PR: 11884
File: packages/chain-adapters/src/tron/TronChainAdapter.ts:732-735
Timestamp: 2026-02-16T15:00:09.111Z
Learning: In packages/chain-adapters/src/tron/TronChainAdapter.ts, inline comments explaining non-obvious domain-specific behavior (e.g., why TRC20 burns to zero address are allowed while mints from zero address are skipped) are acceptable when explicitly requested, especially when the rationale is easy to regress (e.g., sTRX unstaking burn behavior).
| const adapterDir = r(`packages/chain-adapters/src/evm/${c.camelName}`) | ||
| const adapterFile = r( | ||
| `packages/chain-adapters/src/evm/${c.camelName}/${c.pascalName}ChainAdapter.ts`, | ||
| ) | ||
| if (!fs.existsSync(adapterFile)) { | ||
| fs.mkdirSync(adapterDir, { recursive: true }) | ||
| fs.writeFileSync(adapterFile, fill(tmpl('chainAdapter.ts.tmpl'), c)) | ||
| fs.writeFileSync( | ||
| r(`packages/chain-adapters/src/evm/${c.camelName}/index.ts`), | ||
| fill(tmpl('chainAdapterIndex.ts.tmpl'), c), | ||
| ) | ||
| results.push({ | ||
| file: adapterFile, | ||
| operation: 'create-chain-adapter', | ||
| status: 'inserted', | ||
| }) | ||
| } else { | ||
| results.push({ | ||
| file: adapterFile, | ||
| operation: 'create-chain-adapter', | ||
| status: 'skipped', | ||
| message: 'already exists', | ||
| }) | ||
| } |
There was a problem hiding this comment.
Handle partial adapter generation instead of keying only off the class file.
This block creates two artifacts—the chain adapter class and the folder index.ts—but reruns skip as soon as the class file exists. If a previous run stopped between those writes, the missing index.ts is never repaired, so the scaffolder is not actually idempotent.
🧩 Suggested fix
const adapterDir = r(`packages/chain-adapters/src/evm/${c.camelName}`)
const adapterFile = r(
`packages/chain-adapters/src/evm/${c.camelName}/${c.pascalName}ChainAdapter.ts`,
)
- if (!fs.existsSync(adapterFile)) {
+ const adapterIndexFile = r(`packages/chain-adapters/src/evm/${c.camelName}/index.ts`)
+ if (!fs.existsSync(adapterFile) || !fs.existsSync(adapterIndexFile)) {
fs.mkdirSync(adapterDir, { recursive: true })
- fs.writeFileSync(adapterFile, fill(tmpl('chainAdapter.ts.tmpl'), c))
- fs.writeFileSync(
- r(`packages/chain-adapters/src/evm/${c.camelName}/index.ts`),
- fill(tmpl('chainAdapterIndex.ts.tmpl'), c),
- )
+ if (!fs.existsSync(adapterFile)) {
+ fs.writeFileSync(adapterFile, fill(tmpl('chainAdapter.ts.tmpl'), c))
+ }
+ if (!fs.existsSync(adapterIndexFile)) {
+ fs.writeFileSync(adapterIndexFile, fill(tmpl('chainAdapterIndex.ts.tmpl'), c))
+ }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/addChain/codemods.ts` around lines 1529 - 1552, The scaffold
currently decides to skip creation based solely on adapterFile existence
(variable adapterFile) which leaves index.ts missing if a previous run failed;
update the logic in codemods.ts to check both the class file and the index file
(the path used in the second writeFileSync call) — if the directory doesn't
exist create it, then individually ensure the class file and the index.ts are
created when absent (using the same fill(tmpl(...), c) calls), and push
appropriate results entries for each artifact instead of a single
skipped/inserted result so partial generation is repaired on re-run.
There was a problem hiding this comment.
post-MVP — noted
There was a problem hiding this comment.
@gomesalexandre, understood — acknowledged as a post-MVP improvement.
✏️ Learnings added
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 12186
File: scripts/addChain/codemods.ts:1529-1552
Timestamp: 2026-03-17T22:57:18.383Z
Learning: In scripts/addChain/codemods.ts, the chain adapter scaffold checks only for the class file (e.g., AbstractChainAdapter.ts) to determine if creation should be skipped, not the index.ts. If a prior run stopped between writes, the missing index.ts is never repaired. This partial-generation idempotency gap is intentionally deferred as a post-MVP improvement by gomesalexandre.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
🧠 Learnings used
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11569
File: headers/csps/chains/katana.ts:8-10
Timestamp: 2026-01-07T15:36:13.236Z
Learning: In CSP chain files (headers/csps/chains/*.ts), explicitly filtering undefined environment variables with .filter(Boolean) is unnecessary because serializeCsp() in headers/util.ts filters all falsy values during serialization at line 51: `.map(([k, v]) => [k, v.filter(x => !!x)])`. The direct pattern [env.VITE_*_NODE_URL] is sufficient and preferred for consistency with second-class chain CSP files like plasma.ts and monad.ts.
<!-- </add_learning>
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11275
File: headers/csps/chains/plasma.ts:1-10
Timestamp: 2025-12-03T23:19:39.158Z
Learning: For CSP files in headers/csps/chains/, gomesalexandre prefers using Vite's loadEnv() pattern directly to load environment variables (e.g., VITE_PLASMA_NODE_URL, VITE_MONAD_NODE_URL) for consistency with existing second-class chain CSP files, rather than using getConfig() from src/config.ts, even though other parts of the codebase use validated config values.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11924
File: packages/chain-adapters/src/evm/mantle/MantleChainAdapter.ts:1-1
Timestamp: 2026-02-21T10:55:55.870Z
Learning: For second-class EVM chain adapters (those extending SecondClassEvmAdapter), the type guard function (e.g., isMantleChainAdapter, isKatanaChainAdapter, isUnichainChainAdapter) exists in BOTH locations: in the adapter file itself (packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts) AND in src/lib/utils/[chain].ts with defensive null/undefined checks. This pattern is consistent across at least 14 second-class adapters (base, berachain, cronos, hyperevm, ink, katana, linea, mantle, megaeth, monad, optimism, plasma, scroll, sonic, unichain) and should be maintained for consistency unless a comprehensive refactor across all adapters is undertaken.
Learnt from: kaladinlight
Repo: shapeshift/web PR: 11290
File: packages/chain-adapters/src/utxo/zcash/ZcashChainAdapter.ts:48-51
Timestamp: 2025-12-04T22:57:50.850Z
Learning: In packages/chain-adapters/src/**/*ChainAdapter.ts files, the getName() method uses the pattern `const enumIndex = Object.values(ChainAdapterDisplayName).indexOf(ChainAdapterDisplayName.XXX); return Object.keys(ChainAdapterDisplayName)[enumIndex]` to reverse-lookup the enum key from its value. This is the established pattern used consistently across almost all chain adapters (Bitcoin, Ethereum, Litecoin, Dogecoin, Polygon, Arbitrum, Cosmos, etc.) and should be preserved for consistency when adding new chain adapters.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T20:28:34.883Z
Learning: In shapeshift/web, chains added to `walletConnectV2OptionalChains` and `rpcMap` in `src/context/WalletProvider/WalletConnectV2/config.ts` are intentionally NOT gated by their feature flags. Feature-flagged chains (e.g., ink, flowEvmChain, sei, abstract) are unconditionally included in these WalletConnect V2 structures. This is the established convention and should not be flagged as a missing feature-flag guard.
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/utils/constants.ts : Define supported chain IDs for each swapper in utils/constants.ts with both 'sell' and 'buy' properties following the pattern: SupportedChainIds type
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11930
File: packages/chain-adapters/src/evm/soneium/SoneiumChainAdapter.ts:18-20
Timestamp: 2026-02-21T14:23:27.392Z
Learning: In packages/chain-adapters/src/evm/[chain]/[Chain]ChainAdapter.ts files for second-class EVM adapters, the type guard function (e.g., isSoneiumChainAdapter, isMantleChainAdapter) intentionally uses a simple pattern without defensive null/undefined checks: `(adapter as ChainAdapter).getType() === KnownChainIds.[Chain]Mainnet`. These simple type guards are exported for optional per-chain narrowing but are not actively used in hot paths. In practice, callers always check `getChainAdapterManager().get(chainId)` first, so null is never passed. The null-safe production code path uses `isSecondClassEvmAdapter` via `instanceof`. This pattern is consistent across 20+ second-class adapters (Berachain, HyperEvm, Base, Optimism, Linea, Monad, Scroll, Ink, Mode, Sonic, Bob, Plasma, Mantle, Katana, Cronos, MegaEth, Unichain, Soneium). Any defensive null-check additions should be done comprehensively across all adapters in a dedicated cleanup PR, not piecemeal.
Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10290
File: scripts/generateAssetData/color-map.json:41-47
Timestamp: 2025-08-17T21:53:03.806Z
Learning: In the ShapeShift web codebase, native assets (using CAIP-19 slip44 namespace like eip155:1/slip44:60, bip122:.../slip44:..., cosmos:.../slip44:...) are manually hardcoded and not generated via the automated asset generation script. Only ERC20/BEP20 tokens go through the asset generation process. The validation scripts should only validate generated assets, not manually added native assets.
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/*.ts : Implement filterAssetIdsBySellable method to filter assets by supported chain IDs in the sell property
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/src/swappers/*/*.ts : Implement filterBuyAssetsBySellAssetId method to filter assets by supported chain IDs in the buy property
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In shapeshift/web, the batch-prefetch in src/lib/account/evm.ts gates on `wallet.ethGetAddresses`, which is chain-agnostic and works for any EVM-capable wallet regardless of chain-specific support flags like `supportsAbstract`. The chain-specific `supports*` guard is enforced downstream in `deriveEvmAccountIdsAndMetadata`. This pattern is identical across all second-class EVM chains and should not be flagged as a missing pre-check.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10857
File: src/plugins/walletConnectToDapps/eventsManager/useWalletConnectEventsHandler.ts:101-104
Timestamp: 2025-10-23T14:27:19.073Z
Learning: In WalletConnect wallet_switchEthereumChain and wallet_addEthereumChain requests, the chainId parameter is always present as per the protocol spec. Type guards checking for missing chainId in these handlers (like `if (!evmNetworkIdHex) return`) are solely for TypeScript compiler satisfaction, not real runtime edge cases.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-16T21:35:02.159Z
Learning: In packages/swapper/src/swappers/ChainflipSwapper/endpoints.ts (and related files like src/components/MultiHopTrade/components/TradeConfirm/hooks/useChainflipStreamingProgress.tsx), nullish checks (`== null` / `!= null`) MUST be used for `chainflipSwapId` instead of falsy checks, because `0` is a valid u64 swap ID that is falsy in JavaScript. Using `if (!chainflipSwapId)` would incorrectly discard a valid swap ID of `0`.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/TradeAssetSearch/hooks/useGetPopularAssetsQuery.tsx:28-33
Timestamp: 2025-09-04T17:29:59.479Z
Learning: In shapeshift/web, the useGetPopularAssetsQuery function in src/components/TradeAssetSearch/hooks/useGetPopularAssetsQuery.tsx intentionally uses primaryAssets[assetId] instead of falling back to assets[assetId]. The design distributes primary assets across chains by iterating through their related assets and adding the primary asset to each related asset's chain. This ensures primary assets appear in all chains where they have related assets, supporting the grouped asset system.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11569
File: packages/chain-adapters/src/evm/katana/KatanaChainAdapter.ts:44-46
Timestamp: 2026-01-05T23:24:54.841Z
Learning: In packages/chain-adapters/src/evm/**/[chain]ChainAdapter.ts files, second-class EVM chain adapters (those extending SecondClassEvmAdapter, such as Monad, Plasma, HyperEVM, and Katana) use hardcoded strings in their getName() method (e.g., `return 'Monad'`), NOT the enum reverse-lookup pattern. The enum reverse-lookup pattern (`Object.values(ChainAdapterDisplayName).indexOf(...)`) only applies to first-class chain adapters.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11932
File: src/lib/utils/worldchain.ts:39-41
Timestamp: 2026-02-22T12:23:52.513Z
Learning: In src/lib/utils/[chain].ts files for second-class EVM chains (e.g., worldchain.ts, katana.ts, etc.), the per-chain utility functions like getWorldChainTransactionStatus() are effectively dead code after the migration to using the generic SecondClassEvmAdapter.getTransactionStatus() handler. Code quality concerns (like structured logging) for these files are not relevant since they're no longer actively used in hot paths.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11078
File: src/setupVitest.ts:11-15
Timestamp: 2025-11-20T12:00:45.005Z
Learning: In shapeshift/web, src/setupVitest.ts must redirect 'ethers' to 'ethers5' for shapeshiftoss/hdwallet-trezor (and -trezor-connect), same as ledger and shapeshift-multichain. Removing 'trezor' from the regex causes CI/Vitest failures due to ethers v6 vs v5 API differences.
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10369
File: packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts:167-176
Timestamp: 2025-08-26T19:04:38.672Z
Learning: In packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts, when processing assets from data.assets.reduce(), the team prefers using empty catch blocks to gracefully skip any assets that fail processing, rather than specific error type handling, to avoid useless noise and ensure robust asset filtering.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/engine.ts, the `addNamedImport()` idempotency key format is intentional for the current MVP scaffolder. Hardening the idempotency key approach is catalogued as a post-MVP improvement. Do not flag the current format as incorrect.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T21:54:13.597Z
Learning: In scripts/addChain/codemods.ts, the `wrap()` helper intentionally uses `false` (from the engine) to mean "skipped/already present" and thrown exceptions to mean "error". The distinction between "anchor not found" vs "already present" in skip status is a known post-MVP UX improvement and does not affect scaffold correctness. Do not flag this as a masking issue.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/hooks/useSimulateEvmTransaction.ts:0-0
Timestamp: 2025-09-12T13:44:17.019Z
Learning: gomesalexandre prefers letting chain adapter errors throw naturally in useSimulateEvmTransaction rather than adding explicit error handling for missing adapters, consistent with his fail-fast approach and dismissal of defensive validation as "stale" in WalletConnect transaction simulation flows.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11012
File: src/context/WalletProvider/Vultisig/components/Connect.tsx:24-59
Timestamp: 2025-11-19T16:59:50.569Z
Learning: In src/context/WalletProvider/*/components/Connect.tsx files across the ShapeShift web codebase, the established pattern for handling null/undefined adapter from getAdapter() is to simply check `if (adapter) { ... }` without an else clause. All wallet Connect components (Coinbase, Keplr, Phantom, Ledger, MetaMask, WalletConnectV2, KeepKey, Vultisig) follow this pattern—they reset loading state after the if block but do not show error messages when adapter is null. This is an intentional design decision and should be maintained for consistency.
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/**/*.ts : Use TypeScript with explicit types (e.g., SupportedChainIds) for all code in the Swapper system
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/config.ts:127-128
Timestamp: 2025-08-07T11:20:44.614Z
Learning: gomesalexandre prefers required environment variables without default values in the config file (src/config.ts). They want explicit configuration and fail-fast behavior when environment variables are missing, rather than having fallback defaults.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/ContractInteractionBreakdown.tsx:0-0
Timestamp: 2025-09-13T16:45:18.813Z
Learning: gomesalexandre prefers aggressively deleting unused/obsolete code files ("ramboing") rather than fixing technical issues in code that won't be used, demonstrating his preference for keeping codebases clean and PR scope focused.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/types.ts:7-7
Timestamp: 2025-09-10T15:34:29.604Z
Learning: gomesalexandre is comfortable relying on transitive dependencies (like abitype through ethers/viem) rather than explicitly declaring them in package.json, preferring to avoid package.json bloat when the transitive dependency approach works reliably in practice.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10503
File: .env:56-56
Timestamp: 2025-09-16T13:17:02.938Z
Learning: gomesalexandre prefers to enable feature flags globally in the base .env file when the intent is to activate features everywhere, even when there are known issues like crashes, demonstrating his preference for intentional global feature rollouts over cautious per-environment enablement.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10249
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:447-503
Timestamp: 2025-08-13T17:07:10.763Z
Learning: gomesalexandre prefers relying on TypeScript's type system for validation rather than adding defensive runtime null checks when types are properly defined. They favor a TypeScript-first approach over defensive programming with runtime validations.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/hooks/useActionCenterSubscribers/useThorchainLpDepositActionSubscriber.tsx:61-66
Timestamp: 2025-08-14T17:51:47.556Z
Learning: gomesalexandre is not concerned about structured logging and prefers to keep console.error usage as-is rather than implementing structured logging patterns, even when project guidelines suggest otherwise.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10413
File: src/components/Modals/FiatRamps/fiatRampProviders/onramper/utils.ts:29-55
Timestamp: 2025-09-02T14:26:19.028Z
Learning: gomesalexandre prefers to keep preparatory/reference code simple until it's actively consumed, rather than implementing comprehensive error handling, validation, and robustness improvements upfront. They prefer to add these improvements when the code is actually being used in production.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:396-402
Timestamp: 2025-08-14T17:55:57.490Z
Learning: gomesalexandre is comfortable with functions/variables that return undefined or true (tri-state) when only the truthy case matters, preferring to rely on JavaScript's truthy/falsy behavior rather than explicitly returning boolean values.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10783
File: src/context/ModalStackProvider/useModalRegistration.ts:30-41
Timestamp: 2025-10-16T11:14:40.657Z
Learning: gomesalexandre prefers to add lint rules (like typescript-eslint/strict-boolean-expressions for truthiness checks on numbers) to catch common issues project-wide rather than relying on code review to catch them.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10206
File: src/lib/moralis.ts:47-85
Timestamp: 2025-08-07T11:22:16.983Z
Learning: gomesalexandre prefers console.error over structured logging for Moralis API integration debugging, as they find it more conventional and prefer to examine XHR requests directly rather than rely on structured logs for troubleshooting.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:133-137
Timestamp: 2025-09-12T10:15:10.389Z
Learning: gomesalexandre has identified that EIP-712 domain chainId should be preferred over request context chainId for accuracy in WalletConnect dApps structured signing flows. The domain chainId from the parsed message is more specific and accurate than the general request context, especially for asset resolution and network-specific operations.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 0
File: :0-0
Timestamp: 2026-03-17T01:29:21.619Z
Learning: In shapeshift/web PR `#12181`, the primary fix is replacing SHA-based comparison (`privateSha`) with a content diff approach (`privateContentMatchesMain` boolean) in `deriveReleaseState`/`deriveHotfixState` in `scripts/release.ts`. This unblocks new releases when `private` has been squash-synced with `main` (SHA differs even though content is identical). The secondary fix — `createPr` returning `null` on "No commits between" GitHub error — is a defensive improvement bundled in the same PR. The PR title only references the secondary change; the commit message body captures both.
Learnt from: gomes-bot
Repo: shapeshift/web PR: 11884
File: packages/chain-adapters/src/tron/TronChainAdapter.ts:732-735
Timestamp: 2026-02-16T15:00:09.111Z
Learning: In packages/chain-adapters/src/tron/TronChainAdapter.ts, inline comments explaining non-obvious domain-specific behavior (e.g., why TRC20 burns to zero address are allowed while mints from zero address are skipped) are acceptable when explicitly requested, especially when the rationale is easy to regress (e.g., sTRX unstaking burn behavior).
- run generate:caip-adapters to create eip155_2741 adapter - add abstract to generated index.ts imports/exports - add ethOnAbstract to index.test.ts coingeckoToAssetIds expectation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- add usdcOnCelo (0xceba9300f2b948710d2653dd7b07f33a8b32118c) to coingeckoToAssetIds 'usd-coin' test — celo adapter regenerated with native USDC entry when generate:caip-adapters ran - fix shebang: #!/usr/bin/env npx tsx doesn't work on Linux (env treats 'npx tsx' as one arg); use -S to split args Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
addressing latest @coderabbitai comments: ethSupportsNetwork (walletconnectV2.ts) — done in prior commit, 2741 is already at line 139 process.exit(1) (report.ts) — done in prior commit schema.ts relay + wrappedNativeAddress guards — done in prior commit shebang (index.ts) — fixed to `#!/usr/bin/env -S npx tsx` in latest commit batch-prefetch ordering (evm.ts) — the prefetch gates on `wallet.ethGetAddresses` which works for any EVM-capable wallet regardless of `supportsAbstract`. All other second-class EVM chains use the identical pattern — dismissing. wrap() masking anchor misses — post-MVP. `false` from engine = skip, exception = error. The "anchor not found" vs "already present" distinction is a UX improvement but doesn't affect scaffold correctness — dismissing. addNamedImport() idempotency — post-MVP, catalogued for a follow-up hardening pass. migration key from highest entry — valid, post-MVP improvement. Across/Portals/Zerion supported branches — acknowledged, full integration per-swapper varies. Post-MVP when those swappers get Abstract support. partial adapter generation idempotency — post-MVP. |
|
Tip For best results, initiate chat on the files or code changes.
✏️ Learnings added
🧠 Learnings used |
adapters are iterated in insertion order; celo adapter (eip155_42220) was added by regenerate:caip-adapters before sei, so celo comes first Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
abstract is isNativeEth:true — adds one more entry to findAll() results Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Description
Two things in one:
Abstract chain — adds Abstract (EVM, chain ID 2741, Pudgy Penguins' L2 on ZK Stack) as a second-class EVM chain behind
VITE_FEATURE_ABSTRACT. Native asset is ETH, swapper support via Relay (~1-2s bridge and on-chain swap times). Tested end-to-end: bridge in, on-chain DEX swap (ETH→USDT on Abstract), notification center, balance polling.scripts/addChain/scaffolder — automates ~80% of the second-class EVM chain integration points documented in.claude/contracts/second-class-evm-chain.md. Uses the TypeScript compiler API (zero new deps —typescriptalready installed) to locate insertion points via AST, then string-splices. Abstract is the reference config (chains/abstract.json).Usage:
npx tsx scripts/addChain/index.ts chains/<chain>.jsonScaffolder covers ~50 insertion points:
Append-only ordering via
appendLineAfterLastPatternso running the scaffolder for chain B always inserts after chain A — no merge conflicts. Idempotent: safe to run twice.Issue (if applicable)
closes #11980
Risk
Low — new chain behind feature flag, scaffolder is scripts-only (no runtime impact).
Testing
Engineering
VITE_FEATURE_ABSTRACT=truein.env.developmentpnpm run devScaffolder test:
npx tsx scripts/addChain/index.ts chains/abstract.json(idempotent — no-ops on already-applied entries)Operations
Screenshots (if applicable)
QA run (all 21 steps passed): https://qabot-kappa.vercel.app/runs/52fafd4b-483d-426f-aaa5-841c48c690cb
Summary by CodeRabbit
New Features
Chores
Tests