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): trading sign message flow #17005

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

Conversation

FreeWall
Copy link
Member

@FreeWall FreeWall commented Feb 14, 2025

Description

For 1inch fusion/fusion+, user doesn't send a swap tx, only the signature of typed data (permit) is passed to the partner via API.
New sign flow is invoked by SIGN_DATA trade status.

Related Issue

Resolve #17118

Screenshots:

image
image

@FreeWall FreeWall added the +Invity Related to Invity project label Feb 20, 2025
@FreeWall FreeWall requested a review from tomasklim February 24, 2025 10:44
@FreeWall FreeWall force-pushed the feat/trading-sign-message-flow branch from ce372cb to 473bfe2 Compare February 24, 2025 10:49
@FreeWall FreeWall marked this pull request as ready for review February 24, 2025 10:51
Copy link

github-actions bot commented Feb 24, 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

Copy link

coderabbitai bot commented Feb 24, 2025

Walkthrough

The changes involve updates to dependency versions and enhancements to the trading exchange functionality. The version of the @types/invity-api package is updated from ^1.1.3 to ^1.1.5 in multiple package.json files. A new asynchronous function, signDataAndConfirm, is introduced in the useTradingExchangeForm hook to handle the signing of Ethereum transaction data, updating the transaction status to "SIGN_DATA". The TradingExchangeStepType type is modified to include the new "SIGN_DATA" state, and a corresponding method is added to the TradingExchangeFormContextProps interface. Additionally, a new component, TradingOfferExchangeSignData, is conditionally rendered based on the exchange step in the trading offer exchange view. The logic in the trading offer send approval component is refactored to simplify the handling of quote approval. These changes encompass both backend dependency management and frontend trading interface workflows.


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between eed4134 and 9d432f6.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (7)
  • packages/suite/package.json (1 hunks)
  • packages/suite/src/hooks/wallet/trading/form/useTradingExchangeForm.ts (4 hunks)
  • packages/suite/src/types/trading/tradingForm.ts (2 hunks)
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchange.tsx (2 hunks)
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSendApproval.tsx (2 hunks)
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSignData.tsx (1 hunks)
  • suite-common/trading/package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchange.tsx
  • packages/suite/package.json
  • suite-common/trading/package.json
  • packages/suite/src/types/trading/tradingForm.ts
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSendApproval.tsx
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: build-deploy
  • GitHub Check: build-deploy
  • GitHub Check: EAS Update
  • GitHub Check: transport-e2e-test
  • GitHub Check: Setup and Cache Dependencies
  • GitHub Check: Analyze with CodeQL (javascript)
  • GitHub Check: prepare_android_test_app
  • GitHub Check: build-web
  • GitHub Check: test
  • GitHub Check: Socket Security: Pull Request Alerts
🔇 Additional comments (9)
packages/suite/src/hooks/wallet/trading/form/useTradingExchangeForm.ts (5)

429-433: LGTM - New status handling for SIGN_DATA flow.

The conditional branch for handling the 'SIGN_DATA' status follows the existing pattern for other status handling. The implementation correctly sets the exchange step and updates the necessary state.


589-599: Error message should use translations.

The error message is hardcoded without using the translation system.

-                    error: 'Cannot sign, missing data',
+                    error: <Translation id="TR_EXCHANGE_CANNOT_SIGN_MISSING_DATA" />,

600-639: Well-structured data signing implementation with proper error handling.

The implementation correctly handles different network types and signing formats. It properly manages the device connection and account path for the Ethereum network.

There's one issue to fix:

-                    error: 'Cannot sign data, unsupported network',
+                    error: <Translation id="TR_EXCHANGE_CANNOT_SIGN_UNSUPPORTED_NETWORK" />,

640-657: Verify address check before confirming trade.

The function correctly checks for the presence of the receive address before confirming the trade, preventing potential errors in the trading flow.


807-807: Properly exposing the new functionality.

The signDataAndConfirm function is correctly added to the returned object, making it accessible to components that use this hook.

packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSignData.tsx (4)

1-7: LGTM - Well-organized imports.

All necessary components and hooks are imported for the new signing functionality.


8-16: Good data validation with appropriate null guards.

The component correctly checks for the existence of required data (selectedQuote, exchange, dexTx, receive, send) before rendering, preventing potential runtime errors.


17-19: Provider name handling with fallback is well-implemented.

The code correctly extracts the provider name from exchangeInfo with a fallback to the exchange name from selectedQuote, ensuring the UI always displays meaningful information.


20-48: UI for the signature confirmation is well-structured.

The layout provides clear information to the user about the exchange details:

  1. The account from which the exchange is sent
  2. The destination address with proper formatting
  3. A confirmation button with appropriate loading and disabled states

The button triggers the signDataAndConfirm function when clicked, properly integrating with the new signing flow.

✨ Finishing Touches
  • 📝 Generate Docstrings

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.
  • @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 (2)
packages/suite/src/hooks/wallet/trading/form/useTradingExchangeForm.ts (1)

603-639:

❓ Verification inconclusive

Consider future extensibility for other networks.

The current implementation only supports Ethereum network and EIP-712 typed data. While this meets the current requirements, consider structuring the code to easily accommodate future network types.

Let's check if there are any other network types that might need support:


🏁 Script executed:

#!/bin/bash
# Search for network types in the codebase
rg -A 2 "networkType.*=.*" 

Length of output: 66988


Refactor signature handling to support additional networks

While the current implementation correctly handles Ethereum signatures via EIP-712, our codebase clearly uses various network types (e.g., Bitcoin, Cardano, Solana, Ripple). To make the trading exchange form more future-proof, consider abstracting the network-specific signing logic—perhaps using an adapter or factory approach. This would allow you to easily add or modify support for other networks without overly complicating the core conditional logic.

  • Current behavior: Only Ethereum EIP-712 typed data is supported.
  • Suggestion: Isolate the signing functionality into network-specific modules so new networks can be integrated seamlessly.
  • Benefit: Consistent extensibility with the rest of the codebase that handles multiple network types.
packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSignData.tsx (1)

9-15: Consider using TypeScript type guards for validation.

While the current validation works, using TypeScript type guards would make the validation more explicit and type-safe.

Consider this refactor:

-    if (!selectedQuote) return null;
-
-    const { exchange, dexTx, receive, send } = selectedQuote;
-    if (!exchange || !dexTx || !receive || !send) return null;
+    if (!selectedQuote || !isValidQuote(selectedQuote)) return null;
+
+    const { exchange, dexTx, receive, send } = selectedQuote;

+// Type guard function
+function isValidQuote(quote: typeof selectedQuote): quote is NonNullable<typeof selectedQuote> & {
+    exchange: NonNullable<typeof selectedQuote.exchange>;
+    dexTx: NonNullable<typeof selectedQuote.dexTx>;
+    receive: NonNullable<typeof selectedQuote.receive>;
+    send: NonNullable<typeof selectedQuote.send>;
+} {
+    return !!quote && !!quote.exchange && !!quote.dexTx && !!quote.receive && !!quote.send;
+}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a0affe1 and 473bfe2.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (7)
  • packages/suite/package.json (1 hunks)
  • packages/suite/src/hooks/wallet/trading/form/useTradingExchangeForm.ts (4 hunks)
  • packages/suite/src/types/trading/tradingForm.ts (2 hunks)
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchange.tsx (2 hunks)
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSendApproval.tsx (2 hunks)
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSignData.tsx (1 hunks)
  • suite-common/trading/package.json (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • suite-common/trading/package.json
⏰ Context from checks skipped due to timeout of 90000ms (13)
  • GitHub Check: Releases revision Checks
  • GitHub Check: Other Checks
  • GitHub Check: Type Checking
  • GitHub Check: Linting and formatting
  • GitHub Check: Build libs for publishing
  • GitHub Check: Unit Tests
  • GitHub Check: PR-check / node-authorizeCoinjoin cancelCoinjoinAuthorization passphrase unlockPath setBusy checkFirmwareAuthenticity keepSession cancel.test info.test resetDevice-api
  • 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=device-management, trezor-user-env-unix)
  • GitHub Check: prepare_android_test_app
  • GitHub Check: test
  • GitHub Check: Analyze with CodeQL (javascript)
