@account-kit/privy-integration 4.73.1-alpha.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 (80) 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 +36 -17
  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 +11 -9
  14. package/dist/esm/hooks/useAlchemySendTransaction.js.map +1 -1
  15. package/dist/esm/hooks/useAlchemySubmitSwap.js +1 -1
  16. package/dist/esm/hooks/useAlchemySubmitSwap.js.map +1 -1
  17. package/dist/esm/types.d.ts +6 -0
  18. package/dist/esm/types.js.map +1 -1
  19. package/dist/esm/version.d.ts +1 -1
  20. package/dist/esm/version.js +1 -1
  21. package/dist/esm/version.js.map +1 -1
  22. package/dist/types/Provider.d.ts +71 -4
  23. package/dist/types/Provider.d.ts.map +1 -1
  24. package/dist/types/hooks/internal/useEmbeddedWallet.d.ts +4 -3
  25. package/dist/types/hooks/internal/useEmbeddedWallet.d.ts.map +1 -1
  26. package/dist/types/hooks/useAlchemyClient.d.ts +10 -5
  27. package/dist/types/hooks/useAlchemyClient.d.ts.map +1 -1
  28. package/dist/types/hooks/useAlchemyPrepareSwap.d.ts.map +1 -1
  29. package/dist/types/hooks/useAlchemySendTransaction.d.ts.map +1 -1
  30. package/dist/types/types.d.ts +6 -0
  31. package/dist/types/types.d.ts.map +1 -1
  32. package/dist/types/version.d.ts +1 -1
  33. package/dist/types/version.d.ts.map +1 -1
  34. package/package.json +4 -17
  35. package/src/hooks/internal/useEmbeddedWallet.ts +20 -5
  36. package/src/hooks/useAlchemyClient.ts +61 -26
  37. package/src/hooks/useAlchemyPrepareSwap.ts +3 -6
  38. package/src/hooks/useAlchemySendTransaction.ts +16 -13
  39. package/src/hooks/useAlchemySubmitSwap.ts +1 -1
  40. package/src/types.ts +7 -0
  41. package/src/version.ts +1 -1
  42. package/dist/esm/adapters/react-native.d.ts +0 -6
  43. package/dist/esm/adapters/react-native.js +0 -46
  44. package/dist/esm/adapters/react-native.js.map +0 -1
  45. package/dist/esm/adapters/types.d.ts +0 -44
  46. package/dist/esm/adapters/types.js +0 -2
  47. package/dist/esm/adapters/types.js.map +0 -1
  48. package/dist/esm/adapters/web.d.ts +0 -6
  49. package/dist/esm/adapters/web.js +0 -50
  50. package/dist/esm/adapters/web.js.map +0 -1
  51. package/dist/esm/context/AlchemyContext.d.ts +0 -62
  52. package/dist/esm/context/AlchemyContext.js +0 -105
  53. package/dist/esm/context/AlchemyContext.js.map +0 -1
  54. package/dist/esm/providers/ReactNativeProvider.d.ts +0 -33
  55. package/dist/esm/providers/ReactNativeProvider.js +0 -37
  56. package/dist/esm/providers/ReactNativeProvider.js.map +0 -1
  57. package/dist/esm/providers/WebProvider.d.ts +0 -33
  58. package/dist/esm/providers/WebProvider.js +0 -37
  59. package/dist/esm/providers/WebProvider.js.map +0 -1
  60. package/dist/esm/react-native.d.ts +0 -11
  61. package/dist/esm/react-native.js +0 -13
  62. package/dist/esm/react-native.js.map +0 -1
  63. package/dist/types/adapters/react-native.d.ts +0 -7
  64. package/dist/types/adapters/react-native.d.ts.map +0 -1
  65. package/dist/types/adapters/types.d.ts +0 -45
  66. package/dist/types/adapters/types.d.ts.map +0 -1
  67. package/dist/types/adapters/web.d.ts +0 -7
  68. package/dist/types/adapters/web.d.ts.map +0 -1
  69. package/dist/types/context/AlchemyContext.d.ts +0 -63
  70. package/dist/types/context/AlchemyContext.d.ts.map +0 -1
  71. package/dist/types/providers/ReactNativeProvider.d.ts +0 -34
  72. package/dist/types/providers/ReactNativeProvider.d.ts.map +0 -1
  73. package/dist/types/providers/WebProvider.d.ts +0 -34
  74. package/dist/types/providers/WebProvider.d.ts.map +0 -1
  75. package/dist/types/react-native.d.ts +0 -12
  76. package/dist/types/react-native.d.ts.map +0 -1
  77. package/src/adapters/react-native.ts +0 -71
  78. package/src/adapters/types.ts +0 -56
  79. package/src/adapters/web.ts +0 -73
  80. package/src/react-native.ts +0 -29
