@oasisprotocol/privana-sdk 0.5.0 → 0.5.1
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-4IW4V7YJ.cjs} +929 -20
- package/dist/chunk-4IW4V7YJ.cjs.map +1 -0
- package/dist/{chunk-54FC6TO3.js → chunk-SAJ7K5WT.js} +900 -22
- package/dist/chunk-SAJ7K5WT.js.map +1 -0
- package/dist/index.cjs +711 -506
- 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 +56 -339
- package/dist/index.d.ts +56 -339
- package/dist/index.js +419 -301
- 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,198 @@ 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
|
+
|
|
1705
2313
|
// ../../node_modules/@wagmi/core/dist/esm/actions/getChainId.js
|
|
1706
2314
|
function getChainId2(config) {
|
|
1707
2315
|
return config.state.chainId;
|
|
@@ -1712,6 +2320,10 @@ async function getTransactionReceipt(config, parameters) {
|
|
|
1712
2320
|
const action = getAction(client, actions$1.getTransactionReceipt, "getTransactionReceipt");
|
|
1713
2321
|
return action(rest);
|
|
1714
2322
|
}
|
|
2323
|
+
async function getWalletClient3(config, parameters = {}) {
|
|
2324
|
+
const client = await getConnectorClient(config, parameters);
|
|
2325
|
+
return client.extend(viem.walletActions);
|
|
2326
|
+
}
|
|
1715
2327
|
async function waitForTransactionReceipt(config, parameters) {
|
|
1716
2328
|
const { chainId, timeout = 0, ...rest } = parameters;
|
|
1717
2329
|
const client = config.getClient({ chainId });
|
|
@@ -1739,6 +2351,59 @@ async function waitForTransactionReceipt(config, parameters) {
|
|
|
1739
2351
|
chainId: client.chain.id
|
|
1740
2352
|
};
|
|
1741
2353
|
}
|
|
2354
|
+
function useEnsureCorrectChain() {
|
|
2355
|
+
const config = wagmi.useConfig();
|
|
2356
|
+
const chainId = wagmi.useChainId();
|
|
2357
|
+
const { switchChainAsync } = wagmi.useSwitchChain();
|
|
2358
|
+
const waitUntilOnChain = react.useCallback(
|
|
2359
|
+
async (expectedChainId, timeoutMs, pollIntervalMs = 250) => {
|
|
2360
|
+
const startedAt = Date.now();
|
|
2361
|
+
while (Date.now() - startedAt < timeoutMs) {
|
|
2362
|
+
const currentChainId = getChainId2(config);
|
|
2363
|
+
if (currentChainId === expectedChainId) return true;
|
|
2364
|
+
await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
|
|
2365
|
+
}
|
|
2366
|
+
return false;
|
|
2367
|
+
},
|
|
2368
|
+
[config]
|
|
2369
|
+
);
|
|
2370
|
+
const ensureCorrectChain = react.useCallback(
|
|
2371
|
+
async (targetChainId) => {
|
|
2372
|
+
const currentChainId = getChainId2(config);
|
|
2373
|
+
if (currentChainId === targetChainId) return false;
|
|
2374
|
+
let switchErrorMessage;
|
|
2375
|
+
try {
|
|
2376
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
2377
|
+
setTimeout(() => reject(new Error("Chain switch timeout")), 3e3);
|
|
2378
|
+
});
|
|
2379
|
+
await Promise.race([switchChainAsync({ chainId: targetChainId }), timeoutPromise]);
|
|
2380
|
+
} catch (error) {
|
|
2381
|
+
if (error instanceof Error && error.message.includes("Unsupported Chain")) {
|
|
2382
|
+
console.warn("Got 'Unsupported Chain' error, chain may have switched anyway.");
|
|
2383
|
+
} else {
|
|
2384
|
+
switchErrorMessage = error instanceof Error ? error.message : "Unknown chain switch error";
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
const settled = await waitUntilOnChain(targetChainId, 2e4);
|
|
2388
|
+
if (settled) return true;
|
|
2389
|
+
if (switchErrorMessage) {
|
|
2390
|
+
throw new Error(
|
|
2391
|
+
`Failed to switch to chain (Chain ID: ${targetChainId}): ${switchErrorMessage}`
|
|
2392
|
+
);
|
|
2393
|
+
}
|
|
2394
|
+
throw new Error(`Chain switch did not settle in time (expected ${targetChainId}).`);
|
|
2395
|
+
},
|
|
2396
|
+
[config, switchChainAsync, waitUntilOnChain]
|
|
2397
|
+
);
|
|
2398
|
+
const isOnChain = react.useCallback((targetChainId) => chainId === targetChainId, [chainId]);
|
|
2399
|
+
return {
|
|
2400
|
+
chainId,
|
|
2401
|
+
ensureCorrectChain,
|
|
2402
|
+
isOnChain
|
|
2403
|
+
};
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
// src/sdk/hooks/use-fiat-on-ramp.ts
|
|
1742
2407
|
var DEFAULT_DELIVERY_TIMEOUT_MS = 12e4;
|
|
1743
2408
|
var DEFAULT_VERIFICATION_TIMEOUT_MS = 10 * 6e4;
|
|
1744
2409
|
var DEFAULT_FINALITY_RETRY_INTERVAL_MS = 15e3;
|
|
@@ -1746,14 +2411,26 @@ var ERC20_TRANSFER_EVENT = viem.parseAbiItem(
|
|
|
1746
2411
|
"event Transfer(address indexed from, address indexed to, uint256 value)"
|
|
1747
2412
|
);
|
|
1748
2413
|
function useFiatOnRamp(options) {
|
|
1749
|
-
const {
|
|
2414
|
+
const {
|
|
2415
|
+
tokenId,
|
|
2416
|
+
postDepositLock,
|
|
2417
|
+
onCredited,
|
|
2418
|
+
onLockSubmitted,
|
|
2419
|
+
onLockFailed,
|
|
2420
|
+
onError,
|
|
2421
|
+
onDebugEvent
|
|
2422
|
+
} = options;
|
|
1750
2423
|
const deliveryTimeout = options.deliveryTimeout ?? DEFAULT_DELIVERY_TIMEOUT_MS;
|
|
1751
2424
|
const deliveryPollInterval = options.deliveryPollInterval ?? 3e3;
|
|
1752
2425
|
const verificationTimeout = options.verificationTimeout ?? DEFAULT_VERIFICATION_TIMEOUT_MS;
|
|
1753
2426
|
const finalityRetryInterval = options.finalityRetryInterval ?? DEFAULT_FINALITY_RETRY_INTERVAL_MS;
|
|
1754
|
-
const {
|
|
2427
|
+
const { address } = wagmi.useAccount();
|
|
2428
|
+
const { data: walletClient } = wagmi.useWalletClient();
|
|
2429
|
+
const { client, enabledTokens, networkConfig, serviceAddress } = usePrivanaContext();
|
|
1755
2430
|
const { executePrivateRead, privateReadReady } = usePrivateReadRequest();
|
|
2431
|
+
const { ensureCorrectChain } = useEnsureCorrectChain();
|
|
1756
2432
|
const wagmiConfig = wagmi.useConfig();
|
|
2433
|
+
const queryClient = reactQuery.useQueryClient();
|
|
1757
2434
|
const selectedToken = enabledTokens.find((t) => t.id.toLowerCase() === tokenId.toLowerCase());
|
|
1758
2435
|
const [status, setStatus] = react.useState("idle");
|
|
1759
2436
|
const [pending, setPending] = react.useState([]);
|
|
@@ -1764,20 +2441,27 @@ function useFiatOnRamp(options) {
|
|
|
1764
2441
|
const [activeVerificationId, setActiveVerificationId] = react.useState(null);
|
|
1765
2442
|
const [finalityProgress, setFinalityProgress] = react.useState({});
|
|
1766
2443
|
const onCreditedRef = react.useRef(onCredited);
|
|
2444
|
+
const onLockSubmittedRef = react.useRef(onLockSubmitted);
|
|
2445
|
+
const onLockFailedRef = react.useRef(onLockFailed);
|
|
1767
2446
|
const onErrorRef = react.useRef(onError);
|
|
1768
2447
|
const onDebugEventRef = react.useRef(onDebugEvent);
|
|
1769
2448
|
const statusRef = react.useRef(status);
|
|
1770
2449
|
const activeIntentIdRef = react.useRef(null);
|
|
1771
2450
|
const activeVerificationRecordRef = react.useRef(null);
|
|
1772
2451
|
const activeVerificationKeyRef = react.useRef(null);
|
|
2452
|
+
const activeVerificationAmountRef = react.useRef(null);
|
|
2453
|
+
const lockOwnerRef = react.useRef(null);
|
|
1773
2454
|
const triggeredVerificationKeysRef = react.useRef(/* @__PURE__ */ new Set());
|
|
2455
|
+
const activeVerificationDoneRef = react.useRef(null);
|
|
1774
2456
|
const closeReconcilePromiseRef = react.useRef(null);
|
|
1775
2457
|
const purchaseInitiatedRef = react.useRef(false);
|
|
1776
2458
|
react.useEffect(() => {
|
|
1777
2459
|
onCreditedRef.current = onCredited;
|
|
2460
|
+
onLockSubmittedRef.current = onLockSubmitted;
|
|
2461
|
+
onLockFailedRef.current = onLockFailed;
|
|
1778
2462
|
onErrorRef.current = onError;
|
|
1779
2463
|
onDebugEventRef.current = onDebugEvent;
|
|
1780
|
-
}, [onCredited, onError, onDebugEvent]);
|
|
2464
|
+
}, [onCredited, onLockSubmitted, onLockFailed, onError, onDebugEvent]);
|
|
1781
2465
|
react.useEffect(() => {
|
|
1782
2466
|
statusRef.current = status;
|
|
1783
2467
|
}, [status]);
|
|
@@ -1858,13 +2542,64 @@ function useFiatOnRamp(options) {
|
|
|
1858
2542
|
react.useEffect(() => {
|
|
1859
2543
|
refreshPending();
|
|
1860
2544
|
}, [refreshPending]);
|
|
1861
|
-
const clearActiveVerification = react.useCallback(() => {
|
|
2545
|
+
const clearActiveVerification = react.useCallback((expectedKey) => {
|
|
1862
2546
|
const key = activeVerificationKeyRef.current;
|
|
2547
|
+
if (expectedKey != null && key !== null && key !== expectedKey) return;
|
|
1863
2548
|
if (key) triggeredVerificationKeysRef.current.delete(key);
|
|
1864
2549
|
activeVerificationKeyRef.current = null;
|
|
1865
2550
|
activeVerificationRecordRef.current = null;
|
|
2551
|
+
activeVerificationAmountRef.current = null;
|
|
1866
2552
|
setActiveVerificationId(null);
|
|
2553
|
+
activeVerificationDoneRef.current?.();
|
|
2554
|
+
activeVerificationDoneRef.current = null;
|
|
1867
2555
|
}, []);
|
|
2556
|
+
const submitPendingLockAfterCredit = react.useCallback(
|
|
2557
|
+
async (transactionId, userAddress) => {
|
|
2558
|
+
const signedLock = loadPendingLock(userAddress, transactionId);
|
|
2559
|
+
if (!signedLock) {
|
|
2560
|
+
clearPendingLock(userAddress, transactionId);
|
|
2561
|
+
if (!postDepositLock || transactionId !== activeIntentIdRef.current) return;
|
|
2562
|
+
const error2 = new PostDepositLockError(
|
|
2563
|
+
"No persisted signed lock found for this on-ramp",
|
|
2564
|
+
"not-found"
|
|
2565
|
+
);
|
|
2566
|
+
emitDebug("lock:not-found", { transactionId });
|
|
2567
|
+
(onLockFailedRef.current ?? onErrorRef.current)?.(error2);
|
|
2568
|
+
return;
|
|
2569
|
+
}
|
|
2570
|
+
const creditedAmount = activeVerificationAmountRef.current ?? void 0;
|
|
2571
|
+
try {
|
|
2572
|
+
const result = await submitPendingLock({ client, payload: signedLock, creditedAmount });
|
|
2573
|
+
queryClient.invalidateQueries({ queryKey: ["accounting-balance"] });
|
|
2574
|
+
queryClient.invalidateQueries({ queryKey: ["accounting-locked-funds"] });
|
|
2575
|
+
queryClient.invalidateQueries({ queryKey: ["accounting-total-locked-balance"] });
|
|
2576
|
+
queryClient.invalidateQueries({ queryKey: ["accounting-history"] });
|
|
2577
|
+
emitDebug("lock:submitted", {
|
|
2578
|
+
transactionId,
|
|
2579
|
+
amount: signedLock.amount,
|
|
2580
|
+
submissionId: result.submission_id
|
|
2581
|
+
});
|
|
2582
|
+
onLockSubmittedRef.current?.(result);
|
|
2583
|
+
} catch (err) {
|
|
2584
|
+
const error2 = err instanceof PostDepositLockError ? err : new PostDepositLockError(
|
|
2585
|
+
err instanceof Error ? err.message : "Lock submission failed",
|
|
2586
|
+
"submission-failed",
|
|
2587
|
+
BigInt(signedLock.amount),
|
|
2588
|
+
creditedAmount,
|
|
2589
|
+
{ cause: err }
|
|
2590
|
+
);
|
|
2591
|
+
emitDebug("lock:failed", {
|
|
2592
|
+
transactionId,
|
|
2593
|
+
reason: error2.reason,
|
|
2594
|
+
message: error2.message
|
|
2595
|
+
});
|
|
2596
|
+
(onLockFailedRef.current ?? onErrorRef.current)?.(error2);
|
|
2597
|
+
} finally {
|
|
2598
|
+
clearPendingLock(userAddress, transactionId);
|
|
2599
|
+
}
|
|
2600
|
+
},
|
|
2601
|
+
[client, emitDebug, postDepositLock, queryClient]
|
|
2602
|
+
);
|
|
1868
2603
|
const { verify } = useDepositVerification({
|
|
1869
2604
|
pollTimeout: verificationTimeout,
|
|
1870
2605
|
pollInterval: options.verificationPollInterval,
|
|
@@ -1880,6 +2615,7 @@ function useFiatOnRamp(options) {
|
|
|
1880
2615
|
},
|
|
1881
2616
|
onCredited: (depositTxHash) => {
|
|
1882
2617
|
const record = activeVerificationRecordRef.current;
|
|
2618
|
+
const verificationKey = record ? getOnRampVerificationKey(record) : null;
|
|
1883
2619
|
emitDebug("verification:credited", {
|
|
1884
2620
|
depositTxHash,
|
|
1885
2621
|
record: record ? summariseOnRampRecord(record) : null
|
|
@@ -1894,6 +2630,18 @@ function useFiatOnRamp(options) {
|
|
|
1894
2630
|
delete next[record.transaction_id];
|
|
1895
2631
|
return next;
|
|
1896
2632
|
});
|
|
2633
|
+
const lockOwner = lockOwnerRef.current ?? address;
|
|
2634
|
+
if (lockOwner) {
|
|
2635
|
+
void submitPendingLockAfterCredit(record.transaction_id, lockOwner);
|
|
2636
|
+
} else if (postDepositLock) {
|
|
2637
|
+
emitDebug("lock:owner-unavailable", { transactionId: record.transaction_id });
|
|
2638
|
+
(onLockFailedRef.current ?? onErrorRef.current)?.(
|
|
2639
|
+
new PostDepositLockError(
|
|
2640
|
+
"No wallet address available to look up the signed lock for this on-ramp",
|
|
2641
|
+
"not-found"
|
|
2642
|
+
)
|
|
2643
|
+
);
|
|
2644
|
+
}
|
|
1897
2645
|
}
|
|
1898
2646
|
void (async () => {
|
|
1899
2647
|
try {
|
|
@@ -1916,7 +2664,7 @@ function useFiatOnRamp(options) {
|
|
|
1916
2664
|
console.warn("Failed to mark on-ramp row complete:", err);
|
|
1917
2665
|
} finally {
|
|
1918
2666
|
await refreshPending();
|
|
1919
|
-
clearActiveVerification();
|
|
2667
|
+
clearActiveVerification(verificationKey);
|
|
1920
2668
|
if (record && activeIntentIdRef.current === record.transaction_id) {
|
|
1921
2669
|
activeIntentIdRef.current = null;
|
|
1922
2670
|
setActiveIntentId(null);
|
|
@@ -1954,7 +2702,8 @@ function useFiatOnRamp(options) {
|
|
|
1954
2702
|
async ({
|
|
1955
2703
|
currencyCode,
|
|
1956
2704
|
baseCurrencyCode,
|
|
1957
|
-
baseCurrencyAmount
|
|
2705
|
+
baseCurrencyAmount,
|
|
2706
|
+
quoteCurrencyAmount
|
|
1958
2707
|
}) => {
|
|
1959
2708
|
try {
|
|
1960
2709
|
setError(null);
|
|
@@ -1962,12 +2711,34 @@ function useFiatOnRamp(options) {
|
|
|
1962
2711
|
const token = enabledTokens.find((t) => t.id.toLowerCase() === tokenId.toLowerCase());
|
|
1963
2712
|
if (!token) throw new Error(`Unknown token: ${tokenId}`);
|
|
1964
2713
|
if (!depositAddress) throw new Error("Privana deposit address is not ready");
|
|
2714
|
+
let lockAmount;
|
|
2715
|
+
if (postDepositLock) {
|
|
2716
|
+
if (!address || !walletClient) throw new Error("Wallet not connected");
|
|
2717
|
+
if (!quoteCurrencyAmount) {
|
|
2718
|
+
throw new Error(
|
|
2719
|
+
"postDepositLock requires quoteCurrencyAmount to derive the lock amount"
|
|
2720
|
+
);
|
|
2721
|
+
}
|
|
2722
|
+
if (!canUseBrowserStorage()) {
|
|
2723
|
+
throw new Error("Browser storage is required for locked on-ramp recovery");
|
|
2724
|
+
}
|
|
2725
|
+
const buffered = applyLockBuffer(
|
|
2726
|
+
viem.parseUnits(quoteCurrencyAmount, token.decimals),
|
|
2727
|
+
postDepositLock.buffer
|
|
2728
|
+
);
|
|
2729
|
+
lockAmount = clampLockAmount(buffered, postDepositLock.maxAmount);
|
|
2730
|
+
if (lockAmount <= 0n) {
|
|
2731
|
+
throw new Error(`Post-deposit lock amount must be positive, got ${lockAmount}`);
|
|
2732
|
+
}
|
|
2733
|
+
await ensureCorrectChain(networkConfig.chainId);
|
|
2734
|
+
}
|
|
1965
2735
|
emitDebug("intent:create-request", {
|
|
1966
2736
|
tokenId,
|
|
1967
2737
|
chainId: token.chainId,
|
|
1968
2738
|
currencyCode,
|
|
1969
2739
|
baseCurrencyCode: baseCurrencyCode ?? null,
|
|
1970
2740
|
baseCurrencyAmount: baseCurrencyAmount ?? null,
|
|
2741
|
+
quoteCurrencyAmount: quoteCurrencyAmount ?? null,
|
|
1971
2742
|
depositAddress
|
|
1972
2743
|
});
|
|
1973
2744
|
const record = await executePrivateRead(
|
|
@@ -1980,6 +2751,28 @@ function useFiatOnRamp(options) {
|
|
|
1980
2751
|
base_currency_amount: baseCurrencyAmount
|
|
1981
2752
|
})
|
|
1982
2753
|
);
|
|
2754
|
+
if (postDepositLock && address && walletClient && lockAmount !== void 0) {
|
|
2755
|
+
const signingWalletClient = await getWalletClient3(wagmiConfig, {
|
|
2756
|
+
chainId: networkConfig.chainId
|
|
2757
|
+
});
|
|
2758
|
+
const signedLock = await createSignedLockRequest({
|
|
2759
|
+
client,
|
|
2760
|
+
walletClient: signingWalletClient,
|
|
2761
|
+
userAddress: address,
|
|
2762
|
+
networkConfig,
|
|
2763
|
+
serviceAddress: requireServiceAddress(postDepositLock.serviceAddress ?? serviceAddress),
|
|
2764
|
+
tokenId,
|
|
2765
|
+
amount: lockAmount,
|
|
2766
|
+
lockDuration: postDepositLock.lockDuration
|
|
2767
|
+
});
|
|
2768
|
+
savePendingLock(address, record.transaction_id, signedLock);
|
|
2769
|
+
lockOwnerRef.current = address;
|
|
2770
|
+
emitDebug("intent:lock-signed", {
|
|
2771
|
+
transactionId: record.transaction_id,
|
|
2772
|
+
amount: signedLock.amount,
|
|
2773
|
+
expiry: signedLock.expiry
|
|
2774
|
+
});
|
|
2775
|
+
}
|
|
1983
2776
|
activeIntentIdRef.current = record.transaction_id;
|
|
1984
2777
|
setActiveIntentId(record.transaction_id);
|
|
1985
2778
|
emitDebug("intent:create-success", {
|
|
@@ -1995,7 +2788,21 @@ function useFiatOnRamp(options) {
|
|
|
1995
2788
|
throw e;
|
|
1996
2789
|
}
|
|
1997
2790
|
},
|
|
1998
|
-
[
|
|
2791
|
+
[
|
|
2792
|
+
address,
|
|
2793
|
+
client,
|
|
2794
|
+
depositAddress,
|
|
2795
|
+
emitDebug,
|
|
2796
|
+
enabledTokens,
|
|
2797
|
+
ensureCorrectChain,
|
|
2798
|
+
executePrivateRead,
|
|
2799
|
+
networkConfig,
|
|
2800
|
+
postDepositLock,
|
|
2801
|
+
serviceAddress,
|
|
2802
|
+
tokenId,
|
|
2803
|
+
wagmiConfig,
|
|
2804
|
+
walletClient
|
|
2805
|
+
]
|
|
1999
2806
|
);
|
|
2000
2807
|
const registerOnRampTokenMapping = react.useCallback(
|
|
2001
2808
|
async (moonpayTransactionId) => {
|
|
@@ -2117,6 +2924,12 @@ function useFiatOnRamp(options) {
|
|
|
2117
2924
|
});
|
|
2118
2925
|
return;
|
|
2119
2926
|
}
|
|
2927
|
+
const supersededKey = activeVerificationKeyRef.current;
|
|
2928
|
+
if (supersededKey && supersededKey !== verificationKey) {
|
|
2929
|
+
triggeredVerificationKeysRef.current.delete(supersededKey);
|
|
2930
|
+
}
|
|
2931
|
+
activeVerificationDoneRef.current?.();
|
|
2932
|
+
activeVerificationDoneRef.current = null;
|
|
2120
2933
|
triggeredVerificationKeysRef.current.add(verificationKey);
|
|
2121
2934
|
activeVerificationKeyRef.current = verificationKey;
|
|
2122
2935
|
activeVerificationRecordRef.current = record;
|
|
@@ -2167,6 +2980,7 @@ function useFiatOnRamp(options) {
|
|
|
2167
2980
|
`Delivered amount (${record.quote_currency_amount}) is below the minimum deposit.`
|
|
2168
2981
|
);
|
|
2169
2982
|
}
|
|
2983
|
+
activeVerificationAmountRef.current = amount;
|
|
2170
2984
|
if (activeIntentIdRef.current === record.transaction_id) {
|
|
2171
2985
|
setStatus("verifying");
|
|
2172
2986
|
}
|
|
@@ -2185,6 +2999,7 @@ function useFiatOnRamp(options) {
|
|
|
2185
2999
|
if (activeVerificationKeyRef.current === verificationKey) {
|
|
2186
3000
|
activeVerificationKeyRef.current = null;
|
|
2187
3001
|
activeVerificationRecordRef.current = null;
|
|
3002
|
+
activeVerificationAmountRef.current = null;
|
|
2188
3003
|
setActiveVerificationId(null);
|
|
2189
3004
|
}
|
|
2190
3005
|
throw err;
|
|
@@ -2243,6 +3058,7 @@ function useFiatOnRamp(options) {
|
|
|
2243
3058
|
previousStatus,
|
|
2244
3059
|
transactionId
|
|
2245
3060
|
});
|
|
3061
|
+
if (address) clearPendingLock(address, transactionId);
|
|
2246
3062
|
await refreshPending();
|
|
2247
3063
|
if (previousStatus === "awaiting-purchase" || previousStatus === "awaiting-delivery") {
|
|
2248
3064
|
setStatus("idle");
|
|
@@ -2273,7 +3089,7 @@ function useFiatOnRamp(options) {
|
|
|
2273
3089
|
} finally {
|
|
2274
3090
|
closeReconcilePromiseRef.current = null;
|
|
2275
3091
|
}
|
|
2276
|
-
}, [emitDebug, refreshPending, triggerVerification, waitForOnChainHash]);
|
|
3092
|
+
}, [address, emitDebug, refreshPending, triggerVerification, waitForOnChainHash]);
|
|
2277
3093
|
const finishPendingVerification = react.useCallback(
|
|
2278
3094
|
async (record) => {
|
|
2279
3095
|
try {
|
|
@@ -2307,6 +3123,12 @@ function useFiatOnRamp(options) {
|
|
|
2307
3123
|
try {
|
|
2308
3124
|
await triggerVerificationRef.current(record);
|
|
2309
3125
|
} catch {
|
|
3126
|
+
continue;
|
|
3127
|
+
}
|
|
3128
|
+
if (activeVerificationKeyRef.current === key) {
|
|
3129
|
+
await new Promise((resolve) => {
|
|
3130
|
+
activeVerificationDoneRef.current = resolve;
|
|
3131
|
+
});
|
|
2310
3132
|
}
|
|
2311
3133
|
}
|
|
2312
3134
|
})();
|
|
@@ -2423,6 +3245,12 @@ function matchesOnRampTransaction(record, transactionId) {
|
|
|
2423
3245
|
function getOnRampVerificationKey(record) {
|
|
2424
3246
|
return record.on_chain_tx_hash ?? record.transaction_id;
|
|
2425
3247
|
}
|
|
3248
|
+
function requireServiceAddress(serviceAddress) {
|
|
3249
|
+
if (!serviceAddress) {
|
|
3250
|
+
throw new Error("Service address not configured");
|
|
3251
|
+
}
|
|
3252
|
+
return serviceAddress;
|
|
3253
|
+
}
|
|
2426
3254
|
function summariseMoonPayEventProps(props) {
|
|
2427
3255
|
return {
|
|
2428
3256
|
id: props.id,
|
|
@@ -2480,6 +3308,7 @@ function useMoonPayBuyWidget({
|
|
|
2480
3308
|
colorCode,
|
|
2481
3309
|
baseCurrencyCode,
|
|
2482
3310
|
baseCurrencyAmount,
|
|
3311
|
+
quoteCurrencyAmount,
|
|
2483
3312
|
lockAmount,
|
|
2484
3313
|
paymentMethod,
|
|
2485
3314
|
currencyCode,
|
|
@@ -2539,6 +3368,7 @@ function useMoonPayBuyWidget({
|
|
|
2539
3368
|
overlayNode,
|
|
2540
3369
|
baseCurrencyCode,
|
|
2541
3370
|
baseCurrencyAmount,
|
|
3371
|
+
quoteCurrencyAmount,
|
|
2542
3372
|
lockAmount: lockAmount ? "true" : void 0,
|
|
2543
3373
|
paymentMethod,
|
|
2544
3374
|
currencyCode,
|
|
@@ -2564,6 +3394,7 @@ function useMoonPayBuyWidget({
|
|
|
2564
3394
|
overlayNode,
|
|
2565
3395
|
baseCurrencyCode,
|
|
2566
3396
|
baseCurrencyAmount,
|
|
3397
|
+
quoteCurrencyAmount,
|
|
2567
3398
|
lockAmount,
|
|
2568
3399
|
paymentMethod,
|
|
2569
3400
|
currencyCode,
|
|
@@ -2582,6 +3413,7 @@ function FiatOnRampForm({
|
|
|
2582
3413
|
currencyCode,
|
|
2583
3414
|
baseCurrencyCode = "usd",
|
|
2584
3415
|
defaultBaseCurrencyAmount = "100",
|
|
3416
|
+
quoteCurrencyAmount,
|
|
2585
3417
|
tokenSymbol,
|
|
2586
3418
|
theme,
|
|
2587
3419
|
themeId,
|
|
@@ -2590,7 +3422,10 @@ function FiatOnRampForm({
|
|
|
2590
3422
|
autoStart = false,
|
|
2591
3423
|
lockAmount,
|
|
2592
3424
|
paymentMethod,
|
|
3425
|
+
postDepositLock,
|
|
2593
3426
|
onCredited,
|
|
3427
|
+
onLockSubmitted,
|
|
3428
|
+
onLockFailed,
|
|
2594
3429
|
onError,
|
|
2595
3430
|
onDebugEvent
|
|
2596
3431
|
}) {
|
|
@@ -2598,6 +3433,8 @@ function FiatOnRampForm({
|
|
|
2598
3433
|
const [visible, setVisible] = react.useState(false);
|
|
2599
3434
|
const [isPreparing, setIsPreparing] = react.useState(false);
|
|
2600
3435
|
const [rowError, setRowError] = react.useState(null);
|
|
3436
|
+
const [lockError, setLockError] = react.useState(null);
|
|
3437
|
+
const [lockSettled, setLockSettled] = react.useState(false);
|
|
2601
3438
|
const {
|
|
2602
3439
|
status,
|
|
2603
3440
|
activeIntentId,
|
|
@@ -2615,7 +3452,25 @@ function FiatOnRampForm({
|
|
|
2615
3452
|
finishPendingVerification,
|
|
2616
3453
|
handleWidgetClosed,
|
|
2617
3454
|
refreshPending
|
|
2618
|
-
} = useFiatOnRamp({
|
|
3455
|
+
} = useFiatOnRamp({
|
|
3456
|
+
tokenId,
|
|
3457
|
+
postDepositLock,
|
|
3458
|
+
onCredited,
|
|
3459
|
+
// Lock callbacks aren't intent-keyed, so a resumed background row's lock
|
|
3460
|
+
// can settle these flags while a newer purchase is still locking — a
|
|
3461
|
+
// transient overpromise that the newer lock's own outcome then corrects.
|
|
3462
|
+
onLockSubmitted: (response) => {
|
|
3463
|
+
setLockError(null);
|
|
3464
|
+
setLockSettled(true);
|
|
3465
|
+
onLockSubmitted?.(response);
|
|
3466
|
+
},
|
|
3467
|
+
onLockFailed: (err) => {
|
|
3468
|
+
setLockError(err.message);
|
|
3469
|
+
onLockFailed?.(err);
|
|
3470
|
+
},
|
|
3471
|
+
onError,
|
|
3472
|
+
onDebugEvent
|
|
3473
|
+
});
|
|
2619
3474
|
const decimals = selectedToken?.decimals;
|
|
2620
3475
|
const displaySymbol = tokenSymbol ?? selectedToken?.symbol ?? currencyCode.toUpperCase();
|
|
2621
3476
|
const emitFormDebug = react.useCallback(
|
|
@@ -2631,8 +3486,17 @@ function FiatOnRampForm({
|
|
|
2631
3486
|
[onDebugEvent, status, tokenId]
|
|
2632
3487
|
);
|
|
2633
3488
|
const minFiatGate = minDepositBaseUnits !== void 0 && decimals !== void 0 ? Number(viem.formatUnits(minDepositBaseUnits, decimals)) * 1.05 : void 0;
|
|
2634
|
-
const
|
|
3489
|
+
const { units: quoteBaseUnits, failed: quoteParseFailed } = (() => {
|
|
3490
|
+
if (!quoteCurrencyAmount || decimals === void 0) return { units: void 0, failed: false };
|
|
3491
|
+
try {
|
|
3492
|
+
return { units: viem.parseUnits(quoteCurrencyAmount, decimals), failed: false };
|
|
3493
|
+
} catch {
|
|
3494
|
+
return { units: void 0, failed: true };
|
|
3495
|
+
}
|
|
3496
|
+
})();
|
|
3497
|
+
const isBelowMin = quoteBaseUnits !== void 0 && minDepositBaseUnits !== void 0 ? quoteBaseUnits < minDepositBaseUnits : minFiatGate !== void 0 && Number(defaultBaseCurrencyAmount) < minFiatGate;
|
|
2635
3498
|
const isBusy = isPreparing || status === "awaiting-purchase";
|
|
3499
|
+
const lockPending = !!postDepositLock && status === "credited" && !lockSettled && !lockError;
|
|
2636
3500
|
const isInitializing = !!address && !depositAddress;
|
|
2637
3501
|
const isPrePurchase = status === "idle" || status === "awaiting-purchase";
|
|
2638
3502
|
const isVerifying = status === "awaiting-delivery" || status === "verifying";
|
|
@@ -2642,9 +3506,10 @@ function FiatOnRampForm({
|
|
|
2642
3506
|
!depositAddress ? "deposit-address-not-loaded" : null,
|
|
2643
3507
|
isBusy ? `busy:${isPreparing ? "preparing" : status}` : null,
|
|
2644
3508
|
visible ? "widget-open" : null,
|
|
2645
|
-
isBelowMin ? "below-minimum" : null
|
|
3509
|
+
isBelowMin ? "below-minimum" : null,
|
|
3510
|
+
quoteParseFailed ? "invalid-quote-amount" : null
|
|
2646
3511
|
].filter((reason) => Boolean(reason)),
|
|
2647
|
-
[address, depositAddress, isBelowMin, isBusy, isPreparing, status, visible]
|
|
3512
|
+
[address, depositAddress, isBelowMin, isBusy, isPreparing, quoteParseFailed, status, visible]
|
|
2648
3513
|
);
|
|
2649
3514
|
const canBuy = blockReasons.length === 0;
|
|
2650
3515
|
const handleOpen = react.useCallback(async () => {
|
|
@@ -2663,6 +3528,8 @@ function FiatOnRampForm({
|
|
|
2663
3528
|
return;
|
|
2664
3529
|
}
|
|
2665
3530
|
setIsPreparing(true);
|
|
3531
|
+
setLockError(null);
|
|
3532
|
+
setLockSettled(false);
|
|
2666
3533
|
emitFormDebug("form:open-click", {
|
|
2667
3534
|
currencyCode,
|
|
2668
3535
|
tokenSymbol: displaySymbol,
|
|
@@ -2676,7 +3543,8 @@ function FiatOnRampForm({
|
|
|
2676
3543
|
const intent = await prepareOnRampIntent({
|
|
2677
3544
|
currencyCode,
|
|
2678
3545
|
baseCurrencyCode,
|
|
2679
|
-
baseCurrencyAmount: defaultBaseCurrencyAmount
|
|
3546
|
+
baseCurrencyAmount: defaultBaseCurrencyAmount,
|
|
3547
|
+
quoteCurrencyAmount
|
|
2680
3548
|
});
|
|
2681
3549
|
emitFormDebug("form:intent-ready", {
|
|
2682
3550
|
transactionId: intent.transaction_id,
|
|
@@ -2701,6 +3569,7 @@ function FiatOnRampForm({
|
|
|
2701
3569
|
decimals,
|
|
2702
3570
|
displaySymbol,
|
|
2703
3571
|
defaultBaseCurrencyAmount,
|
|
3572
|
+
quoteCurrencyAmount,
|
|
2704
3573
|
depositAddress,
|
|
2705
3574
|
emitFormDebug,
|
|
2706
3575
|
prepareOnRampIntent,
|
|
@@ -2731,6 +3600,7 @@ function FiatOnRampForm({
|
|
|
2731
3600
|
colorCode,
|
|
2732
3601
|
baseCurrencyCode,
|
|
2733
3602
|
baseCurrencyAmount: defaultBaseCurrencyAmount,
|
|
3603
|
+
quoteCurrencyAmount,
|
|
2734
3604
|
lockAmount,
|
|
2735
3605
|
paymentMethod,
|
|
2736
3606
|
currencyCode,
|
|
@@ -2803,7 +3673,7 @@ function FiatOnRampForm({
|
|
|
2803
3673
|
);
|
|
2804
3674
|
})
|
|
2805
3675
|
] }),
|
|
2806
|
-
status === "credited" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2 py-8 text-center", children: [
|
|
3676
|
+
status === "credited" && !lockPending && !lockError && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2 py-8 text-center", children: [
|
|
2807
3677
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleCheckIcon, { className: "text-primary size-8", "aria-hidden": true }),
|
|
2808
3678
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-foreground text-sm font-medium", children: "Purchase credited" }),
|
|
2809
3679
|
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-muted-foreground text-sm", children: [
|
|
@@ -2812,12 +3682,20 @@ function FiatOnRampForm({
|
|
|
2812
3682
|
" deposit is now available in your balance."
|
|
2813
3683
|
] })
|
|
2814
3684
|
] }),
|
|
3685
|
+
lockPending && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-muted-foreground flex items-center gap-2 text-sm", children: [
|
|
3686
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "size-4 animate-spin", "aria-hidden": true }),
|
|
3687
|
+
"Purchase credited \u2014 locking your funds\u2026"
|
|
3688
|
+
] }),
|
|
2815
3689
|
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
3690
|
(isBusy || visible) && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "animate-spin", "aria-hidden": true }),
|
|
2817
3691
|
"Buy"
|
|
2818
3692
|
] }),
|
|
2819
3693
|
widgetElement,
|
|
2820
3694
|
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-destructive text-sm", role: "alert", children: error.message }),
|
|
3695
|
+
lockError && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-destructive text-sm", role: "alert", children: [
|
|
3696
|
+
"Purchase credited to your account, but locking the funds to a service failed: ",
|
|
3697
|
+
lockError
|
|
3698
|
+
] }),
|
|
2821
3699
|
isBelowMin && minFiatGate !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-destructive text-sm", role: "alert", children: [
|
|
2822
3700
|
"Minimum purchase is ~$",
|
|
2823
3701
|
minFiatGate.toFixed(2),
|
|
@@ -2837,43 +3715,63 @@ function parseFinalityProgress(message) {
|
|
|
2837
3715
|
|
|
2838
3716
|
exports.AccountingApiError = AccountingApiError;
|
|
2839
3717
|
exports.Button = Button;
|
|
3718
|
+
exports.DEFAULT_LOCK_DURATION_SECONDS = DEFAULT_LOCK_DURATION_SECONDS;
|
|
3719
|
+
exports.DEFAULT_ONRAMP_LOCK_BUFFER = DEFAULT_ONRAMP_LOCK_BUFFER;
|
|
2840
3720
|
exports.FiatOnRampForm = FiatOnRampForm;
|
|
2841
3721
|
exports.HOSTED_AUTH_CLOCK_SKEW_MS = HOSTED_AUTH_CLOCK_SKEW_MS;
|
|
2842
3722
|
exports.HostedAuthError = HostedAuthError;
|
|
2843
3723
|
exports.HostedAuthRequiredError = HostedAuthRequiredError;
|
|
2844
3724
|
exports.HostedAuthStateMismatchError = HostedAuthStateMismatchError;
|
|
2845
3725
|
exports.HttpClient = HttpClient;
|
|
3726
|
+
exports.LOCK_TYPES = LOCK_TYPES;
|
|
3727
|
+
exports.MODIFY_LOCK_TYPES = MODIFY_LOCK_TYPES;
|
|
2846
3728
|
exports.NETWORK_CONFIG = NETWORK_CONFIG;
|
|
2847
3729
|
exports.NetworkError = NetworkError;
|
|
3730
|
+
exports.PostDepositLockError = PostDepositLockError;
|
|
2848
3731
|
exports.PrivanaClient = PrivanaClient;
|
|
2849
3732
|
exports.PrivanaProvider = PrivanaProvider;
|
|
2850
3733
|
exports.SUPPORTED_CHAINS = SUPPORTED_CHAINS;
|
|
2851
3734
|
exports.SiweAuthProvider = SiweAuthProvider;
|
|
2852
3735
|
exports.Skeleton = Skeleton;
|
|
3736
|
+
exports.TRANSFER_LOCKED_TYPES = TRANSFER_LOCKED_TYPES;
|
|
3737
|
+
exports.TRANSFER_TYPES = TRANSFER_TYPES;
|
|
2853
3738
|
exports.ValidationError = ValidationError;
|
|
3739
|
+
exports.WITHDRAW_FROM_LOCK_TYPES = WITHDRAW_FROM_LOCK_TYPES;
|
|
3740
|
+
exports.WITHDRAW_TYPES = WITHDRAW_TYPES;
|
|
3741
|
+
exports.applyLockBuffer = applyLockBuffer;
|
|
2854
3742
|
exports.applyRefreshResponse = applyRefreshResponse;
|
|
2855
3743
|
exports.buildHostedAuthSession = buildHostedAuthSession;
|
|
2856
3744
|
exports.buildSiweStatement = buildSiweStatement;
|
|
2857
3745
|
exports.buttonVariants = buttonVariants;
|
|
3746
|
+
exports.canUseBrowserStorage = canUseBrowserStorage;
|
|
3747
|
+
exports.clampLockAmount = clampLockAmount;
|
|
2858
3748
|
exports.clearHostedAuthPendingTransaction = clearHostedAuthPendingTransaction;
|
|
3749
|
+
exports.clearPendingLock = clearPendingLock;
|
|
2859
3750
|
exports.cn = cn;
|
|
3751
|
+
exports.createDomain = createDomain;
|
|
2860
3752
|
exports.createHostedAuthPendingStorageKey = createHostedAuthPendingStorageKey;
|
|
2861
3753
|
exports.createHostedAuthState = createHostedAuthState;
|
|
2862
3754
|
exports.createHostedAuthStorageKey = createHostedAuthStorageKey;
|
|
3755
|
+
exports.createLockExpiry = createLockExpiry;
|
|
2863
3756
|
exports.createPkceChallenge = createPkceChallenge;
|
|
2864
3757
|
exports.createPkceVerifier = createPkceVerifier;
|
|
3758
|
+
exports.createSignedLockRequest = createSignedLockRequest;
|
|
3759
|
+
exports.formatCountdown = formatCountdown;
|
|
2865
3760
|
exports.formatTimeRemaining = formatTimeRemaining;
|
|
2866
3761
|
exports.formatTokenAmount = formatTokenAmount;
|
|
2867
3762
|
exports.getAccountingContract = getAccountingContract;
|
|
2868
3763
|
exports.getApiUrl = getApiUrl;
|
|
3764
|
+
exports.getBrowserStorageItem = getBrowserStorageItem;
|
|
2869
3765
|
exports.getChainById = getChainById;
|
|
2870
3766
|
exports.getChainId = getChainId;
|
|
2871
|
-
exports.getChainId2 = getChainId2;
|
|
2872
3767
|
exports.getExplorerAddressUrl = getExplorerAddressUrl;
|
|
2873
3768
|
exports.getExplorerLabel = getExplorerLabel;
|
|
2874
3769
|
exports.getTransactionReceipt = getTransactionReceipt;
|
|
3770
|
+
exports.getWalletClient = getWalletClient3;
|
|
2875
3771
|
exports.isHostedAuthRefreshActive = isHostedAuthRefreshActive;
|
|
2876
3772
|
exports.isHostedAuthSessionActive = isHostedAuthSessionActive;
|
|
3773
|
+
exports.isSignedLockUsable = isSignedLockUsable;
|
|
3774
|
+
exports.loadPendingLock = loadPendingLock;
|
|
2877
3775
|
exports.normalizeAddress = normalizeAddress;
|
|
2878
3776
|
exports.normalizeHex = normalizeHex;
|
|
2879
3777
|
exports.parseHostedAuthCallback = parseHostedAuthCallback;
|
|
@@ -2881,10 +3779,21 @@ exports.parseTokenAmount = parseTokenAmount;
|
|
|
2881
3779
|
exports.persistHostedAuthPendingTransaction = persistHostedAuthPendingTransaction;
|
|
2882
3780
|
exports.readHostedAuthPendingTransaction = readHostedAuthPendingTransaction;
|
|
2883
3781
|
exports.readStoredHostedAuthSession = readStoredHostedAuthSession;
|
|
3782
|
+
exports.removeBrowserStorageItem = removeBrowserStorageItem;
|
|
3783
|
+
exports.savePendingLock = savePendingLock;
|
|
3784
|
+
exports.setBrowserStorageItem = setBrowserStorageItem;
|
|
2884
3785
|
exports.shortenAddress = shortenAddress;
|
|
3786
|
+
exports.signLockMessage = signLockMessage;
|
|
3787
|
+
exports.signModifyLockMessage = signModifyLockMessage;
|
|
3788
|
+
exports.signTransferLockedMessage = signTransferLockedMessage;
|
|
3789
|
+
exports.signTransferMessage = signTransferMessage;
|
|
3790
|
+
exports.signWithdrawFromLockMessage = signWithdrawFromLockMessage;
|
|
3791
|
+
exports.signWithdrawMessage = signWithdrawMessage;
|
|
2885
3792
|
exports.stripHostedAuthCallbackParams = stripHostedAuthCallbackParams;
|
|
3793
|
+
exports.submitPendingLock = submitPendingLock;
|
|
2886
3794
|
exports.syncHostedAuthSessionToClient = syncHostedAuthSessionToClient;
|
|
2887
3795
|
exports.useDepositVerification = useDepositVerification;
|
|
3796
|
+
exports.useEnsureCorrectChain = useEnsureCorrectChain;
|
|
2888
3797
|
exports.useFiatOnRamp = useFiatOnRamp;
|
|
2889
3798
|
exports.usePrivanaContext = usePrivanaContext;
|
|
2890
3799
|
exports.usePrivateReadRequest = usePrivateReadRequest;
|
|
@@ -2892,5 +3801,5 @@ exports.useSafeAccount = useSafeAccount;
|
|
|
2892
3801
|
exports.useSafePrivanaContext = useSafePrivanaContext;
|
|
2893
3802
|
exports.useSiweAuth = useSiweAuth;
|
|
2894
3803
|
exports.waitForTransactionReceipt = waitForTransactionReceipt;
|
|
2895
|
-
//# sourceMappingURL=chunk-
|
|
2896
|
-
//# sourceMappingURL=chunk-
|
|
3804
|
+
//# sourceMappingURL=chunk-4IW4V7YJ.cjs.map
|
|
3805
|
+
//# sourceMappingURL=chunk-4IW4V7YJ.cjs.map
|