@zerodev/wallet-core 0.0.1-alpha.21 → 0.0.1-alpha.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +56 -0
  2. package/dist/_cjs/core/createZeroDevWalletCore.js +3 -1
  3. package/dist/_cjs/core/createZeroDevWalletCore.js.map +1 -1
  4. package/dist/_cjs/index.native.js +2 -2
  5. package/dist/_cjs/index.native.js.map +1 -1
  6. package/dist/_cjs/native/createZeroDevWallet.js +13 -0
  7. package/dist/_cjs/native/createZeroDevWallet.js.map +1 -0
  8. package/dist/_cjs/stampers/noopPasskeyStamper.js +16 -0
  9. package/dist/_cjs/stampers/noopPasskeyStamper.js.map +1 -0
  10. package/dist/_cjs/stubs/native-on-web.js +10 -1
  11. package/dist/_cjs/stubs/native-on-web.js.map +1 -1
  12. package/dist/_cjs/utils/exportWallet.js +52 -57
  13. package/dist/_cjs/utils/exportWallet.js.map +1 -1
  14. package/dist/_esm/core/createZeroDevWalletCore.js +3 -1
  15. package/dist/_esm/core/createZeroDevWalletCore.js.map +1 -1
  16. package/dist/_esm/index.native.js +5 -4
  17. package/dist/_esm/index.native.js.map +1 -1
  18. package/dist/_esm/native/createZeroDevWallet.js +10 -0
  19. package/dist/_esm/native/createZeroDevWallet.js.map +1 -0
  20. package/dist/_esm/stampers/noopPasskeyStamper.js +18 -0
  21. package/dist/_esm/stampers/noopPasskeyStamper.js.map +1 -0
  22. package/dist/_esm/stubs/native-on-web.js +24 -2
  23. package/dist/_esm/stubs/native-on-web.js.map +1 -1
  24. package/dist/_esm/utils/exportWallet.js +52 -57
  25. package/dist/_esm/utils/exportWallet.js.map +1 -1
  26. package/dist/_types/core/createZeroDevWalletCore.d.ts +1 -1
  27. package/dist/_types/core/createZeroDevWalletCore.d.ts.map +1 -1
  28. package/dist/_types/index.native.d.ts +1 -1
  29. package/dist/_types/index.native.d.ts.map +1 -1
  30. package/dist/_types/native/createZeroDevWallet.d.ts +12 -0
  31. package/dist/_types/native/createZeroDevWallet.d.ts.map +1 -0
  32. package/dist/_types/stampers/noopPasskeyStamper.d.ts +8 -0
  33. package/dist/_types/stampers/noopPasskeyStamper.d.ts.map +1 -0
  34. package/dist/_types/stubs/native-on-web.d.ts +5 -1
  35. package/dist/_types/stubs/native-on-web.d.ts.map +1 -1
  36. package/dist/_types/utils/exportWallet.d.ts.map +1 -1
  37. package/dist/tsconfig.build.tsbuildinfo +1 -1
  38. package/package.json +5 -1
  39. package/src/core/createZeroDevWalletCore.ts +3 -2
  40. package/src/index.native.ts +7 -6
  41. package/src/native/createZeroDevWallet.ts +26 -0
  42. package/src/stampers/noopPasskeyStamper.ts +21 -0
  43. package/src/stubs/native-on-web.ts +29 -3
  44. package/src/utils/exportWallet.ts +65 -70
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerodev/wallet-core",
3
- "version": "0.0.1-alpha.21",
3
+ "version": "0.0.1-alpha.22",
4
4
  "description": "ZeroDev Wallet SDK built on Turnkey",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/_cjs/index.js",
@@ -31,6 +31,7 @@
31
31
  },
