@account-kit/privy-integration 4.68.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/LICENSE +21 -0
- package/README.md +372 -0
- package/dist/esm/Provider.d.ts +61 -0
- package/dist/esm/Provider.js +100 -0
- package/dist/esm/Provider.js.map +1 -0
- package/dist/esm/hooks/internal/useEmbeddedWallet.d.ts +10 -0
- package/dist/esm/hooks/internal/useEmbeddedWallet.js +22 -0
- package/dist/esm/hooks/internal/useEmbeddedWallet.js.map +1 -0
- package/dist/esm/hooks/useAlchemyClient.d.ts +17 -0
- package/dist/esm/hooks/useAlchemyClient.js +119 -0
- package/dist/esm/hooks/useAlchemyClient.js.map +1 -0
- package/dist/esm/hooks/useAlchemyPrepareSwap.d.ts +42 -0
- package/dist/esm/hooks/useAlchemyPrepareSwap.js +95 -0
- package/dist/esm/hooks/useAlchemyPrepareSwap.js.map +1 -0
- package/dist/esm/hooks/useAlchemySendTransaction.d.ts +26 -0
- package/dist/esm/hooks/useAlchemySendTransaction.js +127 -0
- package/dist/esm/hooks/useAlchemySendTransaction.js.map +1 -0
- package/dist/esm/hooks/useAlchemySubmitSwap.d.ts +31 -0
- package/dist/esm/hooks/useAlchemySubmitSwap.js +93 -0
- package/dist/esm/hooks/useAlchemySubmitSwap.js.map +1 -0
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.js +8 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/types.d.ts +124 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/util/getChain.d.ts +1 -0
- package/dist/esm/util/getChain.js +98 -0
- package/dist/esm/util/getChain.js.map +1 -0
- package/dist/esm/version.d.ts +1 -0
- package/dist/esm/version.js +4 -0
- package/dist/esm/version.js.map +1 -0
- package/dist/types/Provider.d.ts +62 -0
- package/dist/types/Provider.d.ts.map +1 -0
- package/dist/types/hooks/internal/useEmbeddedWallet.d.ts +11 -0
- package/dist/types/hooks/internal/useEmbeddedWallet.d.ts.map +1 -0
- package/dist/types/hooks/useAlchemyClient.d.ts +18 -0
- package/dist/types/hooks/useAlchemyClient.d.ts.map +1 -0
- package/dist/types/hooks/useAlchemyPrepareSwap.d.ts +43 -0
- package/dist/types/hooks/useAlchemyPrepareSwap.d.ts.map +1 -0
- package/dist/types/hooks/useAlchemySendTransaction.d.ts +27 -0
- package/dist/types/hooks/useAlchemySendTransaction.d.ts.map +1 -0
- package/dist/types/hooks/useAlchemySubmitSwap.d.ts +32 -0
- package/dist/types/hooks/useAlchemySubmitSwap.d.ts.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/types.d.ts +125 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/util/getChain.d.ts +2 -0
- package/dist/types/util/getChain.d.ts.map +1 -0
- package/dist/types/version.d.ts +2 -0
- package/dist/types/version.d.ts.map +1 -0
- package/package.json +66 -0
- package/src/hooks/internal/useEmbeddedWallet.ts +29 -0
- package/src/hooks/useAlchemyClient.ts +160 -0
- package/src/hooks/useAlchemyPrepareSwap.ts +113 -0
- package/src/hooks/useAlchemySendTransaction.ts +160 -0
- package/src/hooks/useAlchemySubmitSwap.ts +120 -0
- package/src/index.ts +23 -0
- package/src/types.ts +159 -0
- package/src/util/getChain.ts +145 -0
- package/src/version.ts +3 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { WalletClientSigner, ConnectionConfigSchema, } from "@aa-sdk/core";
|
|
3
|
+
import { createWalletClient, custom, } from "viem";
|
|
4
|
+
import { useSign7702Authorization } from "@privy-io/react-auth";
|
|
5
|
+
import { createSmartWalletClient, } from "@account-kit/wallet-client";
|
|
6
|
+
import { alchemy } from "@account-kit/infra";
|
|
7
|
+
import { useAlchemyConfig, useClientCache } from "../Provider.js";
|
|
8
|
+
import { getChain } from "../util/getChain.js";
|
|
9
|
+
import { useEmbeddedWallet } from "./internal/useEmbeddedWallet.js";
|
|
10
|
+
/**
|
|
11
|
+
* Hook to get and memoize a SmartWalletClient instance
|
|
12
|
+
* The client is cached in the AlchemyProvider context (React tree scoped)
|
|
13
|
+
* Automatically clears cache on logout via the provider
|
|
14
|
+
*
|
|
15
|
+
* @returns {{ getClient: () => Promise<SmartWalletClient> }} Object containing the smart wallet client getter
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* const { getClient } = useAlchemyClient();
|
|
20
|
+
* const smartWalletClient = await getClient();
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export function useAlchemyClient() {
|
|
24
|
+
const { signAuthorization } = useSign7702Authorization();
|
|
25
|
+
const config = useAlchemyConfig();
|
|
26
|
+
const cache = useClientCache();
|
|
27
|
+
const getEmbeddedWallet = useEmbeddedWallet();
|
|
28
|
+
const getEmbeddedWalletChain = useCallback(() => {
|
|
29
|
+
const embedded = getEmbeddedWallet();
|
|
30
|
+
// Handle CAIP-2 format like "eip155:1"
|
|
31
|
+
const chainIdStr = embedded.chainId?.toString();
|
|
32
|
+
if (!chainIdStr) {
|
|
33
|
+
throw new Error("Embedded wallet chainId is not set. Please ensure the wallet is connected to a network.");
|
|
34
|
+
}
|
|
35
|
+
const numericChainId = chainIdStr.includes(":")
|
|
36
|
+
? chainIdStr.split(":")[1]
|
|
37
|
+
: chainIdStr;
|
|
38
|
+
const parsedChainId = Number(numericChainId);
|
|
39
|
+
if (isNaN(parsedChainId)) {
|
|
40
|
+
throw new Error(`Failed to parse chainId from embedded wallet. Received: ${chainIdStr}`);
|
|
41
|
+
}
|
|
42
|
+
return getChain(parsedChainId);
|
|
43
|
+
}, [getEmbeddedWallet]);
|
|
44
|
+
const getClient = useCallback(async () => {
|
|
45
|
+
const embeddedWallet = getEmbeddedWallet();
|
|
46
|
+
const chain = getEmbeddedWalletChain();
|
|
47
|
+
// Generate a cache key based on configuration and wallet address
|
|
48
|
+
const currentCacheKey = JSON.stringify({
|
|
49
|
+
address: embeddedWallet.address,
|
|
50
|
+
chainId: chain.id,
|
|
51
|
+
apiKey: config.apiKey,
|
|
52
|
+
jwt: config.jwt,
|
|
53
|
+
rpcUrl: config.rpcUrl,
|
|
54
|
+
policyId: config.policyId,
|
|
55
|
+
});
|
|
56
|
+
// Return cached client if configuration hasn't changed
|
|
57
|
+
if (cache.client && cache.cacheKey === currentCacheKey) {
|
|
58
|
+
return cache.client;
|
|
59
|
+
}
|
|
60
|
+
// Configuration changed or no cache exists, create new client
|
|
61
|
+
const provider = await embeddedWallet.getEthereumProvider();
|
|
62
|
+
// Create base signer from Privy wallet
|
|
63
|
+
const baseSigner = new WalletClientSigner(createWalletClient({
|
|
64
|
+
account: embeddedWallet.address,
|
|
65
|
+
chain,
|
|
66
|
+
transport: custom(provider),
|
|
67
|
+
}), "privy");
|
|
68
|
+
// Extend signer with EIP-7702 authorization support
|
|
69
|
+
const signer = {
|
|
70
|
+
...baseSigner,
|
|
71
|
+
signAuthorization: async (unsignedAuth) => {
|
|
72
|
+
const signature = await signAuthorization({
|
|
73
|
+
...unsignedAuth,
|
|
74
|
+
contractAddress: unsignedAuth.address ?? unsignedAuth.contractAddress,
|
|
75
|
+
});
|
|
76
|
+
return {
|
|
77
|
+
...unsignedAuth,
|
|
78
|
+
...signature,
|
|
79
|
+
};
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
// Determine transport configuration using schema validation
|
|
83
|
+
// This properly handles combinations like rpcUrl + jwt together
|
|
84
|
+
const transportConfig = ConnectionConfigSchema.parse({
|
|
85
|
+
rpcUrl: config.rpcUrl,
|
|
86
|
+
apiKey: config.apiKey,
|
|
87
|
+
jwt: config.jwt,
|
|
88
|
+
});
|
|
89
|
+
const transport = alchemy(transportConfig);
|
|
90
|
+
transport.updateHeaders({
|
|
91
|
+
"X-Alchemy-Client-Breadcrumb": "privyIntegrationSdk",
|
|
92
|
+
});
|
|
93
|
+
// Create and cache the smart wallet client in provider context
|
|
94
|
+
cache.client = createSmartWalletClient({
|
|
95
|
+
chain,
|
|
96
|
+
transport,
|
|
97
|
+
signer,
|
|
98
|
+
policyIds: config.policyId
|
|
99
|
+
? Array.isArray(config.policyId)
|
|
100
|
+
? config.policyId
|
|
101
|
+
: [config.policyId]
|
|
102
|
+
: undefined,
|
|
103
|
+
});
|
|
104
|
+
// Store the cache key
|
|
105
|
+
cache.cacheKey = currentCacheKey;
|
|
106
|
+
return cache.client;
|
|
107
|
+
}, [
|
|
108
|
+
getEmbeddedWallet,
|
|
109
|
+
getEmbeddedWalletChain,
|
|
110
|
+
signAuthorization,
|
|
111
|
+
config.apiKey,
|
|
112
|
+
config.jwt,
|
|
113
|
+
config.rpcUrl,
|
|
114
|
+
config.policyId,
|
|
115
|
+
cache,
|
|
116
|
+
]);
|
|
117
|
+
return { getClient };
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=useAlchemyClient.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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 type AuthorizationRequest,\n ConnectionConfigSchema,\n} from \"@aa-sdk/core\";\nimport {\n createWalletClient,\n custom,\n type Address,\n type Authorization,\n} from \"viem\";\nimport { useSign7702Authorization } from \"@privy-io/react-auth\";\nimport {\n createSmartWalletClient,\n type SmartWalletClient,\n} from \"@account-kit/wallet-client\";\nimport { alchemy } from \"@account-kit/infra\";\nimport { useAlchemyConfig, useClientCache } from \"../Provider.js\";\nimport { getChain } from \"../util/getChain.js\";\nimport { useEmbeddedWallet } from \"./internal/useEmbeddedWallet.js\";\n\n/**\n * Hook to get and memoize a SmartWalletClient instance\n * The client is cached in the AlchemyProvider context (React tree scoped)\n * Automatically clears cache on logout via the provider\n *\n * @returns {{ getClient: () => Promise<SmartWalletClient> }} Object containing the smart wallet client getter\n *\n * @example\n * ```tsx\n * const { getClient } = useAlchemyClient();\n * const smartWalletClient = await getClient();\n * ```\n */\nexport function useAlchemyClient() {\n const { signAuthorization } = useSign7702Authorization();\n const config = useAlchemyConfig();\n const cache = useClientCache();\n const getEmbeddedWallet = useEmbeddedWallet();\n\n const getEmbeddedWalletChain = useCallback(() => {\n const embedded = getEmbeddedWallet();\n // Handle CAIP-2 format like \"eip155:1\"\n const chainIdStr = embedded.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\n const numericChainId = chainIdStr.includes(\":\")\n ? chainIdStr.split(\":\")[1]\n : chainIdStr;\n\n const parsedChainId = Number(numericChainId);\n\n if (isNaN(parsedChainId)) {\n throw new Error(\n `Failed to parse chainId from embedded wallet. Received: ${chainIdStr}`,\n );\n }\n\n return getChain(parsedChainId);\n }, [getEmbeddedWallet]);\n\n const getClient = useCallback(async (): Promise<SmartWalletClient> => {\n const embeddedWallet = getEmbeddedWallet();\n const chain = getEmbeddedWalletChain();\n\n // Generate a cache key based on configuration and wallet address\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 });\n\n // Return cached client if configuration hasn't changed\n if (cache.client && cache.cacheKey === currentCacheKey) {\n return cache.client;\n }\n\n // Configuration changed or no cache exists, create new client\n const provider = await embeddedWallet.getEthereumProvider();\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 // Extend signer with EIP-7702 authorization support\n const signer = {\n ...baseSigner,\n signAuthorization: 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 };\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 // Store the cache key\n cache.cacheKey = currentCacheKey;\n\n return cache.client;\n }, [\n getEmbeddedWallet,\n getEmbeddedWalletChain,\n signAuthorization,\n config.apiKey,\n config.jwt,\n config.rpcUrl,\n config.policyId,\n cache,\n ]);\n\n return { getClient };\n}\n"]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { UsePrepareSwapResult } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Hook to request swap quotes and prepare swap calls
|
|
4
|
+
* Part of the two-step swap process: prepare → submit
|
|
5
|
+
* Use with `useAlchemySubmitSwap()` to execute the prepared swap
|
|
6
|
+
*
|
|
7
|
+
* Supports two modes:
|
|
8
|
+
* 1. Specify exact amount to swap FROM (`fromAmount`)
|
|
9
|
+
* 2. Specify minimum amount to receive TO (`minimumToAmount`)
|
|
10
|
+
*
|
|
11
|
+
* @returns {UsePrepareSwapResult} Hook result with prepareSwap function and state
|
|
12
|
+
*
|
|
13
|
+
* @example Complete swap flow
|
|
14
|
+
* ```tsx
|
|
15
|
+
* const { prepareSwap } = useAlchemyPrepareSwap();
|
|
16
|
+
* const { submitSwap } = useAlchemySubmitSwap();
|
|
17
|
+
*
|
|
18
|
+
* // Step 1: Prepare the swap (get quote)
|
|
19
|
+
* const preparedSwap = await prepareSwap({
|
|
20
|
+
* fromToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
|
|
21
|
+
* toToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
22
|
+
* fromAmount: '0xde0b6b3a7640000', // 1 ETH in hex
|
|
23
|
+
* });
|
|
24
|
+
*
|
|
25
|
+
* // Step 2: Execute the swap
|
|
26
|
+
* const result = await submitSwap(preparedSwap);
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @example Swap for minimum amount TO
|
|
30
|
+
* ```tsx
|
|
31
|
+
* const { prepareSwap } = useAlchemyPrepareSwap();
|
|
32
|
+
*
|
|
33
|
+
* // Swap ETH to get at least 100 USDC
|
|
34
|
+
* const result = await prepareSwap({
|
|
35
|
+
* fromToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
|
|
36
|
+
* toToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
37
|
+
* minimumToAmount: '0x5f5e100', // 100 USDC (6 decimals) in hex
|
|
38
|
+
* });
|
|
39
|
+
* console.log('Quote expiry:', new Date(parseInt(result.quote.expiry, 16) * 1000));
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function useAlchemyPrepareSwap(): UsePrepareSwapResult;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
import {} from "viem";
|
|
3
|
+
import { swapActions } from "@account-kit/wallet-client/experimental";
|
|
4
|
+
import { useAlchemyClient } from "./useAlchemyClient.js";
|
|
5
|
+
import { useEmbeddedWallet } from "./internal/useEmbeddedWallet.js";
|
|
6
|
+
/**
|
|
7
|
+
* Hook to request swap quotes and prepare swap calls
|
|
8
|
+
* Part of the two-step swap process: prepare → submit
|
|
9
|
+
* Use with `useAlchemySubmitSwap()` to execute the prepared swap
|
|
10
|
+
*
|
|
11
|
+
* Supports two modes:
|
|
12
|
+
* 1. Specify exact amount to swap FROM (`fromAmount`)
|
|
13
|
+
* 2. Specify minimum amount to receive TO (`minimumToAmount`)
|
|
14
|
+
*
|
|
15
|
+
* @returns {UsePrepareSwapResult} Hook result with prepareSwap function and state
|
|
16
|
+
*
|
|
17
|
+
* @example Complete swap flow
|
|
18
|
+
* ```tsx
|
|
19
|
+
* const { prepareSwap } = useAlchemyPrepareSwap();
|
|
20
|
+
* const { submitSwap } = useAlchemySubmitSwap();
|
|
21
|
+
*
|
|
22
|
+
* // Step 1: Prepare the swap (get quote)
|
|
23
|
+
* const preparedSwap = await prepareSwap({
|
|
24
|
+
* fromToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
|
|
25
|
+
* toToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
26
|
+
* fromAmount: '0xde0b6b3a7640000', // 1 ETH in hex
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* // Step 2: Execute the swap
|
|
30
|
+
* const result = await submitSwap(preparedSwap);
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @example Swap for minimum amount TO
|
|
34
|
+
* ```tsx
|
|
35
|
+
* const { prepareSwap } = useAlchemyPrepareSwap();
|
|
36
|
+
*
|
|
37
|
+
* // Swap ETH to get at least 100 USDC
|
|
38
|
+
* const result = await prepareSwap({
|
|
39
|
+
* fromToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
|
|
40
|
+
* toToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
41
|
+
* minimumToAmount: '0x5f5e100', // 100 USDC (6 decimals) in hex
|
|
42
|
+
* });
|
|
43
|
+
* console.log('Quote expiry:', new Date(parseInt(result.quote.expiry, 16) * 1000));
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export function useAlchemyPrepareSwap() {
|
|
47
|
+
const { getClient } = useAlchemyClient();
|
|
48
|
+
const getEmbeddedWallet = useEmbeddedWallet();
|
|
49
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
50
|
+
const [error, setError] = useState(null);
|
|
51
|
+
const [data, setData] = useState(null);
|
|
52
|
+
const prepareSwap = useCallback(async (request) => {
|
|
53
|
+
setIsLoading(true);
|
|
54
|
+
setError(null);
|
|
55
|
+
try {
|
|
56
|
+
const client = await getClient();
|
|
57
|
+
const embeddedWallet = getEmbeddedWallet();
|
|
58
|
+
// Extend client with swap actions
|
|
59
|
+
const swapClient = client.extend(swapActions);
|
|
60
|
+
// Request the swap quote
|
|
61
|
+
// Note: Gas sponsorship capabilities are configured on the client itself
|
|
62
|
+
const response = await swapClient.requestQuoteV0({
|
|
63
|
+
...request,
|
|
64
|
+
from: request.from || embeddedWallet.address,
|
|
65
|
+
});
|
|
66
|
+
// Validate that we got prepared calls, not raw calls
|
|
67
|
+
if (response.rawCalls) {
|
|
68
|
+
throw new Error("Received raw calls instead of prepared calls. Ensure returnRawCalls is not set to true.");
|
|
69
|
+
}
|
|
70
|
+
setData(response);
|
|
71
|
+
return response;
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
const errorObj = err instanceof Error ? err : new Error("Failed to prepare swap");
|
|
75
|
+
setError(errorObj);
|
|
76
|
+
throw errorObj;
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
setIsLoading(false);
|
|
80
|
+
}
|
|
81
|
+
}, [getClient, getEmbeddedWallet]);
|
|
82
|
+
const reset = useCallback(() => {
|
|
83
|
+
setError(null);
|
|
84
|
+
setData(null);
|
|
85
|
+
setIsLoading(false);
|
|
86
|
+
}, []);
|
|
87
|
+
return {
|
|
88
|
+
prepareSwap,
|
|
89
|
+
isLoading,
|
|
90
|
+
error,
|
|
91
|
+
data,
|
|
92
|
+
reset,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=useAlchemyPrepareSwap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAlchemyPrepareSwap.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemyPrepareSwap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC9C,OAAO,EAAgB,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,yCAAyC,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAOpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,MAAM,UAAU,qBAAqB;IACnC,MAAM,EAAE,SAAS,EAAE,GAAG,gBAAgB,EAAE,CAAC;IACzC,MAAM,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;IAE9C,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IACvD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAA2B,IAAI,CAAC,CAAC;IAEjE,MAAM,WAAW,GAAG,WAAW,CAC7B,KAAK,EAAE,OAA2B,EAA8B,EAAE;QAChE,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;YACjC,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;YAE3C,kCAAkC;YAClC,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAE9C,yBAAyB;YACzB,yEAAyE;YACzE,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,cAAc,CAAC;gBAC/C,GAAG,OAAO;gBACV,IAAI,EAAE,OAAO,CAAC,IAAI,IAAK,cAAc,CAAC,OAAmB;aAC1D,CAAC,CAAC;YAEH,qDAAqD;YACrD,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CACb,yFAAyF,CAC1F,CAAC;YACJ,CAAC;YAED,OAAO,CAAC,QAAQ,CAAC,CAAC;YAClB,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,GACZ,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;YACnE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnB,MAAM,QAAQ,CAAC;QACjB,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,EACD,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAC/B,CAAC;IAEF,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,CAAC;QACd,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO;QACL,WAAW;QACX,SAAS;QACT,KAAK;QACL,IAAI;QACJ,KAAK;KACN,CAAC;AACJ,CAAC","sourcesContent":["import { useCallback, useState } from \"react\";\nimport { type Address } from \"viem\";\nimport { swapActions } from \"@account-kit/wallet-client/experimental\";\nimport { useAlchemyClient } from \"./useAlchemyClient.js\";\nimport { useEmbeddedWallet } from \"./internal/useEmbeddedWallet.js\";\nimport type {\n PrepareSwapRequest,\n PrepareSwapResult,\n UsePrepareSwapResult,\n} from \"../types\";\n\n/**\n * Hook to request swap quotes and prepare swap calls\n * Part of the two-step swap process: prepare → submit\n * Use with `useAlchemySubmitSwap()` to execute the prepared swap\n *\n * Supports two modes:\n * 1. Specify exact amount to swap FROM (`fromAmount`)\n * 2. Specify minimum amount to receive TO (`minimumToAmount`)\n *\n * @returns {UsePrepareSwapResult} Hook result with prepareSwap function and state\n *\n * @example Complete swap flow\n * ```tsx\n * const { prepareSwap } = useAlchemyPrepareSwap();\n * const { submitSwap } = useAlchemySubmitSwap();\n *\n * // Step 1: Prepare the swap (get quote)\n * const preparedSwap = await prepareSwap({\n * fromToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',\n * toToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n * fromAmount: '0xde0b6b3a7640000', // 1 ETH in hex\n * });\n *\n * // Step 2: Execute the swap\n * const result = await submitSwap(preparedSwap);\n * ```\n *\n * @example Swap for minimum amount TO\n * ```tsx\n * const { prepareSwap } = useAlchemyPrepareSwap();\n *\n * // Swap ETH to get at least 100 USDC\n * const result = await prepareSwap({\n * fromToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',\n * toToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n * minimumToAmount: '0x5f5e100', // 100 USDC (6 decimals) in hex\n * });\n * console.log('Quote expiry:', new Date(parseInt(result.quote.expiry, 16) * 1000));\n * ```\n */\nexport function useAlchemyPrepareSwap(): UsePrepareSwapResult {\n const { getClient } = useAlchemyClient();\n const getEmbeddedWallet = useEmbeddedWallet();\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<PrepareSwapResult | null>(null);\n\n const prepareSwap = useCallback(\n async (request: PrepareSwapRequest): Promise<PrepareSwapResult> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const client = await getClient();\n const embeddedWallet = getEmbeddedWallet();\n\n // Extend client with swap actions\n const swapClient = client.extend(swapActions);\n\n // Request the swap quote\n // Note: Gas sponsorship capabilities are configured on the client itself\n const response = await swapClient.requestQuoteV0({\n ...request,\n from: request.from || (embeddedWallet.address as Address),\n });\n\n // Validate that we got prepared calls, not raw calls\n if (response.rawCalls) {\n throw new Error(\n \"Received raw calls instead of prepared calls. Ensure returnRawCalls is not set to true.\",\n );\n }\n\n setData(response);\n return response;\n } catch (err) {\n const errorObj =\n err instanceof Error ? err : new Error(\"Failed to prepare swap\");\n setError(errorObj);\n throw errorObj;\n } finally {\n setIsLoading(false);\n }\n },\n [getClient, getEmbeddedWallet],\n );\n\n const reset = useCallback(() => {\n setError(null);\n setData(null);\n setIsLoading(false);\n }, []);\n\n return {\n prepareSwap,\n isLoading,\n error,\n data,\n reset,\n };\n}\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { UseSendTransactionResult } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* Hook to send transactions with optional gas sponsorship via Alchemy
|
|
4
|
+
* Drop-in alternative to Privy's useSendTransaction hook
|
|
5
|
+
*
|
|
6
|
+
* @returns {UseSendTransactionResult} Hook result with sendTransaction function and state
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* const { sendTransaction, isLoading, error, data } = useAlchemySendTransaction();
|
|
11
|
+
*
|
|
12
|
+
* const handleSend = async () => {
|
|
13
|
+
* try {
|
|
14
|
+
* const result = await sendTransaction({
|
|
15
|
+
* to: '0x...',
|
|
16
|
+
* data: '0x...',
|
|
17
|
+
* value: '1000000000000000000', // 1 ETH
|
|
18
|
+
* });
|
|
19
|
+
* console.log('Transaction hash:', result.txnHash);
|
|
20
|
+
* } catch (err) {
|
|
21
|
+
* console.error('Transaction failed:', err);
|
|
22
|
+
* }
|
|
23
|
+
* };
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function useAlchemySendTransaction(): UseSendTransactionResult;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
import { isHex } from "viem";
|
|
3
|
+
import { useAlchemyClient } from "./useAlchemyClient.js";
|
|
4
|
+
import { useAlchemyConfig } from "../Provider.js";
|
|
5
|
+
import { useEmbeddedWallet } from "./internal/useEmbeddedWallet.js";
|
|
6
|
+
/**
|
|
7
|
+
* Normalize value to hex format
|
|
8
|
+
* Accepts bigint, number, decimal string, or hex string
|
|
9
|
+
*
|
|
10
|
+
* @param {string | number | bigint} value - Value to normalize
|
|
11
|
+
* @returns {Hex} Hex string representation of the value
|
|
12
|
+
*/
|
|
13
|
+
function normalizeValue(value) {
|
|
14
|
+
if (typeof value === "bigint") {
|
|
15
|
+
return `0x${value.toString(16)}`;
|
|
16
|
+
}
|
|
17
|
+
if (typeof value === "number") {
|
|
18
|
+
return `0x${BigInt(value).toString(16)}`;
|
|
19
|
+
}
|
|
20
|
+
if (isHex(value)) {
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
// Assume decimal string
|
|
24
|
+
return `0x${BigInt(value).toString(16)}`;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Hook to send transactions with optional gas sponsorship via Alchemy
|
|
28
|
+
* Drop-in alternative to Privy's useSendTransaction hook
|
|
29
|
+
*
|
|
30
|
+
* @returns {UseSendTransactionResult} Hook result with sendTransaction function and state
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```tsx
|
|
34
|
+
* const { sendTransaction, isLoading, error, data } = useAlchemySendTransaction();
|
|
35
|
+
*
|
|
36
|
+
* const handleSend = async () => {
|
|
37
|
+
* try {
|
|
38
|
+
* const result = await sendTransaction({
|
|
39
|
+
* to: '0x...',
|
|
40
|
+
* data: '0x...',
|
|
41
|
+
* value: '1000000000000000000', // 1 ETH
|
|
42
|
+
* });
|
|
43
|
+
* console.log('Transaction hash:', result.txnHash);
|
|
44
|
+
* } catch (err) {
|
|
45
|
+
* console.error('Transaction failed:', err);
|
|
46
|
+
* }
|
|
47
|
+
* };
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export function useAlchemySendTransaction() {
|
|
51
|
+
const { getClient } = useAlchemyClient();
|
|
52
|
+
const config = useAlchemyConfig();
|
|
53
|
+
const getEmbeddedWallet = useEmbeddedWallet();
|
|
54
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
55
|
+
const [error, setError] = useState(null);
|
|
56
|
+
const [data, setData] = useState(null);
|
|
57
|
+
const sendTransaction = useCallback(async (input, options) => {
|
|
58
|
+
setIsLoading(true);
|
|
59
|
+
setError(null);
|
|
60
|
+
try {
|
|
61
|
+
const client = await getClient();
|
|
62
|
+
const embeddedWallet = getEmbeddedWallet();
|
|
63
|
+
// Determine if transaction should be sponsored
|
|
64
|
+
const hasPolicyId = !!config.policyId;
|
|
65
|
+
const enableSponsorship = !config.disableSponsorship;
|
|
66
|
+
const shouldSponsor = options?.disableSponsorship !== undefined
|
|
67
|
+
? !options.disableSponsorship
|
|
68
|
+
: hasPolicyId && enableSponsorship;
|
|
69
|
+
// Format the transaction call
|
|
70
|
+
const formattedCall = {
|
|
71
|
+
to: input.to,
|
|
72
|
+
data: input.data,
|
|
73
|
+
value: input.value ? normalizeValue(input.value) : undefined,
|
|
74
|
+
};
|
|
75
|
+
// Build capabilities based on sponsorship
|
|
76
|
+
const policyId = Array.isArray(config.policyId)
|
|
77
|
+
? config.policyId[0]
|
|
78
|
+
: config.policyId;
|
|
79
|
+
const capabilities = { eip7702Auth: true };
|
|
80
|
+
if (shouldSponsor && policyId) {
|
|
81
|
+
capabilities.paymasterService = { policyId };
|
|
82
|
+
}
|
|
83
|
+
// Send the transaction
|
|
84
|
+
const result = await client.sendCalls({
|
|
85
|
+
from: embeddedWallet.address,
|
|
86
|
+
calls: [formattedCall],
|
|
87
|
+
capabilities,
|
|
88
|
+
});
|
|
89
|
+
if (!result.preparedCallIds || result.preparedCallIds.length === 0) {
|
|
90
|
+
throw new Error("No prepared call IDs returned from transaction submission");
|
|
91
|
+
}
|
|
92
|
+
// Wait for the transaction to be confirmed
|
|
93
|
+
const txStatus = await client.waitForCallsStatus({
|
|
94
|
+
id: result.preparedCallIds[0],
|
|
95
|
+
timeout: 60000,
|
|
96
|
+
});
|
|
97
|
+
const txnHash = txStatus.receipts?.[0]?.transactionHash;
|
|
98
|
+
if (!txnHash) {
|
|
99
|
+
throw new Error("Transaction hash not found in receipt");
|
|
100
|
+
}
|
|
101
|
+
const txResult = { txnHash };
|
|
102
|
+
setData(txResult);
|
|
103
|
+
return txResult;
|
|
104
|
+
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
const errorObj = err instanceof Error ? err : new Error("Transaction failed");
|
|
107
|
+
setError(errorObj);
|
|
108
|
+
throw errorObj;
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
setIsLoading(false);
|
|
112
|
+
}
|
|
113
|
+
}, [getClient, getEmbeddedWallet, config.policyId, config.disableSponsorship]);
|
|
114
|
+
const reset = useCallback(() => {
|
|
115
|
+
setError(null);
|
|
116
|
+
setData(null);
|
|
117
|
+
setIsLoading(false);
|
|
118
|
+
}, []);
|
|
119
|
+
return {
|
|
120
|
+
sendTransaction,
|
|
121
|
+
isLoading,
|
|
122
|
+
error,
|
|
123
|
+
data,
|
|
124
|
+
reset,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=useAlchemySendTransaction.js.map
|
|
@@ -0,0 +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,EAA0B,KAAK,EAAE,MAAM,MAAM,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAQpE;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,KAA+B;IACrD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;IACnC,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;IAC3C,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACjB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,wBAAwB;IACxB,OAAO,KAAK,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,yBAAyB;IACvC,MAAM,EAAE,SAAS,EAAE,GAAG,gBAAgB,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,MAAM,iBAAiB,GAAG,iBAAiB,EAAE,CAAC;IAE9C,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IACvD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAA+B,IAAI,CAAC,CAAC;IAErE,MAAM,eAAe,GAAG,WAAW,CACjC,KAAK,EACH,KAAiC,EACjC,OAAgC,EACA,EAAE;QAClC,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;YACjC,MAAM,cAAc,GAAG,iBAAiB,EAAE,CAAC;YAE3C,+CAA+C;YAC/C,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;YACtC,MAAM,iBAAiB,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC;YACrD,MAAM,aAAa,GACjB,OAAO,EAAE,kBAAkB,KAAK,SAAS;gBACvC,CAAC,CAAC,CAAC,OAAO,CAAC,kBAAkB;gBAC7B,CAAC,CAAC,WAAW,IAAI,iBAAiB,CAAC;YAEvC,8BAA8B;YAC9B,MAAM,aAAa,GAAG;gBACpB,EAAE,EAAE,KAAK,CAAC,EAAE;gBACZ,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS;aAC7D,CAAC;YAEF,0CAA0C;YAC1C,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC;gBAC7C,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACpB,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;YAEpB,MAAM,YAAY,GAGd,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;YAE1B,IAAI,aAAa,IAAI,QAAQ,EAAE,CAAC;gBAC9B,YAAY,CAAC,gBAAgB,GAAG,EAAE,QAAQ,EAAE,CAAC;YAC/C,CAAC;YAED,uBAAuB;YACvB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC;gBACpC,IAAI,EAAE,cAAc,CAAC,OAAkB;gBACvC,KAAK,EAAE,CAAC,aAAa,CAAC;gBACtB,YAAY;aACb,CAAC,CAAC;YAEH,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnE,MAAM,IAAI,KAAK,CACb,2DAA2D,CAC5D,CAAC;YACJ,CAAC;YAED,2CAA2C;YAC3C,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC;gBAC/C,EAAE,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;gBAC7B,OAAO,EAAE,KAAM;aAChB,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,eAAe,CAAC;YACxD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;YAC3D,CAAC;YAED,MAAM,QAAQ,GAA0B,EAAE,OAAO,EAAE,CAAC;YACpD,OAAO,CAAC,QAAQ,CAAC,CAAC;YAClB,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,GACZ,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;YAC/D,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnB,MAAM,QAAQ,CAAC;QACjB,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,EACD,CAAC,SAAS,EAAE,iBAAiB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,kBAAkB,CAAC,CAC3E,CAAC;IAEF,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,CAAC;QACd,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO;QACL,eAAe;QACf,SAAS;QACT,KAAK;QACL,IAAI;QACJ,KAAK;KACN,CAAC;AACJ,CAAC","sourcesContent":["import { useCallback, useState } from \"react\";\nimport { type Address, type Hex, isHex } from \"viem\";\nimport { useAlchemyClient } from \"./useAlchemyClient.js\";\nimport { useAlchemyConfig } from \"../Provider.js\";\nimport { useEmbeddedWallet } from \"./internal/useEmbeddedWallet.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 * Drop-in alternative to Privy's useSendTransaction hook\n *\n * @returns {UseSendTransactionResult} Hook result with sendTransaction function and state\n *\n * @example\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 */\nexport function useAlchemySendTransaction(): UseSendTransactionResult {\n const { getClient } = useAlchemyClient();\n const config = useAlchemyConfig();\n const getEmbeddedWallet = useEmbeddedWallet();\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,\n options?: SendTransactionOptions,\n ): Promise<SendTransactionResult> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const client = await getClient();\n const embeddedWallet = getEmbeddedWallet();\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\n const formattedCall = {\n to: input.to,\n data: input.data,\n value: input.value ? normalizeValue(input.value) : undefined,\n };\n\n // Build capabilities based on sponsorship\n const policyId = Array.isArray(config.policyId)\n ? config.policyId[0]\n : config.policyId;\n\n const capabilities: {\n eip7702Auth: true;\n paymasterService?: { policyId: string };\n } = { eip7702Auth: true };\n\n if (shouldSponsor && policyId) {\n capabilities.paymasterService = { policyId };\n }\n\n // Send the transaction\n const result = await client.sendCalls({\n from: embeddedWallet.address as Address,\n calls: [formattedCall],\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 [getClient, getEmbeddedWallet, config.policyId, config.disableSponsorship],\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"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { UseSubmitSwapResult } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Hook to sign and submit prepared swap calls
|
|
4
|
+
* Part of the two-step swap process: prepare → submit
|
|
5
|
+
*
|
|
6
|
+
* @returns {UseSubmitSwapResult} Hook result with submitSwap function and state
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* const { prepareSwap } = useAlchemyPrepareSwap();
|
|
11
|
+
* const { submitSwap, isLoading, error, data } = useAlchemySubmitSwap();
|
|
12
|
+
*
|
|
13
|
+
* const handleSwap = async () => {
|
|
14
|
+
* try {
|
|
15
|
+
* // Step 1: Prepare the swap
|
|
16
|
+
* const preparedSwap = await prepareSwap({
|
|
17
|
+
* fromToken: '0x...',
|
|
18
|
+
* toToken: '0x...',
|
|
19
|
+
* fromAmount: '0x...',
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // Step 2: Submit the swap
|
|
23
|
+
* const result = await submitSwap(preparedSwap);
|
|
24
|
+
* console.log('Swap confirmed:', result.txnHash);
|
|
25
|
+
* } catch (err) {
|
|
26
|
+
* console.error('Swap failed:', err);
|
|
27
|
+
* }
|
|
28
|
+
* };
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare function useAlchemySubmitSwap(): UseSubmitSwapResult;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
import { swapActions } from "@account-kit/wallet-client/experimental";
|
|
3
|
+
import { useAlchemyClient } from "./useAlchemyClient.js";
|
|
4
|
+
/**
|
|
5
|
+
* Hook to sign and submit prepared swap calls
|
|
6
|
+
* Part of the two-step swap process: prepare → submit
|
|
7
|
+
*
|
|
8
|
+
* @returns {UseSubmitSwapResult} Hook result with submitSwap function and state
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* const { prepareSwap } = useAlchemyPrepareSwap();
|
|
13
|
+
* const { submitSwap, isLoading, error, data } = useAlchemySubmitSwap();
|
|
14
|
+
*
|
|
15
|
+
* const handleSwap = async () => {
|
|
16
|
+
* try {
|
|
17
|
+
* // Step 1: Prepare the swap
|
|
18
|
+
* const preparedSwap = await prepareSwap({
|
|
19
|
+
* fromToken: '0x...',
|
|
20
|
+
* toToken: '0x...',
|
|
21
|
+
* fromAmount: '0x...',
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* // Step 2: Submit the swap
|
|
25
|
+
* const result = await submitSwap(preparedSwap);
|
|
26
|
+
* console.log('Swap confirmed:', result.txnHash);
|
|
27
|
+
* } catch (err) {
|
|
28
|
+
* console.error('Swap failed:', err);
|
|
29
|
+
* }
|
|
30
|
+
* };
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export function useAlchemySubmitSwap() {
|
|
34
|
+
const { getClient } = useAlchemyClient();
|
|
35
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
36
|
+
const [error, setError] = useState(null);
|
|
37
|
+
const [data, setData] = useState(null);
|
|
38
|
+
const submitSwap = useCallback(async (preparedSwap) => {
|
|
39
|
+
setIsLoading(true);
|
|
40
|
+
setError(null);
|
|
41
|
+
try {
|
|
42
|
+
const client = await getClient();
|
|
43
|
+
// Extend client with swap actions
|
|
44
|
+
const swapClient = client.extend(swapActions);
|
|
45
|
+
// Sign the prepared calls
|
|
46
|
+
const signedCalls = await swapClient.signPreparedCalls(preparedSwap);
|
|
47
|
+
// Send the signed calls
|
|
48
|
+
const { preparedCallIds } = await swapClient.sendPreparedCalls(signedCalls);
|
|
49
|
+
if (!preparedCallIds || preparedCallIds.length === 0) {
|
|
50
|
+
throw new Error("No prepared call IDs returned from swap submission");
|
|
51
|
+
}
|
|
52
|
+
// Wait for the swap to be confirmed
|
|
53
|
+
const callStatusResult = await swapClient.waitForCallsStatus({
|
|
54
|
+
id: preparedCallIds[0],
|
|
55
|
+
timeout: 60000,
|
|
56
|
+
});
|
|
57
|
+
// Validate the transaction was successful
|
|
58
|
+
if (callStatusResult.status !== "success" ||
|
|
59
|
+
!callStatusResult.receipts ||
|
|
60
|
+
!callStatusResult.receipts[0]) {
|
|
61
|
+
throw new Error(`Swap failed with status ${callStatusResult.status}. Full receipt:\n${JSON.stringify(callStatusResult, null, 2)}`);
|
|
62
|
+
}
|
|
63
|
+
const txnHash = callStatusResult.receipts[0].transactionHash;
|
|
64
|
+
if (!txnHash) {
|
|
65
|
+
throw new Error("Transaction hash not found in receipt");
|
|
66
|
+
}
|
|
67
|
+
const result = { txnHash };
|
|
68
|
+
setData(result);
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
const errorObj = err instanceof Error ? err : new Error("Failed to submit swap");
|
|
73
|
+
setError(errorObj);
|
|
74
|
+
throw errorObj;
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
setIsLoading(false);
|
|
78
|
+
}
|
|
79
|
+
}, [getClient]);
|
|
80
|
+
const reset = useCallback(() => {
|
|
81
|
+
setError(null);
|
|
82
|
+
setData(null);
|
|
83
|
+
setIsLoading(false);
|
|
84
|
+
}, []);
|
|
85
|
+
return {
|
|
86
|
+
submitSwap,
|
|
87
|
+
isLoading,
|
|
88
|
+
error,
|
|
89
|
+
data,
|
|
90
|
+
reset,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=useAlchemySubmitSwap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAlchemySubmitSwap.js","sourceRoot":"","sources":["../../../src/hooks/useAlchemySubmitSwap.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useState } from \"react\";\nimport { swapActions } from \"@account-kit/wallet-client/experimental\";\nimport { useAlchemyClient } from \"./useAlchemyClient.js\";\nimport type {\n PrepareSwapResult,\n SubmitSwapResult,\n UseSubmitSwapResult,\n} from \"../types.js\";\n\n/**\n * Hook to sign and submit prepared swap calls\n * Part of the two-step swap process: prepare → submit\n *\n * @returns {UseSubmitSwapResult} Hook result with submitSwap function and state\n *\n * @example\n * ```tsx\n * const { prepareSwap } = useAlchemyPrepareSwap();\n * const { submitSwap, isLoading, error, data } = useAlchemySubmitSwap();\n *\n * const handleSwap = async () => {\n * try {\n * // Step 1: Prepare the swap\n * const preparedSwap = await prepareSwap({\n * fromToken: '0x...',\n * toToken: '0x...',\n * fromAmount: '0x...',\n * });\n *\n * // Step 2: Submit the swap\n * const result = await submitSwap(preparedSwap);\n * console.log('Swap confirmed:', result.txnHash);\n * } catch (err) {\n * console.error('Swap failed:', err);\n * }\n * };\n * ```\n */\nexport function useAlchemySubmitSwap(): UseSubmitSwapResult {\n const { getClient } = useAlchemyClient();\n\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<Error | null>(null);\n const [data, setData] = useState<SubmitSwapResult | null>(null);\n\n const submitSwap = useCallback(\n async (preparedSwap: PrepareSwapResult): Promise<SubmitSwapResult> => {\n setIsLoading(true);\n setError(null);\n\n try {\n const client = await getClient();\n\n // Extend client with swap actions\n const swapClient = client.extend(swapActions);\n\n // Sign the prepared calls\n const signedCalls = await swapClient.signPreparedCalls(preparedSwap);\n\n // Send the signed calls\n const { preparedCallIds } =\n await swapClient.sendPreparedCalls(signedCalls);\n\n if (!preparedCallIds || preparedCallIds.length === 0) {\n throw new Error(\"No prepared call IDs returned from swap submission\");\n }\n\n // Wait for the swap to be confirmed\n const callStatusResult = await swapClient.waitForCallsStatus({\n id: preparedCallIds[0],\n timeout: 60_000,\n });\n\n // Validate the transaction was successful\n if (\n callStatusResult.status !== \"success\" ||\n !callStatusResult.receipts ||\n !callStatusResult.receipts[0]\n ) {\n throw new Error(\n `Swap failed with status ${\n callStatusResult.status\n }. Full receipt:\\n${JSON.stringify(callStatusResult, null, 2)}`,\n );\n }\n\n const txnHash = callStatusResult.receipts[0].transactionHash;\n if (!txnHash) {\n throw new Error(\"Transaction hash not found in receipt\");\n }\n\n const result: SubmitSwapResult = { txnHash };\n setData(result);\n return result;\n } catch (err) {\n const errorObj =\n err instanceof Error ? err : new Error(\"Failed to submit swap\");\n setError(errorObj);\n throw errorObj;\n } finally {\n setIsLoading(false);\n }\n },\n [getClient],\n );\n\n const reset = useCallback(() => {\n setError(null);\n setData(null);\n setIsLoading(false);\n }, []);\n\n return {\n submitSwap,\n isLoading,\n error,\n data,\n reset,\n };\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { AlchemyProvider, useAlchemyConfig } from "./Provider.js";
|
|
2
|
+
export { useAlchemyClient } from "./hooks/useAlchemyClient.js";
|
|
3
|
+
export { useAlchemySendTransaction } from "./hooks/useAlchemySendTransaction.js";
|
|
4
|
+
export { useAlchemyPrepareSwap } from "./hooks/useAlchemyPrepareSwap.js";
|
|
5
|
+
export { useAlchemySubmitSwap } from "./hooks/useAlchemySubmitSwap.js";
|
|
6
|
+
export type { AlchemyProviderConfig, UnsignedTransactionRequest, SendTransactionOptions, SendTransactionResult, UseSendTransactionResult, PrepareSwapRequest, PrepareSwapResult, UsePrepareSwapResult, SubmitSwapResult, UseSubmitSwapResult, SwapQuote, } from "./types.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Provider
|
|
2
|
+
export { AlchemyProvider, useAlchemyConfig } from "./Provider.js";
|
|
3
|
+
// Hooks
|
|
4
|
+
export { useAlchemyClient } from "./hooks/useAlchemyClient.js";
|
|
5
|
+
export { useAlchemySendTransaction } from "./hooks/useAlchemySendTransaction.js";
|
|
6
|
+
export { useAlchemyPrepareSwap } from "./hooks/useAlchemyPrepareSwap.js";
|
|
7
|
+
export { useAlchemySubmitSwap } from "./hooks/useAlchemySubmitSwap.js";
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAElE,QAAQ;AACR,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC","sourcesContent":["// Provider\nexport { AlchemyProvider, useAlchemyConfig } from \"./Provider.js\";\n\n// Hooks\nexport { useAlchemyClient } from \"./hooks/useAlchemyClient.js\";\nexport { useAlchemySendTransaction } from \"./hooks/useAlchemySendTransaction.js\";\nexport { useAlchemyPrepareSwap } from \"./hooks/useAlchemyPrepareSwap.js\";\nexport { useAlchemySubmitSwap } from \"./hooks/useAlchemySubmitSwap.js\";\n\n// Types\nexport type {\n AlchemyProviderConfig,\n UnsignedTransactionRequest,\n SendTransactionOptions,\n SendTransactionResult,\n UseSendTransactionResult,\n PrepareSwapRequest,\n PrepareSwapResult,\n UsePrepareSwapResult,\n SubmitSwapResult,\n UseSubmitSwapResult,\n SwapQuote,\n} from \"./types.js\";\n"]}
|