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

feat(trading): new trading selectors #17619

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from

Conversation

jbazant
Copy link
Contributor

@jbazant jbazant commented Mar 12, 2025

Description

Related Issue

Resolve

Screenshots:

@jbazant jbazant added the no-project This label is used to specify that PR doesn't need to be added to a project label Mar 12, 2025
Copy link

github-actions bot commented Mar 12, 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 trading-tradingSelectors branch from a71588f to e4eae16 Compare March 12, 2025 17:52
@jbazant jbazant requested review from vytick and adderpositive March 12, 2025 17:53
@jbazant jbazant marked this pull request as ready for review March 12, 2025 17:53
@jbazant jbazant force-pushed the trading-tradingSelectors branch from e4eae16 to 5ffa0d1 Compare March 12, 2025 17:54
Copy link

coderabbitai bot commented Mar 12, 2025

Walkthrough

The changes introduce two new JSON fixture files containing data for cryptocurrencies and platforms. The new coins.json file lists various cryptocurrencies with attributes like symbol, name, and service availability, while platforms.json provides platform information including IDs, names, and native coin symbols. The trading logic has been updated to use new utility functions defined in a newly added infoUtils.ts file. These utility functions handle the retrieval of coin information, symbols, native coin symbols, platform data, and contract addresses based on a cryptocurrency identifier. Corresponding selector functions in the trading module have been refactored to leverage these utilities, and related test suites have been added or updated to verify their functionality. Additionally, a change in the TypeScript configuration now ensures that JSON files are included during compilation.

Tip

⚡🧪 Multi-step agentic review comment chat (experimental)
  • We're introducing multi-step agentic chat in review comments. This experimental feature enhances review discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments.
    - To enable this feature, set early_access to true under in the settings.
✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ 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.
  • @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: 0

🧹 Nitpick comments (4)
suite-common/trading/src/utils/infoUtils.ts (2)

8-9: Consider handling undefined cases consistently

While this function works correctly when a coin exists, it might throw an error if getCoinInfoByCryptoId returns undefined (trying to call .toUpperCase() on undefined).

-export const getCoinSymbolByCryptoId = (coins: Coins, cryptoId: CryptoId): string | undefined =>
-    getCoinInfoByCryptoId(coins, cryptoId)?.symbol.toUpperCase();
+export const getCoinSymbolByCryptoId = (coins: Coins, cryptoId: CryptoId): string | undefined => {
+    const coinInfo = getCoinInfoByCryptoId(coins, cryptoId);
+    return coinInfo?.symbol?.toUpperCase();
+};

29-35: Potential unnecessary object creation

This function creates a new object with potentially undefined properties on every call. Consider handling the case where both inputs are undefined more efficiently.

export const getSymbolAndContractAddressByCryptoId = (
    coins: Coins | undefined,
    cryptoId: CryptoId | undefined,
): { coinSymbol: string | undefined; contractAddress: string | undefined } => {
+    if (!coins || !cryptoId) {
+        return { coinSymbol: undefined, contractAddress: undefined };
+    }
+    
+    return {
+        coinSymbol: getCoinInfoByCryptoId(coins, cryptoId)?.symbol,
+        contractAddress: parseCryptoId(cryptoId).contractAddress,
+    };
-): { coinSymbol: string | undefined; contractAddress: string | undefined } => ({
-    coinSymbol: cryptoId ? getCoinInfoByCryptoId(coins ?? {}, cryptoId)?.symbol : undefined,
-    contractAddress: cryptoId ? parseCryptoId(cryptoId).contractAddress : undefined,
-});
};
suite-common/trading/src/selectors/tradingSelectors.ts (2)

1-17: Consider importing from the main package path.

The import on line 4 references a development source (libDev), which might not be ideal for production code.

-import { NetworkSymbolExtended } from '@suite-common/wallet-config/libDev/src';
+import { NetworkSymbolExtended } from '@suite-common/wallet-config';

This would ensure you're using the production version of the module rather than a development one.


150-163: Consider consistent type annotation style.

The type annotation for this function is defined separately from the createMemoizedSelector call. While functionally correct, a more consistent approach would improve code clarity.

