@account-kit/privy-integration 4.73.1-alpha.9 → 4.75.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 (105) hide show
  1. package/README.md +61 -21
  2. package/dist/esm/Provider.d.ts +71 -4
  3. package/dist/esm/Provider.js +109 -4
  4. package/dist/esm/Provider.js.map +1 -1
  5. package/dist/esm/hooks/internal/useEmbeddedWallet.d.ts +4 -3
  6. package/dist/esm/hooks/internal/useEmbeddedWallet.js +13 -5
  7. package/dist/esm/hooks/internal/useEmbeddedWallet.js.map +1 -1
  8. package/dist/esm/hooks/useAlchemyClient.d.ts +10 -5
  9. package/dist/esm/hooks/useAlchemyClient.js +46 -25
  10. package/dist/esm/hooks/useAlchemyClient.js.map +1 -1
  11. package/dist/esm/hooks/useAlchemyPrepareSwap.js +3 -6
  12. package/dist/esm/hooks/useAlchemyPrepareSwap.js.map +1 -1
  13. package/dist/esm/hooks/useAlchemySendTransaction.js +12 -10
  14. package/dist/esm/hooks/useAlchemySendTransaction.js.map +1 -1
  15. package/dist/esm/hooks/useAlchemySolanaTransaction.js +1 -1
  16. package/dist/esm/hooks/useAlchemySolanaTransaction.js.map +1 -1
  17. package/dist/esm/hooks/useAlchemySubmitSwap.js +1 -1
  18. package/dist/esm/hooks/useAlchemySubmitSwap.js.map +1 -1
  19. package/dist/esm/types.d.ts +6 -0
  20. package/dist/esm/types.js.map +1 -1
  21. package/dist/esm/version.d.ts +1 -1
  22. package/dist/esm/version.js +1 -1
  23. package/dist/esm/version.js.map +1 -1
  24. package/dist/types/Provider.d.ts +71 -4
  25. package/dist/types/Provider.d.ts.map +1 -1
  26. package/dist/types/hooks/internal/useEmbeddedWallet.d.ts +4 -3
  27. package/dist/types/hooks/internal/useEmbeddedWallet.d.ts.map +1 -1
  28. package/dist/types/hooks/useAlchemyClient.d.ts +10 -5
  29. package/dist/types/hooks/useAlchemyClient.d.ts.map +1 -1
  30. package/dist/types/hooks/useAlchemyPrepareSwap.d.ts.map +1 -1
  31. package/dist/types/hooks/useAlchemySendTransaction.d.ts.map +1 -1
  32. package/dist/types/types.d.ts +6 -0
  33. package/dist/types/types.d.ts.map +1 -1
  34. package/dist/types/version.d.ts +1 -1
  35. package/dist/types/version.d.ts.map +1 -1
  36. package/package.json +4 -27
  37. package/src/hooks/internal/useEmbeddedWallet.ts +20 -5
  38. package/src/hooks/useAlchemyClient.ts +71 -35
  39. package/src/hooks/useAlchemyPrepareSwap.ts +3 -6
  40. package/src/hooks/useAlchemySendTransaction.ts +17 -14
  41. package/src/hooks/useAlchemySolanaTransaction.ts +1 -1
  42. package/src/hooks/useAlchemySubmitSwap.ts +1 -1
  43. package/src/types.ts +7 -0
  44. package/src/version.ts +1 -1
  45. package/dist/esm/Provider.native.d.ts +0 -6
  46. package/dist/esm/Provider.native.js +0 -13
  47. package/dist/esm/Provider.native.js.map +0 -1
  48. package/dist/esm/adapters/react-native.d.ts +0 -6
  49. package/dist/esm/adapters/react-native.js +0 -130
  50. package/dist/esm/adapters/react-native.js.map +0 -1
  51. package/dist/esm/adapters/types.d.ts +0 -44
  52. package/dist/esm/adapters/types.js +0 -2
  53. package/dist/esm/adapters/types.js.map +0 -1
  54. package/dist/esm/adapters/web.d.ts +0 -6
  55. package/dist/esm/adapters/web.js +0 -50
  56. package/dist/esm/adapters/web.js.map +0 -1
  57. package/dist/esm/adapters/web.native.d.ts +0 -5
  58. package/dist/esm/adapters/web.native.js +0 -6
  59. package/dist/esm/adapters/web.native.js.map +0 -1
  60. package/dist/esm/context/AlchemyContext.d.ts +0 -62
  61. package/dist/esm/context/AlchemyContext.js +0 -105
  62. package/dist/esm/context/AlchemyContext.js.map +0 -1
  63. package/dist/esm/providers/ReactNativeProvider.d.ts +0 -33
  64. package/dist/esm/providers/ReactNativeProvider.js +0 -37
  65. package/dist/esm/providers/ReactNativeProvider.js.map +0 -1
  66. package/dist/esm/providers/WebProvider.d.ts +0 -33
  67. package/dist/esm/providers/WebProvider.js +0 -37
  68. package/dist/esm/providers/WebProvider.js.map +0 -1
  69. package/dist/esm/providers/WebProvider.native.d.ts +0 -5
  70. package/dist/esm/providers/WebProvider.native.js +0 -9
  71. package/dist/esm/providers/WebProvider.native.js.map +0 -1
  72. package/dist/esm/react-native.d.ts +0 -11
  73. package/dist/esm/react-native.js +0 -13
  74. package/dist/esm/react-native.js.map +0 -1
  75. package/dist/types/Provider.native.d.ts +0 -7
  76. package/dist/types/Provider.native.d.ts.map +0 -1
  77. package/dist/types/adapters/react-native.d.ts +0 -7
  78. package/dist/types/adapters/react-native.d.ts.map +0 -1
  79. package/dist/types/adapters/types.d.ts +0 -45
  80. package/dist/types/adapters/types.d.ts.map +0 -1
  81. package/dist/types/adapters/web.d.ts +0 -7
  82. package/dist/types/adapters/web.d.ts.map +0 -1
  83. package/dist/types/adapters/web.native.d.ts +0 -6
  84. package/dist/types/adapters/web.native.d.ts.map +0 -1
  85. package/dist/types/context/AlchemyContext.d.ts +0 -63
  86. package/dist/types/context/AlchemyContext.d.ts.map +0 -1
  87. package/dist/types/providers/ReactNativeProvider.d.ts +0 -34
  88. package/dist/types/providers/ReactNativeProvider.d.ts.map +0 -1
  89. package/dist/types/providers/WebProvider.d.ts +0 -34
  90. package/dist/types/providers/WebProvider.d.ts.map +0 -1
  91. package/dist/types/providers/WebProvider.native.d.ts +0 -6
  92. package/dist/types/providers/WebProvider.native.d.ts.map +0 -1
  93. package/dist/types/react-native.d.ts +0 -12
  94. package/dist/types/react-native.d.ts.map +0 -1
  95. package/src/Provider.native.tsx +0 -18
  96. package/src/Provider.tsx +0 -6
  97. package/src/adapters/react-native.ts +0 -190
  98. package/src/adapters/types.ts +0 -56
  99. package/src/adapters/web.native.ts +0 -6
  100. package/src/adapters/web.ts +0 -73
  101. package/src/context/AlchemyContext.tsx +0 -162
  102. package/src/providers/ReactNativeProvider.tsx +0 -45
  103. package/src/providers/WebProvider.native.tsx +0 -11
  104. package/src/providers/WebProvider.tsx +0 -45
  105. package/src/react-native.ts +0 -29
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@account-kit/privy-integration",
3
- "version": "4.73.1-alpha.9",
3
+ "version": "4.75.0",
4
4
  "description": "Use Alchemy gas sponsorship, swaps and more with Privy",
