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

chalabi/mobile on desktop #150

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open

chalabi/mobile on desktop #150

wants to merge 11 commits into from

Conversation

chalabi2
Copy link
Collaborator

@chalabi2 chalabi2 commented Dec 10, 2024

fixes #132

clears wallet states better so no hangups when attempting mobile connections then closing the modal

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced wallet connection process with improved error handling and user feedback.
    • Introduced a new QRCode component for generating and displaying QR codes.
    • Added QRCodeView component for wallet connection with loading and error states.
  • Bug Fixes

    • Improved logic for determining logo source based on wallet type and dark mode.
  • Chores

    • Updated dependencies in the package.json file for better performance and compatibility.
  • Refactor

    • Streamlined wallet filtering and interaction logic in the WalletList component.
    • Updated modal component for better error handling during wallet connections.

Copy link
Contributor

coderabbitai bot commented Dec 10, 2024

Walkthrough

This pull request introduces comprehensive improvements to wallet connection functionality across multiple components. The changes focus on enhancing mobile wallet support, refining QR code connection processes, and updating logo rendering logic. Key modifications include introducing new components for QR code views, updating wallet connection methods, and improving error handling during wallet connections. The changes aim to provide a more robust and user-friendly wallet connection experience across different devices and wallet types.

Changes

File Change Summary
components/react/modal.tsx Updated QR code connection handling, added state management for QR processes, enhanced error handling
components/react/views/Connecting.tsx Modified logo rendering logic using direct dark mode detection
components/react/views/Error.tsx Updated logo selection method based on wallet type and dark mode
components/react/views/NotExist.tsx Refined logo and title rendering logic
components/react/views/WalletList.tsx Enhanced wallet filtering, added mobile connection support
components/wallet.tsx Improved timeout and error handling for wallet connections
package.json Updated dependencies, added new packages for QR code and scrollbar
pages/_app.tsx Added new wallet options including Email and SMS authentication
components/react/qrCode.tsx New component for generating QR codes
components/react/views/QRCodeView.tsx New component for displaying QR code connection view
components/react/views/index.ts Updated export for QR code component

Assessment against linked issues

Objective Addressed Explanation
Enable mobile wallets on Desktop [#132]

Possibly related PRs

Suggested labels

enhancement, render

Suggested reviewers

  • fmorency

Poem

🐰 A wallet's journey, mobile and bright,
QR codes dancing in digital light,
Connections leap from screen to screen,
With rabbit magic, smooth and clean!
Connection complete, a techno delight! 🌟


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

codecov bot commented Dec 10, 2024

Codecov Report

Attention: Patch coverage is 13.23210% with 400 lines in your changes missing coverage. Please review.

Project coverage is 55.06%. Comparing base (118300c) to head (a0a7c71).

Files with missing lines Patch % Lines
components/react/views/QRCodeView.tsx 4.25% 180 Missing ⚠️
components/react/modal.tsx 26.42% 142 Missing ⚠️
components/react/views/WalletList.tsx 0.00% 41 Missing ⚠️
components/wallet.tsx 3.70% 26 Missing ⚠️
components/react/views/Error.tsx 0.00% 5 Missing ⚠️
components/react/views/Connecting.tsx 0.00% 3 Missing ⚠️
components/react/views/NotExist.tsx 0.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #150      +/-   ##
==========================================
- Coverage   56.02%   55.06%   -0.96%     
==========================================
  Files         148      148              
  Lines       14593    14916     +323     
==========================================
+ Hits         8175     8214      +39     
- Misses       6418     6702     +284     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@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: 5

🧹 Outside diff range and nitpick comments (8)
components/react/views/WalletList.tsx (1)

18-18: Consider using a constant for wallet types

The wallet type lists are hardcoded in multiple places. Consider extracting these into constants to improve maintainability.

+const SOCIAL_WALLET_TYPES = ['Google', 'Twitter', 'Apple', 'Discord', 'GitHub', 'Reddit', 'Email', 'SMS'] as const;
+const BROWSER_WALLET_TYPES = ['Keplr', 'Cosmostation', 'Leap', 'Station', 'Cosmos MetaMask Extension'] as const;

-    ['Google', 'Twitter', 'Apple', 'Discord', 'GitHub', 'Reddit', 'Email', 'SMS'].includes(
+    SOCIAL_WALLET_TYPES.includes(
       wallet.walletInfo.prettyName
     )

-    ['Keplr', 'Cosmostation', 'Leap', 'Station', 'Cosmos MetaMask Extension'].includes(
+    BROWSER_WALLET_TYPES.includes(
       wallet.walletInfo.prettyName
     )

Also applies to: 24-26

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 18-18: components/react/views/WalletList.tsx#L18
Added line #L18 was not covered by tests

components/react/modal.tsx (1)

87-94: Consider making the timeout duration configurable

The 30-second timeout for wallet connections is hardcoded. Consider making this configurable through props or environment variables.

+const WALLET_CONNECTION_TIMEOUT = process.env.NEXT_PUBLIC_WALLET_CONNECTION_TIMEOUT || 30000;

-      }, 30000);
+      }, WALLET_CONNECTION_TIMEOUT);

Also applies to: 111-111

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 87-94: components/react/modal.tsx#L87-L94
Added lines #L87 - L94 were not covered by tests

components/wallet.tsx (3)

39-64: Improved timeout handling for wallet connection.

The timeout implementation has been enhanced with proper cleanup and a longer duration. However, there are a few suggestions for improvement:

  1. Consider extracting the timeout duration to a constant
  2. Add error handling for edge cases