@@ -1,35 +1,46 @@
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();
@@ -60,7 +71,7 @@ export function useAlchemyClient() {
60
71
  return getChain(parsedChainId);
61
72
  }, [getEmbeddedWallet]);
62
73
 
63
- const getClient = useCallback(async (): Promise<SmartWalletClient> => {
74
+ const getClient = useCallback(async (): Promise<AlchemyClientResult> => {
64
75
  const embeddedWallet = getEmbeddedWallet();
65
76
  const chain = getEmbeddedWalletChain();
66
77
 
@@ -72,11 +83,12 @@ export function useAlchemyClient() {
72
83
  jwt: config.jwt,
73
84
  rpcUrl: config.rpcUrl,
74
85
  policyId: config.policyId,
86
+ accountAuthMode: config.accountAuthMode,
75
87
  });
76
88
 
77
- // Return cached client if configuration hasn't changed
78
- if (cache.client && cache.cacheKey === currentCacheKey) {
79
- 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 };
80
92
  }
81
93
 
82
94
  // Configuration changed or no cache exists, create new client
@@ -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,19 +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
169
  getEmbeddedWalletChain,
136
- signAuthorizationFn,
170
+ signAuthorization,
137
171
  config.apiKey,
138
172
  config.jwt,
139
173
  config.rpcUrl,
140
174
  config.policyId,
141
175
  cache,
176
+ config.accountAuthMode,
142
177
  ]);
143
178
 
