-
Notifications
You must be signed in to change notification settings - Fork 21
fix: android ci #549
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
base: onekey
Are you sure you want to change the base?
fix: android ci #549
Conversation
WalkthroughAdd a new shared constants workspace and switch example imports to it, bump two GitHub Actions in an Android workflow, update a react-native-crypto patch to use Changes
Sequence Diagram(s)sequenceDiagram
participant App as Example App
participant Shared as @onekey-internal/shared-constants
participant CryptoPatch as react-native-crypto patch
participant RNGetRand as react-native-get-random-values
Note over App,Shared: Example code imports shared constants
App->>Shared: import getConnectSrc
Shared-->>App: provide CONNECT_SRC
Note over App,CryptoPatch: Crypto module load (patch applied)
App->>CryptoPatch: import 'crypto' shim
alt globalThis.crypto.getRandomValues exists
CryptoPatch-->>App: export crypto APIs (no polyfill)
else
CryptoPatch->>RNGetRand: import getRandomValues
RNGetRand-->>CryptoPatch: getRandomValues fn
CryptoPatch->>CryptoPatch: ensure globalThis.crypto and bind getRandomValues
CryptoPatch-->>App: export crypto APIs (polyfilled)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
🎉 Snyk checks have passed. No issues have been found so far.✅ security/snyk check is complete. No issues have been found. (View Details) ✅ license/snyk check is complete. No issues have been found. (View Details) |
07dac6e
to
1e50f43
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
.github/workflows/build-example-android.yml (3)
13-16
: Fix Node version mismatch (step name says 20, action installs 22).This can break CI and confuse readers. Align the value with the name. Node 20 is also safer for RN builds today.
Apply:
- - name: Use Node.js 20 - uses: actions/setup-node@v4 - with: - node-version: '22' + - name: Use Node.js 20 + uses: actions/setup-node@v4 + with: + node-version: '20'
19-23
: Good upgrade to setup-java v4. Consider enabling its built-in Gradle cache.You can drop the separate cache step and let setup-java handle it.
Option A — add cache here:
- name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'zulu' + cache: 'gradle'
Then remove the dedicated “Cache Gradle packages” step below.
29-36
: Prefer gradle/actions/setup-gradle for smarter caching.It’s more reliable than a generic cache step and cleans up old entries.
Replace this step with:
- - name: Cache Gradle packages - uses: actions/cache@v4 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle- + - name: Setup Gradle with caching + uses: gradle/actions/setup-gradle@v4 + with: + gradle-home-cache-includes: | + caches + notifications + wrapper + gradle-home-cache-cleanup: truepatches/react-native-crypto+2.2.0.patch (1)
1-42
: Action required — verify polyfill wiring & restore randomBytes compatibility before mergingShort: the patch replaces react-native-randombytes with react-native-get-random-values and sets globalThis.crypto.getRandomValues, but it removed the exported crypto.randomBytes API. That will break callers of crypto.randomBytes and the patch in /patches may not even be applied in CI.
Files/locations to inspect and fix
- ./packages/connect-examples/expo-example/package.json — react-native-get-random-values is present here (@^1.10.0). Add it to any packages that use react-native-crypto or to the repo root if the runtime needs it globally.
- ./package.json (repo root) — currently has no patch-package and no postinstall script (patches under /patches won't be applied). Add patch-package as a devDependency and run it in postinstall (or ensure CI applies patches).
- patches/react-native-crypto+2.2.0.patch — the changed file removed exports.randomBytes; restore a compatibility export or provide an explicit fallback.
- ./packages/connect-examples/expo-example/src/testTools/slip39Test/core/slip39Utils.ts — uses crypto.randomBytes() (multiple sites). Search repo for other crypto.randomBytes callers and update or keep compatibility.
- ./packages/connect-examples/expo-example/shim/crypto/index.native.js — this shim already requires react-native-get-random-values and reassigns randomBytes (so expo-example may still work). Other packages likely lack that shim.
Recommended, minimal fixes
- Ensure patch application: add patch-package to root devDependencies and a postinstall script to run it (or update CI).
- Restore a compatibility randomBytes export in the patched react-native-crypto index.js so crypto.randomBytes(...) continues to work. Example (suggested insertion into the patched file):
- import { getRandomValues } from 'react-native-get-random-values';
- function randomBytes(length) {
- const arr = new Uint8Array(length);
- (globalThis.crypto && globalThis.crypto.getRandomValues
? globalThis.crypto.getRandomValues
: getRandomValues)(arr);
- return (typeof Buffer !== 'undefined') ? Buffer.from(arr) : arr;
- }
- exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = randomBytes;
- Or, alternatively, add react-native-get-random-values to every package that will import react-native-crypto (so getRandomValues is present at runtime) and update callers to use globalThis.crypto.getRandomValues where feasible.
Why this is blocking
- Patches won't be applied in CI unless patch-package is configured at the repo root.
- Removing exports.randomBytes breaks existing code that expects crypto.randomBytes (we found concrete call sites).
- react-native-get-random-values is only declared in the expo-example package.json, not globally.
Next step
- Fix package.json (root or target packages) and either restore the randomBytes export in the patch or update all call sites. I can produce an updated patch snippet if you want.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (6)
.github/workflows/build-example-android.yml
(2 hunks)package.json
(1 hunks)packages/connect-examples/expo-example/src/constants/connect.ts
(1 hunks)packages/connect-examples/expo-playground/app/constants/connect.ts
(1 hunks)packages/connect-examples/shared-constants/package.json
(1 hunks)patches/react-native-crypto+2.2.0.patch
(1 hunks)
🧰 Additional context used
🪛 ESLint
packages/connect-examples/expo-playground/app/constants/connect.ts
[error] 1-1: Resolve error: typescript with invalid interface loaded as resolver
(import/namespace)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: build-and-upload
- GitHub Check: Socket Security: Pull Request Alerts
- GitHub Check: build (22)
- GitHub Check: lint (22)
🔇 Additional comments (2)
package.json (1)
13-13
: Workspace entry looks good.This will let Yarn/Lerna bootstrap the new shared-constants package.
packages/connect-examples/expo-example/src/constants/connect.ts (1)
2-4
: Import switch to shared package looks good.Keeps the API the same while centralizing constants.
@@ -1,4 +1,4 @@ | |||
import { getConnectSrc } from '../../../constants'; | |||
import { getConnectSrc } from '@onekey-internal/shared-constants'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Resolve the ESLint “import/namespace” error by exposing types.
The resolver error points to missing/unknown exports for @onekey-internal/shared-constants. After adding "types" and "exports" to that package (see package.json review), this should pass.
Re-run lint after adding types:
🏁 Script executed:
#!/bin/bash
yarn lint --max-warnings=0
Length of output: 322
🏁 Script executed:
#!/bin/bash
# Locate the shared-constants package.json
pkg_path=$(find packages -type f -name package.json -exec grep -l '"name": "@onekey-internal/shared-constants"' {} \;)
echo "Shared constants package.json at: $pkg_path"
# Check for "types" field
echo
echo "Checking for types field in package.json:"
grep -n '"types"' "$pkg_path" || echo "No types field found"
# Check for "exports" field
echo
echo "Checking for exports field in package.json:"
grep -n '"exports"' "$pkg_path" || echo "No exports field found"
Length of output: 834
Add missing “types” and “exports” to shared-constants package
ESLint can’t resolve @onekey-internal/shared-constants
because its package.json lacks type definitions and export paths. Please update packages/connect-examples/shared-constants/package.json:
{
"name": "@onekey-internal/shared-constants",
"version": "x.y.z",
- "main": "lib/index.js",
+ "main": "lib/index.js",
+ "types": "lib/index.d.ts",
+ "exports": {
+ ".": {
+ "import": "./lib/index.js",
+ "require": "./lib/index.cjs"
+ }
+ },
// …other fields…
}
After adding these fields, rerun lint to confirm the import error is resolved:
yarn lint --max-warnings=0
🧰 Tools
🪛 ESLint
[error] 1-1: Resolve error: typescript with invalid interface loaded as resolver
(import/namespace)
🤖 Prompt for AI Agents
In packages/connect-examples/expo-playground/app/constants/connect.ts line 1,
the import of @onekey-internal/shared-constants fails because the
shared-constants package.json is missing type definitions and export paths; open
packages/connect-examples/shared-constants/package.json and add a "types" field
pointing to the package's d.ts (e.g. "types": "dist/index.d.ts" or the correct
path for your build), and add an "exports" map that exposes the package entry
(and any subpaths you consume) for both import and require (e.g. an export for
"." with import and require targets); ensure main/module fields remain
consistent with your build output, update/commit the package.json, run the
TypeScript build if needed to emit .d.ts, then rerun yarn lint --max-warnings=0
to confirm the resolution.
{ | ||
"name": "@onekey-internal/shared-constants", | ||
"version": "1.1.10-alpha.2", | ||
"private": true, | ||
"author": "OneKey", | ||
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme", | ||
"license": "ISC", | ||
"type": "module", | ||
"main": "constants.js" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Ship types and explicit exports to fix TS/ESLint resolution.
The playground file shows an import/namespace resolver error. Add types and exports so TS and eslint-import can resolve the module cleanly.
Apply:
{
"name": "@onekey-internal/shared-constants",
"version": "1.1.10-alpha.2",
"private": true,
"author": "OneKey",
"homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme",
"license": "ISC",
"type": "module",
- "main": "constants.js"
+ "main": "constants.js",
+ "types": "constants.d.ts",
+ "exports": {
+ ".": {
+ "types": "./constants.d.ts",
+ "default": "./constants.js"
+ }
+ },
+ "files": [
+ "constants.js",
+ "constants.d.ts"
+ ],
+ "sideEffects": false
}
Also add a declaration file:
// packages/connect-examples/shared-constants/constants.d.ts
export function getConnectSrc(): string;
Verify the implementation actually exports the symbol:
🏁 Script executed:
#!/bin/bash
# Confirm the JS export exists
rg -n "export\s+(const|function)\s+getConnectSrc\b" packages/connect-examples/shared-constants/constants.*
Length of output: 147
Expose types and exports in shared-constants
We confirmed getConnectSrc
is already exported in constants.js
. To resolve TS and ESLint import errors, add explicit type declarations and exports:
• packages/connect-examples/shared-constants/package.json
• packages/connect-examples/shared-constants/constants.d.ts
Apply:
--- a/packages/connect-examples/shared-constants/package.json
+++ b/packages/connect-examples/shared-constants/package.json
@@
"type": "module",
- "main": "constants.js"
+ "main": "constants.js",
+ "types": "constants.d.ts",
+ "exports": {
+ ".": {
+ "types": "./constants.d.ts",
+ "default": "./constants.js"
+ }
+ },
+ "files": [
+ "constants.js",
+ "constants.d.ts"
+ ],
+ "sideEffects": false
Add declaration file:
// packages/connect-examples/shared-constants/constants.d.ts
export function getConnectSrc(): string;
Verified export:
rg -n "export\s+(const|function)\s+getConnectSrc\b" packages/connect-examples/shared-constants/constants.js
# → 12:export const getConnectSrc = () =>
🤖 Prompt for AI Agents
In packages/connect-examples/shared-constants/package.json lines 1-10,
TypeScript/ESLint import errors occur because no type declaration is exposed;
add a constants.d.ts file with the declaration "export function getConnectSrc():
string;" at packages/connect-examples/shared-constants/constants.d.ts and update
package.json to include a "types": "constants.d.ts" entry (keep "main":
"constants.js"), so the JS export (already present in constants.js) is
accompanied by an explicit type declaration for consumers.
+++ b/node_modules/react-native-crypto/index.js | ||
@@ -1,28 +1,16 @@ | ||
'use strict' | ||
+import { getRandomValues } from 'react-native-get-random-values'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid ESM in a CommonJS module; switch to require/side‑effect import
Metro can handle ESM, but mixing ESM imports with exports.*
inside node_modules is brittle and has bitten RN projects in CI. Use a side‑effect require to ensure the polyfill runs without interop surprises.
-'use strict'
-import { getRandomValues } from 'react-native-get-random-values';
+'use strict'
+// Ensure Web Crypto RNG is registered in RN (Hermes/JSC)
+require('react-native-get-random-values');
📝 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 { getRandomValues } from 'react-native-get-random-values'; | |
'use strict' | |
// Ensure Web Crypto RNG is registered in RN (Hermes/JSC) | |
require('react-native-get-random-values'); |
🤖 Prompt for AI Agents
In patches/react-native-crypto+2.2.0.patch around line 7, the file currently
uses an ESM import "import { getRandomValues } from
'react-native-get-random-values';" inside a CommonJS module which can break
Metro/CI; replace the ESM import with a side-effect require call so the polyfill
is executed without creating ESM/CommonJS interop issues (i.e., remove the
import line and add a top-level require('react-native-get-random-values');).
-import { randomBytes } from 'react-native-randombytes' | ||
-exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = randomBytes | ||
- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
You removed randomBytes/rng/prng exports — this is a breaking API change
react-native-crypto
used to expose randomBytes
, rng
, pseudoRandomBytes
, and prng
. Dropping them can break downstream code (and deviates from Node’s crypto API). Reintroduce a randomBytes
implementation built on crypto.getRandomValues
, including the 65536-per-call chunking required by the Web Crypto spec, and export the aliases.
@@
-exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = randomBytes
+// Keep Node-compatible randomBytes API (sync and callback forms) using Web Crypto.
+const { Buffer } = require('buffer');
+function randomBytes(size, cb) {
+ if (typeof size !== 'number' || size < 0) {
+ const err = new TypeError('size must be a non-negative number');
+ if (typeof cb === 'function') { setTimeout(() => cb(err), 0); return; }
+ throw err;
+ }
+ const g = typeof globalThis === 'object' ? globalThis : (typeof global === 'object' ? global : {});
+ const gv = g.crypto && typeof g.crypto.getRandomValues === 'function' ? g.crypto.getRandomValues : null;
+ const err = gv ? null : new Error('crypto.getRandomValues is unavailable. Ensure react-native-get-random-values is installed and loaded.');
+ if (!gv) {
+ if (typeof cb === 'function') { setTimeout(() => cb(err), 0); return; }
+ throw err;
+ }
+ // Web Crypto allows max 65536 bytes per call
+ const MAX = 65536;
+ const bytes = new Uint8Array(size);
+ for (let offset = 0; offset < bytes.length; offset += MAX) {
+ gv.call(g.crypto, bytes.subarray(offset, Math.min(offset + MAX, bytes.length)));
+ }
+ const buf = Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
+ if (typeof cb === 'function') { setTimeout(() => cb(null, buf), 0); return; }
+ return buf;
+}
+exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = randomBytes
@@
exports.createHash = exports.Hash = require('create-hash')
exports.createHmac = exports.Hmac = require('create-hmac')
Also applies to: 39-41
+if (typeof globalThis === 'object') { | ||
+ if (!globalThis.crypto) { | ||
+ globalThis.crypto = {}; | ||
+ } | ||
+ if (!globalThis.crypto.getRandomValues) { | ||
+ globalThis.crypto.getRandomValues = getRandomValues; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
🛠️ Refactor suggestion
Harden the global guard and don’t silently skip the polyfill
Older RN environments expose global
but not globalThis
. Also, react-native-get-random-values
typically polyfills via side‑effects; a manual assignment may fail if the package doesn’t export getRandomValues
. Make the guard resilient and try a manual attach only if needed.
-if (typeof globalThis === 'object') {
- if (!globalThis.crypto) {
- globalThis.crypto = {};
- }
- if (!globalThis.crypto.getRandomValues) {
- globalThis.crypto.getRandomValues = getRandomValues;
- }
-}
+const g = typeof globalThis === 'object' ? globalThis : (typeof global === 'object' ? global : undefined);
+if (g) {
+ if (!g.crypto) g.crypto = {};
+ // Side-effect import should have set this; if not, try to attach defensively.
+ if (typeof g.crypto.getRandomValues !== 'function') {
+ try {
+ const maybe = require('react-native-get-random-values');
+ const gv = (maybe && (maybe.getRandomValues || (maybe.default && maybe.default.getRandomValues)));
+ if (typeof gv === 'function') g.crypto.getRandomValues = gv;
+ } catch (_) {
+ // Leave unset; randomBytes will throw a clear 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.
+if (typeof globalThis === 'object') { | |
+ if (!globalThis.crypto) { | |
+ globalThis.crypto = {}; | |
+ } | |
+ if (!globalThis.crypto.getRandomValues) { | |
+ globalThis.crypto.getRandomValues = getRandomValues; | |
} | |
- if (typeof globalThis === 'object') { | |
- if (!globalThis.crypto) { | |
- globalThis.crypto = {}; | |
- } | |
- if (!globalThis.crypto.getRandomValues) { | |
- globalThis.crypto.getRandomValues = getRandomValues; | |
- } | |
const g = typeof globalThis === 'object' | |
? globalThis | |
: (typeof global === 'object' ? global : undefined); | |
if (g) { | |
if (!g.crypto) g.crypto = {}; | |
// Side-effect import should have set this; if not, try to attach defensively. | |
if (typeof g.crypto.getRandomValues !== 'function') { | |
try { | |
const maybe = require('react-native-get-random-values'); | |
const gv = maybe && | |
(maybe.getRandomValues || | |
(maybe.default && maybe.default.getRandomValues)); | |
if (typeof gv === 'function') { | |
g.crypto.getRandomValues = gv; | |
} | |
} catch (_) { | |
// Leave unset; randomBytes will throw a clear error. | |
} | |
} | |
} |
🤖 Prompt for AI Agents
In patches/react-native-crypto+2.2.0.patch around lines 29-35, the global guard
assumes globalThis exists and blindly assigns getRandomValues which can fail in
older RN or when the polyfill is provided only via side-effects; replace the
check with a resilient reference (use globalThis || global) and only attach
getRandomValues if available — if getRandomValues is missing, attempt to load
the polyfill (e.g. require or dynamic import of
'react-native-get-random-values') and then attach its exported function to the
chosen global.crypto if present, otherwise leave the environment untouched (no
silent failure).
1e50f43
to
ca7b95f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
.github/workflows/build-example-android.yml (3)
13-16
: Fix mismatch: step says Node 20 but installs Node 22.Rename the step (or set node-version to '20'). Also enable Yarn cache for faster installs.
- - name: Use Node.js 20 + - name: Use Node.js 22 uses: actions/setup-node@v4 with: - node-version: '22' + node-version: '22' + cache: 'yarn' + cache-dependency-path: 'yarn.lock'
18-23
: Use setup-java’s built-in Gradle cache and drop the manual cache step.This simplifies the workflow and avoids duplicate caches.
- name: Set up JDK 17 - uses: actions/setup-java@v4 + uses: actions/setup-java@v4 with: java-version: '17' distribution: 'zulu' + cache: 'gradle' - - name: Cache Gradle packages - uses: actions/cache@v4 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} - restore-keys: | - ${{ runner.os }}-gradle-Also applies to: 28-36
12-12
: Pin GitHub Actions to specific commit SHAsWe’ve found 33 floating refs across eight workflows. To harden our supply chain, replace every
uses: …@v3
/@v4
with the corresponding full commit SHA.Affected workflows and lines:
- release-web.yml: lines 12, 14, 43
- build-example-android.yml: lines 12, 14, 19, 29, 45
- package-publish.yml: lines 17, 44, 49
- lint.yml: lines 25, 28
- build-packages.yml: lines 25, 28
- github-release.yml: lines 40, 45
- build-example-web.yml: lines 12, 18, 50, 58, 64, 78, 88, 96, 101, 157
- build-example-desktop.yml: lines 11, 13, 33, 41, 49
Actions to pin:
- actions/checkout
- actions/setup-node
- actions/setup-java
- actions/cache
- actions/upload-artifact
- actions/download-artifact
- peaceiris/actions-gh-pages
Please update each occurrence to a fixed commit SHA (e.g.
uses: actions/checkout@<full-sha>
).packages/connect-examples/expo-example/src/components/CommonParamsView.tsx (2)
12-14
: Use functional state update to avoid stale writesMultiple quick edits can drop changes because
commonParams
is captured by closure. Use an updater.- const handleSetParam = (param: string, value: any) => { - setOptionalParams({ ...commonParams, [param]: value }); - }; + type CommonParamsT = typeof commonParams; + const handleSetParam = <K extends keyof CommonParamsT>(key: K, value: CommonParamsT[K]) => { + setOptionalParams((prev: CommonParamsT) => ({ ...prev, [key]: value })); + };
49-49
: Prevent NaN from entering state; parse numbers safelyClearing the input sets
NaN
, which then renders as “NaN”. Treat empty asundefined
and set radix.- onChange={value => handleSetParam('retryCount', parseInt(value))} + onChange={value => + handleSetParam('retryCount', value === '' ? undefined : Number.parseInt(value, 10)) + } @@ - onChange={value => handleSetParam('pollIntervalTime', parseInt(value))} + onChange={value => + handleSetParam('pollIntervalTime', value === '' ? undefined : Number.parseInt(value, 10)) + } @@ - onChange={value => handleSetParam('timeout', parseInt(value))} + onChange={value => + handleSetParam('timeout', value === '' ? undefined : Number.parseInt(value, 10)) + }Also applies to: 55-55, 61-61
♻️ Duplicate comments (6)
packages/connect-examples/shared-constants/package.json (1)
1-10
: Expose types and an exports map to fix TS/ESLint resolution.Add types, exports, files, and mark sideEffects false. This unblocks the import in the example apps.
{ "name": "@onekey-internal/shared-constants", "version": "1.1.10-alpha.2", "private": true, "author": "OneKey", "homepage": "https://github.com/OneKeyHQ/hardware-js-sdk#readme", "license": "ISC", "type": "module", - "main": "constants.js" + "main": "constants.js", + "types": "constants.d.ts", + "exports": { + ".": { + "types": "./constants.d.ts", + "default": "./constants.js" + } + }, + "files": [ + "constants.js", + "constants.d.ts" + ], + "sideEffects": false }Add the declaration file:
// packages/connect-examples/shared-constants/constants.d.ts export function getConnectSrc(): string;#!/bin/bash # Verify the JS export exists rg -n "export\\s+(const|function)\\s+getConnectSrc\\b" packages/connect-examples/shared-constants/constants.*packages/connect-examples/expo-playground/app/constants/connect.ts (1)
1-1
: Import path is correct; ensure shared-constants exposes types/exports.After updating the shared package as suggested, re-run lint to clear the “import/namespace” error.
#!/bin/bash yarn lint --max-warnings=0
packages/connect-examples/expo-example/src/constants/connect.ts (1)
2-2
: Remove obsolete ESLint disable above.The import is no longer relative; drop the suppression.
-// eslint-disable-next-line import/no-relative-packages import { getConnectSrc } from '@onekey-internal/shared-constants';
patches/react-native-crypto+2.2.0.patch (3)
7-7
: Avoid ESM import inside a CommonJS module; use side‑effect requirePrevents Metro/CI interop issues.
-'use strict' -import { getRandomValues } from 'react-native-get-random-values'; +'use strict' +// Ensure Web Crypto RNG is registered in RN (Hermes/JSC) +require('react-native-get-random-values');
9-28
: Restoring randomBytes/rng/prng exports to avoid breaking consumersRemoving these is a breaking change. Reintroduce a Node‑compatible
randomBytes
built oncrypto.getRandomValues
.- import { randomBytes } from 'react-native-randombytes' - exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = randomBytes + const { Buffer } = require('buffer'); + function randomBytes(size, cb) { + if (typeof size !== 'number' || size < 0) { + const err = new TypeError('size must be a non-negative number'); + if (typeof cb === 'function') { setTimeout(() => cb(err), 0); return; } + throw err; + } + const g = typeof globalThis === 'object' ? globalThis : (typeof global === 'object' ? global : {}); + const gv = g.crypto && typeof g.crypto.getRandomValues === 'function' ? g.crypto.getRandomValues : null; + const noRngErr = new Error('crypto.getRandomValues is unavailable. Ensure react-native-get-random-values is installed and loaded.'); + if (!gv) { + if (typeof cb === 'function') { setTimeout(() => cb(noRngErr), 0); return; } + throw noRngErr; + } + const MAX = 65536; // Web Crypto max per call + const bytes = new Uint8Array(size); + for (let off = 0; off < bytes.length; off += MAX) { + gv.call(g.crypto, bytes.subarray(off, Math.min(off + MAX, bytes.length))); + } + const buf = Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength); + if (typeof cb === 'function') { setTimeout(() => cb(null, buf), 0); return; } + return buf; + } + exports.randomBytes = exports.rng = exports.pseudoRandomBytes = exports.prng = randomBytes
29-36
: Harden the global guard; attach polyfill defensivelySupport
globalThis
andglobal
, and only attach if available.-if (typeof globalThis === 'object') { - if (!globalThis.crypto) { - globalThis.crypto = {}; - } - if (!globalThis.crypto.getRandomValues) { - globalThis.crypto.getRandomValues = getRandomValues; - } -} +const g = typeof globalThis === 'object' ? globalThis : (typeof global === 'object' ? global : undefined); +if (g) { + if (!g.crypto) g.crypto = {}; + // Side-effect import should set this; if not, try to attach safely. + if (typeof g.crypto.getRandomValues !== 'function') { + try { + const maybe = require('react-native-get-random-values'); + const gv = maybe && (maybe.getRandomValues || (maybe.default && maybe.default.getRandomValues)); + if (typeof gv === 'function') g.crypto.getRandomValues = gv; + } catch (_) { + // Leave unset; randomBytes will throw a clear error. + } + } +}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (7)
.github/workflows/build-example-android.yml
(2 hunks)package.json
(1 hunks)packages/connect-examples/expo-example/src/components/CommonParamsView.tsx
(1 hunks)packages/connect-examples/expo-example/src/constants/connect.ts
(1 hunks)packages/connect-examples/expo-playground/app/constants/connect.ts
(1 hunks)packages/connect-examples/shared-constants/package.json
(1 hunks)patches/react-native-crypto+2.2.0.patch
(1 hunks)
🧰 Additional context used
🪛 ESLint
packages/connect-examples/expo-playground/app/constants/connect.ts
[error] 1-1: Resolve error: typescript with invalid interface loaded as resolver
(import/namespace)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: build (22)
- GitHub Check: lint (22)
🔇 Additional comments (1)
package.json (1)
13-17
: Workspace entry LGTM.New shared-constants workspace is correctly added.
<CommonInput | ||
label="Passphrase State" | ||
type="text" | ||
value={commonParams.passphraseState ?? ''} | ||
onChange={value => handleSetParam('passphraseState', value)} | ||
/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Validate passphraseState values
If only specific states are valid, consider a select with fixed options to prevent bad inputs.
🧹 Nitpick (assertive)
Localize the “Passphrase State” label
Keep labels consistent with react-intl
.
- <CommonInput
- label="Passphrase State"
+ <CommonInput
+ label={intl.formatMessage({
+ id: 'label__passphrase_state',
+ defaultMessage: 'Passphrase State',
+ })}
📝 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.
<CommonInput | |
label="Passphrase State" | |
type="text" | |
value={commonParams.passphraseState ?? ''} | |
onChange={value => handleSetParam('passphraseState', value)} | |
/> | |
<CommonInput | |
label={intl.formatMessage({ | |
id: 'label__passphrase_state', | |
defaultMessage: 'Passphrase State', | |
})} | |
type="text" | |
value={commonParams.passphraseState ?? ''} | |
onChange={value => handleSetParam('passphraseState', value)} | |
/> |
🤖 Prompt for AI Agents
In packages/connect-examples/expo-example/src/components/CommonParamsView.tsx
around lines 19 to 24, the hardcoded label "Passphrase State" should be
localized using react-intl; replace the literal string with a formatted message
lookup (e.g., use intl.formatMessage or <FormattedMessage
id="common.passphraseState" defaultMessage="Passphrase State" />) and add the
corresponding message id and defaultMessage to the component's messages bundle
or messages file so the label renders via react-intl.
label="skipPassphraseCheck" | ||
value={!!commonParams.skipPassphraseCheck} | ||
onToggle={value => handleSetParam('skipPassphraseCheck', value)} | ||
/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 Nitpick (assertive)
Localize the “skipPassphraseCheck” label
Avoid raw strings; align with other labels.
- <SwitchInput
- label="skipPassphraseCheck"
+ <SwitchInput
+ label={intl.formatMessage({
+ id: 'label__skip_passphrase_check',
+ defaultMessage: 'Skip passphrase check',
+ })}
📝 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.
label="skipPassphraseCheck" | |
value={!!commonParams.skipPassphraseCheck} | |
onToggle={value => handleSetParam('skipPassphraseCheck', value)} | |
/> | |
<SwitchInput | |
label={intl.formatMessage({ | |
id: 'label__skip_passphrase_check', | |
defaultMessage: 'Skip passphrase check', | |
})} | |
value={!!commonParams.skipPassphraseCheck} | |
onToggle={value => handleSetParam('skipPassphraseCheck', value)} | |
/> |
🤖 Prompt for AI Agents
In packages/connect-examples/expo-example/src/components/CommonParamsView.tsx
around lines 31 to 34, the Switch label uses a raw string "skipPassphraseCheck";
replace it with the app's localization key like other labels (e.g. use the
existing i18n/t function or labels object) so the label reads
t('skipPassphraseCheck') or labels.common.skipPassphraseCheck (matching the
project pattern), and ensure the translation key exists in the locale files.
Summary by CodeRabbit