@zerodev/wallet-core 0.0.1-alpha.3

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 (250) hide show
  1. package/README.md +272 -0
  2. package/dist/_cjs/actions/auth/authenticateWithEmail.js +17 -0
  3. package/dist/_cjs/actions/auth/authenticateWithEmail.js.map +1 -0
  4. package/dist/_cjs/actions/auth/authenticateWithOAuth.js +17 -0
  5. package/dist/_cjs/actions/auth/authenticateWithOAuth.js.map +1 -0
  6. package/dist/_cjs/actions/auth/getWhoami.js +15 -0
  7. package/dist/_cjs/actions/auth/getWhoami.js.map +1 -0
  8. package/dist/_cjs/actions/auth/index.js +18 -0
  9. package/dist/_cjs/actions/auth/index.js.map +1 -0
  10. package/dist/_cjs/actions/auth/loginWithOTP.js +17 -0
  11. package/dist/_cjs/actions/auth/loginWithOTP.js.map +1 -0
  12. package/dist/_cjs/actions/auth/loginWithStamp.js +29 -0
  13. package/dist/_cjs/actions/auth/loginWithStamp.js.map +1 -0
  14. package/dist/_cjs/actions/auth/registerWithOTP.js +17 -0
  15. package/dist/_cjs/actions/auth/registerWithOTP.js.map +1 -0
  16. package/dist/_cjs/actions/auth/registerWithPasskey.js +17 -0
  17. package/dist/_cjs/actions/auth/registerWithPasskey.js.map +1 -0
  18. package/dist/_cjs/actions/index.js +15 -0
  19. package/dist/_cjs/actions/index.js.map +1 -0
  20. package/dist/_cjs/actions/wallet/getUserWallet.js +13 -0
  21. package/dist/_cjs/actions/wallet/getUserWallet.js.map +1 -0
  22. package/dist/_cjs/actions/wallet/index.js +10 -0
  23. package/dist/_cjs/actions/wallet/index.js.map +1 -0
  24. package/dist/_cjs/actions/wallet/signRawPayload.js +26 -0
  25. package/dist/_cjs/actions/wallet/signRawPayload.js.map +1 -0
  26. package/dist/_cjs/actions/wallet/signTransaction.js +25 -0
  27. package/dist/_cjs/actions/wallet/signTransaction.js.map +1 -0
  28. package/dist/_cjs/adapters/viem.js +89 -0
  29. package/dist/_cjs/adapters/viem.js.map +1 -0
  30. package/dist/_cjs/client/createClient.js +45 -0
  31. package/dist/_cjs/client/createClient.js.map +1 -0
  32. package/dist/_cjs/client/decorators/client.js +21 -0
  33. package/dist/_cjs/client/decorators/client.js.map +1 -0
  34. package/dist/_cjs/client/index.js +9 -0
  35. package/dist/_cjs/client/index.js.map +1 -0
  36. package/dist/_cjs/client/transports/createTransport.js +29 -0
  37. package/dist/_cjs/client/transports/createTransport.js.map +1 -0
  38. package/dist/_cjs/client/transports/rest.js +86 -0
  39. package/dist/_cjs/client/transports/rest.js.map +1 -0
  40. package/dist/_cjs/client/types.js +3 -0
  41. package/dist/_cjs/client/types.js.map +1 -0
  42. package/dist/_cjs/constants.js +9 -0
  43. package/dist/_cjs/constants.js.map +1 -0
  44. package/dist/_cjs/core/createZeroDevWallet.js +330 -0
  45. package/dist/_cjs/core/createZeroDevWallet.js.map +1 -0
  46. package/dist/_cjs/errors/request.js +61 -0
  47. package/dist/_cjs/errors/request.js.map +1 -0
  48. package/dist/_cjs/index.js +31 -0
  49. package/dist/_cjs/index.js.map +1 -0
  50. package/dist/_cjs/package.json +1 -0
  51. package/dist/_cjs/polyfills/window.js +26 -0
  52. package/dist/_cjs/polyfills/window.js.map +1 -0
  53. package/dist/_cjs/stampers/iframeStamper.js +32 -0
  54. package/dist/_cjs/stampers/iframeStamper.js.map +1 -0
  55. package/dist/_cjs/stampers/index.js +10 -0
  56. package/dist/_cjs/stampers/index.js.map +1 -0
  57. package/dist/_cjs/stampers/indexedDbStamper.js +23 -0
  58. package/dist/_cjs/stampers/indexedDbStamper.js.map +1 -0
  59. package/dist/_cjs/stampers/types.js +3 -0
  60. package/dist/_cjs/stampers/types.js.map +1 -0
  61. package/dist/_cjs/stampers/webauthnStamper.js +17 -0
  62. package/dist/_cjs/stampers/webauthnStamper.js.map +1 -0
  63. package/dist/_cjs/storage/adapters.js +18 -0
  64. package/dist/_cjs/storage/adapters.js.map +1 -0
  65. package/dist/_cjs/storage/manager.js +108 -0
  66. package/dist/_cjs/storage/manager.js.map +1 -0
  67. package/dist/_cjs/types/session.js +9 -0
  68. package/dist/_cjs/types/session.js.map +1 -0
  69. package/dist/_cjs/utils/exportWallet.js +70 -0
  70. package/dist/_cjs/utils/exportWallet.js.map +1 -0
  71. package/dist/_cjs/utils/utils.js +75 -0
  72. package/dist/_cjs/utils/utils.js.map +1 -0
  73. package/dist/_esm/actions/auth/authenticateWithEmail.js +18 -0
  74. package/dist/_esm/actions/auth/authenticateWithEmail.js.map +1 -0
  75. package/dist/_esm/actions/auth/authenticateWithOAuth.js +31 -0
  76. package/dist/_esm/actions/auth/authenticateWithOAuth.js.map +1 -0
  77. package/dist/_esm/actions/auth/getWhoami.js +28 -0
  78. package/dist/_esm/actions/auth/getWhoami.js.map +1 -0
  79. package/dist/_esm/actions/auth/index.js +8 -0
  80. package/dist/_esm/actions/auth/index.js.map +1 -0
  81. package/dist/_esm/actions/auth/loginWithOTP.js +36 -0
  82. package/dist/_esm/actions/auth/loginWithOTP.js.map +1 -0
  83. package/dist/_esm/actions/auth/loginWithStamp.js +42 -0
  84. package/dist/_esm/actions/auth/loginWithStamp.js.map +1 -0
  85. package/dist/_esm/actions/auth/registerWithOTP.js +36 -0
  86. package/dist/_esm/actions/auth/registerWithOTP.js.map +1 -0
  87. package/dist/_esm/actions/auth/registerWithPasskey.js +36 -0
  88. package/dist/_esm/actions/auth/registerWithPasskey.js.map +1 -0
  89. package/dist/_esm/actions/index.js +5 -0
  90. package/dist/_esm/actions/index.js.map +1 -0
  91. package/dist/_esm/actions/wallet/getUserWallet.js +26 -0
  92. package/dist/_esm/actions/wallet/getUserWallet.js.map +1 -0
  93. package/dist/_esm/actions/wallet/index.js +4 -0
  94. package/dist/_esm/actions/wallet/index.js.map +1 -0
  95. package/dist/_esm/actions/wallet/signRawPayload.js +41 -0
  96. package/dist/_esm/actions/wallet/signRawPayload.js.map +1 -0
  97. package/dist/_esm/actions/wallet/signTransaction.js +40 -0
  98. package/dist/_esm/actions/wallet/signTransaction.js.map +1 -0
  99. package/dist/_esm/adapters/viem.js +91 -0
  100. package/dist/_esm/adapters/viem.js.map +1 -0
  101. package/dist/_esm/client/createClient.js +56 -0
  102. package/dist/_esm/client/createClient.js.map +1 -0
  103. package/dist/_esm/client/decorators/client.js +42 -0
  104. package/dist/_esm/client/decorators/client.js.map +1 -0
  105. package/dist/_esm/client/index.js +3 -0
  106. package/dist/_esm/client/index.js.map +1 -0
  107. package/dist/_esm/client/transports/createTransport.js +31 -0
  108. package/dist/_esm/client/transports/createTransport.js.map +1 -0
  109. package/dist/_esm/client/transports/rest.js +85 -0
  110. package/dist/_esm/client/transports/rest.js.map +1 -0
  111. package/dist/_esm/client/types.js +2 -0
  112. package/dist/_esm/client/types.js.map +1 -0
  113. package/dist/_esm/constants.js +6 -0
  114. package/dist/_esm/constants.js.map +1 -0
  115. package/dist/_esm/core/createZeroDevWallet.js +332 -0
  116. package/dist/_esm/core/createZeroDevWallet.js.map +1 -0
  117. package/dist/_esm/errors/request.js +60 -0
  118. package/dist/_esm/errors/request.js.map +1 -0
  119. package/dist/_esm/index.js +20 -0
  120. package/dist/_esm/index.js.map +1 -0
  121. package/dist/_esm/package.json +1 -0
  122. package/dist/_esm/polyfills/window.js +24 -0
  123. package/dist/_esm/polyfills/window.js.map +1 -0
  124. package/dist/_esm/stampers/iframeStamper.js +29 -0
  125. package/dist/_esm/stampers/iframeStamper.js.map +1 -0
  126. package/dist/_esm/stampers/index.js +4 -0
  127. package/dist/_esm/stampers/index.js.map +1 -0
  128. package/dist/_esm/stampers/indexedDbStamper.js +20 -0
  129. package/dist/_esm/stampers/indexedDbStamper.js.map +1 -0
  130. package/dist/_esm/stampers/types.js +2 -0
  131. package/dist/_esm/stampers/types.js.map +1 -0
  132. package/dist/_esm/stampers/webauthnStamper.js +15 -0
  133. package/dist/_esm/stampers/webauthnStamper.js.map +1 -0
  134. package/dist/_esm/storage/adapters.js +15 -0
  135. package/dist/_esm/storage/adapters.js.map +1 -0
  136. package/dist/_esm/storage/manager.js +118 -0
  137. package/dist/_esm/storage/manager.js.map +1 -0
  138. package/dist/_esm/types/session.js +6 -0
  139. package/dist/_esm/types/session.js.map +1 -0
  140. package/dist/_esm/utils/exportWallet.js +98 -0
  141. package/dist/_esm/utils/exportWallet.js.map +1 -0
  142. package/dist/_esm/utils/utils.js +105 -0
  143. package/dist/_esm/utils/utils.js.map +1 -0
  144. package/dist/_types/actions/auth/authenticateWithEmail.d.ts +33 -0
  145. package/dist/_types/actions/auth/authenticateWithEmail.d.ts.map +1 -0
  146. package/dist/_types/actions/auth/authenticateWithOAuth.d.ts +40 -0
  147. package/dist/_types/actions/auth/authenticateWithOAuth.d.ts.map +1 -0
  148. package/dist/_types/actions/auth/getWhoami.d.ts +35 -0
  149. package/dist/_types/actions/auth/getWhoami.d.ts.map +1 -0
  150. package/dist/_types/actions/auth/index.d.ts +8 -0
  151. package/dist/_types/actions/auth/index.d.ts.map +1 -0
  152. package/dist/_types/actions/auth/loginWithOTP.d.ts +41 -0
  153. package/dist/_types/actions/auth/loginWithOTP.d.ts.map +1 -0
  154. package/dist/_types/actions/auth/loginWithStamp.d.ts +35 -0
  155. package/dist/_types/actions/auth/loginWithStamp.d.ts.map +1 -0
  156. package/dist/_types/actions/auth/registerWithOTP.d.ts +52 -0
  157. package/dist/_types/actions/auth/registerWithOTP.d.ts.map +1 -0
  158. package/dist/_types/actions/auth/registerWithPasskey.d.ts +53 -0
  159. package/dist/_types/actions/auth/registerWithPasskey.d.ts.map +1 -0
  160. package/dist/_types/actions/index.d.ts +3 -0
  161. package/dist/_types/actions/index.d.ts.map +1 -0
  162. package/dist/_types/actions/wallet/getUserWallet.d.ts +32 -0
  163. package/dist/_types/actions/wallet/getUserWallet.d.ts.map +1 -0
  164. package/dist/_types/actions/wallet/index.d.ts +4 -0
  165. package/dist/_types/actions/wallet/index.d.ts.map +1 -0
  166. package/dist/_types/actions/wallet/signRawPayload.d.ts +37 -0
  167. package/dist/_types/actions/wallet/signRawPayload.d.ts.map +1 -0
  168. package/dist/_types/actions/wallet/signTransaction.d.ts +33 -0
  169. package/dist/_types/actions/wallet/signTransaction.d.ts.map +1 -0
  170. package/dist/_types/adapters/viem.d.ts +9 -0
  171. package/dist/_types/adapters/viem.d.ts.map +1 -0
  172. package/dist/_types/client/createClient.d.ts +18 -0
  173. package/dist/_types/client/createClient.d.ts.map +1 -0
  174. package/dist/_types/client/decorators/client.d.ts +73 -0
  175. package/dist/_types/client/decorators/client.d.ts.map +1 -0
  176. package/dist/_types/client/index.d.ts +4 -0
  177. package/dist/_types/client/index.d.ts.map +1 -0
  178. package/dist/_types/client/transports/createTransport.d.ts +17 -0
  179. package/dist/_types/client/transports/createTransport.d.ts.map +1 -0
  180. package/dist/_types/client/transports/rest.d.ts +30 -0
  181. package/dist/_types/client/transports/rest.d.ts.map +1 -0
  182. package/dist/_types/client/types.d.ts +60 -0
  183. package/dist/_types/client/types.d.ts.map +1 -0
  184. package/dist/_types/constants.d.ts +6 -0
  185. package/dist/_types/constants.d.ts.map +1 -0
  186. package/dist/_types/core/createZeroDevWallet.d.ts +55 -0
  187. package/dist/_types/core/createZeroDevWallet.d.ts.map +1 -0
  188. package/dist/_types/errors/request.d.ts +12 -0
  189. package/dist/_types/errors/request.d.ts.map +1 -0
  190. package/dist/_types/index.d.ts +17 -0
  191. package/dist/_types/index.d.ts.map +1 -0
  192. package/dist/_types/polyfills/window.d.ts +15 -0
  193. package/dist/_types/polyfills/window.d.ts.map +1 -0
  194. package/dist/_types/stampers/iframeStamper.d.ts +7 -0
  195. package/dist/_types/stampers/iframeStamper.d.ts.map +1 -0
  196. package/dist/_types/stampers/index.d.ts +5 -0
  197. package/dist/_types/stampers/index.d.ts.map +1 -0
  198. package/dist/_types/stampers/indexedDbStamper.d.ts +3 -0
  199. package/dist/_types/stampers/indexedDbStamper.d.ts.map +1 -0
  200. package/dist/_types/stampers/types.d.ts +23 -0
  201. package/dist/_types/stampers/types.d.ts.map +1 -0
  202. package/dist/_types/stampers/webauthnStamper.d.ts +5 -0
  203. package/dist/_types/stampers/webauthnStamper.d.ts.map +1 -0
  204. package/dist/_types/storage/adapters.d.ts +3 -0
  205. package/dist/_types/storage/adapters.d.ts.map +1 -0
  206. package/dist/_types/storage/manager.d.ts +19 -0
  207. package/dist/_types/storage/manager.d.ts.map +1 -0
  208. package/dist/_types/types/session.d.ts +17 -0
  209. package/dist/_types/types/session.d.ts.map +1 -0
  210. package/dist/_types/utils/exportWallet.d.ts +44 -0
  211. package/dist/_types/utils/exportWallet.d.ts.map +1 -0
  212. package/dist/_types/utils/utils.d.ts +52 -0
  213. package/dist/_types/utils/utils.d.ts.map +1 -0
  214. package/dist/tsconfig.build.tsbuildinfo +1 -0
  215. package/package.json +73 -0
  216. package/src/actions/auth/authenticateWithEmail.ts +52 -0
  217. package/src/actions/auth/authenticateWithOAuth.ts +58 -0
  218. package/src/actions/auth/getWhoami.ts +51 -0
  219. package/src/actions/auth/index.ts +40 -0
  220. package/src/actions/auth/loginWithOTP.ts +60 -0
  221. package/src/actions/auth/loginWithStamp.ts +68 -0
  222. package/src/actions/auth/registerWithOTP.ts +71 -0
  223. package/src/actions/auth/registerWithPasskey.ts +72 -0
  224. package/src/actions/index.ts +36 -0
  225. package/src/actions/wallet/getUserWallet.ts +46 -0
  226. package/src/actions/wallet/index.ts +17 -0
  227. package/src/actions/wallet/signRawPayload.ts +71 -0
  228. package/src/actions/wallet/signTransaction.ts +60 -0
  229. package/src/adapters/viem.ts +158 -0
  230. package/src/client/createClient.ts +95 -0
  231. package/src/client/decorators/client.ts +152 -0
  232. package/src/client/index.ts +12 -0
  233. package/src/client/transports/createTransport.ts +52 -0
  234. package/src/client/transports/rest.ts +121 -0
  235. package/src/client/types.ts +66 -0
  236. package/src/constants.ts +5 -0
  237. package/src/core/createZeroDevWallet.ts +477 -0
  238. package/src/errors/request.ts +36 -0
  239. package/src/index.ts +75 -0
  240. package/src/polyfills/window.ts +24 -0
  241. package/src/stampers/iframeStamper.ts +35 -0
  242. package/src/stampers/index.ts +8 -0
  243. package/src/stampers/indexedDbStamper.ts +22 -0
  244. package/src/stampers/types.ts +28 -0
  245. package/src/stampers/webauthnStamper.ts +21 -0
  246. package/src/storage/adapters.ts +20 -0
  247. package/src/storage/manager.ts +170 -0
  248. package/src/types/session.ts +18 -0
  249. package/src/utils/exportWallet.ts +124 -0
  250. package/src/utils/utils.ts +136 -0