🔇 Additional comments (9)
packages/suite/package.json (1)

129-129:

✅ Verification successful

Verify the version update of @types/invity-api.

The version bump from ^1.1.2 to ^1.1.3 might be related to new type definitions needed for the sign message flow. Let's verify the changes in this version.


🏁 Script executed:

#!/bin/bash
# Description: Check the changelog or release notes for @types/invity-api version 1.1.3

# Check npm for package details
curl -s https://registry.npmjs.org/@types/invity-api | jq '.versions["1.1.3"]'

# Check for any security advisories
gh api graphql -f query='
{
  securityVulnerabilities(first: 5, ecosystem: NPM, package: "@types/invity-api") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

Length of output: 2316


@types/invity-api Version Update Verified

  • The npm registry confirms that version 1.1.3 is published with the correct package details.
  • No security advisories were reported for this version.
  • The update aligns with the expected changes (e.g., new type definitions for the sign message flow).
packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchange.tsx (1)

13-13:

✅ Verification successful

LGTM! The changes correctly integrate the new sign data flow.

The implementation properly handles the new SIGN_DATA step by:

  1. Adding the new component import
  2. Updating the isActive condition
  3. Conditionally rendering the appropriate component based on the exchange step

Let's verify the component integration:

Also applies to: 54-54, 58-64


🏁 Script executed:

#!/bin/bash
# Description: Verify the TradingOfferExchangeSignData component implementation

# Check if the component exists and exports correctly
ast-grep --pattern 'export const TradingOfferExchangeSignData'

# Check if the component is used correctly
ast-grep --pattern 'TradingOfferExchangeSignData'

Length of output: 7304


Verified Component Integration: TradingOfferExchangeSignData is Correct

I’ve confirmed through the shell script checks that the new sign data flow is correctly integrated. Specifically:

  • Export Verification: The component is properly exported from TradingOfferExchangeSignData.tsx (starting at line 8).
  • Import & Usage: It’s correctly imported in TradingOfferExchange.tsx (line 13) and is used appropriately (e.g., at line 60, and similarly in sections 54 and 58–64).

LGTM! The changes correctly implement the SIGN_DATA step.

packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSendApproval.tsx (1)

104-114: LGTM! The refactoring improves code clarity.

The proceedToSwap function has been simplified while maintaining the same functionality:

  1. Creates a new quote object without mutation
  2. Clears the approval type if present
  3. Dispatches the updated quote
  4. Proceeds with trade confirmation
packages/suite/src/types/trading/tradingForm.ts (1)

143-144: LGTM! The type definitions properly support the new sign data flow.

The changes correctly add:

  1. SIGN_DATA as a valid exchange step type
  2. signDataAndConfirm method to the form context props interface

Also applies to: 272-272

packages/suite/src/hooks/wallet/trading/form/useTradingExchangeForm.ts (4)

590-599: LGTM! Error handling is properly implemented.

The function correctly validates the presence of required data before proceeding with the signing process.


429-433: LGTM! Status handling is consistent.

The new 'SIGN_DATA' status is handled consistently with other status types in the function.


807-807: LGTM! Function export is properly added.

The signDataAndConfirm function is correctly exposed in the hook's return object.


641-657:

❓ Verification inconclusive

Verify trade status update logic.

The function updates the trade status and triggers confirmation. However, there's a potential edge case where receiveAddress is missing.

Let's check how receiveAddress is set:


🏁 Script executed:

#!/bin/bash
# Search for assignments to receiveAddress
rg "receiveAddress.*=" 

Length of output: 670


Action: Confirm Robustness of Trade Status Handling in the Absence of receiveAddress

The current implementation updates the trade status to 'SIGN_DATA' and proceeds to dispatch the trade confirmation only if trade.receiveAddress is present. Our code search found that assignments to receiveAddress primarily occur within test files and related utility functions, which suggests that in production this property might not always be set.

Please verify the following:

  • Ensure that selectedQuote reliably provides a valid receiveAddress in all production flows.
  • Confirm that silently returning when receiveAddress is missing (without logging or error feedback) is the desired behavior, or if additional error handling should be incorporated.
packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSignData.tsx (1)

20-47: LGTM! UI implementation follows best practices.

The component:

  • Uses proper layout components
  • Handles loading and disabled states
  • Provides clear user feedback
  • Uses translations for internationalization

@FreeWall FreeWall force-pushed the feat/trading-sign-message-flow branch from 473bfe2 to 719b896 Compare February 24, 2025 12:00
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 (1)
packages/suite/src/hooks/wallet/trading/form/useTradingExchangeForm.ts (1)

589-657: Consider improving error handling and type safety.

The signDataAndConfirm function has a few areas that could be improved:

  1. The error message "Cannot sign, missing data" is not using translations (as noted in past review comments).
  2. The type check selectedQuote.signData.type === 'eip712-typed-data' could benefit from a type guard.
  3. The early return on missing receiveAddress could show an error message to improve user experience.

Consider applying these improvements:

 const signDataAndConfirm = async () => {
     if (!selectedQuote?.signData) {
         dispatch(
             notificationsActions.addToast({
                 type: 'error',
-                error: 'Cannot sign, missing data',
+                error: 'TR_CANNOT_SIGN_MISSING_DATA',
             }),
         );

         return;
     }

     dispatch(tradingCommonActions.setTradingModalAccountKey(account.key));

     let signature;
     if (
         account.networkType === 'ethereum' &&
         selectedQuote.signData.type === 'eip712-typed-data'
     ) {
         const typedData = selectedQuote?.signData
             .data as EthereumSignTypedDataMessage<EthereumSignTypedDataTypes>;

         const result = await TrezorConnect.ethereumSignTypedData({
             device,
             path: account.path,
             metamask_v4_compat: false,
             data: typedData,
         });

         if (!result.success) {
             dispatch(
                 notificationsActions.addToast({
                     type: 'sign-message-error',
                     error: result.payload.error,
                 }),
             );

             return;
         }

         signature = result.payload.signature;
     } else {
         dispatch(
             notificationsActions.addToast({
                 type: 'error',
-                error: 'Cannot sign data, unsupported network',
+                error: 'TR_CANNOT_SIGN_UNSUPPORTED_NETWORK',
             }),
         );

         return;
     }

     const trade = { ...selectedQuote };
     trade.signature = signature;
     trade.status = 'SIGN_DATA';

     if (!trade.receiveAddress) {
+        dispatch(
+            notificationsActions.addToast({
+                type: 'error',
+                error: 'TR_CANNOT_SIGN_MISSING_RECEIVE_ADDRESS',
+            }),
+        );
         return;
     }

     dispatch(
         tradingExchangeActions.saveTrade(
             trade,
             selectedAccount.account,
             new Date().toISOString(),
         ),
     );
     confirmTrade(trade.receiveAddress, undefined, trade);
 };
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 473bfe2 and 719b896.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (7)
  • packages/suite/package.json (1 hunks)
  • packages/suite/src/hooks/wallet/trading/form/useTradingExchangeForm.ts (4 hunks)
  • packages/suite/src/types/trading/tradingForm.ts (2 hunks)
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchange.tsx (2 hunks)
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSendApproval.tsx (2 hunks)
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSignData.tsx (1 hunks)
  • suite-common/trading/package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • suite-common/trading/package.json
  • packages/suite/package.json
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSignData.tsx
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSendApproval.tsx
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchange.tsx
  • packages/suite/src/types/trading/tradingForm.ts
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Socket Security: Pull Request Alerts
🔇 Additional comments (3)
packages/suite/src/hooks/wallet/trading/form/useTradingExchangeForm.ts (3)

26-29: LGTM!

The new imports from @trezor/connect are correctly added to support Ethereum typed data signing functionality.


429-433: LGTM!

The new case for 'SIGN_DATA' status is properly handled in the confirmTrade function, correctly updating the exchange step.


807-807: LGTM!

The signDataAndConfirm function is correctly exported in the hook's return object.

@FreeWall FreeWall force-pushed the feat/trading-sign-message-flow branch 2 times, most recently from 11e749b to eed4134 Compare February 26, 2025 06:49
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)
packages/suite/src/hooks/wallet/trading/form/useTradingExchangeForm.ts (1)