144
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.1-alpha.0";
3
+ export const VERSION = "4.74.0";
@@ -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,46 +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
- // EIP-7702 authorization not available on React Native
24
- useAuthorizationSigner() {
25
- return null;
26
- },
27
- };
28
- /**
29
- * Adapts an Expo wallet to the common EmbeddedWallet interface
30
- *
31
- * @param {ExpoEmbeddedWallet} wallet - The Expo embedded wallet to adapt
32
- * @returns {EmbeddedWallet} The adapted wallet following the common interface
33
- */
34
- function adaptExpoWallet(wallet) {
35
- return {
36
- address: wallet.address,
37
- chainId: wallet.chainId || "1",
38
- getEthereumProvider: async () => {
39
- if (!wallet.getProvider) {
40
- throw new Error("getProvider is not available on this wallet. Ensure you're using the embedded Ethereum wallet.");
41
- }
42
- return await wallet.getProvider();
43
- },
44
- };
45
- }
46
- //# sourceMappingURL=react-native.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"react-native.js","sourceRoot":"","sources":["../../../src/adapters/react-native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EACL,QAAQ,EACR,yBAAyB,GAE1B,MAAM,gBAAgB,CAAC;AAaxB;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,iBAAiB;QACf,MAAM,EAAE,OAAO,EAAE,GAAG,yBAAyB,EAAE,CAAC;QAEhD,MAAM,iBAAiB,GAAG,WAAW,CAAC,GAAmB,EAAE;YACzD,MAAM,MAAM,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CACb,oGAAoG,CACrG,CAAC;YACJ,CAAC;YAED,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAEd,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,YAAY;QACV,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC5B,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IACzC,CAAC;IAED,uDAAuD;IACvD,sBAAsB;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAC;AAEF;;;;;GAKG;AACH,SAAS,eAAe,CAAC,MAA0B;IACjD,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAwB;QACxC,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,GAAG;QAC9B,mBAAmB,EAAE,KAAK,IAAI,EAAE;YAC9B,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CACb,gGAAgG,CACjG,CAAC;YACJ,CAAC;YACD,OAAO,MAAM,MAAM,CAAC,WAAW,EAAE,CAAC;QACpC,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport {\n usePrivy,\n useEmbeddedEthereumWallet,\n type PrivyEmbeddedWalletProvider,\n} from \"@privy-io/expo\";\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 // EIP-7702 authorization not available on React Native\n useAuthorizationSigner() {\n return null;\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 return {\n address: wallet.address as `0x${string}`,\n chainId: wallet.chainId || \"1\",\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 return await wallet.getProvider();\n },\n };\n}\n"]}
@@ -1,44 +0,0 @@
1
- import type { Address, Authorization } from "viem";
2
- import type { AuthorizationRequest } from "@aa-sdk/core";
3
- /**
4
- * Platform-agnostic embedded wallet interface
5
- * Abstracts differences between @privy-io/react-auth and @privy-io/expo
6
- */
7
- export interface EmbeddedWallet {
8
- /** Wallet address */
9
- address: Address;
10
- /** Chain ID (may be CAIP-2 format like "eip155:1" or numeric) */
11
- chainId: string | number;
12
- /** Get EVM provider for the wallet */
13
- getEthereumProvider(): Promise<any>;
14
- }
15
- /**
16
- * Platform-agnostic Privy auth state
17
- */
18
- export interface PrivyAuthState {
19
- /** Whether user is authenticated */
20
- authenticated: boolean;
21
- /** User object (platform-specific, used for cache invalidation) */
22
- user: any;
23
- }
24
- /**
25
- * Adapter interface that each platform must implement
26
- * Provides platform-specific Privy functionality
27
- */
28
- export interface PrivyAdapter {
29
- /**
30
- * Hook to get embedded wallet
31
- * Must be called as a React hook (follows rules of hooks)
32
- */
33
- useEmbeddedWallet(): () => EmbeddedWallet;
34
- /**
35
- * Hook to get Privy authentication state
36
- * Must be called as a React hook (follows rules of hooks)
37
- */
38
- usePrivyAuth(): PrivyAuthState;
39
- /**
40
- * Hook to get EIP-7702 authorization signer (optional, web only)
41
- * Must be called as a React hook (follows rules of hooks)
42
- */
43
- useAuthorizationSigner?(): ((auth: AuthorizationRequest<number>) => Promise<Authorization<number, true>>) | null;
44
- }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=types.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/adapters/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Address, Authorization } from \"viem\";\nimport type { AuthorizationRequest } from \"@aa-sdk/core\";\n\n/**\n * Platform-agnostic embedded wallet interface\n * Abstracts differences between @privy-io/react-auth and @privy-io/expo\n */\nexport interface EmbeddedWallet {\n /** Wallet address */\n address: Address;\n\n /** Chain ID (may be CAIP-2 format like \"eip155:1\" or numeric) */\n chainId: string | number;\n\n /** Get EVM provider for the wallet */\n getEthereumProvider(): Promise<any>;\n}\n\n/**\n * Platform-agnostic Privy auth state\n */\nexport interface PrivyAuthState {\n /** Whether user is authenticated */\n authenticated: boolean;\n\n /** User object (platform-specific, used for cache invalidation) */\n user: any;\n}\n\n/**\n * Adapter interface that each platform must implement\n * Provides platform-specific Privy functionality\n */\nexport interface PrivyAdapter {\n /**\n * Hook to get embedded wallet\n * Must be called as a React hook (follows rules of hooks)\n */\n useEmbeddedWallet(): () => EmbeddedWallet;\n\n /**\n * Hook to get Privy authentication state\n * Must be called as a React hook (follows rules of hooks)\n */\n usePrivyAuth(): PrivyAuthState;\n\n /**\n * Hook to get EIP-7702 authorization signer (optional, web only)\n * Must be called as a React hook (follows rules of hooks)\n */\n useAuthorizationSigner?():\n | ((\n auth: AuthorizationRequest<number>,\n ) => Promise<Authorization<number, true>>)\n | null;\n}\n"]}
@@ -1,6 +0,0 @@
1
- import type { PrivyAdapter } from "./types.js";
2
- /**
3
- * Web adapter for @privy-io/react-auth
4
- * Implements platform-specific hooks for React web applications
5
- */
6
- export declare const webAdapter: PrivyAdapter;
@@ -1,50 +0,0 @@
1
- import { useCallback } from "react";
2
- import { useWallets, usePrivy, useSign7702Authorization, } from "@privy-io/react-auth";
3
- /**
4
- * Web adapter for @privy-io/react-auth
5
- * Implements platform-specific hooks for React web applications
6
- */
7
- export const webAdapter = {
8
- useEmbeddedWallet() {
9
- const { wallets } = useWallets();
10
- const getEmbeddedWallet = useCallback(() => {
11
- const embedded = wallets.find((w) => w.walletClientType === "privy");
12
- if (!embedded) {
13
- throw new Error("Privy embedded wallet not found. Please ensure the user is authenticated.");
14
- }
15
- return adaptWebWallet(embedded);
16
- }, [wallets]);
17
- return getEmbeddedWallet;
18
- },
19
- usePrivyAuth() {
20
- const { user } = usePrivy();
21
- return { authenticated: !!user, user };
22
- },
23
- useAuthorizationSigner() {
24
- const { signAuthorization } = useSign7702Authorization();
25
- return useCallback(async (unsignedAuth) => {
26
- const signature = await signAuthorization({
27
- ...unsignedAuth,
28
- contractAddress: unsignedAuth.address ?? unsignedAuth.contractAddress,
29
- });
30
- return {
31
- ...unsignedAuth,
32
- ...signature,
33
- };
34
- }, [signAuthorization]);
35
- },
36
- };
37
- /**
38
- * Adapts a Privy web wallet to the common EmbeddedWallet interface
39
- *
40
- * @param {PrivyWallet} wallet - The Privy web wallet to adapt
41
- * @returns {EmbeddedWallet} The adapted wallet following the common interface
42
- */
43
- function adaptWebWallet(wallet) {
44
- return {
45
- address: wallet.address,
46
- chainId: wallet.chainId || "1",
47
- getEthereumProvider: () => wallet.getEthereumProvider(),
48
- };
49
- }
50
- //# sourceMappingURL=web.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"web.js","sourceRoot":"","sources":["../../../src/adapters/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EACL,UAAU,EACV,QAAQ,EACR,wBAAwB,GAEzB,MAAM,sBAAsB,CAAC;AAK9B;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAiB;IACtC,iBAAiB;QACf,MAAM,EAAE,OAAO,EAAE,GAAG,UAAU,EAAE,CAAC;QAEjC,MAAM,iBAAiB,GAAG,WAAW,CAAC,GAAmB,EAAE;YACzD,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB,KAAK,OAAO,CAAC,CAAC;YACrE,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CACb,2EAA2E,CAC5E,CAAC;YACJ,CAAC;YAED,OAAO,cAAc,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAEd,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,YAAY;QACV,MAAM,EAAE,IAAI,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC5B,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IACzC,CAAC;IAED,sBAAsB;QACpB,MAAM,EAAE,iBAAiB,EAAE,GAAG,wBAAwB,EAAE,CAAC;QAEzD,OAAO,WAAW,CAChB,KAAK,EACH,YAA0C,EACJ,EAAE;YACxC,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC;gBACxC,GAAG,YAAY;gBACf,eAAe,EAAE,YAAY,CAAC,OAAO,IAAI,YAAY,CAAC,eAAe;aACtE,CAAC,CAAC;YAEH,OAAO;gBACL,GAAG,YAAY;gBACf,GAAG,SAAS;aACb,CAAC;QACJ,CAAC,EACD,CAAC,iBAAiB,CAAC,CACpB,CAAC;IACJ,CAAC;CACF,CAAC;AAEF;;;;;GAKG;AACH,SAAS,cAAc,CAAC,MAAmB;IACzC,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAwB;QACxC,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,GAAG;QAC9B,mBAAmB,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,EAAE;KACxD,CAAC;AACJ,CAAC","sourcesContent":["import { useCallback } from \"react\";\nimport {\n useWallets,\n usePrivy,\n useSign7702Authorization,\n type ConnectedWallet as PrivyWallet,\n} from \"@privy-io/react-auth\";\nimport type { Authorization } from \"viem\";\nimport type { AuthorizationRequest } from \"@aa-sdk/core\";\nimport type { PrivyAdapter, EmbeddedWallet, PrivyAuthState } from \"./types.js\";\n\n/**\n * Web adapter for @privy-io/react-auth\n * Implements platform-specific hooks for React web applications\n */\nexport const webAdapter: PrivyAdapter = {\n useEmbeddedWallet() {\n const { wallets } = useWallets();\n\n const getEmbeddedWallet = useCallback((): EmbeddedWallet => {\n const embedded = wallets.find((w) => w.walletClientType === \"privy\");\n if (!embedded) {\n throw new Error(\n \"Privy embedded wallet not found. Please ensure the user is authenticated.\",\n );\n }\n\n return adaptWebWallet(embedded);\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 { signAuthorization } = useSign7702Authorization();\n\n return useCallback(\n 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 [signAuthorization],\n );\n },\n};\n\n/**\n * Adapts a Privy web wallet to the common EmbeddedWallet interface\n *\n * @param {PrivyWallet} wallet - The Privy web wallet to adapt\n * @returns {EmbeddedWallet} The adapted wallet following the common interface\n */\nfunction adaptWebWallet(wallet: PrivyWallet): EmbeddedWallet {\n return {\n address: wallet.address as `0x${string}`,\n chainId: wallet.chainId || \"1\",\n getEthereumProvider: () => wallet.getEthereumProvider(),\n };\n}\n"]}
@@ -1,62 +0,0 @@
1
- import { type PropsWithChildren } from "react";
2
- import type { SmartWalletClient } from "@account-kit/wallet-client";
3
- import type { AlchemyProviderConfig } from "../types.js";
4
- import type { PrivyAdapter } from "../adapters/types.js";
5
- /**
6
- * Client cache stored in React tree (similar to QueryClient in React Query)
7
- *
8
- * @internal
9
- */
10
- interface ClientCache {
11
- client: SmartWalletClient | null;
12
- cacheKey: string | null;
13
- }
14
- /**
15
- * Props for AlchemyContextProvider
16
- */
17
- interface AlchemyContextProviderProps extends PropsWithChildren {
18
- config: AlchemyProviderConfig;
19
- adapter: PrivyAdapter;
20
- }
21
- /**
22
- * Internal provider component that manages Alchemy context
23
- * Used by both web and React Native providers
24
- *
25
- * @internal
26
- * @param {AlchemyContextProviderProps} props - Component props
27
- * @param {React.ReactNode} props.children - React children to wrap with context
28
- * @param {AlchemyProviderConfig} props.config - Alchemy configuration
29
- * @param {PrivyAdapter} props.adapter - Platform adapter
30
- * @returns {JSX.Element} Context provider component
31
- */
32
- export declare function AlchemyContextProvider({ children, config, adapter, }: AlchemyContextProviderProps): import("react/jsx-runtime").JSX.Element;
33
- /**
34
- * Hook to access Alchemy provider configuration
35
- * Must be used within an <AlchemyProvider> component
36
- *
37
- * @returns {AlchemyProviderConfig} The current Alchemy configuration
38
- * @throws {Error} If used outside of AlchemyProvider
39
- *
40
- * @example
41
- * ```tsx
42
- * const config = useAlchemyConfig();
43
- * console.log('Policy ID:', config.policyId);
44
- * ```
45
- */
46
- export declare function useAlchemyConfig(): AlchemyProviderConfig;
47
- /**
48
- * Hook to access the platform adapter
49
- * Must be used within an <AlchemyProvider> component
50
- *
51
- * @internal
52
- * @returns {PrivyAdapter} The platform adapter
53
- */
54
- export declare function useAdapter(): PrivyAdapter;
55
- /**
56
- * Hook to access the client cache (internal use only)
57
- *
58
- * @internal
59
- * @returns {ClientCache} The client cache object
60
- */
61
- export declare function useClientCache(): ClientCache;
62
- export {};
@@ -1,105 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { createContext, useContext, useRef, useEffect, } from "react";
3
- /**
4
- * Context for Alchemy configuration
5
- */
6
- const AlchemyConfigContext = createContext(null);
7
- /**
8
- * Context for the platform adapter
9
- */
10
- const AdapterContext = createContext(null);
11
- const ClientCacheContext = createContext(null);
12
- /**
13
- * Internal provider component that manages Alchemy context
14
- * Used by both web and React Native providers
15
- *
16
- * @internal
17
- * @param {AlchemyContextProviderProps} props - Component props
18
- * @param {React.ReactNode} props.children - React children to wrap with context
19
- * @param {AlchemyProviderConfig} props.config - Alchemy configuration
20
- * @param {PrivyAdapter} props.adapter - Platform adapter
21
- * @returns {JSX.Element} Context provider component
22
- */
23
- export function AlchemyContextProvider({ children, config, adapter, }) {
24
- const { authenticated, user } = adapter.usePrivyAuth();
25
- // Store cache in a ref - persists across renders but scoped to this component instance
26
- // This makes it SSR-safe (each request gets its own cache) and React StrictMode-safe
27
- const cache = useRef({
28
- client: null,
29
- cacheKey: null,
30
- });
31
- // Track previous state to detect logout and wallet changes
32
- const prevAuthenticatedRef = useRef(authenticated);
33
- const prevWalletAddressRef = useRef(user?.wallet?.address);
34
- // Automatically reset cache when user logs out or switches wallets
35
- useEffect(() => {
36
- const wasAuthenticated = prevAuthenticatedRef.current;
37
- const prevWalletAddress = prevWalletAddressRef.current;
38
- const currentWalletAddress = user?.wallet?.address;
39
- // Reset cache on logout
40
- if (wasAuthenticated && !authenticated) {
41
- cache.current.client = null;
42
- cache.current.cacheKey = null;
43
- }
44
- // Reset cache on wallet address change (account switching)
45
- if (authenticated &&
46
- prevWalletAddress &&
47
- currentWalletAddress &&
48
- prevWalletAddress !== currentWalletAddress) {
49
- cache.current.client = null;
50
- cache.current.cacheKey = null;
51
- }
52
- // Update refs for next render
53
- prevAuthenticatedRef.current = authenticated;
54
- prevWalletAddressRef.current = currentWalletAddress;
55
- }, [authenticated, user?.wallet?.address]);
56
- return (_jsx(AlchemyConfigContext.Provider, { value: config, children: _jsx(AdapterContext.Provider, { value: adapter, children: _jsx(ClientCacheContext.Provider, { value: cache.current, children: children }) }) }));
57
- }
58
- /**
59
- * Hook to access Alchemy provider configuration
60
- * Must be used within an <AlchemyProvider> component
61
- *
62
- * @returns {AlchemyProviderConfig} The current Alchemy configuration
63
- * @throws {Error} If used outside of AlchemyProvider
64
- *
65
- * @example
66
- * ```tsx
67
- * const config = useAlchemyConfig();
68
- * console.log('Policy ID:', config.policyId);
69
- * ```
70
- */
71
- export function useAlchemyConfig() {
72
- const context = useContext(AlchemyConfigContext);
73
- if (!context) {
74
- throw new Error("useAlchemyConfig must be used within <AlchemyProvider />");
75
- }
76
- return context;
77
- }
78
- /**
79
- * Hook to access the platform adapter
80
- * Must be used within an <AlchemyProvider> component
81
- *
82
- * @internal
83
- * @returns {PrivyAdapter} The platform adapter
84
- */
85
- export function useAdapter() {
86
- const context = useContext(AdapterContext);
87
- if (!context) {
88
- throw new Error("useAdapter must be used within <AlchemyProvider />. Make sure AlchemyProvider is nested inside PrivyProvider.");
89
- }
90
- return context;
91
- }
92
- /**
93
- * Hook to access the client cache (internal use only)
94
- *
95
- * @internal
96
- * @returns {ClientCache} The client cache object
97
- */
98
- export function useClientCache() {
99
- const context = useContext(ClientCacheContext);
100
- if (!context) {
101
- throw new Error("useClientCache must be used within <AlchemyProvider />. Make sure AlchemyProvider is nested inside PrivyProvider.");
102
- }
103
- return context;
104
- }
105
- //# sourceMappingURL=AlchemyContext.js.map