+const WALLET_CONNECTION_TIMEOUT = 30000; // 30 seconds
+
 export const WalletSection: React.FC<WalletSectionProps> = ({ chainName }) => {
   const { connect, openView, status, username, address } = useChain(chainName);
   const [localStatus, setLocalStatus] = useState(status);
   const timeoutRef = useRef<ReturnType<typeof setTimeout>>();

   useEffect(() => {
     if (status === WalletStatus.Connecting) {
       // Clear any existing timeout
       if (timeoutRef.current) {
         clearTimeout(timeoutRef.current);
       }

       // Set new timeout
       timeoutRef.current = setTimeout(() => {
         setLocalStatus(WalletStatus.Error);
-      }, 30000); // 30 seconds timeout
+      }, WALLET_CONNECTION_TIMEOUT);
     } else {

Additionally, the changes lack test coverage. Consider adding tests for:

  • Timeout triggering
  • Cleanup on unmount
  • Status transitions
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 39-39: components/wallet.tsx#L39
Added line #L39 was not covered by tests


[warning] 43-49: components/wallet.tsx#L43-L49
Added lines #L43 - L49 were not covered by tests


[warning] 51-51: components/wallet.tsx#L51
Added line #L51 was not covered by tests


[warning] 54-57: components/wallet.tsx#L54-L57
Added lines #L54 - L57 were not covered by tests


[warning] 60-60: components/wallet.tsx#L60
Added line #L60 was not covered by tests


[warning] 62-64: components/wallet.tsx#L62-L64
Added lines #L62 - L64 were not covered by tests


Line range hint 217-233: Enhanced error handling in IconWallet component.

The addition of WalletStatus.Error handling improves the user experience by allowing reconnection attempts. However, the code could benefit from:

  1. More descriptive error states
  2. User feedback on connection failures
     if (
       status === WalletStatus.Disconnected ||
       status === WalletStatus.Rejected ||
       status === WalletStatus.Error
-    )
-      onClick = onClickConnect;
-    else onClick = openView;
+    ) {
+      onClick = onClickConnect;
+    } else {
+      onClick = openView;
+    }
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 217-221: components/wallet.tsx#L217-L221
Added lines #L217 - L221 were not covered by tests


Line range hint 39-233: Add test coverage for wallet connection handling.

The static analysis indicates that the new code lacks test coverage. This is particularly concerning for critical wallet connection functionality.

Consider adding the following test scenarios:

  1. Wallet connection timeout
  2. Error state handling
  3. Status transitions
  4. Cleanup functionality

Would you like me to help create a test suite for these scenarios?

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 39-39: components/wallet.tsx#L39
Added line #L39 was not covered by tests


[warning] 43-49: components/wallet.tsx#L43-L49
Added lines #L43 - L49 were not covered by tests


[warning] 51-51: components/wallet.tsx#L51
Added line #L51 was not covered by tests


[warning] 54-57: components/wallet.tsx#L54-L57
Added lines #L54 - L57 were not covered by tests


[warning] 60-60: components/wallet.tsx#L60
Added line #L60 was not covered by tests


[warning] 62-64: components/wallet.tsx#L62-L64
Added lines #L62 - L64 were not covered by tests

components/react/views/Connecting.tsx (1)

46-46: Add test coverage for logo rendering logic

The new conditional logic for MetaMask logo rendering is not covered by tests.

Would you like me to help generate test cases for:

  • MetaMask wallet rendering
  • Regular wallet rendering
  • Handling of null/undefined logo props
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 46-46: components/react/views/Connecting.tsx#L46
Added line #L46 was not covered by tests

components/react/views/Error.tsx (1)

48-52: Standardize wallet name prop and improve code style

  1. The prop name currentWalletName differs from name used in other components
  2. The multiline ternary expression could be simplified

Consider these improvements:

- src={
-   currentWalletName === 'Cosmos MetaMask Extension'
-     ? '/metamask.svg'
-     : getRealLogo(logo)
- }
+ src={getWalletLogo(currentWalletName, logo)}

Also, consider renaming the prop to match other components:

- currentWalletName: string;
+ name: string;
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 48-52: components/react/views/Error.tsx#L48-L52
Added lines #L48 - L52 were not covered by tests

components/react/views/Connected.tsx (1)

Line range hint 1-150: Consider enhancing mobile wallet disconnect UX.

Given the PR's objective to improve mobile wallet handling and prevent hangups during disconnect, consider adding a loading state or feedback during the disconnect process.

  const [copied, setCopied] = useState(false);
+ const [isDisconnecting, setIsDisconnecting] = useState(false);

  // ... existing code ...

  <button
    className="w-full btn btn-disconnect-gradient rounded-lg transition duration-200 flex items-center text-white justify-center"
+   disabled={isDisconnecting}
    onClick={async () => {
+     setIsDisconnecting(true);
      try {
        await disconnect();
        onClose();
+     } catch (error) {
+       console.error('Disconnect failed:', error);
+     } finally {
+       setIsDisconnecting(false);
      }
    }}
  >
    <ArrowRightOnRectangleIcon className="w-5 h-5 mr-2" />
-   Disconnect
+   {isDisconnecting ? 'Disconnecting...' : 'Disconnect'}
  </button>
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 60-60: components/react/views/Connected.tsx#L60
Added line #L60 was not covered by tests

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 215915e and 7ff68a0.

⛔ Files ignored due to path filters (7)
  • bun.lockb is excluded by !**/bun.lockb
  • public/browser-wallet.svg is excluded by !**/*.svg
  • public/email_dark.svg is excluded by !**/*.svg
  • public/email_light.svg is excluded by !**/*.svg
  • public/metamask.svg is excluded by !**/*.svg
  • public/sms_dark.svg is excluded by !**/*.svg
  • public/sms_light.svg is excluded by !**/*.svg
📒 Files selected for processing (12)
  • components/bank/forms/sendForm.tsx (0 hunks)
  • components/groups/modals/memberManagementModal.tsx (0 hunks)
  • components/react/modal.tsx (3 hunks)
  • components/react/views/Connected.tsx (1 hunks)
  • components/react/views/Connecting.tsx (1 hunks)
  • components/react/views/Error.tsx (1 hunks)
  • components/react/views/NotExist.tsx (1 hunks)
  • components/react/views/WalletList.tsx (2 hunks)
  • components/wallet.tsx (4 hunks)
  • package.json (1 hunks)
  • pages/_app.tsx (3 hunks)
  • pages/groups/create.tsx (1 hunks)
💤 Files with no reviewable changes (2)
  • components/groups/modals/memberManagementModal.tsx
  • components/bank/forms/sendForm.tsx
✅ Files skipped from review due to trivial changes (1)
  • pages/groups/create.tsx
🧰 Additional context used
🪛 GitHub Check: codecov/patch
components/react/views/NotExist.tsx

[warning] 43-43: components/react/views/NotExist.tsx#L43
Added line #L43 was not covered by tests

components/react/views/Connecting.tsx

[warning] 46-46: components/react/views/Connecting.tsx#L46
Added line #L46 was not covered by tests

components/react/views/Connected.tsx

[warning] 60-60: components/react/views/Connected.tsx#L60
Added line #L60 was not covered by tests

components/react/views/WalletList.tsx

[warning] 18-18: components/react/views/WalletList.tsx#L18
Added line #L18 was not covered by tests


[warning] 24-26: components/react/views/WalletList.tsx#L24-L26
Added lines #L24 - L26 were not covered by tests


[warning] 30-30: components/react/views/WalletList.tsx#L30
Added line #L30 was not covered by tests


[warning] 32-40: components/react/views/WalletList.tsx#L32-L40
Added lines #L32 - L40 were not covered by tests


[warning] 52-52: components/react/views/WalletList.tsx#L52
Added line #L52 was not covered by tests


[warning] 56-86: components/react/views/WalletList.tsx#L56-L86
Added lines #L56 - L86 were not covered by tests

components/react/views/Error.tsx

[warning] 48-52: components/react/views/Error.tsx#L48-L52
Added lines #L48 - L52 were not covered by tests

components/react/modal.tsx

[warning] 81-81: components/react/modal.tsx#L81
Added line #L81 was not covered by tests


[warning] 87-94: components/react/modal.tsx#L87-L94
Added lines #L87 - L94 were not covered by tests


[warning] 101-101: components/react/modal.tsx#L101
Added line #L101 was not covered by tests


[warning] 110-110: components/react/modal.tsx#L110
Added line #L110 was not covered by tests


[warning] 117-119: components/react/modal.tsx#L117-L119
Added lines #L117 - L119 were not covered by tests


[warning] 147-148: components/react/modal.tsx#L147-L148
Added lines #L147 - L148 were not covered by tests


[warning] 151-151: components/react/modal.tsx#L151
Added line #L151 was not covered by tests

components/wallet.tsx

[warning] 39-39: components/wallet.tsx#L39
Added line #L39 was not covered by tests


[warning] 43-49: components/wallet.tsx#L43-L49
Added lines #L43 - L49 were not covered by tests


[warning] 51-51: components/wallet.tsx#L51
Added line #L51 was not covered by tests


[warning] 54-57: components/wallet.tsx#L54-L57
Added lines #L54 - L57 were not covered by tests


[warning] 60-60: components/wallet.tsx#L60
Added line #L60 was not covered by tests


[warning] 62-64: components/wallet.tsx#L62-L64
Added lines #L62 - L64 were not covered by tests


[warning] 217-221: components/wallet.tsx#L217-L221
Added lines #L217 - L221 were not covered by tests


[warning] 230-233: components/wallet.tsx#L230-L233
Added lines #L230 - L233 were not covered by tests

🪛 Biome (1.9.4)
components/react/modal.tsx

[error] 147-147: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)


[error] 151-151: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)

🔇 Additional comments (6)
package.json (1)

36-36: Verify the dependency version for security concerns

The newly added @cosmos-kit/cosmos-extension-metamask dependency should be verified for security vulnerabilities.

✅ Verification successful

The dependency version is secure and up-to-date

The verification shows that:

  • No security vulnerabilities were found for @cosmos-kit/cosmos-extension-metamask
  • The specified version ^0.12.1 matches the latest version available on NPM
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for security advisories and latest versions
gh api graphql -f query='
{
  securityVulnerabilities(first: 5, ecosystem: NPM, package: "@cosmos-kit/cosmos-extension-metamask") {
    nodes {
      advisory {
        summary
        severity
        publishedAt
      }
      vulnerableVersionRange
      firstPatchedVersion {
        identifier
      }
    }
  }
}'

# Check NPM for latest versions
curl -s https://registry.npmjs.org/@cosmos-kit/cosmos-extension-metamask | jq '.["dist-tags"].latest'

Length of output: 482

components/react/views/WalletList.tsx (1)

73-84: Review the mobile wallet connection logic

The mobile wallet connection implementation looks good, but consider adding error handling for cases where getMobileWalletName returns undefined.

✅ Verification successful

The code shows that error handling is already implemented through the nullish coalescing operator || in onWalletClicked(getMobileWalletName(prettyName) || ''). This ensures that even if getMobileWalletName returns undefined, an empty string is passed to onWalletClicked. Let me verify how onWalletClicked handles empty strings.


Let me check the implementation of onWalletClicked to see how it handles the wallet name parameter.


Mobile wallet connection implementation is properly handled

The current implementation is safe and includes proper error handling:

  • Empty string fallback is provided via getMobileWalletName(prettyName) || ''
  • onWalletClicked safely handles the wallet name by:
    • Using optional chaining when accessing the wallet repository (walletRepo?.getWallet(name))
    • Checking wallet existence before operations (wallet?.isWalletNotExist)
    • Including timeout handling for connection attempts
    • Proper state management for different wallet modes and error cases
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for error handling patterns in mobile wallet connections
rg -A 5 "getMobileWalletName" 

Length of output: 1137


Script:

#!/bin/bash
# Check how onWalletClicked handles empty strings
ast-grep --pattern 'onWalletClicked($$$)'

Length of output: 643


Script:

#!/bin/bash
# Find onWalletClicked implementation
ast-grep --pattern 'const onWalletClicked = $_'

Length of output: 1800

components/react/modal.tsx (1)

79-83: LGTM: Proper cleanup of wallet connection state

The useEffect hook correctly handles wallet disconnection when the modal is closed, preventing hanging connections.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 81-81: components/react/modal.tsx#L81
Added line #L81 was not covered by tests

pages/_app.tsx (1)

181-181: LGTM! Wallet integration looks good.

The combination of web3auth wallets, standard wallets, and MetaMask extension wallets provides a comprehensive wallet selection for users, aligning with the PR objective of enabling mobile wallets on desktop.

components/react/views/Connecting.tsx (1)

46-46: 🛠️ Refactor suggestion

Consider improving the MetaMask detection logic

The current implementation has several potential improvements:

  1. The hardcoded string comparison 'Cosmos MetaMask Extension' is fragile and could break if the name changes
  2. The static path '/metamask.svg' could be centralized in a constants file

Consider this refactor:

+ // Add to constants/wallets.ts
+ export const WALLET_TYPES = {
+   METAMASK: 'Cosmos MetaMask Extension'
+ } as const;
+ export const WALLET_LOGOS = {
+   METAMASK: '/metamask.svg'
+ } as const;

- src={name === 'Cosmos MetaMask Extension' ? '/metamask.svg' : getRealLogo(logo)}
+ src={name === WALLET_TYPES.METAMASK ? WALLET_LOGOS.METAMASK : getRealLogo(logo)}

Also, verify the MetaMask logo exists:

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 46-46: components/react/views/Connecting.tsx#L46
Added line #L46 was not covered by tests

components/react/views/Connected.tsx (1)

60-60: Verify MetaMask logo handling across wallet types.

The conditional logo handling for Cosmos MetaMask Extension aligns with the PR's objective of supporting mobile wallets on desktop. However, let's verify the consistency of this implementation across different wallet scenarios.

