@account-kit/privy-integration 4.73.1-alpha.1 → 4.73.1-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/Provider.native.d.ts +6 -0
- package/dist/esm/Provider.native.js +13 -0
- package/dist/esm/Provider.native.js.map +1 -0
- package/dist/esm/adapters/react-native.js +34 -5
- package/dist/esm/adapters/react-native.js.map +1 -1
- package/dist/esm/adapters/web.native.d.ts +5 -0
- package/dist/esm/adapters/web.native.js +6 -0
- package/dist/esm/adapters/web.native.js.map +1 -0
- package/dist/esm/hooks/useAlchemyClient.js +11 -10
- package/dist/esm/hooks/useAlchemyClient.js.map +1 -1
- package/dist/esm/hooks/useAlchemySendTransaction.js +1 -1
- package/dist/esm/hooks/useAlchemySendTransaction.js.map +1 -1
- package/dist/esm/hooks/useAlchemySolanaTransaction.js +1 -1
- package/dist/esm/hooks/useAlchemySolanaTransaction.js.map +1 -1
- package/dist/esm/providers/WebProvider.native.d.ts +5 -0
- package/dist/esm/providers/WebProvider.native.js +9 -0
- package/dist/esm/providers/WebProvider.native.js.map +1 -0
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/version.js.map +1 -1
- package/dist/types/Provider.native.d.ts +7 -0
- package/dist/types/Provider.native.d.ts.map +1 -0
- package/dist/types/adapters/react-native.d.ts.map +1 -1
- package/dist/types/adapters/web.native.d.ts +6 -0
- package/dist/types/adapters/web.native.d.ts.map +1 -0
- package/dist/types/hooks/useAlchemyClient.d.ts.map +1 -1
- package/dist/types/providers/WebProvider.native.d.ts +6 -0
- package/dist/types/providers/WebProvider.native.d.ts.map +1 -0
- package/dist/types/version.d.ts +1 -1
- package/dist/types/version.d.ts.map +1 -1
- package/package.json +14 -4
- package/src/Provider.native.tsx +18 -0
- package/src/Provider.tsx +6 -0
- package/src/adapters/react-native.ts +116 -75
- package/src/adapters/web.native.ts +6 -0
- package/src/context/AlchemyContext.tsx +162 -0
- package/src/hooks/useAlchemyClient.ts +17 -11
- package/src/hooks/useAlchemySendTransaction.ts +1 -1
- package/src/hooks/useAlchemySolanaTransaction.ts +1 -1
- package/src/providers/ReactNativeProvider.tsx +45 -0
- package/src/providers/WebProvider.native.tsx +11 -0
- package/src/providers/WebProvider.tsx +45 -0
- package/src/version.ts +1 -1
|
@@ -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
|
+
}
|
package/src/Provider.tsx
ADDED
|
@@ -48,82 +48,97 @@ export const reactNativeAdapter: PrivyAdapter = {
|
|
|
48
48
|
useAuthorizationSigner() {
|
|
49
49
|
const { wallets } = useEmbeddedEthereumWallet();
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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 {
|
|
51
|
+
// Don't memoize the callback - create it fresh each time to ensure we have the latest wallets
|
|
52
|
+
const signAuthorization = async (
|
|
53
|
+
unsignedAuth: AuthorizationRequest<number>,
|
|
54
|
+
): Promise<Authorization<number, true>> => {
|
|
55
|
+
console.log("[RN Adapter] signAuthorization called with:", unsignedAuth);
|
|
56
|
+
console.log("[RN Adapter] Current wallets:", wallets);
|
|
57
|
+
|
|
58
|
+
const wallet = wallets?.[0];
|
|
59
|
+
if (!wallet) {
|
|
60
|
+
throw new Error(
|
|
61
|
+
"Privy embedded wallet not found. Please ensure the user is authenticated and has created a wallet.",
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
console.log("[RN Adapter] Using wallet:", wallet.address);
|
|
66
|
+
|
|
67
|
+
const provider = await wallet.getProvider?.();
|
|
68
|
+
if (!provider) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
"Provider not available on this wallet. Ensure you're using the embedded Ethereum wallet.",
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Extract the implementation address (handle both 'address' and 'contractAddress' fields)
|
|
75
|
+
const implementationAddress =
|
|
76
|
+
unsignedAuth.address ?? unsignedAuth.contractAddress;
|
|
77
|
+
|
|
78
|
+
if (!implementationAddress) {
|
|
79
|
+
throw new Error(
|
|
80
|
+
"Implementation address is required for EIP-7702 authorization",
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
console.log(
|
|
85
|
+
"[RN Adapter] Signing 7702 auth for address:",
|
|
86
|
+
implementationAddress,
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
// EIP-7702 Authorization structure
|
|
90
|
+
const authorization = {
|
|
91
|
+
domain: {
|
|
92
|
+
name: "EIP-7702",
|
|
93
|
+
version: "1",
|
|
94
|
+
chainId: unsignedAuth.chainId,
|
|
95
|
+
},
|
|
96
|
+
types: {
|
|
97
|
+
Authorization: [
|
|
98
|
+
{ name: "chainId", type: "uint256" },
|
|
99
|
+
{ name: "address", type: "address" },
|
|
100
|
+
{ name: "nonce", type: "uint256" },
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
primaryType: "Authorization" as const,
|
|
104
|
+
message: {
|
|
117
105
|
chainId: unsignedAuth.chainId,
|
|
118
106
|
address: implementationAddress,
|
|
119
107
|
nonce: unsignedAuth.nonce,
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const signature = (await provider.request({
|
|
112
|
+
method: "eth_signTypedData_v4",
|
|
113
|
+
params: [wallet.address, JSON.stringify(authorization)],
|
|
114
|
+
})) as `0x${string}`;
|
|
115
|
+
|
|
116
|
+
console.log("[RN Adapter] Received signature:", signature);
|
|
117
|
+
|
|
118
|
+
// Parse the signature into r, s, v components
|
|
119
|
+
// Signature format: 0x[r(64)][s(64)][v(2)]
|
|
120
|
+
const r = `0x${signature.slice(2, 66)}` as `0x${string}`;
|
|
121
|
+
const s = `0x${signature.slice(66, 130)}` as `0x${string}`;
|
|
122
|
+
const v = parseInt(signature.slice(130, 132), 16);
|
|
123
|
+
|
|
124
|
+
// Convert v to yParity (0 or 1)
|
|
125
|
+
// v can be 27/28 (legacy) or 0/1 (EIP-155)
|
|
126
|
+
const yParity = v >= 27 ? v - 27 : v;
|
|
127
|
+
|
|
128
|
+
const result = {
|
|
129
|
+
chainId: unsignedAuth.chainId,
|
|
130
|
+
address: implementationAddress,
|
|
131
|
+
nonce: unsignedAuth.nonce,
|
|
132
|
+
r,
|
|
133
|
+
s,
|
|
134
|
+
yParity,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
console.log("[RN Adapter] Returning authorization:", result);
|
|
138
|
+
return result;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
return signAuthorization;
|
|
127
142
|
},
|
|
128
143
|
};
|
|
129
144
|
|
|
@@ -134,16 +149,42 @@ export const reactNativeAdapter: PrivyAdapter = {
|
|
|
134
149
|
* @returns {EmbeddedWallet} The adapted wallet following the common interface
|
|
135
150
|
*/
|
|
136
151
|
function adaptExpoWallet(wallet: ExpoEmbeddedWallet): EmbeddedWallet {
|
|
152
|
+
// Use closure to maintain up-to-date chain ID across chain switches
|
|
153
|
+
let cachedChainId = wallet.chainId || "1";
|
|
154
|
+
|
|
137
155
|
return {
|
|
138
156
|
address: wallet.address as `0x${string}`,
|
|
139
|
-
|
|
157
|
+
get chainId() {
|
|
158
|
+
return cachedChainId;
|
|
159
|
+
},
|
|
140
160
|
getEthereumProvider: async () => {
|
|
141
161
|
if (!wallet.getProvider) {
|
|
142
162
|
throw new Error(
|
|
143
163
|
"getProvider is not available on this wallet. Ensure you're using the embedded Ethereum wallet.",
|
|
144
164
|
);
|
|
145
165
|
}
|
|
146
|
-
|
|
166
|
+
const provider = await wallet.getProvider();
|
|
167
|
+
|
|
168
|
+
// Always fetch current chain ID when provider is accessed
|
|
169
|
+
// This ensures we have the latest chain after wallet_switchEthereumChain calls
|
|
170
|
+
try {
|
|
171
|
+
const currentChainId = (await provider.request({
|
|
172
|
+
method: "eth_chainId",
|
|
173
|
+
params: [],
|
|
174
|
+
})) as string;
|
|
175
|
+
|
|
176
|
+
// Convert hex to decimal string format (e.g., "0x1" -> "1")
|
|
177
|
+
cachedChainId = parseInt(currentChainId, 16).toString();
|
|
178
|
+
console.log("[RN Adapter] Updated chain ID to:", cachedChainId);
|
|
179
|
+
} catch (err) {
|
|
180
|
+
console.warn(
|
|
181
|
+
"[Privy Integration] Failed to fetch current chain ID:",
|
|
182
|
+
err,
|
|
183
|
+
);
|
|
184
|
+
// Fall back to cached value if fetch fails
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return provider;
|
|
147
188
|
},
|
|
148
189
|
};
|
|
149
190
|
}
|
|
@@ -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
|
|
38
|
-
const
|
|
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 =
|
|
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
|
-
|
|
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 "../
|
|
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 "../
|
|
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