@account-kit/privy-integration 4.73.1-alpha.1 → 4.73.1-alpha.11

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 (43) hide show
  1. package/dist/esm/Provider.native.d.ts +6 -0
  2. package/dist/esm/Provider.native.js +13 -0
  3. package/dist/esm/Provider.native.js.map +1 -0
  4. package/dist/esm/adapters/react-native.js +49 -37
  5. package/dist/esm/adapters/react-native.js.map +1 -1
  6. package/dist/esm/adapters/web.native.d.ts +5 -0
  7. package/dist/esm/adapters/web.native.js +6 -0
  8. package/dist/esm/adapters/web.native.js.map +1 -0
  9. package/dist/esm/hooks/useAlchemyClient.js +11 -10
  10. package/dist/esm/hooks/useAlchemyClient.js.map +1 -1
  11. package/dist/esm/hooks/useAlchemySendTransaction.js +1 -1
  12. package/dist/esm/hooks/useAlchemySendTransaction.js.map +1 -1
  13. package/dist/esm/hooks/useAlchemySolanaTransaction.js +1 -1
  14. package/dist/esm/hooks/useAlchemySolanaTransaction.js.map +1 -1
  15. package/dist/esm/providers/WebProvider.native.d.ts +5 -0
  16. package/dist/esm/providers/WebProvider.native.js +9 -0
  17. package/dist/esm/providers/WebProvider.native.js.map +1 -0
  18. package/dist/esm/version.d.ts +1 -1
  19. package/dist/esm/version.js +1 -1
  20. package/dist/esm/version.js.map +1 -1
  21. package/dist/types/Provider.native.d.ts +7 -0
  22. package/dist/types/Provider.native.d.ts.map +1 -0
  23. package/dist/types/adapters/react-native.d.ts.map +1 -1
  24. package/dist/types/adapters/web.native.d.ts +6 -0
  25. package/dist/types/adapters/web.native.d.ts.map +1 -0
  26. package/dist/types/hooks/useAlchemyClient.d.ts.map +1 -1
  27. package/dist/types/providers/WebProvider.native.d.ts +6 -0
  28. package/dist/types/providers/WebProvider.native.d.ts.map +1 -0
  29. package/dist/types/version.d.ts +1 -1
  30. package/dist/types/version.d.ts.map +1 -1
  31. package/package.json +14 -4
  32. package/src/Provider.native.tsx +18 -0
  33. package/src/Provider.tsx +6 -0
  34. package/src/adapters/react-native.ts +102 -78
  35. package/src/adapters/web.native.ts +6 -0
  36. package/src/context/AlchemyContext.tsx +162 -0
  37. package/src/hooks/useAlchemyClient.ts +17 -11
  38. package/src/hooks/useAlchemySendTransaction.ts +1 -1
  39. package/src/hooks/useAlchemySolanaTransaction.ts +1 -1
  40. package/src/providers/ReactNativeProvider.tsx +45 -0
  41. package/src/providers/WebProvider.native.tsx +11 -0
  42. package/src/providers/WebProvider.tsx +45 -0
  43. package/src/version.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@account-kit/privy-integration",
3
- "version": "4.73.1-alpha.1",
3
+ "version": "4.73.1-alpha.11",
4
4
  "description": "Use Alchemy gas sponsorship, swaps and more with Privy",
5
5
  "author": "Alchemy",
6
6
  "license": "MIT",
@@ -11,9 +11,18 @@
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
+ },
14
22
  "files": [
15
23
  "dist",
16
24
  "src/**/*.ts",
25
+ "src/**/*.tsx",
17
26
  "!dist/**/*.tsbuildinfo",
18
27
  "!vitest.config.ts",
19
28
  "!.env",
@@ -23,6 +32,7 @@
23
32
  ],
