@account-kit/privy-integration 4.73.0 → 4.74.0

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 (34) hide show
  1. package/README.md +61 -21
  2. package/dist/esm/Provider.d.ts +13 -3
  3. package/dist/esm/Provider.js +13 -3
  4. package/dist/esm/Provider.js.map +1 -1
  5. package/dist/esm/hooks/useAlchemyClient.d.ts +10 -5
  6. package/dist/esm/hooks/useAlchemyClient.js +34 -22
  7. package/dist/esm/hooks/useAlchemyClient.js.map +1 -1
  8. package/dist/esm/hooks/useAlchemyPrepareSwap.js +3 -6
  9. package/dist/esm/hooks/useAlchemyPrepareSwap.js.map +1 -1
  10. package/dist/esm/hooks/useAlchemySendTransaction.js +11 -9
  11. package/dist/esm/hooks/useAlchemySendTransaction.js.map +1 -1
  12. package/dist/esm/hooks/useAlchemySubmitSwap.js +1 -1
  13. package/dist/esm/hooks/useAlchemySubmitSwap.js.map +1 -1
  14. package/dist/esm/types.d.ts +6 -0
  15. package/dist/esm/types.js.map +1 -1
  16. package/dist/esm/version.d.ts +1 -1
  17. package/dist/esm/version.js +1 -1
  18. package/dist/esm/version.js.map +1 -1
  19. package/dist/types/Provider.d.ts +13 -3
  20. package/dist/types/Provider.d.ts.map +1 -1
  21. package/dist/types/hooks/useAlchemyClient.d.ts +10 -5
  22. package/dist/types/hooks/useAlchemyClient.d.ts.map +1 -1
  23. package/dist/types/hooks/useAlchemyPrepareSwap.d.ts.map +1 -1
  24. package/dist/types/hooks/useAlchemySendTransaction.d.ts.map +1 -1
  25. package/dist/types/types.d.ts +6 -0
  26. package/dist/types/types.d.ts.map +1 -1
  27. package/dist/types/version.d.ts +1 -1
  28. package/package.json +4 -4
  29. package/src/hooks/useAlchemyClient.ts +46 -26
  30. package/src/hooks/useAlchemyPrepareSwap.ts +3 -6
  31. package/src/hooks/useAlchemySendTransaction.ts +16 -13
  32. package/src/hooks/useAlchemySubmitSwap.ts +1 -1
  33. package/src/types.ts +7 -0
  34. package/src/version.ts +1 -1
package/README.md CHANGED
@@ -6,7 +6,7 @@ Add gas sponsorship and smart wallet features to your Privy app in under 5 minut
6
6
 
7
7
  If you're already using [Privy](https://privy.io) for authentication, this package lets you upgrade your users' wallets with:
8
8
 
9
- - **🔄 EIP-7702 Delegation** - Upgrade EOAs to smart accounts without migration
9
+ - **🔄 EIP-7702 Delegation** - Upgrade your wallets to smart accounts without migration
10
10
  - **⛽ Gas Sponsorship** - Pay gas fees for your users via Alchemy Gas Manager (EVM & Solana)
11
11
  - **💱 Token Swaps** - Execute swaps through Alchemy's swap infrastructure
12
12
  - **🚀 Batched Transactions** - Send multiple operations in a single transaction using `sendTransaction([...])`
