@zerodev/wallet-react 0.0.1-alpha.1 → 0.0.1-alpha.10

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/CHANGELOG.md +67 -0
  2. package/README.md +30 -17
  3. package/dist/_cjs/actions.js +62 -24
  4. package/dist/_cjs/connector.js +82 -48
  5. package/dist/_cjs/hooks/useExportPrivateKey.js +18 -0
  6. package/dist/_cjs/hooks/useGetUserEmail.js +19 -0
  7. package/dist/_cjs/index.js +8 -1
  8. package/dist/_cjs/oauth.js +60 -55
  9. package/dist/_cjs/provider.js +5 -2
  10. package/dist/_cjs/store.js +4 -9
  11. package/dist/_esm/actions.js +74 -27
  12. package/dist/_esm/connector.js +98 -55
  13. package/dist/_esm/hooks/useExportPrivateKey.js +18 -0
  14. package/dist/_esm/hooks/useGetUserEmail.js +19 -0
  15. package/dist/_esm/index.js +3 -1
  16. package/dist/_esm/oauth.js +71 -53
  17. package/dist/_esm/provider.js +5 -2
  18. package/dist/_esm/store.js +4 -10
  19. package/dist/_types/actions.d.ts +35 -6
  20. package/dist/_types/actions.d.ts.map +1 -1
  21. package/dist/_types/connector.d.ts +0 -2
  22. package/dist/_types/connector.d.ts.map +1 -1
  23. package/dist/_types/hooks/useExportPrivateKey.d.ts +18 -0
  24. package/dist/_types/hooks/useExportPrivateKey.d.ts.map +1 -0
  25. package/dist/_types/hooks/useGetUserEmail.d.ts +18 -0
  26. package/dist/_types/hooks/useGetUserEmail.d.ts.map +1 -0
  27. package/dist/_types/index.d.ts +4 -2
  28. package/dist/_types/index.d.ts.map +1 -1
  29. package/dist/_types/oauth.d.ts +25 -12
  30. package/dist/_types/oauth.d.ts.map +1 -1
  31. package/dist/_types/provider.d.ts.map +1 -1
  32. package/dist/_types/store.d.ts +11 -7
  33. package/dist/_types/store.d.ts.map +1 -1
  34. package/dist/tsconfig.build.tsbuildinfo +1 -1
  35. package/package.json +2 -2
  36. package/src/actions.ts +124 -44
  37. package/src/connector.ts +117 -65
  38. package/src/hooks/useExportPrivateKey.ts +57 -0
  39. package/src/hooks/useGetUserEmail.ts +52 -0
  40. package/src/index.ts +9 -2
  41. package/src/oauth.ts +97 -78
  42. package/src/provider.ts +5 -2
  43. package/src/store.ts +15 -16
  44. package/tsconfig.build.tsbuildinfo +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerodev/wallet-react",
3
- "version": "0.0.1-alpha.1",
3
+ "version": "0.0.1-alpha.10",
4
4
  "description": "React hooks for ZeroDev Wallet SDK",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/_cjs/index.js",
@@ -30,7 +30,7 @@
30
30
  "wagmi": "^3.0.0",
31
31
  "zustand": "^5.0.3",
32
32
  "ox": "^0.3.0",
33
- "@zerodev/wallet-core": "0.0.1-alpha.4"
33
+ "@zerodev/wallet-core": "0.0.1-alpha.9"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/react": "^19",
package/src/actions.ts CHANGED
@@ -1,11 +1,15 @@
1
1
  import type { Config, Connector } from '@wagmi/core'
2
2
  import { connect as wagmiConnect } from '@wagmi/core/actions'
3
+ import {
4
+ createIframeStamper,
5
+ exportPrivateKey as exportPrivateKeySdk,
6
+ exportWallet as exportWalletSdk,
7
+ } from '@zerodev/wallet-core'
3
8
  import type { OAuthProvider } from './oauth.js'
4
9
  import {
5
- buildOAuthUrl,
6
- generateOAuthNonce,
10
+ buildBackendOAuthUrl,
11
+ listenForOAuthMessage,
7
12
  openOAuthPopup,
8
- pollOAuthPopup,
9
13
  } from './oauth.js'
