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: prime login and payment #6480

Merged
merged 17 commits into from
Feb 10, 2025
Merged

feat: prime login and payment #6480

merged 17 commits into from
Feb 10, 2025

Conversation

sidmorizon
Copy link
Contributor

@sidmorizon sidmorizon commented Jan 9, 2025

Summary by CodeRabbit

  • New Features

    • Launched a comprehensive "Prime" suite that includes new subscription management, login dialogs, dashboards, and device management features for premium users.
    • Integrated enhanced web embed routing and wallet connectivity for improved navigation and user experience.
    • Introduced new components for handling email verification and login processes, enhancing user authentication flows.
    • Added support for device management within the Prime suite, allowing users to manage their connected devices effectively.
    • Expanded error handling capabilities with specific error classes for Prime login scenarios.
    • Added new environment variables for enhanced configuration options related to the Prime suite.
    • Introduced new hooks for managing user authentication and payment functionalities.
  • Refactor

    • Consolidated error handling and state management across platforms for smoother performance.
    • Streamlined the routing and configuration for various Prime-related components to enhance modularity and maintainability.
  • Documentation

    • Updated guidelines to reflect new authentication and payment flows.
    • Added documentation for the new "Prime" suite features and components to assist developers in implementation.
  • Chores

    • Performed dependency updates, build process optimizations, and workflow enhancements for increased stability.

Copy link

codesandbox bot commented Jan 9, 2025

Review or Edit in CodeSandbox

Open the branch in Web EditorVS CodeInsiders

Open Preview

Copy link
Contributor

coderabbitai bot commented Jan 9, 2025

Walkthrough

The pull request introduces extensive changes across various project components. New environment variables and a shared environment setup replace older dotenv actions in GitHub workflows. Several workflow files, build scripts, and configuration files are updated to enhance setup, disk space management, and build processes. Sentry integration is improved by adding a fallback error boundary parameter. Major updates include new UI components, hooks, routers, state atoms, and services to support OneKey Prime features like login, subscription management, and device handling. Additional utility, error, and request/header management functions are refined, and new modules are added for Google Play services.

Changes

File(s) Change Summary
Workflow & Environment Config
.env.example
.eslintrc.js
.github/actions/*
.github/workflows/*
apps/ext/package.json
Added new environment variables (ENABLE_ANALYZER, PRIVY_, REVENUECAT_API_KEY_) and replaced dotenv action with "Run Shared Env Setup". Improved disk space cleanup and increased Node memory during builds.
Sentry Integration
apps/desktop/App.tsx
apps/ext/src/ui/renderApp.tsx
apps/mobile/App.tsx
apps/web/index.js
packages/shared/src/modules3rdParty/sentry/*
Updated all withSentryHOC calls to include SentryErrorBoundaryFallback. Enhanced error handling by allowing custom fallback components.
Webpack & Development Env
apps/desktop/webpack.config.js
apps/ext/webpack.config.js
development/env.js
development/webpack/*
Added require for environment files; consolidated dotenv.config() calls; updated analyzer configuration and refactored base config for clarity.
UI & Routing for Web Embed & Prime
apps/web-embed/index.js
apps/web-embed/pages/*
packages/shared/src/consts/webEmbedConsts.ts
packages/kit/src/views/Developer/pages/Gallery/*
Refactored web embed index to use lazy-loaded routes. Introduced new components and pages for OTP input, web embed API, and Prime purchase. Updated header and modal routing to always display the Prime icon and include new routes.
Prime Service & Subscription Integration
packages/kit-bg/src/apis/*
packages/kit-bg/src/dbs/simple/*
packages/kit-bg/src/services/ServicePrime/*
packages/shared/types/prime/*
packages/kit/src/views/Prime/*
Added numerous new API methods, services, state atoms, and hooks to support Prime login, subscription, token management, device logout, and related errors. New UI components and dialogs for Prime login, email code verification, password entry, and subscription plans are implemented.
Miscellaneous Enhancements & Utilities
packages/components/src/*
packages/shared/src/utils/*
packages/shared/src/request/*
packages/kit/.folderslintrc
Extended type definitions (e.g. tooltipProps, OTPInput improvements) and added new utility functions (isValidEmail, generateUUID). Updated folder lint rules and refined request interceptor headers and URI parsing.
Google Play Service Implementation
packages/shared/src/googlePlayService/*
Added android and default implementations for checking Google Play service availability, including new types.
Platform & Request Headers
packages/shared/src/platformEnv.ts
packages/shared/src/request/Interceptor.ts
packages/shared/src/request/InterceptorConsts.ts
Enhanced the platform environment by adding mobileDetectInfo and appFullName. Imported headerPlatform from a centralized constants file and added a new header with the device name.

Sequence Diagram(s)

sequenceDiagram
    participant U as User
    participant D as PrimeLoginEmailDialog
    participant SP as ServicePrime API
    participant P as PrimePersistAtom
    U->>D: Enter email and submit
    D->>SP: Call apiSendEmailVerificationCode
    SP-->>D: Return verification code response
    U->>D: Enter verification code and confirm
    D->>SP: Call apiPrimeLogin with code
    SP-->>D: Return login response
    SP->>P: Update persistent login state
    D-->>U: Display success message
Loading
✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

🪧 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 or 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

socket-security bot commented Jan 10, 2025

👍 Dependency issues cleared. Learn more about Socket for GitHub ↗︎

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report↗︎

@sidmorizon sidmorizon force-pushed the feat/prime-login0 branch 3 times, most recently from 2ed7a9b to 358a2a3 Compare January 14, 2025 07:08
@sidmorizon sidmorizon force-pushed the feat/prime-login0 branch 6 times, most recently from 4d7ea5b to b7a34cb Compare January 20, 2025 12:43
@sidmorizon sidmorizon force-pushed the feat/prime-login0 branch 2 times, most recently from 9a467a4 to cafdfae Compare February 5, 2025 04:34
sidmorizon and others added 8 commits February 5, 2025 16:38
* feat: update confirmButtonProps

* feat: refactor Prime dashboard Lottie animation rendering

* refactor: simplify Prime authentication hooks and remove unused code

* refactor: optimize Prime banner background dark mode Lottie animation

* feat: update app

* refactor: adjust Prime Lottie animation rendering for web and native platforms

---------

Co-authored-by: limichange <[email protected]>
Co-authored-by: morizon <[email protected]>
…6618)

* refactor: simplify Privy authentication configuration and login flow

* fix: improve Prime login email code dialog error handling

* feat: add environment variable support for Privy authentication
@sidmorizon sidmorizon marked this pull request as ready for review February 8, 2025 07:27
@sidmorizon sidmorizon enabled auto-merge (squash) February 8, 2025 07:27
@sidmorizon sidmorizon changed the title Feat/prime login0 feat: prime login and payment Feb 8, 2025
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.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.

🛑 Comments failed to post (159)
packages/kit-bg/src/services/ServiceNotification/PushProvider/PushProviderWebSocket.ts (1)

33-37: 🧹 Nitpick (assertive)

Document the timeout value.

Good use of typed event names and timeout handling. Consider adding a comment explaining why 3000ms was chosen as the timeout value.

packages/kit/src/views/Prime/pages/PrimeDashboard/PrimeUserInfoMoreButton.tsx (4)

115-115: 🛠️ Refactor suggestion

Use translation for dialog description.

The dialog description is hardcoded in English. Use the translation system for consistency.

-            description: 'Are you sure you want to log out?',
+            description: intl.formatMessage({
+              id: ETranslations.prime_logout_confirmation,
+            }),
📝 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.

            description: intl.formatMessage({
              id: ETranslations.prime_logout_confirmation,
            }),

158-160: 🛠️ Refactor suggestion

Remove console.log statement.

Remove debugging console.log statement from production code.

-          onPress={() => {
-            console.log('1');
-          }}
+          onPress={() => {}}

133-138: 🧹 Nitpick (assertive)

Remove unused parameter.

The handleActionListOpen parameter is declared but never used.

    ({
      handleActionListClose,
-    }: {
-      handleActionListClose: () => void;
-      handleActionListOpen: () => void;
-    })
+    }: {
+      handleActionListClose: () => void;
+    })
📝 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.

    ({
      handleActionListClose,
    }: {
      handleActionListClose: () => void;
    }) => (

64-74: 🧹 Nitpick (assertive)

Remove commented-out code.

Delete unused code instead of commenting it out. If you need it later, you can find it in version control.

-      {/* <ActionList.Item
-        label="Change email"
-        icon="EmailOutline"
-        onClose={handleActionListClose}
-        onPress={() => {
-          Toast.success({
-            title: 'Change email not implemented',
-          });
-          updateEmail();
-        }}
-      /> */}
📝 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.


packages/kit/src/views/Developer/pages/Gallery/Components/stories/WebEmbed.tsx (4)

66-66: 🧹 Nitpick (assertive)

Remove commented code

Delete the commented WebViewWebEmbed component if it's no longer needed.


57-57: 🧹 Nitpick (assertive)

Move localhost URL to configuration

Hardcoded localhost URL should be in a configuration file for better environment management.

-            setUrl('http://localhost:3008');
+            setUrl(process.env.DEFAULT_WEBVIEW_URL || 'http://localhost:3008');
📝 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.

            setUrl(process.env.DEFAULT_WEBVIEW_URL || 'http://localhost:3008');

68-71: 🛠️ Refactor suggestion

Add error handling to RPC test

The RPC test call lacks error handling. Add try-catch to handle potential failures gracefully.

-          const result = await webembedApiProxy.test.test1('a', 'b', 'c', 'd');
-          alert(JSON.stringify(result));
+          try {
+            const result = await webembedApiProxy.test.test1('a', 'b', 'c', 'd');
+            alert(JSON.stringify(result));
+          } catch (error) {
+            alert(`RPC test failed: ${error.message}`);
+          }

82-84: 🧹 Nitpick (assertive)

Add meaningful content to Layout props

The description and arrays are empty. Add useful content or remove if unnecessary.

-      description="..."
-      suggestions={[]}
-      boundaryConditions={[]}
+      description="Web embed configuration interface for development purposes"
+      suggestions={['Use local network IP for real devices', 'Update white list in environment variables']}
+      boundaryConditions={['Requires local development server running on port 3008']}
📝 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.

      description="Web embed configuration interface for development purposes"
      suggestions={['Use local network IP for real devices', 'Update white list in environment variables']}
      boundaryConditions={['Requires local development server running on port 3008']}
packages/kit/src/views/Prime/components/PrimeLoginEmailDialogV2/PrimeLoginEmailDialogV2.tsx (4)

84-86: 🛠️ Refactor suggestion

Internationalize validation messages.

Hardcoded English messages should use intl.formatMessage.

  if (!value) {
-   return 'email is required';
+   return intl.formatMessage({ id: ETranslations.form_email_required });
  }
...
  required: {
    value: true,
-   message: 'email is required',
+   message: intl.formatMessage({ id: ETranslations.form_email_required }),
  },

Also applies to: 93-95


107-107: 🧹 Nitpick (assertive)

Improve input text trimming.

The trim logic is unclear and could be simplified.

- onChangeText={(text) => text?.trim() ?? text}
+ onChangeText={(text) => text?.trim() || ''}
📝 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.

              onChangeText={(text) => text?.trim() || ''}

57-60: ⚠️ Potential issue

Improve error handling in submit function.

The catch block swallows errors after calling preventClose.

    } catch (error) {
      options?.preventClose?.();
-     throw error;
+     Dialog.show({
+       title: 'Error',
+       description: 'Failed to send verification code. Please try again.',
+     });
+     console.error('Email submission failed:', error);
    }

23-25: ⚠️ Potential issue

Improve error handling.

Don't just log errors to console. Show error messages to users.

    onError: (error) => {
-     console.log(error);
+     Dialog.show({
+       title: 'Error',
+       description: error.message || 'Failed to login. Please try again.',
+     });
    },
📝 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.

    onError: (error) => {
      Dialog.show({
        title: 'Error',
        description: error.message || 'Failed to login. Please try again.',
      });
    },
packages/kit/src/views/Prime/pages/PrimeDashboard/PrimeSubscriptionPlans.tsx (5)

122-122: ⚠️ Potential issue

Remove unsafe type casting.

The double type casting (as unknown as any) is dangerous and bypasses TypeScript's type checking.

-              p.rcBillingProduct?.normalPeriodDuration as unknown as any
+              p.rcBillingProduct?.normalPeriodDuration as PeriodDuration

128-128: 🛠️ Refactor suggestion

Move currency to configuration.

Don't hardcode the currency symbol. Use a configuration value or pass it as a prop.

-            currency="$"
+            currency={config.defaultCurrency}

35-40: 🛠️ Refactor suggestion

Remove commented code and implement dynamic savings calculation.

Dead code adds noise. Either implement the percentage calculation or remove it entirely.

-    // const savePercent = new BigNumber(1)
-    //   .minus(pricePerMonthBN.div(price))
-    //   .multipliedBy(100)
-    //   .toFixed(1);
-    // promoText = `Save ${savePercent}%`;
-    promoText = `Save 33%`;
+    const savePercent = new BigNumber(1)
+      .minus(pricePerMonthBN.div(price))
+      .multipliedBy(100)
+      .toFixed(1);
+    promoText = `Save ${savePercent}%`;
📝 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.

    const savePercent = new BigNumber(1)
      .minus(pricePerMonthBN.div(price))
      .multipliedBy(100)
      .toFixed(1);
    promoText = `Save ${savePercent}%`;

81-81: 💡 Verification agent

🧩 Analysis chain

Address the i18n TODO comment.

Implement internationalization for the '/month' text to support multiple languages.


🏁 Script executed:

#!/bin/bash
# Check if i18n is already set up in the project
rg -l "i18n" --type ts

Length of output: 1262


Internationalize the '/month' string in PrimeSubscriptionPlans.tsx

The code still uses the hard-coded text. Please update it to use your i18n function (for example, something like i18n.t('subscriptionPlans.perMonth')) and add the key to your translation files.

• File: packages/kit/src/views/Prime/pages/PrimeDashboard/PrimeSubscriptionPlans.tsx, line 81


26-26: 🧹 Nitpick (assertive)

Use a more type-safe approach for period duration.

Replace the string literal type with an enum to prevent typos and improve maintainability.

-  periodDuration: 'P1Y' | 'P1M';
+enum PeriodDuration {
+  YEARLY = 'P1Y',
+  MONTHLY = 'P1M'
+}
+  periodDuration: PeriodDuration;

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

packages/kit-bg/src/providers/ProviderApiPrivate.ts (1)

511-516: 🧹 Nitpick (assertive)

Enhanced logging improves debugging.

The switch to JSON.stringify makes the log output more structured and readable.

Consider adding error handling around JSON.stringify to handle circular references:

-      logName: `ProviderApiPrivate.callWebEmbedApiProxy: ${JSON.stringify({
+      logName: `ProviderApiPrivate.callWebEmbedApiProxy: ${JSON.stringify({
         module: data?.module,
         method: data?.method,
         isWebEmbedApiReady: Boolean(this.isWebEmbedApiReady),
         webEmbedBridge: Boolean(bg?.webEmbedBridge),
-      })}`,
+      }, null, 2)}`.replace(/\n\s*/g, ' '),
apps/web-embed/index.js (1)