589-657: New signDataAndConfirm function aligns with PR objectives.

The implementation of the signDataAndConfirm function looks solid. It correctly:

  1. Validates the presence of sign data
  2. Sets the trading modal account key
  3. Handles Ethereum EIP-712 typed data signing
  4. Properly processes the signing result
  5. Updates the trade with the signature before calling confirmTrade

A couple of suggestions:

  1. Consider adding a check for trade.receiveAddress earlier in the function to avoid unnecessary operations if it's not available.
  2. The error handling for an unsuccessful result from TrezorConnect is good, but consider adding more explicit error handling for unsupported sign data types.
const signDataAndConfirm = async () => {
    if (!selectedQuote?.signData) {
        dispatch(
            notificationsActions.addToast({
                type: 'error',
                error: 'Cannot sign, missing data',
            }),
        );

        return;
    }

+   if (!selectedQuote.receiveAddress) {
+       dispatch(
+           notificationsActions.addToast({
+               type: 'error',
+               error: 'Missing receive address for signed data',
+           }),
+       );
+       return;
+   }

    dispatch(tradingCommonActions.setTradingModalAccountKey(account.key));

    let signature;
    if (
        account.networkType === 'ethereum' &&
        selectedQuote.signData.type === 'eip712-typed-data'
    ) {
        const typedData = selectedQuote?.signData
            .data as EthereumSignTypedDataMessage<EthereumSignTypedDataTypes>;

        const result = await TrezorConnect.ethereumSignTypedData({
            device,
            path: account.path,
            metamask_v4_compat: false,
            data: typedData,
        });

        if (!result.success) {
            dispatch(
                notificationsActions.addToast({
                    type: 'sign-message-error',
                    error: result.payload.error,
                }),
            );

            return;
        }

        signature = result.payload.signature;
    } else {
+       const unsupportedReason = account.networkType !== 'ethereum' 
+           ? 'unsupported network' 
+           : 'unsupported data type';
        dispatch(
            notificationsActions.addToast({
                type: 'error',
-               error: 'Cannot sign data, unsupported network',
+               error: `Cannot sign data, ${unsupportedReason}`,
            }),
        );

        return;
    }

    const trade = { ...selectedQuote };
    trade.signature = signature;
    trade.status = 'SIGN_DATA';

-   if (!trade.receiveAddress) {
-       return;
-   }

    dispatch(
        tradingExchangeActions.saveTrade(
            trade,
            selectedAccount.account,
            new Date().toISOString(),
        ),
    );
    confirmTrade(trade.receiveAddress, undefined, trade);
};
packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSignData.tsx (1)