24
33
  "exports": {
25
34
  ".": {
35
+ "react-native": "./dist/esm/react-native.js",
26
36
  "types": "./dist/types/index.d.ts",
27
37
  "import": "./dist/esm/index.js",
28
38
  "default": "./dist/esm/index.js"
@@ -54,8 +64,8 @@
54
64
  "typescript-template": "*"
55
65
  },
56
66
  "dependencies": {
57
- "@account-kit/infra": "^4.73.1-alpha.1",
58
- "@account-kit/wallet-client": "^4.73.1-alpha.1"
67
+ "@account-kit/infra": "^4.73.1-alpha.11",
68
+ "@account-kit/wallet-client": "^4.73.1-alpha.11"
59
69
  },
60
70
  "peerDependencies": {
61
71
  "@privy-io/expo": "^0.58.0",
@@ -85,5 +95,5 @@
85
95
  "url": "https://github.com/alchemyplatform/aa-sdk/issues"
86
96
  },
87
97
  "homepage": "https://github.com/alchemyplatform/aa-sdk#readme",
88
- "gitHead": "03b2f5bff3d97e39f0be09eeaa6eb1f5a51631c6"
98
+ "gitHead": "29d8866afdb4f5019403ef0897bd13f88dcfa2b4"
89
99
  }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * React Native stub for web Provider