@@ -253,15 +253,16 @@ function SolanaSendButton() {
253
253
 
254
254
  ### AlchemyProvider Props
255
255
 
256
- | Prop | Type | Required | Description |
257
- | -------------------- | -------------------- | ------------- | -------------------------------------------------------------------------------------------------------- |
258
- | `apiKey` | `string` | Conditional\* | Your Alchemy API key for @account-kit/infra transport |
259
- | `jwt` | `string` | Conditional\* | JWT token for authentication (alternative to `apiKey`) |
260
- | `rpcUrl` | `string` | Conditional\* | Custom RPC URL for EVM chains (can be used alone or with `jwt`) |
261
- | `solanaRpcUrl` | `string` | No | Custom RPC URL for Solana (separate from EVM `rpcUrl`) |
262
- | `policyId` | `string \| string[]` | No | Gas Manager policy ID(s) for EVM sponsorship. If array is provided, backend uses first applicable policy |
263
- | `solanaPolicyId` | `string \| string[]` | No | Gas Manager policy ID(s) for Solana sponsorship |
264
- | `disableSponsorship` | `boolean` | No | Set to `true` to disable gas sponsorship by default (default: `false`) |
256
+ | Prop | Type | Required | Description |
257
+ | -------------------- | ---------------------- | ------------- | -------------------------------------------------------------------------------------------------------- |
258
+ | `apiKey` | `string` | Conditional\* | Your Alchemy API key for @account-kit/infra transport |
259
+ | `jwt` | `string` | Conditional\* | JWT token for authentication (alternative to `apiKey`) |
260
+ | `rpcUrl` | `string` | Conditional\* | Custom RPC URL for EVM chains (can be used alone or with `jwt`) |
261
+ | `solanaRpcUrl` | `string` | No | Custom RPC URL for Solana (separate from EVM `rpcUrl`) |
262
+ | `policyId` | `string \| string[]` | No | Gas Manager policy ID(s) for EVM sponsorship. If array is provided, backend uses first applicable policy |
263
+ | `solanaPolicyId` | `string \| string[]` | No | Gas Manager policy ID(s) for Solana sponsorship |
264
+ | `disableSponsorship` | `boolean` | No | Set to `true` to disable gas sponsorship by default (default: `false`) |
265
+ | `accountAuthMode` | `'eip7702' \| 'owner'` | No | Authorization mode for EVM smart accounts (default: `'eip7702'`) |
265
266
 
266
267
  \* **Required configuration (pick one):**
267
268
 
@@ -352,21 +353,23 @@ Send Solana transactions with optional gas sponsorship via Alchemy.
352
353
 
353
354
  #### `useAlchemyClient()`
354
355
 
355
- Get the underlying smart wallet client (advanced use cases).
356
+ Get the underlying smart wallet client and account (advanced use cases).
356
357
 
357
358
  **Returns:**
358
359
 
359
- - `getClient()` - Async function that returns `SmartWalletClient`
360
+ - `getClient()` - Async function that returns `{ client: SmartWalletClient, account: SmartContractAccount }`
361
+ - `client` - The smart wallet client instance
362
+ - `account` - The smart account with address and other account info
360
363
 
361
364
  ## How It Works
362
365
 
363
- ### EIP-7702 Delegation
366
+ ### EIP-7702 Delegation (Default)
364
367
 
365
368
  This package uses [EIP-7702](https://eips.ethereum.org/EIPS/eip-7702) to upgrade your users' Privy wallets into smart accounts **without requiring them to deploy new contracts or migrate funds**.
366
369
 
367
370
  When a user sends their first transaction:
368
371
 
369
- 1. Their EOA signs an EIP-7702 authorization
372
+ 1. Their wallet signs an EIP-7702 authorization
370
373
  2. The authorization delegates to Alchemy's smart account implementation
371
374
  3. The transaction is executed with smart account features (batching, sponsorship, etc.)
372
375
  4. Gas is optionally sponsored by your Gas Manager policy
@@ -377,10 +380,47 @@ Under the hood, this package:
377
380
 
378
381
  1. Connects to your user's Privy embedded wallet
379
382
  2. Wraps it with `WalletClientSigner` from `@aa-sdk/core`
380
- 3. Creates a `SmartWalletClient` with EIP-7702 support
383
+ 3. Creates a `SmartWalletClient` with EIP-7702 support (default) or traditional smart account support
381
384
  4. Routes transactions through Alchemy infrastructure
382
385
  5. Automatically handles sponsorship via Gas Manager policies
383
386
 
387
+ ### Authorization Modes
388
+
389
+ The package supports two authorization modes via the `accountAuthMode` prop:
390
+
391
+ - **`'eip7702'` (default, recommended)**: Uses EIP-7702 to delegate the Privy wallet to a smart account. No separate deployment needed, funds stay at the wallet address. This is the recommended mode for most applications.
392
+ - **`'owner'`**: Uses a traditional smart account with the Privy wallet as the owner/signer. The smart account has a separate address from the owner wallet. Use this if you need compatibility with environments that don't support EIP-7702 yet.
393
+
394
+ ```tsx
395
+ // Default behavior (EIP-7702)
396
+ <AlchemyProvider apiKey="...">
397
+ <YourApp />
398
+ </AlchemyProvider>
399
+
400
+ // Traditional smart account mode
401
+ <AlchemyProvider apiKey="..." accountAuthMode="owner">
402
+ <YourApp />
403
+ </AlchemyProvider>
404
+ ```
405
+
406
+ **Getting the Smart Account Address:**
407
+
408
+ When using `owner` mode, the smart account has a different address from your Privy signer. Access it via `useAlchemyClient`:
409
+
410
+ ```tsx
411
+ import { useAlchemyClient } from "@account-kit/privy-integration";
412
+
413
+ function MyComponent() {
414
+ const { getClient } = useAlchemyClient();
415
+
416
+ const getSmartAccountAddress = async () => {
417
+ const { account } = await getClient();
418
+ console.log("Smart account address:", account.address);
419
+ // This is different from the Privy signer address in owner mode
420
+ };
421
+ }
422
+ ```
423
+
384
424
  ## Get Your API Keys
385
425
 
386
426
  ### Alchemy API Key
@@ -431,7 +471,7 @@ The API is nearly identical, making migration seamless.
431
471
 
432
472
  ### Access the Smart Wallet Client
433
473
 
434
- For advanced use cases, access the underlying client directly:
474
+ For advanced use cases, access the underlying client and account directly:
435
475
 
436
476
  ```tsx
437
477
  import { useAlchemyClient } from "@account-kit/privy-integration";
@@ -440,20 +480,20 @@ function AdvancedComponent() {
440
480
  const { getClient } = useAlchemyClient();
441
481
 
442
482
  const doAdvancedOperation = async () => {
443
- const client = await getClient();
483
+ const { client, account } = await getClient();
444
484
 
445
- // Use any SmartWalletClient method
446
- const address = await client.getAddress();
485
+ // Access the smart account address
486
+ console.log("Smart account address:", account.address);
447
487
 
448
488
  // Direct access to sendCalls with full control
449
489
  await client.sendCalls({
450
- from: address,
490
+ from: account.address,
451
491
  calls: [
452
492
  { to: "0x...", data: "0x..." },
453
493
  { to: "0x...", data: "0x..." },
454
494
  ],
455
495
  capabilities: {
456
- eip7702Auth: true,
496
+ eip7702Auth: true, // Set to true for EIP-7702 mode
457
497
  paymasterService: { policyId: "your-policy-id" },
458
498
  },
459
499
  });
@@ -1,6 +1,13 @@
1
1
  import { type PropsWithChildren } from "react";
2
2
  import type { SmartWalletClient } from "@account-kit/wallet-client";
3
+ import type { SmartContractAccount } from "@aa-sdk/core";
3
4
  import type { AlchemyProviderConfig } from "./types.js";
5
+ /**
6
+ * Normalized config with defaults applied
7
+ *
8
+ * @internal
9
+ */
10
+ export type NormalizedAlchemyConfig = AlchemyProviderConfig & Required<Pick<AlchemyProviderConfig, "accountAuthMode">>;
4
11
  /**
5
12
  * Client cache stored in React tree (similar to QueryClient in React Query)
6
13
  *
@@ -8,6 +15,7 @@ import type { AlchemyProviderConfig } from "./types.js";
8
15
  */
9
16
  interface ClientCache {
10
17
  client: SmartWalletClient | null;
18
+ account: SmartContractAccount | null;
11
19
  cacheKey: string | null;
12
20
  }
13
21
  /**
@@ -24,6 +32,7 @@ interface ClientCache {
24
32
  * @param {string | string[]} [props.policyId] - Gas Manager policy ID(s) for EVM chains
25
33
  * @param {string | string[]} [props.solanaPolicyId] - Gas Manager policy ID(s) for Solana
26
34
  * @param {boolean} [props.disableSponsorship] - Set to true to disable sponsorship by default (default: false)
35
+ * @param {'eip7702' | 'owner'} [props.accountAuthMode] - Authorization mode for EVM smart accounts (default: 'eip7702')
27
36
  * @returns {JSX.Element} Provider component
28
37
  *
29
38
  * @example
@@ -38,21 +47,22 @@ interface ClientCache {
38
47
  * </PrivyProvider>
39
48
  * ```
40
49
  */
41
- export declare function AlchemyProvider({ children, ...config }: PropsWithChildren<AlchemyProviderConfig>): import("react/jsx-runtime").JSX.Element;
50
+ export declare function AlchemyProvider({ children, accountAuthMode, ...config }: PropsWithChildren<AlchemyProviderConfig>): import("react/jsx-runtime").JSX.Element;
42
51
  /**
43
52
  * Hook to access Alchemy provider configuration
44
53
  * Must be used within an <AlchemyProvider> component
45
54
  *
46
- * @returns {AlchemyProviderConfig} The current Alchemy configuration
55
+ * @returns {NormalizedAlchemyConfig} The current Alchemy configuration with defaults applied
47
56
  * @throws {Error} If used outside of AlchemyProvider
48
57
  *
49
58
  * @example
50
59
  * ```tsx
51
60
  * const config = useAlchemyConfig();
52
61
  * console.log('Policy ID:', config.policyId);
62
+ * console.log('Auth Mode:', config.accountAuthMode); // Always defined
53
63
  * ```
54
64
  */
55
- export declare function useAlchemyConfig(): AlchemyProviderConfig;
65
+ export declare function useAlchemyConfig(): NormalizedAlchemyConfig;
56
66
  /**
57
67
  * Hook to access the client cache (internal use only)
58
68
  *
@@ -17,6 +17,7 @@ const ClientCacheContext = createContext(null);
17
17
  * @param {string | string[]} [props.policyId] - Gas Manager policy ID(s) for EVM chains
18
18
  * @param {string | string[]} [props.solanaPolicyId] - Gas Manager policy ID(s) for Solana
19
19
  * @param {boolean} [props.disableSponsorship] - Set to true to disable sponsorship by default (default: false)
20
+ * @param {'eip7702' | 'owner'} [props.accountAuthMode] - Authorization mode for EVM smart accounts (default: 'eip7702')
20
21
  * @returns {JSX.Element} Provider component
21
22
  *
22
23
  * @example
@@ -31,12 +32,18 @@ const ClientCacheContext = createContext(null);
31
32
  * </PrivyProvider>
32
33
  * ```
33
34
  */
34
- export function AlchemyProvider({ children, ...config }) {
35
+ export function AlchemyProvider({ children, accountAuthMode = "eip7702", ...config }) {
35
36
  const { authenticated, user } = usePrivy();
37
+ // Normalize config with default values
38
+ const normalizedConfig = {
39
+ ...config,
40
+ accountAuthMode,
41
+ };
36
42
  // Store cache in a ref - persists across renders but scoped to this component instance
37
43
  // This makes it SSR-safe (each request gets its own cache) and React StrictMode-safe
38
44
  const cache = useRef({
39
45
  client: null,
46
+ account: null,
40
47
  cacheKey: null,
41
48
  });
42
49
  // Track previous state to detect logout and wallet changes
@@ -50,6 +57,7 @@ export function AlchemyProvider({ children, ...config }) {
50
57
  // Reset cache on logout
51
58
  if (wasAuthenticated && !authenticated) {
52
59
  cache.current.client = null;
60
+ cache.current.account = null;
53
61
  cache.current.cacheKey = null;
54
62
  }
55
63
  // Reset cache on wallet address change (account switching)
@@ -58,25 +66,27 @@ export function AlchemyProvider({ children, ...config }) {
58
66
  currentWalletAddress &&
59
67
  prevWalletAddress !== currentWalletAddress) {
60
68
  cache.current.client = null;
69
+ cache.current.account = null;
61
70
  cache.current.cacheKey = null;
62
71
  }
63
72
  // Update refs for next render
64
73
  prevAuthenticatedRef.current = authenticated;
65
74
  prevWalletAddressRef.current = currentWalletAddress;
66
75
  }, [authenticated, user?.wallet?.address]);
67
- return (_jsx(AlchemyContext.Provider, { value: config, children: _jsx(ClientCacheContext.Provider, { value: cache.current, children: children }) }));
76
+ return (_jsx(AlchemyContext.Provider, { value: normalizedConfig, children: _jsx(ClientCacheContext.Provider, { value: cache.current, children: children }) }));
68
77
  }
69
78
  /**
70
79
  * Hook to access Alchemy provider configuration
71
80
  * Must be used within an <AlchemyProvider> component
72
81
  *
73
- * @returns {AlchemyProviderConfig} The current Alchemy configuration
82
+ * @returns {NormalizedAlchemyConfig} The current Alchemy configuration with defaults applied
74
83
  * @throws {Error} If used outside of AlchemyProvider
75
84
  *
76
85
  * @example
77
86
  * ```tsx
78
87
  * const config = useAlchemyConfig();
79
88
  * console.log('Policy ID:', config.policyId);
89
+ * console.log('Auth Mode:', config.accountAuthMode); // Always defined
80
90
  * ```
81
91
  */
82
92
  export function useAlchemyConfig() {
@@ -1 +1 @@
1
- {"version":3,"file":"Provider.js","sourceRoot":"","sources":["../../src/Provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAEL,aAAa,EACb,UAAU,EACV,MAAM,EACN,SAAS,GACV,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAIhD,MAAM,cAAc,GAAG,aAAa,CAA+B,IAAI,CAAC,CAAC;AAYzE,MAAM,kBAAkB,GAAG,aAAa,CAAqB,IAAI,CAAC,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,eAAe,CAAC,EAC9B,QAAQ,EACR,GAAG,MAAM,EACgC;IACzC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,QAAQ,EAAE,CAAC;IAE3C,uFAAuF;IACvF,qFAAqF;IACrF,MAAM,KAAK,GAAG,MAAM,CAAc;QAChC,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,IAAI;KACf,CAAC,CAAC;IAEH,2DAA2D;IAC3D,MAAM,oBAAoB,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;IACnD,MAAM,oBAAoB,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAE3D,mEAAmE;IACnE,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,gBAAgB,GAAG,oBAAoB,CAAC,OAAO,CAAC;QACtD,MAAM,iBAAiB,GAAG,oBAAoB,CAAC,OAAO,CAAC;QACvD,MAAM,oBAAoB,GAAG,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC;QAEnD,wBAAwB;QACxB,IAAI,gBAAgB,IAAI,CAAC,aAAa,EAAE,CAAC;YACvC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;YAC5B,KAAK,CAAC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;QAChC,CAAC;QAED,2DAA2D;QAC3D,IACE,aAAa;YACb,iBAAiB;YACjB,oBAAoB;YACpB,iBAAiB,KAAK,oBAAoB,EAC1C,CAAC;YACD,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;YAC5B,KAAK,CAAC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;QAChC,CAAC;QAED,8BAA8B;QAC9B,oBAAoB,CAAC,OAAO,GAAG,aAAa,CAAC;QAC7C,oBAAoB,CAAC,OAAO,GAAG,oBAAoB,CAAC;IACtD,CAAC,EAAE,CAAC,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAE3C,OAAO,CACL,KAAC,cAAc,CAAC,QAAQ,IAAC,KAAK,EAAE,MAAM,YACpC,KAAC,kBAAkB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,CAAC,OAAO,YAC9C,QAAQ,GACmB,GACN,CAC3B,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,OAAO,GAAG,UAAU,CAAC,cAAc,CAAC,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,OAAO,GAAG,UAAU,CAAC,kBAAkB,CAAC,CAAC;IAC/C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,mHAAmH,CACpH,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC","sourcesContent":["import {\n type PropsWithChildren,\n createContext,\n useContext,\n useRef,\n useEffect,\n} from \"react\";\nimport { usePrivy } from \"@privy-io/react-auth\";\nimport type { SmartWalletClient } from \"@account-kit/wallet-client\";\nimport type { AlchemyProviderConfig } from \"./types.js\";\n\nconst AlchemyContext = createContext<AlchemyProviderConfig | null>(null);\n\n/**\n * Client cache stored in React tree (similar to QueryClient in React Query)\n *\n * @internal\n */\ninterface ClientCache {\n client: SmartWalletClient | null;\n cacheKey: string | null;\n}\n\nconst ClientCacheContext = createContext<ClientCache | null>(null);\n\n/**\n * Provider component that configures Alchemy infrastructure for transaction handling\n * Must be nested INSIDE PrivyProvider to access authentication state\n * Automatically manages client cache lifecycle and resets on logout\n *\n * @param {PropsWithChildren<AlchemyProviderConfig>} props - Component props\n * @param {React.ReactNode} props.children - React children to wrap with Alchemy configuration\n * @param {string} [props.apiKey] - Your Alchemy API key\n * @param {string} [props.jwt] - JWT token for authentication\n * @param {string} [props.rpcUrl] - Custom RPC URL for EVM chains\n * @param {string} [props.solanaRpcUrl] - Custom RPC URL for Solana\n * @param {string | string[]} [props.policyId] - Gas Manager policy ID(s) for EVM chains\n * @param {string | string[]} [props.solanaPolicyId] - Gas Manager policy ID(s) for Solana\n * @param {boolean} [props.disableSponsorship] - Set to true to disable sponsorship by default (default: false)\n * @returns {JSX.Element} Provider component\n *\n * @example\n * ```tsx\n * <PrivyProvider appId=\"...\">\n * <AlchemyProvider\n * apiKey=\"your-alchemy-api-key\"\n * policyId=\"your-gas-policy-id\"\n * >\n * <YourApp />\n * </AlchemyProvider>\n * </PrivyProvider>\n * ```\n */\nexport function AlchemyProvider({\n children,\n ...config\n}: PropsWithChildren<AlchemyProviderConfig>) {\n const { authenticated, user } = usePrivy();\n\n // Store cache in a ref - persists across renders but scoped to this component instance\n // This makes it SSR-safe (each request gets its own cache) and React StrictMode-safe\n const cache = useRef<ClientCache>({\n client: null,\n cacheKey: null,\n });\n\n // Track previous state to detect logout and wallet changes\n const prevAuthenticatedRef = useRef(authenticated);\n const prevWalletAddressRef = useRef(user?.wallet?.address);\n\n // Automatically reset cache when user logs out or switches wallets\n useEffect(() => {\n const wasAuthenticated = prevAuthenticatedRef.current;\n const prevWalletAddress = prevWalletAddressRef.current;\n const currentWalletAddress = user?.wallet?.address;\n\n // Reset cache on logout\n if (wasAuthenticated && !authenticated) {\n cache.current.client = null;\n cache.current.cacheKey = null;\n }\n\n // Reset cache on wallet address change (account switching)\n if (\n authenticated &&\n prevWalletAddress &&\n currentWalletAddress &&\n prevWalletAddress !== currentWalletAddress\n ) {\n cache.current.client = null;\n cache.current.cacheKey = null;\n }\n\n // Update refs for next render\n prevAuthenticatedRef.current = authenticated;\n prevWalletAddressRef.current = currentWalletAddress;\n }, [authenticated, user?.wallet?.address]);\n\n return (\n <AlchemyContext.Provider value={config}>\n <ClientCacheContext.Provider value={cache.current}>\n {children}\n </ClientCacheContext.Provider>\n </AlchemyContext.Provider>\n );\n}\n\n/**\n * Hook to access Alchemy provider configuration\n * Must be used within an <AlchemyProvider> component\n *\n * @returns {AlchemyProviderConfig} The current Alchemy configuration\n * @throws {Error} If used outside of AlchemyProvider\n *\n * @example\n * ```tsx\n * const config = useAlchemyConfig();\n * console.log('Policy ID:', config.policyId);\n * ```\n */\nexport function useAlchemyConfig(): AlchemyProviderConfig {\n const context = useContext(AlchemyContext);\n if (!context) {\n throw new Error(\"useAlchemyConfig must be used within <AlchemyProvider />\");\n }\n return context;\n}\n\n/**\n * Hook to access the client cache (internal use only)\n *\n * @internal\n * @returns {ClientCache} The client cache object\n */\nexport function useClientCache(): ClientCache {\n const context = useContext(ClientCacheContext);\n if (!context) {\n throw new Error(\n \"useClientCache must be used within <AlchemyProvider />. Make sure AlchemyProvider is nested inside PrivyProvider.\",\n );\n }\n return context;\n}\n"]}
1
+ {"version":3,"file":"Provider.js","sourceRoot":"","sources":["../../src/Provider.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n type PropsWithChildren,\n createContext,\n useContext,\n useRef,\n useEffect,\n} from \"react\";\nimport { usePrivy } from \"@privy-io/react-auth\";\nimport type { SmartWalletClient } from \"@account-kit/wallet-client\";\nimport type { SmartContractAccount } from \"@aa-sdk/core\";\nimport type { AlchemyProviderConfig } from \"./types.js\";\n\n/**\n * Normalized config with defaults applied\n *\n * @internal\n */\nexport type NormalizedAlchemyConfig = AlchemyProviderConfig &\n Required<Pick<AlchemyProviderConfig, \"accountAuthMode\">>;\n\nconst AlchemyContext = createContext<NormalizedAlchemyConfig | null>(null);\n\n/**\n * Client cache stored in React tree (similar to QueryClient in React Query)\n *\n * @internal\n */\ninterface ClientCache {\n client: SmartWalletClient | null;\n account: SmartContractAccount | null;\n cacheKey: string | null;\n}\n\nconst ClientCacheContext = createContext<ClientCache | null>(null);\n\n/**\n * Provider component that configures Alchemy infrastructure for transaction handling\n * Must be nested INSIDE PrivyProvider to access authentication state\n * Automatically manages client cache lifecycle and resets on logout\n *\n * @param {PropsWithChildren<AlchemyProviderConfig>} props - Component props\n * @param {React.ReactNode} props.children - React children to wrap with Alchemy configuration\n * @param {string} [props.apiKey] - Your Alchemy API key\n * @param {string} [props.jwt] - JWT token for authentication\n * @param {string} [props.rpcUrl] - Custom RPC URL for EVM chains\n * @param {string} [props.solanaRpcUrl] - Custom RPC URL for Solana\n * @param {string | string[]} [props.policyId] - Gas Manager policy ID(s) for EVM chains\n * @param {string | string[]} [props.solanaPolicyId] - Gas Manager policy ID(s) for Solana\n * @param {boolean} [props.disableSponsorship] - Set to true to disable sponsorship by default (default: false)\n * @param {'eip7702' | 'owner'} [props.accountAuthMode] - Authorization mode for EVM smart accounts (default: 'eip7702')\n * @returns {JSX.Element} Provider component\n *\n * @example\n * ```tsx\n * <PrivyProvider appId=\"...\">\n * <AlchemyProvider\n * apiKey=\"your-alchemy-api-key\"\n * policyId=\"your-gas-policy-id\"\n * >\n * <YourApp />\n * </AlchemyProvider>\n * </PrivyProvider>\n * ```\n */\nexport function AlchemyProvider({\n children,\n accountAuthMode = \"eip7702\",\n ...config\n}: PropsWithChildren<AlchemyProviderConfig>) {\n const { authenticated, user } = usePrivy();\n\n // Normalize config with default values\n const normalizedConfig: NormalizedAlchemyConfig = {\n ...config,\n accountAuthMode,\n };\n\n // Store cache in a ref - persists across renders but scoped to this component instance\n // This makes it SSR-safe (each request gets its own cache) and React StrictMode-safe\n const cache = useRef<ClientCache>({\n client: null,\n account: null,\n cacheKey: null,\n });\n\n // Track previous state to detect logout and wallet changes\n const prevAuthenticatedRef = useRef(authenticated);\n const prevWalletAddressRef = useRef(user?.wallet?.address);\n\n // Automatically reset cache when user logs out or switches wallets\n useEffect(() => {\n const wasAuthenticated = prevAuthenticatedRef.current;\n const prevWalletAddress = prevWalletAddressRef.current;\n const currentWalletAddress = user?.wallet?.address;\n\n // Reset cache on logout\n if (wasAuthenticated && !authenticated) {\n cache.current.client = null;\n cache.current.account = null;\n cache.current.cacheKey = null;\n }\n\n // Reset cache on wallet address change (account switching)\n if (\n authenticated &&\n prevWalletAddress &&\n currentWalletAddress &&\n prevWalletAddress !== currentWalletAddress\n ) {\n cache.current.client = null;\n cache.current.account = null;\n cache.current.cacheKey = null;\n }\n\n // Update refs for next render\n prevAuthenticatedRef.current = authenticated;\n prevWalletAddressRef.current = currentWalletAddress;\n }, [authenticated, user?.wallet?.address]);\n\n return (\n <AlchemyContext.Provider value={normalizedConfig}>\n <ClientCacheContext.Provider value={cache.current}>\n {children}\n </ClientCacheContext.Provider>\n </AlchemyContext.Provider>\n );\n}\n\n/**\n * Hook to access Alchemy provider configuration\n * Must be used within an <AlchemyProvider> component\n *\n * @returns {NormalizedAlchemyConfig} The current Alchemy configuration with defaults applied\n * @throws {Error} If used outside of AlchemyProvider\n *\n * @example\n * ```tsx\n * const config = useAlchemyConfig();\n * console.log('Policy ID:', config.policyId);\n * console.log('Auth Mode:', config.accountAuthMode); // Always defined\n * ```\n */\nexport function useAlchemyConfig(): NormalizedAlchemyConfig {\n const context = useContext(AlchemyContext);\n if (!context) {\n throw new Error(\"useAlchemyConfig must be used within <AlchemyProvider />\");\n }\n return context;\n}\n\n/**\n * Hook to access the client cache (internal use only)\n *\n * @internal\n * @returns {ClientCache} The client cache object\n */\nexport function useClientCache(): ClientCache {\n const context = useContext(ClientCacheContext);\n if (!context) {\n throw new Error(\n \"useClientCache must be used within <AlchemyProvider />. Make sure AlchemyProvider is nested inside PrivyProvider.\",\n );\n }\n return context;\n}\n"]}
@@ -1,17 +1,22 @@
1
+ import { type SmartContractAccount } from "@aa-sdk/core";
1
2
  import { type SmartWalletClient } from "@account-kit/wallet-client";
3
+ export type AlchemyClientResult = {
4
+ client: SmartWalletClient;
5
+ account: SmartContractAccount;
6
+ };
2
7
  /**
3
- * Hook to get and memoize a SmartWalletClient instance
4
- * The client is cached in the AlchemyProvider context (React tree scoped)
8
+ * Hook to get and memoize a SmartWalletClient instance with its associated account
9
+ * The client and account are cached in the AlchemyProvider context (React tree scoped)
5
10
  * Automatically clears cache on logout via the provider
6
11
  *
7
- * @returns {{ getClient: () => Promise<SmartWalletClient> }} Object containing the smart wallet client getter
12
+ * @returns {{ getClient: () => Promise<AlchemyClientResult> }} Object containing the smart wallet client and account getter
8
13
  *
9
14
  * @example
10
15
  * ```tsx
11
16
  * const { getClient } = useAlchemyClient();
12
- * const smartWalletClient = await getClient();
17
+ * const { client, account } = await getClient();
13
18
  * ```
14
19
  */
15
20
  export declare function useAlchemyClient(): {
16
- getClient: () => Promise<SmartWalletClient>;
21
+ getClient: () => Promise<AlchemyClientResult>;
17
22
  };
@@ -8,16 +8,16 @@ import { useAlchemyConfig, useClientCache } from "../Provider.js";
8
8
  import { getChain } from "../util/getChain.js";
9
9
  import { useEmbeddedWallet } from "./internal/useEmbeddedWallet.js";
10
10
  /**
11
- * Hook to get and memoize a SmartWalletClient instance
12
- * The client is cached in the AlchemyProvider context (React tree scoped)
11
+ * Hook to get and memoize a SmartWalletClient instance with its associated account
12
+ * The client and account are cached in the AlchemyProvider context (React tree scoped)
13
13
  * Automatically clears cache on logout via the provider
14
14
  *
15
- * @returns {{ getClient: () => Promise<SmartWalletClient> }} Object containing the smart wallet client getter
15
+ * @returns {{ getClient: () => Promise<AlchemyClientResult> }} Object containing the smart wallet client and account getter
16
16
  *
17
17
  * @example
18
18
  * ```tsx
19
19
  * const { getClient } = useAlchemyClient();
20
- * const smartWalletClient = await getClient();
20
+ * const { client, account } = await getClient();
21
21
  * ```
22
22
  */
23
23
  export function useAlchemyClient() {
@@ -52,10 +52,11 @@ export function useAlchemyClient() {
52
52
  jwt: config.jwt,
53
53
  rpcUrl: config.rpcUrl,
54
54
  policyId: config.policyId,
55
+ accountAuthMode: config.accountAuthMode,
55
56
  });
56
- // Return cached client if configuration hasn't changed
57
- if (cache.client && cache.cacheKey === currentCacheKey) {
58
- return cache.client;
57
+ // Return cached client and account if configuration hasn't changed
58
+ if (cache.client && cache.account && cache.cacheKey === currentCacheKey) {
59
+ return { client: cache.client, account: cache.account };
59
60
  }
60
61
  // Configuration changed or no cache exists, create new client
61
62
  const provider = await embeddedWallet.getEthereumProvider();
@@ -65,20 +66,19 @@ export function useAlchemyClient() {
65
66
  chain,
66
67
  transport: custom(provider),
67
68
  }), "privy");
68
- // Extend signer with EIP-7702 authorization support
69
- const signer = {
70
- ...baseSigner,
71
- signAuthorization: async (unsignedAuth) => {
72
- const signature = await signAuthorization({
73
- ...unsignedAuth,
74
- contractAddress: unsignedAuth.address ?? unsignedAuth.contractAddress,
75
- });
76
- return {
77
- ...unsignedAuth,
78
- ...signature,
79
- };
80
- },
81
- };
69
+ // Optionally extend signer with EIP-7702 authorization support
70
+ const signer = config.accountAuthMode === "eip7702"
71
+ ? {
72
+ ...baseSigner,
73
+ signAuthorization: async (unsignedAuth) => {
74
+ const signature = await signAuthorization({
75
+ ...unsignedAuth,
76
+ contractAddress: unsignedAuth.address ?? unsignedAuth.contractAddress,
77
+ });
78
+ return { ...unsignedAuth, ...signature };
79
+ },
80
+ }
81
+ : baseSigner;
82
82
  // Determine transport configuration using schema validation
83
83
  // This properly handles combinations like rpcUrl + jwt together
84
84
  const transportConfig = ConnectionConfigSchema.parse({
@@ -101,9 +101,20 @@ export function useAlchemyClient() {
101
101
  : [config.policyId]
102
102
  : undefined,
103
103
  });
104
+ // Request the account to properly initialize the smart wallet
105
+ // Pass a creation hint based on auth mode to ensure different accounts for different modes
106
+ // This prevents 7702 accounts from being reused in owner mode and vice versa
107
+ cache.account =
108
+ config.accountAuthMode === "eip7702"
109
+ ? await cache.client.requestAccount({
110
+ creationHint: { accountType: "7702" },
111
+ })
112
+ : await cache.client.requestAccount({
113
+ creationHint: { accountType: "sma-b" },
114
+ });
104
115
  // Store the cache key
105
116
  cache.cacheKey = currentCacheKey;
106
- return cache.client;
117
+ return { client: cache.client, account: cache.account };
107
118
  }, [
108
119
  getEmbeddedWallet,
109
120
  getEmbeddedWalletChain,
@@ -113,6 +124,7 @@ export function useAlchemyClient() {
113
124
  config.rpcUrl,
114
125
  config.policyId,
115
126
  cache,
127
+ config.accountAuthMode,
116
128
  ]);
117
129
  return { getClient };
118
130
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useAlchemyClient.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemyClient.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback } from \"react\";\nimport {\n WalletClientSigner,\n type AuthorizationRequest,\n ConnectionConfigSchema,\n} from \"@aa-sdk/core\";\nimport {\n createWalletClient,\n custom,\n type Address,\n type Authorization,\n} from \"viem\";\nimport { useSign7702Authorization } from \"@privy-io/react-auth\";\nimport {\n createSmartWalletClient,\n type SmartWalletClient,\n} from \"@account-kit/wallet-client\";\nimport { alchemy } from \"@account-kit/infra\";\nimport { useAlchemyConfig, useClientCache } from \"../Provider.js\";\nimport { getChain } from \"../util/getChain.js\";\nimport { useEmbeddedWallet } from \"./internal/useEmbeddedWallet.js\";\n\n/**\n * Hook to get and memoize a SmartWalletClient instance\n * The client is cached in the AlchemyProvider context (React tree scoped)\n * Automatically clears cache on logout via the provider\n *\n * @returns {{ getClient: () => Promise<SmartWalletClient> }} Object containing the smart wallet client getter\n *\n * @example\n * ```tsx\n * const { getClient } = useAlchemyClient();\n * const smartWalletClient = await getClient();\n * ```\n */\nexport function useAlchemyClient() {\n const { signAuthorization } = useSign7702Authorization();\n const config = useAlchemyConfig();\n const cache = useClientCache();\n const getEmbeddedWallet = useEmbeddedWallet();\n\n const getEmbeddedWalletChain = useCallback(() => {\n const embedded = getEmbeddedWallet();\n // Handle CAIP-2 format like \"eip155:1\"\n const chainIdStr = embedded.chainId?.toString();\n\n if (!chainIdStr) {\n throw new Error(\n \"Embedded wallet chainId is not set. Please ensure the wallet is connected to a network.\",\n );\n }\n\n const numericChainId = chainIdStr.includes(\":\")\n ? chainIdStr.split(\":\")[1]\n : chainIdStr;\n\n const parsedChainId = Number(numericChainId);\n\n if (isNaN(parsedChainId)) {\n throw new Error(\n `Failed to parse chainId from embedded wallet. Received: ${chainIdStr}`,\n );\n }\n\n return getChain(parsedChainId);\n }, [getEmbeddedWallet]);\n\n const getClient = useCallback(async (): Promise<SmartWalletClient> => {\n const embeddedWallet = getEmbeddedWallet();\n const chain = getEmbeddedWalletChain();\n\n // Generate a cache key based on configuration and wallet address\n const currentCacheKey = JSON.stringify({\n address: embeddedWallet.address,\n chainId: chain.id,\n apiKey: config.apiKey,\n jwt: config.jwt,\n rpcUrl: config.rpcUrl,\n policyId: config.policyId,\n });\n\n // Return cached client if configuration hasn't changed\n if (cache.client && cache.cacheKey === currentCacheKey) {\n return cache.client;\n }\n\n // Configuration changed or no cache exists, create new client\n const provider = await embeddedWallet.getEthereumProvider();\n\n // Create base signer from Privy wallet\n const baseSigner = new WalletClientSigner(\n createWalletClient({\n account: embeddedWallet.address as Address,\n chain,\n transport: custom(provider),\n }),\n \"privy\",\n );\n\n // Extend signer with EIP-7702 authorization support\n const signer = {\n ...baseSigner,\n signAuthorization: async (\n unsignedAuth: AuthorizationRequest<number>,\n ): Promise<Authorization<number, true>> => {\n const signature = await signAuthorization({\n ...unsignedAuth,\n contractAddress: unsignedAuth.address ?? unsignedAuth.contractAddress,\n });\n\n return {\n ...unsignedAuth,\n ...signature,\n };\n },\n };\n\n // Determine transport configuration using schema validation\n // This properly handles combinations like rpcUrl + jwt together\n const transportConfig = ConnectionConfigSchema.parse({\n rpcUrl: config.rpcUrl,\n apiKey: config.apiKey,\n jwt: config.jwt,\n });\n\n const transport = alchemy(transportConfig);\n\n transport.updateHeaders({\n \"X-Alchemy-Client-Breadcrumb\": \"privyIntegrationSdk\",\n });\n\n // Create and cache the smart wallet client in provider context\n cache.client = createSmartWalletClient({\n chain,\n transport,\n signer,\n policyIds: config.policyId\n ? Array.isArray(config.policyId)\n ? config.policyId\n : [config.policyId]\n : undefined,\n });\n\n // Store the cache key\n cache.cacheKey = currentCacheKey;\n\n return cache.client;\n }, [\n getEmbeddedWallet,\n getEmbeddedWalletChain,\n signAuthorization,\n config.apiKey,\n config.jwt,\n config.rpcUrl,\n config.policyId,\n cache,\n ]);\n\n return { getClient };\n}\n"]}
1
+ {"version":3,"file":"useAlchemyClient.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemyClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EACL,kBAAkB,EAElB,sBAAsB,GAEvB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,kBAAkB,EAClB,MAAM,GAGP,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,EACL,uBAAuB,GAExB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAOpE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,EAAE,iBAAiB,EAAE,GAAG,wBAAwB,EAAE,CAAC;IACzD,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,MAAM,KAAK,GAAG,cAAc,EAAE,CAAC;IAC/B,MAAM,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;IAE9C,MAAM,sBAAsB,GAAG,WAAW,CAAC,GAAG,EAAE;QAC9C,MAAM,QAAQ,GAAG,iBAAiB,EAAE,CAAC;QACrC,uCAAuC;QACvC,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC;QAEhD,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CACb,yFAAyF,CAC1F,CAAC;QACJ,CAAC;QAED,MAAM,cAAc,GAAG,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC;YAC7C,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC1B,CAAC,CAAC,UAAU,CAAC;QAEf,MAAM,aAAa,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;QAE7C,IAAI,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CACb,2DAA2D,UAAU,EAAE,CACxE,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAExB,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,IAAkC,EAAE;QACrE,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAG,sBAAsB,EAAE,CAAC;QAEvC,iEAAiE;QACjE,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC;YACrC,OAAO,EAAE,cAAc,CAAC,OAAO;YAC/B,OAAO,EAAE,KAAK,CAAC,EAAE;YACjB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,eAAe,EAAE,MAAM,CAAC,eAAe;SACxC,CAAC,CAAC;QAEH,mEAAmE;QACnE,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,QAAQ,KAAK,eAAe,EAAE,CAAC;YACxE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QAC1D,CAAC;QAED,8DAA8D;QAC9D,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,mBAAmB,EAAE,CAAC;QAE5D,uCAAuC;QACvC,MAAM,UAAU,GAAG,IAAI,kBAAkB,CACvC,kBAAkB,CAAC;YACjB,OAAO,EAAE,cAAc,CAAC,OAAkB;YAC1C,KAAK;YACL,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC;SAC5B,CAAC,EACF,OAAO,CACR,CAAC;QAEF,+DAA+D;QAC/D,MAAM,MAAM,GACV,MAAM,CAAC,eAAe,KAAK,SAAS;YAClC,CAAC,CAAC;gBACE,GAAG,UAAU;gBACb,iBAAiB,EAAE,KAAK,EACtB,YAA0C,EACJ,EAAE;oBACxC,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC;wBACxC,GAAG,YAAY;wBACf,eAAe,EACb,YAAY,CAAC,OAAO,IAAI,YAAY,CAAC,eAAe;qBACvD,CAAC,CAAC;oBACH,OAAO,EAAE,GAAG,YAAY,EAAE,GAAG,SAAS,EAAE,CAAC;gBAC3C,CAAC;aACF;YACH,CAAC,CAAC,UAAU,CAAC;QAEjB,4DAA4D;QAC5D,gEAAgE;QAChE,MAAM,eAAe,GAAG,sBAAsB,CAAC,KAAK,CAAC;YACnD,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,GAAG,EAAE,MAAM,CAAC,GAAG;SAChB,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;QAE3C,SAAS,CAAC,aAAa,CAAC;YACtB,6BAA6B,EAAE,qBAAqB;SACrD,CAAC,CAAC;QAEH,+DAA+D;QAC/D,KAAK,CAAC,MAAM,GAAG,uBAAuB,CAAC;YACrC,KAAK;YACL,SAAS;YACT,MAAM;YACN,SAAS,EAAE,MAAM,CAAC,QAAQ;gBACxB,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;oBAC9B,CAAC,CAAC,MAAM,CAAC,QAAQ;oBACjB,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;gBACrB,CAAC,CAAC,SAAS;SACd,CAAC,CAAC;QAEH,8DAA8D;QAC9D,2FAA2F;QAC3F,6EAA6E;QAC7E,KAAK,CAAC,OAAO;YACX,MAAM,CAAC,eAAe,KAAK,SAAS;gBAClC,CAAC,CAAC,MAAM,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC;oBAChC,YAAY,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE;iBACtC,CAAC;gBACJ,CAAC,CAAC,MAAM,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC;oBAChC,YAAY,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE;iBACvC,CAAC,CAAC;QAET,sBAAsB;QACtB,KAAK,CAAC,QAAQ,GAAG,eAAe,CAAC;QAEjC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;IAC1D,CAAC,EAAE;QACD,iBAAiB;QACjB,sBAAsB;QACtB,iBAAiB;QACjB,MAAM,CAAC,MAAM;QACb,MAAM,CAAC,GAAG;QACV,MAAM,CAAC,MAAM;QACb,MAAM,CAAC,QAAQ;QACf,KAAK;QACL,MAAM,CAAC,eAAe;KACvB,CAAC,CAAC;IAEH,OAAO,EAAE,SAAS,EAAE,CAAC;AACvB,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport {\n WalletClientSigner,\n type AuthorizationRequest,\n ConnectionConfigSchema,\n type SmartContractAccount,\n} from \"@aa-sdk/core\";\nimport {\n createWalletClient,\n custom,\n type Address,\n type Authorization,\n} from \"viem\";\nimport { useSign7702Authorization } from \"@privy-io/react-auth\";\nimport {\n createSmartWalletClient,\n type SmartWalletClient,\n} from \"@account-kit/wallet-client\";\nimport { alchemy } from \"@account-kit/infra\";\nimport { useAlchemyConfig, useClientCache } from \"../Provider.js\";\nimport { getChain } from \"../util/getChain.js\";\nimport { useEmbeddedWallet } from \"./internal/useEmbeddedWallet.js\";\n\nexport type AlchemyClientResult = {\n client: SmartWalletClient;\n account: SmartContractAccount;\n};\n\n/**\n * Hook to get and memoize a SmartWalletClient instance with its associated account\n * The client and account are cached in the AlchemyProvider context (React tree scoped)\n * Automatically clears cache on logout via the provider\n *\n * @returns {{ getClient: () => Promise<AlchemyClientResult> }} Object containing the smart wallet client and account getter\n *\n * @example\n * ```tsx\n * const { getClient } = useAlchemyClient();\n * const { client, account } = await getClient();\n * ```\n */\nexport function useAlchemyClient() {\n const { signAuthorization } = useSign7702Authorization();\n const config = useAlchemyConfig();\n const cache = useClientCache();\n const getEmbeddedWallet = useEmbeddedWallet();\n\n const getEmbeddedWalletChain = useCallback(() => {\n const embedded = getEmbeddedWallet();\n // Handle CAIP-2 format like \"eip155:1\"\n const chainIdStr = embedded.chainId?.toString();\n\n if (!chainIdStr) {\n throw new Error(\n \"Embedded wallet chainId is not set. Please ensure the wallet is connected to a network.\",\n );\n }\n\n const numericChainId = chainIdStr.includes(\":\")\n ? chainIdStr.split(\":\")[1]\n : chainIdStr;\n\n const parsedChainId = Number(numericChainId);\n\n if (isNaN(parsedChainId)) {\n throw new Error(\n `Failed to parse chainId from embedded wallet. Received: ${chainIdStr}`,\n );\n }\n\n return getChain(parsedChainId);\n }, [getEmbeddedWallet]);\n\n const getClient = useCallback(async (): Promise<AlchemyClientResult> => {\n const embeddedWallet = getEmbeddedWallet();\n const chain = getEmbeddedWalletChain();\n\n // Generate a cache key based on configuration and wallet address\n const currentCacheKey = JSON.stringify({\n address: embeddedWallet.address,\n chainId: chain.id,\n apiKey: config.apiKey,\n jwt: config.jwt,\n rpcUrl: config.rpcUrl,\n policyId: config.policyId,\n accountAuthMode: config.accountAuthMode,\n });\n\n // Return cached client and account if configuration hasn't changed\n if (cache.client && cache.account && cache.cacheKey === currentCacheKey) {\n return { client: cache.client, account: cache.account };\n }\n\n // Configuration changed or no cache exists, create new client\n const provider = await embeddedWallet.getEthereumProvider();\n\n // Create base signer from Privy wallet\n const baseSigner = new WalletClientSigner(\n createWalletClient({\n account: embeddedWallet.address as Address,\n chain,\n transport: custom(provider),\n }),\n \"privy\",\n );\n\n // Optionally extend signer with EIP-7702 authorization support\n const signer =\n config.accountAuthMode === \"eip7702\"\n ? {\n ...baseSigner,\n signAuthorization: async (\n unsignedAuth: AuthorizationRequest<number>,\n ): Promise<Authorization<number, true>> => {\n const signature = await signAuthorization({\n ...unsignedAuth,\n contractAddress:\n unsignedAuth.address ?? unsignedAuth.contractAddress,\n });\n return { ...unsignedAuth, ...signature };\n },\n }\n : baseSigner;\n\n // Determine transport configuration using schema validation\n // This properly handles combinations like rpcUrl + jwt together\n const transportConfig = ConnectionConfigSchema.parse({\n rpcUrl: config.rpcUrl,\n apiKey: config.apiKey,\n jwt: config.jwt,\n });\n\n const transport = alchemy(transportConfig);\n\n transport.updateHeaders({\n \"X-Alchemy-Client-Breadcrumb\": \"privyIntegrationSdk\",\n });\n\n // Create and cache the smart wallet client in provider context\n cache.client = createSmartWalletClient({\n chain,\n transport,\n signer,\n policyIds: config.policyId\n ? Array.isArray(config.policyId)\n ? config.policyId\n : [config.policyId]\n : undefined,\n });\n\n // Request the account to properly initialize the smart wallet\n // Pass a creation hint based on auth mode to ensure different accounts for different modes\n // This prevents 7702 accounts from being reused in owner mode and vice versa\n cache.account =\n config.accountAuthMode === \"eip7702\"\n ? await cache.client.requestAccount({\n creationHint: { accountType: \"7702\" },\n })\n : await cache.client.requestAccount({\n creationHint: { accountType: \"sma-b\" },\n });\n\n // Store the cache key\n cache.cacheKey = currentCacheKey;\n\n return { client: cache.client, account: cache.account };\n }, [\n getEmbeddedWallet,\n getEmbeddedWalletChain,\n signAuthorization,\n config.apiKey,\n config.jwt,\n config.rpcUrl,\n config.policyId,\n cache,\n config.accountAuthMode,\n ]);\n\n return { getClient };\n}\n"]}
@@ -2,7 +2,6 @@ import { useCallback, useState } from "react";
2
2
  import {} from "viem";
