Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

16638 mobile trade account and address picker stub #16935

Merged
merged 3 commits into from
Feb 13, 2025

Conversation

jbazant
Copy link
Contributor

@jbazant jbazant commented Feb 11, 2025

Description

Related Issue

Resolve #16638

Screenshots:

Copy link

github-actions bot commented Feb 11, 2025

🚀 Expo preview is ready!

  • Project → trezor-suite-preview
  • Platforms → android, ios
  • Scheme → trezorsuitelite
  • Runtime Version → 26
  • More info

Learn more about 𝝠 Expo Github Action

@jbazant jbazant force-pushed the 16638-Mobile-Trade-Account-and-address-picker-stub branch 2 times, most recently from e17c3c4 to 1bccaf0 Compare February 11, 2025 16:37
@jbazant jbazant force-pushed the 16638-Mobile-Trade-Account-and-address-picker-stub branch from 1bccaf0 to 51a0287 Compare February 12, 2025 11:23
@jbazant jbazant marked this pull request as ready for review February 12, 2025 11:23
@jbazant jbazant requested a review from a team as a code owner February 12, 2025 11:23
Copy link

coderabbitai bot commented Feb 12, 2025

Walkthrough

The pull request introduces multiple enhancements across the trading module. It adds a new accountSheet object to the internationalization file, which includes localized strings for account management and address handling. The package configuration has been updated to include new dependencies, specifically @trezor/blockchain-link-types and react-redux. Several components have been modified or introduced: the translation functionality is removed from BuyCard, replaced by a new ReceiveAccountPicker component, while components such as AccountSheet, AccountListItem, AccountSheetHeader, and AddressListEmptyComponent are added to improve account display and user interactions. The tradeable assets list has been streamlined by simplifying its item rendering logic. New custom hooks, useReceiveAccountsListData and useSelectedAccount, have been created along with their respective test suites to manage account selection and data formatting. Additionally, new type definitions and configuration references in tsconfig.json have been updated to accommodate these changes and external dependencies.


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (19)
suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsSheet.tsx (2)

26-51: Verify the mock data replacement plan.

Based on previous learnings, these mock arrays and helper functions are intentionally used as visual stubs. Please ensure there's a tracking issue or task for replacing them with real data fetching.

Would you like me to help create a new issue to track the implementation of real data fetching?


57-78: Implement the favorite toggle functionality.

The toggleFavourite function is currently a stub with a TODO comment. Consider implementing this functionality to enable users to manage their favorite assets.

Would you like me to help create a new issue to track the implementation of the favorite toggle functionality?

suite-native/module-trading/src/components/general/TradingBottomSheetSectionList.tsx (1)

88-92: Consider refactoring to avoid O(n^2) complexity with array spreads.

Using the spread operator on the accumulator can degrade performance for larger datasets. Instead, push the new items into the accumulator array.

         if (noSingletonSectionHeader && inputData.length === 1) {
-            return [...acc, ...itemsData];
+            acc.push(...itemsData);
+            return acc;
         }

-        return [...acc, ['sectionHeader', label, key], ...itemsData];
+        acc.push(['sectionHeader', label, key], ...itemsData);
+        return acc;
🧰 Tools
🪛 Biome (1.9.4)

[error] 89-89: Avoid the use of spread (...) syntax on accumulators.

Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.

(lint/performance/noAccumulatingSpread)


[error] 92-92: Avoid the use of spread (...) syntax on accumulators.

Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.

(lint/performance/noAccumulatingSpread)

suite-native/module-trading/src/hooks/useSelectedAccount.ts (1)

13-14: Add JSDoc documentation for better maintainability.

Consider adding JSDoc documentation to describe the hook's purpose, parameters, and return value.

