coinley-pay 0.26.0 → 0.27.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.
@@ -5,7 +5,7 @@ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
5
5
  import { useState, useRef, useEffect, useCallback, useMemo } from "react";
6
6
  import { useConnect, useAccount, useSwitchChain, useSendTransaction, useWaitForTransactionReceipt, WagmiProvider, useDisconnect } from "wagmi";
7
7
  import { QueryClientProvider, QueryClient } from "@tanstack/react-query";
8
- import { s as sdkAnalytics, c as clarityAnalytics, d as dist, a as Buffer2, B as Buffer$1, g as getCurrencyInfo, p as prefetchRates, i as isSupportedCurrency, b as convertToUSD, f as formatCurrency } from "./index-MRszoy4w.js";
8
+ import { s as sdkAnalytics, c as clarityAnalytics, d as dist, a as Buffer2, B as Buffer$1, g as getCurrencyInfo, p as prefetchRates, i as isSupportedCurrency, b as convertToUSD, f as formatCurrency } from "./index-CCOXI1rx.js";
9
9
  import { createConfig, fallback, http, getAccount as getAccount$1, getWalletClient, simulateContract, writeContract, readContract, waitForTransactionReceipt, estimateFeesPerGas as estimateFeesPerGas$1 } from "@wagmi/core";
10
10
  import { injected, metaMask, coinbaseWallet, walletConnect } from "@wagmi/connectors";
11
11
  import { defineChain as defineChain$1, erc20Abi, http as http$1, createPublicClient, fallback as fallback$1 } from "viem";