✅ Verification successful

MetaMask logo handling is consistent across wallet views

The verification confirms:

  • The metamask.svg file exists in the correct location (public/)
  • The MetaMask logo conditional logic is consistently implemented across all wallet state views:
    • Connected view (Connected.tsx)
    • Connecting view (Connecting.tsx)
    • Not Exist view (NotExist.tsx)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify consistent MetaMask logo handling across components
# and ensure the logo file exists

# Check if metamask.svg exists in public directory
fd -t f "metamask.svg" public/

# Check for similar logo handling patterns across components
rg -A 2 "name === 'Cosmos MetaMask Extension'" components/

Length of output: 972

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 60-60: components/react/views/Connected.tsx#L60
Added line #L60 was not covered by tests

Comment on lines 147 to 148
if (currentWalletData!?.mode === 'wallet-connect') {
subtitle = `Approve ${currentWalletData!.prettyName} connection request on your mobile device.`;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove unnecessary non-null assertions

The code uses unnecessary non-null assertions (!). Consider using optional chaining instead.

-        if (currentWalletData!?.mode === 'wallet-connect') {
-          subtitle = `Approve ${currentWalletData!.prettyName} connection request on your mobile device.`;
+        if (currentWalletData?.mode === 'wallet-connect') {
+          subtitle = `Approve ${currentWalletData.prettyName} connection request on your mobile device.`;
         } else {
-          subtitle = `Open the ${currentWalletData!?.prettyName} browser extension to connect your wallet.`;
+          subtitle = `Open the ${currentWalletData?.prettyName} browser extension to connect your wallet.`;
         }

Also applies to: 151-151

🧰 Tools
🪛 Biome (1.9.4)

[error] 147-147: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)

🪛 GitHub Check: codecov/patch

[warning] 147-148: components/react/modal.tsx#L147-L148
Added lines #L147 - L148 were not covered by tests

pages/_app.tsx Outdated
Comment on lines 149 to 158
{
provider: 'email_passwordless',
name: 'Email',
logo: '/email',
},
{
provider: 'sms_passwordless',
name: 'SMS',
logo: '/sms',
},
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Web3Auth configuration requires additional setup

The verification reveals missing critical configuration:

  • Web3Auth dependencies (@web3auth/base and @web3auth/modal) are not present in package.json
  • Required NEXT_PUBLIC_WEB3_CLIENT_ID environment variable is not configured, though it's referenced in the code
  • While email and SMS providers are defined in the UI configuration, the underlying Web3Auth setup appears incomplete

To enable email and SMS authentication:

  • Add required Web3Auth dependencies to package.json
  • Configure NEXT_PUBLIC_WEB3_CLIENT_ID in the environment
  • Verify Web3Auth Modal initialization with proper provider configuration
🔗 Analysis chain

Verify email and SMS authentication configuration.

The addition of email and SMS authentication methods enhances accessibility, but requires proper configuration to function correctly.


Let me gather more information about the Web3Auth configuration and usage in the codebase.


Let me check the Web3Auth configuration and initialization code to understand how email and SMS providers are set up.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify Web3Auth configuration for email and SMS providers
# Check for required environment variables and configuration files

# Check if Web3Auth client ID is configured
if ! grep -q "NEXT_PUBLIC_WEB3_CLIENT_ID" .env*; then
  echo "Warning: Web3Auth client ID environment variable not found"
fi

# Check Web3Auth configuration in package.json
if [ -f "package.json" ]; then
  jq '.dependencies["@web3auth/base"]' package.json
  jq '.dependencies["@web3auth/modal"]' package.json
fi

Length of output: 351


Script:

#!/bin/bash
# Search for Web3Auth related imports and configurations
echo "=== Searching for Web3Auth related imports ==="
rg "@web3auth" -A 3

echo -e "\n=== Searching for Web3Auth configuration patterns ==="
ast-grep --pattern 'new Web3Auth($$$)'

echo -e "\n=== Checking for environment variable usage ==="
rg "NEXT_PUBLIC_WEB3" -A 2

echo -e "\n=== Looking for configuration files ==="
fd -e config.js -e config.ts

Length of output: 882


Script:

#!/bin/bash
# Check Web3Auth configuration and provider setup
echo "=== Checking Web3Auth Modal configuration ==="
rg -A 10 "new Web3Modal" 

echo -e "\n=== Looking for provider configurations ==="
rg "provider.*['\"]email_passwordless['\"]|provider.*['\"]sms_passwordless['\"]" -A 5

echo -e "\n=== Checking authentication related functions ==="
ast-grep --pattern 'async function $_($$_) {
  $$$
  login($$$)
  $$$
}'

Length of output: 923

@@ -40,7 +40,7 @@
</div>
<div className="flex flex-col w-full h-full py-6 mt-4 sm:px-8">
<img
src={getRealLogo(logo)}
src={name === 'Cosmos MetaMask Extension' ? '/metamask.svg' : getRealLogo(logo)}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Extract shared wallet logo logic

The logo rendering logic is duplicated across multiple components (Connecting, NotExist, Error).

Consider creating a shared utility:

+ // Add to utils/wallet.ts
+ export const getWalletLogo = (name: string, logo: string): string => {
+   return name === WALLET_TYPES.METAMASK ? WALLET_LOGOS.METAMASK : getRealLogo(logo);
+ };

- src={name === 'Cosmos MetaMask Extension' ? '/metamask.svg' : getRealLogo(logo)}
+ src={getWalletLogo(name, logo)}

This would improve maintainability and ensure consistent behavior across components.

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 43-43: components/react/views/NotExist.tsx#L43
Added line #L43 was not covered by tests

@@ -57,7 +57,7 @@
<Image
height={0}
width={0}
src={getRealLogo(logo)}
src={name === 'Cosmos MetaMask Extension' ? '/metamask.svg' : getRealLogo(logo)}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add test coverage for MetaMask logo conditional.

The new conditional logic for MetaMask logo handling is currently not covered by tests.

Consider adding test cases to verify:

  1. Logo rendering for Cosmos MetaMask Extension
  2. Logo rendering for other wallet types
describe('Connected component', () => {
  it('should render MetaMask logo for Cosmos MetaMask Extension', () => {
    render(<Connected name="Cosmos MetaMask Extension" logo="some-logo.svg" {...defaultProps} />);
    expect(screen.getByAltText('Cosmos MetaMask Extension')).toHaveAttribute('src', '/metamask.svg');
  });

  it('should render wallet logo for other wallets', () => {
    const logo = 'wallet-logo.svg';
    render(<Connected name="Other Wallet" logo={logo} {...defaultProps} />);
    expect(screen.getByAltText('Other Wallet')).toHaveAttribute('src', getRealLogo(logo));
  });
});
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 60-60: components/react/views/Connected.tsx#L60
Added line #L60 was not covered by tests

@fmorency
Copy link
Contributor

Hey @chalabi2, how does one test this feature on Manifest?

Copy link
Contributor

@fmorency fmorency left a comment

Choose a reason for hiding this comment

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

Awesome!

@chalabi2 can you fix the conflicts, please?

I push a fix for the conflicts. Please review.

Copy link
Contributor

@fmorency fmorency left a comment

Choose a reason for hiding this comment

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

Hey @chalabi2, is there any way to test this? I wasn't able to test it using a local build... The QR code never gets read by the app. I tried Keplr, Leap & Cosmostation.

Copy link
Contributor

@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)
components/react/modal.tsx (2)

88-94: Consider enhancing error feedback for timeout scenarios

The timeout mechanism is well-implemented, but the user experience could be improved by providing more specific feedback when a connection times out.

Consider this enhancement:

 const timeoutId = setTimeout(() => {
   const wallet = walletRepo?.getWallet(name);
   if (wallet?.walletStatus === WalletStatus.Connecting) {
     wallet.disconnect();
-    setCurrentView(ModalView.Error);
+    setCurrentView(ModalView.Error);
+    // Add a custom error message for timeout
+    wallet.setError(new Error('Connection attempt timed out after 30 seconds'));
   }
 }, 30000);

Also applies to: 102-102, 112-112


Line range hint 80-120: Well-structured implementation of wallet state management

The combination of the timeout mechanism, modal closure handling, and connection state cleanup forms a robust solution for managing wallet connections. This implementation effectively prevents hanging states and provides a better user experience, particularly for mobile wallet interactions on desktop platforms.

Consider documenting these timeout and cleanup behaviors in the component's documentation to help future maintainers understand the implemented safeguards.

components/wallet.tsx (2)

40-65: Approve timeout management changes with UX improvement suggestions

The timeout management implementation is technically sound with proper cleanup. However, consider enhancing the user experience when timeouts occur.

Consider adding user feedback when the connection times out:

 timeoutRef.current = setTimeout(() => {
+  // Show a user-friendly error message
+  const errorMessage = 'Mobile wallet connection timed out. Please try again.';
+  // You can dispatch this to your notification system
+  console.error(errorMessage);
   setLocalStatus(WalletStatus.Error);
 }, 30000);

Line range hint 218-234: Approve click handler changes with error handling suggestions

The addition of WalletStatus.Error to the click handler conditions improves the wallet reconnection flow. However, the error state could be more informative.

Consider enhancing error state handling:

 className={`flex justify-center items-center w-8 h-8 hover:text-primary duration-200 ease-in-out ${
-  status === WalletStatus.Connected ? 'cursor-default' : 'cursor-pointer'
+  status === WalletStatus.Connected ? 'cursor-default' : 
+  status === WalletStatus.Error ? 'cursor-pointer text-error' : 'cursor-pointer'
 }`}

Also, consider adding a tooltip for error states to guide users:

+{status === WalletStatus.Error && (
+  <div className="absolute top-full mt-2 text-sm text-error">
+    Connection failed. Click to retry.
+  </div>
+)}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 7ff68a0 and 2a0dfa4.