3
+ * This file prevents Metro from importing web-specific code
4
+ */
5
+
6
+ export function AlchemyProvider() {
7
+ throw new Error(
8
+ "Web Provider is not available in React Native. " +
9
+ 'Import from "@account-kit/privy-integration/react-native" instead.',
10
+ );
11
+ }
12
+
13
+ export function useAlchemyConfig() {
14
+ throw new Error(
15
+ "useAlchemyConfig from web Provider is not available in React Native. " +
16
+ 'Import from "@account-kit/privy-integration/react-native" instead.',
17
+ );
18
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Web-specific exports
3
+ * Re-exports the web provider and hooks for React applications
4
+ */
5
+ export { AlchemyProvider } from "./providers/WebProvider.js";
6
+ export { useAlchemyConfig } from "./context/AlchemyContext.js";
@@ -5,6 +5,8 @@ import {
5
5
  type PrivyEmbeddedWalletProvider,
6
6
  } from "@privy-io/expo";
7
7
  import type { Authorization } from "viem";
8
+ import { hashAuthorization } from "viem/utils";
9
+ import { parseSignature } from "viem";
8
10
  import type { AuthorizationRequest } from "@aa-sdk/core";
9
11
  import type { PrivyAdapter, EmbeddedWallet, PrivyAuthState } from "./types.js";
10
12
 
@@ -48,82 +50,78 @@ export const reactNativeAdapter: PrivyAdapter = {
48
50
  useAuthorizationSigner() {
49
51
  const { wallets } = useEmbeddedEthereumWallet();
50
52
 
51
- return useCallback(
52
- async (
53
- unsignedAuth: AuthorizationRequest<number>,
54
- ): Promise<Authorization<number, true>> => {
55
- const wallet = wallets?.[0];
56
- if (!wallet) {
57
- throw new Error(
58
- "Privy embedded wallet not found. Please ensure the user is authenticated and has created a wallet.",
59
- );
60
- }
61
-
62
- const provider = await wallet.getProvider?.();
63
- if (!provider) {
64
- throw new Error(
65
- "Provider not available on this wallet. Ensure you're using the embedded Ethereum wallet.",
66
- );
67
- }
68
-
69
- // Extract the implementation address (handle both 'address' and 'contractAddress' fields)
70
- const implementationAddress =
71
- unsignedAuth.address ?? unsignedAuth.contractAddress;
72
-
73
- if (!implementationAddress) {
74
- throw new Error(
75
- "Implementation address is required for EIP-7702 authorization",
76
- );
77
- }
78
-
79
- // EIP-7702 Authorization structure
80
- const authorization = {
81
- domain: {
82
- name: "EIP-7702",
83
- version: "1",
84
- chainId: unsignedAuth.chainId,
85
- },
86
- types: {
87
- Authorization: [
88
- { name: "chainId", type: "uint256" },
89
- { name: "address", type: "address" },
90
- { name: "nonce", type: "uint256" },
91
- ],
92
- },
93
- primaryType: "Authorization" as const,
94
- message: {
95
- chainId: unsignedAuth.chainId,
96
- address: implementationAddress,
97
- nonce: unsignedAuth.nonce,
98
- },
99
- };
100
-
101
- const signature = (await provider.request({
102
- method: "eth_signTypedData_v4",
103
- params: [wallet.address, JSON.stringify(authorization)],
104
- })) as `0x${string}`;
105
-
106
- // Parse the signature into r, s, v components
107
- // Signature format: 0x[r(64)][s(64)][v(2)]
108
- const r = `0x${signature.slice(2, 66)}` as `0x${string}`;
109
- const s = `0x${signature.slice(66, 130)}` as `0x${string}`;
110
- const v = parseInt(signature.slice(130, 132), 16);
111
-
112
- // Convert v to yParity (0 or 1)
113
- // v can be 27/28 (legacy) or 0/1 (EIP-155)
114
- const yParity = v >= 27 ? v - 27 : v;
115
-
116
- return {
117
- chainId: unsignedAuth.chainId,
118
- address: implementationAddress,
119
- nonce: unsignedAuth.nonce,
120
- r,
121
- s,
122
- yParity,
123
- };
124
- },
125
- [wallets],
126
- );
53
+ // Don't memoize the callback - create it fresh each time to ensure we have the latest wallets
54
+ const signAuthorization = async (
55
+ unsignedAuth: AuthorizationRequest<number>,
56
+ ): Promise<Authorization<number, true>> => {
57
+ console.log("[RN Adapter] signAuthorization called with:", unsignedAuth);
58
+ console.log("[RN Adapter] Current wallets:", wallets);
59
+
60
+ const wallet = wallets?.[0];
61
+ if (!wallet) {
62
+ throw new Error(
63
+ "Privy embedded wallet not found. Please ensure the user is authenticated and has created a wallet.",
64
+ );
65
+ }
66
+
67
+ console.log("[RN Adapter] Using wallet:", wallet.address);
68
+
69
+ const provider = await wallet.getProvider?.();
70
+ if (!provider) {
71
+ throw new Error(
72
+ "Provider not available on this wallet. Ensure you're using the embedded Ethereum wallet.",
73
+ );
74
+ }
75
+
76
+ // Extract the implementation address (handle both 'address' and 'contractAddress' fields)
77
+ const implementationAddress =
78
+ unsignedAuth.address ?? unsignedAuth.contractAddress;
79
+
80
+ if (!implementationAddress) {
81
+ throw new Error(
82
+ "Implementation address is required for EIP-7702 authorization",
83
+ );
84
+ }
85
+
86
+ console.log(
87
+ "[RN Adapter] Signing 7702 auth for address:",
88
+ implementationAddress,
89
+ );
90
+
91
+ // Create the authorization structure (matches Privy's implementation)
92
+ const authorization = {
93
+ chainId: unsignedAuth.chainId,
94
+ address: implementationAddress,
95
+ nonce: unsignedAuth.nonce,
96
+ };
97
+
98
+ // Hash the authorization using viem (same as Privy does)
99
+ const authorizationHash = hashAuthorization(authorization);
100
+ console.log("[RN Adapter] Authorization hash:", authorizationHash);
101
+
102
+ // Sign the hash directly with secp256k1_sign (same as Privy)
103
+ const signature = (await provider.request({
104
+ method: "secp256k1_sign",
105
+ params: [authorizationHash],
106
+ })) as `0x${string}`;
107
+
108
+ console.log("[RN Adapter] Received signature:", signature);
109
+
110
+ // Parse the signature using viem (same as Privy)
111
+ const parsedSignature = parseSignature(signature);
112
+
113
+ const result = {
114
+ chainId: unsignedAuth.chainId,
115
+ address: implementationAddress,
116
+ nonce: unsignedAuth.nonce,
117
+ ...parsedSignature,
118
+ };
119
+
120
+ console.log("[RN Adapter] Returning authorization:", result);
121
+ return result;
122
+ };
123
+
124
+ return signAuthorization;
127
125
  },
128
126
  };
129
127
 
@@ -134,16 +132,42 @@ export const reactNativeAdapter: PrivyAdapter = {
134
132
  * @returns {EmbeddedWallet} The adapted wallet following the common interface
135
133
  */
136
134
  function adaptExpoWallet(wallet: ExpoEmbeddedWallet): EmbeddedWallet {
135
+ // Use closure to maintain up-to-date chain ID across chain switches
136
+ let cachedChainId = wallet.chainId || "1";
137
+
137
138
  return {
138
139
  address: wallet.address as `0x${string}`,
139
- chainId: wallet.chainId || "1",
140
+ get chainId() {
141
+ return cachedChainId;
142
+ },
140
143
  getEthereumProvider: async () => {
141
144
  if (!wallet.getProvider) {
142
145
  throw new Error(
143
146
  "getProvider is not available on this wallet. Ensure you're using the embedded Ethereum wallet.",
144
147
  );
145
148
  }
146
- return await wallet.getProvider();
149
+ const provider = await wallet.getProvider();
150
+
151
+ // Always fetch current chain ID when provider is accessed
152
+ // This ensures we have the latest chain after wallet_switchEthereumChain calls
153
+ try {
154
+ const currentChainId = (await provider.request({
155
+ method: "eth_chainId",
156
+ params: [],
157
+ })) as string;
158
+
159
+ // Convert hex to decimal string format (e.g., "0x1" -> "1")
160
+ cachedChainId = parseInt(currentChainId, 16).toString();
161
+ console.log("[RN Adapter] Updated chain ID to:", cachedChainId);
162
+ } catch (err) {
163
+ console.warn(
164
+ "[Privy Integration] Failed to fetch current chain ID:",
165
+ err,
166
+ );
167
+ // Fall back to cached value if fetch fails
168
+ }
169
+
170
+ return provider;
147
171
  },
148
172
  };
149
173
  }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * React Native stub for web adapter
3
+ * This file prevents Metro from importing @privy-io/react-auth
4
+ */
5
+
6
+ export const webAdapter = null;
@@ -0,0 +1,162 @@
1
+ import {
2
+ type PropsWithChildren,
3
+ createContext,
4
+ useContext,
5
+ useRef,
6
+ useEffect,
7
+ } from "react";
8
+ import type { SmartWalletClient } from "@account-kit/wallet-client";
9
+ import type { AlchemyProviderConfig } from "../types.js";
10
+ import type { PrivyAdapter } from "../adapters/types.js";
11
+
12
+ /**
13
+ * Context for Alchemy configuration
14
+ */
15
+ const AlchemyConfigContext = createContext<AlchemyProviderConfig | null>(null);
16
+
17
+ /**
18
+ * Context for the platform adapter
19
+ */
20
+ const AdapterContext = createContext<PrivyAdapter | null>(null);
21
+
22
+ /**
23
+ * Client cache stored in React tree (similar to QueryClient in React Query)
24
+ *
25
+ * @internal
26
+ */
27
+ interface ClientCache {
28
+ client: SmartWalletClient | null;
29
+ cacheKey: string | null;
30
+ }
31
+
32
+ const ClientCacheContext = createContext<ClientCache | null>(null);
33
+
34
+ /**
35
+ * Props for AlchemyContextProvider
36
+ */
37
+ interface AlchemyContextProviderProps extends PropsWithChildren {
38
+ config: AlchemyProviderConfig;
39
+ adapter: PrivyAdapter;
40
+ }
41
+
42
+ /**
43
+ * Internal provider component that manages Alchemy context
44
+ * Used by both web and React Native providers
45
+ *
46
+ * @internal
47
+ * @param {AlchemyContextProviderProps} props - Component props
48
+ * @param {React.ReactNode} props.children - React children to wrap with context
49
+ * @param {AlchemyProviderConfig} props.config - Alchemy configuration
50
+ * @param {PrivyAdapter} props.adapter - Platform adapter
51
+ * @returns {JSX.Element} Context provider component
52
+ */
53
+ export function AlchemyContextProvider({
54
+ children,
55
+ config,
56
+ adapter,
57
+ }: AlchemyContextProviderProps) {
58
+ const { authenticated, user } = adapter.usePrivyAuth();
59
+
60
+ // Store cache in a ref - persists across renders but scoped to this component instance
61
+ // This makes it SSR-safe (each request gets its own cache) and React StrictMode-safe
62
+ const cache = useRef<ClientCache>({
63
+ client: null,
64
+ cacheKey: null,
65
+ });
66
+
67
+ // Track previous state to detect logout and wallet changes
68
+ const prevAuthenticatedRef = useRef(authenticated);
69
+ const prevWalletAddressRef = useRef(user?.wallet?.address);
70
+
71
+ // Automatically reset cache when user logs out or switches wallets
72
+ useEffect(() => {
73
+ const wasAuthenticated = prevAuthenticatedRef.current;
74
+ const prevWalletAddress = prevWalletAddressRef.current;
75
+ const currentWalletAddress = user?.wallet?.address;
76
+
77
+ // Reset cache on logout
78
+ if (wasAuthenticated && !authenticated) {
79
+ cache.current.client = null;
80
+ cache.current.cacheKey = null;
81
+ }
82
+
83
+ // Reset cache on wallet address change (account switching)
84
+ if (
85
+ authenticated &&
86
+ prevWalletAddress &&
87
+ currentWalletAddress &&
88
+ prevWalletAddress !== currentWalletAddress
89
+ ) {
90
+ cache.current.client = null;
91
+ cache.current.cacheKey = null;
92
+ }
93
+
94
+ // Update refs for next render
95
+ prevAuthenticatedRef.current = authenticated;
96
+ prevWalletAddressRef.current = currentWalletAddress;
97
+ }, [authenticated, user?.wallet?.address]);
98
+
99
+ return (
100
+ <AlchemyConfigContext.Provider value={config}>
101
+ <AdapterContext.Provider value={adapter}>
102
+ <ClientCacheContext.Provider value={cache.current}>
103
+ {children}
104
+ </ClientCacheContext.Provider>
105
+ </AdapterContext.Provider>
106
+ </AlchemyConfigContext.Provider>
107
+ );
108
+ }
109
+
110
+ /**
111
+ * Hook to access Alchemy provider configuration
112
+ * Must be used within an <AlchemyProvider> component
113
+ *
114
+ * @returns {AlchemyProviderConfig} The current Alchemy configuration
115
+ * @throws {Error} If used outside of AlchemyProvider
116
+ *
117
+ * @example
118
+ * ```tsx
119
+ * const config = useAlchemyConfig();
120
+ * console.log('Policy ID:', config.policyId);
121
+ * ```
122
+ */
123
+ export function useAlchemyConfig(): AlchemyProviderConfig {
124
+ const context = useContext(AlchemyConfigContext);
125
+ if (!context) {
126
+ throw new Error("useAlchemyConfig must be used within <AlchemyProvider />");
127
+ }
128
+ return context;
129
+ }
130
+
131
+ /**
132
+ * Hook to access the platform adapter
133
+ * Must be used within an <AlchemyProvider> component
134
+ *
135
+ * @internal
136
+ * @returns {PrivyAdapter} The platform adapter
137
+ */
138
+ export function useAdapter(): PrivyAdapter {
139
+ const context = useContext(AdapterContext);
140
+ if (!context) {
141
+ throw new Error(
142
+ "useAdapter must be used within <AlchemyProvider />. Make sure AlchemyProvider is nested inside PrivyProvider.",
143
+ );
144
+ }
145
+ return context;
146
+ }
147
+
148
+ /**
149
+ * Hook to access the client cache (internal use only)
150
+ *
151
+ * @internal
152
+ * @returns {ClientCache} The client cache object
153
+ */
154
+ export function useClientCache(): ClientCache {
155
+ const context = useContext(ClientCacheContext);
156
+ if (!context) {
157
+ throw new Error(
158
+ "useClientCache must be used within <AlchemyProvider />. Make sure AlchemyProvider is nested inside PrivyProvider.",
159
+ );
160
+ }
161
+ return context;
162
+ }
@@ -34,10 +34,16 @@ export function useAlchemyClient() {
34
34
  const cache = useClientCache();
35
35
  const getEmbeddedWallet = useEmbeddedWallet();
36
36
 
37
- const getEmbeddedWalletChain = useCallback(() => {
38
- const embedded = getEmbeddedWallet();
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
39
45
  // Handle CAIP-2 format like "eip155:1"
40
- const chainIdStr = embedded.chainId?.toString();
46
+ const chainIdStr = embeddedWallet.chainId?.toString();
41
47
 
42
48
  if (!chainIdStr) {
43
49
  throw new Error(
@@ -57,14 +63,10 @@ export function useAlchemyClient() {
57
63
  );
58
64
  }
59
65
 
60
- return getChain(parsedChainId);
61
- }, [getEmbeddedWallet]);
62
-
63
- const getClient = useCallback(async (): Promise<SmartWalletClient> => {
64
- const embeddedWallet = getEmbeddedWallet();
65
- const chain = getEmbeddedWalletChain();
66
+ const chain = getChain(parsedChainId);
66
67
 
67
68
  // Generate a cache key based on configuration and wallet address
69
+ // IMPORTANT: Include whether authorization signer is available in cache key
68
70
  const currentCacheKey = JSON.stringify({
69
71
  address: embeddedWallet.address,
70
72
  chainId: chain.id,
@@ -72,6 +74,7 @@ export function useAlchemyClient() {
72
74
  jwt: config.jwt,
73
75
  rpcUrl: config.rpcUrl,
74
76
  policyId: config.policyId,
77
+ hasAuthSigner: !!signAuthorizationFn,
75
78
  });
76
79
 
77
80
  // Return cached client if configuration hasn't changed
@@ -80,7 +83,6 @@ export function useAlchemyClient() {
80
83
  }
81
84
 
82
85
  // Configuration changed or no cache exists, create new client
83
- const provider = await embeddedWallet.getEthereumProvider();
84
86
 
85
87
  // Create base signer from Privy wallet
86
88
  const baseSigner = new WalletClientSigner(
@@ -100,6 +102,11 @@ export function useAlchemyClient() {
100
102
  }
101
103
  : baseSigner;
102
104
 
105
+ console.log(
106
+ "[useAlchemyClient] Created signer with authorization support:",
107
+ !!signAuthorizationFn,
108
+ );
109
+
103
110
  // Determine transport configuration using schema validation
104
111
  // This properly handles combinations like rpcUrl + jwt together
105
112
  const transportConfig = ConnectionConfigSchema.parse({
@@ -132,7 +139,6 @@ export function useAlchemyClient() {
132
139
  return cache.client;
133
140
  }, [
134
141
  getEmbeddedWallet,
135
- getEmbeddedWalletChain,
136
142
  signAuthorizationFn,
137
143
  config.apiKey,
138
144
  config.jwt,
@@ -1,7 +1,7 @@
1
1
  import { useCallback, useState } from "react";
2
2
  import { type Address, type Hex, isHex } from "viem";
3
3
  import { useAlchemyClient } from "./useAlchemyClient.js";
4
- import { useAlchemyConfig } from "../Provider.js";
4
+ import { useAlchemyConfig } from "../context/AlchemyContext.js";
5
5
  import { useEmbeddedWallet } from "./internal/useEmbeddedWallet.js";
6
6
  import type {
7
7
  UnsignedTransactionRequest,
@@ -7,7 +7,7 @@ import {
7
7
  TransactionInstruction,
8
8
  VersionedTransaction,
9
9
  } from "@solana/web3.js";
10
- import { useAlchemyConfig } from "../Provider.js";
10
+ import { useAlchemyConfig } from "../context/AlchemyContext.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";
@@ -0,0 +1,45 @@
1
+ import type { PropsWithChildren } from "react";
2
+ import { AlchemyContextProvider } from "../context/AlchemyContext.js";
3
+ import { reactNativeAdapter } from "../adapters/react-native.js";
4
+ import type { AlchemyProviderConfig } from "../types.js";
5
+
6
+ /**
7
+ * Provider component for React Native (Expo) applications
8
+ * Must be nested INSIDE PrivyProvider from @privy-io/expo
9
+ *
10
+ * @param {PropsWithChildren<AlchemyProviderConfig>} props - Component props
11
+ * @param {React.ReactNode} props.children - React children to wrap with Alchemy configuration
12
+ * @param {string} [props.apiKey] - Your Alchemy API key
13
+ * @param {string} [props.jwt] - JWT token for authentication
14
+ * @param {string} [props.rpcUrl] - Custom RPC URL for EVM chains
15
+ * @param {string} [props.solanaRpcUrl] - Custom RPC URL for Solana
16
+ * @param {string | string[]} [props.policyId] - Gas Manager policy ID(s) for EVM chains
17
+ * @param {string | string[]} [props.solanaPolicyId] - Gas Manager policy ID(s) for Solana
18
+ * @param {boolean} [props.disableSponsorship] - Set to true to disable sponsorship by default (default: false)
19
+ * @returns {JSX.Element} Provider component
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * import { PrivyProvider } from '@privy-io/expo';
24
+ * import { AlchemyProvider } from '@account-kit/privy-integration/react-native';
25
+ *
26
+ * <PrivyProvider appId="..." clientId="...">
27
+ * <AlchemyProvider
28
+ * apiKey="your-alchemy-api-key"
29
+ * policyId="your-gas-policy-id"
30
+ * >
31
+ * <YourApp />
32
+ * </AlchemyProvider>
33
+ * </PrivyProvider>
34
+ * ```
35
+ */
36
+ export function AlchemyProvider({
37
+ children,
38
+ ...config
39
+ }: PropsWithChildren<AlchemyProviderConfig>) {
40
+ return (
41
+ <AlchemyContextProvider config={config} adapter={reactNativeAdapter}>
42
+ {children}
43
+ </AlchemyContextProvider>
44
+ );
45
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * React Native stub for WebProvider
3
+ * This file prevents Metro from importing web-specific code
4
+ */
5
+
6
+ export function AlchemyProvider() {
7
+ throw new Error(
8
+ "WebProvider is not available in React Native. " +
9
+ 'Import from "@account-kit/privy-integration/react-native" instead.',
10
+ );
11
+ }
@@ -0,0 +1,45 @@
1
+ import type { PropsWithChildren } from "react";
2
+ import { AlchemyContextProvider } from "../context/AlchemyContext.js";
3
+ import { webAdapter } from "../adapters/web.js";
4
+ import type { AlchemyProviderConfig } from "../types.js";
5
+
6
+ /**
7
+ * Provider component for React web applications
8
+ * Must be nested INSIDE PrivyProvider from @privy-io/react-auth
9
+ *
10
+ * @param {PropsWithChildren<AlchemyProviderConfig>} props - Component props
11
+ * @param {React.ReactNode} props.children - React children to wrap with Alchemy configuration
12
+ * @param {string} [props.apiKey] - Your Alchemy API key
13
+ * @param {string} [props.jwt] - JWT token for authentication
14
+ * @param {string} [props.rpcUrl] - Custom RPC URL for EVM chains
15
+ * @param {string} [props.solanaRpcUrl] - Custom RPC URL for Solana
16
+ * @param {string | string[]} [props.policyId] - Gas Manager policy ID(s) for EVM chains
17
+ * @param {string | string[]} [props.solanaPolicyId] - Gas Manager policy ID(s) for Solana
18
+ * @param {boolean} [props.disableSponsorship] - Set to true to disable sponsorship by default (default: false)
19
+ * @returns {JSX.Element} Provider component
20
+ *
21
+ * @example
22
+ * ```tsx
23
+ * import { PrivyProvider } from '@privy-io/react-auth';
24
+ * import { AlchemyProvider } from '@account-kit/privy-integration';
25
+ *
26
+ * <PrivyProvider appId="...">
27
+ * <AlchemyProvider
28
+ * apiKey="your-alchemy-api-key"
29
+ * policyId="your-gas-policy-id"
30
+ * >
31
+ * <YourApp />
32
+ * </AlchemyProvider>
33
+ * </PrivyProvider>
34
+ * ```
35
+ */
36
+ export function AlchemyProvider({
37
+ children,
38
+ ...config
39
+ }: PropsWithChildren<AlchemyProviderConfig>) {
40
+ return (
41
+ <AlchemyContextProvider config={config} adapter={webAdapter}>
42
+ {children}
43
+ </AlchemyContextProvider>
44
+ );
45
+ }
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.1";
3
+ export const VERSION = "4.73.1-alpha.11";