-
Notifications
You must be signed in to change notification settings - Fork 198
feat: support generic evm routes #11716
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
feat: support generic evm routes #11716
Conversation
…son to v1.62.40-evm-multi-chain.0 Update all 18 @shapeshiftoss/hdwallet-* packages from ^1.62.41 to 1.62.40-evm-multi-chain.0 to enable generic EVM chain support. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ters package.json Updated @shapeshiftoss/hdwallet-core and @shapeshiftoss/hdwallet-ledger from ^1.62.41 to 1.62.40-evm-multi-chain.0 to enable generic EVM chain support. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ckage.json Updated @shapeshiftoss/hdwallet-core from ^1.62.41 to 1.62.40-evm-multi-chain.0 in the swapper package to enable generic EVM chain support. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…Id union Add type definitions for generic EVM chain support: - EvmGenericChainId: template literal type for any EVM chain ID in CAIP-2 format - AnyEvmChainId: union of known and generic EVM chain IDs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…with EvmGenericChainConfig type and GENERIC_EVM_CHAINS array
- Add EvmGenericChainId template literal type for generic EVM chains (eip155:${number})
- Add EvmGenericChainConfig type with fields: chainId, name, displayName, nativeAssetId, rpcUrl, iconName, viemChainKey, multicallAddress, explorerUrl
- Add empty GENERIC_EVM_CHAINS array for future chain configurations
- Import viem types for Address and chains
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add helper functions: - getGenericChainConfig: retrieves chain config by chain ID - isGenericChainId: type guard to check if a chainId is a generic chain ID - getGenericChainAssetId: returns native asset ID for a chain Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create packages/chain-adapters/src/evm/generic/GenericEvmChainAdapter.ts extending SecondClassEvmAdapter for generic EVM chain support. - Accepts EvmGenericChainConfig for dynamic chain configuration - Uses coinType 60 (Ethereum) for BIP44 derivation - Implements getName(), getDisplayName(), getType(), getFeeAssetId() - Adds getExplorerUrl() helper for block explorer access - Includes isGenericEvmChainAdapter type guard Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…eric/index.ts Add index.ts to export all GenericEvmChainAdapter exports following the same pattern used by other second-class EVM adapters like hyperevm and katana. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…pdate viemClientByChainId - Add createGenericViemClient function that creates viem clients for generic EVM chains - Add genericChainClientCache to cache created clients and avoid duplicates - Add extractNetworkId helper to parse chain ID from CAIP-2 format - Add getOrCreateViemClient function that supports both known and generic chains - Use defineChain from viem for chains not in viem/chains - Support viemChainKey config option to use built-in viem chain definitions Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
… CSP for generic chain RPC URLs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…/index.ts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ables
Add placeholder sections for generic EVM chain RPC URLs to .env and
.env.development files. The pattern VITE_GENERIC_CHAIN_{CHAINID}_NODE_URL
allows adding RPC URLs for chains configured in packages/caip/src/genericChains.ts
without modifying code.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…tsx plugin Create plugin that registers generic chain adapters from GENERIC_EVM_CHAINS configuration. The plugin iterates over the config array and creates a GenericEvmChainAdapter for each chain. Feature flag 'GenericEvmChains' controls visibility. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…reFlags Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…hains - Import GENERIC_EVM_CHAINS from @shapeshiftoss/caip - Add generic chain IDs to supportedChains when GenericEvmChains feature flag is enabled - Generic chains are appended to KnownChainIds in the supportedChains array Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Revert hdwallet packages from 1.62.40-evm-multi-chain.0 to 1.62.41 (verdaccio version doesn't exist on npm) - Fix TS2589 in viemClient.ts by adding type assertions for chain types - Update EvmBaseAdapter and SecondClassEvmAdapter to accept AnyEvmChainId (enables GenericEvmChainAdapter to extend SecondClassEvmAdapter) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The feature flag was referenced in preferencesSlice but not defined in config.ts validators, which would cause the app to crash on startup. Also added the flag to test mock store for test compatibility. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
… support - Update ChainAdapterArgs to accept AnyEvmChainId for generic chains - Fix targetNetworkByChainId to use Record<string, ...> with fallback - Update ChainSpecificAccount, ChainSpecificFeeData, ChainSpecificBuildTxData, and ChainSpecificGetFeeDataInput types to handle EvmGenericChainId - Update SignTx type to return ETHSignTx for generic EVM chains - Update BuildSendApiTxInput and BuildDepositTxInput to accept any ChainId - Add exclude patterns for dist directories and generated files in tsconfig Note: Full type-check requires unchained-client generated types which need Java (openapi-generator). The type fixes here address EVM generic chain support. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove unused env variable and loadEnv import from generic CSP - Remove unused AnyEvmChainId import from chain-adapters types - Apply auto-fix for import sorting, prettier formatting, and type-only imports Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes: - Changed type-only import to value import for getGenericChainConfig in viemClient.ts - Created genericChains.test.ts with tests for isGenericChainId, getGenericChainConfig, getGenericChainAssetId, and GENERIC_EVM_CHAINS - Created GenericEvmChainAdapter.test.ts with tests for isGenericEvmChainAdapter and rootBip44Params QA Fix Session: 1 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix import style in viemClient.ts (use top-level type-only import) - Fix import sorting in test files - Remove unused mockConfig variable Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds support for two new EVM-compatible blockchains (Celo and Linea) through a generic EVM chain system. Introduces new chain constants, adapter implementations, asset generation providers, CSP policies, configuration flags, and UI integrations to enable the application to support arbitrary EVM networks dynamically. Changes
Sequence Diagram(s)sequenceDiagram
participant App as Application
participant PluginProvider
participant GenericPlugin as Generic EVM<br/>Plugin
participant ConfigService
participant Adapter as GenericEvmChain<br/>Adapter
participant RpcProvider as RPC Provider<br/>(Env/Default)
participant ViemClient as Viem Client
participant AssetService
App->>PluginProvider: Initialize
PluginProvider->>ConfigService: Check GenericEvmChains<br/>feature flag
alt Feature Enabled
PluginProvider->>GenericPlugin: Register Plugin
GenericPlugin->>GenericPlugin: Iterate GENERIC_EVM_CHAINS<br/>(Celo, Linea)
loop For Each Generic Chain
GenericPlugin->>ConfigService: Resolve RPC URL from<br/>env or defaults
ConfigService-->>GenericPlugin: RPC URL
GenericPlugin->>AssetService: Query ERC20 tokens<br/>for chain
AssetService-->>GenericPlugin: Token metadata
GenericPlugin->>Adapter: Create Adapter<br/>with RPC + tokens
Adapter->>ViemClient: Create PublicClient
ViemClient-->>Adapter: Client ready
Adapter-->>GenericPlugin: Adapter initialized
GenericPlugin->>App: Register in plugin<br/>registry
end
else Feature Disabled
PluginProvider->>App: Skip generic chains
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Rationale: This PR spans 60+ files across multiple packages with heterogeneous changes including: (1) complex type system refactoring (generic constraint broadening, mapping-based conditional type resolution in chain-adapters/types.ts), (2) new adapter implementation (GenericEvmChainAdapter), (3) RelaySwapper refactoring with new assetRequiringApproval field propagation across multiple branches, (4) extensive integration points across adapters/plugins/config/UI, and (5) asset generation pipeline changes. While many changes follow consistent patterns (adding chain references to switches/maps), the type system changes and RelaySwapper logic warrant careful senior-level review for type safety and data flow correctness. Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
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 |
- Commented out Sei imports and asset generation in generateAssetData.ts - Commented out Sei chain config in genericChains.ts - Kept Celo fully configured and active - Black screen issue confirmed to be caused by Sei, not Celo
…ve-been-doing-an-attempt-at-supporting-evms-chai
…t-at-supporting-evms-chai
…t-at-supporting-evms-chai
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 10
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
packages/chain-adapters/src/cosmossdk/CosmosSdkBaseAdapter.ts (1)
253-268: Remove double type assertion; fix the underlying type mismatch.The
as unknown as Account<T>at line 268 bypasses type safety and violates the "no type assertions without proper validation" guideline. Restructure the return using explicitly typed intermediate variables so TypeScript can verify the shape matchesAccount<T>.♻️ Recommended fix
- return { - balance: account.balance, - chainId: this.chainId, - assetId: this.assetId, - chain: this.getType(), - chainSpecific: { - accountNumber: account.accountNumber.toString(), - assets: account.assets, - sequence: account.sequence.toString(), - delegations: account.delegations, - redelegations: account.redelegations, - undelegations: account.undelegations, - rewards: account.rewards, - }, - pubkey: account.pubkey, - } as unknown as Account<T> + const chainSpecific: cosmossdk.Account = { + accountNumber: account.accountNumber.toString(), + assets: account.assets, + sequence: account.sequence.toString(), + delegations: account.delegations, + redelegations: account.redelegations, + undelegations: account.undelegations, + rewards: account.rewards, + } + + return { + balance: account.balance, + chainId: this.chainId, + assetId: this.assetId, + chain: this.getType(), + chainSpecific, + pubkey: account.pubkey, + } as Account<T>packages/chain-adapters/src/types.ts (2)
1-19: ImportEvmGenericChainIdfrom@shapeshiftoss/caipfor chain-ID consistency.This file already sources
ChainIdfrom@shapeshiftoss/caip; the newEvmGenericChainIdshould come from the same package per coding guidelines that specify chain ID types must be imported from@shapeshiftoss/caip.♻️ Proposed change
-import type { ChainId, Nominal } from '@shapeshiftoss/caip' +import type { ChainId, EvmGenericChainId, Nominal } from '@shapeshiftoss/caip' import type { BTCSignTx, CosmosSignTx, ETHSignTx, HDWallet, MayachainSignTx, SolanaSignTx, StarknetSignTx, SuiSignTx, ThorchainSignTx, } from '@shapeshiftoss/hdwallet-core' import type { ChainSpecific, - EvmGenericChainId, KnownChainIds, UtxoAccountType, UtxoChainId, } from '@shapeshiftoss/types'
359-401: Add Cosmos/Thorchain/Mayachain to ChainSpecificGetFeeDataInputMapping or document the intentional omission.Cosmos, Thorchain, and Mayachain are missing from the
ChainSpecificGetFeeDataInputMapping. While their adapters havegetFeeDataimplementations, they ignore the input parameter (marked with_) and return hardcoded fees—they don't accept dynamic chain-specific inputs like EVM or UTXO chains do. Either add placeholder entries for consistency (e.g.,[KnownChainIds.CosmosMainnet]: cosmossdk.GetFeeDataInput), or add a comment explaining why these chains are intentionally omitted.
🤖 Fix all issues with AI agents
In @.env.development:
- Line 113: Move the environment variable VITE_FEATURE_GENERIC_EVM_CHAINS so it
appears before VITE_FEATURE_KATANA to satisfy the dotenv-linter UnorderedKey
rule; open the .env file, locate the lines defining
VITE_FEATURE_GENERIC_EVM_CHAINS and VITE_FEATURE_KATANA, swap their order
(ensure any related comments or grouping remain consistent), save, and re-run
the linter to confirm the warning is resolved.
In `@docs/adding-new-evm-chain.md`:
- Line 470: Replace the bold-as-heading line "**Total: ~15-17 files**" with a
real Markdown heading to satisfy MD036: convert that bold text into an actual
heading of the appropriate level (e.g., H2/H3) matching surrounding headings in
the document and remove the bold formatting so the line starts with the Markdown
heading marker instead; ensure spacing and hierarchy remain consistent with
nearby headings.
- Line 16: Replace the bare URL in the line containing "**CoinGecko Asset
Platform ID**" with a Markdown link to avoid MD034 failures; change the text so
it uses link syntax (e.g., include the URL as
[https://api.coingecko.com/api/v3/asset_platforms] or attach the URL to
descriptive text like [CoinGecko asset
platforms](https://api.coingecko.com/api/v3/asset_platforms)) so the line reads
as a proper markdown link rather than a bare URL.
In
`@scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts`:
- Around line 45-46: The ZERION_API_KEY constant is hardcoded in
generateRelatedAssetIndex.ts which leaks a secret; remove the literal and
instead read the key from an environment/secret store (e.g.
process.env.ZERION_API_KEY or your secrets manager) and keep the runtime guard
(if missing throw new Error(...)) so the process fails fast; also note to rotate
the exposed key in Zerion and update deployment secrets rather than committing
any new secret to source control.
In `@scripts/generateAssetData/overrides.ts`:
- Around line 30-33: The token metadata override for the Celo mainnet address
'eip155:42220/erc20:0x471ece3750da237f93b8e339c536989b8978a438' is
incorrect—it's the native CELO (GoldToken), not wrapped CELO; update the object
value for that key in overrides.ts to use the correct name "Celo" and symbol
"CELO" (replace the current name 'Wrapped CELO' and symbol 'WCELO' for the
referenced key).
In
`@src/components/MultiHopTrade/components/TradeConfirm/hooks/useAllowanceApproval.tsx`:
- Around line 38-52: The code computes assetForApproval optionally then accesses
its properties inconsistently (assetForApproval?.assetId passed to
useIsAllowanceApprovalRequired but assetForApproval.assetId passed to
useApprovalFees and later at another call), which can cause a runtime error if
assetForApproval is undefined; fix by making assetForApproval guaranteed (remove
the optional chaining from tradeQuoteStep when assigning assetForApproval so it
always resolves to tradeQuoteStep.sellAsset) or, if it can legitimately be
undefined, make all accesses consistent by using optional chaining
(assetForApproval?.assetId) and handling undefined results from useApprovalFees
and the later call; update the references to assetForApproval,
useIsAllowanceApprovalRequired, and useApprovalFees accordingly.
In `@src/config.ts`:
- Around line 69-70: Update the environment schema so VITE_CELO_NODE_URL and
VITE_LINEA_NODE_URL are optional and supply the public RPC fallbacks as
defaults; replace the current required url() validators for the symbols
VITE_CELO_NODE_URL and VITE_LINEA_NODE_URL in src/config.ts with optional URL
validators and set their default values to "https://forno.celo.org" (Celo) and
"https://rpc.linea.build" (Linea) respectively so the chains can operate without
custom node URLs.
In `@src/plugins/genericEvmChains/index.tsx`:
- Around line 11-24: The token discovery currently calls fromAssetId multiple
times without validation in createGetKnownTokens, which will throw on malformed
assetIds; update createGetKnownTokens to parse each asset once (e.g., const
parsed = safeParse via try/catch or a helper) before filtering/mapping, skip any
asset where fromAssetId throws or returns invalid data, and then use
parsed.chainId, parsed.assetNamespace, and parsed.assetReference when building
the returned object so malformed assetIds do not break adapter init.
In `@src/state/apis/swapper/helpers/getInputOutputRatioFromQuote.ts`:
- Around line 26-28: Remove the leftover debug console.log calls inside
getInputOutputRatioFromQuote: locate the console.log({ feeAsset }) and the other
console.log block around lines 70–72 and delete them so no debug output is
emitted during quote calculations; ensure no other stray console.log statements
remain in that helper to avoid noisy production logs.
In `@src/state/slices/portfolioSlice/utils/index.ts`:
- Around line 139-142: The default case only checks against the static
evmChainIds array so dynamically configured generic EVM chains return no label;
update the logic in the default branch to detect EVM chains by their namespace
instead of membership in evmChainIds — e.g., derive the chain namespace from
chainId (or use any existing helper like getChainNamespace) and if it indicates
an EVM chain, return middleEllipsis(pubkey) for EvmChainId-like addresses; keep
existing symbols evmChainIds, chainId, EvmChainId, middleEllipsis, and pubkey in
mind when locating and changing the conditional.
🧹 Nitpick comments (12)
src/state/apis/swapper/helpers/swapperApiHelpers.ts (1)
72-102: Debug logging statements should be removed or converted to structured logging.These
console.logstatements appear to be debug artifacts from development. For production code:
- If these logs are no longer needed, remove them before merging.
- If logging is required for observability, use structured logging with appropriate log levels (e.g.,
debugortrace) so they can be filtered in production.Based on coding guidelines, structured logging with relevant context should be used for error debugging.
packages/chain-adapters/src/utxo/UtxoBaseAdapter.ts (1)
213-213: Type assertion viaunknownis a workaround for complex generics.The double assertion (
as unknown as Account<T>) indicates TypeScript can't verify the structural compatibility directly. This is a common pattern when dealing with complex generic types with conditional chain-specific properties. While it works, it bypasses type checking at this point.The object literal's structure is known to be correct at runtime, so this is acceptable, but worth noting for future maintainers that this assertion should be revisited if the
Account<T>type definition changes.packages/swapper/src/swappers/RelaySwapper/endpoints.ts (1)
210-222: Consider whethertxIndexingMapshould be set when notification is skipped.The map is updated at line 222 regardless of whether
notifyTransactionIndexingwas called. This means for generic EVM chains whererelayChainIdmight be undefined, the swap ID is marked as indexed even though no notification was sent.If Relay later adds support for these chains, previously attempted swaps won't trigger notifications. This might be intentional (to avoid retrying), but worth confirming the desired behavior.
packages/swapper/src/swappers/RelaySwapper/constant.ts (1)
74-79: Return type is inconsistent with actual behavior.
getChainIdFromRelayChainIdis typed to returnChainId | undefined, but it always returns a value - either from the known mapping or the constructedeip155:${relayChainId}string. Theundefinedreturn path is never reached.Consider updating the return type to just
ChainIdto accurately reflect the behavior, or add explicitundefinedhandling if there are relay chain IDs that shouldn't be converted.♻️ Suggested fix
-export const getChainIdFromRelayChainId = (relayChainId: number): ChainId | undefined => { +export const getChainIdFromRelayChainId = (relayChainId: number): ChainId => { const knownChainId = relayChainIdToChainId[relayChainId] if (knownChainId) return knownChainId return `eip155:${relayChainId}` as ChainId }packages/swapper/src/swappers/RelaySwapper/utils/relayTokenToAssetId.ts (1)
24-27: Guard may be unreachable based on current implementation.
getChainIdFromRelayChainIdalways returns a value (either from known mapping or constructseip155:${relayChainId}), so the!chainIdcheck at line 25 will never be true.This guard provides good defensive coding against future changes, but if you want consistency, consider either:
- Keep it as-is for defensive programming
- Remove if
getChainIdFromRelayChainIdreturn type is updated toChainId(non-nullable)packages/chain-adapters/src/evm/SecondClassEvmAdapter.ts (1)
275-290: Gas estimation fallback uses magic numbers that may need documentation.The fallback gas limits (300000 for small data, 500000 for larger data) and the 1000-character threshold are heuristics. While practical for preventing transaction failures, consider:
- Adding a comment explaining the rationale for these specific values
- Extracting to named constants for clarity
- The
dataLength > 1000check operates on hex string length, not byte count (hex has 2 chars per byte + '0x' prefix)♻️ Suggested improvement
+// Gas limit fallbacks for when estimation fails due to state-dependent checks +// (e.g., allowance not yet granted, insufficient balance for simulation) +const FALLBACK_GAS_LIMIT_SIMPLE = '300000' // For transactions with small calldata +const FALLBACK_GAS_LIMIT_COMPLEX = '500000' // For transactions with larger calldata +const CALLDATA_COMPLEXITY_THRESHOLD = 1000 // Hex string length threshold if (isFallbackNeeded && estimateGasBody.data) { const dataLength = estimateGasBody.data.length - const fallbackGasLimit = dataLength > 1000 ? '500000' : '300000' + const fallbackGasLimit = dataLength > CALLDATA_COMPLEXITY_THRESHOLD + ? FALLBACK_GAS_LIMIT_COMPLEX + : FALLBACK_GAS_LIMIT_SIMPLE gasLimit = BigInt(fallbackGasLimit) }headers/csps/chains/generic.ts (1)
1-5: Clarify the purpose of this empty CSP configuration.This file exports a CSP with an empty
connect-srcarray, which effectively contributes no additional CSP rules. If Celo and Linea have their own dedicated CSP files (as indicated in the PR summary), this generic placeholder may be unnecessary.Consider either:
- Documenting why this empty placeholder exists (e.g., for future generic chain RPC endpoints)
- Adding a TODO comment explaining planned usage
- Removing if not needed
packages/caip/src/genericChains.test.ts (1)
10-37: Expand test coverage to include positive cases for Celo and Linea.The current tests only cover negative cases (unknown chain IDs) and basic type checks. Since
GENERIC_EVM_CHAINSincludes Celo and Linea configurations, consider adding tests that verify:
isGenericChainIdreturnstruefor Celo (eip155:42220) and Linea (eip155:59144)getGenericChainConfigreturns the expected config object for these chainsgetGenericChainAssetIdreturns the correct asset ID for these chains🧪 Suggested additional test cases
describe('isGenericChainId', () => { it('should return false for unknown chain IDs when array is empty', () => { expect(isGenericChainId('eip155:12345')).toBe(false) }) it('should return false for known chain IDs', () => { expect(isGenericChainId('eip155:1')).toBe(false) }) + + it('should return true for Celo chain ID', () => { + expect(isGenericChainId('eip155:42220')).toBe(true) + }) + + it('should return true for Linea chain ID', () => { + expect(isGenericChainId('eip155:59144')).toBe(true) + }) }) describe('getGenericChainConfig', () => { it('should return undefined for unknown chain IDs', () => { expect(getGenericChainConfig('eip155:99999')).toBeUndefined() }) + + it('should return config for Celo', () => { + const config = getGenericChainConfig('eip155:42220') + expect(config).toBeDefined() + expect(config?.chainId).toBe('eip155:42220') + }) + + it('should return config for Linea', () => { + const config = getGenericChainConfig('eip155:59144') + expect(config).toBeDefined() + expect(config?.chainId).toBe('eip155:59144') + }) }) describe('getGenericChainAssetId', () => { it('should return undefined for unknown chain IDs', () => { expect(getGenericChainAssetId('eip155:99999')).toBeUndefined() }) + + it('should return asset ID for Celo', () => { + expect(getGenericChainAssetId('eip155:42220')).toBeDefined() + }) + + it('should return asset ID for Linea', () => { + expect(getGenericChainAssetId('eip155:59144')).toBeDefined() + }) })packages/caip/src/genericChains.ts (2)
20-39: Consider importing asset IDs from constants to avoid duplication.The
nativeAssetIdvalues are hardcoded strings that duplicateceloAssetIdandlineaAssetIdfromconstants.ts. If circular dependencies aren't a concern, importing them would ensure consistency.♻️ Suggested refactor
+import { celoAssetId, lineaAssetId } from './constants' + export const GENERIC_EVM_CHAINS: EvmGenericChainConfig[] = [ { chainId: 'eip155:42220', name: 'celo', displayName: 'Celo', - nativeAssetId: 'eip155:42220/slip44:60', + nativeAssetId: celoAssetId, iconName: 'celo', viemChainKey: 'celo', explorerUrl: 'https://celoscan.io', }, { chainId: 'eip155:59144', name: 'linea', displayName: 'Linea', - nativeAssetId: 'eip155:59144/slip44:60', + nativeAssetId: lineaAssetId, iconName: 'linea', viemChainKey: 'linea', explorerUrl: 'https://lineascan.build', }, ]
45-48: Type guard naming may be misleading.
isGenericChainIdchecks if the chain is inGENERIC_EVM_CHAINS, not whether it matches theEvmGenericChainIdpattern (eip155:${number}). A chain ID like'eip155:999999'would returnfalseeven though it's a validEvmGenericChainIdpattern.If this is the intended behavior (checking configured chains only), consider renaming to
isConfiguredGenericChainIdfor clarity. Otherwise, adjust the implementation to validate the pattern.packages/contracts/src/viemClient.ts (2)
126-129: Minor: No validation for malformed chainId.
extractNetworkIdassumes the input is always a well-formedEvmGenericChainId. IfchainIdis malformed (e.g., missing colon or non-numeric reference),parseIntcould returnNaN. Since this is an internal function and the type constraint provides some safety, this is low risk but worth noting.
143-147: Native currency symbol derivation may be incorrect for some chains.When
viemChainKeyis not provided, the symbol is derived asconfig.name.substring(0, 4).toUpperCase(). This could produce incorrect symbols (e.g., "LINE" for Linea, when it should be "ETH").Since Celo and Linea both have
viemChainKeyset, this fallback won't be triggered for them. For future chains without viem support, consider adding anativeCurrencySymbolfield toEvmGenericChainConfigto avoid this issue.
| VITE_FEATURE_YIELDS_PAGE=true | ||
| VITE_FEATURE_EARN_TAB=true | ||
| VITE_FEATURE_YIELD_MULTI_ACCOUNT=true | ||
| VITE_FEATURE_GENERIC_EVM_CHAINS=true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix dotenv-linter UnorderedKey for feature flags.
Static analysis reports VITE_FEATURE_GENERIC_EVM_CHAINS should appear before VITE_FEATURE_KATANA. Please reorder to satisfy the linter.
🔧 Suggested reorder
VITE_FEATURE_WC_DIRECT_CONNECTION=true
VITE_FEATURE_CETUS_SWAP=true
VITE_FEATURE_NEAR=true
+VITE_FEATURE_GENERIC_EVM_CHAINS=true
VITE_FEATURE_KATANA=true
VITE_FEATURE_YIELD_XYZ=true
VITE_FEATURE_TON=true
VITE_FEATURE_STONFI_SWAP=true
VITE_FEATURE_YIELDS_PAGE=true
VITE_FEATURE_EARN_TAB=true
VITE_FEATURE_YIELD_MULTI_ACCOUNT=true
-VITE_FEATURE_GENERIC_EVM_CHAINS=true📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| VITE_FEATURE_GENERIC_EVM_CHAINS=true | |
| VITE_FEATURE_WC_DIRECT_CONNECTION=true | |
| VITE_FEATURE_CETUS_SWAP=true | |
| VITE_FEATURE_NEAR=true | |
| VITE_FEATURE_GENERIC_EVM_CHAINS=true | |
| VITE_FEATURE_KATANA=true | |
| VITE_FEATURE_YIELD_XYZ=true | |
| VITE_FEATURE_TON=true | |
| VITE_FEATURE_STONFI_SWAP=true | |
| VITE_FEATURE_YIELDS_PAGE=true | |
| VITE_FEATURE_EARN_TAB=true | |
| VITE_FEATURE_YIELD_MULTI_ACCOUNT=true |
🧰 Tools
🪛 dotenv-linter (4.0.0)
[warning] 113-113: [UnorderedKey] The VITE_FEATURE_GENERIC_EVM_CHAINS key should go before the VITE_FEATURE_KATANA key
(UnorderedKey)
🤖 Prompt for AI Agents
In @.env.development at line 113, Move the environment variable
VITE_FEATURE_GENERIC_EVM_CHAINS so it appears before VITE_FEATURE_KATANA to
satisfy the dotenv-linter UnorderedKey rule; open the .env file, locate the
lines defining VITE_FEATURE_GENERIC_EVM_CHAINS and VITE_FEATURE_KATANA, swap
their order (ensure any related comments or grouping remain consistent), save,
and re-run the linter to confirm the warning is resolved.
| - **Native Token Symbol** (e.g., `CELO` or `ETH`) | ||
| - **RPC URL** (public or private) | ||
| - **Block Explorer URL** (e.g., `https://celoscan.io`) | ||
| - **CoinGecko Asset Platform ID** (find at https://api.coingecko.com/api/v3/asset_platforms) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace the bare URL with a markdown link (MD034).
This avoids markdownlint failures for bare URLs.
🛠️ Suggested fix
- - **CoinGecko Asset Platform ID** (find at https://api.coingecko.com/api/v3/asset_platforms)
+ - **CoinGecko Asset Platform ID** (find at <https://api.coingecko.com/api/v3/asset_platforms>)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - **CoinGecko Asset Platform ID** (find at https://api.coingecko.com/api/v3/asset_platforms) | |
| - **CoinGecko Asset Platform ID** (find at <https://api.coingecko.com/api/v3/asset_platforms>) |
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
16-16: Bare URL used
(MD034, no-bare-urls)
🤖 Prompt for AI Agents
In `@docs/adding-new-evm-chain.md` at line 16, Replace the bare URL in the line
containing "**CoinGecko Asset Platform ID**" with a Markdown link to avoid MD034
failures; change the text so it uses link syntax (e.g., include the URL as
[https://api.coingecko.com/api/v3/asset_platforms] or attach the URL to
descriptive text like [CoinGecko asset
platforms](https://api.coingecko.com/api/v3/asset_platforms)) so the line reads
as a proper markdown link rather than a bare URL.
| | **Web App** | `src/constants/chains.ts`, `src/state/slices/opportunitiesSlice/mappings.ts` | | ||
| | **Environment** | `.env`, `.env.development` | | ||
|
|
||
| **Total: ~15-17 files** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a real heading instead of bold-as-heading (MD036).
This keeps the doc compliant with markdownlint rules.
🛠️ Suggested fix
- **Total: ~15-17 files**
+ ### Total: ~15-17 files📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| **Total: ~15-17 files** | |
| ### Total: ~15-17 files |
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)
470-470: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
🤖 Prompt for AI Agents
In `@docs/adding-new-evm-chain.md` at line 470, Replace the bold-as-heading line
"**Total: ~15-17 files**" with a real Markdown heading to satisfy MD036: convert
that bold text into an actual heading of the appropriate level (e.g., H2/H3)
matching surrounding headings in the document and remove the bold formatting so
the line starts with the Markdown heading marker instead; ensure spacing and
hierarchy remain consistent with nearby headings.
| const ZERION_API_KEY = 'zk_prod_bfcde7977df44972802bb1e372ea2ece' | ||
| if (!ZERION_API_KEY) throw new Error('Missing Zerion API key - see readme for instructions') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove hardcoded Zerion API key (secret leakage).
This exposes a production credential in source control. Please rotate the key and load it from environment/secrets instead.
🔐 Proposed fix
-const ZERION_API_KEY = 'zk_prod_bfcde7977df44972802bb1e372ea2ece'
+const ZERION_API_KEY = process.env.ZERION_API_KEY ?? ''
if (!ZERION_API_KEY) throw new Error('Missing Zerion API key - see readme for instructions')🧰 Tools
🪛 Gitleaks (8.30.0)
[high] 45-45: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🤖 Prompt for AI Agents
In
`@scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts`
around lines 45 - 46, The ZERION_API_KEY constant is hardcoded in
generateRelatedAssetIndex.ts which leaks a secret; remove the literal and
instead read the key from an environment/secret store (e.g.
process.env.ZERION_API_KEY or your secrets manager) and keep the runtime guard
(if missing throw new Error(...)) so the process fails fast; also note to rotate
the exposed key in Zerion and update deployment secrets rather than committing
any new secret to source control.
| 'eip155:42220/erc20:0x471ece3750da237f93b8e339c536989b8978a438': { | ||
| name: 'Wrapped CELO', | ||
| symbol: 'WCELO', | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
Celo WCELO token address 0x471ece3750da237f93b8e339c536989b8978a438 contract
💡 Result:
0x471EcE3750Da237f93b8E339c536989b8978A438 is the CELO (GoldToken) native token contract on Celo mainnet — not wCELO. [1][2]
Wrapped CELO (wCELO) is a separate ERC‑20 on Ethereum (example contract: 0xE452E6Ea2dDeB012e20dB73bf5d3863A3Ac8d77a). [3]
Sources:
- Celo core contracts (CELO / GoldToken address). [1]
- Celo block explorer / token page for 0x471e...a438. [2]
- wCELO (Wrapped Celo) token on Ethereum (Etherscan). [3]
Update token metadata—address is the native CELO token, not wCELO.
The address 0x471ece3750da237f93b8e339c536989b8978a438 on Celo mainnet is the native CELO (GoldToken) contract. Update the override to reflect the correct name and symbol:
'eip155:42220/erc20:0x471ece3750da237f93b8e339c536989b8978a438': {
name: 'Celo',
symbol: 'CELO',
},
🤖 Prompt for AI Agents
In `@scripts/generateAssetData/overrides.ts` around lines 30 - 33, The token
metadata override for the Celo mainnet address
'eip155:42220/erc20:0x471ece3750da237f93b8e339c536989b8978a438' is
incorrect—it's the native CELO (GoldToken), not wrapped CELO; update the object
value for that key in overrides.ts to use the correct name "Celo" and symbol
"CELO" (replace the current name 'Wrapped CELO' and symbol 'WCELO' for the
referenced key).
| // Use wrapped asset if Relay specified one (e.g., native CELO → wrapped CELO) | ||
| const assetForApproval = | ||
| tradeQuoteStep?.relayTransactionMetadata?.assetRequiringApproval ?? tradeQuoteStep?.sellAsset | ||
|
|
||
| const { allowanceCryptoBaseUnitResult, isAllowanceApprovalRequired } = | ||
| useIsAllowanceApprovalRequired({ | ||
| amountCryptoBaseUnit: tradeQuoteStep?.sellAmountIncludingProtocolFeesCryptoBaseUnit, | ||
| assetId: tradeQuoteStep?.sellAsset.assetId, | ||
| assetId: assetForApproval?.assetId, | ||
| from: sellAssetAccountId ? fromAccountId(sellAssetAccountId).account : undefined, | ||
| spender: tradeQuoteStep?.allowanceContract, | ||
| }) | ||
|
|
||
| const { evmFeesResult } = useApprovalFees({ | ||
| amountCryptoBaseUnit: tradeQuoteStep.sellAmountIncludingProtocolFeesCryptoBaseUnit, | ||
| assetId: tradeQuoteStep.sellAsset.assetId, | ||
| assetId: assetForApproval.assetId, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent optional chaining creates potential runtime error.
assetForApproval is accessed with optional chaining on line 45 (assetForApproval?.assetId) but without it on line 52 (assetForApproval.assetId). If assetForApproval can be undefined (which the optional chaining implies), line 52 will throw.
Additionally, the same inconsistency exists on line 96.
Proposed fix
Either be consistent with optional chaining everywhere, or assert the value is defined if the context guarantees it:
// Use wrapped asset if Relay specified one (e.g., native CELO → wrapped CELO)
- const assetForApproval =
- tradeQuoteStep?.relayTransactionMetadata?.assetRequiringApproval ?? tradeQuoteStep?.sellAsset
+ const assetForApproval =
+ tradeQuoteStep.relayTransactionMetadata?.assetRequiringApproval ?? tradeQuoteStep.sellAssetSince tradeQuoteStep is a required parameter and sellAsset is always present on a TradeQuoteStep, removing the optional chaining on tradeQuoteStep makes assetForApproval guaranteed to be defined, allowing direct access on lines 52 and 96 to be safe.
🤖 Prompt for AI Agents
In
`@src/components/MultiHopTrade/components/TradeConfirm/hooks/useAllowanceApproval.tsx`
around lines 38 - 52, The code computes assetForApproval optionally then
accesses its properties inconsistently (assetForApproval?.assetId passed to
useIsAllowanceApprovalRequired but assetForApproval.assetId passed to
useApprovalFees and later at another call), which can cause a runtime error if
assetForApproval is undefined; fix by making assetForApproval guaranteed (remove
the optional chaining from tradeQuoteStep when assigning assetForApproval so it
always resolves to tradeQuoteStep.sellAsset) or, if it can legitimately be
undefined, make all accesses consistent by using optional chaining
(assetForApproval?.assetId) and handling undefined results from useApprovalFees
and the later call; update the references to assetForApproval,
useIsAllowanceApprovalRequired, and useApprovalFees accordingly.
| VITE_CELO_NODE_URL: url(), | ||
| VITE_LINEA_NODE_URL: url(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# Check current src/config.ts around lines 69-70
head -n 80 src/config.ts | tail -n 20Repository: shapeshift/web
Length of output: 727
🏁 Script executed:
# Search for CELO/LINEA env var definitions in .env files and docs
rg "VITE_(CELO|LINEA)_NODE_URL" --type-list | head -20Repository: shapeshift/web
Length of output: 447
🏁 Script executed:
# Check if there are CELO/LINEA chain CSP files
fd -e ts "celo|linea" headers/csps/chains/Repository: shapeshift/web
Length of output: 114
🏁 Script executed:
# Search for how node URLs are used and if there's fallback logic
rg -i "celo.*node|linea.*node" --type ts --type tsx -A 3Repository: shapeshift/web
Length of output: 85
🏁 Script executed:
# Check what other chains use for optional node URLs in config.ts
rg "VITE_.*_NODE_URL.*url\(\)" src/config.tsRepository: shapeshift/web
Length of output: 788
🏁 Script executed:
# Read CELO CSP chain file
cat -n headers/csps/chains/celo.tsRepository: shapeshift/web
Length of output: 535
🏁 Script executed:
# Read LINEA CSP chain file
cat -n headers/csps/chains/linea.tsRepository: shapeshift/web
Length of output: 539
🏁 Script executed:
# Search for fallback to public RPC logic
rg -i "fallback|public.*rpc|getRpcUrl|nodeUrl" --type ts -B 2 -A 3 | head -100Repository: shapeshift/web
Length of output: 7169
🏁 Script executed:
# Check if CELO/LINEA are treated as optional/fallback chains anywhere
rg "celo|linea" src/ --type ts -i -B 2 -A 2 | head -80Repository: shapeshift/web
Length of output: 7273
Make VITE_CELO_NODE_URL and VITE_LINEA_NODE_URL optional with defaults.
Their CSP chain files include hardcoded public RPC fallbacks (https://forno.celo.org and https://rpc.linea.build), meaning these chains can operate without custom node URLs. Both are feature-flagged (optional), following the NEAR fallback pattern. Using required url() validators contradicts the fallback design.
- VITE_CELO_NODE_URL: url(),
- VITE_LINEA_NODE_URL: url(),
+ VITE_CELO_NODE_URL: url({ default: '' }),
+ VITE_LINEA_NODE_URL: url({ default: '' }),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| VITE_CELO_NODE_URL: url(), | |
| VITE_LINEA_NODE_URL: url(), | |
| VITE_CELO_NODE_URL: url({ default: '' }), | |
| VITE_LINEA_NODE_URL: url({ default: '' }), |
🤖 Prompt for AI Agents
In `@src/config.ts` around lines 69 - 70, Update the environment schema so
VITE_CELO_NODE_URL and VITE_LINEA_NODE_URL are optional and supply the public
RPC fallbacks as defaults; replace the current required url() validators for the
symbols VITE_CELO_NODE_URL and VITE_LINEA_NODE_URL in src/config.ts with
optional URL validators and set their default values to "https://forno.celo.org"
(Celo) and "https://rpc.linea.build" (Linea) respectively so the chains can
operate without custom node URLs.
| const createGetKnownTokens = (config: EvmGenericChainConfig) => () => { | ||
| const assetService = getAssetService() | ||
| return assetService.assets | ||
| .filter(asset => { | ||
| const { chainId, assetNamespace } = fromAssetId(asset.assetId) | ||
| return chainId === config.chainId && assetNamespace === 'erc20' | ||
| }) | ||
| .map(asset => ({ | ||
| assetId: asset.assetId, | ||
| contractAddress: fromAssetId(asset.assetId).assetReference, | ||
| symbol: asset.symbol, | ||
| name: asset.name, | ||
| precision: asset.precision, | ||
| })) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard token parsing to avoid hard failures on malformed assetIds.
Line 15 and Line 20 call fromAssetId without protection. If any assetId is malformed, token discovery throws and prevents adapter init. Consider parsing once and skipping invalid entries.
🔧 Suggested fix
-const createGetKnownTokens = (config: EvmGenericChainConfig) => () => {
- const assetService = getAssetService()
- return assetService.assets
- .filter(asset => {
- const { chainId, assetNamespace } = fromAssetId(asset.assetId)
- return chainId === config.chainId && assetNamespace === 'erc20'
- })
- .map(asset => ({
- assetId: asset.assetId,
- contractAddress: fromAssetId(asset.assetId).assetReference,
- symbol: asset.symbol,
- name: asset.name,
- precision: asset.precision,
- }))
-}
+const createGetKnownTokens = (config: EvmGenericChainConfig) => () => {
+ const assetService = getAssetService()
+ return assetService.assets.flatMap(asset => {
+ try {
+ const { chainId, assetNamespace, assetReference } = fromAssetId(asset.assetId)
+ if (chainId !== config.chainId || assetNamespace !== 'erc20') return []
+ return [
+ {
+ assetId: asset.assetId,
+ contractAddress: assetReference,
+ symbol: asset.symbol,
+ name: asset.name,
+ precision: asset.precision,
+ },
+ ]
+ } catch {
+ return []
+ }
+ })
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const createGetKnownTokens = (config: EvmGenericChainConfig) => () => { | |
| const assetService = getAssetService() | |
| return assetService.assets | |
| .filter(asset => { | |
| const { chainId, assetNamespace } = fromAssetId(asset.assetId) | |
| return chainId === config.chainId && assetNamespace === 'erc20' | |
| }) | |
| .map(asset => ({ | |
| assetId: asset.assetId, | |
| contractAddress: fromAssetId(asset.assetId).assetReference, | |
| symbol: asset.symbol, | |
| name: asset.name, | |
| precision: asset.precision, | |
| })) | |
| const createGetKnownTokens = (config: EvmGenericChainConfig) => () => { | |
| const assetService = getAssetService() | |
| return assetService.assets.flatMap(asset => { | |
| try { | |
| const { chainId, assetNamespace, assetReference } = fromAssetId(asset.assetId) | |
| if (chainId !== config.chainId || assetNamespace !== 'erc20') return [] | |
| return [ | |
| { | |
| assetId: asset.assetId, | |
| contractAddress: assetReference, | |
| symbol: asset.symbol, | |
| name: asset.name, | |
| precision: asset.precision, | |
| }, | |
| ] | |
| } catch { | |
| return [] | |
| } | |
| }) | |
| } |
🤖 Prompt for AI Agents
In `@src/plugins/genericEvmChains/index.tsx` around lines 11 - 24, The token
discovery currently calls fromAssetId multiple times without validation in
createGetKnownTokens, which will throw on malformed assetIds; update
createGetKnownTokens to parse each asset once (e.g., const parsed = safeParse
via try/catch or a helper) before filtering/mapping, skip any asset where
fromAssetId throws or returns invalid data, and then use parsed.chainId,
parsed.assetNamespace, and parsed.assetReference when building the returned
object so malformed assetIds do not break adapter init.
| console.log({ | ||
| feeAsset, | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove debug console.log statements before merging.
These console.log statements appear to be leftover debug artifacts from development. They will execute on every trade quote calculation (potentially multiple times per quote with multi-hop trades), polluting the production console output.
🧹 Suggested removal
const feeAsset = selectFeeAssetById(state, tradeQuoteStep?.sellAsset.assetId)
- console.log({
- feeAsset,
- })
if (feeAsset === undefined) const getFeeAssetUsdRate = (feeAssetId: AssetId) => {
const feeAsset = selectFeeAssetById(state, feeAssetId)
- console.log({
- feeAsset,
- })
if (feeAsset === undefined) throw Error(`missing fee asset for assetId ${feeAssetId}`)Also applies to: 70-72
🤖 Prompt for AI Agents
In `@src/state/apis/swapper/helpers/getInputOutputRatioFromQuote.ts` around lines
26 - 28, Remove the leftover debug console.log calls inside
getInputOutputRatioFromQuote: locate the console.log({ feeAsset }) and the other
console.log block around lines 70–72 and delete them so no debug output is
emitted during quote calculations; ensure no other stray console.log statements
remain in that helper to avoid noisy production logs.
| default: { | ||
| if (evmChainIds.includes(chainId as EvmChainId)) { | ||
| return middleEllipsis(pubkey) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cover generic EVM chain IDs not in evmChainIds.
evmChainIds is static, so dynamically configured generic EVM chains won’t match and will still return an empty label. Consider using the chain namespace to cover all EVM chains.
🔧 Suggested fix
default: {
- if (evmChainIds.includes(chainId as EvmChainId)) {
+ if (fromChainId(chainId).chainNamespace === CHAIN_NAMESPACE.Evm) {
return middleEllipsis(pubkey)
}
return ''
}🤖 Prompt for AI Agents
In `@src/state/slices/portfolioSlice/utils/index.ts` around lines 139 - 142, The
default case only checks against the static evmChainIds array so dynamically
configured generic EVM chains return no label; update the logic in the default
branch to detect EVM chains by their namespace instead of membership in
evmChainIds — e.g., derive the chain namespace from chainId (or use any existing
helper like getChainNamespace) and if it indicates an EVM chain, return
middleEllipsis(pubkey) for EvmChainId-like addresses; keep existing symbols
evmChainIds, chainId, EvmChainId, middleEllipsis, and pubkey in mind when
locating and changing the conditional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Swap from ETH -> CELO on native wallet https://jam.dev/c/542e30b0-3f8b-49e0-b44b-076ad43b5418
Swap from ETH -> CELO on phantom https://jam.dev/c/52818379-43f2-42a9-b839-3c1f47119a2a
Swap from CELO -> USDC.CELO worked 👍 https://jam.dev/c/a1d55050-852e-41de-a532-3acdeb3c7e99
In both cases it's showing me that I got both CELO and WCELO and essentially doubles my trade value. Is that expected? The actual swap on relay just shows the regular 1 for 1 asset swap.
Successfully swapped ETH -> LINEA on native 👍
Swap from LINEA -> USDC.LINEA also good, although it was kind of difficult to find ETH.LINEAR on our search. Might just be me 😆 https://jam.dev/c/4d3df3c4-024e-49dd-806c-9c881d444796 👍
So everything looks good just flagging the CELO thing. If there's an explanation or fix for that then happy to approve/merge
|
|
||
| public static readonly rootBip44Params: RootBip44Params = { | ||
| purpose: 44, | ||
| coinType: 60, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this safe to assume for all generic evm chains?
| ) | ||
| } catch (estimateError) { | ||
| const errorMessage = String(estimateError) | ||
| const isFallbackNeeded = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
non-blocking: this logic is probably fine as a catch all. But worth asking the question if there's anything that's not that hard to do that's a bit more reliable and non-reliant on error string matching
Description
First attempt at having generic evm chains support, main things are:
Having a ChainAdapter that would handle any EVM chains magically
What this isn't doing:
It's not a "one line" to add a new chain, but it's closer to what we should do with EVMs: support is easily by just having to add chain names, native assets and a few scaffolded bits
This PR adds support for Generic EVM Chains - a new pattern for quickly adding EVM-compatible chains without the full overhead of a "first-class" chain integration. The first chains supported through this pattern are Celo and Linea.
Key Changes
New Generic Chain Infrastructure:
packages/caip/src/genericChains.ts- defines theGENERIC_EVM_CHAINSconfig array with chain metadataGenericEvmChainAdapterthat reuses existing EVM adapter logicChain Support:
eip155:42220) and Linea (eip155:59144) base assets and tokensRPC Configuration:
VITE_CELO_NODE_URL/VITE_LINEA_NODE_URLenv vars (optional)Issue (if applicable)
Nothing
Risk
Testing
VITE_FEATURE_GENERIC_EVM_CHAINS=truein.envEngineering
Operations
Screenshots (if applicable)
https://jam.dev/c/f1a406e3-71c7-4d58-bb44-aa063f4d3d14
Summary by CodeRabbit
Release Notes
New Features
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.