@account-kit/privy-integration 4.75.3 → 4.75.5-alpha.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.
- package/dist/esm/Provider.d.ts +4 -71
- package/dist/esm/Provider.js +4 -109
- package/dist/esm/Provider.js.map +1 -1
- 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.d.ts +6 -0
- package/dist/esm/adapters/react-native.js +132 -0
- package/dist/esm/adapters/react-native.js.map +1 -0
- package/dist/esm/adapters/types.d.ts +56 -0
- package/dist/esm/adapters/types.js +2 -0
- package/dist/esm/adapters/types.js.map +1 -0
- package/dist/esm/adapters/web.d.ts +6 -0
- package/dist/esm/adapters/web.js +70 -0
- package/dist/esm/adapters/web.js.map +1 -0
- 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/context/AlchemyContext.d.ts +71 -0
- package/dist/esm/context/AlchemyContext.js +115 -0
- package/dist/esm/context/AlchemyContext.js.map +1 -0
- package/dist/esm/hooks/internal/useEmbeddedWallet.d.ts +3 -4
- package/dist/esm/hooks/internal/useEmbeddedWallet.js +6 -13
- package/dist/esm/hooks/internal/useEmbeddedWallet.js.map +1 -1
- package/dist/esm/hooks/useAlchemyClient.js +17 -24
- 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/ReactNativeProvider.d.ts +37 -0
- package/dist/esm/providers/ReactNativeProvider.js +41 -0
- package/dist/esm/providers/ReactNativeProvider.js.map +1 -0
- package/dist/esm/providers/WebProvider.d.ts +37 -0
- package/dist/esm/providers/WebProvider.js +41 -0
- package/dist/esm/providers/WebProvider.js.map +1 -0
- 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/react-native.d.ts +11 -0
- package/dist/esm/react-native.js +13 -0
- package/dist/esm/react-native.js.map +1 -0
- package/dist/esm/types.d.ts +6 -0
- package/dist/esm/types.js.map +1 -1
- 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.d.ts +4 -71
- package/dist/types/Provider.d.ts.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 +7 -0
- package/dist/types/adapters/react-native.d.ts.map +1 -0
- package/dist/types/adapters/types.d.ts +57 -0
- package/dist/types/adapters/types.d.ts.map +1 -0
- package/dist/types/adapters/web.d.ts +7 -0
- package/dist/types/adapters/web.d.ts.map +1 -0
- package/dist/types/adapters/web.native.d.ts +6 -0
- package/dist/types/adapters/web.native.d.ts.map +1 -0
- package/dist/types/context/AlchemyContext.d.ts +72 -0
- package/dist/types/context/AlchemyContext.d.ts.map +1 -0
- package/dist/types/hooks/internal/useEmbeddedWallet.d.ts +3 -4
- package/dist/types/hooks/internal/useEmbeddedWallet.d.ts.map +1 -1
- package/dist/types/hooks/useAlchemyClient.d.ts.map +1 -1
- package/dist/types/providers/ReactNativeProvider.d.ts +38 -0
- package/dist/types/providers/ReactNativeProvider.d.ts.map +1 -0
- package/dist/types/providers/WebProvider.d.ts +38 -0
- package/dist/types/providers/WebProvider.d.ts.map +1 -0
- package/dist/types/providers/WebProvider.native.d.ts +6 -0
- package/dist/types/providers/WebProvider.native.d.ts.map +1 -0
- package/dist/types/react-native.d.ts +12 -0
- package/dist/types/react-native.d.ts.map +1 -0
- package/dist/types/types.d.ts +6 -0
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/version.d.ts +1 -1
- package/dist/types/version.d.ts.map +1 -1
- package/package.json +27 -4
- package/src/Provider.native.tsx +18 -0
- package/src/Provider.tsx +6 -0
- package/src/adapters/react-native.ts +202 -0
- package/src/adapters/types.ts +71 -0
- package/src/adapters/web.native.ts +6 -0
- package/src/adapters/web.ts +107 -0
- package/src/context/AlchemyContext.tsx +185 -0
- package/src/hooks/internal/useEmbeddedWallet.ts +6 -20
- package/src/hooks/useAlchemyClient.ts +24 -38
- package/src/hooks/useAlchemySendTransaction.ts +1 -1
- package/src/hooks/useAlchemySolanaTransaction.ts +1 -1
- package/src/providers/ReactNativeProvider.tsx +49 -0
- package/src/providers/WebProvider.native.tsx +11 -0
- package/src/providers/WebProvider.tsx +49 -0
- package/src/react-native.ts +29 -0
- package/src/types.ts +7 -0
- package/src/version.ts +1 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { type PropsWithChildren } from "react";
|
|
2
|
+
import type { SmartWalletClient } from "@account-kit/wallet-client";
|
|
3
|
+
import type { SmartContractAccount } from "@aa-sdk/core";
|
|
4
|
+
import type { AlchemyProviderConfig } from "../types.js";
|
|
5
|
+
import type { PrivyAdapter } from "../adapters/types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Normalized config with defaults applied
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export type NormalizedAlchemyConfig = AlchemyProviderConfig & Required<Pick<AlchemyProviderConfig, "accountAuthMode">>;
|
|
12
|
+
/**
|
|
13
|
+
* Client cache stored in React tree (similar to QueryClient in React Query)
|
|
14
|
+
*
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
interface ClientCache {
|
|
18
|
+
client: SmartWalletClient | null;
|
|
19
|
+
account: SmartContractAccount | null;
|
|
20
|
+
cacheKey: string | null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Props for AlchemyContextProvider
|
|
24
|
+
*/
|
|
25
|
+
interface AlchemyContextProviderProps extends PropsWithChildren {
|
|
26
|
+
config: AlchemyProviderConfig;
|
|
27
|
+
adapter: PrivyAdapter;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Internal provider component that manages Alchemy context
|
|
31
|
+
* Used by both web and React Native providers
|
|
32
|
+
*
|
|
33
|
+
* @internal
|
|
34
|
+
* @param {AlchemyContextProviderProps} props - Component props
|
|
35
|
+
* @param {React.ReactNode} props.children - React children to wrap with context
|
|
36
|
+
* @param {AlchemyProviderConfig} props.config - Alchemy configuration
|
|
37
|
+
* @param {PrivyAdapter} props.adapter - Platform adapter
|
|
38
|
+
* @returns {JSX.Element} Context provider component
|
|
39
|
+
*/
|
|
40
|
+
export declare function AlchemyContextProvider({ children, config, adapter, }: AlchemyContextProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
41
|
+
/**
|
|
42
|
+
* Hook to access Alchemy provider configuration
|
|
43
|
+
* Must be used within an <AlchemyProvider> component
|
|
44
|
+
*
|
|
45
|
+
* @returns {NormalizedAlchemyConfig} The current Alchemy configuration with defaults applied
|
|
46
|
+
* @throws {Error} If used outside of AlchemyProvider
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```tsx
|
|
50
|
+
* const config = useAlchemyConfig();
|
|
51
|
+
* console.log('Policy ID:', config.policyId);
|
|
52
|
+
* console.log('Auth Mode:', config.accountAuthMode); // Always defined
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare function useAlchemyConfig(): NormalizedAlchemyConfig;
|
|
56
|
+
/**
|
|
57
|
+
* Hook to access the platform adapter
|
|
58
|
+
* Must be used within an <AlchemyProvider> component
|
|
59
|
+
*
|
|
60
|
+
* @internal
|
|
61
|
+
* @returns {PrivyAdapter} The platform adapter
|
|
62
|
+
*/
|
|
63
|
+
export declare function useAdapter(): PrivyAdapter;
|
|
64
|
+
/**
|
|
65
|
+
* Hook to access the client cache (internal use only)
|
|
66
|
+
*
|
|
67
|
+
* @internal
|
|
68
|
+
* @returns {ClientCache} The client cache object
|
|
69
|
+
*/
|
|
70
|
+
export declare function useClientCache(): ClientCache;
|
|
71
|
+
export {};
|
|
@@ -0,0 +1,115 @@
|
|
|
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 } = adapter.usePrivyAuth();
|
|
25
|
+
const walletAddress = adapter.useWalletAddress(config.walletAddress);
|
|
26
|
+
// Normalize config with default values
|
|
27
|
+
const normalizedConfig = {
|
|
28
|
+
...config,
|
|
29
|
+
accountAuthMode: config.accountAuthMode ?? "eip7702",
|
|
30
|
+
};
|
|
31
|
+
// Store cache in a ref - persists across renders but scoped to this component instance
|
|
32
|
+
// This makes it SSR-safe (each request gets its own cache) and React StrictMode-safe
|
|
33
|
+
const cache = useRef({
|
|
34
|
+
client: null,
|
|
35
|
+
account: null,
|
|
36
|
+
cacheKey: null,
|
|
37
|
+
});
|
|
38
|
+
// Track previous state to detect logout and wallet changes
|
|
39
|
+
const prevAuthenticatedRef = useRef(authenticated);
|
|
40
|
+
const prevWalletAddressRef = useRef(walletAddress);
|
|
41
|
+
// Automatically reset cache when user logs out or switches wallets
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const wasAuthenticated = prevAuthenticatedRef.current;
|
|
44
|
+
const prevWalletAddress = prevWalletAddressRef.current;
|
|
45
|
+
const currentWalletAddress = walletAddress;
|
|
46
|
+
// Reset cache on logout
|
|
47
|
+
if (wasAuthenticated && !authenticated) {
|
|
48
|
+
cache.current.client = null;
|
|
49
|
+
cache.current.account = null;
|
|
50
|
+
cache.current.cacheKey = null;
|
|
51
|
+
}
|
|
52
|
+
// Reset cache on wallet address change (account switching)
|
|
53
|
+
if (authenticated &&
|
|
54
|
+
prevWalletAddress &&
|
|
55
|
+
currentWalletAddress &&
|
|
56
|
+
prevWalletAddress !== currentWalletAddress) {
|
|
57
|
+
cache.current.client = null;
|
|
58
|
+
cache.current.account = null;
|
|
59
|
+
cache.current.cacheKey = null;
|
|
60
|
+
}
|
|
61
|
+
// Update refs for next render
|
|
62
|
+
prevAuthenticatedRef.current = authenticated;
|
|
63
|
+
prevWalletAddressRef.current = currentWalletAddress;
|
|
64
|
+
}, [authenticated, walletAddress]);
|
|
65
|
+
return (_jsx(AlchemyConfigContext.Provider, { value: normalizedConfig, children: _jsx(AdapterContext.Provider, { value: adapter, children: _jsx(ClientCacheContext.Provider, { value: cache.current, children: children }) }) }));
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Hook to access Alchemy provider configuration
|
|
69
|
+
* Must be used within an <AlchemyProvider> component
|
|
70
|
+
*
|
|
71
|
+
* @returns {NormalizedAlchemyConfig} The current Alchemy configuration with defaults applied
|
|
72
|
+
* @throws {Error} If used outside of AlchemyProvider
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```tsx
|
|
76
|
+
* const config = useAlchemyConfig();
|
|
77
|
+
* console.log('Policy ID:', config.policyId);
|
|
78
|
+
* console.log('Auth Mode:', config.accountAuthMode); // Always defined
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export function useAlchemyConfig() {
|
|
82
|
+
const context = useContext(AlchemyConfigContext);
|
|
83
|
+
if (!context) {
|
|
84
|
+
throw new Error("useAlchemyConfig must be used within <AlchemyProvider />");
|
|
85
|
+
}
|
|
86
|
+
return context;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Hook to access the platform adapter
|
|
90
|
+
* Must be used within an <AlchemyProvider> component
|
|
91
|
+
*
|
|
92
|
+
* @internal
|
|
93
|
+
* @returns {PrivyAdapter} The platform adapter
|
|
94
|
+
*/
|
|
95
|
+
export function useAdapter() {
|
|
96
|
+
const context = useContext(AdapterContext);
|
|
97
|
+
if (!context) {
|
|
98
|
+
throw new Error("useAdapter must be used within <AlchemyProvider />. Make sure AlchemyProvider is nested inside PrivyProvider.");
|
|
99
|
+
}
|
|
100
|
+
return context;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Hook to access the client cache (internal use only)
|
|
104
|
+
*
|
|
105
|
+
* @internal
|
|
106
|
+
* @returns {ClientCache} The client cache object
|
|
107
|
+
*/
|
|
108
|
+
export function useClientCache() {
|
|
109
|
+
const context = useContext(ClientCacheContext);
|
|
110
|
+
if (!context) {
|
|
111
|
+
throw new Error("useClientCache must be used within <AlchemyProvider />. Make sure AlchemyProvider is nested inside PrivyProvider.");
|
|
112
|
+
}
|
|
113
|
+
return context;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=AlchemyContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AlchemyContext.js","sourceRoot":"","sources":["../../../src/context/AlchemyContext.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n type PropsWithChildren,\n createContext,\n useContext,\n useRef,\n useEffect,\n} from \"react\";\nimport type { SmartWalletClient } from \"@account-kit/wallet-client\";\nimport type { SmartContractAccount } from \"@aa-sdk/core\";\nimport type { AlchemyProviderConfig } from \"../types.js\";\nimport type { PrivyAdapter } from \"../adapters/types.js\";\n\n/**\n * Normalized config with defaults applied\n *\n * @internal\n */\nexport type NormalizedAlchemyConfig = AlchemyProviderConfig &\n Required<Pick<AlchemyProviderConfig, \"accountAuthMode\">>;\n\n/**\n * Context for Alchemy configuration\n */\nconst AlchemyConfigContext = createContext<NormalizedAlchemyConfig | null>(\n null,\n);\n\n/**\n * Context for the platform adapter\n */\nconst AdapterContext = createContext<PrivyAdapter | null>(null);\n\n/**\n * Client cache stored in React tree (similar to QueryClient in React Query)\n *\n * @internal\n */\ninterface ClientCache {\n client: SmartWalletClient | null;\n account: SmartContractAccount | null;\n cacheKey: string | null;\n}\n\nconst ClientCacheContext = createContext<ClientCache | null>(null);\n\n/**\n * Props for AlchemyContextProvider\n */\ninterface AlchemyContextProviderProps extends PropsWithChildren {\n config: AlchemyProviderConfig;\n adapter: PrivyAdapter;\n}\n\n/**\n * Internal provider component that manages Alchemy context\n * Used by both web and React Native providers\n *\n * @internal\n * @param {AlchemyContextProviderProps} props - Component props\n * @param {React.ReactNode} props.children - React children to wrap with context\n * @param {AlchemyProviderConfig} props.config - Alchemy configuration\n * @param {PrivyAdapter} props.adapter - Platform adapter\n * @returns {JSX.Element} Context provider component\n */\nexport function AlchemyContextProvider({\n children,\n config,\n adapter,\n}: AlchemyContextProviderProps) {\n const { authenticated } = adapter.usePrivyAuth();\n const walletAddress = adapter.useWalletAddress(config.walletAddress);\n\n // Normalize config with default values\n const normalizedConfig: NormalizedAlchemyConfig = {\n ...config,\n accountAuthMode: config.accountAuthMode ?? \"eip7702\",\n };\n\n // Store cache in a ref - persists across renders but scoped to this component instance\n // This makes it SSR-safe (each request gets its own cache) and React StrictMode-safe\n const cache = useRef<ClientCache>({\n client: null,\n account: null,\n cacheKey: null,\n });\n\n // Track previous state to detect logout and wallet changes\n const prevAuthenticatedRef = useRef(authenticated);\n const prevWalletAddressRef = useRef(walletAddress);\n\n // Automatically reset cache when user logs out or switches wallets\n useEffect(() => {\n const wasAuthenticated = prevAuthenticatedRef.current;\n const prevWalletAddress = prevWalletAddressRef.current;\n const currentWalletAddress = walletAddress;\n\n // Reset cache on logout\n if (wasAuthenticated && !authenticated) {\n cache.current.client = null;\n cache.current.account = null;\n cache.current.cacheKey = null;\n }\n\n // Reset cache on wallet address change (account switching)\n if (\n authenticated &&\n prevWalletAddress &&\n currentWalletAddress &&\n prevWalletAddress !== currentWalletAddress\n ) {\n cache.current.client = null;\n cache.current.account = null;\n cache.current.cacheKey = null;\n }\n\n // Update refs for next render\n prevAuthenticatedRef.current = authenticated;\n prevWalletAddressRef.current = currentWalletAddress;\n }, [authenticated, walletAddress]);\n\n return (\n <AlchemyConfigContext.Provider value={normalizedConfig}>\n <AdapterContext.Provider value={adapter}>\n <ClientCacheContext.Provider value={cache.current}>\n {children}\n </ClientCacheContext.Provider>\n </AdapterContext.Provider>\n </AlchemyConfigContext.Provider>\n );\n}\n\n/**\n * Hook to access Alchemy provider configuration\n * Must be used within an <AlchemyProvider> component\n *\n * @returns {NormalizedAlchemyConfig} The current Alchemy configuration with defaults applied\n * @throws {Error} If used outside of AlchemyProvider\n *\n * @example\n * ```tsx\n * const config = useAlchemyConfig();\n * console.log('Policy ID:', config.policyId);\n * console.log('Auth Mode:', config.accountAuthMode); // Always defined\n * ```\n */\nexport function useAlchemyConfig(): NormalizedAlchemyConfig {\n const context = useContext(AlchemyConfigContext);\n if (!context) {\n throw new Error(\"useAlchemyConfig must be used within <AlchemyProvider />\");\n }\n return context;\n}\n\n/**\n * Hook to access the platform adapter\n * Must be used within an <AlchemyProvider> component\n *\n * @internal\n * @returns {PrivyAdapter} The platform adapter\n */\nexport function useAdapter(): PrivyAdapter {\n const context = useContext(AdapterContext);\n if (!context) {\n throw new Error(\n \"useAdapter must be used within <AlchemyProvider />. Make sure AlchemyProvider is nested inside PrivyProvider.\",\n );\n }\n return context;\n}\n\n/**\n * Hook to access the client cache (internal use only)\n *\n * @internal\n * @returns {ClientCache} The client cache object\n */\nexport function useClientCache(): ClientCache {\n const context = useContext(ClientCacheContext);\n if (!context) {\n throw new Error(\n \"useClientCache must be used within <AlchemyProvider />. Make sure AlchemyProvider is nested inside PrivyProvider.\",\n );\n }\n return context;\n}\n"]}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { type ConnectedWallet as PrivyWallet } from "@privy-io/react-auth";
|
|
2
1
|
/**
|
|
3
2
|
* Internal hook to get the Privy embedded wallet
|
|
4
|
-
*
|
|
3
|
+
* Uses the platform adapter to abstract differences between web and React Native
|
|
5
4
|
*
|
|
6
5
|
* @internal
|
|
7
|
-
* @returns {() =>
|
|
6
|
+
* @returns {() => EmbeddedWallet} Function that returns the embedded wallet
|
|
8
7
|
* @throws {Error} If embedded wallet is not found
|
|
9
8
|
*/
|
|
10
|
-
export declare function useEmbeddedWallet(): () =>
|
|
9
|
+
export declare function useEmbeddedWallet(): () => import("../../adapters/types.js").EmbeddedWallet;
|
|
@@ -1,22 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useWallets, } from "@privy-io/react-auth";
|
|
1
|
+
import { useAdapter, useAlchemyConfig } from "../../context/AlchemyContext.js";
|
|
3
2
|
/**
|
|
4
3
|
* Internal hook to get the Privy embedded wallet
|
|
5
|
-
*
|
|
4
|
+
* Uses the platform adapter to abstract differences between web and React Native
|
|
6
5
|
*
|
|
7
6
|
* @internal
|
|
8
|
-
* @returns {() =>
|
|
7
|
+
* @returns {() => EmbeddedWallet} Function that returns the embedded wallet
|
|
9
8
|
* @throws {Error} If embedded wallet is not found
|
|
10
9
|
*/
|
|
11
10
|
export function useEmbeddedWallet() {
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
if (!embedded) {
|
|
16
|
-
throw new Error("Privy embedded wallet not found. Please ensure the user is authenticated.");
|
|
17
|
-
}
|
|
18
|
-
return embedded;
|
|
19
|
-
}, [wallets]);
|
|
20
|
-
return getEmbeddedWallet;
|
|
11
|
+
const adapter = useAdapter();
|
|
12
|
+
const config = useAlchemyConfig();
|
|
13
|
+
return adapter.useEmbeddedWallet(config.walletAddress);
|
|
21
14
|
}
|
|
22
15
|
//# sourceMappingURL=useEmbeddedWallet.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEmbeddedWallet.js","sourceRoot":"","sources":["../../../../src/hooks/internal/useEmbeddedWallet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"useEmbeddedWallet.js","sourceRoot":"","sources":["../../../../src/hooks/internal/useEmbeddedWallet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAE/E;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB;IAC/B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,OAAO,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;AACzD,CAAC","sourcesContent":["import { useAdapter, useAlchemyConfig } from \"../../context/AlchemyContext.js\";\n\n/**\n * Internal hook to get the Privy embedded wallet\n * Uses the platform adapter to abstract differences between web and React Native\n *\n * @internal\n * @returns {() => EmbeddedWallet} Function that returns the embedded wallet\n * @throws {Error} If embedded wallet is not found\n */\nexport function useEmbeddedWallet() {\n const adapter = useAdapter();\n const config = useAlchemyConfig();\n return adapter.useEmbeddedWallet(config.walletAddress);\n}\n"]}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { useCallback } from "react";
|
|
2
2
|
import { WalletClientSigner, ConnectionConfigSchema, } from "@aa-sdk/core";
|
|
3
|
-
import { createWalletClient, custom
|
|
4
|
-
import { useSign7702Authorization } from "@privy-io/react-auth";
|
|
3
|
+
import { createWalletClient, custom } from "viem";
|
|
5
4
|
import { createSmartWalletClient, } from "@account-kit/wallet-client";
|
|
6
5
|
import { alchemy } from "@account-kit/infra";
|
|
7
|
-
import { useAlchemyConfig, useClientCache } from "../
|
|
6
|
+
import { useAlchemyConfig, useClientCache, useAdapter, } from "../context/AlchemyContext.js";
|
|
8
7
|
import { getChain } from "../util/getChain.js";
|
|
9
8
|
import { useEmbeddedWallet } from "./internal/useEmbeddedWallet.js";
|
|
10
9
|
/**
|
|
@@ -21,14 +20,19 @@ import { useEmbeddedWallet } from "./internal/useEmbeddedWallet.js";
|
|
|
21
20
|
* ```
|
|
22
21
|
*/
|
|
23
22
|
export function useAlchemyClient() {
|
|
24
|
-
const
|
|
23
|
+
const adapter = useAdapter();
|
|
25
24
|
const config = useAlchemyConfig();
|
|
25
|
+
const signAuthorizationFn = adapter.useAuthorizationSigner?.(config.walletAddress) || null;
|
|
26
26
|
const cache = useClientCache();
|
|
27
27
|
const getEmbeddedWallet = useEmbeddedWallet();
|
|
28
|
-
const
|
|
29
|
-
const
|
|
28
|
+
const getClient = useCallback(async () => {
|
|
29
|
+
const embeddedWallet = getEmbeddedWallet();
|
|
30
|
+
// IMPORTANT: Get provider FIRST to ensure chain ID is updated
|
|
31
|
+
// The provider fetch triggers chain ID update in the adapter
|
|
32
|
+
const provider = await embeddedWallet.getEthereumProvider();
|
|
33
|
+
// NOW get the chain from the SAME wallet instance with updated chain ID
|
|
30
34
|
// Handle CAIP-2 format like "eip155:1"
|
|
31
|
-
const chainIdStr =
|
|
35
|
+
const chainIdStr = embeddedWallet.chainId?.toString();
|
|
32
36
|
if (!chainIdStr) {
|
|
33
37
|
throw new Error("Embedded wallet chainId is not set. Please ensure the wallet is connected to a network.");
|
|
34
38
|
}
|
|
@@ -39,12 +43,9 @@ export function useAlchemyClient() {
|
|
|
39
43
|
if (isNaN(parsedChainId)) {
|
|
40
44
|
throw new Error(`Failed to parse chainId from embedded wallet. Received: ${chainIdStr}`);
|
|
41
45
|
}
|
|
42
|
-
|
|
43
|
-
}, [getEmbeddedWallet]);
|
|
44
|
-
const getClient = useCallback(async () => {
|
|
45
|
-
const embeddedWallet = getEmbeddedWallet();
|
|
46
|
-
const chain = getEmbeddedWalletChain();
|
|
46
|
+
const chain = getChain(parsedChainId);
|
|
47
47
|
// Generate a cache key based on configuration and wallet address
|
|
48
|
+
// IMPORTANT: Include whether authorization signer is available in cache key
|
|
48
49
|
const currentCacheKey = JSON.stringify({
|
|
49
50
|
address: embeddedWallet.address,
|
|
50
51
|
chainId: chain.id,
|
|
@@ -53,13 +54,12 @@ export function useAlchemyClient() {
|
|
|
53
54
|
rpcUrl: config.rpcUrl,
|
|
54
55
|
policyId: config.policyId,
|
|
55
56
|
accountAuthMode: config.accountAuthMode,
|
|
57
|
+
hasAuthSigner: !!signAuthorizationFn,
|
|
56
58
|
});
|
|
57
59
|
// Return cached client and account if configuration hasn't changed
|
|
58
60
|
if (cache.client && cache.account && cache.cacheKey === currentCacheKey) {
|
|
59
61
|
return { client: cache.client, account: cache.account };
|
|
60
62
|
}
|
|
61
|
-
// Configuration changed or no cache exists, create new client
|
|
62
|
-
const provider = await embeddedWallet.getEthereumProvider();
|
|
63
63
|
// Create base signer from Privy wallet
|
|
64
64
|
const baseSigner = new WalletClientSigner(createWalletClient({
|
|
65
65
|
account: embeddedWallet.address,
|
|
@@ -67,16 +67,10 @@ export function useAlchemyClient() {
|
|
|
67
67
|
transport: custom(provider),
|
|
68
68
|
}), "privy");
|
|
69
69
|
// Optionally extend signer with EIP-7702 authorization support
|
|
70
|
-
const signer = config.accountAuthMode === "eip7702"
|
|
70
|
+
const signer = config.accountAuthMode === "eip7702" && !!signAuthorizationFn
|
|
71
71
|
? {
|
|
72
72
|
...baseSigner,
|
|
73
|
-
signAuthorization:
|
|
74
|
-
const signature = await signAuthorization({
|
|
75
|
-
...unsignedAuth,
|
|
76
|
-
contractAddress: unsignedAuth.address ?? unsignedAuth.contractAddress,
|
|
77
|
-
});
|
|
78
|
-
return { ...unsignedAuth, ...signature };
|
|
79
|
-
},
|
|
73
|
+
signAuthorization: signAuthorizationFn,
|
|
80
74
|
}
|
|
81
75
|
: baseSigner;
|
|
82
76
|
// Determine transport configuration using schema validation
|
|
@@ -117,8 +111,7 @@ export function useAlchemyClient() {
|
|
|
117
111
|
return { client: cache.client, account: cache.account };
|
|
118
112
|
}, [
|
|
119
113
|
getEmbeddedWallet,
|
|
120
|
-
|
|
121
|
-
signAuthorization,
|
|
114
|
+
signAuthorizationFn,
|
|
122
115
|
config.apiKey,
|
|
123
116
|
config.jwt,
|
|
124
117
|
config.rpcUrl,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAlchemyClient.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemyClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpC,OAAO,EACL,kBAAkB,
|
|
1
|
+
{"version":3,"file":"useAlchemyClient.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemyClient.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback } from \"react\";\nimport {\n WalletClientSigner,\n ConnectionConfigSchema,\n type SmartContractAccount,\n} from \"@aa-sdk/core\";\nimport { createWalletClient, custom, type Address } from \"viem\";\nimport {\n createSmartWalletClient,\n type SmartWalletClient,\n} from \"@account-kit/wallet-client\";\nimport { alchemy } from \"@account-kit/infra\";\nimport {\n useAlchemyConfig,\n useClientCache,\n useAdapter,\n} from \"../context/AlchemyContext.js\";\nimport { getChain } from \"../util/getChain.js\";\nimport { useEmbeddedWallet } from \"./internal/useEmbeddedWallet.js\";\n\nexport type AlchemyClientResult = {\n client: SmartWalletClient;\n account: SmartContractAccount;\n};\n\n/**\n * Hook to get and memoize a SmartWalletClient instance with its associated account\n * The client and account are cached in the AlchemyProvider context (React tree scoped)\n * Automatically clears cache on logout via the provider\n *\n * @returns {{ getClient: () => Promise<AlchemyClientResult> }} Object containing the smart wallet client and account getter\n *\n * @example\n * ```tsx\n * const { getClient } = useAlchemyClient();\n * const { client, account } = await getClient();\n * ```\n */\nexport function useAlchemyClient() {\n const adapter = useAdapter();\n const config = useAlchemyConfig();\n const signAuthorizationFn =\n adapter.useAuthorizationSigner?.(config.walletAddress) || null;\n const cache = useClientCache();\n const getEmbeddedWallet = useEmbeddedWallet();\n\n const getClient = useCallback(async (): Promise<AlchemyClientResult> => {\n const embeddedWallet = getEmbeddedWallet();\n\n // IMPORTANT: Get provider FIRST to ensure chain ID is updated\n // The provider fetch triggers chain ID update in the adapter\n const provider = await embeddedWallet.getEthereumProvider();\n\n // NOW get the chain from the SAME wallet instance with updated chain ID\n // Handle CAIP-2 format like \"eip155:1\"\n const chainIdStr = embeddedWallet.chainId?.toString();\n\n if (!chainIdStr) {\n throw new Error(\n \"Embedded wallet chainId is not set. Please ensure the wallet is connected to a network.\",\n );\n }\n const numericChainId = chainIdStr.includes(\":\")\n ? chainIdStr.split(\":\")[1]\n : chainIdStr;\n const parsedChainId = Number(numericChainId);\n if (isNaN(parsedChainId)) {\n throw new Error(\n `Failed to parse chainId from embedded wallet. Received: ${chainIdStr}`,\n );\n }\n\n const chain = getChain(parsedChainId);\n\n // Generate a cache key based on configuration and wallet address\n // IMPORTANT: Include whether authorization signer is available in cache key\n const currentCacheKey = JSON.stringify({\n address: embeddedWallet.address,\n chainId: chain.id,\n apiKey: config.apiKey,\n jwt: config.jwt,\n rpcUrl: config.rpcUrl,\n policyId: config.policyId,\n accountAuthMode: config.accountAuthMode,\n hasAuthSigner: !!signAuthorizationFn,\n });\n\n // Return cached client and account if configuration hasn't changed\n if (cache.client && cache.account && cache.cacheKey === currentCacheKey) {\n return { client: cache.client, account: cache.account };\n }\n\n // Create base signer from Privy wallet\n const baseSigner = new WalletClientSigner(\n createWalletClient({\n account: embeddedWallet.address as Address,\n chain,\n transport: custom(provider),\n }),\n \"privy\",\n );\n\n // Optionally extend signer with EIP-7702 authorization support\n const signer =\n config.accountAuthMode === \"eip7702\" && !!signAuthorizationFn\n ? {\n ...baseSigner,\n signAuthorization: signAuthorizationFn,\n }\n : baseSigner;\n\n // Determine transport configuration using schema validation\n // This properly handles combinations like rpcUrl + jwt together\n const transportConfig = ConnectionConfigSchema.parse({\n rpcUrl: config.rpcUrl,\n apiKey: config.apiKey,\n jwt: config.jwt,\n });\n\n const transport = alchemy(transportConfig);\n\n transport.updateHeaders({\n \"X-Alchemy-Client-Breadcrumb\": \"privyIntegrationSdk\",\n });\n\n // Create and cache the smart wallet client in provider context\n cache.client = createSmartWalletClient({\n chain,\n transport,\n signer,\n policyIds: config.policyId\n ? Array.isArray(config.policyId)\n ? config.policyId\n : [config.policyId]\n : undefined,\n });\n\n // Request the account to properly initialize the smart wallet\n // Pass a creation hint based on auth mode to ensure different accounts for different modes\n // This prevents 7702 accounts from being reused in owner mode and vice versa\n cache.account =\n config.accountAuthMode === \"eip7702\"\n ? await cache.client.requestAccount({\n creationHint: { accountType: \"7702\" },\n })\n : await cache.client.requestAccount({\n creationHint: { accountType: \"sma-b\" },\n });\n\n // Store the cache key\n cache.cacheKey = currentCacheKey;\n\n return { client: cache.client, account: cache.account };\n }, [\n getEmbeddedWallet,\n signAuthorizationFn,\n config.apiKey,\n config.jwt,\n config.rpcUrl,\n config.policyId,\n cache,\n config.accountAuthMode,\n ]);\n\n return { getClient };\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useCallback, useState } from "react";
|
|
2
2
|
import { isHex } from "viem";
|
|
3
3
|
import { useAlchemyClient } from "./useAlchemyClient.js";
|
|
4
|
-
import { useAlchemyConfig } from "../
|
|
4
|
+
import { useAlchemyConfig } from "../context/AlchemyContext.js";
|
|
5
5
|
/**
|
|
6
6
|
* Normalize value to hex format
|
|
7
7
|
* Accepts bigint, number, decimal string, or hex string
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAlchemySendTransaction.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemySendTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAY,KAAK,EAAE,MAAM,MAAM,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"useAlchemySendTransaction.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemySendTransaction.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useState } from \"react\";\nimport { type Hex, isHex } from \"viem\";\nimport { useAlchemyClient } from \"./useAlchemyClient.js\";\nimport { useAlchemyConfig } from \"../context/AlchemyContext.js\";\nimport type {\n UnsignedTransactionRequest,\n SendTransactionOptions,\n SendTransactionResult,\n UseSendTransactionResult,\n} from \"../types\";\n\n/**\n * Normalize value to hex format\n * Accepts bigint, number, decimal string, or hex string\n *\n * @param {string | number | bigint} value - Value to normalize\n * @returns {Hex} Hex string representation of the value\n */\nfunction normalizeValue(value: string | number | bigint): Hex {\n if (typeof value === \"bigint\") {\n return `0x${value.toString(16)}`;\n }\n if (typeof value === \"number\") {\n return `0x${BigInt(value).toString(16)}`;\n }\n if (isHex(value)) {\n return value;\n }\n // Assume decimal string\n return `0x${BigInt(value).toString(16)}`;\n}\n\n/**\n * Hook to send transactions with optional gas sponsorship via Alchemy\n * Supports both single transactions and batch transactions\n * Drop-in alternative to Privy's useSendTransaction hook\n *\n * @returns {UseSendTransactionResult} Hook result with sendTransaction function and state\n *\n * @example Single transaction\n * ```tsx\n * const { sendTransaction, isLoading, error, data } = useAlchemySendTransaction();\n *\n * const handleSend = async () => {\n * try {\n * const result = await sendTransaction({\n * to: '0x...',\n * data: '0x...',\n * value: '1000000000000000000', // 1 ETH\n * });\n * console.log('Transaction hash:', result.txnHash);\n * } catch (err) {\n * console.error('Transaction failed:', err);\n * }\n * };\n * ```\n *\n * @example Batch transactions\n * ```tsx\n * const { sendTransaction } = useAlchemySendTransaction();\n *\n * const result = await sendTransaction([\n * { to: '0x...', data: '0x...', value: '1000000000000000000' },\n * { to: '0x...', data: '0x...' },\n * ]);\n * ```\n */\nexport function useAlchemySendTransaction(): UseSendTransactionResult {\n const { getClient } = useAlchemyClient();\n const config = useAlchemyConfig();\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<SendTransactionResult | null>(null);\n\n const sendTransaction = useCallback(\n async (\n input: UnsignedTransactionRequest | UnsignedTransactionRequest[],\n options?: SendTransactionOptions,\n ): Promise<SendTransactionResult> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const { client, account } = await getClient();\n\n // Determine if transaction should be sponsored\n const hasPolicyId = !!config.policyId;\n const enableSponsorship = !config.disableSponsorship;\n const shouldSponsor =\n options?.disableSponsorship !== undefined\n ? !options.disableSponsorship\n : hasPolicyId && enableSponsorship;\n\n // Format the transaction call(s)\n const inputs = Array.isArray(input) ? input : [input];\n const formattedCalls = inputs.map((txn) => ({\n to: txn.to,\n data: txn.data,\n value: txn.value ? normalizeValue(txn.value) : undefined,\n }));\n\n // Build capabilities based on sponsorship and auth mode\n const policyId = Array.isArray(config.policyId)\n ? config.policyId[0]\n : config.policyId;\n\n type Capabilities =\n | { eip7702Auth: true; paymasterService?: { policyId: string } }\n | { paymasterService?: { policyId: string } };\n const capabilities: Capabilities =\n config.accountAuthMode === \"eip7702\" ? { eip7702Auth: true } : {};\n\n if (shouldSponsor && policyId) {\n capabilities.paymasterService = { policyId };\n }\n\n // Send the transaction(s) from the smart account address\n const result = await client.sendCalls({\n from: account.address,\n calls: formattedCalls,\n capabilities,\n });\n\n if (!result.preparedCallIds || result.preparedCallIds.length === 0) {\n throw new Error(\n \"No prepared call IDs returned from transaction submission\",\n );\n }\n\n // Wait for the transaction to be confirmed\n const txStatus = await client.waitForCallsStatus({\n id: result.preparedCallIds[0],\n timeout: 60_000,\n });\n\n const txnHash = txStatus.receipts?.[0]?.transactionHash;\n if (!txnHash) {\n throw new Error(\"Transaction hash not found in receipt\");\n }\n\n const txResult: SendTransactionResult = { txnHash };\n setData(txResult);\n return txResult;\n } catch (err) {\n const errorObj =\n err instanceof Error ? err : new Error(\"Transaction failed\");\n setError(errorObj);\n throw errorObj;\n } finally {\n setIsLoading(false);\n }\n },\n [\n getClient,\n config.policyId,\n config.disableSponsorship,\n config.accountAuthMode,\n ],\n );\n\n const reset = useCallback(() => {\n setError(null);\n setData(null);\n setIsLoading(false);\n }, []);\n\n return {\n sendTransaction,\n isLoading,\n error,\n data,\n reset,\n };\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useCallback, useMemo, useState } from "react";
|
|
2
2
|
import { Connection, PublicKey, SystemProgram, Transaction, TransactionInstruction, VersionedTransaction, } from "@solana/web3.js";
|
|
3
|
-
import { useAlchemyConfig } from "../
|
|
3
|
+
import { useAlchemyConfig } from "../context/AlchemyContext.js";
|
|
4
4
|
import { createSolanaSponsoredTransaction } from "../util/createSolanaSponsoredTransaction.js";
|
|
5
5
|
import { useSignTransaction, useWallets } from "@privy-io/react-auth/solana";
|
|
6
6
|
import { createSolanaTransaction } from "../util/createSolanaTransaction.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAlchemySolanaTransaction.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemySolanaTransaction.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useMemo, useState } from \"react\";\nimport {\n Connection,\n PublicKey,\n SystemProgram,\n Transaction,\n TransactionInstruction,\n VersionedTransaction,\n} from \"@solana/web3.js\";\nimport { useAlchemyConfig } from \"../Provider.js\";\nimport { createSolanaSponsoredTransaction } from \"../util/createSolanaSponsoredTransaction.js\";\nimport { useSignTransaction, useWallets } from \"@privy-io/react-auth/solana\";\nimport { createSolanaTransaction } from \"../util/createSolanaTransaction.js\";\n\n/**\n * Type helper for values that can be synchronous or asynchronous\n *\n * @template T - The value type\n */\nexport type PromiseOrValue<T> = T | Promise<T>;\n\n/**\n * Callback to modify a transaction before it's signed\n * Useful for adding additional signatures or metadata\n *\n * @param transaction - The unsigned transaction to modify\n * @returns The modified transaction\n */\nexport type PreSend = (\n this: void,\n transaction: VersionedTransaction | Transaction,\n) => PromiseOrValue<VersionedTransaction | Transaction>;\n\n/**\n * Callback to transform instructions into a custom transaction\n * Useful for advanced transaction construction (e.g., multi-sig, custom versioning)\n *\n * @param instructions - Array of Solana transaction instructions\n * @returns Constructed transaction (legacy or versioned)\n */\nexport type TransformInstruction = (\n this: void,\n instructions: TransactionInstruction[],\n) => PromiseOrValue<Transaction | VersionedTransaction>;\n\n/**\n * Optional transaction lifecycle hooks for advanced use cases\n */\nexport type SolanaTransactionParamOptions = {\n /** Hook called before signing the transaction */\n preSend?: PreSend;\n /** Custom transaction builder from instructions */\n transformInstruction?: TransformInstruction;\n};\n\n/**\n * Parameters for sending a Solana transaction\n * Supports either a simple transfer or custom instructions\n */\nexport type SolanaTransactionParams =\n | {\n /** Simple SOL transfer parameters */\n transfer: {\n /** Amount in lamports (accepts number or bigint) */\n amount: number | bigint;\n /** Recipient's base58-encoded address */\n toAddress: string;\n };\n /** Optional transaction lifecycle hooks */\n transactionComponents?: SolanaTransactionParamOptions;\n /** Options for confirming the transaction on-chain */\n confirmationOptions?: Parameters<Connection[\"confirmTransaction\"]>[1];\n }\n | {\n /** Custom Solana transaction instructions */\n instructions: TransactionInstruction[];\n /** Optional transaction lifecycle hooks */\n transactionComponents?: SolanaTransactionParamOptions;\n /** Options for confirming the transaction on-chain */\n confirmationOptions?: Parameters<Connection[\"confirmTransaction\"]>[1];\n };\n\n/**\n * Result of a successful Solana transaction\n */\nexport interface SolanaTransactionResult {\n /** Base58-encoded transaction signature (hash) */\n hash: string;\n}\n\n/**\n * Configuration options for useAlchemySolanaTransaction hook\n */\nexport interface UseAlchemySolanaTransactionOptions {\n /** Solana RPC URL (overrides provider config) */\n rpcUrl?: string;\n /** Gas sponsorship policy ID (overrides provider config) */\n policyId?: string | void;\n /** Transaction confirmation options */\n confirmationOptions?: Parameters<Connection[\"confirmTransaction\"]>[1];\n /** Specific wallet address to use (defaults to first available wallet) */\n walletAddress?: string;\n}\n\n/**\n * Return type of useAlchemySolanaTransaction hook\n */\nexport interface UseAlchemySolanaTransactionResult {\n /** Active Solana connection instance */\n readonly connection: Connection | null;\n /** Transaction result if successful */\n readonly data: void | SolanaTransactionResult;\n /** Whether a transaction is currently being sent */\n readonly isPending: boolean;\n /** Error if transaction failed */\n readonly error: Error | null;\n /** Reset hook state (clears error, data, isPending) */\n reset(): void;\n /** Send transaction (fire-and-forget, errors caught internally) */\n sendTransaction(params: SolanaTransactionParams): void;\n /** Send transaction and await result (throws on error) */\n sendTransactionAsync(\n params: SolanaTransactionParams,\n ): Promise<SolanaTransactionResult>;\n}\n\n/**\n * Hook to send Solana transactions with optional gas sponsorship via Alchemy\n * Works with Privy's Solana wallet integration for signing transactions\n * Supports both simple transfers and custom instruction sets\n *\n * @param {UseAlchemySolanaTransactionOptions} [opts] - Configuration options\n * @param {string} [opts.rpcUrl] - Solana RPC URL (overrides provider config)\n * @param {string} [opts.policyId] - Gas sponsorship policy ID (overrides provider config)\n * @param {string} [opts.walletAddress] - Specific wallet address to use (defaults to first wallet)\n * @param {Parameters<Connection[\"confirmTransaction\"]>[1]} [opts.confirmationOptions] - Transaction confirmation options\n * @returns {UseAlchemySolanaTransactionResult} Hook result with transaction functions and state\n *\n * @example Simple SOL transfer\n * ```tsx\n * const { sendTransactionAsync, isPending, error, data } = useAlchemySolanaTransaction({\n * rpcUrl: 'https://solana-mainnet.g.alchemy.com/v2/your-api-key',\n * policyId: 'your-policy-id', // Optional: for gas sponsorship\n * });\n *\n * const handleTransfer = async () => {\n * try {\n * const result = await sendTransactionAsync({\n * transfer: {\n * amount: 1_000_000_000, // 1 SOL in lamports\n * toAddress: 'recipient-address',\n * },\n * });\n * console.log('Transaction hash:', result.hash);\n * } catch (err) {\n * console.error('Transaction failed:', err);\n * }\n * };\n * ```\n *\n * @example Custom instructions\n * ```tsx\n * import { SystemProgram, PublicKey } from '@solana/web3.js';\n *\n * const { sendTransactionAsync } = useAlchemySolanaTransaction();\n *\n * // Build your custom instructions\n * const transferIx = SystemProgram.transfer({\n * fromPubkey: new PublicKey(walletAddress),\n * toPubkey: new PublicKey(recipientAddress),\n * lamports: 1_000_000,\n * });\n *\n * // Pass instructions array to the hook\n * const result = await sendTransactionAsync({\n * instructions: [transferIx],\n * });\n * ```\n *\n * @example With provider configuration\n * ```tsx\n * // In your provider setup\n * <AlchemyProvider\n * solanaRpcUrl=\"https://solana-mainnet.g.alchemy.com/v2/...\"\n * solanaPolicyId=\"your-solana-policy-id\"\n * >\n * <YourApp />\n * </AlchemyProvider>\n *\n * // In your component - uses provider config automatically\n * const { sendTransactionAsync } = useAlchemySolanaTransaction();\n * ```\n */\nexport function useAlchemySolanaTransaction(\n opts: UseAlchemySolanaTransactionOptions = {},\n): UseAlchemySolanaTransactionResult {\n const config = useAlchemyConfig();\n const { wallets } = useWallets();\n const { signTransaction } = useSignTransaction();\n\n // Resolve the Privy Solana wallet to use\n const embeddedWallet = useMemo(() => {\n if (opts.walletAddress) {\n const w = wallets.find((w) => w.address === opts.walletAddress);\n if (!w) throw new Error(\"Specified Solana wallet not found\");\n return w;\n }\n return wallets[0];\n }, [wallets, opts.walletAddress]);\n\n // Build Solana connection from rpcUrl (hook override or provider default)\n const connection = useMemo(() => {\n const url = opts.rpcUrl || config.solanaRpcUrl;\n return url ? new Connection(url) : null;\n }, [opts.rpcUrl, config.solanaRpcUrl]);\n\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<void | SolanaTransactionResult>(undefined);\n\n const resolvedPolicyId = useMemo(() => {\n if (opts.policyId != null) return opts.policyId || undefined;\n // Use solanaPolicyId from config, fallback to policyId for backwards compat\n const configPolicy = config.solanaPolicyId || config.policyId;\n return Array.isArray(configPolicy) ? configPolicy[0] : configPolicy;\n }, [opts.policyId, config.solanaPolicyId, config.policyId]);\n\n const mapTransformInstructions = useMemo(() => {\n const addSponsorship: TransformInstruction = async (instructions) => {\n const policyId = resolvedPolicyId;\n if (!policyId)\n throw new Error(\n \"Gas sponsorship requires a policyId (see provider or hook options).\",\n );\n const localConnection = connection || missing(\"connection\");\n const fromAddress = embeddedWallet?.address;\n if (!fromAddress) throw new Error(\"No embedded Solana wallet connected\");\n return createSolanaSponsoredTransaction(\n instructions,\n localConnection,\n policyId,\n fromAddress,\n );\n };\n const createTx: TransformInstruction = async (instructions) => {\n const localConnection = connection || missing(\"connection\");\n const fromAddress = embeddedWallet?.address;\n if (!fromAddress) throw new Error(\"No embedded Solana wallet connected\");\n return createSolanaTransaction(\n instructions,\n localConnection,\n fromAddress,\n );\n };\n const defaultTransform =\n !!resolvedPolicyId && !config.disableSponsorship\n ? addSponsorship\n : createTx;\n return {\n addSponsorship,\n createTransaction: createTx,\n default: defaultTransform,\n } as const;\n }, [\n resolvedPolicyId,\n config.disableSponsorship,\n connection,\n embeddedWallet?.address,\n ]);\n\n const buildInstructions = useCallback(\n (\n params: SolanaTransactionParams,\n fromAddress: string,\n ): TransactionInstruction[] => {\n if (\"instructions\" in params) return params.instructions;\n return [\n SystemProgram.transfer({\n fromPubkey: new PublicKey(fromAddress),\n toPubkey: new PublicKey(params.transfer.toAddress),\n lamports:\n typeof params.transfer.amount === \"bigint\"\n ? Number(params.transfer.amount) // web3.js currently expects number; callers can pass bigint safely\n : params.transfer.amount,\n }),\n ];\n },\n [],\n );\n\n function toUnsignedBytes(tx: VersionedTransaction | Transaction): Uint8Array {\n // Serialize the full transaction structure (with placeholder signatures)\n // Privy expects the complete transaction format, not just the message\n if (tx instanceof VersionedTransaction) {\n // VersionedTransaction.serialize() includes signature slots\n return tx.serialize();\n }\n // Legacy Transaction: serialize without requiring all signatures\n const buf = tx.serialize({\n requireAllSignatures: false,\n verifySignatures: false,\n });\n return buf instanceof Uint8Array ? buf : new Uint8Array(buf);\n }\n\n const sendTransactionAsync = useCallback(\n async (\n params: SolanaTransactionParams,\n ): Promise<SolanaTransactionResult> => {\n setIsPending(true);\n setError(null);\n try {\n const localConnection = connection || missing(\"connection\");\n if (!embeddedWallet?.address) {\n throw new Error(\"No Solana wallet connected via Privy\");\n }\n\n const fromAddress = embeddedWallet.address;\n const {\n transactionComponents: { preSend, transformInstruction } = {},\n confirmationOptions,\n } = params;\n\n const instructions = buildInstructions(params, fromAddress);\n\n let transaction: VersionedTransaction | Transaction;\n if (transformInstruction) {\n transaction = await transformInstruction(instructions);\n } else {\n transaction = await mapTransformInstructions.default(instructions);\n }\n\n transaction = (await preSend?.(transaction)) || transaction;\n\n // Sign the transaction using Privy's useSignTransaction hook\n const unsignedBytes = toUnsignedBytes(transaction);\n const { signedTransaction } = await signTransaction({\n transaction: unsignedBytes,\n wallet: embeddedWallet,\n });\n\n // Broadcast the signed transaction\n const hash = await localConnection.sendRawTransaction(\n signedTransaction,\n { skipPreflight: false },\n );\n\n if (confirmationOptions || opts.confirmationOptions) {\n await localConnection.confirmTransaction(\n hash,\n confirmationOptions || opts.confirmationOptions,\n );\n }\n\n setData({ hash });\n return { hash };\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n setIsPending(false);\n }\n },\n [\n embeddedWallet,\n connection,\n buildInstructions,\n mapTransformInstructions,\n opts.confirmationOptions,\n signTransaction,\n ],\n );\n\n const sendTransaction = useCallback(\n (params: SolanaTransactionParams) => {\n // Prevent unhandled rejection warnings; error state is already set in sendTransactionAsync\n sendTransactionAsync(params).catch(() => {});\n },\n [sendTransactionAsync],\n );\n\n const reset = useCallback(() => {\n setIsPending(false);\n setError(null);\n setData(undefined);\n }, []);\n\n return {\n connection,\n data,\n isPending,\n error,\n reset,\n sendTransaction,\n sendTransactionAsync,\n };\n}\n\nfunction missing(message: string): never {\n throw new Error(message);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"useAlchemySolanaTransaction.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemySolanaTransaction.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useMemo, useState } from \"react\";\nimport {\n Connection,\n PublicKey,\n SystemProgram,\n Transaction,\n TransactionInstruction,\n VersionedTransaction,\n} from \"@solana/web3.js\";\nimport { useAlchemyConfig } from \"../context/AlchemyContext.js\";\nimport { createSolanaSponsoredTransaction } from \"../util/createSolanaSponsoredTransaction.js\";\nimport { useSignTransaction, useWallets } from \"@privy-io/react-auth/solana\";\nimport { createSolanaTransaction } from \"../util/createSolanaTransaction.js\";\n\n/**\n * Type helper for values that can be synchronous or asynchronous\n *\n * @template T - The value type\n */\nexport type PromiseOrValue<T> = T | Promise<T>;\n\n/**\n * Callback to modify a transaction before it's signed\n * Useful for adding additional signatures or metadata\n *\n * @param transaction - The unsigned transaction to modify\n * @returns The modified transaction\n */\nexport type PreSend = (\n this: void,\n transaction: VersionedTransaction | Transaction,\n) => PromiseOrValue<VersionedTransaction | Transaction>;\n\n/**\n * Callback to transform instructions into a custom transaction\n * Useful for advanced transaction construction (e.g., multi-sig, custom versioning)\n *\n * @param instructions - Array of Solana transaction instructions\n * @returns Constructed transaction (legacy or versioned)\n */\nexport type TransformInstruction = (\n this: void,\n instructions: TransactionInstruction[],\n) => PromiseOrValue<Transaction | VersionedTransaction>;\n\n/**\n * Optional transaction lifecycle hooks for advanced use cases\n */\nexport type SolanaTransactionParamOptions = {\n /** Hook called before signing the transaction */\n preSend?: PreSend;\n /** Custom transaction builder from instructions */\n transformInstruction?: TransformInstruction;\n};\n\n/**\n * Parameters for sending a Solana transaction\n * Supports either a simple transfer or custom instructions\n */\nexport type SolanaTransactionParams =\n | {\n /** Simple SOL transfer parameters */\n transfer: {\n /** Amount in lamports (accepts number or bigint) */\n amount: number | bigint;\n /** Recipient's base58-encoded address */\n toAddress: string;\n };\n /** Optional transaction lifecycle hooks */\n transactionComponents?: SolanaTransactionParamOptions;\n /** Options for confirming the transaction on-chain */\n confirmationOptions?: Parameters<Connection[\"confirmTransaction\"]>[1];\n }\n | {\n /** Custom Solana transaction instructions */\n instructions: TransactionInstruction[];\n /** Optional transaction lifecycle hooks */\n transactionComponents?: SolanaTransactionParamOptions;\n /** Options for confirming the transaction on-chain */\n confirmationOptions?: Parameters<Connection[\"confirmTransaction\"]>[1];\n };\n\n/**\n * Result of a successful Solana transaction\n */\nexport interface SolanaTransactionResult {\n /** Base58-encoded transaction signature (hash) */\n hash: string;\n}\n\n/**\n * Configuration options for useAlchemySolanaTransaction hook\n */\nexport interface UseAlchemySolanaTransactionOptions {\n /** Solana RPC URL (overrides provider config) */\n rpcUrl?: string;\n /** Gas sponsorship policy ID (overrides provider config) */\n policyId?: string | void;\n /** Transaction confirmation options */\n confirmationOptions?: Parameters<Connection[\"confirmTransaction\"]>[1];\n /** Specific wallet address to use (defaults to first available wallet) */\n walletAddress?: string;\n}\n\n/**\n * Return type of useAlchemySolanaTransaction hook\n */\nexport interface UseAlchemySolanaTransactionResult {\n /** Active Solana connection instance */\n readonly connection: Connection | null;\n /** Transaction result if successful */\n readonly data: void | SolanaTransactionResult;\n /** Whether a transaction is currently being sent */\n readonly isPending: boolean;\n /** Error if transaction failed */\n readonly error: Error | null;\n /** Reset hook state (clears error, data, isPending) */\n reset(): void;\n /** Send transaction (fire-and-forget, errors caught internally) */\n sendTransaction(params: SolanaTransactionParams): void;\n /** Send transaction and await result (throws on error) */\n sendTransactionAsync(\n params: SolanaTransactionParams,\n ): Promise<SolanaTransactionResult>;\n}\n\n/**\n * Hook to send Solana transactions with optional gas sponsorship via Alchemy\n * Works with Privy's Solana wallet integration for signing transactions\n * Supports both simple transfers and custom instruction sets\n *\n * @param {UseAlchemySolanaTransactionOptions} [opts] - Configuration options\n * @param {string} [opts.rpcUrl] - Solana RPC URL (overrides provider config)\n * @param {string} [opts.policyId] - Gas sponsorship policy ID (overrides provider config)\n * @param {string} [opts.walletAddress] - Specific wallet address to use (defaults to first wallet)\n * @param {Parameters<Connection[\"confirmTransaction\"]>[1]} [opts.confirmationOptions] - Transaction confirmation options\n * @returns {UseAlchemySolanaTransactionResult} Hook result with transaction functions and state\n *\n * @example Simple SOL transfer\n * ```tsx\n * const { sendTransactionAsync, isPending, error, data } = useAlchemySolanaTransaction({\n * rpcUrl: 'https://solana-mainnet.g.alchemy.com/v2/your-api-key',\n * policyId: 'your-policy-id', // Optional: for gas sponsorship\n * });\n *\n * const handleTransfer = async () => {\n * try {\n * const result = await sendTransactionAsync({\n * transfer: {\n * amount: 1_000_000_000, // 1 SOL in lamports\n * toAddress: 'recipient-address',\n * },\n * });\n * console.log('Transaction hash:', result.hash);\n * } catch (err) {\n * console.error('Transaction failed:', err);\n * }\n * };\n * ```\n *\n * @example Custom instructions\n * ```tsx\n * import { SystemProgram, PublicKey } from '@solana/web3.js';\n *\n * const { sendTransactionAsync } = useAlchemySolanaTransaction();\n *\n * // Build your custom instructions\n * const transferIx = SystemProgram.transfer({\n * fromPubkey: new PublicKey(walletAddress),\n * toPubkey: new PublicKey(recipientAddress),\n * lamports: 1_000_000,\n * });\n *\n * // Pass instructions array to the hook\n * const result = await sendTransactionAsync({\n * instructions: [transferIx],\n * });\n * ```\n *\n * @example With provider configuration\n * ```tsx\n * // In your provider setup\n * <AlchemyProvider\n * solanaRpcUrl=\"https://solana-mainnet.g.alchemy.com/v2/...\"\n * solanaPolicyId=\"your-solana-policy-id\"\n * >\n * <YourApp />\n * </AlchemyProvider>\n *\n * // In your component - uses provider config automatically\n * const { sendTransactionAsync } = useAlchemySolanaTransaction();\n * ```\n */\nexport function useAlchemySolanaTransaction(\n opts: UseAlchemySolanaTransactionOptions = {},\n): UseAlchemySolanaTransactionResult {\n const config = useAlchemyConfig();\n const { wallets } = useWallets();\n const { signTransaction } = useSignTransaction();\n\n // Resolve the Privy Solana wallet to use\n const embeddedWallet = useMemo(() => {\n if (opts.walletAddress) {\n const w = wallets.find((w) => w.address === opts.walletAddress);\n if (!w) throw new Error(\"Specified Solana wallet not found\");\n return w;\n }\n return wallets[0];\n }, [wallets, opts.walletAddress]);\n\n // Build Solana connection from rpcUrl (hook override or provider default)\n const connection = useMemo(() => {\n const url = opts.rpcUrl || config.solanaRpcUrl;\n return url ? new Connection(url) : null;\n }, [opts.rpcUrl, config.solanaRpcUrl]);\n\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<void | SolanaTransactionResult>(undefined);\n\n const resolvedPolicyId = useMemo(() => {\n if (opts.policyId != null) return opts.policyId || undefined;\n // Use solanaPolicyId from config, fallback to policyId for backwards compat\n const configPolicy = config.solanaPolicyId || config.policyId;\n return Array.isArray(configPolicy) ? configPolicy[0] : configPolicy;\n }, [opts.policyId, config.solanaPolicyId, config.policyId]);\n\n const mapTransformInstructions = useMemo(() => {\n const addSponsorship: TransformInstruction = async (instructions) => {\n const policyId = resolvedPolicyId;\n if (!policyId)\n throw new Error(\n \"Gas sponsorship requires a policyId (see provider or hook options).\",\n );\n const localConnection = connection || missing(\"connection\");\n const fromAddress = embeddedWallet?.address;\n if (!fromAddress) throw new Error(\"No embedded Solana wallet connected\");\n return createSolanaSponsoredTransaction(\n instructions,\n localConnection,\n policyId,\n fromAddress,\n );\n };\n const createTx: TransformInstruction = async (instructions) => {\n const localConnection = connection || missing(\"connection\");\n const fromAddress = embeddedWallet?.address;\n if (!fromAddress) throw new Error(\"No embedded Solana wallet connected\");\n return createSolanaTransaction(\n instructions,\n localConnection,\n fromAddress,\n );\n };\n const defaultTransform =\n !!resolvedPolicyId && !config.disableSponsorship\n ? addSponsorship\n : createTx;\n return {\n addSponsorship,\n createTransaction: createTx,\n default: defaultTransform,\n } as const;\n }, [\n resolvedPolicyId,\n config.disableSponsorship,\n connection,\n embeddedWallet?.address,\n ]);\n\n const buildInstructions = useCallback(\n (\n params: SolanaTransactionParams,\n fromAddress: string,\n ): TransactionInstruction[] => {\n if (\"instructions\" in params) return params.instructions;\n return [\n SystemProgram.transfer({\n fromPubkey: new PublicKey(fromAddress),\n toPubkey: new PublicKey(params.transfer.toAddress),\n lamports:\n typeof params.transfer.amount === \"bigint\"\n ? Number(params.transfer.amount) // web3.js currently expects number; callers can pass bigint safely\n : params.transfer.amount,\n }),\n ];\n },\n [],\n );\n\n function toUnsignedBytes(tx: VersionedTransaction | Transaction): Uint8Array {\n // Serialize the full transaction structure (with placeholder signatures)\n // Privy expects the complete transaction format, not just the message\n if (tx instanceof VersionedTransaction) {\n // VersionedTransaction.serialize() includes signature slots\n return tx.serialize();\n }\n // Legacy Transaction: serialize without requiring all signatures\n const buf = tx.serialize({\n requireAllSignatures: false,\n verifySignatures: false,\n });\n return buf instanceof Uint8Array ? buf : new Uint8Array(buf);\n }\n\n const sendTransactionAsync = useCallback(\n async (\n params: SolanaTransactionParams,\n ): Promise<SolanaTransactionResult> => {\n setIsPending(true);\n setError(null);\n try {\n const localConnection = connection || missing(\"connection\");\n if (!embeddedWallet?.address) {\n throw new Error(\"No Solana wallet connected via Privy\");\n }\n\n const fromAddress = embeddedWallet.address;\n const {\n transactionComponents: { preSend, transformInstruction } = {},\n confirmationOptions,\n } = params;\n\n const instructions = buildInstructions(params, fromAddress);\n\n let transaction: VersionedTransaction | Transaction;\n if (transformInstruction) {\n transaction = await transformInstruction(instructions);\n } else {\n transaction = await mapTransformInstructions.default(instructions);\n }\n\n transaction = (await preSend?.(transaction)) || transaction;\n\n // Sign the transaction using Privy's useSignTransaction hook\n const unsignedBytes = toUnsignedBytes(transaction);\n const { signedTransaction } = await signTransaction({\n transaction: unsignedBytes,\n wallet: embeddedWallet,\n });\n\n // Broadcast the signed transaction\n const hash = await localConnection.sendRawTransaction(\n signedTransaction,\n { skipPreflight: false },\n );\n\n if (confirmationOptions || opts.confirmationOptions) {\n await localConnection.confirmTransaction(\n hash,\n confirmationOptions || opts.confirmationOptions,\n );\n }\n\n setData({ hash });\n return { hash };\n } catch (err) {\n const e = err instanceof Error ? err : new Error(String(err));\n setError(e);\n throw e;\n } finally {\n setIsPending(false);\n }\n },\n [\n embeddedWallet,\n connection,\n buildInstructions,\n mapTransformInstructions,\n opts.confirmationOptions,\n signTransaction,\n ],\n );\n\n const sendTransaction = useCallback(\n (params: SolanaTransactionParams) => {\n // Prevent unhandled rejection warnings; error state is already set in sendTransactionAsync\n sendTransactionAsync(params).catch(() => {});\n },\n [sendTransactionAsync],\n );\n\n const reset = useCallback(() => {\n setIsPending(false);\n setError(null);\n setData(undefined);\n }, []);\n\n return {\n connection,\n data,\n isPending,\n error,\n reset,\n sendTransaction,\n sendTransactionAsync,\n };\n}\n\nfunction missing(message: string): never {\n throw new Error(message);\n}\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { PropsWithChildren } from "react";
|
|
2
|
+
import type { AlchemyProviderConfig } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Provider component for React Native (Expo) applications
|
|
5
|
+
* Must be nested INSIDE PrivyProvider from @privy-io/expo
|
|
6
|
+
*
|
|
7
|
+
* @param {PropsWithChildren<AlchemyProviderConfig>} props - Component props
|
|
8
|
+
* @param {React.ReactNode} props.children - React children to wrap with Alchemy configuration
|
|
9
|
+
* @param {string} [props.apiKey] - Your Alchemy API key
|
|
10
|
+
* @param {string} [props.jwt] - JWT token for authentication
|
|
11
|
+
* @param {string} [props.rpcUrl] - Custom RPC URL for EVM chains
|
|
12
|
+
* @param {string} [props.solanaRpcUrl] - Custom RPC URL for Solana
|
|
13
|
+
* @param {string | string[]} [props.policyId] - Gas Manager policy ID(s) for EVM chains
|
|
14
|
+
* @param {string | string[]} [props.solanaPolicyId] - Gas Manager policy ID(s) for Solana
|
|
15
|
+
* @param {boolean} [props.disableSponsorship] - Set to true to disable sponsorship by default (default: false)
|
|
16
|
+
* @param {'eip7702' | 'owner'} [props.accountAuthMode] - Authorization mode for EVM smart accounts (default: 'eip7702')
|
|
17
|
+
* @param {string} [props.walletAddress] - Optional: Specify which wallet address to use (defaults to first wallet in array)
|
|
18
|
+
* @returns {JSX.Element} Provider component
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* import { PrivyProvider } from '@privy-io/expo';
|
|
23
|
+
* import { AlchemyProvider } from '@account-kit/privy-integration/react-native';
|
|
24
|
+
*
|
|
25
|
+
* <PrivyProvider appId="..." clientId="...">
|
|
26
|
+
* <AlchemyProvider
|
|
27
|
+
* apiKey="your-alchemy-api-key"
|
|
28
|
+
* policyId="your-gas-policy-id"
|
|
29
|
+
* accountAuthMode="eip7702"
|
|
30
|
+
* walletAddress="0x123..." // Optional: specify which wallet to use
|
|
31
|
+
* >
|
|
32
|
+
* <YourApp />
|
|
33
|
+
* </AlchemyProvider>
|
|
34
|
+
* </PrivyProvider>
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function AlchemyProvider({ children, ...config }: PropsWithChildren<AlchemyProviderConfig>): import("react/jsx-runtime").JSX.Element;
|