+/**
+ * Hook for managing account selection state in the account picker.
+ * @param {AccountSheetState} props - The account sheet state props
+ * @returns {Object} The selected account state and handlers
+ */
 export const useSelectedAccount = ({ onAccountSelect, onClose, isVisible }: AccountSheetState) => {
suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx (1)

28-36: Add accessibility label for back navigation.

The back navigation button in SearchableSheetHeader should have an accessibility label.

             <SearchableSheetHeader
                 onClose={clearSelectedAccount}
                 title={selectedAccount.accountLabel}
                 leftButtonIcon="caretLeft"
+                leftButtonA11yLabel={translate('generic.buttons.back')}
             />
suite-native/module-trading/src/components/general/AccountSheet/AccountSheet.tsx (2)

32-33: Address TODO comment regarding loading state.

Consider implementing a loading state to improve user experience while data is being fetched.

Would you like me to help implement a loading state for the account list?


18-18: Add type safety to keyExtractor.

The keyExtractor should handle cases where address is undefined.

-const keyExtractor = (item: ReceiveAccount) => `${item.account}_${item.address?.address}`;
+const keyExtractor = (item: ReceiveAccount) => 
+    `${item.account.path}_${item.address?.address ?? 'no-address'}`;
suite-native/module-trading/src/hooks/useReceiveAccountsListData.ts (1)

56-56: Consider memoizing address mapping functions.

The address mapping operations could be memoized to optimize performance for large lists.

+        const mapAddressToReceiveAccount = useCallback(
+            (address: Address) => ({ account: selectedAccount, address }),
+            [selectedAccount],
+        );
+
         return [
             {
                 key: 'unused',
                 label: translate('moduleTrading.accountSheet.newAddress'),
-                data: unused.slice(0, 1).map(address => ({ account: selectedAccount, address })),
+                data: unused.slice(0, 1).map(mapAddressToReceiveAccount),
                 sectionData: undefined,
             },
             {
                 key: 'used',
                 label: translate('moduleTrading.accountSheet.usedAddresses'),
-                data: used.map(address => ({ account: selectedAccount, address })),
+                data: used.map(mapAddressToReceiveAccount),
                 sectionData: undefined,
             },
         ]

Also applies to: 62-62

suite-native/module-trading/src/components/buy/ReceiveAccountPicker.tsx (2)

67-67: Consider making the default symbol configurable.

The default symbol 'btc' is hardcoded. Consider making it configurable through a constant or configuration to improve maintainability.

-                symbol={selectedAsset?.symbol ?? 'btc'}
+                symbol={selectedAsset?.symbol ?? DEFAULT_TRADING_SYMBOL}

59-65: Enhance accessibility for account selection.

The account selection row could benefit from improved accessibility labels to better describe the current selection state.

             <TradingOverviewRow
                 title={translate('moduleTrading.tradingScreen.receiveAccount')}
                 onPress={showSheet}
                 noBottomBorder
+                accessibilityRole="button"
+                accessibilityLabel={
+                    selectedValue
+                        ? `${translate('moduleTrading.tradingScreen.receiveAccount')}: ${selectedValue.account.accountLabel}`
+                        : translate('moduleTrading.tradingScreen.receiveAccount')
+                }
+                accessibilityHint={translate('moduleTrading.tradingScreen.selectAccountHint')}
             >
suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetListItem.tsx (1)

43-43: Enhance accessibility for asset selection.

While the basic accessibility is good, consider adding more ARIA attributes for better screen reader support.

-        <Pressable onPress={onPress} accessibilityRole="radio" accessibilityLabel={name ?? symbol}>
+        <Pressable
+            onPress={onPress}
+            accessibilityRole="radio"
+            accessibilityLabel={name ?? symbol}
+            accessibilityState={{ checked: false }}
+            accessibilityHint={translate('moduleTrading.tradingScreen.selectAssetHint')}
+        >
suite-native/module-trading/src/components/general/SearchableSheetHeader.tsx (1)

23-23: Improve type safety for noOp function.

Consider adding proper type annotation for the noOp function to match the callback type it replaces.

-const noOp = () => {};
+const noOp: (isFilterActive: boolean) => void = () => {};
suite-native/module-trading/src/hooks/__tests__/useSelectedAccount.test.ts (1)

1-131: LGTM with suggestions for additional test cases.

The test coverage is comprehensive but could be enhanced with the following scenarios:

  1. Test error handling when invalid account data is provided
  2. Test behavior when onClose or onAccountSelect callbacks are undefined
  3. Test behavior with other cryptocurrency types besides BTC and ETH
suite-native/module-trading/src/components/general/AccountSheet/AccountListItem.tsx (2)

43-123: Consider performance optimizations and accessibility improvements.

  1. Memoize expensive computations and callbacks:
-export const AccountListItem = ({
+export const AccountListItem = React.memo(({
    symbol,
    receiveAccount: { account, address },
    onPress,
}: AccountListItemProps) => {
    const { applyStyle } = useNativeStyles();
    const { translate } = useTranslate();
    const { DisplaySymbolFormatter, FiatAmountFormatter, CryptoAmountFormatter } = useFormatters();

+   const handlePress = useCallback(() => {
+       onPress();
+   }, [onPress]);

    const cryptoValue = address?.balance ?? account.availableBalance;
    const fiatValue = useFiatFromCryptoValue({ symbol, cryptoValue });

    // ... rest of the component

-};
+});
  1. Enhance accessibility by adding more descriptive labels:
    <Pressable
-       accessibilityRole="radio"
+       accessibilityRole="button"
+       accessibilityState={{ selected: true }}
        accessibilityLabel={account.accountLabel}
+       accessibilityHint={translate('moduleTrading.accountSheet.selectAccountHint')}
        onPress={onPress}
    >

13-17: Improve type safety with stricter prop types.

Consider making the callback prop more specific:

-    onPress: () => void;
+    onPress: (account: ReceiveAccount) => void;
suite-native/module-trading/src/components/general/AccountSheet/__tests__/AccountListItem.comp.test.tsx (2)

8-10: Consider using a more realistic mock for useFiatFromCryptoValue.

The current mock simply returns the input value. A more realistic mock would simulate actual currency conversion:

 jest.mock('@suite-native/formatters', () => ({
-    useFiatFromCryptoValue: ({ cryptoValue }: { cryptoValue: string }) => cryptoValue,
+    useFiatFromCryptoValue: ({ cryptoValue, symbol }: { cryptoValue: string, symbol: string }) => {
+        const mockRates = { btc: 50000, eth: 3000 };
+        return (Number(cryptoValue) * (mockRates[symbol] || 1)).toString();
+    },
 }));

12-145: Add test cases for error scenarios and edge cases.

Consider adding tests for:

  1. Invalid balance values
  2. Missing account label
  3. Network errors in formatters
  4. Extremely long addresses that need truncation
  5. RTL layout support
suite-native/module-trading/src/hooks/__tests__/useReceiveAccountsListData.test.tsx (1)

12-204: Add error handling test cases.

Consider adding tests for:

  1. Network errors when fetching account data
  2. Invalid account data in the store
  3. Race conditions when switching symbols rapidly
  4. Memory leaks from unsubscribed listeners
suite-native/module-trading/package.json (1)

18-18: Dependencies properly configured.

The new dependencies are correctly added. For consistency with react-redux, consider pinning the version of react-native-reanimated.

-        "react-native-reanimated": "3.16.7",
+        "react-native-reanimated": "^3.16.7",

Also applies to: 22-23

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b1ea07e and 51a0287.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (19)
  • suite-native/intl/src/en.ts (1 hunks)
  • suite-native/module-trading/package.json (1 hunks)
  • suite-native/module-trading/src/components/buy/BuyCard.tsx (2 hunks)
  • suite-native/module-trading/src/components/buy/ReceiveAccountPicker.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountListItem.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountSheet.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/AddressListEmptyComponent.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/__tests__/AccountListItem.comp.test.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/SearchableSheetHeader.tsx (4 hunks)
  • suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetListItem.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsSheet.tsx (4 hunks)
  • suite-native/module-trading/src/components/general/TradingBottomSheetSectionList.tsx (1 hunks)
  • suite-native/module-trading/src/hooks/__tests__/useReceiveAccountsListData.test.tsx (1 hunks)
  • suite-native/module-trading/src/hooks/__tests__/useSelectedAccount.test.ts (1 hunks)
  • suite-native/module-trading/src/hooks/useReceiveAccountsListData.ts (1 hunks)
  • suite-native/module-trading/src/hooks/useSelectedAccount.ts (1 hunks)
  • suite-native/module-trading/src/types.ts (2 hunks)
  • suite-native/module-trading/tsconfig.json (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsSheet.tsx (2)
Learnt from: jbazant
PR: trezor/trezor-suite#16668
File: suite-native/module-trading/src/components/TradeableAssetsSheet/TradeableAssetsSheet.tsx:0-0
Timestamp: 2025-02-04T13:18:21.530Z
Learning: The mock data arrays in `suite-native/module-trading/src/components/TradeableAssetsSheet/TradeableAssetsSheet.tsx` are intentionally used as visual stubs and will be replaced with real data fetching in future commits.
Learnt from: jbazant
PR: trezor/trezor-suite#16668
File: suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsFilterTabs.tsx:17-28
Timestamp: 2025-02-04T13:18:46.084Z
Learning: The mock data in TradeableAssetsFilterTabs.tsx is part of a visual stub and will be replaced with dynamic data in future commits.
🪛 Biome (1.9.4)
suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx

[error] 15-15: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

suite-native/module-trading/src/components/general/TradingBottomSheetSectionList.tsx

[error] 89-89: Avoid the use of spread (...) syntax on accumulators.

Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.

(lint/performance/noAccumulatingSpread)


[error] 92-92: Avoid the use of spread (...) syntax on accumulators.

Spread syntax should be avoided on accumulators (like those in .reduce) because it causes a time complexity of O(n^2).
Consider methods such as .splice or .push instead.

(lint/performance/noAccumulatingSpread)

⏰ Context from checks skipped due to timeout of 90000ms (18)
  • GitHub Check: PR-check / node-authorizeCoinjoin cancelCoinjoinAuthorization passphrase unlockPath setBusy checkFirmwareAuthenticity keepSession cancel.test info.test resetDevice-api
  • GitHub Check: PR-check / node-override init-api-flaky
  • GitHub Check: PR-check / web-override init-api-flaky
  • GitHub Check: PR-check / web-authorizeCoinjoin cancelCoinjoinAuthorization passphrase unlockPath setBusy checkFirmwareAuthenticity keepSession cancel.test info.test resetDevice-api
  • GitHub Check: build-deploy
  • GitHub Check: run-desktop-tests (@group=wallet, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: run-desktop-tests (@group=other, trezor-user-env-unix)
  • GitHub Check: EAS Update
  • GitHub Check: run-desktop-tests (@group=settings, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: prepare_android_test_app
  • GitHub Check: run-desktop-tests (@group=device-management, trezor-user-env-unix)
  • GitHub Check: run-desktop-tests (@group=suite, trezor-user-env-unix)
  • GitHub Check: Setup and Cache Dependencies
  • GitHub Check: build-web
  • GitHub Check: build-web
  • GitHub Check: test
  • GitHub Check: Analyze with CodeQL (javascript)
  • GitHub Check: Socket Security: Pull Request Alerts
🔇 Additional comments (10)
suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsSheet.tsx (4)

1-24: LGTM! Clean and focused type definitions.

The import statements and type definitions are well-organized, and the ListItemExtraData type is appropriately focused on the essential isFavourite property.


52-56: LGTM! Robust key generation.

The key extractor function generates unique keys by combining all relevant properties (symbol, contract address, and favorite status).


93-110: LGTM! Well-structured section data.

The section data is properly memoized and organized with clear keys and labels. The dependency array correctly includes both favourites and assetsData.


112-124: Verify the noSingletonSectionHeader prop usage.

The noSingletonSectionHeader prop is used to disable section headers. Please verify if this is the intended behavior, as section headers could help users distinguish between favorites and all assets.

Would you like me to help investigate alternative approaches to section header rendering?

suite-native/module-trading/src/components/general/AccountSheet/AddressListEmptyComponent.tsx (1)

5-10: Add unit test coverage to ensure correct rendering.

Testing that the appropriate translation IDs appear and that the component displays the correct text can help prevent regressions when translation keys change.

[nitpick, offer_assistance]

Would you like me to provide a basic test snippet or open a new issue to track the addition of test coverage?

suite-native/module-trading/src/types.ts (1)

19-22: LGTM: Type definition looks solid.

The ReceiveAccount type is clearly defined and aligns well with the underlying Account and optional Address structures.

suite-native/module-trading/src/hooks/useSelectedAccount.ts (1)

20-24: Verify the account.addresses check.

The condition account.addresses && !address might need additional validation to ensure type safety and handle edge cases.

❌ Verification inconclusive

🏁 Script executed:

#!/bin/bash
# Search for Account type definition and usage of addresses property
ast-grep --pattern 'type Account = {
  $$$
  addresses?: $_
  $$$
}'

Length of output: 70


Action: Manually Verify the account.addresses Validation

Our initial search didn’t reveal an explicit definition for the Account type containing the addresses property. This lack of explicit output suggests one or more of the following:

  • The type definition for Account (with its addresses property) might be defined elsewhere, imported from an external source, or set up differently than the searched pattern.
  • Depending on how addresses is implemented (likely as an array), the current condition account.addresses && !address will pass even when addresses is an empty array—which might not be the intended behavior if you expect a non-empty list.

To ensure type safety and properly handle edge cases, please:

  • Manually verify the definition of the Account type: Locate the actual type or interface for Account in your repository. Ensure that the addresses property is defined the way you expect.
  • Reevaluate the check on account.addresses: If addresses is an array, consider updating the condition (for example, using a length check with account.addresses?.length) to ensure it handles empty arrays appropriately.
suite-native/module-trading/src/components/buy/BuyCard.tsx (1)

4-4: LGTM! Good refactoring.

The changes improve separation of concerns by moving account selection logic to a dedicated ReceiveAccountPicker component.

Also applies to: 7-7, 52-52

suite-native/intl/src/en.ts (1)

1348-1358: Well-structured localization strings!

The new accountSheet strings are well-organized, follow the established patterns, and provide clear, user-friendly messages for the account selection interface.

suite-native/module-trading/tsconfig.json (1)

6-9: LGTM! Proper TypeScript project reference added.

The reference to blockchain-link-types is correctly configured and follows the project's TypeScript setup pattern.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (4)
suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx (1)

28-37: Enhance accessibility for back navigation.

The back navigation using SearchableSheetHeader should provide more context about where the user is navigating back to.

             <SearchableSheetHeader
                 onClose={clearSelectedAccount}
                 title={selectedAccount.accountLabel}
                 leftButtonIcon="caretLeft"
-                leftButtonA11yLabel={translate('generic.buttons.back')}
+                leftButtonA11yLabel={translate('generic.buttons.back') + ' to account selection'}
             />
suite-native/module-trading/src/components/general/AccountSheet/AccountListItem.tsx (1)

21-41: Consolidate similar style definitions.

Multiple style definitions share common properties. Consider extracting shared styles to reduce duplication.

+const baseTextStyle = prepareNativeStyle(({ colors }) => ({
+    color: colors.textDefault,
+}));
+
+const baseAlignedTextStyle = prepareNativeStyle(
+    { extend: baseTextStyle },
+    {
+        textAlign: 'right',
+        flex: 0,
+    },
+);
+
-const labelTextStyle = prepareNativeStyle(({ colors }) => ({
-    color: colors.textDefault,
+const labelTextStyle = prepareNativeStyle(
+    { extend: baseTextStyle },
+    {
     flex: 1,
-}));
+    },
+);
suite-native/module-trading/src/components/general/TradingBottomSheetSectionList.tsx (2)

70-98: Optimize section data transformation.

The transformToInternalFlatListData function creates new arrays on each render. Consider using useMemo for the item data transformation.

 const transformToInternalFlatListData = <T, U = undefined>(
     inputData: SectionListData<T, U>,
     noSingletonSectionHeader: boolean | undefined,
 ): ListInternalItemShape<T, U>[] =>
     inputData.reduce(
         (acc, { key, label, data, sectionData }) => {
-            const itemsData = data.map(
+            const itemsData = useMemo(() => data.map(
                 (item, index): ListInternalItemShape<T, U> => [
                     'item',
                     item,
                     {
                         isFirst: index === 0,
                         isLast: index === data.length - 1,
                         sectionData,
                     },
                 ],
-            );
+            ), [data, sectionData]);

150-158: Optimize items count calculation.

The itemsCount calculation could be more efficient by using a single reduce operation that also tracks the sections count.

-    const sectionsCount = data.length;
-
-    const itemsCount = useMemo(
-        () =>
-            data.reduce(
-                (intermediateDataLength, { data: sectionData }) =>
-                    intermediateDataLength + sectionData.length,
-                0,
-            ),
-        [data],
-    );
+    const { sectionsCount, itemsCount } = useMemo(
+        () => data.reduce(
+            (acc, { data: sectionData }) => ({
+                sectionsCount: acc.sectionsCount + 1,
+                itemsCount: acc.itemsCount + sectionData.length,
+            }),
+            { sectionsCount: 0, itemsCount: 0 },
+        ),
+        [data],
+    );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 51a0287 and 9f4bf2f.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (7)
  • suite-native/module-trading/package.json (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountListItem.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountSheet.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/SearchableSheetHeader.tsx (4 hunks)
  • suite-native/module-trading/src/components/general/TradingBottomSheetSectionList.tsx (1 hunks)
  • suite-native/module-trading/src/hooks/useReceiveAccountsListData.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • suite-native/module-trading/package.json
  • suite-native/module-trading/src/hooks/useReceiveAccountsListData.ts
🧰 Additional context used
🪛 Biome (1.9.4)
suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx

[error] 15-15: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

⏰ Context from checks skipped due to timeout of 90000ms (17)
  • GitHub Check: build-deploy
  • GitHub Check: build-deploy
  • GitHub Check: run-desktop-tests (@group=wallet, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: run-desktop-tests (@group=other, trezor-user-env-unix)
  • GitHub Check: EAS Update
  • GitHub Check: run-desktop-tests (@group=settings, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: test
  • GitHub Check: run-desktop-tests (@group=device-management, trezor-user-env-unix)
  • GitHub Check: Analyze with CodeQL (javascript)
  • GitHub Check: build
  • GitHub Check: Setup and Cache Dependencies
  • GitHub Check: transport-e2e-test
  • GitHub Check: prepare_android_test_app
  • GitHub Check: run-desktop-tests (@group=suite, trezor-user-env-unix)
  • GitHub Check: build-web
  • GitHub Check: Socket Security: Pull Request Alerts
  • GitHub Check: build-web
🔇 Additional comments (4)
suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx (1)

15-18: Fix empty object type in style definition.

The empty object type {} in prepareNativeStyle should be replaced with a proper style type definition.

-const wrapperStyle = prepareNativeStyle<{}>(({ spacings }) => ({
+const wrapperStyle = prepareNativeStyle<{ padding: number; gap: number }>(({ spacings }) => ({
🧰 Tools
🪛 Biome (1.9.4)

[error] 15-15: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

suite-native/module-trading/src/components/general/SearchableSheetHeader.tsx (3)

5-5: LGTM!

The import of IconName type is correctly added to support the new icon prop.


15-16: LGTM!

The new prop types are well-defined and follow React naming conventions.


64-68: LGTM!

The props are correctly passed to SheetHeaderTitle with a good fallback pattern for accessibility labels.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
suite-native/module-trading/src/components/general/AccountSheet/AccountListItem.tsx (3)

25-34: Consider adjusting flex properties for better text handling.

While the styling is generally good, the current flex setup might not handle very long text optimally. Consider using flexShrink: 1 instead of flex: 1 for the label style to prevent text overflow issues while maintaining layout flexibility.

 const labelTextStyle = prepareNativeStyle<TextStyle>(({ colors }, { textColor }) => ({
     color: colors[textColor],
-    flex: 1,
+    flexShrink: 1,
 }));

55-59: Enhance accessibility with role description.

While the component includes good accessibility features, adding a role description would improve the user experience for screen readers.

 <Pressable
     onPress={onPress}
     accessibilityRole="button"
     accessibilityLabel={account.accountLabel}
+    accessibilityRoleDescription={translate('moduleTrading.accountSheet.accountItemRole')}
 >

50-52: Simplify conditional logic.

The conditional checks could be simplified for better readability and maintenance.

-    const shouldDisplayCaret = !isAddressDetail && !!account.addresses;
-    const shouldDisplayBalance = !isAddressDetail || address?.balance != null;
-    const label = isAddressDetail ? address.address : account.accountLabel;
+    const shouldDisplayCaret = !isAddressDetail && Boolean(account.addresses);
+    const shouldDisplayBalance = Boolean(!isAddressDetail || address?.balance);
+    const label = address?.address ?? account.accountLabel;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9f4bf2f and 8a4c559.

📒 Files selected for processing (2)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountListItem.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountSheet.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountSheet.tsx
⏰ Context from checks skipped due to timeout of 90000ms (17)
  • GitHub Check: build-deploy
  • GitHub Check: build-deploy
  • GitHub Check: run-desktop-tests (@group=wallet, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: run-desktop-tests (@group=other, trezor-user-env-unix)
  • GitHub Check: run-desktop-tests (@group=settings, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: EAS Update
  • GitHub Check: run-desktop-tests (@group=device-management, trezor-user-env-unix)
  • GitHub Check: build
  • GitHub Check: transport-e2e-test
  • GitHub Check: Analyze with CodeQL (javascript)
  • GitHub Check: run-desktop-tests (@group=suite, trezor-user-env-unix)
  • GitHub Check: build-web
  • GitHub Check: test
  • GitHub Check: prepare_android_test_app
  • GitHub Check: Setup and Cache Dependencies
  • GitHub Check: build-web
  • GitHub Check: Socket Security: Pull Request Alerts
🔇 Additional comments (2)
suite-native/module-trading/src/components/general/AccountSheet/AccountListItem.tsx (2)

13-23: LGTM! Well-structured type definitions.

The type definitions are clear, properly exported, and follow TypeScript best practices. The constant for height helps maintain consistency across the UI.


47-48: Add error handling for undefined values.

The crypto and fiat value calculations don't handle the case where both values could be undefined.

-    const cryptoValue = isAddressDetail ? address.balance : account.availableBalance;
+    const cryptoValue = isAddressDetail ? address?.balance ?? 0n : account.availableBalance ?? 0n;
     const fiatValue = useFiatFromCryptoValue({ symbol, cryptoValue });

@vytick vytick added the mobile Suite Lite issues and PRs label Feb 12, 2025
@trezor trezor deleted a comment from coderabbitai bot Feb 12, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
suite-native/module-trading/src/components/general/AccountSheet/AccountSheet.tsx (1)

33-33: Add null check for data.

The nullish coalescing operator is used but the type of data is not clear. Consider adding type annotation for better type safety.

-const data = useReceiveAccountsListData(symbol, selectedAccount) ?? [];
+const data: ReceiveAccount[] = useReceiveAccountsListData(symbol, selectedAccount) ?? [];
suite-native/module-trading/src/components/buy/BuyCard.tsx (1)

4-4: Remove unused import.

The Translation import is only used once for the buy title. Consider moving it closer to where it's used.

suite-native/module-trading/src/components/buy/ReceiveAccountPicker.tsx (1)

81-81: Avoid hardcoded fallback value.

The hardcoded fallback of 'btc' might not be suitable for all use cases. Consider making it configurable or using a more generic default.

Apply this diff:

-symbol={selectedSymbol ?? 'btc'}
+symbol={selectedSymbol ?? DEFAULT_NETWORK_SYMBOL}

Add the constant at the top of the file:

const DEFAULT_NETWORK_SYMBOL: NetworkSymbol = 'btc';
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a4c559 and 1dc740c.

📒 Files selected for processing (4)
  • suite-native/module-trading/src/components/buy/BuyCard.tsx (2 hunks)
  • suite-native/module-trading/src/components/buy/ReceiveAccountPicker.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountSheet.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx

[error] 15-15: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

⏰ Context from checks skipped due to timeout of 90000ms (17)
  • GitHub Check: build-deploy
  • GitHub Check: build-deploy
  • GitHub Check: run-desktop-tests (@group=wallet, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: run-desktop-tests (@group=other, trezor-user-env-unix)
  • GitHub Check: EAS Update
  • GitHub Check: build
  • GitHub Check: run-desktop-tests (@group=settings, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: prepare_android_test_app
  • GitHub Check: test
  • GitHub Check: build-web
  • GitHub Check: build-web
  • GitHub Check: run-desktop-tests (@group=device-management, trezor-user-env-unix)
  • GitHub Check: transport-e2e-test
  • GitHub Check: Setup and Cache Dependencies
  • GitHub Check: Analyze with CodeQL (javascript)
  • GitHub Check: run-desktop-tests (@group=suite, trezor-user-env-unix)
  • GitHub Check: Socket Security: Pull Request Alerts
🔇 Additional comments (10)
suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx (2)

9-13: LGTM!

The type definition is clear and follows React's naming conventions.


20-51: LGTM!

The component implementation is well-structured with:

  • Clear conditional rendering
  • Proper use of hooks
  • Good internationalization support
suite-native/module-trading/src/components/general/AccountSheet/AccountSheet.tsx (3)

11-16: LGTM!

The type definition is clear and follows React's naming conventions.


18-19: Improve key extractor robustness.

The key extractor could be more robust by using better fallback values.

-const keyExtractor = (item: ReceiveAccount) =>
-    `${item.account.key}_${item.address?.address ?? 'address_undefined'}`;
+const keyExtractor = (item: ReceiveAccount) =>
+    `${item.account.key}_${item.address?.address ?? item.account.accountIndex}`;

21-60: Consider implementing loading state.

The component should handle loading state from useReceiveAccountsListData hook.

Would you like me to help implement a loading state component that shows a skeleton UI while the data is being fetched?

suite-native/module-trading/src/components/buy/BuyCard.tsx (1)

52-52: LGTM!

The integration of ReceiveAccountPicker with selectedSymbol prop looks good and aligns with the PR objectives for mobile trade account functionality.

suite-native/module-trading/src/components/buy/ReceiveAccountPicker.tsx (4)

28-32: LGTM!

The component is well-structured and reusable, with consistent text styling.


34-58: LGTM!

The component follows the coding style by accepting specific props instead of whole objects, and handles different states appropriately.


74-77: Pass specific props instead of whole objects.

Following the coding style mentioned in past reviews, pass only the required properties instead of accessing them through nested objects.

Apply this diff:

-<ReceiveAccountPickerRight
-    selectedAccountLabel={selectedValue?.account.accountLabel}
-    selectedAddress={selectedValue?.address?.address}
-/>
+<ReceiveAccountPickerRight
+    selectedAccountLabel={selectedValue?.accountLabel}
+    selectedAddress={selectedValue?.address}
+/>

60-88: Consider renaming to AccountPicker.

As suggested in past reviews, this component might be used for selling or swapping as well. Consider renaming it to just AccountPicker for broader use.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
suite-native/module-trading/src/components/buy/ReceiveAccountPicker.tsx (2)

34-58: Add explicit return type annotation for better type safety.

Consider adding an explicit return type annotation to the component for better type safety and documentation.

-const ReceiveAccountPickerRight = ({
+const ReceiveAccountPickerRight = ({
     selectedAccountLabel,
     selectedAddress,
-}: ReceiveAccountPickerRightProps) => {
+}: ReceiveAccountPickerRightProps): JSX.Element => {

81-81: Make the fallback symbol more explicit.

Consider defining the fallback symbol as a constant to make the code more maintainable and self-documenting.

+const DEFAULT_NETWORK_SYMBOL: NetworkSymbol = 'btc';
+
 export const ReceiveAccountPicker = ({ selectedSymbol }: ReceiveAccountPickerProps) => {
   // ...
-                symbol={selectedSymbol ?? 'btc'}
+                symbol={selectedSymbol ?? DEFAULT_NETWORK_SYMBOL}
suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx (1)

19-50: Consider memoizing the component for better performance.

Since this component is likely to be rendered within a list or frequently updated parent component, consider wrapping it with React.memo to prevent unnecessary re-renders.

-export const AccountSheetHeader = ({
+export const AccountSheetHeader = React.memo(({
    selectedAccountLabel,
    clearSelectedAccount,
    onClose,
}: AccountSheetHeaderProps) => {
    const { applyStyle } = useNativeStyles();
    const { translate } = useTranslate();

    // ... rest of the component implementation

-};
+});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 068c0c1 and 867b0cf.

📒 Files selected for processing (2)
  • suite-native/module-trading/src/components/buy/ReceiveAccountPicker.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx

[error] 14-14: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

⏰ Context from checks skipped due to timeout of 90000ms (17)
  • GitHub Check: build-deploy
  • GitHub Check: build-deploy
  • GitHub Check: run-desktop-tests (@group=wallet, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: run-desktop-tests (@group=other, trezor-user-env-unix)
  • GitHub Check: EAS Update
  • GitHub Check: run-desktop-tests (@group=settings, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: build
  • GitHub Check: Analyze with CodeQL (javascript)
  • GitHub Check: run-desktop-tests (@group=device-management, trezor-user-env-unix)
  • GitHub Check: build-web
  • GitHub Check: transport-e2e-test
  • GitHub Check: prepare_android_test_app
  • GitHub Check: Setup and Cache Dependencies
  • GitHub Check: build-web
  • GitHub Check: test
  • GitHub Check: run-desktop-tests (@group=suite, trezor-user-env-unix)
  • GitHub Check: Socket Security: Pull Request Alerts
🔇 Additional comments (6)
suite-native/module-trading/src/components/buy/ReceiveAccountPicker.tsx (3)

1-27: LGTM! Well-structured imports and type definitions.

The imports are well-organized, and the type definitions are clear and focused, following TypeScript best practices.


28-32: LGTM! Clean and focused component implementation.

The component is well-designed with proper text overflow handling and clear prop types.


60-88: Consider future component naming.

Based on past review comments, this component might be used for selling or swapping in the future. While the current name is accurate for its current use, keep in mind that it might need to be renamed to AccountPicker when the functionality expands.

Would you like me to create an issue to track this potential future refactoring?

suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx (3)

1-6: LGTM!

The imports are well-organized and all dependencies are used in the component.


8-12: LGTM!

The type definition is clear and well-structured, with appropriate types for each prop.


14-17: Fix the empty object type.

The empty object type {} should be replaced with a more specific type.

-const wrapperStyle = prepareNativeStyle<{}>
+const wrapperStyle = prepareNativeStyle<Record<string, never>>
🧰 Tools
🪛 Biome (1.9.4)

[error] 14-14: Don't use '{}' as a type.

Prefer explicitly define the object shape. '{}' means "any non-nullable value".

(lint/complexity/noBannedTypes)

Copy link
Contributor

@vytick vytick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice work 👌 Trade UI starts appearing nicely

@jbazant
Copy link
Contributor Author

jbazant commented Feb 13, 2025

/rebase

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsSheetHeader.tsx (2)

10-12: Add JSDoc comments to improve props documentation.

Consider adding JSDoc comments to describe the purpose of the onClose callback and any specific behavior expectations.

 type TradeableAssetsSheetHeaderProps = {
+    /** Callback invoked when the sheet should be closed */
     onClose: () => void;
 };

32-37: Consider memoizing the Animated.View content.

The Animated.View content could be memoized to prevent unnecessary re-renders when parent component props change.

+const MemoizedFilterTabs = React.memo(({ visible, animationDuration }: {
+    visible: boolean;
+    animationDuration: number;
+}) => (
+    <TradeableAssetsFilterTabs
+        visible={visible}
+        animationDuration={animationDuration}
+    />
+));

 <Animated.View layout={LinearTransition.duration(FOCUS_ANIMATION_DURATION)}>
-    <TradeableAssetsFilterTabs
-        visible={isFilterActive}
-        animationDuration={FOCUS_ANIMATION_DURATION}
-    />
+    <MemoizedFilterTabs
+        visible={isFilterActive}
+        animationDuration={FOCUS_ANIMATION_DURATION}
+    />
 </Animated.View>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 867b0cf and 1c4515b.

📒 Files selected for processing (3)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/SearchableSheetHeader.tsx (5 hunks)
  • suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsSheetHeader.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • suite-native/module-trading/src/components/general/SearchableSheetHeader.tsx
  • suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx
⏰ Context from checks skipped due to timeout of 90000ms (16)
  • GitHub Check: build-deploy
  • GitHub Check: build
  • GitHub Check: build-web
  • GitHub Check: run-desktop-tests (@group=wallet, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: build-web
  • GitHub Check: run-desktop-tests (@group=other, trezor-user-env-unix)
  • GitHub Check: run-desktop-tests (@group=settings, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: prepare_android_test_app
  • GitHub Check: run-desktop-tests (@group=device-management, trezor-user-env-unix)
  • GitHub Check: run-desktop-tests (@group=suite, trezor-user-env-unix)
  • GitHub Check: Setup and Cache Dependencies
  • GitHub Check: test
  • GitHub Check: build-deploy
  • GitHub Check: EAS Update
  • GitHub Check: transport-e2e-test
  • GitHub Check: Socket Security: Pull Request Alerts
🔇 Additional comments (1)
suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsSheetHeader.tsx (1)

16-16: LGTM! Type parameter removal improves code clarity.

The removal of the empty object type parameter <{}> from prepareNativeStyle is a good change as it was redundant. Type inference will work correctly for the simple style object being returned.

Copy link

@trezor-ci trezor-ci force-pushed the 16638-Mobile-Trade-Account-and-address-picker-stub branch from 1c4515b to b66e7b0 Compare February 13, 2025 15:50
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
suite-native/module-trading/src/components/general/AccountSheet/AccountListItem.tsx (1)

47-48: 🛠️ Refactor suggestion

Add fallback for undefined cryptoValue.

The cryptoValue calculation should handle cases where both values are undefined.

-    const cryptoValue = isAddressDetail ? address.balance : account.availableBalance;
+    const cryptoValue = isAddressDetail ? address?.balance ?? '0' : account.availableBalance ?? '0';
🧹 Nitpick comments (17)
suite-native/module-trading/src/components/buy/BuyCard.tsx (3)

32-34: Consider replacing hardcoded values with constants or props.

The hardcoded "0.0" value appears to be a placeholder. Consider:

  • Moving it to a constant
  • Making it configurable via props
  • Adding a comment explaining its purpose if it's intentionally static

38-43: Enhance error state handling.

The current ternary operator for selectedValue?.symbol could be improved for better maintainability.

Consider extracting this logic into a separate function for better readability:

-{selectedValue?.symbol ? (
-    <CryptoAmountFormatter value="0" symbol={selectedValue.symbol} />
-) : (
-    '-'
-)}
+{renderCryptoAmount(selectedValue)}

+const renderCryptoAmount = (selectedValue?: TradeableAsset) => {
+    if (!selectedValue?.symbol) return '-';
+    return <CryptoAmountFormatter value="0" symbol={selectedValue.symbol} />;
+};

18-55: Add TypeScript interface for component props.

While the component currently doesn't accept props, it's good practice to explicitly define the interface for future maintainability.

Consider adding:

interface BuyCardProps {
    // Add props as needed
}

export const BuyCard: React.FC<BuyCardProps> = () => {
    // ... existing implementation
};
suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetListItem.tsx (1)

43-43: Consider revising the accessibility role.

The accessibilityRole="radio" might not be the most appropriate choice for this context. A list item or button role would be more semantic for a selectable asset item.

-        <Pressable onPress={onPress} accessibilityRole="radio" accessibilityLabel={name ?? symbol}>
+        <Pressable onPress={onPress} accessibilityRole="button" accessibilityLabel={name ?? symbol}>
suite-native/module-trading/src/components/buy/ReceiveAccountPicker.tsx (1)

28-32: Consider enhancing type safety and reusability.

The component could benefit from:

  1. Using a union type for the variant prop instead of string literals
  2. Making it more reusable by accepting additional text props
-type RightTextProps = {
+type TextVariant = 'body' | 'hint';
+type RightTextProps = {
     children: ReactNode;
     color: Color;
-    variant?: 'body' | 'hint';
+    variant?: TextVariant;
+    numberOfLines?: number;
 };

 const RightText = ({ color, variant = 'body', children }: RightTextProps) => (
     <Text color={color} variant={variant} textAlign="right" ellipsizeMode="tail" numberOfLines={1}>
         {children}
     </Text>
 );
suite-native/module-trading/src/components/general/AccountSheet/AccountSheet.tsx (1)

18-19: Improve keyExtractor robustness.

The keyExtractor falls back to a static string 'address_undefined' which could potentially cause key conflicts. Consider using a more unique identifier.

-    `${item.account.key}_${item.address?.address ?? 'address_undefined'}`;
+    `${item.account.key}_${item.address?.address ?? item.account.accountIndex ?? 'no_address'}`;
suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsSheet.tsx (1)

62-66: Implement toggleFavourite functionality.

The TODO comment indicates missing implementation for the favourite toggle feature.

Would you like me to help implement the toggleFavourite functionality or create an issue to track this task?

suite-native/module-trading/src/components/general/AccountSheet/AccountListItem.tsx (1)

96-106: Simplify conditional rendering logic.

The nested conditional rendering could be simplified by combining conditions.

-                        {shouldDisplayBalance && fiatValue && (
+                        {shouldDisplayBalance && !!fiatValue && (
suite-native/module-trading/src/components/general/AccountSheet/__tests__/AccountListItem.comp.test.tsx (2)

8-10: Enhance mock implementation.

The formatter mock could be more robust by handling edge cases and invalid inputs.

 jest.mock('@suite-native/formatters', () => ({
-    useFiatFromCryptoValue: ({ cryptoValue }: { cryptoValue: string }) => cryptoValue,
+    useFiatFromCryptoValue: ({ cryptoValue }: { cryptoValue: string | undefined }) => 
+        cryptoValue ? cryptoValue : '0',
 }));

33-40: Reduce test data duplication.

Consider extracting common test data setup to reduce duplication across test cases.

const createTestAccount = (overrides = {}) => ({
    key: 'btc1',
    symbol: 'btc',
    accountLabel: 'My BTC account',
    availableBalance: '10000000',
    ...overrides
} as Account);

const createTestAddress = (overrides = {}) => ({
    address: 'BTC_address',
    balance: '5000000',
    ...overrides
} as Address);

Also applies to: 49-56, 67-79, 87-98, 110-121, 129-139

suite-native/module-trading/src/components/general/TradingBottomSheetSectionList.tsx (5)

7-11: Consider constraining the type parameter U.

The type parameter U in ItemRenderConfig is unconstrained. Consider adding a constraint if there are specific requirements for the section data type.

-export type ItemRenderConfig<U> = {
+export type ItemRenderConfig<U extends Record<string, unknown>> = {

13-30: Improve documentation for omitted props.

The comment "not supported" could be more descriptive to explain why these props are not supported.

-    // not supported
+    // These props are not supported as they would conflict with the section list's internal implementation

45-68: Consider using design system tokens for SECTION_HEADER_HEIGHT.

The magic number 48 for SECTION_HEADER_HEIGHT could be derived from the design system's spacing tokens for consistency.

-const SECTION_HEADER_HEIGHT = 48 as const;
+const SECTION_HEADER_HEIGHT = spacings.sp48 as const;

70-97: Consider performance optimizations for data transformation.

The itemsData mapping could be memoized to prevent unnecessary recalculations, and the reduce accumulator type could be more explicit.

 const transformToInternalFlatListData = <T, U = undefined>(
     inputData: SectionListData<T, U>,
     noSingletonSectionHeader: boolean | undefined,
 ): ListInternalItemShape<T, U>[] =>
     inputData.reduce(
         (acc, { key, label, data, sectionData }) => {
-            const itemsData = data.map(
+            const itemsData = useMemo(() => data.map(
                 (item, index): ListInternalItemShape<T, U> => [
                     'item',
                     item,
                     {
                         isFirst: index === 0,
                         isLast: index === data.length - 1,
                         sectionData,
                     },
                 ],
-            );
+            ), [data, sectionData]);

             if (!noSingletonSectionHeader || inputData.length > 1) {
                 acc.push(['sectionHeader', label, key]);
             }

             acc.push(...itemsData);

             return acc;
         },
         [] as ListInternalItemShape<T, U>[],
     );

115-136: Consider accessibility and component extraction.

The render function could be improved by:

  1. Extracting the section header into a reusable component
  2. Adding accessibility props for better screen reader support
+const SectionHeader = ({ label }: { label: ReactNode }) => (
+    <Box paddingVertical="sp12">
+        <Text
+            variant="hint"
+            color="textSubdued"
+            accessibilityRole="header"
+            accessibilityLabel={`Section ${label}`}
+        >
+            {label}
+        </Text>
+    </Box>
+);

 const renderInternalItem = <T, U>(
     item: ListInternalItemShape<T, U>,
     renderItem: (item: T, config: ItemRenderConfig<U>) => ReactElement,
     applyStyle: ReturnType<typeof useNativeStyles>['applyStyle'],
 ): ReactElement => {
     switch (item[0]) {
         case 'sectionHeader':
-            return (
-                <Box paddingVertical="sp12">
-                    <Text variant="hint" color="textSubdued">
-                        {item[1]}
-                    </Text>
-                </Box>
-            );
+            return <SectionHeader label={item[1]} />;

         case 'item':
-            return <Box style={applyStyle(itemStyle, item[2])}>{renderItem(item[1], item[2])}</Box>;
+            return (
+                <Box
+                    style={applyStyle(itemStyle, item[2])}
+                    accessibilityRole="listitem"
+                >
+                    {renderItem(item[1], item[2])}
+                </Box>
+            );

         default:
             throw new UnreachableCaseError(item[0]);
     }
 };
suite-native/module-trading/src/hooks/__tests__/useReceiveAccountsListData.test.tsx (2)

12-85: Consider adding test cases for error handling and edge cases.

The test setup is good, but consider adding tests for:

  1. Invalid network symbols
  2. Empty or malformed account data
  3. Error cases when the store is in an invalid state
it('should handle invalid network symbols gracefully', async () => {
    const { result } = await renderUseReceiveAccountsListDataHook(
        'invalid' as NetworkSymbol,
        undefined
    );
    expect(result.current).toEqual([]);
});

it('should handle malformed account data', async () => {
    const malformedState = {
        ...defaultPreloadedState,
        wallet: {
            accounts: [{ symbol: 'btc' }] as unknown as Account[],
        },
    };
    const { result } = await renderUseReceiveAccountsListDataHook(
        'btc',
        undefined,
        malformedState
    );
    expect(result.current).toEqual([]);
});

86-118: Consider testing symbol validation more thoroughly.

Add test cases to verify that the hook properly validates and handles different network symbols.

it('should handle case-sensitive network symbols', async () => {
    const { result } = await renderUseReceiveAccountsListDataHook(
        'BTC' as NetworkSymbol,
        undefined
    );
    expect(result.current).toEqual([]);
});

it('should handle network symbol changes between BTC-like assets', async () => {
    const { result, rerender } = await renderUseReceiveAccountsListDataHook(
        'btc',
        undefined
    );
    rerender({ symbol: 'ltc' as NetworkSymbol, selectedAccount: undefined });
    expect(result.current).toEqual([]);
});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c4515b and b66e7b0.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (22)
  • suite-native/intl/src/en.ts (1 hunks)
  • suite-native/module-trading/package.json (1 hunks)
  • suite-native/module-trading/src/components/buy/BuyCard.tsx (2 hunks)
  • suite-native/module-trading/src/components/buy/ReceiveAccountPicker.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountListItem.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountSheet.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/AddressListEmptyComponent.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/AccountSheet/__tests__/AccountListItem.comp.test.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/SearchableSheetHeader.tsx (5 hunks)
  • suite-native/module-trading/src/components/general/SelectTradeableAssetButton.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/TradeableAssetButton.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetListItem.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsSheet.tsx (4 hunks)
  • suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsSheetHeader.tsx (1 hunks)
  • suite-native/module-trading/src/components/general/TradingBottomSheetSectionList.tsx (1 hunks)
  • suite-native/module-trading/src/hooks/__tests__/useReceiveAccountsListData.test.tsx (1 hunks)
  • suite-native/module-trading/src/hooks/__tests__/useSelectedAccount.test.ts (1 hunks)
  • suite-native/module-trading/src/hooks/useReceiveAccountsListData.ts (1 hunks)
  • suite-native/module-trading/src/hooks/useSelectedAccount.ts (1 hunks)
  • suite-native/module-trading/src/types.ts (2 hunks)
  • suite-native/module-trading/tsconfig.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (13)
  • suite-native/module-trading/src/types.ts
  • suite-native/module-trading/tsconfig.json
  • suite-native/module-trading/src/components/general/TradeableAssetButton.tsx
  • suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsSheetHeader.tsx
  • suite-native/module-trading/src/components/general/AccountSheet/AddressListEmptyComponent.tsx
  • suite-native/module-trading/package.json
  • suite-native/module-trading/src/components/general/AccountSheet/AccountSheetHeader.tsx
  • suite-native/module-trading/src/hooks/useSelectedAccount.ts
  • suite-native/module-trading/src/hooks/useReceiveAccountsListData.ts
  • suite-native/module-trading/src/components/general/SelectTradeableAssetButton.tsx
  • suite-native/module-trading/src/components/general/SearchableSheetHeader.tsx
  • suite-native/intl/src/en.ts
  • suite-native/module-trading/src/hooks/tests/useSelectedAccount.test.ts
🧰 Additional context used
🧠 Learnings (1)
suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsSheet.tsx (2)
Learnt from: jbazant
PR: trezor/trezor-suite#16668
File: suite-native/module-trading/src/components/TradeableAssetsSheet/TradeableAssetsSheet.tsx:0-0
Timestamp: 2025-02-04T13:18:21.530Z
Learning: The mock data arrays in `suite-native/module-trading/src/components/TradeableAssetsSheet/TradeableAssetsSheet.tsx` are intentionally used as visual stubs and will be replaced with real data fetching in future commits.
Learnt from: jbazant
PR: trezor/trezor-suite#16668
File: suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsFilterTabs.tsx:17-28
Timestamp: 2025-02-04T13:18:46.084Z
Learning: The mock data in TradeableAssetsFilterTabs.tsx is part of a visual stub and will be replaced with dynamic data in future commits.
⏰ Context from checks skipped due to timeout of 90000ms (19)
  • GitHub Check: Analyze with CodeQL (javascript)
  • GitHub Check: PR-check / node-authorizeCoinjoin cancelCoinjoinAuthorization passphrase unlockPath setBusy checkFirmwareAuthenticity keepSession cancel.test info.test resetDevice-api
  • GitHub Check: PR-check / node-override init-api-flaky
  • GitHub Check: PR-check / web-authorizeCoinjoin cancelCoinjoinAuthorization passphrase unlockPath setBusy checkFirmwareAuthenticity keepSession cancel.test info.test resetDevice-api
  • GitHub Check: PR-check / web-override init-api-flaky
  • GitHub Check: run-desktop-tests (@group=wallet, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: build-web
  • GitHub Check: run-desktop-tests (@group=other, trezor-user-env-unix)
  • GitHub Check: run-desktop-tests (@group=settings, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: run-desktop-tests (@group=device-management, trezor-user-env-unix)
  • GitHub Check: build-deploy
  • GitHub Check: run-desktop-tests (@group=suite, trezor-user-env-unix)
  • GitHub Check: Setup and Cache Dependencies
  • GitHub Check: build-web
  • GitHub Check: test
  • GitHub Check: build-deploy
  • GitHub Check: EAS Update
  • GitHub Check: prepare_android_test_app
  • GitHub Check: transport-e2e-test
🔇 Additional comments (12)
suite-native/module-trading/src/components/buy/BuyCard.tsx (1)

1-10: LGTM! Well-organized imports.

The imports are logically grouped and all appear to be used within the component.

suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetListItem.tsx (3)

10-17: LGTM! Clean and well-structured props interface.

The AssetListItemProps type provides a comprehensive and self-documenting interface for the component. The removal of positional props (isFirst, isLast) aligns with modern list rendering practices.


19-27: LGTM! Well-structured and maintainable styling.

The styling implementation follows best practices:

  • Uses constant for consistent item height
  • Leverages flexbox for robust layouts
  • Applies proper spacing and alignment

29-70: LGTM! Clean and robust component implementation.

The component demonstrates good practices:

  • Proper use of formatters for consistent data presentation
  • Graceful handling of null values
  • Clear separation of concerns in the layout structure
suite-native/module-trading/src/components/buy/ReceiveAccountPicker.tsx (3)

1-27: LGTM! Well-structured type definitions and imports.

The type definitions are clear, properly typed, and follow TypeScript best practices. The imports are minimal and logically grouped.


34-58: LGTM! Clean implementation with proper state handling.

The component effectively handles different states of account selection and follows the team's coding style by accepting only the required props.


60-88: Consider making the component more flexible and generic.

  1. The component name could be more generic as it might be used for selling or swapping in the future.
  2. The default symbol 'btc' could be made configurable through props.
-type ReceiveAccountPickerProps = {
+type AccountPickerProps = {
     selectedSymbol?: NetworkSymbol;
+    defaultSymbol?: NetworkSymbol;
 };

-export const ReceiveAccountPicker = ({ selectedSymbol }: ReceiveAccountPickerProps) => {
+export const AccountPicker = ({ selectedSymbol, defaultSymbol = 'btc' }: AccountPickerProps) => {
     // ...
     return (
         <>
             <AccountSheet
-                symbol={selectedSymbol ?? 'btc'}
+                symbol={selectedSymbol ?? defaultSymbol}
                 // ...
             />
         </>
     );
 };
suite-native/module-trading/src/components/general/AccountSheet/AccountSheet.tsx (1)

33-33: Add loading state handling.

The hook result is used with nullish coalescing but there's no handling of the loading state.

Consider implementing a loading state to improve user experience. Would you like me to help implement a loading state component?

suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsSheet.tsx (1)

73-74: 💡 Verification agent

🧩 Analysis chain

Replace mock data functions.

The mock functions for price data should be replaced with actual implementations.


🏁 Script executed:

#!/bin/bash
# Search for other mock data usage
rg "getMockFiatRate|getMockPriceChange" -A 2

Length of output: 1106


Action Required: Replace Mock Data Functions with Real Implementations

The file suite-native/module-trading/src/components/general/TradeableAssetsSheet/TradeableAssetsSheet.tsx still defines and uses mock functions for pricing data:

  • getMockPriceChange() returns a random value computed as Math.random() * 3 - 1.
  • getMockFiatRate() returns a random value computed as Math.random() * 1000.

Please update these functions with actual implementations that fetch real market price data and fiat rates, ensuring consistency with the component's expected data contracts.

⛔ Skipped due to learnings
Learnt from: jbazant
PR: trezor/trezor-suite#16668
File: suite-native/module-trading/src/components/TradeableAssetsSheet/TradeableAssetsSheet.tsx:0-0
Timestamp: 2025-02-04T13:18:21.530Z
Learning: The mock data arrays in `suite-native/module-trading/src/components/TradeableAssetsSheet/TradeableAssetsSheet.tsx` are intentionally used as visual stubs and will be replaced with real data fetching in future commits.
suite-native/module-trading/src/components/general/TradingBottomSheetSectionList.tsx (2)

99-113: LGTM! Well-implemented key extractor.

The key extractor function is well-implemented with proper type safety and exhaustive type checking using UnreachableCaseError.


138-184: LGTM! Well-implemented component with proper optimizations.

The component is well-implemented with:

  • Proper use of generics
  • Performance optimizations using useMemo
  • Accurate list size estimation
suite-native/module-trading/src/hooks/__tests__/useReceiveAccountsListData.test.tsx (1)

120-204: LGTM! Comprehensive test coverage for account selection scenarios.

The test cases for account selection scenarios are well-written and cover important use cases:

  • Non-BTC assets
  • BTC-like assets with addresses
  • Empty sections
  • Account visibility

@jbazant jbazant merged commit 24c929e into develop Feb 13, 2025
72 of 74 checks passed
@jbazant jbazant deleted the 16638-Mobile-Trade-Account-and-address-picker-stub branch February 13, 2025 16:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mobile Suite Lite issues and PRs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Mobile Trade: Account and address picker stub
2 participants