@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.
- package/README.md +403 -0
- package/dist/chunk-CDPQERUC.mjs +3601 -0
- package/dist/deposit.d.mts +184 -0
- package/dist/deposit.d.ts +184 -0
- package/dist/deposit.js +1563 -0
- package/dist/deposit.mjs +628 -0
- package/dist/index.d.mts +4640 -0
- package/dist/index.d.ts +4640 -0
- package/dist/index.js +5568 -0
- package/dist/index.mjs +2010 -0
- package/dist/use-sync-balances-D1Jdkck9.d.mts +246 -0
- package/dist/use-sync-balances-D1Jdkck9.d.ts +246 -0
- package/package.json +102 -0
package/dist/deposit.mjs
ADDED
|
@@ -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
|
+
};
|