@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.mjs
CHANGED
|
@@ -235,15 +235,99 @@ var ZucchiniWalletAdapter = class _ZucchiniWalletAdapter {
|
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
this._lastAccounts = connection?.accounts || [];
|
|
238
|
-
const
|
|
238
|
+
const network = await this.getNetwork();
|
|
239
|
+
const balance = await this.getBalance({ address, network });
|
|
239
240
|
this._connected = true;
|
|
240
241
|
this._address = address || null;
|
|
241
242
|
return {
|
|
242
243
|
address,
|
|
243
244
|
connected: true,
|
|
245
|
+
network,
|
|
244
246
|
balance: balance ?? void 0
|
|
245
247
|
};
|
|
246
248
|
}
|
|
249
|
+
/**
|
|
250
|
+
* Queries the active network of the Zucchini Wallet ('mainnet' | 'testnet').
|
|
251
|
+
*/
|
|
252
|
+
async getNetwork() {
|
|
253
|
+
try {
|
|
254
|
+
const client = await this.getClient();
|
|
255
|
+
if (typeof client.network === "function") {
|
|
256
|
+
const net = await client.network();
|
|
257
|
+
if (net === "mainnet" || net === "testnet") {
|
|
258
|
+
return net;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
} catch {
|
|
262
|
+
}
|
|
263
|
+
const raw = this.provider || (typeof window !== "undefined" ? window.zucchini || window.zcash : null);
|
|
264
|
+
if (raw && typeof raw.request === "function") {
|
|
265
|
+
try {
|
|
266
|
+
const res = await raw.request({ method: "getNetwork" });
|
|
267
|
+
if (res?.network === "main" || res === "main" || res === "mainnet") return "mainnet";
|
|
268
|
+
if (res?.network === "test" || res === "test" || res === "testnet") return "testnet";
|
|
269
|
+
} catch {
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (this._address) {
|
|
273
|
+
if (this._address.startsWith("utest1") || this._address.startsWith("ztestsapling") || this._address.startsWith("tm")) {
|
|
274
|
+
return "testnet";
|
|
275
|
+
}
|
|
276
|
+
if (this._address.startsWith("u1") || this._address.startsWith("zs1") || this._address.startsWith("t1")) {
|
|
277
|
+
return "mainnet";
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return "mainnet";
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Requests a network change. If the extension does not support programmatic
|
|
284
|
+
* switching, informs the application that manual user toggle is needed.
|
|
285
|
+
*/
|
|
286
|
+
async switchNetwork(targetNetwork) {
|
|
287
|
+
const current = await this.getNetwork();
|
|
288
|
+
if (current === targetNetwork) {
|
|
289
|
+
return { success: true, currentNetwork: current };
|
|
290
|
+
}
|
|
291
|
+
const raw = this.provider || (typeof window !== "undefined" ? window.zucchini || window.zcash : null);
|
|
292
|
+
if (raw && typeof raw.request === "function") {
|
|
293
|
+
try {
|
|
294
|
+
await raw.request({
|
|
295
|
+
method: "switchNetwork",
|
|
296
|
+
params: { network: targetNetwork === "mainnet" ? "main" : "test" }
|
|
297
|
+
});
|
|
298
|
+
const updated = await this.getNetwork();
|
|
299
|
+
return { success: updated === targetNetwork, currentNetwork: updated };
|
|
300
|
+
} catch {
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return {
|
|
304
|
+
success: false,
|
|
305
|
+
requiresManualSwitch: true,
|
|
306
|
+
currentNetwork: current
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Subscribes to network change events from the wallet extension.
|
|
311
|
+
*/
|
|
312
|
+
onNetworkChanged(listener) {
|
|
313
|
+
const raw = this.provider || (typeof window !== "undefined" ? window.zucchini || window.zcash : null);
|
|
314
|
+
const handler = async () => {
|
|
315
|
+
const net = await this.getNetwork();
|
|
316
|
+
listener(net);
|
|
317
|
+
};
|
|
318
|
+
if (raw?.on) {
|
|
319
|
+
raw.on("networkChanged", handler);
|
|
320
|
+
raw.on("chainChanged", handler);
|
|
321
|
+
raw.on("accountsChanged", handler);
|
|
322
|
+
return () => {
|
|
323
|
+
raw.off?.("networkChanged", handler);
|
|
324
|
+
raw.off?.("chainChanged", handler);
|
|
325
|
+
raw.off?.("accountsChanged", handler);
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
return () => {
|
|
329
|
+
};
|
|
330
|
+
}
|
|
247
331
|
/**
|
|
248
332
|
* Helper to normalize raw balance formats (e.g. number, string, zatoshis, or pool totals).
|
|
249
333
|
*/
|
|
@@ -411,7 +495,7 @@ var zucchiniWallet = {
|
|
|
411
495
|
return {
|
|
412
496
|
address: session.address,
|
|
413
497
|
connected: true,
|
|
414
|
-
network: options?.network || "mainnet",
|
|
498
|
+
network: session.network || options?.network || "mainnet",
|
|
415
499
|
walletId: "zucchini",
|
|
416
500
|
balance: session.balance
|
|
417
501
|
};
|
|
@@ -422,6 +506,12 @@ var zucchiniWallet = {
|
|
|
422
506
|
getBalance: async (options) => {
|
|
423
507
|
return adapter.getBalance(options);
|
|
424
508
|
},
|
|
509
|
+
getNetwork: async () => {
|
|
510
|
+
return adapter.getNetwork();
|
|
511
|
+
},
|
|
512
|
+
switchNetwork: async (network) => {
|
|
513
|
+
return adapter.switchNetwork(network);
|
|
514
|
+
},
|
|
425
515
|
sendPayment: async (params) => {
|
|
426
516
|
const res = await adapter.requestPayment({
|
|
427
517
|
recipient: params.recipient,
|
|
@@ -1038,9 +1128,27 @@ var CiceroAccountModal = ({
|
|
|
1038
1128
|
const [copied, setCopied] = useState3(false);
|
|
1039
1129
|
const [showQr, setShowQr] = useState3(false);
|
|
1040
1130
|
const [mounted, setMounted] = useState3(false);
|
|
1131
|
+
const [manualNotice, setManualNotice] = useState3(null);
|
|
1041
1132
|
useEffect3(() => {
|
|
1042
1133
|
setMounted(true);
|
|
1043
1134
|
}, []);
|
|
1135
|
+
useEffect3(() => {
|
|
1136
|
+
setManualNotice(null);
|
|
1137
|
+
}, [network, isOpen]);
|
|
1138
|
+
const handleNetworkChange = async (targetNet) => {
|
|
1139
|
+
if (targetNet === network) {
|
|
1140
|
+
setManualNotice(null);
|
|
1141
|
+
return;
|
|
1142
|
+
}
|
|
1143
|
+
const res = await switchNetwork(targetNet);
|
|
1144
|
+
if (res?.requiresManualSwitch) {
|
|
1145
|
+
setManualNotice(
|
|
1146
|
+
`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.`
|
|
1147
|
+
);
|
|
1148
|
+
} else {
|
|
1149
|
+
setManualNotice(null);
|
|
1150
|
+
}
|
|
1151
|
+
};
|
|
1044
1152
|
useEffect3(() => {
|
|
1045
1153
|
const handleKeyDown = (e) => {
|
|
1046
1154
|
if (e.key === "Escape" && isOpen) {
|
|
@@ -1167,29 +1275,34 @@ var CiceroAccountModal = ({
|
|
|
1167
1275
|
)
|
|
1168
1276
|
] })
|
|
1169
1277
|
] }),
|
|
1170
|
-
/* @__PURE__ */ jsxs2("div", { className: "
|
|
1171
|
-
/* @__PURE__ */ jsxs2("div", { className: "flex items-center
|
|
1172
|
-
/* @__PURE__ */
|
|
1173
|
-
|
|
1278
|
+
/* @__PURE__ */ jsxs2("div", { className: "space-y-2", children: [
|
|
1279
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between p-3 rounded-lg border border-[#ededed] bg-white text-xs", children: [
|
|
1280
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2", children: [
|
|
1281
|
+
/* @__PURE__ */ jsx3(ArrowRightLeft, { className: "w-4 h-4 text-[#707070]" }),
|
|
1282
|
+
/* @__PURE__ */ jsx3("span", { className: "text-[#171717] font-medium", children: "Active Network" })
|
|
1283
|
+
] }),
|
|
1284
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-1 p-0.5 rounded bg-[#fafafa] border border-[#dfdfdf]", children: [
|
|
1285
|
+
/* @__PURE__ */ jsx3(
|
|
1286
|
+
"button",
|
|
1287
|
+
{
|
|
1288
|
+
type: "button",
|
|
1289
|
+
onClick: () => handleNetworkChange("mainnet"),
|
|
1290
|
+
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]"}`,
|
|
1291
|
+
children: "Mainnet"
|
|
1292
|
+
}
|
|
1293
|
+
),
|
|
1294
|
+
/* @__PURE__ */ jsx3(
|
|
1295
|
+
"button",
|
|
1296
|
+
{
|
|
1297
|
+
type: "button",
|
|
1298
|
+
onClick: () => handleNetworkChange("testnet"),
|
|
1299
|
+
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]"}`,
|
|
1300
|
+
children: "Testnet"
|
|
1301
|
+
}
|
|
1302
|
+
)
|
|
1303
|
+
] })
|
|
1174
1304
|
] }),
|
|
1175
|
-
/* @__PURE__ */
|
|
1176
|
-
/* @__PURE__ */ jsx3(
|
|
1177
|
-
"button",
|
|
1178
|
-
{
|
|
1179
|
-
onClick: () => switchNetwork("mainnet"),
|
|
1180
|
-
className: `px-2 py-1 rounded text-[11px] font-medium transition-colors ${network === "mainnet" ? "bg-white shadow-sm text-[#24b47e] font-semibold" : "text-[#707070]"}`,
|
|
1181
|
-
children: "Mainnet"
|
|
1182
|
-
}
|
|
1183
|
-
),
|
|
1184
|
-
/* @__PURE__ */ jsx3(
|
|
1185
|
-
"button",
|
|
1186
|
-
{
|
|
1187
|
-
onClick: () => switchNetwork("testnet"),
|
|
1188
|
-
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]"}`,
|
|
1189
|
-
children: "Testnet"
|
|
1190
|
-
}
|
|
1191
|
-
)
|
|
1192
|
-
] })
|
|
1305
|
+
manualNotice && /* @__PURE__ */ jsx3("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__ */ jsx3("span", { children: manualNotice }) })
|
|
1193
1306
|
] })
|
|
1194
1307
|
] }),
|
|
1195
1308
|
/* @__PURE__ */ jsxs2("div", { className: "px-6 py-3.5 bg-[#fafafa] border-t border-[#ededed] flex items-center justify-between", children: [
|
|
@@ -1324,6 +1437,36 @@ var CiceroProvider = ({
|
|
|
1324
1437
|
cleanupReady();
|
|
1325
1438
|
};
|
|
1326
1439
|
}, [autoConnect]);
|
|
1440
|
+
useEffect4(() => {
|
|
1441
|
+
if (typeof window === "undefined") return;
|
|
1442
|
+
const adapter2 = new ZucchiniWalletAdapter();
|
|
1443
|
+
const cleanup = adapter2.onNetworkChanged(async (detectedNet) => {
|
|
1444
|
+
setNetwork(detectedNet);
|
|
1445
|
+
localStorage.setItem("cicero_network", detectedNet);
|
|
1446
|
+
if (account.wallet?.id === "zucchini") {
|
|
1447
|
+
setBalance((prev) => ({ ...prev, isLoading: true }));
|
|
1448
|
+
try {
|
|
1449
|
+
const freshBal = await adapter2.getBalance({
|
|
1450
|
+
address: account.address || void 0,
|
|
1451
|
+
network: detectedNet
|
|
1452
|
+
});
|
|
1453
|
+
const activeZec = freshBal !== null && !isNaN(freshBal) ? freshBal : 0;
|
|
1454
|
+
setBalance({
|
|
1455
|
+
zec: activeZec,
|
|
1456
|
+
usd: convertZecToUsdRef.current(activeZec),
|
|
1457
|
+
isLoading: false
|
|
1458
|
+
});
|
|
1459
|
+
localStorage.setItem("cicero_balance", activeZec.toString());
|
|
1460
|
+
localStorage.setItem(`cicero_balance_${detectedNet}`, activeZec.toString());
|
|
1461
|
+
} catch {
|
|
1462
|
+
setBalance((prev) => ({ ...prev, isLoading: false }));
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
});
|
|
1466
|
+
return () => {
|
|
1467
|
+
cleanup();
|
|
1468
|
+
};
|
|
1469
|
+
}, [account.wallet?.id, account.address]);
|
|
1327
1470
|
useEffect4(() => {
|
|
1328
1471
|
if (account.isConnected) {
|
|
1329
1472
|
setBalance((prev) => {
|
|
@@ -1336,12 +1479,55 @@ var CiceroProvider = ({
|
|
|
1336
1479
|
});
|
|
1337
1480
|
}
|
|
1338
1481
|
}, [account.isConnected, balance.zec, convertZecToUsd]);
|
|
1339
|
-
const switchNetwork = useCallback2(
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1482
|
+
const switchNetwork = useCallback2(
|
|
1483
|
+
async (newNet) => {
|
|
1484
|
+
if (account.wallet?.switchNetwork) {
|
|
1485
|
+
try {
|
|
1486
|
+
const switchRes = await account.wallet.switchNetwork(newNet);
|
|
1487
|
+
if (switchRes && switchRes.requiresManualSwitch) {
|
|
1488
|
+
const currentNet = switchRes.currentNetwork || (account.wallet.getNetwork ? await account.wallet.getNetwork() : network);
|
|
1489
|
+
setNetwork(currentNet);
|
|
1490
|
+
if (typeof window !== "undefined") {
|
|
1491
|
+
localStorage.setItem("cicero_network", currentNet);
|
|
1492
|
+
}
|
|
1493
|
+
return {
|
|
1494
|
+
success: false,
|
|
1495
|
+
requiresManualSwitch: true,
|
|
1496
|
+
currentNetwork: currentNet
|
|
1497
|
+
};
|
|
1498
|
+
}
|
|
1499
|
+
} catch {
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
setNetwork(newNet);
|
|
1503
|
+
if (typeof window !== "undefined") {
|
|
1504
|
+
localStorage.setItem("cicero_network", newNet);
|
|
1505
|
+
}
|
|
1506
|
+
if (account.wallet?.getBalance) {
|
|
1507
|
+
setBalance((prev) => ({ ...prev, isLoading: true }));
|
|
1508
|
+
try {
|
|
1509
|
+
const freshBal = await account.wallet.getBalance({
|
|
1510
|
+
address: account.address || void 0,
|
|
1511
|
+
network: newNet
|
|
1512
|
+
});
|
|
1513
|
+
const activeZec = freshBal !== null && !isNaN(freshBal) ? freshBal : 0;
|
|
1514
|
+
setBalance({
|
|
1515
|
+
zec: activeZec,
|
|
1516
|
+
usd: convertZecToUsdRef.current(activeZec),
|
|
1517
|
+
isLoading: false
|
|
1518
|
+
});
|
|
1519
|
+
if (typeof window !== "undefined" && freshBal !== null) {
|
|
1520
|
+
localStorage.setItem(`cicero_balance_${newNet}`, freshBal.toString());
|
|
1521
|
+
localStorage.setItem("cicero_balance", freshBal.toString());
|
|
1522
|
+
}
|
|
1523
|
+
} catch {
|
|
1524
|
+
setBalance((prev) => ({ ...prev, isLoading: false }));
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
return { success: true, currentNetwork: newNet };
|
|
1528
|
+
},
|
|
1529
|
+
[account.wallet, account.address, network]
|
|
1530
|
+
);
|
|
1345
1531
|
const connect = useCallback2(
|
|
1346
1532
|
async (walletId, customAddressOrKey) => {
|
|
1347
1533
|
const targetWallet = wallets.find((w) => w.id === walletId);
|
|
@@ -1368,6 +1554,13 @@ var CiceroProvider = ({
|
|
|
1368
1554
|
session = await targetWallet.connect({ network });
|
|
1369
1555
|
}
|
|
1370
1556
|
const resolvedAddress = session.address || customAddressOrKey || null;
|
|
1557
|
+
const walletNetwork = session.network || (targetWallet.getNetwork ? await targetWallet.getNetwork() : network);
|
|
1558
|
+
if (walletNetwork && walletNetwork !== network) {
|
|
1559
|
+
setNetwork(walletNetwork);
|
|
1560
|
+
if (typeof window !== "undefined") {
|
|
1561
|
+
localStorage.setItem("cicero_network", walletNetwork);
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1371
1564
|
setAccount({
|
|
1372
1565
|
address: resolvedAddress,
|
|
1373
1566
|
viewingKey: session.viewingKey || null,
|
|
@@ -1660,834 +1853,24 @@ var CiceroConnectButton = ({
|
|
|
1660
1853
|
) });
|
|
1661
1854
|
};
|
|
1662
1855
|
|
|
1663
|
-
// src/components/CiceroPayButton.tsx
|
|
1664
|
-
import { Shield as Shield5 } from "lucide-react";
|
|
1665
|
-
|
|
1666
|
-
// src/hooks/useCiceroPayment.ts
|
|
1667
|
-
import { useState as useState5, useEffect as useEffect5, useCallback as useCallback3, useMemo as useMemo2, useRef as useRef2 } from "react";
|
|
1668
|
-
function useCiceroPayment({
|
|
1669
|
-
recipient,
|
|
1670
|
-
amount,
|
|
1671
|
-
memo,
|
|
1672
|
-
message,
|
|
1673
|
-
network = "mainnet",
|
|
1674
|
-
expiresInSeconds = 900,
|
|
1675
|
-
// 15 mins
|
|
1676
|
-
invoiceId,
|
|
1677
|
-
customRpcUrl,
|
|
1678
|
-
onSuccess,
|
|
1679
|
-
onError,
|
|
1680
|
-
onStatusChange
|
|
1681
|
-
}) {
|
|
1682
|
-
const onSuccessRef = useRef2(onSuccess);
|
|
1683
|
-
onSuccessRef.current = onSuccess;
|
|
1684
|
-
const onErrorRef = useRef2(onError);
|
|
1685
|
-
onErrorRef.current = onError;
|
|
1686
|
-
const onStatusChangeRef = useRef2(onStatusChange);
|
|
1687
|
-
onStatusChangeRef.current = onStatusChange;
|
|
1688
|
-
const [status, setStatus] = useState5("pending");
|
|
1689
|
-
const [txId, setTxId] = useState5(null);
|
|
1690
|
-
const [secondsRemaining, setSecondsRemaining] = useState5(expiresInSeconds);
|
|
1691
|
-
const [isModalOpen, setIsModalOpen] = useState5(false);
|
|
1692
|
-
const [zucchiniAvailable, setZucchiniAvailable] = useState5(false);
|
|
1693
|
-
const [zucchiniAdapter] = useState5(() => new ZucchiniWalletAdapter());
|
|
1694
|
-
const [zucchiniPaying, setZucchiniPaying] = useState5(false);
|
|
1695
|
-
useEffect5(() => {
|
|
1696
|
-
setZucchiniAvailable(ZucchiniWalletAdapter.isAvailable());
|
|
1697
|
-
}, []);
|
|
1698
|
-
const addressType = useMemo2(() => getAddressType(recipient), [recipient]);
|
|
1699
|
-
const isShielded = useMemo2(() => isShieldedAddress(recipient), [recipient]);
|
|
1700
|
-
const memoValidation = useMemo2(
|
|
1701
|
-
() => validateMemoSupport(recipient, memo),
|
|
1702
|
-
[recipient, memo]
|
|
1703
|
-
);
|
|
1704
|
-
const lastWarningRef = useRef2(null);
|
|
1705
|
-
useEffect5(() => {
|
|
1706
|
-
if (!memoValidation.valid && memoValidation.warning) {
|
|
1707
|
-
if (lastWarningRef.current !== memoValidation.warning) {
|
|
1708
|
-
lastWarningRef.current = memoValidation.warning;
|
|
1709
|
-
onErrorRef.current?.(new Error(memoValidation.warning));
|
|
1710
|
-
}
|
|
1711
|
-
} else {
|
|
1712
|
-
lastWarningRef.current = null;
|
|
1713
|
-
}
|
|
1714
|
-
}, [memoValidation.valid, memoValidation.warning]);
|
|
1715
|
-
const zip321Uri = useMemo2(() => {
|
|
1716
|
-
return generateZip321Uri({
|
|
1717
|
-
address: recipient,
|
|
1718
|
-
amount,
|
|
1719
|
-
memo,
|
|
1720
|
-
message
|
|
1721
|
-
});
|
|
1722
|
-
}, [recipient, amount, memo, message]);
|
|
1723
|
-
const deepLinks = useMemo2(() => getWalletDeepLinks(zip321Uri), [zip321Uri]);
|
|
1724
|
-
const updateStatus = useCallback3((newStatus) => {
|
|
1725
|
-
setStatus(newStatus);
|
|
1726
|
-
onStatusChangeRef.current?.(newStatus);
|
|
1727
|
-
}, []);
|
|
1728
|
-
useEffect5(() => {
|
|
1729
|
-
if (status !== "pending") return;
|
|
1730
|
-
const timer = setInterval(() => {
|
|
1731
|
-
setSecondsRemaining((prev) => {
|
|
1732
|
-
if (prev <= 1) {
|
|
1733
|
-
clearInterval(timer);
|
|
1734
|
-
updateStatus("expired");
|
|
1735
|
-
return 0;
|
|
1736
|
-
}
|
|
1737
|
-
return prev - 1;
|
|
1738
|
-
});
|
|
1739
|
-
}, 1e3);
|
|
1740
|
-
return () => clearInterval(timer);
|
|
1741
|
-
}, [status, updateStatus]);
|
|
1742
|
-
const resetPayment = useCallback3(() => {
|
|
1743
|
-
setStatus("pending");
|
|
1744
|
-
setTxId(null);
|
|
1745
|
-
setSecondsRemaining(expiresInSeconds);
|
|
1746
|
-
setZucchiniPaying(false);
|
|
1747
|
-
}, [expiresInSeconds]);
|
|
1748
|
-
const openModal = useCallback3(() => {
|
|
1749
|
-
resetPayment();
|
|
1750
|
-
setIsModalOpen(true);
|
|
1751
|
-
}, [resetPayment]);
|
|
1752
|
-
const closeModal = useCallback3(() => {
|
|
1753
|
-
setIsModalOpen(false);
|
|
1754
|
-
}, []);
|
|
1755
|
-
const payWithZucchini = useCallback3(async () => {
|
|
1756
|
-
setZucchiniPaying(true);
|
|
1757
|
-
try {
|
|
1758
|
-
await zucchiniAdapter.connect();
|
|
1759
|
-
const numAmount = typeof amount === "number" ? amount : parseFloat(amount);
|
|
1760
|
-
const result = await zucchiniAdapter.requestPayment({
|
|
1761
|
-
recipient,
|
|
1762
|
-
amount: numAmount,
|
|
1763
|
-
memo
|
|
1764
|
-
});
|
|
1765
|
-
updateStatus("detected");
|
|
1766
|
-
setTxId(result.txId);
|
|
1767
|
-
setTimeout(() => {
|
|
1768
|
-
updateStatus("confirmed");
|
|
1769
|
-
onSuccessRef.current?.({
|
|
1770
|
-
txId: result.txId,
|
|
1771
|
-
amount: isNaN(numAmount) ? 0 : numAmount,
|
|
1772
|
-
memo
|
|
1773
|
-
});
|
|
1774
|
-
setZucchiniPaying(false);
|
|
1775
|
-
}, 1500);
|
|
1776
|
-
} catch (err) {
|
|
1777
|
-
const error = err instanceof Error ? err : new Error("Zucchini payment failed");
|
|
1778
|
-
onErrorRef.current?.(error);
|
|
1779
|
-
setZucchiniPaying(false);
|
|
1780
|
-
}
|
|
1781
|
-
}, [recipient, amount, memo, zucchiniAdapter, updateStatus]);
|
|
1782
|
-
const simulateDetection = useCallback3(() => {
|
|
1783
|
-
updateStatus("detected");
|
|
1784
|
-
setTimeout(() => {
|
|
1785
|
-
const mockTxId = `0x${Array.from(
|
|
1786
|
-
{ length: 64 },
|
|
1787
|
-
() => Math.floor(Math.random() * 16).toString(16)
|
|
1788
|
-
).join("")}`;
|
|
1789
|
-
setTxId(mockTxId);
|
|
1790
|
-
updateStatus("confirmed");
|
|
1791
|
-
const numAmount = typeof amount === "number" ? amount : parseFloat(amount);
|
|
1792
|
-
onSuccessRef.current?.({
|
|
1793
|
-
txId: mockTxId,
|
|
1794
|
-
amount: isNaN(numAmount) ? 0 : numAmount,
|
|
1795
|
-
memo
|
|
1796
|
-
});
|
|
1797
|
-
}, 2e3);
|
|
1798
|
-
}, [amount, memo, updateStatus]);
|
|
1799
|
-
return {
|
|
1800
|
-
status,
|
|
1801
|
-
txId,
|
|
1802
|
-
secondsRemaining,
|
|
1803
|
-
isModalOpen,
|
|
1804
|
-
openModal,
|
|
1805
|
-
closeModal,
|
|
1806
|
-
resetPayment,
|
|
1807
|
-
zip321Uri,
|
|
1808
|
-
deepLinks,
|
|
1809
|
-
addressType,
|
|
1810
|
-
isShielded,
|
|
1811
|
-
memoValidation,
|
|
1812
|
-
simulateDetection,
|
|
1813
|
-
invoiceId,
|
|
1814
|
-
network,
|
|
1815
|
-
customRpcUrl,
|
|
1816
|
-
// Zucchini Wallet
|
|
1817
|
-
zucchiniAvailable,
|
|
1818
|
-
zucchiniPaying,
|
|
1819
|
-
payWithZucchini
|
|
1820
|
-
};
|
|
1821
|
-
}
|
|
1822
|
-
|
|
1823
|
-
// src/components/CiceroModal.tsx
|
|
1824
|
-
import { useState as useState6, useEffect as useEffect6 } from "react";
|
|
1825
|
-
import { createPortal as createPortal3 } from "react-dom";
|
|
1826
|
-
import {
|
|
1827
|
-
Shield as Shield4,
|
|
1828
|
-
Copy as Copy2,
|
|
1829
|
-
Check as Check2,
|
|
1830
|
-
ExternalLink as ExternalLink3,
|
|
1831
|
-
Clock,
|
|
1832
|
-
CheckCircle2,
|
|
1833
|
-
AlertCircle as AlertCircle2,
|
|
1834
|
-
X as X3,
|
|
1835
|
-
Lock,
|
|
1836
|
-
Sparkles as Sparkles2,
|
|
1837
|
-
Zap
|
|
1838
|
-
} from "lucide-react";
|
|
1839
|
-
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1840
|
-
var CiceroModal = ({
|
|
1841
|
-
isOpen,
|
|
1842
|
-
onClose,
|
|
1843
|
-
recipient,
|
|
1844
|
-
amount,
|
|
1845
|
-
memo,
|
|
1846
|
-
message,
|
|
1847
|
-
network = "mainnet",
|
|
1848
|
-
status,
|
|
1849
|
-
txId,
|
|
1850
|
-
secondsRemaining,
|
|
1851
|
-
zip321Uri,
|
|
1852
|
-
addressType,
|
|
1853
|
-
isShielded,
|
|
1854
|
-
memoValidation,
|
|
1855
|
-
onSimulateDetection,
|
|
1856
|
-
onResetPayment,
|
|
1857
|
-
title = "Pay with Shielded Zcash",
|
|
1858
|
-
subtitle = "Zero-Knowledge, Confidential Checkout",
|
|
1859
|
-
showUsd = true,
|
|
1860
|
-
zucchiniAvailable = false,
|
|
1861
|
-
zucchiniPaying = false,
|
|
1862
|
-
onPayWithZucchini
|
|
1863
|
-
}) => {
|
|
1864
|
-
const [copiedType, setCopiedType] = useState6(null);
|
|
1865
|
-
const { convertZecToUsd } = useZcashPrice(showUsd);
|
|
1866
|
-
useEffect6(() => {
|
|
1867
|
-
const handleKeyDown = (e) => {
|
|
1868
|
-
if (e.key === "Escape" && isOpen) {
|
|
1869
|
-
onClose();
|
|
1870
|
-
}
|
|
1871
|
-
};
|
|
1872
|
-
window.addEventListener("keydown", handleKeyDown);
|
|
1873
|
-
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
1874
|
-
}, [isOpen, onClose]);
|
|
1875
|
-
const [mounted, setMounted] = useState6(false);
|
|
1876
|
-
useEffect6(() => {
|
|
1877
|
-
setMounted(true);
|
|
1878
|
-
}, []);
|
|
1879
|
-
if (!isOpen || !mounted) return null;
|
|
1880
|
-
const copyToClipboard = async (text, type) => {
|
|
1881
|
-
try {
|
|
1882
|
-
await navigator.clipboard.writeText(text);
|
|
1883
|
-
setCopiedType(type);
|
|
1884
|
-
setTimeout(() => setCopiedType(null), 2e3);
|
|
1885
|
-
} catch {
|
|
1886
|
-
}
|
|
1887
|
-
};
|
|
1888
|
-
const formatTime = (secs) => {
|
|
1889
|
-
const m = Math.floor(secs / 60);
|
|
1890
|
-
const s = secs % 60;
|
|
1891
|
-
return `${m}:${s < 10 ? "0" : ""}${s}`;
|
|
1892
|
-
};
|
|
1893
|
-
const usdValue = convertZecToUsd(amount);
|
|
1894
|
-
return createPortal3(
|
|
1895
|
-
/* @__PURE__ */ jsxs5("div", { className: "fixed inset-0 z-[99999] flex items-center justify-center p-4 sm:p-6 overflow-y-auto", children: [
|
|
1896
|
-
/* @__PURE__ */ jsx6(
|
|
1897
|
-
"div",
|
|
1898
|
-
{
|
|
1899
|
-
className: "fixed inset-0 bg-[#171717]/60 backdrop-blur-sm transition-opacity z-[99999]",
|
|
1900
|
-
onClick: onClose
|
|
1901
|
-
}
|
|
1902
|
-
),
|
|
1903
|
-
/* @__PURE__ */ jsxs5("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: [
|
|
1904
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between px-6 py-4 border-b border-[#ededed] bg-[#fafafa]", children: [
|
|
1905
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2.5", children: [
|
|
1906
|
-
/* @__PURE__ */ jsx6("div", { className: "w-8 h-8 rounded-md bg-[#171717] flex items-center justify-center text-[#3ecf8e]", children: /* @__PURE__ */ jsx6(Shield4, { className: "w-4 h-4 fill-[#3ecf8e]" }) }),
|
|
1907
|
-
/* @__PURE__ */ jsxs5("div", { children: [
|
|
1908
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
1909
|
-
/* @__PURE__ */ jsx6("span", { className: "font-medium text-sm text-[#171717]", children: title }),
|
|
1910
|
-
/* @__PURE__ */ jsx6("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" }),
|
|
1911
|
-
network === "testnet" && /* @__PURE__ */ jsx6("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" })
|
|
1912
|
-
] }),
|
|
1913
|
-
/* @__PURE__ */ jsx6("p", { className: "text-xs text-[#707070] mt-0.5", children: subtitle })
|
|
1914
|
-
] })
|
|
1915
|
-
] }),
|
|
1916
|
-
/* @__PURE__ */ jsx6(
|
|
1917
|
-
"button",
|
|
1918
|
-
{
|
|
1919
|
-
onClick: onClose,
|
|
1920
|
-
className: "p-1 rounded-md text-[#707070] hover:text-[#171717] hover:bg-[#ededed] transition-colors",
|
|
1921
|
-
"aria-label": "Close modal",
|
|
1922
|
-
children: /* @__PURE__ */ jsx6(X3, { className: "w-4 h-4" })
|
|
1923
|
-
}
|
|
1924
|
-
)
|
|
1925
|
-
] }),
|
|
1926
|
-
/* @__PURE__ */ jsxs5("div", { className: "px-6 py-2.5 bg-white border-b border-[#ededed] flex items-center justify-between text-xs", children: [
|
|
1927
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
1928
|
-
status === "pending" && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1929
|
-
/* @__PURE__ */ jsxs5("span", { className: "relative flex h-2 w-2", children: [
|
|
1930
|
-
/* @__PURE__ */ jsx6("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-[#3ecf8e] opacity-75" }),
|
|
1931
|
-
/* @__PURE__ */ jsx6("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-[#24b47e]" })
|
|
1932
|
-
] }),
|
|
1933
|
-
/* @__PURE__ */ jsx6("span", { className: "text-[#707070]", children: "Listening for transaction..." })
|
|
1934
|
-
] }),
|
|
1935
|
-
status === "detected" && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1936
|
-
/* @__PURE__ */ jsxs5("span", { className: "relative flex h-2 w-2", children: [
|
|
1937
|
-
/* @__PURE__ */ jsx6("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-amber-400 opacity-75" }),
|
|
1938
|
-
/* @__PURE__ */ jsx6("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-amber-500" })
|
|
1939
|
-
] }),
|
|
1940
|
-
/* @__PURE__ */ jsx6("span", { className: "text-amber-800 font-medium", children: "Transaction spotted in mempool! Confirming..." })
|
|
1941
|
-
] }),
|
|
1942
|
-
status === "confirmed" && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1943
|
-
/* @__PURE__ */ jsx6(CheckCircle2, { className: "w-4 h-4 text-[#24b47e]" }),
|
|
1944
|
-
/* @__PURE__ */ jsx6("span", { className: "text-[#24b47e] font-medium", children: "Payment Confirmed On-Chain!" })
|
|
1945
|
-
] }),
|
|
1946
|
-
status === "expired" && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1947
|
-
/* @__PURE__ */ jsx6(AlertCircle2, { className: "w-4 h-4 text-rose-500" }),
|
|
1948
|
-
/* @__PURE__ */ jsx6("span", { className: "text-rose-600 font-medium", children: "Payment window expired" })
|
|
1949
|
-
] })
|
|
1950
|
-
] }),
|
|
1951
|
-
status === "pending" && /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1 text-[#707070] font-mono text-[11px]", children: [
|
|
1952
|
-
/* @__PURE__ */ jsx6(Clock, { className: "w-3 h-3" }),
|
|
1953
|
-
/* @__PURE__ */ jsx6("span", { children: formatTime(secondsRemaining) })
|
|
1954
|
-
] })
|
|
1955
|
-
] }),
|
|
1956
|
-
/* @__PURE__ */ jsx6("div", { className: "p-6 space-y-5", children: status === "confirmed" ? /* @__PURE__ */ jsxs5("div", { className: "py-6 text-center space-y-4", children: [
|
|
1957
|
-
/* @__PURE__ */ jsx6("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__ */ jsx6(CheckCircle2, { className: "w-8 h-8" }) }),
|
|
1958
|
-
/* @__PURE__ */ jsxs5("div", { children: [
|
|
1959
|
-
/* @__PURE__ */ jsx6("h3", { className: "text-lg font-medium text-[#171717]", children: "Payment Received & Shielded!" }),
|
|
1960
|
-
/* @__PURE__ */ jsx6("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." })
|
|
1961
|
-
] }),
|
|
1962
|
-
txId && /* @__PURE__ */ jsxs5("div", { className: "p-3 bg-[#fafafa] rounded-md border border-[#ededed] text-left", children: [
|
|
1963
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between text-[11px] text-[#707070] mb-1", children: [
|
|
1964
|
-
/* @__PURE__ */ jsx6("span", { children: "Transaction Hash" }),
|
|
1965
|
-
/* @__PURE__ */ jsx6("span", { className: "text-[#24b47e] font-mono", children: "Shielded Note" })
|
|
1966
|
-
] }),
|
|
1967
|
-
/* @__PURE__ */ jsx6("div", { className: "font-mono text-xs text-[#171717] break-all", children: txId })
|
|
1968
|
-
] }),
|
|
1969
|
-
/* @__PURE__ */ jsx6(
|
|
1970
|
-
"button",
|
|
1971
|
-
{
|
|
1972
|
-
onClick: onClose,
|
|
1973
|
-
className: "w-full py-2.5 px-4 rounded-md bg-[#3ecf8e] text-[#171717] font-medium text-sm hover:bg-[#24b47e] transition-colors",
|
|
1974
|
-
children: "Close & Return"
|
|
1975
|
-
}
|
|
1976
|
-
)
|
|
1977
|
-
] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1978
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between p-4 bg-[#fafafa] rounded-lg border border-[#ededed]", children: [
|
|
1979
|
-
/* @__PURE__ */ jsxs5("div", { children: [
|
|
1980
|
-
/* @__PURE__ */ jsx6("span", { className: "text-xs text-[#707070] uppercase font-mono tracking-wider", children: "Total Amount" }),
|
|
1981
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-baseline gap-2 mt-0.5", children: [
|
|
1982
|
-
/* @__PURE__ */ jsxs5("span", { className: "text-2xl font-semibold tracking-tight text-[#171717] font-mono", children: [
|
|
1983
|
-
amount,
|
|
1984
|
-
" ",
|
|
1985
|
-
/* @__PURE__ */ jsx6("span", { className: "text-sm font-normal text-[#707070]", children: "ZEC" })
|
|
1986
|
-
] }),
|
|
1987
|
-
usdValue && /* @__PURE__ */ jsxs5("span", { className: "text-xs text-[#707070] font-mono", children: [
|
|
1988
|
-
"\u2248 $",
|
|
1989
|
-
usdValue,
|
|
1990
|
-
" USD"
|
|
1991
|
-
] })
|
|
1992
|
-
] })
|
|
1993
|
-
] }),
|
|
1994
|
-
/* @__PURE__ */ jsxs5("div", { className: "text-right", children: [
|
|
1995
|
-
/* @__PURE__ */ jsx6("span", { className: "text-[11px] text-[#707070] block font-mono", children: "Address Standard" }),
|
|
1996
|
-
/* @__PURE__ */ jsx6("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" })
|
|
1997
|
-
] })
|
|
1998
|
-
] }),
|
|
1999
|
-
message && /* @__PURE__ */ jsxs5("div", { className: "px-3.5 py-2 bg-[#fafafa] rounded-md border border-[#ededed] text-xs text-[#707070]", children: [
|
|
2000
|
-
/* @__PURE__ */ jsx6("span", { className: "font-medium text-[#171717]", children: "Order Note: " }),
|
|
2001
|
-
/* @__PURE__ */ jsx6("span", { children: message })
|
|
2002
|
-
] }),
|
|
2003
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex flex-col sm:flex-row items-center gap-5 p-4 rounded-lg border border-[#ededed] bg-white", children: [
|
|
2004
|
-
/* @__PURE__ */ jsx6("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx6(CiceroQRCode, { value: zip321Uri, size: 150 }) }),
|
|
2005
|
-
/* @__PURE__ */ jsxs5("div", { className: "space-y-3 w-full text-center sm:text-left", children: [
|
|
2006
|
-
/* @__PURE__ */ jsxs5("div", { children: [
|
|
2007
|
-
/* @__PURE__ */ jsxs5("h4", { className: "text-sm font-medium text-[#171717] flex items-center justify-center sm:justify-start gap-1.5", children: [
|
|
2008
|
-
/* @__PURE__ */ jsx6("span", { children: "Scan with Shielded Wallet" }),
|
|
2009
|
-
/* @__PURE__ */ jsx6(Sparkles2, { className: "w-3.5 h-3.5 text-[#3ecf8e]" })
|
|
2010
|
-
] }),
|
|
2011
|
-
/* @__PURE__ */ jsxs5("p", { className: "text-xs text-[#707070] mt-0.5 leading-relaxed", children: [
|
|
2012
|
-
"Compatible with ",
|
|
2013
|
-
/* @__PURE__ */ jsx6("strong", { className: "text-[#171717]", children: "Zashi" }),
|
|
2014
|
-
", ",
|
|
2015
|
-
/* @__PURE__ */ jsx6("strong", { className: "text-[#171717]", children: "Ywallet" }),
|
|
2016
|
-
", or any ZIP-321 compliant Zcash wallet."
|
|
2017
|
-
] })
|
|
2018
|
-
] }),
|
|
2019
|
-
/* @__PURE__ */ jsxs5(
|
|
2020
|
-
"a",
|
|
2021
|
-
{
|
|
2022
|
-
href: zip321Uri,
|
|
2023
|
-
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",
|
|
2024
|
-
children: [
|
|
2025
|
-
/* @__PURE__ */ jsx6("span", { children: "Open in Mobile / Desktop Wallet" }),
|
|
2026
|
-
/* @__PURE__ */ jsx6(ExternalLink3, { className: "w-3.5 h-3.5 text-[#3ecf8e]" })
|
|
2027
|
-
]
|
|
2028
|
-
}
|
|
2029
|
-
),
|
|
2030
|
-
zucchiniAvailable && onPayWithZucchini && /* @__PURE__ */ jsx6(
|
|
2031
|
-
"button",
|
|
2032
|
-
{
|
|
2033
|
-
onClick: onPayWithZucchini,
|
|
2034
|
-
disabled: zucchiniPaying,
|
|
2035
|
-
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",
|
|
2036
|
-
children: zucchiniPaying ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
2037
|
-
/* @__PURE__ */ jsx6("span", { className: "w-3.5 h-3.5 border-2 border-[#171717]/30 border-t-[#171717] rounded-full animate-spin" }),
|
|
2038
|
-
/* @__PURE__ */ jsx6("span", { children: "Confirming in Zucchini..." })
|
|
2039
|
-
] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
2040
|
-
/* @__PURE__ */ jsx6("span", { className: "text-sm", children: "\u{1F952}" }),
|
|
2041
|
-
/* @__PURE__ */ jsx6("span", { children: "Pay with Zucchini Wallet" })
|
|
2042
|
-
] })
|
|
2043
|
-
}
|
|
2044
|
-
),
|
|
2045
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
2046
|
-
/* @__PURE__ */ jsx6(
|
|
2047
|
-
"button",
|
|
2048
|
-
{
|
|
2049
|
-
onClick: () => copyToClipboard(zip321Uri, "uri"),
|
|
2050
|
-
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",
|
|
2051
|
-
children: copiedType === "uri" ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
2052
|
-
/* @__PURE__ */ jsx6(Check2, { className: "w-3 h-3 text-[#24b47e]" }),
|
|
2053
|
-
/* @__PURE__ */ jsx6("span", { className: "text-[#24b47e]", children: "Copied URI" })
|
|
2054
|
-
] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
2055
|
-
/* @__PURE__ */ jsx6(Copy2, { className: "w-3 h-3 text-[#707070]" }),
|
|
2056
|
-
/* @__PURE__ */ jsx6("span", { children: "Copy ZIP-321 URI" })
|
|
2057
|
-
] })
|
|
2058
|
-
}
|
|
2059
|
-
),
|
|
2060
|
-
/* @__PURE__ */ jsx6(
|
|
2061
|
-
"button",
|
|
2062
|
-
{
|
|
2063
|
-
onClick: () => copyToClipboard(recipient, "address"),
|
|
2064
|
-
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",
|
|
2065
|
-
children: copiedType === "address" ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
2066
|
-
/* @__PURE__ */ jsx6(Check2, { className: "w-3 h-3 text-[#24b47e]" }),
|
|
2067
|
-
/* @__PURE__ */ jsx6("span", { className: "text-[#24b47e]", children: "Copied Address" })
|
|
2068
|
-
] }) : /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
2069
|
-
/* @__PURE__ */ jsx6(Copy2, { className: "w-3 h-3 text-[#707070]" }),
|
|
2070
|
-
/* @__PURE__ */ jsx6("span", { children: "Copy Address" })
|
|
2071
|
-
] })
|
|
2072
|
-
}
|
|
2073
|
-
)
|
|
2074
|
-
] })
|
|
2075
|
-
] })
|
|
2076
|
-
] }),
|
|
2077
|
-
/* @__PURE__ */ jsxs5("div", { className: "space-y-1.5 text-xs", children: [
|
|
2078
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between text-[#707070]", children: [
|
|
2079
|
-
/* @__PURE__ */ jsx6("span", { children: "Recipient Address" }),
|
|
2080
|
-
/* @__PURE__ */ jsx6("span", { className: "font-mono text-[11px]", children: truncateAddress(recipient, 12, 10) })
|
|
2081
|
-
] }),
|
|
2082
|
-
/* @__PURE__ */ jsx6("div", { className: "p-2 bg-[#fafafa] rounded-md border border-[#ededed] font-mono text-[11px] text-[#171717] break-all select-all", children: recipient })
|
|
2083
|
-
] }),
|
|
2084
|
-
memo && /* @__PURE__ */ jsxs5("div", { className: "space-y-1.5 text-xs p-3 rounded-md bg-[#fafafa] border border-[#ededed]", children: [
|
|
2085
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between", children: [
|
|
2086
|
-
/* @__PURE__ */ jsxs5("span", { className: "flex items-center gap-1.5 font-medium text-[#171717]", children: [
|
|
2087
|
-
/* @__PURE__ */ jsx6(Lock, { className: "w-3 h-3 text-[#3ecf8e]" }),
|
|
2088
|
-
/* @__PURE__ */ jsx6("span", { children: "Encrypted Memo" })
|
|
2089
|
-
] }),
|
|
2090
|
-
/* @__PURE__ */ jsxs5("span", { className: "text-[10px] font-mono text-[#707070]", children: [
|
|
2091
|
-
memoValidation.byteLength,
|
|
2092
|
-
"/512 bytes"
|
|
2093
|
-
] })
|
|
2094
|
-
] }),
|
|
2095
|
-
/* @__PURE__ */ jsx6("p", { className: "font-mono text-xs text-[#171717] bg-white p-2 rounded border border-[#dfdfdf]", children: memo }),
|
|
2096
|
-
/* @__PURE__ */ jsx6("p", { className: "text-[11px] text-[#707070]", children: "Only the recipient holding the viewing/spending key can decrypt this message on-chain." })
|
|
2097
|
-
] }),
|
|
2098
|
-
memoValidation.warning && /* @__PURE__ */ jsxs5("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: [
|
|
2099
|
-
/* @__PURE__ */ jsx6(AlertCircle2, { className: "w-4 h-4 flex-shrink-0 mt-0.5 text-amber-600" }),
|
|
2100
|
-
/* @__PURE__ */ jsx6("span", { children: memoValidation.warning })
|
|
2101
|
-
] }),
|
|
2102
|
-
/* @__PURE__ */ jsxs5("div", { className: "pt-2 border-t border-[#ededed] flex items-center justify-between", children: [
|
|
2103
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1.5 text-[11px] text-[#707070]", children: [
|
|
2104
|
-
/* @__PURE__ */ jsx6(Zap, { className: "w-3 h-3 text-[#3ecf8e]" }),
|
|
2105
|
-
/* @__PURE__ */ jsx6("span", { children: "Demo Controls:" })
|
|
2106
|
-
] }),
|
|
2107
|
-
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
2108
|
-
/* @__PURE__ */ jsx6(
|
|
2109
|
-
"button",
|
|
2110
|
-
{
|
|
2111
|
-
onClick: onSimulateDetection,
|
|
2112
|
-
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",
|
|
2113
|
-
children: "Simulate Payment"
|
|
2114
|
-
}
|
|
2115
|
-
),
|
|
2116
|
-
status === "expired" && /* @__PURE__ */ jsx6(
|
|
2117
|
-
"button",
|
|
2118
|
-
{
|
|
2119
|
-
onClick: onResetPayment,
|
|
2120
|
-
className: "px-2.5 py-1 text-[11px] font-medium rounded bg-[#171717] text-white hover:bg-[#212121] transition-colors",
|
|
2121
|
-
children: "Refresh"
|
|
2122
|
-
}
|
|
2123
|
-
)
|
|
2124
|
-
] })
|
|
2125
|
-
] })
|
|
2126
|
-
] }) })
|
|
2127
|
-
] })
|
|
2128
|
-
] }),
|
|
2129
|
-
document.body
|
|
2130
|
-
);
|
|
2131
|
-
};
|
|
2132
|
-
|
|
2133
|
-
// src/components/CiceroPayButton.tsx
|
|
2134
|
-
import { Fragment as Fragment4, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2135
|
-
var CiceroPayButton = ({
|
|
2136
|
-
recipient,
|
|
2137
|
-
amount,
|
|
2138
|
-
memo,
|
|
2139
|
-
message,
|
|
2140
|
-
label = "Pay with Zcash",
|
|
2141
|
-
network = "mainnet",
|
|
2142
|
-
variant = "primary",
|
|
2143
|
-
size = "md",
|
|
2144
|
-
showUsd = true,
|
|
2145
|
-
modalTitle,
|
|
2146
|
-
modalSubtitle,
|
|
2147
|
-
expiresInSeconds = 900,
|
|
2148
|
-
customRpcUrl,
|
|
2149
|
-
invoiceId,
|
|
2150
|
-
onSuccess,
|
|
2151
|
-
onError,
|
|
2152
|
-
onStatusChange,
|
|
2153
|
-
className = "",
|
|
2154
|
-
disabled = false
|
|
2155
|
-
}) => {
|
|
2156
|
-
const {
|
|
2157
|
-
status,
|
|
2158
|
-
txId,
|
|
2159
|
-
secondsRemaining,
|
|
2160
|
-
isModalOpen,
|
|
2161
|
-
openModal,
|
|
2162
|
-
closeModal,
|
|
2163
|
-
resetPayment,
|
|
2164
|
-
zip321Uri,
|
|
2165
|
-
addressType,
|
|
2166
|
-
isShielded,
|
|
2167
|
-
memoValidation,
|
|
2168
|
-
simulateDetection,
|
|
2169
|
-
zucchiniAvailable,
|
|
2170
|
-
zucchiniPaying,
|
|
2171
|
-
payWithZucchini
|
|
2172
|
-
} = useCiceroPayment({
|
|
2173
|
-
recipient,
|
|
2174
|
-
amount,
|
|
2175
|
-
memo,
|
|
2176
|
-
message,
|
|
2177
|
-
network,
|
|
2178
|
-
expiresInSeconds,
|
|
2179
|
-
invoiceId,
|
|
2180
|
-
customRpcUrl,
|
|
2181
|
-
onSuccess,
|
|
2182
|
-
onError,
|
|
2183
|
-
onStatusChange
|
|
2184
|
-
});
|
|
2185
|
-
const sizeClasses = {
|
|
2186
|
-
sm: "text-xs px-3 py-1.5 gap-1.5",
|
|
2187
|
-
md: "text-sm px-4 py-2 gap-2",
|
|
2188
|
-
lg: "text-base px-5 py-2.5 gap-2.5"
|
|
2189
|
-
}[size];
|
|
2190
|
-
const variantClasses = {
|
|
2191
|
-
// Signature Supabase emerald CTA: #3ecf8e background, #171717 text, 6px radius
|
|
2192
|
-
primary: "bg-[#3ecf8e] text-[#171717] hover:bg-[#24b47e] active:bg-[#24b47e] shadow-sm font-medium",
|
|
2193
|
-
// Secondary outline on white
|
|
2194
|
-
outline: "bg-white text-[#171717] border border-[#dfdfdf] hover:border-[#c7c7c7] hover:bg-[#fafafa] font-medium shadow-sm",
|
|
2195
|
-
// Dark canvas-night
|
|
2196
|
-
dark: "bg-[#1c1c1c] text-white hover:bg-[#242424] font-medium shadow-sm"
|
|
2197
|
-
}[variant];
|
|
2198
|
-
return /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
2199
|
-
/* @__PURE__ */ jsxs6(
|
|
2200
|
-
"button",
|
|
2201
|
-
{
|
|
2202
|
-
type: "button",
|
|
2203
|
-
onClick: openModal,
|
|
2204
|
-
disabled,
|
|
2205
|
-
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}`,
|
|
2206
|
-
children: [
|
|
2207
|
-
/* @__PURE__ */ jsx7(
|
|
2208
|
-
Shield5,
|
|
2209
|
-
{
|
|
2210
|
-
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]"}`
|
|
2211
|
-
}
|
|
2212
|
-
),
|
|
2213
|
-
/* @__PURE__ */ jsx7("span", { children: label })
|
|
2214
|
-
]
|
|
2215
|
-
}
|
|
2216
|
-
),
|
|
2217
|
-
/* @__PURE__ */ jsx7(
|
|
2218
|
-
CiceroModal,
|
|
2219
|
-
{
|
|
2220
|
-
isOpen: isModalOpen,
|
|
2221
|
-
onClose: closeModal,
|
|
2222
|
-
recipient,
|
|
2223
|
-
amount,
|
|
2224
|
-
memo,
|
|
2225
|
-
message,
|
|
2226
|
-
network,
|
|
2227
|
-
status,
|
|
2228
|
-
txId,
|
|
2229
|
-
secondsRemaining,
|
|
2230
|
-
zip321Uri,
|
|
2231
|
-
addressType,
|
|
2232
|
-
isShielded,
|
|
2233
|
-
memoValidation,
|
|
2234
|
-
onSimulateDetection: simulateDetection,
|
|
2235
|
-
onResetPayment: resetPayment,
|
|
2236
|
-
title: modalTitle,
|
|
2237
|
-
subtitle: modalSubtitle,
|
|
2238
|
-
showUsd,
|
|
2239
|
-
zucchiniAvailable,
|
|
2240
|
-
zucchiniPaying,
|
|
2241
|
-
onPayWithZucchini: payWithZucchini
|
|
2242
|
-
}
|
|
2243
|
-
)
|
|
2244
|
-
] });
|
|
2245
|
-
};
|
|
2246
|
-
|
|
2247
|
-
// src/components/CiceroInvoice.tsx
|
|
2248
|
-
import { useState as useState7 } from "react";
|
|
2249
|
-
import {
|
|
2250
|
-
Shield as Shield6,
|
|
2251
|
-
Copy as Copy3,
|
|
2252
|
-
Check as Check3,
|
|
2253
|
-
ExternalLink as ExternalLink4,
|
|
2254
|
-
Clock as Clock2,
|
|
2255
|
-
CheckCircle2 as CheckCircle22,
|
|
2256
|
-
AlertCircle as AlertCircle3,
|
|
2257
|
-
Lock as Lock2,
|
|
2258
|
-
Sparkles as Sparkles3
|
|
2259
|
-
} from "lucide-react";
|
|
2260
|
-
import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2261
|
-
var CiceroInvoice = ({
|
|
2262
|
-
recipient,
|
|
2263
|
-
amount,
|
|
2264
|
-
memo,
|
|
2265
|
-
message,
|
|
2266
|
-
network = "mainnet",
|
|
2267
|
-
expiresInSeconds = 900,
|
|
2268
|
-
showUsd = true,
|
|
2269
|
-
invoiceId,
|
|
2270
|
-
customRpcUrl,
|
|
2271
|
-
onSuccess,
|
|
2272
|
-
onError,
|
|
2273
|
-
onStatusChange,
|
|
2274
|
-
className = ""
|
|
2275
|
-
}) => {
|
|
2276
|
-
const [copiedType, setCopiedType] = useState7(null);
|
|
2277
|
-
const { convertZecToUsd } = useZcashPrice(showUsd);
|
|
2278
|
-
const {
|
|
2279
|
-
status,
|
|
2280
|
-
txId,
|
|
2281
|
-
secondsRemaining,
|
|
2282
|
-
zip321Uri,
|
|
2283
|
-
addressType,
|
|
2284
|
-
isShielded,
|
|
2285
|
-
memoValidation,
|
|
2286
|
-
simulateDetection,
|
|
2287
|
-
resetPayment,
|
|
2288
|
-
zucchiniAvailable,
|
|
2289
|
-
zucchiniPaying,
|
|
2290
|
-
payWithZucchini
|
|
2291
|
-
} = useCiceroPayment({
|
|
2292
|
-
recipient,
|
|
2293
|
-
amount,
|
|
2294
|
-
memo,
|
|
2295
|
-
message,
|
|
2296
|
-
network,
|
|
2297
|
-
expiresInSeconds,
|
|
2298
|
-
invoiceId,
|
|
2299
|
-
customRpcUrl,
|
|
2300
|
-
onSuccess,
|
|
2301
|
-
onError,
|
|
2302
|
-
onStatusChange
|
|
2303
|
-
});
|
|
2304
|
-
const copyToClipboard = async (text, type) => {
|
|
2305
|
-
try {
|
|
2306
|
-
await navigator.clipboard.writeText(text);
|
|
2307
|
-
setCopiedType(type);
|
|
2308
|
-
setTimeout(() => setCopiedType(null), 2e3);
|
|
2309
|
-
} catch {
|
|
2310
|
-
}
|
|
2311
|
-
};
|
|
2312
|
-
const formatTime = (secs) => {
|
|
2313
|
-
const m = Math.floor(secs / 60);
|
|
2314
|
-
const s = secs % 60;
|
|
2315
|
-
return `${m}:${s < 10 ? "0" : ""}${s}`;
|
|
2316
|
-
};
|
|
2317
|
-
const usdValue = convertZecToUsd(amount);
|
|
2318
|
-
return /* @__PURE__ */ jsxs7(
|
|
2319
|
-
"div",
|
|
2320
|
-
{
|
|
2321
|
-
className: `bg-white rounded-xl border border-[#ededed] shadow-sm overflow-hidden text-[#171717] font-sans ${className}`,
|
|
2322
|
-
children: [
|
|
2323
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between px-5 py-3.5 border-b border-[#ededed] bg-[#fafafa]", children: [
|
|
2324
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
|
|
2325
|
-
/* @__PURE__ */ jsx8("div", { className: "w-7 h-7 rounded-md bg-[#171717] flex items-center justify-center text-[#3ecf8e]", children: /* @__PURE__ */ jsx8(Shield6, { className: "w-3.5 h-3.5 fill-[#3ecf8e]" }) }),
|
|
2326
|
-
/* @__PURE__ */ jsxs7("div", { children: [
|
|
2327
|
-
/* @__PURE__ */ jsx8("span", { className: "font-medium text-xs text-[#171717]", children: "Shielded Zcash Invoice" }),
|
|
2328
|
-
invoiceId && /* @__PURE__ */ jsxs7("span", { className: "text-[10px] text-[#707070] ml-2 font-mono", children: [
|
|
2329
|
-
"#",
|
|
2330
|
-
invoiceId
|
|
2331
|
-
] })
|
|
2332
|
-
] })
|
|
2333
|
-
] }),
|
|
2334
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
|
|
2335
|
-
/* @__PURE__ */ jsx8("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" }),
|
|
2336
|
-
/* @__PURE__ */ jsx8("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" }),
|
|
2337
|
-
network === "testnet" && /* @__PURE__ */ jsx8("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" })
|
|
2338
|
-
] })
|
|
2339
|
-
] }),
|
|
2340
|
-
/* @__PURE__ */ jsx8("div", { className: "p-5 space-y-4", children: status === "confirmed" ? /* @__PURE__ */ jsxs7("div", { className: "py-6 text-center space-y-3", children: [
|
|
2341
|
-
/* @__PURE__ */ jsx8("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__ */ jsx8(CheckCircle22, { className: "w-6 h-6" }) }),
|
|
2342
|
-
/* @__PURE__ */ jsxs7("div", { children: [
|
|
2343
|
-
/* @__PURE__ */ jsx8("h4", { className: "font-medium text-sm text-[#171717]", children: "Payment Verified!" }),
|
|
2344
|
-
/* @__PURE__ */ jsx8("p", { className: "text-xs text-[#707070] mt-0.5", children: "Shielded transaction detected and settled on-chain." })
|
|
2345
|
-
] }),
|
|
2346
|
-
txId && /* @__PURE__ */ jsx8("div", { className: "font-mono text-[11px] p-2 bg-[#fafafa] rounded border border-[#ededed] text-[#707070] break-all", children: txId })
|
|
2347
|
-
] }) : /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
2348
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between p-3.5 bg-[#fafafa] rounded-lg border border-[#ededed]", children: [
|
|
2349
|
-
/* @__PURE__ */ jsxs7("div", { children: [
|
|
2350
|
-
/* @__PURE__ */ jsx8("span", { className: "text-[10px] text-[#707070] uppercase font-mono tracking-wider", children: "Amount Due" }),
|
|
2351
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-baseline gap-2 mt-0.5", children: [
|
|
2352
|
-
/* @__PURE__ */ jsxs7("span", { className: "text-xl font-semibold tracking-tight text-[#171717] font-mono", children: [
|
|
2353
|
-
amount,
|
|
2354
|
-
" ",
|
|
2355
|
-
/* @__PURE__ */ jsx8("span", { className: "text-xs font-normal text-[#707070]", children: "ZEC" })
|
|
2356
|
-
] }),
|
|
2357
|
-
usdValue && /* @__PURE__ */ jsxs7("span", { className: "text-xs text-[#707070] font-mono", children: [
|
|
2358
|
-
"\u2248 $",
|
|
2359
|
-
usdValue,
|
|
2360
|
-
" USD"
|
|
2361
|
-
] })
|
|
2362
|
-
] })
|
|
2363
|
-
] }),
|
|
2364
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1.5 text-[#707070] font-mono text-xs", children: [
|
|
2365
|
-
/* @__PURE__ */ jsx8(Clock2, { className: "w-3.5 h-3.5" }),
|
|
2366
|
-
/* @__PURE__ */ jsx8("span", { children: formatTime(secondsRemaining) })
|
|
2367
|
-
] })
|
|
2368
|
-
] }),
|
|
2369
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex flex-col sm:flex-row items-center gap-4", children: [
|
|
2370
|
-
/* @__PURE__ */ jsx8(CiceroQRCode, { value: zip321Uri, size: 140 }),
|
|
2371
|
-
/* @__PURE__ */ jsxs7("div", { className: "space-y-2.5 w-full", children: [
|
|
2372
|
-
zucchiniAvailable && /* @__PURE__ */ jsx8(
|
|
2373
|
-
"button",
|
|
2374
|
-
{
|
|
2375
|
-
onClick: payWithZucchini,
|
|
2376
|
-
disabled: zucchiniPaying,
|
|
2377
|
-
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",
|
|
2378
|
-
children: zucchiniPaying ? /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
2379
|
-
/* @__PURE__ */ jsx8("span", { className: "w-3.5 h-3.5 border-2 border-[#171717]/30 border-t-[#171717] rounded-full animate-spin" }),
|
|
2380
|
-
/* @__PURE__ */ jsx8("span", { children: "Confirming in Zucchini..." })
|
|
2381
|
-
] }) : /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
2382
|
-
/* @__PURE__ */ jsx8("span", { children: "\u{1F952}" }),
|
|
2383
|
-
/* @__PURE__ */ jsx8("span", { children: "Pay with Zucchini Wallet" })
|
|
2384
|
-
] })
|
|
2385
|
-
}
|
|
2386
|
-
),
|
|
2387
|
-
/* @__PURE__ */ jsxs7(
|
|
2388
|
-
"a",
|
|
2389
|
-
{
|
|
2390
|
-
href: zip321Uri,
|
|
2391
|
-
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",
|
|
2392
|
-
children: [
|
|
2393
|
-
/* @__PURE__ */ jsx8("span", { children: "Pay with Wallet App" }),
|
|
2394
|
-
/* @__PURE__ */ jsx8(ExternalLink4, { className: "w-3.5 h-3.5 text-[#3ecf8e]" })
|
|
2395
|
-
]
|
|
2396
|
-
}
|
|
2397
|
-
),
|
|
2398
|
-
/* @__PURE__ */ jsxs7("div", { className: "grid grid-cols-2 gap-2", children: [
|
|
2399
|
-
/* @__PURE__ */ jsxs7(
|
|
2400
|
-
"button",
|
|
2401
|
-
{
|
|
2402
|
-
onClick: () => copyToClipboard(zip321Uri, "uri"),
|
|
2403
|
-
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",
|
|
2404
|
-
children: [
|
|
2405
|
-
copiedType === "uri" ? /* @__PURE__ */ jsx8(Check3, { className: "w-3 h-3 text-[#24b47e]" }) : /* @__PURE__ */ jsx8(Copy3, { className: "w-3 h-3 text-[#707070]" }),
|
|
2406
|
-
/* @__PURE__ */ jsx8("span", { children: copiedType === "uri" ? "Copied" : "Copy URI" })
|
|
2407
|
-
]
|
|
2408
|
-
}
|
|
2409
|
-
),
|
|
2410
|
-
/* @__PURE__ */ jsxs7(
|
|
2411
|
-
"button",
|
|
2412
|
-
{
|
|
2413
|
-
onClick: () => copyToClipboard(recipient, "address"),
|
|
2414
|
-
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",
|
|
2415
|
-
children: [
|
|
2416
|
-
copiedType === "address" ? /* @__PURE__ */ jsx8(Check3, { className: "w-3 h-3 text-[#24b47e]" }) : /* @__PURE__ */ jsx8(Copy3, { className: "w-3 h-3 text-[#707070]" }),
|
|
2417
|
-
/* @__PURE__ */ jsx8("span", { children: copiedType === "address" ? "Copied" : "Copy Addr" })
|
|
2418
|
-
]
|
|
2419
|
-
}
|
|
2420
|
-
)
|
|
2421
|
-
] }),
|
|
2422
|
-
/* @__PURE__ */ jsxs7("div", { className: "text-[11px] text-[#707070] font-mono truncate", children: [
|
|
2423
|
-
"To: ",
|
|
2424
|
-
truncateAddress(recipient, 10, 8)
|
|
2425
|
-
] })
|
|
2426
|
-
] })
|
|
2427
|
-
] }),
|
|
2428
|
-
memo && /* @__PURE__ */ jsxs7("div", { className: "p-2.5 bg-[#fafafa] rounded-md border border-[#ededed] text-xs", children: [
|
|
2429
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1 text-[11px] font-medium text-[#171717] mb-0.5", children: [
|
|
2430
|
-
/* @__PURE__ */ jsx8(Lock2, { className: "w-3 h-3 text-[#3ecf8e]" }),
|
|
2431
|
-
/* @__PURE__ */ jsx8("span", { children: "Encrypted Memo" })
|
|
2432
|
-
] }),
|
|
2433
|
-
/* @__PURE__ */ jsx8("div", { className: "font-mono text-[11px] text-[#171717]", children: memo })
|
|
2434
|
-
] }),
|
|
2435
|
-
memoValidation.warning && /* @__PURE__ */ jsxs7("div", { className: "p-2 rounded bg-amber-50 border border-amber-200 text-amber-800 text-[11px] flex items-start gap-1.5", children: [
|
|
2436
|
-
/* @__PURE__ */ jsx8(AlertCircle3, { className: "w-3.5 h-3.5 flex-shrink-0 mt-0.5 text-amber-600" }),
|
|
2437
|
-
/* @__PURE__ */ jsx8("span", { children: memoValidation.warning })
|
|
2438
|
-
] }),
|
|
2439
|
-
status === "expired" && /* @__PURE__ */ jsxs7("div", { className: "p-2 rounded bg-rose-50 border border-rose-200 text-rose-800 text-xs flex items-center justify-between", children: [
|
|
2440
|
-
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1.5", children: [
|
|
2441
|
-
/* @__PURE__ */ jsx8(AlertCircle3, { className: "w-3.5 h-3.5 text-rose-600" }),
|
|
2442
|
-
/* @__PURE__ */ jsx8("span", { children: "Invoice has expired" })
|
|
2443
|
-
] }),
|
|
2444
|
-
/* @__PURE__ */ jsx8(
|
|
2445
|
-
"button",
|
|
2446
|
-
{
|
|
2447
|
-
onClick: resetPayment,
|
|
2448
|
-
className: "px-2 py-0.5 text-[11px] font-medium rounded bg-[#171717] text-white hover:bg-[#212121]",
|
|
2449
|
-
children: "Reset"
|
|
2450
|
-
}
|
|
2451
|
-
)
|
|
2452
|
-
] }),
|
|
2453
|
-
/* @__PURE__ */ jsxs7("div", { className: "pt-2 border-t border-[#ededed] flex items-center justify-between text-[11px] text-[#707070]", children: [
|
|
2454
|
-
/* @__PURE__ */ jsxs7("span", { className: "flex items-center gap-1", children: [
|
|
2455
|
-
/* @__PURE__ */ jsx8(Sparkles3, { className: "w-3 h-3 text-[#3ecf8e]" }),
|
|
2456
|
-
"Demo test"
|
|
2457
|
-
] }),
|
|
2458
|
-
/* @__PURE__ */ jsx8(
|
|
2459
|
-
"button",
|
|
2460
|
-
{
|
|
2461
|
-
onClick: simulateDetection,
|
|
2462
|
-
className: "px-2 py-0.5 rounded border border-[#dfdfdf] hover:border-[#3ecf8e] text-[#171717] bg-white transition-colors",
|
|
2463
|
-
children: "Simulate Success"
|
|
2464
|
-
}
|
|
2465
|
-
)
|
|
2466
|
-
] })
|
|
2467
|
-
] }) })
|
|
2468
|
-
]
|
|
2469
|
-
}
|
|
2470
|
-
);
|
|
2471
|
-
};
|
|
2472
|
-
|
|
2473
1856
|
// src/hooks/useZucchiniWallet.ts
|
|
2474
|
-
import { useState as
|
|
1857
|
+
import { useState as useState5, useEffect as useEffect5, useCallback as useCallback3 } from "react";
|
|
2475
1858
|
function useZucchiniWallet(options = {}) {
|
|
2476
1859
|
const { autoConnect = false } = options;
|
|
2477
|
-
const [adapter2] =
|
|
2478
|
-
const [isAvailable, setIsAvailable] =
|
|
2479
|
-
const [connectionStatus, setConnectionStatus] =
|
|
2480
|
-
const [paymentStatus, setPaymentStatus] =
|
|
2481
|
-
const [session, setSession] =
|
|
2482
|
-
const [error, setError] =
|
|
2483
|
-
|
|
1860
|
+
const [adapter2] = useState5(() => new ZucchiniWalletAdapter());
|
|
1861
|
+
const [isAvailable, setIsAvailable] = useState5(false);
|
|
1862
|
+
const [connectionStatus, setConnectionStatus] = useState5("disconnected");
|
|
1863
|
+
const [paymentStatus, setPaymentStatus] = useState5("idle");
|
|
1864
|
+
const [session, setSession] = useState5(null);
|
|
1865
|
+
const [error, setError] = useState5(null);
|
|
1866
|
+
useEffect5(() => {
|
|
2484
1867
|
const detected = ZucchiniWalletAdapter.isAvailable();
|
|
2485
1868
|
setIsAvailable(detected);
|
|
2486
1869
|
if (detected && autoConnect) {
|
|
2487
1870
|
connect();
|
|
2488
1871
|
}
|
|
2489
1872
|
}, []);
|
|
2490
|
-
const connect =
|
|
1873
|
+
const connect = useCallback3(async () => {
|
|
2491
1874
|
setConnectionStatus("connecting");
|
|
2492
1875
|
setError(null);
|
|
2493
1876
|
try {
|
|
@@ -2502,7 +1885,7 @@ function useZucchiniWallet(options = {}) {
|
|
|
2502
1885
|
throw err;
|
|
2503
1886
|
}
|
|
2504
1887
|
}, [adapter2]);
|
|
2505
|
-
const requestPayment =
|
|
1888
|
+
const requestPayment = useCallback3(
|
|
2506
1889
|
async (params) => {
|
|
2507
1890
|
setPaymentStatus("requesting");
|
|
2508
1891
|
setError(null);
|
|
@@ -2519,7 +1902,7 @@ function useZucchiniWallet(options = {}) {
|
|
|
2519
1902
|
},
|
|
2520
1903
|
[adapter2]
|
|
2521
1904
|
);
|
|
2522
|
-
const disconnect =
|
|
1905
|
+
const disconnect = useCallback3(async () => {
|
|
2523
1906
|
await adapter2.disconnect();
|
|
2524
1907
|
setSession(null);
|
|
2525
1908
|
setConnectionStatus("disconnected");
|
|
@@ -2548,9 +1931,6 @@ export {
|
|
|
2548
1931
|
CiceroAccountModal,
|
|
2549
1932
|
CiceroConnectButton,
|
|
2550
1933
|
CiceroConnectModal,
|
|
2551
|
-
CiceroInvoice,
|
|
2552
|
-
CiceroModal,
|
|
2553
|
-
CiceroPayButton,
|
|
2554
1934
|
CiceroProvider,
|
|
2555
1935
|
CiceroQRCode,
|
|
2556
1936
|
ZucchiniWalletAdapter,
|
|
@@ -2568,7 +1948,6 @@ export {
|
|
|
2568
1948
|
useAccountModal,
|
|
2569
1949
|
useBalance,
|
|
2570
1950
|
useCicero,
|
|
2571
|
-
useCiceroPayment,
|
|
2572
1951
|
useConnectModal,
|
|
2573
1952
|
useZcashPrice,
|
|
2574
1953
|
useZucchiniWallet,
|