5
5
  "author": "Alchemy",
6
6
  "license": "MIT",
@@ -11,18 +11,9 @@
11
11
  "types": "./dist/types/index.d.ts",
12
12
  "typings": "./dist/types/index.d.ts",
13
13
  "sideEffects": false,
14
- "react-native": {
15
- "main": "./dist/esm/react-native.js",
16
- "./dist/esm/adapters/web.js": "./dist/esm/adapters/web.native.js",
17
- "./dist/esm/providers/WebProvider.js": "./dist/esm/providers/WebProvider.native.js",
18
- "./dist/esm/Provider.js": "./dist/esm/Provider.native.js",
19
- "@privy-io/react-auth": false,
20
- "@privy-io/react-auth/solana": false
21
- },
22
14
  "files": [
23
15
  "dist",
24
16
  "src/**/*.ts",
25
- "src/**/*.tsx",
26
17
  "!dist/**/*.tsbuildinfo",
27
18
  "!vitest.config.ts",
28
19
  "!.env",
@@ -32,16 +23,10 @@
32
23
  ],
33
24
  "exports": {
34
25
  ".": {
35
- "react-native": "./dist/esm/react-native.js",
36
26
  "types": "./dist/types/index.d.ts",
37
27
  "import": "./dist/esm/index.js",
38
28
  "default": "./dist/esm/index.js"
39
29
  },
40
- "./react-native": {
41
- "types": "./dist/types/react-native.d.ts",
42
- "import": "./dist/esm/react-native.js",
43
- "default": "./dist/esm/react-native.js"
44
- },
45
30
  "./solana": {
46
31
  "types": "./dist/types/solana.d.ts",
47
32
  "import": "./dist/esm/solana.js",
@@ -59,26 +44,18 @@
59
44
  "test:run": "vitest run --passWithNoTests"
60
45
  },
61
46
  "devDependencies": {
62
- "@privy-io/expo": "0.58.1",
63
47
  "@privy-io/react-auth": "3.3.0",
64
48
  "typescript-template": "*"
65
49
  },
66
50
  "dependencies": {
67
- "@account-kit/infra": "^4.73.1-alpha.9",
68
- "@account-kit/wallet-client": "^4.73.1-alpha.9"
51
+ "@account-kit/infra": "^4.75.0",
52
+ "@account-kit/wallet-client": "^4.75.0"
69
53
  },
70
54
  "peerDependencies": {
71
- "@privy-io/expo": "^0.58.0",
72
55
  "@privy-io/react-auth": "^2.3.1 || ^3.0.0",
73
56
  "viem": "^2.29.2"
74
57
  },
75
58
  "peerDependenciesMeta": {
76
- "@privy-io/react-auth": {
77
- "optional": true
78
- },
79
- "@privy-io/expo": {
80
- "optional": true
81
- },
82
59
  "@solana/web3.js": {
83
60
  "optional": true
84
61
  }
@@ -95,5 +72,5 @@
95
72
  "url": "https://github.com/alchemyplatform/aa-sdk/issues"
96
73
  },
97
74
  "homepage": "https://github.com/alchemyplatform/aa-sdk#readme",
98
- "gitHead": "55c990661fe74790e0321bd9828031dc2b2cd158"
75
+ "gitHead": "2113dcf956dd2b35a98031ef7ec5bc23c0594684"
99
76
  }
