@account-kit/privy-integration 4.75.4 → 4.76.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/README.md +165 -6
- 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 +71 -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/package.json +27 -4
- package/src/Provider.native.tsx +18 -0
- package/src/Provider.tsx +6 -0
- package/src/adapters/react-native.ts +210 -0
- package/src/adapters/types.ts +71 -0
- package/src/adapters/web.native.ts +6 -0
- package/src/adapters/web.ts +113 -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,56 @@
|
|
|
1
|
+
import type { Address, Authorization } from "viem";
|
|
2
|
+
import type { AuthorizationRequest } from "@aa-sdk/core";
|
|
3
|
+
/**
|
|
4
|
+
* Platform-agnostic embedded wallet interface
|
|
5
|
+
* Abstracts differences between @privy-io/react-auth and @privy-io/expo
|
|
6
|
+
*/
|
|
7
|
+
export interface EmbeddedWallet {
|
|
8
|
+
/** Wallet address */
|
|
9
|
+
address: Address;
|
|
10
|
+
/** Chain ID as a string (may be CAIP-2 format like "eip155:1" or numeric string like "1") */
|
|
11
|
+
chainId: string;
|
|
12
|
+
/** Get EVM provider for the wallet */
|
|
13
|
+
getEthereumProvider(): Promise<any>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Platform-agnostic Privy auth state
|
|
17
|
+
*/
|
|
18
|
+
export interface PrivyAuthState {
|
|
19
|
+
/** Whether user is authenticated */
|
|
20
|
+
authenticated: boolean;
|
|
21
|
+
/** User object (platform-specific, used for cache invalidation) */
|
|
22
|
+
user: any;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Adapter interface that each platform must implement
|
|
26
|
+
* Provides platform-specific Privy functionality
|
|
27
|
+
*/
|
|
28
|
+
export interface PrivyAdapter {
|
|
29
|
+
/**
|
|
30
|
+
* Hook to get embedded wallet
|
|
31
|
+
* Must be called as a React hook (follows rules of hooks)
|
|
32
|
+
*
|
|
33
|
+
* @param preferredAddress - Optional address to find a specific wallet
|
|
34
|
+
*/
|
|
35
|
+
useEmbeddedWallet(preferredAddress?: string): () => EmbeddedWallet;
|
|
36
|
+
/**
|
|
37
|
+
* Hook to get Privy authentication state
|
|
38
|
+
* Must be called as a React hook (follows rules of hooks)
|
|
39
|
+
*/
|
|
40
|
+
usePrivyAuth(): PrivyAuthState;
|
|
41
|
+
/**
|
|
42
|
+
* Hook to get current wallet address (for cache invalidation)
|
|
43
|
+
* Returns undefined if no wallet is available
|
|
44
|
+
* Must be called as a React hook (follows rules of hooks)
|
|
45
|
+
*
|
|
46
|
+
* @param preferredAddress - Optional address to find a specific wallet
|
|
47
|
+
*/
|
|
48
|
+
useWalletAddress(preferredAddress?: string): string | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Hook to get EIP-7702 authorization signer (optional, web only)
|
|
51
|
+
* Must be called as a React hook (follows rules of hooks)
|
|
52
|
+
*
|
|
53
|
+
* @param preferredAddress - Optional address to find a specific wallet
|
|
54
|
+
*/
|
|
55
|
+
useAuthorizationSigner?(preferredAddress?: string): ((auth: AuthorizationRequest<number>) => Promise<Authorization<number, true>>) | null;
|
|
56
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/adapters/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Address, Authorization } from \"viem\";\nimport type { AuthorizationRequest } from \"@aa-sdk/core\";\n\n/**\n * Platform-agnostic embedded wallet interface\n * Abstracts differences between @privy-io/react-auth and @privy-io/expo\n */\nexport interface EmbeddedWallet {\n /** Wallet address */\n address: Address;\n\n /** Chain ID as a string (may be CAIP-2 format like \"eip155:1\" or numeric string like \"1\") */\n chainId: string;\n\n /** Get EVM provider for the wallet */\n getEthereumProvider(): Promise<any>;\n}\n\n/**\n * Platform-agnostic Privy auth state\n */\nexport interface PrivyAuthState {\n /** Whether user is authenticated */\n authenticated: boolean;\n\n /** User object (platform-specific, used for cache invalidation) */\n user: any;\n}\n\n/**\n * Adapter interface that each platform must implement\n * Provides platform-specific Privy functionality\n */\nexport interface PrivyAdapter {\n /**\n * Hook to get embedded wallet\n * Must be called as a React hook (follows rules of hooks)\n *\n * @param preferredAddress - Optional address to find a specific wallet\n */\n useEmbeddedWallet(preferredAddress?: string): () => EmbeddedWallet;\n\n /**\n * Hook to get Privy authentication state\n * Must be called as a React hook (follows rules of hooks)\n */\n usePrivyAuth(): PrivyAuthState;\n\n /**\n * Hook to get current wallet address (for cache invalidation)\n * Returns undefined if no wallet is available\n * Must be called as a React hook (follows rules of hooks)\n *\n * @param preferredAddress - Optional address to find a specific wallet\n */\n useWalletAddress(preferredAddress?: string): string | undefined;\n\n /**\n * Hook to get EIP-7702 authorization signer (optional, web only)\n * Must be called as a React hook (follows rules of hooks)\n *\n * @param preferredAddress - Optional address to find a specific wallet\n */\n useAuthorizationSigner?(\n preferredAddress?: string,\n ):\n | ((\n auth: AuthorizationRequest<number>,\n ) => Promise<Authorization<number, true>>)\n | null;\n}\n"]}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { useWallets, usePrivy, useSign7702Authorization, } from "@privy-io/react-auth";
|
|
3
|
+
import { isAddressEqual } from "viem";
|
|
4
|
+
/**
|
|
5
|
+
* Web adapter for @privy-io/react-auth
|
|
6
|
+
* Implements platform-specific hooks for React web applications
|
|
7
|
+
*/
|
|
8
|
+
export const webAdapter = {
|
|
9
|
+
useEmbeddedWallet(preferredAddress) {
|
|
10
|
+
const { wallets } = useWallets();
|
|
11
|
+
const getEmbeddedWallet = useCallback(() => {
|
|
12
|
+
const privyWallets = wallets.filter((w) => w.walletClientType === "privy");
|
|
13
|
+
if (privyWallets.length === 0) {
|
|
14
|
+
throw new Error("Privy embedded wallet not found. Please ensure the user is authenticated.");
|
|
15
|
+
}
|
|
16
|
+
// If a preferred address is specified, find that wallet
|
|
17
|
+
const embedded = preferredAddress
|
|
18
|
+
? privyWallets.find((w) => isAddressEqual(w.address, preferredAddress))
|
|
19
|
+
: privyWallets[0];
|
|
20
|
+
if (!embedded) {
|
|
21
|
+
throw new Error(preferredAddress
|
|
22
|
+
? `Privy embedded wallet with address ${preferredAddress} not found.`
|
|
23
|
+
: "Privy embedded wallet not found. Please ensure the user is authenticated.");
|
|
24
|
+
}
|
|
25
|
+
return adaptWebWallet(embedded);
|
|
26
|
+
}, [wallets, preferredAddress]);
|
|
27
|
+
return getEmbeddedWallet;
|
|
28
|
+
},
|
|
29
|
+
usePrivyAuth() {
|
|
30
|
+
const { user } = usePrivy();
|
|
31
|
+
return { authenticated: !!user, user };
|
|
32
|
+
},
|
|
33
|
+
useWalletAddress(preferredAddress) {
|
|
34
|
+
const { wallets } = useWallets();
|
|
35
|
+
const privyWallets = wallets.filter((w) => w.walletClientType === "privy");
|
|
36
|
+
// If a preferred address is specified, find that wallet
|
|
37
|
+
if (preferredAddress) {
|
|
38
|
+
const wallet = privyWallets.find((w) => isAddressEqual(w.address, preferredAddress));
|
|
39
|
+
return wallet?.address;
|
|
40
|
+
}
|
|
41
|
+
// Otherwise return the first embedded wallet
|
|
42
|
+
return privyWallets[0]?.address;
|
|
43
|
+
},
|
|
44
|
+
useAuthorizationSigner(_preferredAddress) {
|
|
45
|
+
const { signAuthorization } = useSign7702Authorization();
|
|
46
|
+
return useCallback(async (unsignedAuth) => {
|
|
47
|
+
const signature = await signAuthorization({
|
|
48
|
+
...unsignedAuth,
|
|
49
|
+
contractAddress: unsignedAuth.address ?? unsignedAuth.contractAddress,
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
...unsignedAuth,
|
|
53
|
+
...signature,
|
|
54
|
+
};
|
|
55
|
+
}, [signAuthorization]);
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* Adapts a Privy web wallet to the common EmbeddedWallet interface
|
|
60
|
+
*
|
|
61
|
+
* @param {PrivyWallet} wallet - The Privy web wallet to adapt
|
|
62
|
+
* @returns {EmbeddedWallet} The adapted wallet following the common interface
|
|
63
|
+
*/
|
|
64
|
+
function adaptWebWallet(wallet) {
|
|
65
|
+
return {
|
|
66
|
+
address: wallet.address,
|
|
67
|
+
chainId: wallet.chainId || "1",
|
|
68
|
+
getEthereumProvider: () => wallet.getEthereumProvider(),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../../src/adapters/web.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback } from \"react\";\nimport {\n useWallets,\n usePrivy,\n useSign7702Authorization,\n type ConnectedWallet as PrivyWallet,\n} from \"@privy-io/react-auth\";\nimport { isAddressEqual, type Authorization } from \"viem\";\nimport type { AuthorizationRequest } from \"@aa-sdk/core\";\nimport type { PrivyAdapter, EmbeddedWallet, PrivyAuthState } from \"./types.js\";\n\n/**\n * Web adapter for @privy-io/react-auth\n * Implements platform-specific hooks for React web applications\n */\nexport const webAdapter: PrivyAdapter = {\n useEmbeddedWallet(preferredAddress?: string) {\n const { wallets } = useWallets();\n\n const getEmbeddedWallet = useCallback((): EmbeddedWallet => {\n const privyWallets = wallets.filter(\n (w) => w.walletClientType === \"privy\",\n );\n\n if (privyWallets.length === 0) {\n throw new Error(\n \"Privy embedded wallet not found. Please ensure the user is authenticated.\",\n );\n }\n\n // If a preferred address is specified, find that wallet\n const embedded = preferredAddress\n ? privyWallets.find((w) =>\n isAddressEqual(\n w.address as `0x${string}`,\n preferredAddress as `0x${string}`,\n ),\n )\n : privyWallets[0];\n\n if (!embedded) {\n throw new Error(\n preferredAddress\n ? `Privy embedded wallet with address ${preferredAddress} not found.`\n : \"Privy embedded wallet not found. Please ensure the user is authenticated.\",\n );\n }\n\n return adaptWebWallet(embedded);\n }, [wallets, preferredAddress]);\n\n return getEmbeddedWallet;\n },\n\n usePrivyAuth(): PrivyAuthState {\n const { user } = usePrivy();\n return { authenticated: !!user, user };\n },\n\n useWalletAddress(preferredAddress?: string): string | undefined {\n const { wallets } = useWallets();\n const privyWallets = wallets.filter((w) => w.walletClientType === \"privy\");\n\n // If a preferred address is specified, find that wallet\n if (preferredAddress) {\n const wallet = privyWallets.find((w) =>\n isAddressEqual(\n w.address as `0x${string}`,\n preferredAddress as `0x${string}`,\n ),\n );\n return wallet?.address;\n }\n\n // Otherwise return the first embedded wallet\n return privyWallets[0]?.address;\n },\n\n useAuthorizationSigner(_preferredAddress?: string) {\n const { signAuthorization } = useSign7702Authorization();\n\n return useCallback(\n async (\n unsignedAuth: AuthorizationRequest<number>,\n ): Promise<Authorization<number, true>> => {\n const signature = await signAuthorization({\n ...unsignedAuth,\n contractAddress: unsignedAuth.address ?? unsignedAuth.contractAddress,\n });\n\n return {\n ...unsignedAuth,\n ...signature,\n };\n },\n [signAuthorization],\n );\n },\n};\n\n/**\n * Adapts a Privy web wallet to the common EmbeddedWallet interface\n *\n * @param {PrivyWallet} wallet - The Privy web wallet to adapt\n * @returns {EmbeddedWallet} The adapted wallet following the common interface\n */\nfunction adaptWebWallet(wallet: PrivyWallet): EmbeddedWallet {\n return {\n address: wallet.address as `0x${string}`,\n chainId: wallet.chainId || \"1\",\n getEthereumProvider: () => wallet.getEthereumProvider(),\n };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.native.js","sourceRoot":"","sources":["../../../src/adapters/web.native.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC","sourcesContent":["/**\n * React Native stub for web adapter\n * This file prevents Metro from importing @privy-io/react-auth\n */\n\nexport const webAdapter = null;\n"]}
|
|
@@ -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 signing is supported 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
|
+
supportsSignAuthorization: !!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 signing is supported 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 supportsSignAuthorization: !!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
|