16-34: 🧹 Nitpick (assertive)

Consider a more descriptive fallback.

The Suspense fallback is just an empty div. A simple loading indicator might be friendlier. Everything else looks straightforward.

packages/kit/src/views/Prime/purchasesSdk/PurchasesSdkWebBase.ts (4)

14-28: 🧹 Nitpick (assertive)

Use consistent error handling
You're throwing an error if userId is missing. That's good. However, consider standardizing error codes or messages across the codebase so logs remain consistent.


36-41: 🧹 Nitpick (assertive)

Avoid logging sensitive info
Consider removing or redacting user details in console logs to protect privacy in production.


43-64: 🧹 Nitpick (assertive)

Future-proof your package sorting
Right now, you're returning 'Yearly' first. If you add more offering types, a single check might be restrictive. A flexible approach to sorting can help.


66-99: 🛠️ Refactor suggestion

Enhance purchase error handling
You're throwing a generic error for invalid package IDs. Use more descriptive messages for easier debugging. Also handle cases where the user already purchased.

packages/kit/src/views/Prime/hooks/usePrimePayment.native.ts (2)

28-71: 🧹 Nitpick (assertive)

Add user logout logic if needed
You log in with a user ID, but the logout code is commented out. If the user changes, a logout step might be needed.


129-185: 🧹 Nitpick (assertive)

Handle alternative store flows
You handle Google Play. Consider a fallback or more explicit handling for other stores.

packages/kit/src/views/Prime/hooks/usePrimePayment.ts (2)

34-103: 🧹 Nitpick (assertive)

Consider race conditions
You configure Purchases inside getCustomerInfo(). Repeated calls might trigger multiple inits. Guard or cache as needed.


154-199: 🧹 Nitpick (assertive)

Unify error messages
A single "Invalid packageId" error may be too broad. Provide a unique code or message.

packages/kit/src/components/WebViewWebEmbed/index.tsx (1)

47-60: 🧹 Nitpick (assertive)

Handle missing RevenueCat key gracefully.
Throwing an error may cause unhandled promise rejections if unmounted. Consider try/catch or user feedback for missing keys.

packages/kit-bg/src/services/ServicePrime/ServicePrime.tsx (4)

46-60: 🧹 Nitpick (assertive)

getPrimeClient interceptor.
It injects the auth token if present. This is a clean approach. Consider logging or user feedback if token is unavailable.


399-414: 🛠️ Refactor suggestion

promptPrimeLoginEmailDialog with async promise executor (lines 402-411).
Avoid using async in a Promise executor to prevent unexpected rejections.

Apply this patch:

