@cedros/pay-react
Version:
React frontend library for Cedros Pay - unified Stripe and Solana x402 payments
2 lines (1 loc) • 42.7 kB
JavaScript
"use strict";const u=require("react/jsx-runtime"),i=require("react"),l=require("./CedrosContext-DbndTsTA.js"),ke=require("@solana/wallet-adapter-react"),Te=require("@solana/wallet-adapter-base"),Ge=require("@solana/wallet-adapter-react-ui");require("@solana/wallet-adapter-wallets");function Ve(e){return!e||!e.coupon_codes?[]:e.coupon_codes.split(",").map(t=>t.trim()).filter(t=>t.length>0)}function Xe(e,t=", "){return e.join(t)}function Ke(e,t){return e<=0?0:(e-t)/e*100}function Qe(e,t){if(!t||t.length===0)return e;let n=e,o=0;for(const r of t)if(r.discountType==="percentage"){const a=1-r.discountValue/100;n=n*a}else r.discountType==="fixed"&&(o+=r.discountValue);return n=n-o,n<0&&(n=0),Math.ceil(n*100)/100}function Se(e){const t=Number(e);if(!Number.isFinite(t)||t<=0)return 1;const n=Math.floor(t);return n>0?n:1}function Ne(e){return e.map(t=>({resource:t.resource,quantity:Se(t.quantity),metadata:t.metadata}))}function Y(e){return e.reduce((t,n)=>t+Se(n.quantity),0)}function Ze(e){return!!(e&&e.length>0&&(e.length>1||e.length===1&&(e[0].quantity??1)>1))}const Je={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"},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_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_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"},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_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 ee(e){return Je[e]||{message:"An unexpected error occurred",action:"Please try again or contact support if this continues.",technicalHint:`Unknown error code: ${e}`}}const xe=new Map,se=new Map,ie=new Map,Ee=200,ue=2e3;function et(e){const t=ie.get(e);return t?Date.now()<t?!0:(ie.delete(e),!1):!1}function tt(e,t=Ee){const n=Date.now()+t;ie.set(e,n)}function nt(e,t=ue){const n=xe.get(e);if(!n)return!1;const r=Date.now()-n;return r<t?(l.getLogger().debug(`[Deduplication] Duplicate request blocked: ${e} (${r}ms ago)`),!0):!1}function rt(e){xe.set(e,Date.now())}function ot(e){return se.get(e)||null}function at(e,t){se.set(e,t);const n=()=>{se.delete(e),rt(e)};return t.then(n,n),t}async function st(e,t,n={}){const{windowMs:o=ue,throwOnDuplicate:r=!0}=n,a=ot(e);if(a)return l.getLogger().debug(`[Deduplication] Reusing in-flight request: ${e}`),a;if(nt(e,o)){if(r)throw new Error(`Duplicate request blocked: ${e}`);return l.getLogger().warn(`[Deduplication] Duplicate request blocked but not throwing: ${e}`),Promise.reject(new Error("Duplicate request"))}const f=t();return at(e,f)}function de(e,t,n={}){const{cooldownMs:o=Ee,deduplicationWindowMs:r=ue}=n;return async()=>{if(et(e)){l.getLogger().debug(`[Deduplication] Button in cooldown: ${e}`);return}tt(e,o);try{await st(e,async()=>{const a=t();a instanceof Promise&&await a},{windowMs:r,throwOnDuplicate:!1})}catch(a){if(a instanceof Error&&a.message.includes("Duplicate request"))return;throw a}}}function fe(e){return{background:"none",border:"none",fontSize:"1.5rem",cursor:"pointer",color:e,opacity:.6,padding:"0.25rem",lineHeight:1}}const H={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 B(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){B(H.PAYMENT_START,{timestamp:Date.now(),method:e,resource:t,itemCount:n})}function ce(e){B(H.WALLET_CONNECT,{timestamp:Date.now(),wallet:e})}function De(e,t){B(H.WALLET_CONNECTED,{timestamp:Date.now(),wallet:e,publicKey:t})}function J(e,t){B(H.WALLET_ERROR,{timestamp:Date.now(),wallet:t,error:e})}function te(e,t,n){B(H.PAYMENT_PROCESSING,{timestamp:Date.now(),method:e,resource:t,itemCount:n})}function pe(e,t,n,o){B(H.PAYMENT_SUCCESS,{timestamp:Date.now(),method:e,transactionId:t,resource:n,itemCount:o})}function G(e,t,n,o){B(H.PAYMENT_ERROR,{timestamp:Date.now(),method:e,error:t,resource:n,itemCount:o})}var le=(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))(le||{});class A extends Error{code;retryable;details;httpStatus;constructor(t,n,o=!1,r,a){super(n),this.name="PaymentError",this.code=t,this.retryable=o,this.details=r,this.httpStatus=a,Object.setPrototypeOf(this,A.prototype)}canRetry(){return this.retryable}is(t){return this.code===t}isInCategory(t){return t.includes(this.code)}getUserMessage(){const t=this.getErrorInfo();return t.action?`${t.message} ${t.action}`:t.message}getShortMessage(){return this.getErrorInfo().message}getAction(){return this.getErrorInfo().action}getErrorInfo(){return ee(this.code)}static fromErrorResponse(t,n){return new A(t.error.code,t.error.message,t.error.retryable,t.error.details,n)}static fromUnknown(t){return t instanceof A?t:t instanceof Error?new A("internal_error",t.message,!1):new A("internal_error",String(t),!1)}}const it={INSUFFICIENT_FUNDS:["insufficient_funds_sol","insufficient_funds_token"],TRANSACTION_PENDING:["transaction_not_confirmed","transaction_not_found"],VALIDATION:["missing_field","invalid_field","invalid_amount","invalid_wallet","invalid_resource","invalid_cart_item","empty_cart"],COUPON:["invalid_coupon","coupon_not_found","coupon_expired","coupon_usage_limit_reached","coupon_not_applicable","coupon_wrong_payment_method"],RETRYABLE:["transaction_not_confirmed","rpc_error","network_error","stripe_error"],NOT_FOUND:["resource_not_found","cart_not_found","refund_not_found","product_not_found","coupon_not_found","session_not_found"]};async function ct(e){const t=e.status;try{const n=await e.json();if(n.error&&typeof n.error.code=="string"){const o=n;return A.fromErrorResponse(o,t)}return new A(le.INTERNAL_ERROR,n.error||n.message||"An unknown error occurred",!1,void 0,t)}catch{return new A(le.INTERNAL_ERROR,e.statusText||"Request failed",!1,void 0,t)}}function lt(e){return e instanceof A&&e.canRetry()}function ut(e){return e instanceof A?e.getUserMessage():e instanceof Error?e.message:String(e)}function Le(){const{stripeManager:e}=l.useCedrosContext(),[t,n]=i.useState({status:"idle",error:null,transactionId:null}),o=i.useCallback(async(f,p,k,y,v,b)=>{n({status:"loading",error:null,transactionId:null});const _={resource:f,successUrl:p,cancelUrl:k,metadata:y,customerEmail:v,couponCode:b},P=await e.processPayment(_);return n({status:P.success?"success":"error",error:P.success?null:P.error||"Payment failed",transactionId:P.success&&P.transactionId||null}),P},[e]),r=i.useCallback(async(f,p,k,y,v,b)=>{n({status:"loading",error:null,transactionId:null});const _=Ne(f),P=await e.processCartCheckout({items:_,successUrl:p,cancelUrl:k,metadata:y,customerEmail:v,couponCode:b});return n({status:P.success?"success":"error",error:P.success?null:P.error||"Cart checkout failed",transactionId:P.success&&P.transactionId||null}),P},[e]),a=i.useCallback(()=>{n({status:"idle",error:null,transactionId:null})},[]);return{...t,processPayment:o,processCartCheckout:r,reset:a}}function ge(e,t){const n=Ze(t),o=e||(t?.length===1?t[0].resource:"");return{isCartMode:n,effectiveResource:o}}const dt=(e,t,n)=>{const o=e[t];return o?typeof o=="function"?o():Promise.resolve(o):new Promise((r,a)=>{(typeof queueMicrotask=="function"?queueMicrotask:setTimeout)(a.bind(null,new Error("Unknown variable dynamic import: "+t+(t.split("/").length!==n?". Note that variables only represent file names one level deep.":""))))})},ae=new Map;let Z=null;async function Ie(e){if(ae.has(e))return ae.get(e);try{const t=await dt(Object.assign({"./translations/ar.json":()=>Promise.resolve().then(()=>require("./ar-LVoQZTFI.js")),"./translations/bn.json":()=>Promise.resolve().then(()=>require("./bn-BR5Cv1T4.js")),"./translations/de.json":()=>Promise.resolve().then(()=>require("./de-pQxy-oD1.js")),"./translations/en.json":()=>Promise.resolve().then(()=>require("./en-Cz4OpvN-.js")),"./translations/es.json":()=>Promise.resolve().then(()=>require("./es-D24cg8dD.js")),"./translations/fil.json":()=>Promise.resolve().then(()=>require("./fil-BOBft9G-.js")),"./translations/fr.json":()=>Promise.resolve().then(()=>require("./fr-Ct9ub8Fa.js")),"./translations/he.json":()=>Promise.resolve().then(()=>require("./he-DtQqRKRq.js")),"./translations/id.json":()=>Promise.resolve().then(()=>require("./id-CiM2mL7C.js")),"./translations/in.json":()=>Promise.resolve().then(()=>require("./in-Bzcjmxcc.js")),"./translations/it.json":()=>Promise.resolve().then(()=>require("./it-Blb_pIJl.js")),"./translations/jp.json":()=>Promise.resolve().then(()=>require("./jp-9NHyIuwY.js")),"./translations/kr.json":()=>Promise.resolve().then(()=>require("./kr-DvzJ-0yX.js")),"./translations/ms.json":()=>Promise.resolve().then(()=>require("./ms-BOAu5pUB.js")),"./translations/nl.json":()=>Promise.resolve().then(()=>require("./nl-WHh_DfO8.js")),"./translations/pa.json":()=>Promise.resolve().then(()=>require("./pa-B7kIhZCF.js")),"./translations/pl.json":()=>Promise.resolve().then(()=>require("./pl-H0hBKdvF.js")),"./translations/pt.json":()=>Promise.resolve().then(()=>require("./pt-DwGrViQ3.js")),"./translations/ru.json":()=>Promise.resolve().then(()=>require("./ru-CB2m0UDT.js")),"./translations/ta.json":()=>Promise.resolve().then(()=>require("./ta-CAS197uN.js")),"./translations/th.json":()=>Promise.resolve().then(()=>require("./th-Cpz2cFcg.js")),"./translations/tr.json":()=>Promise.resolve().then(()=>require("./tr-hQrEFk86.js")),"./translations/uk.json":()=>Promise.resolve().then(()=>require("./uk-DrK2Sv8C.js")),"./translations/ur.json":()=>Promise.resolve().then(()=>require("./ur-D5-7mN9a.js")),"./translations/vn.json":()=>Promise.resolve().then(()=>require("./vn-B_iut9YL.js")),"./translations/zh.json":()=>Promise.resolve().then(()=>require("./zh-PR82dCHr.js"))}),`./translations/${e}.json`,3),n=t.default||t;return ae.set(e,n),n}catch{return null}}async function ft(){if(Z)return Z;const e=Object.assign({"./translations/ar.json":()=>Promise.resolve().then(()=>require("./ar-LVoQZTFI.js")),"./translations/bn.json":()=>Promise.resolve().then(()=>require("./bn-BR5Cv1T4.js")),"./translations/de.json":()=>Promise.resolve().then(()=>require("./de-pQxy-oD1.js")),"./translations/en.json":()=>Promise.resolve().then(()=>require("./en-Cz4OpvN-.js")),"./translations/es.json":()=>Promise.resolve().then(()=>require("./es-D24cg8dD.js")),"./translations/fil.json":()=>Promise.resolve().then(()=>require("./fil-BOBft9G-.js")),"./translations/fr.json":()=>Promise.resolve().then(()=>require("./fr-Ct9ub8Fa.js")),"./translations/he.json":()=>Promise.resolve().then(()=>require("./he-DtQqRKRq.js")),"./translations/id.json":()=>Promise.resolve().then(()=>require("./id-CiM2mL7C.js")),"./translations/in.json":()=>Promise.resolve().then(()=>require("./in-Bzcjmxcc.js")),"./translations/it.json":()=>Promise.resolve().then(()=>require("./it-Blb_pIJl.js")),"./translations/jp.json":()=>Promise.resolve().then(()=>require("./jp-9NHyIuwY.js")),"./translations/kr.json":()=>Promise.resolve().then(()=>require("./kr-DvzJ-0yX.js")),"./translations/ms.json":()=>Promise.resolve().then(()=>require("./ms-BOAu5pUB.js")),"./translations/nl.json":()=>Promise.resolve().then(()=>require("./nl-WHh_DfO8.js")),"./translations/pa.json":()=>Promise.resolve().then(()=>require("./pa-B7kIhZCF.js")),"./translations/pl.json":()=>Promise.resolve().then(()=>require("./pl-H0hBKdvF.js")),"./translations/pt.json":()=>Promise.resolve().then(()=>require("./pt-DwGrViQ3.js")),"./translations/ru.json":()=>Promise.resolve().then(()=>require("./ru-CB2m0UDT.js")),"./translations/ta.json":()=>Promise.resolve().then(()=>require("./ta-CAS197uN.js")),"./translations/th.json":()=>Promise.resolve().then(()=>require("./th-Cpz2cFcg.js")),"./translations/tr.json":()=>Promise.resolve().then(()=>require("./tr-hQrEFk86.js")),"./translations/uk.json":()=>Promise.resolve().then(()=>require("./uk-DrK2Sv8C.js")),"./translations/ur.json":()=>Promise.resolve().then(()=>require("./ur-D5-7mN9a.js")),"./translations/vn.json":()=>Promise.resolve().then(()=>require("./vn-B_iut9YL.js")),"./translations/zh.json":()=>Promise.resolve().then(()=>require("./zh-PR82dCHr.js"))}),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 Z=t.length>0?t:["en"],Z}function Oe(){return typeof navigator>"u"?"en":(navigator.language||navigator.userLanguage||"en").split("-")[0].toLowerCase()}async function je(e){let t=await Ie(e);if(t||(t=await Ie("en"),t))return t;throw new Error("Critical: No translation files found, not even en.json")}function Ae(e){return(t,n)=>{const o=t.split(".");let r=e;for(const a of o)if(r&&typeof r=="object"&&a in r)r=r[a];else return t;return typeof r!="string"?t:n?Object.entries(n).reduce((a,[f,p])=>a.replace(new RegExp(`\\{${f}\\}`,"g"),p),r):r}}function mt(e,t,n=!0){const o=t.errors[e];if(!o){const r=ee(e);return n&&r.action?`${r.message} ${r.action}`:r.message}return n&&o.action?`${o.message} ${o.action}`:o.message}function ne(e){const[t,n]=i.useState(null),[o,r]=i.useState(!0),a=i.useMemo(()=>e||Oe(),[e]);return i.useEffect(()=>{let p=!1;return(async()=>{r(!0);try{const y=await je(a);p||(n(y),r(!1))}catch(y){console.error("[CedrosPay] Failed to load translations:",y),p||r(!1)}})(),()=>{p=!0}},[a]),{t:i.useMemo(()=>t?Ae(t):p=>({"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..."})[p]||p,[t]),locale:a,isLoading:o,translations:t}}function pt(e,t=!0){const{translations:n}=ne();if(!n){const r=ee(e);return t&&r.action?`${r.message} ${r.action}`:r.message}const o=n.errors[e];if(!o){const r=ee(e);return t&&r.action?`${r.message} ${r.action}`:r.message}return t&&o.action?`${o.message} ${o.action}`:o.message}function qe({resource:e,items:t,successUrl:n,cancelUrl:o,metadata:r,customerEmail:a,couponCode:f,label:p,disabled:k=!1,onAttempt:y,onSuccess:v,onError:b,className:_=""}){const{status:P,error:E,transactionId:q,processPayment:h,processCartCheckout:w}=Le(),c=l.useCedrosTheme(),{isCartMode:C,effectiveResource:d}=ge(e,t),{t:m,translations:S}=ne(),R=p||m("ui.pay_with_card"),N=c.unstyled?_:`${c.className} cedros-theme__stripe-button ${_}`.trim(),g=E&&typeof E!="string"?E?.code??null:null,D=E?typeof E=="string"?E:(O=>{if(!O||!S)return"";const I=S.errors[O];return I?I.action?`${I.message} ${I.action}`:I.message:""})(g):null,x=i.useCallback(async()=>{l.getLogger().debug("[StripeButton] executePayment with couponCode:",f);const O=C&&t?Y(t):void 0;if(me("stripe",d,O),y&&y("stripe"),!C&&!d){const W="Invalid payment configuration: missing resource or items";l.getLogger().error("[StripeButton]",W),G("stripe",W,d,O),b&&b(W);return}let I;te("stripe",d,O),C&&t?(l.getLogger().debug("[StripeButton] Processing cart checkout with coupon:",f),I=await w(t,n,o,r,a,f)):d&&(l.getLogger().debug("[StripeButton] Processing single payment with coupon:",f),I=await h(d,n,o,r,a,f)),I&&I.success&&I.transactionId?(pe("stripe",I.transactionId,d,O),v&&v(I.transactionId)):I&&!I.success&&I.error&&(G("stripe",I.error,d,O),b&&b(I.error))},[f,C,d,t,n,o,r,a,w,h,y,v,b]),M=i.useMemo(()=>C&&t?`stripe-cart-${t.map(O=>O.resource).join("-")}`:`stripe-${d||"unknown"}`,[C,t,d]),V=i.useMemo(()=>de(M,x),[M,x]),X=P==="loading",re=k||X;return u.jsxs("div",{className:N,style:c.unstyled?{}:c.style,children:[u.jsx("button",{onClick:V,disabled:re,className:c.unstyled?_:"cedros-theme__button cedros-theme__stripe",type:"button",children:X?m("ui.processing"):R}),D&&u.jsx("div",{className:c.unstyled?"":"cedros-theme__error",children:D}),q&&u.jsx("div",{className:c.unstyled?"":"cedros-theme__success",children:m("ui.payment_successful")})]})}function Me(){const{x402Manager:e,walletManager:t}=l.useCedrosContext(),{publicKey:n,signTransaction:o}=ke.useWallet(),[r,a]=i.useState({status:"idle",error:null,transactionId:null}),[f,p]=i.useState(null),[k,y]=i.useState(null),v=i.useCallback(()=>{if(!n){const h="Wallet not connected";return a({status:"error",error:h,transactionId:null}),{valid:!1,error:h}}if(!o){const h="Wallet does not support signing";return a({status:"error",error:h,transactionId:null}),{valid:!1,error:h}}return{valid:!0}},[n,o]),b=i.useCallback(async h=>{try{a(c=>({...c,status:"loading"}));const w=await e.requestQuote({resource:h});if(!e.validateRequirement(w))throw new Error("Invalid requirement received from server");return p(w),a(c=>({...c,status:"idle"})),w}catch(w){const c=l.formatError(w,"Failed to fetch requirement");throw a({status:"error",error:c,transactionId:null}),w}},[e]),_=i.useCallback(async(h,w,c,C,d="regular")=>{if(!!h.extra?.feePayer){console.log("⚡ [useX402Payment] GASLESS FLOW - Backend pays fees"),console.log("🔨 [useX402Payment] Requesting backend to build gasless transaction");const{transaction:S,blockhash:R}=await e.buildGaslessTransaction({resourceId:w,userWallet:n.toString(),feePayer:h.extra.feePayer,couponCode:c});console.log("📦 [useX402Payment] Deserializing transaction from backend");const N=t.deserializeTransaction(S);console.log("✍️ [useX402Payment] Requesting wallet to partially sign (transfer authority only)");const g=await t.partiallySignTransaction({transaction:N,signTransaction:o,blockhash:R});console.log("📤 [useX402Payment] Submitting partially-signed transaction to backend");const L=await e.submitGaslessTransaction({resource:w,partialTx:g,couponCode:c,metadata:C,resourceType:d,requirement:h});return L.success&&L.settlement&&y(L.settlement),L}else{const S=await t.buildTransaction({requirement:h,payerPublicKey:n}),R=await t.signTransaction({transaction:S,signTransaction:o}),N=t.buildPaymentPayload({requirement:h,signedTx:R,payerPublicKey:n}),g=await e.submitPayment({resource:w,payload:N,couponCode:c,metadata:C,resourceType:d});return g.success&&g.settlement&&y(g.settlement),g}},[n,o,e,t]),P=i.useCallback(async(h,w,c)=>{const C=v();if(!C.valid)return{success:!1,error:C.error};a({status:"loading",error:null,transactionId:null});try{console.log("🔍 [useX402Payment] Fetching fresh quote for resource:",h);const d=await e.requestQuote({resource:h,couponCode:w});console.log("✅ [useX402Payment] Got quote:",{payTo:d.payTo,amount:d.maxAmountRequired}),p(d),console.log("⚙️ [useX402Payment] Executing payment flow with fresh requirement");const m=await _(d,h,w,c,"regular");return m.success?a({status:"success",error:null,transactionId:m.transactionId||"payment-success"}):a({status:"error",error:m.error||"Payment failed",transactionId:null}),m}catch(d){const m=l.formatError(d,"Payment failed");return a({status:"error",error:m,transactionId:null}),{success:!1,error:m}}},[v,e,_]),E=i.useCallback(async(h,w,c)=>{const C=v();if(!C.valid)return{success:!1,error:C.error};a({status:"loading",error:null,transactionId:null});try{const d=Ne(h),m=await e.requestCartQuote({items:d,metadata:w,couponCode:c}),S=m.cartId,R=m.quote;if(!e.validateRequirement(R))throw new Error("Invalid cart quote received from server");p(R);const N=await _(R,S,c,w,"cart");return N.success?a({status:"success",error:null,transactionId:N.transactionId||"cart-payment-success"}):a({status:"error",error:N.error||"Cart payment failed",transactionId:null}),N}catch(d){const m=l.formatError(d,"Cart payment failed");return a({status:"error",error:m,transactionId:null}),{success:!1,error:m}}},[v,e,_]),q=i.useCallback(()=>{a({status:"idle",error:null,transactionId:null}),p(null),y(null)},[]);return{...r,requirement:f,settlement:k,fetchQuote:b,processPayment:P,processCartPayment:E,reset:q}}function He({resource:e,items:t,label:n,disabled:o=!1,onAttempt:r,onSuccess:a,onError:f,className:p="",testPageUrl:k,hideMessages:y=!1,metadata:v,couponCode:b}){const{connected:_,connecting:P,connect:E,disconnect:q,select:h,wallets:w,wallet:c,publicKey:C}=ke.useWallet(),{status:d,error:m,transactionId:S,processPayment:R,processCartPayment:N}=Me(),g=l.useCedrosTheme(),{solanaError:L}=l.useCedrosContext(),{isCartMode:D,effectiveResource:x}=ge(e,t),{t:M,translations:V}=ne(),X=n||M("ui.pay_with_crypto"),re=m&&typeof m!="string"?m?.code??null:null,O=L&&typeof L!="string"?L?.code??null:null,I=s=>{if(!s||!V)return"";const T=V.errors[s];return T?T.action?`${T.message} ${T.action}`:T.message:""},W=m?typeof m=="string"?m:I(re):null,he=L?typeof L=="string"?L:I(O):null,ye=i.useRef(R),_e=i.useRef(N);i.useEffect(()=>{ye.current=R,_e.current=N},[R,N]);const Ue=i.useMemo(()=>w.map(s=>`${s.adapter.name}-${s.readyState}`).join(","),[w]),K=i.useMemo(()=>w.filter(({readyState:s})=>s===Te.WalletReadyState.Installed||s===Te.WalletReadyState.Loadable),[Ue]);i.useEffect(()=>{if(d==="success"&&S){const s=D&&t?Y(t):void 0;pe("crypto",S,x,s),a&&a(S)}},[d,S,a,D,t,x]),i.useEffect(()=>{if(d==="error"&&m){const s=D&&t?Y(t):void 0;G("crypto",m,x,s),f&&f(m)}},[d,m,f,D,t,x]);const we=typeof window<"u"&&window.top!==window.self,[ve,F]=i.useState(!1),[be,oe]=i.useState(!1),[$,U]=i.useState(null),z=L;i.useEffect(()=>{let s=!1;return s||(async()=>{if(be&&c&&!_&&!P){l.getLogger().debug("[CryptoButton] Wallet detected, attempting auto-connect:",c.adapter.name),oe(!1),ce(c.adapter.name);try{await E(),s||l.getLogger().debug("[CryptoButton] Auto-connect successful")}catch(j){if(!s){l.getLogger().error("[CryptoButton] Auto-connect failed:",j);const Q=j instanceof Error?j.message:"Failed to connect wallet";J(Q,c.adapter.name),U(null)}}}})(),()=>{s=!0}},[c,be,_,P,E]),i.useEffect(()=>{if(l.getLogger().debug("[CryptoButton] Payment useEffect triggered",{connected:_,hasPendingPayment:!!$,hasPublicKey:!!C,pendingPaymentType:$?.type}),_&&$&&C&&c){De(c.adapter.name,C.toString()),l.getLogger().debug("[CryptoButton] All conditions met! Processing pending payment:",$);const s=$;U(null),F(!1);const T=s.type==="cart"&&s.items?Y(s.items):void 0;te("crypto",s.resource,T),s.type==="cart"&&s.items?(l.getLogger().debug("[CryptoButton] Auto-processing cart payment"),_e.current(s.items,s.metadata,s.couponCode)):s.type==="single"&&s.resource&&(l.getLogger().debug("[CryptoButton] Auto-processing single payment"),ye.current(s.resource,s.couponCode,s.metadata))}},[_,$,C,c]);const Pe=i.useCallback(async()=>{l.getLogger().debug("[CryptoButton] executePaymentFlow called",{connected:_,wallet:c?.adapter.name,couponCode:b,isCartMode:D,hasItems:!!t,effectiveResource:x});const s=D&&t?Y(t):void 0;if(me("crypto",x,s),r&&r("crypto"),z){l.getLogger().error("[CryptoButton] Solana dependencies missing:",z),G("crypto",z,x,s),f&&f(z);return}if(we){const T=k||window.location.href;window.open(T,"_blank","noopener,noreferrer");return}if(_)te("crypto",x,s),D&&t?(l.getLogger().debug("[CryptoButton] Processing cart payment with coupon:",b),await N(t,v,b)):x&&(l.getLogger().debug("[CryptoButton] Processing single payment with coupon:",b),await R(x,b,v));else{let T=!1;if(D&&t?(l.getLogger().debug("[CryptoButton] Setting pending cart payment with coupon:",b),U({type:"cart",items:t,metadata:v,couponCode:b}),T=!0):x&&(l.getLogger().debug("[CryptoButton] Setting pending single payment with coupon:",b),U({type:"single",resource:x,metadata:v,couponCode:b}),T=!0),!T){l.getLogger().error("[CryptoButton] No valid payment to process");return}try{if(c)l.getLogger().debug("[CryptoButton] Wallet already selected, connecting:",c.adapter.name),ce(c.adapter.name),await E();else{if(l.getLogger().debug("[CryptoButton] No wallet selected, showing selector. Available wallets:",K.map(j=>j.adapter.name)),K.length===0){U(null);const j="No wallets available";throw J(j),new Error(j)}F(!0)}}catch(j){U(null);const Q=j instanceof Error?j.message:"Failed to connect wallet";l.getLogger().error("[CryptoButton] Connection error:",Q),J(Q,c?.adapter.name)}}},[_,c,b,D,t,x,we,k,K,E,v,N,R,z,r,f]),Ce=i.useMemo(()=>D&&t?`crypto-cart-${t.map(s=>s.resource).join("-")}`:`crypto-${x||"unknown"}`,[D,t,x]),Be=i.useMemo(()=>de(Ce,Pe,{cooldownMs:200,deduplicationWindowMs:0}),[Ce,Pe]),Re=d==="loading",We=o||Re||P||!!z,Fe=Re?M("ui.processing"):X,$e=i.useCallback(async()=>{try{oe(!1),_&&await q(),h(null),F(!0)}catch(s){l.getLogger().error("Failed to change wallet:",s)}},[_,q,h]),ze=i.useCallback(s=>{l.getLogger().debug("[CryptoButton] Wallet clicked:",s),F(!1),h(s),oe(!0),l.getLogger().debug("[CryptoButton] Wallet selected, useEffect will auto-connect")},[h]),Ye=i.useCallback(async()=>{try{await q(),U(null),typeof window<"u"&&window.localStorage&&window.localStorage.removeItem("walletName")}catch(s){l.getLogger().error("Failed to disconnect wallet:",s)}},[q]);return u.jsxs("div",{className:g.unstyled?p:`${g.className} cedros-theme__crypto-button ${p||""}`,style:g.unstyled?{}:g.style,children:[u.jsx("button",{onClick:Be,disabled:We,className:g.unstyled?p:"cedros-theme__button cedros-theme__crypto",type:"button",children:Fe}),ve&&!y&&u.jsx("div",{className:"cedros-modal-overlay",style:{position:"fixed",top:0,left:0,right:0,bottom:0,backgroundColor:g.tokens.modalOverlay,display:"flex",alignItems:"center",justifyContent:"center",zIndex:9999,padding:"1rem"},onClick:()=>F(!1),children:u.jsxs("div",{className:"cedros-modal-content",style:{backgroundColor:g.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 ${g.tokens.modalBorder}`},onClick:s=>s.stopPropagation(),children:[u.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"1.5rem"},children:[u.jsx("h3",{style:{margin:0,fontSize:"1.25rem",fontWeight:600,color:g.tokens.surfaceText},children:M("wallet.select_wallet")}),u.jsx("button",{onClick:()=>F(!1),style:fe(g.tokens.surfaceText),"aria-label":"Close modal",type:"button",children:"×"})]}),u.jsx("div",{style:{display:"flex",flexDirection:"column",gap:"0.75rem"},children:K.map(s=>u.jsxs("button",{onClick:()=>ze(s.adapter.name),style:{width:"100%",padding:"1rem",backgroundColor:g.tokens.surfaceBackground,border:`1px solid ${g.tokens.surfaceBorder}`,borderRadius:"0.5rem",cursor:"pointer",fontSize:"1rem",textAlign:"left",color:g.tokens.surfaceText,display:"flex",alignItems:"center",gap:"1rem",transition:"all 0.2s ease"},onMouseEnter:T=>{T.currentTarget.style.backgroundColor=g.tokens.modalBackground,T.currentTarget.style.borderColor=g.tokens.surfaceText,T.currentTarget.style.transform="translateY(-2px)"},onMouseLeave:T=>{T.currentTarget.style.backgroundColor=g.tokens.surfaceBackground,T.currentTarget.style.borderColor=g.tokens.surfaceBorder,T.currentTarget.style.transform="translateY(0)"},type:"button",children:[u.jsx(Ge.WalletIcon,{wallet:s,style:{width:"24px",height:"24px"}}),u.jsx("span",{style:{fontWeight:500},children:s.adapter.name})]},s.adapter.name))})]})}),_&&!y&&!ve&&u.jsxs("div",{style:{display:"flex",justifyContent:"space-between",marginTop:"0.5rem",fontSize:"0.75rem",color:g.tokens.surfaceText,opacity:.7},children:[u.jsx("button",{onClick:$e,style:{background:"none",border:"none",padding:0,color:"inherit",textDecoration:"none",cursor:"pointer",fontSize:"inherit"},type:"button",children:"Change Wallet"}),u.jsx("button",{onClick:Ye,style:{background:"none",border:"none",padding:0,color:"inherit",textDecoration:"none",cursor:"pointer",fontSize:"inherit"},type:"button",children:M("ui.disconnect")})]}),!y&&he&&u.jsx("div",{className:g.unstyled?"":"cedros-theme__error",children:he}),!y&&W&&u.jsx("div",{className:g.unstyled?"":"cedros-theme__error",children:W}),!y&&S&&u.jsx("div",{className:g.unstyled?"":"cedros-theme__success",children:M("ui.payment_successful")})]})}const gt=({isOpen:e,onClose:t,resource:n,items:o,cardLabel:r="Card",cryptoLabel:a="USDC (Solana)",showCard:f=!0,showCrypto:p=!0,onPaymentAttempt:k,onPaymentSuccess:y,onPaymentError:v,onStripeSuccess:b,onCryptoSuccess:_,onStripeError:P,onCryptoError:E,customerEmail:q,successUrl:h,cancelUrl:w,metadata:c,couponCode:C,testPageUrl:d,hideMessages:m=!1})=>{const{tokens:S}=l.useCedrosTheme();return i.useEffect(()=>{const R=N=>{N.key==="Escape"&&e&&t()};return window.addEventListener("keydown",R),()=>window.removeEventListener("keydown",R)},[e,t]),i.useEffect(()=>{if(e){const R=window.scrollY;return document.body.style.position="fixed",document.body.style.top=`-${R}px`,document.body.style.width="100%",document.body.style.overflowY="scroll",()=>{const N=document.body.style.top?Math.abs(parseInt(document.body.style.top.replace("px",""),10)):0;document.body.style.position="",document.body.style.top="",document.body.style.width="",document.body.style.overflowY="",window.scrollTo(0,N)}}},[e]),e?u.jsx("div",{className:"cedros-modal-overlay",style:{position:"fixed",top:0,left:0,right:0,bottom:0,backgroundColor:S.modalOverlay,display:"flex",alignItems:"center",justifyContent:"center",zIndex:9999,padding:"1rem"},onClick:t,children:u.jsxs("div",{className:"cedros-modal-content",style:{backgroundColor:S.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 ${S.modalBorder}`},onClick:R=>R.stopPropagation(),children:[u.jsxs("div",{style:{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"1.5rem"},children:[u.jsx("h3",{style:{margin:0,fontSize:"1.25rem",fontWeight:600,color:S.surfaceText},children:"Choose Payment Method"}),u.jsx("button",{onClick:t,style:fe(S.surfaceText),"aria-label":"Close modal",children:"×"})]}),u.jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"1rem"},children:[f&&u.jsx(qe,{resource:n,items:o,label:r,onAttempt:k,onSuccess:b||y,onError:P||v,customerEmail:q,successUrl:h,cancelUrl:w,metadata:c,couponCode:C}),p&&u.jsx(He,{resource:n,items:o,label:a,onAttempt:k,onSuccess:_||y,onError:E||v,testPageUrl:d,hideMessages:m,metadata:c,couponCode:C})]})]})}):null};function ht({product:e,paymentMethod:t,showOriginalPrice:n=!1,className:o="",style:r={}}){const a=t==="stripe",f=a?e.fiatAmount:e.cryptoAmount,p=a?e.effectiveFiatAmount:e.effectiveCryptoAmount,k=a?e.fiatCurrency.toUpperCase():e.cryptoToken,y=a?e.hasStripeCoupon:e.hasCryptoCoupon,v=a?e.stripeDiscountPercent:e.cryptoDiscountPercent;return u.jsxs("div",{className:o,style:r,children:[n&&y&&u.jsxs("span",{style:{textDecoration:"line-through",opacity:.6,marginRight:"0.5rem",fontSize:"0.875em"},children:[f.toFixed(2)," ",k]}),u.jsxs("span",{style:{fontWeight:600},children:[p.toFixed(2)," ",k]}),y&&v>0&&u.jsxs("span",{style:{marginLeft:"0.5rem",padding:"0.125rem 0.375rem",backgroundColor:"#10b981",color:"white",borderRadius:"0.25rem",fontSize:"0.75em",fontWeight:600},children:[v,"% OFF"]})]})}function yt({product:e,paymentMethod:t,className:n="",style:o={}}){const r=t==="stripe",a=r?e.hasStripeCoupon:e.hasCryptoCoupon,f=r?e.stripeDiscountPercent:e.cryptoDiscountPercent,p=r?e.stripeCouponCode:e.cryptoCouponCode;if(!a||f===0)return null;const k=r?`${f}% off with card!`:`${f}% off with crypto!`;return u.jsxs("div",{className:n,style:{display:"inline-flex",alignItems:"center",padding:"0.5rem 0.75rem",backgroundColor:r?"#6366f1":"#10b981",color:"white",borderRadius:"0.375rem",fontSize:"0.875rem",fontWeight:600,...o},children:[k,p&&u.jsxs("span",{style:{marginLeft:"0.5rem",opacity:.8,fontSize:"0.75em",fontWeight:400},children:["(",p,")"]})]})}exports.CEDROS_EVENTS=H;exports.CryptoButton=He;exports.ERROR_CATEGORIES=it;exports.PaymentMethodBadge=yt;exports.PaymentModal=gt;exports.ProductPrice=ht;exports.StripeButton=qe;exports.calculateDiscountPercentage=Ke;exports.createDedupedClickHandler=de;exports.createTranslator=Ae;exports.detectLocale=Oe;exports.emitPaymentError=G;exports.emitPaymentProcessing=te;exports.emitPaymentStart=me;exports.emitPaymentSuccess=pe;exports.emitWalletConnect=ce;exports.emitWalletConnected=De;exports.emitWalletError=J;exports.formatCouponCodes=Xe;exports.getAvailableLocales=ft;exports.getCartItemCount=Y;exports.getLocalizedError=mt;exports.getModalCloseButtonStyles=fe;exports.getUserErrorMessage=ut;exports.isRetryableError=lt;exports.loadLocale=je;exports.parseCouponCodes=Ve;exports.parseErrorResponse=ct;exports.stackCheckoutCoupons=Qe;exports.useLocalizedError=pt;exports.usePaymentMode=ge;exports.useStripeCheckout=Le;exports.useTranslation=ne;exports.useX402Payment=Me;