1-48: Well-structured component for handling data signing UI.

The component is cleanly implemented with proper:

  • Type imports and usage
  • Defensive checks for required data
  • Clear UI structure with appropriate components
  • Integration with the trading form context

A couple of observations:

  1. The component correctly checks for the presence of required data and returns null if missing.
  2. It uses the provider name from exchangeInfo with a fallback to the exchange name.
  3. The button is appropriately disabled when the device is not connected.

Consider adding a brief explanation text about what signing means to improve user understanding:

<Column gap={spacings.lg} flex="1">
+   <InfoItem>
+       <Translation id="TR_EXCHANGE_SIGN_DATA_EXPLANATION" />
+   </InfoItem>
    <InfoItem label={<Translation id="TR_EXCHANGE_SEND_FROM" />}>
        <AccountLabeling account={account} />
    </InfoItem>
    ...
</Column>

This would require adding a new translation string that explains the data signing process.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 11e749b and eed4134.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (7)
  • packages/suite/package.json (1 hunks)
  • packages/suite/src/hooks/wallet/trading/form/useTradingExchangeForm.ts (4 hunks)
  • packages/suite/src/types/trading/tradingForm.ts (2 hunks)
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchange.tsx (2 hunks)
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSendApproval.tsx (2 hunks)
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSignData.tsx (1 hunks)
  • suite-common/trading/package.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • suite-common/trading/package.json
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchange.tsx
  • packages/suite/src/views/wallet/trading/common/TradingSelectedOffer/TradingOfferExchange/TradingOfferExchangeSendApproval.tsx
  • packages/suite/package.json
  • packages/suite/src/types/trading/tradingForm.ts
