MetaMask / MetaMask/connect-monorepo
[connect-multichain] createKeyManager() throws "PrivateKey is not a constructor" in browser bundles — eciesjs is CJS-only
- Dominant language
- TypeScript
- Stars
- 12
- Forks
- 11
- PR merge metrics
- No merged PRs in 30d
Description
### What happens
`@metamask/connect-multichain@1.2.0`. Connecting via MWP (the QR flow, no extension installed) throws `PrivateKey is not a constructor` in a production browser bundle. Seen on Angular 22 / esbuild; reproduces in a Vite production build too, but **not** in Vite dev.
### Cause
[`packages/connect-multichain/src/multichain/transports/mwp/KeyManager.ts#L20`](https://github.com/MetaMask/connect-monorepo/blob/main/packages/connect-multichain/src/multichain/transports/mwp/KeyManager.ts#L20):
```ts
const { decrypt, encrypt, PrivateKey, PublicKey } = await import('eciesjs');
```
`eciesjs@0.4.17` is CJS-only — no `module` field, and its `exports` map has no `import` condition. Bundlers therefore shape the dynamic import as `{ default: }`, leaving all four bindings `undefined`. Node and Vite's dev prebundle synthesize the named exports, which is likely why this wasn't caught.
Introduced by #244, which moved eciesjs behind `import()`.
### Workaround we ship (patched dist)
```js
const ecies = await import('eciesjs');
const { decrypt, encrypt, PrivateKey, PublicKey } = ecies.default ?? ecies;
```
Happy to open that as a PR if you want it — the source version needs a small cast, and you may prefer a static import or an ESM-capable crypto dependency instead.
### Same bug, two lines away
`#createDappClient()` in `src/multichain/index.ts` destructures `mwpCore.SessionStore` from `await import('@metamask/mobile-wallet-protocol-core')`, which is also CJS-resolved, giving `undefined is not an object (evaluating 'mwpCore.SessionStore.create')`. That one's root cause is a missing `exports` field upstream, fixed in MetaMask/mobile-wallet-protocol#85 — but it needs a release before it reaches consumers.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Contributor guide
Research direction
Start at packages/connect-multichain/src/multichain/transports/mwp/KeyManager.ts around the dynamic eciesjs import, then inspect the related dynamic import in src/multichain/index.ts. Verify the change with a production Vite or esbuild browser bundle using the MWP QR flow; done means the crypto bindings and SessionStore are available instead of producing the reported constructor or undefined-object errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- angular, typescript, vite
- Domain
- build-system, cryptography, web-dev
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 70/100