-
Notifications
You must be signed in to change notification settings - Fork 199
feat: near chain #11537
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
feat: near chain #11537
Conversation
- Add NearMainnet to KnownChainIds with chainId near:mainnet - Add NEAR to CAIP constants (nearChainId, nearAssetId, ASSET_REFERENCE.Near) - Add NEP-141 token namespace for NEAR fungible tokens - Create NearChainAdapter with RPC-based balance, fee, tx methods - Add NEAR to chain-adapters type mappings (4 places) - Create NEAR plugin with feature flag gating - Add NEAR account derivation using BIP44 path m/44'/397' - Wire transaction status polling for poor man's tx tracking - Add NEAR to CoinGecko adapter (platform: near-protocol) - Create NEAR asset generator script - Add NEAR to popular assets for discoverability - Add NEAR CSP headers for RPC endpoint - Add Near feature flag (disabled by default) NEAR uses Ed25519 signing (SLIP-44 coin type 397) with 24 decimal precision (yoctoNEAR). This second-class citizen implementation uses public RPC at https://free.rpc.fastnear.com without microservices. Behind VITE_FEATURE_NEAR flag. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add missing NEAR chain case to getNativeFeeAssetReference switch statement. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The NEAR RPC returns errors with message="Server error" but the actual descriptive error is in the `data` field. Now we prioritize data > cause.name > message > name to get the actual error like "account ... does not exist". 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add Gotcha 18 documenting that new chains need a case in getNativeFeeAssetReference.ts or the app will crash on load. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The accountToPortfolio function had a placeholder that just broke without adding the account data to the portfolio state. Now properly adds NEAR accounts with balance and token support. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add Gotcha 19 documenting that new chains need implementation in accountToPortfolio() or accounts won't appear in the UI. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add NEAR chain to supported chains and implement NEP-141 asset handling. Native NEAR maps to wNEAR (wrap.near), tokens match by contractId. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
bs58check adds 4-byte checksum which causes key length errors. Use standard bs58 for NEAR Ed25519 keys. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add NearSwapperDeps type and assertGetNearChainAdapter to SwapperDeps - Implement CHAIN_NAMESPACE.Near case in NEAR Intents getTradeQuote getFeeData - Add NEAR fee estimation to Send modal utils - Add NEAR to coingecko utils test expected output 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix stale closure bug where swapsById captured at render time would spread outdated swap status (Idle) when updating actualBuyAmountCryptoBaseUnit, causing the UI to incorrectly show "Awaiting Swap" during NEAR Intents swaps. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds gated NEAR support across the stack: CAIP identifiers, NEP‑141 asset mappings and generation, a full NearChainAdapter (RPC failover, tx build/sign/broadcast, NEP‑141 parsing), swapper endpoints/types and execution flow, UI integrations, plugin registration, env/config/CSP entries, Ledger wiring, tests, and documentation—all largely additive and feature‑flagged. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant UI as Client (UI)
participant Swapper as Swapper API
participant TE as TradeExecution
participant CA as NearChainAdapter
participant RPC as Near RPC
participant Fast as FastNear API
participant Ledger as Ledger/Wallet
UI->>Swapper: request unsigned NEAR tx (getUnsignedNearTransaction)
Swapper->>CA: assertGetNearChainAdapter & build unsigned NearSignTx
CA->>RPC: fetch nonce / block_hash / gas_price
RPC-->>CA: rpc responses
CA->>Fast: fetch NEP‑141 token balances (optional)
Fast-->>CA: token balances
CA-->>Swapper: unsigned NearSignTx (txToSign)
Swapper->>UI: return unsigned tx
UI->>Ledger: signNearTransaction (txBytes, addressN)
Ledger-->>UI: signed tx bytes
UI->>TE: signAndBroadcast callback (signed tx)
TE->>CA: broadcast signed transaction
CA->>RPC: send_transaction
RPC-->>CA: tx_hash / status
CA-->>TE: txHash / status
TE-->>UI: final tx result
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (2)
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 |
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
Show resolved
Hide resolved
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeNetworkFeeCryptoBaseUnit.tsx
Show resolved
Hide resolved
src/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteOrRateInput.ts
Show resolved
Hide resolved
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: 5
🧹 Nitpick comments (7)
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeNetworkFeeCryptoBaseUnit.tsx (1)
243-245: This error should be unreachable due to defensive guards—but clarify NEAR trade readiness.The generic
Errorhere is consistent with the surrounding code pattern. All chain cases in this switch statement (EVM, Solana, Tron, Sui, etc.) throw genericErrorwhen required methods are missing. For helper methods like this React hook, throwing directly is acceptable and follows established patterns in the codebase.However, there's a legitimate concern: NEAR trades are blocked at multiple stages with defensive errors:
getTradeQuoteOrRateInput.ts:238— blocks quote generationuseTradeNetworkFeeCryptoBaseUnit.tsx:243— this hookuseTradeExecution.tsx:607— blocks executionIf both
VITE_FEATURE_NEARandVITE_FEATURE_NEAR_INTENTS_SWAPremain disabled (defaults), NEAR trades cannot reach this code. But the inconsistency between PR objectives marking "swaps TO NEAR" as complete and multiple "not yet supported" errors suggests the implementation isn't ready for production. Verify whether NEAR trades are actually intended to be executable in this PR, or if the PR is only for infrastructure setup..env.development (1)
94-94: Consider alphabetical ordering for consistency.The VITE_FEATURE_NEAR flag is correctly defined, but the dotenv-linter indicates it should be alphabetically ordered among other feature flags for consistency.
📝 Suggested reordering
Consider moving this flag to maintain alphabetical ordering with other
VITE_FEATURE_*flags. Based on the existing flags, it should appear earlier in the feature flags section, likely after flags starting with 'M' and before flags starting with 'N' or later letters.src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx (1)
278-292: Consider extracting duplicated state update logic.The
actualBuyAmountCryptoBaseUnitupdate logic is duplicated between theStatusandSuccesshandlers. Consider extracting to a helper function to reduce duplication.🔎 Proposed refactor
// Extract helper at the top of executeTrade callback const updateActualBuyAmount = (actualBuyAmountCryptoBaseUnit: string) => { const freshActiveSwapId = swapSlice.selectors.selectActiveSwapId(store.getState()) if (freshActiveSwapId) { const currentSwap = swapSlice.selectors.selectSwapsById(store.getState())[freshActiveSwapId] if (currentSwap) { dispatch( swapSlice.actions.upsertSwap({ ...currentSwap, actualBuyAmountCryptoBaseUnit, }), ) } } } // Then in handlers: if (actualBuyAmountCryptoBaseUnit) { updateActualBuyAmount(actualBuyAmountCryptoBaseUnit) }src/lib/utils/near.ts (1)
14-17: Type guard may throw on invalid input.The type guard calls
getChainId()on the input without first verifying that the method exists. If passed an object without this method, it will throw rather than returnfalse.🔎 Proposed fix for safer type guard
export const isNearChainAdapter = (chainAdapter: unknown): chainAdapter is near.ChainAdapter => { if (!chainAdapter || typeof chainAdapter !== 'object') return false + if (!('getChainId' in chainAdapter) || typeof (chainAdapter as any).getChainId !== 'function') return false return (chainAdapter as near.ChainAdapter).getChainId() === nearChainId }packages/chain-adapters/src/near/NearChainAdapter.ts (3)
44-46: Consider avoidingas anycast in type guard.The
as anycast violates the coding guideline to avoidanytypes. Since you're checking for property existence, consider usingunknownwith a type guard:🔎 Suggested fix
const supportsNear = (wallet: HDWallet): wallet is NearWallet => { - return '_supportsNear' in wallet && (wallet as any)._supportsNear === true + return '_supportsNear' in wallet && (wallet as unknown as { _supportsNear: boolean })._supportsNear === true }
193-195: Consider using establishedgetName()pattern for consistency.Based on learnings, other chain adapters use a pattern that reverse-looks up the enum key from
ChainAdapterDisplayName. This ensures consistency if display names change.🔎 Suggested fix
getName() { - return 'NEAR' + const enumIndex = Object.values(ChainAdapterDisplayName).indexOf(ChainAdapterDisplayName.Near) + return Object.keys(ChainAdapterDisplayName)[enumIndex] }
391-398: Consider extractingED25519Signatureclass to module level.Defining a class inside a method works but is unusual. If
@near-js/cryptodoesn't export a suitable signature wrapper, consider moving this to module scope for clarity and reusability.
- Add getUnsignedNearTransaction/getNearTransactionFees to NearIntentsSwapper - Add execNearTransaction to TradeExecution class - Update useTradeExecution hook to handle NEAR chain namespace - Implement token balance fetching via nearblocks API in NearChainAdapter - Add VITE_NEAR_NODE_URL and VITE_NEARBLOCKS_API_URL to environment - Add nearblocks to CSP configuration - Export NEAR CoinGecko adapter (fixes market data) - Add GetNearTradeQuoteInput types to swapper types - Update tests to include NEAR USDC 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update hdwallet to 1.62.35-near-chain.2 with NEAR support - Add verifyLedgerAppOpen calls in NearChainAdapter - Add NEAR to Ledger app gate and constants - Add chainSpecific to buildSendApiTransaction call - Add master documentation for NEAR chain integration 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds a new skill that orchestrates a "crew" of specialized agents for complete blockchain integration including: - Research phase (specs, hw support investigation) - Native wallet support (hdwallet-native) - Ledger hardware wallet support - Trezor hardware wallet support - Web-side chain integration - Swapper integration (if applicable) Uses parallel agent execution where possible and produces master documentation for the entire integration. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add nep141 to isToken() for proper token detection - Implement storage_deposit + ft_transfer batch transactions - Migrate to @near-js/providers FailoverRpcProvider - Add fallback RPC endpoints (lava.build, fastnear.com) - Update CSP to allow fallback RPC URLs - Handle transaction failures/panics in broadcastTransaction 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Near case to translateCoinAndMethod in webhid/webusb transports - Pass contractAddress in NEAR swapper for storage_deposit batch - Update hdwallet to 1.62.35-near-chain.3 - Add Gotcha 22 to chain-integration skill (Ledger transport case) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix Ledger NEAR address derivation to return hex format (not ed25519:base58) - Fix Ledger NEAR signature to return hex format (not bs58) - Handle FailoverRpcProvider's "Exceeded N providers" error for unfunded accounts - Update hdwallet to 1.62.35-near-chain.4 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
NEAR was appearing twice because it's both in top 100 by market cap AND explicitly added for discoverability. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
NearBlocks has rate limits. FastNEAR is the official NEAR ecosystem API with no documented limits and provides all token balances in a single call. Also updates hdwallet to 1.62.35-near-chain.5 (removes Trezor NEAR support since Trezor Connect doesn't actually support NEAR). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Import NearWallet from hdwallet-core instead of duplicating - Convert interfaces to types - Move FastNEAR types to types.ts - Move FASTNEAR_API_URL to .env - Fix validateAddress per NEAR protocol rules - Fetch actual blockHeight/blockTime from RPC - Simplify token balance type - Remove console.log statements
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: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/state/slices/portfolioSlice/utils/index.ts (1)
695-709: Add NEAR handler tomakeAssetsfunction to upsert discovered NEP-141 tokens.NEAR chains discover tokens dynamically via
fetchTokenBalances()and populatechainSpecific.tokensin the account object, but themakeAssetsfunction lacks a handler for NEAR like it has for Solana, Tron, and Sui. This causes discovered NEP-141 tokens to never be upserted into the portfolio's assets slice. Add a NEAR case following the same pattern as the other chains:if (chainId === nearChainId) { const account = portfolioAccounts[pubkey] as Account<KnownChainIds.NearMainnet> return (account.chainSpecific.tokens ?? []).reduce<UpsertAssetsPayload>( (prev, token) => { if (state.assets.byId[token.assetId]) return prev prev.byId[token.assetId] = makeAsset(state.assets.byId, { ...token }) prev.ids.push(token.assetId) return prev }, { byId: {}, ids: [] }, ) }
♻️ Duplicate comments (1)
.claude/skills/chain-integration/SKILL.md (1)
2065-2068: Add language specifier to fenced code block (MD040).The error output on line 2065 lacks a language identifier. Update to specify
text:-``` +```text Error: Chain namespace [chain] on mainnet not supported. at getNativeFeeAssetReference.ts:XX:XX -``` +```
🧹 Nitpick comments (2)
headers/csps/chains/near.ts (1)
8-15: Consider explicit type narrowing for filter.The
filter(Boolean)works but TypeScript may not properly narrow the type. For better type safety:🔎 Proposed refactor for type safety
export const csp: Csp = { 'connect-src': [ env.VITE_NEAR_NODE_URL, env.VITE_NEAR_NODE_URL_FALLBACK_1, env.VITE_NEAR_NODE_URL_FALLBACK_2, 'https://api.fastnear.com', - ].filter(Boolean), + ].filter((url): url is string => Boolean(url)), }packages/chain-adapters/src/near/NearChainAdapter.ts (1)
503-543: Consider documenting the gas estimation approach.The hardcoded gas estimates (60 TGas for tokens, 2.5 TGas for native) are reasonable starting points. The TODO comment about RPC simulation is noted.
For future iterations, consider adding a brief inline note explaining the gas estimate derivation (e.g., storage_deposit 30 TGas + ft_transfer 30 TGas = 60 TGas) to help maintainers understand the values.
NeOMakinG
left a comment
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.
https://jam.dev/c/189478c6-5174-43b8-a684-ef223c589126
Quite happy with this one overall minus:
I'm getting rate limited a lot, we need to throttle in the adapter, but lets do it in a follow up!
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: 0
♻️ Duplicate comments (1)
packages/chain-adapters/src/near/NearChainAdapter.ts (1)
271-289: Address validation regex is insufficient.The existing regex at line 284 allows invalid NEAR account IDs. The pattern
/^(([a-z\d]+[-_])*[a-z\d]+\.)*([a-z\d]+[-_])*[a-z\d]+$/permits:
- Consecutive different separators like
alice_-boborbob-.near- Parts that logically violate NEAR's rules
NEAR account ID rules require each dot-separated part to only contain
a-z,0-9, and separators_or-that are not consecutive and not at boundaries. A corrected regex:🔎 Proposed fix
- if (address.length >= 2 && address.length <= 64) { - const namedAccountRegex = /^(([a-z\d]+[-_])*[a-z\d]+\.)*([a-z\d]+[-_])*[a-z\d]+$/ - if (namedAccountRegex.test(address)) return Promise.resolve(valid) - } + if (address.length >= 2 && address.length <= 64) { + // Each part: starts and ends with [a-z0-9], middle can have single - or _ between alphanumeric chars + const part = /^[a-z\d]+([_-][a-z\d]+)*$/ + const parts = address.split('.') + if (parts.length > 0 && parts.every(p => part.test(p))) { + return Promise.resolve(valid) + } + }This validates each dot-separated part independently, ensuring no consecutive separators or invalid boundaries.
🧹 Nitpick comments (5)
packages/chain-adapters/src/near/NearChainAdapter.ts (5)
138-140: Consider using enum reverse-lookup pattern for consistency.Other chain adapters use the established pattern:
const enumIndex = Object.values(ChainAdapterDisplayName).indexOf(ChainAdapterDisplayName.Near) return Object.keys(ChainAdapterDisplayName)[enumIndex]This maintains consistency across the codebase, though the current implementation is functionally correct.
Based on learnings, this is the established pattern used consistently across almost all chain adapters.
505-545: Fee estimation uses hardcoded gas values.The
getFeeDatamethod uses hardcoded gas estimates with a TODO comment (line 514). While this is acceptable for initial implementation, actual gas simulation via RPC would provide more accurate fee estimates.Consider implementing RPC-based gas simulation when time permits, similar to EVM chain adapters that call estimateGas.
700-707: Clarify Delegate action handling.The logic for extracting
tokenContractIdfrom Delegate actions (lines 700-707) checks fordelegate_action?.receiver_idbut the structure and use case aren't immediately clear.If this handles NEAR's meta-transaction delegation pattern, consider adding a brief comment explaining when this occurs and why we need to override
tokenContractId.
425-431: Inline ED25519Signature class definition.Defining
ED25519Signatureas a local class insidesignTransactionworks but is unconventional. If this class is required by the NEAR signature construction, consider extracting it to a module-level helper with a comment explaining why it's necessary.
196-220: Token balance fetching fails silently.The
fetchTokenBalancesmethod returns an empty array on all failures, which could mask issues like incorrect API URLs or authentication problems. While this graceful degradation prevents crashes, it provides no visibility into what went wrong.Consider logging different error types distinctly (network errors vs. 404 vs. 500) to aid debugging in production.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
yarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (4)
package.jsonpackages/chain-adapters/package.jsonpackages/chain-adapters/src/near/NearChainAdapter.tspackages/swapper/package.json
🚧 Files skipped from review as they are similar to previous changes (2)
- packages/chain-adapters/package.json
- package.json
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,js,jsx}: Never assume a library is available - always check imports/package.json first
Prefer composition over inheritance
Write self-documenting code with clear variable and function names
Keep functions small and focused on a single responsibility
Avoid deep nesting - use early returns instead
Prefer procedural and easy to understand code
Never expose, log, or commit secrets, API keys, or credentials
Validate all inputs, especially user inputs
Handle errors gracefully with meaningful messages
Don't silently catch and ignore exceptions
Log errors appropriately for debugging
Provide fallback behavior when possible
Use appropriate data structures for the task
Never add code comments unless explicitly requested
When modifying code, do not add comments that reference previous implementations or explain what changed. Comments should only describe the current logic and functionality.
Use meaningful names for branches, variables, and functions
Always runyarn lint --fixandyarn type-checkafter making changes
Avoidletvariable assignments - preferconstwith inline IIFE switch statements or extract to functions for conditional logic
Files:
packages/chain-adapters/src/near/NearChainAdapter.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Avoid useEffect where practical - use it only when necessary and following best practices
Avoid 'any' types - use specific type annotations instead
For default values with user overrides, use computed values (useMemo) instead of useEffect - pattern:userSelected ?? smartDefault ?? fallback
When function parameters are unused due to interface requirements, refactor the interface or implementation to remove them rather than prefixing with underscore
Sanitize data before displaying to prevent XSS
Memoize aggressively - wrap component variables inuseMemoand callbacks inuseCallbackwhere possible
For static JSX icon elements (e.g.,<TbCopy />) that don't depend on state/props, define them as constants outside the component to avoid re-renders instead of using useMemo
Account for light/dark mode usinguseColorModeValuehook
Account for responsive mobile designs in all UI components
When applying styles, use the existing standards and conventions of the codebase
Use Chakra UI components and conventions
All copy/text must use translation keys - never hardcode strings
Use the translation hook:useTranslate()fromreact-polyglot
UseuseFeatureFlag('FlagName')hook to access feature flag values in components
Prefertypeoverinterfacefor type definitions
Use strict typing - avoidany
UseNominaltypes for domain identifiers (e.g.,WalletId,AccountId)
Import types from@shapeshiftoss/caipfor chain/account/asset IDs
UseuseAppSelectorfor Redux state
UseuseAppDispatchfor Redux actions
Memoize expensive computations withuseMemo
Memoize callbacks withuseCallback
**/*.{ts,tsx}: UseResult<T, E>pattern for error handling in swappers and APIs; ALWAYS useOk()andErr()from@sniptt/monads; AVOID throwing within swapper API implementations
ALWAYS use custom error classes from@shapeshiftoss/errorswith meaningful error codes for internationalization and relevant details in error objects
ALWAYS wrap async op...
Files:
packages/chain-adapters/src/near/NearChainAdapter.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/naming-conventions.mdc)
**/*.{js,jsx,ts,tsx}: Use camelCase for variables, functions, and methods with descriptive names that explain the purpose
Use verb prefixes for functions that perform actions (e.g., fetch, validate, execute, update, calculate)
Use UPPER_SNAKE_CASE for constants and configuration values with descriptive names
Usehandleprefix for event handlers with descriptive names in camelCase
Use descriptive boolean variable names withis,has,can,shouldprefixes
Use named exports for components, functions, and utilities instead of default exports
Use descriptive import names and avoid renaming imports unless necessary
Avoid non-descriptive variable names likedata,item,obj, and single-letter variable names except in loops
Avoid abbreviations in names unless they are widely understood
Avoid generic function names likefn,func, orcallback
Files:
packages/chain-adapters/src/near/NearChainAdapter.ts
🧠 Learnings (22)
📓 Common learnings
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: 11170
File: patches/@shapeshiftoss+bitcoinjs-lib+7.0.0-shapeshift.0.patch:9-19
Timestamp: 2025-11-25T21:43:10.838Z
Learning: In shapeshift/web, gomesalexandre will not expand PR scope to fix latent bugs in unused API surface (like bitcoinjs-lib patch validation methods) when comprehensive testing proves the actual used code paths work correctly, preferring to avoid costly hdwallet/web verdaccio publish cycles and full regression testing for conceptual issues with zero runtime impact.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:46-59
Timestamp: 2025-09-10T15:34:54.593Z
Learning: After extensive testing by gomesalexandre in PR #10458, dApps do not send EIP-712 domain.chainId as hex or bigint values in practice. The simple String(domain.chainId) conversion is sufficient for real-world usage in WalletConnect dApps structured signing.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-145
Timestamp: 2025-11-12T12:18:00.863Z
Learning: NEAR Intents swapper: The NEAR 1Click API does not provide gas limit estimation logic like other swappers (e.g., magic gasLimit fields). For ERC20 token swaps in getTradeQuote, accurate fee estimation requires token approval and sufficient balance; without these prerequisites, fees may display as 0 or use inaccurate native transfer estimates. This is a known limitation of the NEAR Intents integration.
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to **/*.{ts,tsx} : Import types from `shapeshiftoss/caip` for chain/account/asset IDs
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: 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.
📚 Learning: 2025-11-24T21:20:57.909Z
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
Applied to files:
packages/swapper/package.jsonpackages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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 : Avoid side effects in swap logic; ensure swap methods are deterministic and stateless
Applied to files:
packages/swapper/package.json
📚 Learning: 2025-11-19T22:20:25.661Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10767
File: package.json:324-324
Timestamp: 2025-11-19T22:20:25.661Z
Learning: In shapeshift/web package.json, the resolution "gridplus-sdk/bs58check": "2.1.2" is intentional and must not be removed. It forces gridplus-sdk's transitive bs58check dependency from 4.0.0 down to 2.1.2 because bs58check 4.0.0 breaks legacy address validation (due to bs58 v6.0.0 and noble/hash vs 2.1.2's bs58 v4.0.0 and create-hash).
Applied to files:
packages/swapper/package.json
📚 Learning: 2025-08-08T20:16:12.898Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10222
File: package.json:202-202
Timestamp: 2025-08-08T20:16:12.898Z
Learning: In shapeshift/web, the semver package must be included in dependencies (not devDependencies) because hdwallet packages have transient dependencies that require semver but don't ship it themselves. This ensures semver is available at runtime for hdwallet functionality.
Applied to files:
packages/swapper/package.json
📚 Learning: 2025-11-24T21:20:57.909Z
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 camelCase for variable and function names in the Swapper system
Applied to files:
packages/swapper/package.json
📚 Learning: 2025-08-08T20:27:02.203Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10222
File: package.json:202-202
Timestamp: 2025-08-08T20:27:02.203Z
Learning: In shapeshift/web, while gomesalexandre generally prefers pinned dependencies for security, semver with a caret range (^7.7.2) is acceptable as an exception since it's already a transient dependency of many packages and is being made explicit for hdwallet support.
Applied to files:
packages/swapper/package.json
📚 Learning: 2025-11-24T21:20:57.909Z
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 : Reuse executeEvmTransaction utility for EVM-based swappers instead of implementing custom transaction execution
Applied to files:
packages/swapper/package.json
📚 Learning: 2025-11-24T21:20:57.909Z
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/*/endpoints.ts : Reuse checkEvmSwapStatus utility for checking EVM swap status instead of implementing custom status checks
Applied to files:
packages/swapper/package.json
📚 Learning: 2025-11-24T21:20:57.909Z
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 PascalCase for types, interfaces, and enums in the Swapper system
Applied to files:
packages/swapper/package.json
📚 Learning: 2025-11-24T21:20:57.909Z
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 kebab-case for filenames in the Swapper system
Applied to files:
packages/swapper/package.json
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to **/*.{ts,tsx} : Import types from `shapeshiftoss/caip` for chain/account/asset IDs
Applied to files:
packages/swapper/package.jsonpackages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-08-29T18:09:45.982Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10376
File: vite.config.mts:136-137
Timestamp: 2025-08-29T18:09:45.982Z
Learning: In the ShapeShift web repository vite.config.mts, the commonjsOptions.exclude configuration using bare package name strings like ['shapeshiftoss/caip', 'shapeshiftoss/types'] works correctly for excluding specific packages from CommonJS transformation, despite theoretical concerns about module ID matching patterns.
Applied to files:
packages/swapper/package.json
📚 Learning: 2025-12-09T21:07:22.474Z
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.
Applied to files:
packages/swapper/package.json
📚 Learning: 2025-11-20T12:00:45.005Z
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.
Applied to files:
packages/swapper/package.json
📚 Learning: 2025-12-04T22:57:50.850Z
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.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-12-17T14:50:01.629Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11449
File: packages/chain-adapters/src/tron/TronChainAdapter.ts:570-596
Timestamp: 2025-12-17T14:50:01.629Z
Learning: In packages/chain-adapters/src/tron/TronChainAdapter.ts, the parseTx method uses `unknown` type for the txHashOrTx parameter intentionally. TRON is a "second-class chain" that works differently from other chains - it accepts either a string hash (to fetch TronTx via unchained client) or a TronTx object directly. The base chain-adapter interface is strongly typed and doesn't accommodate this flexible signature, so `unknown` is used as an appropriate escape hatch rather than a type safety issue.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-08-22T12:58:26.590Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/Layout/Header/ActionCenter/components/GenericTransactionActionCard.tsx:108-111
Timestamp: 2025-08-22T12:58:26.590Z
Learning: In the RFOX GenericTransactionDisplayType flow in src/components/Layout/Header/ActionCenter/components/GenericTransactionActionCard.tsx, the txHash is always guaranteed to be present according to NeOMakinG, so defensive null checks for txLink are not needed in this context.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-09-12T13:44:17.019Z
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.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-08-26T19:04:38.672Z
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.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-11-19T16:59:50.569Z
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.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-11-12T12:49:17.895Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-125
Timestamp: 2025-11-12T12:49:17.895Z
Learning: In packages/chain-adapters/src/evm/utils.ts, the getErc20Data function already includes a guard that returns an empty string when contractAddress is undefined (line 8: `if (!contractAddress) return ''`). This built-in handling means callers don't need to conditionally invoke getErc20Data—it safely handles both ERC20 tokens and native assets.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
🔇 Additional comments (3)
packages/swapper/package.json (1)
42-42: Dependency version 1.62.36 does not exist on npm registry.The specified version of
@shapeshiftoss/hdwallet-coreis not published on npm. The latest published version is 1.62.3. This will cause the build to fail duringnpm install. Confirm either:
- The correct published version number
- That this version is in the process of being released to npm
- Alternative approach if using an unreleased build
The NEAR integration in the codebase is properly implemented and ready, but this dependency issue must be resolved first.
⛔ Skipped due to learnings
Learnt from: gomesalexandre Repo: shapeshift/web PR: 10767 File: package.json:324-324 Timestamp: 2025-11-19T22:20:25.661Z Learning: In shapeshift/web package.json, the resolution "gridplus-sdk/bs58check": "2.1.2" is intentional and must not be removed. It forces gridplus-sdk's transitive bs58check dependency from 4.0.0 down to 2.1.2 because bs58check 4.0.0 breaks legacy address validation (due to bs58 v6.0.0 and noble/hash vs 2.1.2's bs58 v4.0.0 and create-hash).Learnt from: gomesalexandre Repo: shapeshift/web PR: 10222 File: package.json:202-202 Timestamp: 2025-08-08T20:27:02.203Z Learning: In shapeshift/web, while gomesalexandre generally prefers pinned dependencies for security, semver with a caret range (^7.7.2) is acceptable as an exception since it's already a transient dependency of many packages and is being made explicit for hdwallet support.Learnt from: gomesalexandre Repo: shapeshift/web PR: 10222 File: package.json:202-202 Timestamp: 2025-08-08T20:16:12.898Z Learning: In shapeshift/web, the semver package must be included in dependencies (not devDependencies) because hdwallet packages have transient dependencies that require semver but don't ship it themselves. This ensures semver is available at runtime for hdwallet functionality.Learnt from: gomesalexandre Repo: shapeshift/web PR: 10232 File: packages/unchained-client/openapitools.json:61-61 Timestamp: 2025-08-08T10:23:16.843Z Learning: In shapeshift/web, for temporary “monkey patch” PRs (e.g., packages/unchained-client/openapitools.json using jsDelivr CDN refs like cosmos/mayachain), gomesalexandre is fine with branch-based URLs and does not want SHA pinning. Treat this as a scoped exception to their general preference for pinned dependencies/refs.Learnt from: NeOMakinG Repo: shapeshift/web PR: 10231 File: src/components/MultiHopTrade/components/TradeInput/components/HighlightedTokens.tsx:14-14 Timestamp: 2025-08-08T15:00:22.321Z Learning: In shapeshift/web reviews for NeOMakinG, avoid nitpicks to change deep-relative imports to '@/…' alias paths within feature/non-refactor PRs; defer such style-only changes to a dedicated follow-up refactor unless they fix an issue.Learnt from: gomesalexandre Repo: shapeshift/web PR: 11170 File: patches/@shapeshiftoss+bitcoinjs-lib+7.0.0-shapeshift.0.patch:9-19 Timestamp: 2025-11-25T21:43:10.838Z Learning: In shapeshift/web, gomesalexandre will not expand PR scope to fix latent bugs in unused API surface (like bitcoinjs-lib patch validation methods) when comprehensive testing proves the actual used code paths work correctly, preferring to avoid costly hdwallet/web verdaccio publish cycles and full regression testing for conceptual issues with zero runtime impact.Learnt from: gomesalexandre Repo: shapeshift/web PR: 10206 File: package.json:0-0 Timestamp: 2025-08-07T11:20:05.201Z Learning: gomesalexandre prefers pinned dependencies (exact versions without caret ranges) as a general security practice to prevent vulnerabilities from being introduced through automatic version bumps. He referenced the LedgerHQ/connect-kit vulnerability (GitHub issue #29) as an example of security risks from dependency updates.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.packages/chain-adapters/src/near/NearChainAdapter.ts (2)
122-126: Re: RPC failover and rate limiting concerns.Previous feedback indicates that
FailoverRpcProvidermay not switch providers on rate limit errors, and multiple sequential RPC calls (e.g., ingetAddress,buildSendApiTransaction) can trigger rate limits.Based on learnings, gomesalexandre prefers to address issues when they materially impact production rather than speculatively. If RPC rate limiting is causing failures in testing, consider:
- Verifying that
FailoverRpcProvidertreats rate limit errors as failures (inspect the provider's retry logic)- Implementing request throttling with PQueue if rate limits persist
- Adding retry logic with exponential backoff for rate-limited requests
Can you confirm whether RPC rate limiting is actively blocking functionality in current testing? If so, please provide error logs or failure patterns.
599-603: Block details now properly fetched.The previous review comment about placeholder
blockTimeandblockHeighthas been addressed. The code now fetches block details usingprovider.block({ blockId: blockHash })and extracts accurate height and timestamp values.
The @near-js/providers FailoverRpcProvider doesn't retry on HTTP 429 errors, causing rapid failover through all providers when rate limited. Added withRateLimitRetry wrapper that: - Detects rate limit errors (429, 'rate limit', 'too many') - Retries up to 3 times with exponential backoff (1s, 2s, 4s) - Wraps all critical RPC calls (query, status, sendTransaction, etc.) This prevents burning through all providers and gives time for rate limits to reset.
Each JsonRpcProvider was retrying 12 times before allowing FailoverRpcProvider to switch to next RPC URL. This caused rate limit errors to hammer the same endpoint repeatedly. Now configured with retries: 2, allowing faster failover: - Try provider 1: 3 attempts (1 initial + 2 retries) - Failover to provider 2: 3 attempts - Failover to provider 3: 3 attempts Total: 9 attempts across 3 providers instead of 12 on one
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: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/state/slices/portfolioSlice/utils/index.ts (1)
592-807: Critical: Missing Near case inmakeAssetsfunction.The
makeAssetsfunction handles dynamic asset creation for token-supporting chains (EVM, Solana, Tron, Sui, Starknet) but lacks a Near case. Since Near supports tokens viachainSpecific.tokens(as evidenced by theaccountToPortfolioimplementation at lines 355-362), this omission will prevent Near tokens from being upserted into the assets state.Impact: Near tokens discovered during portfolio fetches won't appear in the UI, won't show balances, and won't be tradeable—breaking core Near token functionality.
🔎 Proposed fix: Add Near case to makeAssets
if (chainId === starknetChainId) { const account = portfolioAccounts[pubkey] as Account<KnownChainIds.StarknetMainnet> return (account.chainSpecific.tokens ?? []).reduce<UpsertAssetsPayload>( (prev, token) => { if (state.assets.byId[token.assetId]) return prev prev.byId[token.assetId] = makeAsset(state.assets.byId, { ...token }) prev.ids.push(token.assetId) return prev }, { byId: {}, ids: [] }, ) } + + if (chainId === nearChainId) { + const account = portfolioAccounts[pubkey] as Account<KnownChainIds.NearMainnet> + + return (account.chainSpecific.tokens ?? []).reduce<UpsertAssetsPayload>( + (prev, token) => { + if (state.assets.byId[token.assetId]) return prev + + prev.byId[token.assetId] = makeAsset(state.assets.byId, { ...token }) + prev.ids.push(token.assetId) + + return prev + }, + { byId: {}, ids: [] }, + ) + } }
♻️ Duplicate comments (1)
src/components/Modals/Send/utils.ts (1)
385-403: Update NEAR pubKey handling to follow the skipDeviceDerivation pattern.Line 396 unconditionally passes
pubKey: fromAccountId(sendInput.accountId).account, but this should be conditional onskipDeviceDerivationto match the established pattern across other chains (EVM line 232, UTXO line 260, Solana line 329). This was already flagged in a previous review comment.🔎 Proposed fix
return adapter.buildSendTransaction({ to, value, wallet, accountNumber, - pubKey: fromAccountId(sendInput.accountId).account, + pubKey: skipDeviceDerivation ? fromAccountId(sendInput.accountId).account : undefined, sendMax: sendInput.sendMax, chainSpecific: { gasPrice: fees.chainSpecific.gasPrice, contractAddress, }, } as BuildSendTxInput<KnownChainIds.NearMainnet>)
🧹 Nitpick comments (2)
.env (1)
310-310: Move feature flag to the feature flags section for consistency.The
VITE_FEATURE_NEARflag is defined at the end of the file, but all other feature flags are grouped together at lines 3-63. For maintainability and consistency with the established pattern, move this flag to the feature flags section.📍 Suggested placement
Move line 310 to the feature flags section (after line 62, before line 63):
VITE_FEATURE_ADDRESS_BOOK=true VITE_FEATURE_CHATWOOT=true VITE_FEATURE_SWAPPER_FIAT_RAMPS=true +VITE_FEATURE_NEAR=false # absolute URL prefixAnd remove from line 310.
packages/chain-adapters/src/near/NearChainAdapter.ts (1)
352-444: Consider extracting NEP-141 constants to class-level.Lines 386-389 define inline constants (STORAGE_DEPOSIT_AMOUNT, FT_TRANSFER_GAS, etc.) that could be moved to static readonly properties at the top of the class for better maintainability.
🔎 Optional refactoring
export class ChainAdapter implements IChainAdapter<KnownChainIds.NearMainnet> { static readonly rootBip44Params: RootBip44Params = { purpose: 44, coinType: Number(ASSET_REFERENCE.Near), accountNumber: 0, } + + // NEP-141 token transfer constants + private static readonly STORAGE_DEPOSIT_AMOUNT = BigInt('1250000000000000000000') // 0.00125 NEAR + private static readonly FT_TRANSFER_GAS = BigInt(30_000_000_000_000) // 30 TGas + private static readonly STORAGE_DEPOSIT_GAS = BigInt(30_000_000_000_000) // 30 TGas + private static readonly ONE_YOCTO = BigInt(1)Then reference them as
ChainAdapter.STORAGE_DEPOSIT_AMOUNT, etc.
- Use env var for FastNEAR CSP instead of hardcoded URL - Add documentation for local ED25519Signature class - Pass contractAddress in NEAR fee estimation for correct token gas
Align NEAR with EVM/UTXO/Solana patterns - only pass pubKey for hardware wallets (Ledger/Trezor/GridPlus) that skip device derivation.
- Add NEAR case to getL1RateOrQuote.ts (unsupported error) - Add NEAR types to types.ts (SwapperDeps, ExecutionProps, etc.) - Add executeNearTransaction to utils.ts - Add NEAR case to useTradeExecution.tsx - Add assertGetNearChainAdapter to useRfoxBridge.ts and swapperApiHelpers.ts - Add NEAR support to portfolioSlice utils (accountToPortfolio, checkAccountHasActivity, isAssetSupportedByWallet)
b48ea16 to
f9d359d
Compare
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: 0
🧹 Nitpick comments (1)
packages/chain-adapters/src/near/NearChainAdapter.ts (1)
187-189: Consider using the standard enum reverse-lookup pattern for consistency.The
getName()method returns a hardcoded string'NEAR'instead of using the enum reverse-lookup pattern used consistently across other chain adapters.Based on learnings, the established pattern is:
const enumIndex = Object.values(ChainAdapterDisplayName).indexOf(ChainAdapterDisplayName.Near) return Object.keys(ChainAdapterDisplayName)[enumIndex]This ensures consistency with Bitcoin, Ethereum, Litecoin, Dogecoin, Polygon, Arbitrum, Cosmos, and other adapters.
🔎 Standard pattern used by other adapters
getName() { - return 'NEAR' + const enumIndex = Object.values(ChainAdapterDisplayName).indexOf(ChainAdapterDisplayName.Near) + return Object.keys(ChainAdapterDisplayName)[enumIndex] }
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (10)
headers/csps/chains/near.tspackages/chain-adapters/src/near/NearChainAdapter.tspackages/swapper/src/thorchain-utils/getL1RateOrQuote.tspackages/swapper/src/types.tspackages/swapper/src/utils.tssrc/components/Modals/Send/utils.tssrc/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsxsrc/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.tssrc/state/apis/swapper/helpers/swapperApiHelpers.tssrc/state/slices/portfolioSlice/utils/index.ts
🚧 Files skipped from review as they are similar to previous changes (8)
- packages/swapper/src/thorchain-utils/getL1RateOrQuote.ts
- packages/swapper/src/utils.ts
- headers/csps/chains/near.ts
- src/state/apis/swapper/helpers/swapperApiHelpers.ts
- src/components/Modals/Send/utils.ts
- src/pages/RFOX/components/Stake/Bridge/hooks/useRfoxBridge.ts
- packages/swapper/src/types.ts
- src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,js,jsx}: Never assume a library is available - always check imports/package.json first
Prefer composition over inheritance
Write self-documenting code with clear variable and function names
Keep functions small and focused on a single responsibility
Avoid deep nesting - use early returns instead
Prefer procedural and easy to understand code
Never expose, log, or commit secrets, API keys, or credentials
Validate all inputs, especially user inputs
Handle errors gracefully with meaningful messages
Don't silently catch and ignore exceptions
Log errors appropriately for debugging
Provide fallback behavior when possible
Use appropriate data structures for the task
Never add code comments unless explicitly requested
When modifying code, do not add comments that reference previous implementations or explain what changed. Comments should only describe the current logic and functionality.
Use meaningful names for branches, variables, and functions
Always runyarn lint --fixandyarn type-checkafter making changes
Avoidletvariable assignments - preferconstwith inline IIFE switch statements or extract to functions for conditional logic
Files:
src/state/slices/portfolioSlice/utils/index.tspackages/chain-adapters/src/near/NearChainAdapter.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Avoid useEffect where practical - use it only when necessary and following best practices
Avoid 'any' types - use specific type annotations instead
For default values with user overrides, use computed values (useMemo) instead of useEffect - pattern:userSelected ?? smartDefault ?? fallback
When function parameters are unused due to interface requirements, refactor the interface or implementation to remove them rather than prefixing with underscore
Sanitize data before displaying to prevent XSS
Memoize aggressively - wrap component variables inuseMemoand callbacks inuseCallbackwhere possible
For static JSX icon elements (e.g.,<TbCopy />) that don't depend on state/props, define them as constants outside the component to avoid re-renders instead of using useMemo
Account for light/dark mode usinguseColorModeValuehook
Account for responsive mobile designs in all UI components
When applying styles, use the existing standards and conventions of the codebase
Use Chakra UI components and conventions
All copy/text must use translation keys - never hardcode strings
Use the translation hook:useTranslate()fromreact-polyglot
UseuseFeatureFlag('FlagName')hook to access feature flag values in components
Prefertypeoverinterfacefor type definitions
Use strict typing - avoidany
UseNominaltypes for domain identifiers (e.g.,WalletId,AccountId)
Import types from@shapeshiftoss/caipfor chain/account/asset IDs
UseuseAppSelectorfor Redux state
UseuseAppDispatchfor Redux actions
Memoize expensive computations withuseMemo
Memoize callbacks withuseCallback
**/*.{ts,tsx}: UseResult<T, E>pattern for error handling in swappers and APIs; ALWAYS useOk()andErr()from@sniptt/monads; AVOID throwing within swapper API implementations
ALWAYS use custom error classes from@shapeshiftoss/errorswith meaningful error codes for internationalization and relevant details in error objects
ALWAYS wrap async op...
Files:
src/state/slices/portfolioSlice/utils/index.tspackages/chain-adapters/src/near/NearChainAdapter.ts
src/state/slices/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
src/state/slices/**/*.ts: Migrations are required when changing persisted state structure (seesrc/state/migrations/)
Export selectors from slice using inlineselectorsproperty
Files:
src/state/slices/portfolioSlice/utils/index.ts
src/state/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
src/state/**/*.{ts,tsx}: UsecreateDeepEqualOutputSelectorfrom@/state/selector-utilsfor deep equality checks
UsecreateCachedSelectorfromre-reselectfor parameterized selectors
Files:
src/state/slices/portfolioSlice/utils/index.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/naming-conventions.mdc)
**/*.{js,jsx,ts,tsx}: Use camelCase for variables, functions, and methods with descriptive names that explain the purpose
Use verb prefixes for functions that perform actions (e.g., fetch, validate, execute, update, calculate)
Use UPPER_SNAKE_CASE for constants and configuration values with descriptive names
Usehandleprefix for event handlers with descriptive names in camelCase
Use descriptive boolean variable names withis,has,can,shouldprefixes
Use named exports for components, functions, and utilities instead of default exports
Use descriptive import names and avoid renaming imports unless necessary
Avoid non-descriptive variable names likedata,item,obj, and single-letter variable names except in loops
Avoid abbreviations in names unless they are widely understood
Avoid generic function names likefn,func, orcallback
Files:
src/state/slices/portfolioSlice/utils/index.tspackages/chain-adapters/src/near/NearChainAdapter.ts
🧠 Learnings (21)
📓 Common learnings
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:46-59
Timestamp: 2025-09-10T15:34:54.593Z
Learning: After extensive testing by gomesalexandre in PR #10458, dApps do not send EIP-712 domain.chainId as hex or bigint values in practice. The simple String(domain.chainId) conversion is sufficient for real-world usage in WalletConnect dApps structured signing.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11170
File: patches/@shapeshiftoss+bitcoinjs-lib+7.0.0-shapeshift.0.patch:9-19
Timestamp: 2025-11-25T21:43:10.838Z
Learning: In shapeshift/web, gomesalexandre will not expand PR scope to fix latent bugs in unused API surface (like bitcoinjs-lib patch validation methods) when comprehensive testing proves the actual used code paths work correctly, preferring to avoid costly hdwallet/web verdaccio publish cycles and full regression testing for conceptual issues with zero runtime impact.
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: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/ButtonWalletPredicate/ButtonWalletPredicate.tsx:7-7
Timestamp: 2025-08-27T09:47:06.275Z
Learning: In shapeshift/web project, NeOMakinG consistently prefers to defer UI/UX improvements and refactoring work (like the Drawer.Close hack fix in ButtonWalletPredicate.tsx) to follow-up PRs rather than expanding the scope of feature PRs, even when the improvements would enhance robustness.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-145
Timestamp: 2025-11-12T12:18:00.863Z
Learning: NEAR Intents swapper: The NEAR 1Click API does not provide gas limit estimation logic like other swappers (e.g., magic gasLimit fields). For ERC20 token swaps in getTradeQuote, accurate fee estimation requires token approval and sufficient balance; without these prerequisites, fees may display as 0 or use inaccurate native transfer estimates. This is a known limitation of the NEAR Intents integration.
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.
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to **/*.{ts,tsx} : Import types from `shapeshiftoss/caip` for chain/account/asset IDs
Applied to files:
src/state/slices/portfolioSlice/utils/index.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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
Applied to files:
src/state/slices/portfolioSlice/utils/index.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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
Applied to files:
src/state/slices/portfolioSlice/utils/index.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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
Applied to files:
src/state/slices/portfolioSlice/utils/index.ts
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to src/state/slices/**/*.ts : Migrations are required when changing persisted state structure (see `src/state/migrations/`)
Applied to files:
src/state/slices/portfolioSlice/utils/index.ts
📚 Learning: 2025-10-23T14:27:19.073Z
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.
Applied to files:
src/state/slices/portfolioSlice/utils/index.ts
📚 Learning: 2025-10-07T03:44:27.350Z
Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10760
File: src/components/ManageHiddenAssets/ManageHiddenAssetsList.tsx:78-84
Timestamp: 2025-10-07T03:44:27.350Z
Learning: In the ShapeShift web codebase, the following are stable references and do not need to be included in useCallback/useMemo dependency arrays:
- `navigate` from `useBrowserRouter()` hook
- Modal control objects (like `walletDrawer`) from `useModal()` hook (including their `isOpen`, `close`, and `open` methods)
- These are backed by stable context providers
Applied to files:
src/state/slices/portfolioSlice/utils/index.ts
📚 Learning: 2025-08-21T22:16:55.203Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10326
File: src/hooks/useActionCenterSubscribers/useFetchBasePortfolio.ts:33-35
Timestamp: 2025-08-21T22:16:55.203Z
Learning: In the ShapeShift web codebase Base portfolio management hack, the accountsById[accountId] check in upsertBasePortfolio serves as a security safeguard to ensure only user-associated accounts get balance updates, not just an existence check - this boundary should be maintained even during degraded Base state.
Applied to files:
src/state/slices/portfolioSlice/utils/index.ts
📚 Learning: 2025-09-08T15:53:09.362Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10442
File: src/components/TradeAssetSearch/components/GroupedAssetList/GroupedAssetList.tsx:34-35
Timestamp: 2025-09-08T15:53:09.362Z
Learning: In DefaultAssetList.tsx, the GroupedAssetList component already receives the activeChainId prop correctly on line ~58, contrary to automated analysis that may flag it as missing.
Applied to files:
src/state/slices/portfolioSlice/utils/index.ts
📚 Learning: 2025-09-04T17:29:59.479Z
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.
Applied to files:
src/state/slices/portfolioSlice/utils/index.ts
📚 Learning: 2025-08-21T22:14:39.915Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10326
File: src/hooks/useActionCenterSubscribers/useFetchBasePortfolio.ts:18-29
Timestamp: 2025-08-21T22:14:39.915Z
Learning: In the ShapeShift web codebase, temporary Base portfolio management hacks (marked with "TEMP HACK FOR BASE" comments) may use burst patterns like calling portfolioApi.getAccount with forceRefetch in tight loops, which are acceptable given they're temporary solutions and already used elsewhere in the app.
Applied to files:
src/state/slices/portfolioSlice/utils/index.ts
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Portfolio state is filtered by active `walletId`
Applied to files:
src/state/slices/portfolioSlice/utils/index.ts
📚 Learning: 2025-09-16T08:47:31.440Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10528
File: src/plugins/walletConnectToDapps/utils/createApprovalNamespaces.ts:39-47
Timestamp: 2025-09-16T08:47:31.440Z
Learning: In WalletConnect dApps createApprovalNamespaces logic, required namespaces have different semantics than optional namespaces. Required namespaces are validated upfront in the UI - users cannot proceed without accounts for all required chains, and required chains are always selected and unselectable. Therefore, additional filtering by selectedChainIds is unnecessary for required namespaces since the validation flow guarantees they will be supported and selected.
Applied to files:
src/state/slices/portfolioSlice/utils/index.ts
📚 Learning: 2025-09-18T23:47:14.810Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10566
File: src/hooks/useWalletSupportsChain/useWalletSupportsChain.ts:55-66
Timestamp: 2025-09-18T23:47:14.810Z
Learning: In the useWalletSupportsChain architecture, checkWalletHasRuntimeSupport() determines if the app has runtime capability to interact with a chain type (not actual signing capabilities), while walletSupportsChain() does the actual capabilities detection by checking account IDs. For Ledger read-only mode, checkWalletHasRuntimeSupport should return true since the app can display balances/addresses, with KeyManager being the source of truth rather than wallet instance.
Applied to files:
src/state/slices/portfolioSlice/utils/index.ts
📚 Learning: 2025-12-04T22:57:50.850Z
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.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-12-17T14:50:01.629Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11449
File: packages/chain-adapters/src/tron/TronChainAdapter.ts:570-596
Timestamp: 2025-12-17T14:50:01.629Z
Learning: In packages/chain-adapters/src/tron/TronChainAdapter.ts, the parseTx method uses `unknown` type for the txHashOrTx parameter intentionally. TRON is a "second-class chain" that works differently from other chains - it accepts either a string hash (to fetch TronTx via unchained client) or a TronTx object directly. The base chain-adapter interface is strongly typed and doesn't accommodate this flexible signature, so `unknown` is used as an appropriate escape hatch rather than a type safety issue.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-09-12T13:44:17.019Z
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.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-08-22T12:58:26.590Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/Layout/Header/ActionCenter/components/GenericTransactionActionCard.tsx:108-111
Timestamp: 2025-08-22T12:58:26.590Z
Learning: In the RFOX GenericTransactionDisplayType flow in src/components/Layout/Header/ActionCenter/components/GenericTransactionActionCard.tsx, the txHash is always guaranteed to be present according to NeOMakinG, so defensive null checks for txLink are not needed in this context.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-11-12T12:49:17.895Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-125
Timestamp: 2025-11-12T12:49:17.895Z
Learning: In packages/chain-adapters/src/evm/utils.ts, the getErc20Data function already includes a guard that returns an empty string when contractAddress is undefined (line 8: `if (!contractAddress) return ''`). This built-in handling means callers don't need to conditionally invoke getErc20Data—it safely handles both ERC20 tokens and native assets.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
🧬 Code graph analysis (2)
src/state/slices/portfolioSlice/utils/index.ts (4)
packages/caip/src/constants.ts (2)
nearChainId(90-90)CHAIN_NAMESPACE(93-102)packages/chain-adapters/src/types.ts (1)
Account(66-72)packages/chain-adapters/src/near/types.ts (1)
Account(19-21)src/lib/utils/near.ts (1)
supportsNear(10-12)
packages/chain-adapters/src/near/NearChainAdapter.ts (5)
src/lib/utils/near.ts (1)
supportsNear(10-12)packages/caip/src/constants.ts (3)
ASSET_REFERENCE(150-177)nearChainId(90-90)nearAssetId(27-27)packages/chain-adapters/src/types.ts (10)
GetBip44ParamsInput(133-138)AssetBalance(74-77)Account(66-72)BuildSendApiTxInput(211-213)BuildSendTxInput(200-209)SignTxInput(285-288)SignAndBroadcastTransactionInput(430-434)BroadcastTransactionInput(424-428)GetFeeDataInput(353-360)Transaction(148-152)packages/chain-adapters/src/error/ErrorHandler.ts (1)
ErrorHandler(28-79)packages/chain-adapters/src/near/types.ts (4)
FastNearFtResponse(12-15)Account(19-21)NearSignTx(38-43)GetFeeDataInput(29-32)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Call / Static
🔇 Additional comments (6)
src/state/slices/portfolioSlice/utils/index.ts (5)
24-24: LGTM - NEAR imports are correct.The
nearChainIdimport follows the pattern of other chains, and the customsupportsNearutility is appropriate for a new chain integration that may not yet be fully integrated into the upstream@shapeshiftoss/hdwallet-corepackage.Also applies to: 83-83
111-111: LGTM - Consistent label formatting for NEAR accounts.The
nearChainIdcase correctly usesmiddleEllipsis(pubkey), which is consistent with other account-based chains like Solana, Tron, Sui, and Starknet.
312-332: LGTM - NEAR portfolio integration follows established patterns.The
CHAIN_NAMESPACE.Nearcase correctly implements the same token processing pattern used by Solana, Tron, Sui, and Starknet. The type casting, account creation, token iteration, and balance tracking are all consistent with the existing codebase architecture.
415-419: LGTM - NEAR activity detection and wallet support are correct.Both implementations follow the established patterns:
checkAccountHasActivitycorrectly uses balance-only detection, consistent with Solana, Tron, Sui, and StarknetisAssetSupportedByWalletproperly delegates to thesupportsNearutilityAlso applies to: 496-497
554-760: No action needed. NEAR tokens are properly handled inaccountToPortfolio(lines 312-331) where they're processed with the same pattern as other non-EVM chains. The absence of a NEAR case inmakeAssetsis intentional since NEAR tokens are pre-loaded via asset generation and don't require the Portals API integration that EVM chains need.packages/chain-adapters/src/near/NearChainAdapter.ts (1)
322-346: LGTM! The validation logic correctly enforces NEAR account ID rules.The
validateAddressimplementation correctly handles all three NEAR account types:
- NEAR-implicit accounts (64 hex chars)
- ETH-implicit accounts (0x + 40 hex chars)
- Named accounts with proper validation
The named account regex
/^(([a-z\d]+[-_])*[a-z\d]+\.)*([a-z\d]+[-_])*[a-z\d]+$/correctly enforces:
- Only lowercase alphanumeric + separators (
-,_)- Cannot start/end with separators
- No consecutive separators
- Dot-separated parts for subaccounts
Testing the regex against the examples from the past review comment:
.alice→ rejected (must start with alphanumeric) ✓alice-→ rejected (must end with alphanumeric) ✓alice..bob→ rejected (requires alphanumeric between dots) ✓alice_-bob→ rejected (requires alphanumeric between separators) ✓
CSP connect-src doesn't support wildcard paths, so the base domain must be used in the env var while the /v1 path prefix is handled in the code.
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: 0
🧹 Nitpick comments (2)
.env (1)
166-169: Reorder NEAR-related environment variables to maintain alphabetical consistency.The new NEAR node URLs (lines 166–169) and feature flag (line 310) are placed out of alphabetical order relative to other variables in their respective sections. The linter reports:
- VITE_NEAR_NODE_URL and fallbacks should come before VITE_OPTIMISM_NODE_URL (line 150)
- VITE_FASTNEAR_API_URL should come before VITE_GNOSIS_NODE_URL (line 153)
- VITE_FEATURE_NEAR should come before VITE_FEATURE_PLASMA (line 307)
This appears to be a project convention. Consider moving these entries to maintain alphabetical ordering within their respective sections.
🔎 Suggested reordering (if alphabetical ordering is enforced)
For the nodes section, move VITE_NEAR* and VITE_FASTNEAR_API_URL entries to appear earlier (after MONAD_NODE_URL around line 158).
For the feature flags section, move VITE_FEATURE_NEAR before VITE_FEATURE_PLASMA (currently at line 307).
Also applies to: 310-310
packages/chain-adapters/src/near/NearChainAdapter.ts (1)
574-614: Gas estimates are conservative; implement RPC simulation in follow-up.The estimates at lines 587-588 are significantly higher than typical NEAR gas costs (native: ~0.45 TGas vs 2.5 TGas; token transfers: ~14–15 TGas ft_transfer + ~10 TGas storage vs 30 TGas each). This conservative approach is acceptable for initial release and the TODO on line 582 appropriately flags the need for actual RPC simulation. Consider implementing gas simulation via NEAR RPC in a follow-up to provide more accurate fee estimates based on contract execution rather than static defaults.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
.envpackages/chain-adapters/src/near/NearChainAdapter.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx,js,jsx}: Never assume a library is available - always check imports/package.json first
Prefer composition over inheritance
Write self-documenting code with clear variable and function names
Keep functions small and focused on a single responsibility
Avoid deep nesting - use early returns instead
Prefer procedural and easy to understand code
Never expose, log, or commit secrets, API keys, or credentials
Validate all inputs, especially user inputs
Handle errors gracefully with meaningful messages
Don't silently catch and ignore exceptions
Log errors appropriately for debugging
Provide fallback behavior when possible
Use appropriate data structures for the task
Never add code comments unless explicitly requested
When modifying code, do not add comments that reference previous implementations or explain what changed. Comments should only describe the current logic and functionality.
Use meaningful names for branches, variables, and functions
Always runyarn lint --fixandyarn type-checkafter making changes
Avoidletvariable assignments - preferconstwith inline IIFE switch statements or extract to functions for conditional logic
Files:
packages/chain-adapters/src/near/NearChainAdapter.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Avoid useEffect where practical - use it only when necessary and following best practices
Avoid 'any' types - use specific type annotations instead
For default values with user overrides, use computed values (useMemo) instead of useEffect - pattern:userSelected ?? smartDefault ?? fallback
When function parameters are unused due to interface requirements, refactor the interface or implementation to remove them rather than prefixing with underscore
Sanitize data before displaying to prevent XSS
Memoize aggressively - wrap component variables inuseMemoand callbacks inuseCallbackwhere possible
For static JSX icon elements (e.g.,<TbCopy />) that don't depend on state/props, define them as constants outside the component to avoid re-renders instead of using useMemo
Account for light/dark mode usinguseColorModeValuehook
Account for responsive mobile designs in all UI components
When applying styles, use the existing standards and conventions of the codebase
Use Chakra UI components and conventions
All copy/text must use translation keys - never hardcode strings
Use the translation hook:useTranslate()fromreact-polyglot
UseuseFeatureFlag('FlagName')hook to access feature flag values in components
Prefertypeoverinterfacefor type definitions
Use strict typing - avoidany
UseNominaltypes for domain identifiers (e.g.,WalletId,AccountId)
Import types from@shapeshiftoss/caipfor chain/account/asset IDs
UseuseAppSelectorfor Redux state
UseuseAppDispatchfor Redux actions
Memoize expensive computations withuseMemo
Memoize callbacks withuseCallback
**/*.{ts,tsx}: UseResult<T, E>pattern for error handling in swappers and APIs; ALWAYS useOk()andErr()from@sniptt/monads; AVOID throwing within swapper API implementations
ALWAYS use custom error classes from@shapeshiftoss/errorswith meaningful error codes for internationalization and relevant details in error objects
ALWAYS wrap async op...
Files:
packages/chain-adapters/src/near/NearChainAdapter.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/naming-conventions.mdc)
**/*.{js,jsx,ts,tsx}: Use camelCase for variables, functions, and methods with descriptive names that explain the purpose
Use verb prefixes for functions that perform actions (e.g., fetch, validate, execute, update, calculate)
Use UPPER_SNAKE_CASE for constants and configuration values with descriptive names
Usehandleprefix for event handlers with descriptive names in camelCase
Use descriptive boolean variable names withis,has,can,shouldprefixes
Use named exports for components, functions, and utilities instead of default exports
Use descriptive import names and avoid renaming imports unless necessary
Avoid non-descriptive variable names likedata,item,obj, and single-letter variable names except in loops
Avoid abbreviations in names unless they are widely understood
Avoid generic function names likefn,func, orcallback
Files:
packages/chain-adapters/src/near/NearChainAdapter.ts
🧠 Learnings (14)
📓 Common learnings
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11170
File: patches/@shapeshiftoss+bitcoinjs-lib+7.0.0-shapeshift.0.patch:9-19
Timestamp: 2025-11-25T21:43:10.838Z
Learning: In shapeshift/web, gomesalexandre will not expand PR scope to fix latent bugs in unused API surface (like bitcoinjs-lib patch validation methods) when comprehensive testing proves the actual used code paths work correctly, preferring to avoid costly hdwallet/web verdaccio publish cycles and full regression testing for conceptual issues with zero runtime impact.
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: 10458
File: src/plugins/walletConnectToDapps/components/modals/EIP712MessageDisplay.tsx:46-59
Timestamp: 2025-09-10T15:34:54.593Z
Learning: After extensive testing by gomesalexandre in PR #10458, dApps do not send EIP-712 domain.chainId as hex or bigint values in practice. The simple String(domain.chainId) conversion is sufficient for real-world usage in WalletConnect dApps structured signing.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/ButtonWalletPredicate/ButtonWalletPredicate.tsx:7-7
Timestamp: 2025-08-27T09:47:06.275Z
Learning: In shapeshift/web project, NeOMakinG consistently prefers to defer UI/UX improvements and refactoring work (like the Drawer.Close hack fix in ButtonWalletPredicate.tsx) to follow-up PRs rather than expanding the scope of feature PRs, even when the improvements would enhance robustness.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10231
File: src/components/MultiHopTrade/components/TradeInput/components/HighlightedTokens.tsx:14-14
Timestamp: 2025-08-08T15:00:22.321Z
Learning: In shapeshift/web reviews for NeOMakinG, avoid nitpicks to change deep-relative imports to '@/…' alias paths within feature/non-refactor PRs; defer such style-only changes to a dedicated follow-up refactor unless they fix an issue.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10879
File: src/context/WalletProvider/WalletConnectV2/components/WalletConnectDirectRow.tsx:64-81
Timestamp: 2025-10-22T22:11:22.918Z
Learning: In early WalletConnect POC/features behind a flag, gomesalexandre prioritizes connection correctness/stability over UX polish; minimal safety guards (like preventing concurrent connects) are preferred, while visuals will be wired later by reallybeard.
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10232
File: packages/unchained-client/openapitools.json:61-61
Timestamp: 2025-08-08T10:23:16.843Z
Learning: In shapeshift/web, for temporary “monkey patch” PRs (e.g., packages/unchained-client/openapitools.json using jsDelivr CDN refs like cosmos/mayachain), gomesalexandre is fine with branch-based URLs and does not want SHA pinning. Treat this as a scoped exception to their general preference for pinned dependencies/refs.
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.
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to src/config.ts : Default values always come from environment variables prefixed with `VITE_FEATURE_`
Applied to files:
.env
📚 Learning: 2025-12-03T23:19:39.158Z
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.
Applied to files:
.env
📚 Learning: 2025-09-09T06:01:24.130Z
Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10424
File: .env.production:3-3
Timestamp: 2025-09-09T06:01:24.130Z
Learning: In Vite, environment variables have a fallback mechanism where .env.production takes precedence over .env, but variables defined only in .env will still be available in the production environment if not overridden in .env.production.
Applied to files:
.env
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: To add a new feature flag: (1) Add to `FeatureFlags` type in `src/state/slices/preferencesSlice/preferencesSlice.ts`, (2) Add environment variable validation in `src/config.ts`, (3) Add to initial state in `preferencesSlice.ts`, (4) Add to test mock in `src/test/mocks/store.ts`, (5) Set appropriate values in `.env`, `.env.development`, and `.env.production`
Applied to files:
.env
📚 Learning: 2025-12-04T22:57:50.850Z
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.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-09-12T13:44:17.019Z
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.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-12-17T14:50:01.629Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11449
File: packages/chain-adapters/src/tron/TronChainAdapter.ts:570-596
Timestamp: 2025-12-17T14:50:01.629Z
Learning: In packages/chain-adapters/src/tron/TronChainAdapter.ts, the parseTx method uses `unknown` type for the txHashOrTx parameter intentionally. TRON is a "second-class chain" that works differently from other chains - it accepts either a string hash (to fetch TronTx via unchained client) or a TronTx object directly. The base chain-adapter interface is strongly typed and doesn't accommodate this flexible signature, so `unknown` is used as an appropriate escape hatch rather than a type safety issue.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-11-19T16:59:50.569Z
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.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-11-24T21:20:57.909Z
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
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-08-26T19:04:38.672Z
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.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-11-24T21:20:04.979Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-24T21:20:04.979Z
Learning: Applies to **/*.{ts,tsx} : Import types from `shapeshiftoss/caip` for chain/account/asset IDs
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-08-22T12:58:26.590Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/Layout/Header/ActionCenter/components/GenericTransactionActionCard.tsx:108-111
Timestamp: 2025-08-22T12:58:26.590Z
Learning: In the RFOX GenericTransactionDisplayType flow in src/components/Layout/Header/ActionCenter/components/GenericTransactionActionCard.tsx, the txHash is always guaranteed to be present according to NeOMakinG, so defensive null checks for txLink are not needed in this context.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
📚 Learning: 2025-11-12T12:49:17.895Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: packages/swapper/src/swappers/NearIntentsSwapper/swapperApi/getTradeQuote.ts:109-125
Timestamp: 2025-11-12T12:49:17.895Z
Learning: In packages/chain-adapters/src/evm/utils.ts, the getErc20Data function already includes a guard that returns an empty string when contractAddress is undefined (line 8: `if (!contractAddress) return ''`). This built-in handling means callers don't need to conditionally invoke getErc20Data—it safely handles both ERC20 tokens and native assets.
Applied to files:
packages/chain-adapters/src/near/NearChainAdapter.ts
🪛 dotenv-linter (4.0.0)
.env
[warning] 166-166: [UnorderedKey] The VITE_NEAR_NODE_URL key should go before the VITE_OPTIMISM_NODE_URL key
(UnorderedKey)
[warning] 167-167: [UnorderedKey] The VITE_NEAR_NODE_URL_FALLBACK_1 key should go before the VITE_OPTIMISM_NODE_URL key
(UnorderedKey)
[warning] 168-168: [UnorderedKey] The VITE_NEAR_NODE_URL_FALLBACK_2 key should go before the VITE_OPTIMISM_NODE_URL key
(UnorderedKey)
[warning] 169-169: [UnorderedKey] The VITE_FASTNEAR_API_URL key should go before the VITE_GNOSIS_NODE_URL key
(UnorderedKey)
[warning] 310-310: [UnorderedKey] The VITE_FEATURE_NEAR key should go before the VITE_FEATURE_PLASMA key
(UnorderedKey)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Call / Static
🔇 Additional comments (6)
packages/chain-adapters/src/near/NearChainAdapter.ts (6)
121-176: LGTM: Robust rate limit handling.The constructor validation and rate limit retry logic with exponential backoff is well-implemented. The
withRateLimitRetrywrapper correctly detects rate limit errors via multiple heuristics and only retries those specific errors, while re-throwing others immediately. This addresses the failover concerns from previous reviews.
108-243: LGTM: Solid chain adapter foundation.The core adapter structure follows established patterns:
- Proper type guards with
assertSupportsChain- Error handling via
ErrorHandlerwith translation keys- Ledger support via
verifyLedgerAppOpen- BIP44 derivation correctly implements NEAR's 3-level path (line 209-216)
- Address derivation handles both pubkey and wallet cases
The implementation is comprehensive and follows the codebase conventions for chain adapters.
466-519: LGTM: Custom signature handling matches established patterns.The custom
ED25519Signatureclass (lines 492-498) mirrors the pattern used in the Sui chain adapter, as noted in the comment. This approach is appropriate when the library doesn't expose the needed constructor. The Borsh serialization and base64 encoding follows NEAR protocol requirements correctly.
650-743: LGTM: Comprehensive transaction parsing.The
parseTximplementation correctly:
- Fetches actual block details for accurate height and timestamp (lines 668-674), addressing the previous review comment
- Calculates total fees from all burnt tokens across transaction and receipts (lines 676-686)
- Parses both native NEAR transfers and NEP-141 token transfers
- Handles send/receive distinction based on pubkey
The integration with
parseNep141Transfersprovides complete transaction history parsing for NEAR's multi-receipt model.
322-346: The named account regex correctly implements all NEAR protocol requirements: it enforces alphanumeric start/end for dot-separated parts, prevents consecutive separators, and respects the 2-64 character length constraint. No changes needed.
386-402: Storage deposit and gas constants should be queried from the contract instead of hardcoded.The NEP-141 token transfer implementation uses reasonable default constants:
STORAGE_DEPOSIT_AMOUNT = 0.00125 NEARis a typical registration costFT_TRANSFER_GAS = 30 TGasis within normal rangeONE_YOCTO = 1is protocol-requiredHowever, each NEP-141 contract can define its own storage deposit requirement via
storage_balance_bounds(). The hardcoded approach will fail for contracts requiring different amounts. Consider querying the contract's actual storage deposit requirement before execution instead of using a universal constant, or document that this adapter only supports contracts with the standard 0.00125 NEAR deposit requirement.
Description
Test with hdwallet fren
TODO:
you know what Trezor too because why notIssue (if applicable)
N/A
Risk
I mean it's a new chain
Testing
Engineering
Operations
☝🏽
🏁 My feature is behind a flag and doesn't require operations testing (yet)
Screenshots (if applicable)
Summary by CodeRabbit
New Features
Documentation
Configuration
✏️ Tip: You can customize this high-level summary in your review settings.