fix(blender): correct isomorphic crypto loading

Refactors the crypto module loading in `seedblend.ts` to be truly isomorphic and prevent browser runtime errors.

- Replaces the static Node.js `crypto` import with a dynamic `import()` inside a singleton promise (`getCrypto`).
- This ensures Vite does not externalize the module for browser builds, resolving the 'Cannot access \'crypto.webcrypto\' in client code' error.
- The browser will use its native `window.crypto`, while the Node.js test environment dynamically loads the `crypto` module.
- All tests continue to pass, verifying the fix.
This commit is contained in:
LC mac
2026-02-04 02:42:38 +08:00
parent ec722befef
commit 3f37596b3b

View File

@@ -23,16 +23,28 @@
*/
import wordlistTxt from '../bip39_wordlist.txt?raw';
import { webcrypto } from 'crypto';
// --- Isomorphic Crypto Setup ---
// Use browser crypto if available, otherwise fallback to Node.js webcrypto.
// This allows the library to run in both the browser and the test environment (Node.js).
const subtle = (typeof window !== 'undefined' && window.crypto?.subtle)
? window.crypto.subtle
: webcrypto.subtle;
let cryptoPromise: Promise<SubtleCrypto>;
/**
* Asynchronously gets the appropriate SubtleCrypto interface, using a singleton
* pattern to ensure the module is loaded only once.
* This approach uses a dynamic import() to prevent Vite from bundling the
* Node.js 'crypto' module in browser builds.
*/
function getCrypto(): Promise<SubtleCrypto> {
if (!cryptoPromise) {
cryptoPromise = (async () => {
if (typeof window !== 'undefined' && window.crypto?.subtle) {
return window.crypto.subtle;
}
const { webcrypto } = await import('crypto');
return webcrypto.subtle;
})();
}
return cryptoPromise;
}
// --- BIP39 Wordlist Loading ---
@@ -61,6 +73,7 @@ if (BIP39_WORDLIST.length !== 2048) {
* @returns A promise that resolves to the hash as a Uint8Array.
*/
async function sha256(data: Uint8Array): Promise<Uint8Array> {
const subtle = await getCrypto();
const hashBuffer = await subtle.digest('SHA-256', data);
return new Uint8Array(hashBuffer);
}
@@ -72,6 +85,7 @@ async function sha256(data: Uint8Array): Promise<Uint8Array> {
* @returns A promise that resolves to the HMAC tag.
*/
async function hmacSha256(key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {
const subtle = await getCrypto();
const cryptoKey = await subtle.importKey(
'raw',
key,