⛔ Files ignored due to path filters (1)
  • bun.lockb is excluded by !**/bun.lockb
📒 Files selected for processing (7)
  • components/bank/forms/sendForm.tsx (0 hunks)
  • components/groups/modals/memberManagementModal.tsx (0 hunks)
  • components/react/modal.tsx (3 hunks)
  • components/react/views/WalletList.tsx (2 hunks)
  • components/wallet.tsx (4 hunks)
  • package.json (1 hunks)
  • pages/_app.tsx (3 hunks)
💤 Files with no reviewable changes (2)
  • components/bank/forms/sendForm.tsx
  • components/groups/modals/memberManagementModal.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • package.json
  • components/react/views/WalletList.tsx
  • pages/_app.tsx
🧰 Additional context used
🪛 Biome (1.9.4)
components/react/modal.tsx

[error] 148-148: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)


[error] 152-152: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)

🔇 Additional comments (4)
components/react/modal.tsx (3)

118-120: LGTM: Consistent cleanup implementation

The disconnection logic in onCloseModal is well-implemented and consistent with the cleanup strategy in useEffect.


148-152: Remove unnecessary non-null assertions

The code uses unnecessary non-null assertions (!). Consider using optional chaining instead.

🧰 Tools
🪛 Biome (1.9.4)

[error] 148-148: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)


[error] 152-152: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)


80-84: LGTM: Proper cleanup of connecting state

The useEffect hook correctly handles wallet disconnection when the modal is closed during the connecting state, preventing hanging connections.

Let's verify the cleanup behavior:

✅ Verification successful

Cleanup implementation is consistent and well-integrated

The verification shows that the wallet disconnection logic in the useEffect hook is properly implemented and aligns with the codebase's patterns:

  • The same WalletStatus.Connecting check is consistently used across the codebase
  • The disconnect cleanup is implemented in multiple relevant places (modal close, timeout, and useEffect)
  • The implementation follows the same pattern as other wallet status handling in the components
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for similar cleanup patterns in other modal components
ast-grep --pattern 'useEffect(() => {
  if (!$isOpen && $wallet?.$status === $CONNECTING) {
    $wallet.$disconnect();
  }
}, [$deps])'

Length of output: 137


Script:

#!/bin/bash
# Let's try a broader search for wallet disconnection patterns
rg "disconnect.*wallet|wallet.*disconnect" -A 2 -B 2

# Also search for similar useEffect cleanup patterns
rg "useEffect.*isOpen.*disconnect" -A 2 -B 2

# And check for WalletStatus usage
rg "WalletStatus\.Connecting" -A 2 -B 2

Length of output: 2558

components/wallet.tsx (1)

1-1: Verify mobile wallet detection and handling

Let's verify the implementation handles mobile wallets correctly on desktop platforms.

✅ Verification successful

Let me try a different search strategy to verify the mobile wallet handling implementation.


Based on the search results, I can now provide a final response:

Mobile wallet handling is properly implemented

The codebase shows comprehensive mobile wallet detection and handling:

  • Proper device detection through useDeviceDetect hook using both modern userAgentData and fallback userAgent checks
  • Conditional wallet connection flows for mobile vs desktop:
    • Mobile users are directed to the Connecting view
    • Desktop users see QR code for WalletConnect
  • Appropriate timeout handling (30s) for wallet connections
  • Mobile-specific UI adaptations throughout the application
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for mobile wallet related code and configurations
echo "Searching for mobile wallet related code..."
rg -l "mobile.*wallet|wallet.*mobile" --type ts --type tsx

# Search for wallet detection logic
echo "Searching for wallet detection logic..."
ast-grep --pattern 'if ($CONDITION) {
  $$$
  mobile
  $$$
}'

# Search for related test files
echo "Searching for wallet-related test files..."
fd -e test.tsx -e test.ts -e spec.tsx -e spec.ts wallet

Length of output: 491


Script:

#!/bin/bash
# Search for mobile-related conditions in TypeScript/React files
echo "Searching for mobile detection patterns..."
rg "isMobile|mobile.*detect|detect.*mobile" --type typescript --type-add 'typescript:*.{ts,tsx}'

# Look for wallet connection logic
echo "Searching for wallet connection handling..."
rg "connect.*wallet|wallet.*connect" -A 5 --type typescript --type-add 'typescript:*.{ts,tsx}'

# Search for user agent or device detection
echo "Searching for device detection..."
rg "userAgent|navigator\." --type typescript --type-add 'typescript:*.{ts,tsx}'

Length of output: 10410

Copy link
Contributor

@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: 6

🧹 Nitpick comments (7)
components/react/qrCode.tsx (1)

38-55: Avoid overcomplicating corner square drawing logic.
The nested loop for rendering the corner squares (lines 38–55) is functional but somewhat difficult to parse, especially with custom border radius logic for each iteration. Consider extracting the corner square rendering into a helper function to improve readability and maintainability.

Example refactor:

-    qrList.forEach(({ x, y }) => {
-      const x1 = (matrix.length - 7) * cellSize * x;
-      const y1 = (matrix.length - 7) * cellSize * y;
-      for (let i = 0; i < 3; i++) {
-        dots.push(
-          <rect
-            fill={i % 2 !== 0 ? 'white' : 'black'}
-            height={cellSize * (7 - i * 2)}
-            key={`${i}-${x}-${y}`}
-            rx={(i - 2) * -5 + (i === 0 ? 2 : 0)}
-            ry={(i - 2) * -5 + (i === 0 ? 2 : 0)}
-            width={cellSize * (7 - i * 2)}
-            x={x1 + cellSize * i}
-            y={y1 + cellSize * i}
-          />
-        );
-      }
-    });
+    const renderCornerSquare = (cornerX: number, cornerY: number) => {
+      const startX = (matrix.length - 7) * cellSize * cornerX;
+      const startY = (matrix.length - 7) * cellSize * cornerY;
+      for (let i = 0; i < 3; i++) {
+        dots.push(
+          <rect
+            key={`corner-${i}-${cornerX}-${cornerY}`}
+            fill={i % 2 !== 0 ? 'white' : 'black'}
+            width={cellSize * (7 - i * 2)}
+            height={cellSize * (7 - i * 2)}
+            x={startX + cellSize * i}
+            y={startY + cellSize * i}
+            rx={(i - 2) * -5 + (i === 0 ? 2 : 0)}
+            ry={(i - 2) * -5 + (i === 0 ? 2 : 0)}
+          />
+        );
+      }
+    };
+    qrList.forEach(({ x, y }) => renderCornerSquare(x, y));
components/react/views/QRCodeView.tsx (2)

48-48: Suggestion: Use optional chaining to reduce potential undefined references.
On line 48, we can simplify by using optional chaining for accessing wallet?.message.

- const hasError = qrUrl?.state === State.Error || (wallet?.message && wallet.message.includes('No matching key.'));
+ const hasError = qrUrl?.state === State.Error || wallet?.message?.includes('No matching key.');
🧰 Tools
🪛 Biome (1.9.4)

[error] 48-48: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


152-158: Remove unnecessary Fragment to avoid redundancy.
Static analysis suggests removing the fragment (lines 152–158) since there’s only a single child, and the adjacent HTML element can exist without an extra fragment.

- {status === 'pending' && (
-   <>
-     <QRCodeLoader
-       message={'Generating Qr code...'}
-       logoUrl={wallet?.walletInfo.logo?.toString() ?? ''}
-       logoSize={40}
-     />
-   </>
- )}
+ {status === 'pending' && (
+   <QRCodeLoader
+     message={'Generating Qr code...'}
+     logoUrl={wallet?.walletInfo.logo?.toString() ?? ''}
+     logoSize={40}
+   />
+ )}
🧰 Tools
🪛 Biome (1.9.4)

[error] 152-158: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

components/react/views/WalletList.tsx (3)

75-86: Enhance mobile wallet connection UX.

The mobile wallet connection UI could be improved:

  1. Add loading state during connection
  2. Provide feedback on connection status
  3. Handle connection failures gracefully

Consider adding a loading state and error handling:

 <div
   onClick={e => {
     e.stopPropagation();
+    setIsConnecting(true);
     onWalletClicked(getMobileWalletName(prettyName) || '', true);
   }}
   className="p-1.5 rounded-lg dark:hover:bg-[#ffffff1a] hover:bg-[#0000000d] dark:bg-[#ffffff37] bg-[#d5d5e4]  transition cursor-pointer"
   title={`Connect with ${prettyName} Mobile`}
 >
-  <img src={getRealLogo('/sms')} alt="mobile" className="w-5 h-5" />
+  {isConnecting ? (
+    <div className="w-5 h-5 animate-spin rounded-full border-2 border-primary border-t-transparent" />
+  ) : (
+    <img src={getRealLogo('/sms')} alt="mobile" className="w-5 h-5" />
+  )}
 </div>

13-13: Document the isMobileConnect parameter.

The new isMobileConnect parameter in onWalletClicked should be documented to explain its purpose and usage.

Add JSDoc documentation:

-  onWalletClicked: (name: string, isMobileConnect?: boolean) => void;
+  /**
+   * Callback when a wallet is selected
+   * @param name - The name of the selected wallet
+   * @param isMobileConnect - If true, indicates this is a mobile wallet connection
+   */
+  onWalletClicked: (name: string, isMobileConnect?: boolean) => void;
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 13-13: components/react/views/WalletList.tsx#L13
Added line #L13 was not covered by tests


20-22: Consider using constants for wallet types.

The wallet type arrays are hardcoded in multiple places. Consider extracting them into constants for better maintainability.

