Conversation
📝 WalkthroughWalkthroughAdds end-to-end Starknet support: environment flags and node URL, a Starknet chain adapter and types, asset generation and native STRK asset, UI/account deployment flows, swapper and trade execution integrations, feature-flag gating, CSP updates, and related tests/hooks across the codebase. Changes
Sequence Diagram(s)mermaid Note over Adapter,RPC: errors map to TxStatus (Confirmed/Failed/Unknown) Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
- Import and use isStarknetChainAdapter type guard - Remove all 'as any' casts for adapter methods (isAccountDeployed, deployAccount, getStarknetProvider) - Fix feeData.fast.chainSpecific.maxFee access without casting - Affected files: Form.tsx (4 fixes), TradeFooterButton.tsx (4 fixes), useSendActionSubscriber.tsx (1 fix) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Issue #3 - Debug Code: - Remove 25+ console.log/console.debug statements from StarknetChainAdapter - Remove debug log from NearIntentsSwapper helpers - Remove debug logs from Send Form deployment flow - Keep console.error for error handling/logging Issue #7 - RPC Error Handling: - Remove silent fallback to '0x0' for nonce fetch failures - Throw errors when nonce RPC call fails instead of silently continuing - Prevents confusing transaction failures downstream 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Issue #4 - Test Files: - Remove test-starknet-deploy.js from repo root - Remove scripts/test-starknet-asset-generation.ts (untracked) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Match Sui/Tron pattern: throw errors from parseTx instead of returning Unknown status - Remove unused computedAddress calculation block (leftover from debug code removal) - Keep inner try-catch for optional detail fetches (block timestamp, tx details) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Remove temporary Starknet-only regeneration - Restore full chain regeneration (all chains) - Uncomment console.log for related asset processing - Now that Starknet assets are added, can regenerate all chains normally 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Types cleanup: - Move all inline RPC/Starknet types from ChainAdapter to types.ts - Follow Sui/Tron pattern: no inline types in adapter - Cleaner imports and better organization Nonce handling fix: - Fee estimation: Fallback to 0x0 if account not deployed (for estimates) - buildSendApiTransaction: Check isAccountDeployed() first, use 0x0 for undeployed - Prevents errors when trying to send before account deployment - Matches expected Starknet behavior (0x0 nonce for first tx) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Assets: - Add 38 Starknet assets (1 base + 37 tokens) to encoded asset data - Update related asset index for Starknet assets - Total assets now: 25,494 (from 25,456) Dependencies: - Bump hdwallet packages to 1.62.33-starknet.14 - Update yarn.lock Migrations: - Add migration 255 for asset data changes - Keep single migration as per review guidelines Lint: - Fix line length in starknet/index.ts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
Add starknetAssetId to popular assets list when Starknet feature flag is enabled, matching the pattern used for other second-class chains (Sui, Tron, etc.). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Update yarn.lock with @shapeshiftoss/hdwallet-* packages to 1.62.33 - Fix duplicate imports in starknet types.ts - Add starknet assets to asset generation script 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
There was a problem hiding this comment.
See hdwallet review - functionally does the thing, additionally, added proper (ish, assuming it holds next regen) regen of starknet assets which was failing (not sure regen will work and it may ditch those, as there seems to be shenanigans here and super hard to debug, but #11520 will make that a breeze to debug. Feel free to run regen again and see if they hold in!)
- Few qs here re: cleanup .md/test/env vars for you to tackle before merging
- also will definitely need a proper cleanup here, will do another implementation pass once opened, many many hacky bits that need cleanup, but functionally does the do
- as you noted, the whole flow of send -> account creation is odd and feels broken, feels weird to have "Broadcasting transaction" spinning, but actually doesn't, then activation modal opens up on top of it, activation is broadcasted and modal closed, then send modal is visible without a loading state and automagically does the previous send after a sec or 2.
Maybe defer activation to earlier in the flow (i.e block flow and enforce activation when attempting to do Starknet Tx bits in send/swapper land vs. letting it seemingly go through and then activate at broadcast time) so we 1. don't have to write so many hacky bits and 2. don't get into such flow in the first place?
Merry Christmas ser! 🎄
Resolved conflicts in package.json files and yarn.lock by keeping hdwallet packages at 1.62.33 (our version). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
- Remove debug console.log statements - Update hdwallet dependencies to 1.62.34 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
There was a problem hiding this comment.
Actionable comments posted: 7
♻️ Duplicate comments (1)
STARKNET_SWAP_SUPPORT.md (1)
1-136: Documentation file noted - decision needed on whether to keep.This documentation provides useful internal reference for Starknet swap implementation, including file locations, troubleshooting tips, and testing instructions. However, the specific line number references (e.g., "Lines 239-256") will become stale as the codebase evolves.
If keeping this documentation, consider:
- Removing specific line number references or linking to GitHub permalinks instead
- Moving to a more permanent documentation location (e.g., internal wiki or ADR)
Addressing the previous review comment: This decision should be made by the maintainers based on documentation strategy.
🧹 Nitpick comments (10)
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts (1)
64-69: Consider simplifying the redundant chainId checks.Lines 68-69 check
asset.chainId === suiChainIdandasset.chainId === starknetChainId, but these are redundant because:
nearNetworkis derived fromchainIdToNearIntentsChain[asset.chainId]- If
nearNetworkis'sui'or'starknet', thenasset.chainIdmust already besuiChainIdorstarknetChainIdrespectively- The
isTokenLookupChain(nearNetwork)check on line 66 already covers both casesThe condition could be simplified to:
const requiresLookup = isNep245Chain(nearNetwork) || isTokenLookupChain(nearNetwork) || asset.chainId === solanaChainId🔎 Proposed simplification
const requiresLookup = isNep245Chain(nearNetwork) || isTokenLookupChain(nearNetwork) || - asset.chainId === solanaChainId || - asset.chainId === suiChainId || - asset.chainId === starknetChainId + asset.chainId === solanaChainIdsrc/components/MultiHopTrade/hooks/useGetTradeQuotes/getTradeQuoteOrRateInput.ts (1)
239-256: LGTM with optional refinement suggestion.The Starknet case implementation correctly follows the pattern established by Solana and Sui cases. The adapter retrieval, address derivation, and return value structure are all consistent.
Optional: Consider explicit type cast for consistency
For consistency with other cases (EVM uses
as EvmChainId, Cosmos usesas CosmosSdkChainId, etc.), consider explicitly casting the chainId on line 253:return { ...tradeQuoteInputCommonArgs, - chainId: sellAsset.chainId, + chainId: sellAsset.chainId as StarknetChainId, sendAddress, } as GetTradeQuoteInputThis would align with the pattern used in lines 109, 128, 170, 193, 217, and 235, though the current implementation may work if StarknetChainId is compatible with the base ChainId type.
scripts/generateAssetData/coingecko.ts (1)
170-177: Hardcoded explorer URLs differ from the pattern used by other chains.Other chains import explorer configuration from
@shapeshiftoss/utils(e.g.,ethereum.explorer,solana.explorerAddressLink), while Starknet hardcodes the StarkScan URLs directly. Similarly,categoryis hardcoded as'starknet'rather than usingadapters.chainIdToCoingeckoAssetPlatform(chainId).This works but diverges from the established pattern. Consider extracting Starknet explorer config to
@shapeshiftoss/utilsin a follow-up for consistency.src/lib/utils/starknet.ts (1)
36-36: Consider typing the receipt if the Starknet provider types are available.Using
anyhere works, but if@starknet/starknet.jsprovides receipt types, using them would improve type safety.🔎 Potential improvement
- const receipt: any = await provider.getTransactionReceipt(txHash) + const receipt = await provider.getTransactionReceipt(txHash)If the provider's return type is properly typed, this would give you compile-time safety on the
execution_statusproperty access.src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx (1)
190-195: Info toast will persist indefinitely.The info toast uses
duration: nullwhich means it won't auto-dismiss. After the success toast appears, the info toast may remain visible unless explicitly closed. Consider either:
- Closing it manually before showing the success toast
- Using a finite duration
🔎 Potential approach
+ const infoToastId = toast({ - toast({ status: 'info', title: translate('starknet.deployAccount.deployingTitle'), description: translate('starknet.deployAccount.deployingDescription'), duration: null, + id: 'starknet-deploy-info', }) // ... wait for transaction ... + toast.close('starknet-deploy-info') toast({ status: 'success',src/components/Modals/Send/Form.tsx (1)
265-271: Consider handling undefined accountMetadata more defensively.If
selectPortfolioAccountMetadataByAccountIdreturnsundefined, the code defaultsaccountNumberto0. This silent fallback may mask configuration issues. Consider logging a warning or validating the account exists.const accountMetadata = selectPortfolioAccountMetadataByAccountId( store.getState(), { accountId: formAccountId, }, ) -const accountNumber = accountMetadata?.bip44Params.accountNumber ?? 0 +if (!accountMetadata) { + console.warn('Account metadata not found for Starknet deployment, defaulting to account 0') +} +const accountNumber = accountMetadata?.bip44Params.accountNumber ?? 0scripts/generateAssetData/starknet/index.ts (1)
35-54: Consider usingconstwith reduce pattern instead ofletformodifiedAssets.Per coding guidelines, avoid
letvariable assignments. The batch processing loop could use a functional approach.🔎 Alternative using reduce
-let modifiedAssets: Asset[] = [] - -for (const [i, batch] of assetBatches.entries()) { - console.info(`processing Starknet batch ${i + 1} of ${assetBatches.length}`) - const promises = batch.map(({ assetId }) => { - const { info } = generateTrustWalletUrl(assetId) - return axios.head(info) - }) - const result = await Promise.allSettled(promises) - const newModifiedTokens = result.map((res, idx) => { - const key = i * batchSize + idx - if (res.status === 'rejected') { - return uniqueAssets[key] - } else { - const { icon } = generateTrustWalletUrl(uniqueAssets[key].assetId) - return { ...uniqueAssets[key], icon } - } - }) - modifiedAssets = modifiedAssets.concat(newModifiedTokens) -} +const modifiedAssets: Asset[] = [] + +for (const [i, batch] of assetBatches.entries()) { + console.info(`processing Starknet batch ${i + 1} of ${assetBatches.length}`) + const promises = batch.map(({ assetId }) => { + const { info } = generateTrustWalletUrl(assetId) + return axios.head(info) + }) + const result = await Promise.allSettled(promises) + const newModifiedTokens = result.map((res, idx) => { + const key = i * batchSize + idx + if (res.status === 'rejected') { + return uniqueAssets[key] + } else { + const { icon } = generateTrustWalletUrl(uniqueAssets[key].assetId) + return { ...uniqueAssets[key], icon } + } + }) + modifiedAssets.push(...newModifiedTokens) +}Note: Using
pushwith spread on aconstarray is acceptable since we're mutating the array contents, not reassigning the variable.packages/chain-adapters/src/starknet/StarknetChainAdapter.ts (3)
77-79: Consider using the enumIndex pattern for getName() for consistency.Based on learnings, other chain adapters use the pattern
Object.values(ChainAdapterDisplayName).indexOf(ChainAdapterDisplayName.XXX)to reverse-lookup the enum key. While the hardcoded string works, using the established pattern ensures consistency across all chain adapters.🔎 Consistent pattern with other adapters
getName() { - return 'Starknet' + const enumIndex = Object.values(ChainAdapterDisplayName).indexOf( + ChainAdapterDisplayName.Starknet, + ) + return Object.keys(ChainAdapterDisplayName)[enumIndex] }
210-216: Simplify duplicate return statements.The error handling has redundant
return falsestatements that can be consolidated.🔎 Simplified error handling
// If we get an error, account is not deployed if (result.error) { - // Error code 20 = CONTRACT_NOT_FOUND means not deployed - if (result.error.code === 20) { - return false - } + // Error code 20 = CONTRACT_NOT_FOUND means not deployed + // Other errors also indicate the account is not accessible/deployed return false }
432-727: Large method could benefit from extraction, but acceptable for initial implementation.The
buildSendApiTransactionmethod is quite large (~295 lines) with multiple responsibilities: balance fetching for sendMax, nonce retrieval, fee estimation, calldata building, and transaction hash calculation. While this could be refactored into smaller helper methods for maintainability, it's acceptable for the initial Starknet implementation. Consider extracting helpers in a follow-up.
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
Outdated
Show resolved
Hide resolved
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts (1)
905-950: ** Fee estimation uses unrealistic hardcoded gas values.**As noted in the previous review, the hardcoded
typicalL1GasConsumedvalue of 100,000 (0x186a0) is 20-100x higher than actual typical L1 gas consumption for Starknet v3 transactions (typically ~1,000-5,000 gas for simple operations). This will cause significantly overestimated fees displayed to users.For accurate fee estimation, consider:
- Using transaction-specific fee estimation via
starknet_estimateFeefor each transaction type- If generic estimates are needed, use more realistic baseline values (e.g., 2,000-5,000 instead of 100,000)
Based on web search results from the previous review analyzing Starknet mainnet fee consumption patterns.
🧹 Nitpick comments (2)
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts (2)
77-79: Consider using the established getName() pattern for consistency.Almost all other chain adapters (Bitcoin, Ethereum, Litecoin, etc.) use the pattern that reverse-lookups the enum key from its value. For consistency across adapters, consider:
🔎 Suggested refactor to match established pattern
getName() { - return 'Starknet' + const enumIndex = Object.values(ChainAdapterDisplayName).indexOf(ChainAdapterDisplayName.Starknet) + return Object.keys(ChainAdapterDisplayName)[enumIndex] }Based on learnings, this is the established pattern used consistently across almost all chain adapters for reverse-lookup of enum keys.
202-223: Consider specific error code handling to avoid masking RPC failures.Lines 214-215 return
falsefor any error other than code 20, which may mask genuine RPC failures (network issues, auth failures, etc.). Consider only treating specific "not found" error codes as "not deployed" and propagating unexpected errors.🔎 Suggested improvement
// If we get an error, account is not deployed if (result.error) { // Error code 20 = CONTRACT_NOT_FOUND means not deployed if (result.error.code === 20) { return false } - return false + // Unexpected error - propagate it + throw new Error(`Unexpected RPC error: ${result.error.message}`) } // If we got a nonce, account is deployed return true } catch (error) { - return false + // Only treat "not found" errors as not deployed + const errorMessage = error instanceof Error ? error.message : String(error) + if (errorMessage.includes('not found') || errorMessage.includes('CONTRACT_NOT_FOUND')) { + return false + } + throw error }
📜 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/starknet/StarknetChainAdapter.tspackages/swapper/package.json
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/chain-adapters/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/starknet/StarknetChainAdapter.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/starknet/StarknetChainAdapter.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/starknet/StarknetChainAdapter.ts
🧠 Learnings (20)
📓 Common learnings
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/components/Stake/components/StakeSummary.tsx:112-114
Timestamp: 2025-08-22T13:00:44.879Z
Learning: NeOMakinG prefers to keep PR changes minimal and focused on the core objectives, avoiding cosmetic or defensive code improvements that aren't directly related to the PR scope, even when they would improve robustness.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10128
File: .cursor/rules/error-handling.mdc:266-274
Timestamp: 2025-07-29T10:35:22.059Z
Learning: NeOMakinG prefers less nitpicky suggestions on documentation and best practices files, finding overly detailed suggestions on minor implementation details (like console.error vs logger.error) too granular for cursor rules documentation.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/pages/Dashboard/components/AccountList/AccountTable.tsx:60-0
Timestamp: 2025-09-02T08:34:08.157Z
Learning: NeOMakinG prefers code review comments to focus only on actual PR changes, not pre-existing code issues, unless there are critical security or correctness concerns directly related to the new functionality.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:42-86
Timestamp: 2025-08-08T11:41:22.794Z
Learning: NeOMakinG prefers not to include refactors in move-only PRs; such suggestions should be deferred to follow-up issues instead of being applied within the same PR.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/Table/Table.theme.ts:177-180
Timestamp: 2025-09-02T12:38:46.940Z
Learning: NeOMakinG prefers to defer technical debt and CSS correctness issues (like improper hover selectors) to follow-up PRs when the current PR is already large and focused on major feature implementation, even when the issues are valid from a usability/technical perspective.
📚 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-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-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.jsonpackage.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 TypeScript with explicit types (e.g., SupportedChainIds) for all code in the Swapper system
Applied to files:
packages/swapper/package.jsonpackages/chain-adapters/src/starknet/StarknetChainAdapter.ts
📚 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.jsonpackage.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.jsonpackage.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.jsonpackage.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/src/swappers/*/*.ts : All swappers must implement the Swapper interface from packages/swapper/src/types.ts
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: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.jsonpackage.json
📚 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.jsonpackage.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.jsonpackage.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:
package.jsonpackages/chain-adapters/src/starknet/StarknetChainAdapter.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:
package.json
📚 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/starknet/StarknetChainAdapter.ts
📚 Learning: 2025-09-12T13:43:19.770Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/utils/EIP155RequestHandlerUtil.ts:94-103
Timestamp: 2025-09-12T13:43:19.770Z
Learning: gomesalexandre has implemented a reliable gasLimit flow in WalletConnect dApps where Tenderly simulation provides gas estimates that get written to the form via setValue in GasSelectionMenu.tsx, making customTransactionData.gasLimit the primary reliable source. The sendTransaction.gasLimit fallback is kept as "paranoia" but may rarely be hit in practice due to this simulation-based architecture.
Applied to files:
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts
📚 Learning: 2025-11-12T12:18:00.863Z
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.
Applied to files:
packages/chain-adapters/src/starknet/StarknetChainAdapter.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/starknet/StarknetChainAdapter.ts
🔇 Additional comments (14)
package.json (1)
103-120: LGTM! Consistent hdwallet package version bumps.All 18 hdwallet packages are consistently updated from 1.62.32 to 1.62.34, maintaining proper synchronization across the hoisted dependencies. This aligns with the PR's Starknet implementation objectives, where account derivation and wallet support are core requirements.
packages/swapper/package.json (1)
42-42: Remove this verification request - hdwallet-core v1.62.34 does not include Starknet support.The shapeshift/hdwallet repository has no Starknet implementation. Starknet support in this PR is provided by shapeshift/web's own chain adapters (
packages/chain-adapters/src/starknet/), not by the hdwallet-core dependency. The version bump to 1.62.34 should be verified for its actual purpose (bug fixes, other features), not Starknet alignment.Likely an incorrect or invalid review comment.
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts (12)
45-50: LGTM - Well-defined constants.The STRK token address and OpenZeppelin account class hash are correctly defined as module-level constants for reuse throughout the adapter.
52-75: LGTM - Proper initialization and wallet validation.The class structure follows established patterns from other chain adapters, with proper BIP44 parameters and wallet type assertions.
107-132: LGTM - Address derivation logic is sound.The method correctly handles the pubKey shortcut, validates wallet support, and derives the address using BIP44 parameters. The TODO for Ledger verification is acceptable for initial implementation.
134-183: LGTM - Proper balance fetching with undeployed account handling.The Uint256 balance reconstruction is correct, and the try-catch appropriately handles undeployed accounts that cannot return balances yet.
185-192: LGTM - Proper address validation.Correctly delegates to starknet.js validateAndParseAddress and returns the appropriate ValidAddressResult type.
229-433: LGTM - Account deployment flow is comprehensive.The deployment logic correctly:
- Validates account state before deployment
- Uses RPC fee estimation with appropriate fallbacks
- Applies sensible margins (5x amount, 2x price) to resource bounds
- Properly signs and broadcasts the deployment transaction
The hardcoded placeholder values in the initial fee estimation request (lines 281-284) are appropriate since the RPC returns actual estimates.
457-569: SendMax fee estimation logic appears sound.The sendMax implementation:
- Queries the current balance
- Estimates fees for a dummy transaction with the full balance
- Subtracts estimated fees from balance to determine maximum sendable amount
This approach is reasonable for ERC-20 transfers where fees are paid in STRK.
571-742: LGTM - Transaction building logic is thorough.The method properly:
- Handles Uint256 value splitting for large amounts
- Constructs ERC-20 transfer calls with correct selector
- Manages nonce for both deployed and undeployed accounts
- Estimates fees and applies consistent safety margins
- Returns complete transaction details for signing
744-757: LGTM - Proper delegation pattern.This wrapper correctly derives the sender address and delegates to buildSendApiTransaction.
759-828: LGTM - Signature flow correctly implemented.The method properly:
- Validates wallet support
- Extracts transaction details and signs with the wallet
- Formats signatures with hex prefixes
- Serializes BigInt values to strings for JSON compatibility
830-903: LGTM - Sign and broadcast flow is correct.The methods properly:
- Chain signing and broadcasting operations
- Handle JSON serialization/deserialization round-trip
- Convert resource bounds through appropriate type transformations
- Submit transactions via the correct RPC endpoint
964-1147: LGTM - Transaction parsing logic is comprehensive.The parseTx method correctly:
- Handles pending and not-found transactions gracefully
- Maps Starknet execution status to internal TxStatus enum
- Parses fees from multiple response formats (v3 object structure and legacy)
- Extracts transfer events using the correct Transfer selector
- Reconstructs Uint256 amounts from low/high parts
- Creates both Send and Receive transfers based on address matching
- Normalizes addresses for consistent comparison
The error handling is robust throughout.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx (1)
133-141: Hardcoded toast strings should use translation keys.The toast messages on lines 137-138 use hardcoded English strings instead of translation keys, which violates coding guidelines.
🧹 Nitpick comments (3)
src/hooks/useIsStarknetAccountDeployed/useIsStarknetAccountDeployed.ts (1)
8-25: Minor: Avoid redundantfromAccountIdcall.
fromAccountId(accountId)is called on line 11, but the result isn't reused on line 19 where.accountis needed. Consider destructuringaccountalongsidechainIdfrom the first call.🔎 Suggested optimization
const checkStarknetAccountDeployment = async (accountId: AccountId | undefined) => { if (!accountId) return true - const { chainId } = fromAccountId(accountId) + const { chainId, account: fromAddress } = fromAccountId(accountId) if (chainId !== starknetChainId) return true try { const chainAdapterManager = getChainAdapterManager() const adapter = chainAdapterManager.get(chainId) if (!isStarknetChainAdapter(adapter)) return true - const fromAddress = fromAccountId(accountId).account return await adapter.isAccountDeployed(fromAddress) } catch (error) { console.error('Failed to check Starknet account deployment status:', error) return true } }src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx (1)
96-141: Consider extracting deployment mutation to a shared hook.The
deployAccountMutationlogic here is nearly identical to the implementation inSendAmountDetails.tsx. This duplication could lead to divergence over time. Consider extracting this into a shareduseDeployStarknetAccounthook that both components can consume.Given the PR author's preference for minimal focused changes, this refactor can be deferred to a follow-up. Based on learnings, the PR author prefers keeping changes minimal.
src/components/Modals/Send/views/SendAmountDetails.tsx (1)
117-162: Code duplication with TradeFooterButton.tsx.This
deployAccountMutationis nearly identical to the one inTradeFooterButton.tsx. As mentioned in that file's review, consider extracting to a shareduseDeployStarknetAccounthook.Based on learnings, this can be deferred to a follow-up PR to keep changes focused.
📜 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 (6)
.envsrc/assets/translations/en/main.jsonsrc/components/Modals/Send/Form.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/hooks/useIsStarknetAccountDeployed/useIsStarknetAccountDeployed.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/assets/translations/en/main.json
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{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/components/Modals/Send/Form.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsxsrc/hooks/useIsStarknetAccountDeployed/useIsStarknetAccountDeployed.tssrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
**/*.{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/components/Modals/Send/Form.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsxsrc/hooks/useIsStarknetAccountDeployed/useIsStarknetAccountDeployed.tssrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/error-handling.mdc)
**/*.{tsx,jsx}: ALWAYS wrap React components in error boundaries and provide user-friendly fallback components with error logging
ALWAYS useuseErrorToasthook for displaying errors with translated error messages and handle different error types appropriatelyUse PascalCase for React component names and match the component name to the file name
Files:
src/components/Modals/Send/Form.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
**/*.{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/components/Modals/Send/Form.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsxsrc/hooks/useIsStarknetAccountDeployed/useIsStarknetAccountDeployed.tssrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/react-best-practices.mdc)
**/*.{jsx,tsx}: ALWAYS useuseMemofor expensive computations, object/array creations, and filtered data
ALWAYS useuseMemofor derived values and computed properties
ALWAYS useuseMemofor conditional values and simple transformations
ALWAYS useuseCallbackfor event handlers and functions passed as props
ALWAYS useuseCallbackfor any function that could be passed as a prop or dependency
ALWAYS include all dependencies inuseEffect,useMemo,useCallbackdependency arrays
NEVER use// eslint-disable-next-line react-hooks/exhaustive-depsunless absolutely necessary, and ALWAYS explain why dependencies are excluded if using eslint disable
ALWAYS use named exports for components; NEVER use default exports for components
KEEP component files under 200 lines when possible; BREAK DOWN large components into smaller, reusable pieces
EXTRACT complex logic into custom hooks
ALWAYS wrap components in error boundaries for production
ALWAYS handle async errors properly in async operations
ALWAYS provide user-friendly error messages in error handling
ALWAYS use virtualization for lists with 100+ items
ALWAYS implement proper key props for list items
ALWAYS lazy load heavy components using React.lazy for code splitting
ALWAYS use Suspense wrapper for lazy loaded components
USE local state for component-level state; LIFT state up when needed across multiple components; USE Context for avoiding prop drilling; USE Redux only for global state shared across multiple places
Wrap components receiving props withmemofor performance optimization
Files:
src/components/Modals/Send/Form.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react-best-practices.mdc)
Ensure TypeScript types are explicit and proper; avoid use of
anytype
Files:
src/components/Modals/Send/Form.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
🧠 Learnings (51)
📓 Common learnings
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/swapper.mdc:0-0
Timestamp: 2025-11-24T21:20:57.909Z
Learning: Applies to packages/swapper/**/*.ts : Use TypeScript with explicit types (e.g., SupportedChainIds) for all code in the Swapper system
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/components/Stake/components/StakeSummary.tsx:112-114
Timestamp: 2025-08-22T13:00:44.879Z
Learning: NeOMakinG prefers to keep PR changes minimal and focused on the core objectives, avoiding cosmetic or defensive code improvements that aren't directly related to the PR scope, even when they would improve robustness.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10128
File: .cursor/rules/error-handling.mdc:266-274
Timestamp: 2025-07-29T10:35:22.059Z
Learning: NeOMakinG prefers less nitpicky suggestions on documentation and best practices files, finding overly detailed suggestions on minor implementation details (like console.error vs logger.error) too granular for cursor rules documentation.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/pages/Dashboard/components/AccountList/AccountTable.tsx:60-0
Timestamp: 2025-09-02T08:34:08.157Z
Learning: NeOMakinG prefers code review comments to focus only on actual PR changes, not pre-existing code issues, unless there are critical security or correctness concerns directly related to the new functionality.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:42-86
Timestamp: 2025-08-08T11:41:22.794Z
Learning: NeOMakinG prefers not to include refactors in move-only PRs; such suggestions should be deferred to follow-up issues instead of being applied within the same PR.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/Table/Table.theme.ts:177-180
Timestamp: 2025-09-02T12:38:46.940Z
Learning: NeOMakinG prefers to defer technical debt and CSS correctness issues (like improper hover selectors) to follow-up PRs when the current PR is already large and focused on major feature implementation, even when the issues are valid from a usability/technical perspective.
📚 Learning: 2025-10-21T17:11:18.087Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10871
File: src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx:426-428
Timestamp: 2025-10-21T17:11:18.087Z
Learning: In src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx, within the handleInputChange function, use .toFixed() without arguments (not .toString()) when converting BigNumber amounts for input field synchronization. This avoids exponential notation in the input while preserving precision for presentational components like <Amount.Crypto /> and <Amount.Fiat /> to format appropriately.
Applied to files:
src/components/Modals/Send/Form.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-09-12T11:52:39.280Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP155TransactionConfirmation.tsx:18-21
Timestamp: 2025-09-12T11:52:39.280Z
Learning: In WalletConnect dApps integration, gomesalexandre has implemented intentional routing logic where EIP155TransactionConfirmation is typed for EthSignTransactionCallRequest only, while a separate SendTransactionConfirmation component handles EthSendTransactionCallRequest. The WalletConnectModalManager contains conditional logic to route native send transactions to SendTransactionConfirmation and other transaction types to EIP155TransactionConfirmation, creating a clean separation of concerns between signing and sending flows.
Applied to files:
src/components/Modals/Send/Form.tsx
📚 Learning: 2025-08-29T07:07:49.332Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10386
File: src/components/MultiHopTrade/components/VerifyAddresses/VerifyAddresses.tsx:272-294
Timestamp: 2025-08-29T07:07:49.332Z
Learning: In UTXO sell address verification flow in VerifyAddresses.tsx, the user wants address verification to be marked as "verified/complete" before starting the change address fetch, not after. The verification step and change address fetch should be treated as separate sequential operations in the UI flow.
Applied to files:
src/components/Modals/Send/Form.tsx
📚 Learning: 2025-09-12T12:00:33.924Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/SendTransactionConfirmation.tsx:42-50
Timestamp: 2025-09-12T12:00:33.924Z
Learning: gomesalexandre prefers maintaining consistency with existing code patterns in WalletConnect modals, including side-effects-during-render for error handling (showErrorToast + handleReject), rather than introducing isolated refactors that would make the codebase inconsistent.
Applied to files:
src/components/Modals/Send/Form.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-09-12T12:00:33.924Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/SendTransactionConfirmation.tsx:42-50
Timestamp: 2025-09-12T12:00:33.924Z
Learning: gomesalexandre prefers maintaining consistency with existing code patterns across WalletConnect modal components, including side-effects-during-render for error handling (showErrorToast + handleReject calls before return null), rather than introducing isolated refactors that would create inconsistency in the codebase.
Applied to files:
src/components/Modals/Send/Form.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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} : All copy/text must use translation keys - never hardcode strings
Applied to files:
src/components/Modals/Send/Form.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-11-24T21:20:17.804Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-11-24T21:20:17.804Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS use `useErrorToast` hook for displaying errors with translated error messages and handle different error types appropriately
Applied to files:
src/components/Modals/Send/Form.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-08T15:00:49.887Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10231
File: src/components/AssetSearch/components/AssetList.tsx:2-2
Timestamp: 2025-08-08T15:00:49.887Z
Learning: Project shapeshift/web: NeOMakinG prefers avoiding minor a11y/UI nitpicks (e.g., adding aria-hidden to decorative icons in empty states like src/components/AssetSearch/components/AssetList.tsx) within feature PRs; defer such suggestions to a follow-up instead of blocking the PR.
Applied to files:
src/components/Modals/Send/Form.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-14T17:56:23.721Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:545-566
Timestamp: 2025-08-14T17:56:23.721Z
Learning: gomesalexandre prefers not to extract helper functions for toast rendering patterns in TransactionRow.tsx (src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx), considering it over-abstraction even when there's code duplication between deposit and withdraw flows.
Applied to files:
src/components/Modals/Send/Form.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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/assets/translations/en/main.json : Add English copy to `src/assets/translations/en/main.json` (find appropriate section)
Applied to files:
src/components/Modals/Send/Form.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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/components/Modals/Send/Form.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-12-27T16:02:52.792Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11536
File: src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx:252-265
Timestamp: 2025-12-27T16:02:52.792Z
Learning: When reviewing bug fixes, especially in shapeshift/web, prefer minimal changes that fix correctness over introducing broader refactors or quality-of-life improvements (e.g., extracting duplicated logic) unless such improvements are essential to the fix. Apply this guideline broadly to TSX files and related components, not just the specific location, to keep changes focused and maintainable.
Applied to files:
src/components/Modals/Send/Form.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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/components/Modals/Send/views/SendAmountDetails.tsxsrc/hooks/useIsStarknetAccountDeployed/useIsStarknetAccountDeployed.tssrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-14T17:54:32.563Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/ReusableLpStatus.tsx:97-108
Timestamp: 2025-08-14T17:54:32.563Z
Learning: In ReusableLpStatus component (src/pages/ThorChainLP/components/ReusableLpStatus/ReusableLpStatus.tsx), the txAssets dependency is stable from first render because poolAsset, baseAsset, actionSide, and action are all defined first render, making the current txAssetsStatuses initialization pattern safe without needing useEffect synchronization.
Applied to files:
src/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-21T22:15:25.918Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10326
File: src/hooks/useActionCenterSubscribers/useFetchBasePortfolio.ts:31-59
Timestamp: 2025-08-21T22:15:25.918Z
Learning: In the ShapeShift web codebase, the maintainer prefers inferred return types for React hooks over explicit return types, particularly for complex hooks that can have intricate return signatures.
Applied to files:
src/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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/components/Modals/Send/views/SendAmountDetails.tsx
📚 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} : Use Chakra UI components and conventions
Applied to files:
src/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-07-29T10:27:23.424Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10128
File: .cursor/rules/react-best-practices.mdc:8-14
Timestamp: 2025-07-29T10:27:23.424Z
Learning: The ShapeShift team practices aggressive memoization in React components as documented in .cursor/rules/react-best-practices.mdc. They use useMemo for all transformations, derived values, and conditional values, and useCallback for all event handlers and functions that could be passed as props. This approach was adopted after experiencing performance issues ("had hard time") and is their current established practice, though they acknowledge it may evolve in the future.
Applied to files:
src/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-11-24T21:20:44.637Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:20:44.637Z
Learning: Applies to **/*.{jsx,tsx} : EXTRACT complex logic into custom hooks
Applied to files:
src/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-10-17T07:51:58.374Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10783
File: src/context/WalletProvider/NewWalletViews/NewWalletViewsSwitch.tsx:344-349
Timestamp: 2025-10-17T07:51:58.374Z
Learning: In the shapeshift/web codebase, Chakra UI's ModalContent component supports the containerProps prop. When using the useModalRegistration hook from ModalStackProvider, spreading {...modalContentProps} directly onto ModalContent is correct and properly applies z-index and pointer-events through containerProps.sx. Do not suggest extracting sx from modalContentProps.containerProps.sx.
Applied to files:
src/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-08-15T07:51:16.374Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10278
File: src/components/AssetHeader/hooks/useQuickBuy.ts:97-99
Timestamp: 2025-08-15T07:51:16.374Z
Learning: The selectPortfolioUserCurrencyBalanceByAssetId selector in src/state/slices/portfolioSlice/selectors.ts accepts a filter object with an assetId property (signature: (state, { assetId })), not a raw AssetId string. Passing a filter object like { assetId: someAssetId } is the correct usage pattern.
Applied to files:
src/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-22T12:58:36.070Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/Layout/Header/ActionCenter/components/Notifications/RewardDistributionNotification.tsx:33-55
Timestamp: 2025-08-22T12:58:36.070Z
Learning: In RewardDistributionNotification component (src/components/Layout/Header/ActionCenter/components/Notifications/RewardDistributionNotification.tsx), NeOMakinG confirmed that runeAsset is expected to always be defined when the component renders, so defensive guards against undefined runeAsset are not needed.
Applied to files:
src/components/Modals/Send/views/SendAmountDetails.tsx
📚 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} : Account for light/dark mode using `useColorModeValue` hook
Applied to files:
src/hooks/useIsStarknetAccountDeployed/useIsStarknetAccountDeployed.ts
📚 Learning: 2025-07-29T15:04:28.083Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10139
File: src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx:109-115
Timestamp: 2025-07-29T15:04:28.083Z
Learning: In src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx, the component is used under an umbrella that 100% of the time contains the quote, making the type assertion `activeTradeQuote?.steps[currentHopIndex] as TradeQuoteStep` safe. Adding conditional returns before hooks would violate React's Rules of Hooks.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-08T11:41:36.971Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:88-109
Timestamp: 2025-08-08T11:41:36.971Z
Learning: In MultiHopTrade Confirm flow (src/components/MultiHopTrade/components/TradeConfirm/TradeConfirm.tsx), the Confirm route does not remount; navigating away goes to the swapper input page. Therefore, persistent deduplication across remounts for quote tracking is unnecessary; a ref-based single-mount dedupe is sufficient.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-08T11:40:55.734Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/components/TradeConfirm/TradeConfirm.tsx:41-41
Timestamp: 2025-08-08T11:40:55.734Z
Learning: In MultiHopTrade confirm flow (src/components/MultiHopTrade/components/TradeConfirm/TradeConfirm.tsx and related hooks), there is only one active trade per flow. Because of this, persistent (module/Redux) dedupe for QuotesReceived in useTrackTradeQuotes is not necessary; the existing ref-based dedupe is acceptable.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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} : Use the translation hook: `useTranslate()` from `react-polyglot`
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-09-08T22:00:48.005Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10418
File: src/plugins/walletConnectToDapps/components/header/WalletConnectToDappsHeaderButton.tsx:0-0
Timestamp: 2025-09-08T22:00:48.005Z
Learning: gomesalexandre dismissed an aria-label accessibility suggestion with "meh" in PR #10418 for WalletConnectToDappsHeaderButton.tsx, consistent with the team's pattern of deferring minor a11y improvements to follow-up PRs rather than expanding feature PR scope.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-11-24T21:20:17.804Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-11-24T21:20:17.804Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS use custom error classes from `shapeshiftoss/errors` with meaningful error codes for internationalization and relevant details in error objects
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-13T15:50:41.994Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10272
File: src/components/RatingModal.tsx:104-0
Timestamp: 2025-08-13T15:50:41.994Z
Learning: In the ShapeShift web codebase, internal strings like Discord webhook embed content (used for team notifications/feedback) don't need to be translated, only user-facing strings require translation keys. The team distinguishes between internal tooling strings and user-facing UI strings for internationalization purposes.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-11T09:46:41.060Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10219
File: src/components/MultiHopTrade/components/TradeInput/TradeInput.tsx:167-172
Timestamp: 2025-08-11T09:46:41.060Z
Learning: In the shapeshift/web repository, the display cache logic for trade quotes (using `selectUserAvailableTradeQuotes` and `selectUserUnavailableTradeQuotes`) is intentionally kept the same between `TradeInput.tsx` and `TradeQuotes.tsx` components. The `hasQuotes` computation in `TradeInput.tsx` uses these display cache selectors by design, matching the pattern used in `TradeQuotes.tsx`.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-11-24T21:20:17.804Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-11-24T21:20:17.804Z
Learning: Applies to **/swapper{s,}/**/*.{ts,tsx} : ALWAYS use `makeSwapErrorRight` for swapper errors with `TradeQuoteError` enum for error codes and provide detailed error information
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-04T16:02:27.360Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10171
File: src/components/MultiHopTrade/components/TradeConfirm/components/ExpandedStepperSteps.tsx:458-458
Timestamp: 2025-08-04T16:02:27.360Z
Learning: In multi-hop swap transactions, last hop sell transactions might not be detected by the swapper (unlike buy transactions which are always known immediately). The conditional stepSource logic for last hop buy transactions (`isLastHopSellTxSeen ? stepSource : undefined`) serves as defensive programming for future multi-hop support with intermediate chains, even though multi-hop functionality is not currently supported in production.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-10T21:09:25.643Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10215
File: src/components/MultiHopTrade/hooks/useGetTradeRateInput.ts:65-67
Timestamp: 2025-08-10T21:09:25.643Z
Learning: In the MultiHopTrade components, `selectInputBuyAsset` and `selectInputSellAsset` selectors from `tradeInputSlice` always return defined values because they have default values in the initial state (BTC for buyAsset, ETH for sellAsset, with fallback to defaultAsset). Null checks for these assets are unnecessary when using these selectors.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-15T07:51:16.374Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10278
File: src/components/AssetHeader/hooks/useQuickBuy.ts:97-99
Timestamp: 2025-08-15T07:51:16.374Z
Learning: The selectPortfolioUserCurrencyBalanceByAssetId selector in src/state/slices/portfolioSlice/selectors.ts expects a filter object with an assetId property, not a raw AssetId string. The selector signature is (state: ReduxState, filter) where filter should have an assetId property. This pattern is consistent across portfolio selectors that use selectAssetIdParamFromFilter. Passing a filter object like { assetId: someAssetId } is the correct usage pattern.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-15T07:51:16.374Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10278
File: src/components/AssetHeader/hooks/useQuickBuy.ts:97-99
Timestamp: 2025-08-15T07:51:16.374Z
Learning: The selectPortfolioUserCurrencyBalanceByAssetId selector in src/state/slices/portfolioSlice/selectors.ts accepts a filter object with an assetId property, not a raw AssetId string. The selector signature is (state: ReduxState, filter) where filter is expected to have an assetId property. Passing a filter object like { assetId: someAssetId } is the correct usage pattern.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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-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-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: Applies to {.env.development,.env.production} : Use `.env.development` for dev-only features and `.env.production` for prod settings
Applied to files:
.env
📚 Learning: 2025-11-12T09:00:20.961Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: .env:38-38
Timestamp: 2025-11-12T09:00:20.961Z
Learning: In the shapeshift/web repository, alphabetical ordering of environment variables in .env files is not enforced or required, despite dotenv-linter warnings suggesting otherwise.
Applied to files:
.env
📚 Learning: 2025-08-13T13:45:25.748Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10265
File: src/pages/ThorChainLP/queries/hooks/usePools.ts:93-0
Timestamp: 2025-08-13T13:45:25.748Z
Learning: In the ShapeShift web app, inbound addresses data for Thorchain pools requires aggressive caching settings (staleTime: 0, gcTime: 0, refetchInterval: 60_000) to ensure trading status and LP deposit availability are always current. This is intentional business-critical behavior, not a performance issue to be optimized.
Applied to files:
.env
🧬 Code graph analysis (3)
src/components/Modals/Send/Form.tsx (1)
src/components/Modals/Send/utils.ts (1)
maybeFetchChangeAddress(459-483)
src/components/Modals/Send/views/SendAmountDetails.tsx (6)
src/hooks/useNotificationToast.tsx (1)
useNotificationToast(27-70)src/state/store.ts (1)
useAppSelector(144-144)src/state/slices/portfolioSlice/selectors.ts (1)
selectPortfolioAccountMetadataByAccountId(121-126)src/hooks/useIsStarknetAccountDeployed/useIsStarknetAccountDeployed.ts (1)
useIsStarknetAccountDeployed(27-35)packages/caip/src/constants.ts (1)
starknetChainId(89-89)src/lib/utils/starknet.ts (1)
isStarknetChainAdapter(9-14)
src/hooks/useIsStarknetAccountDeployed/useIsStarknetAccountDeployed.ts (2)
packages/caip/src/constants.ts (1)
starknetChainId(89-89)src/lib/utils/starknet.ts (1)
isStarknetChainAdapter(9-14)
🪛 dotenv-linter (4.0.0)
.env
[warning] 162-162: [UnorderedKey] The VITE_STARKNET_NODE_URL key should go before the VITE_THORCHAIN_NODE_URL key
(UnorderedKey)
🔇 Additional comments (9)
.env (2)
10-10: LGTM!The new feature flag is correctly positioned alphabetically among other feature flags and defaults to
false, aligning with the PR objective of gating Starknet support behind a feature flag.
162-162: LGTM!The Starknet node URL is correctly positioned alphabetically (between SOLANA and TRON) and uses the Lava RPC endpoint as intended per the PR description.
src/hooks/useIsStarknetAccountDeployed/useIsStarknetAccountDeployed.ts (1)
27-35: LGTM!The hook correctly uses React Query with appropriate configuration:
enabledguards against undefinedaccountId,staleTimeof 30s is reasonable for deployment status, andrefetchInterval: falseprevents unnecessary polling.src/components/Modals/Send/Form.tsx (2)
142-151: LGTM!The
executeSendfunction cleanly separates transaction execution from post-send flow handling. The null check on line 145 correctly short-circuits when the send fails.
231-247: LGTM!The refactored
handleSubmitcorrectly orchestrates the send flow: validates wallet, fetches change address for UTXO chains, executes the send, and completes the flow. Dependencies are properly included.src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx (2)
173-195: LGTM!The translation logic correctly handles the Starknet deployment state, showing the deploy button text when
isStarknetAccountDeployed === falseduring initializing/previewing states.
224-247: LGTM!The
handleClickflow correctly gates on Starknet deployment status before proceeding with trade submission. The early return after triggering deployment prevents the trade from executing before the account is deployed.src/components/Modals/Send/views/SendAmountDetails.tsx (2)
182-191: Verify: After successful deployment, user needs to click again.When
deployAccountMutation.mutate()succeeds,onSuccessonly callsrefetchDeploymentStatus(). The user remains on the same screen and must click the button again to proceed toSendRoutes.Confirm.If this is intentional UX (giving users confirmation before continuing), this is fine. However, if the intent is to auto-navigate after deployment, the flow should call
navigate(SendRoutes.Confirm)inonSuccess.
396-403: LGTM!The UI correctly shows a warning alert when Starknet account is not deployed, and the button states appropriately reflect deployment progress with loading text and disabled states.
Also applies to: 423-457
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx (1)
104-146: Consider extracting shared logic betweenfailActionandcompleteAction.Both callbacks share ~90% of their implementation, differing only in:
- Action status (
FailedvsComplete)- Message key
- Toast status (
errorvssuccess)This duplication could be eliminated by extracting a shared helper that accepts these values as parameters.
🔎 Proposed refactor to reduce duplication
+ const updateActionWithToast = useCallback( + ( + action: ReturnType<typeof selectPendingWalletSendActions>[number], + status: ActionStatus, + message: string, + toastStatus: 'success' | 'error', + ) => { + const { txHash } = action.transactionMetadata + + dispatch( + actionSlice.actions.upsertAction({ + ...action, + status, + updatedAt: Date.now(), + transactionMetadata: { + ...action.transactionMetadata, + message, + }, + }), + ) + + const isActive = toast.isActive(txHash) + if (isActive) return + + toast({ + id: txHash, + duration: isDrawerOpen ? 5000 : null, + status: toastStatus, + render: ({ onClose, ...props }) => { + const handleClick = () => { + onClose() + openActionCenter() + } + return ( + <GenericTransactionNotification + handleClick={handleClick} + actionId={txHash} + onClose={onClose} + {...props} + /> + ) + }, + }) + }, + [dispatch, toast, isDrawerOpen, openActionCenter], + ) + const completeAction = useCallback( (action: ReturnType<typeof selectPendingWalletSendActions>[number]) => { - const { txHash, accountId, accountIdsToRefetch } = action.transactionMetadata - - dispatch( - actionSlice.actions.upsertAction({ - ...action, - status: ActionStatus.Complete, - updatedAt: Date.now(), - transactionMetadata: { - ...action.transactionMetadata, - message: 'modals.send.youHaveSent', - }, - }), + updateActionWithToast( + action, + ActionStatus.Complete, + 'modals.send.youHaveSent', + 'success', ) + const { accountId, accountIdsToRefetch } = action.transactionMetadata const chainId = fromAccountId(accountId).chainId const isSecondClassChain = SECOND_CLASS_CHAINS.includes(chainId as KnownChainIds) if (isSecondClassChain) { // ... existing portfolio refresh logic } - - const isActive = toast.isActive(txHash) - if (isActive) return - - toast({ - // ... existing toast logic - }) }, - [dispatch, toast, isDrawerOpen, openActionCenter], + [updateActionWithToast], ) const failAction = useCallback( (action: ReturnType<typeof selectPendingWalletSendActions>[number]) => { - const { txHash } = action.transactionMetadata - - dispatch( - actionSlice.actions.upsertAction({ - ...action, - status: ActionStatus.Failed, - updatedAt: Date.now(), - transactionMetadata: { - ...action.transactionMetadata, - message: 'modals.send.sendFailed', - }, - }), - ) - - const isActive = toast.isActive(txHash) - if (isActive) return - - toast({ - id: txHash, - duration: isDrawerOpen ? 5000 : null, - status: 'error', - render: ({ onClose, ...props }) => { - const handleClick = () => { - onClose() - openActionCenter() - } - return ( - <GenericTransactionNotification - handleClick={handleClick} - actionId={txHash} - onClose={onClose} - {...props} - /> - ) - }, - }) + updateActionWithToast( + action, + ActionStatus.Failed, + 'modals.send.sendFailed', + 'error', + ) }, - [dispatch, toast, isDrawerOpen, openActionCenter], + [updateActionWithToast], )
📜 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 (8)
.env.env.developmentscripts/generateAssetData/generateAssetData.tssrc/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsxsrc/constants/chains.tssrc/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsxsrc/lib/asset-service/service/encodedAssetData.jsonsrc/lib/asset-service/service/encodedRelatedAssetIndex.json
🚧 Files skipped from review as they are similar to previous changes (2)
- src/constants/chains.ts
- scripts/generateAssetData/generateAssetData.ts
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{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/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsxsrc/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
**/*.{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/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsxsrc/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/error-handling.mdc)
**/*.{tsx,jsx}: ALWAYS wrap React components in error boundaries and provide user-friendly fallback components with error logging
ALWAYS useuseErrorToasthook for displaying errors with translated error messages and handle different error types appropriatelyUse PascalCase for React component names and match the component name to the file name
Files:
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsxsrc/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
**/*.{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/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsxsrc/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/react-best-practices.mdc)
**/*.{jsx,tsx}: ALWAYS useuseMemofor expensive computations, object/array creations, and filtered data
ALWAYS useuseMemofor derived values and computed properties
ALWAYS useuseMemofor conditional values and simple transformations
ALWAYS useuseCallbackfor event handlers and functions passed as props
ALWAYS useuseCallbackfor any function that could be passed as a prop or dependency
ALWAYS include all dependencies inuseEffect,useMemo,useCallbackdependency arrays
NEVER use// eslint-disable-next-line react-hooks/exhaustive-depsunless absolutely necessary, and ALWAYS explain why dependencies are excluded if using eslint disable
ALWAYS use named exports for components; NEVER use default exports for components
KEEP component files under 200 lines when possible; BREAK DOWN large components into smaller, reusable pieces
EXTRACT complex logic into custom hooks
ALWAYS wrap components in error boundaries for production
ALWAYS handle async errors properly in async operations
ALWAYS provide user-friendly error messages in error handling
ALWAYS use virtualization for lists with 100+ items
ALWAYS implement proper key props for list items
ALWAYS lazy load heavy components using React.lazy for code splitting
ALWAYS use Suspense wrapper for lazy loaded components
USE local state for component-level state; LIFT state up when needed across multiple components; USE Context for avoiding prop drilling; USE Redux only for global state shared across multiple places
Wrap components receiving props withmemofor performance optimization
Files:
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsxsrc/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react-best-practices.mdc)
Ensure TypeScript types are explicit and proper; avoid use of
anytype
Files:
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsxsrc/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
{.env.development,.env.production}
📄 CodeRabbit inference engine (CLAUDE.md)
Use
.env.developmentfor dev-only features and.env.productionfor prod settings
Files:
.env.development
🧠 Learnings (35)
📓 Common learnings
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/AssetSearch/components/AssetList.tsx:2-2
Timestamp: 2025-08-08T15:00:49.887Z
Learning: Project shapeshift/web: NeOMakinG prefers avoiding minor a11y/UI nitpicks (e.g., adding aria-hidden to decorative icons in empty states like src/components/AssetSearch/components/AssetList.tsx) within feature PRs; defer such suggestions to a follow-up instead of blocking the PR.
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: NeOMakinG
Repo: shapeshift/web PR: 10376
File: packages/contracts/src/viemClient.ts:39-40
Timestamp: 2025-08-27T09:51:36.901Z
Learning: NeOMakinG confirmed that issues flagged by CodeRabbit that predate the PR changes and are unrelated to the PR's core objective should be addressed separately, not within the current PR scope.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/components/Stake/components/StakeSummary.tsx:112-114
Timestamp: 2025-08-22T13:00:44.879Z
Learning: NeOMakinG prefers to keep PR changes minimal and focused on the core objectives, avoiding cosmetic or defensive code improvements that aren't directly related to the PR scope, even when they would improve robustness.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10128
File: .cursor/rules/error-handling.mdc:266-274
Timestamp: 2025-07-29T10:35:22.059Z
Learning: NeOMakinG prefers less nitpicky suggestions on documentation and best practices files, finding overly detailed suggestions on minor implementation details (like console.error vs logger.error) too granular for cursor rules documentation.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/pages/Dashboard/components/AccountList/AccountTable.tsx:60-0
Timestamp: 2025-09-02T08:34:08.157Z
Learning: NeOMakinG prefers code review comments to focus only on actual PR changes, not pre-existing code issues, unless there are critical security or correctness concerns directly related to the new functionality.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:42-86
Timestamp: 2025-08-08T11:41:22.794Z
Learning: NeOMakinG prefers not to include refactors in move-only PRs; such suggestions should be deferred to follow-up issues instead of being applied within the same PR.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/Table/Table.theme.ts:177-180
Timestamp: 2025-09-02T12:38:46.940Z
Learning: NeOMakinG prefers to defer technical debt and CSS correctness issues (like improper hover selectors) to follow-up PRs when the current PR is already large and focused on major feature implementation, even when the issues are valid from a usability/technical perspective.
📚 Learning: 2025-08-22T15:07:18.021Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10326
File: src/hooks/useActionCenterSubscribers/useThorchainLpActionSubscriber.tsx:37-41
Timestamp: 2025-08-22T15:07:18.021Z
Learning: In src/hooks/useActionCenterSubscribers/useThorchainLpActionSubscriber.tsx, kaladinlight prefers not to await the upsertBasePortfolio call in the Base chain handling block, indicating intentional fire-and-forget behavior for Base portfolio upserts in the THORChain LP completion flow.
Applied to files:
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
📚 Learning: 2025-08-22T13:16:12.721Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/hooks/useRfoxRewardDistributionActionSubscriber.tsx:104-105
Timestamp: 2025-08-22T13:16:12.721Z
Learning: In src/pages/RFOX/hooks/useRfoxRewardDistributionActionSubscriber.tsx, the guard `if (!actions[actionId]) return` before upserting completed reward distributions is intentional product behavior. NeOMakinG confirmed that the system should only show completion notifications for reward distributions that were previously seen in a pending state, not for distributions the user missed during the pending phase.
Applied to files:
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
📚 Learning: 2025-08-25T12:58:39.547Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/Layout/Header/ActionCenter/components/Notifications/RewardDistributionNotification.tsx:69-70
Timestamp: 2025-08-25T12:58:39.547Z
Learning: In RewardDistributionNotification component (src/components/Layout/Header/ActionCenter/components/Notifications/RewardDistributionNotification.tsx), NeOMakinG confirmed that action is expected to always be defined when the component renders, so defensive guards against undefined action are not needed.
Applied to files:
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
📚 Learning: 2025-08-22T14:59:04.889Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10326
File: src/hooks/useActionCenterSubscribers/useGenericTransactionSubscriber.tsx:105-111
Timestamp: 2025-08-22T14:59:04.889Z
Learning: In the ShapeShift web Base chain handling, the await pattern inside forEach in useGenericTransactionSubscriber is intentional to delay the entire action completion flow (not just fetchBasePortfolio) for Base chain transactions. The user kaladinlight wants everything below the Base portfolio refresh - including dispatch, query invalidation, and toast notifications - to also be delayed by ~10 seconds to accommodate Base's degraded node state.
Applied to files:
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
📚 Learning: 2025-08-22T13:02:58.824Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/hooks/useRfoxRewardDistributionActionSubscriber.tsx:33-41
Timestamp: 2025-08-22T13:02:58.824Z
Learning: In src/pages/RFOX/hooks/useRfoxRewardDistributionActionSubscriber.tsx, NeOMakinG declined optimizing useMemo dependencies to depend on lifetimeRewardDistributionsQuery.data instead of the entire query object, indicating indifference toward this type of performance optimization.
Applied to files:
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
📚 Learning: 2025-08-14T17:54:32.563Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/ReusableLpStatus.tsx:97-108
Timestamp: 2025-08-14T17:54:32.563Z
Learning: In ReusableLpStatus component (src/pages/ThorChainLP/components/ReusableLpStatus/ReusableLpStatus.tsx), the txAssets dependency is stable from first render because poolAsset, baseAsset, actionSide, and action are all defined first render, making the current txAssetsStatuses initialization pattern safe without needing useEffect synchronization.
Applied to files:
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
📚 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:
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsxsrc/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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:
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
📚 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} : Use `useAppDispatch` for Redux actions
Applied to files:
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx
📚 Learning: 2025-12-27T16:02:52.792Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11536
File: src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx:252-265
Timestamp: 2025-12-27T16:02:52.792Z
Learning: When reviewing bug fixes, especially in shapeshift/web, prefer minimal changes that fix correctness over introducing broader refactors or quality-of-life improvements (e.g., extracting duplicated logic) unless such improvements are essential to the fix. Apply this guideline broadly to TSX files and related components, not just the specific location, to keep changes focused and maintainable.
Applied to files:
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsxsrc/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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.env.development
📚 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-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 {.env.development,.env.production} : Use `.env.development` for dev-only features and `.env.production` for prod settings
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-12T09:00:20.961Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11016
File: .env:38-38
Timestamp: 2025-11-12T09:00:20.961Z
Learning: In the shapeshift/web repository, alphabetical ordering of environment variables in .env files is not enforced or required, despite dotenv-linter warnings suggesting otherwise.
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.env.development
📚 Learning: 2025-07-29T15:04:28.083Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10139
File: src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx:109-115
Timestamp: 2025-07-29T15:04:28.083Z
Learning: In src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx, the component is used under an umbrella that 100% of the time contains the quote, making the type assertion `activeTradeQuote?.steps[currentHopIndex] as TradeQuoteStep` safe. Adding conditional returns before hooks would violate React's Rules of Hooks.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 Learning: 2025-08-08T11:40:55.734Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/components/TradeConfirm/TradeConfirm.tsx:41-41
Timestamp: 2025-08-08T11:40:55.734Z
Learning: In MultiHopTrade confirm flow (src/components/MultiHopTrade/components/TradeConfirm/TradeConfirm.tsx and related hooks), there is only one active trade per flow. Because of this, persistent (module/Redux) dedupe for QuotesReceived in useTrackTradeQuotes is not necessary; the existing ref-based dedupe is acceptable.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 Learning: 2025-08-04T16:02:27.360Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10171
File: src/components/MultiHopTrade/components/TradeConfirm/components/ExpandedStepperSteps.tsx:458-458
Timestamp: 2025-08-04T16:02:27.360Z
Learning: In multi-hop swap transactions, last hop sell transactions might not be detected by the swapper (unlike buy transactions which are always known immediately). The conditional stepSource logic for last hop buy transactions (`isLastHopSellTxSeen ? stepSource : undefined`) serves as defensive programming for future multi-hop support with intermediate chains, even though multi-hop functionality is not currently supported in production.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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:
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 Learning: 2025-08-08T11:41:36.971Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:88-109
Timestamp: 2025-08-08T11:41:36.971Z
Learning: In MultiHopTrade Confirm flow (src/components/MultiHopTrade/components/TradeConfirm/TradeConfirm.tsx), the Confirm route does not remount; navigating away goes to the swapper input page. Therefore, persistent deduplication across remounts for quote tracking is unnecessary; a ref-based single-mount dedupe is sufficient.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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:
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 Learning: 2025-08-05T23:36:13.214Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10187
File: src/state/slices/preferencesSlice/selectors.ts:21-25
Timestamp: 2025-08-05T23:36:13.214Z
Learning: The AssetId type from 'shapeshiftoss/caip' package is a string type alias, so it can be used directly as a return type for cache key resolvers in re-reselect selectors without needing explicit string conversion.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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:
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 Learning: 2025-09-12T09:48:46.305Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/WalletConnectSigningModal/StructuredMessage/StructuredMessage.tsx:0-0
Timestamp: 2025-09-12T09:48:46.305Z
Learning: In WalletConnect signing flows dealing with structured message data (like StructuredField.value in StructuredMessage.tsx), gomesalexandre prefers using `any` type for values representing dynamic Solidity types from external API responses, consistent with their approach to other external API parsing in WalletConnect flows.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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:
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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:
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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:
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
📚 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:
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx
🧬 Code graph analysis (2)
src/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx (4)
src/state/slices/actionSlice/selectors.ts (1)
selectPendingWalletSendActions(119-124)src/state/slices/actionSlice/actionSlice.ts (1)
actionSlice(11-39)src/lib/utils/starknet.ts (2)
isStarknetChainAdapter(9-14)getStarknetTransactionStatus(29-46)src/state/slices/txHistorySlice/txHistorySlice.ts (1)
txHistory(120-161)
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx (2)
packages/caip/src/constants.ts (1)
CHAIN_NAMESPACE(91-99)src/lib/utils/starknet.ts (1)
assertGetStarknetChainAdapter(16-27)
🪛 dotenv-linter (4.0.0)
.env
[warning] 164-164: [UnorderedKey] The VITE_STARKNET_NODE_URL key should go before the VITE_THORCHAIN_NODE_URL key
(UnorderedKey)
.env.development
[warning] 73-73: [UnorderedKey] The VITE_STARKNET_NODE_URL key should go before the VITE_THORCHAIN_NODE_URL key
(UnorderedKey)
[warning] 88-88: [UnorderedKey] The VITE_FEATURE_STARKNET key should go before the VITE_FEATURE_SWAPPER_FIAT_RAMPS 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 (7)
.env (1)
10-10: Configuration correctly gated and uses appropriate node endpoint.The feature flag defaults to
falsefor production, and the node URL correctly points to the Lava public RPC endpoint for Starknet. Both changes align with the PR objectives of a feature-gated implementation.Also applies to: 164-164
.env.development (1)
73-73: Development environment correctly enables Starknet feature.The feature flag is enabled in development (line 88), and the node URL is consistent with
.env(line 73). This allows testing of Starknet functionality during development while keeping it disabled by default in production.Also applies to: 88-88
src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx (2)
4-9: LGTM! Starknet imports follow established patterns.The addition of
StarknetSignTxtype andassertGetStarknetChainAdapterutility follows the same pattern as existing chain implementations (Solana, Sui, etc.). The imports are properly structured and necessary for the new Starknet execution path.Also applies to: 44-44
617-647: Starknet execution case is properly implemented and follows established patterns.The implementation is verified as correct:
execStarknetTransactionmethod exists inTradeExecutionclass with proper signature matching the usage- Method validates required swapper methods (
getUnsignedStarknetTransaction,executeStarknetTransaction) before execution- Follows the same pattern as other chain implementations (Solana, Sui, Tron) via
_execWalletAgnostic- All required parameters correctly passed from the hook
- Proper handling of sign/broadcast callback, analytics tracking, and polling cancellation
- Type safety maintained with properly defined
StarknetTransactionExecutionInputsrc/hooks/useActionCenterSubscribers/useSendActionSubscriber.tsx (3)
18-18: LGTM - Starknet utility imports.The new imports are correctly used in the Starknet polling case below.
204-239: Verify intended behavioral difference from other second-class chains.Starknet is the only second-class chain that distinguishes between
FailedandConfirmedtransaction statuses:
- All other chains (Tron, Sui, Monad, Plasma, HyperEvm, Thorchain, Mayachain) treat
TxStatus.Failedthe same asTxStatus.Confirmedand callcompleteAction()for both.- Starknet explicitly handles failed transactions with
failAction(), which does NOT refresh portfolios.Potential concerns:
Portfolio refresh on failure: When a Starknet transaction fails after being submitted on-chain, gas fees may have been consumed, changing the account balance. However,
failAction()doesn't trigger the portfolio refresh thatcompleteAction()performs for second-class chains (lines 62-74). Should portfolio balances be refreshed on failure?Consistency: Line 172's comment states "as for now we don't support failed sends lets consider it confirmed". Is this Starknet-specific failure handling intentional product direction, or should other chains also adopt this pattern?
Please confirm:
- Portfolio refresh is intentionally skipped for failed Starknet transactions
- The behavioral difference from other second-class chains is intentional (Starknet distinguishes failures, others don't)
319-319: LGTM - Dependency array correctly updated.The addition of
failActionto the dependency array is correct since the callback is now invoked within the effect.
gomesalexandre
left a comment
There was a problem hiding this comment.
Does the thing!
One thing I spotted here is we'll want to have proper fees for near sends as I'm able to send max balance of STRK, but other than that LGTM with the new flow 🌮
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx (1)
122-126: Consider adding an explicit timeout to waitForTransaction.While Starknet providers typically have internal timeouts, explicitly specifying a timeout parameter improves code clarity and ensures predictable behavior. This defensive practice helps prevent indefinite hangs in case of network issues or provider changes.
🔎 Add explicit timeout
await starknetProvider.waitForTransaction(deployTxHash, { retryInterval: 2000, + timeout: 300000, // 5 minutes successStates: ['ACCEPTED_ON_L2', 'ACCEPTED_ON_L1'], })
📜 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 (16)
packages/caip/src/adapters/coincap/generated/eip155_1/adapter.jsonis excluded by!**/generated/**packages/caip/src/adapters/coincap/generated/eip155_137/adapter.jsonis excluded by!**/generated/**packages/caip/src/adapters/coincap/generated/eip155_42161/adapter.jsonis excluded by!**/generated/**packages/caip/src/adapters/coincap/generated/eip155_43114/adapter.jsonis excluded by!**/generated/**packages/caip/src/adapters/coincap/generated/eip155_56/adapter.jsonis excluded by!**/generated/**packages/caip/src/adapters/coincap/generated/eip155_8453/adapter.jsonis excluded by!**/generated/**packages/caip/src/adapters/coincap/generated/solana_5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/adapter.jsonis excluded by!**/generated/**packages/caip/src/adapters/coingecko/generated/eip155_1/adapter.jsonis excluded by!**/generated/**packages/caip/src/adapters/coingecko/generated/eip155_42161/adapter.jsonis excluded by!**/generated/**packages/caip/src/adapters/coingecko/generated/eip155_43114/adapter.jsonis excluded by!**/generated/**packages/caip/src/adapters/coingecko/generated/eip155_56/adapter.jsonis excluded by!**/generated/**packages/caip/src/adapters/coingecko/generated/eip155_8453/adapter.jsonis excluded by!**/generated/**packages/caip/src/adapters/coingecko/generated/solana_5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp/adapter.jsonis excluded by!**/generated/**public/generated/asset-manifest.jsonis excluded by!**/generated/**public/generated/generatedAssetData.jsonis excluded by!**/generated/**public/generated/relatedAssetIndex.jsonis excluded by!**/generated/**
📒 Files selected for processing (11)
packages/caip/src/adapters/coincap/index.tspackages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tspackages/utils/src/getAssetNamespaceFromChainId.tsscripts/generateAssetData/color-map.jsonscripts/generateAssetData/generateAssetData.tsscripts/generateTradableAssetMap/index.tssrc/assets/translations/en/main.jsonsrc/components/Modals/Send/views/SendAmountDetails.tsxsrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/lib/asset-service/service/AssetService.tssrc/state/migrations/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/assets/translations/en/main.json
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{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/lib/asset-service/service/AssetService.tspackages/caip/src/adapters/coincap/index.tssrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxpackages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tssrc/state/migrations/index.tspackages/utils/src/getAssetNamespaceFromChainId.tsscripts/generateTradableAssetMap/index.tsscripts/generateAssetData/generateAssetData.tssrc/components/Modals/Send/views/SendAmountDetails.tsx
**/*.{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/lib/asset-service/service/AssetService.tspackages/caip/src/adapters/coincap/index.tssrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxpackages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tssrc/state/migrations/index.tspackages/utils/src/getAssetNamespaceFromChainId.tsscripts/generateTradableAssetMap/index.tsscripts/generateAssetData/generateAssetData.tssrc/components/Modals/Send/views/SendAmountDetails.tsx
**/*.{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/lib/asset-service/service/AssetService.tspackages/caip/src/adapters/coincap/index.tssrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxpackages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tssrc/state/migrations/index.tspackages/utils/src/getAssetNamespaceFromChainId.tsscripts/generateTradableAssetMap/index.tsscripts/generateAssetData/generateAssetData.tssrc/components/Modals/Send/views/SendAmountDetails.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursor/rules/error-handling.mdc)
**/*.{tsx,jsx}: ALWAYS wrap React components in error boundaries and provide user-friendly fallback components with error logging
ALWAYS useuseErrorToasthook for displaying errors with translated error messages and handle different error types appropriatelyUse PascalCase for React component names and match the component name to the file name
Files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/react-best-practices.mdc)
**/*.{jsx,tsx}: ALWAYS useuseMemofor expensive computations, object/array creations, and filtered data
ALWAYS useuseMemofor derived values and computed properties
ALWAYS useuseMemofor conditional values and simple transformations
ALWAYS useuseCallbackfor event handlers and functions passed as props
ALWAYS useuseCallbackfor any function that could be passed as a prop or dependency
ALWAYS include all dependencies inuseEffect,useMemo,useCallbackdependency arrays
NEVER use// eslint-disable-next-line react-hooks/exhaustive-depsunless absolutely necessary, and ALWAYS explain why dependencies are excluded if using eslint disable
ALWAYS use named exports for components; NEVER use default exports for components
KEEP component files under 200 lines when possible; BREAK DOWN large components into smaller, reusable pieces
EXTRACT complex logic into custom hooks
ALWAYS wrap components in error boundaries for production
ALWAYS handle async errors properly in async operations
ALWAYS provide user-friendly error messages in error handling
ALWAYS use virtualization for lists with 100+ items
ALWAYS implement proper key props for list items
ALWAYS lazy load heavy components using React.lazy for code splitting
ALWAYS use Suspense wrapper for lazy loaded components
USE local state for component-level state; LIFT state up when needed across multiple components; USE Context for avoiding prop drilling; USE Redux only for global state shared across multiple places
Wrap components receiving props withmemofor performance optimization
Files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
**/*.tsx
📄 CodeRabbit inference engine (.cursor/rules/react-best-practices.mdc)
Ensure TypeScript types are explicit and proper; avoid use of
anytype
Files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
**/swapper{s,}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/error-handling.mdc)
ALWAYS use
makeSwapErrorRightfor swapper errors withTradeQuoteErrorenum for error codes and provide detailed error information
Files:
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
packages/swapper/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/swapper.mdc)
packages/swapper/**/*.ts: Use TypeScript with explicit types (e.g., SupportedChainIds) for all code in the Swapper system
Use camelCase for variable and function names in the Swapper system
Use PascalCase for types, interfaces, and enums in the Swapper system
Use kebab-case for filenames in the Swapper system
Files:
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
packages/swapper/src/swappers/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/swapper.mdc)
packages/swapper/src/swappers/**/*.ts: Adhere to the Swapper directory structure: each swapper resides in packages/swapper/src/swappers// with required files (SwapperName.ts, endpoints.ts, types.ts, utils/constants.ts, utils/helpers.ts)
Validate inputs and log errors for debugging in Swapper system implementations
Swapper files must be located in packages/swapper/src/swappers/ directory structure and not placed outside this location
Avoid side effects in swap logic; ensure swap methods are deterministic and stateless
Files:
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.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/migrations/index.ts
🧠 Learnings (67)
📓 Common learnings
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/components/Stake/components/StakeSummary.tsx:112-114
Timestamp: 2025-08-22T13:00:44.879Z
Learning: NeOMakinG prefers to keep PR changes minimal and focused on the core objectives, avoiding cosmetic or defensive code improvements that aren't directly related to the PR scope, even when they would improve robustness.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10128
File: .cursor/rules/error-handling.mdc:266-274
Timestamp: 2025-07-29T10:35:22.059Z
Learning: NeOMakinG prefers less nitpicky suggestions on documentation and best practices files, finding overly detailed suggestions on minor implementation details (like console.error vs logger.error) too granular for cursor rules documentation.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/pages/Dashboard/components/AccountList/AccountTable.tsx:60-0
Timestamp: 2025-09-02T08:34:08.157Z
Learning: NeOMakinG prefers code review comments to focus only on actual PR changes, not pre-existing code issues, unless there are critical security or correctness concerns directly related to the new functionality.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:42-86
Timestamp: 2025-08-08T11:41:22.794Z
Learning: NeOMakinG prefers not to include refactors in move-only PRs; such suggestions should be deferred to follow-up issues instead of being applied within the same PR.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/Table/Table.theme.ts:177-180
Timestamp: 2025-09-02T12:38:46.940Z
Learning: NeOMakinG prefers to defer technical debt and CSS correctness issues (like improper hover selectors) to follow-up PRs when the current PR is already large and focused on major feature implementation, even when the issues are valid from a usability/technical perspective.
📚 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/lib/asset-service/service/AssetService.tssrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxpackages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tspackages/utils/src/getAssetNamespaceFromChainId.tsscripts/generateTradableAssetMap/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/lib/asset-service/service/AssetService.tssrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxpackages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tspackages/utils/src/getAssetNamespaceFromChainId.tsscripts/generateTradableAssetMap/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/lib/asset-service/service/AssetService.tspackages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tspackages/utils/src/getAssetNamespaceFromChainId.tsscripts/generateAssetData/generateAssetData.tssrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-08-08T15:00:49.887Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10231
File: src/components/AssetSearch/components/AssetList.tsx:2-2
Timestamp: 2025-08-08T15:00:49.887Z
Learning: Project shapeshift/web: NeOMakinG prefers avoiding minor a11y/UI nitpicks (e.g., adding aria-hidden to decorative icons in empty states like src/components/AssetSearch/components/AssetList.tsx) within feature PRs; defer such suggestions to a follow-up instead of blocking the PR.
Applied to files:
src/lib/asset-service/service/AssetService.tssrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 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/lib/asset-service/service/AssetService.tspackages/caip/src/adapters/coincap/index.tssrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxpackages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tspackages/utils/src/getAssetNamespaceFromChainId.tsscripts/generateTradableAssetMap/index.tssrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 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/lib/asset-service/service/AssetService.tspackages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tspackages/utils/src/getAssetNamespaceFromChainId.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/lib/asset-service/service/AssetService.tssrc/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxpackages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tspackages/utils/src/getAssetNamespaceFromChainId.tsscripts/generateTradableAssetMap/index.ts
📚 Learning: 2025-08-11T09:45:51.174Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10219
File: src/components/MultiHopTrade/components/TradeInput/TradeInput.tsx:175-180
Timestamp: 2025-08-11T09:45:51.174Z
Learning: gomesalexandre prefers truthy checks over explicit boolean comparisons (e.g., `walletSupportsSellAssetChain` instead of `walletSupportsSellAssetChain === true`) when dealing with tri-state values (boolean | null) in TypeScript, as the falsy behavior for null/undefined is intentional and acceptable.
Applied to files:
src/lib/asset-service/service/AssetService.ts
📚 Learning: 2025-09-04T17:27:33.328Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/TradeAssetSearch/components/SearchTermAssetList.tsx:88-94
Timestamp: 2025-09-04T17:27:33.328Z
Learning: In shapeshift/web, NFTs never have related assets in the grouping system. The related assets feature is designed for fungible tokens that exist across multiple chains (like USDC on different chains), not for NFTs which are unique. Therefore, checking isNft() for related asset IDs is unnecessary since NFT asset IDs won't be present in the relatedAssetIdsById mapping.
Applied to files:
src/lib/asset-service/service/AssetService.tspackages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.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/config.ts : Default values always come from environment variables prefixed with `VITE_FEATURE_`
Applied to files:
packages/caip/src/adapters/coincap/index.tsscripts/generateTradableAssetMap/index.ts
📚 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:
packages/caip/src/adapters/coincap/index.tsscripts/generateTradableAssetMap/index.ts
📚 Learning: 2025-07-29T15:04:28.083Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10139
File: src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx:109-115
Timestamp: 2025-07-29T15:04:28.083Z
Learning: In src/components/MultiHopTrade/components/TradeConfirm/components/ExpandableStepperSteps.tsx, the component is used under an umbrella that 100% of the time contains the quote, making the type assertion `activeTradeQuote?.steps[currentHopIndex] as TradeQuoteStep` safe. Adding conditional returns before hooks would violate React's Rules of Hooks.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-08T11:41:36.971Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:88-109
Timestamp: 2025-08-08T11:41:36.971Z
Learning: In MultiHopTrade Confirm flow (src/components/MultiHopTrade/components/TradeConfirm/TradeConfirm.tsx), the Confirm route does not remount; navigating away goes to the swapper input page. Therefore, persistent deduplication across remounts for quote tracking is unnecessary; a ref-based single-mount dedupe is sufficient.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-08T11:40:55.734Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/components/TradeConfirm/TradeConfirm.tsx:41-41
Timestamp: 2025-08-08T11:40:55.734Z
Learning: In MultiHopTrade confirm flow (src/components/MultiHopTrade/components/TradeConfirm/TradeConfirm.tsx and related hooks), there is only one active trade per flow. Because of this, persistent (module/Redux) dedupe for QuotesReceived in useTrackTradeQuotes is not necessary; the existing ref-based dedupe is acceptable.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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} : All copy/text must use translation keys - never hardcode strings
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-11-24T21:20:17.804Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-11-24T21:20:17.804Z
Learning: Applies to **/*.{tsx,jsx} : ALWAYS use `useErrorToast` hook for displaying errors with translated error messages and handle different error types appropriately
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-08-14T17:56:23.721Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx:545-566
Timestamp: 2025-08-14T17:56:23.721Z
Learning: gomesalexandre prefers not to extract helper functions for toast rendering patterns in TransactionRow.tsx (src/pages/ThorChainLP/components/ReusableLpStatus/TransactionRow.tsx), considering it over-abstraction even when there's code duplication between deposit and withdraw flows.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 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/assets/translations/en/main.json : Add English copy to `src/assets/translations/en/main.json` (find appropriate section)
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 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} : Use the translation hook: `useTranslate()` from `react-polyglot`
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-09-08T22:00:48.005Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10418
File: src/plugins/walletConnectToDapps/components/header/WalletConnectToDappsHeaderButton.tsx:0-0
Timestamp: 2025-09-08T22:00:48.005Z
Learning: gomesalexandre dismissed an aria-label accessibility suggestion with "meh" in PR #10418 for WalletConnectToDappsHeaderButton.tsx, consistent with the team's pattern of deferring minor a11y improvements to follow-up PRs rather than expanding feature PR scope.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-11-24T21:20:17.804Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-11-24T21:20:17.804Z
Learning: Applies to **/*.{ts,tsx} : ALWAYS use custom error classes from `shapeshiftoss/errors` with meaningful error codes for internationalization and relevant details in error objects
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-08-13T15:50:41.994Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10272
File: src/components/RatingModal.tsx:104-0
Timestamp: 2025-08-13T15:50:41.994Z
Learning: In the ShapeShift web codebase, internal strings like Discord webhook embed content (used for team notifications/feedback) don't need to be translated, only user-facing strings require translation keys. The team distinguishes between internal tooling strings and user-facing UI strings for internationalization purposes.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-08-11T09:46:41.060Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10219
File: src/components/MultiHopTrade/components/TradeInput/TradeInput.tsx:167-172
Timestamp: 2025-08-11T09:46:41.060Z
Learning: In the shapeshift/web repository, the display cache logic for trade quotes (using `selectUserAvailableTradeQuotes` and `selectUserUnavailableTradeQuotes`) is intentionally kept the same between `TradeInput.tsx` and `TradeQuotes.tsx` components. The `hasQuotes` computation in `TradeInput.tsx` uses these display cache selectors by design, matching the pattern used in `TradeQuotes.tsx`.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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} : Use Chakra UI components and conventions
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-08-21T22:15:25.918Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10326
File: src/hooks/useActionCenterSubscribers/useFetchBasePortfolio.ts:31-59
Timestamp: 2025-08-21T22:15:25.918Z
Learning: In the ShapeShift web codebase, the maintainer prefers inferred return types for React hooks over explicit return types, particularly for complex hooks that can have intricate return signatures.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-11-24T21:20:17.804Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-11-24T21:20:17.804Z
Learning: Applies to **/swapper{s,}/**/*.{ts,tsx} : ALWAYS use `makeSwapErrorRight` for swapper errors with `TradeQuoteError` enum for error codes and provide detailed error information
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-07-29T10:27:23.424Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10128
File: .cursor/rules/react-best-practices.mdc:8-14
Timestamp: 2025-07-29T10:27:23.424Z
Learning: The ShapeShift team practices aggressive memoization in React components as documented in .cursor/rules/react-best-practices.mdc. They use useMemo for all transformations, derived values, and conditional values, and useCallback for all event handlers and functions that could be passed as props. This approach was adopted after experiencing performance issues ("had hard time") and is their current established practice, though they acknowledge it may evolve in the future.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 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:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxpackages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tsscripts/generateTradableAssetMap/index.ts
📚 Learning: 2025-10-01T04:16:42.281Z
Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10707
File: src/components/Modals/FiatRamps/fiatRampProviders/onramper/utils.ts:104-107
Timestamp: 2025-10-01T04:16:42.281Z
Learning: In the ShapeShift web codebase, React Query expects functions to return at least `null` rather than `undefined`. When implementing quote fetching functions that may not return a value, they should explicitly return `null` instead of implicit `undefined` to ensure proper React Query caching and state management.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-04T16:02:27.360Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10171
File: src/components/MultiHopTrade/components/TradeConfirm/components/ExpandedStepperSteps.tsx:458-458
Timestamp: 2025-08-04T16:02:27.360Z
Learning: In multi-hop swap transactions, last hop sell transactions might not be detected by the swapper (unlike buy transactions which are always known immediately). The conditional stepSource logic for last hop buy transactions (`isLastHopSellTxSeen ? stepSource : undefined`) serves as defensive programming for future multi-hop support with intermediate chains, even though multi-hop functionality is not currently supported in production.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 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:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxpackages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.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:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-14T17:54:32.563Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10276
File: src/pages/ThorChainLP/components/ReusableLpStatus/ReusableLpStatus.tsx:97-108
Timestamp: 2025-08-14T17:54:32.563Z
Learning: In ReusableLpStatus component (src/pages/ThorChainLP/components/ReusableLpStatus/ReusableLpStatus.tsx), the txAssets dependency is stable from first render because poolAsset, baseAsset, actionSide, and action are all defined first render, making the current txAssetsStatuses initialization pattern safe without needing useEffect synchronization.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxpackages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tsscripts/generateTradableAssetMap/index.tsscripts/generateAssetData/generateAssetData.tssrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-09-12T12:00:33.924Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/SendTransactionConfirmation.tsx:42-50
Timestamp: 2025-09-12T12:00:33.924Z
Learning: gomesalexandre prefers maintaining consistency with existing code patterns across WalletConnect modal components, including side-effects-during-render for error handling (showErrorToast + handleReject calls before return null), rather than introducing isolated refactors that would create inconsistency in the codebase.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-09-12T12:00:33.924Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/SendTransactionConfirmation.tsx:42-50
Timestamp: 2025-09-12T12:00:33.924Z
Learning: gomesalexandre prefers maintaining consistency with existing code patterns in WalletConnect modals, including side-effects-during-render for error handling (showErrorToast + handleReject), rather than introducing isolated refactors that would make the codebase inconsistent.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-08-10T21:09:25.643Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10215
File: src/components/MultiHopTrade/hooks/useGetTradeRateInput.ts:65-67
Timestamp: 2025-08-10T21:09:25.643Z
Learning: In the MultiHopTrade components, `selectInputBuyAsset` and `selectInputSellAsset` selectors from `tradeInputSlice` always return defined values because they have default values in the initial state (BTC for buyAsset, ETH for sellAsset, with fallback to defaultAsset). Null checks for these assets are unnecessary when using these selectors.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-15T07:51:16.374Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10278
File: src/components/AssetHeader/hooks/useQuickBuy.ts:97-99
Timestamp: 2025-08-15T07:51:16.374Z
Learning: The selectPortfolioUserCurrencyBalanceByAssetId selector in src/state/slices/portfolioSlice/selectors.ts expects a filter object with an assetId property, not a raw AssetId string. The selector signature is (state: ReduxState, filter) where filter should have an assetId property. This pattern is consistent across portfolio selectors that use selectAssetIdParamFromFilter. Passing a filter object like { assetId: someAssetId } is the correct usage pattern.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-15T07:51:16.374Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10278
File: src/components/AssetHeader/hooks/useQuickBuy.ts:97-99
Timestamp: 2025-08-15T07:51:16.374Z
Learning: The selectPortfolioUserCurrencyBalanceByAssetId selector in src/state/slices/portfolioSlice/selectors.ts accepts a filter object with an assetId property (signature: (state, { assetId })), not a raw AssetId string. Passing a filter object like { assetId: someAssetId } is the correct usage pattern.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-08-15T07:51:16.374Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10278
File: src/components/AssetHeader/hooks/useQuickBuy.ts:97-99
Timestamp: 2025-08-15T07:51:16.374Z
Learning: The selectPortfolioUserCurrencyBalanceByAssetId selector in src/state/slices/portfolioSlice/selectors.ts accepts a filter object with an assetId property, not a raw AssetId string. The selector signature is (state: ReduxState, filter) where filter is expected to have an assetId property. Passing a filter object like { assetId: someAssetId } is the correct usage pattern.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-08-22T15:07:18.021Z
Learnt from: kaladinlight
Repo: shapeshift/web PR: 10326
File: src/hooks/useActionCenterSubscribers/useThorchainLpActionSubscriber.tsx:37-41
Timestamp: 2025-08-22T15:07:18.021Z
Learning: In src/hooks/useActionCenterSubscribers/useThorchainLpActionSubscriber.tsx, kaladinlight prefers not to await the upsertBasePortfolio call in the Base chain handling block, indicating intentional fire-and-forget behavior for Base portfolio upserts in the THORChain LP completion flow.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
📚 Learning: 2025-12-27T16:02:52.792Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11536
File: src/components/MultiHopTrade/components/TradeConfirm/hooks/useTradeExecution.tsx:252-265
Timestamp: 2025-12-27T16:02:52.792Z
Learning: When reviewing bug fixes, especially in shapeshift/web, prefer minimal changes that fix correctness over introducing broader refactors or quality-of-life improvements (e.g., extracting duplicated logic) unless such improvements are essential to the fix. Apply this guideline broadly to TSX files and related components, not just the specific location, to keep changes focused and maintainable.
Applied to files:
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsxsrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 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/src/swappers/NearIntentsSwapper/utils/helpers/helpers.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 : Reuse executeEvmTransaction utility for EVM-based swappers instead of implementing custom transaction execution
Applied to files:
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.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/index.ts : Export unique functions and types from packages/swapper/src/index.ts only if needed for external consumption
Applied to files:
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tsscripts/generateTradableAssetMap/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 : Validate inputs and log errors for debugging in Swapper system implementations
Applied to files:
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.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/*/endpoints.ts : Reuse checkEvmSwapStatus utility for checking EVM swap status instead of implementing custom status checks
Applied to files:
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.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 : All swappers must implement the Swapper interface from packages/swapper/src/types.ts
Applied to files:
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
📚 Learning: 2025-08-05T23:36:13.214Z
Learnt from: premiumjibles
Repo: shapeshift/web PR: 10187
File: src/state/slices/preferencesSlice/selectors.ts:21-25
Timestamp: 2025-08-05T23:36:13.214Z
Learning: The AssetId type from 'shapeshiftoss/caip' package is a string type alias, so it can be used directly as a return type for cache key resolvers in re-reselect selectors without needing explicit string conversion.
Applied to files:
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tsscripts/generateTradableAssetMap/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:
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tspackages/utils/src/getAssetNamespaceFromChainId.tsscripts/generateTradableAssetMap/index.tsscripts/generateAssetData/generateAssetData.tssrc/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-08-17T21:53:03.806Z
Learnt from: 0xApotheosis
Repo: shapeshift/web PR: 10290
File: scripts/generateAssetData/color-map.json:41-47
Timestamp: 2025-08-17T21:53:03.806Z
Learning: In the ShapeShift web codebase, native assets (using CAIP-19 slip44 namespace like eip155:1/slip44:60, bip122:.../slip44:..., cosmos:.../slip44:...) are manually hardcoded and not generated via the automated asset generation script. Only ERC20/BEP20 tokens go through the asset generation process. The validation scripts should only validate generated assets, not manually added native assets.
Applied to files:
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.tspackages/utils/src/getAssetNamespaceFromChainId.tsscripts/generateTradableAssetMap/index.tsscripts/generateAssetData/generateAssetData.ts
📚 Learning: 2025-11-12T12:18:00.863Z
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.
Applied to files:
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
📚 Learning: 2025-09-04T13:22:35.399Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/state/slices/assetsSlice/selectors.ts:45-51
Timestamp: 2025-09-04T13:22:35.399Z
Learning: In shapeshift/web, the isPrimaryAsset function in src/lib/utils/asset.ts is intentionally designed to only treat null relatedAssetKey as primary (not undefined). The asset generation process specifically sets relatedAssetKey to null for primary assets, while undefined means the asset doesn't participate in grouping and should not be considered primary. Only assets with null relatedAssetKey or where relatedAssetKey === assetId are primary assets.
Applied to files:
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.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/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts
📚 Learning: 2025-08-27T13:49:48.668Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10375
File: src/state/migrations/index.ts:214-215
Timestamp: 2025-08-27T13:49:48.668Z
Learning: The clearAssetsMigrations system in the ShapeShift web app works independently of the root persistConfig version. Migration numbers (like 171) don't need to match the root persistConfig version field, and the system has been functioning correctly for months/years without manual version bumps.
Applied to files:
src/state/migrations/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/migrations/index.ts
📚 Learning: 2025-08-27T13:49:48.668Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10375
File: src/state/migrations/index.ts:214-215
Timestamp: 2025-08-27T13:49:48.668Z
Learning: The ShapeShift web app uses an automated versioning system for Redux Persist migrations. The version is calculated as `Math.max(...Object.keys(clearAssetsMigrations).map(Number))`, which automatically uses the highest migration number as the version. This eliminates the need to manually update persistConfig versions when adding new migrations - the system automatically bumps the version when new migration numbers are added to the migration objects.
Applied to files:
src/state/migrations/index.ts
📚 Learning: 2025-12-04T11:05:01.146Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11281
File: packages/swapper/src/swappers/PortalsSwapper/utils/fetchSquidStatus.ts:98-106
Timestamp: 2025-12-04T11:05:01.146Z
Learning: In packages/swapper/src/swappers/PortalsSwapper/utils/fetchSquidStatus.ts, getSquidTrackingLink should return blockchain explorer links (using Asset.explorerTxLink) rather than API endpoints. For non-GMP Squid swaps: return source chain explorer link with sourceTxHash when pending/failed, and destination chain explorer link with destinationTxHash when confirmed.
Applied to files:
packages/utils/src/getAssetNamespaceFromChainId.tsscripts/generateTradableAssetMap/index.ts
📚 Learning: 2025-12-26T15:45:47.558Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11515
File: scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts:100-122
Timestamp: 2025-12-26T15:45:47.558Z
Learning: In scripts/generateAssetData/generateRelatedAssetIndex/generateRelatedAssetIndex.ts, gomesalexandre is comfortable with the fetchBridgedCategoryMappings function lacking try-catch error handling for CoinGecko API calls. He prefers letting the script crash on API failures rather than adding defensive error handling, consistent with his fail-fast approach for asset generation scripts.
Applied to files:
scripts/generateTradableAssetMap/index.tsscripts/generateAssetData/generateAssetData.ts
📚 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:
scripts/generateTradableAssetMap/index.ts
📚 Learning: 2025-08-13T13:45:25.748Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10265
File: src/pages/ThorChainLP/queries/hooks/usePools.ts:93-0
Timestamp: 2025-08-13T13:45:25.748Z
Learning: In the ShapeShift web app, inbound addresses data for Thorchain pools requires aggressive caching settings (staleTime: 0, gcTime: 0, refetchInterval: 60_000) to ensure trading status and LP deposit availability are always current. This is intentional business-critical behavior, not a performance issue to be optimized.
Applied to files:
scripts/generateTradableAssetMap/index.ts
📚 Learning: 2025-10-21T17:11:18.087Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10871
File: src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx:426-428
Timestamp: 2025-10-21T17:11:18.087Z
Learning: In src/components/Modals/Send/hooks/useSendDetails/useSendDetails.tsx, within the handleInputChange function, use .toFixed() without arguments (not .toString()) when converting BigNumber amounts for input field synchronization. This avoids exponential notation in the input while preserving precision for presentational components like <Amount.Crypto /> and <Amount.Fiat /> to format appropriately.
Applied to files:
src/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-09-12T10:44:46.723Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/WalletConnectSigningModal/content/SendTransactionContent.tsx:0-0
Timestamp: 2025-09-12T10:44:46.723Z
Learning: gomesalexandre dismissed a clipboard error handling suggestion in PR #10461 for SendTransactionContent.tsx, demonstrating that the current navigator.clipboard.writeText implementation works as expected and preferring to keep it simple without additional try/catch error handling.
Applied to files:
src/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-11-24T21:20:44.637Z
Learnt from: CR
Repo: shapeshift/web PR: 0
File: .cursor/rules/react-best-practices.mdc:0-0
Timestamp: 2025-11-24T21:20:44.637Z
Learning: Applies to **/*.{jsx,tsx} : EXTRACT complex logic into custom hooks
Applied to files:
src/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-10-17T07:51:58.374Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10783
File: src/context/WalletProvider/NewWalletViews/NewWalletViewsSwitch.tsx:344-349
Timestamp: 2025-10-17T07:51:58.374Z
Learning: In the shapeshift/web codebase, Chakra UI's ModalContent component supports the containerProps prop. When using the useModalRegistration hook from ModalStackProvider, spreading {...modalContentProps} directly onto ModalContent is correct and properly applies z-index and pointer-events through containerProps.sx. Do not suggest extracting sx from modalContentProps.containerProps.sx.
Applied to files:
src/components/Modals/Send/views/SendAmountDetails.tsx
📚 Learning: 2025-08-22T12:58:36.070Z
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/components/Layout/Header/ActionCenter/components/Notifications/RewardDistributionNotification.tsx:33-55
Timestamp: 2025-08-22T12:58:36.070Z
Learning: In RewardDistributionNotification component (src/components/Layout/Header/ActionCenter/components/Notifications/RewardDistributionNotification.tsx), NeOMakinG confirmed that runeAsset is expected to always be defined when the component renders, so defensive guards against undefined runeAsset are not needed.
Applied to files:
src/components/Modals/Send/views/SendAmountDetails.tsx
🧬 Code graph analysis (5)
src/lib/asset-service/service/AssetService.ts (1)
packages/caip/src/constants.ts (1)
starknetChainId(89-89)
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx (8)
src/hooks/useNotificationToast.tsx (1)
useNotificationToast(27-70)src/state/store.ts (1)
useAppSelector(144-144)src/state/slices/tradeInputSlice/selectors.ts (1)
selectFirstHopSellAccountId(46-46)src/state/slices/portfolioSlice/selectors.ts (1)
selectPortfolioAccountMetadataByAccountId(121-126)src/hooks/useIsStarknetAccountDeployed/useIsStarknetAccountDeployed.ts (1)
useIsStarknetAccountDeployed(27-35)packages/caip/src/constants.ts (1)
starknetChainId(89-89)src/lib/utils/starknet.ts (1)
isStarknetChainAdapter(9-14)src/components/Text/Text.tsx (1)
Text(19-83)
packages/swapper/src/swappers/NearIntentsSwapper/utils/helpers/helpers.ts (3)
packages/types/src/base.ts (1)
Asset(88-110)packages/swapper/src/swappers/NearIntentsSwapper/types.ts (1)
chainIdToNearIntentsChain(30-47)packages/caip/src/constants.ts (1)
solanaChainId(86-86)
src/state/migrations/index.ts (1)
src/state/migrations/clearAssets.ts (1)
clearAssets(6-8)
scripts/generateAssetData/generateAssetData.ts (2)
packages/caip/src/adapters/coingecko/generated/index.ts (1)
starknet(47-47)packages/utils/src/assetData/baseAssets.ts (1)
starknet(423-437)
⏰ 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
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
Show resolved
Hide resolved
src/components/MultiHopTrade/components/TradeConfirm/TradeFooterButton.tsx
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts (2)
45-50: Consider exporting public constants for reusability.The
STRK_TOKEN_ADDRESSandOPENZEPPELIN_ACCOUNT_CLASS_HASHconstants are currently module-scoped. If other parts of the codebase need to reference these values (e.g., for asset generation, UI display, or testing), consider exporting them.Note: The static analysis warning about line 46 is a false positive—this is a public contract address on Starknet mainnet, not a secret.
77-79: Follow the established enum reverse-lookup pattern for getName().Most chain adapters use the pattern of reverse-looking up the enum key from the display name value:
const enumIndex = Object.values(ChainAdapterDisplayName).indexOf(ChainAdapterDisplayName.Starknet) return Object.keys(ChainAdapterDisplayName)[enumIndex]This maintains consistency across the codebase. Based on learnings, this is the established pattern used in Bitcoin, Ethereum, Litecoin, Cosmos, and other chain adapters.
🔎 Proposed fix
getName() { - return 'Starknet' + const enumIndex = Object.values(ChainAdapterDisplayName).indexOf(ChainAdapterDisplayName.Starknet) + 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 (1)
packages/chain-adapters/src/starknet/StarknetChainAdapter.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/starknet/StarknetChainAdapter.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/starknet/StarknetChainAdapter.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/starknet/StarknetChainAdapter.ts
🧠 Learnings (15)
📓 Common learnings
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/AssetSearch/components/AssetList.tsx:2-2
Timestamp: 2025-08-08T15:00:49.887Z
Learning: Project shapeshift/web: NeOMakinG prefers avoiding minor a11y/UI nitpicks (e.g., adding aria-hidden to decorative icons in empty states like src/components/AssetSearch/components/AssetList.tsx) within feature PRs; defer such suggestions to a follow-up instead of blocking the PR.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10323
File: src/pages/RFOX/components/Stake/components/StakeSummary.tsx:112-114
Timestamp: 2025-08-22T13:00:44.879Z
Learning: NeOMakinG prefers to keep PR changes minimal and focused on the core objectives, avoiding cosmetic or defensive code improvements that aren't directly related to the PR scope, even when they would improve robustness.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10128
File: .cursor/rules/error-handling.mdc:266-274
Timestamp: 2025-07-29T10:35:22.059Z
Learning: NeOMakinG prefers less nitpicky suggestions on documentation and best practices files, finding overly detailed suggestions on minor implementation details (like console.error vs logger.error) too granular for cursor rules documentation.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/pages/Dashboard/components/AccountList/AccountTable.tsx:60-0
Timestamp: 2025-09-02T08:34:08.157Z
Learning: NeOMakinG prefers code review comments to focus only on actual PR changes, not pre-existing code issues, unless there are critical security or correctness concerns directly related to the new functionality.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10234
File: src/components/MultiHopTrade/hooks/useGetTradeQuotes/hooks/useTrackTradeQuotes.ts:42-86
Timestamp: 2025-08-08T11:41:22.794Z
Learning: NeOMakinG prefers not to include refactors in move-only PRs; such suggestions should be deferred to follow-up issues instead of being applied within the same PR.
Learnt from: NeOMakinG
Repo: shapeshift/web PR: 10380
File: src/components/Table/Table.theme.ts:177-180
Timestamp: 2025-09-02T12:38:46.940Z
Learning: NeOMakinG prefers to defer technical debt and CSS correctness issues (like improper hover selectors) to follow-up PRs when the current PR is already large and focused on major feature implementation, even when the issues are valid from a usability/technical perspective.
📚 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/starknet/StarknetChainAdapter.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/starknet/StarknetChainAdapter.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/starknet/StarknetChainAdapter.ts
📚 Learning: 2025-09-12T13:43:19.770Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/utils/EIP155RequestHandlerUtil.ts:94-103
Timestamp: 2025-09-12T13:43:19.770Z
Learning: gomesalexandre has implemented a reliable gasLimit flow in WalletConnect dApps where Tenderly simulation provides gas estimates that get written to the form via setValue in GasSelectionMenu.tsx, making customTransactionData.gasLimit the primary reliable source. The sendTransaction.gasLimit fallback is kept as "paranoia" but may rarely be hit in practice due to this simulation-based architecture.
Applied to files:
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts
📚 Learning: 2025-09-12T13:43:50.695Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/hooks/useSimulateEvmTransaction.ts:91-95
Timestamp: 2025-09-12T13:43:50.695Z
Learning: gomesalexandre dismissed gas calculation overflow validation in useSimulateEvmTransaction hook as "stale", preferring to trust Tenderly's simulation data without defensive validation checks, consistent with his established pattern of relying on external service quality over defensive programming in WalletConnect flows.
Applied to files:
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts
📚 Learning: 2025-09-11T22:53:19.837Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/modals/EIP155TransactionConfirmation.tsx:27-31
Timestamp: 2025-09-11T22:53:19.837Z
Learning: gomesalexandre trusts Tenderly's data quality and doesn't want defensive validation for gas values (transaction?.gasLimit ?? transaction?.gas) in WalletConnect flows, preferring to rely on the external service providing valid hex values.
Applied to files:
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts
📚 Learning: 2025-10-15T15:57:39.956Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10810
File: src/plugins/walletConnectToDapps/utils/tenderly/index.ts:212-0
Timestamp: 2025-10-15T15:57:39.956Z
Learning: gomesalexandre uses discriminated union patterns (e.g., `isEIP1559 ? { max_fee_per_gas, max_priority_fee_per_gas } : { gas_price }`) in WalletConnect flows without additional validation guards, trusting that the runtime data structure ensures mutual exclusivity between EIP-1559 and legacy gas pricing fields.
Applied to files:
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts
📚 Learning: 2025-12-03T23:16:28.342Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11261
File: src/components/MultiHopTrade/components/TradeConfirm/hooks/useAllowanceApproval.tsx:117-172
Timestamp: 2025-12-03T23:16:28.342Z
Learning: In TRON transaction confirmation polling (e.g., approval flows in useAllowanceApproval.tsx), gomesalexandre is comfortable with optimistic completion when polling times out after the configured duration (e.g., 60 seconds). He considers the timeout a "paranoia" safety net for unlikely scenarios, expecting normal transactions to complete much faster. He prefers to defer more sophisticated timeout/failure handling as a separate follow-up concern rather than expanding PR scope.
Applied to files:
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts
📚 Learning: 2025-09-10T15:35:46.223Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10458
File: src/plugins/walletConnectToDapps/components/modals/EIP155SignTypedDataConfirmation.tsx:55-55
Timestamp: 2025-09-10T15:35:46.223Z
Learning: gomesalexandre prefers fail-fast early returns over graceful degradation when critical data is missing in WalletConnect flows (like peer metadata in EIP155SignTypedDataConfirmation.tsx). He favors "safety first, always double-wrap" approach and believes missing peer metadata indicates bigger problems that should be surfaced explicitly rather than masked with partial UI rendering.
Applied to files:
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts
📚 Learning: 2025-09-12T10:35:51.632Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/utils/tenderly/index.ts:33-45
Timestamp: 2025-09-12T10:35:51.632Z
Learning: gomesalexandre consistently dismisses CodeRabbit suggestions about replacing console.error/console.warn with structured logging in API integration code, preferring simple console logging for debugging Tenderly transaction simulation APIs in WalletConnect flows.
Applied to files:
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts
📚 Learning: 2025-12-03T23:21:16.985Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 11261
File: src/lib/utils/tron/getAllowance.ts:14-59
Timestamp: 2025-12-03T23:21:16.985Z
Learning: In src/lib/utils/tron/getAllowance.ts, gomesalexandre is not concerned about adding comprehensive error handling (try-catch blocks, custom error classes) for the getTrc20Allowance utility function, because it is used close to the view layer. He prefers simpler error handling for view-layer utilities, letting errors propagate naturally rather than adding defensive guards.
Applied to files:
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts
📚 Learning: 2025-09-12T13:43:19.770Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/utils/EIP155RequestHandlerUtil.ts:94-103
Timestamp: 2025-09-12T13:43:19.770Z
Learning: gomesalexandre has implemented a sophisticated gasLimit management system in WalletConnect dApps using Tenderly simulation. The GasSelectionMenu component automatically adjusts gasLimit via setValue when simulation shows higher gas usage than currently set, handling edge cases like dApps that enforce low gas limits (e.g., 21000) when actual usage is higher (e.g., 23322). This makes customTransactionData.gasLimit highly reliable as the primary source.
Applied to files:
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts
📚 Learning: 2025-09-12T10:44:46.723Z
Learnt from: gomesalexandre
Repo: shapeshift/web PR: 10461
File: src/plugins/walletConnectToDapps/components/WalletConnectSigningModal/content/SendTransactionContent.tsx:0-0
Timestamp: 2025-09-12T10:44:46.723Z
Learning: gomesalexandre dismissed a clipboard error handling suggestion in PR #10461 for SendTransactionContent.tsx, demonstrating that the current navigator.clipboard.writeText implementation works as expected and preferring to keep it simple without additional try/catch error handling.
Applied to files:
packages/chain-adapters/src/starknet/StarknetChainAdapter.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/starknet/StarknetChainAdapter.ts
🪛 Gitleaks (8.30.0)
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts
[high] 46-46: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ 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 (4)
packages/chain-adapters/src/starknet/StarknetChainAdapter.ts (4)
324-337: Verify resource bounds safety margins are appropriate.The code applies 500% multiplier (5x) to gas amounts and 200% multiplier (2x) to gas prices. While conservative safety margins are important for Starknet's resource bounds model, these values seem quite high and could result in users locking up significantly more funds than necessary for transaction execution.
Are these multipliers based on documented best practices or empirical testing? Consider:
- 5x gas amount means users must have 5x the estimated gas available
- Combined with 2x price multiplier, this is ~10x the estimated cost
- This could impact UX for users with limited balances
If these are standard/tested values for Starknet, this is fine. Otherwise, consider reducing to more typical values (e.g., 150-200% for amounts, 110-150% for prices).
905-1007: Fee estimation implementation looks good—past concern addressed.The current implementation correctly uses a dummy transaction to estimate fees (lines 949-954), with hardcoded fallbacks only when the estimation fails entirely. This addresses the previous review comment about using RPC estimation instead of fixed values.
The fallback values (100,000 for L1 gas amounts) are reasonable defaults for error cases where the estimation service is unavailable, as they prevent the method from throwing while still providing conservative estimates.
Note: The optional chaining in lines 957-974 ensures the fallbacks are used only when
feeEstimatefields are missing, not as primary values.
1120-1182: Transfer event parsing logic looks correct for Starknet.The implementation properly:
- Identifies Transfer events by selector (line 1118)
- Reconstructs Uint256 amounts from low/high parts (lines 1129-1131)
- Normalizes addresses for comparison (lines 1136-1137, 1149-1151)
- Creates both Send and Receive transfers when the user is involved (lines 1154-1173)
The address normalization prevents issues with inconsistent padding in Starknet addresses.
677-689: Resource bounds multipliers are consistent across the codebase.The same safety margins (500% for gas amounts, 200% for prices) are applied consistently in both
deployAccountandbuildSendApiTransactionmethods. This ensures predictable behavior across different transaction types.
Description
To be tested with hdwallet fren: https://github.com/shapeshift/hdwallet/pull/774/files#diff-5f742e6bef51b5334a6a133d812213b430d7b01ca375fd6864d8b4b0e75aa957
As usually, new chain =
-- Using a fresh new account will require to deploy an account on chain, will cost less than 1 sent, implemented a modal for that
Notes to be fixed as follow up prefered:
Issue (if applicable)
Nothing to close
Risk
Low, behind a flag
Testing
Engineering
Operations
Screenshots (if applicable)
https://jam.dev/c/62a96c16-a8d8-4dc5-bc3a-d0aa5796770c
Summary by CodeRabbit
New Features
Bug Fixes / Improvements
✏️ Tip: You can customize this high-level summary in your review settings.