fix/PRO-3690/change-token-atlas-buy-to-pulse#407
Conversation
WalkthroughImplements token-atlas → pulse deep-link flow: updates Pulse AppWrapper, HomeScreen, and Buy to parse URL params, run background token search, auto-select token/chain, and adjust search modal behavior. TokenGraphColumn now builds pulse URLs and receives selectedToken props. Tests updated (Pulse, Exchange), Authorized animation bypass added, and test store wired to API slice. Changes
Sequence Diagram(s)sequenceDiagram
participant TA as Token Atlas
participant User
participant Router
participant Pulse.AppWrapper
participant Pulse.Buy
participant API as pillarXApiSearchTokens
User->>TA: Click "Buy"
TA->>Router: Navigate to /pulse?asset=...&blockchain=...&from=token-atlas
Router->>Pulse.AppWrapper: Mount with query
Note over Pulse.AppWrapper: If from=token-atlas then don't open search modal
Pulse.AppWrapper->>Pulse.Buy: Render with setBuyToken, setChains
Pulse.Buy->>API: useGetSearchTokensQuery(filters from URL)
API-->>Pulse.Buy: { data, isLoading }
alt Results ready
Pulse.Buy->>Pulse.Buy: Build SelectedToken
Pulse.Buy->>Pulse.AppWrapper: setBuyToken(token)
Pulse.Buy->>Pulse.AppWrapper: setChains(chain)
Pulse.Buy->>Pulse.Buy: Stop searching UI
else Loading/No results
Pulse.Buy->>Pulse.Buy: Show loading or fallback UI
end
sequenceDiagram
participant Router
participant Authorized
Router->>Authorized: Mount with location.search
alt from=token-atlas
Authorized->>Authorized: setShowAnimation(false)
else other sources
Authorized->>Authorized: Show animation then hide after timer
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ 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). (3)
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 |
Deploying x with
|
| Latest commit: |
9419129
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://395e5950.x-e62.pages.dev |
| Branch Preview URL: | https://fix-pro-3690-change-token-at.x-e62.pages.dev |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
src/apps/pulse/components/Buy/Buy.tsx (3)
338-400: Consider improving error handling and token validation.The token auto-selection logic is comprehensive, but could benefit from better error handling and validation. The token mapping logic correctly handles both address and symbol searches.
Consider adding error handling for the search process:
// Auto-select token when search results are ready useEffect(() => { + if (fromTokenAtlas && tokenToSearch && !token && !isSearchLoading && !searchData?.result?.data) { + // Handle case where search returns no results + console.warn('No search results found for token:', tokenToSearch); + setIsSearchingToken(false); + return; + } + if ( fromTokenAtlas && tokenToSearch && !token && searchData?.result?.data && !isSearchLoading ) { const foundToken = searchData.result.data.find( (searchToken: TokenAssetResponse | PairResponse | undefined) => { + if (!searchToken) return false; + if (isAddress(tokenToSearch)) { return ( ( searchToken as TokenAssetResponse )?.contracts?.[0]?.toLowerCase() === tokenToSearch.toLowerCase() ); } return ( (searchToken as TokenAssetResponse)?.symbol?.toLowerCase() === tokenToSearch.toLowerCase() ); } ); if (foundToken && 'name' in foundToken && setBuyToken) { const chainIdFromUrl = blockchain ? chainNameToChainIdTokensData(blockchain) : 1; + // Validate essential token data before creating token object + if (!foundToken.name || !foundToken.symbol || !foundToken.contracts?.[0]) { + console.warn('Incomplete token data from search:', foundToken); + setIsSearchingToken(false); + return; + } const tokenToSelect = { name: foundToken.name, symbol: foundToken.symbol, logo: foundToken.logo ?? '', address: foundToken.contracts?.[0] || '', chainId: chainIdFromUrl, decimals: Array.isArray(foundToken.decimals) ? foundToken.decimals[0] || 18 : foundToken.decimals || 18, usdValue: foundToken.price?.toString() || '0', dailyPriceChange: 0, }; setBuyToken(tokenToSelect as SelectedToken); // Set the correct chain based on the blockchain parameter if (blockchain) { setChains(blockchain as MobulaChainNames); } setIsSearchingToken(false); + } else { + // Handle case where token is not found in search results + console.warn('Token not found in search results:', tokenToSearch); + setIsSearchingToken(false); } } }, [
363-366: Unify chain-id fallback — don't silently default to Ethereum (1)chainNameToChainIdTokensData (src/services/tokensData.ts) returns '' for unknown names; in src/apps/pulse/components/Buy/Buy.tsx (lines 363–366) you do
const chainIdFromUrl = blockchain ? chainNameToChainIdTokensData(blockchain) : 1;— this silently treats missing/invalid blockchain as Ethereum and conflicts with other modules that treat invalid mapping as 0/throw. Validate the mapping and handle invalid chains explicitly (e.g.const id = chainNameToChainIdTokensData(blockchain) ?? 0and guard/throw), or make an explicit, documented default (e.g. usegetChainId(MobulaChainNames.Ethereum)) if Ethereum is intended.
75-94: Verify search API hook implementation and add explicit error handling.I checked src/services/pillarXApiSearchTokens.ts — getSearchTokens uses fetchBaseQuery wrapped with retry(maxRetries:5) and returns MobulaApiResponse but has no transformResponse or custom error handling. In src/apps/pulse/components/Buy/Buy.tsx the hook only uses data/isLoading and guards with searchData?.result?.data && !isSearchLoading, but does not handle isError/error or isFetching. Recommend: surface hook errors (check isError/error), handle isFetching consistently, and either normalize the API response in the service (transformResponse / default shape) or add explicit runtime guards and user-facing error UI in Buy.tsx.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
src/apps/pulse/components/App/AppWrapper.tsx(2 hunks)src/apps/pulse/components/App/HomeScreen.tsx(4 hunks)src/apps/pulse/components/App/tests/HomeScreen.test.tsx(5 hunks)src/apps/pulse/components/Buy/Buy.tsx(6 hunks)src/apps/pulse/components/Buy/tests/Buy.test.tsx(5 hunks)src/apps/the-exchange/components/CardsSwap/test/CardSwap.test.tsx(1 hunks)src/apps/token-atlas/components/TokenGraphColumn/TokenGraphColumn.tsx(2 hunks)src/apps/token-atlas/index.tsx(1 hunks)src/containers/Authorized.tsx(1 hunks)src/test-utils/testUtils.tsx(2 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-03-28T09:22:22.712Z
Learnt from: RanaBug
PR: pillarwallet/x#275
File: src/apps/the-exchange/components/DropdownTokensList/DropdownTokenList.tsx:180-195
Timestamp: 2025-03-28T09:22:22.712Z
Learning: In the Exchange app, `swapTokenList` and `receiveTokenList` are derived from `searchTokenResult` when search is active, so including `searchToken` in the useEffect dependency array that uses these lists would be redundant as the lists will update when search results change.
Applied to files:
src/apps/pulse/components/App/HomeScreen.tsxsrc/apps/pulse/components/App/AppWrapper.tsxsrc/apps/pulse/components/Buy/Buy.tsxsrc/test-utils/testUtils.tsx
📚 Learning: 2025-08-20T09:14:16.888Z
Learnt from: RanaBug
PR: pillarwallet/x#374
File: src/apps/pillarx-app/index.tsx:12-12
Timestamp: 2025-08-20T09:14:16.888Z
Learning: In this codebase, Transaction Kit providers are set up at the container level (src/containers/Authorized.tsx), not at individual app component levels. App components like src/apps/pillarx-app/index.tsx are children that consume the context through the provider tree.
Applied to files:
src/apps/pulse/components/Buy/tests/Buy.test.tsxsrc/apps/pulse/components/App/tests/HomeScreen.test.tsxsrc/apps/pulse/components/Buy/Buy.tsx
🧬 Code graph analysis (5)
src/apps/pulse/components/App/HomeScreen.tsx (1)
src/apps/pulse/types/tokens.ts (1)
SelectedToken(1-10)
src/apps/token-atlas/components/TokenGraphColumn/TokenGraphColumn.tsx (2)
src/apps/token-atlas/types/types.tsx (1)
SelectedTokenType(14-23)src/services/tokensData.ts (1)
chainIdToChainNameTokensData(210-231)
src/apps/pulse/components/Buy/tests/Buy.test.tsx (2)
src/test-utils/testUtils.tsx (1)
TestWrapper(117-135)src/apps/pulse/components/Buy/Buy.tsx (1)
Buy(56-679)
src/apps/pulse/components/App/tests/HomeScreen.test.tsx (2)
src/test-utils/testUtils.tsx (1)
TestWrapper(117-135)src/apps/pulse/components/App/HomeScreen.tsx (1)
HomeScreen(45-412)
src/apps/pulse/components/Buy/Buy.tsx (4)
src/apps/pulse/types/tokens.ts (1)
SelectedToken(1-10)src/apps/pulse/utils/constants.ts (1)
getChainId(28-49)src/types/api.ts (2)
TokenAssetResponse(549-568)PairResponse(570-656)src/services/tokensData.ts (1)
chainNameToChainIdTokensData(234-255)
⏰ 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). (3)
- GitHub Check: lint
- GitHub Check: unit-tests
- GitHub Check: build
🔇 Additional comments (19)
src/containers/Authorized.tsx (1)
50-66: LGTM! Proper token-atlas flow optimization.The early exit when coming from token-atlas appropriately skips the loading animation to provide a smoother user experience. The implementation correctly preserves the existing timer logic for all other flows.
src/test-utils/testUtils.tsx (1)
20-22: LGTM! Enhanced test store for API testing.The integration of
pillarXApiSearchTokensAPI slice enables proper testing of the token search functionality introduced in the PR. The reducer and middleware are correctly configured in the test store.Also applies to: 42-45
src/apps/the-exchange/components/CardsSwap/test/CardSwap.test.tsx (1)
92-106: LGTM! Improved mock pattern for better test isolation.The async mock factory with
importOriginalpreserves all original module exports while only overriding the specific function needed for testing. This approach is more maintainable and reduces the risk of breaking changes in the mock.src/apps/token-atlas/components/TokenGraphColumn/TokenGraphColumn.tsx (2)
41-46: LGTM! Prop-driven architecture improves component reusability.The component now receives token data and utility functions through props instead of internal state access, making it more testable and flexible for different contexts.
Also applies to: 48-54
215-231: LGTM! Proper asset parameter derivation for token-atlas integration.The logic correctly handles different token types:
- Wrapped/native tokens use the symbol via
getSymbol()- Non-zero address tokens use the contract address
- Fallback to symbol for other cases
The navigation to
/pulsewith proper query parameters enables seamless token-atlas to Pulse app integration.src/apps/token-atlas/index.tsx (1)
299-302: LGTM! Proper prop wiring for TokenGraphColumn.The required props
selectedToken,isWrappedOrNativeToken, andgetSymbolare correctly passed from the parent component's context, enabling the new navigation functionality in TokenGraphColumn.src/apps/pulse/components/App/tests/HomeScreen.test.tsx (2)
20-22: LGTM! Proper test wrapper and extended props coverage.The migration to
TestWrapperaligns with the updated test infrastructure, and the new mock props (setBuyToken,chains,setChains) cover the enhanced HomeScreen interface for token-atlas integration.Also applies to: 39-42
44-54: LGTM! Consistent test wrapper usage.All test rendering consistently uses
TestWrapperwhich provides the necessary providers and store configuration for the enhanced component functionality.Also applies to: 79-92, 129-137, 247-255
src/apps/pulse/components/App/HomeScreen.tsx (2)
18-18: LGTM! Proper type imports and prop additions.The
MobulaChainNamesimport and new props (setBuyToken,setChains) enable upstream state management for token selection from child components.Also applies to: 41-43, 53-55
384-386: LGTM! Proper prop forwarding to Buy component.The
setBuyTokenandsetChainsprops are correctly passed to the Buy component, enabling the token-atlas flow to update parent state when tokens are auto-selected.src/apps/pulse/components/Buy/tests/Buy.test.tsx (3)
15-16: LGTM! Proper imports for enhanced Buy component.The
MobulaChainNamesandTestWrapperimports support the new token selection and chain management functionality in the Buy component.Also applies to: 20-22
32-39: **LGTM! Consistent mock approach.**The mock approach usingvi.mockwith a function that returns the mocked implementation is consistent with Vitest best practices. The mock correctly returns the expected shape foruseGetSearchTokensQuery.
148-151: LGTM! Comprehensive test prop coverage and wrapper consistency.The new mock props (
setBuyToken,chains,setChains) align with the Buy component's enhanced interface for token-atlas integration. The consistent use ofTestWrapperensures proper test environment setup with all required providers.Also applies to: 175-181, 189-197
src/apps/pulse/components/App/AppWrapper.tsx (2)
42-60: LGTM! Well-structured token-atlas conditional routing logic.The conditional logic correctly handles the token-atlas flow by preventing the search modal from opening when users come from token-atlas, allowing the Buy component to handle the search and token selection instead. The validation logic for addresses and symbols is appropriate with reasonable length constraints.
84-85: LGTM! Proper prop threading for token-atlas integration.The new props
setBuyTokenandsetChainsare correctly passed to HomeScreen to enable the token-atlas flow where Buy component can update the selected token and chain context.src/apps/pulse/components/Buy/Buy.tsx (4)
13-33: LGTM! Comprehensive imports for token-atlas integration.All necessary imports are properly added to support the new functionality including React Router hooks, Viem utilities, search API services, and type definitions.
52-54: LGTM! Proper interface expansion for token-atlas props.The BuyProps interface correctly adds the required props
setBuyTokenandsetChainsto support the token-atlas flow where the Buy component needs to update parent state.
332-336: LGTM! Clean trigger logic for token-atlas search.The effect properly initializes the search state when coming from token-atlas with valid parameters and no existing token selection.
519-536: LGTM! Clean loading state implementation.The conditional rendering properly shows a loading spinner with "Searching..." text when the token-atlas search is in progress, providing good user feedback.
Description
How Has This Been Tested?
Screenshots (if appropriate):
Types of changes
Summary by CodeRabbit
New Features
Improvements