32
32
  "./react-native": {
33
33
  "browser": "./dist/_esm/stubs/native-on-web.js",
34
+ "node": "./dist/_esm/stubs/native-on-web.js",
34
35
  "import": {
35
36
  "types": "./dist/_types/index.native.d.ts",
36
37
  "default": "./dist/_esm/index.native.js"
@@ -39,6 +40,7 @@
39
40
  },
40
41
  "./react-native/stampers/secure-store": {
41
42
  "browser": "./dist/_esm/stubs/native-on-web.js",
43
+ "node": "./dist/_esm/stubs/native-on-web.js",
42
44
  "import": {
43
45
  "types": "./dist/_types/native/stampers/secureStore.d.ts",
44
46
  "default": "./dist/_esm/native/stampers/secureStore.js"
@@ -47,6 +49,7 @@
47
49
  },
48
50
  "./react-native/stampers/passkey": {
49
51
  "browser": "./dist/_esm/stubs/native-on-web.js",
52
+ "node": "./dist/_esm/stubs/native-on-web.js",
50
53
  "import": {
51
54
  "types": "./dist/_types/native/stampers/passkey.d.ts",
52
55
  "default": "./dist/_esm/native/stampers/passkey.js"
@@ -55,6 +58,7 @@
55
58
  },
56
59
  "./react-native/storage/async-storage": {
57
60
  "browser": "./dist/_esm/stubs/native-on-web.js",
61
+ "node": "./dist/_esm/stubs/native-on-web.js",
58
62
  "import": {
59
63
  "types": "./dist/_types/native/storage/asyncStorage.d.ts",
60
64
  "default": "./dist/_esm/native/storage/asyncStorage.js"
@@ -16,6 +16,7 @@ import {
16
16
  DEFAULT_SESSION_EXPIRATION_IN_SECONDS,
17
17
  KMS_SERVER_URL,
18
18
  } from '../constants.js'
19
+ import { createNoopPasskeyStamper } from '../stampers/noopPasskeyStamper.js'
19
20
  import type { ApiKeyStamper, PasskeyStamper } from '../stampers/types.js'
20
21
  import {
21
22
  createStorageManager,
@@ -32,7 +33,7 @@ export interface ZeroDevWalletConfigCore {
32
33
  sessionStorage: StorageAdapter
33
34
  rpId: string
34
35
  apiKeyStamper: ApiKeyStamper
35
- passkeyStamper: PasskeyStamper
36
+ passkeyStamper?: PasskeyStamper
36
37
  fetchOptions?: CreateTransportOptions['fetchOptions']
37
38
  }
38
39
 
@@ -123,9 +124,9 @@ export async function createZeroDevWalletCore(
123
124
  sessionStorage,
124
125
  rpId,
125
126
  apiKeyStamper,
126
- passkeyStamper,
127
127
  organizationId = DEFAULT_ORGANIZATION_ID,
128
128
  } = config
129
+ const passkeyStamper = config.passkeyStamper ?? createNoopPasskeyStamper()
129
130
 
130
131
  const sessionStorageManager = createStorageManager(sessionStorage)
131
132
 
@@ -79,13 +79,14 @@ export type {
79
79
  AuthParams,
80
80
  ZeroDevWalletSDK,
81
81
  } from './core/createZeroDevWalletCore.js'
82
- // RN entry re-exports core directly. `ZeroDevWalletConfigCore` already has
83
- // all four adapter fields required, so RN consumers get compile-time enforcement
84
- // without a separate type wrapper.
82
+ // RN entry re-exports through a thin wrapper that auto-injects the
83
+ // `Origin: https://${rpId}` header on Turnkey requests. `ZeroDevWalletConfig`
84
+ // matches the strict `ZeroDevWalletConfigCore` shape, so RN consumers still
85
+ // get compile-time enforcement of the four required adapter fields.
85
86
  export {
86
- createZeroDevWalletCore as createZeroDevWallet,
87
- type ZeroDevWalletConfigCore as ZeroDevWalletConfig,
88
- } from './core/createZeroDevWalletCore.js'
87
+ createZeroDevWallet,
88
+ type ZeroDevWalletConfig,
89
+ } from './native/createZeroDevWallet.js'
89
90
  export type {
90
91
  ApiKeyStamper,
91
92
  Attestation,
@@ -0,0 +1,26 @@
1
+ import {
2
+ createZeroDevWalletCore,
3
+ type ZeroDevWalletConfigCore,
4
+ type ZeroDevWalletSDK,
5
+ } from '../core/createZeroDevWalletCore.js'
6
+
7
+ /**
8
+ * React Native config — mirrors `web/createZeroDevWallet.ts`'s wrapper
9
+ * pattern. RN consumers must supply all four adapter fields up front
10
+ * (no platform-native defaults exist for IndexedDB/WebAuthn). The only
11
+ * RN-specific defaulting is `fetchOptions`: when omitted, we set
12
+ * `Origin: https://${rpId}` so Turnkey's ACL accepts the request. Power
13
+ * users wanting a different Origin can pass `fetchOptions` explicitly.
14
+ */
15
+ export type ZeroDevWalletConfig = ZeroDevWalletConfigCore
16
+
17
+ export async function createZeroDevWallet(
18
+ config: ZeroDevWalletConfig,
19
+ ): Promise<ZeroDevWalletSDK> {
20
+ return createZeroDevWalletCore({
21
+ ...config,
22
+ fetchOptions: config.fetchOptions ?? {
23
+ headers: { Origin: `https://${config.rpId}` },
24
+ },
25
+ })
26
+ }
@@ -0,0 +1,21 @@
1
+ import type { PasskeyStamper } from './types.js'
2
+
3
+ const NOT_CONFIGURED_MESSAGE =
4
+ 'passkeyStamper is not configured. Pass passkeyStamper to zeroDevWallet({ ... }) — use createReactNativePasskeyStamper({ rpId }) on React Native or createWebauthnStamper({ rpId }) on web.'
5
+
6
+ /**
7
+ * Internal fallback used when a consumer doesn't supply a `passkeyStamper`.
8
+ * Methods throw on use, so passkey register/login fails with an actionable
9
+ * message — all other flows (apiKey signing, OAuth, OTP) are unaffected.
10
+ */
11
+ export function createNoopPasskeyStamper(): PasskeyStamper {
12
+ return {
13
+ async stamp() {
14
+ throw new Error(NOT_CONFIGURED_MESSAGE)
15
+ },
16
+ async register() {
17
+ throw new Error(NOT_CONFIGURED_MESSAGE)
18
+ },
19
+ async clear() {},
20
+ }
21
+ }
@@ -1,3 +1,29 @@
1
- throw new Error(
2
- '@zerodev/wallet-core react-native subpaths cannot be imported in a web environment. Use the bare specifier (`import { ... } from "@zerodev/wallet-core"`) instead.',
3
- )
1
+ // Catch-all stub used by every `./react-native/*` subpath in this package
2
+ // under the `browser` and `node` exports conditions. Both are needed for
3
+ // Expo web: the client bundle resolves with `browser` active, while Expo
4
+ // Router's SSR/RSC route render drops platform conditions (no `browser`)
5
+ // and turns on `node` instead — so the web stub has to be gated on both or
6
+ // the SSR pass falls through to the native impl. Imports must be safe on web
7
+ // (some route files are bundled even when they aren't rendered) so we expose
8
+ // the RN-only symbols as throw-on-use functions instead of throwing at
9
+ // module-init time.
10
+ //
11
+ // Anyone who *uses* these on web gets a clear actionable error; anyone who
12
+ // merely imports them (typically because their universal app bundles the
13
+ // native variant too) is unaffected.
14
+
15
+ const message =
16
+ '@zerodev/wallet-core react-native subpaths cannot be imported in a web environment. Use the bare specifier (`import { ... } from "@zerodev/wallet-core"`) instead.'
17
+
18
+ function throwOnUse(): never {
19
+ throw new Error(message)
20
+ }
21
+
22
+ export const createSecureStoreStamper = throwOnUse
23
+ export const createReactNativePasskeyStamper = throwOnUse
24
+ export const asyncStorageAdapter = throwOnUse
25
+
26
+ // For the broad `./react-native` entry: any consumer reaching it on web is
27
+ // already off-pattern (they should use the bare specifier). Default export
28
+ // covers `import X from '...'`.
29
+ export default throwOnUse
@@ -43,84 +43,79 @@ export async function exportWallet(
43
43
  ): Promise<{ exportBundle: string; walletId: string; organizationId: string }> {
44
44
  const { targetPublicKey, wallet } = params
45
45
 
46
- try {
47
- const session = await wallet.getSession()
48
- if (!session) {
49
- throw new Error('Session not found')
50
- }
51
- const { organizationId } = session
46
+ const session = await wallet.getSession()
47
+ if (!session) {
48
+ throw new Error('Session not found')
49
+ }
50
+ const { organizationId } = session
52
51
 
53
- const listWalletsBody = JSON.stringify({
54
- organizationId,
55
- })
52
+ const listWalletsBody = JSON.stringify({
53
+ organizationId,
54
+ })
56
55
 
57
- const listWalletsStamp =
58
- await wallet.client[
59
- session.stamperType === 'apiKey' ? 'apiKeyStamper' : 'passkeyStamper'
60
- ].stamp(listWalletsBody)
61
- if (!listWalletsStamp) {
62
- throw new Error('Failed to stamp list wallets body')
63
- }
56
+ const listWalletsStamp =
57
+ await wallet.client[
58
+ session.stamperType === 'apiKey' ? 'apiKeyStamper' : 'passkeyStamper'
59
+ ].stamp(listWalletsBody)
60
+ if (!listWalletsStamp) {
61
+ throw new Error('Failed to stamp list wallets body')
62
+ }
64
63
 
65
- const listWalletsResponse = await fetch(
66
- 'https://api.turnkey.com/public/v1/query/list_wallets',
67
- {
68
- method: 'POST',
69
- body: listWalletsBody,
70
- headers: {
71
- [listWalletsStamp.stampHeaderName]: listWalletsStamp.stampHeaderValue,
72
- },
64
+ const listWalletsResponse = await fetch(
65
+ 'https://api.turnkey.com/public/v1/query/list_wallets',
66
+ {
67
+ method: 'POST',
68
+ body: listWalletsBody,
69
+ headers: {
70
+ [listWalletsStamp.stampHeaderName]: listWalletsStamp.stampHeaderValue,
73
71
  },
74
- )
75
- if (!listWalletsResponse.ok) {
76
- throw new Error('Failed to list wallets')
77
- }
78
- const listWalletsData = await listWalletsResponse.json()
72
+ },
73
+ )
74
+ if (!listWalletsResponse.ok) {
75
+ throw new Error('Failed to list wallets')
76
+ }
77
+ const listWalletsData = await listWalletsResponse.json()
79
78
 
80
- const walletId = listWalletsData.wallets[0].walletId
79
+ const walletId = listWalletsData.wallets[0].walletId
81
80
 
82
- const exportWalletBody = JSON.stringify({
83
- type: 'ACTIVITY_TYPE_EXPORT_WALLET',
84
- timestampMs: Date.now().toString(),
85
- organizationId: organizationId,
86
- parameters: {
87
- walletId: walletId,
88
- targetPublicKey,
89
- language: 'MNEMONIC_LANGUAGE_ENGLISH',
90
- },
91
- })
92
- const exportWalletStamp =
93
- await wallet.client[
94
- session.stamperType === 'apiKey' ? 'apiKeyStamper' : 'passkeyStamper'
95
- ].stamp(exportWalletBody)
96
- if (!exportWalletStamp) {
97
- throw new Error('Failed to stamp export wallet body')
98
- }
99
- const exportWalletResponse = await fetch(
100
- 'https://api.turnkey.com/public/v1/submit/export_wallet',
101
- {
102
- method: 'POST',
103
- body: exportWalletBody,
104
- headers: {
105
- [exportWalletStamp.stampHeaderName]:
106
- exportWalletStamp.stampHeaderValue,
107
- },
81
+ const exportWalletBody = JSON.stringify({
82
+ type: 'ACTIVITY_TYPE_EXPORT_WALLET',
83
+ timestampMs: Date.now().toString(),
84
+ organizationId: organizationId,
85
+ parameters: {
86
+ walletId: walletId,
87
+ targetPublicKey,
88
+ language: 'MNEMONIC_LANGUAGE_ENGLISH',
89
+ },
90
+ })
91
+ const exportWalletStamp =
92
+ await wallet.client[
93
+ session.stamperType === 'apiKey' ? 'apiKeyStamper' : 'passkeyStamper'
94
+ ].stamp(exportWalletBody)
95
+ if (!exportWalletStamp) {
96
+ throw new Error('Failed to stamp export wallet body')
97
+ }
98
+ const exportWalletResponse = await fetch(
99
+ 'https://api.turnkey.com/public/v1/submit/export_wallet',
100
+ {
101
+ method: 'POST',
102
+ body: exportWalletBody,
103
+ headers: {
104
+ [exportWalletStamp.stampHeaderName]: exportWalletStamp.stampHeaderValue,
108
105
  },
109
- )
110
- if (!exportWalletResponse.ok) {
111
- throw new Error('Failed to export wallet')
112
- }
113
- const exportWalletData = await exportWalletResponse.json()
114
-
115
- const exportBundle =
116
- exportWalletData?.activity?.result?.exportWalletResult?.exportBundle
106
+ },
107
+ )
108
+ if (!exportWalletResponse.ok) {
109
+ throw new Error('Failed to export wallet')
110
+ }
111
+ const exportWalletData = await exportWalletResponse.json()
117
112
 
118
- if (!exportBundle) {
119
- throw new Error('Export bundle not found in response')
120
- }
113
+ const exportBundle =
114
+ exportWalletData?.activity?.result?.exportWalletResult?.exportBundle
121
115
 
122
- return { exportBundle, walletId, organizationId }
123
- } catch (_) {
124
- throw new Error('Error exporting wallet')
116
+ if (!exportBundle) {
117
+ throw new Error('Export bundle not found in response')
125
118
  }
119
+
120
+ return { exportBundle, walletId, organizationId }
126
121
  }