+const SOCIAL_WALLETS = ['Google', 'Twitter', 'Apple', 'Discord', 'GitHub', 'Reddit', 'Email', 'SMS'] as const;
+const BROWSER_WALLETS = ['Keplr', 'Cosmostation', 'Leap', 'Station', 'Cosmos MetaMask Extension'] as const;
+const MOBILE_WALLETS = ['Keplr Mobile', 'Cosmostation Mobile', 'Leap Mobile'] as const;

 const social = wallets.filter(wallet =>
-  ['Google', 'Twitter', 'Apple', 'Discord', 'GitHub', 'Reddit', 'Email', 'SMS'].includes(
+  SOCIAL_WALLETS.includes(
     wallet.walletInfo.prettyName
   )
 );

Also applies to: 26-28, 32-32

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 20-20: components/react/views/WalletList.tsx#L20
Added line #L20 was not covered by tests

components/react/modal.tsx (1)

182-191: Centralize wallet disconnection logic

The wallet disconnection logic is spread across multiple handlers. Consider centralizing this logic to ensure consistent cleanup.

Extract the disconnection logic into a shared function:

+ const disconnectWallet = (wallet?: ChainWalletBase) => {
+   if (wallet?.walletStatus === WalletStatus.Connecting) {
+     wallet.disconnect();
+   }
+ };

  useEffect(() => {
    if (!isOpen) {
-     if (qrWallet?.walletStatus === WalletStatus.Connecting) {
-       qrWallet.disconnect();
-       setQRWallet(undefined);
-     }
+     disconnectWallet(qrWallet);
+     setQRWallet(undefined);
      setQRState(State.Init);
      setQrMessage('');
    }
  }, [isOpen, qrWallet]);

Also applies to: 194-198, 200-206

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 185-186: components/react/modal.tsx#L185-L186
Added lines #L185 - L186 were not covered by tests

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 2a0dfa4 and d5ee8ec.

⛔ Files ignored due to path filters (1)
  • bun.lockb is excluded by !**/bun.lockb
📒 Files selected for processing (12)
  • components/react/modal.tsx (7 hunks)
  • components/react/qrCode.tsx (1 hunks)
  • components/react/views/Connected.tsx (1 hunks)
  • components/react/views/Connecting.tsx (1 hunks)
  • components/react/views/Error.tsx (1 hunks)
  • components/react/views/NotExist.tsx (1 hunks)
  • components/react/views/QRCode.tsx (0 hunks)
  • components/react/views/QRCodeView.tsx (1 hunks)
  • components/react/views/WalletList.tsx (2 hunks)
  • components/react/views/index.ts (1 hunks)
  • package.json (3 hunks)
  • pages/_app.tsx (3 hunks)
💤 Files with no reviewable changes (1)
  • components/react/views/QRCode.tsx
✅ Files skipped from review due to trivial changes (1)
  • components/react/views/index.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • pages/_app.tsx
  • package.json
🧰 Additional context used
🪛 Biome (1.9.4)
components/react/views/QRCodeView.tsx

[error] 48-48: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 152-158: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

components/react/modal.tsx

[error] 6-6: Do not shadow the global "Error" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)


[error] 232-232: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)


[error] 236-236: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)

🪛 GitHub Check: codecov/patch
components/react/views/QRCodeView.tsx

[warning] 14-31: components/react/views/QRCodeView.tsx#L14-L31
Added lines #L14 - L31 were not covered by tests


[warning] 35-175: components/react/views/QRCodeView.tsx#L35-L175
Added lines #L35 - L175 were not covered by tests

components/react/modal.tsx

[warning] 63-66: components/react/modal.tsx#L63-L66
Added lines #L63 - L66 were not covered by tests


[warning] 88-98: components/react/modal.tsx#L88-L98
Added lines #L88 - L98 were not covered by tests


[warning] 100-100: components/react/modal.tsx#L100
Added line #L100 was not covered by tests


[warning] 106-106: components/react/modal.tsx#L106
Added line #L106 was not covered by tests


[warning] 111-112: components/react/modal.tsx#L111-L112
Added lines #L111 - L112 were not covered by tests


[warning] 115-175: components/react/modal.tsx#L115-L175
Added lines #L115 - L175 were not covered by tests


[warning] 185-186: components/react/modal.tsx#L185-L186
Added lines #L185 - L186 were not covered by tests


[warning] 194-196: components/react/modal.tsx#L194-L196
Added lines #L194 - L196 were not covered by tests


[warning] 200-204: components/react/modal.tsx#L200-L204
Added lines #L200 - L204 were not covered by tests


[warning] 232-233: components/react/modal.tsx#L232-L233
Added lines #L232 - L233 were not covered by tests


[warning] 236-236: components/react/modal.tsx#L236
Added line #L236 was not covered by tests


[warning] 252-252: components/react/modal.tsx#L252
Added line #L252 was not covered by tests


[warning] 290-293: components/react/modal.tsx#L290-L293
Added lines #L290 - L293 were not covered by tests

components/react/views/Connected.tsx

[warning] 62-64: components/react/views/Connected.tsx#L62-L64
Added lines #L62 - L64 were not covered by tests

components/react/views/Connecting.tsx

[warning] 48-50: components/react/views/Connecting.tsx#L48-L50
Added lines #L48 - L50 were not covered by tests

components/react/views/Error.tsx

[warning] 50-56: components/react/views/Error.tsx#L50-L56
Added lines #L50 - L56 were not covered by tests

components/react/views/NotExist.tsx

[warning] 45-47: components/react/views/NotExist.tsx#L45-L47
Added lines #L45 - L47 were not covered by tests

components/react/views/WalletList.tsx

[warning] 13-13: components/react/views/WalletList.tsx#L13
Added line #L13 was not covered by tests


[warning] 20-20: components/react/views/WalletList.tsx#L20
Added line #L20 was not covered by tests


[warning] 26-28: components/react/views/WalletList.tsx#L26-L28
Added lines #L26 - L28 were not covered by tests


[warning] 32-32: components/react/views/WalletList.tsx#L32
Added line #L32 was not covered by tests


[warning] 35-41: components/react/views/WalletList.tsx#L35-L41
Added lines #L35 - L41 were not covered by tests


[warning] 53-53: components/react/views/WalletList.tsx#L53
Added line #L53 was not covered by tests


[warning] 57-89: components/react/views/WalletList.tsx#L57-L89
Added lines #L57 - L89 were not covered by tests

🪛 eslint
components/react/views/Connected.tsx

[error] 62-64: Replace ⏎············src={name·===·'Cosmos·MetaMask·Extension'·?·'/metamask.svg'·:·getRealLogo(logo)}⏎ with ············src={name·===·'Cosmos·MetaMask·Extension'·?·'/metamask.svg'·:·getRealLogo(logo)}

(prettier/prettier)

components/react/views/Connecting.tsx

[error] 48-50: Replace ⏎··········src={name·===·'Cosmos·MetaMask·Extension'·?·'/metamask.svg'·:·getRealLogo(logo)}⏎ with ··········src={name·===·'Cosmos·MetaMask·Extension'·?·'/metamask.svg'·:·getRealLogo(logo)}

(prettier/prettier)

components/react/views/Error.tsx

[error] 50-51: Delete

(prettier/prettier)


[error] 55-56: Delete

(prettier/prettier)

components/react/views/NotExist.tsx

[error] 45-47: Replace ⏎··········src={name·===·'Cosmos·MetaMask·Extension'·?·'/metamask.svg'·:·getRealLogo(logo)}⏎ with ··········src={name·===·'Cosmos·MetaMask·Extension'·?·'/metamask.svg'·:·getRealLogo(logo)}

(prettier/prettier)

components/react/views/WalletList.tsx

[error] 57-58: Delete

(prettier/prettier)


[error] 88-89: Delete

(prettier/prettier)

🔇 Additional comments (7)
components/react/qrCode.tsx (1)

57-95: Ensure logo size logic is robust.
When computing the “clear arena” for the logo on lines 57–95, we specifically rely on the ratio of logo size to the computed cell size. Consider adding checks for very large or very small logos, or for scenarios where the user sets a smaller overall “size” prop than the expected minimum for the included logo. This helps prevent visual overlap or unexpected results.

components/react/views/QRCodeView.tsx (1)

14-31: Test coverage is missing.
Portions of this file (lines 14–31 and 35–175) are untested according to the patch coverage report. Consider adding unit tests or at least partial coverage to confirm the various states—pending, error, expired—for the QR code.

Would you like to generate a test script for these lines to ensure coverage?

Also applies to: 35-175

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 14-31: components/react/views/QRCodeView.tsx#L14-L31
Added lines #L14 - L31 were not covered by tests

components/react/views/NotExist.tsx (1)

45-47: Refactor repeated logo logic (duplicate comment).
This is the same suggestion as in other components. Extract this special-cased logic into a shared helper to avoid code duplication and enable consistent updates in the future.

🧰 Tools
🪛 eslint

[error] 45-47: Replace ⏎··········src={name·===·'Cosmos·MetaMask·Extension'·?·'/metamask.svg'·:·getRealLogo(logo)}⏎ with ··········src={name·===·'Cosmos·MetaMask·Extension'·?·'/metamask.svg'·:·getRealLogo(logo)}

(prettier/prettier)

🪛 GitHub Check: codecov/patch

[warning] 45-47: components/react/views/NotExist.tsx#L45-L47
Added lines #L45 - L47 were not covered by tests

components/react/views/Error.tsx (1)

50-56: Add test coverage for MetaMask logo conditional.

The new conditional logic for MetaMask logo handling is currently not covered by tests.

Would you like me to help generate test cases for:

  1. Logo rendering for Cosmos MetaMask Extension
  2. Logo rendering for other wallet types
🧰 Tools
🪛 eslint

[error] 50-51: Delete

(prettier/prettier)