@@ -1,14 +1,29 @@
1
- import { useAdapter } from "../../context/AlchemyContext.js";
1
+ import { useCallback } from "react";
2
+ import {
3
+ useWallets,
4
+ type ConnectedWallet as PrivyWallet,
5
+ } from "@privy-io/react-auth";
2
6
 
3
7
  /**
4
8
  * Internal hook to get the Privy embedded wallet
5
- * Uses the platform adapter to abstract differences between web and React Native
9
+ * Shared across multiple hooks to avoid duplication
6
10
  *
7
11
  * @internal
8
- * @returns {() => EmbeddedWallet} Function that returns the embedded wallet
12
+ * @returns {() => PrivyWallet} Function that returns the embedded wallet
9
13
  * @throws {Error} If embedded wallet is not found
10
14
  */
11
15
  export function useEmbeddedWallet() {
12
- const adapter = useAdapter();
13
- return adapter.useEmbeddedWallet();
16
+ const { wallets } = useWallets();
17
+
18
+ const getEmbeddedWallet = useCallback((): PrivyWallet => {
19
+ const embedded = wallets.find((w) => w.walletClientType === "privy");
20
+ if (!embedded) {
21
+ throw new Error(
22
+ "Privy embedded wallet not found. Please ensure the user is authenticated.",
23
+ );
24
+ }
25
+ return embedded;
26
+ }, [wallets]);
27
+
28
+ return getEmbeddedWallet;
14
29
  }
