@oasisprotocol/privana-sdk 0.5.0 → 0.5.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/dist/{chunk-ACLJPC75.cjs → chunk-UHXVYWTF.cjs} +936 -20
- package/dist/chunk-UHXVYWTF.cjs.map +1 -0
- package/dist/{chunk-54FC6TO3.js → chunk-ZVUMV4NR.js} +907 -23
- package/dist/chunk-ZVUMV4NR.js.map +1 -0
- package/dist/index.cjs +823 -538
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +58 -341
- package/dist/index.d.ts +58 -341
- package/dist/index.js +532 -334
- package/dist/index.js.map +1 -1
- package/dist/on-ramp.cjs +3 -3
- package/dist/on-ramp.d.cts +40 -4
- package/dist/on-ramp.d.ts +40 -4
- package/dist/on-ramp.js +1 -1
- package/dist/pending-lock-BdkuMjmY.d.cts +600 -0
- package/dist/pending-lock-BdkuMjmY.d.ts +600 -0
- package/package.json +1 -1
- package/dist/chunk-54FC6TO3.js.map +0 -1
- package/dist/chunk-ACLJPC75.cjs.map +0 -1
- package/dist/on-ramp-XLXsy0aI.d.cts +0 -130
- package/dist/on-ramp-XLXsy0aI.d.ts +0 -130
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { usePrivanaContext, createHostedAuthPendingStorageKey, clearHostedAuthPendingTransaction, HostedAuthRequiredError, HostedAuthError, createPkceVerifier, createPkceChallenge, createHostedAuthState, persistHostedAuthPendingTransaction, parseHostedAuthCallback, readHostedAuthPendingTransaction, HostedAuthStateMismatchError, buildHostedAuthSession, useSafePrivanaContext, usePrivateReadRequest, formatTokenAmount, useDepositVerification, getTransactionReceipt, waitForTransactionReceipt, cn, Button, stripHostedAuthCallbackParams, AccountingApiError,
|
|
3
|
-
export { AccountingApiError, Button, HOSTED_AUTH_CLOCK_SKEW_MS, HostedAuthError, HostedAuthRequiredError, HostedAuthStateMismatchError, HttpClient, NETWORK_CONFIG, NetworkError, PrivanaClient, PrivanaProvider, SUPPORTED_CHAINS, SiweAuthProvider, Skeleton, ValidationError, applyRefreshResponse, buildHostedAuthSession, buildSiweStatement, buttonVariants, clearHostedAuthPendingTransaction, createHostedAuthPendingStorageKey, createHostedAuthState, createHostedAuthStorageKey, createPkceChallenge, createPkceVerifier, getAccountingContract, getApiUrl, getChainById, getChainId, getExplorerAddressUrl, getExplorerLabel, isHostedAuthRefreshActive, isHostedAuthSessionActive, normalizeAddress, normalizeHex, parseHostedAuthCallback, persistHostedAuthPendingTransaction, readHostedAuthPendingTransaction, readStoredHostedAuthSession, stripHostedAuthCallbackParams, syncHostedAuthSessionToClient, useDepositVerification, usePrivanaContext, useSafeAccount, useSafePrivanaContext, useSiweAuth } from './chunk-
|
|
2
|
+
import { usePrivanaContext, createHostedAuthPendingStorageKey, clearHostedAuthPendingTransaction, HostedAuthRequiredError, HostedAuthError, createPkceVerifier, createPkceChallenge, createHostedAuthState, persistHostedAuthPendingTransaction, parseHostedAuthCallback, readHostedAuthPendingTransaction, HostedAuthStateMismatchError, buildHostedAuthSession, useSafePrivanaContext, usePrivateReadRequest, formatTokenAmount, submitPendingLock, PostDepositLockError, useDepositVerification, useEnsureCorrectChain, getTransactionReceipt, getBlockNumber, waitForTransactionReceipt, canUseBrowserStorage, clampLockAmount, getWalletClient, createSignedLockRequest, signWithdrawMessage, signLockMessage, signTransferMessage, signTransferLockedMessage, signModifyLockMessage, cn, Button, stripHostedAuthCallbackParams, AccountingApiError, getBrowserStorageItem, removeBrowserStorageItem, isSignedLockUsable, setBrowserStorageItem, shortenAddress, formatTimeRemaining, parseTokenAmount, getExplorerAddressUrl, getExplorerLabel, Skeleton, formatCountdown, FiatOnRampForm } from './chunk-ZVUMV4NR.js';
|
|
3
|
+
export { AccountingApiError, Button, DEFAULT_LOCK_DURATION_SECONDS, DEFAULT_ONRAMP_LOCK_BUFFER, HOSTED_AUTH_CLOCK_SKEW_MS, HostedAuthError, HostedAuthRequiredError, HostedAuthStateMismatchError, HttpClient, LOCK_TYPES, MODIFY_LOCK_TYPES, NETWORK_CONFIG, NetworkError, PostDepositLockError, PrivanaClient, PrivanaProvider, SUPPORTED_CHAINS, SiweAuthProvider, Skeleton, TRANSFER_LOCKED_TYPES, TRANSFER_TYPES, ValidationError, WITHDRAW_FROM_LOCK_TYPES, WITHDRAW_TYPES, applyLockBuffer, applyRefreshResponse, buildHostedAuthSession, buildSiweStatement, buttonVariants, clampLockAmount, clearHostedAuthPendingTransaction, clearPendingLock, createDomain, createHostedAuthPendingStorageKey, createHostedAuthState, createHostedAuthStorageKey, createLockExpiry, createPkceChallenge, createPkceVerifier, createSignedLockRequest, getAccountingContract, getApiUrl, getChainById, getChainId, getExplorerAddressUrl, getExplorerLabel, isHostedAuthRefreshActive, isHostedAuthSessionActive, isSignedLockUsable, loadPendingLock, normalizeAddress, normalizeHex, parseHostedAuthCallback, persistHostedAuthPendingTransaction, readHostedAuthPendingTransaction, readStoredHostedAuthSession, savePendingLock, signLockMessage, signModifyLockMessage, signTransferLockedMessage, signTransferMessage, signWithdrawFromLockMessage, signWithdrawMessage, stripHostedAuthCallbackParams, submitPendingLock, syncHostedAuthSessionToClient, useDepositVerification, usePrivanaContext, useSafeAccount, useSafePrivanaContext, useSiweAuth } from './chunk-ZVUMV4NR.js';
|
|
4
4
|
import { useState, useRef, useMemo, useCallback, useContext, useEffect, useId } from 'react';
|
|
5
5
|
import { QueryClientContext, useQuery, useQueryClient, useMutation, keepPreviousData } from '@tanstack/react-query';
|
|
6
|
-
import { useAccount, useWalletClient, useConfig, useWriteContract, useSendTransaction,
|
|
6
|
+
import { useAccount, useWalletClient, useConfig, useWriteContract, useSendTransaction, useBalance as useBalance$1, useReadContract } from 'wagmi';
|
|
7
7
|
import { zeroAddress, erc20Abi } from 'viem';
|
|
8
8
|
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
9
9
|
import { XIcon } from 'lucide-react';
|
|
@@ -12,202 +12,6 @@ import { toast } from 'sonner';
|
|
|
12
12
|
import { QRCodeSVG } from 'qrcode.react';
|
|
13
13
|
import { MoonPayProvider, MoonPayContext } from '@moonpay/moonpay-react';
|
|
14
14
|
|
|
15
|
-
// src/sdk/signatures/eip712-types.ts
|
|
16
|
-
function createDomain(chainId, verifyingContract) {
|
|
17
|
-
return {
|
|
18
|
-
name: "AccountingModule",
|
|
19
|
-
version: "1",
|
|
20
|
-
chainId,
|
|
21
|
-
verifyingContract
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
var LOCK_TYPES = {
|
|
25
|
-
Lock: [
|
|
26
|
-
{ name: "serviceAddress", type: "address" },
|
|
27
|
-
{ name: "tokenId", type: "bytes32" },
|
|
28
|
-
{ name: "amount", type: "uint256" },
|
|
29
|
-
{ name: "expiry", type: "uint256" },
|
|
30
|
-
{ name: "nonce", type: "uint256" }
|
|
31
|
-
]
|
|
32
|
-
};
|
|
33
|
-
var TRANSFER_TYPES = {
|
|
34
|
-
Transfer: [
|
|
35
|
-
{ name: "toAddress", type: "address" },
|
|
36
|
-
{ name: "tokenId", type: "bytes32" },
|
|
37
|
-
{ name: "amount", type: "uint256" },
|
|
38
|
-
{ name: "nonce", type: "uint256" }
|
|
39
|
-
]
|
|
40
|
-
};
|
|
41
|
-
var TRANSFER_LOCKED_TYPES = {
|
|
42
|
-
TransferLocked: [
|
|
43
|
-
{ name: "userAddress", type: "address" },
|
|
44
|
-
{ name: "toAddress", type: "address" },
|
|
45
|
-
{ name: "lockId", type: "uint256" },
|
|
46
|
-
{ name: "amount", type: "uint256" },
|
|
47
|
-
{ name: "nonce", type: "uint256" },
|
|
48
|
-
{ name: "serviceAddress", type: "address" }
|
|
49
|
-
]
|
|
50
|
-
};
|
|
51
|
-
var WITHDRAW_TYPES = {
|
|
52
|
-
Withdraw: [
|
|
53
|
-
{ name: "tokenId", type: "bytes32" },
|
|
54
|
-
{ name: "amount", type: "uint256" },
|
|
55
|
-
{ name: "nonce", type: "uint256" }
|
|
56
|
-
]
|
|
57
|
-
};
|
|
58
|
-
var MODIFY_LOCK_TYPES = {
|
|
59
|
-
ModifyLock: [
|
|
60
|
-
{ name: "lockId", type: "uint256" },
|
|
61
|
-
{ name: "amount", type: "uint256" },
|
|
62
|
-
{ name: "newExpiry", type: "uint256" },
|
|
63
|
-
{ name: "nonce", type: "uint256" }
|
|
64
|
-
]
|
|
65
|
-
};
|
|
66
|
-
var WITHDRAW_FROM_LOCK_TYPES = {
|
|
67
|
-
WithdrawFromLock: [
|
|
68
|
-
{ name: "userAddress", type: "address" },
|
|
69
|
-
{ name: "toAddress", type: "address" },
|
|
70
|
-
{ name: "lockId", type: "uint256" },
|
|
71
|
-
{ name: "amount", type: "uint256" },
|
|
72
|
-
{ name: "nonce", type: "uint256" }
|
|
73
|
-
]
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
// src/sdk/signatures/sign-lock.ts
|
|
77
|
-
async function signLockMessage({
|
|
78
|
-
walletClient,
|
|
79
|
-
chainId,
|
|
80
|
-
verifyingContract,
|
|
81
|
-
message
|
|
82
|
-
}) {
|
|
83
|
-
const account = walletClient.account;
|
|
84
|
-
if (!account) {
|
|
85
|
-
throw new Error("No account connected to wallet client");
|
|
86
|
-
}
|
|
87
|
-
const domain = createDomain(chainId, verifyingContract);
|
|
88
|
-
const signature = await walletClient.signTypedData({
|
|
89
|
-
account,
|
|
90
|
-
domain,
|
|
91
|
-
types: LOCK_TYPES,
|
|
92
|
-
primaryType: "Lock",
|
|
93
|
-
message
|
|
94
|
-
});
|
|
95
|
-
return signature;
|
|
96
|
-
}
|
|
97
|
-
function createLockExpiry(minutesFromNow = 60) {
|
|
98
|
-
return BigInt(Math.floor(Date.now() / 1e3) + minutesFromNow * 60);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// src/sdk/signatures/sign-modify-lock.ts
|
|
102
|
-
async function signModifyLockMessage({
|
|
103
|
-
walletClient,
|
|
104
|
-
chainId,
|
|
105
|
-
verifyingContract,
|
|
106
|
-
message
|
|
107
|
-
}) {
|
|
108
|
-
const account = walletClient.account;
|
|
109
|
-
if (!account) {
|
|
110
|
-
throw new Error("No account connected to wallet client");
|
|
111
|
-
}
|
|
112
|
-
const domain = createDomain(chainId, verifyingContract);
|
|
113
|
-
const signature = await walletClient.signTypedData({
|
|
114
|
-
account,
|
|
115
|
-
domain,
|
|
116
|
-
types: MODIFY_LOCK_TYPES,
|
|
117
|
-
primaryType: "ModifyLock",
|
|
118
|
-
message
|
|
119
|
-
});
|
|
120
|
-
return signature;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// src/sdk/signatures/sign-transfer.ts
|
|
124
|
-
async function signTransferMessage({
|
|
125
|
-
walletClient,
|
|
126
|
-
chainId,
|
|
127
|
-
verifyingContract,
|
|
128
|
-
message
|
|
129
|
-
}) {
|
|
130
|
-
const account = walletClient.account;
|
|
131
|
-
if (!account) {
|
|
132
|
-
throw new Error("No account connected to wallet client");
|
|
133
|
-
}
|
|
134
|
-
const domain = createDomain(chainId, verifyingContract);
|
|
135
|
-
const signature = await walletClient.signTypedData({
|
|
136
|
-
account,
|
|
137
|
-
domain,
|
|
138
|
-
types: TRANSFER_TYPES,
|
|
139
|
-
primaryType: "Transfer",
|
|
140
|
-
message
|
|
141
|
-
});
|
|
142
|
-
return signature;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// src/sdk/signatures/sign-transfer-locked.ts
|
|
146
|
-
async function signTransferLockedMessage({
|
|
147
|
-
walletClient,
|
|
148
|
-
chainId,
|
|
149
|
-
verifyingContract,
|
|
150
|
-
message
|
|
151
|
-
}) {
|
|
152
|
-
const account = walletClient.account;
|
|
153
|
-
if (!account) {
|
|
154
|
-
throw new Error("No account connected to wallet client");
|
|
155
|
-
}
|
|
156
|
-
const domain = createDomain(chainId, verifyingContract);
|
|
157
|
-
const signature = await walletClient.signTypedData({
|
|
158
|
-
account,
|
|
159
|
-
domain,
|
|
160
|
-
types: TRANSFER_LOCKED_TYPES,
|
|
161
|
-
primaryType: "TransferLocked",
|
|
162
|
-
message
|
|
163
|
-
});
|
|
164
|
-
return signature;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// src/sdk/signatures/sign-withdraw.ts
|
|
168
|
-
async function signWithdrawMessage({
|
|
169
|
-
walletClient,
|
|
170
|
-
chainId,
|
|
171
|
-
verifyingContract,
|
|
172
|
-
message
|
|
173
|
-
}) {
|
|
174
|
-
const account = walletClient.account;
|
|
175
|
-
if (!account) {
|
|
176
|
-
throw new Error("No account connected to wallet client");
|
|
177
|
-
}
|
|
178
|
-
const domain = createDomain(chainId, verifyingContract);
|
|
179
|
-
const signature = await walletClient.signTypedData({
|
|
180
|
-
account,
|
|
181
|
-
domain,
|
|
182
|
-
types: WITHDRAW_TYPES,
|
|
183
|
-
primaryType: "Withdraw",
|
|
184
|
-
message
|
|
185
|
-
});
|
|
186
|
-
return signature;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// src/sdk/signatures/sign-withdraw-from-lock.ts
|
|
190
|
-
async function signWithdrawFromLockMessage({
|
|
191
|
-
walletClient,
|
|
192
|
-
chainId,
|
|
193
|
-
verifyingContract,
|
|
194
|
-
message
|
|
195
|
-
}) {
|
|
196
|
-
const account = walletClient.account;
|
|
197
|
-
if (!account) {
|
|
198
|
-
throw new Error("No account connected to wallet client");
|
|
199
|
-
}
|
|
200
|
-
const domain = createDomain(chainId, verifyingContract);
|
|
201
|
-
const signature = await walletClient.signTypedData({
|
|
202
|
-
account,
|
|
203
|
-
domain,
|
|
204
|
-
types: WITHDRAW_FROM_LOCK_TYPES,
|
|
205
|
-
primaryType: "WithdrawFromLock",
|
|
206
|
-
message
|
|
207
|
-
});
|
|
208
|
-
return signature;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
15
|
// src/sdk/hooks/use-privana-client.ts
|
|
212
16
|
function usePrivanaClient() {
|
|
213
17
|
const { client } = usePrivanaContext();
|
|
@@ -468,75 +272,22 @@ function useBatchBalances(options) {
|
|
|
468
272
|
refetch: query.refetch
|
|
469
273
|
};
|
|
470
274
|
}
|
|
471
|
-
function useEnsureCorrectChain() {
|
|
472
|
-
const config = useConfig();
|
|
473
|
-
const chainId = useChainId();
|
|
474
|
-
const { switchChainAsync } = useSwitchChain();
|
|
475
|
-
const waitUntilOnChain = useCallback(
|
|
476
|
-
async (expectedChainId, timeoutMs, pollIntervalMs = 250) => {
|
|
477
|
-
const startedAt = Date.now();
|
|
478
|
-
while (Date.now() - startedAt < timeoutMs) {
|
|
479
|
-
const currentChainId = getChainId2(config);
|
|
480
|
-
if (currentChainId === expectedChainId) return true;
|
|
481
|
-
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
482
|
-
}
|
|
483
|
-
return false;
|
|
484
|
-
},
|
|
485
|
-
[config]
|
|
486
|
-
);
|
|
487
|
-
const ensureCorrectChain = useCallback(
|
|
488
|
-
async (targetChainId) => {
|
|
489
|
-
const currentChainId = getChainId2(config);
|
|
490
|
-
if (currentChainId === targetChainId) return false;
|
|
491
|
-
let switchErrorMessage;
|
|
492
|
-
try {
|
|
493
|
-
const timeoutPromise = new Promise((_, reject) => {
|
|
494
|
-
setTimeout(() => reject(new Error("Chain switch timeout")), 3e3);
|
|
495
|
-
});
|
|
496
|
-
await Promise.race([switchChainAsync({ chainId: targetChainId }), timeoutPromise]);
|
|
497
|
-
} catch (error) {
|
|
498
|
-
if (error instanceof Error && error.message.includes("Unsupported Chain")) {
|
|
499
|
-
console.warn("Got 'Unsupported Chain' error, chain may have switched anyway.");
|
|
500
|
-
} else {
|
|
501
|
-
switchErrorMessage = error instanceof Error ? error.message : "Unknown chain switch error";
|
|
502
|
-
}
|
|
503
|
-
}
|
|
504
|
-
const settled = await waitUntilOnChain(targetChainId, 2e4);
|
|
505
|
-
if (settled) return true;
|
|
506
|
-
if (switchErrorMessage) {
|
|
507
|
-
throw new Error(
|
|
508
|
-
`Failed to switch to chain (Chain ID: ${targetChainId}): ${switchErrorMessage}`
|
|
509
|
-
);
|
|
510
|
-
}
|
|
511
|
-
throw new Error(`Chain switch did not settle in time (expected ${targetChainId}).`);
|
|
512
|
-
},
|
|
513
|
-
[config, switchChainAsync, waitUntilOnChain]
|
|
514
|
-
);
|
|
515
|
-
const isOnChain = useCallback((targetChainId) => chainId === targetChainId, [chainId]);
|
|
516
|
-
return {
|
|
517
|
-
chainId,
|
|
518
|
-
ensureCorrectChain,
|
|
519
|
-
isOnChain
|
|
520
|
-
};
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
// src/sdk/hooks/use-deposit.ts
|
|
524
275
|
var STALE_MS = 30 * 60 * 1e3;
|
|
525
276
|
function storageKey(address) {
|
|
526
277
|
return `privana:pending-deposit:${address.toLowerCase()}`;
|
|
527
278
|
}
|
|
528
279
|
function savePendingDeposit(address, data) {
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
280
|
+
const stored = setBrowserStorageItem(storageKey(address), JSON.stringify(data));
|
|
281
|
+
if (!stored && data.signedLock) {
|
|
282
|
+
throw new Error("Unable to persist pending locked deposit for recovery");
|
|
532
283
|
}
|
|
533
284
|
}
|
|
534
285
|
function loadPendingDeposit(address) {
|
|
535
286
|
try {
|
|
536
|
-
const raw =
|
|
287
|
+
const raw = getBrowserStorageItem(storageKey(address));
|
|
537
288
|
if (!raw) return null;
|
|
538
289
|
const data = JSON.parse(raw);
|
|
539
|
-
if (Date.now() - data.savedAt > STALE_MS) {
|
|
290
|
+
if (Date.now() - data.savedAt > STALE_MS && !(data.signedLock && isSignedLockUsable(data.signedLock))) {
|
|
540
291
|
clearPendingDeposit(address);
|
|
541
292
|
return null;
|
|
542
293
|
}
|
|
@@ -545,15 +296,20 @@ function loadPendingDeposit(address) {
|
|
|
545
296
|
return null;
|
|
546
297
|
}
|
|
547
298
|
}
|
|
548
|
-
function clearPendingDeposit(address) {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
299
|
+
function clearPendingDeposit(address, onlyForTxHash) {
|
|
300
|
+
if (onlyForTxHash) {
|
|
301
|
+
try {
|
|
302
|
+
const raw = getBrowserStorageItem(storageKey(address));
|
|
303
|
+
const recordTxHash = raw ? JSON.parse(raw).txHash : void 0;
|
|
304
|
+
if (recordTxHash && recordTxHash !== onlyForTxHash) return;
|
|
305
|
+
} catch {
|
|
306
|
+
}
|
|
552
307
|
}
|
|
308
|
+
removeBrowserStorageItem(storageKey(address));
|
|
553
309
|
}
|
|
554
310
|
function useDeposit(options = {}) {
|
|
555
311
|
const { address } = useAccount();
|
|
556
|
-
const { client, enabledTokens, getChainById: getChainById2 } = usePrivanaContext();
|
|
312
|
+
const { client, enabledTokens, getChainById: getChainById2, networkConfig, serviceAddress } = usePrivanaContext();
|
|
557
313
|
const { data: walletClient } = useWalletClient();
|
|
558
314
|
const queryClient = useQueryClient();
|
|
559
315
|
const config = useConfig();
|
|
@@ -570,21 +326,54 @@ function useDeposit(options = {}) {
|
|
|
570
326
|
const onDepositAddressReceivedRef = useRef(options.onDepositAddressReceived);
|
|
571
327
|
const onDepositSuccessRef = useRef(options.onDepositSuccess);
|
|
572
328
|
const onCreditedRef = useRef(options.onCredited);
|
|
329
|
+
const onLockSubmittedRef = useRef(options.onLockSubmitted);
|
|
330
|
+
const onLockFailedRef = useRef(options.onLockFailed);
|
|
573
331
|
const onCheckTimeoutRef = useRef(options.onCheckTimeout);
|
|
574
332
|
const onErrorRef = useRef(options.onError);
|
|
575
333
|
useEffect(() => {
|
|
576
334
|
onDepositAddressReceivedRef.current = options.onDepositAddressReceived;
|
|
577
335
|
onDepositSuccessRef.current = options.onDepositSuccess;
|
|
578
336
|
onCreditedRef.current = options.onCredited;
|
|
337
|
+
onLockSubmittedRef.current = options.onLockSubmitted;
|
|
338
|
+
onLockFailedRef.current = options.onLockFailed;
|
|
579
339
|
onCheckTimeoutRef.current = options.onCheckTimeout;
|
|
580
340
|
onErrorRef.current = options.onError;
|
|
581
341
|
}, [
|
|
582
342
|
options.onDepositAddressReceived,
|
|
583
343
|
options.onDepositSuccess,
|
|
584
344
|
options.onCredited,
|
|
345
|
+
options.onLockSubmitted,
|
|
346
|
+
options.onLockFailed,
|
|
585
347
|
options.onCheckTimeout,
|
|
586
348
|
options.onError
|
|
587
349
|
]);
|
|
350
|
+
const pendingLockRef = useRef(null);
|
|
351
|
+
const submitPendingLockAfterCredit = useCallback(
|
|
352
|
+
async (signedLock, response) => {
|
|
353
|
+
try {
|
|
354
|
+
const result = await submitPendingLock({
|
|
355
|
+
client,
|
|
356
|
+
payload: signedLock,
|
|
357
|
+
creditedAmount: response.amount != null ? BigInt(response.amount) : void 0
|
|
358
|
+
});
|
|
359
|
+
queryClient.invalidateQueries({ queryKey: ["accounting-balance"] });
|
|
360
|
+
queryClient.invalidateQueries({ queryKey: ["accounting-locked-funds"] });
|
|
361
|
+
queryClient.invalidateQueries({ queryKey: ["accounting-total-locked-balance"] });
|
|
362
|
+
queryClient.invalidateQueries({ queryKey: ["accounting-history"] });
|
|
363
|
+
onLockSubmittedRef.current?.(result);
|
|
364
|
+
} catch (err) {
|
|
365
|
+
const error2 = err instanceof PostDepositLockError ? err : new PostDepositLockError(
|
|
366
|
+
err instanceof Error ? err.message : "Lock submission failed",
|
|
367
|
+
"submission-failed",
|
|
368
|
+
BigInt(signedLock.amount),
|
|
369
|
+
void 0,
|
|
370
|
+
{ cause: err }
|
|
371
|
+
);
|
|
372
|
+
(onLockFailedRef.current ?? onErrorRef.current)?.(error2);
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
[client, queryClient]
|
|
376
|
+
);
|
|
588
377
|
const {
|
|
589
378
|
isVerifying,
|
|
590
379
|
didTimeout,
|
|
@@ -597,8 +386,16 @@ function useDeposit(options = {}) {
|
|
|
597
386
|
pollTimeout: options.pollTimeout,
|
|
598
387
|
onCredited: (hash, response) => {
|
|
599
388
|
verificationContextRef.current = null;
|
|
600
|
-
|
|
601
|
-
|
|
389
|
+
const signedLock = pendingLockRef.current;
|
|
390
|
+
pendingLockRef.current = null;
|
|
391
|
+
if (signedLock) {
|
|
392
|
+
void submitPendingLockAfterCredit(signedLock, response).finally(() => {
|
|
393
|
+
if (address) clearPendingDeposit(address, hash);
|
|
394
|
+
});
|
|
395
|
+
} else if (address) {
|
|
396
|
+
clearPendingDeposit(address);
|
|
397
|
+
}
|
|
398
|
+
onCreditedRef.current?.(hash, response, signedLock !== null);
|
|
602
399
|
},
|
|
603
400
|
onCheckTimeout: (hash) => {
|
|
604
401
|
onCheckTimeoutRef.current?.(hash);
|
|
@@ -649,6 +446,7 @@ function useDeposit(options = {}) {
|
|
|
649
446
|
resetVerification();
|
|
650
447
|
if (address) clearPendingDeposit(address);
|
|
651
448
|
verificationContextRef.current = null;
|
|
449
|
+
pendingLockRef.current = null;
|
|
652
450
|
setDepositAddress(null);
|
|
653
451
|
setTxHash(void 0);
|
|
654
452
|
setIsSwitchingChain(false);
|
|
@@ -668,6 +466,7 @@ function useDeposit(options = {}) {
|
|
|
668
466
|
setTxHash(hash);
|
|
669
467
|
setDepositAddress(persisted.depositAddress);
|
|
670
468
|
setIsWaitingForConfirmation(true);
|
|
469
|
+
pendingLockRef.current = persisted.signedLock ?? null;
|
|
671
470
|
const ctx = {
|
|
672
471
|
hash,
|
|
673
472
|
chainId: persisted.chainId,
|
|
@@ -680,8 +479,12 @@ function useDeposit(options = {}) {
|
|
|
680
479
|
try {
|
|
681
480
|
let confirmed = false;
|
|
682
481
|
try {
|
|
683
|
-
await getTransactionReceipt(config, {
|
|
684
|
-
|
|
482
|
+
const receipt = await getTransactionReceipt(config, {
|
|
483
|
+
hash,
|
|
484
|
+
chainId: persisted.chainId
|
|
485
|
+
});
|
|
486
|
+
const blockNumber = await getBlockNumber(config, { chainId: persisted.chainId });
|
|
487
|
+
confirmed = blockNumber - receipt.blockNumber + 1n >= BigInt(confirmations);
|
|
685
488
|
} catch {
|
|
686
489
|
}
|
|
687
490
|
if (!confirmed) {
|
|
@@ -724,13 +527,6 @@ function useDeposit(options = {}) {
|
|
|
724
527
|
if (!sourceChain) throw new Error(`Chain ${token.chainId} not configured`);
|
|
725
528
|
const addrResponse = await addressMutation.mutateAsync();
|
|
726
529
|
if (isStale()) return;
|
|
727
|
-
setIsSwitchingChain(true);
|
|
728
|
-
try {
|
|
729
|
-
await ensureCorrectChain(sourceChain.id);
|
|
730
|
-
} finally {
|
|
731
|
-
if (!isStale()) setIsSwitchingChain(false);
|
|
732
|
-
}
|
|
733
|
-
if (isStale()) return;
|
|
734
530
|
const depositAddr = addrResponse.deposit_address;
|
|
735
531
|
if (!depositAddr || depositAddr === zeroAddress) {
|
|
736
532
|
throw new Error("Invalid deposit address received from API");
|
|
@@ -743,6 +539,43 @@ function useDeposit(options = {}) {
|
|
|
743
539
|
`Amount is below the minimum deposit (${minAmountStr}) for ${isNative ? "native" : "ERC-20"} on chain ${sourceChain.id}`
|
|
744
540
|
);
|
|
745
541
|
}
|
|
542
|
+
if (params.postDepositLock && !canUseBrowserStorage()) {
|
|
543
|
+
throw new Error("Browser storage is required for locked deposit recovery");
|
|
544
|
+
}
|
|
545
|
+
const lockAmount = clampLockAmount(params.amount, params.postDepositLock?.maxAmount);
|
|
546
|
+
let signedLock;
|
|
547
|
+
if (params.postDepositLock) {
|
|
548
|
+
setIsSwitchingChain(true);
|
|
549
|
+
try {
|
|
550
|
+
await ensureCorrectChain(networkConfig.chainId);
|
|
551
|
+
} finally {
|
|
552
|
+
if (!isStale()) setIsSwitchingChain(false);
|
|
553
|
+
}
|
|
554
|
+
if (isStale()) return;
|
|
555
|
+
const signingWalletClient = await getWalletClient(config, {
|
|
556
|
+
chainId: networkConfig.chainId
|
|
557
|
+
});
|
|
558
|
+
signedLock = await createSignedLockRequest({
|
|
559
|
+
client,
|
|
560
|
+
walletClient: signingWalletClient,
|
|
561
|
+
userAddress: address,
|
|
562
|
+
networkConfig,
|
|
563
|
+
serviceAddress: requireServiceAddress(
|
|
564
|
+
params.postDepositLock.serviceAddress ?? serviceAddress
|
|
565
|
+
),
|
|
566
|
+
tokenId: params.tokenId,
|
|
567
|
+
amount: lockAmount,
|
|
568
|
+
lockDuration: params.postDepositLock.lockDuration
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
if (isStale()) return;
|
|
572
|
+
setIsSwitchingChain(true);
|
|
573
|
+
try {
|
|
574
|
+
await ensureCorrectChain(sourceChain.id);
|
|
575
|
+
} finally {
|
|
576
|
+
if (!isStale()) setIsSwitchingChain(false);
|
|
577
|
+
}
|
|
578
|
+
if (isStale()) return;
|
|
746
579
|
const hash = token.contract === zeroAddress ? await sendTransactionAsync({
|
|
747
580
|
to: depositAddr,
|
|
748
581
|
value: params.amount,
|
|
@@ -762,13 +595,19 @@ function useDeposit(options = {}) {
|
|
|
762
595
|
amount: params.amount
|
|
763
596
|
};
|
|
764
597
|
verificationContextRef.current = ctx;
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
598
|
+
pendingLockRef.current = signedLock ?? null;
|
|
599
|
+
try {
|
|
600
|
+
savePendingDeposit(address, {
|
|
601
|
+
txHash: hash,
|
|
602
|
+
chainId: sourceChain.id,
|
|
603
|
+
amount: params.amount.toString(),
|
|
604
|
+
depositAddress: addrResponse,
|
|
605
|
+
signedLock,
|
|
606
|
+
savedAt: Date.now()
|
|
607
|
+
});
|
|
608
|
+
} catch (err) {
|
|
609
|
+
console.warn("Failed to persist pending deposit after transfer broadcast:", err);
|
|
610
|
+
}
|
|
772
611
|
try {
|
|
773
612
|
setIsWaitingForConfirmation(true);
|
|
774
613
|
try {
|
|
@@ -803,12 +642,15 @@ function useDeposit(options = {}) {
|
|
|
803
642
|
address,
|
|
804
643
|
walletClient,
|
|
805
644
|
addressMutation,
|
|
645
|
+
client,
|
|
806
646
|
getChainById2,
|
|
807
647
|
config,
|
|
808
648
|
confirmations,
|
|
809
649
|
enabledTokens,
|
|
810
650
|
ensureCorrectChain,
|
|
651
|
+
networkConfig,
|
|
811
652
|
queryClient,
|
|
653
|
+
serviceAddress,
|
|
812
654
|
writeContractAsync,
|
|
813
655
|
sendTransactionAsync,
|
|
814
656
|
reset,
|
|
@@ -843,6 +685,12 @@ function useDeposit(options = {}) {
|
|
|
843
685
|
reset
|
|
844
686
|
};
|
|
845
687
|
}
|
|
688
|
+
function requireServiceAddress(serviceAddress) {
|
|
689
|
+
if (!serviceAddress) {
|
|
690
|
+
throw new Error("Service address not configured");
|
|
691
|
+
}
|
|
692
|
+
return serviceAddress;
|
|
693
|
+
}
|
|
846
694
|
function useDepositAddress(options = {}) {
|
|
847
695
|
const queryClient = useContext(QueryClientContext);
|
|
848
696
|
const accountingContext = useSafePrivanaContext();
|
|
@@ -1370,6 +1218,59 @@ function useExpiredLocks(options = {}) {
|
|
|
1370
1218
|
refetch: query.refetch
|
|
1371
1219
|
};
|
|
1372
1220
|
}
|
|
1221
|
+
function statusCodeOf(error) {
|
|
1222
|
+
return error instanceof AccountingApiError ? error.statusCode : void 0;
|
|
1223
|
+
}
|
|
1224
|
+
function usePendingDeposits(options = {}) {
|
|
1225
|
+
const queryClient = useContext(QueryClientContext);
|
|
1226
|
+
const accountingContext = useSafePrivanaContext();
|
|
1227
|
+
const hasProviders = !!queryClient && !!accountingContext;
|
|
1228
|
+
const client = accountingContext?.client;
|
|
1229
|
+
const { executePrivateRead, privateReadAddress, privateReadQueryScope, privateReadReady } = usePrivateReadRequest();
|
|
1230
|
+
const { chainId, tokenAddress, lookbackBlocks } = options;
|
|
1231
|
+
const query = useQuery({
|
|
1232
|
+
queryKey: ["accounting-pending-deposits", ...privateReadQueryScope, chainId, tokenAddress],
|
|
1233
|
+
queryFn: async () => {
|
|
1234
|
+
if (!privateReadAddress) throw new Error("No authenticated account available");
|
|
1235
|
+
if (!chainId) throw new Error("No chain ID provided");
|
|
1236
|
+
if (!client) throw new Error("No accounting client");
|
|
1237
|
+
try {
|
|
1238
|
+
return await executePrivateRead(
|
|
1239
|
+
() => client.getPendingDeposits({
|
|
1240
|
+
chain_id: chainId,
|
|
1241
|
+
token_address: tokenAddress,
|
|
1242
|
+
lookback_blocks: lookbackBlocks
|
|
1243
|
+
})
|
|
1244
|
+
);
|
|
1245
|
+
} catch (error) {
|
|
1246
|
+
if (statusCodeOf(error) === 404) {
|
|
1247
|
+
return { pending: [], scanned_from_block: 0, scanned_to_block: 0 };
|
|
1248
|
+
}
|
|
1249
|
+
throw error;
|
|
1250
|
+
}
|
|
1251
|
+
},
|
|
1252
|
+
enabled: hasProviders && (options.enabled ?? true) && privateReadReady && !!privateReadAddress && !!chainId && !!client,
|
|
1253
|
+
// A 503 means discovery is not configured for this chain server-side —
|
|
1254
|
+
// polling can't fix that, so stop until a manual refetch succeeds.
|
|
1255
|
+
refetchInterval: (query2) => statusCodeOf(query2.state.error) === 503 ? false : options.refetchInterval ?? 3e4,
|
|
1256
|
+
staleTime: 25e3,
|
|
1257
|
+
retry: (failureCount, error) => {
|
|
1258
|
+
const status = statusCodeOf(error);
|
|
1259
|
+
if (status === 429 || status === 404 || status === 503) return false;
|
|
1260
|
+
return failureCount < 2;
|
|
1261
|
+
}
|
|
1262
|
+
});
|
|
1263
|
+
return {
|
|
1264
|
+
pending: query.data?.pending ?? [],
|
|
1265
|
+
scannedToBlock: query.data?.scanned_to_block,
|
|
1266
|
+
isFetching: query.isFetching,
|
|
1267
|
+
isError: query.isError,
|
|
1268
|
+
error: query.error,
|
|
1269
|
+
isRateLimited: statusCodeOf(query.error) === 429,
|
|
1270
|
+
isUnavailable: statusCodeOf(query.error) === 503,
|
|
1271
|
+
refetch: async () => (await query.refetch()).data
|
|
1272
|
+
};
|
|
1273
|
+
}
|
|
1373
1274
|
function usePendingWithdrawals(options = {}) {
|
|
1374
1275
|
const { address, isConnected } = useAccount();
|
|
1375
1276
|
const { client, pollingInterval } = usePrivanaContext();
|
|
@@ -2029,7 +1930,8 @@ function TransactionErrorView({
|
|
|
2029
1930
|
explorerLabel,
|
|
2030
1931
|
onRetry,
|
|
2031
1932
|
onDismiss,
|
|
2032
|
-
isRetrying
|
|
1933
|
+
isRetrying,
|
|
1934
|
+
retryLabel = "Retry Verification"
|
|
2033
1935
|
}) {
|
|
2034
1936
|
return /* @__PURE__ */ jsxs("div", { className: "flex w-full flex-col gap-4", children: [
|
|
2035
1937
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
@@ -2068,7 +1970,7 @@ function TransactionErrorView({
|
|
|
2068
1970
|
onClick: onRetry,
|
|
2069
1971
|
disabled: isRetrying,
|
|
2070
1972
|
className: "bg-primary text-primary-foreground hover:bg-primary/90 flex h-10 flex-1 cursor-pointer items-center justify-center rounded-[10px] px-3 py-2 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50",
|
|
2071
|
-
children: isRetrying ? "Retrying..." :
|
|
1973
|
+
children: isRetrying ? "Retrying..." : retryLabel
|
|
2072
1974
|
}
|
|
2073
1975
|
)
|
|
2074
1976
|
] })
|
|
@@ -3285,7 +3187,10 @@ function TokenSelectorView2({ selectedTokenId, onSelect }) {
|
|
|
3285
3187
|
function CreditCardWidgetView({
|
|
3286
3188
|
token,
|
|
3287
3189
|
amount,
|
|
3288
|
-
allowance
|
|
3190
|
+
allowance,
|
|
3191
|
+
onCredited,
|
|
3192
|
+
onLockSubmitted,
|
|
3193
|
+
onLockFailed
|
|
3289
3194
|
}) {
|
|
3290
3195
|
const moonpayCurrencyCode = token?.moonpayCurrencyCode;
|
|
3291
3196
|
const containerRef = useRef(null);
|
|
@@ -3300,10 +3205,18 @@ function CreditCardWidgetView({
|
|
|
3300
3205
|
{
|
|
3301
3206
|
tokenId: token.id,
|
|
3302
3207
|
currencyCode: moonpayCurrencyCode,
|
|
3303
|
-
|
|
3208
|
+
quoteCurrencyAmount: amount || void 0,
|
|
3209
|
+
lockAmount: true,
|
|
3304
3210
|
variant: "embedded",
|
|
3305
3211
|
autoStart: true,
|
|
3306
|
-
theme: widgetTheme
|
|
3212
|
+
theme: widgetTheme,
|
|
3213
|
+
postDepositLock: allowance ? {
|
|
3214
|
+
maxAmount: BigInt(allowance.value),
|
|
3215
|
+
lockDuration: allowance.lockDuration
|
|
3216
|
+
} : void 0,
|
|
3217
|
+
onCredited,
|
|
3218
|
+
onLockSubmitted,
|
|
3219
|
+
onLockFailed
|
|
3307
3220
|
}
|
|
3308
3221
|
) : /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground text-sm", children: [
|
|
3309
3222
|
token?.symbol ?? "This token",
|
|
@@ -3605,7 +3518,7 @@ function DepositView({
|
|
|
3605
3518
|
className: "bg-secondary text-foreground hover:bg-secondary/80 cursor-pointer rounded px-3 py-2.5 text-xs font-semibold transition-colors",
|
|
3606
3519
|
children: "MAX"
|
|
3607
3520
|
}
|
|
3608
|
-
) : isCreditCard ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: "USD" }) : selectedToken && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: selectedToken.symbol })
|
|
3521
|
+
) : isCreditCard ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: selectedToken?.symbol ?? "USD" }) : selectedToken && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: selectedToken.symbol })
|
|
3609
3522
|
]
|
|
3610
3523
|
}
|
|
3611
3524
|
),
|
|
@@ -3659,14 +3572,105 @@ function SummaryRow({ value, label }) {
|
|
|
3659
3572
|
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: label })
|
|
3660
3573
|
] });
|
|
3661
3574
|
}
|
|
3575
|
+
var LISTENING_WINDOW_MS = 36e5;
|
|
3576
|
+
function remainingSeconds(deadline) {
|
|
3577
|
+
return Math.max(0, Math.round((deadline - Date.now()) / 1e3));
|
|
3578
|
+
}
|
|
3579
|
+
function useCountdown(deadline) {
|
|
3580
|
+
const [secondsLeft, setSecondsLeft] = useState(() => remainingSeconds(deadline));
|
|
3581
|
+
useEffect(() => {
|
|
3582
|
+
if (remainingSeconds(deadline) <= 0) return;
|
|
3583
|
+
const id = setInterval(() => {
|
|
3584
|
+
const left = remainingSeconds(deadline);
|
|
3585
|
+
setSecondsLeft(left);
|
|
3586
|
+
if (left <= 0) clearInterval(id);
|
|
3587
|
+
}, 1e3);
|
|
3588
|
+
return () => clearInterval(id);
|
|
3589
|
+
}, [deadline]);
|
|
3590
|
+
return secondsLeft;
|
|
3591
|
+
}
|
|
3592
|
+
function AwaitingDepositStatus({
|
|
3593
|
+
title,
|
|
3594
|
+
subtitle,
|
|
3595
|
+
remaining
|
|
3596
|
+
}) {
|
|
3597
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3 text-center", children: [
|
|
3598
|
+
/* @__PURE__ */ jsx("div", { className: "text-foreground", children: /* @__PURE__ */ jsx(Spinner, { size: 32 }) }),
|
|
3599
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3600
|
+
/* @__PURE__ */ jsx("h3", { className: "text-foreground text-xl leading-6 font-medium", children: title }),
|
|
3601
|
+
/* @__PURE__ */ jsxs("p", { className: "text-muted-foreground text-sm leading-[18px]", children: [
|
|
3602
|
+
subtitle,
|
|
3603
|
+
remaining && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3604
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
3605
|
+
"Remaining time: ",
|
|
3606
|
+
remaining
|
|
3607
|
+
] })
|
|
3608
|
+
] })
|
|
3609
|
+
] })
|
|
3610
|
+
] });
|
|
3611
|
+
}
|
|
3662
3612
|
function ExternalDepositView({
|
|
3663
3613
|
token,
|
|
3664
|
-
amount
|
|
3614
|
+
amount,
|
|
3615
|
+
onCredited
|
|
3665
3616
|
}) {
|
|
3666
3617
|
const { getChainById: getChainById2 } = usePrivanaContext();
|
|
3667
3618
|
const { depositAddress, isReady, isLoading } = useDepositAddress();
|
|
3668
3619
|
const chain = token ? getChainById2(token.chainId) : void 0;
|
|
3669
3620
|
const [copied, setCopied] = useState(false);
|
|
3621
|
+
const [deadline] = useState(() => Date.now() + LISTENING_WINDOW_MS);
|
|
3622
|
+
const secondsLeft = useCountdown(deadline);
|
|
3623
|
+
const listening = secondsLeft > 0;
|
|
3624
|
+
const [nothingFound, setNothingFound] = useState(false);
|
|
3625
|
+
const [credited, setCredited] = useState(null);
|
|
3626
|
+
const verification = useDepositVerification({
|
|
3627
|
+
onCredited: (txHash) => {
|
|
3628
|
+
if (onCredited) {
|
|
3629
|
+
onCredited();
|
|
3630
|
+
return;
|
|
3631
|
+
}
|
|
3632
|
+
setCredited({ txHash });
|
|
3633
|
+
}
|
|
3634
|
+
});
|
|
3635
|
+
const { isVerifying, verificationFailed, didTimeout, verify } = verification;
|
|
3636
|
+
const scanPaused = isVerifying || verificationFailed || didTimeout || !!credited;
|
|
3637
|
+
const {
|
|
3638
|
+
pending,
|
|
3639
|
+
isFetching: isScanning,
|
|
3640
|
+
isError: isScanError,
|
|
3641
|
+
isRateLimited,
|
|
3642
|
+
isUnavailable,
|
|
3643
|
+
refetch: refetchPendingDeposits
|
|
3644
|
+
} = usePendingDeposits({
|
|
3645
|
+
chainId: token?.chainId,
|
|
3646
|
+
enabled: isReady && !!depositAddress && !!token,
|
|
3647
|
+
refetchInterval: listening && !scanPaused ? 3e4 : false
|
|
3648
|
+
});
|
|
3649
|
+
const processedRef = useRef(/* @__PURE__ */ new Set());
|
|
3650
|
+
useEffect(() => {
|
|
3651
|
+
if (scanPaused) return;
|
|
3652
|
+
const next = [...pending].sort((a, b) => a.block_number - b.block_number).find((d) => !processedRef.current.has(`${d.tx_hash}:${d.log_index}`));
|
|
3653
|
+
if (!next) return;
|
|
3654
|
+
processedRef.current.add(`${next.tx_hash}:${next.log_index}`);
|
|
3655
|
+
void verify({
|
|
3656
|
+
hash: next.tx_hash,
|
|
3657
|
+
chainId: next.chain_id,
|
|
3658
|
+
amount: BigInt(next.amount),
|
|
3659
|
+
logIndex: next.log_index
|
|
3660
|
+
});
|
|
3661
|
+
}, [pending, scanPaused, verify]);
|
|
3662
|
+
const nothingFoundTimerRef = useRef(void 0);
|
|
3663
|
+
useEffect(() => () => clearTimeout(nothingFoundTimerRef.current), []);
|
|
3664
|
+
const handleRefresh = () => {
|
|
3665
|
+
processedRef.current.clear();
|
|
3666
|
+
void refetchPendingDeposits().then((result) => {
|
|
3667
|
+
if (!result || result.pending.length === 0) {
|
|
3668
|
+
setNothingFound(true);
|
|
3669
|
+
clearTimeout(nothingFoundTimerRef.current);
|
|
3670
|
+
nothingFoundTimerRef.current = setTimeout(() => setNothingFound(false), 4e3);
|
|
3671
|
+
}
|
|
3672
|
+
});
|
|
3673
|
+
};
|
|
3670
3674
|
const handleCopy = () => {
|
|
3671
3675
|
if (!depositAddress) return;
|
|
3672
3676
|
void navigator.clipboard.writeText(depositAddress);
|
|
@@ -3704,6 +3708,55 @@ function ExternalDepositView({
|
|
|
3704
3708
|
}
|
|
3705
3709
|
)
|
|
3706
3710
|
] })
|
|
3711
|
+
] }),
|
|
3712
|
+
credited ? /* @__PURE__ */ jsx(
|
|
3713
|
+
TransactionSuccessView,
|
|
3714
|
+
{
|
|
3715
|
+
title: "Deposit Credited",
|
|
3716
|
+
message: `Transfer ${shortenAddress(credited.txHash)} has been credited to your Privana balance.`,
|
|
3717
|
+
onDone: () => {
|
|
3718
|
+
setCredited(null);
|
|
3719
|
+
verification.reset();
|
|
3720
|
+
void refetchPendingDeposits();
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
3723
|
+
) : verificationFailed || didTimeout ? /* @__PURE__ */ jsx(
|
|
3724
|
+
TransactionErrorView,
|
|
3725
|
+
{
|
|
3726
|
+
title: "Could not verify deposit",
|
|
3727
|
+
message: didTimeout ? "Verification timed out \u2014 your deposit may still be credited in the background." : verification.error?.message ?? "Your transfer was found but could not be verified.",
|
|
3728
|
+
onRetry: () => void verification.retryVerification(),
|
|
3729
|
+
onDismiss: () => verification.reset(),
|
|
3730
|
+
isRetrying: isVerifying
|
|
3731
|
+
}
|
|
3732
|
+
) : isVerifying ? /* @__PURE__ */ jsx(
|
|
3733
|
+
AwaitingDepositStatus,
|
|
3734
|
+
{
|
|
3735
|
+
title: "Deposit detected",
|
|
3736
|
+
subtitle: "Crediting the incoming transaction to your Privana balance..."
|
|
3737
|
+
}
|
|
3738
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3739
|
+
/* @__PURE__ */ jsx(
|
|
3740
|
+
AwaitingDepositStatus,
|
|
3741
|
+
{
|
|
3742
|
+
title: "Awaiting Deposit",
|
|
3743
|
+
subtitle: listening ? "We are listening for your incoming transaction for the next hour." : "We've stopped listening automatically. Use the button below to check for your deposit.",
|
|
3744
|
+
remaining: listening ? formatCountdown(secondsLeft) : void 0
|
|
3745
|
+
}
|
|
3746
|
+
),
|
|
3747
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
3748
|
+
/* @__PURE__ */ jsx(
|
|
3749
|
+
"button",
|
|
3750
|
+
{
|
|
3751
|
+
type: "button",
|
|
3752
|
+
onClick: handleRefresh,
|
|
3753
|
+
disabled: !depositAddress || isScanning,
|
|
3754
|
+
className: "bg-secondary text-foreground hover:bg-secondary/80 flex h-10 w-full cursor-pointer items-center justify-center rounded-[10px] px-3 py-2 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50",
|
|
3755
|
+
children: "Refresh deposit status"
|
|
3756
|
+
}
|
|
3757
|
+
),
|
|
3758
|
+
isRateLimited ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-center text-sm", children: "Checked too recently \u2014 try again in a moment." }) : isUnavailable ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-center text-sm", children: "Deposit discovery is unavailable for this chain." }) : isScanError ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-center text-sm", children: "Chain temporarily unreachable \u2014 retrying automatically." }) : nothingFound ? /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-center text-sm", children: "No incoming transaction found yet." }) : null
|
|
3759
|
+
] })
|
|
3707
3760
|
] })
|
|
3708
3761
|
] });
|
|
3709
3762
|
}
|
|
@@ -3716,6 +3769,7 @@ function DepositModalContent({
|
|
|
3716
3769
|
onConnectWallet,
|
|
3717
3770
|
onDeposit,
|
|
3718
3771
|
onDepositSuccess,
|
|
3772
|
+
onLockFailed,
|
|
3719
3773
|
onClose,
|
|
3720
3774
|
onCloseBlockedChange,
|
|
3721
3775
|
onExit
|
|
@@ -3747,6 +3801,21 @@ function DepositModalContent({
|
|
|
3747
3801
|
const [showSuccess, setShowSuccess] = useState(false);
|
|
3748
3802
|
const [showTimeout, setShowTimeout] = useState(false);
|
|
3749
3803
|
const [cancelled, setCancelled] = useState(false);
|
|
3804
|
+
const [isSubmittingLock, setIsSubmittingLock] = useState(false);
|
|
3805
|
+
const [lockFailedMessage, setLockFailedMessage] = useState(null);
|
|
3806
|
+
const finishDeposit = () => {
|
|
3807
|
+
setAmount("");
|
|
3808
|
+
if (onDepositSuccess) {
|
|
3809
|
+
resetDeposit();
|
|
3810
|
+
onDepositSuccess();
|
|
3811
|
+
} else {
|
|
3812
|
+
setShowSuccess(true);
|
|
3813
|
+
}
|
|
3814
|
+
};
|
|
3815
|
+
const finishCardPurchase = () => {
|
|
3816
|
+
setAmount("");
|
|
3817
|
+
onDepositSuccess?.();
|
|
3818
|
+
};
|
|
3750
3819
|
const {
|
|
3751
3820
|
txHash,
|
|
3752
3821
|
isGettingAddress,
|
|
@@ -3761,14 +3830,24 @@ function DepositModalContent({
|
|
|
3761
3830
|
retryVerification,
|
|
3762
3831
|
reset: resetDeposit
|
|
3763
3832
|
} = useDeposit({
|
|
3764
|
-
onCredited: () => {
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
onDepositSuccess();
|
|
3769
|
-
} else {
|
|
3770
|
-
setShowSuccess(true);
|
|
3833
|
+
onCredited: (_txHash, _response, lockPending) => {
|
|
3834
|
+
if (lockPending) {
|
|
3835
|
+
setIsSubmittingLock(true);
|
|
3836
|
+
return;
|
|
3771
3837
|
}
|
|
3838
|
+
finishDeposit();
|
|
3839
|
+
},
|
|
3840
|
+
onLockSubmitted: () => {
|
|
3841
|
+
setIsSubmittingLock(false);
|
|
3842
|
+
finishDeposit();
|
|
3843
|
+
},
|
|
3844
|
+
// The deposit credited; only the policy lock failed. Success must not
|
|
3845
|
+
// fire (the host would act on unlocked funds) — show the dedicated
|
|
3846
|
+
// error view and let the host re-prompt for a fresh lock.
|
|
3847
|
+
onLockFailed: (err) => {
|
|
3848
|
+
setIsSubmittingLock(false);
|
|
3849
|
+
setLockFailedMessage(err.message);
|
|
3850
|
+
onLockFailed?.(err);
|
|
3772
3851
|
},
|
|
3773
3852
|
onCheckTimeout: () => {
|
|
3774
3853
|
setAmount("");
|
|
@@ -3801,7 +3880,11 @@ function DepositModalContent({
|
|
|
3801
3880
|
setCancelled(false);
|
|
3802
3881
|
deposit({
|
|
3803
3882
|
tokenId: token.id,
|
|
3804
|
-
amount: parseTokenAmount(args.amount, token.decimals)
|
|
3883
|
+
amount: parseTokenAmount(args.amount, token.decimals),
|
|
3884
|
+
postDepositLock: allowance ? {
|
|
3885
|
+
maxAmount: BigInt(allowance.value),
|
|
3886
|
+
lockDuration: allowance.lockDuration
|
|
3887
|
+
} : void 0
|
|
3805
3888
|
}).catch((err) => {
|
|
3806
3889
|
toast.error(err instanceof Error ? err.message : "Deposit failed");
|
|
3807
3890
|
});
|
|
@@ -3811,26 +3894,32 @@ function DepositModalContent({
|
|
|
3811
3894
|
const depositSteps = [
|
|
3812
3895
|
{
|
|
3813
3896
|
label: "Getting deposit address",
|
|
3814
|
-
status: isGettingAddress ? "active" : isSwitchingChain || isSendingTransaction || isWaitingForConfirmation || isWaitingForProcessing ? "completed" : "pending"
|
|
3897
|
+
status: isGettingAddress ? "active" : isSwitchingChain || isSendingTransaction || isWaitingForConfirmation || isWaitingForProcessing || isSubmittingLock ? "completed" : "pending"
|
|
3815
3898
|
},
|
|
3816
3899
|
{
|
|
3817
3900
|
label: `Switching to ${targetChain?.name ?? "deposit chain"}`,
|
|
3818
|
-
status: isSwitchingChain ? "active" : isSendingTransaction || isWaitingForConfirmation || isWaitingForProcessing ? "completed" : "pending"
|
|
3901
|
+
status: isSwitchingChain ? "active" : isSendingTransaction || isWaitingForConfirmation || isWaitingForProcessing || isSubmittingLock ? "completed" : "pending"
|
|
3819
3902
|
},
|
|
3820
3903
|
{
|
|
3821
3904
|
label: "Confirm in wallet",
|
|
3822
|
-
status: isSendingTransaction ? "active" : isWaitingForConfirmation || isWaitingForProcessing ? "completed" : "pending"
|
|
3905
|
+
status: isSendingTransaction ? "active" : isWaitingForConfirmation || isWaitingForProcessing || isSubmittingLock ? "completed" : "pending"
|
|
3823
3906
|
},
|
|
3824
3907
|
{
|
|
3825
3908
|
label: "Confirming transaction",
|
|
3826
|
-
status: isWaitingForConfirmation ? "active" : isWaitingForProcessing ? "completed" : "pending"
|
|
3909
|
+
status: isWaitingForConfirmation ? "active" : isWaitingForProcessing || isSubmittingLock ? "completed" : "pending"
|
|
3827
3910
|
},
|
|
3828
3911
|
{
|
|
3829
3912
|
label: "Verifying deposit \u2014 may take up to a few minutes",
|
|
3830
|
-
status: isWaitingForProcessing ? "active" : "pending"
|
|
3831
|
-
}
|
|
3913
|
+
status: isWaitingForProcessing ? "active" : isSubmittingLock ? "completed" : "pending"
|
|
3914
|
+
},
|
|
3915
|
+
...allowance ? [
|
|
3916
|
+
{
|
|
3917
|
+
label: `Locking funds for ${appName}`,
|
|
3918
|
+
status: isSubmittingLock ? "active" : "pending"
|
|
3919
|
+
}
|
|
3920
|
+
] : []
|
|
3832
3921
|
];
|
|
3833
|
-
const flowView = showSuccess ? "deposit-success" : showTimeout ? "deposit-timeout" : verificationFailed ? "deposit-error" : isPending && !cancelled ? "depositing" : null;
|
|
3922
|
+
const flowView = showSuccess ? "deposit-success" : lockFailedMessage ? "lock-error" : showTimeout ? "deposit-timeout" : verificationFailed ? "deposit-error" : isPending && !cancelled || isSubmittingLock ? "depositing" : null;
|
|
3834
3923
|
const activeView = flowView ?? view;
|
|
3835
3924
|
const handleDepositDone = () => {
|
|
3836
3925
|
setShowSuccess(false);
|
|
@@ -3842,6 +3931,12 @@ function DepositModalContent({
|
|
|
3842
3931
|
setCancelled(true);
|
|
3843
3932
|
resetDeposit();
|
|
3844
3933
|
};
|
|
3934
|
+
const handleLockFailedDone = () => {
|
|
3935
|
+
setLockFailedMessage(null);
|
|
3936
|
+
setAmount("");
|
|
3937
|
+
setCancelled(false);
|
|
3938
|
+
resetDeposit();
|
|
3939
|
+
};
|
|
3845
3940
|
const handleDismissVerificationError = () => {
|
|
3846
3941
|
setAmount("");
|
|
3847
3942
|
setCancelled(false);
|
|
@@ -3895,6 +3990,14 @@ function DepositModalContent({
|
|
|
3895
3990
|
onDone: handleDepositDone
|
|
3896
3991
|
}
|
|
3897
3992
|
),
|
|
3993
|
+
activeView === "lock-error" && /* @__PURE__ */ jsx(
|
|
3994
|
+
TransactionWarningView,
|
|
3995
|
+
{
|
|
3996
|
+
title: "Deposit credited, lock failed",
|
|
3997
|
+
message: `Your deposit was credited but locking the funds for ${appName} failed: ${lockFailedMessage}`,
|
|
3998
|
+
onDone: handleLockFailedDone
|
|
3999
|
+
}
|
|
4000
|
+
),
|
|
3898
4001
|
activeView === "deposit-timeout" && /* @__PURE__ */ jsx(
|
|
3899
4002
|
TransactionWarningView,
|
|
3900
4003
|
{
|
|
@@ -3988,8 +4091,28 @@ function DepositModalContent({
|
|
|
3988
4091
|
}
|
|
3989
4092
|
}
|
|
3990
4093
|
),
|
|
3991
|
-
activeView === "external-deposit" && /* @__PURE__ */ jsx(
|
|
3992
|
-
|
|
4094
|
+
activeView === "external-deposit" && /* @__PURE__ */ jsx(
|
|
4095
|
+
ExternalDepositView,
|
|
4096
|
+
{
|
|
4097
|
+
token: selectedToken,
|
|
4098
|
+
amount,
|
|
4099
|
+
onCredited: allowance ? void 0 : onDepositSuccess
|
|
4100
|
+
}
|
|
4101
|
+
),
|
|
4102
|
+
activeView === "credit-card-widget" && /* @__PURE__ */ jsx(MoonPayGate, { enabled: true, children: /* @__PURE__ */ jsx(
|
|
4103
|
+
CreditCardWidgetView,
|
|
4104
|
+
{
|
|
4105
|
+
token: selectedToken,
|
|
4106
|
+
amount,
|
|
4107
|
+
allowance,
|
|
4108
|
+
onCredited: allowance ? void 0 : finishCardPurchase,
|
|
4109
|
+
onLockSubmitted: finishCardPurchase,
|
|
4110
|
+
onLockFailed: (err) => {
|
|
4111
|
+
setLockFailedMessage(err.message);
|
|
4112
|
+
onLockFailed?.(err);
|
|
4113
|
+
}
|
|
4114
|
+
}
|
|
4115
|
+
) })
|
|
3993
4116
|
] });
|
|
3994
4117
|
}
|
|
3995
4118
|
function DepositModal({ open, onClose, ...handlers }) {
|
|
@@ -4432,7 +4555,7 @@ function WalletBalanceView({
|
|
|
4432
4555
|
allowance,
|
|
4433
4556
|
amount,
|
|
4434
4557
|
onAmountChange,
|
|
4435
|
-
|
|
4558
|
+
onFundSession,
|
|
4436
4559
|
onAddFunds,
|
|
4437
4560
|
onWithdraw
|
|
4438
4561
|
}) {
|
|
@@ -4457,18 +4580,17 @@ function WalletBalanceView({
|
|
|
4457
4580
|
const hasValidAmount = !!amount && parseFloat(amount) > 0;
|
|
4458
4581
|
const tooManyDecimals = hasValidAmount && !!token && amount.includes(".") && amount.split(".")[1].length > token.decimals;
|
|
4459
4582
|
const exceedsBalance = hasValidAmount && !tooManyDecimals && !!token && !isBalanceLoading && !isBalanceError && parseTokenAmount(amount, token.decimals) > availableWei;
|
|
4460
|
-
const
|
|
4583
|
+
const canFundSession = hasValidAmount && !!token && !tooManyDecimals && !exceedsBalance && !isBalanceLoading && !isBalanceError;
|
|
4461
4584
|
const handleMax = () => {
|
|
4462
4585
|
const max = availableFormatted.replace(/\s/g, "");
|
|
4463
4586
|
if (parseFloat(max) > 0) onAmountChange(max);
|
|
4464
4587
|
};
|
|
4465
|
-
const
|
|
4466
|
-
if (!token || !
|
|
4467
|
-
|
|
4468
|
-
onAmountChange("");
|
|
4588
|
+
const handleFundSession = () => {
|
|
4589
|
+
if (!token || !canFundSession || !onFundSession) return;
|
|
4590
|
+
onFundSession({ tokenId: token.id, amount });
|
|
4469
4591
|
};
|
|
4470
4592
|
const showInput = variant !== "fully-in-use";
|
|
4471
|
-
const
|
|
4593
|
+
const showInlineFund = variant === "session-zero" || variant === "mixed";
|
|
4472
4594
|
return /* @__PURE__ */ jsxs("div", { className: "bg-muted flex flex-col gap-6 rounded-[10px] p-5", children: [
|
|
4473
4595
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
4474
4596
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
@@ -4520,14 +4642,14 @@ function WalletBalanceView({
|
|
|
4520
4642
|
}
|
|
4521
4643
|
)
|
|
4522
4644
|
] }),
|
|
4523
|
-
|
|
4645
|
+
showInlineFund && /* @__PURE__ */ jsx(
|
|
4524
4646
|
"button",
|
|
4525
4647
|
{
|
|
4526
4648
|
type: "button",
|
|
4527
|
-
disabled: !
|
|
4528
|
-
onClick:
|
|
4649
|
+
disabled: !onFundSession || !canFundSession,
|
|
4650
|
+
onClick: handleFundSession,
|
|
4529
4651
|
className: "border-border flex h-10 min-w-20 cursor-pointer items-center justify-center rounded-[10px] border px-3 text-sm font-medium text-[#4fc77f] transition-opacity hover:opacity-80 disabled:cursor-not-allowed disabled:opacity-50",
|
|
4530
|
-
children: "
|
|
4652
|
+
children: "Fund session"
|
|
4531
4653
|
}
|
|
4532
4654
|
)
|
|
4533
4655
|
] }),
|
|
@@ -4551,10 +4673,10 @@ function WalletBalanceView({
|
|
|
4551
4673
|
"button",
|
|
4552
4674
|
{
|
|
4553
4675
|
type: "button",
|
|
4554
|
-
disabled: !
|
|
4555
|
-
onClick:
|
|
4676
|
+
disabled: !onFundSession || !canFundSession,
|
|
4677
|
+
onClick: handleFundSession,
|
|
4556
4678
|
className: "bg-primary text-primary-foreground hover:bg-primary/90 flex h-10 flex-1 cursor-pointer items-center justify-center rounded-[10px] px-3 py-2 text-sm font-medium transition-colors disabled:cursor-not-allowed disabled:opacity-50",
|
|
4557
|
-
children: "
|
|
4679
|
+
children: "Fund session"
|
|
4558
4680
|
}
|
|
4559
4681
|
),
|
|
4560
4682
|
/* @__PURE__ */ jsx(
|
|
@@ -4591,10 +4713,34 @@ function WalletBalanceView({
|
|
|
4591
4713
|
] }) })
|
|
4592
4714
|
] });
|
|
4593
4715
|
}
|
|
4716
|
+
function invokeGuarded(runRef, invoke, handlers) {
|
|
4717
|
+
const run = ++runRef.current;
|
|
4718
|
+
const isCurrent = () => runRef.current === run;
|
|
4719
|
+
let result;
|
|
4720
|
+
try {
|
|
4721
|
+
result = invoke();
|
|
4722
|
+
} catch (err) {
|
|
4723
|
+
if (isCurrent()) handlers.onError(err);
|
|
4724
|
+
return;
|
|
4725
|
+
}
|
|
4726
|
+
if (result == null || typeof result.then !== "function") {
|
|
4727
|
+
handlers.onSyncResult();
|
|
4728
|
+
return;
|
|
4729
|
+
}
|
|
4730
|
+
handlers.onAsyncStart();
|
|
4731
|
+
result.then(
|
|
4732
|
+
() => {
|
|
4733
|
+
if (isCurrent()) handlers.onSuccess();
|
|
4734
|
+
},
|
|
4735
|
+
(err) => {
|
|
4736
|
+
if (isCurrent()) handlers.onError(err);
|
|
4737
|
+
}
|
|
4738
|
+
);
|
|
4739
|
+
}
|
|
4594
4740
|
function WalletModalContent({
|
|
4595
4741
|
session,
|
|
4596
4742
|
allowance,
|
|
4597
|
-
|
|
4743
|
+
onFundSession,
|
|
4598
4744
|
onEndSession,
|
|
4599
4745
|
onDepositSuccess,
|
|
4600
4746
|
onClose,
|
|
@@ -4609,7 +4755,10 @@ function WalletModalContent({
|
|
|
4609
4755
|
const [depositBlocked, setDepositBlocked] = useState(false);
|
|
4610
4756
|
const [withdrawPending, setWithdrawPending] = useState(false);
|
|
4611
4757
|
const [endSessionError, setEndSessionError] = useState(null);
|
|
4758
|
+
const [fundSessionError, setFundSessionError] = useState(null);
|
|
4612
4759
|
const endSessionRunRef = useRef(0);
|
|
4760
|
+
const fundSessionRunRef = useRef(0);
|
|
4761
|
+
const [pendingFundSession, setPendingFundSession] = useState(null);
|
|
4613
4762
|
const prevAddressRef = useRef(address);
|
|
4614
4763
|
useEffect(() => {
|
|
4615
4764
|
const prev = prevAddressRef.current;
|
|
@@ -4621,10 +4770,13 @@ function WalletModalContent({
|
|
|
4621
4770
|
setDepositBlocked(false);
|
|
4622
4771
|
setWithdrawPending(false);
|
|
4623
4772
|
setEndSessionError(null);
|
|
4773
|
+
setFundSessionError(null);
|
|
4774
|
+
setPendingFundSession(null);
|
|
4624
4775
|
endSessionRunRef.current++;
|
|
4776
|
+
fundSessionRunRef.current++;
|
|
4625
4777
|
}
|
|
4626
4778
|
}, [address, hostedAuthConfig]);
|
|
4627
|
-
const closeBlocked = depositBlocked || withdrawPending || view === "ending-session";
|
|
4779
|
+
const closeBlocked = depositBlocked || withdrawPending || view === "funding-session" || view === "ending-session";
|
|
4628
4780
|
useEffect(() => {
|
|
4629
4781
|
onCloseBlockedChange?.(closeBlocked);
|
|
4630
4782
|
}, [closeBlocked, onCloseBlockedChange]);
|
|
@@ -4638,20 +4790,16 @@ function WalletModalContent({
|
|
|
4638
4790
|
};
|
|
4639
4791
|
const startEndSession = () => {
|
|
4640
4792
|
if (!onEndSession) return;
|
|
4641
|
-
const run = ++endSessionRunRef.current;
|
|
4642
4793
|
setEndSessionError(null);
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
() =>
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
},
|
|
4649
|
-
(err) => {
|
|
4650
|
-
if (endSessionRunRef.current !== run) return;
|
|
4794
|
+
invokeGuarded(endSessionRunRef, () => onEndSession(), {
|
|
4795
|
+
onSyncResult: () => setView("withdraw"),
|
|
4796
|
+
onAsyncStart: () => setView("ending-session"),
|
|
4797
|
+
onSuccess: () => setView("withdraw"),
|
|
4798
|
+
onError: (err) => {
|
|
4651
4799
|
setEndSessionError(err instanceof Error ? err.message : null);
|
|
4652
4800
|
setView("end-session-error");
|
|
4653
4801
|
}
|
|
4654
|
-
);
|
|
4802
|
+
});
|
|
4655
4803
|
};
|
|
4656
4804
|
const handleWithdraw = () => {
|
|
4657
4805
|
if (session && onEndSession) {
|
|
@@ -4665,6 +4813,36 @@ function WalletModalContent({
|
|
|
4665
4813
|
setEndSessionError(null);
|
|
4666
4814
|
setView("balance");
|
|
4667
4815
|
};
|
|
4816
|
+
const fundSession = (args) => {
|
|
4817
|
+
if (!onFundSession) return;
|
|
4818
|
+
setFundSessionError(null);
|
|
4819
|
+
setPendingFundSession(args);
|
|
4820
|
+
setAmount("");
|
|
4821
|
+
invokeGuarded(fundSessionRunRef, () => onFundSession(args), {
|
|
4822
|
+
onSyncResult: () => {
|
|
4823
|
+
setPendingFundSession(null);
|
|
4824
|
+
setView("balance");
|
|
4825
|
+
},
|
|
4826
|
+
onAsyncStart: () => setView("funding-session"),
|
|
4827
|
+
onSuccess: () => {
|
|
4828
|
+
setPendingFundSession(null);
|
|
4829
|
+
setView("balance");
|
|
4830
|
+
},
|
|
4831
|
+
onError: (err) => {
|
|
4832
|
+
setFundSessionError(err instanceof Error ? err.message : null);
|
|
4833
|
+
setView("fund-session-error");
|
|
4834
|
+
}
|
|
4835
|
+
});
|
|
4836
|
+
};
|
|
4837
|
+
const dismissFundSessionError = () => {
|
|
4838
|
+
fundSessionRunRef.current++;
|
|
4839
|
+
setFundSessionError(null);
|
|
4840
|
+
if (pendingFundSession) {
|
|
4841
|
+
setAmount(pendingFundSession.amount);
|
|
4842
|
+
setPendingFundSession(null);
|
|
4843
|
+
}
|
|
4844
|
+
setView("balance");
|
|
4845
|
+
};
|
|
4668
4846
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4669
4847
|
onClose && /* @__PURE__ */ jsx(
|
|
4670
4848
|
"button",
|
|
@@ -4680,7 +4858,7 @@ function WalletModalContent({
|
|
|
4680
4858
|
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
4681
4859
|
}
|
|
4682
4860
|
),
|
|
4683
|
-
(view === "balance" || view === "ending-session" || view === "end-session-error") && /* @__PURE__ */ jsx("div", { className: "flex items-center px-5 py-4", children: /* @__PURE__ */ jsx("span", { className: "text-foreground text-xl leading-5 font-medium", children: appName }) }),
|
|
4861
|
+
(view === "balance" || view === "funding-session" || view === "fund-session-error" || view === "ending-session" || view === "end-session-error") && /* @__PURE__ */ jsx("div", { className: "flex items-center px-5 py-4", children: /* @__PURE__ */ jsx("span", { className: "text-foreground text-xl leading-5 font-medium", children: appName }) }),
|
|
4684
4862
|
view === "balance" && /* @__PURE__ */ jsx(
|
|
4685
4863
|
WalletBalanceView,
|
|
4686
4864
|
{
|
|
@@ -4688,11 +4866,30 @@ function WalletModalContent({
|
|
|
4688
4866
|
allowance,
|
|
4689
4867
|
amount,
|
|
4690
4868
|
onAmountChange: setAmount,
|
|
4691
|
-
|
|
4869
|
+
onFundSession: onFundSession ? fundSession : void 0,
|
|
4692
4870
|
onAddFunds: () => setView("deposit"),
|
|
4693
4871
|
onWithdraw: handleWithdraw
|
|
4694
4872
|
}
|
|
4695
4873
|
),
|
|
4874
|
+
view === "funding-session" && /* @__PURE__ */ jsx("div", { className: "bg-muted flex flex-col gap-6 rounded-[10px] p-5", children: /* @__PURE__ */ jsx(
|
|
4875
|
+
TransactionProgressView,
|
|
4876
|
+
{
|
|
4877
|
+
title: "Funding session...",
|
|
4878
|
+
steps: [{ label: "Waiting for the session to be funded", status: "active" }]
|
|
4879
|
+
}
|
|
4880
|
+
) }),
|
|
4881
|
+
view === "fund-session-error" && /* @__PURE__ */ jsx("div", { className: "bg-muted flex flex-col gap-6 rounded-[10px] p-5", children: /* @__PURE__ */ jsx(
|
|
4882
|
+
TransactionErrorView,
|
|
4883
|
+
{
|
|
4884
|
+
title: "Could not fund session",
|
|
4885
|
+
message: fundSessionError ? `Your session could not be funded. (${fundSessionError})` : "Your session could not be funded.",
|
|
4886
|
+
onRetry: () => {
|
|
4887
|
+
if (pendingFundSession) fundSession(pendingFundSession);
|
|
4888
|
+
},
|
|
4889
|
+
onDismiss: dismissFundSessionError,
|
|
4890
|
+
retryLabel: "Try again"
|
|
4891
|
+
}
|
|
4892
|
+
) }),
|
|
4696
4893
|
view === "ending-session" && /* @__PURE__ */ jsx("div", { className: "bg-muted flex flex-col gap-6 rounded-[10px] p-5", children: /* @__PURE__ */ jsx(
|
|
4697
4894
|
TransactionProgressView,
|
|
4698
4895
|
{
|
|
@@ -4706,7 +4903,8 @@ function WalletModalContent({
|
|
|
4706
4903
|
title: "Could not end session",
|
|
4707
4904
|
message: endSessionError ? `Your game session could not be ended, so the funds committed to it are not available to withdraw yet. (${endSessionError})` : "Your game session could not be ended, so the funds committed to it are not available to withdraw yet.",
|
|
4708
4905
|
onRetry: startEndSession,
|
|
4709
|
-
onDismiss: dismissEndSessionError
|
|
4906
|
+
onDismiss: dismissEndSessionError,
|
|
4907
|
+
retryLabel: "Try again"
|
|
4710
4908
|
}
|
|
4711
4909
|
) }),
|
|
4712
4910
|
view === "withdraw" && /* @__PURE__ */ jsx(WithdrawModalContent, { onBack: exitWithdraw, onPendingChange: setWithdrawPending }),
|
|
@@ -4780,6 +4978,6 @@ function WalletInlineModal({ className, ...handlers }) {
|
|
|
4780
4978
|
);
|
|
4781
4979
|
}
|
|
4782
4980
|
|
|
4783
|
-
export { DepositInlineModal, DepositModal,
|
|
4981
|
+
export { DepositInlineModal, DepositModal, PrivanaButton, PrivanaIcon, PrivanaInlineModal, PrivanaModal, WalletInlineModal, WalletModal, WithdrawInlineModal, WithdrawModal, getChainIcon, getTokenIcon, useBalance, useBatchBalances, useDeposit, useDepositAddress, useExpiredLocks, useHistory, useHostedRedirectAuth, useLockFunds, useLockedFunds, useModifyLock, usePendingDeposits, usePendingWithdrawals, usePrivanaClient, useTokenInfo, useTokenList, useTotalLockedBalance, useTransfer, useUnlockFunds, useWithdraw };
|
|
4784
4982
|
//# sourceMappingURL=index.js.map
|
|
4785
4983
|
//# sourceMappingURL=index.js.map
|