diff --git a/src/Utils/chat-utils.ts b/src/Utils/chat-utils.ts index d35ec93a..ff872a26 100644 --- a/src/Utils/chat-utils.ts +++ b/src/Utils/chat-utils.ts @@ -19,7 +19,7 @@ import { type MessageLabelAssociation } from '../Types/LabelAssociation' import { type BinaryNode, getBinaryNodeChild, getBinaryNodeChildren, isJidGroup, jidNormalizedUser } from '../WABinary' -import { expandAppStateKeys } from 'whatsapp-rust-bridge' +import { expandAppStateKeys } from './wasm-bridge' import { aesDecrypt, aesEncrypt, hmacSign } from './crypto' import { toNumber } from './generics' import type { ILogger } from './logger' @@ -102,7 +102,7 @@ const makeLtHashGenerator = ({ indexValueMap, hash }: Pick { - const result = LT_HASH_ANTI_TAMPERING.subtractThenAdd(new Uint8Array(hash), addBuffs, subBuffs) + const result = LT_HASH_ANTI_TAMPERING().subtractThenAdd(new Uint8Array(hash), addBuffs, subBuffs) return { hash: Buffer.from(result), diff --git a/src/Utils/crypto.ts b/src/Utils/crypto.ts index 9152b01f..982828a5 100644 --- a/src/Utils/crypto.ts +++ b/src/Utils/crypto.ts @@ -118,7 +118,7 @@ export function sha256(buffer: Buffer) { return createHash('sha256').update(buffer).digest() } -export { hkdf, md5 } from 'whatsapp-rust-bridge' +export { hkdf, md5 } from './wasm-bridge' export async function derivePairingCodeKey(pairingCode: string, salt: Buffer): Promise { // Convert inputs to formats Web Crypto API can work with diff --git a/src/Utils/index.ts b/src/Utils/index.ts index 0b376f3d..2c8e793b 100644 --- a/src/Utils/index.ts +++ b/src/Utils/index.ts @@ -9,6 +9,7 @@ export * from './noise-handler' export * from './history' export * from './chat-utils' export * from './lt-hash' +export { wasmBridgeReady } from './wasm-bridge' export * from './auth-utils' export * from './use-multi-file-auth-state' export * from './link-preview' diff --git a/src/Utils/lt-hash.ts b/src/Utils/lt-hash.ts index 9bae3362..8da2a1b6 100644 --- a/src/Utils/lt-hash.ts +++ b/src/Utils/lt-hash.ts @@ -1,3 +1,3 @@ -import { LTHashAntiTampering } from 'whatsapp-rust-bridge' +import { getLTHashAntiTampering } from './wasm-bridge' -export const LT_HASH_ANTI_TAMPERING = new LTHashAntiTampering() +export { getLTHashAntiTampering as LT_HASH_ANTI_TAMPERING } diff --git a/src/Utils/wasm-bridge.ts b/src/Utils/wasm-bridge.ts new file mode 100644 index 00000000..1c603907 --- /dev/null +++ b/src/Utils/wasm-bridge.ts @@ -0,0 +1,40 @@ +type WasmBridgeModule = typeof import('whatsapp-rust-bridge') + +let _bridge: WasmBridgeModule | undefined + +// Start loading eagerly using .then() instead of top-level await. +// This prevents the whatsapp-rust-bridge top-level await from propagating +// through the ESM graph, which would break CJS require() consumers. +const _bridgeReady = import('whatsapp-rust-bridge').then(m => { + _bridge = m + return m +}) + +export { _bridgeReady as wasmBridgeReady } + +function getBridge(): WasmBridgeModule { + if (!_bridge) { + throw new Error( + 'whatsapp-rust-bridge not yet loaded. ' + + 'Ensure async operations have started before calling crypto functions.' + ) + } + + return _bridge +} + +export const hkdf: WasmBridgeModule['hkdf'] = (...args) => getBridge().hkdf(...args) + +export const md5: WasmBridgeModule['md5'] = (...args) => getBridge().md5(...args) + +export const expandAppStateKeys: WasmBridgeModule['expandAppStateKeys'] = (...args) => getBridge().expandAppStateKeys(...args) + +let _ltHash: InstanceType | undefined + +export function getLTHashAntiTampering(): InstanceType { + if (!_ltHash) { + _ltHash = new (getBridge().LTHashAntiTampering)() + } + + return _ltHash +}