@@ -20453,7 +20453,7 @@ const PaymentStatus = ({
20453
20453
  const networkName = (selectedNetwork == null ? void 0 : selectedNetwork.name) || (selectedNetwork == null ? void 0 : selectedNetwork.displayName) || (selectedNetwork == null ? void 0 : selectedNetwork.shortName) || "Network";
20454
20454
  const explorerUrl = getExplorerUrl(transactionHash, selectedNetwork);
20455
20455
  const explorerName = getExplorerName(selectedNetwork);
20456
- return /* @__PURE__ */ jsxs("div", { className: "relative flex h-full min-h-0 w-full flex-col justify-between px-3 pb-0 pt-12", children: [
20456
+ return /* @__PURE__ */ jsxs("div", { className: "relative flex min-h-[500px] w-full flex-col px-3 pb-0 pt-12", children: [
20457
20457
  onClose && /* @__PURE__ */ jsx(
20458
20458
  "button",
20459
20459
  {
@@ -20478,7 +20478,7 @@ const PaymentStatus = ({
20478
20478
  ] })
20479
20479
  ] })
20480
20480
  ] }),
20481
- /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
20481
+ /* @__PURE__ */ jsxs("div", { className: "w-full flex-1", children: [
20482
20482
  /* @__PURE__ */ jsx("p", { className: "mb-1 text-xs font-medium text-[#4B5563]", children: "Transaction ID" }),
20483
20483
  /* @__PURE__ */ jsxs(
20484
20484
  "button",
@@ -21120,7 +21120,7 @@ const WalletSelector = ({
21120
21120
  try {
21121
21121
  setAppKitError(null);
21122
21122
  setWalletConnectAddress(solanaAccountState.address);
21123
- const { createWalletConnectAdapter } = await import("./appKitSolana-D38g1-Lm.js");
21123
+ const { createWalletConnectAdapter } = await import("./appKitSolana-CnR-9LnG.js");
21124
21124
  const adapter = createWalletConnectAdapter(solanaAccountState.address);
21125
21125
  await solanaWallet.connectWalletConnect(adapter, solanaAccountState.address);
21126
21126
  console.log("✅ WalletConnect synced with SDK");
@@ -21225,7 +21225,7 @@ const WalletSelector = ({
21225
21225
  setAppKitLoading(true);
21226
21226
  setAppKitError(null);
21227
21227
  try {
21228
- const { initializeAppKitEVM, openAppKitModal } = await import("./appKitEVM-Bu9jo5n-.js");
21228
+ const { initializeAppKitEVM, openAppKitModal } = await import("./appKitEVM-BWbPyL29.js");
21229
21229
  await initializeAppKitEVM(wagmiConfig);
21230
21230
  await openAppKitModal();
21231
21231
  } catch (error) {
@@ -21245,7 +21245,7 @@ const WalletSelector = ({
21245
21245
  setAppKitError(null);
21246
21246
  try {
21247
21247
  console.log("📦 Loading AppKit Solana module...");
21248
- const { initializeAppKitSolana } = await import("./appKitSolana-D38g1-Lm.js");
21248
+ const { initializeAppKitSolana } = await import("./appKitSolana-CnR-9LnG.js");
21249
21249
  console.log("✅ Module loaded, initializing...");
21250
21250
  const modal = await initializeAppKitSolana(solanaWallet);
21251
21251
  console.log("✅ AppKit Solana initialized successfully");
@@ -23282,6 +23282,11 @@ const CoinleyPaymentInternal = ({
23282
23282
  const [verifyingPayment, setVerifyingPayment] = useState(false);
23283
23283
  const [manualCheckStatus, setManualCheckStatus] = useState(null);
23284
23284
  const [processingStatusMessage, setProcessingStatusMessage] = useState("");
23285
+ const [underpaymentInfo, setUnderpaymentInfo] = useState(null);
23286
+ const [underpaymentChoice, setUnderpaymentChoice] = useState(null);
23287
+ const [underpaymentView, setUnderpaymentView] = useState("choice");
23288
+ const [refundAddress, setRefundAddress] = useState("");
23289
+ const [refundRequestSubmitted, setRefundRequestSubmitted] = useState(false);
23285
23290
  const manualCheckTimeout = useRef(null);
23286
23291
  const [copiedField, setCopiedField] = useState(null);
23287
23292
  const [expirationTime, setExpirationTime] = useState(null);
@@ -23421,6 +23426,46 @@ const CoinleyPaymentInternal = ({
23421
23426
  const hasCommittedTransaction = Boolean(
23422
23427
  currentTransactionHash || (solanaTransaction == null ? void 0 : solanaTransaction.txSignature) || (paymentData == null ? void 0 : paymentData.transactionHash)
23423
23428
  );
23429
+ const normalizeUnderpaymentInfo = useCallback((payment = {}) => {
23430
+ const raw = payment.underpayment || payment.underpaymentDetails || payment.shortPayment || payment.partialPayment || null;
23431
+ const statusText = String(payment.status || payment.depositStatus || (raw == null ? void 0 : raw.status) || "").toLowerCase();
23432
+ const paymentStateText = String(payment.paymentState || (raw == null ? void 0 : raw.paymentState) || "").toLowerCase();
23433
+ const hasUnderpaymentStatus = ["underpaid", "underpayment", "partial", "partial_payment", "short_paid", "shortfall"].includes(statusText) || ["underpaid", "partial", "short_paid", "shortfall"].includes(paymentStateText);
23434
+ const explicitUnderpayment = payment.isUnderpaid || payment.underpaid || (raw == null ? void 0 : raw.isUnderpaid) || (raw == null ? void 0 : raw.underpaid);
23435
+ if (!raw && !hasUnderpaymentStatus && !explicitUnderpayment) {
23436
+ return null;
23437
+ }
23438
+ const expected = Number(
23439
+ (raw == null ? void 0 : raw.expectedAmount) ?? payment.expectedAmount ?? payment.amount ?? payment.totalAmount ?? paymentAmount ?? 0
23440
+ );
23441
+ const received = Number(
23442
+ (raw == null ? void 0 : raw.receivedAmount) ?? (raw == null ? void 0 : raw.amountReceived) ?? payment.receivedAmount ?? payment.amountReceived ?? payment.depositAmount ?? payment.balance ?? 0
23443
+ );
23444
+ const shortfall = Number(
23445
+ (raw == null ? void 0 : raw.shortfallAmount) ?? (raw == null ? void 0 : raw.remainingAmount) ?? (raw == null ? void 0 : raw.amountRemaining) ?? (raw == null ? void 0 : raw.offsetAmount) ?? payment.shortfallAmount ?? payment.remainingAmount ?? payment.amountRemaining ?? payment.offsetAmount ?? Math.max(expected - received, 0)
23446
+ );
23447
+ if (!shortfall || shortfall <= 0) {
23448
+ return null;
23449
+ }
23450
+ return {
23451
+ expectedAmount: expected,
23452
+ receivedAmount: received,
23453
+ shortfallAmount: shortfall,
23454
+ tokenSymbol: (raw == null ? void 0 : raw.tokenSymbol) || (raw == null ? void 0 : raw.currency) || payment.currency || (selectedToken == null ? void 0 : selectedToken.symbol) || "Token",
23455
+ refundNetworkLabel: (raw == null ? void 0 : raw.refundNetworkLabel) || (raw == null ? void 0 : raw.refundNetwork) || payment.refundNetworkLabel || (selectedNetwork == null ? void 0 : selectedNetwork.displayName) || (selectedNetwork == null ? void 0 : selectedNetwork.name) || (selectedNetwork == null ? void 0 : selectedNetwork.shortName) || "selected network",
23456
+ paymentState: payment.paymentState || (raw == null ? void 0 : raw.paymentState) || statusText || "underpaid"
23457
+ };
23458
+ }, [paymentAmount, selectedNetwork, selectedToken]);
23459
+ const activateUnderpaymentFlow = useCallback((payment) => {
23460
+ const normalized = normalizeUnderpaymentInfo(payment);
23461
+ if (!normalized) return false;
23462
+ setUnderpaymentInfo(normalized);
23463
+ setUnderpaymentChoice(null);
23464
+ setUnderpaymentView("choice");
23465
+ setManualCheckStatus(null);
23466
+ setRefundRequestSubmitted(false);
23467
+ return true;
23468
+ }, [normalizeUnderpaymentInfo]);
23424
23469
  const selectedNetworkIsSolana = (selectedNetwork == null ? void 0 : selectedNetwork.chainType) === "solana" || (selectedNetwork == null ? void 0 : selectedNetwork.shortName) === "solana";
23425
23470
  const sourceNeedsMerchantBridge = Boolean(
23426
23471
  selectedNetwork && !selectedNetworkIsSolana && !isMerchantReceiveNetwork(selectedNetwork)
@@ -23873,6 +23918,11 @@ const CoinleyPaymentInternal = ({
23873
23918
  try {
23874
23919
  const statusResult = await paymentFlow.api.getDepositStatus(paymentData.id);
23875
23920
  if (statusResult.success && statusResult.payment) {
23921
+ if (activateUnderpaymentFlow(statusResult.payment)) {
23922
+ clearInterval(pollInterval);
23923
+ setCurrentStep(PAYMENT_STEPS.CONFIRM);
23924
+ return;
23925
+ }
23876
23926
  const status = statusResult.payment.status;
23877
23927
  const txHash = statusResult.payment.depositTxHash || statusResult.payment.sweepTxHash || statusResult.payment.transactionHash;
23878
23928
  if ((status === "completed" || status === "swept") && txHash) {
@@ -23929,7 +23979,7 @@ const CoinleyPaymentInternal = ({
23929
23979
  }
23930
23980
  }, 5e3);
23931
23981
  return () => clearInterval(pollInterval);
23932
- }, [currentStep, paymentData == null ? void 0 : paymentData.id, paymentData == null ? void 0 : paymentData.depositAddress, selectedNetwork, selectedToken, onSuccess]);
23982
+ }, [currentStep, paymentData == null ? void 0 : paymentData.id, paymentData == null ? void 0 : paymentData.depositAddress, selectedNetwork, selectedToken, onSuccess, activateUnderpaymentFlow]);
23933
23983
  useEffect(() => {
23934
23984
  const shouldPoll = (paymentData == null ? void 0 : paymentData.id) && (activeTab === PAYMENT_TABS.QR || activeTab === PAYMENT_TABS.TRANSFER) && currentStep === PAYMENT_STEPS.CONFIRM && !verifyingPayment && paymentType !== PAYMENT_TYPES.DEPOSIT;
23935
23985
  if (!shouldPoll) {
@@ -25457,6 +25507,10 @@ const CoinleyPaymentInternal = ({
25457
25507
  try {
25458
25508
  const statusResult = await paymentFlow.api.getDepositStatus(paymentData.id);
25459
25509
  if (statusResult.success && statusResult.payment) {
25510
+ if (activateUnderpaymentFlow(statusResult.payment)) {
25511
+ clearInterval(pollInterval);
25512
+ return;
25513
+ }
25460
25514
  const status = statusResult.payment.status;
25461
25515
  const txHash = statusResult.payment.depositTxHash || statusResult.payment.sweepTxHash || statusResult.payment.transactionHash;
25462
25516
  if ((status === "completed" || status === "swept") && txHash) {
@@ -25492,7 +25546,7 @@ const CoinleyPaymentInternal = ({
25492
25546
  console.log("🛑 Stopping deposit auto-detection polling");
25493
25547
  clearInterval(pollInterval);
25494
25548
  };
25495
- }, [paymentData == null ? void 0 : paymentData.id, paymentData == null ? void 0 : paymentData.depositAddress, paymentType, currentStep, verifyingPayment, expirationTime == null ? void 0 : expirationTime.expired, selectedNetwork, selectedToken, onSuccess, paymentFlow.api]);
25549
+ }, [paymentData == null ? void 0 : paymentData.id, paymentData == null ? void 0 : paymentData.depositAddress, paymentType, currentStep, verifyingPayment, expirationTime == null ? void 0 : expirationTime.expired, selectedNetwork, selectedToken, onSuccess, paymentFlow.api, activateUnderpaymentFlow]);
25496
25550
  useEffect(() => {
25497
25551
  return () => {
25498
25552
  if (manualCheckTimeout.current) {
@@ -25500,12 +25554,44 @@ const CoinleyPaymentInternal = ({
25500
25554
  }
25501
25555
  };
25502
25556
  }, []);
25557
+ useEffect(() => {
25558
+ setUnderpaymentInfo(null);
25559
+ setUnderpaymentChoice(null);
25560
+ setUnderpaymentView("choice");
25561
+ setRefundAddress("");
25562
+ setRefundRequestSubmitted(false);
25563
+ }, [paymentData == null ? void 0 : paymentData.id]);
25564
+ const handleRefundRequestSubmit = useCallback(() => {
25565
+ const trimmedAddress = refundAddress.trim();
25566
+ if (!trimmedAddress) return;
25567
+ setRefundRequestSubmitted(true);
25568
+ setManualCheckStatus(null);
25569
+ const refundPayload = {
25570
+ paymentId: paymentData == null ? void 0 : paymentData.id,
25571
+ refundAddress: trimmedAddress,
25572
+ amountReceived: underpaymentInfo == null ? void 0 : underpaymentInfo.receivedAmount,
25573
+ amountRemaining: underpaymentInfo == null ? void 0 : underpaymentInfo.shortfallAmount,
25574
+ network: selectedNetwork == null ? void 0 : selectedNetwork.shortName,
25575
+ currency: selectedToken == null ? void 0 : selectedToken.symbol
25576
+ };
25577
+ if (typeof (config == null ? void 0 : config.onRefundRequest) === "function") {
25578
+ config.onRefundRequest(refundPayload);
25579
+ }
25580
+ if (typeof window !== "undefined") {
25581
+ window.dispatchEvent(new CustomEvent("coinley:refund-requested", {
25582
+ detail: refundPayload
25583
+ }));
25584
+ }
25585
+ }, [config, refundAddress, paymentData == null ? void 0 : paymentData.id, selectedNetwork == null ? void 0 : selectedNetwork.shortName, selectedToken == null ? void 0 : selectedToken.symbol, underpaymentInfo]);
25503
25586
  const handleDepositManualCheck = useCallback(async () => {
25504
25587
  if (manualCheckStatus === "checking" || !(paymentData == null ? void 0 : paymentData.id)) return;
25505
25588
  setManualCheckStatus("checking");
25506
25589
  try {
25507
25590
  const statusResult = await paymentFlow.api.getDepositStatus(paymentData.id);
25508
25591
  if (statusResult.success && statusResult.payment) {
25592
+ if (activateUnderpaymentFlow(statusResult.payment)) {
25593
+ return;
25594
+ }
25509
25595
  const status = statusResult.payment.status;
25510
25596
  const txHash = statusResult.payment.depositTxHash || statusResult.payment.sweepTxHash || statusResult.payment.transactionHash;
25511
25597
  if ((status === "completed" || status === "swept") && txHash) {
@@ -25542,7 +25628,7 @@ const CoinleyPaymentInternal = ({
25542
25628
  setManualCheckStatus(null);
25543
25629
  }, 1e4);
25544
25630
  }
25545
- }, [manualCheckStatus, paymentData == null ? void 0 : paymentData.id, paymentFlow.api, config == null ? void 0 : config.amount, selectedNetwork, selectedToken, onSuccess]);
25631
+ }, [manualCheckStatus, paymentData == null ? void 0 : paymentData.id, paymentFlow.api, config == null ? void 0 : config.amount, selectedNetwork, selectedToken, onSuccess, activateUnderpaymentFlow]);
25546
25632
  if (!isOpen) return null;
25547
25633
  if (currentStep === PAYMENT_STEPS.PROCESSING) {
25548
25634
  return /* @__PURE__ */ jsxs("div", { id: SDK_ROOT_ID, className: `${SDK_ROOT_CLASS} fixed inset-0 z-50`, style: { fontFamily: FONT_FAMILY }, children: [
@@ -25588,7 +25674,7 @@ const CoinleyPaymentInternal = ({
25588
25674
  if (currentStep === PAYMENT_STEPS.SUCCESS) {
25589
25675
  return /* @__PURE__ */ jsxs("div", { id: SDK_ROOT_ID, className: `${SDK_ROOT_CLASS} fixed inset-0 z-50`, style: { fontFamily: FONT_FAMILY }, children: [
25590
25676
  /* @__PURE__ */ jsx("div", { className: "fixed inset-0 bg-black bg-opacity-50" }),
25591
- /* @__PURE__ */ jsx("div", { className: isMobile ? "fixed inset-0 flex items-end" : "fixed inset-0 flex items-center justify-center p-4", style: { zIndex: 51 }, children: /* @__PURE__ */ jsx("div", { className: isMobile ? "relative flex w-full max-h-[92vh] flex-col overflow-y-auto rounded-t-[28px] bg-white px-4 pb-5 pt-5 animate-slide-up-sheet" : "relative flex h-[553px] w-[450px] max-w-[calc(100vw-32px)] flex-col overflow-hidden rounded-[28px] bg-white px-4 pb-5 pt-5", children: /* @__PURE__ */ jsx(
25677
+ /* @__PURE__ */ jsx("div", { className: isMobile ? "fixed inset-0 flex items-end" : "fixed inset-0 flex items-center justify-center p-4", style: { zIndex: 51 }, children: /* @__PURE__ */ jsx("div", { className: isMobile ? "relative flex w-full max-h-[92vh] flex-col overflow-y-auto rounded-t-[28px] bg-white px-4 pb-5 pt-5 animate-slide-up-sheet" : "relative flex max-h-[calc(100vh-32px)] min-h-0 w-[450px] max-w-[calc(100vw-32px)] flex-col overflow-y-auto rounded-[28px] bg-white px-4 pb-5 pt-5", children: /* @__PURE__ */ jsx(
25592
25678
  PaymentStatus,
25593
25679
  {
25594
25680
  status: "success",
@@ -25605,6 +25691,8 @@ const CoinleyPaymentInternal = ({
25605
25691
  ] });
25606
25692
  }
25607
25693
  const paymentAmountLabel = isConverting ? "..." : `$${formatAmount(paymentAmount || (config == null ? void 0 : config.amount) || 0)}`;
25694
+ const underpaymentOffsetAmountLabel = underpaymentInfo ? `$${formatAmount(underpaymentInfo.shortfallAmount || 0)}` : paymentAmountLabel;
25695
+ const summaryPaymentAmountLabel = underpaymentInfo && (underpaymentView === "offset" || underpaymentView === "refund") ? underpaymentOffsetAmountLabel : paymentAmountLabel;
25608
25696
  const getTokenDisplaySymbol = (token) => (token == null ? void 0 : token.symbol) || (token == null ? void 0 : token.tokenSymbol) || (token == null ? void 0 : token.currency) || (token == null ? void 0 : token.ticker) || (token == null ? void 0 : token.name) || "Token";
25609
25697
  const getLogoFallbackUrl = (label = "?", background = "7042D2") => {
25610
25698
  const safeLabel = String(label || "?").slice(0, 2).toUpperCase();
@@ -25639,7 +25727,7 @@ const CoinleyPaymentInternal = ({
25639
25727
  /* @__PURE__ */ jsx("div", { className: "flex-1 pt-[13px] border-t border-dashed border-[#DFE1E7]" }),
25640
25728
  /* @__PURE__ */ jsxs("div", { className: "text-right", children: [
25641
25729
  /* @__PURE__ */ jsx("p", { className: "text-[11px] leading-none text-[#9EA0A8] mb-1", children: "To Pay:" }),
25642
- /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-[#1F2430]", children: paymentAmountLabel })
25730
+ /* @__PURE__ */ jsx("p", { className: "text-xs font-semibold text-[#1F2430]", children: summaryPaymentAmountLabel })
25643
25731
  ] })
25644
25732
  ] }),
25645
25733
  merchantCurrency !== "USD" && currencyInfo && exchangeRate && !isConverting && /* @__PURE__ */ jsxs("p", { className: "text-[11px] text-[#9EA0A8] mt-2", children: [
@@ -25665,6 +25753,141 @@ const CoinleyPaymentInternal = ({
25665
25753
  method.tab
25666
25754
  )) })
25667
25755
  ] });
25756
+ const renderUnderpaymentWarning = (title = "Amount received is less than expected", description = null) => /* @__PURE__ */ jsxs("div", { className: "mb-5 rounded-lg border border-[#F5E5B8] bg-[#FFF9E8] px-3 py-2", children: [
25757
+ /* @__PURE__ */ jsxs("div", { className: `flex items-start gap-2 text-[#B54708] ${title && description ? "mb-1" : ""}`, children: [
25758
+ /* @__PURE__ */ jsx("svg", { className: "mt-0.5 h-4 w-4 flex-shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v4m0 4h.01M12 3a9 9 0 110 18 9 9 0 010-18z" }) }),
25759
+ title ? /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold", children: title }) : /* @__PURE__ */ jsx("p", { className: "text-xs leading-5 text-[#B54708]", children: description })
25760
+ ] }),
25761
+ title && description && /* @__PURE__ */ jsx("p", { className: "pl-6 text-xs leading-5 text-[#B54708]", children: description })
25762
+ ] });
25763
+ const renderUnderpaymentOptionCard = ({ choice, icon, title, description }) => {
25764
+ const selected = underpaymentChoice === choice;
25765
+ return /* @__PURE__ */ jsxs(
25766
+ "button",
25767
+ {
25768
+ type: "button",
25769
+ onClick: () => {
25770
+ setUnderpaymentChoice(choice);
25771
+ setRefundRequestSubmitted(false);
25772
+ },
25773
+ className: `relative flex min-h-[118px] flex-1 flex-col items-start rounded-xl border p-3 text-left transition-colors ${selected ? "border-[#8B5CF6] bg-[#F4EEFF]" : "border-[#ECEEF2] bg-white hover:border-[#D7C5FF]"}`,
25774
+ children: [
25775
+ selected && /* @__PURE__ */ jsx("span", { className: "absolute right-[-7px] top-[-9px] flex h-5 w-5 items-center justify-center rounded-full border border-[#8B5CF6] bg-white text-[#7042D2]", children: /* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2.5, d: "M5 13l4 4L19 7" }) }) }),
25776
+ /* @__PURE__ */ jsx("div", { className: "mb-3 flex h-6 w-6 items-center justify-center text-[#111827]", children: icon }),
25777
+ /* @__PURE__ */ jsx("p", { className: "mb-1 text-sm font-semibold text-[#111827]", children: title }),
25778
+ /* @__PURE__ */ jsx("p", { className: "text-xs leading-4 text-[#A3A5AC]", children: description })
25779
+ ]
25780
+ }
25781
+ );
25782
+ };
25783
+ const renderUnderpaymentChoicePanel = () => /* @__PURE__ */ jsxs("div", { className: "pt-1", children: [
25784
+ renderUnderpaymentWarning(
25785
+ "Amount received is less than expected",
25786
+ `We received $${formatAmount(underpaymentInfo.receivedAmount || 0)} but expected $${formatAmount(underpaymentInfo.expectedAmount || paymentAmount || 0)}. Your transaction is on hold, please choose how to proceed.`
25787
+ ),
25788
+ /* @__PURE__ */ jsxs("div", { className: "mb-5 flex gap-2", children: [
25789
+ renderUnderpaymentOptionCard({
25790
+ choice: "offset",
25791
+ title: "Send offset",
25792
+ description: underpaymentChoice === "offset" ? "Top up the shortfall and complete this transfer with extended time" : "Top up the shortfall with extended time",
25793
+ icon: /* @__PURE__ */ jsx("svg", { className: "h-6 w-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.8, d: "M4 4v6h6M20 20v-6h-6M5.5 15.5A7 7 0 0017.7 18M18.5 8.5A7 7 0 006.3 6" }) })
25794
+ }),
25795
+ renderUnderpaymentOptionCard({
25796
+ choice: "refund",
25797
+ title: "Cancel & refund",
25798
+ description: "Cancel my transaction so i get refunded",
25799
+ icon: /* @__PURE__ */ jsxs("svg", { className: "h-6 w-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [
25800
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9", strokeWidth: 1.8 }),
25801
+ /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.8, d: "M9 9l6 6m0-6l-6 6" })
25802
+ ] })
25803
+ })
25804
+ ] }),
25805
+ /* @__PURE__ */ jsx(
25806
+ "button",
25807
+ {
25808
+ type: "button",
25809
+ disabled: !underpaymentChoice,
25810
+ onClick: () => {
25811
+ setRefundRequestSubmitted(false);
25812
+ if (underpaymentChoice === "offset") {
25813
+ modalOpenedAtRef.current = Date.now();
25814
+ setTimeRemaining(paymentTimeoutMs);
25815
+ }
25816
+ setUnderpaymentView(underpaymentChoice === "refund" ? "refund" : "offset");
25817
+ },
25818
+ className: `h-11 w-full rounded-xl px-4 text-sm font-semibold text-white transition-colors ${underpaymentChoice ? "bg-[#7042D2] hover:bg-[#5b34b1]" : "cursor-not-allowed bg-[#B59AE9]"}`,
25819
+ children: "Continue"
25820
+ }
25821
+ )
25822
+ ] });
25823
+ const renderUnderpaymentOffsetPanel = () => /* @__PURE__ */ jsxs("div", { className: "pt-1", children: [
25824
+ /* @__PURE__ */ jsxs("div", { className: "mb-5 flex items-start gap-3", children: [
25825
+ /* @__PURE__ */ jsx("div", { className: "h-[92px] w-[92px] flex-shrink-0 bg-white", children: depositQrCode ? /* @__PURE__ */ jsx("img", { src: depositQrCode, alt: "Deposit Address QR Code", className: "h-full w-full" }) : /* @__PURE__ */ jsx("div", { className: "flex h-full w-full items-center justify-center rounded-lg bg-gray-100", children: /* @__PURE__ */ jsx("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-[#E5E7EB] border-t-[#7042D2]" }) }) }),
25826
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 pt-1", children: [
25827
+ /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs font-medium text-[#1F2430]", children: "Same Wallet address" }),
25828
+ /* @__PURE__ */ jsxs("div", { className: "flex min-h-[58px] items-center gap-2 rounded-xl border border-[#EEF0F4] bg-[#FAFAFB] px-3 py-2", children: [
25829
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 break-all text-sm leading-5 text-[#1F2430]", children: paymentData.depositAddress }),
25830
+ /* @__PURE__ */ jsx(
25831
+ "button",
25832
+ {
25833
+ onClick: () => copyToClipboard(paymentData.depositAddress, "depositAddress"),
25834
+ className: `flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-lg transition-colors ${copiedField === "depositAddress" ? "bg-green-100 text-green-600" : "text-[#7042D2] hover:bg-purple-50"}`,
25835
+ "aria-label": "Copy wallet address",
25836
+ children: copiedField === "depositAddress" ? /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }) : /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" }) })
25837
+ }
25838
+ )
25839
+ ] })
25840
+ ] })
25841
+ ] }),
25842
+ renderUnderpaymentWarning(
25843
+ null,
25844
+ "Send only the offset amount to the same address. Make sure to add network fees on top of this amount."
25845
+ ),
25846
+ /* @__PURE__ */ jsx(
25847
+ "button",
25848
+ {
25849
+ type: "button",
25850
+ onClick: handleDepositManualCheck,
25851
+ disabled: manualCheckStatus === "checking",
25852
+ className: `h-11 w-full rounded-xl px-4 text-sm font-semibold text-white transition-colors ${manualCheckStatus === "checking" ? "cursor-not-allowed bg-purple-400" : "bg-[#7042D2] hover:bg-[#5b34b1]"}`,
25853
+ children: manualCheckStatus === "checking" ? "Checking for your payment..." : "I've sent the offset"
25854
+ }
25855
+ )
25856
+ ] });
25857
+ const renderUnderpaymentRefundPanel = () => /* @__PURE__ */ jsxs("div", { className: "pt-1", children: [
25858
+ renderUnderpaymentWarning(
25859
+ `Refund of $${formatAmount(underpaymentInfo.receivedAmount || 0)} ${underpaymentInfo.tokenSymbol}`,
25860
+ `Provide a ${underpaymentInfo.tokenSymbol} wallet address on the same network (${underpaymentInfo.refundNetworkLabel}) to receive your refund. Network fees will be deducted.`
25861
+ ),
25862
+ /* @__PURE__ */ jsxs("label", { className: "mb-2 block text-xs font-medium text-[#111827]", children: [
25863
+ "Your ",
25864
+ underpaymentInfo.tokenSymbol,
25865
+ " (",
25866
+ underpaymentInfo.refundNetworkLabel,
25867
+ ") receiving wallet address"
25868
+ ] }),
25869
+ /* @__PURE__ */ jsx(
25870
+ "input",
25871
+ {
25872
+ type: "text",
25873
+ value: refundAddress,
25874
+ onChange: (event) => setRefundAddress(event.target.value),
25875
+ placeholder: "Paste your wallet address here",
25876
+ className: "mb-5 h-11 w-full rounded-xl border border-[#E4E6EB] bg-white px-3 text-sm text-[#1F2430] outline-none transition-colors placeholder:text-[#8B8E98] focus:border-[#B49AF0]"
25877
+ }
25878
+ ),
25879
+ /* @__PURE__ */ jsx(
25880
+ "button",
25881
+ {
25882
+ type: "button",
25883
+ disabled: !refundAddress.trim(),
25884
+ onClick: handleRefundRequestSubmit,
25885
+ className: `h-11 w-full rounded-xl px-4 text-sm font-semibold text-white transition-colors ${refundAddress.trim() ? "bg-[#7042D2] hover:bg-[#5b34b1]" : "cursor-not-allowed bg-[#B59AE9]"}`,
25886
+ children: refundRequestSubmitted ? "Refund request submitted" : "Submit refund request"
25887
+ }
25888
+ ),
25889
+ refundRequestSubmitted && /* @__PURE__ */ jsx("p", { className: "mt-2 text-center text-xs leading-5 text-[#8B8E98]", children: "Keep this screen open while we continue checking the payment status." })
25890
+ ] });
25668
25891
  const transferNetworks = networks.filter((network) => {
25669
25892
  const chainId = parseInt(network.chainId);
25670
25893
  const supportedChains = [8453, 56, 42161, 137, 10, 43114, 143, 59144, 534352, 130];
@@ -26564,20 +26787,13 @@ const CoinleyPaymentInternal = ({
26564
26787
  activeTab === PAYMENT_TABS.QR && /* @__PURE__ */ jsx(Fragment, { children: qrWalletChoiceConfirmed ? renderQrPaymentPanel() : renderQrWalletChoicePanel() }),
26565
26788
  activeTab === PAYMENT_TABS.TRANSFER && /* @__PURE__ */ jsxs(Fragment, { children: [
26566
26789
  (!selectedNetwork || !selectedToken || !(paymentData == null ? void 0 : paymentData.depositAddress)) && renderTransferSetupPanel(),
26567
- selectedNetwork && selectedToken && (paymentData == null ? void 0 : paymentData.depositAddress) && /* @__PURE__ */ jsxs("div", { className: "pt-1", children: [
26568
- expirationTime && !expirationTime.expired && /* @__PURE__ */ jsxs("div", { className: "mb-4 rounded-lg border border-[#F2E8C8] bg-[#FFF9E8] px-3 py-2 text-xs font-medium text-[#C56416]", children: [
26569
- "Address expires in ",
26570
- String(expirationTime.minutes).padStart(2, "0"),
26571
- ":",
26572
- String(expirationTime.seconds).padStart(2, "0")
26573
- ] }),
26790
+ selectedNetwork && selectedToken && (paymentData == null ? void 0 : paymentData.depositAddress) && (underpaymentInfo ? /* @__PURE__ */ jsx(Fragment, { children: underpaymentView === "offset" ? renderUnderpaymentOffsetPanel() : underpaymentView === "refund" ? renderUnderpaymentRefundPanel() : renderUnderpaymentChoicePanel() }) : /* @__PURE__ */ jsxs("div", { className: "pt-1", children: [
26574
26791
  (expirationTime == null ? void 0 : expirationTime.expired) && /* @__PURE__ */ jsx("div", { className: "mb-4 rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-xs font-medium text-red-600", children: "Timer exhausted - No transaction detected. Please generate a new address." }),
26575
- /* @__PURE__ */ jsx("p", { className: "mb-4 text-xs leading-5 text-[#9EA0A8]", children: "Simply scan the QR code which holds just the address, input the amount, and transfer the funds" }),
26576
- /* @__PURE__ */ jsxs("div", { className: "mb-5 flex items-center gap-4", children: [
26792
+ /* @__PURE__ */ jsxs("div", { className: "mb-5 flex items-start gap-3", children: [
26577
26793
  /* @__PURE__ */ jsx("div", { className: "h-[92px] w-[92px] flex-shrink-0 bg-white", children: depositQrCode ? /* @__PURE__ */ jsx("img", { src: depositQrCode, alt: "Deposit Address QR Code", className: "h-full w-full" }) : /* @__PURE__ */ jsx("div", { className: "flex h-full w-full items-center justify-center rounded-lg bg-gray-100", children: /* @__PURE__ */ jsx("div", { className: "h-6 w-6 animate-spin rounded-full border-2 border-[#E5E7EB] border-t-[#7042D2]" }) }) }),
26578
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
26794
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 pt-1", children: [
26579
26795
  /* @__PURE__ */ jsx("p", { className: "mb-2 text-xs font-medium text-[#1F2430]", children: "Wallet address" }),
26580
- /* @__PURE__ */ jsxs("div", { className: "flex min-h-[60px] items-center gap-2 rounded-xl border border-[#EEF0F4] bg-[#FAFAFB] px-3 py-2", children: [
26796
+ /* @__PURE__ */ jsxs("div", { className: "flex min-h-[58px] items-center gap-2 rounded-xl border border-[#EEF0F4] bg-[#FAFAFB] px-3 py-2", children: [
26581
26797
  /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 break-all text-sm leading-5 text-[#1F2430]", children: paymentData.depositAddress }),
26582
26798
  /* @__PURE__ */ jsx(
26583
26799
  "button",
@@ -26591,6 +26807,13 @@ const CoinleyPaymentInternal = ({
26591
26807
  ] })
26592
26808
  ] })
26593
26809
  ] }),
26810
+ /* @__PURE__ */ jsxs("div", { className: "mb-3 rounded-lg border border-[#F5E5B8] bg-[#FFF9E8] px-3 py-2.5", children: [
26811
+ /* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-center gap-2 text-[#C55A11]", children: [
26812
+ /* @__PURE__ */ jsx("svg", { className: "h-4 w-4 flex-shrink-0", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v4m0 4h.01M12 3a9 9 0 110 18 9 9 0 010-18z" }) }),
26813
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold", children: "Important!" })
26814
+ ] }),
26815
+ /* @__PURE__ */ jsx("p", { className: "pl-6 text-xs leading-5 text-[#C55A11]", children: "We must receive the exact amount shown. If your exchange charges a withdrawal fee, add it on top of this amount before sending." })
26816
+ ] }),
26594
26817
  !(expirationTime == null ? void 0 : expirationTime.expired) && /* @__PURE__ */ jsx("div", { className: "mt-2", children: manualCheckStatus === "not_found" ? /* @__PURE__ */ jsxs("div", { className: "p-3 bg-amber-50 border border-amber-200 rounded-xl mb-3", children: [
26595
26818
  /* @__PURE__ */ jsx("p", { className: "text-sm text-amber-700", children: "We haven't received your payment yet. It may take a few moments for the transaction to appear on the blockchain. We'll keep checking automatically." }),
26596
26819
  /* @__PURE__ */ jsx(
@@ -26615,15 +26838,8 @@ const CoinleyPaymentInternal = ({
26615
26838
  "Checking for your payment..."
26616
26839
  ] }) : "I've made this transfer"
26617
26840
  }
26618
- ) }),
26619
- paymentData && !verifyingPayment && !(expirationTime == null ? void 0 : expirationTime.expired) && manualCheckStatus !== "not_found" && /* @__PURE__ */ jsxs("div", { className: "mt-4 flex items-center justify-center gap-2 text-xs text-[#A3A5AC]", children: [
26620
- /* @__PURE__ */ jsxs("span", { className: "relative flex h-2 w-2", children: [
26621
- /* @__PURE__ */ jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" }),
26622
- /* @__PURE__ */ jsx("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-green-500" })
26623
- ] }),
26624
- "Checking automatically every few seconds..."
26625
- ] })
26626
- ] })
26841
+ ) })
26842
+ ] }))
26627
26843
  ] }),
26628
26844
  (error || transactionError) && /* @__PURE__ */ jsxs("div", { className: "mt-4 p-4 bg-red-50 border border-red-200 rounded-xl", children: [
26629
26845
  /* @__PURE__ */ jsx("p", { className: "text-red-800 text-sm", children: error || transactionError }),
@@ -26663,6 +26879,10 @@ const CoinleyPaymentInternal = ({
26663
26879
  const isWalletTokenSelectionView = activeTab === PAYMENT_TABS.WALLET && selectedNetwork && !selectedToken && !showWalletConfirm && !(showMobileWalletPicker && isMobile);
26664
26880
  const isQrPaymentActiveView = activeTab === PAYMENT_TABS.QR && qrWalletChoiceConfirmed;
26665
26881
  const handleTransferAddressBack = async () => {
26882
+ if (underpaymentInfo && underpaymentView !== "choice") {
26883
+ setUnderpaymentView("choice");
26884
+ return;
26885
+ }
26666
26886
  setPaymentData((prev) => {
26667
26887
  if (!prev) return prev;
26668
26888
  return {
@@ -26674,6 +26894,11 @@ const CoinleyPaymentInternal = ({
26674
26894
  };
26675
26895
  });
26676
26896
  setExpirationTime(null);
26897
+ setUnderpaymentInfo(null);
26898
+ setUnderpaymentChoice(null);
26899
+ setUnderpaymentView("choice");
26900
+ setRefundAddress("");
26901
+ setRefundRequestSubmitted(false);
26677
26902
  await resetAllTransactionState();
26678
26903
  setActiveTab(PAYMENT_TABS.TRANSFER);
26679
26904
  };
@@ -26768,4 +26993,4 @@ export {
26768
26993
  isFeatureEnabled as i,
26769
26994
  logo as l
26770
26995
  };
26771
- //# sourceMappingURL=CoinleyPayment-tHjB69By.js.map
26996
+ //# sourceMappingURL=CoinleyPayment-Dy4VNYcm.js.map
@@ -1,4 +1,4 @@
1
- import { i as isFeatureEnabled, F as FEATURES, c as chainTransports, W as WALLETCONNECT_PROJECT_ID, l as logo } from "./CoinleyPayment-tHjB69By.js";
1
+ import { i as isFeatureEnabled, F as FEATURES, c as chainTransports, W as WALLETCONNECT_PROJECT_ID, l as logo } from "./CoinleyPayment-Dy4VNYcm.js";
2
2
  let appKitInstance = null;
3
3
  let isInitializing = false;
4
4
  let initializationPromise = null;
@@ -112,4 +112,4 @@ export {
112
112
  initializeAppKitEVM,
113
113
  openAppKitModal
114
114
  };
115
- //# sourceMappingURL=appKitEVM-Bu9jo5n-.js.map
115
+ //# sourceMappingURL=appKitEVM-BWbPyL29.js.map
@@ -1,4 +1,4 @@
1
- import { F as FEATURES, l as logo, W as WALLETCONNECT_PROJECT_ID } from "./CoinleyPayment-tHjB69By.js";
1
+ import { F as FEATURES, l as logo, W as WALLETCONNECT_PROJECT_ID } from "./CoinleyPayment-Dy4VNYcm.js";
2
2
  let appKitInstance = null;
3
3
  let isInitializing = false;
4
4
  let initializationPromise = null;
@@ -242,4 +242,4 @@ export {
242
242
  disconnectWalletConnect,
243
243
  initializeAppKitSolana
244
244
  };
245
- //# sourceMappingURL=appKitSolana-D38g1-Lm.js.map
245
+ //# sourceMappingURL=appKitSolana-CnR-9LnG.js.map