@zerodev/wallet-core 0.0.1-alpha.5 → 0.0.1-alpha.6

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerodev/wallet-core",
3
- "version": "0.0.1-alpha.5",
3
+ "version": "0.0.1-alpha.6",
4
4
  "description": "ZeroDev Wallet SDK built on Turnkey",
5
5
  "main": "./dist/_cjs/index.js",
6
6
  "module": "./dist/_esm/index.js",
package/src/index.ts CHANGED
@@ -70,6 +70,8 @@ export type {
70
70
  export type { StorageAdapter, StorageManager } from './storage/manager.js'
71
71
  // Session types
72
72
  export type { StamperType, ZeroDevWalletSession } from './types/session.js'
73
+ export type { KeyFormat } from './utils/exportPrivateKey.js'
74
+ export { exportPrivateKey } from './utils/exportPrivateKey.js'
73
75
  export { exportWallet } from './utils/exportWallet.js'
74
76
  // Utils
75
77
  export { normalizeTimestamp } from './utils/utils.js'
@@ -1,5 +1,8 @@
1
- import { IframeStamper as TurnkeyIframeStamper } from '@turnkey/iframe-stamper'
2
- import type { IframeStamper } from './types.js'
1
+ import {
2
+ KeyFormat,
3
+ IframeStamper as TurnkeyIframeStamper,
4
+ } from '@turnkey/iframe-stamper'
5
+ import type { IframeStamper, KeyFormat as KeyFormatType } from './types.js'
3
6
 
4
7
  export async function createIframeStamper(cfg: {
5
8
  iframeUrl: string
@@ -31,5 +34,16 @@ export async function createIframeStamper(cfg: {
31
34
  async injectWalletExportBundle(bundle: string, organizationId: string) {
32
35
  return await inner.injectWalletExportBundle(bundle, organizationId)
33
36
  },
37
+ async injectKeyExportBundle(
38
+ bundle: string,
39
+ organizationId: string,
40
+ keyFormat?: KeyFormatType,
41
+ ) {
42
+ return await inner.injectKeyExportBundle(
43
+ bundle,
44
+ organizationId,
45
+ keyFormat ? KeyFormat[keyFormat] : KeyFormat.Hexadecimal,
46
+ )
47
+ },
34
48
  }
35
49
  }
@@ -13,6 +13,8 @@ export type Stamper = {
13
13
  clear: () => Promise<void>
14
14
  }
15
15
 
16
+ export type KeyFormat = 'Hexadecimal' | 'Solana'
17
+
16
18
  export type IframeStamper = Stamper & {
17
19
  init(): Promise<string>
18
20
  injectCredentialBundle(bundle: string): Promise<boolean>
@@ -20,6 +22,11 @@ export type IframeStamper = Stamper & {
20
22
  bundle: string,
21
23
  organizationId: string,
22
24
  ): Promise<boolean>
25
+ injectKeyExportBundle(
26
+ bundle: string,
27
+ organizationId: string,
28
+ keyFormat?: KeyFormat,
29
+ ): Promise<boolean>
23
30
  }
24
31
 
25
32
  export type IndexedDbStamper = Stamper & {
@@ -0,0 +1,116 @@
1
+ import type { ZeroDevWalletSDK } from '../core/createZeroDevWallet.js'
2
+ import type { KeyFormat } from '../stampers/types.js'
3
+
4
+ export type ExportPrivateKeyParameters = {
5
+ /** Wallet to use for the export */
6
+ wallet: ZeroDevWalletSDK
7
+ /** Target public key from export iframe for encryption */
8
+ targetPublicKey: string
9
+ /** Wallet address to export (optional, defaults to wallet's account address) */
10
+ address?: string
11
+ }
12
+
13
+ /**
14
+ * Export a wallet account's private key
15
+ *
16
+ * This calls Turnkey's export_wallet_account API to get an encrypted bundle
17
+ * containing the account's private key. The bundle is encrypted with the
18
+ * targetPublicKey (from Turnkey's export iframe).
19
+ *
20
+ * @param params - Export parameters
21
+ * @returns Encrypted export bundle and metadata
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * // In UI: Initialize export iframe first
26
+ * const iframeStamper = await createIframeStamper({
27
+ * iframeUrl: 'https://export.turnkey.com',
28
+ * iframeContainer: document.getElementById('export-container'),
29
+ * iframeElementId: 'export-iframe'
30
+ * });
31
+ * const targetPublicKey = await iframeStamper.init();
32
+ *
33
+ * // Call SDK to get encrypted bundle
34
+ * const { exportBundle, address, organizationId } = await exportPrivateKey({
35
+ * wallet,
36
+ * targetPublicKey
37
+ * });
38
+ *
39
+ * // Inject into iframe to display private key
40
+ * await iframeStamper.injectKeyExportBundle(exportBundle, organizationId, 'Hexadecimal');
41
+ * ```
42
+ */
43
+ export async function exportPrivateKey(
44
+ params: ExportPrivateKeyParameters,
45
+ ): Promise<{ exportBundle: string; address: string; organizationId: string }> {
46
+ const { targetPublicKey, wallet, address: addressParam } = params
47
+
48
+ const session = await wallet.getSession()
49
+ if (!session) {
50
+ throw new Error('Session not found')
51
+ }
52
+ const { organizationId } = session
53
+
54
+ // If address not provided, get it from the wallet's account
55
+ let address = addressParam
56
+ if (!address) {
57
+ const account = await wallet.toAccount()
58
+ if (!account?.address) {
59
+ throw new Error('Could not get address from wallet account')
60
+ }
61
+ address = account.address
62
+ }
63
+
64
+ const exportBody = JSON.stringify({
65
+ type: 'ACTIVITY_TYPE_EXPORT_WALLET_ACCOUNT',
66
+ timestampMs: Date.now().toString(),
67
+ organizationId: organizationId,
68
+ parameters: {
69
+ address: address,
70
+ targetPublicKey,
71
+ },
72
+ })
73
+
74
+ const stamperKey =
75
+ session.stamperType === 'indexedDb' ? 'indexedDbStamper' : 'webauthnStamper'
76
+ const stamper = wallet.client[stamperKey]
77
+ if (!stamper) {
78
+ throw new Error(`Stamper '${stamperKey}' not found on wallet.client`)
79
+ }
80
+
81
+ const exportStamp = await stamper.stamp(exportBody)
82
+ if (!exportStamp) {
83
+ throw new Error('Failed to stamp export body')
84
+ }
85
+
86
+ const exportResponse = await fetch(
87
+ 'https://api.turnkey.com/public/v1/submit/export_wallet_account',
88
+ {
89
+ method: 'POST',
90
+ body: exportBody,
91
+ headers: {
92
+ [exportStamp.stampHeaderName]: exportStamp.stampHeaderValue,
93
+ },
94
+ },
95
+ )
96
+ if (!exportResponse.ok) {
97
+ const errorText = await exportResponse.text()
98
+ throw new Error(
99
+ `Failed to export wallet account: ${exportResponse.status} ${errorText}`,
100
+ )
101
+ }
102
+ const exportData = await exportResponse.json()
103
+
104
+ const exportBundle =
105
+ exportData?.activity?.result?.exportWalletAccountResult?.exportBundle
106
+
107
+ if (!exportBundle) {
108
+ throw new Error(
109
+ `Export bundle not found in response: ${JSON.stringify(exportData)}`,
110
+ )
111
+ }
112
+
113
+ return { exportBundle, address: address!, organizationId }
114
+ }
115
+
116
+ export type { KeyFormat }