@@ -0,0 +1,35 @@
1
+ import { IframeStamper as TurnkeyIframeStamper } from '@turnkey/iframe-stamper'
2
+ import type { IframeStamper } from './types.js'
3
+
4
+ export async function createIframeStamper(cfg: {
5
+ iframeUrl: string
6
+ iframeContainer: HTMLElement | null | undefined
7
+ iframeElementId: string
8
+ }): Promise<IframeStamper> {
9
+ const inner = new TurnkeyIframeStamper({
10
+ iframeUrl: cfg.iframeUrl,
11
+ iframeContainer: cfg.iframeContainer,
12
+ iframeElementId: cfg.iframeElementId,
13
+ })
14
+
15
+ return {
16
+ async init() {
17
+ return await inner.init()
18
+ },
19
+ async injectCredentialBundle(bundle: string) {
20
+ return await inner.injectCredentialBundle(bundle)
21
+ },
22
+ async getPublicKey() {
23
+ return await inner.getEmbeddedPublicKey()
24
+ },
25
+ async stamp(payload: string) {
26
+ return await inner.stamp(payload)
27
+ },
28
+ async clear() {
29
+ await inner.clear()
30
+ },
31
+ async injectWalletExportBundle(bundle: string, organizationId: string) {
32
+ return await inner.injectWalletExportBundle(bundle, organizationId)
33
+ },
34
+ }
35
+ }
@@ -0,0 +1,8 @@
1
+ export { createIframeStamper } from './iframeStamper.js'
2
+ export { createIndexedDbStamper } from './indexedDbStamper.js'
3
+ export type {
4
+ IframeStamper,
5
+ IndexedDbStamper,
6
+ WebauthnStamper,
7
+ } from './types.js'
8
+ export { createWebauthnStamper } from './webauthnStamper.js'
@@ -0,0 +1,22 @@
1
+ import { IndexedDbStamper as TurnkeyIndexedDbStamper } from '@turnkey/indexed-db-stamper'
2
+ import type { IndexedDbStamper } from './types.js'
3
+
4
+ export async function createIndexedDbStamper(): Promise<IndexedDbStamper> {
5
+ const inner = new TurnkeyIndexedDbStamper()
6
+ await inner.init()
7
+
8
+ return {
9
+ async getPublicKey() {
10
+ return await inner.getPublicKey()
11
+ },
12
+ async stamp(payload: string) {
13
+ return await inner.stamp(payload)
14
+ },
15
+ async clear() {
16
+ await inner.clear()
17
+ },
18
+ async resetKeyPair(externalKeyPair?: CryptoKeyPair) {
19
+ await inner.resetKeyPair(externalKeyPair)
20
+ },
21
+ }
22
+ }
@@ -0,0 +1,28 @@
1
+ /** Base stamper that transport depends on */
2
+ export type Stamp = {
3
+ stampHeaderName: string
4
+ stampHeaderValue: string
5
+ }
6
+
7
+ export type Stamper = {
8
+ /** retrieve public key compressed or otherwise as per the stamper */
9
+ getPublicKey: () => Promise<string | null>
10
+ /** produce Turnkey header value for a given request body */
11
+ stamp: (payload: string) => Promise<Stamp>
12
+ /** clear local state (embedded key, IDB keypair, etc.) */
13
+ clear: () => Promise<void>
14
+ }
15
+
16
+ export type IframeStamper = Stamper & {
17
+ init(): Promise<string>
18
+ injectCredentialBundle(bundle: string): Promise<boolean>
19
+ injectWalletExportBundle(
20
+ bundle: string,
21
+ organizationId: string,
22
+ ): Promise<boolean>
23
+ }
24
+
25
+ export type IndexedDbStamper = Stamper & {
26
+ resetKeyPair: (externalKeyPair?: CryptoKeyPair) => Promise<void>
27
+ }
28
+ export type WebauthnStamper = Stamper
@@ -0,0 +1,21 @@
1
+ import { WebauthnStamper as TurnkeyWebauthnStamper } from '@turnkey/webauthn-stamper'
2
+ import type { WebauthnStamper } from './types.js'
3
+
4
+ export async function createWebauthnStamper({
5
+ rpId,
6
+ }: {
7
+ rpId: string
8
+ }): Promise<WebauthnStamper> {
9
+ const inner = new TurnkeyWebauthnStamper({ rpId })
10
+
11
+ return {
12
+ async getPublicKey() {
13
+ // return await inner.();
14
+ return null
15
+ },
16
+ async stamp(payload: string) {
17
+ return await inner.stamp(payload)
18
+ },
19
+ async clear() {},
20
+ }
21
+ }
@@ -0,0 +1,20 @@
1
+ import WindowWrapper from '../polyfills/window.js'
2
+ import type { StorageAdapter } from './manager.js'
3
+
4
+ export function createWebStorageAdapter(
5
+ storage: Storage = WindowWrapper.localStorage,
6
+ ): StorageAdapter {
7
+ return {
8
+ getItem(key: string): string | null {
9
+ return storage.getItem(key)
10
+ },
11
+
12
+ setItem(key: string, value: string): void {
13
+ storage.setItem(key, value)
14
+ },
15
+
16
+ removeItem(key: string): void {
17
+ storage.removeItem(key)
18
+ },
19
+ }
20
+ }
@@ -0,0 +1,170 @@
1
+ import type { ZeroDevWalletSession } from '../types/session.js'
2
+ import { normalizeTimestamp } from '../utils/utils.js'
3
+
4
+ export type StorageAdapter = {
5
+ getItem(key: string): string | null | Promise<string | null>
6
+ setItem(key: string, value: string): void | Promise<void>
7
+ removeItem(key: string): void | Promise<void>
8
+ }
9
+
10
+ export type StorageManager = {
11
+ storeSession(
12
+ sessionData: ZeroDevWalletSession,
13
+ sessionKey: string,
14
+ ): Promise<void>
15
+ getActiveSession(): Promise<ZeroDevWalletSession | undefined>
16
+ getActiveSessionKey(): Promise<string | undefined>
17
+ getSession(sessionKey: string): Promise<ZeroDevWalletSession | undefined>
18
+ listSessionKeys(): Promise<string[]>
19
+ listSessions(): Promise<ZeroDevWalletSession[]>
20
+ setActiveSession(sessionKey: string): Promise<void>
21
+ clearSession(sessionKey: string): Promise<void>
22
+ clearAllSessions(): Promise<void>
23
+ }
24
+
25
+ export function createStorageManager(adapter: StorageAdapter): StorageManager {
26
+ const ACTIVE_SESSION_KEY = '@zerodev/active_session'
27
+ const ALL_SESSIONS_KEY = '@zerodev/sessions'
28
+
29
+ const storeSession = async (
30
+ sessionData: ZeroDevWalletSession,
31
+ sessionKey: string,
32
+ ): Promise<void> => {
33
+ // Store the session data
34
+ await adapter.setItem(sessionKey, JSON.stringify(sessionData))
35
+
36
+ // Add to sessions list if not already present
37
+ const sessionsStr = await adapter.getItem(ALL_SESSIONS_KEY)
38
+ const sessions = JSON.parse(sessionsStr || '[]')
39
+ if (!sessions.includes(sessionKey)) {
40
+ sessions.push(sessionKey)
41
+ await adapter.setItem(ALL_SESSIONS_KEY, JSON.stringify(sessions))
42
+ }
43
+
44
+ // Set as active session
45
+ await adapter.setItem(ACTIVE_SESSION_KEY, sessionKey)
46
+ }
47
+
48
+ const getActiveSession = async (): Promise<
49
+ ZeroDevWalletSession | undefined
50
+ > => {
51
+ const activeKey = await adapter.getItem(ACTIVE_SESSION_KEY)
52
+ if (!activeKey) return undefined
53
+
54
+ return getSession(activeKey)
55
+ }
56
+
57
+ const getActiveSessionKey = async (): Promise<string | undefined> => {
58
+ const key = await adapter.getItem(ACTIVE_SESSION_KEY)
59
+ return key || undefined
60
+ }
61
+
62
+ const getSession = async (
63
+ sessionKey: string,
64
+ ): Promise<ZeroDevWalletSession | undefined> => {
65
+ const sessionStr = await adapter.getItem(sessionKey)
66
+ if (!sessionStr) return undefined
67
+
68
+ try {
69
+ const session: ZeroDevWalletSession = JSON.parse(sessionStr)
70
+
71
+ // Check if session is expired
72
+ if (session.expiry && normalizeTimestamp(session.expiry) < Date.now()) {
73
+ await clearSession(sessionKey)
74
+ return undefined
75
+ }
76
+
77
+ return session
78
+ } catch (_error) {
79
+ // Invalid JSON, clean up
80
+ await clearSession(sessionKey)
81
+ return undefined
82
+ }
83
+ }
84
+
85
+ const listSessionKeys = async (): Promise<string[]> => {
86
+ const sessionsStr = await adapter.getItem(ALL_SESSIONS_KEY)
87
+ const sessionKeys = JSON.parse(sessionsStr || '[]')
88
+
89
+ // Clean up any keys that don't have corresponding sessions
90
+ const validKeys: string[] = []
91
+ for (const key of sessionKeys) {
92
+ const exists = await adapter.getItem(key)
93
+ if (exists) {
94
+ validKeys.push(key)
95
+ }
96
+ }
97
+
98
+ // Update the list if we found invalid keys
99
+ if (validKeys.length !== sessionKeys.length) {
100
+ await adapter.setItem(ALL_SESSIONS_KEY, JSON.stringify(validKeys))
101
+ }
102
+
103
+ return validKeys
104
+ }
105
+
106
+ const listSessions = async (): Promise<ZeroDevWalletSession[]> => {
107
+ const sessionKeys = await listSessionKeys()
108
+ const sessions: ZeroDevWalletSession[] = []
109
+
110
+ for (const key of sessionKeys) {
111
+ const session = await getSession(key)
112
+ if (session) {
113
+ sessions.push(session)
114
+ }
115
+ }
116
+
117
+ return sessions
118
+ }
119
+
120
+ const setActiveSession = async (sessionKey: string): Promise<void> => {
121
+ // Verify the session exists
122
+ const session = await getSession(sessionKey)
123
+ if (!session) {
124
+ throw new Error(`Session not found: ${sessionKey}`)
125
+ }
126
+
127
+ await adapter.setItem(ACTIVE_SESSION_KEY, sessionKey)
128
+ }
129
+
130
+ const clearSession = async (sessionKey: string): Promise<void> => {
131
+ // Remove the session data
132
+ await adapter.removeItem(sessionKey)
133
+
134
+ // Remove from sessions list
135
+ const sessions = await listSessionKeys()
136
+ const updated = sessions.filter((k) => k !== sessionKey)
137
+ await adapter.setItem(ALL_SESSIONS_KEY, JSON.stringify(updated))
138
+
139
+ // Clear active session if it was the cleared one
140
+ const activeKey = await adapter.getItem(ACTIVE_SESSION_KEY)
141
+ if (activeKey === sessionKey) {
142
+ await adapter.removeItem(ACTIVE_SESSION_KEY)
143
+ }
144
+ }
145
+
146
+ const clearAllSessions = async (): Promise<void> => {
147
+ const sessions = await listSessionKeys()
148
+
149
+ // Remove all session data
150
+ for (const key of sessions) {
151
+ await adapter.removeItem(key)
152
+ }
153
+
154
+ // Clear the metadata
155
+ await adapter.removeItem(ALL_SESSIONS_KEY)
156
+ await adapter.removeItem(ACTIVE_SESSION_KEY)
157
+ }
158
+
159
+ return {
160
+ storeSession,
161
+ getActiveSession,
162
+ getActiveSessionKey,
163
+ getSession,
164
+ listSessionKeys,
165
+ listSessions,
166
+ setActiveSession,
167
+ clearSession,
168
+ clearAllSessions,
169
+ }
170
+ }
@@ -0,0 +1,18 @@
1
+ export enum SessionType {
2
+ READ_ONLY = 'SESSION_TYPE_READ_ONLY',
3
+ READ_WRITE = 'SESSION_TYPE_READ_WRITE',
4
+ }
5
+
6
+ export type StamperType = 'iframe' | 'indexedDb' | 'passkey'
7
+
8
+ export type ZeroDevWalletSession = {
9
+ id: string
10
+ userId: string
11
+ organizationId: string
12
+ stamperType: StamperType
13
+ sessionType?: SessionType
14
+ token?: string
15
+ publicKey?: string
16
+ expiry: number
17
+ createdAt: number
18
+ }
@@ -0,0 +1,124 @@
1
+ import type { ZeroDevWalletSDK } from '../core/createZeroDevWallet.js'
2
+
3
+ export type ExportWalletParameters = {
4
+ /** Wallet to use for the export */
5
+ wallet: ZeroDevWalletSDK
6
+ /** Target public key from export iframe for encryption */
7
+ targetPublicKey: string
8
+ }
9
+
10
+ /**
11
+ * TODO: Add it as standard action in the SDK when backend is ready
12
+ * Export a wallet's seed phrase
13
+ *
14
+ * This calls Turnkey's export_wallet API to get an encrypted bundle
15
+ * containing the wallet's mnemonic. The bundle is encrypted with the
16
+ * targetPublicKey (from Turnkey's export iframe).
17
+ *
18
+ * @param params - Export parameters
19
+ * @returns Encrypted export bundle
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * // In UI: Initialize export iframe first
24
+ * const iframeStamper = await createIframeStamper({
25
+ * iframeUrl: 'https://export.turnkey.com',
26
+ * iframeContainer: document.getElementById('export-container'),
27
+ * iframeElementId: 'export-iframe'
28
+ * });
29
+ * const targetPublicKey = await iframeStamper.init();
30
+ *
31
+ * // Call SDK to get encrypted bundle
32
+ * const exportBundle = await exportWallet({
33
+ * wallet,
34
+ * targetPublicKey
35
+ * });
36
+ *
37
+ * // Inject into iframe to display seed phrase
38
+ * await iframeStamper.injectWalletExportBundle(exportBundle, organizationId);
39
+ * ```
40
+ */
41
+ export async function exportWallet(
42
+ params: ExportWalletParameters,
43
+ ): Promise<{ exportBundle: string; walletId: string; organizationId: string }> {
44
+ const { targetPublicKey, wallet } = params
45
+
46
+ try {
47
+ const session = await wallet.getSession()
48
+ if (!session) {
49
+ throw new Error('Session not found')
50
+ }
51
+ const { organizationId } = session
52
+
53
+ const listWalletsBody = JSON.stringify({
54
+ organizationId,
55
+ })
56
+
57
+ const listWalletsStamp = await wallet
58
+ .client()
59
+ ?.stamper.stamp(listWalletsBody)
60
+ if (!listWalletsStamp) {
61
+ throw new Error('Failed to stamp list wallets body')
62
+ }
63
+
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,
71
+ },
72
+ },
73
+ )
74
+ if (!listWalletsResponse.ok) {
75
+ throw new Error('Failed to list wallets')
76
+ }
77
+ const listWalletsData = await listWalletsResponse.json()
78
+
79
+ const walletId = listWalletsData.wallets[0].walletId
80
+
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 = await wallet
92
+ .client()
93
+ ?.stamper.stamp(exportWalletBody)
94
+ if (!exportWalletStamp) {
95
+ throw new Error('Failed to stamp export wallet body')
96
+ }
97
+ const exportWalletResponse = await fetch(
98
+ 'https://api.turnkey.com/public/v1/submit/export_wallet',
99
+ {
100
+ method: 'POST',
101
+ body: exportWalletBody,
102
+ headers: {
103
+ [exportWalletStamp.stampHeaderName]:
104
+ exportWalletStamp.stampHeaderValue,
105
+ },
106
+ },
107
+ )
108
+ if (!exportWalletResponse.ok) {
109
+ throw new Error('Failed to export wallet')
110
+ }
111
+ const exportWalletData = await exportWalletResponse.json()
112
+
113
+ const exportBundle =
114
+ exportWalletData?.activity?.result?.exportWalletResult?.exportBundle
115
+
116
+ if (!exportBundle) {
117
+ throw new Error('Export bundle not found in response')
118
+ }
119
+
120
+ return { exportBundle, walletId, organizationId }
121
+ } catch (_) {
122
+ throw new Error('Error exporting wallet')
123
+ }
124
+ }
@@ -0,0 +1,136 @@
1
+ import type { PartialBy } from 'viem'
2
+ import type { ZeroDevWalletSession } from '../types/session.js'
3
+
4
+ /**
5
+ * Parses a session from a JWT.
6
+ *
7
+ * @param token - The JWT to parse.
8
+ * @returns {PartialBy<ZeroDevWalletSession, "createdAt" | "id" | "stamperType">} - The parsed session.
9
+ */
10
+ export function parseSession(
11
+ token: string | ZeroDevWalletSession,
12
+ ): PartialBy<ZeroDevWalletSession, 'createdAt' | 'id' | 'stamperType'> {
13
+ if (typeof token !== 'string') {
14
+ return token
15
+ }
16
+ const [, payload] = token.split('.')
17
+ if (!payload) {
18
+ throw new Error('Invalid JWT: Missing payload')
19
+ }
20
+
21
+ const decoded = JSON.parse(Buffer.from(payload, 'base64').toString())
22
+ const {
23
+ exp,
24
+ public_key: publicKey,
25
+ session_type: sessionType,
26
+ user_id: userId,
27
+ organization_id: organizationId,
28
+ } = decoded
29
+
30
+ if (!exp || !publicKey || !sessionType || !userId || !organizationId) {
31
+ throw new Error('JWT payload missing required fields')
32
+ }
33
+
34
+ return {
35
+ sessionType,
36
+ userId,
37
+ organizationId,
38
+ expiry: exp,
39
+ token: publicKey,
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Normalizes a timestamp to milliseconds.
45
+ *
46
+ * @param timestamp - The timestamp to normalize.
47
+ * @returns {number} - The normalized timestamp.
48
+ */
49
+ export function normalizeTimestamp(timestamp: number): number {
50
+ return timestamp < 1e10 ? timestamp * 1_000 : timestamp
51
+ }
52
+
53
+ /**
54
+ * Generates a random buffer of 32 bytes.
55
+ *
56
+ * @returns {ArrayBuffer} - The random buffer.
57
+ */
58
+ export const generateRandomBuffer = (): ArrayBuffer => {
59
+ const arr = new Uint8Array(32)
60
+ crypto.getRandomValues(arr)
61
+ return arr.buffer
62
+ }
63
+
64
+ /**
65
+ * Encodes a challenge in base64url format.
66
+ *
67
+ * @param challenge - The challenge to encode.
68
+ * @returns {string} - The encoded challenge.
69
+ */
70
+ export const base64UrlEncode = (challenge: ArrayBuffer): string => {
71
+ return Buffer.from(challenge)
72
+ .toString('base64')
73
+ .replace(/\+/g, '-')
74
+ .replace(/\//g, '_')
75
+ .replace(/=/g, '')
76
+ }
77
+
78
+ /**
79
+ * Compresses an uncompressed P-256 public key into its 33-byte compressed form.
80
+ *
81
+ * @param {Uint8Array} raw - The uncompressed public key (65 bytes, starting with 0x04).
82
+ * @returns {Uint8Array} - The compressed public key (33 bytes, starting with 0x02 or 0x03).
83
+ * @throws {Error} - If the input key is not a valid uncompressed P-256 key.
84
+ */
85
+ export function pointEncode(raw: Uint8Array): Uint8Array {
86
+ if (raw.length !== 65 || raw[0] !== 0x04) {
87
+ throw new Error('Invalid uncompressed P-256 key')
88
+ }
89
+
90
+ const x = raw.slice(1, 33)
91
+ const y = raw.slice(33, 65)
92
+
93
+ if (x.length !== 32 || y.length !== 32) {
94
+ throw new Error('Invalid x or y length')
95
+ }
96
+
97
+ const prefix = (y[31]! & 1) === 0 ? 0x02 : 0x03
98
+
99
+ const compressed = new Uint8Array(33)
100
+ compressed[0] = prefix
101
+ compressed.set(x, 1)
102
+ return compressed
103
+ }
104
+
105
+ /**
106
+ * Converts a Uint8Array into a lowercase hex string.
107
+ *
108
+ * @param {Uint8Array} input - The input byte array.
109
+ * @returns {string} - The resulting hex string.
110
+ */
111
+ export function uint8ArrayToHexString(input: Uint8Array): string {
112
+ return input.reduce(
113
+ (result, x) => result + x.toString(16).padStart(2, '0'),
114
+ '',
115
+ )
116
+ }
117
+
118
+ /**
119
+ * Generates a compressed public key from a key pair.
120
+ *
121
+ * @returns {Promise<string>} - The compressed public key.
122
+ */
123
+ export async function generateCompressedPublicKeyFromKeyPair(
124
+ keyPair: CryptoKeyPair,
125
+ ): Promise<string> {
126
+ const rawPubKey = new Uint8Array(
127
+ await crypto.subtle.exportKey('raw', keyPair.publicKey),
128
+ )
129
+ const compressedPubKey = pointEncode(rawPubKey)
130
+ const compressedHex = uint8ArrayToHexString(compressedPubKey)
131
+ return compressedHex
132
+ }
133
+
134
+ export const humanReadableDateTime = (): string => {
135
+ return new Date().toLocaleString().replaceAll('/', '-').replaceAll(':', '.')
136
+ }