@@ -1,49 +1,54 @@
1
1
  import { useCallback } from "react";
2
- import { WalletClientSigner, ConnectionConfigSchema } from "@aa-sdk/core";
3
- import { createWalletClient, custom, type Address } from "viem";
2
+ import {
3
+ WalletClientSigner,
4
+ type AuthorizationRequest,
5
+ ConnectionConfigSchema,
6
+ type SmartContractAccount,
7
+ } from "@aa-sdk/core";
8
+ import {
9
+ createWalletClient,
10
+ custom,
11
+ type Address,
12
+ type Authorization,
13
+ } from "viem";
14
+ import { useSign7702Authorization } from "@privy-io/react-auth";
4
15
  import {
5
16
  createSmartWalletClient,
6
17
  type SmartWalletClient,
7
18
  } from "@account-kit/wallet-client";
8
19
  import { alchemy } from "@account-kit/infra";
9
- import {
10
- useAlchemyConfig,
11
- useClientCache,
12
- useAdapter,
13
- } from "../context/AlchemyContext.js";
20
+ import { useAlchemyConfig, useClientCache } from "../Provider.js";
14
21
  import { getChain } from "../util/getChain.js";
15
22
  import { useEmbeddedWallet } from "./internal/useEmbeddedWallet.js";
16
23
 
24
+ export type AlchemyClientResult = {
25
+ client: SmartWalletClient;
26
+ account: SmartContractAccount;
27
+ };
28
+
17
29
  /**
18
- * Hook to get and memoize a SmartWalletClient instance
19
- * 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)
20
32
  * Automatically clears cache on logout via the provider
21
33
  *
22
- * @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
23
35
  *
24
36
  * @example
25
37
  * ```tsx
26
38
  * const { getClient } = useAlchemyClient();
27
- * const smartWalletClient = await getClient();
39
+ * const { client, account } = await getClient();
28
40
  * ```
29
41
  */
