@agg-build/hooks 1.0.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.
@@ -0,0 +1,628 @@
1
+ import {
2
+ __async,
3
+ getWalletAddressFromUserProfile,
4
+ useAggAuthState,
5
+ useAggBalanceState,
6
+ useAggUiConfig,
7
+ useDepositAddresses,
8
+ useRampQuotes,
9
+ useRampSession,
10
+ useSyncBalances
11
+ } from "./chunk-CDPQERUC.mjs";
12
+
13
+ // src/deposit/normalize-wallet-error.ts
14
+ function normalizeWalletError(error, supportedChains) {
15
+ var _a, _b;
16
+ const message = error instanceof Error ? error.message : String(error);
17
+ const lower = message.toLowerCase();
18
+ if (lower.includes("user rejected") || lower.includes("user denied") || lower.includes("rejected the request") || lower.includes("denied transaction signature")) {
19
+ return { message: "Wallet request rejected.", tone: "error" };
20
+ }
21
+ const chainMismatch = message.includes("does not match the target chain") || message.includes("Expected Chain ID:");
22
+ if (chainMismatch) {
23
+ const match = message.match(/Expected Chain ID:\s*(\d+)/i);
24
+ const targetChainId = match ? Number(match[1]) : void 0;
25
+ const targetChainName = (_b = (_a = supportedChains == null ? void 0 : supportedChains.find((chain) => chain.chainId === targetChainId)) == null ? void 0 : _a.name) != null ? _b : targetChainId ? `chain ${targetChainId}` : "the selected chain";
26
+ return {
27
+ message: `Wallet chain does not match. Please switch your wallet to ${targetChainName}.`,
28
+ tone: "warning"
29
+ };
30
+ }
31
+ return { message, tone: "error" };
32
+ }
33
+
34
+ // src/deposit/use-wallet-token-balance.ts
35
+ import { useEffect, useMemo, useState } from "react";
36
+ import { useQuery } from "@tanstack/react-query";
37
+ import { formatUnits } from "viem";
38
+ import { useAccount, useReadContract } from "wagmi";
39
+ import { useWallet } from "@solana/wallet-adapter-react";
40
+ import { Connection, PublicKey } from "@solana/web3.js";
41
+
42
+ // src/deposit/constants.ts
43
+ var DEFAULT_SOLANA_RPC_ENDPOINT = "https://solana-rpc.publicnode.com";
44
+ var SVM_CHAIN_IDS = /* @__PURE__ */ new Set([792703809]);
45
+
46
+ // src/deposit/use-wallet-token-balance.ts
47
+ var ERC20_BALANCE_OF_ABI = [
48
+ {
49
+ name: "balanceOf",
50
+ type: "function",
51
+ stateMutability: "view",
52
+ inputs: [{ name: "account", type: "address" }],
53
+ outputs: [{ name: "", type: "uint256" }]
54
+ }
55
+ ];
56
+ function getPhantomProvider() {
57
+ var _a, _b;
58
+ if (typeof window === "undefined") return void 0;
59
+ const w = window;
60
+ return (_b = (_a = w.phantom) == null ? void 0 : _a.solana) != null ? _b : w.solana;
61
+ }
62
+ function useWalletTokenBalance({
63
+ isOpen = true,
64
+ chainId,
65
+ tokenAddress,
66
+ decimals,
67
+ svmAddress
68
+ }) {
69
+ var _a, _b, _c;
70
+ const { solanaRpcUrl } = useAggUiConfig();
71
+ const rpcEndpoint = solanaRpcUrl != null ? solanaRpcUrl : DEFAULT_SOLANA_RPC_ENDPOINT;
72
+ const isSvm = chainId !== void 0 && SVM_CHAIN_IDS.has(chainId);
73
+ const { address: evmAddress } = useAccount();
74
+ const evmEnabled = isOpen && !isSvm && !!chainId && !!tokenAddress && !!evmAddress && decimals !== void 0;
75
+ const { data: rawEvmBalance, isLoading: evmLoading } = useReadContract({
76
+ address: tokenAddress,
77
+ chainId,
78
+ abi: ERC20_BALANCE_OF_ABI,
79
+ functionName: "balanceOf",
80
+ args: evmAddress ? [evmAddress] : void 0,
81
+ query: { enabled: evmEnabled, staleTime: 0, refetchOnMount: true }
82
+ });
83
+ const { publicKey: adapterPublicKey } = useWallet();
84
+ const [phantomAddress, setPhantomAddress] = useState(void 0);
85
+ useEffect(() => {
86
+ var _a2;
87
+ if (!isSvm) return;
88
+ const provider = getPhantomProvider();
89
+ if (!provider) return;
90
+ const existing = (_a2 = provider.publicKey) == null ? void 0 : _a2.toBase58();
91
+ if (existing) {
92
+ setPhantomAddress(existing);
93
+ return;
94
+ }
95
+ provider.connect({ onlyIfTrusted: true }).then((res) => setPhantomAddress(res.publicKey.toString())).catch(() => {
96
+ });
97
+ }, [isSvm]);
98
+ const resolvedSvmAddress = (_b = (_a = adapterPublicKey == null ? void 0 : adapterPublicKey.toBase58()) != null ? _a : phantomAddress) != null ? _b : svmAddress;
99
+ const connection = useMemo(() => new Connection(rpcEndpoint), [rpcEndpoint]);
100
+ const svmEnabled = isOpen && isSvm && !!resolvedSvmAddress && !!tokenAddress;
101
+ const svmQuery = useQuery({
102
+ queryKey: ["svm-token-balance", resolvedSvmAddress != null ? resolvedSvmAddress : null, tokenAddress != null ? tokenAddress : null, isOpen],
103
+ enabled: svmEnabled,
104
+ staleTime: 0,
105
+ queryFn: () => __async(null, null, function* () {
106
+ var _a2;
107
+ if (!resolvedSvmAddress || !tokenAddress) return 0;
108
+ const owner = new PublicKey(resolvedSvmAddress);
109
+ const mint = new PublicKey(tokenAddress);
110
+ const accounts = yield connection.getTokenAccountsByOwner(owner, { mint });
111
+ if (accounts.value.length === 0) return 0;
112
+ const first = accounts.value[0];
113
+ if (!first) return 0;
114
+ const balance = yield connection.getTokenAccountBalance(first.pubkey);
115
+ return (_a2 = balance.value.uiAmount) != null ? _a2 : 0;
116
+ })
117
+ });
118
+ if (isSvm) {
119
+ const awaitingSelection2 = isOpen && !!chainId && !tokenAddress;
120
+ return {
121
+ balance: (_c = svmQuery.data) != null ? _c : 0,
122
+ isLoading: awaitingSelection2 || svmQuery.isLoading || svmQuery.isFetching
123
+ };
124
+ }
125
+ const evmBalance = rawEvmBalance !== void 0 && decimals !== void 0 ? Number(formatUnits(rawEvmBalance, decimals)) : 0;
126
+ const awaitingSelection = isOpen && !!chainId && !tokenAddress;
127
+ return { balance: evmBalance, isLoading: awaitingSelection || evmLoading };
128
+ }
129
+
130
+ // src/deposit/use-wallet-send-token.ts
131
+ import { useCallback } from "react";
132
+ import { parseUnits } from "viem";
133
+ import { useWriteContract } from "wagmi";
134
+ import { useWallet as useWallet2 } from "@solana/wallet-adapter-react";
135
+ import {
136
+ Connection as Connection2,
137
+ Keypair,
138
+ PublicKey as PublicKey2,
139
+ SystemProgram,
140
+ Transaction,
141
+ TransactionInstruction
142
+ } from "@solana/web3.js";
143
+ function getPhantomProvider2() {
144
+ var _a, _b;
145
+ if (typeof window === "undefined") return void 0;
146
+ const w = window;
147
+ return (_b = (_a = w.phantom) == null ? void 0 : _a.solana) != null ? _b : w.solana;
148
+ }
149
+ var ERC20_TRANSFER_ABI = [
150
+ {
151
+ constant: false,
152
+ inputs: [
153
+ { name: "to", type: "address" },
154
+ { name: "amount", type: "uint256" }
155
+ ],
156
+ name: "transfer",
157
+ outputs: [{ name: "", type: "bool" }],
158
+ type: "function"
159
+ }
160
+ ];
161
+ function useWalletSendToken() {
162
+ const { solanaRpcUrl } = useAggUiConfig();
163
+ const rpcEndpoint = solanaRpcUrl != null ? solanaRpcUrl : DEFAULT_SOLANA_RPC_ENDPOINT;
164
+ const { writeContractAsync } = useWriteContract();
165
+ const { publicKey, sendTransaction } = useWallet2();
166
+ return useCallback(
167
+ (params) => __async(null, null, function* () {
168
+ var _a, _b;
169
+ const isSvm = SVM_CHAIN_IDS.has(params.chainId);
170
+ if (!isSvm) {
171
+ const tokenAddress = params.token.address;
172
+ if (!tokenAddress) {
173
+ throw new Error("Missing ERC-20 token address for EVM transfer");
174
+ }
175
+ const value = parseUnits(params.amount || "0", params.token.decimals);
176
+ const txHash = yield writeContractAsync({
177
+ chainId: params.chainId,
178
+ address: tokenAddress,
179
+ abi: ERC20_TRANSFER_ABI,
180
+ functionName: "transfer",
181
+ args: [params.to, value]
182
+ });
183
+ return { txId: txHash };
184
+ }
185
+ if (!params.token.address) {
186
+ throw new Error("Missing SPL token mint address for Solana transfer");
187
+ }
188
+ const phantom = getPhantomProvider2();
189
+ let ownerBase58 = publicKey == null ? void 0 : publicKey.toBase58();
190
+ if (!ownerBase58 && phantom) {
191
+ try {
192
+ const res = yield phantom.connect();
193
+ ownerBase58 = res.publicKey.toString();
194
+ } catch (err) {
195
+ throw new Error(
196
+ `Failed to connect Phantom: ${err instanceof Error ? err.message : String(err)}`
197
+ );
198
+ }
199
+ }
200
+ if (!ownerBase58) {
201
+ throw new Error("No Solana wallet connected");
202
+ }
203
+ const sendConnection = new Connection2(rpcEndpoint, "confirmed");
204
+ const TOKEN_PROGRAM_ID = new PublicKey2("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
205
+ const ASSOCIATED_TOKEN_PROGRAM_ID = new PublicKey2(
206
+ "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
207
+ );
208
+ const owner = new PublicKey2(ownerBase58);
209
+ const mint = new PublicKey2(params.token.address);
210
+ const destinationOwner = new PublicKey2(params.to);
211
+ const getAta = (walletPk, mintPk) => {
212
+ const [ata] = PublicKey2.findProgramAddressSync(
213
+ [walletPk.toBuffer(), TOKEN_PROGRAM_ID.toBuffer(), mintPk.toBuffer()],
214
+ ASSOCIATED_TOKEN_PROGRAM_ID
215
+ );
216
+ return ata;
217
+ };
218
+ const sourceAta = getAta(owner, mint);
219
+ const destinationAta = getAta(destinationOwner, mint);
220
+ const tx = new Transaction();
221
+ let destinationTokenAccountSigner = null;
222
+ const destinationOwnerInfo = yield sendConnection.getAccountInfo(destinationOwner);
223
+ const destinationInfo = yield sendConnection.getAccountInfo(destinationAta);
224
+ let destinationTokenAccount = destinationAta;
225
+ if (!destinationInfo) {
226
+ const rentExemptLamports = yield sendConnection.getMinimumBalanceForRentExemption(165);
227
+ const payerLamports = yield sendConnection.getBalance(owner, "confirmed");
228
+ const feeBufferLamports = 1e4;
229
+ const requiredLamports = rentExemptLamports + feeBufferLamports;
230
+ if (payerLamports < requiredLamports) {
231
+ const requiredSol = (requiredLamports / 1e9).toFixed(6);
232
+ const currentSol = (payerLamports / 1e9).toFixed(6);
233
+ throw new Error(
234
+ `This Solana deposit needs about ${requiredSol} SOL to create the destination token account, but the connected wallet only has ${currentSol} SOL available.`
235
+ );
236
+ }
237
+ const canCreateAta = (_b = (_a = destinationOwnerInfo == null ? void 0 : destinationOwnerInfo.owner) == null ? void 0 : _a.equals(SystemProgram.programId)) != null ? _b : false;
238
+ if (canCreateAta) {
239
+ const createIx = new TransactionInstruction({
240
+ programId: ASSOCIATED_TOKEN_PROGRAM_ID,
241
+ keys: [
242
+ { pubkey: owner, isSigner: true, isWritable: true },
243
+ { pubkey: destinationAta, isSigner: false, isWritable: true },
244
+ { pubkey: destinationOwner, isSigner: false, isWritable: false },
245
+ { pubkey: mint, isSigner: false, isWritable: false },
246
+ { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
247
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false }
248
+ ],
249
+ data: Buffer.alloc(0)
250
+ });
251
+ tx.add(createIx);
252
+ } else {
253
+ destinationTokenAccountSigner = Keypair.generate();
254
+ destinationTokenAccount = destinationTokenAccountSigner.publicKey;
255
+ tx.add(
256
+ SystemProgram.createAccount({
257
+ fromPubkey: owner,
258
+ newAccountPubkey: destinationTokenAccount,
259
+ lamports: rentExemptLamports,
260
+ space: 165,
261
+ programId: TOKEN_PROGRAM_ID
262
+ })
263
+ );
264
+ const initAccountData = Buffer.concat([
265
+ Buffer.from([18]),
266
+ // InitializeAccount3
267
+ destinationOwner.toBuffer()
268
+ ]);
269
+ tx.add(
270
+ new TransactionInstruction({
271
+ programId: TOKEN_PROGRAM_ID,
272
+ keys: [
273
+ { pubkey: destinationTokenAccount, isSigner: false, isWritable: true },
274
+ { pubkey: mint, isSigner: false, isWritable: false }
275
+ ],
276
+ data: initAccountData
277
+ })
278
+ );
279
+ }
280
+ }
281
+ let factor = BigInt(1);
282
+ for (let i = 0; i < params.token.decimals; i += 1) {
283
+ factor *= BigInt(10);
284
+ }
285
+ const amountRaw = BigInt(Math.trunc(Number(params.amount || "0") * Number(factor)));
286
+ const data = new Uint8Array(10);
287
+ data[0] = 12;
288
+ let remaining = amountRaw;
289
+ const mask = BigInt(255);
290
+ for (let i = 0; i < 8; i += 1) {
291
+ data[1 + i] = Number(remaining & mask);
292
+ remaining >>= BigInt(8);
293
+ }
294
+ data[9] = params.token.decimals;
295
+ const transferIx = new TransactionInstruction({
296
+ programId: TOKEN_PROGRAM_ID,
297
+ keys: [
298
+ { pubkey: sourceAta, isSigner: false, isWritable: true },
299
+ { pubkey: mint, isSigner: false, isWritable: false },
300
+ { pubkey: destinationTokenAccount, isSigner: false, isWritable: true },
301
+ { pubkey: owner, isSigner: true, isWritable: false }
302
+ ],
303
+ data: Buffer.from(data)
304
+ });
305
+ tx.add(transferIx);
306
+ tx.feePayer = owner;
307
+ const { blockhash } = yield sendConnection.getLatestBlockhash("confirmed");
308
+ tx.recentBlockhash = blockhash;
309
+ if (destinationTokenAccountSigner) {
310
+ tx.partialSign(destinationTokenAccountSigner);
311
+ }
312
+ let signature;
313
+ if (publicKey && sendTransaction) {
314
+ signature = yield sendTransaction(tx, sendConnection);
315
+ } else if (phantom) {
316
+ const res = yield phantom.signAndSendTransaction(tx);
317
+ signature = res.signature;
318
+ } else {
319
+ throw new Error("No Solana signer available");
320
+ }
321
+ return { txId: signature };
322
+ }),
323
+ [publicKey, rpcEndpoint, sendTransaction, writeContractAsync]
324
+ );
325
+ }
326
+
327
+ // src/deposit/use-wallet-transaction-status.ts
328
+ import { useMemo as useMemo2 } from "react";
329
+ import { useQuery as useQuery2 } from "@tanstack/react-query";
330
+ import { formatEther } from "viem";
331
+ import { Connection as Connection3 } from "@solana/web3.js";
332
+ import { useWaitForTransactionReceipt } from "wagmi";
333
+ function useWalletTransactionStatus({
334
+ chainId,
335
+ txId
336
+ }) {
337
+ var _a;
338
+ const { solanaRpcUrl } = useAggUiConfig();
339
+ const rpcEndpoint = solanaRpcUrl != null ? solanaRpcUrl : DEFAULT_SOLANA_RPC_ENDPOINT;
340
+ const isSvm = chainId !== void 0 && SVM_CHAIN_IDS.has(chainId);
341
+ const evmHash = !isSvm && txId ? txId : void 0;
342
+ const evmReceipt = useWaitForTransactionReceipt({
343
+ chainId,
344
+ hash: evmHash,
345
+ query: {
346
+ enabled: !!evmHash && !!chainId,
347
+ refetchInterval: 2e3
348
+ }
349
+ });
350
+ const connection = useMemo2(() => new Connection3(rpcEndpoint, "confirmed"), [rpcEndpoint]);
351
+ const svmQuery = useQuery2({
352
+ queryKey: ["wallet-transaction-status", chainId != null ? chainId : null, txId != null ? txId : null],
353
+ enabled: isSvm && !!txId,
354
+ refetchInterval: (query) => query.state.data === "settled" || query.state.data === "error" ? false : 2e3,
355
+ queryFn: () => __async(null, null, function* () {
356
+ if (!txId) return "submitted";
357
+ const [status] = (yield connection.getSignatureStatuses([txId], { searchTransactionHistory: true })).value;
358
+ if (!status) return "submitted";
359
+ if (status.err) return "error";
360
+ if (status.confirmationStatus === "confirmed" || status.confirmationStatus === "finalized") {
361
+ return "settled";
362
+ }
363
+ return "confirming";
364
+ })
365
+ });
366
+ if (isSvm) {
367
+ return { status: txId ? (_a = svmQuery.data) != null ? _a : "submitted" : null, gasFee: "" };
368
+ }
369
+ if (!txId) {
370
+ return { status: null, gasFee: "" };
371
+ }
372
+ if (evmReceipt.isError) {
373
+ return { status: "error", gasFee: "" };
374
+ }
375
+ if (!evmReceipt.data) {
376
+ return { status: evmReceipt.isPending ? "confirming" : "submitted", gasFee: "" };
377
+ }
378
+ const effectiveGasPrice = evmReceipt.data.effectiveGasPrice;
379
+ const gasFeeWei = effectiveGasPrice * evmReceipt.data.gasUsed;
380
+ const gasFeeEth = Number(formatEther(gasFeeWei));
381
+ const gasFee = gasFeeEth > 0 ? `${gasFeeEth.toFixed(6)} ETH` : "";
382
+ return { status: "settled", gasFee };
383
+ }
384
+
385
+ // src/deposit/use-deposit-flow.ts
386
+ import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo3, useRef, useState as useState2 } from "react";
387
+ import { useAccount as useAccount2, useSwitchChain } from "wagmi";
388
+ import { useWallet as useSolanaWallet } from "@solana/wallet-adapter-react";
389
+ function useDepositFlow(options) {
390
+ var _a, _b;
391
+ const { open, onOpenChange } = options;
392
+ const { user } = useAggAuthState();
393
+ const { walletActions } = useAggUiConfig();
394
+ const { totalBalance } = useAggBalanceState();
395
+ const deposit = useDepositAddresses({ enabled: !!user });
396
+ const { supportedChains } = deposit;
397
+ const { mutate: syncBalancesMutate } = useSyncBalances();
398
+ const defaultSendToken = useWalletSendToken();
399
+ const sendToken = (_a = walletActions == null ? void 0 : walletActions.sendToken) != null ? _a : defaultSendToken;
400
+ const { mutateAsync: getRampQuotes } = useRampQuotes();
401
+ const { mutateAsync: createRampSession } = useRampSession();
402
+ const [depositAmount, setDepositAmount] = useState2("");
403
+ const [cardAmount, setCardAmount] = useState2("");
404
+ const [cardNetwork, setCardNetwork] = useState2("solana");
405
+ const [walletModalChainId, setWalletModalChainId] = useState2(null);
406
+ const [walletModalTokenSymbol, setWalletModalTokenSymbol] = useState2(null);
407
+ const [walletTransaction, setWalletTransaction] = useState2(null);
408
+ const [walletTransactionError, setWalletTransactionError] = useState2(null);
409
+ const [walletTransactionErrorTone, setWalletTransactionErrorTone] = useState2(
410
+ "error"
411
+ );
412
+ const [pendingCardPurchaseSummary, setPendingCardPurchaseSummary] = useState2(null);
413
+ const rampRedirectHandled = useRef(false);
414
+ useEffect2(() => {
415
+ var _a2, _b2;
416
+ if (rampRedirectHandled.current) return;
417
+ if (typeof window === "undefined") return;
418
+ const url = new URL(window.location.href);
419
+ const cryptoAmount = url.searchParams.get("cryptoAmount");
420
+ const cryptoCurrency = url.searchParams.get("cryptoCurrency");
421
+ if (!cryptoAmount) return;
422
+ rampRedirectHandled.current = true;
423
+ const network = (_a2 = url.searchParams.get("network")) != null ? _a2 : "";
424
+ const totalFee = (_b2 = url.searchParams.get("totalFeeInFiat")) != null ? _b2 : "";
425
+ setPendingCardPurchaseSummary({
426
+ amountReceived: `+${cryptoAmount} ${cryptoCurrency != null ? cryptoCurrency : "USDC"}`,
427
+ network: network.charAt(0).toUpperCase() + network.slice(1),
428
+ fees: totalFee ? `$${totalFee}` : ""
429
+ });
430
+ onOpenChange(true);
431
+ }, []);
432
+ const { chainId: connectedChainId, address: connectedAddress } = useAccount2();
433
+ const { switchChainAsync } = useSwitchChain();
434
+ const { publicKey: solanaPublicKey } = useSolanaWallet();
435
+ const balanceChainId = walletModalChainId ? Number(walletModalChainId) : connectedChainId;
436
+ const selectedChainTokens = useMemo3(() => {
437
+ var _a2;
438
+ if (!supportedChains || !balanceChainId) return [];
439
+ const chain = supportedChains.find((c) => c.chainId === balanceChainId);
440
+ return (_a2 = chain == null ? void 0 : chain.tokens) != null ? _a2 : [];
441
+ }, [supportedChains, balanceChainId]);
442
+ const selectedTokenMeta = useMemo3(() => {
443
+ if (!walletModalTokenSymbol) return void 0;
444
+ const match = selectedChainTokens.find((t) => t.symbol === walletModalTokenSymbol);
445
+ return match ? { address: match.address, decimals: match.decimals } : void 0;
446
+ }, [selectedChainTokens, walletModalTokenSymbol]);
447
+ const authSvmAddress = useMemo3(() => {
448
+ var _a2;
449
+ const wallets = user == null ? void 0 : user.wallets;
450
+ return (_a2 = wallets == null ? void 0 : wallets.find((w) => w.chain === "solana" || w.chain === "svm")) == null ? void 0 : _a2.address;
451
+ }, [user]);
452
+ const isSvmBalanceChain = balanceChainId !== void 0 && SVM_CHAIN_IDS.has(balanceChainId);
453
+ const walletAddress = useMemo3(() => {
454
+ var _a2, _b2, _c;
455
+ if (isSvmBalanceChain) {
456
+ return (_b2 = (_a2 = solanaPublicKey == null ? void 0 : solanaPublicKey.toBase58()) != null ? _a2 : authSvmAddress) != null ? _b2 : "";
457
+ }
458
+ return (_c = connectedAddress != null ? connectedAddress : getWalletAddressFromUserProfile(user)) != null ? _c : "";
459
+ }, [authSvmAddress, connectedAddress, isSvmBalanceChain, solanaPublicKey, user]);
460
+ const walletLabel = useMemo3(() => {
461
+ return walletAddress ? `${walletAddress.slice(0, 6)}...${walletAddress.slice(-4)}` : "\u2014";
462
+ }, [walletAddress]);
463
+ const { balance: walletBalance, isLoading: isWalletBalanceLoading } = useWalletTokenBalance({
464
+ isOpen: open,
465
+ chainId: balanceChainId,
466
+ tokenAddress: selectedTokenMeta == null ? void 0 : selectedTokenMeta.address,
467
+ decimals: selectedTokenMeta == null ? void 0 : selectedTokenMeta.decimals,
468
+ svmAddress: authSvmAddress
469
+ });
470
+ const { status: observedWalletTransactionStatus, gasFee: walletTransactionGasFee } = useWalletTransactionStatus({
471
+ chainId: walletTransaction == null ? void 0 : walletTransaction.chainId,
472
+ txId: (_b = walletTransaction == null ? void 0 : walletTransaction.txId) != null ? _b : null
473
+ });
474
+ const walletTransactionStatus = walletTransactionError ? "error" : walletTransaction ? observedWalletTransactionStatus != null ? observedWalletTransactionStatus : "submitted" : void 0;
475
+ const syncedDepositTxIdRef = useRef(null);
476
+ useEffect2(() => {
477
+ if (walletTransactionStatus !== "settled" || !(walletTransaction == null ? void 0 : walletTransaction.txId)) return;
478
+ if (syncedDepositTxIdRef.current === walletTransaction.txId) return;
479
+ syncedDepositTxIdRef.current = walletTransaction.txId;
480
+ syncBalancesMutate();
481
+ }, [syncBalancesMutate, walletTransaction == null ? void 0 : walletTransaction.txId, walletTransactionStatus]);
482
+ const handleDepositModalOpenChange = useCallback2(
483
+ (isOpen) => {
484
+ if (!isOpen) {
485
+ setDepositAmount("");
486
+ setCardAmount("");
487
+ setCardNetwork("solana");
488
+ setWalletModalChainId(null);
489
+ setWalletModalTokenSymbol(null);
490
+ setWalletTransaction(null);
491
+ setWalletTransactionError(null);
492
+ setWalletTransactionErrorTone("error");
493
+ setPendingCardPurchaseSummary(null);
494
+ syncedDepositTxIdRef.current = null;
495
+ }
496
+ onOpenChange(isOpen);
497
+ },
498
+ [onOpenChange]
499
+ );
500
+ const handleConfirmWalletDeposit = useCallback2(
501
+ (params) => __async(null, null, function* () {
502
+ var _a2, _b2, _c;
503
+ const { address, amount, chainId, token } = params;
504
+ const chain = (_a2 = supportedChains == null ? void 0 : supportedChains.find((c) => c.chainId === chainId)) != null ? _a2 : null;
505
+ const tokenMeta = (_b2 = chain == null ? void 0 : chain.tokens.find((t) => t.symbol === token)) != null ? _b2 : null;
506
+ try {
507
+ setWalletTransactionError(null);
508
+ setWalletTransactionErrorTone("error");
509
+ const isEvmTarget = !SVM_CHAIN_IDS.has(chainId);
510
+ if (isEvmTarget && connectedChainId && connectedChainId !== chainId) {
511
+ yield switchChainAsync({ chainId });
512
+ }
513
+ const { txId } = yield sendToken({
514
+ chainId,
515
+ token: {
516
+ symbol: token,
517
+ address: tokenMeta == null ? void 0 : tokenMeta.address,
518
+ decimals: (_c = tokenMeta == null ? void 0 : tokenMeta.decimals) != null ? _c : 6
519
+ },
520
+ to: address,
521
+ amount
522
+ });
523
+ setWalletTransaction({ chainId, txId });
524
+ } catch (err) {
525
+ setWalletTransaction(null);
526
+ const normalizedError = normalizeWalletError(err, supportedChains);
527
+ setWalletTransactionError(normalizedError.message);
528
+ setWalletTransactionErrorTone(normalizedError.tone);
529
+ throw err;
530
+ }
531
+ }),
532
+ [connectedChainId, sendToken, supportedChains, switchChainAsync]
533
+ );
534
+ const handleGetCardQuotes = useCallback2(
535
+ (params) => __async(null, null, function* () {
536
+ const quotes = yield getRampQuotes(params);
537
+ return quotes.map(
538
+ (q, i) => ({
539
+ id: q.serviceProvider,
540
+ name: q.serviceProvider,
541
+ quote: `~ ${q.destinationAmount.toFixed(2)} USDC`,
542
+ fee: `$${q.totalFee.toFixed(2)}`,
543
+ badge: i === 0 ? "best" : q.lowKyc ? "low-kyc" : void 0
544
+ })
545
+ );
546
+ }),
547
+ [getRampQuotes]
548
+ );
549
+ const handleCreateCardSession = useCallback2(
550
+ (params) => __async(null, null, function* () {
551
+ if (!params.walletAddress) {
552
+ throw new Error("Deposit address not available for the selected network");
553
+ }
554
+ const session = yield createRampSession(params);
555
+ return {
556
+ id: session.id,
557
+ widgetUrl: session.widgetUrl,
558
+ serviceProviderWidgetUrl: session.serviceProviderWidgetUrl
559
+ };
560
+ }),
561
+ [createRampSession]
562
+ );
563
+ const cardRedirectUrl = typeof window !== "undefined" ? `${window.location.origin}/profile?tab=activity` : void 0;
564
+ return {
565
+ open,
566
+ onOpenChange: handleDepositModalOpenChange,
567
+ pendingCardPurchaseSummary,
568
+ walletFlow: {
569
+ balance: totalBalance != null ? totalBalance : 0,
570
+ walletLabel,
571
+ walletBalance,
572
+ isWalletBalanceLoading,
573
+ amount: depositAmount,
574
+ formErrorMessage: walletTransaction ? void 0 : walletTransactionError != null ? walletTransactionError : void 0,
575
+ formErrorTone: walletTransactionErrorTone,
576
+ transactionStatus: walletTransactionStatus,
577
+ transactionErrorMessage: walletTransactionError != null ? walletTransactionError : void 0,
578
+ successSummary: {
579
+ fromWallet: walletLabel,
580
+ gasFee: walletTransactionGasFee
581
+ }
582
+ },
583
+ onWalletAmountChange: setDepositAmount,
584
+ onWalletMax: useCallback2(() => setDepositAmount(String(walletBalance)), [walletBalance]),
585
+ onConfirmWalletDeposit: handleConfirmWalletDeposit,
586
+ onWalletNetworkChange: setWalletModalChainId,
587
+ onWalletTokenChange: setWalletModalTokenSymbol,
588
+ initialWalletChainId: connectedChainId ? String(connectedChainId) : void 0,
589
+ connectedWalletKind: connectedChainId && !solanaPublicKey ? "evm" : solanaPublicKey && !connectedChainId ? "solana" : void 0,
590
+ sendCryptoConfig: { minDeposit: "$1", feeEstimate: "~$0.01", eta: "~30s" },
591
+ onDoneSendCrypto: useCallback2(
592
+ () => handleDepositModalOpenChange(false),
593
+ [handleDepositModalOpenChange]
594
+ ),
595
+ cardFlow: {
596
+ amount: cardAmount,
597
+ currency: "USD",
598
+ tokenOptions: [{ value: "USDC", label: "USDC" }],
599
+ selectedToken: "USDC",
600
+ selectedNetwork: cardNetwork,
601
+ providers: [],
602
+ purchaseSummary: { amountReceived: "", network: "", fees: "" },
603
+ minAmount: 11
604
+ },
605
+ onCardAmountChange: setCardAmount,
606
+ onCardNetworkChange: setCardNetwork,
607
+ onDoneCardPurchase: useCallback2(() => {
608
+ syncBalancesMutate();
609
+ if (typeof window !== "undefined") {
610
+ window.history.replaceState({}, "", window.location.pathname);
611
+ }
612
+ }, [syncBalancesMutate]),
613
+ cardRedirectUrl,
614
+ onGetCardQuotes: handleGetCardQuotes,
615
+ onCreateCardSession: handleCreateCardSession
616
+ };
617
+ }
618
+ export {
619
+ DEFAULT_SOLANA_RPC_ENDPOINT,
620
+ SVM_CHAIN_IDS,
621
+ normalizeWalletError,
622
+ useDepositAddresses,
623
+ useDepositFlow,
624
+ useSyncBalances,
625
+ useWalletSendToken,
626
+ useWalletTokenBalance,
627
+ useWalletTransactionStatus
628
+ };