@cicero-zcash/react 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -159
- package/dist/index.d.mts +30 -140
- package/dist/index.d.ts +30 -140
- package/dist/index.js +234 -837
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +234 -855
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -6
package/dist/index.js
CHANGED
|
@@ -33,9 +33,6 @@ __export(index_exports, {
|
|
|
33
33
|
CiceroAccountModal: () => CiceroAccountModal,
|
|
34
34
|
CiceroConnectButton: () => CiceroConnectButton,
|
|
35
35
|
CiceroConnectModal: () => CiceroConnectModal,
|
|
36
|
-
CiceroInvoice: () => CiceroInvoice,
|
|
37
|
-
CiceroModal: () => CiceroModal,
|
|
38
|
-
CiceroPayButton: () => CiceroPayButton,
|
|
39
36
|
CiceroProvider: () => CiceroProvider,
|
|
40
37
|
CiceroQRCode: () => CiceroQRCode,
|
|
41
38
|
ZucchiniWalletAdapter: () => ZucchiniWalletAdapter,
|
|
@@ -53,7 +50,6 @@ __export(index_exports, {
|
|
|
53
50
|
useAccountModal: () => useAccountModal,
|
|
54
51
|
useBalance: () => useBalance,
|
|
55
52
|
useCicero: () => useCicero,
|
|
56
|
-
useCiceroPayment: () => useCiceroPayment,
|
|
57
53
|
useConnectModal: () => useConnectModal,
|
|
58
54
|
useZcashPrice: () => useZcashPrice,
|
|
59
55
|
useZucchiniWallet: () => useZucchiniWallet,
|
|
@@ -294,15 +290,99 @@ var ZucchiniWalletAdapter = class _ZucchiniWalletAdapter {
|
|
|
294
290
|
}
|
|
295
291
|
}
|
|
296
292
|
this._lastAccounts = connection?.accounts || [];
|
|
297
|
-
const
|
|
293
|
+
const network = await this.getNetwork();
|
|
294
|
+
const balance = await this.getBalance({ address, network });
|
|
298
295
|
this._connected = true;
|
|
299
296
|
this._address = address || null;
|
|
300
297
|
return {
|
|
301
298
|
address,
|
|
302
299
|
connected: true,
|
|
300
|
+
network,
|
|
303
301
|
balance: balance ?? void 0
|
|
304
302
|
};
|
|
305
303
|
}
|
|
304
|
+
/**
|
|
305
|
+
* Queries the active network of the Zucchini Wallet ('mainnet' | 'testnet').
|
|
306
|
+
*/
|
|
307
|
+
async getNetwork() {
|
|
308
|
+
try {
|
|
309
|
+
const client = await this.getClient();
|
|
310
|
+
if (typeof client.network === "function") {
|
|
311
|
+
const net = await client.network();
|
|
312
|
+
if (net === "mainnet" || net === "testnet") {
|
|
313
|
+
return net;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
} catch {
|
|
317
|
+
}
|
|
318
|
+
const raw = this.provider || (typeof window !== "undefined" ? window.zucchini || window.zcash : null);
|
|
319
|
+
if (raw && typeof raw.request === "function") {
|
|
320
|
+
try {
|
|
321
|
+
const res = await raw.request({ method: "getNetwork" });
|
|
322
|
+
if (res?.network === "main" || res === "main" || res === "mainnet") return "mainnet";
|
|
323
|
+
if (res?.network === "test" || res === "test" || res === "testnet") return "testnet";
|
|
324
|
+
} catch {
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (this._address) {
|
|
328
|
+
if (this._address.startsWith("utest1") || this._address.startsWith("ztestsapling") || this._address.startsWith("tm")) {
|
|
329
|
+
return "testnet";
|
|
330
|
+
}
|
|
331
|
+
if (this._address.startsWith("u1") || this._address.startsWith("zs1") || this._address.startsWith("t1")) {
|
|
332
|
+
return "mainnet";
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
return "mainnet";
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Requests a network change. If the extension does not support programmatic
|
|
339
|
+
* switching, informs the application that manual user toggle is needed.
|
|
340
|
+
*/
|
|
341
|
+
async switchNetwork(targetNetwork) {
|
|
342
|
+
const current = await this.getNetwork();
|
|
343
|
+
if (current === targetNetwork) {
|
|
344
|
+
return { success: true, currentNetwork: current };
|
|
345
|
+
}
|
|
346
|
+
const raw = this.provider || (typeof window !== "undefined" ? window.zucchini || window.zcash : null);
|
|
347
|
+
if (raw && typeof raw.request === "function") {
|
|
348
|
+
try {
|
|
349
|
+
await raw.request({
|
|
350
|
+
method: "switchNetwork",
|
|
351
|
+
params: { network: targetNetwork === "mainnet" ? "main" : "test" }
|
|
352
|
+
});
|
|
353
|
+
const updated = await this.getNetwork();
|
|
354
|
+
return { success: updated === targetNetwork, currentNetwork: updated };
|
|
355
|
+
} catch {
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
return {
|
|
359
|
+
success: false,
|
|
360
|
+
requiresManualSwitch: true,
|
|
361
|
+
currentNetwork: current
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Subscribes to network change events from the wallet extension.
|
|
366
|
+
*/
|
|
367
|
+
onNetworkChanged(listener) {
|
|
368
|
+
const raw = this.provider || (typeof window !== "undefined" ? window.zucchini || window.zcash : null);
|
|
369
|
+
const handler = async () => {
|
|
370
|
+
const net = await this.getNetwork();
|
|
371
|
+
listener(net);
|
|
372
|
+
};
|
|
373
|
+
if (raw?.on) {
|
|
374
|
+
raw.on("networkChanged", handler);
|
|
375
|
+
raw.on("chainChanged", handler);
|
|
376
|
+
raw.on("accountsChanged", handler);
|
|
377
|
+
return () => {
|
|
378
|
+
raw.off?.("networkChanged", handler);
|
|
379
|
+
raw.off?.("chainChanged", handler);
|
|
380
|
+
raw.off?.("accountsChanged", handler);
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
return () => {
|
|
384
|
+
};
|
|
385
|
+
}
|
|
306
386
|
/**
|
|
307
387
|
* Helper to normalize raw balance formats (e.g. number, string, zatoshis, or pool totals).
|
|
308
388
|
*/
|
|
@@ -470,7 +550,7 @@ var zucchiniWallet = {
|
|
|
470
550
|
return {
|
|
471
551
|
address: session.address,
|
|
472
552
|
connected: true,
|
|
473
|
-
network: options?.network || "mainnet",
|
|
553
|
+
network: session.network || options?.network || "mainnet",
|
|
474
554
|
walletId: "zucchini",
|
|
475
555
|
balance: session.balance
|
|
476
556
|
};
|
|
@@ -481,6 +561,12 @@ var zucchiniWallet = {
|
|
|
481
561
|
getBalance: async (options) => {
|
|
482
562
|
return adapter.getBalance(options);
|
|
483
563
|
},
|
|
564
|
+
getNetwork: async () => {
|
|
565
|
+
return adapter.getNetwork();
|
|
566
|
+
},
|
|
567
|
+
switchNetwork: async (network) => {
|
|
568
|
+
return adapter.switchNetwork(network);
|
|
569
|
+
},
|
|
484
570
|
sendPayment: async (params) => {
|
|
485
571
|
const res = await adapter.requestPayment({
|
|
486
572
|
recipient: params.recipient,
|
|
@@ -1080,9 +1166,27 @@ var CiceroAccountModal = ({
|
|
|
1080
1166
|
const [copied, setCopied] = (0, import_react3.useState)(false);
|
|
1081
1167
|
const [showQr, setShowQr] = (0, import_react3.useState)(false);
|
|
1082
1168
|
const [mounted, setMounted] = (0, import_react3.useState)(false);
|
|
1169
|
+
const [manualNotice, setManualNotice] = (0, import_react3.useState)(null);
|
|
1083
1170
|
(0, import_react3.useEffect)(() => {
|
|
1084
1171
|
setMounted(true);
|
|
1085
1172
|
}, []);
|
|
1173
|
+
(0, import_react3.useEffect)(() => {
|
|
1174
|
+
setManualNotice(null);
|
|
1175
|
+
}, [network, isOpen]);
|
|
1176
|
+
const handleNetworkChange = async (targetNet) => {
|
|
1177
|
+
if (targetNet === network) {
|
|
1178
|
+
setManualNotice(null);
|
|
1179
|
+
return;
|
|
1180
|
+
}
|
|
1181
|
+
const res = await switchNetwork(targetNet);
|
|
1182
|
+
if (res?.requiresManualSwitch) {
|
|
1183
|
+
setManualNotice(
|
|
1184
|
+
`Wallet is currently active on ${network === "mainnet" ? "Mainnet" : "Testnet"}. Switch network inside your extension settings (Settings \u2192 Network) and Cicero will automatically update your balance.`
|
|
1185
|
+
);
|
|
1186
|
+
} else {
|
|
1187
|
+
setManualNotice(null);
|
|
1188
|
+
}
|
|
1189
|
+
};
|
|
1086
1190
|
(0, import_react3.useEffect)(() => {
|
|
1087
1191
|
const handleKeyDown = (e) => {
|
|
1088
1192
|
if (e.key === "Escape" && isOpen) {
|
|
@@ -1209,29 +1313,34 @@ var CiceroAccountModal = ({
|
|
|
1209
1313
|
)
|
|
1210
1314
|
] })
|
|
1211
1315
|
] }),
|
|
1212
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "
|
|
1213
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center
|
|
1214
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
1215
|
-
|
|
1316
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "space-y-2", children: [
|
|
1317
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center justify-between p-3 rounded-lg border border-[#ededed] bg-white text-xs", children: [
|
|
1318
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
1319
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.ArrowRightLeft, { className: "w-4 h-4 text-[#707070]" }),
|
|
1320
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-[#171717] font-medium", children: "Active Network" })
|
|
1321
|
+
] }),
|
|
1322
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center gap-1 p-0.5 rounded bg-[#fafafa] border border-[#dfdfdf]", children: [
|
|
1323
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1324
|
+
"button",
|
|
1325
|
+
{
|
|
1326
|
+
type: "button",
|
|
1327
|
+
onClick: () => handleNetworkChange("mainnet"),
|
|
1328
|
+
className: `px-2 py-1 rounded text-[11px] font-medium transition-colors ${network === "mainnet" ? "bg-white shadow-sm text-[#24b47e] font-semibold" : "text-[#707070] hover:text-[#171717]"}`,
|
|
1329
|
+
children: "Mainnet"
|
|
1330
|
+
}
|
|
1331
|
+
),
|
|
1332
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1333
|
+
"button",
|
|
1334
|
+
{
|
|
1335
|
+
type: "button",
|
|
1336
|
+
onClick: () => handleNetworkChange("testnet"),
|
|
1337
|
+
className: `px-2 py-1 rounded text-[11px] font-medium transition-colors ${network === "testnet" ? "bg-white shadow-sm text-amber-700 font-semibold" : "text-[#707070] hover:text-[#171717]"}`,
|
|
1338
|
+
children: "Testnet"
|
|
1339
|
+
}
|
|
1340
|
+
)
|
|
1341
|
+
] })
|
|
1216
1342
|
] }),
|
|
1217
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
1218
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1219
|
-
"button",
|
|
1220
|
-
{
|
|
1221
|
-
onClick: () => switchNetwork("mainnet"),
|
|
1222
|
-
className: `px-2 py-1 rounded text-[11px] font-medium transition-colors ${network === "mainnet" ? "bg-white shadow-sm text-[#24b47e] font-semibold" : "text-[#707070]"}`,
|
|
1223
|
-
children: "Mainnet"
|
|
1224
|
-
}
|
|
1225
|
-
),
|
|
1226
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1227
|
-
"button",
|
|
1228
|
-
{
|
|
1229
|
-
onClick: () => switchNetwork("testnet"),
|
|
1230
|
-
className: `px-2 py-1 rounded text-[11px] font-medium transition-colors ${network === "testnet" ? "bg-white shadow-sm text-amber-700 font-semibold" : "text-[#707070]"}`,
|
|
1231
|
-
children: "Testnet"
|
|
1232
|
-
}
|
|
1233
|
-
)
|
|
1234
|
-
] })
|
|
1343
|
+
manualNotice && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "p-2.5 rounded-md bg-amber-50 border border-amber-200 text-amber-800 text-[11px] leading-relaxed animate-in fade-in", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: manualNotice }) })
|
|
1235
1344
|
] })
|
|
1236
1345
|
] }),
|
|
1237
1346
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "px-6 py-3.5 bg-[#fafafa] border-t border-[#ededed] flex items-center justify-between", children: [
|
|
@@ -1366,6 +1475,36 @@ var CiceroProvider = ({
|
|
|
1366
1475
|
cleanupReady();
|
|
1367
1476
|
};
|
|
1368
1477
|
}, [autoConnect]);
|
|
1478
|
+
(0, import_react4.useEffect)(() => {
|
|
1479
|
+
if (typeof window === "undefined") return;
|
|
1480
|
+
const adapter2 = new ZucchiniWalletAdapter();
|
|
1481
|
+
const cleanup = adapter2.onNetworkChanged(async (detectedNet) => {
|
|
1482
|
+
setNetwork(detectedNet);
|
|
1483
|
+
localStorage.setItem("cicero_network", detectedNet);
|
|
1484
|
+
if (account.wallet?.id === "zucchini") {
|
|
1485
|
+
setBalance((prev) => ({ ...prev, isLoading: true }));
|
|
1486
|
+
try {
|
|
1487
|
+
const freshBal = await adapter2.getBalance({
|
|
1488
|
+
address: account.address || void 0,
|
|
1489
|
+
network: detectedNet
|
|
1490
|
+
});
|
|
1491
|
+
const activeZec = freshBal !== null && !isNaN(freshBal) ? freshBal : 0;
|
|
1492
|
+
setBalance({
|
|
1493
|
+
zec: activeZec,
|
|
1494
|
+
usd: convertZecToUsdRef.current(activeZec),
|
|
1495
|
+
isLoading: false
|
|
1496
|
+
});
|
|
1497
|
+
localStorage.setItem("cicero_balance", activeZec.toString());
|
|
1498
|
+
localStorage.setItem(`cicero_balance_${detectedNet}`, activeZec.toString());
|
|
1499
|
+
} catch {
|
|
1500
|
+
setBalance((prev) => ({ ...prev, isLoading: false }));
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
});
|
|
1504
|
+
return () => {
|
|
1505
|
+
cleanup();
|
|
1506
|
+
};
|
|
1507
|
+
}, [account.wallet?.id, account.address]);
|
|
1369
1508
|
(0, import_react4.useEffect)(() => {
|
|
1370
1509
|
if (account.isConnected) {
|
|
1371
1510
|
setBalance((prev) => {
|
|
@@ -1378,12 +1517,55 @@ var CiceroProvider = ({
|
|
|
1378
1517
|
});
|
|
1379
1518
|
}
|
|
1380
1519
|
}, [account.isConnected, balance.zec, convertZecToUsd]);
|
|
1381
|
-
const switchNetwork = (0, import_react4.useCallback)(
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1520
|
+
const switchNetwork = (0, import_react4.useCallback)(
|
|
1521
|
+
async (newNet) => {
|
|
1522
|
+
if (account.wallet?.switchNetwork) {
|
|
1523
|
+
try {
|
|
1524
|
+
const switchRes = await account.wallet.switchNetwork(newNet);
|
|
1525
|
+
if (switchRes && switchRes.requiresManualSwitch) {
|
|
1526
|
+
const currentNet = switchRes.currentNetwork || (account.wallet.getNetwork ? await account.wallet.getNetwork() : network);
|
|
1527
|
+
setNetwork(currentNet);
|
|
1528
|
+
if (typeof window !== "undefined") {
|
|
1529
|
+
localStorage.setItem("cicero_network", currentNet);
|
|
1530
|
+
}
|
|
1531
|
+
return {
|
|
1532
|
+
success: false,
|
|
1533
|
+
requiresManualSwitch: true,
|
|
1534
|
+
currentNetwork: currentNet
|
|
1535
|
+
};
|
|
1536
|
+
}
|
|
1537
|
+
} catch {
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
setNetwork(newNet);
|
|
1541
|
+
if (typeof window !== "undefined") {
|
|
1542
|
+
localStorage.setItem("cicero_network", newNet);
|
|
1543
|
+
}
|
|
1544
|
+
if (account.wallet?.getBalance) {
|
|
1545
|
+
setBalance((prev) => ({ ...prev, isLoading: true }));
|
|
1546
|
+
try {
|
|
1547
|
+
const freshBal = await account.wallet.getBalance({
|
|
1548
|
+
address: account.address || void 0,
|
|
1549
|
+
network: newNet
|
|
1550
|
+
});
|
|
1551
|
+
const activeZec = freshBal !== null && !isNaN(freshBal) ? freshBal : 0;
|
|
1552
|
+
setBalance({
|
|
1553
|
+
zec: activeZec,
|
|
1554
|
+
usd: convertZecToUsdRef.current(activeZec),
|
|
1555
|
+
isLoading: false
|
|
1556
|
+
});
|
|
1557
|
+
if (typeof window !== "undefined" && freshBal !== null) {
|
|
1558
|
+
localStorage.setItem(`cicero_balance_${newNet}`, freshBal.toString());
|
|
1559
|
+
localStorage.setItem("cicero_balance", freshBal.toString());
|
|
1560
|
+
}
|
|
1561
|
+
} catch {
|
|
1562
|
+
setBalance((prev) => ({ ...prev, isLoading: false }));
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1565
|
+
return { success: true, currentNetwork: newNet };
|
|
1566
|
+
},
|
|
1567
|
+
[account.wallet, account.address, network]
|
|
1568
|
+
);
|
|
1387
1569
|
const connect = (0, import_react4.useCallback)(
|
|
1388
1570
|
async (walletId, customAddressOrKey) => {
|
|
1389
1571
|
const targetWallet = wallets.find((w) => w.id === walletId);
|
|
@@ -1410,6 +1592,13 @@ var CiceroProvider = ({
|
|
|
1410
1592
|
session = await targetWallet.connect({ network });
|
|
1411
1593
|
}
|
|
1412
1594
|
const resolvedAddress = session.address || customAddressOrKey || null;
|
|
1595
|
+
const walletNetwork = session.network || (targetWallet.getNetwork ? await targetWallet.getNetwork() : network);
|
|
1596
|
+
if (walletNetwork && walletNetwork !== network) {
|
|
1597
|
+
setNetwork(walletNetwork);
|
|
1598
|
+
if (typeof window !== "undefined") {
|
|
1599
|
+
localStorage.setItem("cicero_network", walletNetwork);
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1413
1602
|
setAccount({
|
|
1414
1603
|
address: resolvedAddress,
|
|
1415
1604
|
viewingKey: session.viewingKey || null,
|
|
@@ -1702,812 +1891,24 @@ var CiceroConnectButton = ({
|
|
|
1702
1891
|
) });
|
|
1703
1892
|
};
|
|
1704
1893
|
|
|
1705
|
-
// src/components/CiceroPayButton.tsx
|
|
1706
|
-
var import_lucide_react5 = require("lucide-react");
|
|
1707
|
-
|
|
1708
|
-
// src/hooks/useCiceroPayment.ts
|
|
1709
|
-
var import_react5 = require("react");
|
|
1710
|
-
function useCiceroPayment({
|
|
1711
|
-
recipient,
|
|
1712
|
-
amount,
|
|
1713
|
-
memo,
|
|
1714
|
-
message,
|
|
1715
|
-
network = "mainnet",
|
|
1716
|
-
expiresInSeconds = 900,
|
|
1717
|
-
// 15 mins
|
|
1718
|
-
invoiceId,
|
|
1719
|
-
customRpcUrl,
|
|
1720
|
-
onSuccess,
|
|
1721
|
-
onError,
|
|
1722
|
-
onStatusChange
|
|
1723
|
-
}) {
|
|
1724
|
-
const onSuccessRef = (0, import_react5.useRef)(onSuccess);
|
|
1725
|
-
onSuccessRef.current = onSuccess;
|
|
1726
|
-
const onErrorRef = (0, import_react5.useRef)(onError);
|
|
1727
|
-
onErrorRef.current = onError;
|
|
1728
|
-
const onStatusChangeRef = (0, import_react5.useRef)(onStatusChange);
|
|
1729
|
-
onStatusChangeRef.current = onStatusChange;
|
|
1730
|
-
const [status, setStatus] = (0, import_react5.useState)("pending");
|
|
1731
|
-
const [txId, setTxId] = (0, import_react5.useState)(null);
|
|
1732
|
-
const [secondsRemaining, setSecondsRemaining] = (0, import_react5.useState)(expiresInSeconds);
|
|
1733
|
-
const [isModalOpen, setIsModalOpen] = (0, import_react5.useState)(false);
|
|
1734
|
-
const [zucchiniAvailable, setZucchiniAvailable] = (0, import_react5.useState)(false);
|
|
1735
|
-
const [zucchiniAdapter] = (0, import_react5.useState)(() => new ZucchiniWalletAdapter());
|
|
1736
|
-
const [zucchiniPaying, setZucchiniPaying] = (0, import_react5.useState)(false);
|
|
1737
|
-
(0, import_react5.useEffect)(() => {
|
|
1738
|
-
setZucchiniAvailable(ZucchiniWalletAdapter.isAvailable());
|
|
1739
|
-
}, []);
|
|
1740
|
-
const addressType = (0, import_react5.useMemo)(() => getAddressType(recipient), [recipient]);
|
|
1741
|
-
const isShielded = (0, import_react5.useMemo)(() => isShieldedAddress(recipient), [recipient]);
|
|
1742
|
-
const memoValidation = (0, import_react5.useMemo)(
|
|
1743
|
-
() => validateMemoSupport(recipient, memo),
|
|
1744
|
-
[recipient, memo]
|
|
1745
|
-
);
|
|
1746
|
-
const lastWarningRef = (0, import_react5.useRef)(null);
|
|
1747
|
-
(0, import_react5.useEffect)(() => {
|
|
1748
|
-
if (!memoValidation.valid && memoValidation.warning) {
|
|
1749
|
-
if (lastWarningRef.current !== memoValidation.warning) {
|
|
1750
|
-
lastWarningRef.current = memoValidation.warning;
|
|
1751
|
-
onErrorRef.current?.(new Error(memoValidation.warning));
|
|
1752
|
-
}
|
|
1753
|
-
} else {
|
|
1754
|
-
lastWarningRef.current = null;
|
|
1755
|
-
}
|
|
1756
|
-
}, [memoValidation.valid, memoValidation.warning]);
|
|
1757
|
-
const zip321Uri = (0, import_react5.useMemo)(() => {
|
|
1758
|
-
return generateZip321Uri({
|
|
1759
|
-
address: recipient,
|
|
1760
|
-
amount,
|
|
1761
|
-
memo,
|
|
1762
|
-
message
|
|
1763
|
-
});
|
|
1764
|
-
}, [recipient, amount, memo, message]);
|
|
1765
|
-
const deepLinks = (0, import_react5.useMemo)(() => getWalletDeepLinks(zip321Uri), [zip321Uri]);
|
|
1766
|
-
const updateStatus = (0, import_react5.useCallback)((newStatus) => {
|
|
1767
|
-
setStatus(newStatus);
|
|
1768
|
-
onStatusChangeRef.current?.(newStatus);
|
|
1769
|
-
}, []);
|
|
1770
|
-
(0, import_react5.useEffect)(() => {
|
|
1771
|
-
if (status !== "pending") return;
|
|
1772
|
-
const timer = setInterval(() => {
|
|
1773
|
-
setSecondsRemaining((prev) => {
|
|
1774
|
-
if (prev <= 1) {
|
|
1775
|
-
clearInterval(timer);
|
|
1776
|
-
updateStatus("expired");
|
|
1777
|
-
return 0;
|
|
1778
|
-
}
|
|
1779
|
-
return prev - 1;
|
|
1780
|
-
});
|
|
1781
|
-
}, 1e3);
|
|
1782
|
-
return () => clearInterval(timer);
|
|
1783
|
-
}, [status, updateStatus]);
|
|
1784
|
-
const resetPayment = (0, import_react5.useCallback)(() => {
|
|
1785
|
-
setStatus("pending");
|
|
1786
|
-
setTxId(null);
|
|
1787
|
-
setSecondsRemaining(expiresInSeconds);
|
|
1788
|
-
setZucchiniPaying(false);
|
|
1789
|
-
}, [expiresInSeconds]);
|
|
1790
|
-
const openModal = (0, import_react5.useCallback)(() => {
|
|
1791
|
-
resetPayment();
|
|
1792
|
-
setIsModalOpen(true);
|
|
1793
|
-
}, [resetPayment]);
|
|
1794
|
-
const closeModal = (0, import_react5.useCallback)(() => {
|
|
1795
|
-
setIsModalOpen(false);
|
|
1796
|
-
}, []);
|
|
1797
|
-
const payWithZucchini = (0, import_react5.useCallback)(async () => {
|
|
1798
|
-
setZucchiniPaying(true);
|
|
1799
|
-
try {
|
|
1800
|
-
await zucchiniAdapter.connect();
|
|
1801
|
-
const numAmount = typeof amount === "number" ? amount : parseFloat(amount);
|
|
1802
|
-
const result = await zucchiniAdapter.requestPayment({
|
|
1803
|
-
recipient,
|
|
1804
|
-
amount: numAmount,
|
|
1805
|
-
memo
|
|
1806
|
-
});
|
|
1807
|
-
updateStatus("detected");
|
|
1808
|
-
setTxId(result.txId);
|
|
1809
|
-
setTimeout(() => {
|
|
1810
|
-
updateStatus("confirmed");
|
|
1811
|
-
onSuccessRef.current?.({
|
|
1812
|
-
txId: result.txId,
|
|
1813
|
-
amount: isNaN(numAmount) ? 0 : numAmount,
|
|
1814
|
-
memo
|
|
1815
|
-
});
|
|
1816
|
-
setZucchiniPaying(false);
|
|
1817
|
-
}, 1500);
|
|
1818
|
-
} catch (err) {
|
|
1819
|
-
const error = err instanceof Error ? err : new Error("Zucchini payment failed");
|
|
1820
|
-
onErrorRef.current?.(error);
|
|
1821
|
-
setZucchiniPaying(false);
|
|
1822
|
-
}
|
|
1823
|
-
}, [recipient, amount, memo, zucchiniAdapter, updateStatus]);
|
|
1824
|
-
const simulateDetection = (0, import_react5.useCallback)(() => {
|
|
1825
|
-
updateStatus("detected");
|
|
1826
|
-
setTimeout(() => {
|
|
1827
|
-
const mockTxId = `0x${Array.from(
|
|
1828
|
-
{ length: 64 },
|
|
1829
|
-
() => Math.floor(Math.random() * 16).toString(16)
|
|
1830
|
-
).join("")}`;
|
|
1831
|
-
setTxId(mockTxId);
|
|
1832
|
-
updateStatus("confirmed");
|
|
1833
|
-
const numAmount = typeof amount === "number" ? amount : parseFloat(amount);
|
|
1834
|
-
onSuccessRef.current?.({
|
|
1835
|
-
txId: mockTxId,
|
|
1836
|
-
amount: isNaN(numAmount) ? 0 : numAmount,
|
|
1837
|
-
memo
|
|
1838
|
-
});
|
|
1839
|
-
}, 2e3);
|
|
1840
|
-
}, [amount, memo, updateStatus]);
|
|
1841
|
-
return {
|
|
1842
|
-
status,
|
|
1843
|
-
txId,
|
|
1844
|
-
secondsRemaining,
|
|
1845
|
-
isModalOpen,
|
|
1846
|
-
openModal,
|
|
1847
|
-
closeModal,
|
|
1848
|
-
resetPayment,
|
|
1849
|
-
zip321Uri,
|
|
1850
|
-
deepLinks,
|
|
1851
|
-
addressType,
|
|
1852
|
-
isShielded,
|
|
1853
|
-
memoValidation,
|
|
1854
|
-
simulateDetection,
|
|
1855
|
-
invoiceId,
|
|
1856
|
-
network,
|
|
1857
|
-
customRpcUrl,
|
|
1858
|
-
// Zucchini Wallet
|
|
1859
|
-
zucchiniAvailable,
|
|
1860
|
-
zucchiniPaying,
|
|
1861
|
-
payWithZucchini
|
|
1862
|
-
};
|
|
1863
|
-
}
|
|
1864
|
-
|
|
1865
|
-
// src/components/CiceroModal.tsx
|
|
1866
|
-
var import_react6 = require("react");
|
|
1867
|
-
var import_react_dom3 = require("react-dom");
|
|
1868
|
-
var import_lucide_react4 = require("lucide-react");
|
|
1869
|
-
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1870
|
-
var CiceroModal = ({
|
|
1871
|
-
isOpen,
|
|
1872
|
-
onClose,
|
|
1873
|
-
recipient,
|
|
1874
|
-
amount,
|
|
1875
|
-
memo,
|
|
1876
|
-
message,
|
|
1877
|
-
network = "mainnet",
|
|
1878
|
-
status,
|
|
1879
|
-
txId,
|
|
1880
|
-
secondsRemaining,
|
|
1881
|
-
zip321Uri,
|
|
1882
|
-
addressType,
|
|
1883
|
-
isShielded,
|
|
1884
|
-
memoValidation,
|
|
1885
|
-
onSimulateDetection,
|
|
1886
|
-
onResetPayment,
|
|
1887
|
-
title = "Pay with Shielded Zcash",
|
|
1888
|
-
subtitle = "Zero-Knowledge, Confidential Checkout",
|
|
1889
|
-
showUsd = true,
|
|
1890
|
-
zucchiniAvailable = false,
|
|
1891
|
-
zucchiniPaying = false,
|
|
1892
|
-
onPayWithZucchini
|
|
1893
|
-
}) => {
|
|
1894
|
-
const [copiedType, setCopiedType] = (0, import_react6.useState)(null);
|
|
1895
|
-
const { convertZecToUsd } = useZcashPrice(showUsd);
|
|
1896
|
-
(0, import_react6.useEffect)(() => {
|
|
1897
|
-
const handleKeyDown = (e) => {
|
|
1898
|
-
if (e.key === "Escape" && isOpen) {
|
|
1899
|
-
onClose();
|
|
1900
|
-
}
|
|
1901
|
-
};
|
|
1902
|
-
window.addEventListener("keydown", handleKeyDown);
|
|
1903
|
-
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
1904
|
-
}, [isOpen, onClose]);
|
|
1905
|
-
const [mounted, setMounted] = (0, import_react6.useState)(false);
|
|
1906
|
-
(0, import_react6.useEffect)(() => {
|
|
1907
|
-
setMounted(true);
|
|
1908
|
-
}, []);
|
|
1909
|
-
if (!isOpen || !mounted) return null;
|
|
1910
|
-
const copyToClipboard = async (text, type) => {
|
|
1911
|
-
try {
|
|
1912
|
-
await navigator.clipboard.writeText(text);
|
|
1913
|
-
setCopiedType(type);
|
|
1914
|
-
setTimeout(() => setCopiedType(null), 2e3);
|
|
1915
|
-
} catch {
|
|
1916
|
-
}
|
|
1917
|
-
};
|
|
1918
|
-
const formatTime = (secs) => {
|
|
1919
|
-
const m = Math.floor(secs / 60);
|
|
1920
|
-
const s = secs % 60;
|
|
1921
|
-
return `${m}:${s < 10 ? "0" : ""}${s}`;
|
|
1922
|
-
};
|
|
1923
|
-
const usdValue = convertZecToUsd(amount);
|
|
1924
|
-
return (0, import_react_dom3.createPortal)(
|
|
1925
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "fixed inset-0 z-[99999] flex items-center justify-center p-4 sm:p-6 overflow-y-auto", children: [
|
|
1926
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1927
|
-
"div",
|
|
1928
|
-
{
|
|
1929
|
-
className: "fixed inset-0 bg-[#171717]/60 backdrop-blur-sm transition-opacity z-[99999]",
|
|
1930
|
-
onClick: onClose
|
|
1931
|
-
}
|
|
1932
|
-
),
|
|
1933
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "relative w-full max-w-lg bg-white rounded-xl border border-[#ededed] shadow-2xl overflow-hidden z-[100000] text-[#171717] font-sans animate-in fade-in zoom-in-95 duration-150", children: [
|
|
1934
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between px-6 py-4 border-b border-[#ededed] bg-[#fafafa]", children: [
|
|
1935
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2.5", children: [
|
|
1936
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "w-8 h-8 rounded-md bg-[#171717] flex items-center justify-center text-[#3ecf8e]", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Shield, { className: "w-4 h-4 fill-[#3ecf8e]" }) }),
|
|
1937
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
|
|
1938
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
1939
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-medium text-sm text-[#171717]", children: title }),
|
|
1940
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[10px] uppercase tracking-wider font-semibold px-2 py-0.5 rounded-full bg-[#3ecf8e]/15 text-[#24b47e] border border-[#3ecf8e]/30", children: isShielded ? "zk-Shielded" : "Transparent" }),
|
|
1941
|
-
network === "testnet" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[10px] uppercase tracking-wider font-semibold px-2 py-0.5 rounded-full bg-amber-100 text-amber-800 border border-amber-200", children: "Testnet" })
|
|
1942
|
-
] }),
|
|
1943
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-xs text-[#707070] mt-0.5", children: subtitle })
|
|
1944
|
-
] })
|
|
1945
|
-
] }),
|
|
1946
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1947
|
-
"button",
|
|
1948
|
-
{
|
|
1949
|
-
onClick: onClose,
|
|
1950
|
-
className: "p-1 rounded-md text-[#707070] hover:text-[#171717] hover:bg-[#ededed] transition-colors",
|
|
1951
|
-
"aria-label": "Close modal",
|
|
1952
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.X, { className: "w-4 h-4" })
|
|
1953
|
-
}
|
|
1954
|
-
)
|
|
1955
|
-
] }),
|
|
1956
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "px-6 py-2.5 bg-white border-b border-[#ededed] flex items-center justify-between text-xs", children: [
|
|
1957
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
1958
|
-
status === "pending" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1959
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "relative flex h-2 w-2", children: [
|
|
1960
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-[#3ecf8e] opacity-75" }),
|
|
1961
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-[#24b47e]" })
|
|
1962
|
-
] }),
|
|
1963
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[#707070]", children: "Listening for transaction..." })
|
|
1964
|
-
] }),
|
|
1965
|
-
status === "detected" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1966
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "relative flex h-2 w-2", children: [
|
|
1967
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-amber-400 opacity-75" }),
|
|
1968
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-amber-500" })
|
|
1969
|
-
] }),
|
|
1970
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-amber-800 font-medium", children: "Transaction spotted in mempool! Confirming..." })
|
|
1971
|
-
] }),
|
|
1972
|
-
status === "confirmed" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1973
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.CheckCircle2, { className: "w-4 h-4 text-[#24b47e]" }),
|
|
1974
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[#24b47e] font-medium", children: "Payment Confirmed On-Chain!" })
|
|
1975
|
-
] }),
|
|
1976
|
-
status === "expired" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1977
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.AlertCircle, { className: "w-4 h-4 text-rose-500" }),
|
|
1978
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-rose-600 font-medium", children: "Payment window expired" })
|
|
1979
|
-
] })
|
|
1980
|
-
] }),
|
|
1981
|
-
status === "pending" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-1 text-[#707070] font-mono text-[11px]", children: [
|
|
1982
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Clock, { className: "w-3 h-3" }),
|
|
1983
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: formatTime(secondsRemaining) })
|
|
1984
|
-
] })
|
|
1985
|
-
] }),
|
|
1986
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "p-6 space-y-5", children: status === "confirmed" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "py-6 text-center space-y-4", children: [
|
|
1987
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "w-16 h-16 mx-auto rounded-full bg-[#3ecf8e]/15 border border-[#3ecf8e]/40 flex items-center justify-center text-[#24b47e] animate-bounce", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.CheckCircle2, { className: "w-8 h-8" }) }),
|
|
1988
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
|
|
1989
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { className: "text-lg font-medium text-[#171717]", children: "Payment Received & Shielded!" }),
|
|
1990
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-xs text-[#707070] max-w-sm mx-auto mt-1", children: "Your transaction has been verified using zero-knowledge proofs. No sender or recipient address was leaked." })
|
|
1991
|
-
] }),
|
|
1992
|
-
txId && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "p-3 bg-[#fafafa] rounded-md border border-[#ededed] text-left", children: [
|
|
1993
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between text-[11px] text-[#707070] mb-1", children: [
|
|
1994
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Transaction Hash" }),
|
|
1995
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[#24b47e] font-mono", children: "Shielded Note" })
|
|
1996
|
-
] }),
|
|
1997
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "font-mono text-xs text-[#171717] break-all", children: txId })
|
|
1998
|
-
] }),
|
|
1999
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2000
|
-
"button",
|
|
2001
|
-
{
|
|
2002
|
-
onClick: onClose,
|
|
2003
|
-
className: "w-full py-2.5 px-4 rounded-md bg-[#3ecf8e] text-[#171717] font-medium text-sm hover:bg-[#24b47e] transition-colors",
|
|
2004
|
-
children: "Close & Return"
|
|
2005
|
-
}
|
|
2006
|
-
)
|
|
2007
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2008
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between p-4 bg-[#fafafa] rounded-lg border border-[#ededed]", children: [
|
|
2009
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
|
|
2010
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-xs text-[#707070] uppercase font-mono tracking-wider", children: "Total Amount" }),
|
|
2011
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-baseline gap-2 mt-0.5", children: [
|
|
2012
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-2xl font-semibold tracking-tight text-[#171717] font-mono", children: [
|
|
2013
|
-
amount,
|
|
2014
|
-
" ",
|
|
2015
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-sm font-normal text-[#707070]", children: "ZEC" })
|
|
2016
|
-
] }),
|
|
2017
|
-
usdValue && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-xs text-[#707070] font-mono", children: [
|
|
2018
|
-
"\u2248 $",
|
|
2019
|
-
usdValue,
|
|
2020
|
-
" USD"
|
|
2021
|
-
] })
|
|
2022
|
-
] })
|
|
2023
|
-
] }),
|
|
2024
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "text-right", children: [
|
|
2025
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[11px] text-[#707070] block font-mono", children: "Address Standard" }),
|
|
2026
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "inline-block mt-0.5 px-2 py-0.5 text-xs font-mono font-medium rounded bg-white border border-[#dfdfdf] text-[#171717]", children: addressType === "unified" ? "Unified (ZIP-316)" : addressType === "sapling" ? "Sapling (Shielded)" : "Transparent" })
|
|
2027
|
-
] })
|
|
2028
|
-
] }),
|
|
2029
|
-
message && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "px-3.5 py-2 bg-[#fafafa] rounded-md border border-[#ededed] text-xs text-[#707070]", children: [
|
|
2030
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-medium text-[#171717]", children: "Order Note: " }),
|
|
2031
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: message })
|
|
2032
|
-
] }),
|
|
2033
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col sm:flex-row items-center gap-5 p-4 rounded-lg border border-[#ededed] bg-white", children: [
|
|
2034
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex-shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CiceroQRCode, { value: zip321Uri, size: 150 }) }),
|
|
2035
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "space-y-3 w-full text-center sm:text-left", children: [
|
|
2036
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
|
|
2037
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("h4", { className: "text-sm font-medium text-[#171717] flex items-center justify-center sm:justify-start gap-1.5", children: [
|
|
2038
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Scan with Shielded Wallet" }),
|
|
2039
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Sparkles, { className: "w-3.5 h-3.5 text-[#3ecf8e]" })
|
|
2040
|
-
] }),
|
|
2041
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "text-xs text-[#707070] mt-0.5 leading-relaxed", children: [
|
|
2042
|
-
"Compatible with ",
|
|
2043
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { className: "text-[#171717]", children: "Zashi" }),
|
|
2044
|
-
", ",
|
|
2045
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { className: "text-[#171717]", children: "Ywallet" }),
|
|
2046
|
-
", or any ZIP-321 compliant Zcash wallet."
|
|
2047
|
-
] })
|
|
2048
|
-
] }),
|
|
2049
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2050
|
-
"a",
|
|
2051
|
-
{
|
|
2052
|
-
href: zip321Uri,
|
|
2053
|
-
className: "inline-flex items-center justify-center gap-1.5 w-full py-2 px-3 rounded-md bg-[#171717] text-white text-xs font-medium hover:bg-[#212121] transition-colors",
|
|
2054
|
-
children: [
|
|
2055
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Open in Mobile / Desktop Wallet" }),
|
|
2056
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.ExternalLink, { className: "w-3.5 h-3.5 text-[#3ecf8e]" })
|
|
2057
|
-
]
|
|
2058
|
-
}
|
|
2059
|
-
),
|
|
2060
|
-
zucchiniAvailable && onPayWithZucchini && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2061
|
-
"button",
|
|
2062
|
-
{
|
|
2063
|
-
onClick: onPayWithZucchini,
|
|
2064
|
-
disabled: zucchiniPaying,
|
|
2065
|
-
className: "inline-flex items-center justify-center gap-2 w-full py-2.5 px-3 rounded-md bg-[#3ecf8e] text-[#171717] text-xs font-semibold hover:bg-[#24b47e] transition-colors disabled:opacity-60 disabled:cursor-wait shadow-sm",
|
|
2066
|
-
children: zucchiniPaying ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2067
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-3.5 h-3.5 border-2 border-[#171717]/30 border-t-[#171717] rounded-full animate-spin" }),
|
|
2068
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Confirming in Zucchini..." })
|
|
2069
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2070
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-sm", children: "\u{1F952}" }),
|
|
2071
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Pay with Zucchini Wallet" })
|
|
2072
|
-
] })
|
|
2073
|
-
}
|
|
2074
|
-
),
|
|
2075
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2076
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2077
|
-
"button",
|
|
2078
|
-
{
|
|
2079
|
-
onClick: () => copyToClipboard(zip321Uri, "uri"),
|
|
2080
|
-
className: "flex-1 py-1.5 px-2.5 rounded-md border border-[#ededed] hover:border-[#dfdfdf] hover:bg-[#fafafa] text-xs font-medium text-[#171717] transition-colors flex items-center justify-center gap-1",
|
|
2081
|
-
children: copiedType === "uri" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2082
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Check, { className: "w-3 h-3 text-[#24b47e]" }),
|
|
2083
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[#24b47e]", children: "Copied URI" })
|
|
2084
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2085
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Copy, { className: "w-3 h-3 text-[#707070]" }),
|
|
2086
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Copy ZIP-321 URI" })
|
|
2087
|
-
] })
|
|
2088
|
-
}
|
|
2089
|
-
),
|
|
2090
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2091
|
-
"button",
|
|
2092
|
-
{
|
|
2093
|
-
onClick: () => copyToClipboard(recipient, "address"),
|
|
2094
|
-
className: "flex-1 py-1.5 px-2.5 rounded-md border border-[#ededed] hover:border-[#dfdfdf] hover:bg-[#fafafa] text-xs font-medium text-[#171717] transition-colors flex items-center justify-center gap-1",
|
|
2095
|
-
children: copiedType === "address" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2096
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Check, { className: "w-3 h-3 text-[#24b47e]" }),
|
|
2097
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[#24b47e]", children: "Copied Address" })
|
|
2098
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
2099
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Copy, { className: "w-3 h-3 text-[#707070]" }),
|
|
2100
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Copy Address" })
|
|
2101
|
-
] })
|
|
2102
|
-
}
|
|
2103
|
-
)
|
|
2104
|
-
] })
|
|
2105
|
-
] })
|
|
2106
|
-
] }),
|
|
2107
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "space-y-1.5 text-xs", children: [
|
|
2108
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between text-[#707070]", children: [
|
|
2109
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Recipient Address" }),
|
|
2110
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-mono text-[11px]", children: truncateAddress(recipient, 12, 10) })
|
|
2111
|
-
] }),
|
|
2112
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "p-2 bg-[#fafafa] rounded-md border border-[#ededed] font-mono text-[11px] text-[#171717] break-all select-all", children: recipient })
|
|
2113
|
-
] }),
|
|
2114
|
-
memo && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "space-y-1.5 text-xs p-3 rounded-md bg-[#fafafa] border border-[#ededed]", children: [
|
|
2115
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
2116
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "flex items-center gap-1.5 font-medium text-[#171717]", children: [
|
|
2117
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Lock, { className: "w-3 h-3 text-[#3ecf8e]" }),
|
|
2118
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Encrypted Memo" })
|
|
2119
|
-
] }),
|
|
2120
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "text-[10px] font-mono text-[#707070]", children: [
|
|
2121
|
-
memoValidation.byteLength,
|
|
2122
|
-
"/512 bytes"
|
|
2123
|
-
] })
|
|
2124
|
-
] }),
|
|
2125
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "font-mono text-xs text-[#171717] bg-white p-2 rounded border border-[#dfdfdf]", children: memo }),
|
|
2126
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-[11px] text-[#707070]", children: "Only the recipient holding the viewing/spending key can decrypt this message on-chain." })
|
|
2127
|
-
] }),
|
|
2128
|
-
memoValidation.warning && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "p-2.5 rounded-md bg-amber-50 border border-amber-200 text-amber-800 text-xs flex items-start gap-2", children: [
|
|
2129
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.AlertCircle, { className: "w-4 h-4 flex-shrink-0 mt-0.5 text-amber-600" }),
|
|
2130
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: memoValidation.warning })
|
|
2131
|
-
] }),
|
|
2132
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "pt-2 border-t border-[#ededed] flex items-center justify-between", children: [
|
|
2133
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-1.5 text-[11px] text-[#707070]", children: [
|
|
2134
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Zap, { className: "w-3 h-3 text-[#3ecf8e]" }),
|
|
2135
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "Demo Controls:" })
|
|
2136
|
-
] }),
|
|
2137
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2138
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2139
|
-
"button",
|
|
2140
|
-
{
|
|
2141
|
-
onClick: onSimulateDetection,
|
|
2142
|
-
className: "px-2.5 py-1 text-[11px] font-medium rounded border border-[#dfdfdf] hover:border-[#3ecf8e] hover:text-[#24b47e] bg-white text-[#171717] transition-colors",
|
|
2143
|
-
children: "Simulate Payment"
|
|
2144
|
-
}
|
|
2145
|
-
),
|
|
2146
|
-
status === "expired" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2147
|
-
"button",
|
|
2148
|
-
{
|
|
2149
|
-
onClick: onResetPayment,
|
|
2150
|
-
className: "px-2.5 py-1 text-[11px] font-medium rounded bg-[#171717] text-white hover:bg-[#212121] transition-colors",
|
|
2151
|
-
children: "Refresh"
|
|
2152
|
-
}
|
|
2153
|
-
)
|
|
2154
|
-
] })
|
|
2155
|
-
] })
|
|
2156
|
-
] }) })
|
|
2157
|
-
] })
|
|
2158
|
-
] }),
|
|
2159
|
-
document.body
|
|
2160
|
-
);
|
|
2161
|
-
};
|
|
2162
|
-
|
|
2163
|
-
// src/components/CiceroPayButton.tsx
|
|
2164
|
-
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
2165
|
-
var CiceroPayButton = ({
|
|
2166
|
-
recipient,
|
|
2167
|
-
amount,
|
|
2168
|
-
memo,
|
|
2169
|
-
message,
|
|
2170
|
-
label = "Pay with Zcash",
|
|
2171
|
-
network = "mainnet",
|
|
2172
|
-
variant = "primary",
|
|
2173
|
-
size = "md",
|
|
2174
|
-
showUsd = true,
|
|
2175
|
-
modalTitle,
|
|
2176
|
-
modalSubtitle,
|
|
2177
|
-
expiresInSeconds = 900,
|
|
2178
|
-
customRpcUrl,
|
|
2179
|
-
invoiceId,
|
|
2180
|
-
onSuccess,
|
|
2181
|
-
onError,
|
|
2182
|
-
onStatusChange,
|
|
2183
|
-
className = "",
|
|
2184
|
-
disabled = false
|
|
2185
|
-
}) => {
|
|
2186
|
-
const {
|
|
2187
|
-
status,
|
|
2188
|
-
txId,
|
|
2189
|
-
secondsRemaining,
|
|
2190
|
-
isModalOpen,
|
|
2191
|
-
openModal,
|
|
2192
|
-
closeModal,
|
|
2193
|
-
resetPayment,
|
|
2194
|
-
zip321Uri,
|
|
2195
|
-
addressType,
|
|
2196
|
-
isShielded,
|
|
2197
|
-
memoValidation,
|
|
2198
|
-
simulateDetection,
|
|
2199
|
-
zucchiniAvailable,
|
|
2200
|
-
zucchiniPaying,
|
|
2201
|
-
payWithZucchini
|
|
2202
|
-
} = useCiceroPayment({
|
|
2203
|
-
recipient,
|
|
2204
|
-
amount,
|
|
2205
|
-
memo,
|
|
2206
|
-
message,
|
|
2207
|
-
network,
|
|
2208
|
-
expiresInSeconds,
|
|
2209
|
-
invoiceId,
|
|
2210
|
-
customRpcUrl,
|
|
2211
|
-
onSuccess,
|
|
2212
|
-
onError,
|
|
2213
|
-
onStatusChange
|
|
2214
|
-
});
|
|
2215
|
-
const sizeClasses = {
|
|
2216
|
-
sm: "text-xs px-3 py-1.5 gap-1.5",
|
|
2217
|
-
md: "text-sm px-4 py-2 gap-2",
|
|
2218
|
-
lg: "text-base px-5 py-2.5 gap-2.5"
|
|
2219
|
-
}[size];
|
|
2220
|
-
const variantClasses = {
|
|
2221
|
-
// Signature Supabase emerald CTA: #3ecf8e background, #171717 text, 6px radius
|
|
2222
|
-
primary: "bg-[#3ecf8e] text-[#171717] hover:bg-[#24b47e] active:bg-[#24b47e] shadow-sm font-medium",
|
|
2223
|
-
// Secondary outline on white
|
|
2224
|
-
outline: "bg-white text-[#171717] border border-[#dfdfdf] hover:border-[#c7c7c7] hover:bg-[#fafafa] font-medium shadow-sm",
|
|
2225
|
-
// Dark canvas-night
|
|
2226
|
-
dark: "bg-[#1c1c1c] text-white hover:bg-[#242424] font-medium shadow-sm"
|
|
2227
|
-
}[variant];
|
|
2228
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
2229
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2230
|
-
"button",
|
|
2231
|
-
{
|
|
2232
|
-
type: "button",
|
|
2233
|
-
onClick: openModal,
|
|
2234
|
-
disabled,
|
|
2235
|
-
className: `inline-flex items-center justify-center rounded-[6px] transition-all duration-150 select-none disabled:opacity-50 disabled:cursor-not-allowed ${sizeClasses} ${variantClasses} ${className}`,
|
|
2236
|
-
children: [
|
|
2237
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2238
|
-
import_lucide_react5.Shield,
|
|
2239
|
-
{
|
|
2240
|
-
className: `flex-shrink-0 ${size === "sm" ? "w-3.5 h-3.5" : size === "lg" ? "w-5 h-5" : "w-4 h-4"} ${variant === "primary" ? "fill-[#171717]/20" : "text-[#3ecf8e]"}`
|
|
2241
|
-
}
|
|
2242
|
-
),
|
|
2243
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: label })
|
|
2244
|
-
]
|
|
2245
|
-
}
|
|
2246
|
-
),
|
|
2247
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2248
|
-
CiceroModal,
|
|
2249
|
-
{
|
|
2250
|
-
isOpen: isModalOpen,
|
|
2251
|
-
onClose: closeModal,
|
|
2252
|
-
recipient,
|
|
2253
|
-
amount,
|
|
2254
|
-
memo,
|
|
2255
|
-
message,
|
|
2256
|
-
network,
|
|
2257
|
-
status,
|
|
2258
|
-
txId,
|
|
2259
|
-
secondsRemaining,
|
|
2260
|
-
zip321Uri,
|
|
2261
|
-
addressType,
|
|
2262
|
-
isShielded,
|
|
2263
|
-
memoValidation,
|
|
2264
|
-
onSimulateDetection: simulateDetection,
|
|
2265
|
-
onResetPayment: resetPayment,
|
|
2266
|
-
title: modalTitle,
|
|
2267
|
-
subtitle: modalSubtitle,
|
|
2268
|
-
showUsd,
|
|
2269
|
-
zucchiniAvailable,
|
|
2270
|
-
zucchiniPaying,
|
|
2271
|
-
onPayWithZucchini: payWithZucchini
|
|
2272
|
-
}
|
|
2273
|
-
)
|
|
2274
|
-
] });
|
|
2275
|
-
};
|
|
2276
|
-
|
|
2277
|
-
// src/components/CiceroInvoice.tsx
|
|
2278
|
-
var import_react7 = require("react");
|
|
2279
|
-
var import_lucide_react6 = require("lucide-react");
|
|
2280
|
-
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
2281
|
-
var CiceroInvoice = ({
|
|
2282
|
-
recipient,
|
|
2283
|
-
amount,
|
|
2284
|
-
memo,
|
|
2285
|
-
message,
|
|
2286
|
-
network = "mainnet",
|
|
2287
|
-
expiresInSeconds = 900,
|
|
2288
|
-
showUsd = true,
|
|
2289
|
-
invoiceId,
|
|
2290
|
-
customRpcUrl,
|
|
2291
|
-
onSuccess,
|
|
2292
|
-
onError,
|
|
2293
|
-
onStatusChange,
|
|
2294
|
-
className = ""
|
|
2295
|
-
}) => {
|
|
2296
|
-
const [copiedType, setCopiedType] = (0, import_react7.useState)(null);
|
|
2297
|
-
const { convertZecToUsd } = useZcashPrice(showUsd);
|
|
2298
|
-
const {
|
|
2299
|
-
status,
|
|
2300
|
-
txId,
|
|
2301
|
-
secondsRemaining,
|
|
2302
|
-
zip321Uri,
|
|
2303
|
-
addressType,
|
|
2304
|
-
isShielded,
|
|
2305
|
-
memoValidation,
|
|
2306
|
-
simulateDetection,
|
|
2307
|
-
resetPayment,
|
|
2308
|
-
zucchiniAvailable,
|
|
2309
|
-
zucchiniPaying,
|
|
2310
|
-
payWithZucchini
|
|
2311
|
-
} = useCiceroPayment({
|
|
2312
|
-
recipient,
|
|
2313
|
-
amount,
|
|
2314
|
-
memo,
|
|
2315
|
-
message,
|
|
2316
|
-
network,
|
|
2317
|
-
expiresInSeconds,
|
|
2318
|
-
invoiceId,
|
|
2319
|
-
customRpcUrl,
|
|
2320
|
-
onSuccess,
|
|
2321
|
-
onError,
|
|
2322
|
-
onStatusChange
|
|
2323
|
-
});
|
|
2324
|
-
const copyToClipboard = async (text, type) => {
|
|
2325
|
-
try {
|
|
2326
|
-
await navigator.clipboard.writeText(text);
|
|
2327
|
-
setCopiedType(type);
|
|
2328
|
-
setTimeout(() => setCopiedType(null), 2e3);
|
|
2329
|
-
} catch {
|
|
2330
|
-
}
|
|
2331
|
-
};
|
|
2332
|
-
const formatTime = (secs) => {
|
|
2333
|
-
const m = Math.floor(secs / 60);
|
|
2334
|
-
const s = secs % 60;
|
|
2335
|
-
return `${m}:${s < 10 ? "0" : ""}${s}`;
|
|
2336
|
-
};
|
|
2337
|
-
const usdValue = convertZecToUsd(amount);
|
|
2338
|
-
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2339
|
-
"div",
|
|
2340
|
-
{
|
|
2341
|
-
className: `bg-white rounded-xl border border-[#ededed] shadow-sm overflow-hidden text-[#171717] font-sans ${className}`,
|
|
2342
|
-
children: [
|
|
2343
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center justify-between px-5 py-3.5 border-b border-[#ededed] bg-[#fafafa]", children: [
|
|
2344
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2345
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "w-7 h-7 rounded-md bg-[#171717] flex items-center justify-center text-[#3ecf8e]", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react6.Shield, { className: "w-3.5 h-3.5 fill-[#3ecf8e]" }) }),
|
|
2346
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
|
|
2347
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "font-medium text-xs text-[#171717]", children: "Shielded Zcash Invoice" }),
|
|
2348
|
-
invoiceId && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "text-[10px] text-[#707070] ml-2 font-mono", children: [
|
|
2349
|
-
"#",
|
|
2350
|
-
invoiceId
|
|
2351
|
-
] })
|
|
2352
|
-
] })
|
|
2353
|
-
] }),
|
|
2354
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2355
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[10px] font-mono px-1.5 py-0.5 rounded bg-white border border-[#dfdfdf] text-[#171717]", children: addressType === "unified" ? "Unified" : addressType === "sapling" ? "Sapling" : "Transparent" }),
|
|
2356
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[10px] uppercase tracking-wider font-semibold px-2 py-0.5 rounded-full bg-[#3ecf8e]/15 text-[#24b47e] border border-[#3ecf8e]/30", children: isShielded ? "zk-Shielded" : "Transparent" }),
|
|
2357
|
-
network === "testnet" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[10px] uppercase tracking-wider font-semibold px-2 py-0.5 rounded-full bg-amber-100 text-amber-800 border border-amber-200", children: "Testnet" })
|
|
2358
|
-
] })
|
|
2359
|
-
] }),
|
|
2360
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "p-5 space-y-4", children: status === "confirmed" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "py-6 text-center space-y-3", children: [
|
|
2361
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "w-12 h-12 mx-auto rounded-full bg-[#3ecf8e]/15 border border-[#3ecf8e]/40 flex items-center justify-center text-[#24b47e]", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react6.CheckCircle2, { className: "w-6 h-6" }) }),
|
|
2362
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
|
|
2363
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h4", { className: "font-medium text-sm text-[#171717]", children: "Payment Verified!" }),
|
|
2364
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-xs text-[#707070] mt-0.5", children: "Shielded transaction detected and settled on-chain." })
|
|
2365
|
-
] }),
|
|
2366
|
-
txId && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "font-mono text-[11px] p-2 bg-[#fafafa] rounded border border-[#ededed] text-[#707070] break-all", children: txId })
|
|
2367
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2368
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center justify-between p-3.5 bg-[#fafafa] rounded-lg border border-[#ededed]", children: [
|
|
2369
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
|
|
2370
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[10px] text-[#707070] uppercase font-mono tracking-wider", children: "Amount Due" }),
|
|
2371
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-baseline gap-2 mt-0.5", children: [
|
|
2372
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "text-xl font-semibold tracking-tight text-[#171717] font-mono", children: [
|
|
2373
|
-
amount,
|
|
2374
|
-
" ",
|
|
2375
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-xs font-normal text-[#707070]", children: "ZEC" })
|
|
2376
|
-
] }),
|
|
2377
|
-
usdValue && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "text-xs text-[#707070] font-mono", children: [
|
|
2378
|
-
"\u2248 $",
|
|
2379
|
-
usdValue,
|
|
2380
|
-
" USD"
|
|
2381
|
-
] })
|
|
2382
|
-
] })
|
|
2383
|
-
] }),
|
|
2384
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-1.5 text-[#707070] font-mono text-xs", children: [
|
|
2385
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react6.Clock, { className: "w-3.5 h-3.5" }),
|
|
2386
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: formatTime(secondsRemaining) })
|
|
2387
|
-
] })
|
|
2388
|
-
] }),
|
|
2389
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-col sm:flex-row items-center gap-4", children: [
|
|
2390
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CiceroQRCode, { value: zip321Uri, size: 140 }),
|
|
2391
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-2.5 w-full", children: [
|
|
2392
|
-
zucchiniAvailable && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2393
|
-
"button",
|
|
2394
|
-
{
|
|
2395
|
-
onClick: payWithZucchini,
|
|
2396
|
-
disabled: zucchiniPaying,
|
|
2397
|
-
className: "inline-flex items-center justify-center gap-1.5 w-full py-2 px-3 rounded-md bg-[#3ecf8e] text-[#171717] text-xs font-semibold hover:bg-[#24b47e] transition-colors disabled:opacity-60 shadow-sm",
|
|
2398
|
-
children: zucchiniPaying ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2399
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "w-3.5 h-3.5 border-2 border-[#171717]/30 border-t-[#171717] rounded-full animate-spin" }),
|
|
2400
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Confirming in Zucchini..." })
|
|
2401
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
2402
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "\u{1F952}" }),
|
|
2403
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Pay with Zucchini Wallet" })
|
|
2404
|
-
] })
|
|
2405
|
-
}
|
|
2406
|
-
),
|
|
2407
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2408
|
-
"a",
|
|
2409
|
-
{
|
|
2410
|
-
href: zip321Uri,
|
|
2411
|
-
className: "inline-flex items-center justify-center gap-1.5 w-full py-2 px-3 rounded-md bg-[#171717] text-white text-xs font-medium hover:bg-[#212121] transition-colors",
|
|
2412
|
-
children: [
|
|
2413
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Pay with Wallet App" }),
|
|
2414
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react6.ExternalLink, { className: "w-3.5 h-3.5 text-[#3ecf8e]" })
|
|
2415
|
-
]
|
|
2416
|
-
}
|
|
2417
|
-
),
|
|
2418
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
2419
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2420
|
-
"button",
|
|
2421
|
-
{
|
|
2422
|
-
onClick: () => copyToClipboard(zip321Uri, "uri"),
|
|
2423
|
-
className: "py-1.5 px-2 rounded-md border border-[#ededed] hover:bg-[#fafafa] text-[11px] font-medium text-[#171717] transition-colors flex items-center justify-center gap-1",
|
|
2424
|
-
children: [
|
|
2425
|
-
copiedType === "uri" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react6.Check, { className: "w-3 h-3 text-[#24b47e]" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react6.Copy, { className: "w-3 h-3 text-[#707070]" }),
|
|
2426
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: copiedType === "uri" ? "Copied" : "Copy URI" })
|
|
2427
|
-
]
|
|
2428
|
-
}
|
|
2429
|
-
),
|
|
2430
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2431
|
-
"button",
|
|
2432
|
-
{
|
|
2433
|
-
onClick: () => copyToClipboard(recipient, "address"),
|
|
2434
|
-
className: "py-1.5 px-2 rounded-md border border-[#ededed] hover:bg-[#fafafa] text-[11px] font-medium text-[#171717] transition-colors flex items-center justify-center gap-1",
|
|
2435
|
-
children: [
|
|
2436
|
-
copiedType === "address" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react6.Check, { className: "w-3 h-3 text-[#24b47e]" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react6.Copy, { className: "w-3 h-3 text-[#707070]" }),
|
|
2437
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: copiedType === "address" ? "Copied" : "Copy Addr" })
|
|
2438
|
-
]
|
|
2439
|
-
}
|
|
2440
|
-
)
|
|
2441
|
-
] }),
|
|
2442
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "text-[11px] text-[#707070] font-mono truncate", children: [
|
|
2443
|
-
"To: ",
|
|
2444
|
-
truncateAddress(recipient, 10, 8)
|
|
2445
|
-
] })
|
|
2446
|
-
] })
|
|
2447
|
-
] }),
|
|
2448
|
-
memo && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "p-2.5 bg-[#fafafa] rounded-md border border-[#ededed] text-xs", children: [
|
|
2449
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-1 text-[11px] font-medium text-[#171717] mb-0.5", children: [
|
|
2450
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react6.Lock, { className: "w-3 h-3 text-[#3ecf8e]" }),
|
|
2451
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Encrypted Memo" })
|
|
2452
|
-
] }),
|
|
2453
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "font-mono text-[11px] text-[#171717]", children: memo })
|
|
2454
|
-
] }),
|
|
2455
|
-
memoValidation.warning && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "p-2 rounded bg-amber-50 border border-amber-200 text-amber-800 text-[11px] flex items-start gap-1.5", children: [
|
|
2456
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react6.AlertCircle, { className: "w-3.5 h-3.5 flex-shrink-0 mt-0.5 text-amber-600" }),
|
|
2457
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: memoValidation.warning })
|
|
2458
|
-
] }),
|
|
2459
|
-
status === "expired" && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "p-2 rounded bg-rose-50 border border-rose-200 text-rose-800 text-xs flex items-center justify-between", children: [
|
|
2460
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
2461
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react6.AlertCircle, { className: "w-3.5 h-3.5 text-rose-600" }),
|
|
2462
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Invoice has expired" })
|
|
2463
|
-
] }),
|
|
2464
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2465
|
-
"button",
|
|
2466
|
-
{
|
|
2467
|
-
onClick: resetPayment,
|
|
2468
|
-
className: "px-2 py-0.5 text-[11px] font-medium rounded bg-[#171717] text-white hover:bg-[#212121]",
|
|
2469
|
-
children: "Reset"
|
|
2470
|
-
}
|
|
2471
|
-
)
|
|
2472
|
-
] }),
|
|
2473
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "pt-2 border-t border-[#ededed] flex items-center justify-between text-[11px] text-[#707070]", children: [
|
|
2474
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "flex items-center gap-1", children: [
|
|
2475
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react6.Sparkles, { className: "w-3 h-3 text-[#3ecf8e]" }),
|
|
2476
|
-
"Demo test"
|
|
2477
|
-
] }),
|
|
2478
|
-
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2479
|
-
"button",
|
|
2480
|
-
{
|
|
2481
|
-
onClick: simulateDetection,
|
|
2482
|
-
className: "px-2 py-0.5 rounded border border-[#dfdfdf] hover:border-[#3ecf8e] text-[#171717] bg-white transition-colors",
|
|
2483
|
-
children: "Simulate Success"
|
|
2484
|
-
}
|
|
2485
|
-
)
|
|
2486
|
-
] })
|
|
2487
|
-
] }) })
|
|
2488
|
-
]
|
|
2489
|
-
}
|
|
2490
|
-
);
|
|
2491
|
-
};
|
|
2492
|
-
|
|
2493
1894
|
// src/hooks/useZucchiniWallet.ts
|
|
2494
|
-
var
|
|
1895
|
+
var import_react5 = require("react");
|
|
2495
1896
|
function useZucchiniWallet(options = {}) {
|
|
2496
1897
|
const { autoConnect = false } = options;
|
|
2497
|
-
const [adapter2] = (0,
|
|
2498
|
-
const [isAvailable, setIsAvailable] = (0,
|
|
2499
|
-
const [connectionStatus, setConnectionStatus] = (0,
|
|
2500
|
-
const [paymentStatus, setPaymentStatus] = (0,
|
|
2501
|
-
const [session, setSession] = (0,
|
|
2502
|
-
const [error, setError] = (0,
|
|
2503
|
-
(0,
|
|
1898
|
+
const [adapter2] = (0, import_react5.useState)(() => new ZucchiniWalletAdapter());
|
|
1899
|
+
const [isAvailable, setIsAvailable] = (0, import_react5.useState)(false);
|
|
1900
|
+
const [connectionStatus, setConnectionStatus] = (0, import_react5.useState)("disconnected");
|
|
1901
|
+
const [paymentStatus, setPaymentStatus] = (0, import_react5.useState)("idle");
|
|
1902
|
+
const [session, setSession] = (0, import_react5.useState)(null);
|
|
1903
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
1904
|
+
(0, import_react5.useEffect)(() => {
|
|
2504
1905
|
const detected = ZucchiniWalletAdapter.isAvailable();
|
|
2505
1906
|
setIsAvailable(detected);
|
|
2506
1907
|
if (detected && autoConnect) {
|
|
2507
1908
|
connect();
|
|
2508
1909
|
}
|
|
2509
1910
|
}, []);
|
|
2510
|
-
const connect = (0,
|
|
1911
|
+
const connect = (0, import_react5.useCallback)(async () => {
|
|
2511
1912
|
setConnectionStatus("connecting");
|
|
2512
1913
|
setError(null);
|
|
2513
1914
|
try {
|
|
@@ -2522,7 +1923,7 @@ function useZucchiniWallet(options = {}) {
|
|
|
2522
1923
|
throw err;
|
|
2523
1924
|
}
|
|
2524
1925
|
}, [adapter2]);
|
|
2525
|
-
const requestPayment = (0,
|
|
1926
|
+
const requestPayment = (0, import_react5.useCallback)(
|
|
2526
1927
|
async (params) => {
|
|
2527
1928
|
setPaymentStatus("requesting");
|
|
2528
1929
|
setError(null);
|
|
@@ -2539,7 +1940,7 @@ function useZucchiniWallet(options = {}) {
|
|
|
2539
1940
|
},
|
|
2540
1941
|
[adapter2]
|
|
2541
1942
|
);
|
|
2542
|
-
const disconnect = (0,
|
|
1943
|
+
const disconnect = (0, import_react5.useCallback)(async () => {
|
|
2543
1944
|
await adapter2.disconnect();
|
|
2544
1945
|
setSession(null);
|
|
2545
1946
|
setConnectionStatus("disconnected");
|
|
@@ -2569,9 +1970,6 @@ function useZucchiniWallet(options = {}) {
|
|
|
2569
1970
|
CiceroAccountModal,
|
|
2570
1971
|
CiceroConnectButton,
|
|
2571
1972
|
CiceroConnectModal,
|
|
2572
|
-
CiceroInvoice,
|
|
2573
|
-
CiceroModal,
|
|
2574
|
-
CiceroPayButton,
|
|
2575
1973
|
CiceroProvider,
|
|
2576
1974
|
CiceroQRCode,
|
|
2577
1975
|
ZucchiniWalletAdapter,
|
|
@@ -2589,7 +1987,6 @@ function useZucchiniWallet(options = {}) {
|
|
|
2589
1987
|
useAccountModal,
|
|
2590
1988
|
useBalance,
|
|
2591
1989
|
useCicero,
|
|
2592
|
-
useCiceroPayment,
|
|
2593
1990
|
useConnectModal,
|
|
2594
1991
|
useZcashPrice,
|
|
2595
1992
|
useZucchiniWallet,
|