[error] 55-56: Delete

(prettier/prettier)

🪛 GitHub Check: codecov/patch

[warning] 50-56: components/react/views/Error.tsx#L50-L56
Added lines #L50 - L56 were not covered by tests

components/react/views/Connected.tsx (1)

62-64: Add test coverage for MetaMask logo conditional.

The new conditional logic for MetaMask logo handling is currently not covered by tests.

🧰 Tools
🪛 eslint

[error] 62-64: Replace ⏎············src={name·===·'Cosmos·MetaMask·Extension'·?·'/metamask.svg'·:·getRealLogo(logo)}⏎ with ············src={name·===·'Cosmos·MetaMask·Extension'·?·'/metamask.svg'·:·getRealLogo(logo)}

(prettier/prettier)

🪛 GitHub Check: codecov/patch

[warning] 62-64: components/react/views/Connected.tsx#L62-L64
Added lines #L62 - L64 were not covered by tests

components/react/modal.tsx (2)

232-236: Remove unnecessary non-null assertions

The code uses unnecessary non-null assertions (!). Consider using optional chaining instead.

🧰 Tools
🪛 Biome (1.9.4)

[error] 232-232: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)


[error] 236-236: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)

🪛 GitHub Check: codecov/patch

[warning] 232-233: components/react/modal.tsx#L232-L233
Added lines #L232 - L233 were not covered by tests


[warning] 236-236: components/react/modal.tsx#L236
Added line #L236 was not covered by tests


289-295: LGTM: Good user feedback for reconnection state

The default case provides clear visual feedback during reconnection attempts with a loading indicator and informative message.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 290-293: components/react/modal.tsx#L290-L293
Added lines #L290 - L293 were not covered by tests

Comment on lines 48 to 50

src={name === 'Cosmos MetaMask Extension' ? '/metamask.svg' : getRealLogo(logo)}

Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor repeated logo logic into a shared utility.
Multiple components replicate the same logic: “If name === 'Cosmos MetaMask Extension', use '/metamask.svg', otherwise call getRealLogo(logo).” Centralizing this logic in a utility function is more maintainable, ensuring consistent handling of future special cases.

- src={name === 'Cosmos MetaMask Extension' ? '/metamask.svg' : getRealLogo(logo)}
+ import { getWalletLogo } from '@/utils/wallet';
+ 
+ src={getWalletLogo(name, logo)}

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 eslint

[error] 48-50: Replace ⏎··········src={name·===·'Cosmos·MetaMask·Extension'·?·'/metamask.svg'·:·getRealLogo(logo)}⏎ with ··········src={name·===·'Cosmos·MetaMask·Extension'·?·'/metamask.svg'·:·getRealLogo(logo)}

(prettier/prettier)

🪛 GitHub Check: codecov/patch

[warning] 48-50: components/react/views/Connecting.tsx#L48-L50
Added lines #L48 - L50 were not covered by tests

Comment on lines +35 to +41
const hasMobileVersion = (prettyName: string) => {
return mobile.some(w => w.walletInfo.prettyName.startsWith(prettyName));
};

const getMobileWalletName = (browserName: string) => {
return mobile.find(w => w.walletInfo.prettyName.startsWith(browserName))?.walletInfo.name;
};
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add input validation to utility functions.

The new utility functions hasMobileVersion and getMobileWalletName should include input validation and error handling.

Consider this implementation:

 const hasMobileVersion = (prettyName: string) => {
+  if (!prettyName) return false;
   return mobile.some(w => w.walletInfo.prettyName.startsWith(prettyName));
 };

 const getMobileWalletName = (browserName: string) => {
+  if (!browserName) return undefined;
   return mobile.find(w => w.walletInfo.prettyName.startsWith(browserName))?.walletInfo.name;
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const hasMobileVersion = (prettyName: string) => {
return mobile.some(w => w.walletInfo.prettyName.startsWith(prettyName));
};
const getMobileWalletName = (browserName: string) => {
return mobile.find(w => w.walletInfo.prettyName.startsWith(browserName))?.walletInfo.name;
};
const hasMobileVersion = (prettyName: string) => {
if (!prettyName) return false;
return mobile.some(w => w.walletInfo.prettyName.startsWith(prettyName));
};
const getMobileWalletName = (browserName: string) => {
if (!browserName) return undefined;
return mobile.find(w => w.walletInfo.prettyName.startsWith(browserName))?.walletInfo.name;
};
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 35-41: components/react/views/WalletList.tsx#L35-L41
Added lines #L35 - L41 were not covered by tests

@@ -3,10 +3,12 @@
import { WalletStatus } from 'cosmos-kit';
import React, { useCallback, Fragment, useState, useMemo, useEffect } from 'react';
import { Dialog, Transition, Portal } from '@headlessui/react';
import { Connected, Connecting, Error, NotExist, QRCode, WalletList, Contacts } from './views';
import { Connected, Connecting, Error, NotExist, QRCodeView, WalletList, Contacts } from './views';
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Avoid shadowing global Error type

The import of Error from ./views shadows the global Error type which could lead to confusion.

Rename the imported component to avoid shadowing:

- import { Connected, Connecting, Error, NotExist, QRCodeView, WalletList, Contacts } from './views';
+ import { Connected, Connecting, ErrorView, NotExist, QRCodeView, WalletList, Contacts } from './views';

Also applies to: 10-11

🧰 Tools
🪛 Biome (1.9.4)

[error] 6-6: Do not shadow the global "Error" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

Comment on lines 86 to 102
useEffect(() => {
if (currentView === ModalView.QRCode && qrWallet) {
(qrWallet.client as any)?.setActions?.({
qrUrl: {
state: (s: State) => setQRState(s),
message: (msg: string) => setQrMessage(msg),
},
onError: (err: Error) => {
if (err.message?.includes('No matching key')) {
setQRState(State.Error);
setQrMessage(err.message);
qrWallet.setMessage?.(err.message);
}
},
});
}
}, [currentView, qrWallet]);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for QR code action setup

The QR code action setup could be more robust with proper type checking and error boundaries.

Consider adding error handling:

  useEffect(() => {
    if (currentView === ModalView.QRCode && qrWallet) {
+     try {
        (qrWallet.client as any)?.setActions?.({
          qrUrl: {
            state: (s: State) => setQRState(s),
            message: (msg: string) => setQrMessage(msg),
          },
          onError: (err: Error) => {
            if (err.message?.includes('No matching key')) {
              setQRState(State.Error);
              setQrMessage(err.message);
              qrWallet.setMessage?.(err.message);
            }
          },
        });
+     } catch (error) {
+       console.error('Failed to setup QR code actions:', error);
+       setQRState(State.Error);
+       setQrMessage('Failed to setup QR code connection');
+     }
    }
  }, [currentView, qrWallet]);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
useEffect(() => {
if (currentView === ModalView.QRCode && qrWallet) {
(qrWallet.client as any)?.setActions?.({
qrUrl: {
state: (s: State) => setQRState(s),
message: (msg: string) => setQrMessage(msg),
},
onError: (err: Error) => {
if (err.message?.includes('No matching key')) {
setQRState(State.Error);
setQrMessage(err.message);
qrWallet.setMessage?.(err.message);
}
},
});
}
}, [currentView, qrWallet]);
useEffect(() => {
if (currentView === ModalView.QRCode && qrWallet) {
try {
(qrWallet.client as any)?.setActions?.({
qrUrl: {
state: (s: State) => setQRState(s),
message: (msg: string) => setQrMessage(msg),
},
onError: (err: Error) => {
if (err.message?.includes('No matching key')) {
setQRState(State.Error);
setQrMessage(err.message);
qrWallet.setMessage?.(err.message);
}
},
});
} catch (error) {
console.error('Failed to setup QR code actions:', error);
setQRState(State.Error);
setQrMessage('Failed to setup QR code connection');
}
}
}, [currentView, qrWallet]);
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 88-98: components/react/modal.tsx#L88-L98
Added lines #L88 - L98 were not covered by tests


[warning] 100-100: components/react/modal.tsx#L100
Added line #L100 was not covered by tests

Comment on lines +63 to +67
if (current?.walletInfo.mode === 'wallet-connect' && !isMobile) {
setCurrentView(ModalView.QRCode);
} else {
setCurrentView(ModalView.Connecting);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Codebase verification

Add test coverage for wallet connection modal view states

The verification confirms that there are no existing tests for the wallet connection modal view states. The modal component implements critical view management logic through the ModalView enum, including states for WalletList, QRCode, Connecting, and other wallet-related views, but lacks corresponding test coverage.

Key areas needing test coverage:

  • View transitions based on wallet connection mode (wallet-connect)
  • Mobile vs desktop view handling
  • State management for different wallet connection phases
🔗 Analysis chain

Add test coverage for view management logic

The view management logic for wallet connection states lacks test coverage.

Let's verify the test coverage:

Would you like me to help create test cases for the wallet connection view states?

Also applies to: 84-84

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for existing test files
fd -e test.tsx -e spec.tsx modal

# Check for wallet connection test patterns
rg -l "describe.*wallet.*connection" -g "*.test.{ts,tsx}"

Length of output: 393


Script:

#!/bin/bash
# Let's check for any existing tests related to the modal component
rg -A 5 "describe.*modal" components/react/__tests__/

# Check if there are any test files in the components/react directory
fd -e test.tsx -e spec.tsx . components/react/

# Look for any wallet-related test patterns in the codebase
rg -l "test.*wallet|describe.*wallet" -g "*.test.{ts,tsx}"

# Check the modal component implementation to understand the test scope better
ast-grep --pattern 'enum ModalView {
  $$$
}'

Length of output: 803

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 63-66: components/react/modal.tsx#L63-L66
Added lines #L63 - L66 were not covered by tests

Comment on lines 116 to 177
if (wallet?.walletInfo.mode === 'wallet-connect') {
if (isMobile) {
setCurrentView(ModalView.Connecting);
walletRepo?.connect(name).catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.Error);
});
return;
}