30
42
  export function useAlchemyClient() {
31
- const adapter = useAdapter();
32
- const signAuthorizationFn = adapter.useAuthorizationSigner?.() || null;
43
+ const { signAuthorization } = useSign7702Authorization();
33
44
  const config = useAlchemyConfig();
34
45
  const cache = useClientCache();
35
46
  const getEmbeddedWallet = useEmbeddedWallet();
36
47
 
37
- const getClient = useCallback(async (): Promise<SmartWalletClient> => {
38
- const embeddedWallet = getEmbeddedWallet();
39
-
40
- // IMPORTANT: Get provider FIRST to ensure chain ID is updated
41
- // The provider fetch triggers chain ID update in the adapter
42
- const provider = await embeddedWallet.getEthereumProvider();
43
-
44
- // NOW get the chain from the SAME wallet instance with updated chain ID
48
+ const getEmbeddedWalletChain = useCallback(() => {
49
+ const embedded = getEmbeddedWallet();
45
50
  // Handle CAIP-2 format like "eip155:1"
46
- const chainIdStr = embeddedWallet.chainId?.toString();
51
+ const chainIdStr = embedded.chainId?.toString();
47
52
 
48
53
  if (!chainIdStr) {
49
54
  throw new Error(
@@ -63,7 +68,12 @@ export function useAlchemyClient() {
63
68
  );
64
69
  }
65
70
 
66
- const chain = getChain(parsedChainId);
71
+ return getChain(parsedChainId);
72
+ }, [getEmbeddedWallet]);
73
+
74
+ const getClient = useCallback(async (): Promise<AlchemyClientResult> => {
75
+ const embeddedWallet = getEmbeddedWallet();
76
+ const chain = getEmbeddedWalletChain();
67
77
 
68
78
  // Generate a cache key based on configuration and wallet address
69
79
  const currentCacheKey = JSON.stringify({
@@ -73,14 +83,16 @@ export function useAlchemyClient() {
73
83
  jwt: config.jwt,
74
84
  rpcUrl: config.rpcUrl,
75
85
  policyId: config.policyId,
86
+ accountAuthMode: config.accountAuthMode,
76
87
  });
77
88
 
78
- // Return cached client if configuration hasn't changed
79
- if (cache.client && cache.cacheKey === currentCacheKey) {
80
- 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 };
81
92
  }
82
93
 
83
94
  // Configuration changed or no cache exists, create new client
95
+ const provider = await embeddedWallet.getEthereumProvider();
84
96
 
85
97
  // Create base signer from Privy wallet
86
98
  const baseSigner = new WalletClientSigner(
@@ -92,13 +104,23 @@ export function useAlchemyClient() {
92
104
  "privy",
93
105
  );
94
106
 
95
- // Extend signer with EIP-7702 authorization support (if available)
96
- const signer = signAuthorizationFn
97
- ? {
98
- ...baseSigner,
99
- signAuthorization: signAuthorizationFn,
100
- }
101
- : baseSigner;
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;
102
124
 
103
125
  // Determine transport configuration using schema validation
104
126
  // This properly handles combinations like rpcUrl + jwt together
@@ -126,18 +148,32 @@ export function useAlchemyClient() {
126
148
  : undefined,
127
149
  });
128
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
+
129
163
  // Store the cache key
130
164
  cache.cacheKey = currentCacheKey;
131
165
 
132
- return cache.client;
166
+ return { client: cache.client, account: cache.account };
133
167
  }, [
134
168
  getEmbeddedWallet,
135
- signAuthorizationFn,
169
+ getEmbeddedWalletChain,
170
+ signAuthorization,
136
171
  config.apiKey,
137
172
  config.jwt,
138
173
  config.rpcUrl,
139
174
  config.policyId,
140
175
  cache,
176
+ config.accountAuthMode,
141
177
  ]);
142
178
 
143
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
- import { useAlchemyConfig } from "../context/AlchemyContext.js";
5
- import { useEmbeddedWallet } from "./internal/useEmbeddedWallet.js";
4
+ import { useAlchemyConfig } from "../Provider.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(() => {
@@ -7,7 +7,7 @@ import {
7
7
  TransactionInstruction,
8
8
  VersionedTransaction,
9
9
  } from "@solana/web3.js";
10
- import { useAlchemyConfig } from "../context/AlchemyContext.js";
10
+ import { useAlchemyConfig } from "../Provider.js";
11
11
  import { createSolanaSponsoredTransaction } from "../util/createSolanaSponsoredTransaction.js";
12
12
  import { useSignTransaction, useWallets } from "@privy-io/react-auth/solana";
13
13
  import { createSolanaTransaction } from "../util/createSolanaTransaction.js";
@@ -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.1-alpha.9";
3
+ export const VERSION = "4.75.0";
@@ -1,6 +0,0 @@
1
- /**
2
- * React Native stub for web Provider
3
- * This file prevents Metro from importing web-specific code
4
- */
5
- export declare function AlchemyProvider(): void;
6
- export declare function useAlchemyConfig(): void;
@@ -1,13 +0,0 @@
1
- /**
2
- * React Native stub for web Provider
3
- * This file prevents Metro from importing web-specific code
4
- */
5
- export function AlchemyProvider() {
6
- throw new Error("Web Provider is not available in React Native. " +
7
- 'Import from "@account-kit/privy-integration/react-native" instead.');
8
- }
9
- export function useAlchemyConfig() {
10
- throw new Error("useAlchemyConfig from web Provider is not available in React Native. " +
11
- 'Import from "@account-kit/privy-integration/react-native" instead.');
12
- }
13
- //# sourceMappingURL=Provider.native.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Provider.native.js","sourceRoot":"","sources":["../../src/Provider.native.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,eAAe;IAC7B,MAAM,IAAI,KAAK,CACb,iDAAiD;QAC/C,oEAAoE,CACvE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,IAAI,KAAK,CACb,uEAAuE;QACrE,oEAAoE,CACvE,CAAC;AACJ,CAAC","sourcesContent":["/**\n * React Native stub for web Provider\n * This file prevents Metro from importing web-specific code\n */\n\nexport function AlchemyProvider() {\n throw new Error(\n \"Web Provider is not available in React Native. \" +\n 'Import from \"@account-kit/privy-integration/react-native\" instead.',\n );\n}\n\nexport function useAlchemyConfig() {\n throw new Error(\n \"useAlchemyConfig from web Provider is not available in React Native. \" +\n 'Import from \"@account-kit/privy-integration/react-native\" instead.',\n );\n}\n"]}
@@ -1,6 +0,0 @@
1
- import type { PrivyAdapter } from "./types.js";
2
- /**
3
- * React Native (Expo) adapter for @privy-io/expo
4
- * Implements platform-specific hooks for React Native applications
5
- */
6
- export declare const reactNativeAdapter: PrivyAdapter;
@@ -1,130 +0,0 @@
1
- import { useCallback } from "react";
2
- import { usePrivy, useEmbeddedEthereumWallet, } from "@privy-io/expo";
3
- /**
4
- * React Native (Expo) adapter for @privy-io/expo
5
- * Implements platform-specific hooks for React Native applications
6
- */
7
- export const reactNativeAdapter = {
8
- useEmbeddedWallet() {
9
- const { wallets } = useEmbeddedEthereumWallet();
10
- const getEmbeddedWallet = useCallback(() => {
11
- const wallet = wallets?.[0];
12
- if (!wallet) {
13
- throw new Error("Privy embedded wallet not found. Please ensure the user is authenticated and has created a wallet.");
14
- }
15
- return adaptExpoWallet(wallet);
16
- }, [wallets]);
17
- return getEmbeddedWallet;
18
- },
19
- usePrivyAuth() {
20
- const { user } = usePrivy();
21
- return { authenticated: !!user, user };
22
- },
23
- useAuthorizationSigner() {
24
- const { wallets } = useEmbeddedEthereumWallet();
25
- // Don't memoize the callback - create it fresh each time to ensure we have the latest wallets
26
- const signAuthorization = async (unsignedAuth) => {
27
- console.log("[RN Adapter] signAuthorization called with:", unsignedAuth);
28
- console.log("[RN Adapter] Current wallets:", wallets);
29
- const wallet = wallets?.[0];
30
- if (!wallet) {
31
- throw new Error("Privy embedded wallet not found. Please ensure the user is authenticated and has created a wallet.");
32
- }
33
- console.log("[RN Adapter] Using wallet:", wallet.address);
34
- const provider = await wallet.getProvider?.();
35
- if (!provider) {
36
- throw new Error("Provider not available on this wallet. Ensure you're using the embedded Ethereum wallet.");
37
- }
38
- // Extract the implementation address (handle both 'address' and 'contractAddress' fields)
39
- const implementationAddress = unsignedAuth.address ?? unsignedAuth.contractAddress;
40
- if (!implementationAddress) {
41
- throw new Error("Implementation address is required for EIP-7702 authorization");
42
- }
43
- console.log("[RN Adapter] Signing 7702 auth for address:", implementationAddress);
44
- // EIP-7702 Authorization structure
45
- const authorization = {
46
- domain: {
47
- name: "EIP-7702",
48
- version: "1",
49
- chainId: unsignedAuth.chainId,
50
- },
51
- types: {
52
- Authorization: [
53
- { name: "chainId", type: "uint256" },
54
- { name: "address", type: "address" },
55
- { name: "nonce", type: "uint256" },
56
- ],
57
- },
58
- primaryType: "Authorization",
59
- message: {
60
- chainId: unsignedAuth.chainId,
61
- address: implementationAddress,
62
- nonce: unsignedAuth.nonce,
63
- },
64
- };
65
- const signature = (await provider.request({
66
- method: "eth_signTypedData_v4",
67
- params: [wallet.address, JSON.stringify(authorization)],
68
- }));
69
- console.log("[RN Adapter] Received signature:", signature);
70
- // Parse the signature into r, s, v components
71
- // Signature format: 0x[r(64)][s(64)][v(2)]
72
- const r = `0x${signature.slice(2, 66)}`;
73
- const s = `0x${signature.slice(66, 130)}`;
74
- const v = parseInt(signature.slice(130, 132), 16);
75
- // Convert v to yParity (0 or 1)
76
- // v can be 27/28 (legacy) or 0/1 (EIP-155)
77
- const yParity = v >= 27 ? v - 27 : v;
78
- const result = {
79
- chainId: unsignedAuth.chainId,
80
- address: implementationAddress,
81
- nonce: unsignedAuth.nonce,
82
- r,
83
- s,
84
- yParity,
85
- };
86
- console.log("[RN Adapter] Returning authorization:", result);
87
- return result;
88
- };
89
- return signAuthorization;
90
- },
91
- };
92
- /**
93
- * Adapts an Expo wallet to the common EmbeddedWallet interface
94
- *
95
- * @param {ExpoEmbeddedWallet} wallet - The Expo embedded wallet to adapt
96
- * @returns {EmbeddedWallet} The adapted wallet following the common interface
97
- */
98
- function adaptExpoWallet(wallet) {
99
- // Use closure to maintain up-to-date chain ID across chain switches
100
- let cachedChainId = wallet.chainId || "1";
101
- return {
102
- address: wallet.address,
103
- get chainId() {
104
- return cachedChainId;
105
- },
106
- getEthereumProvider: async () => {
107
- if (!wallet.getProvider) {
108
- throw new Error("getProvider is not available on this wallet. Ensure you're using the embedded Ethereum wallet.");
109
- }
110
- const provider = await wallet.getProvider();
111
- // Always fetch current chain ID when provider is accessed
112
- // This ensures we have the latest chain after wallet_switchEthereumChain calls
113
- try {
114
- const currentChainId = (await provider.request({
115
- method: "eth_chainId",
116
- params: [],
117
- }));
118
- // Convert hex to decimal string format (e.g., "0x1" -> "1")
119
- cachedChainId = parseInt(currentChainId, 16).toString();
120
- console.log("[RN Adapter] Updated chain ID to:", cachedChainId);
121
- }
122
- catch (err) {
123
- console.warn("[Privy Integration] Failed to fetch current chain ID:", err);
124
- // Fall back to cached value if fetch fails
125
- }
126
- return provider;
127
- },
128
- };
129
- }
130
- //# sourceMappingURL=react-native.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"react-native.js","sourceRoot":"","sources":["../../../src/adapters/react-native.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback } from \"react\";\nimport {\n usePrivy,\n useEmbeddedEthereumWallet,\n type PrivyEmbeddedWalletProvider,\n} from \"@privy-io/expo\";\nimport type { Authorization } from \"viem\";\nimport type { AuthorizationRequest } from \"@aa-sdk/core\";\nimport type { PrivyAdapter, EmbeddedWallet, PrivyAuthState } from \"./types.js\";\n\n/**\n * Wallet type from @privy-io/expo\n * Based on the example app structure\n */\ninterface ExpoEmbeddedWallet {\n address: string;\n chainId?: string;\n getProvider?: () => Promise<PrivyEmbeddedWalletProvider>;\n}\n\n/**\n * React Native (Expo) adapter for @privy-io/expo\n * Implements platform-specific hooks for React Native applications\n */\nexport const reactNativeAdapter: PrivyAdapter = {\n useEmbeddedWallet() {\n const { wallets } = useEmbeddedEthereumWallet();\n\n const getEmbeddedWallet = useCallback((): EmbeddedWallet => {\n const wallet = wallets?.[0];\n if (!wallet) {\n throw new Error(\n \"Privy embedded wallet not found. Please ensure the user is authenticated and has created a wallet.\",\n );\n }\n\n return adaptExpoWallet(wallet);\n }, [wallets]);\n\n return getEmbeddedWallet;\n },\n\n usePrivyAuth(): PrivyAuthState {\n const { user } = usePrivy();\n return { authenticated: !!user, user };\n },\n\n useAuthorizationSigner() {\n const { wallets } = useEmbeddedEthereumWallet();\n\n // Don't memoize the callback - create it fresh each time to ensure we have the latest wallets\n const signAuthorization = async (\n unsignedAuth: AuthorizationRequest<number>,\n ): Promise<Authorization<number, true>> => {\n console.log(\"[RN Adapter] signAuthorization called with:\", unsignedAuth);\n console.log(\"[RN Adapter] Current wallets:\", wallets);\n\n const wallet = wallets?.[0];\n if (!wallet) {\n throw new Error(\n \"Privy embedded wallet not found. Please ensure the user is authenticated and has created a wallet.\",\n );\n }\n\n console.log(\"[RN Adapter] Using wallet:\", wallet.address);\n\n const provider = await wallet.getProvider?.();\n if (!provider) {\n throw new Error(\n \"Provider not available on this wallet. Ensure you're using the embedded Ethereum wallet.\",\n );\n }\n\n // Extract the implementation address (handle both 'address' and 'contractAddress' fields)\n const implementationAddress =\n unsignedAuth.address ?? unsignedAuth.contractAddress;\n\n if (!implementationAddress) {\n throw new Error(\n \"Implementation address is required for EIP-7702 authorization\",\n );\n }\n\n console.log(\n \"[RN Adapter] Signing 7702 auth for address:\",\n implementationAddress,\n );\n\n // EIP-7702 Authorization structure\n const authorization = {\n domain: {\n name: \"EIP-7702\",\n version: \"1\",\n chainId: unsignedAuth.chainId,\n },\n types: {\n Authorization: [\n { name: \"chainId\", type: \"uint256\" },\n { name: \"address\", type: \"address\" },\n { name: \"nonce\", type: \"uint256\" },\n ],\n },\n primaryType: \"Authorization\" as const,\n message: {\n chainId: unsignedAuth.chainId,\n address: implementationAddress,\n nonce: unsignedAuth.nonce,\n },\n };\n\n const signature = (await provider.request({\n method: \"eth_signTypedData_v4\",\n params: [wallet.address, JSON.stringify(authorization)],\n })) as `0x${string}`;\n\n console.log(\"[RN Adapter] Received signature:\", signature);\n\n // Parse the signature into r, s, v components\n // Signature format: 0x[r(64)][s(64)][v(2)]\n const r = `0x${signature.slice(2, 66)}` as `0x${string}`;\n const s = `0x${signature.slice(66, 130)}` as `0x${string}`;\n const v = parseInt(signature.slice(130, 132), 16);\n\n // Convert v to yParity (0 or 1)\n // v can be 27/28 (legacy) or 0/1 (EIP-155)\n const yParity = v >= 27 ? v - 27 : v;\n\n const result = {\n chainId: unsignedAuth.chainId,\n address: implementationAddress,\n nonce: unsignedAuth.nonce,\n r,\n s,\n yParity,\n };\n\n console.log(\"[RN Adapter] Returning authorization:\", result);\n return result;\n };\n\n return signAuthorization;\n },\n};\n\n/**\n * Adapts an Expo wallet to the common EmbeddedWallet interface\n *\n * @param {ExpoEmbeddedWallet} wallet - The Expo embedded wallet to adapt\n * @returns {EmbeddedWallet} The adapted wallet following the common interface\n */\nfunction adaptExpoWallet(wallet: ExpoEmbeddedWallet): EmbeddedWallet {\n // Use closure to maintain up-to-date chain ID across chain switches\n let cachedChainId = wallet.chainId || \"1\";\n\n return {\n address: wallet.address as `0x${string}`,\n get chainId() {\n return cachedChainId;\n },\n getEthereumProvider: async () => {\n if (!wallet.getProvider) {\n throw new Error(\n \"getProvider is not available on this wallet. Ensure you're using the embedded Ethereum wallet.\",\n );\n }\n const provider = await wallet.getProvider();\n\n // Always fetch current chain ID when provider is accessed\n // This ensures we have the latest chain after wallet_switchEthereumChain calls\n try {\n const currentChainId = (await provider.request({\n method: \"eth_chainId\",\n params: [],\n })) as string;\n\n // Convert hex to decimal string format (e.g., \"0x1\" -> \"1\")\n cachedChainId = parseInt(currentChainId, 16).toString();\n console.log(\"[RN Adapter] Updated chain ID to:\", cachedChainId);\n } catch (err) {\n console.warn(\n \"[Privy Integration] Failed to fetch current chain ID:\",\n err,\n );\n // Fall back to cached value if fetch fails\n }\n\n return provider;\n },\n };\n}\n"]}