- const email = await new Promise<string>(async (resolve, reject) => {
+ const email = await new Promise<string>((resolve, reject) => {

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

🧰 Tools
🪛 Biome (1.9.4)

[error] 402-411: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)


440-465: 🛠️ Refactor suggestion

promptPrimeLoginPasswordDialog with async promise executor (lines 449-462).
Avoid using async in a Promise executor.

Apply this patch:

- const password = await new Promise<string>(async (resolve, reject) => {
+ const password = await new Promise<string>((resolve, reject) => {

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

🧰 Tools
🪛 Biome (1.9.4)

[error] 449-462: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)


488-512: 🛠️ Refactor suggestion

promptPrimeLoginEmailCodeDialog with async promise executor (lines 497-510).
Avoid using async in the executor.

Apply:

- const code = await new Promise<string>(async (resolve, reject) => {
+ const code = await new Promise<string>((resolve, reject) => {

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

🧰 Tools
🪛 Biome (1.9.4)

[error] 497-510: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)

packages/shared/src/googlePlayService/googlePlayServiceTypes.ts (1)

1-3: 🧹 Nitpick (assertive)

Clean interface design!

The interface is well-defined and focused. Consider adding JSDoc comments to document the purpose and behavior of the isAvailable method.

 export type IGooglePlayService = {
+  /** Checks if Google Play Services is available on the device */
   isAvailable: () => Promise<boolean>;
 };
📝 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.

export type IGooglePlayService = {
  /** Checks if Google Play Services is available on the device */
  isAvailable: () => Promise<boolean>;
};
packages/shared/src/consts/webEmbedConsts.ts (1)

1-5: 🧹 Nitpick (assertive)

Well-structured route constants!

The enum follows good naming patterns and uses clear, RESTful paths. Consider adding JSDoc comments to document each route's purpose.

 export enum EWebEmbedRoutePath {
+  /** Home page route */
   index = '/',
+  /** Prime subscription purchase page */
   primePurchase = '/prime/purchase',
+  /** Web embed API endpoint */
   webEmbedApi = '/webembed/api',
 }
apps/desktop/webpack.config.js (1)

1-1: 💡 Verification agent

🧩 Analysis chain

Verify environment setup.

The environment setup is now required before webpack config. Ensure all necessary environment variables are defined in the .env file.


🏁 Script executed:

#!/bin/bash
# Check if required env file exists and contains necessary variables
if [ -f "../../.env" ]; then
    echo "Checking .env file..."
    grep -E "^(ENABLE_ANALYZER|PRIVY_APP_ID|REVENUECAT_API_KEY)=" ../../.env || echo "Missing required environment variables"
else
    echo ".env file not found"
fi

Length of output: 72


Environment setup issue detected.
Our check shows the required .env file is missing. The script did not find the file at "../../.env".
Please ensure a .env file exists with the necessary variables, such as ENABLE_ANALYZER, PRIVY_APP_ID, and REVENUECAT_API_KEY.

packages/shared/src/googlePlayService/googlePlayService.ts (1)

3-5: ⚠️ Potential issue

Implement actual Google Play services check

The current implementation always returns false. This could cause issues on Android devices where Google Play services are actually available.

Consider using the @react-native-community/google-signin package for proper detection:

-const googlePlayService: IGooglePlayService = {
-  isAvailable: () => Promise.resolve(false),
-};
+import { GoogleSignin } from '@react-native-community/google-signin';
+
+const googlePlayService: IGooglePlayService = {
+  isAvailable: async () => {
+    try {
+      return await GoogleSignin.hasPlayServices();
+    } catch {
+      return false;
+    }
+  },
+};
📝 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.

import { GoogleSignin } from '@react-native-community/google-signin';

const googlePlayService: IGooglePlayService = {
  isAvailable: async () => {
    try {
      return await GoogleSignin.hasPlayServices();
    } catch {
      return false;
    }
  },
};
packages/shared/src/routes/prime.ts (2)

1-4: 🧹 Nitpick (assertive)

Add documentation for routes

Add JSDoc comments to describe each route's purpose and usage.

Example:

 export enum EPrimePages {
+  /** Main dashboard for Prime features */
   PrimeDashboard = 'PrimeDashboard',
+  /** Device limit warning/management screen */
   PrimeDeviceLimit = 'PrimeDeviceLimit',
 }
📝 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.

export enum EPrimePages {
  /** Main dashboard for Prime features */
  PrimeDashboard = 'PrimeDashboard',
  /** Device limit warning/management screen */
  PrimeDeviceLimit = 'PrimeDeviceLimit',
}

6-9: 🧹 Nitpick (assertive)

Consider consistent naming pattern

The route names mix different patterns: Prime vs PrimeDevice. Consider using consistent prefixing.

Example:

 export type IPrimeParamList = {
   [EPrimePages.PrimeDashboard]: undefined;
-  [EPrimePages.PrimeDeviceLimit]: undefined;
+  [EPrimePages.PrimeDevicesLimit]: undefined;
 };
📝 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.

export type IPrimeParamList = {
  [EPrimePages.PrimeDashboard]: undefined;
  [EPrimePages.PrimeDevicesLimit]: undefined;
};
apps/web-embed/webpack.config.js (1)

5-8: ⚠️ Potential issue

Remove sensitive information from console logs.

The RevenueCat API key is sensitive. Remove this console.log to prevent exposing it in browser consoles.

-console.log(
-  'process.env.REVENUECAT_API_KEY_WEB_SANDBOX',
-  process.env.REVENUECAT_API_KEY_WEB_SANDBOX,
-);
📝 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.


apps/web-embed/utils/webEmbedAppSettings.ts (2)

12-14: 🧹 Nitpick (assertive)

Consider using named exports.

Default exports can make code harder to refactor. Consider using named exports instead.

-export default {
-  getSettings,
-};
+export { getSettings };
📝 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.

export { getSettings };

7-10: 🧹 Nitpick (assertive)

Add type safety checks.

The settings getter could be more robust. Add type checking and default values.

 function getSettings(): IWebEmbedOnekeyAppSettings | undefined {
-  const settings = globalThis.WEB_EMBED_ONEKEY_APP_SETTINGS;
-  return settings;
+  const settings = globalThis.WEB_EMBED_ONEKEY_APP_SETTINGS;
+  if (!settings) return undefined;
+  
+  return {
+    themeVariant: settings.themeVariant || 'default',
+    localeVariant: settings.localeVariant || 'en',
+    revenuecatApiKey: settings.revenuecatApiKey
+  };
 }
packages/kit/src/views/Prime/purchasesSdk/PurchasesSdkWebEmbed.ts (1)

4-12: 🛠️ Refactor suggestion

Add type safety and improve error handling

The getApiKey method needs improvements:

  1. Empty string fallback is risky
  2. Missing type assertion for settings
  3. Environment check could be more explicit

Here's a safer implementation:

  async getApiKey(): Promise<string> {
    const settings = globalThis.WEB_EMBED_ONEKEY_APP_SETTINGS;
-   if (process.env.NODE_ENV !== 'production') {
+   const isDevelopment = process.env.NODE_ENV === 'development';
+   if (isDevelopment) {
      if (!settings?.revenuecatApiKey) {
-       return process.env.REVENUECAT_API_KEY_WEB_SANDBOX || '';
+       const sandboxKey = process.env.REVENUECAT_API_KEY_WEB_SANDBOX;
+       if (!sandboxKey) {
+         throw new Error('Sandbox API key not found');
+       }
+       return sandboxKey;
      }
    }
-   return settings?.revenuecatApiKey || '';
+   const apiKey = settings?.revenuecatApiKey;
+   if (!apiKey) {
+     throw new Error('API key not found');
+   }
+   return apiKey;
  }
apps/web-embed/pages/PageIndex.tsx (1)

7-17: 🧹 Nitpick (assertive)

Improve component structure and styling

Move inline styles to a CSS module and refactor navigation links.

Here's a cleaner implementation:

+ const NAV_ITEMS = [
+   { path: EWebEmbedRoutePath.webEmbedApi, label: 'WebEmbedApi' },
+   { path: EWebEmbedRoutePath.primePurchase, label: 'PrimePurchase' },
+ ];

  return (
-   <div style={{ padding: '20px' }}>
+   <div className={styles.container}>
      <h1>PageIndex</h1>
      <ul>
-       <li>
-         <Link to={EWebEmbedRoutePath.webEmbedApi}>WebEmbedApi</Link>
-       </li>
-       <li>
-         <Link to={EWebEmbedRoutePath.primePurchase}>PrimePurchase</Link>
-       </li>
+       {NAV_ITEMS.map(({ path, label }) => (
+         <li key={path}>
+           <Link to={path}>{label}</Link>
+         </li>
+       ))}
      </ul>
    </div>
📝 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.

const NAV_ITEMS = [
  { path: EWebEmbedRoutePath.webEmbedApi, label: 'WebEmbedApi' },
  { path: EWebEmbedRoutePath.primePurchase, label: 'PrimePurchase' },
];

return (
  <div className={styles.container}>
    <h1>PageIndex</h1>
    <ul>
      {NAV_ITEMS.map(({ path, label }) => (
        <li key={path}>
          <Link to={path}>{label}</Link>
        </li>
      ))}
    </ul>
  </div>
);
apps/desktop/App.tsx (1)

15-16: 🧹 Nitpick (assertive)

Remove commented code

Delete unused commented export.

 export default withSentryHOC(KitProvider, SentryErrorBoundaryFallback);
- // export default KitProvider;
📝 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.

export default withSentryHOC(KitProvider, SentryErrorBoundaryFallback);
apps/web-embed/pages/WebEmbedAppProvider.tsx (1)

15-16: 🛠️ Refactor suggestion

Replace type casting with proper types

Remove 'any' type casting and use proper types for theme and locale.

- theme={(settings?.themeVariant as any) || 'light'}
- locale={(settings?.localeVariant as any) || 'en-US'}
+ theme={settings?.themeVariant || 'light'}
+ locale={settings?.localeVariant || 'en-US'}

Add type definitions:

type ThemeVariant = 'light' | 'dark';
type LocaleVariant = 'en-US' | 'zh-CN'; // add other supported locales
packages/kit/src/views/Prime/hooks/useFetchPrimeUserInfo.ts (1)

9-16: 🧹 Nitpick (assertive)

Add error handling to fetchPrimeUserInfo.

The function should catch and handle potential API errors.

 const fetchPrimeUserInfo = useCallback(async () => {
   if (isReady && user?.id) {
-    const userInfo =
-      await backgroundApiProxy.servicePrime.apiFetchPrimeUserInfo();
-    return userInfo;
+    try {
+      const userInfo =
+        await backgroundApiProxy.servicePrime.apiFetchPrimeUserInfo();
+      return userInfo;
+    } catch (error) {
+      console.error('Failed to fetch Prime user info:', error);
+      throw error;
+    }
   }
   return undefined;
 }, [isReady, user?.id]);
📝 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.

  const fetchPrimeUserInfo = useCallback(async () => {
    if (isReady && user?.id) {
      try {
        const userInfo =
          await backgroundApiProxy.servicePrime.apiFetchPrimeUserInfo();
        return userInfo;
      } catch (error) {
        console.error('Failed to fetch Prime user info:', error);
        throw error;
      }
    }
    return undefined;
  }, [isReady, user?.id]);
packages/shared/types/prime/primeTypes.ts (1)

1-11: 🧹 Nitpick (assertive)

Add JSDoc documentation to types.

Add descriptions to help other developers understand the purpose and usage of these types.

+/**
+ * Information about a user's Prime subscription status
+ */
 export type IPrimeSubscriptionInfo = {
   isActive: boolean;
   expiresAt: number;
 };
+
+/**
+ * Comprehensive user information including login status and subscription details
+ */
 export type IPrimeUserInfo = {
   isLoggedIn: boolean;
   email: string | undefined;
   privyUserId: string | undefined;
   subscriptionManageUrl: string | undefined;
   primeSubscription: IPrimeSubscriptionInfo | undefined;
 };
📝 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.

/**
 * Information about a user's Prime subscription status
 */
export type IPrimeSubscriptionInfo = {
  isActive: boolean;
  expiresAt: number;
};

/**
 * Comprehensive user information including login status and subscription details
 */
export type IPrimeUserInfo = {
  isLoggedIn: boolean;
  email: string | undefined;
  privyUserId: string | undefined;
  subscriptionManageUrl: string | undefined;
  primeSubscription: IPrimeSubscriptionInfo | undefined;
};
packages/kit/src/views/Prime/purchasesSdk/PurchasesSdkWeb.ts (2)

13-15: 🧹 Nitpick (assertive)

Improve error message clarity

Make the error message more specific about which API key is missing.

-      throw new Error('No REVENUECAT api key found');
+      throw new Error(
+        `RevenueCat API key not found for ${
+          devSettings?.settings?.usePrimeSandboxPayment ? 'sandbox' : 'production'
+        } environment`
+      );
📝 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.

    if (!apiKey) {
-      throw new Error('No REVENUECAT api key found');
+      throw new Error(
+        `RevenueCat API key not found for ${
+          devSettings?.settings?.usePrimeSandboxPayment ? 'sandbox' : 'production'
+        } environment`
+      );
    }

9-12: 💡 Verification agent

🧩 Analysis chain

Add fallback for missing environment variables

The code assumes environment variables exist. Add explicit checks for both production and sandbox API keys.


🏁 Script executed:

#!/bin/bash
# Check if environment variables are defined in .env files
rg "REVENUECAT_API_KEY_WEB" -l
rg "REVENUECAT_API_KEY_WEB_SANDBOX" -l

Length of output: 841


Action Required: Implement Explicit Fallback for Missing Environment Variables

The current implementation in packages/kit/src/views/Prime/purchasesSdk/PurchasesSdkWeb.ts directly retrieves API keys without checking if they are defined. Even though the environment variables exist in various parts of the repo, the code does not safeguard against a missing key.

Consider updating the code as follows:

  • Check if process.env.REVENUECAT_API_KEY_WEB is defined before proceeding. If it’s missing, provide a clear error message or a safe fallback.
  • Likewise, when the sandbox mode is enabled, verify process.env.REVENUECAT_API_KEY_WEB_SANDBOX is present.
  • Example adjustment:
const prodApiKey = process.env.REVENUECAT_API_KEY_WEB;
if (!prodApiKey) {
  throw new Error('Missing RevenueCat API key for production.');
}

let apiKey = prodApiKey;

if (devSettings?.settings?.usePrimeSandboxPayment) {
  const sandboxApiKey = process.env.REVENUECAT_API_KEY_WEB_SANDBOX;
  if (!sandboxApiKey) {
    throw new Error('Missing RevenueCat API key for sandbox mode.');
  }
  apiKey = sandboxApiKey;
}

These explicit checks will enhance security and help prevent runtime issues if an expected environment variable is missing.

packages/kit-bg/src/dbs/simple/entity/SimpleDbEntityPrime.ts (2)

5-7: 🛠️ Refactor suggestion

Consider adding token expiry

Add expiration tracking for the auth token to enhance security.

 export interface ISimpleDBPrime {
   authToken: string;
+  tokenExpiry: number;
 }

19-25: 🛠️ Refactor suggestion

Add token validation

Add input validation for the auth token before saving.

 @backgroundMethod()
 async saveAuthToken(authToken: string) {
+  if (!authToken || typeof authToken !== 'string') {
+    throw new Error('Invalid auth token');
+  }
   await this.setRawData((v) => ({
     ...v,
     authToken,
   }));
 }
development/env.js (1)

17-18: 🧹 Nitpick (assertive)

Consider using a debug logger

Replace console.log with a proper debug logger for better control over development logging.

-  // console.log('process.env', process.env);
+  // debug('Environment variables: %O', process.env);
📝 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.

  // debug('Environment variables: %O', process.env);
packages/shared/src/googlePlayService/googlePlayService.android.ts (2)

11-15: 🧹 Nitpick (assertive)

Improve logging format

Use structured logging for better parsing and filtering.

-      console.log(
-        'googlePlayService: isAvailable result >>>>> ',
-        hasPlayServices,
-      );
+      console.log({
+        service: 'googlePlayService',
+        method: 'isAvailable',
+        result: hasPlayServices
+      });
📝 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.

      console.log({
        service: 'googlePlayService',
        method: 'isAvailable',
        result: hasPlayServices
      });
      return hasPlayServices;

17-18: 🧹 Nitpick (assertive)

Add error type information

Log the error type for better debugging.

-      console.error('googlePlayService: isAvailable error >>>>> ', e);
+      console.error({
+        service: 'googlePlayService',
+        method: 'isAvailable',
+        error: e instanceof Error ? e.message : String(e),
+        errorType: e?.constructor?.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.

      console.error({
        service: 'googlePlayService',
        method: 'isAvailable',
        error: e instanceof Error ? e.message : String(e),
        errorType: e?.constructor?.name
      });
      return false;
packages/components/src/content/LottieView/type.tsx (1)

17-17: 🛠️ Refactor suggestion

Remove redundant type union

Line 17 is redundant since width and height are already optional in lines 15-16.

-  } & ({ width?: StackProps['width'] } | { height?: StackProps['height'] });
📝 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.


apps/ext/src/ui/renderApp.tsx (1)

8-8: 🧹 Nitpick (assertive)

Move import to group

Move this import to the existing import group below to maintain consistent ordering.

-import { SentryErrorBoundaryFallback } from '@onekeyhq/kit/src/components/ErrorBoundary';
 import {
   initSentry,
   withSentryHOC,
 } from '@onekeyhq/shared/src/modules3rdParty/sentry';
+import { SentryErrorBoundaryFallback } from '@onekeyhq/kit/src/components/ErrorBoundary';
📝 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.

import {
  initSentry,
  withSentryHOC,
} from '@onekeyhq/shared/src/modules3rdParty/sentry';
import { SentryErrorBoundaryFallback } from '@onekeyhq/kit/src/components/ErrorBoundary';
packages/kit/src/views/Prime/hooks/usePrivyUniversalV2/usePrivyUniversalV2Types.ts (1)

18-19: 🧹 Nitpick (assertive)

Replace 'any' with a specific error type.

Define a custom error type or use Error type for better type safety.

-    onError?: (error: any) => void;
+    onError?: (error: Error) => void;
📝 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.

    onError?: (error: Error) => void;
  }) => {
packages/components/src/primitives/Icon/react/colored/OnekeyPrimeDark.tsx (1)

9-9: 🧹 Nitpick (assertive)

Improve accessibility and gradient ID.

Add aria-label and use more descriptive gradient ID.

-  <Svg viewBox="0 0 24 24" fill="none" accessibilityRole="image" {...props}>
+  <Svg viewBox="0 0 24 24" fill="none" accessibilityRole="image" aria-label="OneKey Prime Dark" {...props}>
-        id="a"
+        id="prime_dark_gradient"

Also applies to: 19-19

packages/kit/src/views/Prime/hooks/usePrimeAuthV2.tsx (1)

14-20: 🧹 Nitpick (assertive)

Add error logging for failed API calls.

The error handling is good, but we should log API failures.

 const logoutWithApi: () => Promise<void> = useCallback(async () => {
   try {
     await backgroundApiProxy.servicePrime.apiLogout();
   } catch (error) {
+    console.error('Prime logout API failed:', error);
   } finally {
     await logout();
   }
 }, [logout]);
📝 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.

  const logoutWithApi: () => Promise<void> = useCallback(async () => {
    try {
      await backgroundApiProxy.servicePrime.apiLogout();
    } catch (error) {
      console.error('Prime logout API failed:', error);
    } finally {
      await logout();
    }
  }, [logout]);
packages/kit/src/views/Prime/pages/PrimeDashboard/PrimeLottieAnimation.tsx (1)

22-35: 🧹 Nitpick (assertive)

Consider using transform3d for better performance.

Using CSS transform3d triggers hardware acceleration.

 <Stack
   style={{
     position: 'absolute',
     top: '50%',
-    transform: 'translateY(-50%)',
+    transform: 'translate3d(0, -50%, 0)',
     left: 0,
     right: 0,
     paddingBottom: '100%',
   }}
 >
📝 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.

  return (
    <Stack
      style={{
        position: 'absolute',
        top: '50%',
        transform: 'translate3d(0, -50%, 0)',
        left: 0,
        right: 0,
        paddingBottom: '100%',
      }}
    >
      <PrimeLottie />
    </Stack>
  );
packages/kit/src/views/Prime/components/PrivyProvider.native.tsx (2)

18-23: 🧹 Nitpick (assertive)

Improve error messages.

Add more context to error messages to help with debugging.

   if (!appId) {
-    throw new Error('PRIVY_APP_ID is not set');
+    throw new Error('Configuration error: PRIVY_APP_ID environment variable is required');
   }
   if (!clientId) {
-    throw new Error('PRIVY_MOBILE_CLIENT_ID is not set');
+    throw new Error('Configuration error: PRIVY_MOBILE_CLIENT_ID environment variable is required');
   }

14-17: 🛠️ Refactor suggestion

Move hardcoded values to constants.

Hardcoded IDs should be in a constants file for better maintainability.

+const DEFAULT_APP_ID = 'cm6c9xup40017zyrnnp8zh0bt';
+const DEFAULT_CLIENT_ID = 'client-WY5gESiXQgTXogYv2M8iCM3LaaDDaKAdigE9Bg7a9pr1W';
+
 export function PrivyProvider({ children }: { children: React.ReactNode }) {
-  const appId = process.env.PRIVY_APP_ID || 'cm6c9xup40017zyrnnp8zh0bt';
+  const appId = process.env.PRIVY_APP_ID || DEFAULT_APP_ID;
   const clientId =
-    process.env.PRIVY_MOBILE_CLIENT_ID ||
-    'client-WY5gESiXQgTXogYv2M8iCM3LaaDDaKAdigE9Bg7a9pr1W';
+    process.env.PRIVY_MOBILE_CLIENT_ID || DEFAULT_CLIENT_ID;
📝 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.

const DEFAULT_APP_ID = 'cm6c9xup40017zyrnnp8zh0bt';
const DEFAULT_CLIENT_ID = 'client-WY5gESiXQgTXogYv2M8iCM3LaaDDaKAdigE9Bg7a9pr1W';

export function PrivyProvider({ children }: { children: React.ReactNode }) {
  const appId = process.env.PRIVY_APP_ID || DEFAULT_APP_ID;
  const clientId =
    process.env.PRIVY_MOBILE_CLIENT_ID || DEFAULT_CLIENT_ID;
  // ...rest of the implementation
}
development/scripts/web-embed.js (2)

30-33: ⚠️ Potential issue

Remove API key logging

Logging API keys is a security risk. They could appear in build logs or console output.

-  console.log(
-    'process.env.REVENUECAT_API_KEY_WEB_SANDBOX',
-    process.env.REVENUECAT_API_KEY_WEB_SANDBOX,
-  );
📝 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.



7-7: 🧹 Nitpick (assertive)

Add API key validation

Check if required API keys exist before building.

 require('../env');
+if (!process.env.REVENUECAT_API_KEY_WEB_SANDBOX) {
+  console.error('Missing REVENUECAT_API_KEY_WEB_SANDBOX');
+  exit(1);
+}

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

packages/kit/src/views/Prime/hooks/usePrivyUniversal/usePrivyUniversalTypes.ts (1)

5-29: 🧹 Nitpick (assertive)

Add JSDoc comments

Add documentation to explain the type's purpose and properties.

+/**
+ * Universal interface for Privy authentication across native and web platforms.
+ * @property native - Native platform specific authentication methods and state
+ * @property web - Web platform specific authentication methods and state
+ * @property userEmail - User's email address
+ * @property privyUserId - Unique Privy user identifier
+ * @property authenticated - Authentication status
+ * @property isReady - Initialization status
+ * @property logout - Logout method
+ * @property getAccessToken - Access token retrieval method
+ */
 export type IUsePrivyUniversal = {
📝 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.

/**
 * Universal interface for Privy authentication across native and web platforms.
 * @property native - Native platform specific authentication methods and state
 * @property web - Web platform specific authentication methods and state
 * @property userEmail - User's email address
 * @property privyUserId - Unique Privy user identifier
 * @property authenticated - Authentication status
 * @property isReady - Initialization status
 * @property logout - Logout method
 * @property getAccessToken - Access token retrieval method
 */
export type IUsePrivyUniversal = {
  native:
    | {
        error: Error | null | undefined;
        user: PrivyUser | null | undefined;
        login: ((config: LoginUIConfig) => void) | undefined;
      }
    | undefined;
  web:
    | {
        user: User | null | undefined;
        login:
          | ((options?: LoginModalOptions | React.MouseEvent<any, any>) => void)
          | undefined;
        updateEmail: (() => void) | undefined; // web only
        updatePhone: (() => void) | undefined; // web only
      }
    | undefined;
  userEmail: string | undefined;
  privyUserId: string | undefined;
  authenticated: boolean;
  isReady: boolean;
  logout: () => Promise<void>;
  getAccessToken: () => Promise<string | null>;
};
packages/shared/src/modules3rdParty/sentry/index.desktop.ts (1)

32-34: 🧹 Nitpick (assertive)

Improve error logging

Replace console.error with proper error tracking in production.

     onError: (error, info) => {
-      console.error('error', error, info);
+      if (process.env.NODE_ENV === 'development') {
+        console.error('error', error, info);
+      }
+      Sentry.captureException(error, { extra: info });
     },
packages/shared/src/modules3rdParty/sentry/index.ext.ts (1)

31-36: 🧹 Nitpick (assertive)

Extract shared error handling logic

This code is duplicated in index.desktop.ts. Create a shared utility.

Create a new file errorHandling.ts:

export const createErrorBoundaryOptions = (errorBoundaryFallback?: FallbackRender) => ({
  onError: (error: Error, info: any) => {
    if (process.env.NODE_ENV === 'development') {
      console.error('error', error, info);
    }
    Sentry.captureException(error, { extra: info });
  },
  fallback: errorBoundaryFallback,
});

Then use it in both files:

-  Sentry.withErrorBoundary(Sentry.withProfiler(Component), {
-    onError: (error, info) => {
-      console.error('error', error, info);
-    },
-    fallback: errorBoundaryFallback,
-  });
+  Sentry.withErrorBoundary(
+    Sentry.withProfiler(Component),
+    createErrorBoundaryOptions(errorBoundaryFallback)
+  );
packages/kit/src/views/Prime/components/PrimeDeviceLogoutAlertDialog.tsx (2)

25-28: 🧹 Nitpick (assertive)

Fix grammar in alert message

The text has a grammar error. Change "This device been deactivated" to "This device has been deactivated".

-          This device been deactivated from another device. If this wasn't you,
+          This device has been deactivated from another device. If this wasn't you,

34-36: 🧹 Nitpick (assertive)

Remove empty callback

The cancel button has an empty async callback. Since no action is needed, you can remove the callback entirely.

-        onCancel={async () => {
-          //
-        }}
📝 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.


packages/kit/src/views/Prime/hooks/usePrivyUniversalV2/usePrivyUniversalV2.ts (1)

13-15: 🧹 Nitpick (assertive)

Add type for error parameter

The error callback lacks type information. Consider adding a specific error type to improve type safety.

-        onError: (error) => {
+        onError: (error: Error) => {
packages/kit/src/views/Prime/hooks/usePrivyUniversalV2/usePrivyUniversalV2.native.ts (2)

5-39: 🧹 Nitpick (assertive)

Consider sharing common logic

This hook shares significant code with its web counterpart. Consider extracting common logic into a shared utility function.


33-36: 🧹 Nitpick (assertive)

Add null check for user ID

The user ID access could be unsafe. Add a null check or use nullish coalescing.

-          id: user?.id || '',
+          id: user?.id ?? '',
📝 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.

    user: authenticated
      ? {
          id: user?.id ?? '',
        }
packages/kit/src/provider/Container/DialogLoadingContainer/DialogLoadingContainer.tsx (2)

17-22: 🧹 Nitpick (assertive)

Add error handling for dialog operations

The showFn should handle potential failures in dialog operations.

 const showFn = async (
   payload: IAppEventBusPayload[EAppEventBusNames.ShowDialogLoading],
 ) => {
+  try {
     await hideFn();
     dialogRef.current = Dialog.loading(payload);
+  } catch (error) {
+    console.error('Failed to show loading dialog:', error);
+  }
 };
📝 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.

    const showFn = async (
      payload: IAppEventBusPayload[EAppEventBusNames.ShowDialogLoading],
    ) => {
      try {
        await hideFn();
        dialogRef.current = Dialog.loading(payload);
      } catch (error) {
        console.error('Failed to show loading dialog:', error);
      }
    };

14-16: 🧹 Nitpick (assertive)

Add cleanup for in-flight async operations

The async hideFn could leak if the component unmounts during execution.

 const hideFn = async () => {
+  if (!dialogRef.current) return;
   await dialogRef.current?.close();
+  dialogRef.current = null;
 };
📝 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.

    const hideFn = async () => {
      if (!dialogRef.current) return;
      await dialogRef.current?.close();
      dialogRef.current = null;
    };
packages/shared/src/modules3rdParty/sentry/index.ts (2)

27-28: 🧹 Nitpick (assertive)

Define specific type for breadcrumb args

Using any type reduces type safety. Consider using Sentry's breadcrumb types.

-export const addBreadcrumb = (args: any) => {};
+import type { Breadcrumb } from '@sentry/types';
+export const addBreadcrumb = (args: Breadcrumb) => {};
📝 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.

// eslint-disable-next-line @typescript-eslint/no-unused-vars
import type { Breadcrumb } from '@sentry/types';
export const addBreadcrumb = (args: Breadcrumb) => {};

35-37: 🧹 Nitpick (assertive)

Enhance error logging

Add more context to error logs for better debugging.

 onError: (error, info) => {
-  console.error('error', error, info);
+  console.error('Sentry error boundary caught error:', {
+    error,
+    componentStack: info.componentStack,
+  });
 },
📝 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.

    onError: (error, info) => {
      console.error('Sentry error boundary caught error:', {
        error,
        componentStack: info.componentStack,
      });
    },
development/webpack/webpack.analyzer.config.js (1)

8-9: 🧹 Nitpick (assertive)

Improve log readability

Make console logs more distinct and informative.

-console.log('ENABLE_ANALYZER_HTML_REPORT >>>>>> ', ENABLE_ANALYZER_HTML_REPORT);
-console.log('ENABLE_ANALYZER >>>>>> ', ENABLE_ANALYZER);
+console.log('[Webpack Analyzer] HTML Report enabled:', ENABLE_ANALYZER_HTML_REPORT);
+console.log('[Webpack Analyzer] Analyzer enabled:', ENABLE_ANALYZER);
📝 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.

console.log('[Webpack Analyzer] HTML Report enabled:', ENABLE_ANALYZER_HTML_REPORT);
console.log('[Webpack Analyzer] Analyzer enabled:', ENABLE_ANALYZER);
packages/kit/src/views/Prime/hooks/usePrivyUniversal/usePrivyUniversal.ts (2)

31-32: 🧹 Nitpick (assertive)

Add null checks for user properties

Add optional chaining to prevent potential runtime errors.

-userEmail: privy.user?.email?.address,
-privyUserId: privy.user?.id,
+userEmail: privy.user?.email?.address ?? null,
+privyUserId: privy.user?.id ?? null,
📝 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.

      userEmail: privy.user?.email?.address ?? null,
      privyUserId: privy.user?.id ?? null,

16-19: 🧹 Nitpick (assertive)

Improve login completion logging

Replace console log with proper logging utility and add environment check.

 onComplete(...args) {
-  console.log('privy login complete >>> ', args);
+  if (process.env.NODE_ENV !== 'production') {
+    console.log('[Privy] Login completed:', args);
+  }
 },
📝 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.

    onComplete(...args) {
      if (process.env.NODE_ENV !== 'production') {
        console.log('[Privy] Login completed:', args);
      }
    },
  });
packages/kit/src/views/Prime/hooks/usePrivyUniversal/usePrivyUniversal.native.ts (2)

12-12: 🧹 Nitpick (assertive)

Remove console.log statement

Remove debug logging before deploying to production.

-  console.log('usePrivyUniversal: isReady >>>>> ', isReady);
📝 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.

// (The console.log statement has been removed)

16-21: 🧹 Nitpick (assertive)

Use type guard instead of type assertion

Replace unsafe type assertion with a type guard for better type safety.

-      const emailUser = user?.linked_accounts?.find(
-        (item) => item.type === 'email',
-      );
-      if (emailUser) {
-        const address: string = (emailUser as { address: string }).address;
-        return address;
+      const emailUser = user?.linked_accounts?.find(
+        (item): item is { type: 'email'; address: string } => 
+          item.type === 'email' && 'address' in item
+      );
+      if (emailUser) {
+        return emailUser.address;
packages/kit/src/views/Prime/components/PrivyProvider.tsx (1)

11-14: ⚠️ Potential issue

Remove hardcoded credentials

Move fallback credentials to environment variables. Hardcoding sensitive values in source code is a security risk.

-  const appId = process.env.PRIVY_APP_ID || 'cm6c9xup40017zyrnnp8zh0bt';
-  const clientId =
-    process.env.PRIVY_MOBILE_CLIENT_ID ||
-    'client-WY5gESiXQgTXogYv2M8iCM3LaaDDaKAdigGMM4dCxSzy6';
+  const appId = process.env.PRIVY_APP_ID;
+  const clientId = process.env.PRIVY_MOBILE_CLIENT_ID;
packages/kit/src/views/Prime/hooks/PrimeSignupTest.tsx (2)

8-8: 🧹 Nitpick (assertive)

Remove hardcoded test email

Remove the hardcoded email address from the initial state.

-  const [email, setEmail] = useState('[email protected]');
+  const [email, setEmail] = useState('');
📝 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.

  const [email, setEmail] = useState('');

21-25: 🛠️ Refactor suggestion

Improve error handling

Console logging isn't sufficient for error handling. Display error message to user.

    onError(error) {
-      console.log('error', error);
-      // show a toast, update form errors, etc...
+      Toast.error({
+        title: 'Login Error',
+        message: error.message,
+      });
    },
📝 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.

    onError(error) {
      Toast.error({
        title: 'Login Error',
        message: error.message,
      });
    },
  });
development/envExposedToClient.js (1)

31-31: 🧹 Nitpick (assertive)

Add links to workflow files

Make the comment more helpful by adding direct links to the workflow files.

- // ***        also update Inject Environment Variables at release-ios.yml, release-android      ***
+ // ***        also update Inject Environment Variables at:
+ // ***        - .github/workflows/release-ios.yml
+ // ***        - .github/workflows/release-android.yml                                          ***
📝 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.

  // ***        also update Inject Environment Variables at:
  // ***        - .github/workflows/release-ios.yml
  // ***        - .github/workflows/release-android.yml                                          ***
packages/kit/src/views/Developer/pages/Gallery/Components/stories/WebView.tsx (2)

22-24: ⚠️ Potential issue

Remove hardcoded test values

Replace hardcoded test values with proper test data or environment variables.

-        primeUserId: 'hello-world-1234567890',
-        primeUserEmail: '[email protected]',
+        primeUserId: process.env.PRIME_TEST_USER_ID,
+        primeUserEmail: process.env.PRIME_TEST_USER_EMAIL,
📝 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.

        primeUserId: process.env.PRIME_TEST_USER_ID,
        primeUserEmail: process.env.PRIME_TEST_USER_EMAIL,
      },

20-20: 🛠️ Refactor suggestion

Fix type casting

Avoid using any type. Define proper type for hashRoutePath.

-      hashRoutePath: hashRoutePath as any,
+      hashRoutePath: hashRoutePath as EWebEmbedRoutePath,
📝 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.

      hashRoutePath: hashRoutePath as EWebEmbedRoutePath,
packages/shared/src/modules3rdParty/sentry/index.native.ts (1)

44-53: 🧹 Nitpick (assertive)

Add JSDoc comments

The implementation looks good. Add documentation for the new parameter.

+/**
+ * HOC that wraps a component with Sentry error boundary
+ * @param Component - The component to wrap
+ * @param errorBoundaryFallback - Optional custom fallback UI when an error occurs
+ * @returns Wrapped component with error boundary
+ */
 export const withSentryHOC = (
   Component: ComponentType<any>,
   errorBoundaryFallback?: FallbackRender,
 ): ComponentType<any> =>
📝 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.

/**
 * HOC that wraps a component with Sentry error boundary
 * @param Component - The component to wrap
 * @param errorBoundaryFallback - Optional custom fallback UI when an error occurs
 * @returns Wrapped component with error boundary
 */
export const withSentryHOC = (
  Component: ComponentType<any>,
  errorBoundaryFallback?: FallbackRender,
): ComponentType<any> =>
  withErrorBoundary(withProfiler(wrap(Component)), {
    onError: (error, info) => {
      console.error('error', error, info);
    },
    fallback: errorBoundaryFallback,
  });
development/webpack/utils.js (1)

6-6: 🛠️ Refactor suggestion

Remove debug console.log

Debug logs should not be committed to production code. They clutter the console.

-  console.log('createResolveExtensions>>>>>>', platform, configName);
📝 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.


packages/kit/src/views/Prime/pages/PrimeDashboard/PrimeUserInfo.tsx (1)

33-36: 🧹 Nitpick (assertive)

Remove commented console.log statements

Clean up unused debug code.

-        onPress={() => {
-          // console.log(privy?.web?.user);
-          // console.log(privy?.native?.user);
-        }}
+        onPress={() => {}}
📝 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.

        onPress={() => {}}
packages/kit/src/views/Prime/components/PrimeHeaderIconButton/PrimeHeaderIconButton.tsx (1)

27-31: 🧹 Nitpick (assertive)

Improve error message clarity

The error message "Prime not ready" is too technical. Make it more user-friendly.

-        title: 'Prime not ready.',
+        title: 'Please wait while Prime initializes...',
📝 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.

      Toast.message({
-        title: 'Prime not ready.',
+        title: 'Please wait while Prime initializes...',
      });
      return;
    }
packages/kit-bg/src/services/ServiceNotification/NotificationProvider/NotificationProvider.web.ts (1)

18-18: 💡 Verification agent

🧩 Analysis chain

Verify WebSocket provider initialization

The WebSocket provider is now initialized but the implementation is missing. Ensure proper error handling and connection management.


🏁 Script executed:

#!/bin/bash
# Check if WebSocket implementation exists
rg -A 5 "initWebSocketProvider|WebSocket" 

Length of output: 30271


WebSocket Provider Initialization Needs Further Implementation

  • The call to initWebSocketProvider() in NotificationProvider.web.ts properly initiates the WebSocket provider.
  • The base class (NotificationProviderBase) and PushProviderWebSocket show that error handling and connection events (error, reconnect, disconnect, etc.) are managed.
  • However, key methods in NotificationProvider.web.ts (e.g. showAndFocusApp) remain unimplemented, which could affect proper error handling or UI response in the web environment.
packages/kit-bg/src/states/jotai/atoms/prime.ts (1)

34-38: 🧹 Nitpick (assertive)

Add email validation type

The email field should use a more specific type for validation.

export type IPrimeLoginDialogAtomPasswordData = {
  isRegister?: boolean;
-  email: string;
+  email: `${string}@${string}.${string}`;
  promiseId: number;
};
📝 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.

export type IPrimeLoginDialogAtomPasswordData = {
  isRegister?: boolean;
  email: `${string}@${string}.${string}`;
  promiseId: number;
};
packages/components/src/forms/OTPInput/index.tsx (1)

42-72: 🛠️ Refactor suggestion

Add accessibility props

The OTP input needs accessibility support for screen readers.

    <OtpInput
      ref={ref}
+     accessibilityLabel="Enter verification code"
+     accessibilityHint="Enter the code sent to your email"
      theme={{
📝 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.

  return (
    <OtpInput
      ref={ref}
      accessibilityLabel="Enter verification code"
      accessibilityHint="Enter the code sent to your email"
      theme={{
        pinCodeTextStyle: {
          fontSize: 20,
          fontWeight: 'bold',
          color: theme.text.val,
        },
        pinCodeContainerStyle: {
          width: 50,
          height: 50,
          borderWidth: 1,
          borderColor:
            innerStatus === 'error' ? theme.red8.val : theme.neutral7.val,
        },
        filledPinCodeContainerStyle: {
          borderWidth: 2,
          backgroundColor: theme.gray2.val,
        },
        focusedPinCodeContainerStyle: {
          borderWidth: 2,
          borderColor:
            innerStatus === 'error' ? theme.red8.val : theme.borderActive.val,
        },
      }}
      focusColor={theme.text.val}
      numberOfDigits={numberOfDigits}
      {...rest}
    />
  );
packages/kit/src/components/ErrorBoundary/index.tsx (2)

50-69: 🛠️ Refactor suggestion

Utilize all provided props for better error reporting.

The function receives componentStack, eventId, and resetError props but doesn't use them. These could provide valuable debug information and recovery options.

 function SentryErrorBoundaryFallback({
   error,
   componentStack,
   eventId,
   resetError,
 }: {
   error: unknown;
   componentStack: string;
   eventId: string;
   resetError(): void;
 }) {
   return (
-    <SafeAreaView>
-      <Text>
-        {(error as Error | undefined)?.message ||
-          'unknown error by error boundary'}
-      </Text>
+    <SafeAreaView style={{ padding: 16 }}>
+      <Text style={{ fontSize: 16, color: 'red' }}>
+        {(error as Error | undefined)?.message || 'Unknown Error'}
+      </Text>
+      <Text style={{ marginTop: 8, fontSize: 14 }}>Event ID: {eventId}</Text>
+      <Text style={{ marginTop: 8, fontSize: 14 }}>{componentStack}</Text>
+      <Button onPress={resetError}>Try Again</Button>
     </SafeAreaView>
   );
 }
📝 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.

function SentryErrorBoundaryFallback({
  error,
  componentStack,
  eventId,
  resetError,
}: {
  error: unknown;
  componentStack: string;
  eventId: string;
  resetError(): void;
}) {
  return (
    <SafeAreaView style={{ padding: 16 }}>
      <Text style={{ fontSize: 16, color: 'red' }}>
        {(error as Error | undefined)?.message || 'Unknown Error'}
      </Text>
      <Text style={{ marginTop: 8, fontSize: 14 }}>Event ID: {eventId}</Text>
      <Text style={{ marginTop: 8, fontSize: 14 }}>{componentStack}</Text>
      <Button onPress={resetError}>Try Again</Button>
    </SafeAreaView>
  );
}

37-48: 🧹 Nitpick (assertive)

Enhance error message presentation.

The error UI is basic. Consider adding:

  • Error message styling
  • Error details expansion/collapse
  • Retry button
 class ErrorBoundarySimple extends ErrorBoundaryBase {
   override render() {
     if (this.state.error) {
       return (
-        <SafeAreaView>
-          <Text>{this.state.error.message}</Text>
+        <SafeAreaView style={{ padding: 16 }}>
+          <Text style={{ fontSize: 16, color: 'red' }}>{this.state.error.message}</Text>
+          <Text style={{ marginTop: 8, fontSize: 14 }}>
+            {this.state.error.stack}
+          </Text>
+          <Button onPress={() => this.setState({ error: null })}>
+            Retry
+          </Button>
         </SafeAreaView>
       );
     }
     return this.props.children;
   }
 }
📝 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.

class ErrorBoundarySimple extends ErrorBoundaryBase {
  override render() {
    if (this.state.error) {
      return (
        <SafeAreaView style={{ padding: 16 }}>
          <Text style={{ fontSize: 16, color: 'red' }}>{this.state.error.message}</Text>
          <Text style={{ marginTop: 8, fontSize: 14 }}>
            {this.state.error.stack}
          </Text>
          <Button onPress={() => this.setState({ error: null })}>
            Retry
          </Button>
        </SafeAreaView>
      );
    }
    return this.props.children;
  }
}
packages/kit/src/views/Prime/hooks/usePrivyAuthSyncToAtom.ts (2)

75-83: ⚠️ Potential issue

Add error handling to logout operation.

The logout operation could fail silently.

 useEffect(() => {
   const fn = async () => {
+    try {
       await logout();
+    } catch (error) {
+      console.error('Failed to logout:', error);
+    }
   };
   appEventBus.on(EAppEventBusNames.PrimeLoginInvalidToken, fn);
   return () => {
     appEventBus.off(EAppEventBusNames.PrimeLoginInvalidToken, fn);
   };
 }, [logout]);
📝 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.

  useEffect(() => {
    const fn = async () => {
      try {
        await logout();
      } catch (error) {
        console.error('Failed to logout:', error);
      }
    };
    appEventBus.on(EAppEventBusNames.PrimeLoginInvalidToken, fn);
    return () => {
      appEventBus.off(EAppEventBusNames.PrimeLoginInvalidToken, fn);
    };
  }, [logout]);

32-74: ⚠️ Potential issue

Add error handling to async operations.

The async function lacks try-catch blocks. Errors could silently fail.

 useEffect(() => {
   void (async () => {
+    try {
       if (!isReady) {
         return;
       }
       let accessToken: string | null = '';
       if (authenticated) {
         accessToken = await getAccessToken();
       }

       await backgroundApiProxy.simpleDb.prime.saveAuthToken(accessToken || '');

       if (accessToken) {
         setPrimePersistAtom((v) => ({
           ...v,
           isLoggedIn: true,
           email: userEmail,
           privyUserId,
         }));
       } else {
         setPrimePersistAtom((v) => ({
           ...v,
           isLoggedIn: false,
           email: undefined,
           privyUserId: undefined,
         }));
       }

       setPrimeInitAtom((v) => ({
         ...v,
         isReady: true,
       }));
+    } catch (error) {
+      console.error('Failed to sync Privy auth state:', error);
+      setPrimeInitAtom((v) => ({
+        ...v,
+        isReady: true,
+        error: error instanceof Error ? error.message : 'Unknown error',
+      }));
+    }
   })();
 }, [
   setPrimePersistAtom,
   setPrimeInitAtom,
   authenticated,
   getAccessToken,
   isReady,
   userEmail,
   privyUserId,
 ]);
📝 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.

  useEffect(() => {
    void (async () => {
      try {
        if (!isReady) {
          return;
        }
        let accessToken: string | null = '';
        if (authenticated) {
          accessToken = await getAccessToken();
        }

        await backgroundApiProxy.simpleDb.prime.saveAuthToken(accessToken || '');

        if (accessToken) {
          setPrimePersistAtom((v) => ({
            ...v,
            isLoggedIn: true,
            email: userEmail,
            privyUserId,
          }));
        } else {
          setPrimePersistAtom((v) => ({
            ...v,
            isLoggedIn: false,
            email: undefined,
            privyUserId: undefined,
          }));
        }

        setPrimeInitAtom((v) => ({
          ...v,
          isReady: true,
        }));
      } catch (error) {
        console.error('Failed to sync Privy auth state:', error);
        setPrimeInitAtom((v) => ({
          ...v,
          isReady: true,
          error: error instanceof Error ? error.message : 'Unknown error',
        }));
      }
    })();
  }, [
    setPrimePersistAtom,
    setPrimeInitAtom,
    authenticated,
    getAccessToken,
    isReady,
    userEmail,
    privyUserId,
  ]);
apps/web-embed/pages/PageWebEmbedApi.ts (2)

53-65: ⚠️ Potential issue

Replace global flag with useRef.

Using a global flag for component state is an anti-pattern.

-let isInitExecuted = false;
 const PageWebEmbedApi = memo(() => {
+  const isInitExecuted = useRef(false);
   useEffect(() => {
-    if (isInitExecuted) {
+    if (isInitExecuted.current) {
       return;
     }
-    isInitExecuted = true;
+    isInitExecuted.current = true;
     init();
     printMessageToBody('web-embed init...');
     printMessageToBody(`${globalThis.location.href}`);
   }, []);
   return null;
 });
📝 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.

const PageWebEmbedApi = memo(() => {
  const isInitExecuted = useRef(false);
  useEffect(() => {
    if (isInitExecuted.current) {
      return;
    }
    isInitExecuted.current = true;
    init();
    printMessageToBody('web-embed init...');
    printMessageToBody(`${globalThis.location.href}`);
  }, []);
  return null;
});

9-16: ⚠️ Potential issue

Move refresh button creation into component.

Creating DOM elements in the global scope is an anti-pattern. Move this into the component.

-// create button which can refresh, append to body
-const refreshButton = document.createElement('button');
-refreshButton.textContent = 'Refresh';
-refreshButton.addEventListener('click', () => {
-  globalThis.location.reload();
-});
-document.body.appendChild(refreshButton);
+const PageWebEmbedApi = memo(() => {
+  useEffect(() => {
+    const refreshButton = document.createElement('button');
+    refreshButton.textContent = 'Refresh';
+    refreshButton.addEventListener('click', () => {
+      globalThis.location.reload();
+    });
+    document.body.appendChild(refreshButton);
+    return () => {
+      refreshButton.remove();
+    };
+  }, []);

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

development/lint/eslint-rule-force-async-bg-api.js (3)

5-6: 🧹 Nitpick (assertive)

Translate comments to English.

Keep comments in English for better maintainability.

-        type: 'problem', // 规则类型:problem, suggestion, layout
+        type: 'problem', // Rule type: problem, suggestion, layout
📝 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.

        type: 'problem', // Rule type: problem, suggestion, layout
        docs: {

23-29: 🧹 Nitpick (assertive)

Use optional chaining for better readability.

The code can be simplified using optional chaining.

-            const hasBackgroundMethod =
-              node.decorators &&
-              node.decorators.some(
-                (decorator) =>
-                  decorator.expression.type === 'CallExpression' &&
-                  decorator.expression.callee.name === 'backgroundMethod',
-              );
+            const hasBackgroundMethod = node.decorators?.some(
+              (decorator) =>
+                decorator.expression.type === 'CallExpression' &&
+                decorator.expression.callee.name === 'backgroundMethod',
+            );
📝 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.

            const hasBackgroundMethod = node.decorators?.some(
              (decorator) =>
                decorator.expression.type === 'CallExpression' &&
                decorator.expression.callee.name === 'backgroundMethod',
            );

43-50: 🧹 Nitpick (assertive)

Use optional chaining consistently.

Apply the same optional chaining pattern here.

-            const hasBackgroundMethod =
-              node.parent.type === 'MethodDefinition' &&
-              node.parent.decorators &&
-              node.parent.decorators.some(
-                (decorator) =>
-                  decorator.expression.type === 'CallExpression' &&
-                  decorator.expression.callee.name === 'backgroundMethod',
-              );
+            const hasBackgroundMethod =
+              node.parent.type === 'MethodDefinition' &&
+              node.parent.decorators?.some(
+                (decorator) =>
+                  decorator.expression.type === 'CallExpression' &&
+                  decorator.expression.callee.name === 'backgroundMethod',
+              );
📝 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.

            const hasBackgroundMethod =
              node.parent.type === 'MethodDefinition' &&
              node.parent.decorators?.some(
                (decorator) =>
                  decorator.expression.type === 'CallExpression' &&
                  decorator.expression.callee.name === 'backgroundMethod',
              );
packages/kit/src/views/Prime/pages/PrimeDashboard/PrimeBenefitsList.tsx (3)

67-67: ⚠️ Potential issue

Replace placeholder text in Analytics subtitle

The subtitle "sint occaecat cupidatat non proident" appears to be Lorem ipsum placeholder text.

Replace with actual descriptive text about the analytics feature.


38-42: 🧹 Nitpick (assertive)

Enhance Toast messages with meaningful feedback

Toast messages only repeat the title without providing useful feedback to users.

Add more descriptive messages. For example:

-          Toast.success({
-            title: 'Sync',
-          });
+          Toast.success({
+            title: 'Sync',
+            message: 'Opening sync settings...',
+          });

Also applies to: 48-52, 58-62, 68-72, 78-82


5-29: 🧹 Nitpick (assertive)

Consider extracting icon styles to a reusable component

The YStack styling for icons is repeated across multiple instances.

Create a reusable IconContainer component:

function IconContainer({ children }: { children: React.ReactNode }) {
  return (
    <YStack borderRadius="$3" borderCurve="continuous" bg="$brand4" p="$2">
      {children}
    </YStack>
  );
}
packages/kit/src/views/Setting/utils/devMode.ts (1)

74-76: ⚠️ Potential issue

Log errors in catch block

Empty catch block silently swallows errors.

Add error logging:

-    } catch (error) {
-      /* empty */
+    } catch (error) {
+      console.error('Failed to enable dev mode:', error);
packages/shared/src/utils/openUrlUtils.ts (1)

32-58: ⚠️ Potential issue

Add URL validation

The function accepts URLs without validation.

Add URL validation before opening:

function openUrlByWebviewPro({
  url,
  title,
  isWebEmbed,
  hashRoutePath,
  hashRouteQueryParams,
}: {
  url: string;
  title: string;
  isWebEmbed?: boolean;
  hashRoutePath?: EWebEmbedRoutePath;
  hashRouteQueryParams?: Record<string, string>;
}) {
+  try {
+    new URL(url);
+  } catch (e) {
+    throw new Error('Invalid URL provided');
+  }
  appGlobals.$navigationRef.current?.navigate(ERootRoutes.Modal, {
📝 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.

function openUrlByWebviewPro({
  url,
  title,
  isWebEmbed,
  hashRoutePath,
  hashRouteQueryParams,
}: {
  url: string;
  title: string;
  isWebEmbed?: boolean;
  hashRoutePath?: EWebEmbedRoutePath;
  hashRouteQueryParams?: Record<string, string>;
}) {
  try {
    new URL(url);
  } catch (e) {
    throw new Error('Invalid URL provided');
  }
  appGlobals.$navigationRef.current?.navigate(ERootRoutes.Modal, {
    screen: EModalRoutes.WebViewModal,
    params: {
      screen: EModalWebViewRoutes.WebView,
      params: {
        url,
        title,
        isWebEmbed,
        hashRoutePath,
        hashRouteQueryParams,
      },
    },
  });
}
packages/kit-bg/src/services/ServiceBase.ts (2)

73-83: 🛠️ Refactor suggestion

Improve error handling in withDialogLoading

The function swallows errors silently.

Add error handling:

  async withDialogLoading<T>(
    payload: IAppEventBusPayload[EAppEventBusNames.ShowDialogLoading],
    fn: () => Promise<T>,
  ) {
    try {
      this.showDialogLoading(payload);
      return await fn();
    } catch (error) {
+      console.error('Operation failed:', error);
+      throw error;
    } finally {
      this.hideDialogLoading();
    }
  }

63-67: 🧹 Nitpick (assertive)

Add return type annotation

Method lacks return type annotation.

Add void return type:

-  showDialogLoading(
+  showDialogLoading(): void {
    payload: IAppEventBusPayload[EAppEventBusNames.ShowDialogLoading],
  ) {

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

packages/kit/src/views/Prime/hooks/usePrimeAuth.ts (1)

38-38: 🧹 Nitpick (assertive)

Remove debug console.log statement.

Production code should not contain debug logging.

-      console.log('prime email >>> ', email);
📝 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.


packages/kit/src/views/Prime/components/PrimeLoginEmailDialog/PrimeLoginEmailDialog.tsx (2)

51-59: 🧹 Nitpick (assertive)

Enhance email validation error messages

The error messages could be more user-friendly and internationalized.

-                  return 'email is required';
+                  return intl.formatMessage({ id: 'msg__email_required' });
-                  return 'invalid email';
+                  return intl.formatMessage({ id: 'msg__invalid_email' });

75-76: 🧹 Nitpick (assertive)

Consider debouncing the trim operation

The trim operation on every text change could affect performance with rapid typing.

-              onChangeText={(text) => text?.trim() ?? text}
+              onChangeText={useCallback(
+                (text) => text?.trim() ?? text,
+                []
+              )}

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

packages/kit/src/provider/index.tsx (2)

55-59: 🛠️ Refactor suggestion

Add font loading error handling

The useFonts hook result should be checked to handle font loading failures gracefully.

-  useFonts({
+  const [fontsLoaded, error] = useFonts({
     Inter_400Regular,
     Inter_500Medium,
     Inter_600SemiBold,
   });
+
+  if (error) {
+    console.error('Error loading fonts:', error);
+  }
+
+  if (!fontsLoaded) {
+    return null; // or a loading indicator
+  }
📝 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.

  const [fontsLoaded, error] = useFonts({
    Inter_400Regular,
    Inter_500Medium,
    Inter_600SemiBold,
  });

  if (error) {
    console.error('Error loading fonts:', error);
  }

  if (!fontsLoaded) {
    return null; // or a loading indicator
  }

62-82: 🧹 Nitpick (assertive)

Consider memoizing the content

The content JSX structure could be memoized to prevent unnecessary re-renders.

+  const content = useMemo(() => (
     <SafeAreaProvider>
       ...
     </SafeAreaProvider>
-  );
+  ), []);
📝 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.

  const content = useMemo(() => (
    <SafeAreaProvider>
      <PrivyProvider>
        <GlobalJotaiReady>
          <GestureHandlerRootView style={flexStyle}>
            <ThemeProvider>
              <NetworkReachabilityTracker />
              <SplashProvider>
                <Container />
              </SplashProvider>
              <PasswordVerifyPromptMount />
              <WebViewWebEmbedProvider />
              <LastActivityTracker />
              <SystemLocaleTracker />
              <StateActiveContainer />
              <InAppNotification />
              <SyncHomeAccountToDappAccountProvider />
            </ThemeProvider>
          </GestureHandlerRootView>
        </GlobalJotaiReady>
      </PrivyProvider>
    </SafeAreaProvider>
  ), []);
packages/shared/src/utils/stringUtils.ts (1)

103-108: 🧹 Nitpick (assertive)

Consider making isValidEmail more flexible.

The function is well-implemented but could be more reusable.

Consider this change:

-function isValidEmail(email: string): boolean {
+function isValidEmail(email: string | undefined | null): boolean {
   if (!email || !isString(email)) {
     return false;
   }
   return validator.isEmail(email);
 }
📝 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.

function isValidEmail(email: string | undefined | null): boolean {
  if (!email || !isString(email)) {
    return false;
  }
  return validator.isEmail(email);
}
packages/kit/src/views/Prime/pages/PrimeDeviceLimit/PrimeDeviceLimit.tsx (2)

60-60: 🧹 Nitpick (assertive)

Remove debug console.log statement.

Production code should not contain console.log statements.

-  console.log(devices);
📝 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.



51-55: 🧹 Nitpick (assertive)

Add error handling for device logout.

The logout operation should handle potential API failures gracefully.

   onConfirm: async () => {
+    try {
       await backgroundApiProxy.servicePrime.apiLogoutPrimeUserDevice({
         instanceId,
       });
       navigation.popStack();
+    } catch (error) {
+      Dialog.show({
+        title: 'Logout Failed',
+        description: 'Failed to logout device. Please try again.',
+      });
+    }
   },
📝 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.

      onConfirm: async () => {
        try {
          await backgroundApiProxy.servicePrime.apiLogoutPrimeUserDevice({
            instanceId,
          });
          navigation.popStack();
        } catch (error) {
          Dialog.show({
            title: 'Logout Failed',
            description: 'Failed to logout device. Please try again.',
          });
        }
      },
packages/kit/src/views/Prime/components/PrimeLoginEmailCodeDialogV2/PrimeLoginEmailCodeDialogV2.tsx (3)

40-48: 🛠️ Refactor suggestion

Add error handling to sendEmailVerificationCode.

The function swallows errors silently. Add proper error handling to inform users when code sending fails.

   try {
     console.log('sendCode', email);
     void sendCode({ email });
     setCountdown(COUNTDOWN_TIME);
+  } catch (error) {
+    // Show error to user
+    console.error('Failed to send verification code:', error);
   } finally {
     setIsResending(false);
   }

36-38: ⚠️ Potential issue

Fix the incorrect order of operations in sendEmailVerificationCode.

The isResending check happens after setting isResending to true, making it unreachable.

 const sendEmailVerificationCode = useCallback(async () => {
+  if (isResending) {
+    return;
+  }
   setIsResending(true);
-
-  if (isResending) {
-    return;
-  }
📝 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.

 const sendEmailVerificationCode = useCallback(async () => {
+  if (isResending) {
+    return;
+  }
   setIsResending(true);
   // ... rest of the code remains unchanged ...
 }, [isResending]);

103-111: 🧹 Nitpick (assertive)

Consider adding validation feedback.

The OTP input could benefit from immediate validation feedback as users type.

 <OTPInput
   status={state.status === 'error' ? 'error' : 'normal'}
   numberOfDigits={6}
   value={verificationCode}
   onTextChange={(value) => {
     setState({ status: 'initial' });
     setVerificationCode(value);
+    if (value.length === 6 && !/^\d{6}$/.test(value)) {
+      setState({ status: 'error' });
+    }
   }}
 />
📝 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.

          <OTPInput
            status={state.status === 'error' ? 'error' : 'normal'}
            numberOfDigits={6}
            value={verificationCode}
            onTextChange={(value) => {
              setState({ status: 'initial' });
              setVerificationCode(value);
              if (value.length === 6 && !/^\d{6}$/.test(value)) {
                setState({ status: 'error' });
              }
            }}
          />
packages/kit/src/views/Prime/components/PrimeLoginEmailCodeDialog/PrimeLoginEmailCodeDialog.tsx (2)

106-112: ⚠️ Potential issue

Remove debug toast notification.

The toast showing verification code in plain text poses a security risk.

 onComplete={(value) => {
   setCode(value);
-  Toast.success({
-    title: 'code',
-    message: value,
-  });
 }}
📝 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.

            onComplete={(value) => {
              setCode(value);
            }}

127-130: ⚠️ Potential issue

Improve error handling in dialog confirmation.

The error is thrown after preventClose(), which could lead to unhandled rejections.

 } catch (error) {
   preventClose();
-  throw error;
+  Toast.error({
+    title: 'Error',
+    message: 'Failed to verify code. Please try again.',
+  });
 }
📝 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.

          } catch (error) {
            preventClose();
            Toast.error({
              title: 'Error',
              message: 'Failed to verify code. Please try again.',
            });
          }
packages/shared/src/utils/promiseUtils.ts (1)

153-156: 🧹 Nitpick (assertive)

Consider using private field syntax.

Use modern JavaScript private field syntax (#) for better encapsulation.

-  _resolveFn: ((value: T) => void) | undefined;
+  #resolveFn: ((value: T) => void) | undefined;

   ready = new Promise<T>((resolve) => {
-    this._resolveFn = resolve;
+    this.#resolveFn = resolve;
   });
📝 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.

  ready = new Promise<T>((resolve) => {
-    this._resolveFn = resolve;
+    this.#resolveFn = resolve;
  });

-  _resolveFn: ((value: T) => void) | undefined;
+  #resolveFn: ((value: T) => void) | undefined;
packages/kit/src/views/WebView/pages/WebViewModal/index.tsx (1)

106-114: 🧹 Nitpick (assertive)

Add error handling to the message handler.

The webembedCustomReceiveHandler should handle malformed payloads and unknown methods gracefully.

 const webembedCustomReceiveHandler = useCallback(
   (payload: IJsBridgeMessagePayload) => {
+    try {
       const data = payload.data as IJsonRpcRequest;
       if (data.method === 'wallet_closeWebViewModal') {
         navigation.pop();
       }
+    } catch (error) {
+      console.error('Failed to process webembed message:', error);
+    }
   },
   [navigation],
 );
📝 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.

  const webembedCustomReceiveHandler = useCallback(
    (payload: IJsBridgeMessagePayload) => {
      try {
        const data = payload.data as IJsonRpcRequest;
        if (data.method === 'wallet_closeWebViewModal') {
          navigation.pop();
        }
      } catch (error) {
        console.error('Failed to process webembed message:', error);
      }
    },
    [navigation],
  );
packages/kit/src/views/Developer/pages/Gallery/Components/stories/Logger.tsx (1)

109-129: ⚠️ Potential issue

Fix potential precision loss in Int toString.

The regular integer version will lose precision at runtime. Use BigInt consistently for large numbers.

Apply this fix:

-                  // eslint-disable-next-line no-loss-of-precision, @typescript-eslint/no-loss-of-precision
-                  (1_234_567_890_123_456_789_077_777_777_777_777_777_799_999_999_999_998_888_888).toString(),
+                  1_234_567_890_123_456_789_077_777_777_777_777_777_799_999_999_999_998_888_888n.toString(),
📝 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.

            <Button
              onPress={() => {
                console.log(
                  'BigInt toString: ',
                  1_234_567_890_123_456_789_077_777_777_777_777_777_799_999_999_999_998_888_888n.toString(),
                );
              }}
            >
              BigInt toString
            </Button>
            <Button
              onPress={() => {
                console.log(
                  'Int toString: ',
                  1_234_567_890_123_456_789_077_777_777_777_777_777_799_999_999_999_998_888_888n.toString(),
                );
              }}
            >
              Int toString
            </Button>
🧰 Tools
🪛 Biome (1.9.4)

[error] 124-124: This number literal will lose precision at runtime.

The value at runtime will be 1234567890123456800000000000000000000000000000000000000000

(lint/correctness/noPrecisionLoss)

packages/kit/src/provider/Container/PrimeLoginContainer/PrimeLoginContainer.tsx (2)

21-21: 🧹 Nitpick (assertive)

Address TODO comment about container renaming.

The comment suggests renaming to PrimeDialogContainer. Let's track this technical debt.

Would you like me to create an issue to track this renaming task?


37-39: 🧹 Nitpick (assertive)

Consider consolidating dialog refs.

Multiple similar refs could be combined into a single object for better maintainability.

-  const emailDialogRef = useRef<IDialogInstance | undefined>(undefined);
-  const passwordDialogRef = useRef<IDialogInstance | undefined>(undefined);
-  const emailCodeDialogRef = useRef<IDialogInstance | undefined>(undefined);
+  const dialogRefs = useRef<Record<string, IDialogInstance | undefined>>({
+    email: undefined,
+    password: undefined,
+    emailCode: undefined,
+  });
📝 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.

  const dialogRefs = useRef<Record<string, IDialogInstance | undefined>>({
    email: undefined,
    password: undefined,
    emailCode: undefined,
  });
packages/kit-bg/src/dbs/simple/base/SimpleDb.ts (1)

40-41: 🧹 Nitpick (assertive)

Move prime property to maintain alphabetical order.

The prime property should be grouped with other similar properties to maintain the file's organization.

Move the property after line 92 to maintain alphabetical ordering with other properties.

packages/kit/src/views/Prime/components/PrimeLoginPasswordDialog/PrimeLoginPasswordDialog.tsx (3)

196-203: 🧹 Nitpick (assertive)

Remove commented-out code.

Dead code should be removed rather than commented out.

Remove the commented-out confirmPassword input section:

-    {/* {isRegister ? (
-      <Input
-        secureTextEntry
-        placeholder="Confirm Password"
-        value={confirmPassword}
-        onChangeText={setConfirmPassword}
-      />
-    ) : null} */}
📝 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.



85-111: 🛠️ Refactor suggestion

Enhance error handling in submit function.

The error handling could be more specific and user-friendly.

Add specific error handling:

 try {
   const encodedPassword = await backgroundApiProxy.servicePassword.encodeSensitiveText({
     text: formData.password,
   });
   await backgroundApiProxy.servicePrime.ensurePrimeLoginValidPassword(encodedPassword);
   await backgroundApiProxy.servicePrime.resolvePrimeLoginPasswordDialog({
     promiseId,
     password: encodedPassword,
   });
 } catch (error) {
   options?.preventClose?.();
-  throw error;
+  if (error instanceof ValidationError) {
+    form.setError('password', { message: 'Invalid password format' });
+  } else if (error instanceof NetworkError) {
+    Toast.error({ title: 'Network error. Please try again.' });
+  } else {
+    Toast.error({ title: 'An unexpected error occurred' });
+  }
+  throw error;
 }
📝 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.

  const submit = useCallback(
    async (options: { preventClose?: () => void } = {}) => {
      await form.trigger();
      if (!form.formState.isValid) {
        options?.preventClose?.();
        return;
      }
      const formData = form.getValues();
      try {
        const encodedPassword =
          await backgroundApiProxy.servicePassword.encodeSensitiveText({
            text: formData.password,
          });
        await backgroundApiProxy.servicePrime.ensurePrimeLoginValidPassword(
          encodedPassword,
        );
        await backgroundApiProxy.servicePrime.resolvePrimeLoginPasswordDialog({
          promiseId,
          password: encodedPassword,
        });
      } catch (error) {
        options?.preventClose?.();
        if (error instanceof ValidationError) {
          form.setError('password', { message: 'Invalid password format' });
        } else if (error instanceof NetworkError) {
          Toast.error({ title: 'Network error. Please try again.' });
        } else {
          Toast.error({ title: 'An unexpected error occurred' });
        }
        throw error;
      }
    },
    [form, promiseId],
  );

50-66: 🧹 Nitpick (assertive)

Password validation regex could be more secure.

The password validation checks for basic requirements but could be strengthened.

Consider adding these improvements:

  • Maximum length limit
  • Check for common password patterns
  • Prevent password reuse
  • Rate limit attempts
 const isValidPassword = useCallback((password: string) => {
+  const MAX_LENGTH = 128;
+  if (password.length > MAX_LENGTH) {
+    return false;
+  }
   let minLength = true;
   let minNumberCharacter = true;
   let minLetterCharacter = true;
   let minSpecialCharacter = true;
📝 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.

  const isValidPassword = useCallback((password: string) => {
    const MAX_LENGTH = 128;
    if (password.length > MAX_LENGTH) {
      return false;
    }
    let minLength = true;
    let minNumberCharacter = true;
    let minLetterCharacter = true;
    let minSpecialCharacter = true;

    if (password.length < 8) {
      minLength = false;
    }
    if (!/\d/.test(password)) {
      minNumberCharacter = false;
    }
    if (!/[a-zA-Z]/.test(password)) {
      minLetterCharacter = false;
    }
    // eslint-disable-next-line no-useless-escape
    if (!/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>/?`~]/.test(password)) {
      // further logic likely follows...
    }
  });
apps/web-embed/pages/PageWebEmbedPrimePurchase.tsx (4)

274-281: 🛠️ Refactor suggestion

Use environment variables for test values.

Replace hardcoded test values with environment variables to prevent accidental exposure.

-  if (process.env.NODE_ENV !== 'production') {
-    if (!primeUserId) {
-      primeUserId = 'did:privy:j32hasdfgg3288372';
-    }
-    if (!primeUserEmail) {
-      primeUserEmail = '[email protected]';
-    }
-  }
+  if (process.env.NODE_ENV !== 'production') {
+    if (!primeUserId) {
+      primeUserId = process.env.TEST_PRIME_USER_ID;
+    }
+    if (!primeUserEmail) {
+      primeUserEmail = process.env.TEST_PRIME_USER_EMAIL;
+    }
+  }

12-29: 🧹 Nitpick (assertive)

Add error handling for native toast requests.

The function should catch and handle potential failures when showing native toasts.

 async function showNativeToast({
   method,
   title,
   message,
 }: {
   method: 'success' | 'error' | 'info';
   title: string;
   message?: string | undefined;
 }) {
+  try {
     await globalThis.$onekey.$private.request({
       method: 'wallet_showToast',
       params: {
         method,
         title,
         message,
       },
     });
+  } catch (error) {
+    console.error('Failed to show native toast:', error);
+  }
 }
📝 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.

async function showNativeToast({
  method,
  title,
  message,
}: {
  method: 'success' | 'error' | 'info';
  title: string;
  message?: string | undefined;
}) {
  try {
    await globalThis.$onekey.$private.request({
      method: 'wallet_showToast',
      params: {
        method,
        title,
        message,
      },
    });
  } catch (error) {
    console.error('Failed to show native toast:', error);
  }
}

50-70: 🛠️ Refactor suggestion

Add accessibility attributes to the SVG spinner.

The SVG needs a title and aria-label for screen readers.

 function Spinner() {
   return (
     <svg
       width="24"
       height="24"
       viewBox="0 0 24 24"
+      role="img"
+      aria-label="Loading spinner"
       style={{
         animation: 'spin 1s linear infinite',
       }}
     >
+      <title>Loading spinner</title>
       <path
         stroke="currentColor"
         strokeLinecap="round"
         strokeLinejoin="round"
         strokeWidth={2}
         d="M12 3v3m0 12v3M5.636 5.636l2.122 2.121m8.485 8.486 2.121 2.121M3 12.001h3m12 0h3M5.636 18.364l2.122-2.121m8.485-8.486 2.121-2.121"
         fill="none"
       />
     </svg>
   );
 }
📝 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.

function Spinner() {
  return (
    <svg
      width="24"
      height="24"
      viewBox="0 0 24 24"
      role="img"
      aria-label="Loading spinner"
      style={{
        animation: 'spin 1s linear infinite',
      }}
    >
      <title>Loading spinner</title>
      <path
        stroke="currentColor"
        strokeLinecap="round"
        strokeLinejoin="round"
        strokeWidth={2}
        d="M12 3v3m0 12v3M5.636 5.636l2.122 2.121m8.485 8.486 2.121 2.121M3 12.001h3m12 0h3M5.636 18.364l2.122-2.121m8.485-8.486 2.121-2.121"
        fill="none"
      />
    </svg>
  );
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 52-59: Alternative text title element cannot be empty

For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.

(lint/a11y/noSvgWithoutTitle)


231-256: ⚠️ Potential issue

Implement error handling in the purchase flow.

The purchase flow needs proper error handling and user feedback.

 onClick={async () => {
   if (isLoading) {
     return;
   }
   try {
     setIsLoading(true);
     if (!selectedPackageId) {
       throw new Error('No package selected');
     }
     const result = await purchasesSdk.purchasePackage({
       userId: primeUserId,
       email: primeUserEmail,
       packageId: selectedPackageId,
     });
-    // TODO toast error
     if (result) {
       await showNativeToast({
         method: 'success',
         title: `Purchase success`,
       });
       await closeNativeWebViewModal();
     }
+  } catch (error) {
+    await showNativeToast({
+      method: 'error',
+      title: 'Purchase failed',
+      message: error.message,
+    });
   } finally {
     setIsLoading(false);
   }
 }}
📝 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.

      onClick={async () => {
        if (isLoading) {
          return;
        }
        try {
          setIsLoading(true);
          if (!selectedPackageId) {
            throw new Error('No package selected');
          }
          const result = await purchasesSdk.purchasePackage({
            userId: primeUserId,
            email: primeUserEmail,
            packageId: selectedPackageId,
          });
          if (result) {
            await showNativeToast({
              method: 'success',
              title: `Purchase success`,
            });
            await closeNativeWebViewModal();
          }
        } catch (error) {
          await showNativeToast({
            method: 'error',
            title: 'Purchase failed',
            message: error.message,
          });
        } finally {
          setIsLoading(false);
        }
      }}
packages/kit-bg/src/services/ServiceCustomRpc.ts (1)

242-245: 🛠️ Refactor suggestion

Add proper error handling for network fetch.

Using void to ignore the promise could hide important errors. Consider logging or handling errors more explicitly.

-          void this.fetchNetworkFromServer().catch((error) => {
-            defaultLogger.account.wallet.getServerNetworksError(error);
-          });
+          this.fetchNetworkFromServer().catch((error) => {
+            defaultLogger.account.wallet.getServerNetworksError(error);
+            // Consider emitting an event or updating state to show fetch failure
+            appEventBus.emit(EAppEventBusNames.NetworkFetchFailed, error);
+          });
📝 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.

          this.fetchNetworkFromServer().catch((error) => {
            defaultLogger.account.wallet.getServerNetworksError(error);
            // Consider emitting an event or updating state to show fetch failure
            appEventBus.emit(EAppEventBusNames.NetworkFetchFailed, error);
          });
        }
packages/kit/src/views/Prime/pages/PrimeDashboard/PrimeDashboard.tsx (2)

93-107: ⚠️ Potential issue

Fix hardcoded wait time and empty URL.

The function uses a hardcoded wait time and an empty URL, which could cause reliability issues.

 const purchaseByWebview = useCallback(async () => {
   navigation.popStack();
-  await timerUtils.wait(1000);
+  // Consider using a navigation event listener instead of arbitrary wait
+  await new Promise(resolve => navigation.addListener('transitionEnd', resolve));
   openUrlUtils.openUrlByWebviewPro({
-    url: '',
+    url: process.env.PRIME_PURCHASE_URL || 'https://prime.onekey.so/purchase',
     title: 'WebView',
     isWebEmbed: true,
     hashRoutePath: EWebEmbedRoutePath.primePurchase,
     hashRouteQueryParams: {
       primeUserId: user?.privyUserId || '',
       primeUserEmail: user?.email || '',
     },
   });
 }, [navigation, user?.privyUserId, user?.email]);

238-312: ⚠️ Potential issue

Remove or hide debug buttons in production.

Debug buttons expose sensitive operations and use console.log. These should be hidden in production.

+const DebugButtons = () => {
+  if (process.env.NODE_ENV === 'production') {
+    return null;
+  }
+  return (
     <XStack flexWrap="wrap">
       <Button onPress={() => { void logout(); }}>Logout</Button>
       {/* ... other debug buttons ... */}
     </XStack>
+  );
+};

 // In the render method:
-<XStack flexWrap="wrap">
-  {/* debug buttons */}
-</XStack>
+<DebugButtons />
📝 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.

// Add the DebugButtons component
const DebugButtons = () => {
  if (process.env.NODE_ENV === 'production') {
    return null;
  }
  return (
    <XStack flexWrap="wrap">
      <Button
        onPress={() => {
          void logout();
        }}
      >
        Logout
      </Button>
      <Button
        onPress={() => {
          void getAccessToken().then(showDebugMessageByDialog);
        }}
      >
        Get Access Token
      </Button>
      <Button
        onPress={() => {
          showDebugMessageByDialog({
            ready: isReady,
            authenticated,
          });
        }}
      >
        User Info
      </Button>
      <Button
        onPress={() => {
          //
        }}
      >
        shouldShowConfirmButton={shouldShowConfirmButton.toString()}
      </Button>
      <Button
        onPress={() => {
          void getCustomerInfo().then(showDebugMessageByDialog);
        }}
      >
        CustomerInfo
      </Button>
      <Button
        onPress={() => {
          void fetchPrimeUserInfo().then(showDebugMessageByDialog);
        }}
      >
        ServerPrimeUserInfo
      </Button>
      <Button
        onPress={() => {
          void getPaywallPackagesNative?.().then(showDebugMessageByDialog);
          void getPaywallPackagesWeb?.().then(showDebugMessageByDialog);
        }}
      >
        PaywallPackages
      </Button>
      <Button
        onPress={() => {
          void backgroundApiProxy.servicePrime
            .apiGetPrimeUserDevices()
            .then(console.log);
        }}
      >
        UserDevices
      </Button>
      <Button
        onPress={() => {
          navigation.pushFullModal(EModalRoutes.PrimeModal, {
            screen: EPrimePages.PrimeDeviceLimit,
          });
        }}
      >
        DeviceLimit
      </Button>
    </XStack>
  );
};

// In your component's render method (or return block), replace the old debug buttons block:
return (
  <>
    {/* other components */}
    <DebugButtons />
    {/* other components */}
  </>
);
development/webpack/webpack.base.config.js (1)

106-116: 🧹 Nitpick (assertive)

Use environment variables for babel loader configuration.

Consider making babel loader options configurable through environment variables.

 const babelLoaderOption = {
   babelrc: false,
   configFile: true,
   sourceType: 'unambiguous',
   root: basePath,
-  compact: !isDev,
-  sourceMaps: isDev,
-  inputSourceMap: isDev,
+  compact: process.env.BABEL_COMPACT !== 'false' && !isDev,
+  sourceMaps: process.env.BABEL_SOURCEMAPS === 'true' || isDev,
+  inputSourceMap: process.env.BABEL_SOURCEMAPS === 'true' || isDev,
   cacheCompression: false,
   cacheDirectory: path.resolve(basePath, 'node_modules/.cache/babel-loader'),
 };
📝 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.

  const babelLoaderOption = {
    babelrc: false,
    configFile: true,
    sourceType: 'unambiguous',
    root: basePath,
    compact: process.env.BABEL_COMPACT !== 'false' && !isDev,
    sourceMaps: process.env.BABEL_SOURCEMAPS === 'true' || isDev,
    inputSourceMap: process.env.BABEL_SOURCEMAPS === 'true' || isDev,
    cacheCompression: false,
    cacheDirectory: path.resolve(basePath, 'node_modules/.cache/babel-loader'),
  };
.eslintrc.js (1)

1-2: 💡 Verification agent

🧩 Analysis chain

Verify the impact of disabling force-async-bg-api rule

The force-async-bg-api rule and its import are commented out with TODO comments. This could lead to inconsistent background method handling.

Run this script to find methods that would be affected:

Also applies to: 11-11


🏁 Script executed:

#!/bin/bash
# Find methods with @backgroundMethod decorator that might need async
ast-grep --pattern $'@backgroundMethod()
$$$
$method() {
  $$$
}'

Length of output: 66


🏁 Script executed:

#!/bin/bash
echo "Searching for any instance of force-async-bg-api:"
rg 'force-async-bg-api'
echo "------------------------------"
echo "Searching for occurrences of '@backgroundMethod':"
rg '@backgroundMethod'

Length of output: 66105


Impact of Disabling 'force-async-bg-api' ESLint Rule

Our investigation confirms that:

  • The custom ESLint rule (force-async-bg-api) is defined in development/lint/eslint-rule-force-async-bg-api.js but is commented out in .eslintrc.js.
  • Numerous files, particularly in the packages/kit-bg directory, use the @backgroundMethod decorator.

This setup means that any methods marked with @backgroundMethod aren’t being checked for an async declaration. Without the lint rule enforcing async usage, there’s a risk that a background method may be implemented without the proper asynchronous handling, potentially leading to inconsistencies or subtle bugs.

We recommend reviewing those methods manually or re-enabling the rule to ensure robust async behavior.

packages/components/src/composite/Dialog/index.tsx (1)

518-544: 🧹 Nitpick (assertive)

Consider adding error handling for clipboard operations

The clipboard operation in dialogDebugMessage should handle potential failures.

-          onPress={async () => {
-            await setStringAsync(dataContent);
-            Toast.success({
-              title: 'Copied',
-            });
+          onPress={async () => {
+            try {
+              await setStringAsync(dataContent);
+              Toast.success({
+                title: 'Copied',
+              });
+            } catch (error) {
+              Toast.error({
+                title: 'Failed to copy',
+              });
+            }
+          }}
📝 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.

const dialogDebugMessage = (
  props: IDialogShowProps & { debugMessage: any },
) => {
  const dataContent = JSON.stringify(props.debugMessage, null, 2);
  console.log('dialogDebugMessage:', dataContent);
  return dialogShow({
    title: 'DebugMessage',
    showFooter: false,
    showConfirmButton: false,
    showCancelButton: false,
    renderContent: (
      <ScrollView maxHeight="$48" nestedScrollEnabled>
        <SizableText
          onPress={async () => {
            try {
              await setStringAsync(dataContent);
              Toast.success({
                title: 'Copied',
              });
            } catch (error) {
              Toast.error({
                title: 'Failed to copy',
              });
            }
          }}
        >
          {dataContent}
        </SizableText>
      </ScrollView>
    ),
    ...props,
  });
};
packages/shared/src/errors/errors/appErrors.ts (2)

120-129: 🧹 Nitpick (assertive)

Add className override for consistency.

Similar to the previous error class, consider adding className override.

export class OneKeyErrorPrimeLoginExceedDeviceLimit extends OneKeyError {
  constructor(props?: IOneKeyError | string) {
    super(
      normalizeErrorProps(props, {
        defaultMessage: 'Prime exceed device limit',
        defaultAutoToast: true,
      }),
    );
  }
+ override className = EOneKeyErrorClassNames.OneKeyErrorPrimeLoginExceedDeviceLimit;
}

109-118: 🧹 Nitpick (assertive)

Add className override for consistency.

Other error classes in this file override className. Consider adding it here for consistency.

export class OneKeyErrorPrimeLoginInvalidToken extends OneKeyError {
  constructor(props?: IOneKeyError | string) {
    super(
      normalizeErrorProps(props, {
        defaultMessage: 'Prime login invalid, please login again',
        defaultAutoToast: true,
      }),
    );
  }
+ override className = EOneKeyErrorClassNames.OneKeyErrorPrimeLoginInvalidToken;
}
packages/kit/src/views/Onboarding/pages/ConnectHardwareWallet/ConnectYourDevice.tsx (1)

1-1: 🧹 Nitpick (assertive)

Consider extracting nested components to separate files.

The ESLint rule react/no-unstable-nested-components is disabled. This rule prevents performance issues and improves code organization. Instead of disabling it:

  • Move DeviceListItem, ConnectByQrCode, and other nested components to separate files
  • Import them where needed
packages/kit/src/components/Captcha/Captcha.tsx (1)

1-3: 🧹 Nitpick (assertive)

Minimal Captcha Component.
The Captcha component currently returns an empty fragment. Consider adding implementation details or a placeholder comment if further work is planned.

.github/workflows/unittest.yml (1)

73-73: 🧹 Nitpick (assertive)

Remove Extra Blank Line.

Static analysis detected an extra blank line here. Please remove it to maintain a clean YAML file.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 73-73: too many blank lines

(1 > 0) (empty-lines)

.github/workflows/release-android-debug.yml (2)

10-10: 🧹 Nitpick (assertive)

Minor Formatting Adjustment.
Line 10 shows a formatting change (likely a newline tweak). Please confirm that this change was intentional.


84-84: 🧹 Nitpick (assertive)

Formatting Check.
Line 84 appears as an isolated change. Verify if this line was added for spacing or if any content was meant to be updated.

.github/workflows/release-android.yml (2)

15-15: 🧹 Nitpick (assertive)

Workflow Dispatch Formatting.
Line 15 has a minor formatting change. Please verify if this blank/update is intentional.


107-107: 🧹 Nitpick (assertive)

Formatting Check Post-EAS Build.
Line 107 appears to be a formatting adjustment. Confirm if this whitespace change is deliberate.

.github/workflows/release-ios.yml (1)

91-94: 🧹 Nitpick (assertive)

Sentry Properties Write.
There’s a minor change at line 94—possibly a trailing newline or spacing adjustment. Verify if any additional sentry configuration was intended here.

.github/workflows/release-desktop-snap.yml (2)

12-12: 🧹 Nitpick (assertive)

Remove Trailing Whitespace.
Extra spaces on this line should be removed to pass YAMLlint.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 12-12: trailing spaces

(trailing-spaces)


25-26: 🧹 Nitpick (assertive)

Clean Up Extra Spaces.
There are trailing spaces in these lines. Removing them will improve clarity.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 25-25: trailing spaces

(trailing-spaces)


[error] 26-26: trailing spaces

(trailing-spaces)

.github/workflows/release-desktop.yml (1)

25-25: 🧹 Nitpick (assertive)

Remove Trailing Whitespace.
Please eliminate the extra spaces on this line.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 25-25: trailing spaces

(trailing-spaces)

.github/actions/shared-env/action.yml (3)

4-50: 🧹 Nitpick (assertive)

Review Input Parameters.
All critical inputs are defined. Consider adding a definition for "is-split-bundle" since it is used later.


151-151: 🧹 Nitpick (assertive)

Remove Trailing Whitespace.
Eliminate extra spaces on this line for cleaner formatting.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 151-151: trailing spaces

(trailing-spaces)


174-174: 🧹 Nitpick (assertive)

Reduce Extra Blank Lines.
Remove the superfluous blank line to improve readability.

🧰 Tools
🪛 YAMLlint (1.35.1)

[error] 174-174: too many blank lines

(2 > 0) (empty-lines)

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: 10

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 50c88cd and 9160e9e.

📒 Files selected for processing (3)
  • packages/kit/src/components/WebViewWebEmbed/index.tsx (5 hunks)
  • packages/kit/src/views/Prime/components/PrivyProvider.native.tsx (1 hunks)
  • packages/kit/src/views/Prime/components/PrivyProvider.tsx (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: unittest (20.x)
  • GitHub Check: lint (20.x)
🔇 Additional comments (15)
packages/kit/src/views/Prime/components/PrivyProvider.native.tsx (1)

1-7: Clean and focused imports!

The imports are well-organized and purposeful.

packages/kit/src/views/Prime/components/PrivyProvider.tsx (1)

26-29: Document login method restrictions.

The code comments out several login methods. Add a comment explaining why only email login is enabled.

Are the other login methods intentionally disabled? Please confirm if this is a temporary or permanent restriction.

packages/kit/src/components/WebViewWebEmbed/index.tsx (13)

5-13: Looks good.
These imports accurately add new hooks and route enums. No issues spotted.


25-31: Clean extension of props.
Adding hashRoutePath and hashRouteQueryParams improves navigation. Implementation looks consistent.


40-42: Neat usage of new hooks.
Good job fetching theme and locale variants here.


44-44: State variable initialization is fine.
Storing an empty string as the default for the key is logical.


47-57: Method to fetch API key is clear.
You fetch dev settings, switch keys if sandbox is enabled, and handle missing keys. All good.


59-60: Side-effect is correct.
You only call getApiKey once on mount. Simple and effective.


62-73: Smart memo usage.
You wait for theme, locale, and the API key before populating webEmbedAppSettings. Looks structured.


76-79: Conditional remoteUrl logic is sound.
In dev or when devSettingsPersistAtom.enabled, you fall back to config.url. Handling is neat.

Also applies to: 85-85


106-109: Early return prevents errors.
Returning null if webEmbedAppSettings is absent is a good defensive pattern.


133-141: Dependency array is correct.
All relevant dependencies are included. Looks good.


143-161: Bridge integration is well-structured.
You handle platform checks and connect backgroundApiProxy properly.


225-230: Singleton view is neatly composed.
No issues with pass-through props or usage.


123-130: Embed caution with sensitive keys.
Embedding the API key in window object is okay if it’s not truly private. Verify it’s safe.

Below is a script to search for references to these environment variables. Assess if they're exposed externally.

✅ Verification successful

🏁 Script executed:

#!/bin/bash
rg "REVENUECAT_API_KEY_WEB" -A 5

Length of output: 4586


API key exposure is intentional and safe.
The grep results confirm that REVENUECAT_API_KEY_WEB is listed in the file (development/envExposedToClient.js) that defines which environment variables are exposed to the client. This indicates that the API key is not treated as a truly private secret and is safe to embed in the window object.

huhuanming
huhuanming previously approved these changes Feb 8, 2025
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: 24

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 209f5b0 and 28a6671.

📒 Files selected for processing (11)
  • apps/desktop/src-electron/app.ts (1 hunks)
  • apps/web-embed/pages/PageWebEmbedPrimePurchase.tsx (1 hunks)
  • development/spellCheckerSkipWords.js (3 hunks)
  • packages/components/src/forms/Slider/index.native.tsx (1 hunks)
  • packages/kit-bg/src/services/ServiceCloudBackup/index.ts (1 hunks)
  • packages/kit-bg/src/services/ServicePassword/index.ts (1 hunks)
  • packages/kit-bg/src/services/ServicePrime/ServicePrime.tsx (1 hunks)
  • packages/kit/src/components/Password/components/PasswordVerify.tsx (1 hunks)
  • packages/kit/src/views/Prime/components/PrimeLoginEmailCodeDialog/PrimeLoginEmailCodeDialog.tsx (1 hunks)
  • packages/kit/src/views/Prime/components/PrimeLoginEmailCodeDialogV2/PrimeLoginEmailCodeDialogV2.tsx (1 hunks)
  • packages/shared/src/utils/debug/dbPerfMonitor.ts (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
apps/web-embed/pages/PageWebEmbedPrimePurchase.tsx

[error] 52-59: Alternative text title element cannot be empty

For accessibility purposes, SVGs should have an alternative text, provided via title element. If the svg element has role="img", you should add the aria-label or aria-labelledby attribute.

(lint/a11y/noSvgWithoutTitle)


[error] 177-178: The elements with the following roles can be changed to the following elements:

For examples and more information, see WAI-ARIA Roles

(lint/a11y/useSemanticElements)

packages/kit-bg/src/services/ServicePrime/ServicePrime.tsx

[error] 404-413: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)


[error] 451-464: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)


[error] 499-512: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: lint (20.x)
🔇 Additional comments (9)
packages/shared/src/utils/debug/dbPerfMonitor.ts (1)

183-183: Type Update is Spot-On!

Switching to ReturnType improves type inference and ensures compatibility across both Node and browser environments. No issues detected.

packages/components/src/forms/Slider/index.native.tsx (1)

26-26: Type change looks good!

Using ReturnType<typeof setTimeout> instead of NodeJS.Timeout provides better type safety and platform compatibility.

packages/kit/src/components/Password/components/PasswordVerify.tsx (1)

86-86: Type change looks good!

Using ReturnType<typeof setTimeout> | null instead of NodeJS.Timeout | null provides better type safety while maintaining null union type.

packages/kit-bg/src/services/ServicePassword/index.ts (1)

70-70: Type changes look good!

The updates to timeout and interval types provide better type safety:

  • cachedPasswordTimeOutObject: Now uses ReturnType<typeof setTimeout>
  • passwordPromptTimeout: Now uses ReturnType<typeof setTimeout>
  • extCheckLockStatusTimer: Now uses ReturnType<typeof setInterval>

Also applies to: 76-76, 80-80

packages/kit-bg/src/services/ServiceCloudBackup/index.ts (1)

668-668: Timer type updated for cross-platform consistency.
Updating the timer property to ReturnType improves type safety across environments. This change aligns with similar updates in our codebase and reduces potential mismatches between Node.js and browser timer types.

packages/kit-bg/src/services/ServicePrime/ServicePrime.tsx (2)

339-341: 🧹 Nitpick (assertive)

Implement CAPTCHA verification.

The TODO comment about CAPTCHA verification needs implementation. This is important for security.

Would you like me to help implement the CAPTCHA verification logic or create an issue to track this task?


391-391: 🧹 Nitpick (assertive)

Implement password management dialogs.

The TODO comments for forget password and change password dialogs need implementation.

Would you like me to help implement these password management dialogs or create issues to track these tasks?

Also applies to: 398-399

packages/kit/src/views/Prime/components/PrimeLoginEmailCodeDialog/PrimeLoginEmailCodeDialog.tsx (2)

45-57: LGTM! Clean timer implementation.

The countdown timer implementation is correct with proper cleanup and type definition.


59-61: LGTM! Proper initial code sending.

The effect correctly triggers the verification code sending on component mount.

originalix
originalix previously approved these changes Feb 9, 2025
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: 16

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 28a6671 and e81f6d6.

📒 Files selected for processing (8)
  • apps/desktop/src-electron/app.ts (1 hunks)
  • packages/kit-bg/src/services/ServicePrime/ServicePrime.tsx (1 hunks)
  • packages/kit/src/views/Prime/components/PrimeLoginEmailCodeDialog/PrimeLoginEmailCodeDialog.tsx (1 hunks)
  • packages/kit/src/views/Prime/components/PrimeLoginEmailCodeDialogV2/PrimeLoginEmailCodeDialogV2.tsx (1 hunks)
  • packages/kit/src/views/Prime/hooks/usePrivyAuthSyncToAtom.ts (1 hunks)
  • packages/kit/src/views/Prime/hooks/usePrivyUniversalV2/usePrivyUniversalV2.native.ts (1 hunks)
  • packages/kit/src/views/Prime/hooks/usePrivyUniversalV2/usePrivyUniversalV2.ts (1 hunks)
  • packages/kit/src/views/Prime/hooks/usePrivyUniversalV2/usePrivyUniversalV2Types.ts (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
packages/kit-bg/src/services/ServicePrime/ServicePrime.tsx

[error] 399-408: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)


[error] 446-459: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)


[error] 494-507: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)

⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: lint (20.x)
  • GitHub Check: unittest (20.x)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (30)
apps/desktop/src-electron/app.ts (1)

79-79: Type Update Confirmed.
The variable is now typed as ReturnType, which correctly matches its usage for setInterval. This aligns with previous feedback.

packages/kit/src/views/Prime/hooks/usePrivyUniversalV2/usePrivyUniversalV2Types.ts (1)

21-22: Clarify email parameter requirement.

The email parameter in loginWithCode is marked optional, but it might be required if not in the correct state. Consider adding runtime validation or making it required.

Could you confirm if the email parameter is truly optional in all cases?

packages/kit/src/views/Prime/hooks/usePrivyUniversalV2/usePrivyUniversalV2.native.ts (2)

1-5: Clean imports - looking good!

The imports are well-organized and each serves a clear purpose.


24-54: 🛠️ Refactor suggestion

Enhance error handling in async operations

The spread operator usage could mask errors. Also, empty string fallbacks might cause issues.

-          id: user?.id || '',
-          email: userEmail || '',
+          id: user?.id ?? '',
+          email: userEmail ?? '',

Also, consider adding error handling in async functions:

         sendCode: async (...sendCodeArgs) => {
-          await sendCode(...sendCodeArgs);
+          try {
+            await sendCode(...sendCodeArgs);
+          } catch (error) {
+            onError?.(error);
+            throw error;
+          }
         },
packages/kit/src/views/Prime/components/PrimeLoginEmailCodeDialogV2/PrimeLoginEmailCodeDialogV2.tsx (2)

16-16: Move COUNTDOWN_TIME to a constants file.

Move this constant to a shared constants file. Other components might need the same countdown duration.


33-68: LGTM! Clean implementation of the timer and resend logic.

The code handles edge cases well and uses setTimeout for accurate timing.

packages/kit/src/views/Prime/hooks/usePrivyUniversalV2/usePrivyUniversalV2.ts (3)

1-4: Clean imports with good type separation!

The imports are focused and well-organized, with clear separation between external and internal dependencies.


20-25: Avoid spreading unknown arguments to async functions.

The spread operator with async functions can lead to unexpected behavior if the arguments don't match.

-        sendCode: async (...sendCodeArgs) => {
-          await sendCode(...sendCodeArgs);
+        sendCode: async (email: string) => {
+          await sendCode(email);
         },
-        loginWithCode: async (...loginWithCodeArgs) => {
-          await loginWithCode(...loginWithCodeArgs);
+        loginWithCode: async (code: string) => {
+          await loginWithCode(code);
         },

32-37: 🛠️ Refactor suggestion

Add null checks for user properties.

The current user object transformation could throw if user is null.

     user: authenticated
       ? {
-          id: user?.id || '',
-          email: user?.email?.address || '',
+          id: user?.id ?? '',
+          email: user?.email?.address ?? '',
        }

Likely invalid or redundant comment.

packages/kit/src/views/Prime/components/PrimeLoginEmailCodeDialog/PrimeLoginEmailCodeDialog.tsx (13)

1-2: No issues found.
The imports look clean and straightforward.


3-15: No issues found.
These UI imports and background proxy references are consistent.


16-16: Make the constant name more descriptive.
Replace COUNTDOWN_TIME with a clearer naming, for example RESEND_CODE_COUNTDOWN_SECONDS.


18-22: Function signature looks good.
No suggestions here.


23-28: Consolidate duplicate state variables.
You keep both “code” and “verificationCode.” Merging them reduces confusion and potential errors.


29-43: Add validation checks before sending the code.
Guard against empty email and verifyUUID before making the API call.


45-57: Countdown logic looks correct.
The timer clears properly to avoid memory leaks.


59-61: Auto-triggering code send is fine.
This ensures the code dispatch on mount.


63-67: Internationalize button text.
Avoid hardcoded Chinese strings. Use translation keys.


69-100: General UI structure is fine.
No issues spotted in the layout or button usage.


102-113: Remove the verification code from Toast.
Showing codes in Toast is a security concern.


116-132: Add loading feedback on confirmation.
Disable or show a spinner to prevent multiple submissions while awaiting resolution.


135-135: No issues.
The closing of the component is concise.

packages/kit-bg/src/services/ServicePrime/ServicePrime.tsx (8)

53-60: **Use cookies instead of simpleDb **
This TODO repeats a past suggestion. Storing tokens in cookies is more secure.


110-110: Verify 404 endpoint
“TODO 404 not found.” Ensure the endpoint path is correct or handle the possible 404 error.


184-228: **Remove or clean out old commented code **
These lines are marked deprecated. A previous reviewer suggested fully removing them.


290-293: **Localize error message **
Use i18n for "Invalid email" to keep error handling consistent.


370-389: **Remove console.log **
A past reviewer already suggested removing console logs in production code.


399-408: **Avoid async in Promise executor **
This is the same anti-pattern mentioned before.

🧰 Tools
🪛 Biome (1.9.4)

[error] 399-408: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)


446-459: **Avoid async in Promise executor **
Same fix needed to remove the async from the executor.

🧰 Tools
🪛 Biome (1.9.4)

[error] 446-459: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)


494-507: **Avoid async in Promise executor **
Same issue as above.

🧰 Tools
🪛 Biome (1.9.4)

[error] 494-507: Promise executor functions should not be async.

(lint/suspicious/noAsyncPromiseExecutor)

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

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between e81f6d6 and f43173a.

📒 Files selected for processing (1)
  • packages/kit-bg/src/providers/ProviderApiPrivate.ts (4 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: lint (20.x)
  • GitHub Check: unittest (20.x)
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (2)
packages/kit-bg/src/providers/ProviderApiPrivate.ts (2)

11-11: LGTM! Clean import additions.

The new imports support the toast notification feature.

Also applies to: 19-19, 31-34


505-510: Great logging enhancement!

The detailed JSON logging will make debugging web embed API issues easier.

@sidmorizon sidmorizon merged commit 6df71a8 into x Feb 10, 2025
8 checks passed
@sidmorizon sidmorizon deleted the feat/prime-login0 branch February 10, 2025 03:47
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.

4 participants