setQRWallet(wallet);
setCurrentView(ModalView.QRCode);

const timeoutId = setTimeout(() => {
if (wallet?.walletStatus === WalletStatus.Connecting) {
wallet.disconnect();
setCurrentView(ModalView.Error);
}
}, 30000);

walletRepo
?.connect(name)
.then(() => {
if (wallet?.walletStatus === WalletStatus.Connected) {
setCurrentView(ModalView.Connected);
}
})
.catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.QRCode);
setQRState(State.Error);
setQrMessage(error.message);
})
.finally(() => {
clearTimeout(timeoutId);
});

if (qrState === State.Pending && !wallet?.qrUrl?.data) {
setCurrentView(ModalView.Connecting);
}
} else {
setQRWallet(undefined);

setCurrentView(ModalView.Connecting);

const timeoutId = setTimeout(() => {
if (wallet?.walletStatus === WalletStatus.Connecting) {
wallet.disconnect();
setCurrentView(ModalView.Error);
}
}, 30000);

walletRepo
?.connect(name)
.catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.Error);
})
.finally(() => {
clearTimeout(timeoutId);
});
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor duplicated timeout logic

The wallet connection timeout logic is duplicated for both QR and regular wallet connections.

Extract the timeout logic into a reusable function:

+ const setupConnectionTimeout = (wallet: ChainWalletBase, onTimeout: () => void) => {
+   const timeoutId = setTimeout(() => {
+     if (wallet?.walletStatus === WalletStatus.Connecting) {
+       wallet.disconnect();
+       onTimeout();
+     }
+   }, 30000);
+   return timeoutId;
+ };

  if (wallet?.walletInfo.mode === 'wallet-connect') {
    // ... existing code ...
-   const timeoutId = setTimeout(() => {
-     if (wallet?.walletStatus === WalletStatus.Connecting) {
-       wallet.disconnect();
-       setCurrentView(ModalView.Error);
-     }
-   }, 30000);
+   const timeoutId = setupConnectionTimeout(wallet, () => setCurrentView(ModalView.Error));
    // ... rest of the code ...
  } else {
    // ... existing code ...
-   const timeoutId = setTimeout(() => {
-     if (wallet?.walletStatus === WalletStatus.Connecting) {
-       wallet.disconnect();
-       setCurrentView(ModalView.Error);
-     }
-   }, 30000);
+   const timeoutId = setupConnectionTimeout(wallet, () => setCurrentView(ModalView.Error));
    // ... rest of the code ...
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (wallet?.walletInfo.mode === 'wallet-connect') {
if (isMobile) {
setCurrentView(ModalView.Connecting);
walletRepo?.connect(name).catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.Error);
});
return;
}
setQRWallet(wallet);
setCurrentView(ModalView.QRCode);
const timeoutId = setTimeout(() => {
if (wallet?.walletStatus === WalletStatus.Connecting) {
wallet.disconnect();
setCurrentView(ModalView.Error);
}
}, 30000);
walletRepo
?.connect(name)
.then(() => {
if (wallet?.walletStatus === WalletStatus.Connected) {
setCurrentView(ModalView.Connected);
}
})
.catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.QRCode);
setQRState(State.Error);
setQrMessage(error.message);
})
.finally(() => {
clearTimeout(timeoutId);
});
if (qrState === State.Pending && !wallet?.qrUrl?.data) {
setCurrentView(ModalView.Connecting);
}
} else {
setQRWallet(undefined);
setCurrentView(ModalView.Connecting);
const timeoutId = setTimeout(() => {
if (wallet?.walletStatus === WalletStatus.Connecting) {
wallet.disconnect();
setCurrentView(ModalView.Error);
}
}, 30000);
walletRepo
?.connect(name)
.catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.Error);
})
.finally(() => {
clearTimeout(timeoutId);
});
}
const setupConnectionTimeout = (wallet: ChainWalletBase, onTimeout: () => void) => {
const timeoutId = setTimeout(() => {
if (wallet?.walletStatus === WalletStatus.Connecting) {
wallet.disconnect();
onTimeout();
}
}, 30000);
return timeoutId;
};
if (wallet?.walletInfo.mode === 'wallet-connect') {
if (isMobile) {
setCurrentView(ModalView.Connecting);
walletRepo?.connect(name).catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.Error);
});
return;
}
setQRWallet(wallet);
setCurrentView(ModalView.QRCode);
const timeoutId = setupConnectionTimeout(wallet, () => setCurrentView(ModalView.Error));
walletRepo
?.connect(name)
.then(() => {
if (wallet?.walletStatus === WalletStatus.Connected) {
setCurrentView(ModalView.Connected);
}
})
.catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.QRCode);
setQRState(State.Error);
setQrMessage(error.message);
})
.finally(() => {
clearTimeout(timeoutId);
});
if (qrState === State.Pending && !wallet?.qrUrl?.data) {
setCurrentView(ModalView.Connecting);
}
} else {
setQRWallet(undefined);
setCurrentView(ModalView.Connecting);
const timeoutId = setupConnectionTimeout(wallet, () => setCurrentView(ModalView.Error));
walletRepo
?.connect(name)
.catch(error => {
console.error('Wallet connection error:', error);
setCurrentView(ModalView.Error);
})
.finally(() => {
clearTimeout(timeoutId);
});
}

@chalabi2
Copy link
Collaborator Author

@fmorency

Couple things here

  • Cosmostation does not have a qr code scanner in their wallet for wallet connections so i removed that.

  • I believe Leap mobile does not support "Suggest Chain" functionality so the chain needs to be added to the leap mobile wallet for QrCode and mobile wallet connections. This indicates its not an issue with the code but needs additional configuration on the mobile app.

  • isMobile determines if it is actually a mobile device or not, which allows different connection types depending on if we are on desktop or mobile, that means no qrCode on mobile but direct connection.

  • QrCode renders when the qrUri is available. Allows to show loading qr code message. If a connection was already made (if youve already scanned the qr code) the connection will be re-established.

Copy link
Contributor

@fmorency fmorency left a comment

Choose a reason for hiding this comment

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

I tested Keplr and it works, thank you!

This PR also contains the email/sms PR which is not working.

I thing the PRs should be merged in the following order

  1. Fix the email/sms PR (SMS rendering is broken)
  2. Merge the email/sms PR
  3. Update this PR with the latest changes
  4. Merge this PR

@chalabi2
Copy link
Collaborator Author

I tested Keplr and it works, thank you!

This PR also contains the email/sms PR which is not working.

I thing the PRs should be merged in the following order

1. Fix the email/sms PR (SMS rendering is broken)

2. Merge the email/sms PR

3. Update this PR with the latest changes

4. Merge this PR

On it. I mistakenly left emoji's in the SMS input rendering lol.

@fmorency
Copy link
Contributor

@chalabi2 can you fix the conflicts? I'll merge after this is done.

Copy link
Contributor

@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

♻️ Duplicate comments (2)
components/react/modal.tsx (2)

139-157: ⚠️ Potential issue

Add error boundary for QR code action setup.

The QR code action setup could benefit from proper error handling.

 useEffect(() => {
   if (currentView === ModalView.QRCode && qrWallet) {
+    try {
       (qrWallet.client as any)?.setActions?.({
         qrUrl: {
           state: (s: State) => setQRState(s),
           message: (msg: string) => setQrMessage(msg),
         },
         onError: (err: Error) => {
           if (err.message?.includes('No matching key')) {
             setQRState(State.Error);
             setQrMessage(err.message);
             qrWallet.setMessage?.(err.message);
           }
         },
       });
+    } catch (error) {
+      console.error('Failed to setup QR code actions:', error);
+      setQRState(State.Error);
+      setQrMessage('Failed to setup QR code connection');
+    }
   }
 }, [currentView, qrWallet]);
🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 143-153: components/react/modal.tsx#L143-L153
Added lines #L143 - L153 were not covered by tests


[warning] 155-155: components/react/modal.tsx#L155
Added line #L155 was not covered by tests


208-281: 🛠️ Refactor suggestion

Refactor duplicated timeout logic.

The wallet connection timeout logic is duplicated between QR and regular wallet connections.

Extract the timeout logic into a reusable function as suggested in the past review.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 209-245: components/react/modal.tsx#L209-L245
Added lines #L209 - L245 were not covered by tests


[warning] 259-277: components/react/modal.tsx#L259-L277
Added lines #L259 - L277 were not covered by tests

🧹 Nitpick comments (2)
components/react/views/QRCodeView.tsx (2)

46-56: Consider consolidating error detection logic.

The error detection logic is spread across multiple checks. Consider extracting these checks into a dedicated utility function for better maintainability.

+ const getQRCodeError = (qrUrl?: { message?: string }, wallet?: ChainWalletBase) => {
+   const isExpired = qrUrl?.message === ExpiredError.message || 
+     (wallet?.message && wallet.message.includes('Proposal expired'));
+   
+   const hasError = qrUrl?.state === State.Error ||
+     (wallet?.message && (
+       wallet.message.includes('No matching key') ||
+       wallet.message.includes('Record was recently deleted') ||
+       wallet.message.includes('Proposal expired')
+     ));
+   
+   return { isExpired, hasError };
+ };
🧰 Tools
🪛 Biome (1.9.4)

[error] 49-49: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


74-84: Add error type information for better error handling.

The error handling in handleRetry could be improved with proper error type information.

