@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
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createContext, useContext, useRef, useCallback, useSyncExternalStore, useState, useEffect, useMemo } from 'react';
|
|
3
|
-
import { WagmiContext, useConfig, useAccount } from 'wagmi';
|
|
3
|
+
import { WagmiContext, useConfig, useChainId, useSwitchChain, useAccount, useWalletClient } from 'wagmi';
|
|
4
4
|
import { watchAccount, getAccount, getWalletClient } from 'wagmi/actions';
|
|
5
5
|
import { createSiweMessage } from 'viem/siwe';
|
|
6
6
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
7
|
-
import { parseAbiItem, zeroAddress, hexToString, parseUnits, decodeEventLog, formatUnits } from 'viem';
|
|
7
|
+
import { parseAbiItem, zeroAddress, walletActions, hexToString, parseUnits, decodeEventLog, formatUnits, createClient, custom } from 'viem';
|
|
8
8
|
import { useQueryClient } from '@tanstack/react-query';
|
|
9
9
|
import { Slot } from '@radix-ui/react-slot';
|
|
10
10
|
import { cva } from 'class-variance-authority';
|
|
11
11
|
import { clsx } from 'clsx';
|
|
12
12
|
import { twMerge } from 'tailwind-merge';
|
|
13
|
-
import {
|
|
13
|
+
import { parseAccount, getAddress } from 'viem/utils';
|
|
14
|
+
import { getBlockNumber as getBlockNumber$1, getTransactionReceipt as getTransactionReceipt$1, waitForTransactionReceipt as waitForTransactionReceipt$1, getTransaction, call } from 'viem/actions';
|
|
14
15
|
import { Loader2, CircleCheckIcon } from 'lucide-react';
|
|
15
16
|
import { MoonPayBuyWidget } from '@moonpay/moonpay-react';
|
|
16
17
|
|
|
@@ -34,7 +35,7 @@ var config_default = {
|
|
|
34
35
|
testnet: {
|
|
35
36
|
chainId: 23295,
|
|
36
37
|
name: "Sapphire Testnet",
|
|
37
|
-
accountingContract: "
|
|
38
|
+
accountingContract: "0xad3C76e4E621C0cfF7540479Ee9B0A945723A642",
|
|
38
39
|
apiUrl: "https://api.testnet.privana.finance"
|
|
39
40
|
},
|
|
40
41
|
mainnet: {
|
|
@@ -372,6 +373,19 @@ var PrivanaClient = class {
|
|
|
372
373
|
async getDepositStatus(depositId) {
|
|
373
374
|
return this.http.get(`/v1/accounting/deposits/status/${depositId}`);
|
|
374
375
|
}
|
|
376
|
+
async getPendingDeposits(request) {
|
|
377
|
+
const params = new URLSearchParams({ chain_id: String(request.chain_id) });
|
|
378
|
+
if (request.version !== void 0) params.set("version", String(request.version));
|
|
379
|
+
if (request.token_address !== void 0) {
|
|
380
|
+
params.set("token_address", normalizeAddress(request.token_address));
|
|
381
|
+
}
|
|
382
|
+
if (request.lookback_blocks !== void 0) {
|
|
383
|
+
params.set("lookback_blocks", String(request.lookback_blocks));
|
|
384
|
+
}
|
|
385
|
+
return this.http.get(
|
|
386
|
+
`/v1/accounting/deposits/pending?${params.toString()}`
|
|
387
|
+
);
|
|
388
|
+
}
|
|
375
389
|
async getBalance(tokenId) {
|
|
376
390
|
const token = normalizeHex(tokenId);
|
|
377
391
|
return this.http.get(`/v1/accounting/balances/${token}`);
|
|
@@ -623,6 +637,202 @@ var PrivanaClient = class {
|
|
|
623
637
|
this.http.removeHeader("Authorization");
|
|
624
638
|
}
|
|
625
639
|
};
|
|
640
|
+
|
|
641
|
+
// src/sdk/signatures/eip712-types.ts
|
|
642
|
+
function createDomain(chainId, verifyingContract) {
|
|
643
|
+
return {
|
|
644
|
+
name: "AccountingModule",
|
|
645
|
+
version: "1",
|
|
646
|
+
chainId,
|
|
647
|
+
verifyingContract
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
var LOCK_TYPES = {
|
|
651
|
+
Lock: [
|
|
652
|
+
{ name: "serviceAddress", type: "address" },
|
|
653
|
+
{ name: "tokenId", type: "bytes32" },
|
|
654
|
+
{ name: "amount", type: "uint256" },
|
|
655
|
+
{ name: "expiry", type: "uint256" },
|
|
656
|
+
{ name: "nonce", type: "uint256" }
|
|
657
|
+
]
|
|
658
|
+
};
|
|
659
|
+
var TRANSFER_TYPES = {
|
|
660
|
+
Transfer: [
|
|
661
|
+
{ name: "toAddress", type: "address" },
|
|
662
|
+
{ name: "tokenId", type: "bytes32" },
|
|
663
|
+
{ name: "amount", type: "uint256" },
|
|
664
|
+
{ name: "nonce", type: "uint256" }
|
|
665
|
+
]
|
|
666
|
+
};
|
|
667
|
+
var TRANSFER_LOCKED_TYPES = {
|
|
668
|
+
TransferLocked: [
|
|
669
|
+
{ name: "userAddress", type: "address" },
|
|
670
|
+
{ name: "toAddress", type: "address" },
|
|
671
|
+
{ name: "lockId", type: "uint256" },
|
|
672
|
+
{ name: "amount", type: "uint256" },
|
|
673
|
+
{ name: "nonce", type: "uint256" },
|
|
674
|
+
{ name: "serviceAddress", type: "address" }
|
|
675
|
+
]
|
|
676
|
+
};
|
|
677
|
+
var WITHDRAW_TYPES = {
|
|
678
|
+
Withdraw: [
|
|
679
|
+
{ name: "tokenId", type: "bytes32" },
|
|
680
|
+
{ name: "amount", type: "uint256" },
|
|
681
|
+
{ name: "nonce", type: "uint256" }
|
|
682
|
+
]
|
|
683
|
+
};
|
|
684
|
+
var MODIFY_LOCK_TYPES = {
|
|
685
|
+
ModifyLock: [
|
|
686
|
+
{ name: "lockId", type: "uint256" },
|
|
687
|
+
{ name: "amount", type: "uint256" },
|
|
688
|
+
{ name: "newExpiry", type: "uint256" },
|
|
689
|
+
{ name: "nonce", type: "uint256" }
|
|
690
|
+
]
|
|
691
|
+
};
|
|
692
|
+
var WITHDRAW_FROM_LOCK_TYPES = {
|
|
693
|
+
WithdrawFromLock: [
|
|
694
|
+
{ name: "userAddress", type: "address" },
|
|
695
|
+
{ name: "toAddress", type: "address" },
|
|
696
|
+
{ name: "lockId", type: "uint256" },
|
|
697
|
+
{ name: "amount", type: "uint256" },
|
|
698
|
+
{ name: "nonce", type: "uint256" }
|
|
699
|
+
]
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
// src/sdk/signatures/sign-lock.ts
|
|
703
|
+
async function signLockMessage({
|
|
704
|
+
walletClient,
|
|
705
|
+
chainId,
|
|
706
|
+
verifyingContract,
|
|
707
|
+
message
|
|
708
|
+
}) {
|
|
709
|
+
const account = walletClient.account;
|
|
710
|
+
if (!account) {
|
|
711
|
+
throw new Error("No account connected to wallet client");
|
|
712
|
+
}
|
|
713
|
+
const domain = createDomain(chainId, verifyingContract);
|
|
714
|
+
const signature = await walletClient.signTypedData({
|
|
715
|
+
account,
|
|
716
|
+
domain,
|
|
717
|
+
types: LOCK_TYPES,
|
|
718
|
+
primaryType: "Lock",
|
|
719
|
+
message
|
|
720
|
+
});
|
|
721
|
+
return signature;
|
|
722
|
+
}
|
|
723
|
+
function createLockExpiry(minutesFromNow = 60) {
|
|
724
|
+
return BigInt(Math.floor(Date.now() / 1e3) + minutesFromNow * 60);
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
// src/sdk/signatures/sign-modify-lock.ts
|
|
728
|
+
async function signModifyLockMessage({
|
|
729
|
+
walletClient,
|
|
730
|
+
chainId,
|
|
731
|
+
verifyingContract,
|
|
732
|
+
message
|
|
733
|
+
}) {
|
|
734
|
+
const account = walletClient.account;
|
|
735
|
+
if (!account) {
|
|
736
|
+
throw new Error("No account connected to wallet client");
|
|
737
|
+
}
|
|
738
|
+
const domain = createDomain(chainId, verifyingContract);
|
|
739
|
+
const signature = await walletClient.signTypedData({
|
|
740
|
+
account,
|
|
741
|
+
domain,
|
|
742
|
+
types: MODIFY_LOCK_TYPES,
|
|
743
|
+
primaryType: "ModifyLock",
|
|
744
|
+
message
|
|
745
|
+
});
|
|
746
|
+
return signature;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// src/sdk/signatures/sign-transfer.ts
|
|
750
|
+
async function signTransferMessage({
|
|
751
|
+
walletClient,
|
|
752
|
+
chainId,
|
|
753
|
+
verifyingContract,
|
|
754
|
+
message
|
|
755
|
+
}) {
|
|
756
|
+
const account = walletClient.account;
|
|
757
|
+
if (!account) {
|
|
758
|
+
throw new Error("No account connected to wallet client");
|
|
759
|
+
}
|
|
760
|
+
const domain = createDomain(chainId, verifyingContract);
|
|
761
|
+
const signature = await walletClient.signTypedData({
|
|
762
|
+
account,
|
|
763
|
+
domain,
|
|
764
|
+
types: TRANSFER_TYPES,
|
|
765
|
+
primaryType: "Transfer",
|
|
766
|
+
message
|
|
767
|
+
});
|
|
768
|
+
return signature;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
// src/sdk/signatures/sign-transfer-locked.ts
|
|
772
|
+
async function signTransferLockedMessage({
|
|
773
|
+
walletClient,
|
|
774
|
+
chainId,
|
|
775
|
+
verifyingContract,
|
|
776
|
+
message
|
|
777
|
+
}) {
|
|
778
|
+
const account = walletClient.account;
|
|
779
|
+
if (!account) {
|
|
780
|
+
throw new Error("No account connected to wallet client");
|
|
781
|
+
}
|
|
782
|
+
const domain = createDomain(chainId, verifyingContract);
|
|
783
|
+
const signature = await walletClient.signTypedData({
|
|
784
|
+
account,
|
|
785
|
+
domain,
|
|
786
|
+
types: TRANSFER_LOCKED_TYPES,
|
|
787
|
+
primaryType: "TransferLocked",
|
|
788
|
+
message
|
|
789
|
+
});
|
|
790
|
+
return signature;
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// src/sdk/signatures/sign-withdraw.ts
|
|
794
|
+
async function signWithdrawMessage({
|
|
795
|
+
walletClient,
|
|
796
|
+
chainId,
|
|
797
|
+
verifyingContract,
|
|
798
|
+
message
|
|
799
|
+
}) {
|
|
800
|
+
const account = walletClient.account;
|
|
801
|
+
if (!account) {
|
|
802
|
+
throw new Error("No account connected to wallet client");
|
|
803
|
+
}
|
|
804
|
+
const domain = createDomain(chainId, verifyingContract);
|
|
805
|
+
const signature = await walletClient.signTypedData({
|
|
806
|
+
account,
|
|
807
|
+
domain,
|
|
808
|
+
types: WITHDRAW_TYPES,
|
|
809
|
+
primaryType: "Withdraw",
|
|
810
|
+
message
|
|
811
|
+
});
|
|
812
|
+
return signature;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
// src/sdk/signatures/sign-withdraw-from-lock.ts
|
|
816
|
+
async function signWithdrawFromLockMessage({
|
|
817
|
+
walletClient,
|
|
818
|
+
chainId,
|
|
819
|
+
verifyingContract,
|
|
820
|
+
message
|
|
821
|
+
}) {
|
|
822
|
+
const account = walletClient.account;
|
|
823
|
+
if (!account) {
|
|
824
|
+
throw new Error("No account connected to wallet client");
|
|
825
|
+
}
|
|
826
|
+
const domain = createDomain(chainId, verifyingContract);
|
|
827
|
+
const signature = await walletClient.signTypedData({
|
|
828
|
+
account,
|
|
829
|
+
domain,
|
|
830
|
+
types: WITHDRAW_FROM_LOCK_TYPES,
|
|
831
|
+
primaryType: "WithdrawFromLock",
|
|
832
|
+
message
|
|
833
|
+
});
|
|
834
|
+
return signature;
|
|
835
|
+
}
|
|
626
836
|
var defaultResult = {
|
|
627
837
|
address: void 0,
|
|
628
838
|
isConnected: false,
|
|
@@ -1168,6 +1378,205 @@ function usePrivanaContext() {
|
|
|
1168
1378
|
function useSafePrivanaContext() {
|
|
1169
1379
|
return useContext(PrivanaContext);
|
|
1170
1380
|
}
|
|
1381
|
+
|
|
1382
|
+
// src/sdk/hooks/browser-storage.ts
|
|
1383
|
+
function storageCandidate(name) {
|
|
1384
|
+
try {
|
|
1385
|
+
if (typeof window === "undefined") return void 0;
|
|
1386
|
+
return window[name] ?? void 0;
|
|
1387
|
+
} catch {
|
|
1388
|
+
return void 0;
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
function storageCandidates() {
|
|
1392
|
+
return [storageCandidate("localStorage"), storageCandidate("sessionStorage")].filter(
|
|
1393
|
+
(storage) => storage !== void 0
|
|
1394
|
+
);
|
|
1395
|
+
}
|
|
1396
|
+
function canUseBrowserStorage() {
|
|
1397
|
+
const probeKey = "privana:storage-probe";
|
|
1398
|
+
for (const storage of storageCandidates()) {
|
|
1399
|
+
try {
|
|
1400
|
+
storage.setItem(probeKey, "1");
|
|
1401
|
+
storage.removeItem(probeKey);
|
|
1402
|
+
return true;
|
|
1403
|
+
} catch {
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
return false;
|
|
1407
|
+
}
|
|
1408
|
+
function setBrowserStorageItem(key, value) {
|
|
1409
|
+
let stored = false;
|
|
1410
|
+
for (const storage of storageCandidates()) {
|
|
1411
|
+
try {
|
|
1412
|
+
storage.setItem(key, value);
|
|
1413
|
+
stored = true;
|
|
1414
|
+
} catch {
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
return stored;
|
|
1418
|
+
}
|
|
1419
|
+
function getBrowserStorageItem(key) {
|
|
1420
|
+
for (const storage of storageCandidates()) {
|
|
1421
|
+
try {
|
|
1422
|
+
const value = storage.getItem(key);
|
|
1423
|
+
if (value !== null) return value;
|
|
1424
|
+
} catch {
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
return null;
|
|
1428
|
+
}
|
|
1429
|
+
function removeBrowserStorageItem(key) {
|
|
1430
|
+
for (const storage of storageCandidates()) {
|
|
1431
|
+
try {
|
|
1432
|
+
storage.removeItem(key);
|
|
1433
|
+
} catch {
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
// src/sdk/hooks/pending-lock.ts
|
|
1439
|
+
var DEFAULT_LOCK_DURATION_SECONDS = 259200;
|
|
1440
|
+
var DEFAULT_ONRAMP_LOCK_BUFFER = 0.02;
|
|
1441
|
+
var BUFFER_SCALE = 1000000n;
|
|
1442
|
+
function applyLockBuffer(amount, buffer = DEFAULT_ONRAMP_LOCK_BUFFER) {
|
|
1443
|
+
if (!Number.isFinite(buffer) || buffer < 0 || buffer >= 1) {
|
|
1444
|
+
throw new Error(`Lock buffer must be in [0, 1), got ${buffer}`);
|
|
1445
|
+
}
|
|
1446
|
+
const shave = BigInt(Math.max(0, Math.ceil(buffer * Number(BUFFER_SCALE) - 1e-6)));
|
|
1447
|
+
return amount * (BUFFER_SCALE - shave) / BUFFER_SCALE;
|
|
1448
|
+
}
|
|
1449
|
+
function clampLockAmount(amount, maxAmount) {
|
|
1450
|
+
return maxAmount !== void 0 && maxAmount < amount ? maxAmount : amount;
|
|
1451
|
+
}
|
|
1452
|
+
async function createSignedLockRequest({
|
|
1453
|
+
client,
|
|
1454
|
+
walletClient,
|
|
1455
|
+
userAddress,
|
|
1456
|
+
networkConfig,
|
|
1457
|
+
serviceAddress,
|
|
1458
|
+
tokenId,
|
|
1459
|
+
amount,
|
|
1460
|
+
lockDuration = DEFAULT_LOCK_DURATION_SECONDS
|
|
1461
|
+
}) {
|
|
1462
|
+
if (amount <= 0n) {
|
|
1463
|
+
throw new Error("Lock amount must be positive");
|
|
1464
|
+
}
|
|
1465
|
+
const expiry = BigInt(Math.floor(Date.now() / 1e3) + lockDuration);
|
|
1466
|
+
const { nonce } = await client.getLockNonce(userAddress);
|
|
1467
|
+
const signature = await signLockMessage({
|
|
1468
|
+
walletClient,
|
|
1469
|
+
chainId: networkConfig.chainId,
|
|
1470
|
+
verifyingContract: networkConfig.accountingContract,
|
|
1471
|
+
message: {
|
|
1472
|
+
serviceAddress,
|
|
1473
|
+
tokenId,
|
|
1474
|
+
amount,
|
|
1475
|
+
expiry,
|
|
1476
|
+
nonce: BigInt(nonce)
|
|
1477
|
+
}
|
|
1478
|
+
});
|
|
1479
|
+
return {
|
|
1480
|
+
service_address: serviceAddress,
|
|
1481
|
+
token_id: tokenId,
|
|
1482
|
+
amount: amount.toString(),
|
|
1483
|
+
expiry: expiry.toString(),
|
|
1484
|
+
nonce: String(nonce),
|
|
1485
|
+
signature
|
|
1486
|
+
};
|
|
1487
|
+
}
|
|
1488
|
+
var EXPIRY_SLACK_SECONDS = 60;
|
|
1489
|
+
function isSignedLockUsable(payload) {
|
|
1490
|
+
const expiry = Number(payload.expiry);
|
|
1491
|
+
if (!Number.isFinite(expiry)) return false;
|
|
1492
|
+
return expiry > Math.floor(Date.now() / 1e3) + EXPIRY_SLACK_SECONDS;
|
|
1493
|
+
}
|
|
1494
|
+
var PostDepositLockError = class _PostDepositLockError extends Error {
|
|
1495
|
+
constructor(message, reason, signedAmount, creditedAmount, options) {
|
|
1496
|
+
super(message, options);
|
|
1497
|
+
this.reason = reason;
|
|
1498
|
+
this.signedAmount = signedAmount;
|
|
1499
|
+
this.creditedAmount = creditedAmount;
|
|
1500
|
+
this.name = "PostDepositLockError";
|
|
1501
|
+
Object.setPrototypeOf(this, _PostDepositLockError.prototype);
|
|
1502
|
+
}
|
|
1503
|
+
};
|
|
1504
|
+
async function submitPendingLock({
|
|
1505
|
+
client,
|
|
1506
|
+
payload,
|
|
1507
|
+
creditedAmount
|
|
1508
|
+
}) {
|
|
1509
|
+
let signedAmount;
|
|
1510
|
+
try {
|
|
1511
|
+
signedAmount = BigInt(payload.amount);
|
|
1512
|
+
} catch (err) {
|
|
1513
|
+
throw new PostDepositLockError(
|
|
1514
|
+
"Stored signed lock payload is malformed",
|
|
1515
|
+
"submission-failed",
|
|
1516
|
+
void 0,
|
|
1517
|
+
creditedAmount,
|
|
1518
|
+
{ cause: err }
|
|
1519
|
+
);
|
|
1520
|
+
}
|
|
1521
|
+
if (!isSignedLockUsable(payload)) {
|
|
1522
|
+
throw new PostDepositLockError(
|
|
1523
|
+
"Signed lock expired before the deposit was credited",
|
|
1524
|
+
"expired",
|
|
1525
|
+
signedAmount,
|
|
1526
|
+
creditedAmount
|
|
1527
|
+
);
|
|
1528
|
+
}
|
|
1529
|
+
if (creditedAmount !== void 0 && creditedAmount < signedAmount) {
|
|
1530
|
+
throw new PostDepositLockError(
|
|
1531
|
+
`Credited amount (${creditedAmount}) is below the signed lock amount (${signedAmount})`,
|
|
1532
|
+
"credited-below-signed",
|
|
1533
|
+
signedAmount,
|
|
1534
|
+
creditedAmount
|
|
1535
|
+
);
|
|
1536
|
+
}
|
|
1537
|
+
try {
|
|
1538
|
+
return await client.lockFunds(payload);
|
|
1539
|
+
} catch (err) {
|
|
1540
|
+
throw new PostDepositLockError(
|
|
1541
|
+
err instanceof Error ? err.message : "Lock submission failed",
|
|
1542
|
+
"submission-failed",
|
|
1543
|
+
signedAmount,
|
|
1544
|
+
creditedAmount,
|
|
1545
|
+
{ cause: err }
|
|
1546
|
+
);
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
function pendingLockKey(userAddress, correlationId) {
|
|
1550
|
+
return `privana:pending-lock:${userAddress.toLowerCase()}:${correlationId}`;
|
|
1551
|
+
}
|
|
1552
|
+
function savePendingLock(userAddress, correlationId, payload) {
|
|
1553
|
+
const record = { payload, savedAt: Date.now() };
|
|
1554
|
+
const stored = setBrowserStorageItem(
|
|
1555
|
+
pendingLockKey(userAddress, correlationId),
|
|
1556
|
+
JSON.stringify(record)
|
|
1557
|
+
);
|
|
1558
|
+
if (!stored) {
|
|
1559
|
+
throw new Error("Unable to persist signed lock for recovery");
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
function loadPendingLock(userAddress, correlationId) {
|
|
1563
|
+
const key = pendingLockKey(userAddress, correlationId);
|
|
1564
|
+
try {
|
|
1565
|
+
const raw = getBrowserStorageItem(key);
|
|
1566
|
+
if (!raw) return void 0;
|
|
1567
|
+
const record = JSON.parse(raw);
|
|
1568
|
+
if (!record?.payload?.signature) {
|
|
1569
|
+
removeBrowserStorageItem(key);
|
|
1570
|
+
return void 0;
|
|
1571
|
+
}
|
|
1572
|
+
return record.payload;
|
|
1573
|
+
} catch {
|
|
1574
|
+
return void 0;
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
function clearPendingLock(userAddress, correlationId) {
|
|
1578
|
+
removeBrowserStorageItem(pendingLockKey(userAddress, correlationId));
|
|
1579
|
+
}
|
|
1171
1580
|
var INITIAL_AUTH_BACKOFF_MS = 5e3;
|
|
1172
1581
|
var MAX_AUTH_BACKOFF_MS = 6e4;
|
|
1173
1582
|
var DEFAULT_SIWE_AUTH_VALIDITY_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -1399,7 +1808,7 @@ function useDepositVerification(options = {}) {
|
|
|
1399
1808
|
const runVerification = useCallback(
|
|
1400
1809
|
async (ctx, generation) => {
|
|
1401
1810
|
const isStale = () => generation !== generationRef.current;
|
|
1402
|
-
const { hash, chainId, amount } = ctx;
|
|
1811
|
+
const { hash, chainId, amount, logIndex } = ctx;
|
|
1403
1812
|
setVerificationFailed(false);
|
|
1404
1813
|
setError(null);
|
|
1405
1814
|
setDidTimeout(false);
|
|
@@ -1427,7 +1836,8 @@ function useDepositVerification(options = {}) {
|
|
|
1427
1836
|
() => client.checkDeposit({
|
|
1428
1837
|
chain_id: chainId,
|
|
1429
1838
|
tx_hash: hash,
|
|
1430
|
-
amount: amount.toString()
|
|
1839
|
+
amount: amount.toString(),
|
|
1840
|
+
log_index: logIndex
|
|
1431
1841
|
})
|
|
1432
1842
|
);
|
|
1433
1843
|
if (result.status === "error" && isInsufficientFinalityMessage(result.detail)) {
|
|
@@ -1632,6 +2042,12 @@ function formatTimeRemaining(expiryTimestamp) {
|
|
|
1632
2042
|
}
|
|
1633
2043
|
return `${minutes}m left`;
|
|
1634
2044
|
}
|
|
2045
|
+
function formatCountdown(secondsLeft) {
|
|
2046
|
+
const clamped = Math.max(0, secondsLeft);
|
|
2047
|
+
const minutes = Math.floor(clamped / 60);
|
|
2048
|
+
const seconds = clamped % 60;
|
|
2049
|
+
return `${minutes}m:${String(seconds).padStart(2, "0")}s`;
|
|
2050
|
+
}
|
|
1635
2051
|
var buttonVariants = cva(
|
|
1636
2052
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
1637
2053
|
{
|
|
@@ -1700,6 +2116,204 @@ function getAction(client, actionFn, name) {
|
|
|
1700
2116
|
return (params) => actionFn(client, params);
|
|
1701
2117
|
}
|
|
1702
2118
|
|
|
2119
|
+
// ../../node_modules/@wagmi/core/dist/esm/version.js
|
|
2120
|
+
var version = "3.3.1";
|
|
2121
|
+
|
|
2122
|
+
// ../../node_modules/@wagmi/core/dist/esm/utils/getVersion.js
|
|
2123
|
+
var getVersion = () => `@wagmi/core@${version}`;
|
|
2124
|
+
|
|
2125
|
+
// ../../node_modules/@wagmi/core/dist/esm/errors/base.js
|
|
2126
|
+
var __classPrivateFieldGet = function(receiver, state, kind, f) {
|
|
2127
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
2128
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
2129
|
+
};
|
|
2130
|
+
var _BaseError_instances;
|
|
2131
|
+
var _BaseError_walk;
|
|
2132
|
+
var BaseError = class _BaseError extends Error {
|
|
2133
|
+
get docsBaseUrl() {
|
|
2134
|
+
return "https://wagmi.sh/core";
|
|
2135
|
+
}
|
|
2136
|
+
get version() {
|
|
2137
|
+
return getVersion();
|
|
2138
|
+
}
|
|
2139
|
+
constructor(shortMessage, options = {}) {
|
|
2140
|
+
super();
|
|
2141
|
+
_BaseError_instances.add(this);
|
|
2142
|
+
Object.defineProperty(this, "details", {
|
|
2143
|
+
enumerable: true,
|
|
2144
|
+
configurable: true,
|
|
2145
|
+
writable: true,
|
|
2146
|
+
value: void 0
|
|
2147
|
+
});
|
|
2148
|
+
Object.defineProperty(this, "docsPath", {
|
|
2149
|
+
enumerable: true,
|
|
2150
|
+
configurable: true,
|
|
2151
|
+
writable: true,
|
|
2152
|
+
value: void 0
|
|
2153
|
+
});
|
|
2154
|
+
Object.defineProperty(this, "metaMessages", {
|
|
2155
|
+
enumerable: true,
|
|
2156
|
+
configurable: true,
|
|
2157
|
+
writable: true,
|
|
2158
|
+
value: void 0
|
|
2159
|
+
});
|
|
2160
|
+
Object.defineProperty(this, "shortMessage", {
|
|
2161
|
+
enumerable: true,
|
|
2162
|
+
configurable: true,
|
|
2163
|
+
writable: true,
|
|
2164
|
+
value: void 0
|
|
2165
|
+
});
|
|
2166
|
+
Object.defineProperty(this, "name", {
|
|
2167
|
+
enumerable: true,
|
|
2168
|
+
configurable: true,
|
|
2169
|
+
writable: true,
|
|
2170
|
+
value: "WagmiCoreError"
|
|
2171
|
+
});
|
|
2172
|
+
const details = options.cause instanceof _BaseError ? options.cause.details : options.cause?.message ? options.cause.message : options.details;
|
|
2173
|
+
const docsPath = options.cause instanceof _BaseError ? options.cause.docsPath || options.docsPath : options.docsPath;
|
|
2174
|
+
this.message = [
|
|
2175
|
+
shortMessage || "An error occurred.",
|
|
2176
|
+
"",
|
|
2177
|
+
...options.metaMessages ? [...options.metaMessages, ""] : [],
|
|
2178
|
+
...docsPath ? [
|
|
2179
|
+
`Docs: ${this.docsBaseUrl}${docsPath}.html${options.docsSlug ? `#${options.docsSlug}` : ""}`
|
|
2180
|
+
] : [],
|
|
2181
|
+
...details ? [`Details: ${details}`] : [],
|
|
2182
|
+
`Version: ${this.version}`
|
|
2183
|
+
].join("\n");
|
|
2184
|
+
if (options.cause)
|
|
2185
|
+
this.cause = options.cause;
|
|
2186
|
+
this.details = details;
|
|
2187
|
+
this.docsPath = docsPath;
|
|
2188
|
+
this.metaMessages = options.metaMessages;
|
|
2189
|
+
this.shortMessage = shortMessage;
|
|
2190
|
+
}
|
|
2191
|
+
walk(fn) {
|
|
2192
|
+
return __classPrivateFieldGet(this, _BaseError_instances, "m", _BaseError_walk).call(this, this, fn);
|
|
2193
|
+
}
|
|
2194
|
+
};
|
|
2195
|
+
_BaseError_instances = /* @__PURE__ */ new WeakSet(), _BaseError_walk = function _BaseError_walk2(err, fn) {
|
|
2196
|
+
if (fn?.(err))
|
|
2197
|
+
return err;
|
|
2198
|
+
if (err.cause)
|
|
2199
|
+
return __classPrivateFieldGet(this, _BaseError_instances, "m", _BaseError_walk2).call(this, err.cause, fn);
|
|
2200
|
+
return err;
|
|
2201
|
+
};
|
|
2202
|
+
|
|
2203
|
+
// ../../node_modules/@wagmi/core/dist/esm/errors/config.js
|
|
2204
|
+
var ConnectorNotConnectedError = class extends BaseError {
|
|
2205
|
+
constructor() {
|
|
2206
|
+
super("Connector not connected.");
|
|
2207
|
+
Object.defineProperty(this, "name", {
|
|
2208
|
+
enumerable: true,
|
|
2209
|
+
configurable: true,
|
|
2210
|
+
writable: true,
|
|
2211
|
+
value: "ConnectorNotConnectedError"
|
|
2212
|
+
});
|
|
2213
|
+
}
|
|
2214
|
+
};
|
|
2215
|
+
var ConnectorAccountNotFoundError = class extends BaseError {
|
|
2216
|
+
constructor({ address, connector }) {
|
|
2217
|
+
super(`Account "${address}" not found for connector "${connector.name}".`);
|
|
2218
|
+
Object.defineProperty(this, "name", {
|
|
2219
|
+
enumerable: true,
|
|
2220
|
+
configurable: true,
|
|
2221
|
+
writable: true,
|
|
2222
|
+
value: "ConnectorAccountNotFoundError"
|
|
2223
|
+
});
|
|
2224
|
+
}
|
|
2225
|
+
};
|
|
2226
|
+
var ConnectorChainMismatchError = class extends BaseError {
|
|
2227
|
+
constructor({ connectionChainId, connectorChainId }) {
|
|
2228
|
+
super(`The current chain of the connector (id: ${connectorChainId}) does not match the connection's chain (id: ${connectionChainId}).`, {
|
|
2229
|
+
metaMessages: [
|
|
2230
|
+
`Current Chain ID: ${connectorChainId}`,
|
|
2231
|
+
`Expected Chain ID: ${connectionChainId}`
|
|
2232
|
+
]
|
|
2233
|
+
});
|
|
2234
|
+
Object.defineProperty(this, "name", {
|
|
2235
|
+
enumerable: true,
|
|
2236
|
+
configurable: true,
|
|
2237
|
+
writable: true,
|
|
2238
|
+
value: "ConnectorChainMismatchError"
|
|
2239
|
+
});
|
|
2240
|
+
}
|
|
2241
|
+
};
|
|
2242
|
+
var ConnectorUnavailableReconnectingError = class extends BaseError {
|
|
2243
|
+
constructor({ connector }) {
|
|
2244
|
+
super(`Connector "${connector.name}" unavailable while reconnecting.`, {
|
|
2245
|
+
details: [
|
|
2246
|
+
"During the reconnection step, the only connector methods guaranteed to be available are: `id`, `name`, `type`, `uid`.",
|
|
2247
|
+
"All other methods are not guaranteed to be available until reconnection completes and connectors are fully restored.",
|
|
2248
|
+
"This error commonly occurs for connectors that asynchronously inject after reconnection has already started."
|
|
2249
|
+
].join(" ")
|
|
2250
|
+
});
|
|
2251
|
+
Object.defineProperty(this, "name", {
|
|
2252
|
+
enumerable: true,
|
|
2253
|
+
configurable: true,
|
|
2254
|
+
writable: true,
|
|
2255
|
+
value: "ConnectorUnavailableReconnectingError"
|
|
2256
|
+
});
|
|
2257
|
+
}
|
|
2258
|
+
};
|
|
2259
|
+
async function getConnectorClient(config, parameters = {}) {
|
|
2260
|
+
const { assertChainId = true } = parameters;
|
|
2261
|
+
let connection;
|
|
2262
|
+
if (parameters.connector) {
|
|
2263
|
+
const { connector: connector2 } = parameters;
|
|
2264
|
+
if (config.state.status === "reconnecting" && !connector2.getAccounts && !connector2.getChainId)
|
|
2265
|
+
throw new ConnectorUnavailableReconnectingError({ connector: connector2 });
|
|
2266
|
+
const [accounts, chainId2] = await Promise.all([
|
|
2267
|
+
connector2.getAccounts().catch((e) => {
|
|
2268
|
+
if (parameters.account === null)
|
|
2269
|
+
return [];
|
|
2270
|
+
throw e;
|
|
2271
|
+
}),
|
|
2272
|
+
connector2.getChainId()
|
|
2273
|
+
]);
|
|
2274
|
+
connection = {
|
|
2275
|
+
accounts,
|
|
2276
|
+
chainId: chainId2,
|
|
2277
|
+
connector: connector2
|
|
2278
|
+
};
|
|
2279
|
+
} else
|
|
2280
|
+
connection = config.state.connections.get(config.state.current);
|
|
2281
|
+
if (!connection)
|
|
2282
|
+
throw new ConnectorNotConnectedError();
|
|
2283
|
+
const chainId = parameters.chainId ?? connection.chainId;
|
|
2284
|
+
const connectorChainId = await connection.connector.getChainId();
|
|
2285
|
+
if (assertChainId && connectorChainId !== chainId)
|
|
2286
|
+
throw new ConnectorChainMismatchError({
|
|
2287
|
+
connectionChainId: chainId,
|
|
2288
|
+
connectorChainId
|
|
2289
|
+
});
|
|
2290
|
+
const connector = connection.connector;
|
|
2291
|
+
if (connector.getClient)
|
|
2292
|
+
return connector.getClient({ chainId });
|
|
2293
|
+
const account = parseAccount(parameters.account ?? connection.accounts[0]);
|
|
2294
|
+
if (account)
|
|
2295
|
+
account.address = getAddress(account.address);
|
|
2296
|
+
if (parameters.account && !connection.accounts.some((x) => x.toLowerCase() === account.address.toLowerCase()))
|
|
2297
|
+
throw new ConnectorAccountNotFoundError({
|
|
2298
|
+
address: account.address,
|
|
2299
|
+
connector
|
|
2300
|
+
});
|
|
2301
|
+
const chain = config.chains.find((chain2) => chain2.id === chainId);
|
|
2302
|
+
const provider = await connection.connector.getProvider({ chainId });
|
|
2303
|
+
return createClient({
|
|
2304
|
+
account,
|
|
2305
|
+
chain,
|
|
2306
|
+
name: "Connector Client",
|
|
2307
|
+
transport: (opts) => custom(provider)({ ...opts, retryCount: 0 })
|
|
2308
|
+
});
|
|
2309
|
+
}
|
|
2310
|
+
function getBlockNumber(config, parameters = {}) {
|
|
2311
|
+
const { chainId, ...rest } = parameters;
|
|
2312
|
+
const client = config.getClient({ chainId });
|
|
2313
|
+
const action = getAction(client, getBlockNumber$1, "getBlockNumber");
|
|
2314
|
+
return action(rest);
|
|
2315
|
+
}
|
|
2316
|
+
|
|
1703
2317
|
// ../../node_modules/@wagmi/core/dist/esm/actions/getChainId.js
|
|
1704
2318
|
function getChainId2(config) {
|
|
1705
2319
|
return config.state.chainId;
|
|
@@ -1710,6 +2324,10 @@ async function getTransactionReceipt(config, parameters) {
|
|
|
1710
2324
|
const action = getAction(client, getTransactionReceipt$1, "getTransactionReceipt");
|
|
1711
2325
|
return action(rest);
|
|
1712
2326
|
}
|
|
2327
|
+
async function getWalletClient3(config, parameters = {}) {
|
|
2328
|
+
const client = await getConnectorClient(config, parameters);
|
|
2329
|
+
return client.extend(walletActions);
|
|
2330
|
+
}
|
|
1713
2331
|
async function waitForTransactionReceipt(config, parameters) {
|
|
1714
2332
|
const { chainId, timeout = 0, ...rest } = parameters;
|
|
1715
2333
|
const client = config.getClient({ chainId });
|
|
@@ -1737,6 +2355,59 @@ async function waitForTransactionReceipt(config, parameters) {
|
|
|
1737
2355
|
chainId: client.chain.id
|
|
1738
2356
|
};
|
|
1739
2357
|
}
|
|
2358
|
+
function useEnsureCorrectChain() {
|
|
2359
|
+
const config = useConfig();
|
|
2360
|
+
const chainId = useChainId();
|
|
2361
|
+
const { switchChainAsync } = useSwitchChain();
|
|
2362
|
+
const waitUntilOnChain = useCallback(
|
|
2363
|
+
async (expectedChainId, timeoutMs, pollIntervalMs = 250) => {
|
|
2364
|
+
const startedAt = Date.now();
|
|
2365
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
2366
|
+
const currentChainId = getChainId2(config);
|
|
2367
|
+
if (currentChainId === expectedChainId) return true;
|
|
2368
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
2369
|
+
}
|
|
2370
|
+
return false;
|
|
2371
|
+
},
|
|
2372
|
+
[config]
|
|
2373
|
+
);
|
|
2374
|
+
const ensureCorrectChain = useCallback(
|
|
2375
|
+
async (targetChainId) => {
|
|
2376
|
+
const currentChainId = getChainId2(config);
|
|
2377
|
+
if (currentChainId === targetChainId) return false;
|
|
2378
|
+
let switchErrorMessage;
|
|
2379
|
+
try {
|
|
2380
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
2381
|
+
setTimeout(() => reject(new Error("Chain switch timeout")), 3e3);
|
|
2382
|
+
});
|
|
2383
|
+
await Promise.race([switchChainAsync({ chainId: targetChainId }), timeoutPromise]);
|
|
2384
|
+
} catch (error) {
|
|
2385
|
+
if (error instanceof Error && error.message.includes("Unsupported Chain")) {
|
|
2386
|
+
console.warn("Got 'Unsupported Chain' error, chain may have switched anyway.");
|
|
2387
|
+
} else {
|
|
2388
|
+
switchErrorMessage = error instanceof Error ? error.message : "Unknown chain switch error";
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
const settled = await waitUntilOnChain(targetChainId, 2e4);
|
|
2392
|
+
if (settled) return true;
|
|
2393
|
+
if (switchErrorMessage) {
|
|
2394
|
+
throw new Error(
|
|
2395
|
+
`Failed to switch to chain (Chain ID: ${targetChainId}): ${switchErrorMessage}`
|
|
2396
|
+
);
|
|
2397
|
+
}
|
|
2398
|
+
throw new Error(`Chain switch did not settle in time (expected ${targetChainId}).`);
|
|
2399
|
+
},
|
|
2400
|
+
[config, switchChainAsync, waitUntilOnChain]
|
|
2401
|
+
);
|
|
2402
|
+
const isOnChain = useCallback((targetChainId) => chainId === targetChainId, [chainId]);
|
|
2403
|
+
return {
|
|
2404
|
+
chainId,
|
|
2405
|
+
ensureCorrectChain,
|
|
2406
|
+
isOnChain
|
|
2407
|
+
};
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
// src/sdk/hooks/use-fiat-on-ramp.ts
|
|
1740
2411
|
var DEFAULT_DELIVERY_TIMEOUT_MS = 12e4;
|
|
1741
2412
|
var DEFAULT_VERIFICATION_TIMEOUT_MS = 10 * 6e4;
|
|
1742
2413
|
var DEFAULT_FINALITY_RETRY_INTERVAL_MS = 15e3;
|
|
@@ -1744,14 +2415,26 @@ var ERC20_TRANSFER_EVENT = parseAbiItem(
|
|
|
1744
2415
|
"event Transfer(address indexed from, address indexed to, uint256 value)"
|
|
1745
2416
|
);
|
|
1746
2417
|
function useFiatOnRamp(options) {
|
|
1747
|
-
const {
|
|
2418
|
+
const {
|
|
2419
|
+
tokenId,
|
|
2420
|
+
postDepositLock,
|
|
2421
|
+
onCredited,
|
|
2422
|
+
onLockSubmitted,
|
|
2423
|
+
onLockFailed,
|
|
2424
|
+
onError,
|
|
2425
|
+
onDebugEvent
|
|
2426
|
+
} = options;
|
|
1748
2427
|
const deliveryTimeout = options.deliveryTimeout ?? DEFAULT_DELIVERY_TIMEOUT_MS;
|
|
1749
2428
|
const deliveryPollInterval = options.deliveryPollInterval ?? 3e3;
|
|
1750
2429
|
const verificationTimeout = options.verificationTimeout ?? DEFAULT_VERIFICATION_TIMEOUT_MS;
|
|
1751
2430
|
const finalityRetryInterval = options.finalityRetryInterval ?? DEFAULT_FINALITY_RETRY_INTERVAL_MS;
|
|
1752
|
-
const {
|
|
2431
|
+
const { address } = useAccount();
|
|
2432
|
+
const { data: walletClient } = useWalletClient();
|
|
2433
|
+
const { client, enabledTokens, networkConfig, serviceAddress } = usePrivanaContext();
|
|
1753
2434
|
const { executePrivateRead, privateReadReady } = usePrivateReadRequest();
|
|
2435
|
+
const { ensureCorrectChain } = useEnsureCorrectChain();
|
|
1754
2436
|
const wagmiConfig = useConfig();
|
|
2437
|
+
const queryClient = useQueryClient();
|
|
1755
2438
|
const selectedToken = enabledTokens.find((t) => t.id.toLowerCase() === tokenId.toLowerCase());
|
|
1756
2439
|
const [status, setStatus] = useState("idle");
|
|
1757
2440
|
const [pending, setPending] = useState([]);
|
|
@@ -1762,20 +2445,27 @@ function useFiatOnRamp(options) {
|
|
|
1762
2445
|
const [activeVerificationId, setActiveVerificationId] = useState(null);
|
|
1763
2446
|
const [finalityProgress, setFinalityProgress] = useState({});
|
|
1764
2447
|
const onCreditedRef = useRef(onCredited);
|
|
2448
|
+
const onLockSubmittedRef = useRef(onLockSubmitted);
|
|
2449
|
+
const onLockFailedRef = useRef(onLockFailed);
|
|
1765
2450
|
const onErrorRef = useRef(onError);
|
|
1766
2451
|
const onDebugEventRef = useRef(onDebugEvent);
|
|
1767
2452
|
const statusRef = useRef(status);
|
|
1768
2453
|
const activeIntentIdRef = useRef(null);
|
|
1769
2454
|
const activeVerificationRecordRef = useRef(null);
|
|
1770
2455
|
const activeVerificationKeyRef = useRef(null);
|
|
2456
|
+
const activeVerificationAmountRef = useRef(null);
|
|
2457
|
+
const lockOwnerRef = useRef(null);
|
|
1771
2458
|
const triggeredVerificationKeysRef = useRef(/* @__PURE__ */ new Set());
|
|
2459
|
+
const activeVerificationDoneRef = useRef(null);
|
|
1772
2460
|
const closeReconcilePromiseRef = useRef(null);
|
|
1773
2461
|
const purchaseInitiatedRef = useRef(false);
|
|
1774
2462
|
useEffect(() => {
|
|
1775
2463
|
onCreditedRef.current = onCredited;
|
|
2464
|
+
onLockSubmittedRef.current = onLockSubmitted;
|
|
2465
|
+
onLockFailedRef.current = onLockFailed;
|
|
1776
2466
|
onErrorRef.current = onError;
|
|
1777
2467
|
onDebugEventRef.current = onDebugEvent;
|
|
1778
|
-
}, [onCredited, onError, onDebugEvent]);
|
|
2468
|
+
}, [onCredited, onLockSubmitted, onLockFailed, onError, onDebugEvent]);
|
|
1779
2469
|
useEffect(() => {
|
|
1780
2470
|
statusRef.current = status;
|
|
1781
2471
|
}, [status]);
|
|
@@ -1856,13 +2546,64 @@ function useFiatOnRamp(options) {
|
|
|
1856
2546
|
useEffect(() => {
|
|
1857
2547
|
refreshPending();
|
|
1858
2548
|
}, [refreshPending]);
|
|
1859
|
-
const clearActiveVerification = useCallback(() => {
|
|
2549
|
+
const clearActiveVerification = useCallback((expectedKey) => {
|
|
1860
2550
|
const key = activeVerificationKeyRef.current;
|
|
2551
|
+
if (expectedKey != null && key !== null && key !== expectedKey) return;
|
|
1861
2552
|
if (key) triggeredVerificationKeysRef.current.delete(key);
|
|
1862
2553
|
activeVerificationKeyRef.current = null;
|
|
1863
2554
|
activeVerificationRecordRef.current = null;
|
|
2555
|
+
activeVerificationAmountRef.current = null;
|
|
1864
2556
|
setActiveVerificationId(null);
|
|
2557
|
+
activeVerificationDoneRef.current?.();
|
|
2558
|
+
activeVerificationDoneRef.current = null;
|
|
1865
2559
|
}, []);
|
|
2560
|
+
const submitPendingLockAfterCredit = useCallback(
|
|
2561
|
+
async (transactionId, userAddress) => {
|
|
2562
|
+
const signedLock = loadPendingLock(userAddress, transactionId);
|
|
2563
|
+
if (!signedLock) {
|
|
2564
|
+
clearPendingLock(userAddress, transactionId);
|
|
2565
|
+
if (!postDepositLock || transactionId !== activeIntentIdRef.current) return;
|
|
2566
|
+
const error2 = new PostDepositLockError(
|
|
2567
|
+
"No persisted signed lock found for this on-ramp",
|
|
2568
|
+
"not-found"
|
|
2569
|
+
);
|
|
2570
|
+
emitDebug("lock:not-found", { transactionId });
|
|
2571
|
+
(onLockFailedRef.current ?? onErrorRef.current)?.(error2);
|
|
2572
|
+
return;
|
|
2573
|
+
}
|
|
2574
|
+
const creditedAmount = activeVerificationAmountRef.current ?? void 0;
|
|
2575
|
+
try {
|
|
2576
|
+
const result = await submitPendingLock({ client, payload: signedLock, creditedAmount });
|
|
2577
|
+
queryClient.invalidateQueries({ queryKey: ["accounting-balance"] });
|
|
2578
|
+
queryClient.invalidateQueries({ queryKey: ["accounting-locked-funds"] });
|
|
2579
|
+
queryClient.invalidateQueries({ queryKey: ["accounting-total-locked-balance"] });
|
|
2580
|
+
queryClient.invalidateQueries({ queryKey: ["accounting-history"] });
|
|
2581
|
+
emitDebug("lock:submitted", {
|
|
2582
|
+
transactionId,
|
|
2583
|
+
amount: signedLock.amount,
|
|
2584
|
+
submissionId: result.submission_id
|
|
2585
|
+
});
|
|
2586
|
+
onLockSubmittedRef.current?.(result);
|
|
2587
|
+
} catch (err) {
|
|
2588
|
+
const error2 = err instanceof PostDepositLockError ? err : new PostDepositLockError(
|
|
2589
|
+
err instanceof Error ? err.message : "Lock submission failed",
|
|
2590
|
+
"submission-failed",
|
|
2591
|
+
BigInt(signedLock.amount),
|
|
2592
|
+
creditedAmount,
|
|
2593
|
+
{ cause: err }
|
|
2594
|
+
);
|
|
2595
|
+
emitDebug("lock:failed", {
|
|
2596
|
+
transactionId,
|
|
2597
|
+
reason: error2.reason,
|
|
2598
|
+
message: error2.message
|
|
2599
|
+
});
|
|
2600
|
+
(onLockFailedRef.current ?? onErrorRef.current)?.(error2);
|
|
2601
|
+
} finally {
|
|
2602
|
+
clearPendingLock(userAddress, transactionId);
|
|
2603
|
+
}
|
|
2604
|
+
},
|
|
2605
|
+
[client, emitDebug, postDepositLock, queryClient]
|
|
2606
|
+
);
|
|
1866
2607
|
const { verify } = useDepositVerification({
|
|
1867
2608
|
pollTimeout: verificationTimeout,
|
|
1868
2609
|
pollInterval: options.verificationPollInterval,
|
|
@@ -1878,6 +2619,7 @@ function useFiatOnRamp(options) {
|
|
|
1878
2619
|
},
|
|
1879
2620
|
onCredited: (depositTxHash) => {
|
|
1880
2621
|
const record = activeVerificationRecordRef.current;
|
|
2622
|
+
const verificationKey = record ? getOnRampVerificationKey(record) : null;
|
|
1881
2623
|
emitDebug("verification:credited", {
|
|
1882
2624
|
depositTxHash,
|
|
1883
2625
|
record: record ? summariseOnRampRecord(record) : null
|
|
@@ -1892,6 +2634,18 @@ function useFiatOnRamp(options) {
|
|
|
1892
2634
|
delete next[record.transaction_id];
|
|
1893
2635
|
return next;
|
|
1894
2636
|
});
|
|
2637
|
+
const lockOwner = lockOwnerRef.current ?? address;
|
|
2638
|
+
if (lockOwner) {
|
|
2639
|
+
void submitPendingLockAfterCredit(record.transaction_id, lockOwner);
|
|
2640
|
+
} else if (postDepositLock) {
|
|
2641
|
+
emitDebug("lock:owner-unavailable", { transactionId: record.transaction_id });
|
|
2642
|
+
(onLockFailedRef.current ?? onErrorRef.current)?.(
|
|
2643
|
+
new PostDepositLockError(
|
|
2644
|
+
"No wallet address available to look up the signed lock for this on-ramp",
|
|
2645
|
+
"not-found"
|
|
2646
|
+
)
|
|
2647
|
+
);
|
|
2648
|
+
}
|
|
1895
2649
|
}
|
|
1896
2650
|
void (async () => {
|
|
1897
2651
|
try {
|
|
@@ -1914,7 +2668,7 @@ function useFiatOnRamp(options) {
|
|
|
1914
2668
|
console.warn("Failed to mark on-ramp row complete:", err);
|
|
1915
2669
|
} finally {
|
|
1916
2670
|
await refreshPending();
|
|
1917
|
-
clearActiveVerification();
|
|
2671
|
+
clearActiveVerification(verificationKey);
|
|
1918
2672
|
if (record && activeIntentIdRef.current === record.transaction_id) {
|
|
1919
2673
|
activeIntentIdRef.current = null;
|
|
1920
2674
|
setActiveIntentId(null);
|
|
@@ -1952,7 +2706,8 @@ function useFiatOnRamp(options) {
|
|
|
1952
2706
|
async ({
|
|
1953
2707
|
currencyCode,
|
|
1954
2708
|
baseCurrencyCode,
|
|
1955
|
-
baseCurrencyAmount
|
|
2709
|
+
baseCurrencyAmount,
|
|
2710
|
+
quoteCurrencyAmount
|
|
1956
2711
|
}) => {
|
|
1957
2712
|
try {
|
|
1958
2713
|
setError(null);
|
|
@@ -1960,12 +2715,34 @@ function useFiatOnRamp(options) {
|
|
|
1960
2715
|
const token = enabledTokens.find((t) => t.id.toLowerCase() === tokenId.toLowerCase());
|
|
1961
2716
|
if (!token) throw new Error(`Unknown token: ${tokenId}`);
|
|
1962
2717
|
if (!depositAddress) throw new Error("Privana deposit address is not ready");
|
|
2718
|
+
let lockAmount;
|
|
2719
|
+
if (postDepositLock) {
|
|
2720
|
+
if (!address || !walletClient) throw new Error("Wallet not connected");
|
|
2721
|
+
if (!quoteCurrencyAmount) {
|
|
2722
|
+
throw new Error(
|
|
2723
|
+
"postDepositLock requires quoteCurrencyAmount to derive the lock amount"
|
|
2724
|
+
);
|
|
2725
|
+
}
|
|
2726
|
+
if (!canUseBrowserStorage()) {
|
|
2727
|
+
throw new Error("Browser storage is required for locked on-ramp recovery");
|
|
2728
|
+
}
|
|
2729
|
+
const buffered = applyLockBuffer(
|
|
2730
|
+
parseUnits(quoteCurrencyAmount, token.decimals),
|
|
2731
|
+
postDepositLock.buffer
|
|
2732
|
+
);
|
|
2733
|
+
lockAmount = clampLockAmount(buffered, postDepositLock.maxAmount);
|
|
2734
|
+
if (lockAmount <= 0n) {
|
|
2735
|
+
throw new Error(`Post-deposit lock amount must be positive, got ${lockAmount}`);
|
|
2736
|
+
}
|
|
2737
|
+
await ensureCorrectChain(networkConfig.chainId);
|
|
2738
|
+
}
|
|
1963
2739
|
emitDebug("intent:create-request", {
|
|
1964
2740
|
tokenId,
|
|
1965
2741
|
chainId: token.chainId,
|
|
1966
2742
|
currencyCode,
|
|
1967
2743
|
baseCurrencyCode: baseCurrencyCode ?? null,
|
|
1968
2744
|
baseCurrencyAmount: baseCurrencyAmount ?? null,
|
|
2745
|
+
quoteCurrencyAmount: quoteCurrencyAmount ?? null,
|
|
1969
2746
|
depositAddress
|
|
1970
2747
|
});
|
|
1971
2748
|
const record = await executePrivateRead(
|
|
@@ -1978,6 +2755,28 @@ function useFiatOnRamp(options) {
|
|
|
1978
2755
|
base_currency_amount: baseCurrencyAmount
|
|
1979
2756
|
})
|
|
1980
2757
|
);
|
|
2758
|
+
if (postDepositLock && address && walletClient && lockAmount !== void 0) {
|
|
2759
|
+
const signingWalletClient = await getWalletClient3(wagmiConfig, {
|
|
2760
|
+
chainId: networkConfig.chainId
|
|
2761
|
+
});
|
|
2762
|
+
const signedLock = await createSignedLockRequest({
|
|
2763
|
+
client,
|
|
2764
|
+
walletClient: signingWalletClient,
|
|
2765
|
+
userAddress: address,
|
|
2766
|
+
networkConfig,
|
|
2767
|
+
serviceAddress: requireServiceAddress(postDepositLock.serviceAddress ?? serviceAddress),
|
|
2768
|
+
tokenId,
|
|
2769
|
+
amount: lockAmount,
|
|
2770
|
+
lockDuration: postDepositLock.lockDuration
|
|
2771
|
+
});
|
|
2772
|
+
savePendingLock(address, record.transaction_id, signedLock);
|
|
2773
|
+
lockOwnerRef.current = address;
|
|
2774
|
+
emitDebug("intent:lock-signed", {
|
|
2775
|
+
transactionId: record.transaction_id,
|
|
2776
|
+
amount: signedLock.amount,
|
|
2777
|
+
expiry: signedLock.expiry
|
|
2778
|
+
});
|
|
2779
|
+
}
|
|
1981
2780
|
activeIntentIdRef.current = record.transaction_id;
|
|
1982
2781
|
setActiveIntentId(record.transaction_id);
|
|
1983
2782
|
emitDebug("intent:create-success", {
|
|
@@ -1993,7 +2792,21 @@ function useFiatOnRamp(options) {
|
|
|
1993
2792
|
throw e;
|
|
1994
2793
|
}
|
|
1995
2794
|
},
|
|
1996
|
-
[
|
|
2795
|
+
[
|
|
2796
|
+
address,
|
|
2797
|
+
client,
|
|
2798
|
+
depositAddress,
|
|
2799
|
+
emitDebug,
|
|
2800
|
+
enabledTokens,
|
|
2801
|
+
ensureCorrectChain,
|
|
2802
|
+
executePrivateRead,
|
|
2803
|
+
networkConfig,
|
|
2804
|
+
postDepositLock,
|
|
2805
|
+
serviceAddress,
|
|
2806
|
+
tokenId,
|
|
2807
|
+
wagmiConfig,
|
|
2808
|
+
walletClient
|
|
2809
|
+
]
|
|
1997
2810
|
);
|
|
1998
2811
|
const registerOnRampTokenMapping = useCallback(
|
|
1999
2812
|
async (moonpayTransactionId) => {
|
|
@@ -2115,6 +2928,12 @@ function useFiatOnRamp(options) {
|
|
|
2115
2928
|
});
|
|
2116
2929
|
return;
|
|
2117
2930
|
}
|
|
2931
|
+
const supersededKey = activeVerificationKeyRef.current;
|
|
2932
|
+
if (supersededKey && supersededKey !== verificationKey) {
|
|
2933
|
+
triggeredVerificationKeysRef.current.delete(supersededKey);
|
|
2934
|
+
}
|
|
2935
|
+
activeVerificationDoneRef.current?.();
|
|
2936
|
+
activeVerificationDoneRef.current = null;
|
|
2118
2937
|
triggeredVerificationKeysRef.current.add(verificationKey);
|
|
2119
2938
|
activeVerificationKeyRef.current = verificationKey;
|
|
2120
2939
|
activeVerificationRecordRef.current = record;
|
|
@@ -2165,6 +2984,7 @@ function useFiatOnRamp(options) {
|
|
|
2165
2984
|
`Delivered amount (${record.quote_currency_amount}) is below the minimum deposit.`
|
|
2166
2985
|
);
|
|
2167
2986
|
}
|
|
2987
|
+
activeVerificationAmountRef.current = amount;
|
|
2168
2988
|
if (activeIntentIdRef.current === record.transaction_id) {
|
|
2169
2989
|
setStatus("verifying");
|
|
2170
2990
|
}
|
|
@@ -2183,6 +3003,7 @@ function useFiatOnRamp(options) {
|
|
|
2183
3003
|
if (activeVerificationKeyRef.current === verificationKey) {
|
|
2184
3004
|
activeVerificationKeyRef.current = null;
|
|
2185
3005
|
activeVerificationRecordRef.current = null;
|
|
3006
|
+
activeVerificationAmountRef.current = null;
|
|
2186
3007
|
setActiveVerificationId(null);
|
|
2187
3008
|
}
|
|
2188
3009
|
throw err;
|
|
@@ -2241,6 +3062,7 @@ function useFiatOnRamp(options) {
|
|
|
2241
3062
|
previousStatus,
|
|
2242
3063
|
transactionId
|
|
2243
3064
|
});
|
|
3065
|
+
if (address) clearPendingLock(address, transactionId);
|
|
2244
3066
|
await refreshPending();
|
|
2245
3067
|
if (previousStatus === "awaiting-purchase" || previousStatus === "awaiting-delivery") {
|
|
2246
3068
|
setStatus("idle");
|
|
@@ -2271,7 +3093,7 @@ function useFiatOnRamp(options) {
|
|
|
2271
3093
|
} finally {
|
|
2272
3094
|
closeReconcilePromiseRef.current = null;
|
|
2273
3095
|
}
|
|
2274
|
-
}, [emitDebug, refreshPending, triggerVerification, waitForOnChainHash]);
|
|
3096
|
+
}, [address, emitDebug, refreshPending, triggerVerification, waitForOnChainHash]);
|
|
2275
3097
|
const finishPendingVerification = useCallback(
|
|
2276
3098
|
async (record) => {
|
|
2277
3099
|
try {
|
|
@@ -2305,6 +3127,12 @@ function useFiatOnRamp(options) {
|
|
|
2305
3127
|
try {
|
|
2306
3128
|
await triggerVerificationRef.current(record);
|
|
2307
3129
|
} catch {
|
|
3130
|
+
continue;
|
|
3131
|
+
}
|
|
3132
|
+
if (activeVerificationKeyRef.current === key) {
|
|
3133
|
+
await new Promise((resolve) => {
|
|
3134
|
+
activeVerificationDoneRef.current = resolve;
|
|
3135
|
+
});
|
|
2308
3136
|
}
|
|
2309
3137
|
}
|
|
2310
3138
|
})();
|
|
@@ -2421,6 +3249,12 @@ function matchesOnRampTransaction(record, transactionId) {
|
|
|
2421
3249
|
function getOnRampVerificationKey(record) {
|
|
2422
3250
|
return record.on_chain_tx_hash ?? record.transaction_id;
|
|
2423
3251
|
}
|
|
3252
|
+
function requireServiceAddress(serviceAddress) {
|
|
3253
|
+
if (!serviceAddress) {
|
|
3254
|
+
throw new Error("Service address not configured");
|
|
3255
|
+
}
|
|
3256
|
+
return serviceAddress;
|
|
3257
|
+
}
|
|
2424
3258
|
function summariseMoonPayEventProps(props) {
|
|
2425
3259
|
return {
|
|
2426
3260
|
id: props.id,
|
|
@@ -2478,6 +3312,7 @@ function useMoonPayBuyWidget({
|
|
|
2478
3312
|
colorCode,
|
|
2479
3313
|
baseCurrencyCode,
|
|
2480
3314
|
baseCurrencyAmount,
|
|
3315
|
+
quoteCurrencyAmount,
|
|
2481
3316
|
lockAmount,
|
|
2482
3317
|
paymentMethod,
|
|
2483
3318
|
currencyCode,
|
|
@@ -2537,6 +3372,7 @@ function useMoonPayBuyWidget({
|
|
|
2537
3372
|
overlayNode,
|
|
2538
3373
|
baseCurrencyCode,
|
|
2539
3374
|
baseCurrencyAmount,
|
|
3375
|
+
quoteCurrencyAmount,
|
|
2540
3376
|
lockAmount: lockAmount ? "true" : void 0,
|
|
2541
3377
|
paymentMethod,
|
|
2542
3378
|
currencyCode,
|
|
@@ -2562,6 +3398,7 @@ function useMoonPayBuyWidget({
|
|
|
2562
3398
|
overlayNode,
|
|
2563
3399
|
baseCurrencyCode,
|
|
2564
3400
|
baseCurrencyAmount,
|
|
3401
|
+
quoteCurrencyAmount,
|
|
2565
3402
|
lockAmount,
|
|
2566
3403
|
paymentMethod,
|
|
2567
3404
|
currencyCode,
|
|
@@ -2580,6 +3417,7 @@ function FiatOnRampForm({
|
|
|
2580
3417
|
currencyCode,
|
|
2581
3418
|
baseCurrencyCode = "usd",
|
|
2582
3419
|
defaultBaseCurrencyAmount = "100",
|
|
3420
|
+
quoteCurrencyAmount,
|
|
2583
3421
|
tokenSymbol,
|
|
2584
3422
|
theme,
|
|
2585
3423
|
themeId,
|
|
@@ -2588,7 +3426,10 @@ function FiatOnRampForm({
|
|
|
2588
3426
|
autoStart = false,
|
|
2589
3427
|
lockAmount,
|
|
2590
3428
|
paymentMethod,
|
|
3429
|
+
postDepositLock,
|
|
2591
3430
|
onCredited,
|
|
3431
|
+
onLockSubmitted,
|
|
3432
|
+
onLockFailed,
|
|
2592
3433
|
onError,
|
|
2593
3434
|
onDebugEvent
|
|
2594
3435
|
}) {
|
|
@@ -2596,6 +3437,8 @@ function FiatOnRampForm({
|
|
|
2596
3437
|
const [visible, setVisible] = useState(false);
|
|
2597
3438
|
const [isPreparing, setIsPreparing] = useState(false);
|
|
2598
3439
|
const [rowError, setRowError] = useState(null);
|
|
3440
|
+
const [lockError, setLockError] = useState(null);
|
|
3441
|
+
const [lockSettled, setLockSettled] = useState(false);
|
|
2599
3442
|
const {
|
|
2600
3443
|
status,
|
|
2601
3444
|
activeIntentId,
|
|
@@ -2613,7 +3456,25 @@ function FiatOnRampForm({
|
|
|
2613
3456
|
finishPendingVerification,
|
|
2614
3457
|
handleWidgetClosed,
|
|
2615
3458
|
refreshPending
|
|
2616
|
-
} = useFiatOnRamp({
|
|
3459
|
+
} = useFiatOnRamp({
|
|
3460
|
+
tokenId,
|
|
3461
|
+
postDepositLock,
|
|
3462
|
+
onCredited,
|
|
3463
|
+
// Lock callbacks aren't intent-keyed, so a resumed background row's lock
|
|
3464
|
+
// can settle these flags while a newer purchase is still locking — a
|
|
3465
|
+
// transient overpromise that the newer lock's own outcome then corrects.
|
|
3466
|
+
onLockSubmitted: (response) => {
|
|
3467
|
+
setLockError(null);
|
|
3468
|
+
setLockSettled(true);
|
|
3469
|
+
onLockSubmitted?.(response);
|
|
3470
|
+
},
|
|
3471
|
+
onLockFailed: (err) => {
|
|
3472
|
+
setLockError(err.message);
|
|
3473
|
+
onLockFailed?.(err);
|
|
3474
|
+
},
|
|
3475
|
+
onError,
|
|
3476
|
+
onDebugEvent
|
|
3477
|
+
});
|
|
2617
3478
|
const decimals = selectedToken?.decimals;
|
|
2618
3479
|
const displaySymbol = tokenSymbol ?? selectedToken?.symbol ?? currencyCode.toUpperCase();
|
|
2619
3480
|
const emitFormDebug = useCallback(
|
|
@@ -2629,8 +3490,17 @@ function FiatOnRampForm({
|
|
|
2629
3490
|
[onDebugEvent, status, tokenId]
|
|
2630
3491
|
);
|
|
2631
3492
|
const minFiatGate = minDepositBaseUnits !== void 0 && decimals !== void 0 ? Number(formatUnits(minDepositBaseUnits, decimals)) * 1.05 : void 0;
|
|
2632
|
-
const
|
|
3493
|
+
const { units: quoteBaseUnits, failed: quoteParseFailed } = (() => {
|
|
3494
|
+
if (!quoteCurrencyAmount || decimals === void 0) return { units: void 0, failed: false };
|
|
3495
|
+
try {
|
|
3496
|
+
return { units: parseUnits(quoteCurrencyAmount, decimals), failed: false };
|
|
3497
|
+
} catch {
|
|
3498
|
+
return { units: void 0, failed: true };
|
|
3499
|
+
}
|
|
3500
|
+
})();
|
|
3501
|
+
const isBelowMin = quoteBaseUnits !== void 0 && minDepositBaseUnits !== void 0 ? quoteBaseUnits < minDepositBaseUnits : minFiatGate !== void 0 && Number(defaultBaseCurrencyAmount) < minFiatGate;
|
|
2633
3502
|
const isBusy = isPreparing || status === "awaiting-purchase";
|
|
3503
|
+
const lockPending = !!postDepositLock && status === "credited" && !lockSettled && !lockError;
|
|
2634
3504
|
const isInitializing = !!address && !depositAddress;
|
|
2635
3505
|
const isPrePurchase = status === "idle" || status === "awaiting-purchase";
|
|
2636
3506
|
const isVerifying = status === "awaiting-delivery" || status === "verifying";
|
|
@@ -2640,9 +3510,10 @@ function FiatOnRampForm({
|
|
|
2640
3510
|
!depositAddress ? "deposit-address-not-loaded" : null,
|
|
2641
3511
|
isBusy ? `busy:${isPreparing ? "preparing" : status}` : null,
|
|
2642
3512
|
visible ? "widget-open" : null,
|
|
2643
|
-
isBelowMin ? "below-minimum" : null
|
|
3513
|
+
isBelowMin ? "below-minimum" : null,
|
|
3514
|
+
quoteParseFailed ? "invalid-quote-amount" : null
|
|
2644
3515
|
].filter((reason) => Boolean(reason)),
|
|
2645
|
-
[address, depositAddress, isBelowMin, isBusy, isPreparing, status, visible]
|
|
3516
|
+
[address, depositAddress, isBelowMin, isBusy, isPreparing, quoteParseFailed, status, visible]
|
|
2646
3517
|
);
|
|
2647
3518
|
const canBuy = blockReasons.length === 0;
|
|
2648
3519
|
const handleOpen = useCallback(async () => {
|
|
@@ -2661,6 +3532,8 @@ function FiatOnRampForm({
|
|
|
2661
3532
|
return;
|
|
2662
3533
|
}
|
|
2663
3534
|
setIsPreparing(true);
|
|
3535
|
+
setLockError(null);
|
|
3536
|
+
setLockSettled(false);
|
|
2664
3537
|
emitFormDebug("form:open-click", {
|
|
2665
3538
|
currencyCode,
|
|
2666
3539
|
tokenSymbol: displaySymbol,
|
|
@@ -2674,7 +3547,8 @@ function FiatOnRampForm({
|
|
|
2674
3547
|
const intent = await prepareOnRampIntent({
|
|
2675
3548
|
currencyCode,
|
|
2676
3549
|
baseCurrencyCode,
|
|
2677
|
-
baseCurrencyAmount: defaultBaseCurrencyAmount
|
|
3550
|
+
baseCurrencyAmount: defaultBaseCurrencyAmount,
|
|
3551
|
+
quoteCurrencyAmount
|
|
2678
3552
|
});
|
|
2679
3553
|
emitFormDebug("form:intent-ready", {
|
|
2680
3554
|
transactionId: intent.transaction_id,
|
|
@@ -2699,6 +3573,7 @@ function FiatOnRampForm({
|
|
|
2699
3573
|
decimals,
|
|
2700
3574
|
displaySymbol,
|
|
2701
3575
|
defaultBaseCurrencyAmount,
|
|
3576
|
+
quoteCurrencyAmount,
|
|
2702
3577
|
depositAddress,
|
|
2703
3578
|
emitFormDebug,
|
|
2704
3579
|
prepareOnRampIntent,
|
|
@@ -2729,6 +3604,7 @@ function FiatOnRampForm({
|
|
|
2729
3604
|
colorCode,
|
|
2730
3605
|
baseCurrencyCode,
|
|
2731
3606
|
baseCurrencyAmount: defaultBaseCurrencyAmount,
|
|
3607
|
+
quoteCurrencyAmount,
|
|
2732
3608
|
lockAmount,
|
|
2733
3609
|
paymentMethod,
|
|
2734
3610
|
currencyCode,
|
|
@@ -2801,7 +3677,7 @@ function FiatOnRampForm({
|
|
|
2801
3677
|
);
|
|
2802
3678
|
})
|
|
2803
3679
|
] }),
|
|
2804
|
-
status === "credited" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 py-8 text-center", children: [
|
|
3680
|
+
status === "credited" && !lockPending && !lockError && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 py-8 text-center", children: [
|
|
2805
3681
|
/* @__PURE__ */ jsx(CircleCheckIcon, { className: "text-primary size-8", "aria-hidden": true }),
|
|
2806
3682
|
/* @__PURE__ */ jsx("p", { className: "text-foreground text-sm font-medium", children: "Purchase credited" }),
|
|
2807
3683
|
/* @__PURE__ */ jsxs("p", { className: "text-muted-foreground text-sm", children: [
|
|
@@ -2810,12 +3686,20 @@ function FiatOnRampForm({
|
|
|
2810
3686
|
" deposit is now available in your balance."
|
|
2811
3687
|
] })
|
|
2812
3688
|
] }),
|
|
3689
|
+
lockPending && /* @__PURE__ */ jsxs("p", { className: "text-muted-foreground flex items-center gap-2 text-sm", children: [
|
|
3690
|
+
/* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin", "aria-hidden": true }),
|
|
3691
|
+
"Purchase credited \u2014 locking your funds\u2026"
|
|
3692
|
+
] }),
|
|
2813
3693
|
autoStart ? !visible && isPrePurchase && /* @__PURE__ */ jsx(Skeleton, { className: "h-[656px] w-full rounded-md" }) : isInitializing ? /* @__PURE__ */ jsx(Skeleton, { className: "h-9 w-full rounded-md" }) : /* @__PURE__ */ jsxs(Button, { type: "button", onClick: handleOpen, disabled: !canBuy, children: [
|
|
2814
3694
|
(isBusy || visible) && /* @__PURE__ */ jsx(Loader2, { className: "animate-spin", "aria-hidden": true }),
|
|
2815
3695
|
"Buy"
|
|
2816
3696
|
] }),
|
|
2817
3697
|
widgetElement,
|
|
2818
3698
|
error && /* @__PURE__ */ jsx("p", { className: "text-destructive text-sm", role: "alert", children: error.message }),
|
|
3699
|
+
lockError && /* @__PURE__ */ jsxs("p", { className: "text-destructive text-sm", role: "alert", children: [
|
|
3700
|
+
"Purchase credited to your account, but locking the funds to a service failed: ",
|
|
3701
|
+
lockError
|
|
3702
|
+
] }),
|
|
2819
3703
|
isBelowMin && minFiatGate !== void 0 && /* @__PURE__ */ jsxs("p", { className: "text-destructive text-sm", role: "alert", children: [
|
|
2820
3704
|
"Minimum purchase is ~$",
|
|
2821
3705
|
minFiatGate.toFixed(2),
|
|
@@ -2833,6 +3717,6 @@ function parseFinalityProgress(message) {
|
|
|
2833
3717
|
return match ? `${match[1]} confirmations` : null;
|
|
2834
3718
|
}
|
|
2835
3719
|
|
|
2836
|
-
export { AccountingApiError, Button, FiatOnRampForm, HOSTED_AUTH_CLOCK_SKEW_MS, HostedAuthError, HostedAuthRequiredError, HostedAuthStateMismatchError, HttpClient, NETWORK_CONFIG, NetworkError, PrivanaClient, PrivanaProvider, SUPPORTED_CHAINS, SiweAuthProvider, Skeleton, ValidationError, applyRefreshResponse, buildHostedAuthSession, buildSiweStatement, buttonVariants, clearHostedAuthPendingTransaction, cn, createHostedAuthPendingStorageKey, createHostedAuthState, createHostedAuthStorageKey, createPkceChallenge, createPkceVerifier, formatTimeRemaining, formatTokenAmount, getAccountingContract, getApiUrl, getChainById, getChainId,
|
|
2837
|
-
//# sourceMappingURL=chunk-
|
|
2838
|
-
//# sourceMappingURL=chunk-
|
|
3720
|
+
export { AccountingApiError, Button, DEFAULT_LOCK_DURATION_SECONDS, DEFAULT_ONRAMP_LOCK_BUFFER, FiatOnRampForm, 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, canUseBrowserStorage, clampLockAmount, clearHostedAuthPendingTransaction, clearPendingLock, cn, createDomain, createHostedAuthPendingStorageKey, createHostedAuthState, createHostedAuthStorageKey, createLockExpiry, createPkceChallenge, createPkceVerifier, createSignedLockRequest, formatCountdown, formatTimeRemaining, formatTokenAmount, getAccountingContract, getApiUrl, getBlockNumber, getBrowserStorageItem, getChainById, getChainId, getExplorerAddressUrl, getExplorerLabel, getTransactionReceipt, getWalletClient3 as getWalletClient, isHostedAuthRefreshActive, isHostedAuthSessionActive, isSignedLockUsable, loadPendingLock, normalizeAddress, normalizeHex, parseHostedAuthCallback, parseTokenAmount, persistHostedAuthPendingTransaction, readHostedAuthPendingTransaction, readStoredHostedAuthSession, removeBrowserStorageItem, savePendingLock, setBrowserStorageItem, shortenAddress, signLockMessage, signModifyLockMessage, signTransferLockedMessage, signTransferMessage, signWithdrawFromLockMessage, signWithdrawMessage, stripHostedAuthCallbackParams, submitPendingLock, syncHostedAuthSessionToClient, useDepositVerification, useEnsureCorrectChain, useFiatOnRamp, usePrivanaContext, usePrivateReadRequest, useSafeAccount, useSafePrivanaContext, useSiweAuth, waitForTransactionReceipt };
|
|
3721
|
+
//# sourceMappingURL=chunk-ZVUMV4NR.js.map
|
|
3722
|
+
//# sourceMappingURL=chunk-ZVUMV4NR.js.map
|