@agg-build/hooks 1.0.0 → 1.0.2
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 +1 -1
- package/dist/chunk-EB64HHYM.mjs +31 -0
- package/dist/chunk-NOYHQUW2.mjs +389 -0
- package/dist/{chunk-CDPQERUC.mjs → chunk-V6VNA7MX.mjs} +105 -38
- package/dist/deposit.d.mts +2 -1
- package/dist/deposit.d.ts +2 -1
- package/dist/deposit.js +63 -4
- package/dist/deposit.mjs +5 -3
- package/dist/index.d.mts +77 -195
- package/dist/index.d.ts +77 -195
- package/dist/index.js +681 -172
- package/dist/index.mjs +90 -40
- package/dist/{use-sync-balances-D1Jdkck9.d.mts → use-deposit-addresses-B9ICS-3U.d.mts} +1 -11
- package/dist/{use-sync-balances-D1Jdkck9.d.ts → use-deposit-addresses-B9ICS-3U.d.ts} +1 -11
- package/dist/use-sync-balances-B1_8tBKw.d.mts +14 -0
- package/dist/use-sync-balances-B1_8tBKw.d.ts +14 -0
- package/dist/withdraw.d.mts +293 -0
- package/dist/withdraw.d.ts +293 -0
- package/dist/withdraw.js +1406 -0
- package/dist/withdraw.mjs +16 -0
- package/package.json +15 -2
package/README.md
CHANGED
|
@@ -393,7 +393,7 @@ Optional (only needed for wallet-based sign-in / deposits):
|
|
|
393
393
|
## Links
|
|
394
394
|
|
|
395
395
|
- Documentation — <https://docs.agg.market/>
|
|
396
|
-
- Demo app — <https://
|
|
396
|
+
- Demo app — <https://agg.market/>
|
|
397
397
|
- Vanilla SDK — [`@agg-build/sdk`](https://www.npmjs.com/package/@agg-build/sdk)
|
|
398
398
|
- Trading UI — [`@agg-build/ui`](https://www.npmjs.com/package/@agg-build/ui)
|
|
399
399
|
- Connect / sign-in UX — [`@agg-build/auth`](https://www.npmjs.com/package/@agg-build/auth)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__async,
|
|
3
|
+
useAggClient
|
|
4
|
+
} from "./chunk-V6VNA7MX.mjs";
|
|
5
|
+
|
|
6
|
+
// src/use-ramp-quotes.ts
|
|
7
|
+
import { useMutation } from "@tanstack/react-query";
|
|
8
|
+
function useRampQuotes() {
|
|
9
|
+
const client = useAggClient();
|
|
10
|
+
return useMutation({
|
|
11
|
+
mutationFn: (params) => __async(null, null, function* () {
|
|
12
|
+
return client.getRampQuotes(params);
|
|
13
|
+
})
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// src/use-ramp-session.ts
|
|
18
|
+
import { useMutation as useMutation2 } from "@tanstack/react-query";
|
|
19
|
+
function useRampSession() {
|
|
20
|
+
const client = useAggClient();
|
|
21
|
+
return useMutation2({
|
|
22
|
+
mutationFn: (params) => __async(null, null, function* () {
|
|
23
|
+
return client.createRampSession(params);
|
|
24
|
+
})
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export {
|
|
29
|
+
useRampQuotes,
|
|
30
|
+
useRampSession
|
|
31
|
+
};
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import {
|
|
2
|
+
__async,
|
|
3
|
+
invalidateBalanceQueries,
|
|
4
|
+
useAggBalanceState,
|
|
5
|
+
useAggClient,
|
|
6
|
+
useAggWebSocket,
|
|
7
|
+
useAggWebSocketConnectionState,
|
|
8
|
+
useDepositAddresses,
|
|
9
|
+
useManagedBalances,
|
|
10
|
+
useOnWithdrawalLifecycle,
|
|
11
|
+
useSyncBalances,
|
|
12
|
+
useWithdrawManaged
|
|
13
|
+
} from "./chunk-V6VNA7MX.mjs";
|
|
14
|
+
|
|
15
|
+
// src/withdraw/use-withdraw-flow.ts
|
|
16
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
17
|
+
var EVM_ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/;
|
|
18
|
+
var SOLANA_ADDRESS_REGEX = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
|
|
19
|
+
var SOLANA_CHAIN_ID = 792703809;
|
|
20
|
+
var WITHDRAWAL_SUPPORTED_CHAIN_IDS = /* @__PURE__ */ new Set([
|
|
21
|
+
1,
|
|
22
|
+
// Ethereum
|
|
23
|
+
137,
|
|
24
|
+
// Polygon
|
|
25
|
+
42161,
|
|
26
|
+
// Arbitrum
|
|
27
|
+
8453,
|
|
28
|
+
// Base
|
|
29
|
+
56,
|
|
30
|
+
// BNB
|
|
31
|
+
SOLANA_CHAIN_ID
|
|
32
|
+
]);
|
|
33
|
+
var isValidDestinationAddress = (address, chainId) => {
|
|
34
|
+
if (chainId === SOLANA_CHAIN_ID) return SOLANA_ADDRESS_REGEX.test(address);
|
|
35
|
+
return EVM_ADDRESS_REGEX.test(address);
|
|
36
|
+
};
|
|
37
|
+
var DEFAULT_WITHDRAW_SUMMARY = {
|
|
38
|
+
amountReceived: "",
|
|
39
|
+
network: "",
|
|
40
|
+
toWallet: "",
|
|
41
|
+
fees: "\u2014"
|
|
42
|
+
};
|
|
43
|
+
var formatRawTokenAmount = (rawAmount, decimals) => {
|
|
44
|
+
if (!rawAmount) return "0";
|
|
45
|
+
const raw = BigInt(rawAmount);
|
|
46
|
+
const divisor = BigInt(`1${"0".repeat(decimals)}`);
|
|
47
|
+
const whole = raw / divisor;
|
|
48
|
+
const remainder = raw % divisor;
|
|
49
|
+
if (remainder === BigInt(0)) return whole.toString();
|
|
50
|
+
return `${whole.toString()}.${remainder.toString().padStart(decimals, "0").replace(/0+$/, "")}`;
|
|
51
|
+
};
|
|
52
|
+
var formatRawTokenAmountForDisplay = (rawAmount, decimals, fractionDigits = 2) => {
|
|
53
|
+
const [wholePart, fractionalPart = ""] = formatRawTokenAmount(rawAmount, decimals).split(".");
|
|
54
|
+
const normalizedFraction = fractionalPart.padEnd(fractionDigits, "0").slice(0, fractionDigits);
|
|
55
|
+
return `${wholePart}.${normalizedFraction}`;
|
|
56
|
+
};
|
|
57
|
+
var parseTokenAmountToRaw = (amount, decimals) => {
|
|
58
|
+
const normalizedAmount = amount.trim();
|
|
59
|
+
if (!normalizedAmount || !/^\d*(?:\.\d*)?$/.test(normalizedAmount)) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
const [wholePart = "0", fractionalPart = ""] = normalizedAmount.split(".");
|
|
63
|
+
if (fractionalPart.length > decimals) return null;
|
|
64
|
+
const normalizedWhole = wholePart === "" ? "0" : wholePart;
|
|
65
|
+
const normalizedFraction = fractionalPart.padEnd(decimals, "0");
|
|
66
|
+
try {
|
|
67
|
+
return `${BigInt(normalizedWhole)}${normalizedFraction}`.replace(/^0+(?=\d)/, "");
|
|
68
|
+
} catch (e) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var shortenAddress = (address) => address.length > 12 ? `${address.slice(0, 6)}...${address.slice(-4)}` : address;
|
|
73
|
+
function useWithdrawFlow(options) {
|
|
74
|
+
var _a, _b;
|
|
75
|
+
const { open, onOpenChange } = options;
|
|
76
|
+
const { totalBalance } = useAggBalanceState();
|
|
77
|
+
const { balances } = useManagedBalances({ enabled: open });
|
|
78
|
+
const { supportedChains } = useDepositAddresses({ enabled: open });
|
|
79
|
+
const withdrawMutation = useWithdrawManaged();
|
|
80
|
+
const syncBalances = useSyncBalances();
|
|
81
|
+
const ws = useAggWebSocket();
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (!open) return;
|
|
84
|
+
syncBalances.mutate(void 0, {
|
|
85
|
+
onError: () => {
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}, [open]);
|
|
89
|
+
const [withdrawDestination, setWithdrawDestination] = useState("");
|
|
90
|
+
const [withdrawAmount, setWithdrawAmount] = useState("");
|
|
91
|
+
const [withdrawToken, setWithdrawToken] = useState("USDC");
|
|
92
|
+
const [withdrawNetwork, setWithdrawNetwork] = useState("");
|
|
93
|
+
const [withdrawSummary, setWithdrawSummary] = useState(DEFAULT_WITHDRAW_SUMMARY);
|
|
94
|
+
const [withdrawalId, setWithdrawalId] = useState(null);
|
|
95
|
+
const networkOptions = useMemo(
|
|
96
|
+
() => (supportedChains != null ? supportedChains : []).filter((chain) => WITHDRAWAL_SUPPORTED_CHAIN_IDS.has(chain.chainId)).map((chain) => ({
|
|
97
|
+
value: String(chain.chainId),
|
|
98
|
+
label: chain.name
|
|
99
|
+
})),
|
|
100
|
+
[supportedChains]
|
|
101
|
+
);
|
|
102
|
+
const resolvedWithdrawNetwork = withdrawNetwork || ((_a = networkOptions[0]) == null ? void 0 : _a.value) || "";
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
if (!networkOptions.length) return;
|
|
105
|
+
if (!withdrawNetwork || !networkOptions.some((option) => option.value === withdrawNetwork)) {
|
|
106
|
+
setWithdrawNetwork(networkOptions[0].value);
|
|
107
|
+
}
|
|
108
|
+
}, [networkOptions, withdrawNetwork]);
|
|
109
|
+
const tokenOptions = useMemo(() => {
|
|
110
|
+
var _a2, _b2, _c;
|
|
111
|
+
const selectedChainId = Number(resolvedWithdrawNetwork);
|
|
112
|
+
const supportedTokensForNetwork = (_b2 = (_a2 = supportedChains == null ? void 0 : supportedChains.find((chain) => chain.chainId === selectedChainId)) == null ? void 0 : _a2.tokens) != null ? _b2 : [];
|
|
113
|
+
const withdrawableSymbols = new Set(supportedTokensForNetwork.map((token) => token.symbol));
|
|
114
|
+
return ((_c = balances == null ? void 0 : balances.cash) != null ? _c : []).filter((cashEntry) => withdrawableSymbols.has(cashEntry.tokenSymbol)).map((cashEntry) => ({
|
|
115
|
+
value: cashEntry.tokenSymbol,
|
|
116
|
+
label: cashEntry.tokenSymbol
|
|
117
|
+
}));
|
|
118
|
+
}, [balances, resolvedWithdrawNetwork, supportedChains]);
|
|
119
|
+
const resolvedWithdrawToken = tokenOptions.some((option) => option.value === withdrawToken) ? withdrawToken : ((_b = tokenOptions[0]) == null ? void 0 : _b.value) || "";
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
if (!tokenOptions.length) return;
|
|
122
|
+
if (!tokenOptions.some((option) => option.value === withdrawToken)) {
|
|
123
|
+
setWithdrawToken(tokenOptions[0].value);
|
|
124
|
+
}
|
|
125
|
+
}, [tokenOptions, withdrawToken]);
|
|
126
|
+
const selectedCashEntry = useMemo(
|
|
127
|
+
() => balances == null ? void 0 : balances.cash.find((cashEntry) => cashEntry.tokenSymbol === resolvedWithdrawToken),
|
|
128
|
+
[balances, resolvedWithdrawToken]
|
|
129
|
+
);
|
|
130
|
+
const selectedTokenDecimals = useMemo(() => {
|
|
131
|
+
var _a2, _b2, _c, _d;
|
|
132
|
+
const selectedChainId = Number(resolvedWithdrawNetwork);
|
|
133
|
+
return (_d = (_c = (_b2 = (_a2 = supportedChains == null ? void 0 : supportedChains.find((chain) => chain.chainId === selectedChainId)) == null ? void 0 : _a2.tokens.find((token) => token.symbol === resolvedWithdrawToken)) == null ? void 0 : _b2.decimals) != null ? _c : selectedCashEntry == null ? void 0 : selectedCashEntry.decimals) != null ? _d : 6;
|
|
134
|
+
}, [
|
|
135
|
+
resolvedWithdrawNetwork,
|
|
136
|
+
resolvedWithdrawToken,
|
|
137
|
+
selectedCashEntry == null ? void 0 : selectedCashEntry.decimals,
|
|
138
|
+
supportedChains
|
|
139
|
+
]);
|
|
140
|
+
const exactBalance = useMemo(() => {
|
|
141
|
+
if (!selectedCashEntry) return "0";
|
|
142
|
+
return formatRawTokenAmount(selectedCashEntry.totalRaw, selectedCashEntry.decimals);
|
|
143
|
+
}, [selectedCashEntry]);
|
|
144
|
+
const balanceDisplay = useMemo(() => {
|
|
145
|
+
if (!selectedCashEntry) return `0.00 ${resolvedWithdrawToken || withdrawToken}`;
|
|
146
|
+
return `${formatRawTokenAmountForDisplay(
|
|
147
|
+
selectedCashEntry.totalRaw,
|
|
148
|
+
selectedCashEntry.decimals
|
|
149
|
+
)} ${resolvedWithdrawToken}`;
|
|
150
|
+
}, [resolvedWithdrawToken, selectedCashEntry, withdrawToken]);
|
|
151
|
+
const resetFlowState = useCallback(() => {
|
|
152
|
+
setWithdrawDestination("");
|
|
153
|
+
setWithdrawAmount("");
|
|
154
|
+
setWithdrawToken("USDC");
|
|
155
|
+
setWithdrawNetwork("");
|
|
156
|
+
setWithdrawSummary(DEFAULT_WITHDRAW_SUMMARY);
|
|
157
|
+
setWithdrawalId(null);
|
|
158
|
+
}, []);
|
|
159
|
+
const handleWithdrawOpenChange = useCallback(
|
|
160
|
+
(isOpen) => {
|
|
161
|
+
if (!isOpen) resetFlowState();
|
|
162
|
+
onOpenChange(isOpen);
|
|
163
|
+
},
|
|
164
|
+
[onOpenChange, resetFlowState]
|
|
165
|
+
);
|
|
166
|
+
useEffect(() => {
|
|
167
|
+
if (!open) resetFlowState();
|
|
168
|
+
}, [open, resetFlowState]);
|
|
169
|
+
const handleWithdrawProvider = useCallback(() => __async(null, null, function* () {
|
|
170
|
+
var _a2, _b2;
|
|
171
|
+
const destinationChainId = Number(resolvedWithdrawNetwork);
|
|
172
|
+
const trimmedDestination = withdrawDestination.trim();
|
|
173
|
+
const amountRaw = parseTokenAmountToRaw(withdrawAmount, selectedTokenDecimals);
|
|
174
|
+
if (!amountRaw || BigInt(amountRaw) <= BigInt(0)) {
|
|
175
|
+
throw new Error("Enter a withdrawal amount greater than zero.");
|
|
176
|
+
}
|
|
177
|
+
if (!Number.isFinite(destinationChainId) || destinationChainId <= 0) {
|
|
178
|
+
throw new Error("Select a destination network.");
|
|
179
|
+
}
|
|
180
|
+
if (!isValidDestinationAddress(trimmedDestination, destinationChainId)) {
|
|
181
|
+
const expected = destinationChainId === SOLANA_CHAIN_ID ? "a Solana wallet address (base58, 32\u201344 chars)" : "an EVM destination address (0x\u2026 40 hex chars)";
|
|
182
|
+
throw new Error(`Enter ${expected}.`);
|
|
183
|
+
}
|
|
184
|
+
if (selectedCashEntry) {
|
|
185
|
+
const scaleBy = (n, exp) => {
|
|
186
|
+
if (exp <= 0) return n;
|
|
187
|
+
return n * BigInt(`1${"0".repeat(exp)}`);
|
|
188
|
+
};
|
|
189
|
+
const balanceInDestFrame = (() => {
|
|
190
|
+
const native = BigInt(selectedCashEntry.totalRaw);
|
|
191
|
+
if (selectedCashEntry.decimals === selectedTokenDecimals) return native;
|
|
192
|
+
if (selectedCashEntry.decimals > selectedTokenDecimals) {
|
|
193
|
+
return native / scaleBy(BigInt(1), selectedCashEntry.decimals - selectedTokenDecimals);
|
|
194
|
+
}
|
|
195
|
+
return scaleBy(native, selectedTokenDecimals - selectedCashEntry.decimals);
|
|
196
|
+
})();
|
|
197
|
+
if (BigInt(amountRaw) > balanceInDestFrame) {
|
|
198
|
+
throw new Error("Withdrawal amount exceeds your available balance.");
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
ws == null ? void 0 : ws.connect();
|
|
202
|
+
yield new Promise((resolve, reject) => {
|
|
203
|
+
withdrawMutation.mutate(
|
|
204
|
+
{
|
|
205
|
+
amountRaw,
|
|
206
|
+
tokenSymbol: resolvedWithdrawToken,
|
|
207
|
+
destinationAddress: trimmedDestination,
|
|
208
|
+
destinationChainId
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
onSuccess: (data) => {
|
|
212
|
+
setWithdrawalId(data.withdrawalId);
|
|
213
|
+
resolve();
|
|
214
|
+
},
|
|
215
|
+
onError: reject
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
});
|
|
219
|
+
setWithdrawSummary({
|
|
220
|
+
amountReceived: `${formatRawTokenAmountForDisplay(amountRaw, selectedTokenDecimals)} ${resolvedWithdrawToken}`,
|
|
221
|
+
network: (_b2 = (_a2 = supportedChains == null ? void 0 : supportedChains.find((chain) => chain.chainId === destinationChainId)) == null ? void 0 : _a2.name) != null ? _b2 : resolvedWithdrawNetwork,
|
|
222
|
+
toWallet: shortenAddress(trimmedDestination),
|
|
223
|
+
fees: "\u2014"
|
|
224
|
+
});
|
|
225
|
+
}), [
|
|
226
|
+
resolvedWithdrawNetwork,
|
|
227
|
+
resolvedWithdrawToken,
|
|
228
|
+
selectedCashEntry,
|
|
229
|
+
selectedTokenDecimals,
|
|
230
|
+
supportedChains,
|
|
231
|
+
withdrawAmount,
|
|
232
|
+
withdrawDestination,
|
|
233
|
+
withdrawMutation,
|
|
234
|
+
ws
|
|
235
|
+
]);
|
|
236
|
+
return {
|
|
237
|
+
open,
|
|
238
|
+
onOpenChange: handleWithdrawOpenChange,
|
|
239
|
+
withdrawFlow: {
|
|
240
|
+
balance: totalBalance,
|
|
241
|
+
balanceDisplay,
|
|
242
|
+
amount: withdrawAmount,
|
|
243
|
+
destinationWallet: withdrawDestination,
|
|
244
|
+
tokenOptions,
|
|
245
|
+
networkOptions,
|
|
246
|
+
selectedToken: resolvedWithdrawToken,
|
|
247
|
+
selectedNetwork: resolvedWithdrawNetwork,
|
|
248
|
+
purchaseSummary: withdrawSummary,
|
|
249
|
+
withdrawalId
|
|
250
|
+
},
|
|
251
|
+
onWithdrawDestinationChange: setWithdrawDestination,
|
|
252
|
+
onWithdrawAmountChange: setWithdrawAmount,
|
|
253
|
+
onWithdrawTokenChange: setWithdrawToken,
|
|
254
|
+
onWithdrawNetworkChange: setWithdrawNetwork,
|
|
255
|
+
onMaxClick: useCallback(() => {
|
|
256
|
+
setWithdrawAmount(exactBalance === "0" ? "0" : exactBalance);
|
|
257
|
+
}, [exactBalance]),
|
|
258
|
+
onSelectWithdrawProvider: useCallback(
|
|
259
|
+
(_providerId) => __async(null, null, function* () {
|
|
260
|
+
return handleWithdrawProvider();
|
|
261
|
+
}),
|
|
262
|
+
[handleWithdrawProvider]
|
|
263
|
+
),
|
|
264
|
+
onDoneWithdraw: useCallback(() => handleWithdrawOpenChange(false), [handleWithdrawOpenChange])
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// src/withdraw/use-withdrawal-lifecycle.ts
|
|
269
|
+
import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useRef, useState as useState2 } from "react";
|
|
270
|
+
import { useQueryClient } from "@tanstack/react-query";
|
|
271
|
+
var INITIAL_STATE = {
|
|
272
|
+
pending: true,
|
|
273
|
+
status: null,
|
|
274
|
+
terminal: false,
|
|
275
|
+
lastLeg: null,
|
|
276
|
+
legs: [],
|
|
277
|
+
errorMessage: null,
|
|
278
|
+
timestamp: null
|
|
279
|
+
};
|
|
280
|
+
var restLegToWsLeg = (leg) => ({
|
|
281
|
+
sourceChainId: leg.sourceChainId,
|
|
282
|
+
destChainId: leg.destChainId,
|
|
283
|
+
type: leg.type,
|
|
284
|
+
// The wire-level WS leg status enum and the REST leg status enum are the
|
|
285
|
+
// same union (planned/submitted/confirmed/failed). Keep the cast narrow to
|
|
286
|
+
// avoid pulling the SDK enum apart for a one-line bridge.
|
|
287
|
+
status: leg.status,
|
|
288
|
+
amountRaw: leg.amountRaw,
|
|
289
|
+
txHash: leg.txHash,
|
|
290
|
+
bridgeOperationId: leg.bridgeOperationId
|
|
291
|
+
});
|
|
292
|
+
var mergeLegs = (prev, snapshot, delta) => {
|
|
293
|
+
if (snapshot) return snapshot;
|
|
294
|
+
if (!delta) return prev;
|
|
295
|
+
const idx = prev.findIndex(
|
|
296
|
+
(l) => l.sourceChainId === delta.sourceChainId && l.destChainId === delta.destChainId && l.type === delta.type
|
|
297
|
+
);
|
|
298
|
+
if (idx === -1) return [...prev, delta];
|
|
299
|
+
const next = prev.slice();
|
|
300
|
+
next[idx] = delta;
|
|
301
|
+
return next;
|
|
302
|
+
};
|
|
303
|
+
var restToLifecycleState = (response) => {
|
|
304
|
+
var _a;
|
|
305
|
+
return {
|
|
306
|
+
pending: false,
|
|
307
|
+
status: response.status,
|
|
308
|
+
terminal: response.status === "completed" || response.status === "partial" || response.status === "failed",
|
|
309
|
+
lastLeg: null,
|
|
310
|
+
legs: response.legs.map(restLegToWsLeg),
|
|
311
|
+
errorMessage: (_a = response.errorMessage) != null ? _a : null,
|
|
312
|
+
// No server timestamp on the REST response — we use 0 as "older than any
|
|
313
|
+
// WS timestamp" so a subsequent WS event always wins. Callers that read
|
|
314
|
+
// `timestamp` should treat 0/null interchangeably as "unset".
|
|
315
|
+
timestamp: 0
|
|
316
|
+
};
|
|
317
|
+
};
|
|
318
|
+
function useWithdrawalLifecycle(withdrawalId) {
|
|
319
|
+
const client = useAggClient();
|
|
320
|
+
const wsConnected = useAggWebSocketConnectionState();
|
|
321
|
+
const queryClient = useQueryClient();
|
|
322
|
+
const [state, setState] = useState2(INITIAL_STATE);
|
|
323
|
+
const stateRef = useRef(state);
|
|
324
|
+
stateRef.current = state;
|
|
325
|
+
const balanceRefetchedForRef = useRef(null);
|
|
326
|
+
useEffect2(() => {
|
|
327
|
+
setState(INITIAL_STATE);
|
|
328
|
+
}, [withdrawalId]);
|
|
329
|
+
useEffect2(() => {
|
|
330
|
+
if (!withdrawalId) return;
|
|
331
|
+
let cancelled = false;
|
|
332
|
+
(() => __async(null, null, function* () {
|
|
333
|
+
try {
|
|
334
|
+
const response = yield client.getWithdrawalStatus(withdrawalId);
|
|
335
|
+
if (cancelled) return;
|
|
336
|
+
if (response.withdrawalId !== withdrawalId) return;
|
|
337
|
+
const current = stateRef.current;
|
|
338
|
+
const wsAlreadyWon = current.timestamp != null && current.timestamp > 0;
|
|
339
|
+
if (wsAlreadyWon) return;
|
|
340
|
+
setState(restToLifecycleState(response));
|
|
341
|
+
} catch (e) {
|
|
342
|
+
}
|
|
343
|
+
}))();
|
|
344
|
+
return () => {
|
|
345
|
+
cancelled = true;
|
|
346
|
+
};
|
|
347
|
+
}, [client, withdrawalId, wsConnected]);
|
|
348
|
+
const handler = useMemo2(() => {
|
|
349
|
+
if (!withdrawalId) return null;
|
|
350
|
+
return (msg) => {
|
|
351
|
+
if (msg.withdrawalId !== withdrawalId) return;
|
|
352
|
+
setState((prev) => {
|
|
353
|
+
var _a, _b;
|
|
354
|
+
return {
|
|
355
|
+
pending: false,
|
|
356
|
+
status: msg.status,
|
|
357
|
+
terminal: msg.terminal,
|
|
358
|
+
lastLeg: (_a = msg.leg) != null ? _a : null,
|
|
359
|
+
// `legs[]` is the cumulative server-known truth. Snapshots
|
|
360
|
+
// (`pending` / terminal rollup) carry a full `legs[]` and replace
|
|
361
|
+
// it. Intermediate per-leg deltas carry only `leg` (no `legs[]`)
|
|
362
|
+
// — merge the delta into the existing array by
|
|
363
|
+
// (sourceChainId, destChainId, type) so the timeline UI doesn't
|
|
364
|
+
// collapse to empty between snapshots.
|
|
365
|
+
legs: mergeLegs(prev.legs, msg.legs, msg.leg),
|
|
366
|
+
errorMessage: (_b = msg.errorMessage) != null ? _b : null,
|
|
367
|
+
timestamp: msg.timestamp
|
|
368
|
+
};
|
|
369
|
+
});
|
|
370
|
+
};
|
|
371
|
+
}, [withdrawalId]);
|
|
372
|
+
useOnWithdrawalLifecycle(handler);
|
|
373
|
+
useEffect2(() => {
|
|
374
|
+
if (!withdrawalId) return;
|
|
375
|
+
if (!state.terminal) return;
|
|
376
|
+
if (balanceRefetchedForRef.current === withdrawalId) return;
|
|
377
|
+
balanceRefetchedForRef.current = withdrawalId;
|
|
378
|
+
invalidateBalanceQueries(queryClient);
|
|
379
|
+
client.syncManagedBalances().catch(() => {
|
|
380
|
+
});
|
|
381
|
+
}, [client, queryClient, state.terminal, withdrawalId]);
|
|
382
|
+
const reset = useCallback2(() => setState(INITIAL_STATE), []);
|
|
383
|
+
return { state, reset };
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
export {
|
|
387
|
+
useWithdrawFlow,
|
|
388
|
+
useWithdrawalLifecycle
|
|
389
|
+
};
|