3
3
  import { swapActions } from "@account-kit/wallet-client/experimental";
4
4
  import { useAlchemyClient } from "./useAlchemyClient.js";
5
- import { useEmbeddedWallet } from "./internal/useEmbeddedWallet.js";
6
5
  /**
7
6
  * Hook to request swap quotes and prepare swap calls
8
7
  * Part of the two-step swap process: prepare → submit
@@ -45,7 +44,6 @@ import { useEmbeddedWallet } from "./internal/useEmbeddedWallet.js";
45
44
  */
46
45
  export function useAlchemyPrepareSwap() {
47
46
  const { getClient } = useAlchemyClient();
48
- const getEmbeddedWallet = useEmbeddedWallet();
49
47
  const [isLoading, setIsLoading] = useState(false);
50
48
  const [error, setError] = useState(null);
51
49
  const [data, setData] = useState(null);
@@ -53,15 +51,14 @@ export function useAlchemyPrepareSwap() {
53
51
  setIsLoading(true);
54
52
  setError(null);
55
53
  try {
56
- const client = await getClient();
57
- const embeddedWallet = getEmbeddedWallet();
54
+ const { client, account } = await getClient();
58
55
  // Extend client with swap actions
59
56
  const swapClient = client.extend(swapActions);
60
57
  // Request the swap quote
61
58
  // Note: Gas sponsorship capabilities are configured on the client itself
62
59
  const response = await swapClient.requestQuoteV0({
63
60
  ...request,
64
- from: request.from || embeddedWallet.address,
61
+ from: request.from || account.address,
65
62
  });
66
63
  // Validate that we got prepared calls, not raw calls
67
64
  if (response.rawCalls) {
@@ -78,7 +75,7 @@ export function useAlchemyPrepareSwap() {
78
75
  finally {
79
76
  setIsLoading(false);
80
77
  }
81
- }, [getClient, getEmbeddedWallet]);
78
+ }, [getClient]);
82
79
  const reset = useCallback(() => {
83
80
  setError(null);
84
81
  setData(null);
@@ -1 +1 @@
1
- {"version":3,"file":"useAlchemyPrepareSwap.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemyPrepareSwap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAgB,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAOpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,EAAE,SAAS,EAAE,GAAG,gBAAgB,EAAE,CAAC;IACzC,MAAM,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;IAE9C,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IACvD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAA2B,IAAI,CAAC,CAAC;IAEjE,MAAM,WAAW,GAAG,WAAW,CAC7B,KAAK,EAAE,OAA2B,EAA8B,EAAE;QAChE,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;YACjC,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;YAE3C,kCAAkC;YAClC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAE9C,yBAAyB;YACzB,yEAAyE;YACzE,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,cAAc,CAAC;gBAC/C,GAAG,OAAO;gBACV,IAAI,EAAE,OAAO,CAAC,IAAI,IAAK,cAAc,CAAC,OAAmB;aAC1D,CAAC,CAAC;YAEH,qDAAqD;YACrD,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CACb,yFAAyF,CAC1F,CAAC;YACJ,CAAC;YAED,OAAO,CAAC,QAAQ,CAAC,CAAC;YAClB,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,GACZ,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YACnE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnB,MAAM,QAAQ,CAAC;QACjB,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,EACD,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAC/B,CAAC;IAEF,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,CAAC;QACd,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO;QACL,WAAW;QACX,SAAS;QACT,KAAK;QACL,IAAI;QACJ,KAAK;KACN,CAAC;AACJ,CAAC","sourcesContent":["import { useCallback, useState } from \"react\";\nimport { type Address } from \"viem\";\nimport { swapActions } from \"@account-kit/wallet-client/experimental\";\nimport { useAlchemyClient } from \"./useAlchemyClient.js\";\nimport { useEmbeddedWallet } from \"./internal/useEmbeddedWallet.js\";\nimport type {\n PrepareSwapRequest,\n PrepareSwapResult,\n UsePrepareSwapResult,\n} from \"../types\";\n\n/**\n * Hook to request swap quotes and prepare swap calls\n * Part of the two-step swap process: prepare → submit\n * Use with `useAlchemySubmitSwap()` to execute the prepared swap\n *\n * Supports two modes:\n * 1. Specify exact amount to swap FROM (`fromAmount`)\n * 2. Specify minimum amount to receive TO (`minimumToAmount`)\n *\n * @returns {UsePrepareSwapResult} Hook result with prepareSwap function and state\n *\n * @example Complete swap flow\n * ```tsx\n * const { prepareSwap } = useAlchemyPrepareSwap();\n * const { submitSwap } = useAlchemySubmitSwap();\n *\n * // Step 1: Prepare the swap (get quote)\n * const preparedSwap = await prepareSwap({\n * fromToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',\n * toToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n * fromAmount: '0xde0b6b3a7640000', // 1 ETH in hex\n * });\n *\n * // Step 2: Execute the swap\n * const result = await submitSwap(preparedSwap);\n * ```\n *\n * @example Swap for minimum amount TO\n * ```tsx\n * const { prepareSwap } = useAlchemyPrepareSwap();\n *\n * // Swap ETH to get at least 100 USDC\n * const result = await prepareSwap({\n * fromToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',\n * toToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n * minimumToAmount: '0x5f5e100', // 100 USDC (6 decimals) in hex\n * });\n * console.log('Quote expiry:', new Date(parseInt(result.quote.expiry, 16) * 1000));\n * ```\n */\nexport function useAlchemyPrepareSwap(): UsePrepareSwapResult {\n const { getClient } = useAlchemyClient();\n const getEmbeddedWallet = useEmbeddedWallet();\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<PrepareSwapResult | null>(null);\n\n const prepareSwap = useCallback(\n async (request: PrepareSwapRequest): Promise<PrepareSwapResult> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const client = await getClient();\n const embeddedWallet = getEmbeddedWallet();\n\n // Extend client with swap actions\n const swapClient = client.extend(swapActions);\n\n // Request the swap quote\n // Note: Gas sponsorship capabilities are configured on the client itself\n const response = await swapClient.requestQuoteV0({\n ...request,\n from: request.from || (embeddedWallet.address as Address),\n });\n\n // Validate that we got prepared calls, not raw calls\n if (response.rawCalls) {\n throw new Error(\n \"Received raw calls instead of prepared calls. Ensure returnRawCalls is not set to true.\",\n );\n }\n\n setData(response);\n return response;\n } catch (err) {\n const errorObj =\n err instanceof Error ? err : new Error(\"Failed to prepare swap\");\n setError(errorObj);\n throw errorObj;\n } finally {\n setIsLoading(false);\n }\n },\n [getClient, getEmbeddedWallet],\n );\n\n const reset = useCallback(() => {\n setError(null);\n setData(null);\n setIsLoading(false);\n }, []);\n\n return {\n prepareSwap,\n isLoading,\n error,\n data,\n reset,\n };\n}\n"]}
1
+ {"version":3,"file":"useAlchemyPrepareSwap.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemyPrepareSwap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAgB,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAOzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,EAAE,SAAS,EAAE,GAAG,gBAAgB,EAAE,CAAC;IAEzC,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IACvD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAA2B,IAAI,CAAC,CAAC;IAEjE,MAAM,WAAW,GAAG,WAAW,CAC7B,KAAK,EAAE,OAA2B,EAA8B,EAAE;QAChE,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEf,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,SAAS,EAAE,CAAC;YAE9C,kCAAkC;YAClC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAE9C,yBAAyB;YACzB,yEAAyE;YACzE,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,cAAc,CAAC;gBAC/C,GAAG,OAAO;gBACV,IAAI,EAAE,OAAO,CAAC,IAAI,IAAK,OAAO,CAAC,OAAmB;aACnD,CAAC,CAAC;YAEH,qDAAqD;YACrD,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CACb,yFAAyF,CAC1F,CAAC;YACJ,CAAC;YAED,OAAO,CAAC,QAAQ,CAAC,CAAC;YAClB,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,GACZ,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YACnE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnB,MAAM,QAAQ,CAAC;QACjB,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,EACD,CAAC,SAAS,CAAC,CACZ,CAAC;IAEF,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,CAAC;QACd,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO;QACL,WAAW;QACX,SAAS;QACT,KAAK;QACL,IAAI;QACJ,KAAK;KACN,CAAC;AACJ,CAAC","sourcesContent":["import { useCallback, useState } from \"react\";\nimport { type Address } from \"viem\";\nimport { swapActions } from \"@account-kit/wallet-client/experimental\";\nimport { useAlchemyClient } from \"./useAlchemyClient.js\";\nimport type {\n PrepareSwapRequest,\n PrepareSwapResult,\n UsePrepareSwapResult,\n} from \"../types\";\n\n/**\n * Hook to request swap quotes and prepare swap calls\n * Part of the two-step swap process: prepare → submit\n * Use with `useAlchemySubmitSwap()` to execute the prepared swap\n *\n * Supports two modes:\n * 1. Specify exact amount to swap FROM (`fromAmount`)\n * 2. Specify minimum amount to receive TO (`minimumToAmount`)\n *\n * @returns {UsePrepareSwapResult} Hook result with prepareSwap function and state\n *\n * @example Complete swap flow\n * ```tsx\n * const { prepareSwap } = useAlchemyPrepareSwap();\n * const { submitSwap } = useAlchemySubmitSwap();\n *\n * // Step 1: Prepare the swap (get quote)\n * const preparedSwap = await prepareSwap({\n * fromToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',\n * toToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n * fromAmount: '0xde0b6b3a7640000', // 1 ETH in hex\n * });\n *\n * // Step 2: Execute the swap\n * const result = await submitSwap(preparedSwap);\n * ```\n *\n * @example Swap for minimum amount TO\n * ```tsx\n * const { prepareSwap } = useAlchemyPrepareSwap();\n *\n * // Swap ETH to get at least 100 USDC\n * const result = await prepareSwap({\n * fromToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',\n * toToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n * minimumToAmount: '0x5f5e100', // 100 USDC (6 decimals) in hex\n * });\n * console.log('Quote expiry:', new Date(parseInt(result.quote.expiry, 16) * 1000));\n * ```\n */\nexport function useAlchemyPrepareSwap(): UsePrepareSwapResult {\n const { getClient } = useAlchemyClient();\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<PrepareSwapResult | null>(null);\n\n const prepareSwap = useCallback(\n async (request: PrepareSwapRequest): Promise<PrepareSwapResult> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const { client, account } = await getClient();\n\n // Extend client with swap actions\n const swapClient = client.extend(swapActions);\n\n // Request the swap quote\n // Note: Gas sponsorship capabilities are configured on the client itself\n const response = await swapClient.requestQuoteV0({\n ...request,\n from: request.from || (account.address as Address),\n });\n\n // Validate that we got prepared calls, not raw calls\n if (response.rawCalls) {\n throw new Error(\n \"Received raw calls instead of prepared calls. Ensure returnRawCalls is not set to true.\",\n );\n }\n\n setData(response);\n return response;\n } catch (err) {\n const errorObj =\n err instanceof Error ? err : new Error(\"Failed to prepare swap\");\n setError(errorObj);\n throw errorObj;\n } finally {\n setIsLoading(false);\n }\n },\n [getClient],\n );\n\n const reset = useCallback(() => {\n setError(null);\n setData(null);\n setIsLoading(false);\n }, []);\n\n return {\n prepareSwap,\n isLoading,\n error,\n data,\n reset,\n };\n}\n"]}
@@ -2,7 +2,6 @@ import { useCallback, useState } from "react";
2
2
  import { isHex } from "viem";
3
3
  import { useAlchemyClient } from "./useAlchemyClient.js";
4
4
  import { useAlchemyConfig } from "../Provider.js";
5
- import { useEmbeddedWallet } from "./internal/useEmbeddedWallet.js";
6
5
  /**
7
6
  * Normalize value to hex format
8
7
  * Accepts bigint, number, decimal string, or hex string
@@ -61,7 +60,6 @@ function normalizeValue(value) {
61
60
  export function useAlchemySendTransaction() {
62
61
  const { getClient } = useAlchemyClient();
63
62
  const config = useAlchemyConfig();
64
- const getEmbeddedWallet = useEmbeddedWallet();
65
63
  const [isLoading, setIsLoading] = useState(false);
66
64
  const [error, setError] = useState(null);
67
65
  const [data, setData] = useState(null);
@@ -69,8 +67,7 @@ export function useAlchemySendTransaction() {
69
67
  setIsLoading(true);
70
68
  setError(null);
71
69
  try {
72
- const client = await getClient();
73
- const embeddedWallet = getEmbeddedWallet();
70
+ const { client, account } = await getClient();
74
71
  // Determine if transaction should be sponsored
75
72
  const hasPolicyId = !!config.policyId;
76
73
  const enableSponsorship = !config.disableSponsorship;
@@ -84,17 +81,17 @@ export function useAlchemySendTransaction() {
84
81
  data: txn.data,
85
82
  value: txn.value ? normalizeValue(txn.value) : undefined,
86
83
  }));
87
- // Build capabilities based on sponsorship
84
+ // Build capabilities based on sponsorship and auth mode
88
85
  const policyId = Array.isArray(config.policyId)
89
86
  ? config.policyId[0]
90
87
  : config.policyId;
91
- const capabilities = { eip7702Auth: true };
88
+ const capabilities = config.accountAuthMode === "eip7702" ? { eip7702Auth: true } : {};
92
89
  if (shouldSponsor && policyId) {
93
90
  capabilities.paymasterService = { policyId };
94
91
  }
95
- // Send the transaction(s)
92
+ // Send the transaction(s) from the smart account address
96
93
  const result = await client.sendCalls({
97
- from: embeddedWallet.address,
94
+ from: account.address,
98
95
  calls: formattedCalls,
99
96
  capabilities,
100
97
  });
@@ -122,7 +119,12 @@ export function useAlchemySendTransaction() {
122
119
  finally {
123
120
  setIsLoading(false);
124
121
  }
125
- }, [getClient, getEmbeddedWallet, config.policyId, config.disableSponsorship]);
122
+ }, [
123
+ getClient,
124
+ config.policyId,
125
+ config.disableSponsorship,
126
+ config.accountAuthMode,
127
+ ]);
126
128
  const reset = useCallback(() => {
127
129
  setError(null);
128
130
  setData(null);
@@ -1 +1 @@
1
- {"version":3,"file":"useAlchemySendTransaction.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemySendTransaction.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useState } from \"react\";\nimport { type Address, type Hex, isHex } from \"viem\";\nimport { useAlchemyClient } from \"./useAlchemyClient.js\";\nimport { useAlchemyConfig } from \"../Provider.js\";\nimport { useEmbeddedWallet } from \"./internal/useEmbeddedWallet.js\";\nimport type {\n UnsignedTransactionRequest,\n SendTransactionOptions,\n SendTransactionResult,\n UseSendTransactionResult,\n} from \"../types\";\n\n/**\n * Normalize value to hex format\n * Accepts bigint, number, decimal string, or hex string\n *\n * @param {string | number | bigint} value - Value to normalize\n * @returns {Hex} Hex string representation of the value\n */\nfunction normalizeValue(value: string | number | bigint): Hex {\n if (typeof value === \"bigint\") {\n return `0x${value.toString(16)}`;\n }\n if (typeof value === \"number\") {\n return `0x${BigInt(value).toString(16)}`;\n }\n if (isHex(value)) {\n return value;\n }\n // Assume decimal string\n return `0x${BigInt(value).toString(16)}`;\n}\n\n/**\n * Hook to send transactions with optional gas sponsorship via Alchemy\n * Supports both single transactions and batch transactions\n * Drop-in alternative to Privy's useSendTransaction hook\n *\n * @returns {UseSendTransactionResult} Hook result with sendTransaction function and state\n *\n * @example Single transaction\n * ```tsx\n * const { sendTransaction, isLoading, error, data } = useAlchemySendTransaction();\n *\n * const handleSend = async () => {\n * try {\n * const result = await sendTransaction({\n * to: '0x...',\n * data: '0x...',\n * value: '1000000000000000000', // 1 ETH\n * });\n * console.log('Transaction hash:', result.txnHash);\n * } catch (err) {\n * console.error('Transaction failed:', err);\n * }\n * };\n * ```\n *\n * @example Batch transactions\n * ```tsx\n * const { sendTransaction } = useAlchemySendTransaction();\n *\n * const result = await sendTransaction([\n * { to: '0x...', data: '0x...', value: '1000000000000000000' },\n * { to: '0x...', data: '0x...' },\n * ]);\n * ```\n */\nexport function useAlchemySendTransaction(): UseSendTransactionResult {\n const { getClient } = useAlchemyClient();\n const config = useAlchemyConfig();\n const getEmbeddedWallet = useEmbeddedWallet();\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<SendTransactionResult | null>(null);\n\n const sendTransaction = useCallback(\n async (\n input: UnsignedTransactionRequest | UnsignedTransactionRequest[],\n options?: SendTransactionOptions,\n ): Promise<SendTransactionResult> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const client = await getClient();\n const embeddedWallet = getEmbeddedWallet();\n\n // Determine if transaction should be sponsored\n const hasPolicyId = !!config.policyId;\n const enableSponsorship = !config.disableSponsorship;\n const shouldSponsor =\n options?.disableSponsorship !== undefined\n ? !options.disableSponsorship\n : hasPolicyId && enableSponsorship;\n\n // Format the transaction call(s)\n const inputs = Array.isArray(input) ? input : [input];\n const formattedCalls = inputs.map((txn) => ({\n to: txn.to,\n data: txn.data,\n value: txn.value ? normalizeValue(txn.value) : undefined,\n }));\n\n // Build capabilities based on sponsorship\n const policyId = Array.isArray(config.policyId)\n ? config.policyId[0]\n : config.policyId;\n\n const capabilities: {\n eip7702Auth: true;\n paymasterService?: { policyId: string };\n } = { eip7702Auth: true };\n\n if (shouldSponsor && policyId) {\n capabilities.paymasterService = { policyId };\n }\n\n // Send the transaction(s)\n const result = await client.sendCalls({\n from: embeddedWallet.address as Address,\n calls: formattedCalls,\n capabilities,\n });\n\n if (!result.preparedCallIds || result.preparedCallIds.length === 0) {\n throw new Error(\n \"No prepared call IDs returned from transaction submission\",\n );\n }\n\n // Wait for the transaction to be confirmed\n const txStatus = await client.waitForCallsStatus({\n id: result.preparedCallIds[0],\n timeout: 60_000,\n });\n\n const txnHash = txStatus.receipts?.[0]?.transactionHash;\n if (!txnHash) {\n throw new Error(\"Transaction hash not found in receipt\");\n }\n\n const txResult: SendTransactionResult = { txnHash };\n setData(txResult);\n return txResult;\n } catch (err) {\n const errorObj =\n err instanceof Error ? err : new Error(\"Transaction failed\");\n setError(errorObj);\n throw errorObj;\n } finally {\n setIsLoading(false);\n }\n },\n [getClient, getEmbeddedWallet, config.policyId, config.disableSponsorship],\n );\n\n const reset = useCallback(() => {\n setError(null);\n setData(null);\n setIsLoading(false);\n }, []);\n\n return {\n sendTransaction,\n isLoading,\n error,\n data,\n reset,\n };\n}\n"]}
1
+ {"version":3,"file":"useAlchemySendTransaction.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemySendTransaction.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useState } from \"react\";\nimport { type Hex, isHex } from \"viem\";\nimport { useAlchemyClient } from \"./useAlchemyClient.js\";\nimport { useAlchemyConfig } from \"../Provider.js\";\nimport type {\n UnsignedTransactionRequest,\n SendTransactionOptions,\n SendTransactionResult,\n UseSendTransactionResult,\n} from \"../types\";\n\n/**\n * Normalize value to hex format\n * Accepts bigint, number, decimal string, or hex string\n *\n * @param {string | number | bigint} value - Value to normalize\n * @returns {Hex} Hex string representation of the value\n */\nfunction normalizeValue(value: string | number | bigint): Hex {\n if (typeof value === \"bigint\") {\n return `0x${value.toString(16)}`;\n }\n if (typeof value === \"number\") {\n return `0x${BigInt(value).toString(16)}`;\n }\n if (isHex(value)) {\n return value;\n }\n // Assume decimal string\n return `0x${BigInt(value).toString(16)}`;\n}\n\n/**\n * Hook to send transactions with optional gas sponsorship via Alchemy\n * Supports both single transactions and batch transactions\n * Drop-in alternative to Privy's useSendTransaction hook\n *\n * @returns {UseSendTransactionResult} Hook result with sendTransaction function and state\n *\n * @example Single transaction\n * ```tsx\n * const { sendTransaction, isLoading, error, data } = useAlchemySendTransaction();\n *\n * const handleSend = async () => {\n * try {\n * const result = await sendTransaction({\n * to: '0x...',\n * data: '0x...',\n * value: '1000000000000000000', // 1 ETH\n * });\n * console.log('Transaction hash:', result.txnHash);\n * } catch (err) {\n * console.error('Transaction failed:', err);\n * }\n * };\n * ```\n *\n * @example Batch transactions\n * ```tsx\n * const { sendTransaction } = useAlchemySendTransaction();\n *\n * const result = await sendTransaction([\n * { to: '0x...', data: '0x...', value: '1000000000000000000' },\n * { to: '0x...', data: '0x...' },\n * ]);\n * ```\n */\nexport function useAlchemySendTransaction(): UseSendTransactionResult {\n const { getClient } = useAlchemyClient();\n const config = useAlchemyConfig();\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<SendTransactionResult | null>(null);\n\n const sendTransaction = useCallback(\n async (\n input: UnsignedTransactionRequest | UnsignedTransactionRequest[],\n options?: SendTransactionOptions,\n ): Promise<SendTransactionResult> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const { client, account } = await getClient();\n\n // Determine if transaction should be sponsored\n const hasPolicyId = !!config.policyId;\n const enableSponsorship = !config.disableSponsorship;\n const shouldSponsor =\n options?.disableSponsorship !== undefined\n ? !options.disableSponsorship\n : hasPolicyId && enableSponsorship;\n\n // Format the transaction call(s)\n const inputs = Array.isArray(input) ? input : [input];\n const formattedCalls = inputs.map((txn) => ({\n to: txn.to,\n data: txn.data,\n value: txn.value ? normalizeValue(txn.value) : undefined,\n }));\n\n // Build capabilities based on sponsorship and auth mode\n const policyId = Array.isArray(config.policyId)\n ? config.policyId[0]\n : config.policyId;\n\n type Capabilities =\n | { eip7702Auth: true; paymasterService?: { policyId: string } }\n | { paymasterService?: { policyId: string } };\n const capabilities: Capabilities =\n config.accountAuthMode === \"eip7702\" ? { eip7702Auth: true } : {};\n\n if (shouldSponsor && policyId) {\n capabilities.paymasterService = { policyId };\n }\n\n // Send the transaction(s) from the smart account address\n const result = await client.sendCalls({\n from: account.address,\n calls: formattedCalls,\n capabilities,\n });\n\n if (!result.preparedCallIds || result.preparedCallIds.length === 0) {\n throw new Error(\n \"No prepared call IDs returned from transaction submission\",\n );\n }\n\n // Wait for the transaction to be confirmed\n const txStatus = await client.waitForCallsStatus({\n id: result.preparedCallIds[0],\n timeout: 60_000,\n });\n\n const txnHash = txStatus.receipts?.[0]?.transactionHash;\n if (!txnHash) {\n throw new Error(\"Transaction hash not found in receipt\");\n }\n\n const txResult: SendTransactionResult = { txnHash };\n setData(txResult);\n return txResult;\n } catch (err) {\n const errorObj =\n err instanceof Error ? err : new Error(\"Transaction failed\");\n setError(errorObj);\n throw errorObj;\n } finally {\n setIsLoading(false);\n }\n },\n [\n getClient,\n config.policyId,\n config.disableSponsorship,\n config.accountAuthMode,\n ],\n );\n\n const reset = useCallback(() => {\n setError(null);\n setData(null);\n setIsLoading(false);\n }, []);\n\n return {\n sendTransaction,\n isLoading,\n error,\n data,\n reset,\n };\n}\n"]}
@@ -39,7 +39,7 @@ export function useAlchemySubmitSwap() {
39
39
  setIsLoading(true);
40
40
  setError(null);
41
41
  try {
42
- const client = await getClient();
42
+ const { client } = await getClient();
43
43
  // Extend client with swap actions
44
44
  const swapClient = client.extend(swapActions);
45
45
  // Sign the prepared calls
@@ -1 +1 @@
1
- {"version":3,"file":"useAlchemySubmitSwap.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemySubmitSwap.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useState } from \"react\";\nimport { swapActions } from \"@account-kit/wallet-client/experimental\";\nimport { useAlchemyClient } from \"./useAlchemyClient.js\";\nimport type {\n PrepareSwapResult,\n SubmitSwapResult,\n UseSubmitSwapResult,\n} from \"../types.js\";\n\n/**\n * Hook to sign and submit prepared swap calls\n * Part of the two-step swap process: prepare → submit\n *\n * @returns {UseSubmitSwapResult} Hook result with submitSwap function and state\n *\n * @example\n * ```tsx\n * const { prepareSwap } = useAlchemyPrepareSwap();\n * const { submitSwap, isLoading, error, data } = useAlchemySubmitSwap();\n *\n * const handleSwap = async () => {\n * try {\n * // Step 1: Prepare the swap\n * const preparedSwap = await prepareSwap({\n * fromToken: '0x...',\n * toToken: '0x...',\n * fromAmount: '0x...',\n * });\n *\n * // Step 2: Submit the swap\n * const result = await submitSwap(preparedSwap);\n * console.log('Swap confirmed:', result.txnHash);\n * } catch (err) {\n * console.error('Swap failed:', err);\n * }\n * };\n * ```\n */\nexport function useAlchemySubmitSwap(): UseSubmitSwapResult {\n const { getClient } = useAlchemyClient();\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<SubmitSwapResult | null>(null);\n\n const submitSwap = useCallback(\n async (preparedSwap: PrepareSwapResult): Promise<SubmitSwapResult> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const client = await getClient();\n\n // Extend client with swap actions\n const swapClient = client.extend(swapActions);\n\n // Sign the prepared calls\n const signedCalls = await swapClient.signPreparedCalls(preparedSwap);\n\n // Send the signed calls\n const { preparedCallIds } =\n await swapClient.sendPreparedCalls(signedCalls);\n\n if (!preparedCallIds || preparedCallIds.length === 0) {\n throw new Error(\"No prepared call IDs returned from swap submission\");\n }\n\n // Wait for the swap to be confirmed\n const callStatusResult = await swapClient.waitForCallsStatus({\n id: preparedCallIds[0],\n timeout: 60_000,\n });\n\n // Validate the transaction was successful\n if (\n callStatusResult.status !== \"success\" ||\n !callStatusResult.receipts ||\n !callStatusResult.receipts[0]\n ) {\n throw new Error(\n `Swap failed with status ${\n callStatusResult.status\n }. Full receipt:\\n${JSON.stringify(callStatusResult, null, 2)}`,\n );\n }\n\n const txnHash = callStatusResult.receipts[0].transactionHash;\n if (!txnHash) {\n throw new Error(\"Transaction hash not found in receipt\");\n }\n\n const result: SubmitSwapResult = { txnHash };\n setData(result);\n return result;\n } catch (err) {\n const errorObj =\n err instanceof Error ? err : new Error(\"Failed to submit swap\");\n setError(errorObj);\n throw errorObj;\n } finally {\n setIsLoading(false);\n }\n },\n [getClient],\n );\n\n const reset = useCallback(() => {\n setError(null);\n setData(null);\n setIsLoading(false);\n }, []);\n\n return {\n submitSwap,\n isLoading,\n error,\n data,\n reset,\n };\n}\n"]}
1
+ {"version":3,"file":"useAlchemySubmitSwap.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemySubmitSwap.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useState } from \"react\";\nimport { swapActions } from \"@account-kit/wallet-client/experimental\";\nimport { useAlchemyClient } from \"./useAlchemyClient.js\";\nimport type {\n PrepareSwapResult,\n SubmitSwapResult,\n UseSubmitSwapResult,\n} from \"../types.js\";\n\n/**\n * Hook to sign and submit prepared swap calls\n * Part of the two-step swap process: prepare → submit\n *\n * @returns {UseSubmitSwapResult} Hook result with submitSwap function and state\n *\n * @example\n * ```tsx\n * const { prepareSwap } = useAlchemyPrepareSwap();\n * const { submitSwap, isLoading, error, data } = useAlchemySubmitSwap();\n *\n * const handleSwap = async () => {\n * try {\n * // Step 1: Prepare the swap\n * const preparedSwap = await prepareSwap({\n * fromToken: '0x...',\n * toToken: '0x...',\n * fromAmount: '0x...',\n * });\n *\n * // Step 2: Submit the swap\n * const result = await submitSwap(preparedSwap);\n * console.log('Swap confirmed:', result.txnHash);\n * } catch (err) {\n * console.error('Swap failed:', err);\n * }\n * };\n * ```\n */\nexport function useAlchemySubmitSwap(): UseSubmitSwapResult {\n const { getClient } = useAlchemyClient();\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<SubmitSwapResult | null>(null);\n\n const submitSwap = useCallback(\n async (preparedSwap: PrepareSwapResult): Promise<SubmitSwapResult> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const { client } = await getClient();\n\n // Extend client with swap actions\n const swapClient = client.extend(swapActions);\n\n // Sign the prepared calls\n const signedCalls = await swapClient.signPreparedCalls(preparedSwap);\n\n // Send the signed calls\n const { preparedCallIds } =\n await swapClient.sendPreparedCalls(signedCalls);\n\n if (!preparedCallIds || preparedCallIds.length === 0) {\n throw new Error(\"No prepared call IDs returned from swap submission\");\n }\n\n // Wait for the swap to be confirmed\n const callStatusResult = await swapClient.waitForCallsStatus({\n id: preparedCallIds[0],\n timeout: 60_000,\n });\n\n // Validate the transaction was successful\n if (\n callStatusResult.status !== \"success\" ||\n !callStatusResult.receipts ||\n !callStatusResult.receipts[0]\n ) {\n throw new Error(\n `Swap failed with status ${\n callStatusResult.status\n }. Full receipt:\\n${JSON.stringify(callStatusResult, null, 2)}`,\n );\n }\n\n const txnHash = callStatusResult.receipts[0].transactionHash;\n if (!txnHash) {\n throw new Error(\"Transaction hash not found in receipt\");\n }\n\n const result: SubmitSwapResult = { txnHash };\n setData(result);\n return result;\n } catch (err) {\n const errorObj =\n err instanceof Error ? err : new Error(\"Failed to submit swap\");\n setError(errorObj);\n throw errorObj;\n } finally {\n setIsLoading(false);\n }\n },\n [getClient],\n );\n\n const reset = useCallback(() => {\n setError(null);\n setData(null);\n setIsLoading(false);\n }, []);\n\n return {\n submitSwap,\n isLoading,\n error,\n data,\n reset,\n };\n}\n"]}
@@ -13,6 +13,12 @@ export type AlchemyProviderConfig = z.infer<typeof ConnectionConfigSchema> & {
13
13
  solanaPolicyId?: string | string[];
14
14
  /** Solana RPC URL (separate from EVM rpcUrl) */
15
15
  solanaRpcUrl?: string;
16
+ /**
17
+ * How EVM smart account calls should be authorized.
18
+ * - 'eip7702' (default): delegated authorization via EIP-7702.
19
+ * - 'owner': sign as the account owner (Privy embedded wallet), no 7702.
20
+ */
21
+ accountAuthMode?: "eip7702" | "owner";
16
22
  /**
17
23
  * Set to true to disable gas sponsorship by default
18
24
  * Default: false (sponsorship enabled when policyId is provided)
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC","sourcesContent":["import type { Address, Hash, Hex } from \"viem\";\nimport type { swapActions } from \"@account-kit/wallet-client/experimental\";\nimport { ConnectionConfigSchema } from \"@aa-sdk/core\";\nimport type { z } from \"zod\";\n\n/**\n * Configuration for the Alchemy provider\n * Uses ConnectionConfigSchema to ensure valid transport configuration\n */\nexport type AlchemyProviderConfig = z.infer<typeof ConnectionConfigSchema> & {\n /** Policy ID(s) for EVM gas sponsorship */\n policyId?: string | string[];\n\n /** Policy ID(s) for Solana gas sponsorship */\n solanaPolicyId?: string | string[];\n\n /** Solana RPC URL (separate from EVM rpcUrl) */\n solanaRpcUrl?: string;\n\n /**\n * Set to true to disable gas sponsorship by default\n * Default: false (sponsorship enabled when policyId is provided)\n */\n disableSponsorship?: boolean;\n};\n\n/**\n * Unsigned transaction request\n */\nexport interface UnsignedTransactionRequest {\n /** Recipient address */\n to: Address;\n\n /** Transaction data (calldata) */\n data?: Hex;\n\n /** Transaction value - accepts string | number | bigint */\n value?: string | number | bigint;\n}\n\n/**\n * Options for sending a transaction\n */\nexport interface SendTransactionOptions {\n /**\n * Set to true to disable sponsorship for this specific transaction\n * Default: false (follows provider's disableSponsorship setting)\n */\n disableSponsorship?: boolean;\n}\n\n/**\n * Result of a successful transaction\n */\nexport interface SendTransactionResult {\n /** EVM transaction hash (first receipt hash) */\n txnHash: Hash;\n}\n\n/**\n * Hook result for sending transactions\n */\nexport interface UseSendTransactionResult {\n /** Whether the transaction is currently being sent */\n isLoading: boolean;\n\n /** Error if transaction failed */\n error: Error | null;\n\n /** Transaction result if successful */\n data: SendTransactionResult | null;\n\n /** Reset the hook state */\n reset(): void;\n\n /** Send a single transaction or batch of transactions */\n sendTransaction(\n input: UnsignedTransactionRequest | UnsignedTransactionRequest[],\n options?: SendTransactionOptions,\n ): Promise<SendTransactionResult>;\n}\n\n/**\n * Request parameters for preparing a swap\n * Derived directly from the SDK to ensure type safety\n *\n * Note: Provide either `fromAmount` OR `minimumToAmount`, not both.\n * - Use `fromAmount` to specify exact amount to swap FROM\n * - Use `minimumToAmount` to specify minimum amount to receive TO\n */\nexport type PrepareSwapRequest = Parameters<\n ReturnType<typeof swapActions>[\"requestQuoteV0\"]\n>[0];\n\n/**\n * Response from requestQuoteV0\n * Derived directly from the SDK to ensure type safety\n */\nexport type RequestQuoteV0Result = Awaited<\n ReturnType<ReturnType<typeof swapActions>[\"requestQuoteV0\"]>\n>;\n\n/**\n * Swap quote information extracted from prepared swap calls\n * Derived directly from the SDK response\n */\nexport type SwapQuote = NonNullable<RequestQuoteV0Result[\"quote\"]>;\n\n/**\n * Result of preparing a swap (full response from requestQuoteV0)\n * Contains quote and prepared calls ready for signing\n */\nexport type PrepareSwapResult = Extract<\n RequestQuoteV0Result,\n { rawCalls?: false | undefined }\n>;\n\n/**\n * Hook result for preparing swaps\n */\nexport interface UsePrepareSwapResult {\n /** Whether the swap is being prepared */\n isLoading: boolean;\n\n /** Error if preparation failed */\n error: Error | null;\n\n /** Prepared swap data if successful */\n data: PrepareSwapResult | null;\n\n /** Reset the hook state */\n reset(): void;\n\n /** Request a swap quote and prepare calls */\n prepareSwap(request: PrepareSwapRequest): Promise<PrepareSwapResult>;\n}\n\n/**\n * Result of submitting a swap\n * Simplified wrapper that extracts the transaction hash\n */\nexport interface SubmitSwapResult {\n /** Transaction hash of the swap */\n txnHash: Hash;\n}\n\n/**\n * Hook result for submitting swaps\n */\nexport interface UseSubmitSwapResult {\n /** Whether the swap is being submitted */\n isLoading: boolean;\n\n /** Error if submission failed */\n error: Error | null;\n\n /** Swap submission result if successful */\n data: SubmitSwapResult | null;\n\n /** Reset the hook state */\n reset(): void;\n\n /** Sign and submit prepared swap calls */\n submitSwap(preparedSwap: PrepareSwapResult): Promise<SubmitSwapResult>;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC","sourcesContent":["import type { Address, Hash, Hex } from \"viem\";\nimport type { swapActions } from \"@account-kit/wallet-client/experimental\";\nimport { ConnectionConfigSchema } from \"@aa-sdk/core\";\nimport type { z } from \"zod\";\n\n/**\n * Configuration for the Alchemy provider\n * Uses ConnectionConfigSchema to ensure valid transport configuration\n */\nexport type AlchemyProviderConfig = z.infer<typeof ConnectionConfigSchema> & {\n /** Policy ID(s) for EVM gas sponsorship */\n policyId?: string | string[];\n\n /** Policy ID(s) for Solana gas sponsorship */\n solanaPolicyId?: string | string[];\n\n /** Solana RPC URL (separate from EVM rpcUrl) */\n solanaRpcUrl?: string;\n\n /**\n * How EVM smart account calls should be authorized.\n * - 'eip7702' (default): delegated authorization via EIP-7702.\n * - 'owner': sign as the account owner (Privy embedded wallet), no 7702.\n */\n accountAuthMode?: \"eip7702\" | \"owner\";\n\n /**\n * Set to true to disable gas sponsorship by default\n * Default: false (sponsorship enabled when policyId is provided)\n */\n disableSponsorship?: boolean;\n};\n\n/**\n * Unsigned transaction request\n */\nexport interface UnsignedTransactionRequest {\n /** Recipient address */\n to: Address;\n\n /** Transaction data (calldata) */\n data?: Hex;\n\n /** Transaction value - accepts string | number | bigint */\n value?: string | number | bigint;\n}\n\n/**\n * Options for sending a transaction\n */\nexport interface SendTransactionOptions {\n /**\n * Set to true to disable sponsorship for this specific transaction\n * Default: false (follows provider's disableSponsorship setting)\n */\n disableSponsorship?: boolean;\n}\n\n/**\n * Result of a successful transaction\n */\nexport interface SendTransactionResult {\n /** EVM transaction hash (first receipt hash) */\n txnHash: Hash;\n}\n\n/**\n * Hook result for sending transactions\n */\nexport interface UseSendTransactionResult {\n /** Whether the transaction is currently being sent */\n isLoading: boolean;\n\n /** Error if transaction failed */\n error: Error | null;\n\n /** Transaction result if successful */\n data: SendTransactionResult | null;\n\n /** Reset the hook state */\n reset(): void;\n\n /** Send a single transaction or batch of transactions */\n sendTransaction(\n input: UnsignedTransactionRequest | UnsignedTransactionRequest[],\n options?: SendTransactionOptions,\n ): Promise<SendTransactionResult>;\n}\n\n/**\n * Request parameters for preparing a swap\n * Derived directly from the SDK to ensure type safety\n *\n * Note: Provide either `fromAmount` OR `minimumToAmount`, not both.\n * - Use `fromAmount` to specify exact amount to swap FROM\n * - Use `minimumToAmount` to specify minimum amount to receive TO\n */\nexport type PrepareSwapRequest = Parameters<\n ReturnType<typeof swapActions>[\"requestQuoteV0\"]\n>[0];\n\n/**\n * Response from requestQuoteV0\n * Derived directly from the SDK to ensure type safety\n */\nexport type RequestQuoteV0Result = Awaited<\n ReturnType<ReturnType<typeof swapActions>[\"requestQuoteV0\"]>\n>;\n\n/**\n * Swap quote information extracted from prepared swap calls\n * Derived directly from the SDK response\n */\nexport type SwapQuote = NonNullable<RequestQuoteV0Result[\"quote\"]>;\n\n/**\n * Result of preparing a swap (full response from requestQuoteV0)\n * Contains quote and prepared calls ready for signing\n */\nexport type PrepareSwapResult = Extract<\n RequestQuoteV0Result,\n { rawCalls?: false | undefined }\n>;\n\n/**\n * Hook result for preparing swaps\n */\nexport interface UsePrepareSwapResult {\n /** Whether the swap is being prepared */\n isLoading: boolean;\n\n /** Error if preparation failed */\n error: Error | null;\n\n /** Prepared swap data if successful */\n data: PrepareSwapResult | null;\n\n /** Reset the hook state */\n reset(): void;\n\n /** Request a swap quote and prepare calls */\n prepareSwap(request: PrepareSwapRequest): Promise<PrepareSwapResult>;\n}\n\n/**\n * Result of submitting a swap\n * Simplified wrapper that extracts the transaction hash\n */\nexport interface SubmitSwapResult {\n /** Transaction hash of the swap */\n txnHash: Hash;\n}\n\n/**\n * Hook result for submitting swaps\n */\nexport interface UseSubmitSwapResult {\n /** Whether the swap is being submitted */\n isLoading: boolean;\n\n /** Error if submission failed */\n error: Error | null;\n\n /** Swap submission result if successful */\n data: SubmitSwapResult | null;\n\n /** Reset the hook state */\n reset(): void;\n\n /** Sign and submit prepared swap calls */\n submitSwap(preparedSwap: PrepareSwapResult): Promise<SubmitSwapResult>;\n}\n"]}
@@ -1 +1 @@
1
- export declare const VERSION = "4.73.0";
1
+ export declare const VERSION = "4.74.0";
@@ -1,4 +1,4 @@
1
1
  // This file is autogenerated by inject-version.ts. Any changes will be
2
2
  // overwritten on commit!
3
- export const VERSION = "4.73.0";
3
+ export const VERSION = "4.74.0";
4
4
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,yBAAyB;AACzB,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAC","sourcesContent":["// This file is autogenerated by inject-version.ts. Any changes will be\n// overwritten on commit!\nexport const VERSION = \"4.73.0\";\n"]}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/version.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,yBAAyB;AACzB,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAC","sourcesContent":["// This file is autogenerated by inject-version.ts. Any changes will be\n// overwritten on commit!\nexport const VERSION = \"4.74.0\";\n"]}
@@ -1,6 +1,13 @@
1
1
  import { type PropsWithChildren } from "react";
2
2
  import type { SmartWalletClient } from "@account-kit/wallet-client";
3
+ import type { SmartContractAccount } from "@aa-sdk/core";
3
4
  import type { AlchemyProviderConfig } from "./types.js";
5
+ /**
6
+ * Normalized config with defaults applied
7
+ *
8
+ * @internal
9
+ */
10
+ export type NormalizedAlchemyConfig = AlchemyProviderConfig & Required<Pick<AlchemyProviderConfig, "accountAuthMode">>;
4
11
  /**
5
12
  * Client cache stored in React tree (similar to QueryClient in React Query)
6
13
  *
@@ -8,6 +15,7 @@ import type { AlchemyProviderConfig } from "./types.js";
8
15
  */
9
16
  interface ClientCache {
10
17
  client: SmartWalletClient | null;
18
+ account: SmartContractAccount | null;
11
19
  cacheKey: string | null;
12
20
  }
13
21
  /**
@@ -24,6 +32,7 @@ interface ClientCache {
24
32
  * @param {string | string[]} [props.policyId] - Gas Manager policy ID(s) for EVM chains
25
33
  * @param {string | string[]} [props.solanaPolicyId] - Gas Manager policy ID(s) for Solana
26
34
  * @param {boolean} [props.disableSponsorship] - Set to true to disable sponsorship by default (default: false)
35
+ * @param {'eip7702' | 'owner'} [props.accountAuthMode] - Authorization mode for EVM smart accounts (default: 'eip7702')
27
36
  * @returns {JSX.Element} Provider component
28
37
  *
29
38
  * @example
@@ -38,21 +47,22 @@ interface ClientCache {
38
47
  * </PrivyProvider>
39
48
  * ```
40
49
  */
41
- export declare function AlchemyProvider({ children, ...config }: PropsWithChildren<AlchemyProviderConfig>): import("react/jsx-runtime").JSX.Element;
50
+ export declare function AlchemyProvider({ children, accountAuthMode, ...config }: PropsWithChildren<AlchemyProviderConfig>): import("react/jsx-runtime").JSX.Element;
42
51
  /**
43
52
  * Hook to access Alchemy provider configuration
44
53
  * Must be used within an <AlchemyProvider> component
45
54
  *
46
- * @returns {AlchemyProviderConfig} The current Alchemy configuration
55
+ * @returns {NormalizedAlchemyConfig} The current Alchemy configuration with defaults applied
47
56
  * @throws {Error} If used outside of AlchemyProvider
48
57
  *
49
58
  * @example
50
59
  * ```tsx
51
60
  * const config = useAlchemyConfig();
52
61
  * console.log('Policy ID:', config.policyId);
62
+ * console.log('Auth Mode:', config.accountAuthMode); // Always defined
53
63
  * ```
54
64
  */
55
- export declare function useAlchemyConfig(): AlchemyProviderConfig;
65
+ export declare function useAlchemyConfig(): NormalizedAlchemyConfig;
56
66
  /**
57
67
  * Hook to access the client cache (internal use only)
58
68
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Provider.d.ts","sourceRoot":"","sources":["../../src/Provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,iBAAiB,EAKvB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAIxD;;;;GAIG;AACH,UAAU,WAAW;IACnB,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACjC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,GAAG,MAAM,EACV,EAAE,iBAAiB,CAAC,qBAAqB,CAAC,2CAiD1C;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,IAAI,qBAAqB,CAMxD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAQ5C"}
1
+ {"version":3,"file":"Provider.d.ts","sourceRoot":"","sources":["../../src/Provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,iBAAiB,EAKvB,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExD;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG,qBAAqB,GACzD,QAAQ,CAAC,IAAI,CAAC,qBAAqB,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAI3D;;;;GAIG;AACH,UAAU,WAAW;IACnB,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACjC,OAAO,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACrC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAID;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,eAA2B,EAC3B,GAAG,MAAM,EACV,EAAE,iBAAiB,CAAC,qBAAqB,CAAC,2CA0D1C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,IAAI,uBAAuB,CAM1D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAQ5C"}
@@ -1,18 +1,23 @@
1
+ import { type SmartContractAccount } from "@aa-sdk/core";
1
2
  import { type SmartWalletClient } from "@account-kit/wallet-client";
3
+ export type AlchemyClientResult = {
4
+ client: SmartWalletClient;
5
+ account: SmartContractAccount;
6
+ };
2
7
  /**
3
- * Hook to get and memoize a SmartWalletClient instance
4
- * The client is cached in the AlchemyProvider context (React tree scoped)
8
+ * Hook to get and memoize a SmartWalletClient instance with its associated account
9
+ * The client and account are cached in the AlchemyProvider context (React tree scoped)
5
10
  * Automatically clears cache on logout via the provider
6
11
  *
7
- * @returns {{ getClient: () => Promise<SmartWalletClient> }} Object containing the smart wallet client getter
12
+ * @returns {{ getClient: () => Promise<AlchemyClientResult> }} Object containing the smart wallet client and account getter
8
13
  *
9
14
  * @example
10
15
  * ```tsx
11
16
  * const { getClient } = useAlchemyClient();
12
- * const smartWalletClient = await getClient();
17
+ * const { client, account } = await getClient();
13
18
  * ```
14
19
  */
15
20
  export declare function useAlchemyClient(): {
16
- getClient: () => Promise<SmartWalletClient>;
21
+ getClient: () => Promise<AlchemyClientResult>;
17
22
  };
18
23
  //# sourceMappingURL=useAlchemyClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useAlchemyClient.d.ts","sourceRoot":"","sources":["../../../src/hooks/useAlchemyClient.ts"],"names":[],"mappings":"AAaA,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,4BAA4B,CAAC;AAMpC;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB;qBAgCU,OAAO,CAAC,iBAAiB,CAAC;EA4FnE"}
1
+ {"version":3,"file":"useAlchemyClient.d.ts","sourceRoot":"","sources":["../../../src/hooks/useAlchemyClient.ts"],"names":[],"mappings":"AACA,OAAO,EAIL,KAAK,oBAAoB,EAC1B,MAAM,cAAc,CAAC;AAQtB,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,4BAA4B,CAAC;AAMpC,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,oBAAoB,CAAC;CAC/B,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB;qBAgCU,OAAO,CAAC,mBAAmB,CAAC;EA0GrE"}
@@ -1 +1 @@
1
- {"version":3,"file":"useAlchemyPrepareSwap.d.ts","sourceRoot":"","sources":["../../../src/hooks/useAlchemyPrepareSwap.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAGV,oBAAoB,EACrB,MAAM,UAAU,CAAC;AAElB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,qBAAqB,IAAI,oBAAoB,CA6D5D"}
1
+ {"version":3,"file":"useAlchemyPrepareSwap.d.ts","sourceRoot":"","sources":["../../../src/hooks/useAlchemyPrepareSwap.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAGV,oBAAoB,EACrB,MAAM,UAAU,CAAC;AAElB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAgB,qBAAqB,IAAI,oBAAoB,CA2D5D"}
@@ -1 +1 @@
1
- {"version":3,"file":"useAlchemySendTransaction.d.ts","sourceRoot":"","sources":["../../../src/hooks/useAlchemySendTransaction.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAIV,wBAAwB,EACzB,MAAM,UAAU,CAAC;AAuBlB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,yBAAyB,IAAI,wBAAwB,CAuGpE"}
1
+ {"version":3,"file":"useAlchemySendTransaction.d.ts","sourceRoot":"","sources":["../../../src/hooks/useAlchemySendTransaction.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAIV,wBAAwB,EACzB,MAAM,UAAU,CAAC;AAuBlB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,yBAAyB,IAAI,wBAAwB,CA2GpE"}
@@ -13,6 +13,12 @@ export type AlchemyProviderConfig = z.infer<typeof ConnectionConfigSchema> & {
13
13
  solanaPolicyId?: string | string[];
14
14
  /** Solana RPC URL (separate from EVM rpcUrl) */
15
15
  solanaRpcUrl?: string;
16
+ /**
17
+ * How EVM smart account calls should be authorized.
18
+ * - 'eip7702' (default): delegated authorization via EIP-7702.
19
+ * - 'owner': sign as the account owner (Privy embedded wallet), no 7702.
20
+ */
21
+ accountAuthMode?: "eip7702" | "owner";
16
22
  /**
17
23
  * Set to true to disable gas sponsorship by default
18
24
  * Default: false (sponsorship enabled when policyId is provided)
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "4.73.0";
1
+ export declare const VERSION = "4.74.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@account-kit/privy-integration",
3
- "version": "4.73.0",
3
+ "version": "4.74.0",
4
4
  "description": "Use Alchemy gas sponsorship, swaps and more with Privy",
5
5
  "author": "Alchemy",
6
6
  "license": "MIT",
@@ -48,8 +48,8 @@
48
48
  "typescript-template": "*"
49
49
  },
50
50
  "dependencies": {
51
- "@account-kit/infra": "^4.73.0",
52
- "@account-kit/wallet-client": "^4.73.0"
51
+ "@account-kit/infra": "^4.74.0",
52
+ "@account-kit/wallet-client": "^4.74.0"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "@privy-io/react-auth": "^2.3.1 || ^3.0.0",
@@ -72,5 +72,5 @@
72
72
  "url": "https://github.com/alchemyplatform/aa-sdk/issues"
73
73
  },
74
74
  "homepage": "https://github.com/alchemyplatform/aa-sdk#readme",
75
- "gitHead": "1471537aa2b9e8cac4661b7162aa9c702efac7f1"
75
+ "gitHead": "4e77fc8eef6262c294f325d4acad720c15a5cbe2"
76
76
  }
@@ -3,6 +3,7 @@ import {
3
3
  WalletClientSigner,
4
4
  type AuthorizationRequest,
5
5
  ConnectionConfigSchema,
6
+ type SmartContractAccount,
6
7
  } from "@aa-sdk/core";
7
8
  import {
8
9
  createWalletClient,
@@ -20,17 +21,22 @@ import { useAlchemyConfig, useClientCache } from "../Provider.js";
20
21
  import { getChain } from "../util/getChain.js";
21
22
  import { useEmbeddedWallet } from "./internal/useEmbeddedWallet.js";
22
23
 
24
+ export type AlchemyClientResult = {
25
+ client: SmartWalletClient;
26
+ account: SmartContractAccount;
27
+ };
28
+
23
29
  /**
24
- * Hook to get and memoize a SmartWalletClient instance
25
- * The client is cached in the AlchemyProvider context (React tree scoped)
30
+ * Hook to get and memoize a SmartWalletClient instance with its associated account
31
+ * The client and account are cached in the AlchemyProvider context (React tree scoped)
26
32
  * Automatically clears cache on logout via the provider
27
33
  *
28
- * @returns {{ getClient: () => Promise<SmartWalletClient> }} Object containing the smart wallet client getter
34
+ * @returns {{ getClient: () => Promise<AlchemyClientResult> }} Object containing the smart wallet client and account getter
29
35
  *
30
36
  * @example
31
37
  * ```tsx
32
38
  * const { getClient } = useAlchemyClient();
33
- * const smartWalletClient = await getClient();
39
+ * const { client, account } = await getClient();
34
40
  * ```
35
41
  */
36
42
  export function useAlchemyClient() {
@@ -65,7 +71,7 @@ export function useAlchemyClient() {
65
71
  return getChain(parsedChainId);
66
72
  }, [getEmbeddedWallet]);
67
73
 
68
- const getClient = useCallback(async (): Promise<SmartWalletClient> => {
74
+ const getClient = useCallback(async (): Promise<AlchemyClientResult> => {
69
75
  const embeddedWallet = getEmbeddedWallet();
70
76
  const chain = getEmbeddedWalletChain();
71
77
 
@@ -77,11 +83,12 @@ export function useAlchemyClient() {
77
83
  jwt: config.jwt,
78
84
  rpcUrl: config.rpcUrl,
79
85
  policyId: config.policyId,
86
+ accountAuthMode: config.accountAuthMode,
80
87
  });
81
88
 
82
- // Return cached client if configuration hasn't changed
83
- if (cache.client && cache.cacheKey === currentCacheKey) {
84
- return cache.client;
89
+ // Return cached client and account if configuration hasn't changed
90
+ if (cache.client && cache.account && cache.cacheKey === currentCacheKey) {
91
+ return { client: cache.client, account: cache.account };
85
92
  }
86
93
 
87
94
  // Configuration changed or no cache exists, create new client
@@ -97,23 +104,23 @@ export function useAlchemyClient() {
97
104
  "privy",
98
105
  );
99
106
 
100
- // Extend signer with EIP-7702 authorization support
101
- const signer = {
102
- ...baseSigner,
103
- signAuthorization: async (
104
- unsignedAuth: AuthorizationRequest<number>,
105
- ): Promise<Authorization<number, true>> => {
106
- const signature = await signAuthorization({
107
- ...unsignedAuth,
108
- contractAddress: unsignedAuth.address ?? unsignedAuth.contractAddress,
109
- });
110
-
111
- return {
112
- ...unsignedAuth,
113
- ...signature,
114
- };
115
- },
116
- };
107
+ // Optionally extend signer with EIP-7702 authorization support
108
+ const signer =
109
+ config.accountAuthMode === "eip7702"
110
+ ? {
111
+ ...baseSigner,
112
+ signAuthorization: async (
113
+ unsignedAuth: AuthorizationRequest<number>,
114
+ ): Promise<Authorization<number, true>> => {
115
+ const signature = await signAuthorization({
116
+ ...unsignedAuth,
117
+ contractAddress:
118
+ unsignedAuth.address ?? unsignedAuth.contractAddress,
119
+ });
120
+ return { ...unsignedAuth, ...signature };
121
+ },
122
+ }
123
+ : baseSigner;
117
124
 
118
125
  // Determine transport configuration using schema validation
119
126
  // This properly handles combinations like rpcUrl + jwt together
@@ -141,10 +148,22 @@ export function useAlchemyClient() {
141
148
  : undefined,
142
149
  });
143
150
 
151
+ // Request the account to properly initialize the smart wallet
152
+ // Pass a creation hint based on auth mode to ensure different accounts for different modes
153
+ // This prevents 7702 accounts from being reused in owner mode and vice versa
154
+ cache.account =
155
+ config.accountAuthMode === "eip7702"
156
+ ? await cache.client.requestAccount({
157
+ creationHint: { accountType: "7702" },
158
+ })
159
+ : await cache.client.requestAccount({
160
+ creationHint: { accountType: "sma-b" },
161
+ });
162
+
144
163
  // Store the cache key
145
164
  cache.cacheKey = currentCacheKey;
146
165
 
147
- return cache.client;
166
+ return { client: cache.client, account: cache.account };
148
167
  }, [
149
168
  getEmbeddedWallet,
150
169
  getEmbeddedWalletChain,
@@ -154,6 +173,7 @@ export function useAlchemyClient() {
154
173
  config.rpcUrl,
155
174
  config.policyId,
156
175
  cache,
176
+ config.accountAuthMode,
157
177
  ]);
158
178
 
159
179
  return { getClient };
@@ -2,7 +2,6 @@ import { useCallback, useState } from "react";
2
2
  import { type Address } from "viem";
3
3
  import { swapActions } from "@account-kit/wallet-client/experimental";
4
4
  import { useAlchemyClient } from "./useAlchemyClient.js";
5
- import { useEmbeddedWallet } from "./internal/useEmbeddedWallet.js";
6
5
  import type {
7
6
  PrepareSwapRequest,
8
7
  PrepareSwapResult,
@@ -51,7 +50,6 @@ import type {
51
50
  */
52
51
  export function useAlchemyPrepareSwap(): UsePrepareSwapResult {
53
52
  const { getClient } = useAlchemyClient();
54
- const getEmbeddedWallet = useEmbeddedWallet();
55
53
 
56
54
  const [isLoading, setIsLoading] = useState(false);
57
55
  const [error, setError] = useState<Error | null>(null);
@@ -63,8 +61,7 @@ export function useAlchemyPrepareSwap(): UsePrepareSwapResult {
63
61
  setError(null);
64
62
 
65
63
  try {
66
- const client = await getClient();
67
- const embeddedWallet = getEmbeddedWallet();
64
+ const { client, account } = await getClient();
68
65
 
69
66
  // Extend client with swap actions
70
67
  const swapClient = client.extend(swapActions);
@@ -73,7 +70,7 @@ export function useAlchemyPrepareSwap(): UsePrepareSwapResult {
73
70
  // Note: Gas sponsorship capabilities are configured on the client itself
74
71
  const response = await swapClient.requestQuoteV0({
75
72
  ...request,
76
- from: request.from || (embeddedWallet.address as Address),
73
+ from: request.from || (account.address as Address),
77
74
  });
78
75
 
79
76
  // Validate that we got prepared calls, not raw calls
@@ -94,7 +91,7 @@ export function useAlchemyPrepareSwap(): UsePrepareSwapResult {
94
91
  setIsLoading(false);
95
92
  }
96
93
  },
97
- [getClient, getEmbeddedWallet],
94
+ [getClient],
98
95
  );
99
96
 
100
97
  const reset = useCallback(() => {
@@ -1,8 +1,7 @@
1
1
  import { useCallback, useState } from "react";
2
- import { type Address, type Hex, isHex } from "viem";
2
+ import { type Hex, isHex } from "viem";
3
3
  import { useAlchemyClient } from "./useAlchemyClient.js";
4
4
  import { useAlchemyConfig } from "../Provider.js";
5
- import { useEmbeddedWallet } from "./internal/useEmbeddedWallet.js";
6
5
  import type {
7
6
  UnsignedTransactionRequest,
8
7
  SendTransactionOptions,
@@ -69,7 +68,6 @@ function normalizeValue(value: string | number | bigint): Hex {
69
68
  export function useAlchemySendTransaction(): UseSendTransactionResult {
70
69
  const { getClient } = useAlchemyClient();
71
70
  const config = useAlchemyConfig();
72
- const getEmbeddedWallet = useEmbeddedWallet();
73
71
 
74
72
  const [isLoading, setIsLoading] = useState(false);
75
73
  const [error, setError] = useState<Error | null>(null);
@@ -84,8 +82,7 @@ export function useAlchemySendTransaction(): UseSendTransactionResult {
84
82
  setError(null);
85
83
 
86
84
  try {
87
- const client = await getClient();
88
- const embeddedWallet = getEmbeddedWallet();
85
+ const { client, account } = await getClient();
89
86
 
90
87
  // Determine if transaction should be sponsored
91
88
  const hasPolicyId = !!config.policyId;
@@ -103,23 +100,24 @@ export function useAlchemySendTransaction(): UseSendTransactionResult {
103
100
  value: txn.value ? normalizeValue(txn.value) : undefined,
104
101
  }));
105
102
 
106
- // Build capabilities based on sponsorship
103
+ // Build capabilities based on sponsorship and auth mode
107
104
  const policyId = Array.isArray(config.policyId)
108
105
  ? config.policyId[0]
109
106
  : config.policyId;
110
107
 
111
- const capabilities: {
112
- eip7702Auth: true;
113
- paymasterService?: { policyId: string };
114
- } = { eip7702Auth: true };
108
+ type Capabilities =
109
+ | { eip7702Auth: true; paymasterService?: { policyId: string } }
110
+ | { paymasterService?: { policyId: string } };
111
+ const capabilities: Capabilities =
112
+ config.accountAuthMode === "eip7702" ? { eip7702Auth: true } : {};
115
113
 
116
114
  if (shouldSponsor && policyId) {
117
115
  capabilities.paymasterService = { policyId };
118
116
  }
119
117
 
120
- // Send the transaction(s)
118
+ // Send the transaction(s) from the smart account address
121
119
  const result = await client.sendCalls({
122
- from: embeddedWallet.address as Address,
120
+ from: account.address,
123
121
  calls: formattedCalls,
124
122
  capabilities,
125
123
  });
@@ -153,7 +151,12 @@ export function useAlchemySendTransaction(): UseSendTransactionResult {
153
151
  setIsLoading(false);
154
152
  }
155
153
  },
156
- [getClient, getEmbeddedWallet, config.policyId, config.disableSponsorship],
154
+ [
155
+ getClient,
156
+ config.policyId,
157
+ config.disableSponsorship,
158
+ config.accountAuthMode,
159
+ ],
157
160
  );
158
161
 
159
162
  const reset = useCallback(() => {
@@ -49,7 +49,7 @@ export function useAlchemySubmitSwap(): UseSubmitSwapResult {
49
49
  setError(null);
50
50
 
51
51
  try {
52
- const client = await getClient();
52
+ const { client } = await getClient();
53
53
 
54
54
  // Extend client with swap actions
55
55
  const swapClient = client.extend(swapActions);
package/src/types.ts CHANGED
@@ -17,6 +17,13 @@ export type AlchemyProviderConfig = z.infer<typeof ConnectionConfigSchema> & {
17
17
  /** Solana RPC URL (separate from EVM rpcUrl) */
18
18
  solanaRpcUrl?: string;
19
19
 
20
+ /**
21
+ * How EVM smart account calls should be authorized.
22
+ * - 'eip7702' (default): delegated authorization via EIP-7702.
23
+ * - 'owner': sign as the account owner (Privy embedded wallet), no 7702.
24
+ */
25
+ accountAuthMode?: "eip7702" | "owner";
26
+
20
27
  /**
21
28
  * Set to true to disable gas sponsorship by default
22
29
  * Default: false (sponsorship enabled when policyId is provided)
package/src/version.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  // This file is autogenerated by inject-version.ts. Any changes will be
2
2
  // overwritten on commit!
3
- export const VERSION = "4.73.0";
3
+ export const VERSION = "4.74.0";