⏰ Context from checks skipped due to timeout of 90000ms (15)
  • 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: build-deploy
  • GitHub Check: build-deploy
  • GitHub Check: EAS Update
  • GitHub Check: test
  • GitHub Check: build-web
  • GitHub Check: transport-e2e-test
  • GitHub Check: Setup and Cache Dependencies
  • GitHub Check: Analyze with CodeQL (javascript)
  • GitHub Check: prepare_android_test_app
  • GitHub Check: Socket Security: Pull Request Alerts
  • GitHub Check: build-web
🔇 Additional comments (3)
packages/suite/src/hooks/wallet/trading/form/useTradingExchangeForm.ts (3)

26-29: Good addition of specific Ethereum types for type safety.

The addition of explicit EthereumSignTypedDataMessage and EthereumSignTypedDataTypes types from @trezor/connect improves type safety when working with typed data signing.


429-433: Properly handling the new SIGN_DATA status.

The conditional branch for handling the 'SIGN_DATA' status is correctly implemented, updating the exchange step and maintaining the flow consistency.


807-807: Good export of the new functionality.

Adding signDataAndConfirm to the returned object makes the function available to other components, maintaining a clean API.

@FreeWall FreeWall force-pushed the feat/trading-sign-message-flow branch from eed4134 to 9d432f6 Compare February 27, 2025 14:24
@tomasklim tomasklim added the release Will be included in the upcoming release. Needs to be backported to the release branch. label Feb 27, 2025
Copy link
Member

@tomasklim tomasklim left a comment

Choose a reason for hiding this comment

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

It works and I do not have problem that we show just follow instructions on device.

However, there is problem with the result of the trade.

Check you receive
Screenshot 2025-02-28 at 14 51 03

Check amounts
Screenshot 2025-02-28 at 14 51 24

Check the actual result
Screenshot 2025-02-28 at 14 52 02

const providerName =
exchangeInfo?.providerInfos[exchange]?.companyName || selectedQuote.exchange;

return (
Copy link
Member

@tomasklim tomasklim Feb 28, 2025

Choose a reason for hiding this comment

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

I like how clean this screen is.
However, a lot of users will see for the first time signing on the device.
I would love to have some banner here.

Screenshot 2025-02-28 at 15 04 20

In case we do the above, I find this ok
Screenshot 2025-02-28 at 15 07 13

@@ -268,6 +269,7 @@ export interface TradingExchangeFormContextProps
setExchangeStep: (step: TradingExchangeStepType) => void;
confirmTrade: (address: string, extraField?: string, trade?: ExchangeTrade) => Promise<boolean>;
sendTransaction: () => void;
signDataAndConfirm: () => void;
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's return Promise

new Date().toISOString(),
),
);
confirmTrade(trade.receiveAddress, undefined, trade);
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's await the Promise

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
+Invity Related to Invity project release Will be included in the upcoming release. Needs to be backported to the release branch.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Trading - sign typed data flow in DEX swaps
4 participants