@cedros/pay-react
Version:
React frontend library for Cedros Pay - unified Stripe and Solana x402 payments
1,383 lines • 56.4 kB
JavaScript
import { jsxs as E, jsx as S } from "react/jsx-runtime";
import { useState as F, useCallback as x, useMemo as W, useEffect as B, useRef as Ce } from "react";
import { g as m, u as fe, a as me, f as se } from "./CedrosContext-CFEXGwQg.mjs";
import { useWallet as De } from "@solana/wallet-adapter-react";
import { WalletReadyState as ke } from "@solana/wallet-adapter-base";
import { WalletIcon as Ge } from "@solana/wallet-adapter-react-ui";
import "@solana/wallet-adapter-wallets";
function wt(e) {
return !e || !e.coupon_codes ? [] : e.coupon_codes.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
}
function bt(e, t = ", ") {
return e.join(t);
}
function vt(e, t) {
return e <= 0 ? 0 : (e - t) / e * 100;
}
function It(e, t) {
if (!t || t.length === 0)
return e;
let n = e, o = 0;
for (const a of t)
if (a.discountType === "percentage") {
const r = 1 - a.discountValue / 100;
n = n * r;
} else a.discountType === "fixed" && (o += a.discountValue);
return n = n - o, n < 0 && (n = 0), Math.ceil(n * 100) / 100;
}
function Ee(e) {
const t = Number(e);
if (!Number.isFinite(t) || t <= 0)
return 1;
const n = Math.floor(t);
return n > 0 ? n : 1;
}
function Oe(e) {
return e.map((t) => ({
resource: t.resource,
quantity: Ee(t.quantity),
metadata: t.metadata
}));
}
function K(e) {
return e.reduce((t, n) => t + Ee(n.quantity), 0);
}
function Ve(e) {
return !!(e && e.length > 0 && (e.length > 1 || e.length === 1 && (e[0].quantity ?? 1) > 1));
}
const Xe = {
// ===== PAYMENT VERIFICATION ERRORS (402) =====
invalid_payment_proof: {
message: "Payment verification failed",
action: "Please try your payment again. If this continues, contact support.",
technicalHint: "Invalid payment proof format"
},
invalid_signature: {
message: "Transaction signature is invalid",
action: "Please approve the transaction in your wallet and try again.",
technicalHint: "Transaction signature verification failed"
},
invalid_transaction: {
message: "Transaction format is invalid",
action: "Please try your payment again. If this continues, try updating your wallet app.",
technicalHint: "Malformed transaction structure"
},
transaction_not_found: {
message: "Transaction not found on the blockchain",
action: "Your transaction may still be processing. Please wait a moment and check your wallet, or try again.",
technicalHint: "Transaction signature not found on-chain"
},
transaction_not_confirmed: {
message: "Transaction is still processing",
action: "Please wait a moment for the blockchain to confirm your transaction, then try again.",
technicalHint: "Transaction not yet confirmed"
},
transaction_failed: {
message: "Transaction failed on the blockchain",
action: "Check your wallet for details. You may need to adjust your transaction settings or add more SOL for fees.",
technicalHint: "On-chain transaction failure"
},
transaction_expired: {
message: "Transaction took too long to process",
action: "Please try your payment again. Consider increasing transaction priority if your wallet supports it.",
technicalHint: "Transaction blockhash expired"
},
invalid_recipient: {
message: "Payment was sent to the wrong address",
action: "Please try again and ensure you approve the correct transaction in your wallet.",
technicalHint: "Recipient address mismatch"
},
invalid_sender: {
message: "Payment sender wallet is invalid",
action: "Please reconnect your wallet and try again.",
technicalHint: "Sender address validation failed"
},
unauthorized_refund_issuer: {
message: "You are not authorized to issue refunds",
action: "Only authorized accounts can process refunds. Please contact support if you believe this is an error.",
technicalHint: "Refund issuer not in authorized list"
},
amount_below_minimum: {
message: "Payment amount is too low",
action: "Please check the required amount and try again.",
technicalHint: "Amount below minimum threshold"
},
amount_mismatch: {
message: "Payment amount does not match the quote",
action: "The price may have changed. Please refresh and try your payment again.",
technicalHint: "Amount does not match quote"
},
insufficient_funds_sol: {
message: "Not enough SOL for transaction fees",
action: "Add at least 0.001 SOL to your wallet to cover network fees, then try again.",
technicalHint: "Insufficient SOL balance for fees"
},
insufficient_funds_token: {
message: "Insufficient balance in your wallet",
action: "Add more funds to your wallet and try again.",
technicalHint: "Insufficient token balance"
},
invalid_token_mint: {
message: "Incorrect payment token",
action: "Please pay with the correct token as shown in the payment details.",
technicalHint: "Token mint address mismatch"
},
not_spl_transfer: {
message: "Transaction is not a valid token transfer",
action: "Please ensure you are sending the correct token type from your wallet.",
technicalHint: "Transaction is not an SPL token transfer"
},
missing_token_account: {
message: "Token account not found",
action: "Your wallet may need to create a token account first. Try again or use a different wallet.",
technicalHint: "Associated token account does not exist"
},
invalid_token_program: {
message: "Invalid token program",
action: "Please try your payment again. If this continues, try using a different wallet.",
technicalHint: "Token program ID mismatch"
},
missing_memo: {
message: "Payment memo is required but was not included",
action: "Please try your payment again and ensure transaction details are approved in your wallet.",
technicalHint: "Required memo instruction missing"
},
invalid_memo: {
message: "Payment memo format is invalid",
action: "Please try your payment again.",
technicalHint: "Memo does not match expected format"
},
payment_already_used: {
message: "This payment has already been processed",
action: "Check your transaction history. If you need to make another payment, please start a new transaction.",
technicalHint: "Payment signature already recorded"
},
signature_reused: {
message: "Transaction signature has already been used",
action: "Please create a new payment transaction.",
technicalHint: "Duplicate signature detected"
},
quote_expired: {
message: "Payment quote has expired",
action: "Prices are updated frequently. Please refresh and try your payment again.",
technicalHint: "Quote timestamp expired"
},
// ===== VALIDATION ERRORS (400) =====
missing_field: {
message: "Required information is missing",
action: "Please check all required fields and try again.",
technicalHint: "Required field not provided"
},
invalid_field: {
message: "Some information is invalid",
action: "Please check your input and try again.",
technicalHint: "Field validation failed"
},
invalid_amount: {
message: "Payment amount is invalid",
action: "Please check the amount and try again.",
technicalHint: "Amount validation failed"
},
invalid_wallet: {
message: "Wallet address is invalid",
action: "Please reconnect your wallet and try again.",
technicalHint: "Wallet address validation failed"
},
invalid_resource: {
message: "Invalid item selection",
action: "Please refresh the page and try again.",
technicalHint: "Resource ID validation failed"
},
invalid_coupon: {
message: "Invalid coupon code",
action: "Please check the coupon code and try again.",
technicalHint: "Coupon code format invalid"
},
invalid_cart_item: {
message: "One or more cart items are invalid",
action: "Please review your cart and try again.",
technicalHint: "Cart item validation failed"
},
empty_cart: {
message: "Your cart is empty",
action: "Please add items to your cart before checking out.",
technicalHint: "Cart contains no items"
},
// ===== RESOURCE/STATE ERRORS (404) =====
resource_not_found: {
message: "Item not found",
action: "This item may no longer be available. Please refresh and try again.",
technicalHint: "Resource not found in database"
},
cart_not_found: {
message: "Shopping cart not found",
action: "Your cart may have expired. Please start a new order.",
technicalHint: "Cart ID not found"
},
refund_not_found: {
message: "Refund not found",
action: "Please check your refund reference number or contact support.",
technicalHint: "Refund ID not found"
},
product_not_found: {
message: "Product not available",
action: "This product may no longer be available. Please browse our current selection.",
technicalHint: "Product ID not found"
},
coupon_not_found: {
message: "Coupon code not found",
action: "Please check the coupon code or remove it to continue.",
technicalHint: "Coupon code not in database"
},
session_not_found: {
message: "Payment session expired",
action: "Please start a new payment.",
technicalHint: "Session ID not found or expired"
},
cart_already_paid: {
message: "This order has already been paid",
action: "Check your order history. If you need to make another purchase, please start a new order.",
technicalHint: "Cart marked as paid"
},
refund_already_processed: {
message: "This refund has already been processed",
action: "Check your transaction history or contact support for details.",
technicalHint: "Refund already completed"
},
// ===== COUPON-SPECIFIC ERRORS (409) =====
coupon_expired: {
message: "Coupon has expired",
action: "Please remove the coupon code or use a different code.",
technicalHint: "Coupon expiration date passed"
},
coupon_usage_limit_reached: {
message: "Coupon usage limit reached",
action: "This coupon has been fully redeemed. Please try a different code.",
technicalHint: "Coupon max uses exceeded"
},
coupon_not_applicable: {
message: "Coupon cannot be applied to this purchase",
action: "Please check the coupon terms or remove it to continue.",
technicalHint: "Coupon conditions not met"
},
coupon_wrong_payment_method: {
message: "Coupon not valid for this payment method",
action: "Try a different payment method or remove the coupon code.",
technicalHint: "Coupon restricted to specific payment methods"
},
// ===== EXTERNAL SERVICE ERRORS (502) =====
stripe_error: {
message: "Card payment service temporarily unavailable",
action: "Please try again in a moment, or use cryptocurrency payment instead.",
technicalHint: "Stripe API error"
},
rpc_error: {
message: "Blockchain network temporarily unavailable",
action: "Please try again in a moment, or use card payment instead.",
technicalHint: "Solana RPC error"
},
network_error: {
message: "Network connection issue",
action: "Please check your internet connection and try again.",
technicalHint: "Network request failed"
},
// ===== INTERNAL/SYSTEM ERRORS (500) =====
internal_error: {
message: "Something went wrong on our end",
action: "Please try again. If this continues, contact support.",
technicalHint: "Internal server error"
},
database_error: {
message: "Service temporarily unavailable",
action: "Please try again in a moment.",
technicalHint: "Database operation failed"
},
config_error: {
message: "Service configuration error",
action: "Please contact support for assistance.",
technicalHint: "Server misconfiguration"
}
};
function ne(e) {
return Xe[e] || {
message: "An unexpected error occurred",
action: "Please try again or contact support if this continues.",
technicalHint: `Unknown error code: ${e}`
};
}
const xe = /* @__PURE__ */ new Map(), le = /* @__PURE__ */ new Map(), ue = /* @__PURE__ */ new Map(), Ae = 200, ge = 2e3;
function Ke(e) {
const t = ue.get(e);
return t ? Date.now() < t ? !0 : (ue.delete(e), !1) : !1;
}
function Qe(e, t = Ae) {
const n = Date.now() + t;
ue.set(e, n);
}
function Ze(e, t = ge) {
const n = xe.get(e);
if (!n)
return !1;
const a = Date.now() - n;
return a < t ? (m().debug(`[Deduplication] Duplicate request blocked: ${e} (${a}ms ago)`), !0) : !1;
}
function Je(e) {
xe.set(e, Date.now());
}
function et(e) {
return le.get(e) || null;
}
function tt(e, t) {
le.set(e, t);
const n = () => {
le.delete(e), Je(e);
};
return t.then(n, n), t;
}
async function nt(e, t, n = {}) {
const { windowMs: o = ge, throwOnDuplicate: a = !0 } = n, r = et(e);
if (r)
return m().debug(`[Deduplication] Reusing in-flight request: ${e}`), r;
if (Ze(e, o)) {
if (a)
throw new Error(`Duplicate request blocked: ${e}`);
return m().warn(`[Deduplication] Duplicate request blocked but not throwing: ${e}`), Promise.reject(new Error("Duplicate request"));
}
const l = t();
return tt(e, l);
}
function Le(e, t, n = {}) {
const { cooldownMs: o = Ae, deduplicationWindowMs: a = ge } = n;
return async () => {
if (Ke(e)) {
m().debug(`[Deduplication] Button in cooldown: ${e}`);
return;
}
Qe(e, o);
try {
await nt(
e,
async () => {
const r = t();
r instanceof Promise && await r;
},
{ windowMs: a, throwOnDuplicate: !1 }
);
} catch (r) {
if (r instanceof Error && r.message.includes("Duplicate request"))
return;
throw r;
}
};
}
function je(e) {
return {
background: "none",
border: "none",
fontSize: "1.5rem",
cursor: "pointer",
color: e,
opacity: 0.6,
padding: "0.25rem",
lineHeight: 1
};
}
const $ = {
PAYMENT_START: "cedros:payment:start",
WALLET_CONNECT: "cedros:wallet:connect",
WALLET_CONNECTED: "cedros:wallet:connected",
WALLET_ERROR: "cedros:wallet:error",
PAYMENT_PROCESSING: "cedros:payment:processing",
PAYMENT_SUCCESS: "cedros:payment:success",
PAYMENT_ERROR: "cedros:payment:error"
};
function z(e, t) {
if (typeof window > "u")
return;
const n = new CustomEvent(e, {
detail: t,
bubbles: !0,
cancelable: !1
});
window.dispatchEvent(n);
}
function Me(e, t, n) {
z($.PAYMENT_START, {
timestamp: Date.now(),
method: e,
resource: t,
itemCount: n
});
}
function Se(e) {
z($.WALLET_CONNECT, {
timestamp: Date.now(),
wallet: e
});
}
function at(e, t) {
z($.WALLET_CONNECTED, {
timestamp: Date.now(),
wallet: e,
publicKey: t
});
}
function ie(e, t) {
z($.WALLET_ERROR, {
timestamp: Date.now(),
wallet: t,
error: e
});
}
function de(e, t, n) {
z($.PAYMENT_PROCESSING, {
timestamp: Date.now(),
method: e,
resource: t,
itemCount: n
});
}
function He(e, t, n, o) {
z($.PAYMENT_SUCCESS, {
timestamp: Date.now(),
method: e,
transactionId: t,
resource: n,
itemCount: o
});
}
function ae(e, t, n, o) {
z($.PAYMENT_ERROR, {
timestamp: Date.now(),
method: e,
error: t,
resource: n,
itemCount: o
});
}
var pe = /* @__PURE__ */ ((e) => (e.INVALID_PAYMENT_PROOF = "invalid_payment_proof", e.INVALID_SIGNATURE = "invalid_signature", e.INVALID_TRANSACTION = "invalid_transaction", e.TRANSACTION_NOT_FOUND = "transaction_not_found", e.TRANSACTION_NOT_CONFIRMED = "transaction_not_confirmed", e.TRANSACTION_FAILED = "transaction_failed", e.TRANSACTION_EXPIRED = "transaction_expired", e.INVALID_RECIPIENT = "invalid_recipient", e.INVALID_SENDER = "invalid_sender", e.UNAUTHORIZED_REFUND_ISSUER = "unauthorized_refund_issuer", e.AMOUNT_BELOW_MINIMUM = "amount_below_minimum", e.AMOUNT_MISMATCH = "amount_mismatch", e.INSUFFICIENT_FUNDS_SOL = "insufficient_funds_sol", e.INSUFFICIENT_FUNDS_TOKEN = "insufficient_funds_token", e.INVALID_TOKEN_MINT = "invalid_token_mint", e.NOT_SPL_TRANSFER = "not_spl_transfer", e.MISSING_TOKEN_ACCOUNT = "missing_token_account", e.INVALID_TOKEN_PROGRAM = "invalid_token_program", e.MISSING_MEMO = "missing_memo", e.INVALID_MEMO = "invalid_memo", e.PAYMENT_ALREADY_USED = "payment_already_used", e.SIGNATURE_REUSED = "signature_reused", e.QUOTE_EXPIRED = "quote_expired", e.MISSING_FIELD = "missing_field", e.INVALID_FIELD = "invalid_field", e.INVALID_AMOUNT = "invalid_amount", e.INVALID_WALLET = "invalid_wallet", e.INVALID_RESOURCE = "invalid_resource", e.INVALID_COUPON = "invalid_coupon", e.INVALID_CART_ITEM = "invalid_cart_item", e.EMPTY_CART = "empty_cart", e.RESOURCE_NOT_FOUND = "resource_not_found", e.CART_NOT_FOUND = "cart_not_found", e.REFUND_NOT_FOUND = "refund_not_found", e.PRODUCT_NOT_FOUND = "product_not_found", e.COUPON_NOT_FOUND = "coupon_not_found", e.SESSION_NOT_FOUND = "session_not_found", e.CART_ALREADY_PAID = "cart_already_paid", e.REFUND_ALREADY_PROCESSED = "refund_already_processed", e.COUPON_EXPIRED = "coupon_expired", e.COUPON_USAGE_LIMIT_REACHED = "coupon_usage_limit_reached", e.COUPON_NOT_APPLICABLE = "coupon_not_applicable", e.COUPON_WRONG_PAYMENT_METHOD = "coupon_wrong_payment_method", e.STRIPE_ERROR = "stripe_error", e.RPC_ERROR = "rpc_error", e.NETWORK_ERROR = "network_error", e.INTERNAL_ERROR = "internal_error", e.DATABASE_ERROR = "database_error", e.CONFIG_ERROR = "config_error", e))(pe || {});
class M extends Error {
/** Machine-readable error code enum */
code;
/** Whether this error can be safely retried */
retryable;
/** Additional error context */
details;
/** HTTP status code (if from API response) */
httpStatus;
constructor(t, n, o = !1, a, r) {
super(n), this.name = "PaymentError", this.code = t, this.retryable = o, this.details = a, this.httpStatus = r, Object.setPrototypeOf(this, M.prototype);
}
/**
* Check if this error is retryable
*/
canRetry() {
return this.retryable;
}
/**
* Check if this is a specific error code
*/
is(t) {
return this.code === t;
}
/**
* Check if this error is in a specific category
*/
isInCategory(t) {
return t.includes(this.code);
}
/**
* Get a user-friendly error message
* Uses structured error messages with actionable guidance
*/
getUserMessage() {
const t = this.getErrorInfo();
return t.action ? `${t.message} ${t.action}` : t.message;
}
/**
* Get short error message without action guidance
*/
getShortMessage() {
return this.getErrorInfo().message;
}
/**
* Get actionable guidance for this error
*/
getAction() {
return this.getErrorInfo().action;
}
/**
* Get error info from error messages map
* @private
*/
getErrorInfo() {
return ne(this.code);
}
/**
* Create PaymentError from API error response
*/
static fromErrorResponse(t, n) {
return new M(
t.error.code,
t.error.message,
t.error.retryable,
t.error.details,
n
);
}
/**
* Create PaymentError from unknown error
* Useful for catch blocks where error type is unknown
*/
static fromUnknown(t) {
return t instanceof M ? t : t instanceof Error ? new M(
"internal_error",
t.message,
!1
) : new M(
"internal_error",
String(t),
!1
);
}
}
const Tt = {
/** Insufficient funds errors requiring user to add funds */
INSUFFICIENT_FUNDS: [
"insufficient_funds_sol",
"insufficient_funds_token"
/* INSUFFICIENT_FUNDS_TOKEN */
],
/** Transaction state errors that may resolve with time */
TRANSACTION_PENDING: [
"transaction_not_confirmed",
"transaction_not_found"
/* TRANSACTION_NOT_FOUND */
],
/** Validation errors requiring input correction */
VALIDATION: [
"missing_field",
"invalid_field",
"invalid_amount",
"invalid_wallet",
"invalid_resource",
"invalid_cart_item",
"empty_cart"
/* EMPTY_CART */
],
/** Coupon-related errors */
COUPON: [
"invalid_coupon",
"coupon_not_found",
"coupon_expired",
"coupon_usage_limit_reached",
"coupon_not_applicable",
"coupon_wrong_payment_method"
/* COUPON_WRONG_PAYMENT_METHOD */
],
/** Retryable errors (temporary failures) */
RETRYABLE: [
"transaction_not_confirmed",
"rpc_error",
"network_error",
"stripe_error"
/* STRIPE_ERROR */
],
/** Resource not found errors */
NOT_FOUND: [
"resource_not_found",
"cart_not_found",
"refund_not_found",
"product_not_found",
"coupon_not_found",
"session_not_found"
/* SESSION_NOT_FOUND */
]
};
async function Rt(e) {
const t = e.status;
try {
const n = await e.json();
if (n.error && typeof n.error.code == "string") {
const o = n;
return M.fromErrorResponse(o, t);
}
return new M(
pe.INTERNAL_ERROR,
n.error || n.message || "An unknown error occurred",
!1,
void 0,
t
);
} catch {
return new M(
pe.INTERNAL_ERROR,
e.statusText || "Request failed",
!1,
void 0,
t
);
}
}
function Nt(e) {
return e instanceof M && e.canRetry();
}
function Ct(e) {
return e instanceof M ? e.getUserMessage() : e instanceof Error ? e.message : String(e);
}
function ot() {
const { stripeManager: e } = fe(), [t, n] = F({
status: "idle",
error: null,
transactionId: null
}), o = x(
async (l, d, N, g, _, w) => {
n({
status: "loading",
error: null,
transactionId: null
});
const y = {
resource: l,
successUrl: d,
cancelUrl: N,
metadata: g,
customerEmail: _,
couponCode: w
}, b = await e.processPayment(y);
return n({
status: b.success ? "success" : "error",
error: b.success ? null : b.error || "Payment failed",
transactionId: b.success && b.transactionId || null
}), b;
},
[e]
), a = x(
async (l, d, N, g, _, w) => {
n({
status: "loading",
error: null,
transactionId: null
});
const y = Oe(l), b = await e.processCartCheckout({
items: y,
successUrl: d,
cancelUrl: N,
metadata: g,
customerEmail: _,
couponCode: w
});
return n({
status: b.success ? "success" : "error",
error: b.success ? null : b.error || "Cart checkout failed",
transactionId: b.success && b.transactionId || null
}), b;
},
[e]
), r = x(() => {
n({
status: "idle",
error: null,
transactionId: null
});
}, []);
return {
...t,
processPayment: o,
processCartCheckout: a,
reset: r
};
}
function Fe(e, t) {
const n = Ve(t), o = e || (t?.length === 1 ? t[0].resource : "");
return {
isCartMode: n,
effectiveResource: o
};
}
const rt = (e, t, n) => {
const o = e[t];
return o ? typeof o == "function" ? o() : Promise.resolve(o) : new Promise((a, r) => {
(typeof queueMicrotask == "function" ? queueMicrotask : setTimeout)(r.bind(null, /* @__PURE__ */ new Error("Unknown variable dynamic import: " + t + (t.split("/").length !== n ? ". Note that variables only represent file names one level deep." : ""))));
});
}, ce = /* @__PURE__ */ new Map();
let te = null;
async function Pe(e) {
if (ce.has(e))
return ce.get(e);
try {
const t = await rt(/* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-w27mU-4x.mjs"), "./translations/bn.json": () => import("./bn-Ba_k3Kex.mjs"), "./translations/de.json": () => import("./de-CoZiPFN7.mjs"), "./translations/en.json": () => import("./en-C739WV_-.mjs"), "./translations/es.json": () => import("./es-BWGIBp2f.mjs"), "./translations/fil.json": () => import("./fil-Czo27xmj.mjs"), "./translations/fr.json": () => import("./fr-DQ-2ThBv.mjs"), "./translations/he.json": () => import("./he-DpV1WnBQ.mjs"), "./translations/id.json": () => import("./id-BJMqsu19.mjs"), "./translations/in.json": () => import("./in-BxgxKLQH.mjs"), "./translations/it.json": () => import("./it-DZFFPALf.mjs"), "./translations/jp.json": () => import("./jp-ZExTrlHK.mjs"), "./translations/kr.json": () => import("./kr-DHX3i4Ht.mjs"), "./translations/ms.json": () => import("./ms-Cv1fdIi2.mjs"), "./translations/nl.json": () => import("./nl-BmGonsKb.mjs"), "./translations/pa.json": () => import("./pa-BfwcJIar.mjs"), "./translations/pl.json": () => import("./pl-DE5IB9xv.mjs"), "./translations/pt.json": () => import("./pt-CLzkqDzf.mjs"), "./translations/ru.json": () => import("./ru-DM6-oUR0.mjs"), "./translations/ta.json": () => import("./ta-A5HnrGb5.mjs"), "./translations/th.json": () => import("./th-3fbB3Ytp.mjs"), "./translations/tr.json": () => import("./tr-BrgfFFdq.mjs"), "./translations/uk.json": () => import("./uk-0hFun_g_.mjs"), "./translations/ur.json": () => import("./ur-CaOjJXai.mjs"), "./translations/vn.json": () => import("./vn-0nlIZFLP.mjs"), "./translations/zh.json": () => import("./zh-B4Endr1F.mjs") }), `./translations/${e}.json`, 3), n = t.default || t;
return ce.set(e, n), n;
} catch {
return null;
}
}
async function kt() {
if (te)
return te;
const e = /* @__PURE__ */ Object.assign({ "./translations/ar.json": () => import("./ar-w27mU-4x.mjs"), "./translations/bn.json": () => import("./bn-Ba_k3Kex.mjs"), "./translations/de.json": () => import("./de-CoZiPFN7.mjs"), "./translations/en.json": () => import("./en-C739WV_-.mjs"), "./translations/es.json": () => import("./es-BWGIBp2f.mjs"), "./translations/fil.json": () => import("./fil-Czo27xmj.mjs"), "./translations/fr.json": () => import("./fr-DQ-2ThBv.mjs"), "./translations/he.json": () => import("./he-DpV1WnBQ.mjs"), "./translations/id.json": () => import("./id-BJMqsu19.mjs"), "./translations/in.json": () => import("./in-BxgxKLQH.mjs"), "./translations/it.json": () => import("./it-DZFFPALf.mjs"), "./translations/jp.json": () => import("./jp-ZExTrlHK.mjs"), "./translations/kr.json": () => import("./kr-DHX3i4Ht.mjs"), "./translations/ms.json": () => import("./ms-Cv1fdIi2.mjs"), "./translations/nl.json": () => import("./nl-BmGonsKb.mjs"), "./translations/pa.json": () => import("./pa-BfwcJIar.mjs"), "./translations/pl.json": () => import("./pl-DE5IB9xv.mjs"), "./translations/pt.json": () => import("./pt-CLzkqDzf.mjs"), "./translations/ru.json": () => import("./ru-DM6-oUR0.mjs"), "./translations/ta.json": () => import("./ta-A5HnrGb5.mjs"), "./translations/th.json": () => import("./th-3fbB3Ytp.mjs"), "./translations/tr.json": () => import("./tr-BrgfFFdq.mjs"), "./translations/uk.json": () => import("./uk-0hFun_g_.mjs"), "./translations/ur.json": () => import("./ur-CaOjJXai.mjs"), "./translations/vn.json": () => import("./vn-0nlIZFLP.mjs"), "./translations/zh.json": () => import("./zh-B4Endr1F.mjs") }), t = [];
for (const n in e) {
const o = n.match(/\.\/translations\/([a-z]{2,3}(?:-[A-Z]{2})?)\.json$/);
o && t.push(o[1]);
}
return te = t.length > 0 ? t : ["en"], te;
}
function st() {
return typeof navigator > "u" ? "en" : (navigator.language || navigator.userLanguage || "en").split("-")[0].toLowerCase();
}
async function it(e) {
let t = await Pe(e);
if (t || (t = await Pe("en"), t))
return t;
throw new Error("Critical: No translation files found, not even en.json");
}
function ct(e) {
return (t, n) => {
const o = t.split(".");
let a = e;
for (const r of o)
if (a && typeof a == "object" && r in a)
a = a[r];
else
return t;
return typeof a != "string" ? t : n ? Object.entries(n).reduce(
(r, [l, d]) => r.replace(new RegExp(`\\{${l}\\}`, "g"), d),
a
) : a;
};
}
function St(e, t, n = !0) {
const o = t.errors[e];
if (!o) {
const a = ne(e);
return n && a.action ? `${a.message} ${a.action}` : a.message;
}
return n && o.action ? `${o.message} ${o.action}` : o.message;
}
function ye(e) {
const [t, n] = F(null), [o, a] = F(!0), r = W(() => e || st(), [e]);
return B(() => {
let d = !1;
return (async () => {
a(!0);
try {
const g = await it(r);
d || (n(g), a(!1));
} catch (g) {
console.error("[CedrosPay] Failed to load translations:", g), d || a(!1);
}
})(), () => {
d = !0;
};
}, [r]), {
t: W(() => t ? ct(t) : (d) => ({
"ui.purchase": "Purchase",
"ui.pay_with_card": "Pay with Card",
"ui.pay_with_crypto": "Pay with USDC",
"ui.pay_with_usdc": "Pay with USDC",
"ui.card": "Card",
"ui.usdc_solana": "USDC (Solana)",
"ui.crypto": "Crypto",
"ui.processing": "Processing...",
"ui.loading": "Loading...",
"ui.connect_wallet": "Connect Wallet",
"ui.connecting": "Connecting..."
})[d] || d, [t]),
locale: r,
isLoading: o,
translations: t
};
}
function Pt(e, t = !0) {
const { translations: n } = ye();
if (!n) {
const a = ne(e);
return t && a.action ? `${a.message} ${a.action}` : a.message;
}
const o = n.errors[e];
if (!o) {
const a = ne(e);
return t && a.action ? `${a.message} ${a.action}` : a.message;
}
return t && o.action ? `${o.message} ${o.action}` : o.message;
}
function lt({
resource: e,
items: t,
successUrl: n,
cancelUrl: o,
metadata: a,
customerEmail: r,
couponCode: l,
label: d,
disabled: N = !1,
onAttempt: g,
onSuccess: _,
onError: w,
className: y = ""
}) {
const { status: b, error: D, transactionId: H, processPayment: f, processCartCheckout: h } = ot(), i = me(), { isCartMode: v, effectiveResource: c } = Fe(e, t), { t: u, translations: C } = ye(), I = d || u("ui.pay_with_card"), k = i.unstyled ? y : `${i.className} cedros-theme__stripe-button ${y}`.trim(), p = D && typeof D != "string" ? D?.code ?? null : null, O = D ? typeof D == "string" ? D : ((L) => {
if (!L || !C) return "";
const R = C.errors[L];
return R ? R.action ? `${R.message} ${R.action}` : R.message : "";
})(p) : null, P = x(async () => {
m().debug("[StripeButton] executePayment with couponCode:", l);
const L = v && t ? K(t) : void 0;
if (Me("stripe", c, L), g && g("stripe"), !v && !c) {
const Y = "Invalid payment configuration: missing resource or items";
m().error("[StripeButton]", Y), ae("stripe", Y, c, L), w && w(Y);
return;
}
let R;
de("stripe", c, L), v && t ? (m().debug("[StripeButton] Processing cart checkout with coupon:", l), R = await h(
t,
n,
o,
a,
r,
l
)) : c && (m().debug("[StripeButton] Processing single payment with coupon:", l), R = await f(
c,
n,
o,
a,
r,
l
)), R && R.success && R.transactionId ? (He("stripe", R.transactionId, c, L), _ && _(R.transactionId)) : R && !R.success && R.error && (ae("stripe", R.error, c, L), w && w(R.error));
}, [l, v, c, t, n, o, a, r, h, f, g, _, w]), U = W(() => v && t ? `stripe-cart-${t.map((L) => L.resource).join("-")}` : `stripe-${c || "unknown"}`, [v, t, c]), Q = W(
() => Le(U, P),
[U, P]
), Z = b === "loading", oe = N || Z;
return /* @__PURE__ */ E("div", { className: k, style: i.unstyled ? {} : i.style, children: [
/* @__PURE__ */ S(
"button",
{
onClick: Q,
disabled: oe,
className: i.unstyled ? y : "cedros-theme__button cedros-theme__stripe",
type: "button",
children: Z ? u("ui.processing") : I
}
),
O && /* @__PURE__ */ S("div", { className: i.unstyled ? "" : "cedros-theme__error", children: O }),
H && /* @__PURE__ */ S("div", { className: i.unstyled ? "" : "cedros-theme__success", children: u("ui.payment_successful") })
] });
}
function ut() {
const { x402Manager: e, walletManager: t } = fe(), { publicKey: n, signTransaction: o } = De(), [a, r] = F({
status: "idle",
error: null,
transactionId: null
}), [l, d] = F(null), [N, g] = F(null), _ = x(() => {
if (!n) {
const f = "Wallet not connected";
return r({ status: "error", error: f, transactionId: null }), { valid: !1, error: f };
}
if (!o) {
const f = "Wallet does not support signing";
return r({ status: "error", error: f, transactionId: null }), { valid: !1, error: f };
}
return { valid: !0 };
}, [n, o]), w = x(
async (f) => {
try {
r((i) => ({ ...i, status: "loading" }));
const h = await e.requestQuote({ resource: f });
if (!e.validateRequirement(h))
throw new Error("Invalid requirement received from server");
return d(h), r((i) => ({ ...i, status: "idle" })), h;
} catch (h) {
const i = se(h, "Failed to fetch requirement");
throw r({
status: "error",
error: i,
transactionId: null
}), h;
}
},
[e]
), y = x(
async (f, h, i, v, c = "regular") => {
if (!!f.extra?.feePayer) {
console.log("⚡ [useX402Payment] GASLESS FLOW - Backend pays fees"), console.log("🔨 [useX402Payment] Requesting backend to build gasless transaction");
const { transaction: C, blockhash: I } = await e.buildGaslessTransaction({
resourceId: h,
userWallet: n.toString(),
feePayer: f.extra.feePayer,
couponCode: i
});
console.log("📦 [useX402Payment] Deserializing transaction from backend");
const k = t.deserializeTransaction(C);
console.log("✍️ [useX402Payment] Requesting wallet to partially sign (transfer authority only)");
const p = await t.partiallySignTransaction({
transaction: k,
signTransaction: o,
blockhash: I
});
console.log("📤 [useX402Payment] Submitting partially-signed transaction to backend");
const A = await e.submitGaslessTransaction({
resource: h,
partialTx: p,
couponCode: i,
metadata: v,
resourceType: c,
requirement: f
});
return A.success && A.settlement && g(A.settlement), A;
} else {
const C = await t.buildTransaction({
requirement: f,
payerPublicKey: n
}), I = await t.signTransaction({
transaction: C,
signTransaction: o
}), k = t.buildPaymentPayload({
requirement: f,
signedTx: I,
payerPublicKey: n
}), p = await e.submitPayment({
resource: h,
payload: k,
couponCode: i,
metadata: v,
resourceType: c
});
return p.success && p.settlement && g(p.settlement), p;
}
},
[n, o, e, t]
), b = x(
async (f, h, i) => {
const v = _();
if (!v.valid)
return { success: !1, error: v.error };
r({
status: "loading",
error: null,
transactionId: null
});
try {
console.log("🔍 [useX402Payment] Fetching fresh quote for resource:", f);
const c = await e.requestQuote({ resource: f, couponCode: h });
console.log("✅ [useX402Payment] Got quote:", { payTo: c.payTo, amount: c.maxAmountRequired }), d(c), console.log("⚙️ [useX402Payment] Executing payment flow with fresh requirement");
const u = await y(c, f, h, i, "regular");
return u.success ? r({
status: "success",
error: null,
transactionId: u.transactionId || "payment-success"
}) : r({
status: "error",
error: u.error || "Payment failed",
transactionId: null
}), u;
} catch (c) {
const u = se(c, "Payment failed");
return r({
status: "error",
error: u,
transactionId: null
}), { success: !1, error: u };
}
},
[_, e, y]
), D = x(
async (f, h, i) => {
const v = _();
if (!v.valid)
return { success: !1, error: v.error };
r({
status: "loading",
error: null,
transactionId: null
});
try {
const c = Oe(f), u = await e.requestCartQuote({
items: c,
metadata: h,
couponCode: i
}), C = u.cartId, I = u.quote;
if (!e.validateRequirement(I))
throw new Error("Invalid cart quote received from server");
d(I);
const k = await y(I, C, i, h, "cart");
return k.success ? r({
status: "success",
error: null,
transactionId: k.transactionId || "cart-payment-success"
}) : r({
status: "error",
error: k.error || "Cart payment failed",
transactionId: null
}), k;
} catch (c) {
const u = se(c, "Cart payment failed");
return r({
status: "error",
error: u,
transactionId: null
}), { success: !1, error: u };
}
},
[_, e, y]
), H = x(() => {
r({
status: "idle",
error: null,
transactionId: null
}), d(null), g(null);
}, []);
return {
...a,
requirement: l,
settlement: N,
fetchQuote: w,
processPayment: b,
processCartPayment: D,
reset: H
};
}
function dt({
resource: e,
items: t,
label: n,
disabled: o = !1,
onAttempt: a,
onSuccess: r,
onError: l,
className: d = "",
testPageUrl: N,
hideMessages: g = !1,
metadata: _,
couponCode: w
}) {
const { connected: y, connecting: b, connect: D, disconnect: H, select: f, wallets: h, wallet: i, publicKey: v } = De(), { status: c, error: u, transactionId: C, processPayment: I, processCartPayment: k } = ut(), p = me(), { solanaError: A } = fe(), { isCartMode: O, effectiveResource: P } = Fe(e, t), { t: U, translations: Q } = ye(), Z = n || U("ui.pay_with_crypto"), oe = u && typeof u != "string" ? u?.code ?? null : null, L = A && typeof A != "string" ? A?.code ?? null : null, R = (s) => {
if (!s || !Q) return "";
const T = Q.errors[s];
return T ? T.action ? `${T.message} ${T.action}` : T.message : "";
}, Y = u ? typeof u == "string" ? u : R(oe) : null, he = A ? typeof A == "string" ? A : R(L) : null, _e = Ce(I), we = Ce(k);
B(() => {
_e.current = I, we.current = k;
}, [I, k]);
const Ue = W(
() => h.map((s) => `${s.adapter.name}-${s.readyState}`).join(","),
[h]
), J = W(
() => h.filter(
({ readyState: s }) => s === ke.Installed || s === ke.Loadable
),
// walletStateKey is derived from availableWallets, so we only need availableWallets as dependency
// eslint-disable-next-line react-hooks/exhaustive-deps
[Ue]
);
B(() => {
if (c === "success" && C) {
const s = O && t ? K(t) : void 0;
He("crypto", C, P, s), r && r(C);
}
}, [c, C, r, O, t, P]), B(() => {
if (c === "error" && u) {
const s = O && t ? K(t) : void 0;
ae("crypto", u, P, s), l && l(u);
}
}, [c, u, l, O, t, P]);
const be = typeof window < "u" && window.top !== window.self, [ve, G] = F(!1), [Ie, re] = F(!1), [V, q] = F(null), X = A;
B(() => {
let s = !1;
return s || (async () => {
if (Ie && i && !y && !b) {
m().debug("[CryptoButton] Wallet detected, attempting auto-connect:", i.adapter.name), re(!1), Se(i.adapter.name);
try {
await D(), s || m().debug("[CryptoButton] Auto-connect successful");
} catch (j) {
if (!s) {
m().error("[CryptoButton] Auto-connect failed:", j);
const ee = j instanceof Error ? j.message : "Failed to connect wallet";
ie(ee, i.adapter.name), q(null);
}
}
}
})(), () => {
s = !0;
};
}, [i, Ie, y, b, D]), B(() => {
if (m().debug("[CryptoButton] Payment useEffect triggered", {
connected: y,
hasPendingPayment: !!V,
hasPublicKey: !!v,
pendingPaymentType: V?.type
}), y && V && v && i) {
at(i.adapter.name, v.toString()), m().debug("[CryptoButton] All conditions met! Processing pending payment:", V);
const s = V;
q(null), G(!1);
const T = s.type === "cart" && s.items ? K(s.items) : void 0;
de("crypto", s.resource, T), s.type === "cart" && s.items ? (m().debug("[CryptoButton] Auto-processing cart payment"), we.current(s.items, s.metadata, s.couponCode)) : s.type === "single" && s.resource && (m().debug("[CryptoButton] Auto-processing single payment"), _e.current(s.resource, s.couponCode, s.metadata));
}
}, [y, V, v, i]);
const Te = x(async () => {
m().debug("[CryptoButton] executePaymentFlow called", {
connected: y,
wallet: i?.adapter.name,
couponCode: w,
isCartMode: O,
hasItems: !!t,
effectiveResource: P
});
const s = O && t ? K(t) : void 0;
if (Me("crypto", P, s), a && a("crypto"), X) {
m().error("[CryptoButton] Solana dependencies missing:", X), ae("crypto", X, P, s), l && l(X);
return;
}
if (be) {
const T = N || window.location.href;
window.open(T, "_blank", "noopener,noreferrer");
return;
}
if (y)
de("crypto", P, s), O && t ? (m().debug("[CryptoButton] Processing cart payment with coupon:", w), await k(t, _, w)) : P && (m().debug("[CryptoButton] Processing single payment with coupon:", w), await I(P, w, _));
else {
let T = !1;
if (O && t ? (m().debug("[CryptoButton] Setting pending cart payment with coupon:", w), q({ type: "cart", items: t, metadata: _, couponCode: w }), T = !0) : P && (m().debug("[CryptoButton] Setting pending single payment with coupon:", w), q({ type: "single", resource: P, metadata: _, couponCode: w }), T = !0), !T) {
m().error("[CryptoButton] No valid payment to process");
return;
}
try {
if (i)
m().debug("[CryptoButton] Wallet already selected, connecting:", i.adapter.name), Se(i.adapter.name), await D();
else {
if (m().debug(
"[CryptoButton] No wallet selected, showing selector. Available wallets:",
J.map((j) => j.adapter.name)
), J.length === 0) {
q(null);
const j = "No wallets available";
throw ie(j), new Error(j);
}
G(!0);
}
} catch (j) {
q(null);
const ee = j instanceof Error ? j.message : "Failed to connect wallet";
m().error("[CryptoButton] Connection error:", ee), ie(ee, i?.adapter.name);
}
}
}, [y, i, w, O, t, P, be, N, J, D, _, k, I, X, a, l]), Re = W(() => O && t ? `crypto-cart-${t.map((s) => s.resource).join("-")}` : `crypto-${P || "unknown"}`, [O, t, P]), Be = W(
() => Le(Re, Te, {
cooldownMs: 200,
deduplicationWindowMs: 0
// MUST be 0 for crypto - each payment needs fresh transaction
}),
[Re, Te]
), Ne = c === "loading", We = o || Ne || b || !!X, qe = Ne ? U("ui.processing") : Z, $e = x(async () => {
try {
re(!1), y && await H(), f(null), G(!0);
} catch (s) {
m().error("Failed to change wallet:", s);
}
}, [y, H, f]), ze = x((s) => {
m().debug("[CryptoButton] Wallet clicked:", s), G(!1), f(s), re(!0), m().debug("[CryptoButton] Wallet selected, useEffect will auto-connect");
}, [f]), Ye = x(async () => {
try {
await H(), q(null), typeof window < "u" && window.localStorage && window.localStorage.removeItem("walletName");
} catch (s) {
m().error("Failed to disconnect wallet:", s);
}
}, [H]);
return /* @__PURE__ */ E("div", { className: p.unstyled ? d : `${p.className} cedros-theme__crypto-button ${d || ""}`, style: p.unstyled ? {} : p.style, children: [
/* @__PURE__ */ S(
"button",
{
onClick: Be,
disabled: We,
className: p.unstyled ? d : "cedros-theme__button cedros-theme__crypto",
type: "button",
children: qe
}
),
ve && !g && /* @__PURE__ */ S(
"div",
{
className: "cedros-modal-overlay",
style: {
position: "fixed",
top: 0,
left: 0,
right: 0,
bottom: 0,
backgroundColor: p.tokens.modalOverlay,
display: "flex",
alignItems: "center",
justifyContent: "center",
zIndex: 9999,
padding: "1rem"
},
onClick: () => G(!1),
children: /* @__PURE__ */ E(
"div",
{
className: "cedros-modal-content",
style: {
backgroundColor: p.tokens.modalBackground,
borderRadius: "12px",
padding: "2rem",
maxWidth: "400px",
width: "100%",
boxShadow: "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)",
border: `1px solid ${p.tokens.modalBorder}`
},
onClick: (s) => s.stopPropagation(),
children: [
/* @__PURE__ */ E(
"div",
{
style: {
display: "flex",
justifyContent: "space-between",
alignItems: "center",
marginBottom: "1.5rem"
},
children: [
/* @__PURE__ */ S(
"h3",
{
style: {
margin: 0,
fontSize: "1.25rem",
fontWeight: 600,
color: p.tokens.surfaceText
},
children: U("wallet.select_wallet")
}
),
/* @__PURE__ */ S(
"button",
{
onClick: () => G(!1),
style: je(p.tokens.surfaceText),
"aria-label": "Close modal",
type: "button",
children: "×"
}
)
]
}
),
/* @__PURE__ */ S("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: J.map((s) => /* @__PURE__ */ E(
"button",
{
onClick: () => ze(s.adapter.name),
style: {
width: "100%",
padding: "1rem",
backgroundColor: p.tokens.surfaceBackground,
border: `1px solid ${p.tokens.surfaceBorder}`,
borderRadius: "0.5rem",
cursor: "pointer",
fontSize: "1rem",
textAlign: "left",
color: p.tokens.surfaceText,
display: "flex",
alignItems: "center",
gap: "1rem",
transition: "all 0.2s ease"
},
onMouseEnter: (T) => {
T.currentTarget.style.backgroundColor = p.tokens.modalBackground, T.currentTarget.style.borderColor = p.tokens.surfaceText, T.currentTarget.style.transform = "translateY(-2px)";
},
onMouseLeave: (T) => {
T.currentTarget.style.backgroundColor = p.tokens.surfaceBackground, T.currentTarget.style.borderColor = p.tokens.surfaceBorder, T.currentTarget.style.transform = "translateY(0)";
},
type: "button",
children: [
/* @__PURE__ */ S(Ge, { wallet: s, style: { width: "24px", height: "24px" } }),
/* @__PURE__ */ S("span", { style: { fontWeight: 500 }, children: s.adapter.name })
]
},
s.adapter.name
)) })
]
}
)
}
),
y && !g && !ve && /* @__PURE__ */ E("div", { style: {
display: "flex",
justifyContent: "space-between",
marginTop: "0.5rem",
fontSize: "0.75rem",
color: p.tokens.surfaceText,
opacity: 0.7
}, children: [
/* @__PURE__ */ S(
"button",
{
onClick: $e,
style: {
background: "none",
border: "none",
padding: 0,
color: "inherit",
textDecoration: "none",
cursor: "pointer",
fontSize: "inherit"
},
type: "button",
children: "Change Wallet"
}
),
/* @__PURE__ */ S(
"button",
{
onClick: Ye,
style: {
background: "none",
border: "none",
padding: 0,
color: "inherit",
textDecoration: "none",
cursor: "pointer",
fontSize: "inherit"
},
type: "button",
children: U("ui.disconnect")
}
)
] }),
!g && he && /* @__PURE__ */ S("div", { className: p.unstyled ? "" : "cedros-theme__error", children: he }),
!g && Y && /* @__PURE__ */ S("div", { className: p.unstyled ? "" : "cedros-theme__error", children: Y }),
!g && C && /* @__PURE__ */ S("div", { className: p.unstyled ? "" : "cedros-theme__success", children: U("ui.payment_successful") })
] });
}
const Dt = ({
isOpen: e,
onClose: t,
resource: n,
items: o,
cardLabel: a = "Card",
cryptoLabel: r = "USDC (Solana)",
showCard: l = !0,
showCrypto: d = !0,
onPaymentAttempt: N,
onPaymentSuccess: g,
onPaymentError: _,
onStripeSuccess: w,
onCryptoSuccess: y,
onStripeError: b,
onCryptoError: D,
customerEmail: H,
successUrl: f,
cancelUrl: h,
metadata: i,
couponCode: v,
testPageUrl: c,
hideMessages: u = !1
}) => {
const { tokens: C } = me();
return B(() => {
const I = (k) => {
k.key === "Escape" && e && t();
};
return window.addEventListener("keydown", I), () => window.removeEventListener("keydown", I);
}, [e, t]), B(() => {
if (e) {
const I = window.scrollY;
re