- } catch (error) {
+ } catch (error: unknown) {
    console.error('Retry connection error:', error);
    if (error instanceof Error) {
      wallet.setMessage?.(error.message);
+   } else {
+     wallet.setMessage?.('An unknown error occurred');
    }
  }
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between bf3b8e3 and a0a7c71.

📒 Files selected for processing (2)
  • components/react/modal.tsx (14 hunks)
  • components/react/views/QRCodeView.tsx (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
components/react/views/QRCodeView.tsx

[error] 49-49: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 173-179: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

components/react/modal.tsx

[error] 446-446: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 447-447: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)

🪛 GitHub Check: codecov/patch
components/react/views/QRCodeView.tsx

[warning] 14-31: components/react/views/QRCodeView.tsx#L14-L31
Added lines #L14 - L31 were not covered by tests


[warning] 35-196: components/react/views/QRCodeView.tsx#L35-L196
Added lines #L35 - L196 were not covered by tests

components/react/modal.tsx

[warning] 62-66: components/react/modal.tsx#L62-L66
Added lines #L62 - L66 were not covered by tests


[warning] 111-114: components/react/modal.tsx#L111-L114
Added lines #L111 - L114 were not covered by tests


[warning] 143-153: components/react/modal.tsx#L143-L153
Added lines #L143 - L153 were not covered by tests


[warning] 155-155: components/react/modal.tsx#L155
Added line #L155 was not covered by tests


[warning] 163-176: components/react/modal.tsx#L163-L176
Added lines #L163 - L176 were not covered by tests


[warning] 184-199: components/react/modal.tsx#L184-L199
Added lines #L184 - L199 were not covered by tests


[warning] 209-245: components/react/modal.tsx#L209-L245
Added lines #L209 - L245 were not covered by tests


[warning] 259-277: components/react/modal.tsx#L259-L277
Added lines #L259 - L277 were not covered by tests


[warning] 293-296: components/react/modal.tsx#L293-L296
Added lines #L293 - L296 were not covered by tests


[warning] 300-302: components/react/modal.tsx#L300-L302
Added lines #L300 - L302 were not covered by tests


[warning] 304-305: components/react/modal.tsx#L304-L305
Added lines #L304 - L305 were not covered by tests


[warning] 308-315: components/react/modal.tsx#L308-L315
Added lines #L308 - L315 were not covered by tests


[warning] 334-335: components/react/modal.tsx#L334-L335
Added lines #L334 - L335 were not covered by tests


[warning] 347-349: components/react/modal.tsx#L347-L349
Added lines #L347 - L349 were not covered by tests


[warning] 358-362: components/react/modal.tsx#L358-L362
Added lines #L358 - L362 were not covered by tests


[warning] 399-399: components/react/modal.tsx#L399
Added line #L399 was not covered by tests


[warning] 423-423: components/react/modal.tsx#L423
Added line #L423 was not covered by tests


[warning] 448-448: components/react/modal.tsx#L448
Added line #L448 was not covered by tests


[warning] 467-467: components/react/modal.tsx#L467
Added line #L467 was not covered by tests


[warning] 509-512: components/react/modal.tsx#L509-L512
Added lines #L509 - L512 were not covered by tests

🔇 Additional comments (4)
components/react/views/QRCodeView.tsx (2)

14-33: LGTM: Well-structured skeleton loader component.

The QRCodeLoader component provides a good user experience with a loading indicator and optional message display.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 14-31: components/react/views/QRCodeView.tsx#L14-L31
Added lines #L14 - L31 were not covered by tests


1-199: Add test coverage for the QRCodeView component.

The component lacks test coverage for critical functionality:

  • QR code state transitions
  • Error handling scenarios
  • Retry mechanism
  • Component mounting/unmounting

Would you like me to help create comprehensive test cases for this component?

✅ Verification successful

Test coverage needed for QRCodeView component

The verification confirms that while there is an established testing infrastructure with Jest (evidenced by multiple __tests__ directories and existing test files), there is no test coverage for the QRCodeView component. The component handles critical wallet connection flows including:

  • QR code state management
  • Error handling and recovery
  • Loading states and suspense
  • User interactions (retry, close, return)

Key files to add:

  • components/react/__tests__/QRCodeView.test.tsx
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for existing test coverage
fd -e test.tsx -e spec.tsx QRCodeView

# Check for any existing QR code related tests
rg -l "describe.*QR.*code" -g "*.test.{ts,tsx}"

Length of output: 89


Script:

#!/bin/bash
# Let's check for any test files in the components/react directory
fd -e test.tsx -e spec.tsx . components/react/

# Check for any test files that might reference QRCode
rg -l "QRCode" -g "*.test.{ts,tsx,js,jsx}"

# Check if there's a __tests__ directory
fd -t d "__tests__"

# Look for jest configuration to confirm test setup
fd -g "jest.config.*"

Length of output: 750

🧰 Tools
🪛 Biome (1.9.4)

[error] 49-49: Change to an optional chain.

Unsafe fix: Change to an optional chain.

(lint/complexity/useOptionalChain)


[error] 173-179: Avoid using unnecessary Fragment.

A fragment is redundant if it contains only one child, or if it is the child of a html element, and is not a keyed fragment.
Unsafe fix: Remove the Fragment

(lint/complexity/noUselessFragments)

🪛 GitHub Check: codecov/patch

[warning] 14-31: components/react/views/QRCodeView.tsx#L14-L31
Added lines #L14 - L31 were not covered by tests


[warning] 35-196: components/react/views/QRCodeView.tsx#L35-L196
Added lines #L35 - L196 were not covered by tests

components/react/modal.tsx (2)

52-69: LGTM: Well-structured error handling utilities.

The error constants and helper function improve code maintainability and error handling consistency.

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 62-66: components/react/modal.tsx#L62-L66
Added lines #L62 - L66 were not covered by tests


Line range hint 1-586: Add test coverage for wallet connection modal view states.

The modal component's view management logic lacks test coverage.

#!/bin/bash
# Check for existing modal test coverage
fd -e test.tsx -e spec.tsx modal

# Check for wallet connection test patterns
rg -l "describe.*wallet.*connection" -g "*.test.{ts,tsx}"

Would you like me to help create test cases for the wallet connection view states?

🧰 Tools
🪛 GitHub Check: codecov/patch

[warning] 143-153: components/react/modal.tsx#L143-L153
Added lines #L143 - L153 were not covered by tests


[warning] 155-155: components/react/modal.tsx#L155
Added line #L155 was not covered by tests


[warning] 163-176: components/react/modal.tsx#L163-L176
Added lines #L163 - L176 were not covered by tests


[warning] 184-199: components/react/modal.tsx#L184-L199
Added lines #L184 - L199 were not covered by tests


[warning] 209-245: components/react/modal.tsx#L209-L245
Added lines #L209 - L245 were not covered by tests


[warning] 259-277: components/react/modal.tsx#L259-L277
Added lines #L259 - L277 were not covered by tests


[warning] 293-296: components/react/modal.tsx#L293-L296
Added lines #L293 - L296 were not covered by tests


[warning] 300-302: components/react/modal.tsx#L300-L302
Added lines #L300 - L302 were not covered by tests


[warning] 304-305: components/react/modal.tsx#L304-L305
Added lines #L304 - L305 were not covered by tests


[warning] 308-315: components/react/modal.tsx#L308-L315
Added lines #L308 - L315 were not covered by tests


[warning] 334-335: components/react/modal.tsx#L334-L335
Added lines #L334 - L335 were not covered by tests


[warning] 347-349: components/react/modal.tsx#L347-L349
Added lines #L347 - L349 were not covered by tests


[warning] 358-362: components/react/modal.tsx#L358-L362
Added lines #L358 - L362 were not covered by tests

Comment on lines 446 to 452
let subtitle: string;
if (currentWalletData!?.mode === 'wallet-connect') {
subtitle = `Approve ${currentWalletData!.prettyName} connection request on your mobile.`;
subtitle = `Approve ${currentWalletData!.prettyName} connection request on your mobile device.`;
} else {
subtitle = `Open the ${
currentWalletData!?.prettyName
} browser extension to connect your wallet.`;
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix switch case declaration scoping.

The variable declaration in the switch case could lead to scoping issues.

 case ModalView.Connecting:
+  {
     let subtitle: string;
     if (currentWalletData!?.mode === 'wallet-connect') {
       subtitle = `Approve ${currentWalletData!.prettyName} connection request on your mobile device.`;
     } else {
       subtitle = `Open the ${currentWalletData!?.prettyName} browser extension to connect your wallet.`;
     }
     return (
       <Connecting
         // ... props
       />
     );
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let subtitle: string;
if (currentWalletData!?.mode === 'wallet-connect') {
subtitle = `Approve ${currentWalletData!.prettyName} connection request on your mobile.`;
subtitle = `Approve ${currentWalletData!.prettyName} connection request on your mobile device.`;
} else {
subtitle = `Open the ${
currentWalletData!?.prettyName
} browser extension to connect your wallet.`;
{
let subtitle: string;
if (currentWalletData!?.mode === 'wallet-connect') {
subtitle = `Approve ${currentWalletData!.prettyName} connection request on your mobile device.`;
} else {
subtitle = `Open the ${
currentWalletData!?.prettyName
} browser extension to connect your wallet.`;
🧰 Tools
🪛 Biome (1.9.4)

[error] 446-446: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.

The declaration is defined in this switch clause:

Unsafe fix: Wrap the declaration in a block.

(lint/correctness/noSwitchDeclarations)


[error] 447-447: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)


[error] 451-451: Forbidden extra non-null assertion.

Safe fix: Remove extra non-null assertion.

(lint/suspicious/noExtraNonNullAssertion)

🪛 GitHub Check: codecov/patch

[warning] 448-448: components/react/modal.tsx#L448
Added line #L448 was not covered by tests

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enable mobile wallets on Desktop
2 participants