10
14
 
11
15
  /**
@@ -111,12 +115,12 @@ export declare namespace loginPasskey {
111
115
 
112
116
  /**
113
117
  * Authenticate with OAuth (opens popup)
118
+ * Uses backend OAuth flow where the backend handles PKCE and token exchange
114
119
  */
115
120
  export async function authenticateOAuth(
116
121
  config: Config,
117
122
  parameters: {
118
123
  provider: OAuthProvider
119
- clientId?: string
120
124
  connector?: Connector
121
125
  },
122
126
  ): Promise<void> {
@@ -129,38 +133,23 @@ export async function authenticateOAuth(
129
133
 
130
134
  if (!wallet) throw new Error('Wallet not initialized')
131
135
  if (!oauthConfig) {
132
- throw new Error(
133
- 'OAuth is not configured. Please provide oauthConfig to zeroDevWallet connector.',
134
- )
135
- }
136
-
137
- // Get client ID for the provider
138
- let clientId = parameters.clientId
139
- if (!clientId) {
140
- clientId = oauthConfig.googleClientId
141
- }
142
-
143
- if (!clientId) {
144
- throw new Error(`Client ID not configured for ${parameters.provider}`)
136
+ throw new Error('Wallet not initialized. Please wait for connector setup.')
145
137
  }
146
138
 
147
- if (!oauthConfig.redirectUri) {
148
- throw new Error('OAuth redirect URI is not configured.')
149
- }
150
-
151
- // Generate nonce from wallet public key
139
+ // Get wallet public key for the OAuth flow
152
140
  const publicKey = await wallet.getPublicKey()
153
141
  if (!publicKey) {
154
142
  throw new Error('Failed to get wallet public key')
155
143
  }
156
- const nonce = generateOAuthNonce(publicKey)
157
144
 
158
- // Build OAuth URL
159
- const oauthUrl = buildOAuthUrl({
145
+ // Build OAuth URL that redirects to backend
146
+ // Use current origin as redirect - SDK auto-detects callback on any page
147
+ const oauthUrl = buildBackendOAuthUrl({
160
148
  provider: parameters.provider,
161
- clientId,
162
- redirectUri: oauthConfig.redirectUri,
163
- nonce,
149
+ backendUrl: oauthConfig.backendUrl,
150
+ projectId: oauthConfig.projectId,
151
+ publicKey,
152
+ returnTo: `${window.location.origin}?oauth_success=true&oauth_provider=${parameters.provider}`,
164
153
  })
165
154
 
166
155
  // Open popup
@@ -170,18 +159,18 @@ export async function authenticateOAuth(
170
159
  throw new Error(`Failed to open ${parameters.provider} login window.`)
171
160
  }
172
161
 
173
- // Poll for OAuth completion
162
+ // Listen for OAuth completion via postMessage
174
163
  return new Promise<void>((resolve, reject) => {
175
- pollOAuthPopup(
164
+ const cleanup = listenForOAuthMessage(
176
165
  authWindow,
177
166
  window.location.origin,
178
- async (idToken) => {
167
+ async () => {
179
168
  try {
180
169
  // Complete OAuth authentication with wallet-core
170
+ // The backend has stored the OAuth session in a cookie
181
171
  await wallet.auth({
182
172
  type: 'oauth',
183
173
  provider: parameters.provider,
184
- credential: idToken,
185
174
  })
186
175
 
187
176
  const [session, eoaAccount] = await Promise.all([
@@ -200,7 +189,10 @@ export async function authenticateOAuth(
200
189
  reject(err)
201
190
  }
202
191
  },
203
- reject,
192
+ (error) => {
193
+ cleanup()
194
+ reject(error)
195
+ },
204
196
  )
205
197
  })
206
198
  }
@@ -208,7 +200,6 @@ export async function authenticateOAuth(
208
200
  export declare namespace authenticateOAuth {
209
201
  type Parameters = {
210
202
  provider: OAuthProvider
211
- clientId?: string
212
203
  connector?: Connector
213
204
  }
214
205
  type ReturnType = void
@@ -225,7 +216,7 @@ export async function sendOTP(
225
216
  emailCustomization?: { magicLinkTemplate?: string }
226
217
  connector?: Connector
227
218
  },
228
- ): Promise<{ otpId: string; subOrganizationId: string }> {
219
+ ): Promise<{ otpId: string }> {
229
220
  const connector = parameters.connector ?? getZeroDevConnector(config)
230
221
 
231
222
  // @ts-expect-error - getStore is a custom method
@@ -246,7 +237,6 @@ export async function sendOTP(
246
237
 
247
238
  return {
248
239
  otpId: result.otpId,
249
- subOrganizationId: result.subOrganizationId,
250
240
  }
251
241
  }
252
242
 
@@ -256,7 +246,7 @@ export declare namespace sendOTP {
256
246
  emailCustomization?: { magicLinkTemplate?: string }
257
247
  connector?: Connector
258
248
  }
259
- type ReturnType = { otpId: string; subOrganizationId: string }
249
+ type ReturnType = { otpId: string }
260
250
  type ErrorType = Error
261
251
  }
262
252
 
@@ -268,7 +258,6 @@ export async function verifyOTP(
268
258
  parameters: {
269
259
  code: string
270
260
  otpId: string
271
- subOrganizationId: string
272
261
  connector?: Connector
273
262
  },
274
263
  ): Promise<void> {
@@ -285,7 +274,6 @@ export async function verifyOTP(
285
274
  mode: 'verifyOtp',
286
275
  otpId: parameters.otpId,
287
276
  otpCode: parameters.code,
288
- subOrganizationId: parameters.subOrganizationId,
289
277
  })
290
278
 
291
279
  const [session, eoaAccount] = await Promise.all([
@@ -304,7 +292,6 @@ export declare namespace verifyOTP {
304
292
  type Parameters = {
305
293
  code: string
306
294
  otpId: string
307
- subOrganizationId: string
308
295
  connector?: Connector
309
296
  }
310
297
  type ReturnType = void
@@ -344,6 +331,44 @@ export declare namespace refreshSession {
344
331
  type ErrorType = Error
345
332
  }
346
333
 
334
+ /**
335
+ * Get user email
336
+ */
337
+ export async function getUserEmail(config: Config): Promise<{ email: string }> {
338
+ const connector = getZeroDevConnector(config)
339
+
340
+ // @ts-expect-error - getStore is a custom method
341
+ const store = await connector.getStore()
342
+ const wallet = store.getState().wallet
343
+
344
+ if (!wallet) throw new Error('Wallet not initialized')
345
+
346
+ const oauthConfig = store.getState().oauthConfig
347
+ if (!oauthConfig) {
348
+ throw new Error('Wallet not initialized. Please wait for connector setup.')
349
+ }
350
+
351
+ const session = store.getState().session
352
+ if (!session) {
353
+ throw new Error('No active session')
354
+ }
355
+
356
+ // Call the core SDK method
357
+ return await wallet.client.getUserEmail({
358
+ organizationId: session.organizationId,
359
+ projectId: oauthConfig.projectId,
360
+ token: session.token,
361
+ })
362
+ }
363
+
364
+ export declare namespace getUserEmail {
365
+ type Parameters = {
366
+ connector?: Connector
367
+ }
368
+ type ReturnType = { email: string }
369
+ type ErrorType = Error
370
+ }
371
+
347
372
  /**
348
373
  * Export wallet
349
374
  */
@@ -362,10 +387,6 @@ export async function exportWallet(
362
387
 
363
388
  if (!wallet) throw new Error('Wallet not initialized')
364
389
 
365
- const { exportWallet: exportWalletSdk, createIframeStamper } = await import(
366
- '@zerodev/wallet-core'
367
- )
368
-
369
390
  const iframeContainer = document.getElementById(parameters.iframeContainerId)
370
391
  if (!iframeContainer) {
371
392
  throw new Error('Iframe container not found')
@@ -400,3 +421,62 @@ export declare namespace exportWallet {
400
421
  type ReturnType = void
401
422
  type ErrorType = Error
402
423
  }
424
+
425
+ /**
426
+ * Export private key
427
+ */
428
+ export async function exportPrivateKey(
429
+ config: Config,
430
+ parameters: {
431
+ iframeContainerId: string
432
+ address?: string
433
+ keyFormat?: 'Hexadecimal' | 'Solana'
434
+ connector?: Connector
435
+ },
436
+ ): Promise<void> {
437
+ const connector = parameters.connector ?? getZeroDevConnector(config)
438
+
439
+ // @ts-expect-error - getStore is a custom method
440
+ const store = await connector.getStore()
441
+ const wallet = store.getState().wallet
442
+
443
+ if (!wallet) throw new Error('Wallet not initialized')
444
+
445
+ const iframeContainer = document.getElementById(parameters.iframeContainerId)
446
+ if (!iframeContainer) {
447
+ throw new Error('Iframe container not found')
448
+ }
449
+
450
+ const iframeStamper = await createIframeStamper({
451
+ iframeUrl: 'https://export.turnkey.com',
452
+ iframeContainer,
453
+ iframeElementId: 'export-private-key-iframe',
454
+ })
455
+
456
+ const publicKey = await iframeStamper.init()
457
+ const { exportBundle, organizationId } = await exportPrivateKeySdk({
458
+ wallet,
459
+ targetPublicKey: publicKey,
460
+ ...(parameters.address && { address: parameters.address }),
461
+ })
462
+
463
+ const success = await iframeStamper.injectKeyExportBundle(
464
+ exportBundle,
465
+ organizationId,
466
+ parameters.keyFormat ?? 'Hexadecimal',
467
+ )
468
+ if (success !== true) {
469
+ throw new Error('Failed to inject export bundle')
470
+ }
471
+ }
472
+
473
+ export declare namespace exportPrivateKey {
474
+ type Parameters = {
475
+ iframeContainerId: string
476
+ address?: string
477
+ keyFormat?: 'Hexadecimal' | 'Solana'
478
+ connector?: Connector
479
+ }
480
+ type ReturnType = void
481
+ type ErrorType = Error
482
+ }
package/src/connector.ts CHANGED
@@ -6,13 +6,71 @@ import {
6
6
  } from '@zerodev/sdk'
7
7
  import { getEntryPoint, KERNEL_V3_3 } from '@zerodev/sdk/constants'
8
8
  import type { StorageAdapter } from '@zerodev/wallet-core'
9
- import { createZeroDevWallet } from '@zerodev/wallet-core'
9
+ import { createZeroDevWallet, KMS_SERVER_URL } from '@zerodev/wallet-core'
10
10
  import { type Chain, createPublicClient, http } from 'viem'
11
- import type { OAuthConfig } from './oauth.js'
11
+ import { handleOAuthCallback, type OAuthProvider } from './oauth.js'
12
12
  import { createProvider } from './provider.js'
13
13
  import { createZeroDevWalletStore } from './store.js'
14
14
  import { getAAUrl } from './utils/aaUtils.js'
15
15
 
16
+ // OAuth URL parameter used to detect callback
17
+ const OAUTH_SUCCESS_PARAM = 'oauth_success'
18
+ const OAUTH_PROVIDER_PARAM = 'oauth_provider'
19
+
20
+ /**
21
+ * Detect OAuth callback from URL params and handle it.
22
+ * - If in popup: sends postMessage to opener and closes
23
+ * - If not in popup: completes auth directly
24
+ */
25
+ async function detectAndHandleOAuthCallback(
26
+ wallet: Awaited<ReturnType<typeof createZeroDevWallet>>,
27
+ store: ReturnType<typeof createZeroDevWalletStore>,
28
+ ): Promise<boolean> {
29
+ if (typeof window === 'undefined') return false
30
+
31
+ const params = new URLSearchParams(window.location.search)
32
+ const isOAuthCallback = params.get(OAUTH_SUCCESS_PARAM) === 'true'
33
+
34
+ if (!isOAuthCallback) return false
35
+
36
+ // If in popup, use the existing handler to notify opener
37
+ if (window.opener) {
38
+ handleOAuthCallback(OAUTH_SUCCESS_PARAM)
39
+ return true
40
+ }
41
+
42
+ // Not in popup - complete auth directly (redirect flow)
43
+ console.log('OAuth callback detected, completing authentication...')
44
+ const provider = (params.get(OAUTH_PROVIDER_PARAM) ||
45
+ 'google') as OAuthProvider
46
+
47
+ try {
48
+ await wallet.auth({ type: 'oauth', provider })
49
+
50
+ const [session, eoaAccount] = await Promise.all([
51
+ wallet.getSession(),
52
+ wallet.toAccount(),
53
+ ])
54
+
55
+ store.getState().setEoaAccount(eoaAccount)
56
+ store.getState().setSession(session || null)
57
+
58
+ // Clean up URL params
59
+ params.delete(OAUTH_SUCCESS_PARAM)
60
+ params.delete(OAUTH_PROVIDER_PARAM)
61
+ const newUrl = params.toString()
62
+ ? `${window.location.pathname}?${params.toString()}`
63
+ : window.location.pathname
64
+ window.history.replaceState({}, '', newUrl)
65
+
66
+ console.log('OAuth authentication completed')
67
+ return true
68
+ } catch (error) {
69
+ console.error('OAuth authentication failed:', error)
70
+ return false
71
+ }
72
+ }
73
+
16
74
  export type ZeroDevWalletConnectorParams = {
17
75
  projectId: string
18
76
  organizationId?: string
@@ -23,7 +81,6 @@ export type ZeroDevWalletConnectorParams = {
23
81
  sessionStorage?: StorageAdapter
24
82
  autoRefreshSession?: boolean
25
83
  sessionWarningThreshold?: number
26
- oauthConfig?: OAuthConfig
27
84
  }
28
85
 
29
86
  export function zeroDevWallet(
@@ -50,62 +107,57 @@ export function zeroDevWallet(
50
107
  return createConnector<Provider, Properties>((wagmiConfig) => {
51
108
  let store: ReturnType<typeof createZeroDevWalletStore>
52
109
  let provider: ReturnType<typeof createProvider>
53
- let initPromise: Promise<void> | undefined
54
110
 
55
111
  // Get transports from Wagmi config (uses user's RPC URLs)
56
112
  const transports = wagmiConfig.transports
57
113
 
58
114
  // Lazy initialization - only runs on client side
59
115
  const initialize = async () => {
60
- initPromise ??= (async () => {
61
- console.log('Initializing ZeroDevWallet connector...')
62
-
63
- // Initialize wallet SDK
64
- const wallet = await createZeroDevWallet({
65
- projectId: params.projectId,
66
- ...(params.organizationId && {
67
- organizationId: params.organizationId,
68
- }),
69
- ...(params.proxyBaseUrl && { proxyBaseUrl: params.proxyBaseUrl }),
70
- ...(params.sessionStorage && {
71
- sessionStorage: params.sessionStorage,
72
- }),
73
- ...(params.rpId && { rpId: params.rpId }),
74
- })
75
-
76
- // Create store
77
- store = createZeroDevWalletStore()
78
- store.getState().setWallet(wallet)
79
-
80
- // Initialize chainIds
81
- const chainIds = params.chains.map((c) => c.id)
82
- store.setState({ chainIds })
83
-
84
- // Store OAuth config if provided
85
- if (params.oauthConfig) {
86
- store.getState().setOAuthConfig(params.oauthConfig)
87
- }
88
-
89
- // Create EIP-1193 provider
90
- provider = createProvider({
91
- store,
92
- config: params,
93
- chains: Array.from(params.chains),
94
- })
95
-
96
- // Check for existing session (page reload)
97
- const session = await wallet.getSession()
98
- if (session) {
99
- console.log('Found existing session, restoring...')
100
- const eoaAccount = await wallet.toAccount()
101
- store.getState().setEoaAccount(eoaAccount)
102
- store.getState().setSession(session)
103
- }
104
-
105
- console.log('ZeroDevWallet connector initialized')
106
- })()
107
-
108
- return initPromise
116
+ console.log('Initializing ZeroDevWallet connector...')
117
+
118
+ // Initialize wallet SDK
119
+ const wallet = await createZeroDevWallet({
120
+ projectId: params.projectId,
121
+ ...(params.organizationId && {
122
+ organizationId: params.organizationId,
123
+ }),
124
+ ...(params.proxyBaseUrl && { proxyBaseUrl: params.proxyBaseUrl }),
125
+ ...(params.sessionStorage && {
126
+ sessionStorage: params.sessionStorage,
127
+ }),
128
+ ...(params.rpId && { rpId: params.rpId }),
129
+ })
130
+
131
+ // Create store
132
+ store = createZeroDevWalletStore()
133
+ store.getState().setWallet(wallet)
134
+
135
+ // Store OAuth config - uses proxyBaseUrl and projectId from params
136
+ store.getState().setOAuthConfig({
137
+ backendUrl: params.proxyBaseUrl || `${KMS_SERVER_URL}/api/v1`,
138
+ projectId: params.projectId,
139
+ })
140
+
141
+ // Create EIP-1193 provider
142
+ provider = createProvider({
143
+ store,
144
+ config: params,
145
+ chains: Array.from(params.chains),
146
+ })
147
+
148
+ // Check for existing session (page reload)
149
+ const session = await wallet.getSession()
150
+ if (session) {
151
+ console.log('Found existing session, restoring...')
152
+ const eoaAccount = await wallet.toAccount()
153
+ store.getState().setEoaAccount(eoaAccount)
154
+ store.getState().setSession(session)
155
+ }
156
+
157
+ // Auto-detect OAuth callback (when popup redirects back with ?oauth_success=true)
158
+ await detectAndHandleOAuthCallback(wallet, store)
159
+
160
+ console.log('ZeroDevWallet connector initialized')
109
161
  }
110
162
 
111
163
  return {
@@ -137,10 +189,8 @@ export function zeroDevWallet(
137
189
  const state = store.getState()
138
190
 
139
191
  // Determine active chain
140
- const activeChainId = chainId || state.chainIds[0]
141
- if (!activeChainId) {
142
- throw new Error('No chain configured')
143
- }
192
+ const activeChainId =
193
+ chainId ?? state.activeChainId ?? params.chains[0].id
144
194
 
145
195
  // If reconnecting and already have kernel account, return immediately
146
196
  if (isReconnecting && state.kernelAccounts.has(activeChainId)) {
@@ -203,7 +253,7 @@ export function zeroDevWallet(
203
253
  }
204
254
 
205
255
  // Set as active chain
206
- store.getState().setActiveChain(activeChainId)
256
+ store.getState().setActiveChainId(activeChainId)
207
257
 
208
258
  // Get fresh state after updates
209
259
  const freshState = store.getState()
@@ -234,7 +284,7 @@ export function zeroDevWallet(
234
284
 
235
285
  async getAccounts() {
236
286
  if (!store) return []
237
- const { eoaAccount, kernelAccounts, chainIds } = store.getState()
287
+ const { eoaAccount, kernelAccounts, activeChainId } = store.getState()
238
288
 
239
289
  // Return EOA address if we have it (EIP-7702: EOA address = kernel address)
240
290
  if (eoaAccount) {
@@ -242,24 +292,25 @@ export function zeroDevWallet(
242
292
  }
243
293
 
244
294
  // Fallback: check kernel accounts
245
- const activeAccount = chainIds[0]
246
- ? kernelAccounts.get(chainIds[0])
295
+ const activeAccount = activeChainId
296
+ ? kernelAccounts.get(activeChainId)
247
297
  : null
248
298
  return activeAccount ? [activeAccount.address] : []
249
299
  },
250
300
 
251
301
  async getChainId() {
252
302
  if (!store) return params.chains[0].id
253
- return store.getState().chainIds[0] || params.chains[0].id
303
+ return store.getState().activeChainId ?? params.chains[0].id
254
304
  },
255
305
 
256
306
  async getProvider() {
257
- await initialize()
307
+ if (!provider) {
308
+ await initialize()
309
+ }
258
310
  return provider
259
311
  },
260
312
 
261
313
  async switchChain({ chainId }) {
262
- await initialize()
263
314
  console.log(`Switching to chain ${chainId}...`)
264
315
  const state = store.getState()
265
316
 
@@ -268,7 +319,7 @@ export function zeroDevWallet(
268
319
  }
269
320
 
270
321
  // Update active chain
271
- store.getState().setActiveChain(chainId)
322
+ store.getState().setActiveChainId(chainId)
272
323
 
273
324
  // Create kernel account for new chain if doesn't exist
274
325
  if (!state.kernelAccounts.has(chainId)) {
@@ -309,6 +360,7 @@ export function zeroDevWallet(
309
360
  store.getState().setKernelClient(chainId, kernelClient)
310
361
  }
311
362
 
363
+ wagmiConfig.emitter.emit('change', { chainId })
312
364
  return params.chains.find((c) => c.id === chainId)!
313
365
  },
314
366
 
@@ -0,0 +1,57 @@
1
+ 'use client'
2
+
3
+ import {
4
+ type UseMutationOptions,
5
+ type UseMutationResult,
6
+ useMutation,
7
+ } from '@tanstack/react-query'
8
+ import { type Config, type ResolvedRegister, useConfig } from 'wagmi'
9
+ import { exportPrivateKey } from '../actions.js'
10
+
11
+ type ConfigParameter<config extends Config = Config> = {
12
+ config?: Config | config | undefined
13
+ }
14
+
15
+ /**
16
+ * Hook to export private key
17
+ */
18
+ export function useExportPrivateKey<
19
+ config extends Config = ResolvedRegister['config'],
20
+ context = unknown,
21
+ >(
22
+ parameters: useExportPrivateKey.Parameters<config, context> = {},
23
+ ): useExportPrivateKey.ReturnType<context> {
24
+ const { mutation } = parameters
25
+ const config = useConfig(parameters)
26
+
27
+ return useMutation({
28
+ ...mutation,
29
+ async mutationFn(variables: exportPrivateKey.Parameters) {
30
+ return exportPrivateKey(config, variables)
31
+ },
32
+ mutationKey: ['exportPrivateKey'],
33
+ })
34
+ }
35
+
36
+ export declare namespace useExportPrivateKey {
37
+ type Parameters<
38
+ config extends Config = Config,
39
+ context = unknown,
40
+ > = ConfigParameter<config> & {
41
+ mutation?:
42
+ | UseMutationOptions<
43
+ exportPrivateKey.ReturnType,
44
+ exportPrivateKey.ErrorType,
45
+ exportPrivateKey.Parameters,
46
+ context
47
+ >
48
+ | undefined
49
+ }
50
+
51
+ type ReturnType<context = unknown> = UseMutationResult<
52
+ exportPrivateKey.ReturnType,
53
+ exportPrivateKey.ErrorType,
54
+ exportPrivateKey.Parameters,
55
+ context
56
+ >
57
+ }
@@ -0,0 +1,52 @@
1
+ 'use client'
2
+
3
+ import {
4
+ type UseQueryOptions,
5
+ type UseQueryResult,
6
+ useQuery,
7
+ } from '@tanstack/react-query'
8
+ import { type Config, type ResolvedRegister, useConfig } from 'wagmi'
9
+ import { getUserEmail } from '../actions.js'
10
+
11
+ type ConfigParameter<config extends Config = Config> = {
12
+ config?: Config | config | undefined
13
+ }
14
+
15
+ /**
16
+ * Hook to fetch user email address
17
+ */
18
+ export function useGetUserEmail<
19
+ config extends Config = ResolvedRegister['config'],
20
+ >(parameters: useGetUserEmail.Parameters<config>): useGetUserEmail.ReturnType {
21
+ const { query } = parameters
22
+ const config = useConfig(parameters)
23
+
24
+ return useQuery({
25
+ ...query,
26
+ queryKey: ['getUserEmail'],
27
+ queryFn: async () => {
28
+ return getUserEmail(config)
29
+ },
30
+ enabled: Boolean(config),
31
+ })
32
+ }
33
+
34
+ export declare namespace useGetUserEmail {
35
+ type Parameters<config extends Config = Config> = ConfigParameter<config> & {
36
+ query?:
37
+ | Omit<
38
+ UseQueryOptions<
39
+ getUserEmail.ReturnType,
40
+ getUserEmail.ErrorType,
41
+ getUserEmail.ReturnType
42
+ >,
43
+ 'queryKey' | 'queryFn'
44
+ >
45
+ | undefined
46
+ }
47
+
48
+ type ReturnType = UseQueryResult<
49
+ getUserEmail.ReturnType,
50
+ getUserEmail.ErrorType
51
+ >
52
+ }