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