-export const selectSymbolAndContractAddressByCryptoId: (
-    state: TradingRootState,
-    cryptoId: CryptoId,
-) => {
-    coinSymbol: NetworkSymbolExtended | undefined;
-    contractAddress: string | undefined;
-} = createMemoizedSelector(
+export const selectSymbolAndContractAddressByCryptoId = createMemoizedSelector<
+    TradingRootState,
+    CryptoId,
+    {
+        coinSymbol: NetworkSymbolExtended | undefined;
+        contractAddress: string | undefined;
+    }
+>(

This makes the type annotations more consistent with TypeScript conventions and improves readability.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 8ddf478 and 5ffa0d1.

📒 Files selected for processing (10)
  • suite-common/trading/src/__fixtures__/coins.json (1 hunks)
  • suite-common/trading/src/__fixtures__/platforms.json (1 hunks)
  • suite-common/trading/src/hooks/useTradingInfo.ts (2 hunks)
  • suite-common/trading/src/selectors/__tests__/tradingSelectors.test.ts (1 hunks)
  • suite-common/trading/src/selectors/tradingSelectors.ts (2 hunks)
  • suite-common/trading/src/thunks/buy/handleRequestThunk.ts (3 hunks)
  • suite-common/trading/src/thunks/buy/selectQuoteThunk.ts (2 hunks)
  • suite-common/trading/src/utils/__tests__/infoUtils.test.ts (1 hunks)
  • suite-common/trading/src/utils/infoUtils.ts (1 hunks)
  • suite-common/trading/tsconfig.json (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (15)
  • GitHub Check: Type Checking
  • GitHub Check: Releases revision Checks
  • GitHub Check: Build libs for publishing
  • GitHub Check: Linting and formatting
  • GitHub Check: Unit Tests
  • GitHub Check: run-e2e-suite-desktop-tests (@group=wallet, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: run-e2e-suite-desktop-tests (@group=other, trezor-user-env-unix)
  • GitHub Check: run-e2e-suite-desktop-tests (@group=passphrase, trezor-user-env-unix)
  • GitHub Check: run-e2e-suite-desktop-tests (@group=settings, trezor-user-env-unix bitcoin-regtest)
  • GitHub Check: run-e2e-suite-desktop-tests (@group=device-management, trezor-user-env-unix)
  • GitHub Check: run-e2e-suite-desktop-tests (@group=suite, trezor-user-env-unix)
  • GitHub Check: build-web
  • GitHub Check: Analyze with CodeQL (javascript)
  • GitHub Check: prepare_android_test_app
  • GitHub Check: EAS Update
🔇 Additional comments (34)
suite-common/trading/src/__fixtures__/coins.json (1)

1-52: Well-structured cryptocurrency data object

The new coins.json file provides a well-organized structure for cryptocurrency information, including:

  • Basic cryptocurrency details (symbol, name, coingeckoId)
  • Service availability flags (buy, sell, exchange capabilities)
  • Support for both native coins and tokens (using a platform--contractAddress format for token IDs)

This seems to be a good foundation for handling multiple cryptocurrencies in the trading system.

suite-common/trading/src/utils/infoUtils.ts (3)

5-7: Simple and focused utility function

This utility function has a clear single responsibility - retrieving coin information by cryptoId. The implementation is straightforward and efficient.


11-14: Simple platform info retrieval function

Like the coin information function, this utility has a clear purpose and implementation.


16-27: Good fallback mechanism for native coin symbols

The function tries to get the native coin symbol from platform info first, then falls back to the coin info if needed. The nullish coalescing operator (??) is used appropriately here.

suite-common/trading/tsconfig.json (1)

17-18: Added necessary JSON file support

Including JSON files in the TypeScript compilation process is essential since the new implementation uses JSON files as data sources. This change ensures that TypeScript properly recognizes and processes the JSON files in the project.

suite-common/trading/src/__fixtures__/platforms.json (1)

1-12: Well-structured platforms data

The platforms.json file provides a clean structure for platform information, with consistent property naming. Both Ethereum and Base platforms use "eth" as their native coin symbol, which is correctly reflected in the data.

suite-common/trading/src/thunks/buy/selectQuoteThunk.ts (2)

11-11: Good refactor for better naming convention

The renamed import selectCoinSymbolByCryptoId follows a more consistent naming pattern than the previous cryptoIdToCoinSymbol, making it clearer that this is a selector function.


42-42: Good addition of fallback value

The null coalescing operator (??) with 'unknown' fallback is a good defensive programming practice, ensuring the code handles cases where the symbol might not be found.

suite-common/trading/src/utils/__tests__/infoUtils.test.ts (6)

1-12: Good test organization and imports

The imports are well-structured, bringing in both the necessary types from 'invity-api' and the fixture data needed for testing. All utility functions being tested are properly imported.


13-22: Clear test data setup

The btcCoinInfo constant provides a clean reference object for testing, making the test assertions more readable.


24-31: Well-written basic function tests

The tests for getCoinInfoByCryptoId and getCoinSymbolByCryptoId are clear and focused, each verifying a specific aspect of the function behavior.


33-39: Good platform selection test

The test for getPlatformsInfoByCryptoId properly verifies that the function returns the correct platform information structure.


41-50: Efficient testing with it.each

Using it.each is an excellent pattern for testing multiple scenarios efficiently. The test cases cover important variations including tokens with contract addresses.


52-84: Comprehensive edge case testing

This section thoroughly tests getSymbolAndContractAddressByCryptoId with various inputs, including edge cases like undefined inputs. Well-structured with nested describes for better organization.

suite-common/trading/src/thunks/buy/handleRequestThunk.ts (3)

13-13: Good refactor for better naming convention

The renamed import selectCoinSymbolByCryptoId follows a more consistent naming pattern, making it clearer that this is a selector function.


33-34: Simplified function implementation

The getQuotesRequest function has been simplified from an async function with await to a direct return arrow function. This makes the code more concise without changing functionality.


129-131: Good addition of fallback value

Using the null coalescing operator (??) with the original requestData.receiveCurrency as fallback is a good defensive programming practice, ensuring the code handles cases where the symbol might not be found.

suite-common/trading/src/selectors/__tests__/tradingSelectors.test.ts (7)

1-17: Well-structured imports and type definitions

The imports are organized logically, bringing in both fixture data and the selector functions being tested. The explicit import of TradingRootState helps ensure type safety in the tests.


18-42: Good test state setup

The mock state is well-structured, containing all necessary data for testing the selectors. Using spread operators with the initial state ensures the test state matches the actual application state structure.


44-54: Clear basic selector tests

The tests for selectTradingBuyQuotesRequest and selectTradingBuySelectedQuote are straightforward and verify that the selectors return the expected parts of the state.


56-71: Thorough coin data selector tests

The tests for selectCoinInfoByCryptoId and selectCoinSymbolByCryptoId effectively verify that these selectors return the correct coin information and properly formatted symbol.


73-79: Good platform selector test

The test for selectPlatformByCryptoId properly verifies that the selector returns the correct platform information structure.


81-90: Efficient testing with it.each for native coin symbols

Using it.each is an excellent pattern for testing multiple scenarios efficiently. The test cases cover important variations including tokens with contract addresses.


92-116: Comprehensive testing of symbol and contract address selector

This section thoroughly tests selectSymbolAndContractAddressByCryptoId with various inputs. The addition of a stability test (line 111-114) is particularly good practice, ensuring that the selector function is memoized correctly and returns consistent results for the same input.

suite-common/trading/src/hooks/useTradingInfo.ts (6)

26-32: Good refactoring to utility functions.

The introduction of these utility functions from infoUtils.ts improves code modularity and reusability. This approach separates the implementation details from the hooks, making the code more maintainable.


104-104: Clean implementation using utility function.

Good refactoring to leverage the utility function instead of direct access to the platforms object.


108-111: Appropriate use of utility function.

The function has been refactored to use the imported utility, which is a good improvement for maintainability.


114-114: Good simplification using utility.

The function now delegates the complexity to the utility function, making this hook easier to understand.


119-119: Clean implementation with utility.

Good refactoring to use the utility function instead of direct manipulation.


124-124: Improved implementation with utility.

Good refactoring to delegate the logic to a specialized utility function.

suite-common/trading/src/selectors/tradingSelectors.ts (4)

126-130: Well-structured selector implementation.

Good implementation using the utility function to retrieve coin information.


132-136: Clean selector implementation.

The new selector properly leverages the utility function for retrieving coin symbols.


138-142: Good addition of platform selector.

This selector cleanly retrieves platform information using the appropriate utility.


144-148: Well-implemented native coin symbol selector.

The selector correctly uses the utility to retrieve native coin symbols.

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.

Looks good 👍. Just a few minor things to tackle

@@ -39,7 +39,7 @@ export const selectQuoteThunk = createThunk(
// consent to continue (modal)
const result = await userConsent(
provider.name,
cryptoIdToCoinSymbol(getState(), quote.receiveCurrency),
selectCoinSymbolByCryptoId(getState(), quote.receiveCurrency) ?? 'unknown',
Copy link
Contributor

Choose a reason for hiding this comment

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

It probably shouldnt get here without CoinSymbol and should return few lines before, wdyt?


import { createWeakMapSelector, returnStableArrayIfEmpty } from '@suite-common/redux-utils';
import { NetworkSymbolExtended } from '@suite-common/wallet-config/libDev/src';
Copy link
Contributor

Choose a reason for hiding this comment

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

🐰 is right here

Suggested change
import { NetworkSymbolExtended } from '@suite-common/wallet-config/libDev/src';
import { NetworkSymbolExtended } from '@suite-common/wallet-config'

return allQuotes;
};
const getQuotesRequest = ({ requestData, signal }: GetQuotesRequest) =>
invityAPI.getBuyQuotes(requestData, signal);
Copy link
Contributor

Choose a reason for hiding this comment

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

❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
no-project This label is used to specify that PR doesn't need to be added to a project
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants