@stacknet/keyutils 0.1.18 → 0.1.20

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.
@@ -1,2 +1,2 @@
1
- 'use strict';var yt=require('react'),jsxRuntime=require('react/jsx-runtime'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),lucideReact=require('lucide-react');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var yt__default=/*#__PURE__*/_interopDefault(yt);var Ce=yt.createContext(null);function C(){let e=yt.useContext(Ce);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function oe({config:e,callbacks:t={},children:r}){typeof e.apiBaseUrl!="string"&&console.error("[KeyUtils] apiBaseUrl must be a string");let s=yt.useMemo(()=>({config:e,callbacks:t}),[e,t]);return jsxRuntime.jsx(Ce.Provider,{value:s,children:r})}function u(...e){return tailwindMerge.twMerge(clsx.clsx(e))}function I(e){return e==null?"0":e>=1e9?`${(e/1e9).toFixed(1)}B`:e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:e.toLocaleString()}function Se(e,t){return t<=0?0:Math.min(100,Math.round(e/t*100))}function Ke(e){return e>=70?"bg-green-500":e>=30?"bg-yellow-500":"bg-red-500"}function z(e){let t=typeof e=="string"&&/^\d+$/.test(e)?Number(e):e,r=new Date(t);return isNaN(r.getTime())?String(e):r.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}function Re(){if(typeof navigator>"u")return "mac";let e=navigator.userAgent.toLowerCase();return /iphone|ipad|ipod/.test(e)?"ios":/android/.test(e)?"android":/win/.test(e)?"windows":/linux/.test(e)?"linux":"mac"}function Ue(){let{config:e}=C(),[t,r]=yt.useState(null),[s,g]=yt.useState(true),[m,f]=yt.useState(null),a=yt.useRef(true),n=yt.useRef(e.apiBaseUrl);n.current=e.apiBaseUrl;let c=async()=>{try{a.current&&(g(!0),f(null));let d=await fetch(`${n.current}/api/keys/pricing`);if(!d.ok){let i=`Pricing unavailable (${d.status})`;try{let o=await d.json();o.error&&(i=o.error);}catch{}throw new Error(i)}let p=await d.json();a.current&&r(p);}catch(d){a.current&&f(d instanceof Error?d.message:"Failed to fetch pricing");}finally{a.current&&g(false);}};return yt.useEffect(()=>{a.current=true,c();let d=setInterval(c,6e4);return ()=>{a.current=false,clearInterval(d);}},[]),{pricing:t,loading:s,error:m,refresh:c}}function Be(){let{config:e,callbacks:t}=C(),[r,s]=yt.useState(false),[g,m]=yt.useState(null),[f,a]=yt.useState(null);return {mint:yt.useCallback(async(c,d,p=1)=>{try{s(!0),a(null),t.onPaymentComplete?.(c,d);let i=await fetch(`${e.apiBaseUrl}/api/keys/mint`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({paymentMethod:c,paymentRef:d,quantity:p})});if(!i.ok){let w="Key generation failed";try{let P=await i.json();P.error&&(w=P.error);}catch{}throw new Error(w)}let o=await i.json(),l=o.keys?.[0]||o,b={success:!0,key:{id:l.keyId||l.id||"",key:l.key||"",userId:l.userId||"",status:"active",tokenBalance:l.tokenBalance??l.currentTokenBalance??0,maxTokens:l.initialTokenBalance??l.tokenBalance??0,createdAt:String(l.createdAt||Date.now())},transactionId:d};return m(b),t.onMintSuccess?.(b),b}catch(i){let o=i instanceof Error?i:new Error("Key generation failed");return a(o.message),t.onMintError?.(o),{success:false,error:o.message}}finally{s(false);}},[e.apiBaseUrl,t]),minting:r,result:g,error:f}}function Le(){let{config:e}=C(),[t,r]=yt.useState(false),[s,g]=yt.useState(null),m=yt.useRef(true);return {createSession:yt.useCallback(async(a,n)=>{try{r(!0),g(null);let c=await fetch(`${e.apiBaseUrl}/api/keys/stripe-session`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({priceCents:a,quantity:n,stackId:e.stackId,referrerUrl:window.location.href})});if(!c.ok){let p=`Checkout failed (${c.status})`;try{let i=await c.json();i.error&&(p=i.error);}catch{}throw new Error(p)}let{url:d}=await c.json();if(d){try{sessionStorage.setItem("keyutils_stripe_pending","1");}catch{}window.location.href=d;}else throw new Error("No checkout URL returned")}catch(c){if(m.current){let d=c instanceof Error?c.message:"Checkout failed";g(d),r(false);}}},[e.apiBaseUrl,e.stackId]),loading:t,error:s}}var je=/^[1-9A-HJ-NP-Za-km-z]{32,44}$/;function de({amountSol:e,onSuccess:t,onError:r,disabled:s,className:g,style:m}){let{config:f}=C(),[a,n]=yt.useState(false),[c,d]=yt.useState(null),p=!!(f.merchantWallet&&je.test(f.merchantWallet)),i=yt.useCallback(async()=>{if(p)try{n(!0),d(null);let{Connection:o,PublicKey:l,Transaction:b,SystemProgram:w,LAMPORTS_PER_SOL:P}=await import('@solana/web3.js'),T=typeof window<"u"?window.solana:void 0;if(!T||typeof T!="object"||!T.isPhantom)throw new Error("Phantom wallet not found. Please install Phantom.");let j=T,k;try{k=new l(f.merchantWallet);}catch{throw new Error("Invalid merchant wallet address.")}let q=await j.connect(),_=new l(q.publicKey.toString()),K=new o(f.solanaRpcUrl||"https://api.mainnet-beta.solana.com"),{blockhash:F}=await K.getLatestBlockhash(),W=BigInt(Math.floor(e*1e9)),Z=f.protocolTreasuryWallet,B=f.protocolFeeBps??500,D=new b({recentBlockhash:F,feePayer:_});if(Z&&je.test(Z)&&B>0){let X=W*BigInt(B)/10000n,Je=W-X,Ze=new l(Z);D.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(Je)}),w.transfer({fromPubkey:_,toPubkey:Ze,lamports:Number(X)}));}else D.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(W)}));let{signature:re}=await j.signAndSendTransaction(D);t(re);}catch(o){let l=o instanceof Error?o:new Error("Payment failed");d(l.message),r?.(l);}finally{n(false);}},[e,f.merchantWallet,p,t,r]);return jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("button",{onClick:i,disabled:s||a||!p,"aria-label":`Pay ${e.toFixed(4)} SOL`,className:u("flex w-full items-center justify-center gap-2 rounded-lg bg-purple-600 px-4 py-6 font-medium text-white transition-colors hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed",g),style:m,children:a?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Loader2,{className:"h-4 w-4 animate-spin"}),"Processing..."]}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:["Pay ",e.toFixed(4)," SOL"]})}),c&&jsxRuntime.jsx("p",{className:"mt-2 text-center text-xs text-red-500",children:c})]})}function ue({result:e,className:t,style:r}){let[s,g]=yt.useState(false),m=yt.useRef(null);yt.useEffect(()=>()=>{m.current&&clearTimeout(m.current);},[]);let f=yt.useCallback(()=>{e.key?.key&&(navigator.clipboard.writeText(e.key.key),g(true),m.current&&clearTimeout(m.current),m.current=setTimeout(()=>g(false),2e3));},[e.key?.key]);return !e.success||!e.key?null:jsxRuntime.jsxs("div",{className:u("rounded-lg border border-green-500/20 bg-green-500/10 p-6 text-center",t),style:r,children:[jsxRuntime.jsx(lucideReact.CheckCircle,{className:"mx-auto mb-3 h-12 w-12 text-green-500"}),jsxRuntime.jsx("h3",{className:"mb-2 text-lg font-semibold text-foreground",children:"Key Generated!"}),jsxRuntime.jsx("p",{className:"mb-4 text-sm text-muted-foreground",children:"Your node key has been successfully generated."}),jsxRuntime.jsxs("div",{className:"mx-auto flex max-w-md items-center gap-2 rounded-md border bg-background p-3",children:[jsxRuntime.jsx("code",{className:"flex-1 truncate text-xs text-foreground",children:e.key.key}),jsxRuntime.jsx("button",{onClick:f,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",children:s?jsxRuntime.jsx(lucideReact.Check,{className:"h-4 w-4 text-green-500"}):jsxRuntime.jsx(lucideReact.Copy,{className:"h-4 w-4"})})]})]})}function A({className:e}){return jsxRuntime.jsx("div",{className:u("animate-pulse rounded-xl bg-muted",e)})}function me(){return jsxRuntime.jsxs("div",{className:"space-y-6",children:[jsxRuntime.jsxs("div",{className:"px-6 py-10 flex flex-col items-center gap-3",children:[jsxRuntime.jsx(A,{className:"h-14 w-48"}),jsxRuntime.jsx(A,{className:"h-5 w-64"})]}),jsxRuntime.jsx(A,{className:"h-[72px] w-full rounded-2xl"}),jsxRuntime.jsx(A,{className:"h-[68px] w-full rounded-2xl"}),jsxRuntime.jsx(A,{className:"h-[60px] w-full rounded-2xl"})]})}function Y({count:e=3}){return jsxRuntime.jsx("div",{className:"space-y-3",children:Array.from({length:e}).map((t,r)=>jsxRuntime.jsxs("div",{className:"rounded-xl border p-4 space-y-3",children:[jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsx(A,{className:"h-4 w-32"}),jsxRuntime.jsx(A,{className:"h-4 w-16"})]}),jsxRuntime.jsx(A,{className:"h-2 w-full rounded-full"}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx(A,{className:"h-3 w-24"}),jsxRuntime.jsx(A,{className:"h-3 w-20"})]})]},r))})}function Ct({quantity:e,max:t,onChange:r}){return jsxRuntime.jsxs("div",{className:"flex items-center justify-between rounded-2xl bg-muted/20 px-6 py-6",children:[jsxRuntime.jsx("span",{className:"text-sm font-medium text-foreground",children:"Quantity"}),jsxRuntime.jsxs("div",{className:"flex items-center gap-0 rounded-xl bg-background",children:[jsxRuntime.jsx("button",{onClick:()=>r(Math.max(1,e-1)),disabled:e<=1,"aria-label":"Decrease quantity",className:"flex h-12 w-12 items-center justify-center rounded-l-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsxRuntime.jsx(lucideReact.Minus,{className:"h-5 w-5"})}),jsxRuntime.jsx("span",{className:"flex h-12 w-14 items-center justify-center border-x text-xl font-bold text-foreground","aria-live":"polite",children:e}),jsxRuntime.jsx("button",{onClick:()=>r(Math.min(t,e+1)),disabled:e>=t,"aria-label":"Increase quantity",className:"flex h-12 w-12 items-center justify-center rounded-r-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsxRuntime.jsx(lucideReact.Plus,{className:"h-5 w-5"})})]})]})}function $e({pricing:e,quantity:t}){let[r,s]=yt.useState(false),g=e.priceUsd*t;return jsxRuntime.jsxs("div",{className:"rounded-2xl border bg-background",children:[jsxRuntime.jsxs("button",{onClick:()=>s(!r),"aria-expanded":r,className:"flex w-full items-center justify-between px-6 py-6 text-left",children:[jsxRuntime.jsxs("span",{className:"text-foreground",children:[jsxRuntime.jsxs("span",{className:"text-xl font-bold",children:["$",g.toFixed(2)]})," ",jsxRuntime.jsx("span",{className:"text-sm text-muted-foreground",children:"total fees included"})]}),r?jsxRuntime.jsx(lucideReact.ChevronUp,{className:"h-5 w-5 text-muted-foreground"}):jsxRuntime.jsx(lucideReact.ChevronDown,{className:"h-5 w-5 text-muted-foreground"})]}),r&&jsxRuntime.jsxs("div",{className:"border-t px-6 pb-8 pt-4 space-y-3 text-sm",children:[jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsxs("span",{className:"text-muted-foreground",children:["Node Key \xD7 ",t]}),jsxRuntime.jsxs("span",{className:"text-foreground",children:["$",(e.priceUsd*t).toFixed(2)]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Keys sold"}),jsxRuntime.jsx("span",{className:"text-foreground",children:e.keysSold})]}),e.daysUntilHalving>0&&jsxRuntime.jsxs("div",{className:"flex justify-between text-muted-foreground",children:[jsxRuntime.jsx("span",{children:"Next refresh"}),jsxRuntime.jsxs("span",{children:[e.daysUntilHalving," day",e.daysUntilHalving!==1?"s":""]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between border-t pt-3 font-semibold",children:[jsxRuntime.jsx("span",{className:"text-foreground",children:"Total"}),jsxRuntime.jsxs("span",{className:"text-foreground",children:["$",g.toFixed(2)]})]})]})]})}function fe({className:e,style:t}){let{config:r}=C(),{pricing:s,loading:g,error:m,refresh:f}=Ue(),{mint:a,minting:n,result:c,error:d}=Be(),{createSession:p,loading:i,error:o}=Le(),[l,b]=yt.useState(1),[w,P]=yt.useState(r.paymentMethods?.includes("stripe")?"stripe":"solana"),[T,j]=yt.useState(0),[k,q]=yt.useState(false),_=yt__default.default.useRef(l);_.current=l;let K=Math.max(1,r.maxQuantity||5),F=[...r.paymentMethods||["solana"]].sort((B,D)=>B==="stripe"?-1:D==="stripe"?1:0);if(yt.useEffect(()=>{if(typeof window>"u")return;let D=new URLSearchParams(window.location.search).get("session_id");if(!D){try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}return}if(/^cs_(test|live)_/.test(D)&&!k&&!c?.success){let re=false;try{re=sessionStorage.getItem("keyutils_stripe_pending")==="1";}catch{}if(!re)return;try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}q(true);let X=new URL(window.location.href);X.searchParams.delete("session_id"),window.history.replaceState({},"",X.toString()),a("stripe",D,_.current);}},[k,c,a]),c?.success)return jsxRuntime.jsx("div",{className:u("flex flex-col items-center justify-center",e),style:t,children:jsxRuntime.jsx(ue,{result:c})});if(k||n)return jsxRuntime.jsx("div",{className:u("flex flex-col",e),style:t,children:jsxRuntime.jsx(me,{})});if(g)return jsxRuntime.jsx("div",{className:u("flex flex-col",e),style:t,children:jsxRuntime.jsx(me,{})});if(m||!s)return jsxRuntime.jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-24",e),style:t,children:[jsxRuntime.jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load pricing"}),jsxRuntime.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m||"Please check your connection and try again."})]}),jsxRuntime.jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let W=async B=>{j(2),await a(w,B,l);},Z=()=>{p(s.priceCents,l);};return jsxRuntime.jsx("div",{className:u("flex flex-col",e),style:t,children:jsxRuntime.jsxs("div",{className:"space-y-6",children:[T===0&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[r.keyImage&&jsxRuntime.jsx("img",{src:r.keyImage,alt:"Node Key",className:r.keyImageClass||"w-1/2 mx-auto"}),jsxRuntime.jsxs("div",{className:"px-6 py-10 text-center",children:[jsxRuntime.jsxs("p",{className:"text-5xl font-bold tracking-tight text-foreground md:text-6xl",children:["$",s.priceUsd.toFixed(2)]}),jsxRuntime.jsxs("p",{className:"mt-2 text-base text-muted-foreground",children:["per key \xB7 ",s.tokenAllocationFormatted||I(s.tokenAllocation)," tokens included"]})]}),jsxRuntime.jsx(Ct,{quantity:l,max:K,onChange:b}),jsxRuntime.jsx($e,{pricing:s,quantity:l}),jsxRuntime.jsx("button",{onClick:()=>j(1),className:"w-full rounded-2xl bg-foreground py-6 text-center text-base font-semibold text-background transition-colors hover:bg-foreground/90",children:"Continue to Payment"})]}),T===1&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[F.length>1&&jsxRuntime.jsx("div",{role:"tablist",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:F.map(B=>jsxRuntime.jsxs("button",{role:"tab","aria-selected":w===B,onClick:()=>P(B),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-4 text-sm font-medium transition-colors",w===B?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:[B==="stripe"?jsxRuntime.jsx(lucideReact.CreditCard,{className:"h-5 w-5"}):jsxRuntime.jsx(lucideReact.Wallet,{className:"h-5 w-5"}),B==="stripe"?"Credit Card":"Crypto"]},B))}),jsxRuntime.jsx($e,{pricing:s,quantity:l}),w==="stripe"?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("button",{onClick:Z,disabled:i,className:"flex w-full items-center justify-center gap-2 rounded-2xl bg-foreground py-6 text-base font-semibold text-background transition-colors hover:bg-foreground/90 disabled:opacity-50",children:i?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Loader2,{className:"h-5 w-5 animate-spin"}),"Redirecting to Stripe..."]}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.CreditCard,{className:"h-5 w-5"}),"Pay with Card"]})}),o&&jsxRuntime.jsx("p",{className:"text-center text-sm text-red-500",children:o})]}):w==="solana"?jsxRuntime.jsx(de,{amountSol:s.priceSol??0,onSuccess:W,className:"rounded-2xl py-5 text-base"}):null,d&&jsxRuntime.jsx("p",{className:"text-center text-sm text-red-500",children:d}),jsxRuntime.jsx("button",{onClick:()=>j(0),className:"w-full py-3 text-center text-sm text-muted-foreground hover:text-foreground transition-colors",children:"\u2190 Back"})]})]})})}var Tt={ios:"iOS",android:"Android",windows:"Windows",mac:"macOS",linux:"Linux"},Ut=["mac","windows","linux","ios","android"];function pe({downloads:e,className:t,style:r}){let{config:s}=C(),g=yt.useMemo(()=>Re(),[]),m=e||Ut.map(n=>({platform:n,label:Tt[n],url:"#",compatible:n===g})),f=m.find(n=>n.compatible)||m[0],a=m.filter(n=>n.platform!==f.platform);return jsxRuntime.jsxs("div",{className:u("space-y-8",t),style:r,children:[jsxRuntime.jsxs("div",{className:"flex flex-col items-center gap-6 pt-4 mt-4",children:[s.aispImage&&jsxRuntime.jsx("img",{src:s.aispImage,alt:"aiSP",className:"w-full sm:w-1/2 mx-auto px-4 sm:px-0"}),jsxRuntime.jsxs("div",{className:"text-center",children:[jsxRuntime.jsx("p",{className:"text-lg sm:text-2xl font-medium text-foreground",children:"Download the AI Service Provider App"}),jsxRuntime.jsx("p",{className:"mt-1 text-sm sm:text-base text-muted-foreground",children:"Load your keys and run your node."})]}),jsxRuntime.jsxs("a",{href:f.url,className:"inline-flex items-center gap-3 rounded-full px-10 py-4 text-lg font-semibold text-white transition-colors hover:opacity-90",style:{backgroundColor:"#0900f4"},children:[jsxRuntime.jsx(lucideReact.Download,{className:"h-5 w-5"}),"Get aiSP for ",f.label]})]}),jsxRuntime.jsxs("p",{className:"text-center text-sm text-muted-foreground",children:["aiSP is also available on"," ",a.map((n,c)=>jsxRuntime.jsxs(yt__default.default.Fragment,{children:[c>0&&(c===a.length-1?" and ":", "),jsxRuntime.jsx("a",{href:n.url,className:"font-medium underline transition-colors hover:text-foreground",style:{color:"#066bff"},children:n.label})]},n.platform)),"."]}),jsxRuntime.jsxs("div",{className:"flex flex-col items-center gap-2 mt-12",children:[jsxRuntime.jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["Source code is available on",jsxRuntime.jsx("a",{href:"https://github.com/stack-net",target:"_blank",rel:"noopener noreferrer",className:"text-foreground underline hover:text-foreground/80 color-[#0900f4]",children:"Github"})]}),jsxRuntime.jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["By downloading, you agree to the",jsxRuntime.jsx("a",{href:s.termsUrl||"/terms",className:"text-foreground underline hover:text-foreground/80",children:"Open Source Applications Terms"})]})]})]})}function Et(e){return {id:e.id||"",keyIndex:e.keyIndex??e.key_index??null,key:e.key||e.keyPrefix||"",userId:e.userId||e.user_id||"",status:e.status||"active",tokenBalance:e.tokenBalance??e.currentTokenBalance??e.current_token_balance??0,maxTokens:e.maxTokens??e.initialTokenBalance??e.initial_token_balance??0,createdAt:String(e.createdAt??e.created_at??""),expiresAt:e.expiresAt,label:e.label||e.keyPrefix||e.key_prefix||void 0,paperWork:e.paperWork||e.paper_work||void 0,stackId:e.stackId,stackName:e.stackName}}function J(){let{config:e}=C(),[t,r]=yt.useState([]),[s,g]=yt.useState(true),[m,f]=yt.useState(null),a=yt.useRef(true),n=e.apiBaseUrl,c=yt.useCallback(async()=>{try{g(!0),f(null);let p=await fetch(`${n}/api/keys`);if(!p.ok){let l=`Failed to fetch keys (${p.status})`;try{let b=await p.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let i=await p.json(),o=Array.isArray(i)?i:i.keys??[];a.current&&r(o.map(Et));}catch(p){a.current&&f(p instanceof Error?p.message:"Failed to fetch keys");}finally{a.current&&g(false);}},[n]);yt.useEffect(()=>(a.current=true,c(),()=>{a.current=false;}),[c]);let d=t.reduce((p,i)=>p+i.tokenBalance,0);return {keys:t,totalBalance:d,loading:s,error:m,refresh:c}}function Oe(){let{config:e,callbacks:t}=C(),[r,s]=yt.useState(false),[g,m]=yt.useState(null),[f,a]=yt.useState(null),n=yt.useRef(true),c=yt.useCallback(async(p,i)=>{try{s(!0),a(null);let o=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({askPriceCents:i,stackId:e.stackId,stackName:e.stackName})});if(!o.ok){let b=`Listing failed (${o.status})`;try{let w=await o.json();w.error&&(b=w.error);}catch{}throw new Error(b)}let l=await o.json();return n.current&&(m(l),t.onListingCreated?.(l)),l}catch(o){let l=o instanceof Error?o.message:"Listing failed";return n.current&&a(l),null}finally{n.current&&s(false);}},[e.apiBaseUrl,e.stackId,e.stackName,t]),d=yt.useCallback(async p=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"DELETE"});if(!i.ok){let o=`Delist failed (${i.status})`;try{let l=await i.json();l.error&&(o=l.error);}catch{}throw new Error(o)}return n.current&&m(null),!0}catch(i){let o=i instanceof Error?i.message:"Delist failed";return n.current&&a(o),false}finally{n.current&&s(false);}},[e.apiBaseUrl]);return {listKey:c,delistKey:d,listing:r,result:g,error:f}}function V({current:e,max:t,className:r,style:s,showLabel:g=true}){let m=Se(e,t),f=Ke(m);return jsxRuntime.jsxs("div",{className:u("w-full",r),style:s,children:[g&&jsxRuntime.jsxs("div",{className:"mb-1 flex items-center justify-between text-xs text-muted-foreground",children:[jsxRuntime.jsxs("span",{children:[I(e)," / ",I(t)]}),jsxRuntime.jsxs("span",{children:[m,"%"]})]}),jsxRuntime.jsx("div",{className:"h-2 w-full overflow-hidden rounded-full bg-muted",children:jsxRuntime.jsx("div",{className:u("h-full rounded-full transition-all duration-500",f),style:{width:`${m}%`}})})]})}function At({nodeKey:e,selected:t,onSelect:r}){return jsxRuntime.jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsxRuntime.jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsxRuntime.jsx(lucideReact.Check,{className:"h-3 w-3 text-background"})}),jsxRuntime.jsxs("div",{className:"min-w-0 flex-1",children:[jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsxRuntime.jsx("span",{className:u("text-xs font-medium capitalize",e.status==="active"?"text-green-500":"text-muted-foreground"),children:e.status})]}),jsxRuntime.jsx(V,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function be({className:e,style:t}){let{config:r}=C(),{keys:s,loading:g,error:m,refresh:f}=J(),{listKey:a,listing:n,result:c,error:d}=Oe(),[p,i]=yt.useState(null),[o,l]=yt.useState(""),[b,w]=yt.useState(false),P=s.find(K=>K.id===p),T=parseInt(o.replace(/[^0-9]/g,""),10)||0,j=T>0&&Number.isFinite(T),k=!!P&&j&&b&&!n,q=async()=>{if(!k||!P)return;let K=T*100;await a(P.id,K)&&f();};if(c)return jsxRuntime.jsxs("div",{className:u("flex flex-col items-center gap-4 rounded-xl bg-green-500/10 py-12",e),style:t,children:[jsxRuntime.jsx(lucideReact.CheckCircle,{className:"h-12 w-12 text-green-500"}),jsxRuntime.jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Key Listed!"}),jsxRuntime.jsx("p",{className:"text-sm text-muted-foreground",children:"Your key is now on the Global Open AI Network marketplace."}),jsxRuntime.jsxs("p",{className:"text-xs text-muted-foreground",children:["Listing ID: ",jsxRuntime.jsx("code",{children:c.listingId})]}),jsxRuntime.jsxs("a",{href:`https://market.stacknet.org/keys/${c.keyId}`,target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-2 rounded-xl bg-foreground px-6 py-3 text-sm font-semibold text-background transition-colors hover:bg-foreground/90",children:[jsxRuntime.jsx(lucideReact.ExternalLink,{className:"h-4 w-4"}),"View Listing"]})]});if(g)return jsxRuntime.jsxs("div",{className:u("space-y-5 px-1",e),style:t,children:[jsxRuntime.jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsxRuntime.jsx(Y,{count:2})]});if(m)return jsxRuntime.jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-16",e),style:t,children:[jsxRuntime.jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsxRuntime.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m})]}),jsxRuntime.jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let _=s.filter(K=>K.status==="active");return _.length===0?jsxRuntime.jsxs("div",{className:u("flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed py-16",e),style:t,children:[jsxRuntime.jsx(lucideReact.AlertTriangle,{className:"h-8 w-8 text-muted-foreground"}),jsxRuntime.jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys to sell."})]}):jsxRuntime.jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsxRuntime.jsx("div",{className:"space-y-2",children:_.map(K=>jsxRuntime.jsx(At,{nodeKey:K,selected:p===K.id,onSelect:()=>i(K.id)},K.id))})]}),P&&jsxRuntime.jsxs("div",{className:"rounded-xl border bg-muted/30 p-5 space-y-2 text-sm",children:[P.keyIndex&&jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Key #"}),jsxRuntime.jsxs("span",{className:"text-foreground font-semibold",children:["#",P.keyIndex]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Key ID"}),jsxRuntime.jsx("code",{className:"text-xs text-foreground",children:P.id})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Originating Stack"}),jsxRuntime.jsx("span",{className:"text-foreground",children:r.stackName||"Unknown"})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Tokens (remaining / total)"}),jsxRuntime.jsxs("span",{className:"text-foreground",children:[I(P.tokenBalance)," / ",I(P.maxTokens)]})]}),P.paperWork&&jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Paper earned"}),jsxRuntime.jsx("span",{className:"text-foreground",children:P.paperWork})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Created"}),jsxRuntime.jsx("span",{className:"text-foreground",children:z(P.createdAt)})]})]}),jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("label",{htmlFor:"listing-price",className:"mb-2 block text-sm sm:text-lg font-semibold text-foreground",children:"Listing Price (USD)"}),jsxRuntime.jsxs("div",{className:"relative",children:[jsxRuntime.jsx("span",{className:"absolute left-4 top-1/2 -translate-y-1/2 text-2xl font-bold text-muted-foreground",children:"$"}),jsxRuntime.jsx("input",{id:"listing-price",type:"text",inputMode:"numeric",value:o,onChange:K=>{let F=K.target.value.replace(/[^0-9]/g,""),W=parseInt(F,10);l(isNaN(W)?"":W.toLocaleString("en-US"));},placeholder:"0",className:"w-full rounded-xl border bg-background py-6 pl-10 pr-4 text-3xl font-bold text-foreground placeholder:text-muted-foreground/30 focus:outline-none focus:ring-2 focus:ring-foreground/20"})]})]}),jsxRuntime.jsxs("div",{className:"flex items-start gap-3",children:[jsxRuntime.jsx("button",{type:"button",role:"checkbox","aria-checked":b,onClick:()=>w(!b),className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded border-2 transition-colors cursor-pointer",b?"border-foreground bg-foreground":"border-muted-foreground/40"),children:b&&jsxRuntime.jsx(lucideReact.Check,{className:"h-3 w-3 text-background"})}),jsxRuntime.jsxs("span",{className:"text-xs text-muted-foreground leading-relaxed",children:["I agree to list this key on the Global Open AI Network marketplace. The key will be deactivated upon sale and transferred to the buyer. Listing fees may apply."," ",jsxRuntime.jsx("a",{href:r.termsUrl||"/terms",className:"text-foreground underline",target:"_blank",rel:"noopener noreferrer",children:"Terms"})]})]}),d&&jsxRuntime.jsx("p",{className:"text-sm text-red-500",children:d}),jsxRuntime.jsxs("button",{onClick:q,disabled:!k,className:u("flex w-full items-center justify-center gap-2 rounded-xl py-4 text-sm font-semibold transition-colors",k?"bg-foreground text-background hover:bg-foreground/90":"bg-muted text-muted-foreground cursor-not-allowed"),children:[jsxRuntime.jsx(lucideReact.ExternalLink,{className:"h-4 w-4"}),n?"Listing...":"List on Marketplace"]})]})}function Qe(){let{config:e,callbacks:t}=C(),[r,s]=yt.useState(false),[g,m]=yt.useState(null),[f,a]=yt.useState(null),n=yt.useRef(true);return {transferKey:yt.useCallback(async(d,p)=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${d}/transfer`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({recipientId:p})});if(!i.ok){let l=`Transfer failed (${i.status})`;try{let b=await i.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let o=await i.json();return n.current&&(m(o),t.onTransferComplete?.(o)),o}catch(i){let o=i instanceof Error?i.message:"Transfer failed";return n.current&&a(o),null}finally{n.current&&s(false);}},[e.apiBaseUrl,t]),transferring:r,result:g,error:f}}function Qt({nodeKey:e,selected:t,onSelect:r}){return jsxRuntime.jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsxRuntime.jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsxRuntime.jsx(lucideReact.Check,{className:"h-3 w-3 text-background"})}),jsxRuntime.jsxs("div",{className:"min-w-0 flex-1",children:[jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsxRuntime.jsx("span",{className:"text-xs font-medium capitalize text-green-500",children:e.status})]}),jsxRuntime.jsx(V,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function ve({className:e,style:t}){let{keys:r,loading:s}=J(),{transferKey:g,transferring:m,result:f,error:a}=Qe(),[n,c]=yt.useState(null),[d,p]=yt.useState(""),[i,o]=yt.useState(false),l=r.filter(k=>k.status==="active"),b=l.find(k=>k.id===n),w=b&&d.trim()===b.userId,P=n&&d.trim().length>0&&i&&!w&&!m,T=async()=>{!n||!d.trim()||await g(n,d.trim());},j=()=>{c(null),p(""),o(false);};return f?jsxRuntime.jsxs("div",{className:u("flex flex-col items-center gap-4 py-8",e),style:t,children:[jsxRuntime.jsx(lucideReact.CheckCircle,{className:"h-12 w-12 text-green-500"}),jsxRuntime.jsxs("div",{className:"text-center",children:[jsxRuntime.jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Transfer Complete"}),jsxRuntime.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"Key transferred successfully"})]}),jsxRuntime.jsxs("div",{className:"w-full max-w-sm space-y-2 rounded-xl border border-border bg-muted/30 p-4 text-sm",children:[jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Key"}),jsxRuntime.jsxs("span",{className:"font-mono text-foreground",children:[f.keyId.slice(0,20),"..."]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Recipient"}),jsxRuntime.jsxs("span",{className:"font-mono text-foreground",children:[f.toUserId.slice(0,20),"..."]})]})]}),jsxRuntime.jsx("button",{onClick:j,className:"mt-2 rounded-lg border border-border px-4 py-2 text-sm font-medium text-foreground hover:bg-muted/50 transition-colors",children:"Transfer Another"})]}):jsxRuntime.jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("h3",{className:"mb-3 text-sm font-medium text-foreground",children:"Select Key to Transfer"}),s?jsxRuntime.jsx(Y,{count:2}):l.length===0?jsxRuntime.jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys available for transfer."}):jsxRuntime.jsx("div",{className:"space-y-2",children:l.map(k=>jsxRuntime.jsx(Qt,{nodeKey:k,selected:n===k.id,onSelect:()=>c(k.id)},k.id))})]}),n&&jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("label",{className:"mb-1.5 block text-sm font-medium text-foreground",children:"Recipient User ID"}),jsxRuntime.jsx("input",{type:"text",value:d,onChange:k=>{p(k.target.value),o(false);},placeholder:"Enter recipient's user ID or global ID",className:"w-full rounded-lg border border-border bg-background px-3 py-2.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-foreground/30 focus:outline-none focus:ring-1 focus:ring-foreground/10"}),w&&jsxRuntime.jsx("p",{className:"mt-1.5 text-xs text-red-500",children:"Cannot transfer a key to yourself"})]}),b&&d.trim().length>0&&!w&&jsxRuntime.jsx("div",{className:"rounded-xl border border-amber-500/30 bg-amber-500/5 p-4",children:jsxRuntime.jsxs("div",{className:"flex items-start gap-3",children:[jsxRuntime.jsx(lucideReact.AlertTriangle,{className:"mt-0.5 h-5 w-5 shrink-0 text-amber-500"}),jsxRuntime.jsxs("div",{className:"space-y-3",children:[jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Confirm Transfer"}),jsxRuntime.jsxs("p",{className:"mt-1 text-xs text-muted-foreground",children:["You are about to transfer key"," ",jsxRuntime.jsx("span",{className:"font-mono font-medium",children:b.keyIndex?`#${b.keyIndex}`:b.id.slice(0,12)})," ","(",I(b.tokenBalance)," tokens) to"," ",jsxRuntime.jsxs("span",{className:"font-mono font-medium",children:[d.trim().slice(0,20),"..."]})]})]}),jsxRuntime.jsxs("label",{className:"flex items-start gap-2 cursor-pointer",children:[jsxRuntime.jsx("input",{type:"checkbox",checked:i,onChange:k=>o(k.target.checked),className:"mt-0.5 h-4 w-4 rounded border-border"}),jsxRuntime.jsx("span",{className:"text-xs text-muted-foreground",children:"I confirm this transfer is permanent and cannot be undone."})]})]})]})}),a&&jsxRuntime.jsx("p",{className:"text-sm text-red-500",children:a}),jsxRuntime.jsx("button",{onClick:T,disabled:!P,className:u("flex w-full items-center justify-center gap-2 rounded-lg px-4 py-3 text-sm font-medium transition-all",P?"bg-foreground text-background hover:opacity-90":"bg-muted text-muted-foreground cursor-not-allowed"),children:m?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("div",{className:"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent"}),"Transferring..."]}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Send,{className:"h-4 w-4"}),"Transfer Key"]})})]})}var qt=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"},{id:"transfer",label:"Transfer"}];function zt({active:e,onChange:t}){return jsxRuntime.jsx("div",{role:"tablist","aria-label":"Key actions",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:qt.map(({id:r,label:s})=>jsxRuntime.jsx("button",{role:"tab","aria-selected":e===r,"aria-controls":`panel-${r}`,id:`tab-${r}`,onClick:()=>t(r),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium transition-all",e===r?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:jsxRuntime.jsx("span",{className:"inline",children:s})},r))})}function Yt({defaultTab:e="buy",className:t,style:r}){let[s,g]=yt.useState(e);return jsxRuntime.jsxs("div",{className:u("flex flex-col",t),style:r,children:[jsxRuntime.jsx("div",{className:"sticky top-0 z-10 bg-background/80 px-5 pb-3 pt-2 sm:pt-5 backdrop-blur-sm sm:px-10 md:px-16 lg:px-20",children:jsxRuntime.jsx("div",{className:"mx-auto max-w-xl",children:jsxRuntime.jsx(zt,{active:s,onChange:g})})}),jsxRuntime.jsx("div",{className:"flex flex-1 flex-col px-5 pb-8 sm:px-10 md:px-16 md:pb-12 lg:px-20",children:jsxRuntime.jsx("div",{className:"mx-auto w-full max-w-xl flex-1",children:jsxRuntime.jsxs("div",{role:"tabpanel",id:`panel-${s}`,"aria-labelledby":`tab-${s}`,children:[s==="buy"&&jsxRuntime.jsx(fe,{className:"flex-1"}),s==="use"&&jsxRuntime.jsx(pe,{className:"flex-1"}),s==="sell"&&jsxRuntime.jsx(be,{className:"flex-1"}),s==="transfer"&&jsxRuntime.jsx(ve,{className:"flex-1"})]})})})]})}function Jt({apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:g,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p,onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P,defaultTab:T,className:j,style:k}){return jsxRuntime.jsx(oe,{config:{apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:g,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p},callbacks:{onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P},children:jsxRuntime.jsx(Yt,{defaultTab:T,className:j,style:k})})}function ze(e){let{config:t}=C(),[r,s]=yt.useState([]),[g,m]=yt.useState(false),[f,a]=yt.useState(null),n=yt.useRef(true),c=t.apiBaseUrl,d=yt.useCallback(async()=>{if(e)try{m(!0),a(null);let p=await fetch(`${c}/api/keys/${e}/ledger`);if(!p.ok){let o=`Failed to fetch ledger (${p.status})`;try{let l=await p.json();l.error&&(o=l.error);}catch{}throw new Error(o)}let i=await p.json();n.current&&s(Array.isArray(i)?i:i.entries??[]);}catch(p){n.current&&a(p instanceof Error?p.message:"Failed to fetch ledger");}finally{n.current&&m(false);}},[c,e]);return yt.useEffect(()=>(n.current=true,d(),()=>{n.current=false;}),[d]),{entries:r,loading:g,error:f,refresh:d}}var we=20;function Pe({nodeKey:e,className:t,style:r}){let[s,g]=yt.useState(false),[m,f]=yt.useState(false),a=yt.useRef(null),{entries:n,loading:c}=ze(s?e.id:null);yt.useEffect(()=>()=>{a.current&&clearTimeout(a.current);},[]);let d=yt.useCallback(()=>{e.key&&(navigator.clipboard.writeText(e.key),f(true),a.current&&clearTimeout(a.current),a.current=setTimeout(()=>f(false),2e3));},[e.key]),p=e.status==="active"?"text-green-500":e.status==="expired"?"text-red-500":"text-yellow-500",i=n.slice(0,we);return jsxRuntime.jsxs("div",{className:u("rounded-lg border bg-background",t),style:r,children:[jsxRuntime.jsxs("div",{className:"p-4",children:[jsxRuntime.jsxs("div",{className:"mb-3 flex items-center justify-between",children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsx("button",{onClick:()=>g(!s),"aria-expanded":s,"aria-label":s?"Collapse ledger":"Expand ledger",className:"text-muted-foreground hover:text-foreground",children:s?jsxRuntime.jsx(lucideReact.ChevronDown,{className:"h-4 w-4"}):jsxRuntime.jsx(lucideReact.ChevronRight,{className:"h-4 w-4"})}),jsxRuntime.jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]})]}),jsxRuntime.jsx("span",{className:u("text-xs font-medium capitalize",p),children:e.status})]}),e.key&&jsxRuntime.jsxs("div",{className:"mb-3 flex items-center gap-2",children:[jsxRuntime.jsx("code",{className:"flex-1 truncate rounded bg-muted px-2 py-1 text-xs text-muted-foreground",children:e.key}),jsxRuntime.jsx("button",{onClick:d,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground",children:m?jsxRuntime.jsx(lucideReact.Check,{className:"h-3.5 w-3.5 text-green-500"}):jsxRuntime.jsx(lucideReact.Copy,{className:"h-3.5 w-3.5"})})]}),jsxRuntime.jsx(V,{current:e.tokenBalance,max:e.maxTokens}),jsxRuntime.jsxs("div",{className:"mt-2 flex items-center justify-between text-xs text-muted-foreground",children:[jsxRuntime.jsxs("span",{children:["Created ",z(e.createdAt)]}),e.expiresAt&&jsxRuntime.jsxs("span",{children:["Expires ",z(e.expiresAt)]})]})]}),s&&jsxRuntime.jsxs("div",{className:"border-t px-4 py-3",children:[jsxRuntime.jsx("h4",{className:"mb-2 text-xs font-medium text-muted-foreground",children:"Ledger"}),c?jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:"Loading..."}):i.length===0?jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:"No ledger entries."}):jsxRuntime.jsxs("div",{className:"space-y-1.5",children:[i.map(o=>jsxRuntime.jsxs("div",{className:"flex items-center justify-between text-xs",children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsxs("span",{className:u("font-medium",o.type==="credit"||o.type==="reward"?"text-green-500":"text-red-500"),children:[o.type==="credit"||o.type==="reward"?"+":"-",I(Math.abs(o.amount))]}),jsxRuntime.jsx("span",{className:"text-muted-foreground",children:o.description})]}),jsxRuntime.jsx("span",{className:"text-muted-foreground",children:z(o.createdAt)})]},o.id)),n.length>we&&jsxRuntime.jsxs("p",{className:"pt-1 text-xs text-muted-foreground",children:["Showing ",we," of ",n.length," entries"]})]})]})]})}var lr=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"}];function ne({baseHref:e}){return jsxRuntime.jsx("div",{className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5 mb-6",children:lr.map(({id:t,label:r})=>jsxRuntime.jsx("a",{href:`${e}?tab=${t}`,className:"flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium text-muted-foreground hover:text-foreground transition-all",children:r},t))})}function cr({getKeyHref:e="/keys/get",showTabs:t=true,className:r,style:s}){let{keys:g,totalBalance:m,loading:f,error:a,refresh:n}=J();return f?jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(ne,{baseHref:e}),jsxRuntime.jsx(Y,{count:3})]}):a?jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(ne,{baseHref:e}),jsxRuntime.jsxs("div",{className:"flex flex-col items-center justify-center gap-4 py-12",children:[jsxRuntime.jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsxRuntime.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:a})]}),jsxRuntime.jsx("button",{onClick:()=>n(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]})]}):g.length===0?jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(ne,{baseHref:e}),jsxRuntime.jsxs("div",{className:"flex flex-col items-center justify-center gap-4 rounded-lg border border-dashed py-12",children:[jsxRuntime.jsx(lucideReact.KeyRound,{className:"h-10 w-10 text-muted-foreground"}),jsxRuntime.jsxs("div",{className:"text-center",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"No keys yet"}),jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:"Get your first node key to start earning."})]}),e&&jsxRuntime.jsx("a",{href:e,className:"rounded-lg bg-foreground px-4 py-2 text-sm font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]})]}):jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(ne,{baseHref:e}),jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsxs("p",{className:"text-sm text-muted-foreground",children:[g.length," key",g.length!==1?"s":""," \xB7 Total balance: ",I(m)]}),e&&jsxRuntime.jsx("a",{href:e,className:"rounded-md bg-foreground px-3 py-1.5 text-xs font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]}),g.map(c=>jsxRuntime.jsx(Pe,{nodeKey:c},c.id))]})}
2
- exports.BuyKeyWidget=Jt;exports.BuyPanel=fe;exports.KeyBalanceBar=V;exports.KeyCard=Pe;exports.KeyList=cr;exports.KeyUtilsProvider=oe;exports.MintSuccess=ue;exports.SellPanel=be;exports.SolanaPayButton=de;exports.TransferPanel=ve;exports.UsePanel=pe;exports.useKeyUtilsContext=C;
1
+ 'use strict';var bt=require('react'),jsxRuntime=require('react/jsx-runtime'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),lucideReact=require('lucide-react');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var bt__default=/*#__PURE__*/_interopDefault(bt);var Se=bt.createContext(null);function C(){let e=bt.useContext(Se);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function ae({config:e,callbacks:t={},children:r}){typeof e.apiBaseUrl!="string"&&console.error("[KeyUtils] apiBaseUrl must be a string");let s=bt.useMemo(()=>({config:e,callbacks:t}),[e,t]);return jsxRuntime.jsx(Se.Provider,{value:s,children:r})}function A(){if(typeof document>"u")return {};let e=document.cookie.match(/(?:^|;\s*)__csrf=([^;]*)/);return e?{"x-csrf-token":e[1]}:{}}function u(...e){return tailwindMerge.twMerge(clsx.clsx(e))}function I(e){return e==null?"0":e>=1e9?`${(e/1e9).toFixed(1)}B`:e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:e.toLocaleString()}function Ke(e,t){return t<=0?0:Math.min(100,Math.round(e/t*100))}function Re(e){return e>=70?"bg-green-500":e>=30?"bg-yellow-500":"bg-red-500"}function Y(e){let t=typeof e=="string"&&/^\d+$/.test(e)?Number(e):e,r=new Date(t);return isNaN(r.getTime())?String(e):r.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}function Te(){if(typeof navigator>"u")return "mac";let e=navigator.userAgent.toLowerCase();return /iphone|ipad|ipod/.test(e)?"ios":/android/.test(e)?"android":/win/.test(e)?"windows":/linux/.test(e)?"linux":"mac"}function Be(){let{config:e}=C(),[t,r]=bt.useState(null),[s,g]=bt.useState(true),[m,f]=bt.useState(null),a=bt.useRef(true),n=bt.useRef(e.apiBaseUrl);n.current=e.apiBaseUrl;let c=async()=>{try{a.current&&(g(!0),f(null));let d=await fetch(`${n.current}/api/keys/pricing`,{credentials:"include"});if(!d.ok){let i=`Pricing unavailable (${d.status})`;try{let o=await d.json();o.error&&(i=o.error);}catch{}throw new Error(i)}let p=await d.json();a.current&&r(p);}catch(d){a.current&&f(d instanceof Error?d.message:"Failed to fetch pricing");}finally{a.current&&g(false);}};return bt.useEffect(()=>{a.current=true,c();let d=setInterval(c,6e4);return ()=>{a.current=false,clearInterval(d);}},[]),{pricing:t,loading:s,error:m,refresh:c}}function Ie(){let{config:e,callbacks:t}=C(),[r,s]=bt.useState(false),[g,m]=bt.useState(null),[f,a]=bt.useState(null);return {mint:bt.useCallback(async(c,d,p=1)=>{try{s(!0),a(null),t.onPaymentComplete?.(c,d);let i=await fetch(`${e.apiBaseUrl}/api/keys/mint`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({paymentMethod:c,paymentRef:d,quantity:p})});if(!i.ok){let w="Key generation failed";try{let P=await i.json();P.error&&(w=P.error);}catch{}throw new Error(w)}let o=await i.json(),l=o.keys?.[0]||o,b={success:!0,key:{id:l.keyId||l.id||"",key:l.key||"",userId:l.userId||"",status:"active",tokenBalance:l.tokenBalance??l.currentTokenBalance??0,maxTokens:l.initialTokenBalance??l.tokenBalance??0,createdAt:String(l.createdAt||Date.now())},transactionId:d};return m(b),t.onMintSuccess?.(b),b}catch(i){let o=i instanceof Error?i:new Error("Key generation failed");return a(o.message),t.onMintError?.(o),{success:false,error:o.message}}finally{s(false);}},[e.apiBaseUrl,t]),minting:r,result:g,error:f}}function Ee(){let{config:e}=C(),[t,r]=bt.useState(false),[s,g]=bt.useState(null),m=bt.useRef(true);return {createSession:bt.useCallback(async(a,n)=>{try{r(!0),g(null);let c=await fetch(`${e.apiBaseUrl}/api/keys/stripe-session`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({priceCents:a,quantity:n,stackId:e.stackId,referrerUrl:window.location.href})});if(!c.ok){let p=`Checkout failed (${c.status})`;try{let i=await c.json();i.error&&(p=i.error);}catch{}throw new Error(p)}let{url:d}=await c.json();if(d){try{sessionStorage.setItem("keyutils_stripe_pending","1");}catch{}window.location.href=d;}else throw new Error("No checkout URL returned")}catch(c){if(m.current){let d=c instanceof Error?c.message:"Checkout failed";g(d),r(false);}}},[e.apiBaseUrl,e.stackId]),loading:t,error:s}}var Me=/^[1-9A-HJ-NP-Za-km-z]{32,44}$/;function ue({amountSol:e,onSuccess:t,onError:r,disabled:s,className:g,style:m}){let{config:f}=C(),[a,n]=bt.useState(false),[c,d]=bt.useState(null),p=!!(f.merchantWallet&&Me.test(f.merchantWallet)),i=bt.useCallback(async()=>{if(p)try{n(!0),d(null);let{Connection:o,PublicKey:l,Transaction:b,SystemProgram:w,LAMPORTS_PER_SOL:P}=await import('@solana/web3.js'),T=typeof window<"u"?window.solana:void 0;if(!T||typeof T!="object"||!T.isPhantom)throw new Error("Phantom wallet not found. Please install Phantom.");let j=T,k;try{k=new l(f.merchantWallet);}catch{throw new Error("Invalid merchant wallet address.")}let z=await j.connect(),_=new l(z.publicKey.toString()),K=new o(f.solanaRpcUrl||"https://api.mainnet-beta.solana.com"),{blockhash:G}=await K.getLatestBlockhash(),F=BigInt(Math.floor(e*1e9)),Z=f.protocolTreasuryWallet,B=f.protocolFeeBps??500,O=new b({recentBlockhash:G,feePayer:_});if(Z&&Me.test(Z)&&B>0){let X=F*BigInt(B)/10000n,Je=F-X,Ze=new l(Z);O.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(Je)}),w.transfer({fromPubkey:_,toPubkey:Ze,lamports:Number(X)}));}else O.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(F)}));let{signature:se}=await j.signAndSendTransaction(O);t(se);}catch(o){let l=o instanceof Error?o:new Error("Payment failed");d(l.message),r?.(l);}finally{n(false);}},[e,f.merchantWallet,p,t,r]);return jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("button",{onClick:i,disabled:s||a||!p,"aria-label":`Pay ${e.toFixed(4)} SOL`,className:u("flex w-full items-center justify-center gap-2 rounded-lg bg-purple-600 px-4 py-6 font-medium text-white transition-colors hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed",g),style:m,children:a?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Loader2,{className:"h-4 w-4 animate-spin"}),"Processing..."]}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:["Pay ",e.toFixed(4)," SOL"]})}),c&&jsxRuntime.jsx("p",{className:"mt-2 text-center text-xs text-red-500",children:c})]})}function me({result:e,className:t,style:r}){let[s,g]=bt.useState(false),m=bt.useRef(null);bt.useEffect(()=>()=>{m.current&&clearTimeout(m.current);},[]);let f=bt.useCallback(()=>{e.key?.key&&(navigator.clipboard.writeText(e.key.key),g(true),m.current&&clearTimeout(m.current),m.current=setTimeout(()=>g(false),2e3));},[e.key?.key]);return !e.success||!e.key?null:jsxRuntime.jsxs("div",{className:u("rounded-lg border border-green-500/20 bg-green-500/10 p-6 text-center",t),style:r,children:[jsxRuntime.jsx(lucideReact.CheckCircle,{className:"mx-auto mb-3 h-12 w-12 text-green-500"}),jsxRuntime.jsx("h3",{className:"mb-2 text-lg font-semibold text-foreground",children:"Key Generated!"}),jsxRuntime.jsx("p",{className:"mb-4 text-sm text-muted-foreground",children:"Your node key has been successfully generated."}),jsxRuntime.jsxs("div",{className:"mx-auto flex max-w-md items-center gap-2 rounded-md border bg-background p-3",children:[jsxRuntime.jsx("code",{className:"flex-1 truncate text-xs text-foreground",children:e.key.key}),jsxRuntime.jsx("button",{onClick:f,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",children:s?jsxRuntime.jsx(lucideReact.Check,{className:"h-4 w-4 text-green-500"}):jsxRuntime.jsx(lucideReact.Copy,{className:"h-4 w-4"})})]})]})}function $({className:e}){return jsxRuntime.jsx("div",{className:u("animate-pulse rounded-xl bg-muted",e)})}function fe(){return jsxRuntime.jsxs("div",{className:"space-y-6",children:[jsxRuntime.jsxs("div",{className:"px-6 py-10 flex flex-col items-center gap-3",children:[jsxRuntime.jsx($,{className:"h-14 w-48"}),jsxRuntime.jsx($,{className:"h-5 w-64"})]}),jsxRuntime.jsx($,{className:"h-[72px] w-full rounded-2xl"}),jsxRuntime.jsx($,{className:"h-[68px] w-full rounded-2xl"}),jsxRuntime.jsx($,{className:"h-[60px] w-full rounded-2xl"})]})}function H({count:e=3}){return jsxRuntime.jsx("div",{className:"space-y-3",children:Array.from({length:e}).map((t,r)=>jsxRuntime.jsxs("div",{className:"rounded-xl border p-4 space-y-3",children:[jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsx($,{className:"h-4 w-32"}),jsxRuntime.jsx($,{className:"h-4 w-16"})]}),jsxRuntime.jsx($,{className:"h-2 w-full rounded-full"}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx($,{className:"h-3 w-24"}),jsxRuntime.jsx($,{className:"h-3 w-20"})]})]},r))})}function St({quantity:e,max:t,onChange:r}){return jsxRuntime.jsxs("div",{className:"flex items-center justify-between rounded-2xl bg-muted/20 px-6 py-6",children:[jsxRuntime.jsx("span",{className:"text-sm font-medium text-foreground",children:"Quantity"}),jsxRuntime.jsxs("div",{className:"flex items-center gap-0 rounded-xl bg-background",children:[jsxRuntime.jsx("button",{onClick:()=>r(Math.max(1,e-1)),disabled:e<=1,"aria-label":"Decrease quantity",className:"flex h-12 w-12 items-center justify-center rounded-l-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsxRuntime.jsx(lucideReact.Minus,{className:"h-5 w-5"})}),jsxRuntime.jsx("span",{className:"flex h-12 w-14 items-center justify-center border-x text-xl font-bold text-foreground","aria-live":"polite",children:e}),jsxRuntime.jsx("button",{onClick:()=>r(Math.min(t,e+1)),disabled:e>=t,"aria-label":"Increase quantity",className:"flex h-12 w-12 items-center justify-center rounded-r-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsxRuntime.jsx(lucideReact.Plus,{className:"h-5 w-5"})})]})]})}function De({pricing:e,quantity:t}){let[r,s]=bt.useState(false),g=e.priceUsd*t;return jsxRuntime.jsxs("div",{className:"rounded-2xl border bg-background",children:[jsxRuntime.jsxs("button",{onClick:()=>s(!r),"aria-expanded":r,className:"flex w-full items-center justify-between px-6 py-6 text-left",children:[jsxRuntime.jsxs("span",{className:"text-foreground",children:[jsxRuntime.jsxs("span",{className:"text-xl font-bold",children:["$",g.toFixed(2)]})," ",jsxRuntime.jsx("span",{className:"text-sm text-muted-foreground",children:"total fees included"})]}),r?jsxRuntime.jsx(lucideReact.ChevronUp,{className:"h-5 w-5 text-muted-foreground"}):jsxRuntime.jsx(lucideReact.ChevronDown,{className:"h-5 w-5 text-muted-foreground"})]}),r&&jsxRuntime.jsxs("div",{className:"border-t px-6 pb-8 pt-4 space-y-3 text-sm",children:[jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsxs("span",{className:"text-muted-foreground",children:["Node Key \xD7 ",t]}),jsxRuntime.jsxs("span",{className:"text-foreground",children:["$",(e.priceUsd*t).toFixed(2)]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Keys sold"}),jsxRuntime.jsx("span",{className:"text-foreground",children:e.keysSold})]}),e.daysUntilHalving>0&&jsxRuntime.jsxs("div",{className:"flex justify-between text-muted-foreground",children:[jsxRuntime.jsx("span",{children:"Next refresh"}),jsxRuntime.jsxs("span",{children:[e.daysUntilHalving," day",e.daysUntilHalving!==1?"s":""]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between border-t pt-3 font-semibold",children:[jsxRuntime.jsx("span",{className:"text-foreground",children:"Total"}),jsxRuntime.jsxs("span",{className:"text-foreground",children:["$",g.toFixed(2)]})]})]})]})}function pe({className:e,style:t}){let{config:r}=C(),{pricing:s,loading:g,error:m,refresh:f}=Be(),{mint:a,minting:n,result:c,error:d}=Ie(),{createSession:p,loading:i,error:o}=Ee(),[l,b]=bt.useState(1),[w,P]=bt.useState(r.paymentMethods?.includes("stripe")?"stripe":"solana"),[T,j]=bt.useState(0),[k,z]=bt.useState(false),_=bt__default.default.useRef(l);_.current=l;let K=Math.max(1,r.maxQuantity||5),G=[...r.paymentMethods||["solana"]].sort((B,O)=>B==="stripe"?-1:O==="stripe"?1:0);if(bt.useEffect(()=>{if(typeof window>"u")return;let O=new URLSearchParams(window.location.search).get("session_id");if(!O){try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}return}if(/^cs_(test|live)_/.test(O)&&!k&&!c?.success){let se=false;try{se=sessionStorage.getItem("keyutils_stripe_pending")==="1";}catch{}if(!se)return;try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}z(true);let X=new URL(window.location.href);X.searchParams.delete("session_id"),window.history.replaceState({},"",X.toString()),a("stripe",O,_.current);}},[k,c,a]),c?.success)return jsxRuntime.jsx("div",{className:u("flex flex-col items-center justify-center",e),style:t,children:jsxRuntime.jsx(me,{result:c})});if(k||n)return jsxRuntime.jsx("div",{className:u("flex flex-col",e),style:t,children:jsxRuntime.jsx(fe,{})});if(g)return jsxRuntime.jsx("div",{className:u("flex flex-col",e),style:t,children:jsxRuntime.jsx(fe,{})});if(m||!s)return jsxRuntime.jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-24",e),style:t,children:[jsxRuntime.jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load pricing"}),jsxRuntime.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m||"Please check your connection and try again."})]}),jsxRuntime.jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let F=async B=>{j(2),await a(w,B,l);},Z=()=>{p(s.priceCents,l);};return jsxRuntime.jsx("div",{className:u("flex flex-col",e),style:t,children:jsxRuntime.jsxs("div",{className:"space-y-6",children:[T===0&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[r.keyImage&&jsxRuntime.jsx("img",{src:r.keyImage,alt:"Node Key",className:r.keyImageClass||"w-1/2 mx-auto"}),jsxRuntime.jsxs("div",{className:"px-6 py-10 text-center",children:[jsxRuntime.jsxs("p",{className:"text-5xl font-bold tracking-tight text-foreground md:text-6xl",children:["$",s.priceUsd.toFixed(2)]}),jsxRuntime.jsxs("p",{className:"mt-2 text-base text-muted-foreground",children:["per key \xB7 ",s.tokenAllocationFormatted||I(s.tokenAllocation)," tokens included"]})]}),jsxRuntime.jsx(St,{quantity:l,max:K,onChange:b}),jsxRuntime.jsx(De,{pricing:s,quantity:l}),jsxRuntime.jsx("button",{onClick:()=>j(1),className:"w-full rounded-2xl bg-foreground py-6 text-center text-base font-semibold text-background transition-colors hover:bg-foreground/90",children:"Continue to Payment"})]}),T===1&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[G.length>1&&jsxRuntime.jsx("div",{role:"tablist",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:G.map(B=>jsxRuntime.jsxs("button",{role:"tab","aria-selected":w===B,onClick:()=>P(B),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-4 text-sm font-medium transition-colors",w===B?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:[B==="stripe"?jsxRuntime.jsx(lucideReact.CreditCard,{className:"h-5 w-5"}):jsxRuntime.jsx(lucideReact.Wallet,{className:"h-5 w-5"}),B==="stripe"?"Credit Card":"Crypto"]},B))}),jsxRuntime.jsx(De,{pricing:s,quantity:l}),w==="stripe"?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("button",{onClick:Z,disabled:i,className:"flex w-full items-center justify-center gap-2 rounded-2xl bg-foreground py-6 text-base font-semibold text-background transition-colors hover:bg-foreground/90 disabled:opacity-50",children:i?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Loader2,{className:"h-5 w-5 animate-spin"}),"Redirecting to Stripe..."]}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.CreditCard,{className:"h-5 w-5"}),"Pay with Card"]})}),o&&jsxRuntime.jsx("p",{className:"text-center text-sm text-red-500",children:o})]}):w==="solana"?jsxRuntime.jsx(ue,{amountSol:s.priceSol??0,onSuccess:F,className:"rounded-2xl py-5 text-base"}):null,d&&jsxRuntime.jsx("p",{className:"text-center text-sm text-red-500",children:d}),jsxRuntime.jsx("button",{onClick:()=>j(0),className:"w-full py-3 text-center text-sm text-muted-foreground hover:text-foreground transition-colors",children:"\u2190 Back"})]})]})})}var Ut={ios:"iOS",android:"Android",windows:"Windows",mac:"macOS",linux:"Linux"},Bt=["mac","windows","linux","ios","android"];function ge({downloads:e,className:t,style:r}){let{config:s}=C(),g=bt.useMemo(()=>Te(),[]),m=e||Bt.map(n=>({platform:n,label:Ut[n],url:"#",compatible:n===g})),f=m.find(n=>n.compatible)||m[0],a=m.filter(n=>n.platform!==f.platform);return jsxRuntime.jsxs("div",{className:u("space-y-8",t),style:r,children:[jsxRuntime.jsxs("div",{className:"flex flex-col items-center gap-6 pt-4 mt-4",children:[s.aispImage&&jsxRuntime.jsx("img",{src:s.aispImage,alt:"aiSP",className:"w-full sm:w-1/2 mx-auto px-4 sm:px-0"}),jsxRuntime.jsxs("div",{className:"text-center",children:[jsxRuntime.jsx("p",{className:"text-lg sm:text-2xl font-medium text-foreground",children:"Download the AI Service Provider App"}),jsxRuntime.jsx("p",{className:"mt-1 text-sm sm:text-base text-muted-foreground",children:"Load your keys and run your node."})]}),jsxRuntime.jsxs("a",{href:f.url,className:"inline-flex items-center gap-3 rounded-full px-10 py-4 text-lg font-semibold text-white transition-colors hover:opacity-90",style:{backgroundColor:"#0900f4"},children:[jsxRuntime.jsx(lucideReact.Download,{className:"h-5 w-5"}),"Get aiSP for ",f.label]})]}),jsxRuntime.jsxs("p",{className:"text-center text-sm text-muted-foreground",children:["aiSP is also available on"," ",a.map((n,c)=>jsxRuntime.jsxs(bt__default.default.Fragment,{children:[c>0&&(c===a.length-1?" and ":", "),jsxRuntime.jsx("a",{href:n.url,className:"font-medium underline transition-colors hover:text-foreground",style:{color:"#066bff"},children:n.label})]},n.platform)),"."]}),jsxRuntime.jsxs("div",{className:"flex flex-col items-center gap-2 mt-12",children:[jsxRuntime.jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["Source code is available on",jsxRuntime.jsx("a",{href:"https://github.com/stack-net",target:"_blank",rel:"noopener noreferrer",className:"text-foreground underline hover:text-foreground/80 color-[#0900f4]",children:"Github"})]}),jsxRuntime.jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["By downloading, you agree to the",jsxRuntime.jsx("a",{href:s.termsUrl||"/terms",className:"text-foreground underline hover:text-foreground/80",children:"Open Source Applications Terms"})]})]})]})}function jt(e){return {id:e.id||"",keyIndex:e.keyIndex??e.key_index??null,key:e.key||e.keyPrefix||"",userId:e.userId||e.user_id||"",status:e.status||"active",tokenBalance:e.tokenBalance??e.currentTokenBalance??e.current_token_balance??0,maxTokens:e.maxTokens??e.initialTokenBalance??e.initial_token_balance??0,createdAt:String(e.createdAt??e.created_at??""),expiresAt:e.expiresAt,label:e.label||e.keyPrefix||e.key_prefix||void 0,paperWork:e.paperWork||e.paper_work||void 0,stackId:e.stackId,stackName:e.stackName}}function J(){let{config:e}=C(),[t,r]=bt.useState([]),[s,g]=bt.useState(true),[m,f]=bt.useState(null),a=bt.useRef(true),n=e.apiBaseUrl,c=bt.useCallback(async()=>{try{g(!0),f(null);let p=await fetch(`${n}/api/keys`,{credentials:"include"});if(!p.ok){let l=`Failed to fetch keys (${p.status})`;try{let b=await p.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let i=await p.json(),o=Array.isArray(i)?i:i.keys??[];a.current&&r(o.map(jt));}catch(p){a.current&&f(p instanceof Error?p.message:"Failed to fetch keys");}finally{a.current&&g(false);}},[n]);bt.useEffect(()=>(a.current=true,c(),()=>{a.current=false;}),[c]);let d=t.reduce((p,i)=>p+i.tokenBalance,0);return {keys:t,totalBalance:d,loading:s,error:m,refresh:c}}function We(){let{config:e,callbacks:t}=C(),[r,s]=bt.useState(false),[g,m]=bt.useState(null),[f,a]=bt.useState(null),n=bt.useRef(true),c=bt.useCallback(async(p,i)=>{try{s(!0),a(null);let o=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({askPriceCents:i,stackId:e.stackId,stackName:e.stackName})});if(!o.ok){let b=`Listing failed (${o.status})`;try{let w=await o.json();w.error&&(b=w.error);}catch{}throw new Error(b)}let l=await o.json();return n.current&&(m(l),t.onListingCreated?.(l)),l}catch(o){let l=o instanceof Error?o.message:"Listing failed";return n.current&&a(l),null}finally{n.current&&s(false);}},[e.apiBaseUrl,e.stackId,e.stackName,t]),d=bt.useCallback(async p=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"DELETE",headers:{...A()},credentials:"include"});if(!i.ok){let o=`Delist failed (${i.status})`;try{let l=await i.json();l.error&&(o=l.error);}catch{}throw new Error(o)}return n.current&&m(null),!0}catch(i){let o=i instanceof Error?i.message:"Delist failed";return n.current&&a(o),false}finally{n.current&&s(false);}},[e.apiBaseUrl]);return {listKey:c,delistKey:d,listing:r,result:g,error:f}}function q({current:e,max:t,className:r,style:s,showLabel:g=true}){let m=Ke(e,t),f=Re(m);return jsxRuntime.jsxs("div",{className:u("w-full",r),style:s,children:[g&&jsxRuntime.jsxs("div",{className:"mb-1 flex items-center justify-between text-xs text-muted-foreground",children:[jsxRuntime.jsxs("span",{children:[I(e)," / ",I(t)]}),jsxRuntime.jsxs("span",{children:[m,"%"]})]}),jsxRuntime.jsx("div",{className:"h-2 w-full overflow-hidden rounded-full bg-muted",children:jsxRuntime.jsx("div",{className:u("h-full rounded-full transition-all duration-500",f),style:{width:`${m}%`}})})]})}function $t({nodeKey:e,selected:t,onSelect:r}){return jsxRuntime.jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsxRuntime.jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsxRuntime.jsx(lucideReact.Check,{className:"h-3 w-3 text-background"})}),jsxRuntime.jsxs("div",{className:"min-w-0 flex-1",children:[jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsxRuntime.jsx("span",{className:u("text-xs font-medium capitalize",e.status==="active"?"text-green-500":"text-muted-foreground"),children:e.status})]}),jsxRuntime.jsx(q,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function he({className:e,style:t}){let{config:r}=C(),{keys:s,loading:g,error:m,refresh:f}=J(),{listKey:a,listing:n,result:c,error:d}=We(),[p,i]=bt.useState(null),[o,l]=bt.useState(""),[b,w]=bt.useState(false),P=s.find(K=>K.id===p),T=parseInt(o.replace(/[^0-9]/g,""),10)||0,j=T>0&&Number.isFinite(T),k=!!P&&j&&b&&!n,z=async()=>{if(!k||!P)return;let K=T*100;await a(P.id,K)&&f();};if(c)return jsxRuntime.jsxs("div",{className:u("flex flex-col items-center gap-4 rounded-xl bg-green-500/10 py-12",e),style:t,children:[jsxRuntime.jsx(lucideReact.CheckCircle,{className:"h-12 w-12 text-green-500"}),jsxRuntime.jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Key Listed!"}),jsxRuntime.jsx("p",{className:"text-sm text-muted-foreground",children:"Your key is now on the Global Open AI Network marketplace."}),jsxRuntime.jsxs("p",{className:"text-xs text-muted-foreground",children:["Listing ID: ",jsxRuntime.jsx("code",{children:c.listingId})]}),jsxRuntime.jsxs("a",{href:`https://market.stacknet.org/keys/${c.keyId}`,target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-2 rounded-xl bg-foreground px-6 py-3 text-sm font-semibold text-background transition-colors hover:bg-foreground/90",children:[jsxRuntime.jsx(lucideReact.ExternalLink,{className:"h-4 w-4"}),"View Listing"]})]});if(g)return jsxRuntime.jsxs("div",{className:u("space-y-5 px-1",e),style:t,children:[jsxRuntime.jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsxRuntime.jsx(H,{count:2})]});if(m)return jsxRuntime.jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-16",e),style:t,children:[jsxRuntime.jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsxRuntime.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m})]}),jsxRuntime.jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let _=s.filter(K=>K.status==="active");return _.length===0?jsxRuntime.jsxs("div",{className:u("flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed py-16",e),style:t,children:[jsxRuntime.jsx(lucideReact.AlertTriangle,{className:"h-8 w-8 text-muted-foreground"}),jsxRuntime.jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys to sell."})]}):jsxRuntime.jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsxRuntime.jsx("div",{className:"space-y-2",children:_.map(K=>jsxRuntime.jsx($t,{nodeKey:K,selected:p===K.id,onSelect:()=>i(K.id)},K.id))})]}),P&&jsxRuntime.jsxs("div",{className:"rounded-xl border bg-muted/30 p-5 space-y-2 text-sm",children:[P.keyIndex&&jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Key #"}),jsxRuntime.jsxs("span",{className:"text-foreground font-semibold",children:["#",P.keyIndex]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Key ID"}),jsxRuntime.jsx("code",{className:"text-xs text-foreground",children:P.id})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Originating Stack"}),jsxRuntime.jsx("span",{className:"text-foreground",children:r.stackName||"Unknown"})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Tokens (remaining / total)"}),jsxRuntime.jsxs("span",{className:"text-foreground",children:[I(P.tokenBalance)," / ",I(P.maxTokens)]})]}),P.paperWork&&jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Paper earned"}),jsxRuntime.jsx("span",{className:"text-foreground",children:P.paperWork})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Created"}),jsxRuntime.jsx("span",{className:"text-foreground",children:Y(P.createdAt)})]})]}),jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("label",{htmlFor:"listing-price",className:"mb-2 block text-sm sm:text-lg font-semibold text-foreground",children:"Listing Price (USD)"}),jsxRuntime.jsxs("div",{className:"relative",children:[jsxRuntime.jsx("span",{className:"absolute left-4 top-1/2 -translate-y-1/2 text-2xl font-bold text-muted-foreground",children:"$"}),jsxRuntime.jsx("input",{id:"listing-price",type:"text",inputMode:"numeric",value:o,onChange:K=>{let G=K.target.value.replace(/[^0-9]/g,""),F=parseInt(G,10);l(isNaN(F)?"":F.toLocaleString("en-US"));},placeholder:"0",className:"w-full rounded-xl border bg-background py-6 pl-10 pr-4 text-3xl font-bold text-foreground placeholder:text-muted-foreground/30 focus:outline-none focus:ring-2 focus:ring-foreground/20"})]})]}),jsxRuntime.jsxs("div",{className:"flex items-start gap-3",children:[jsxRuntime.jsx("button",{type:"button",role:"checkbox","aria-checked":b,onClick:()=>w(!b),className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded border-2 transition-colors cursor-pointer",b?"border-foreground bg-foreground":"border-muted-foreground/40"),children:b&&jsxRuntime.jsx(lucideReact.Check,{className:"h-3 w-3 text-background"})}),jsxRuntime.jsxs("span",{className:"text-xs text-muted-foreground leading-relaxed",children:["I agree to list this key on the Global Open AI Network marketplace. The key will be deactivated upon sale and transferred to the buyer. Listing fees may apply."," ",jsxRuntime.jsx("a",{href:r.termsUrl||"/terms",className:"text-foreground underline",target:"_blank",rel:"noopener noreferrer",children:"Terms"})]})]}),d&&jsxRuntime.jsx("p",{className:"text-sm text-red-500",children:d}),jsxRuntime.jsxs("button",{onClick:z,disabled:!k,className:u("flex w-full items-center justify-center gap-2 rounded-xl py-4 text-sm font-semibold transition-colors",k?"bg-foreground text-background hover:bg-foreground/90":"bg-muted text-muted-foreground cursor-not-allowed"),children:[jsxRuntime.jsx(lucideReact.ExternalLink,{className:"h-4 w-4"}),n?"Listing...":"List on Marketplace"]})]})}function Ve(){let{config:e,callbacks:t}=C(),[r,s]=bt.useState(false),[g,m]=bt.useState(null),[f,a]=bt.useState(null),n=bt.useRef(true);return {transferKey:bt.useCallback(async(d,p)=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${d}/transfer`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({recipientId:p})});if(!i.ok){let l=`Transfer failed (${i.status})`;try{let b=await i.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let o=await i.json();return n.current&&(m(o),t.onTransferComplete?.(o)),o}catch(i){let o=i instanceof Error?i.message:"Transfer failed";return n.current&&a(o),null}finally{n.current&&s(false);}},[e.apiBaseUrl,t]),transferring:r,result:g,error:f}}function Vt({nodeKey:e,selected:t,onSelect:r}){return jsxRuntime.jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsxRuntime.jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsxRuntime.jsx(lucideReact.Check,{className:"h-3 w-3 text-background"})}),jsxRuntime.jsxs("div",{className:"min-w-0 flex-1",children:[jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsxRuntime.jsx("span",{className:"text-xs font-medium capitalize text-green-500",children:e.status})]}),jsxRuntime.jsx(q,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function ke({className:e,style:t}){let{keys:r,loading:s}=J(),{transferKey:g,transferring:m,result:f,error:a}=Ve(),[n,c]=bt.useState(null),[d,p]=bt.useState(""),[i,o]=bt.useState(false),l=r.filter(k=>k.status==="active"),b=l.find(k=>k.id===n),w=b&&d.trim()===b.userId,P=n&&d.trim().length>0&&i&&!w&&!m,T=async()=>{!n||!d.trim()||await g(n,d.trim());},j=()=>{c(null),p(""),o(false);};return f?jsxRuntime.jsxs("div",{className:u("flex flex-col items-center gap-4 py-8",e),style:t,children:[jsxRuntime.jsx(lucideReact.CheckCircle,{className:"h-12 w-12 text-green-500"}),jsxRuntime.jsxs("div",{className:"text-center",children:[jsxRuntime.jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Transfer Complete"}),jsxRuntime.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"Key transferred successfully"})]}),jsxRuntime.jsxs("div",{className:"w-full max-w-sm space-y-2 rounded-xl border border-border bg-muted/30 p-4 text-sm",children:[jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Key"}),jsxRuntime.jsxs("span",{className:"font-mono text-foreground",children:[f.keyId.slice(0,20),"..."]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Recipient"}),jsxRuntime.jsxs("span",{className:"font-mono text-foreground",children:[f.toUserId.slice(0,20),"..."]})]})]}),jsxRuntime.jsx("button",{onClick:j,className:"mt-2 rounded-lg border border-border px-4 py-2 text-sm font-medium text-foreground hover:bg-muted/50 transition-colors",children:"Transfer Another"})]}):jsxRuntime.jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("h3",{className:"mb-3 text-sm font-medium text-foreground",children:"Select Key to Transfer"}),s?jsxRuntime.jsx(H,{count:2}):l.length===0?jsxRuntime.jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys available for transfer."}):jsxRuntime.jsx("div",{className:"space-y-2",children:l.map(k=>jsxRuntime.jsx(Vt,{nodeKey:k,selected:n===k.id,onSelect:()=>c(k.id)},k.id))})]}),n&&jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("label",{className:"mb-1.5 block text-sm font-medium text-foreground",children:"Recipient User ID"}),jsxRuntime.jsx("input",{type:"text",value:d,onChange:k=>{p(k.target.value),o(false);},placeholder:"Enter recipient's user ID or global ID",className:"w-full rounded-lg border border-border bg-background px-3 py-2.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-foreground/30 focus:outline-none focus:ring-1 focus:ring-foreground/10"}),w&&jsxRuntime.jsx("p",{className:"mt-1.5 text-xs text-red-500",children:"Cannot transfer a key to yourself"})]}),b&&d.trim().length>0&&!w&&jsxRuntime.jsx("div",{className:"rounded-xl border border-amber-500/30 bg-amber-500/5 p-4",children:jsxRuntime.jsxs("div",{className:"flex items-start gap-3",children:[jsxRuntime.jsx(lucideReact.AlertTriangle,{className:"mt-0.5 h-5 w-5 shrink-0 text-amber-500"}),jsxRuntime.jsxs("div",{className:"space-y-3",children:[jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Confirm Transfer"}),jsxRuntime.jsxs("p",{className:"mt-1 text-xs text-muted-foreground",children:["You are about to transfer key"," ",jsxRuntime.jsx("span",{className:"font-mono font-medium",children:b.keyIndex?`#${b.keyIndex}`:b.id.slice(0,12)})," ","(",I(b.tokenBalance)," tokens) to"," ",jsxRuntime.jsxs("span",{className:"font-mono font-medium",children:[d.trim().slice(0,20),"..."]})]})]}),jsxRuntime.jsxs("label",{className:"flex items-start gap-2 cursor-pointer",children:[jsxRuntime.jsx("input",{type:"checkbox",checked:i,onChange:k=>o(k.target.checked),className:"mt-0.5 h-4 w-4 rounded border-border"}),jsxRuntime.jsx("span",{className:"text-xs text-muted-foreground",children:"I confirm this transfer is permanent and cannot be undone."})]})]})]})}),a&&jsxRuntime.jsx("p",{className:"text-sm text-red-500",children:a}),jsxRuntime.jsx("button",{onClick:T,disabled:!P,className:u("flex w-full items-center justify-center gap-2 rounded-lg px-4 py-3 text-sm font-medium transition-all",P?"bg-foreground text-background hover:opacity-90":"bg-muted text-muted-foreground cursor-not-allowed"),children:m?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("div",{className:"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent"}),"Transferring..."]}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Send,{className:"h-4 w-4"}),"Transfer Key"]})})]})}var zt=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"},{id:"transfer",label:"Transfer"}];function Yt({active:e,onChange:t}){return jsxRuntime.jsx("div",{role:"tablist","aria-label":"Key actions",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:zt.map(({id:r,label:s})=>jsxRuntime.jsx("button",{role:"tab","aria-selected":e===r,"aria-controls":`panel-${r}`,id:`tab-${r}`,onClick:()=>t(r),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium transition-all",e===r?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:jsxRuntime.jsx("span",{className:"inline",children:s})},r))})}function Ht({defaultTab:e="buy",className:t,style:r}){let[s,g]=bt.useState(e);return jsxRuntime.jsxs("div",{className:u("flex flex-col",t),style:r,children:[jsxRuntime.jsx("div",{className:"sticky top-0 z-10 bg-background/80 px-5 pb-3 pt-2 sm:pt-5 backdrop-blur-sm sm:px-10 md:px-16 lg:px-20",children:jsxRuntime.jsx("div",{className:"mx-auto max-w-xl",children:jsxRuntime.jsx(Yt,{active:s,onChange:g})})}),jsxRuntime.jsx("div",{className:"flex flex-1 flex-col px-5 pb-8 sm:px-10 md:px-16 md:pb-12 lg:px-20",children:jsxRuntime.jsx("div",{className:"mx-auto w-full max-w-xl flex-1",children:jsxRuntime.jsxs("div",{role:"tabpanel",id:`panel-${s}`,"aria-labelledby":`tab-${s}`,children:[s==="buy"&&jsxRuntime.jsx(pe,{className:"flex-1"}),s==="use"&&jsxRuntime.jsx(ge,{className:"flex-1"}),s==="sell"&&jsxRuntime.jsx(he,{className:"flex-1"}),s==="transfer"&&jsxRuntime.jsx(ke,{className:"flex-1"})]})})})]})}function Jt({apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:g,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p,onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P,defaultTab:T,className:j,style:k}){return jsxRuntime.jsx(ae,{config:{apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:g,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p},callbacks:{onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P},children:jsxRuntime.jsx(Ht,{defaultTab:T,className:j,style:k})})}function Ye(e){let{config:t}=C(),[r,s]=bt.useState([]),[g,m]=bt.useState(false),[f,a]=bt.useState(null),n=bt.useRef(true),c=t.apiBaseUrl,d=bt.useCallback(async()=>{if(e)try{m(!0),a(null);let p=await fetch(`${c}/api/keys/${e}/ledger`,{credentials:"include"});if(!p.ok){let o=`Failed to fetch ledger (${p.status})`;try{let l=await p.json();l.error&&(o=l.error);}catch{}throw new Error(o)}let i=await p.json();n.current&&s(Array.isArray(i)?i:i.entries??[]);}catch(p){n.current&&a(p instanceof Error?p.message:"Failed to fetch ledger");}finally{n.current&&m(false);}},[c,e]);return bt.useEffect(()=>(n.current=true,d(),()=>{n.current=false;}),[d]),{entries:r,loading:g,error:f,refresh:d}}var Pe=20;function Ce({nodeKey:e,className:t,style:r}){let[s,g]=bt.useState(false),[m,f]=bt.useState(false),a=bt.useRef(null),{entries:n,loading:c}=Ye(s?e.id:null);bt.useEffect(()=>()=>{a.current&&clearTimeout(a.current);},[]);let d=bt.useCallback(()=>{e.key&&(navigator.clipboard.writeText(e.key),f(true),a.current&&clearTimeout(a.current),a.current=setTimeout(()=>f(false),2e3));},[e.key]),p=e.status==="active"?"text-green-500":e.status==="expired"?"text-red-500":"text-yellow-500",i=n.slice(0,Pe);return jsxRuntime.jsxs("div",{className:u("rounded-lg border bg-background",t),style:r,children:[jsxRuntime.jsxs("div",{className:"p-4",children:[jsxRuntime.jsxs("div",{className:"mb-3 flex items-center justify-between",children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsx("button",{onClick:()=>g(!s),"aria-expanded":s,"aria-label":s?"Collapse ledger":"Expand ledger",className:"text-muted-foreground hover:text-foreground",children:s?jsxRuntime.jsx(lucideReact.ChevronDown,{className:"h-4 w-4"}):jsxRuntime.jsx(lucideReact.ChevronRight,{className:"h-4 w-4"})}),jsxRuntime.jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]})]}),jsxRuntime.jsx("span",{className:u("text-xs font-medium capitalize",p),children:e.status})]}),e.key&&jsxRuntime.jsxs("div",{className:"mb-3 flex items-center gap-2",children:[jsxRuntime.jsx("code",{className:"flex-1 truncate rounded bg-muted px-2 py-1 text-xs text-muted-foreground",children:e.key}),jsxRuntime.jsx("button",{onClick:d,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground",children:m?jsxRuntime.jsx(lucideReact.Check,{className:"h-3.5 w-3.5 text-green-500"}):jsxRuntime.jsx(lucideReact.Copy,{className:"h-3.5 w-3.5"})})]}),jsxRuntime.jsx(q,{current:e.tokenBalance,max:e.maxTokens}),jsxRuntime.jsxs("div",{className:"mt-2 flex items-center justify-between text-xs text-muted-foreground",children:[jsxRuntime.jsxs("span",{children:["Created ",Y(e.createdAt)]}),e.expiresAt&&jsxRuntime.jsxs("span",{children:["Expires ",Y(e.expiresAt)]})]})]}),s&&jsxRuntime.jsxs("div",{className:"border-t px-4 py-3",children:[jsxRuntime.jsx("h4",{className:"mb-2 text-xs font-medium text-muted-foreground",children:"Ledger"}),c?jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:"Loading..."}):i.length===0?jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:"No ledger entries."}):jsxRuntime.jsxs("div",{className:"space-y-1.5",children:[i.map(o=>jsxRuntime.jsxs("div",{className:"flex items-center justify-between text-xs",children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsxs("span",{className:u("font-medium",o.type==="credit"||o.type==="reward"?"text-green-500":"text-red-500"),children:[o.type==="credit"||o.type==="reward"?"+":"-",I(Math.abs(o.amount))]}),jsxRuntime.jsx("span",{className:"text-muted-foreground",children:o.description})]}),jsxRuntime.jsx("span",{className:"text-muted-foreground",children:Y(o.createdAt)})]},o.id)),n.length>Pe&&jsxRuntime.jsxs("p",{className:"pt-1 text-xs text-muted-foreground",children:["Showing ",Pe," of ",n.length," entries"]})]})]})]})}var cr=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"}];function oe({baseHref:e}){return jsxRuntime.jsx("div",{className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5 mb-6",children:cr.map(({id:t,label:r})=>jsxRuntime.jsx("a",{href:`${e}?tab=${t}`,className:"flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium text-muted-foreground hover:text-foreground transition-all",children:r},t))})}function dr({getKeyHref:e="/keys/get",showTabs:t=true,className:r,style:s}){let{keys:g,totalBalance:m,loading:f,error:a,refresh:n}=J();return f?jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(oe,{baseHref:e}),jsxRuntime.jsx(H,{count:3})]}):a?jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(oe,{baseHref:e}),jsxRuntime.jsxs("div",{className:"flex flex-col items-center justify-center gap-4 py-12",children:[jsxRuntime.jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsxRuntime.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:a})]}),jsxRuntime.jsx("button",{onClick:()=>n(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]})]}):g.length===0?jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(oe,{baseHref:e}),jsxRuntime.jsxs("div",{className:"flex flex-col items-center justify-center gap-4 rounded-lg border border-dashed py-12",children:[jsxRuntime.jsx(lucideReact.KeyRound,{className:"h-10 w-10 text-muted-foreground"}),jsxRuntime.jsxs("div",{className:"text-center",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"No keys yet"}),jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:"Get your first node key to start earning."})]}),e&&jsxRuntime.jsx("a",{href:e,className:"rounded-lg bg-foreground px-4 py-2 text-sm font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]})]}):jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(oe,{baseHref:e}),jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsxs("p",{className:"text-sm text-muted-foreground",children:[g.length," key",g.length!==1?"s":""," \xB7 Total balance: ",I(m)]}),e&&jsxRuntime.jsx("a",{href:e,className:"rounded-md bg-foreground px-3 py-1.5 text-xs font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]}),g.map(c=>jsxRuntime.jsx(Ce,{nodeKey:c},c.id))]})}
2
+ exports.BuyKeyWidget=Jt;exports.BuyPanel=pe;exports.KeyBalanceBar=q;exports.KeyCard=Ce;exports.KeyList=dr;exports.KeyUtilsProvider=ae;exports.MintSuccess=me;exports.SellPanel=he;exports.SolanaPayButton=ue;exports.TransferPanel=ke;exports.UsePanel=ge;exports.useKeyUtilsContext=C;
@@ -1,2 +1,2 @@
1
- import yt,{createContext,useContext,useMemo,useState,useCallback,useRef,useEffect}from'react';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {Loader2,CheckCircle,Check,Copy,CreditCard,Wallet,Download,ExternalLink,AlertTriangle,Send,ChevronDown,ChevronRight,KeyRound,Minus,Plus,ChevronUp}from'lucide-react';var Ce=createContext(null);function C(){let e=useContext(Ce);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function oe({config:e,callbacks:t={},children:r}){typeof e.apiBaseUrl!="string"&&console.error("[KeyUtils] apiBaseUrl must be a string");let s=useMemo(()=>({config:e,callbacks:t}),[e,t]);return jsx(Ce.Provider,{value:s,children:r})}function u(...e){return twMerge(clsx(e))}function I(e){return e==null?"0":e>=1e9?`${(e/1e9).toFixed(1)}B`:e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:e.toLocaleString()}function Se(e,t){return t<=0?0:Math.min(100,Math.round(e/t*100))}function Ke(e){return e>=70?"bg-green-500":e>=30?"bg-yellow-500":"bg-red-500"}function z(e){let t=typeof e=="string"&&/^\d+$/.test(e)?Number(e):e,r=new Date(t);return isNaN(r.getTime())?String(e):r.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}function Re(){if(typeof navigator>"u")return "mac";let e=navigator.userAgent.toLowerCase();return /iphone|ipad|ipod/.test(e)?"ios":/android/.test(e)?"android":/win/.test(e)?"windows":/linux/.test(e)?"linux":"mac"}function Ue(){let{config:e}=C(),[t,r]=useState(null),[s,g]=useState(true),[m,f]=useState(null),a=useRef(true),n=useRef(e.apiBaseUrl);n.current=e.apiBaseUrl;let c=async()=>{try{a.current&&(g(!0),f(null));let d=await fetch(`${n.current}/api/keys/pricing`);if(!d.ok){let i=`Pricing unavailable (${d.status})`;try{let o=await d.json();o.error&&(i=o.error);}catch{}throw new Error(i)}let p=await d.json();a.current&&r(p);}catch(d){a.current&&f(d instanceof Error?d.message:"Failed to fetch pricing");}finally{a.current&&g(false);}};return useEffect(()=>{a.current=true,c();let d=setInterval(c,6e4);return ()=>{a.current=false,clearInterval(d);}},[]),{pricing:t,loading:s,error:m,refresh:c}}function Be(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[g,m]=useState(null),[f,a]=useState(null);return {mint:useCallback(async(c,d,p=1)=>{try{s(!0),a(null),t.onPaymentComplete?.(c,d);let i=await fetch(`${e.apiBaseUrl}/api/keys/mint`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({paymentMethod:c,paymentRef:d,quantity:p})});if(!i.ok){let w="Key generation failed";try{let P=await i.json();P.error&&(w=P.error);}catch{}throw new Error(w)}let o=await i.json(),l=o.keys?.[0]||o,b={success:!0,key:{id:l.keyId||l.id||"",key:l.key||"",userId:l.userId||"",status:"active",tokenBalance:l.tokenBalance??l.currentTokenBalance??0,maxTokens:l.initialTokenBalance??l.tokenBalance??0,createdAt:String(l.createdAt||Date.now())},transactionId:d};return m(b),t.onMintSuccess?.(b),b}catch(i){let o=i instanceof Error?i:new Error("Key generation failed");return a(o.message),t.onMintError?.(o),{success:false,error:o.message}}finally{s(false);}},[e.apiBaseUrl,t]),minting:r,result:g,error:f}}function Le(){let{config:e}=C(),[t,r]=useState(false),[s,g]=useState(null),m=useRef(true);return {createSession:useCallback(async(a,n)=>{try{r(!0),g(null);let c=await fetch(`${e.apiBaseUrl}/api/keys/stripe-session`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({priceCents:a,quantity:n,stackId:e.stackId,referrerUrl:window.location.href})});if(!c.ok){let p=`Checkout failed (${c.status})`;try{let i=await c.json();i.error&&(p=i.error);}catch{}throw new Error(p)}let{url:d}=await c.json();if(d){try{sessionStorage.setItem("keyutils_stripe_pending","1");}catch{}window.location.href=d;}else throw new Error("No checkout URL returned")}catch(c){if(m.current){let d=c instanceof Error?c.message:"Checkout failed";g(d),r(false);}}},[e.apiBaseUrl,e.stackId]),loading:t,error:s}}var je=/^[1-9A-HJ-NP-Za-km-z]{32,44}$/;function de({amountSol:e,onSuccess:t,onError:r,disabled:s,className:g,style:m}){let{config:f}=C(),[a,n]=useState(false),[c,d]=useState(null),p=!!(f.merchantWallet&&je.test(f.merchantWallet)),i=useCallback(async()=>{if(p)try{n(!0),d(null);let{Connection:o,PublicKey:l,Transaction:b,SystemProgram:w,LAMPORTS_PER_SOL:P}=await import('@solana/web3.js'),T=typeof window<"u"?window.solana:void 0;if(!T||typeof T!="object"||!T.isPhantom)throw new Error("Phantom wallet not found. Please install Phantom.");let j=T,k;try{k=new l(f.merchantWallet);}catch{throw new Error("Invalid merchant wallet address.")}let q=await j.connect(),_=new l(q.publicKey.toString()),K=new o(f.solanaRpcUrl||"https://api.mainnet-beta.solana.com"),{blockhash:F}=await K.getLatestBlockhash(),W=BigInt(Math.floor(e*1e9)),Z=f.protocolTreasuryWallet,B=f.protocolFeeBps??500,D=new b({recentBlockhash:F,feePayer:_});if(Z&&je.test(Z)&&B>0){let X=W*BigInt(B)/10000n,Je=W-X,Ze=new l(Z);D.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(Je)}),w.transfer({fromPubkey:_,toPubkey:Ze,lamports:Number(X)}));}else D.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(W)}));let{signature:re}=await j.signAndSendTransaction(D);t(re);}catch(o){let l=o instanceof Error?o:new Error("Payment failed");d(l.message),r?.(l);}finally{n(false);}},[e,f.merchantWallet,p,t,r]);return jsxs("div",{children:[jsx("button",{onClick:i,disabled:s||a||!p,"aria-label":`Pay ${e.toFixed(4)} SOL`,className:u("flex w-full items-center justify-center gap-2 rounded-lg bg-purple-600 px-4 py-6 font-medium text-white transition-colors hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed",g),style:m,children:a?jsxs(Fragment,{children:[jsx(Loader2,{className:"h-4 w-4 animate-spin"}),"Processing..."]}):jsxs(Fragment,{children:["Pay ",e.toFixed(4)," SOL"]})}),c&&jsx("p",{className:"mt-2 text-center text-xs text-red-500",children:c})]})}function ue({result:e,className:t,style:r}){let[s,g]=useState(false),m=useRef(null);useEffect(()=>()=>{m.current&&clearTimeout(m.current);},[]);let f=useCallback(()=>{e.key?.key&&(navigator.clipboard.writeText(e.key.key),g(true),m.current&&clearTimeout(m.current),m.current=setTimeout(()=>g(false),2e3));},[e.key?.key]);return !e.success||!e.key?null:jsxs("div",{className:u("rounded-lg border border-green-500/20 bg-green-500/10 p-6 text-center",t),style:r,children:[jsx(CheckCircle,{className:"mx-auto mb-3 h-12 w-12 text-green-500"}),jsx("h3",{className:"mb-2 text-lg font-semibold text-foreground",children:"Key Generated!"}),jsx("p",{className:"mb-4 text-sm text-muted-foreground",children:"Your node key has been successfully generated."}),jsxs("div",{className:"mx-auto flex max-w-md items-center gap-2 rounded-md border bg-background p-3",children:[jsx("code",{className:"flex-1 truncate text-xs text-foreground",children:e.key.key}),jsx("button",{onClick:f,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",children:s?jsx(Check,{className:"h-4 w-4 text-green-500"}):jsx(Copy,{className:"h-4 w-4"})})]})]})}function A({className:e}){return jsx("div",{className:u("animate-pulse rounded-xl bg-muted",e)})}function me(){return jsxs("div",{className:"space-y-6",children:[jsxs("div",{className:"px-6 py-10 flex flex-col items-center gap-3",children:[jsx(A,{className:"h-14 w-48"}),jsx(A,{className:"h-5 w-64"})]}),jsx(A,{className:"h-[72px] w-full rounded-2xl"}),jsx(A,{className:"h-[68px] w-full rounded-2xl"}),jsx(A,{className:"h-[60px] w-full rounded-2xl"})]})}function Y({count:e=3}){return jsx("div",{className:"space-y-3",children:Array.from({length:e}).map((t,r)=>jsxs("div",{className:"rounded-xl border p-4 space-y-3",children:[jsxs("div",{className:"flex items-center justify-between",children:[jsx(A,{className:"h-4 w-32"}),jsx(A,{className:"h-4 w-16"})]}),jsx(A,{className:"h-2 w-full rounded-full"}),jsxs("div",{className:"flex justify-between",children:[jsx(A,{className:"h-3 w-24"}),jsx(A,{className:"h-3 w-20"})]})]},r))})}function Ct({quantity:e,max:t,onChange:r}){return jsxs("div",{className:"flex items-center justify-between rounded-2xl bg-muted/20 px-6 py-6",children:[jsx("span",{className:"text-sm font-medium text-foreground",children:"Quantity"}),jsxs("div",{className:"flex items-center gap-0 rounded-xl bg-background",children:[jsx("button",{onClick:()=>r(Math.max(1,e-1)),disabled:e<=1,"aria-label":"Decrease quantity",className:"flex h-12 w-12 items-center justify-center rounded-l-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsx(Minus,{className:"h-5 w-5"})}),jsx("span",{className:"flex h-12 w-14 items-center justify-center border-x text-xl font-bold text-foreground","aria-live":"polite",children:e}),jsx("button",{onClick:()=>r(Math.min(t,e+1)),disabled:e>=t,"aria-label":"Increase quantity",className:"flex h-12 w-12 items-center justify-center rounded-r-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsx(Plus,{className:"h-5 w-5"})})]})]})}function $e({pricing:e,quantity:t}){let[r,s]=useState(false),g=e.priceUsd*t;return jsxs("div",{className:"rounded-2xl border bg-background",children:[jsxs("button",{onClick:()=>s(!r),"aria-expanded":r,className:"flex w-full items-center justify-between px-6 py-6 text-left",children:[jsxs("span",{className:"text-foreground",children:[jsxs("span",{className:"text-xl font-bold",children:["$",g.toFixed(2)]})," ",jsx("span",{className:"text-sm text-muted-foreground",children:"total fees included"})]}),r?jsx(ChevronUp,{className:"h-5 w-5 text-muted-foreground"}):jsx(ChevronDown,{className:"h-5 w-5 text-muted-foreground"})]}),r&&jsxs("div",{className:"border-t px-6 pb-8 pt-4 space-y-3 text-sm",children:[jsxs("div",{className:"flex justify-between",children:[jsxs("span",{className:"text-muted-foreground",children:["Node Key \xD7 ",t]}),jsxs("span",{className:"text-foreground",children:["$",(e.priceUsd*t).toFixed(2)]})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Keys sold"}),jsx("span",{className:"text-foreground",children:e.keysSold})]}),e.daysUntilHalving>0&&jsxs("div",{className:"flex justify-between text-muted-foreground",children:[jsx("span",{children:"Next refresh"}),jsxs("span",{children:[e.daysUntilHalving," day",e.daysUntilHalving!==1?"s":""]})]}),jsxs("div",{className:"flex justify-between border-t pt-3 font-semibold",children:[jsx("span",{className:"text-foreground",children:"Total"}),jsxs("span",{className:"text-foreground",children:["$",g.toFixed(2)]})]})]})]})}function fe({className:e,style:t}){let{config:r}=C(),{pricing:s,loading:g,error:m,refresh:f}=Ue(),{mint:a,minting:n,result:c,error:d}=Be(),{createSession:p,loading:i,error:o}=Le(),[l,b]=useState(1),[w,P]=useState(r.paymentMethods?.includes("stripe")?"stripe":"solana"),[T,j]=useState(0),[k,q]=useState(false),_=yt.useRef(l);_.current=l;let K=Math.max(1,r.maxQuantity||5),F=[...r.paymentMethods||["solana"]].sort((B,D)=>B==="stripe"?-1:D==="stripe"?1:0);if(useEffect(()=>{if(typeof window>"u")return;let D=new URLSearchParams(window.location.search).get("session_id");if(!D){try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}return}if(/^cs_(test|live)_/.test(D)&&!k&&!c?.success){let re=false;try{re=sessionStorage.getItem("keyutils_stripe_pending")==="1";}catch{}if(!re)return;try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}q(true);let X=new URL(window.location.href);X.searchParams.delete("session_id"),window.history.replaceState({},"",X.toString()),a("stripe",D,_.current);}},[k,c,a]),c?.success)return jsx("div",{className:u("flex flex-col items-center justify-center",e),style:t,children:jsx(ue,{result:c})});if(k||n)return jsx("div",{className:u("flex flex-col",e),style:t,children:jsx(me,{})});if(g)return jsx("div",{className:u("flex flex-col",e),style:t,children:jsx(me,{})});if(m||!s)return jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-24",e),style:t,children:[jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load pricing"}),jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m||"Please check your connection and try again."})]}),jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let W=async B=>{j(2),await a(w,B,l);},Z=()=>{p(s.priceCents,l);};return jsx("div",{className:u("flex flex-col",e),style:t,children:jsxs("div",{className:"space-y-6",children:[T===0&&jsxs(Fragment,{children:[r.keyImage&&jsx("img",{src:r.keyImage,alt:"Node Key",className:r.keyImageClass||"w-1/2 mx-auto"}),jsxs("div",{className:"px-6 py-10 text-center",children:[jsxs("p",{className:"text-5xl font-bold tracking-tight text-foreground md:text-6xl",children:["$",s.priceUsd.toFixed(2)]}),jsxs("p",{className:"mt-2 text-base text-muted-foreground",children:["per key \xB7 ",s.tokenAllocationFormatted||I(s.tokenAllocation)," tokens included"]})]}),jsx(Ct,{quantity:l,max:K,onChange:b}),jsx($e,{pricing:s,quantity:l}),jsx("button",{onClick:()=>j(1),className:"w-full rounded-2xl bg-foreground py-6 text-center text-base font-semibold text-background transition-colors hover:bg-foreground/90",children:"Continue to Payment"})]}),T===1&&jsxs(Fragment,{children:[F.length>1&&jsx("div",{role:"tablist",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:F.map(B=>jsxs("button",{role:"tab","aria-selected":w===B,onClick:()=>P(B),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-4 text-sm font-medium transition-colors",w===B?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:[B==="stripe"?jsx(CreditCard,{className:"h-5 w-5"}):jsx(Wallet,{className:"h-5 w-5"}),B==="stripe"?"Credit Card":"Crypto"]},B))}),jsx($e,{pricing:s,quantity:l}),w==="stripe"?jsxs(Fragment,{children:[jsx("button",{onClick:Z,disabled:i,className:"flex w-full items-center justify-center gap-2 rounded-2xl bg-foreground py-6 text-base font-semibold text-background transition-colors hover:bg-foreground/90 disabled:opacity-50",children:i?jsxs(Fragment,{children:[jsx(Loader2,{className:"h-5 w-5 animate-spin"}),"Redirecting to Stripe..."]}):jsxs(Fragment,{children:[jsx(CreditCard,{className:"h-5 w-5"}),"Pay with Card"]})}),o&&jsx("p",{className:"text-center text-sm text-red-500",children:o})]}):w==="solana"?jsx(de,{amountSol:s.priceSol??0,onSuccess:W,className:"rounded-2xl py-5 text-base"}):null,d&&jsx("p",{className:"text-center text-sm text-red-500",children:d}),jsx("button",{onClick:()=>j(0),className:"w-full py-3 text-center text-sm text-muted-foreground hover:text-foreground transition-colors",children:"\u2190 Back"})]})]})})}var Tt={ios:"iOS",android:"Android",windows:"Windows",mac:"macOS",linux:"Linux"},Ut=["mac","windows","linux","ios","android"];function pe({downloads:e,className:t,style:r}){let{config:s}=C(),g=useMemo(()=>Re(),[]),m=e||Ut.map(n=>({platform:n,label:Tt[n],url:"#",compatible:n===g})),f=m.find(n=>n.compatible)||m[0],a=m.filter(n=>n.platform!==f.platform);return jsxs("div",{className:u("space-y-8",t),style:r,children:[jsxs("div",{className:"flex flex-col items-center gap-6 pt-4 mt-4",children:[s.aispImage&&jsx("img",{src:s.aispImage,alt:"aiSP",className:"w-full sm:w-1/2 mx-auto px-4 sm:px-0"}),jsxs("div",{className:"text-center",children:[jsx("p",{className:"text-lg sm:text-2xl font-medium text-foreground",children:"Download the AI Service Provider App"}),jsx("p",{className:"mt-1 text-sm sm:text-base text-muted-foreground",children:"Load your keys and run your node."})]}),jsxs("a",{href:f.url,className:"inline-flex items-center gap-3 rounded-full px-10 py-4 text-lg font-semibold text-white transition-colors hover:opacity-90",style:{backgroundColor:"#0900f4"},children:[jsx(Download,{className:"h-5 w-5"}),"Get aiSP for ",f.label]})]}),jsxs("p",{className:"text-center text-sm text-muted-foreground",children:["aiSP is also available on"," ",a.map((n,c)=>jsxs(yt.Fragment,{children:[c>0&&(c===a.length-1?" and ":", "),jsx("a",{href:n.url,className:"font-medium underline transition-colors hover:text-foreground",style:{color:"#066bff"},children:n.label})]},n.platform)),"."]}),jsxs("div",{className:"flex flex-col items-center gap-2 mt-12",children:[jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["Source code is available on",jsx("a",{href:"https://github.com/stack-net",target:"_blank",rel:"noopener noreferrer",className:"text-foreground underline hover:text-foreground/80 color-[#0900f4]",children:"Github"})]}),jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["By downloading, you agree to the",jsx("a",{href:s.termsUrl||"/terms",className:"text-foreground underline hover:text-foreground/80",children:"Open Source Applications Terms"})]})]})]})}function Et(e){return {id:e.id||"",keyIndex:e.keyIndex??e.key_index??null,key:e.key||e.keyPrefix||"",userId:e.userId||e.user_id||"",status:e.status||"active",tokenBalance:e.tokenBalance??e.currentTokenBalance??e.current_token_balance??0,maxTokens:e.maxTokens??e.initialTokenBalance??e.initial_token_balance??0,createdAt:String(e.createdAt??e.created_at??""),expiresAt:e.expiresAt,label:e.label||e.keyPrefix||e.key_prefix||void 0,paperWork:e.paperWork||e.paper_work||void 0,stackId:e.stackId,stackName:e.stackName}}function J(){let{config:e}=C(),[t,r]=useState([]),[s,g]=useState(true),[m,f]=useState(null),a=useRef(true),n=e.apiBaseUrl,c=useCallback(async()=>{try{g(!0),f(null);let p=await fetch(`${n}/api/keys`);if(!p.ok){let l=`Failed to fetch keys (${p.status})`;try{let b=await p.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let i=await p.json(),o=Array.isArray(i)?i:i.keys??[];a.current&&r(o.map(Et));}catch(p){a.current&&f(p instanceof Error?p.message:"Failed to fetch keys");}finally{a.current&&g(false);}},[n]);useEffect(()=>(a.current=true,c(),()=>{a.current=false;}),[c]);let d=t.reduce((p,i)=>p+i.tokenBalance,0);return {keys:t,totalBalance:d,loading:s,error:m,refresh:c}}function Oe(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[g,m]=useState(null),[f,a]=useState(null),n=useRef(true),c=useCallback(async(p,i)=>{try{s(!0),a(null);let o=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({askPriceCents:i,stackId:e.stackId,stackName:e.stackName})});if(!o.ok){let b=`Listing failed (${o.status})`;try{let w=await o.json();w.error&&(b=w.error);}catch{}throw new Error(b)}let l=await o.json();return n.current&&(m(l),t.onListingCreated?.(l)),l}catch(o){let l=o instanceof Error?o.message:"Listing failed";return n.current&&a(l),null}finally{n.current&&s(false);}},[e.apiBaseUrl,e.stackId,e.stackName,t]),d=useCallback(async p=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"DELETE"});if(!i.ok){let o=`Delist failed (${i.status})`;try{let l=await i.json();l.error&&(o=l.error);}catch{}throw new Error(o)}return n.current&&m(null),!0}catch(i){let o=i instanceof Error?i.message:"Delist failed";return n.current&&a(o),false}finally{n.current&&s(false);}},[e.apiBaseUrl]);return {listKey:c,delistKey:d,listing:r,result:g,error:f}}function V({current:e,max:t,className:r,style:s,showLabel:g=true}){let m=Se(e,t),f=Ke(m);return jsxs("div",{className:u("w-full",r),style:s,children:[g&&jsxs("div",{className:"mb-1 flex items-center justify-between text-xs text-muted-foreground",children:[jsxs("span",{children:[I(e)," / ",I(t)]}),jsxs("span",{children:[m,"%"]})]}),jsx("div",{className:"h-2 w-full overflow-hidden rounded-full bg-muted",children:jsx("div",{className:u("h-full rounded-full transition-all duration-500",f),style:{width:`${m}%`}})})]})}function At({nodeKey:e,selected:t,onSelect:r}){return jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsx(Check,{className:"h-3 w-3 text-background"})}),jsxs("div",{className:"min-w-0 flex-1",children:[jsxs("div",{className:"flex items-center justify-between",children:[jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsx("span",{className:u("text-xs font-medium capitalize",e.status==="active"?"text-green-500":"text-muted-foreground"),children:e.status})]}),jsx(V,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function be({className:e,style:t}){let{config:r}=C(),{keys:s,loading:g,error:m,refresh:f}=J(),{listKey:a,listing:n,result:c,error:d}=Oe(),[p,i]=useState(null),[o,l]=useState(""),[b,w]=useState(false),P=s.find(K=>K.id===p),T=parseInt(o.replace(/[^0-9]/g,""),10)||0,j=T>0&&Number.isFinite(T),k=!!P&&j&&b&&!n,q=async()=>{if(!k||!P)return;let K=T*100;await a(P.id,K)&&f();};if(c)return jsxs("div",{className:u("flex flex-col items-center gap-4 rounded-xl bg-green-500/10 py-12",e),style:t,children:[jsx(CheckCircle,{className:"h-12 w-12 text-green-500"}),jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Key Listed!"}),jsx("p",{className:"text-sm text-muted-foreground",children:"Your key is now on the Global Open AI Network marketplace."}),jsxs("p",{className:"text-xs text-muted-foreground",children:["Listing ID: ",jsx("code",{children:c.listingId})]}),jsxs("a",{href:`https://market.stacknet.org/keys/${c.keyId}`,target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-2 rounded-xl bg-foreground px-6 py-3 text-sm font-semibold text-background transition-colors hover:bg-foreground/90",children:[jsx(ExternalLink,{className:"h-4 w-4"}),"View Listing"]})]});if(g)return jsxs("div",{className:u("space-y-5 px-1",e),style:t,children:[jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsx(Y,{count:2})]});if(m)return jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-16",e),style:t,children:[jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m})]}),jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let _=s.filter(K=>K.status==="active");return _.length===0?jsxs("div",{className:u("flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed py-16",e),style:t,children:[jsx(AlertTriangle,{className:"h-8 w-8 text-muted-foreground"}),jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys to sell."})]}):jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxs("div",{children:[jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsx("div",{className:"space-y-2",children:_.map(K=>jsx(At,{nodeKey:K,selected:p===K.id,onSelect:()=>i(K.id)},K.id))})]}),P&&jsxs("div",{className:"rounded-xl border bg-muted/30 p-5 space-y-2 text-sm",children:[P.keyIndex&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key #"}),jsxs("span",{className:"text-foreground font-semibold",children:["#",P.keyIndex]})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key ID"}),jsx("code",{className:"text-xs text-foreground",children:P.id})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Originating Stack"}),jsx("span",{className:"text-foreground",children:r.stackName||"Unknown"})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Tokens (remaining / total)"}),jsxs("span",{className:"text-foreground",children:[I(P.tokenBalance)," / ",I(P.maxTokens)]})]}),P.paperWork&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Paper earned"}),jsx("span",{className:"text-foreground",children:P.paperWork})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Created"}),jsx("span",{className:"text-foreground",children:z(P.createdAt)})]})]}),jsxs("div",{children:[jsx("label",{htmlFor:"listing-price",className:"mb-2 block text-sm sm:text-lg font-semibold text-foreground",children:"Listing Price (USD)"}),jsxs("div",{className:"relative",children:[jsx("span",{className:"absolute left-4 top-1/2 -translate-y-1/2 text-2xl font-bold text-muted-foreground",children:"$"}),jsx("input",{id:"listing-price",type:"text",inputMode:"numeric",value:o,onChange:K=>{let F=K.target.value.replace(/[^0-9]/g,""),W=parseInt(F,10);l(isNaN(W)?"":W.toLocaleString("en-US"));},placeholder:"0",className:"w-full rounded-xl border bg-background py-6 pl-10 pr-4 text-3xl font-bold text-foreground placeholder:text-muted-foreground/30 focus:outline-none focus:ring-2 focus:ring-foreground/20"})]})]}),jsxs("div",{className:"flex items-start gap-3",children:[jsx("button",{type:"button",role:"checkbox","aria-checked":b,onClick:()=>w(!b),className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded border-2 transition-colors cursor-pointer",b?"border-foreground bg-foreground":"border-muted-foreground/40"),children:b&&jsx(Check,{className:"h-3 w-3 text-background"})}),jsxs("span",{className:"text-xs text-muted-foreground leading-relaxed",children:["I agree to list this key on the Global Open AI Network marketplace. The key will be deactivated upon sale and transferred to the buyer. Listing fees may apply."," ",jsx("a",{href:r.termsUrl||"/terms",className:"text-foreground underline",target:"_blank",rel:"noopener noreferrer",children:"Terms"})]})]}),d&&jsx("p",{className:"text-sm text-red-500",children:d}),jsxs("button",{onClick:q,disabled:!k,className:u("flex w-full items-center justify-center gap-2 rounded-xl py-4 text-sm font-semibold transition-colors",k?"bg-foreground text-background hover:bg-foreground/90":"bg-muted text-muted-foreground cursor-not-allowed"),children:[jsx(ExternalLink,{className:"h-4 w-4"}),n?"Listing...":"List on Marketplace"]})]})}function Qe(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[g,m]=useState(null),[f,a]=useState(null),n=useRef(true);return {transferKey:useCallback(async(d,p)=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${d}/transfer`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({recipientId:p})});if(!i.ok){let l=`Transfer failed (${i.status})`;try{let b=await i.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let o=await i.json();return n.current&&(m(o),t.onTransferComplete?.(o)),o}catch(i){let o=i instanceof Error?i.message:"Transfer failed";return n.current&&a(o),null}finally{n.current&&s(false);}},[e.apiBaseUrl,t]),transferring:r,result:g,error:f}}function Qt({nodeKey:e,selected:t,onSelect:r}){return jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsx(Check,{className:"h-3 w-3 text-background"})}),jsxs("div",{className:"min-w-0 flex-1",children:[jsxs("div",{className:"flex items-center justify-between",children:[jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsx("span",{className:"text-xs font-medium capitalize text-green-500",children:e.status})]}),jsx(V,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function ve({className:e,style:t}){let{keys:r,loading:s}=J(),{transferKey:g,transferring:m,result:f,error:a}=Qe(),[n,c]=useState(null),[d,p]=useState(""),[i,o]=useState(false),l=r.filter(k=>k.status==="active"),b=l.find(k=>k.id===n),w=b&&d.trim()===b.userId,P=n&&d.trim().length>0&&i&&!w&&!m,T=async()=>{!n||!d.trim()||await g(n,d.trim());},j=()=>{c(null),p(""),o(false);};return f?jsxs("div",{className:u("flex flex-col items-center gap-4 py-8",e),style:t,children:[jsx(CheckCircle,{className:"h-12 w-12 text-green-500"}),jsxs("div",{className:"text-center",children:[jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Transfer Complete"}),jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"Key transferred successfully"})]}),jsxs("div",{className:"w-full max-w-sm space-y-2 rounded-xl border border-border bg-muted/30 p-4 text-sm",children:[jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key"}),jsxs("span",{className:"font-mono text-foreground",children:[f.keyId.slice(0,20),"..."]})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Recipient"}),jsxs("span",{className:"font-mono text-foreground",children:[f.toUserId.slice(0,20),"..."]})]})]}),jsx("button",{onClick:j,className:"mt-2 rounded-lg border border-border px-4 py-2 text-sm font-medium text-foreground hover:bg-muted/50 transition-colors",children:"Transfer Another"})]}):jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxs("div",{children:[jsx("h3",{className:"mb-3 text-sm font-medium text-foreground",children:"Select Key to Transfer"}),s?jsx(Y,{count:2}):l.length===0?jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys available for transfer."}):jsx("div",{className:"space-y-2",children:l.map(k=>jsx(Qt,{nodeKey:k,selected:n===k.id,onSelect:()=>c(k.id)},k.id))})]}),n&&jsxs("div",{children:[jsx("label",{className:"mb-1.5 block text-sm font-medium text-foreground",children:"Recipient User ID"}),jsx("input",{type:"text",value:d,onChange:k=>{p(k.target.value),o(false);},placeholder:"Enter recipient's user ID or global ID",className:"w-full rounded-lg border border-border bg-background px-3 py-2.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-foreground/30 focus:outline-none focus:ring-1 focus:ring-foreground/10"}),w&&jsx("p",{className:"mt-1.5 text-xs text-red-500",children:"Cannot transfer a key to yourself"})]}),b&&d.trim().length>0&&!w&&jsx("div",{className:"rounded-xl border border-amber-500/30 bg-amber-500/5 p-4",children:jsxs("div",{className:"flex items-start gap-3",children:[jsx(AlertTriangle,{className:"mt-0.5 h-5 w-5 shrink-0 text-amber-500"}),jsxs("div",{className:"space-y-3",children:[jsxs("div",{children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Confirm Transfer"}),jsxs("p",{className:"mt-1 text-xs text-muted-foreground",children:["You are about to transfer key"," ",jsx("span",{className:"font-mono font-medium",children:b.keyIndex?`#${b.keyIndex}`:b.id.slice(0,12)})," ","(",I(b.tokenBalance)," tokens) to"," ",jsxs("span",{className:"font-mono font-medium",children:[d.trim().slice(0,20),"..."]})]})]}),jsxs("label",{className:"flex items-start gap-2 cursor-pointer",children:[jsx("input",{type:"checkbox",checked:i,onChange:k=>o(k.target.checked),className:"mt-0.5 h-4 w-4 rounded border-border"}),jsx("span",{className:"text-xs text-muted-foreground",children:"I confirm this transfer is permanent and cannot be undone."})]})]})]})}),a&&jsx("p",{className:"text-sm text-red-500",children:a}),jsx("button",{onClick:T,disabled:!P,className:u("flex w-full items-center justify-center gap-2 rounded-lg px-4 py-3 text-sm font-medium transition-all",P?"bg-foreground text-background hover:opacity-90":"bg-muted text-muted-foreground cursor-not-allowed"),children:m?jsxs(Fragment,{children:[jsx("div",{className:"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent"}),"Transferring..."]}):jsxs(Fragment,{children:[jsx(Send,{className:"h-4 w-4"}),"Transfer Key"]})})]})}var qt=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"},{id:"transfer",label:"Transfer"}];function zt({active:e,onChange:t}){return jsx("div",{role:"tablist","aria-label":"Key actions",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:qt.map(({id:r,label:s})=>jsx("button",{role:"tab","aria-selected":e===r,"aria-controls":`panel-${r}`,id:`tab-${r}`,onClick:()=>t(r),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium transition-all",e===r?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:jsx("span",{className:"inline",children:s})},r))})}function Yt({defaultTab:e="buy",className:t,style:r}){let[s,g]=useState(e);return jsxs("div",{className:u("flex flex-col",t),style:r,children:[jsx("div",{className:"sticky top-0 z-10 bg-background/80 px-5 pb-3 pt-2 sm:pt-5 backdrop-blur-sm sm:px-10 md:px-16 lg:px-20",children:jsx("div",{className:"mx-auto max-w-xl",children:jsx(zt,{active:s,onChange:g})})}),jsx("div",{className:"flex flex-1 flex-col px-5 pb-8 sm:px-10 md:px-16 md:pb-12 lg:px-20",children:jsx("div",{className:"mx-auto w-full max-w-xl flex-1",children:jsxs("div",{role:"tabpanel",id:`panel-${s}`,"aria-labelledby":`tab-${s}`,children:[s==="buy"&&jsx(fe,{className:"flex-1"}),s==="use"&&jsx(pe,{className:"flex-1"}),s==="sell"&&jsx(be,{className:"flex-1"}),s==="transfer"&&jsx(ve,{className:"flex-1"})]})})})]})}function Jt({apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:g,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p,onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P,defaultTab:T,className:j,style:k}){return jsx(oe,{config:{apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:g,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p},callbacks:{onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P},children:jsx(Yt,{defaultTab:T,className:j,style:k})})}function ze(e){let{config:t}=C(),[r,s]=useState([]),[g,m]=useState(false),[f,a]=useState(null),n=useRef(true),c=t.apiBaseUrl,d=useCallback(async()=>{if(e)try{m(!0),a(null);let p=await fetch(`${c}/api/keys/${e}/ledger`);if(!p.ok){let o=`Failed to fetch ledger (${p.status})`;try{let l=await p.json();l.error&&(o=l.error);}catch{}throw new Error(o)}let i=await p.json();n.current&&s(Array.isArray(i)?i:i.entries??[]);}catch(p){n.current&&a(p instanceof Error?p.message:"Failed to fetch ledger");}finally{n.current&&m(false);}},[c,e]);return useEffect(()=>(n.current=true,d(),()=>{n.current=false;}),[d]),{entries:r,loading:g,error:f,refresh:d}}var we=20;function Pe({nodeKey:e,className:t,style:r}){let[s,g]=useState(false),[m,f]=useState(false),a=useRef(null),{entries:n,loading:c}=ze(s?e.id:null);useEffect(()=>()=>{a.current&&clearTimeout(a.current);},[]);let d=useCallback(()=>{e.key&&(navigator.clipboard.writeText(e.key),f(true),a.current&&clearTimeout(a.current),a.current=setTimeout(()=>f(false),2e3));},[e.key]),p=e.status==="active"?"text-green-500":e.status==="expired"?"text-red-500":"text-yellow-500",i=n.slice(0,we);return jsxs("div",{className:u("rounded-lg border bg-background",t),style:r,children:[jsxs("div",{className:"p-4",children:[jsxs("div",{className:"mb-3 flex items-center justify-between",children:[jsxs("div",{className:"flex items-center gap-2",children:[jsx("button",{onClick:()=>g(!s),"aria-expanded":s,"aria-label":s?"Collapse ledger":"Expand ledger",className:"text-muted-foreground hover:text-foreground",children:s?jsx(ChevronDown,{className:"h-4 w-4"}):jsx(ChevronRight,{className:"h-4 w-4"})}),jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]})]}),jsx("span",{className:u("text-xs font-medium capitalize",p),children:e.status})]}),e.key&&jsxs("div",{className:"mb-3 flex items-center gap-2",children:[jsx("code",{className:"flex-1 truncate rounded bg-muted px-2 py-1 text-xs text-muted-foreground",children:e.key}),jsx("button",{onClick:d,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground",children:m?jsx(Check,{className:"h-3.5 w-3.5 text-green-500"}):jsx(Copy,{className:"h-3.5 w-3.5"})})]}),jsx(V,{current:e.tokenBalance,max:e.maxTokens}),jsxs("div",{className:"mt-2 flex items-center justify-between text-xs text-muted-foreground",children:[jsxs("span",{children:["Created ",z(e.createdAt)]}),e.expiresAt&&jsxs("span",{children:["Expires ",z(e.expiresAt)]})]})]}),s&&jsxs("div",{className:"border-t px-4 py-3",children:[jsx("h4",{className:"mb-2 text-xs font-medium text-muted-foreground",children:"Ledger"}),c?jsx("p",{className:"text-xs text-muted-foreground",children:"Loading..."}):i.length===0?jsx("p",{className:"text-xs text-muted-foreground",children:"No ledger entries."}):jsxs("div",{className:"space-y-1.5",children:[i.map(o=>jsxs("div",{className:"flex items-center justify-between text-xs",children:[jsxs("div",{className:"flex items-center gap-2",children:[jsxs("span",{className:u("font-medium",o.type==="credit"||o.type==="reward"?"text-green-500":"text-red-500"),children:[o.type==="credit"||o.type==="reward"?"+":"-",I(Math.abs(o.amount))]}),jsx("span",{className:"text-muted-foreground",children:o.description})]}),jsx("span",{className:"text-muted-foreground",children:z(o.createdAt)})]},o.id)),n.length>we&&jsxs("p",{className:"pt-1 text-xs text-muted-foreground",children:["Showing ",we," of ",n.length," entries"]})]})]})]})}var lr=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"}];function ne({baseHref:e}){return jsx("div",{className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5 mb-6",children:lr.map(({id:t,label:r})=>jsx("a",{href:`${e}?tab=${t}`,className:"flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium text-muted-foreground hover:text-foreground transition-all",children:r},t))})}function cr({getKeyHref:e="/keys/get",showTabs:t=true,className:r,style:s}){let{keys:g,totalBalance:m,loading:f,error:a,refresh:n}=J();return f?jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(ne,{baseHref:e}),jsx(Y,{count:3})]}):a?jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(ne,{baseHref:e}),jsxs("div",{className:"flex flex-col items-center justify-center gap-4 py-12",children:[jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:a})]}),jsx("button",{onClick:()=>n(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]})]}):g.length===0?jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(ne,{baseHref:e}),jsxs("div",{className:"flex flex-col items-center justify-center gap-4 rounded-lg border border-dashed py-12",children:[jsx(KeyRound,{className:"h-10 w-10 text-muted-foreground"}),jsxs("div",{className:"text-center",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"No keys yet"}),jsx("p",{className:"text-xs text-muted-foreground",children:"Get your first node key to start earning."})]}),e&&jsx("a",{href:e,className:"rounded-lg bg-foreground px-4 py-2 text-sm font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]})]}):jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(ne,{baseHref:e}),jsxs("div",{className:"flex items-center justify-between",children:[jsxs("p",{className:"text-sm text-muted-foreground",children:[g.length," key",g.length!==1?"s":""," \xB7 Total balance: ",I(m)]}),e&&jsx("a",{href:e,className:"rounded-md bg-foreground px-3 py-1.5 text-xs font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]}),g.map(c=>jsx(Pe,{nodeKey:c},c.id))]})}
2
- export{Jt as BuyKeyWidget,fe as BuyPanel,V as KeyBalanceBar,Pe as KeyCard,cr as KeyList,oe as KeyUtilsProvider,ue as MintSuccess,be as SellPanel,de as SolanaPayButton,ve as TransferPanel,pe as UsePanel,C as useKeyUtilsContext};
1
+ import bt,{createContext,useContext,useMemo,useState,useCallback,useRef,useEffect}from'react';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {Loader2,CheckCircle,Check,Copy,CreditCard,Wallet,Download,ExternalLink,AlertTriangle,Send,ChevronDown,ChevronRight,KeyRound,Minus,Plus,ChevronUp}from'lucide-react';var Se=createContext(null);function C(){let e=useContext(Se);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function ae({config:e,callbacks:t={},children:r}){typeof e.apiBaseUrl!="string"&&console.error("[KeyUtils] apiBaseUrl must be a string");let s=useMemo(()=>({config:e,callbacks:t}),[e,t]);return jsx(Se.Provider,{value:s,children:r})}function A(){if(typeof document>"u")return {};let e=document.cookie.match(/(?:^|;\s*)__csrf=([^;]*)/);return e?{"x-csrf-token":e[1]}:{}}function u(...e){return twMerge(clsx(e))}function I(e){return e==null?"0":e>=1e9?`${(e/1e9).toFixed(1)}B`:e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:e.toLocaleString()}function Ke(e,t){return t<=0?0:Math.min(100,Math.round(e/t*100))}function Re(e){return e>=70?"bg-green-500":e>=30?"bg-yellow-500":"bg-red-500"}function Y(e){let t=typeof e=="string"&&/^\d+$/.test(e)?Number(e):e,r=new Date(t);return isNaN(r.getTime())?String(e):r.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}function Te(){if(typeof navigator>"u")return "mac";let e=navigator.userAgent.toLowerCase();return /iphone|ipad|ipod/.test(e)?"ios":/android/.test(e)?"android":/win/.test(e)?"windows":/linux/.test(e)?"linux":"mac"}function Be(){let{config:e}=C(),[t,r]=useState(null),[s,g]=useState(true),[m,f]=useState(null),a=useRef(true),n=useRef(e.apiBaseUrl);n.current=e.apiBaseUrl;let c=async()=>{try{a.current&&(g(!0),f(null));let d=await fetch(`${n.current}/api/keys/pricing`,{credentials:"include"});if(!d.ok){let i=`Pricing unavailable (${d.status})`;try{let o=await d.json();o.error&&(i=o.error);}catch{}throw new Error(i)}let p=await d.json();a.current&&r(p);}catch(d){a.current&&f(d instanceof Error?d.message:"Failed to fetch pricing");}finally{a.current&&g(false);}};return useEffect(()=>{a.current=true,c();let d=setInterval(c,6e4);return ()=>{a.current=false,clearInterval(d);}},[]),{pricing:t,loading:s,error:m,refresh:c}}function Ie(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[g,m]=useState(null),[f,a]=useState(null);return {mint:useCallback(async(c,d,p=1)=>{try{s(!0),a(null),t.onPaymentComplete?.(c,d);let i=await fetch(`${e.apiBaseUrl}/api/keys/mint`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({paymentMethod:c,paymentRef:d,quantity:p})});if(!i.ok){let w="Key generation failed";try{let P=await i.json();P.error&&(w=P.error);}catch{}throw new Error(w)}let o=await i.json(),l=o.keys?.[0]||o,b={success:!0,key:{id:l.keyId||l.id||"",key:l.key||"",userId:l.userId||"",status:"active",tokenBalance:l.tokenBalance??l.currentTokenBalance??0,maxTokens:l.initialTokenBalance??l.tokenBalance??0,createdAt:String(l.createdAt||Date.now())},transactionId:d};return m(b),t.onMintSuccess?.(b),b}catch(i){let o=i instanceof Error?i:new Error("Key generation failed");return a(o.message),t.onMintError?.(o),{success:false,error:o.message}}finally{s(false);}},[e.apiBaseUrl,t]),minting:r,result:g,error:f}}function Ee(){let{config:e}=C(),[t,r]=useState(false),[s,g]=useState(null),m=useRef(true);return {createSession:useCallback(async(a,n)=>{try{r(!0),g(null);let c=await fetch(`${e.apiBaseUrl}/api/keys/stripe-session`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({priceCents:a,quantity:n,stackId:e.stackId,referrerUrl:window.location.href})});if(!c.ok){let p=`Checkout failed (${c.status})`;try{let i=await c.json();i.error&&(p=i.error);}catch{}throw new Error(p)}let{url:d}=await c.json();if(d){try{sessionStorage.setItem("keyutils_stripe_pending","1");}catch{}window.location.href=d;}else throw new Error("No checkout URL returned")}catch(c){if(m.current){let d=c instanceof Error?c.message:"Checkout failed";g(d),r(false);}}},[e.apiBaseUrl,e.stackId]),loading:t,error:s}}var Me=/^[1-9A-HJ-NP-Za-km-z]{32,44}$/;function ue({amountSol:e,onSuccess:t,onError:r,disabled:s,className:g,style:m}){let{config:f}=C(),[a,n]=useState(false),[c,d]=useState(null),p=!!(f.merchantWallet&&Me.test(f.merchantWallet)),i=useCallback(async()=>{if(p)try{n(!0),d(null);let{Connection:o,PublicKey:l,Transaction:b,SystemProgram:w,LAMPORTS_PER_SOL:P}=await import('@solana/web3.js'),T=typeof window<"u"?window.solana:void 0;if(!T||typeof T!="object"||!T.isPhantom)throw new Error("Phantom wallet not found. Please install Phantom.");let j=T,k;try{k=new l(f.merchantWallet);}catch{throw new Error("Invalid merchant wallet address.")}let z=await j.connect(),_=new l(z.publicKey.toString()),K=new o(f.solanaRpcUrl||"https://api.mainnet-beta.solana.com"),{blockhash:G}=await K.getLatestBlockhash(),F=BigInt(Math.floor(e*1e9)),Z=f.protocolTreasuryWallet,B=f.protocolFeeBps??500,O=new b({recentBlockhash:G,feePayer:_});if(Z&&Me.test(Z)&&B>0){let X=F*BigInt(B)/10000n,Je=F-X,Ze=new l(Z);O.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(Je)}),w.transfer({fromPubkey:_,toPubkey:Ze,lamports:Number(X)}));}else O.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(F)}));let{signature:se}=await j.signAndSendTransaction(O);t(se);}catch(o){let l=o instanceof Error?o:new Error("Payment failed");d(l.message),r?.(l);}finally{n(false);}},[e,f.merchantWallet,p,t,r]);return jsxs("div",{children:[jsx("button",{onClick:i,disabled:s||a||!p,"aria-label":`Pay ${e.toFixed(4)} SOL`,className:u("flex w-full items-center justify-center gap-2 rounded-lg bg-purple-600 px-4 py-6 font-medium text-white transition-colors hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed",g),style:m,children:a?jsxs(Fragment,{children:[jsx(Loader2,{className:"h-4 w-4 animate-spin"}),"Processing..."]}):jsxs(Fragment,{children:["Pay ",e.toFixed(4)," SOL"]})}),c&&jsx("p",{className:"mt-2 text-center text-xs text-red-500",children:c})]})}function me({result:e,className:t,style:r}){let[s,g]=useState(false),m=useRef(null);useEffect(()=>()=>{m.current&&clearTimeout(m.current);},[]);let f=useCallback(()=>{e.key?.key&&(navigator.clipboard.writeText(e.key.key),g(true),m.current&&clearTimeout(m.current),m.current=setTimeout(()=>g(false),2e3));},[e.key?.key]);return !e.success||!e.key?null:jsxs("div",{className:u("rounded-lg border border-green-500/20 bg-green-500/10 p-6 text-center",t),style:r,children:[jsx(CheckCircle,{className:"mx-auto mb-3 h-12 w-12 text-green-500"}),jsx("h3",{className:"mb-2 text-lg font-semibold text-foreground",children:"Key Generated!"}),jsx("p",{className:"mb-4 text-sm text-muted-foreground",children:"Your node key has been successfully generated."}),jsxs("div",{className:"mx-auto flex max-w-md items-center gap-2 rounded-md border bg-background p-3",children:[jsx("code",{className:"flex-1 truncate text-xs text-foreground",children:e.key.key}),jsx("button",{onClick:f,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",children:s?jsx(Check,{className:"h-4 w-4 text-green-500"}):jsx(Copy,{className:"h-4 w-4"})})]})]})}function $({className:e}){return jsx("div",{className:u("animate-pulse rounded-xl bg-muted",e)})}function fe(){return jsxs("div",{className:"space-y-6",children:[jsxs("div",{className:"px-6 py-10 flex flex-col items-center gap-3",children:[jsx($,{className:"h-14 w-48"}),jsx($,{className:"h-5 w-64"})]}),jsx($,{className:"h-[72px] w-full rounded-2xl"}),jsx($,{className:"h-[68px] w-full rounded-2xl"}),jsx($,{className:"h-[60px] w-full rounded-2xl"})]})}function H({count:e=3}){return jsx("div",{className:"space-y-3",children:Array.from({length:e}).map((t,r)=>jsxs("div",{className:"rounded-xl border p-4 space-y-3",children:[jsxs("div",{className:"flex items-center justify-between",children:[jsx($,{className:"h-4 w-32"}),jsx($,{className:"h-4 w-16"})]}),jsx($,{className:"h-2 w-full rounded-full"}),jsxs("div",{className:"flex justify-between",children:[jsx($,{className:"h-3 w-24"}),jsx($,{className:"h-3 w-20"})]})]},r))})}function St({quantity:e,max:t,onChange:r}){return jsxs("div",{className:"flex items-center justify-between rounded-2xl bg-muted/20 px-6 py-6",children:[jsx("span",{className:"text-sm font-medium text-foreground",children:"Quantity"}),jsxs("div",{className:"flex items-center gap-0 rounded-xl bg-background",children:[jsx("button",{onClick:()=>r(Math.max(1,e-1)),disabled:e<=1,"aria-label":"Decrease quantity",className:"flex h-12 w-12 items-center justify-center rounded-l-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsx(Minus,{className:"h-5 w-5"})}),jsx("span",{className:"flex h-12 w-14 items-center justify-center border-x text-xl font-bold text-foreground","aria-live":"polite",children:e}),jsx("button",{onClick:()=>r(Math.min(t,e+1)),disabled:e>=t,"aria-label":"Increase quantity",className:"flex h-12 w-12 items-center justify-center rounded-r-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsx(Plus,{className:"h-5 w-5"})})]})]})}function De({pricing:e,quantity:t}){let[r,s]=useState(false),g=e.priceUsd*t;return jsxs("div",{className:"rounded-2xl border bg-background",children:[jsxs("button",{onClick:()=>s(!r),"aria-expanded":r,className:"flex w-full items-center justify-between px-6 py-6 text-left",children:[jsxs("span",{className:"text-foreground",children:[jsxs("span",{className:"text-xl font-bold",children:["$",g.toFixed(2)]})," ",jsx("span",{className:"text-sm text-muted-foreground",children:"total fees included"})]}),r?jsx(ChevronUp,{className:"h-5 w-5 text-muted-foreground"}):jsx(ChevronDown,{className:"h-5 w-5 text-muted-foreground"})]}),r&&jsxs("div",{className:"border-t px-6 pb-8 pt-4 space-y-3 text-sm",children:[jsxs("div",{className:"flex justify-between",children:[jsxs("span",{className:"text-muted-foreground",children:["Node Key \xD7 ",t]}),jsxs("span",{className:"text-foreground",children:["$",(e.priceUsd*t).toFixed(2)]})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Keys sold"}),jsx("span",{className:"text-foreground",children:e.keysSold})]}),e.daysUntilHalving>0&&jsxs("div",{className:"flex justify-between text-muted-foreground",children:[jsx("span",{children:"Next refresh"}),jsxs("span",{children:[e.daysUntilHalving," day",e.daysUntilHalving!==1?"s":""]})]}),jsxs("div",{className:"flex justify-between border-t pt-3 font-semibold",children:[jsx("span",{className:"text-foreground",children:"Total"}),jsxs("span",{className:"text-foreground",children:["$",g.toFixed(2)]})]})]})]})}function pe({className:e,style:t}){let{config:r}=C(),{pricing:s,loading:g,error:m,refresh:f}=Be(),{mint:a,minting:n,result:c,error:d}=Ie(),{createSession:p,loading:i,error:o}=Ee(),[l,b]=useState(1),[w,P]=useState(r.paymentMethods?.includes("stripe")?"stripe":"solana"),[T,j]=useState(0),[k,z]=useState(false),_=bt.useRef(l);_.current=l;let K=Math.max(1,r.maxQuantity||5),G=[...r.paymentMethods||["solana"]].sort((B,O)=>B==="stripe"?-1:O==="stripe"?1:0);if(useEffect(()=>{if(typeof window>"u")return;let O=new URLSearchParams(window.location.search).get("session_id");if(!O){try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}return}if(/^cs_(test|live)_/.test(O)&&!k&&!c?.success){let se=false;try{se=sessionStorage.getItem("keyutils_stripe_pending")==="1";}catch{}if(!se)return;try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}z(true);let X=new URL(window.location.href);X.searchParams.delete("session_id"),window.history.replaceState({},"",X.toString()),a("stripe",O,_.current);}},[k,c,a]),c?.success)return jsx("div",{className:u("flex flex-col items-center justify-center",e),style:t,children:jsx(me,{result:c})});if(k||n)return jsx("div",{className:u("flex flex-col",e),style:t,children:jsx(fe,{})});if(g)return jsx("div",{className:u("flex flex-col",e),style:t,children:jsx(fe,{})});if(m||!s)return jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-24",e),style:t,children:[jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load pricing"}),jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m||"Please check your connection and try again."})]}),jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let F=async B=>{j(2),await a(w,B,l);},Z=()=>{p(s.priceCents,l);};return jsx("div",{className:u("flex flex-col",e),style:t,children:jsxs("div",{className:"space-y-6",children:[T===0&&jsxs(Fragment,{children:[r.keyImage&&jsx("img",{src:r.keyImage,alt:"Node Key",className:r.keyImageClass||"w-1/2 mx-auto"}),jsxs("div",{className:"px-6 py-10 text-center",children:[jsxs("p",{className:"text-5xl font-bold tracking-tight text-foreground md:text-6xl",children:["$",s.priceUsd.toFixed(2)]}),jsxs("p",{className:"mt-2 text-base text-muted-foreground",children:["per key \xB7 ",s.tokenAllocationFormatted||I(s.tokenAllocation)," tokens included"]})]}),jsx(St,{quantity:l,max:K,onChange:b}),jsx(De,{pricing:s,quantity:l}),jsx("button",{onClick:()=>j(1),className:"w-full rounded-2xl bg-foreground py-6 text-center text-base font-semibold text-background transition-colors hover:bg-foreground/90",children:"Continue to Payment"})]}),T===1&&jsxs(Fragment,{children:[G.length>1&&jsx("div",{role:"tablist",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:G.map(B=>jsxs("button",{role:"tab","aria-selected":w===B,onClick:()=>P(B),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-4 text-sm font-medium transition-colors",w===B?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:[B==="stripe"?jsx(CreditCard,{className:"h-5 w-5"}):jsx(Wallet,{className:"h-5 w-5"}),B==="stripe"?"Credit Card":"Crypto"]},B))}),jsx(De,{pricing:s,quantity:l}),w==="stripe"?jsxs(Fragment,{children:[jsx("button",{onClick:Z,disabled:i,className:"flex w-full items-center justify-center gap-2 rounded-2xl bg-foreground py-6 text-base font-semibold text-background transition-colors hover:bg-foreground/90 disabled:opacity-50",children:i?jsxs(Fragment,{children:[jsx(Loader2,{className:"h-5 w-5 animate-spin"}),"Redirecting to Stripe..."]}):jsxs(Fragment,{children:[jsx(CreditCard,{className:"h-5 w-5"}),"Pay with Card"]})}),o&&jsx("p",{className:"text-center text-sm text-red-500",children:o})]}):w==="solana"?jsx(ue,{amountSol:s.priceSol??0,onSuccess:F,className:"rounded-2xl py-5 text-base"}):null,d&&jsx("p",{className:"text-center text-sm text-red-500",children:d}),jsx("button",{onClick:()=>j(0),className:"w-full py-3 text-center text-sm text-muted-foreground hover:text-foreground transition-colors",children:"\u2190 Back"})]})]})})}var Ut={ios:"iOS",android:"Android",windows:"Windows",mac:"macOS",linux:"Linux"},Bt=["mac","windows","linux","ios","android"];function ge({downloads:e,className:t,style:r}){let{config:s}=C(),g=useMemo(()=>Te(),[]),m=e||Bt.map(n=>({platform:n,label:Ut[n],url:"#",compatible:n===g})),f=m.find(n=>n.compatible)||m[0],a=m.filter(n=>n.platform!==f.platform);return jsxs("div",{className:u("space-y-8",t),style:r,children:[jsxs("div",{className:"flex flex-col items-center gap-6 pt-4 mt-4",children:[s.aispImage&&jsx("img",{src:s.aispImage,alt:"aiSP",className:"w-full sm:w-1/2 mx-auto px-4 sm:px-0"}),jsxs("div",{className:"text-center",children:[jsx("p",{className:"text-lg sm:text-2xl font-medium text-foreground",children:"Download the AI Service Provider App"}),jsx("p",{className:"mt-1 text-sm sm:text-base text-muted-foreground",children:"Load your keys and run your node."})]}),jsxs("a",{href:f.url,className:"inline-flex items-center gap-3 rounded-full px-10 py-4 text-lg font-semibold text-white transition-colors hover:opacity-90",style:{backgroundColor:"#0900f4"},children:[jsx(Download,{className:"h-5 w-5"}),"Get aiSP for ",f.label]})]}),jsxs("p",{className:"text-center text-sm text-muted-foreground",children:["aiSP is also available on"," ",a.map((n,c)=>jsxs(bt.Fragment,{children:[c>0&&(c===a.length-1?" and ":", "),jsx("a",{href:n.url,className:"font-medium underline transition-colors hover:text-foreground",style:{color:"#066bff"},children:n.label})]},n.platform)),"."]}),jsxs("div",{className:"flex flex-col items-center gap-2 mt-12",children:[jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["Source code is available on",jsx("a",{href:"https://github.com/stack-net",target:"_blank",rel:"noopener noreferrer",className:"text-foreground underline hover:text-foreground/80 color-[#0900f4]",children:"Github"})]}),jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["By downloading, you agree to the",jsx("a",{href:s.termsUrl||"/terms",className:"text-foreground underline hover:text-foreground/80",children:"Open Source Applications Terms"})]})]})]})}function jt(e){return {id:e.id||"",keyIndex:e.keyIndex??e.key_index??null,key:e.key||e.keyPrefix||"",userId:e.userId||e.user_id||"",status:e.status||"active",tokenBalance:e.tokenBalance??e.currentTokenBalance??e.current_token_balance??0,maxTokens:e.maxTokens??e.initialTokenBalance??e.initial_token_balance??0,createdAt:String(e.createdAt??e.created_at??""),expiresAt:e.expiresAt,label:e.label||e.keyPrefix||e.key_prefix||void 0,paperWork:e.paperWork||e.paper_work||void 0,stackId:e.stackId,stackName:e.stackName}}function J(){let{config:e}=C(),[t,r]=useState([]),[s,g]=useState(true),[m,f]=useState(null),a=useRef(true),n=e.apiBaseUrl,c=useCallback(async()=>{try{g(!0),f(null);let p=await fetch(`${n}/api/keys`,{credentials:"include"});if(!p.ok){let l=`Failed to fetch keys (${p.status})`;try{let b=await p.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let i=await p.json(),o=Array.isArray(i)?i:i.keys??[];a.current&&r(o.map(jt));}catch(p){a.current&&f(p instanceof Error?p.message:"Failed to fetch keys");}finally{a.current&&g(false);}},[n]);useEffect(()=>(a.current=true,c(),()=>{a.current=false;}),[c]);let d=t.reduce((p,i)=>p+i.tokenBalance,0);return {keys:t,totalBalance:d,loading:s,error:m,refresh:c}}function We(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[g,m]=useState(null),[f,a]=useState(null),n=useRef(true),c=useCallback(async(p,i)=>{try{s(!0),a(null);let o=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({askPriceCents:i,stackId:e.stackId,stackName:e.stackName})});if(!o.ok){let b=`Listing failed (${o.status})`;try{let w=await o.json();w.error&&(b=w.error);}catch{}throw new Error(b)}let l=await o.json();return n.current&&(m(l),t.onListingCreated?.(l)),l}catch(o){let l=o instanceof Error?o.message:"Listing failed";return n.current&&a(l),null}finally{n.current&&s(false);}},[e.apiBaseUrl,e.stackId,e.stackName,t]),d=useCallback(async p=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"DELETE",headers:{...A()},credentials:"include"});if(!i.ok){let o=`Delist failed (${i.status})`;try{let l=await i.json();l.error&&(o=l.error);}catch{}throw new Error(o)}return n.current&&m(null),!0}catch(i){let o=i instanceof Error?i.message:"Delist failed";return n.current&&a(o),false}finally{n.current&&s(false);}},[e.apiBaseUrl]);return {listKey:c,delistKey:d,listing:r,result:g,error:f}}function q({current:e,max:t,className:r,style:s,showLabel:g=true}){let m=Ke(e,t),f=Re(m);return jsxs("div",{className:u("w-full",r),style:s,children:[g&&jsxs("div",{className:"mb-1 flex items-center justify-between text-xs text-muted-foreground",children:[jsxs("span",{children:[I(e)," / ",I(t)]}),jsxs("span",{children:[m,"%"]})]}),jsx("div",{className:"h-2 w-full overflow-hidden rounded-full bg-muted",children:jsx("div",{className:u("h-full rounded-full transition-all duration-500",f),style:{width:`${m}%`}})})]})}function $t({nodeKey:e,selected:t,onSelect:r}){return jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsx(Check,{className:"h-3 w-3 text-background"})}),jsxs("div",{className:"min-w-0 flex-1",children:[jsxs("div",{className:"flex items-center justify-between",children:[jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsx("span",{className:u("text-xs font-medium capitalize",e.status==="active"?"text-green-500":"text-muted-foreground"),children:e.status})]}),jsx(q,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function he({className:e,style:t}){let{config:r}=C(),{keys:s,loading:g,error:m,refresh:f}=J(),{listKey:a,listing:n,result:c,error:d}=We(),[p,i]=useState(null),[o,l]=useState(""),[b,w]=useState(false),P=s.find(K=>K.id===p),T=parseInt(o.replace(/[^0-9]/g,""),10)||0,j=T>0&&Number.isFinite(T),k=!!P&&j&&b&&!n,z=async()=>{if(!k||!P)return;let K=T*100;await a(P.id,K)&&f();};if(c)return jsxs("div",{className:u("flex flex-col items-center gap-4 rounded-xl bg-green-500/10 py-12",e),style:t,children:[jsx(CheckCircle,{className:"h-12 w-12 text-green-500"}),jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Key Listed!"}),jsx("p",{className:"text-sm text-muted-foreground",children:"Your key is now on the Global Open AI Network marketplace."}),jsxs("p",{className:"text-xs text-muted-foreground",children:["Listing ID: ",jsx("code",{children:c.listingId})]}),jsxs("a",{href:`https://market.stacknet.org/keys/${c.keyId}`,target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-2 rounded-xl bg-foreground px-6 py-3 text-sm font-semibold text-background transition-colors hover:bg-foreground/90",children:[jsx(ExternalLink,{className:"h-4 w-4"}),"View Listing"]})]});if(g)return jsxs("div",{className:u("space-y-5 px-1",e),style:t,children:[jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsx(H,{count:2})]});if(m)return jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-16",e),style:t,children:[jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m})]}),jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let _=s.filter(K=>K.status==="active");return _.length===0?jsxs("div",{className:u("flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed py-16",e),style:t,children:[jsx(AlertTriangle,{className:"h-8 w-8 text-muted-foreground"}),jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys to sell."})]}):jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxs("div",{children:[jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsx("div",{className:"space-y-2",children:_.map(K=>jsx($t,{nodeKey:K,selected:p===K.id,onSelect:()=>i(K.id)},K.id))})]}),P&&jsxs("div",{className:"rounded-xl border bg-muted/30 p-5 space-y-2 text-sm",children:[P.keyIndex&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key #"}),jsxs("span",{className:"text-foreground font-semibold",children:["#",P.keyIndex]})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key ID"}),jsx("code",{className:"text-xs text-foreground",children:P.id})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Originating Stack"}),jsx("span",{className:"text-foreground",children:r.stackName||"Unknown"})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Tokens (remaining / total)"}),jsxs("span",{className:"text-foreground",children:[I(P.tokenBalance)," / ",I(P.maxTokens)]})]}),P.paperWork&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Paper earned"}),jsx("span",{className:"text-foreground",children:P.paperWork})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Created"}),jsx("span",{className:"text-foreground",children:Y(P.createdAt)})]})]}),jsxs("div",{children:[jsx("label",{htmlFor:"listing-price",className:"mb-2 block text-sm sm:text-lg font-semibold text-foreground",children:"Listing Price (USD)"}),jsxs("div",{className:"relative",children:[jsx("span",{className:"absolute left-4 top-1/2 -translate-y-1/2 text-2xl font-bold text-muted-foreground",children:"$"}),jsx("input",{id:"listing-price",type:"text",inputMode:"numeric",value:o,onChange:K=>{let G=K.target.value.replace(/[^0-9]/g,""),F=parseInt(G,10);l(isNaN(F)?"":F.toLocaleString("en-US"));},placeholder:"0",className:"w-full rounded-xl border bg-background py-6 pl-10 pr-4 text-3xl font-bold text-foreground placeholder:text-muted-foreground/30 focus:outline-none focus:ring-2 focus:ring-foreground/20"})]})]}),jsxs("div",{className:"flex items-start gap-3",children:[jsx("button",{type:"button",role:"checkbox","aria-checked":b,onClick:()=>w(!b),className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded border-2 transition-colors cursor-pointer",b?"border-foreground bg-foreground":"border-muted-foreground/40"),children:b&&jsx(Check,{className:"h-3 w-3 text-background"})}),jsxs("span",{className:"text-xs text-muted-foreground leading-relaxed",children:["I agree to list this key on the Global Open AI Network marketplace. The key will be deactivated upon sale and transferred to the buyer. Listing fees may apply."," ",jsx("a",{href:r.termsUrl||"/terms",className:"text-foreground underline",target:"_blank",rel:"noopener noreferrer",children:"Terms"})]})]}),d&&jsx("p",{className:"text-sm text-red-500",children:d}),jsxs("button",{onClick:z,disabled:!k,className:u("flex w-full items-center justify-center gap-2 rounded-xl py-4 text-sm font-semibold transition-colors",k?"bg-foreground text-background hover:bg-foreground/90":"bg-muted text-muted-foreground cursor-not-allowed"),children:[jsx(ExternalLink,{className:"h-4 w-4"}),n?"Listing...":"List on Marketplace"]})]})}function Ve(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[g,m]=useState(null),[f,a]=useState(null),n=useRef(true);return {transferKey:useCallback(async(d,p)=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${d}/transfer`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({recipientId:p})});if(!i.ok){let l=`Transfer failed (${i.status})`;try{let b=await i.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let o=await i.json();return n.current&&(m(o),t.onTransferComplete?.(o)),o}catch(i){let o=i instanceof Error?i.message:"Transfer failed";return n.current&&a(o),null}finally{n.current&&s(false);}},[e.apiBaseUrl,t]),transferring:r,result:g,error:f}}function Vt({nodeKey:e,selected:t,onSelect:r}){return jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsx(Check,{className:"h-3 w-3 text-background"})}),jsxs("div",{className:"min-w-0 flex-1",children:[jsxs("div",{className:"flex items-center justify-between",children:[jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsx("span",{className:"text-xs font-medium capitalize text-green-500",children:e.status})]}),jsx(q,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function ke({className:e,style:t}){let{keys:r,loading:s}=J(),{transferKey:g,transferring:m,result:f,error:a}=Ve(),[n,c]=useState(null),[d,p]=useState(""),[i,o]=useState(false),l=r.filter(k=>k.status==="active"),b=l.find(k=>k.id===n),w=b&&d.trim()===b.userId,P=n&&d.trim().length>0&&i&&!w&&!m,T=async()=>{!n||!d.trim()||await g(n,d.trim());},j=()=>{c(null),p(""),o(false);};return f?jsxs("div",{className:u("flex flex-col items-center gap-4 py-8",e),style:t,children:[jsx(CheckCircle,{className:"h-12 w-12 text-green-500"}),jsxs("div",{className:"text-center",children:[jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Transfer Complete"}),jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"Key transferred successfully"})]}),jsxs("div",{className:"w-full max-w-sm space-y-2 rounded-xl border border-border bg-muted/30 p-4 text-sm",children:[jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key"}),jsxs("span",{className:"font-mono text-foreground",children:[f.keyId.slice(0,20),"..."]})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Recipient"}),jsxs("span",{className:"font-mono text-foreground",children:[f.toUserId.slice(0,20),"..."]})]})]}),jsx("button",{onClick:j,className:"mt-2 rounded-lg border border-border px-4 py-2 text-sm font-medium text-foreground hover:bg-muted/50 transition-colors",children:"Transfer Another"})]}):jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxs("div",{children:[jsx("h3",{className:"mb-3 text-sm font-medium text-foreground",children:"Select Key to Transfer"}),s?jsx(H,{count:2}):l.length===0?jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys available for transfer."}):jsx("div",{className:"space-y-2",children:l.map(k=>jsx(Vt,{nodeKey:k,selected:n===k.id,onSelect:()=>c(k.id)},k.id))})]}),n&&jsxs("div",{children:[jsx("label",{className:"mb-1.5 block text-sm font-medium text-foreground",children:"Recipient User ID"}),jsx("input",{type:"text",value:d,onChange:k=>{p(k.target.value),o(false);},placeholder:"Enter recipient's user ID or global ID",className:"w-full rounded-lg border border-border bg-background px-3 py-2.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-foreground/30 focus:outline-none focus:ring-1 focus:ring-foreground/10"}),w&&jsx("p",{className:"mt-1.5 text-xs text-red-500",children:"Cannot transfer a key to yourself"})]}),b&&d.trim().length>0&&!w&&jsx("div",{className:"rounded-xl border border-amber-500/30 bg-amber-500/5 p-4",children:jsxs("div",{className:"flex items-start gap-3",children:[jsx(AlertTriangle,{className:"mt-0.5 h-5 w-5 shrink-0 text-amber-500"}),jsxs("div",{className:"space-y-3",children:[jsxs("div",{children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Confirm Transfer"}),jsxs("p",{className:"mt-1 text-xs text-muted-foreground",children:["You are about to transfer key"," ",jsx("span",{className:"font-mono font-medium",children:b.keyIndex?`#${b.keyIndex}`:b.id.slice(0,12)})," ","(",I(b.tokenBalance)," tokens) to"," ",jsxs("span",{className:"font-mono font-medium",children:[d.trim().slice(0,20),"..."]})]})]}),jsxs("label",{className:"flex items-start gap-2 cursor-pointer",children:[jsx("input",{type:"checkbox",checked:i,onChange:k=>o(k.target.checked),className:"mt-0.5 h-4 w-4 rounded border-border"}),jsx("span",{className:"text-xs text-muted-foreground",children:"I confirm this transfer is permanent and cannot be undone."})]})]})]})}),a&&jsx("p",{className:"text-sm text-red-500",children:a}),jsx("button",{onClick:T,disabled:!P,className:u("flex w-full items-center justify-center gap-2 rounded-lg px-4 py-3 text-sm font-medium transition-all",P?"bg-foreground text-background hover:opacity-90":"bg-muted text-muted-foreground cursor-not-allowed"),children:m?jsxs(Fragment,{children:[jsx("div",{className:"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent"}),"Transferring..."]}):jsxs(Fragment,{children:[jsx(Send,{className:"h-4 w-4"}),"Transfer Key"]})})]})}var zt=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"},{id:"transfer",label:"Transfer"}];function Yt({active:e,onChange:t}){return jsx("div",{role:"tablist","aria-label":"Key actions",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:zt.map(({id:r,label:s})=>jsx("button",{role:"tab","aria-selected":e===r,"aria-controls":`panel-${r}`,id:`tab-${r}`,onClick:()=>t(r),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium transition-all",e===r?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:jsx("span",{className:"inline",children:s})},r))})}function Ht({defaultTab:e="buy",className:t,style:r}){let[s,g]=useState(e);return jsxs("div",{className:u("flex flex-col",t),style:r,children:[jsx("div",{className:"sticky top-0 z-10 bg-background/80 px-5 pb-3 pt-2 sm:pt-5 backdrop-blur-sm sm:px-10 md:px-16 lg:px-20",children:jsx("div",{className:"mx-auto max-w-xl",children:jsx(Yt,{active:s,onChange:g})})}),jsx("div",{className:"flex flex-1 flex-col px-5 pb-8 sm:px-10 md:px-16 md:pb-12 lg:px-20",children:jsx("div",{className:"mx-auto w-full max-w-xl flex-1",children:jsxs("div",{role:"tabpanel",id:`panel-${s}`,"aria-labelledby":`tab-${s}`,children:[s==="buy"&&jsx(pe,{className:"flex-1"}),s==="use"&&jsx(ge,{className:"flex-1"}),s==="sell"&&jsx(he,{className:"flex-1"}),s==="transfer"&&jsx(ke,{className:"flex-1"})]})})})]})}function Jt({apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:g,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p,onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P,defaultTab:T,className:j,style:k}){return jsx(ae,{config:{apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:g,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p},callbacks:{onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P},children:jsx(Ht,{defaultTab:T,className:j,style:k})})}function Ye(e){let{config:t}=C(),[r,s]=useState([]),[g,m]=useState(false),[f,a]=useState(null),n=useRef(true),c=t.apiBaseUrl,d=useCallback(async()=>{if(e)try{m(!0),a(null);let p=await fetch(`${c}/api/keys/${e}/ledger`,{credentials:"include"});if(!p.ok){let o=`Failed to fetch ledger (${p.status})`;try{let l=await p.json();l.error&&(o=l.error);}catch{}throw new Error(o)}let i=await p.json();n.current&&s(Array.isArray(i)?i:i.entries??[]);}catch(p){n.current&&a(p instanceof Error?p.message:"Failed to fetch ledger");}finally{n.current&&m(false);}},[c,e]);return useEffect(()=>(n.current=true,d(),()=>{n.current=false;}),[d]),{entries:r,loading:g,error:f,refresh:d}}var Pe=20;function Ce({nodeKey:e,className:t,style:r}){let[s,g]=useState(false),[m,f]=useState(false),a=useRef(null),{entries:n,loading:c}=Ye(s?e.id:null);useEffect(()=>()=>{a.current&&clearTimeout(a.current);},[]);let d=useCallback(()=>{e.key&&(navigator.clipboard.writeText(e.key),f(true),a.current&&clearTimeout(a.current),a.current=setTimeout(()=>f(false),2e3));},[e.key]),p=e.status==="active"?"text-green-500":e.status==="expired"?"text-red-500":"text-yellow-500",i=n.slice(0,Pe);return jsxs("div",{className:u("rounded-lg border bg-background",t),style:r,children:[jsxs("div",{className:"p-4",children:[jsxs("div",{className:"mb-3 flex items-center justify-between",children:[jsxs("div",{className:"flex items-center gap-2",children:[jsx("button",{onClick:()=>g(!s),"aria-expanded":s,"aria-label":s?"Collapse ledger":"Expand ledger",className:"text-muted-foreground hover:text-foreground",children:s?jsx(ChevronDown,{className:"h-4 w-4"}):jsx(ChevronRight,{className:"h-4 w-4"})}),jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]})]}),jsx("span",{className:u("text-xs font-medium capitalize",p),children:e.status})]}),e.key&&jsxs("div",{className:"mb-3 flex items-center gap-2",children:[jsx("code",{className:"flex-1 truncate rounded bg-muted px-2 py-1 text-xs text-muted-foreground",children:e.key}),jsx("button",{onClick:d,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground",children:m?jsx(Check,{className:"h-3.5 w-3.5 text-green-500"}):jsx(Copy,{className:"h-3.5 w-3.5"})})]}),jsx(q,{current:e.tokenBalance,max:e.maxTokens}),jsxs("div",{className:"mt-2 flex items-center justify-between text-xs text-muted-foreground",children:[jsxs("span",{children:["Created ",Y(e.createdAt)]}),e.expiresAt&&jsxs("span",{children:["Expires ",Y(e.expiresAt)]})]})]}),s&&jsxs("div",{className:"border-t px-4 py-3",children:[jsx("h4",{className:"mb-2 text-xs font-medium text-muted-foreground",children:"Ledger"}),c?jsx("p",{className:"text-xs text-muted-foreground",children:"Loading..."}):i.length===0?jsx("p",{className:"text-xs text-muted-foreground",children:"No ledger entries."}):jsxs("div",{className:"space-y-1.5",children:[i.map(o=>jsxs("div",{className:"flex items-center justify-between text-xs",children:[jsxs("div",{className:"flex items-center gap-2",children:[jsxs("span",{className:u("font-medium",o.type==="credit"||o.type==="reward"?"text-green-500":"text-red-500"),children:[o.type==="credit"||o.type==="reward"?"+":"-",I(Math.abs(o.amount))]}),jsx("span",{className:"text-muted-foreground",children:o.description})]}),jsx("span",{className:"text-muted-foreground",children:Y(o.createdAt)})]},o.id)),n.length>Pe&&jsxs("p",{className:"pt-1 text-xs text-muted-foreground",children:["Showing ",Pe," of ",n.length," entries"]})]})]})]})}var cr=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"}];function oe({baseHref:e}){return jsx("div",{className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5 mb-6",children:cr.map(({id:t,label:r})=>jsx("a",{href:`${e}?tab=${t}`,className:"flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium text-muted-foreground hover:text-foreground transition-all",children:r},t))})}function dr({getKeyHref:e="/keys/get",showTabs:t=true,className:r,style:s}){let{keys:g,totalBalance:m,loading:f,error:a,refresh:n}=J();return f?jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(oe,{baseHref:e}),jsx(H,{count:3})]}):a?jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(oe,{baseHref:e}),jsxs("div",{className:"flex flex-col items-center justify-center gap-4 py-12",children:[jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:a})]}),jsx("button",{onClick:()=>n(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]})]}):g.length===0?jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(oe,{baseHref:e}),jsxs("div",{className:"flex flex-col items-center justify-center gap-4 rounded-lg border border-dashed py-12",children:[jsx(KeyRound,{className:"h-10 w-10 text-muted-foreground"}),jsxs("div",{className:"text-center",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"No keys yet"}),jsx("p",{className:"text-xs text-muted-foreground",children:"Get your first node key to start earning."})]}),e&&jsx("a",{href:e,className:"rounded-lg bg-foreground px-4 py-2 text-sm font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]})]}):jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(oe,{baseHref:e}),jsxs("div",{className:"flex items-center justify-between",children:[jsxs("p",{className:"text-sm text-muted-foreground",children:[g.length," key",g.length!==1?"s":""," \xB7 Total balance: ",I(m)]}),e&&jsx("a",{href:e,className:"rounded-md bg-foreground px-3 py-1.5 text-xs font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]}),g.map(c=>jsx(Ce,{nodeKey:c},c.id))]})}
2
+ export{Jt as BuyKeyWidget,pe as BuyPanel,q as KeyBalanceBar,Ce as KeyCard,dr as KeyList,ae as KeyUtilsProvider,me as MintSuccess,he as SellPanel,ue as SolanaPayButton,ke as TransferPanel,ge as UsePanel,C as useKeyUtilsContext};
@@ -1 +1 @@
1
- 'use strict';var react=require('react');require('react/jsx-runtime');var L=react.createContext(null);function d(){let e=react.useContext(L);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function S(){let{config:e}=d(),[c,g]=react.useState(null),[u,f]=react.useState(true),[y,m]=react.useState(null),s=react.useRef(true),a=react.useRef(e.apiBaseUrl);a.current=e.apiBaseUrl;let l=async()=>{try{s.current&&(f(!0),m(null));let i=await fetch(`${a.current}/api/keys/pricing`);if(!i.ok){let t=`Pricing unavailable (${i.status})`;try{let r=await i.json();r.error&&(t=r.error);}catch{}throw new Error(t)}let n=await i.json();s.current&&g(n);}catch(i){s.current&&m(i instanceof Error?i.message:"Failed to fetch pricing");}finally{s.current&&f(false);}};return react.useEffect(()=>{s.current=true,l();let i=setInterval(l,6e4);return ()=>{s.current=false,clearInterval(i);}},[]),{pricing:c,loading:u,error:y,refresh:l}}function M(e){return {id:e.id||"",keyIndex:e.keyIndex??e.key_index??null,key:e.key||e.keyPrefix||"",userId:e.userId||e.user_id||"",status:e.status||"active",tokenBalance:e.tokenBalance??e.currentTokenBalance??e.current_token_balance??0,maxTokens:e.maxTokens??e.initialTokenBalance??e.initial_token_balance??0,createdAt:String(e.createdAt??e.created_at??""),expiresAt:e.expiresAt,label:e.label||e.keyPrefix||e.key_prefix||void 0,paperWork:e.paperWork||e.paper_work||void 0,stackId:e.stackId,stackName:e.stackName}}function N(){let{config:e}=d(),[c,g]=react.useState([]),[u,f]=react.useState(true),[y,m]=react.useState(null),s=react.useRef(true),a=e.apiBaseUrl,l=react.useCallback(async()=>{try{f(!0),m(null);let n=await fetch(`${a}/api/keys`);if(!n.ok){let o=`Failed to fetch keys (${n.status})`;try{let p=await n.json();p.error&&(o=p.error);}catch{}throw new Error(o)}let t=await n.json(),r=Array.isArray(t)?t:t.keys??[];s.current&&g(r.map(M));}catch(n){s.current&&m(n instanceof Error?n.message:"Failed to fetch keys");}finally{s.current&&f(false);}},[a]);react.useEffect(()=>(s.current=true,l(),()=>{s.current=false;}),[l]);let i=c.reduce((n,t)=>n+t.tokenBalance,0);return {keys:c,totalBalance:i,loading:u,error:y,refresh:l}}function O(e){let{config:c}=d(),[g,u]=react.useState([]),[f,y]=react.useState(false),[m,s]=react.useState(null),a=react.useRef(true),l=c.apiBaseUrl,i=react.useCallback(async()=>{if(e)try{y(!0),s(null);let n=await fetch(`${l}/api/keys/${e}/ledger`);if(!n.ok){let r=`Failed to fetch ledger (${n.status})`;try{let o=await n.json();o.error&&(r=o.error);}catch{}throw new Error(r)}let t=await n.json();a.current&&u(Array.isArray(t)?t:t.entries??[]);}catch(n){a.current&&s(n instanceof Error?n.message:"Failed to fetch ledger");}finally{a.current&&y(false);}},[l,e]);return react.useEffect(()=>(a.current=true,i(),()=>{a.current=false;}),[i]),{entries:g,loading:f,error:m,refresh:i}}function J(){let{config:e,callbacks:c}=d(),[g,u]=react.useState(false),[f,y]=react.useState(null),[m,s]=react.useState(null);return {mint:react.useCallback(async(l,i,n=1)=>{try{u(!0),s(null),c.onPaymentComplete?.(l,i);let t=await fetch(`${e.apiBaseUrl}/api/keys/mint`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({paymentMethod:l,paymentRef:i,quantity:n})});if(!t.ok){let k="Key generation failed";try{let C=await t.json();C.error&&(k=C.error);}catch{}throw new Error(k)}let r=await t.json(),o=r.keys?.[0]||r,p={success:!0,key:{id:o.keyId||o.id||"",key:o.key||"",userId:o.userId||"",status:"active",tokenBalance:o.tokenBalance??o.currentTokenBalance??0,maxTokens:o.initialTokenBalance??o.tokenBalance??0,createdAt:String(o.createdAt||Date.now())},transactionId:i};return y(p),c.onMintSuccess?.(p),p}catch(t){let r=t instanceof Error?t:new Error("Key generation failed");return s(r.message),c.onMintError?.(r),{success:false,error:r.message}}finally{u(false);}},[e.apiBaseUrl,c]),minting:g,result:f,error:m}}function q(){let{config:e,callbacks:c}=d(),[g,u]=react.useState(false),[f,y]=react.useState(null),[m,s]=react.useState(null),a=react.useRef(true),l=react.useCallback(async(n,t)=>{try{u(!0),s(null);let r=await fetch(`${e.apiBaseUrl}/api/keys/${n}/list`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({askPriceCents:t,stackId:e.stackId,stackName:e.stackName})});if(!r.ok){let p=`Listing failed (${r.status})`;try{let k=await r.json();k.error&&(p=k.error);}catch{}throw new Error(p)}let o=await r.json();return a.current&&(y(o),c.onListingCreated?.(o)),o}catch(r){let o=r instanceof Error?r.message:"Listing failed";return a.current&&s(o),null}finally{a.current&&u(false);}},[e.apiBaseUrl,e.stackId,e.stackName,c]),i=react.useCallback(async n=>{try{u(!0),s(null);let t=await fetch(`${e.apiBaseUrl}/api/keys/${n}/list`,{method:"DELETE"});if(!t.ok){let r=`Delist failed (${t.status})`;try{let o=await t.json();o.error&&(r=o.error);}catch{}throw new Error(r)}return a.current&&y(null),!0}catch(t){let r=t instanceof Error?t.message:"Delist failed";return a.current&&s(r),false}finally{a.current&&u(false);}},[e.apiBaseUrl]);return {listKey:l,delistKey:i,listing:g,result:f,error:m}}function G(){let{config:e}=d(),[c,g]=react.useState(false),[u,f]=react.useState(null),y=react.useRef(true);return {createSession:react.useCallback(async(s,a)=>{try{g(!0),f(null);let l=await fetch(`${e.apiBaseUrl}/api/keys/stripe-session`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({priceCents:s,quantity:a,stackId:e.stackId,referrerUrl:window.location.href})});if(!l.ok){let n=`Checkout failed (${l.status})`;try{let t=await l.json();t.error&&(n=t.error);}catch{}throw new Error(n)}let{url:i}=await l.json();if(i){try{sessionStorage.setItem("keyutils_stripe_pending","1");}catch{}window.location.href=i;}else throw new Error("No checkout URL returned")}catch(l){if(y.current){let i=l instanceof Error?l.message:"Checkout failed";f(i),g(false);}}},[e.apiBaseUrl,e.stackId]),loading:c,error:u}}function X(){let{config:e,callbacks:c}=d(),[g,u]=react.useState(false),[f,y]=react.useState(null),[m,s]=react.useState(null),a=react.useRef(true);return {transferKey:react.useCallback(async(i,n)=>{try{u(!0),s(null);let t=await fetch(`${e.apiBaseUrl}/api/keys/${i}/transfer`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({recipientId:n})});if(!t.ok){let o=`Transfer failed (${t.status})`;try{let p=await t.json();p.error&&(o=p.error);}catch{}throw new Error(o)}let r=await t.json();return a.current&&(y(r),c.onTransferComplete?.(r)),r}catch(t){let r=t instanceof Error?t.message:"Transfer failed";return a.current&&s(r),null}finally{a.current&&u(false);}},[e.apiBaseUrl,c]),transferring:g,result:f,error:m}}exports.useKeyLedger=O;exports.useKeys=N;exports.useListKey=q;exports.useMintKey=J;exports.usePricing=S;exports.useStripeCheckout=G;exports.useTransferKey=X;
1
+ 'use strict';var react=require('react');require('react/jsx-runtime');var I=react.createContext(null);function g(){let e=react.useContext(I);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function $(){let{config:e}=g(),[c,d]=react.useState(null),[u,f]=react.useState(true),[y,m]=react.useState(null),s=react.useRef(true),a=react.useRef(e.apiBaseUrl);a.current=e.apiBaseUrl;let l=async()=>{try{s.current&&(f(!0),m(null));let i=await fetch(`${a.current}/api/keys/pricing`,{credentials:"include"});if(!i.ok){let t=`Pricing unavailable (${i.status})`;try{let r=await i.json();r.error&&(t=r.error);}catch{}throw new Error(t)}let n=await i.json();s.current&&d(n);}catch(i){s.current&&m(i instanceof Error?i.message:"Failed to fetch pricing");}finally{s.current&&f(false);}};return react.useEffect(()=>{s.current=true,l();let i=setInterval(l,6e4);return ()=>{s.current=false,clearInterval(i);}},[]),{pricing:c,loading:u,error:y,refresh:l}}function N(e){return {id:e.id||"",keyIndex:e.keyIndex??e.key_index??null,key:e.key||e.keyPrefix||"",userId:e.userId||e.user_id||"",status:e.status||"active",tokenBalance:e.tokenBalance??e.currentTokenBalance??e.current_token_balance??0,maxTokens:e.maxTokens??e.initialTokenBalance??e.initial_token_balance??0,createdAt:String(e.createdAt??e.created_at??""),expiresAt:e.expiresAt,label:e.label||e.keyPrefix||e.key_prefix||void 0,paperWork:e.paperWork||e.paper_work||void 0,stackId:e.stackId,stackName:e.stackName}}function _(){let{config:e}=g(),[c,d]=react.useState([]),[u,f]=react.useState(true),[y,m]=react.useState(null),s=react.useRef(true),a=e.apiBaseUrl,l=react.useCallback(async()=>{try{f(!0),m(null);let n=await fetch(`${a}/api/keys`,{credentials:"include"});if(!n.ok){let o=`Failed to fetch keys (${n.status})`;try{let p=await n.json();p.error&&(o=p.error);}catch{}throw new Error(o)}let t=await n.json(),r=Array.isArray(t)?t:t.keys??[];s.current&&d(r.map(N));}catch(n){s.current&&m(n instanceof Error?n.message:"Failed to fetch keys");}finally{s.current&&f(false);}},[a]);react.useEffect(()=>(s.current=true,l(),()=>{s.current=false;}),[l]);let i=c.reduce((n,t)=>n+t.tokenBalance,0);return {keys:c,totalBalance:i,loading:u,error:y,refresh:l}}function F(e){let{config:c}=g(),[d,u]=react.useState([]),[f,y]=react.useState(false),[m,s]=react.useState(null),a=react.useRef(true),l=c.apiBaseUrl,i=react.useCallback(async()=>{if(e)try{y(!0),s(null);let n=await fetch(`${l}/api/keys/${e}/ledger`,{credentials:"include"});if(!n.ok){let r=`Failed to fetch ledger (${n.status})`;try{let o=await n.json();o.error&&(r=o.error);}catch{}throw new Error(r)}let t=await n.json();a.current&&u(Array.isArray(t)?t:t.entries??[]);}catch(n){a.current&&s(n instanceof Error?n.message:"Failed to fetch ledger");}finally{a.current&&y(false);}},[l,e]);return react.useEffect(()=>(a.current=true,i(),()=>{a.current=false;}),[i]),{entries:d,loading:f,error:m,refresh:i}}function k(){if(typeof document>"u")return {};let e=document.cookie.match(/(?:^|;\s*)__csrf=([^;]*)/);return e?{"x-csrf-token":e[1]}:{}}function J(){let{config:e,callbacks:c}=g(),[d,u]=react.useState(false),[f,y]=react.useState(null),[m,s]=react.useState(null);return {mint:react.useCallback(async(l,i,n=1)=>{try{u(!0),s(null),c.onPaymentComplete?.(l,i);let t=await fetch(`${e.apiBaseUrl}/api/keys/mint`,{method:"POST",headers:{"Content-Type":"application/json",...k()},credentials:"include",body:JSON.stringify({paymentMethod:l,paymentRef:i,quantity:n})});if(!t.ok){let h="Key generation failed";try{let P=await t.json();P.error&&(h=P.error);}catch{}throw new Error(h)}let r=await t.json(),o=r.keys?.[0]||r,p={success:!0,key:{id:o.keyId||o.id||"",key:o.key||"",userId:o.userId||"",status:"active",tokenBalance:o.tokenBalance??o.currentTokenBalance??0,maxTokens:o.initialTokenBalance??o.tokenBalance??0,createdAt:String(o.createdAt||Date.now())},transactionId:i};return y(p),c.onMintSuccess?.(p),p}catch(t){let r=t instanceof Error?t:new Error("Key generation failed");return s(r.message),c.onMintError?.(r),{success:false,error:r.message}}finally{u(false);}},[e.apiBaseUrl,c]),minting:d,result:f,error:m}}function q(){let{config:e,callbacks:c}=g(),[d,u]=react.useState(false),[f,y]=react.useState(null),[m,s]=react.useState(null),a=react.useRef(true),l=react.useCallback(async(n,t)=>{try{u(!0),s(null);let r=await fetch(`${e.apiBaseUrl}/api/keys/${n}/list`,{method:"POST",headers:{"Content-Type":"application/json",...k()},credentials:"include",body:JSON.stringify({askPriceCents:t,stackId:e.stackId,stackName:e.stackName})});if(!r.ok){let p=`Listing failed (${r.status})`;try{let h=await r.json();h.error&&(p=h.error);}catch{}throw new Error(p)}let o=await r.json();return a.current&&(y(o),c.onListingCreated?.(o)),o}catch(r){let o=r instanceof Error?r.message:"Listing failed";return a.current&&s(o),null}finally{a.current&&u(false);}},[e.apiBaseUrl,e.stackId,e.stackName,c]),i=react.useCallback(async n=>{try{u(!0),s(null);let t=await fetch(`${e.apiBaseUrl}/api/keys/${n}/list`,{method:"DELETE",headers:{...k()},credentials:"include"});if(!t.ok){let r=`Delist failed (${t.status})`;try{let o=await t.json();o.error&&(r=o.error);}catch{}throw new Error(r)}return a.current&&y(null),!0}catch(t){let r=t instanceof Error?t.message:"Delist failed";return a.current&&s(r),false}finally{a.current&&u(false);}},[e.apiBaseUrl]);return {listKey:l,delistKey:i,listing:d,result:f,error:m}}function G(){let{config:e}=g(),[c,d]=react.useState(false),[u,f]=react.useState(null),y=react.useRef(true);return {createSession:react.useCallback(async(s,a)=>{try{d(!0),f(null);let l=await fetch(`${e.apiBaseUrl}/api/keys/stripe-session`,{method:"POST",headers:{"Content-Type":"application/json",...k()},credentials:"include",body:JSON.stringify({priceCents:s,quantity:a,stackId:e.stackId,referrerUrl:window.location.href})});if(!l.ok){let n=`Checkout failed (${l.status})`;try{let t=await l.json();t.error&&(n=t.error);}catch{}throw new Error(n)}let{url:i}=await l.json();if(i){try{sessionStorage.setItem("keyutils_stripe_pending","1");}catch{}window.location.href=i;}else throw new Error("No checkout URL returned")}catch(l){if(y.current){let i=l instanceof Error?l.message:"Checkout failed";f(i),d(false);}}},[e.apiBaseUrl,e.stackId]),loading:c,error:u}}function Y(){let{config:e,callbacks:c}=g(),[d,u]=react.useState(false),[f,y]=react.useState(null),[m,s]=react.useState(null),a=react.useRef(true);return {transferKey:react.useCallback(async(i,n)=>{try{u(!0),s(null);let t=await fetch(`${e.apiBaseUrl}/api/keys/${i}/transfer`,{method:"POST",headers:{"Content-Type":"application/json",...k()},credentials:"include",body:JSON.stringify({recipientId:n})});if(!t.ok){let o=`Transfer failed (${t.status})`;try{let p=await t.json();p.error&&(o=p.error);}catch{}throw new Error(o)}let r=await t.json();return a.current&&(y(r),c.onTransferComplete?.(r)),r}catch(t){let r=t instanceof Error?t.message:"Transfer failed";return a.current&&s(r),null}finally{a.current&&u(false);}},[e.apiBaseUrl,c]),transferring:d,result:f,error:m}}exports.useKeyLedger=F;exports.useKeys=_;exports.useListKey=q;exports.useMintKey=J;exports.usePricing=$;exports.useStripeCheckout=G;exports.useTransferKey=Y;
@@ -1 +1 @@
1
- import {createContext,useState,useRef,useEffect,useCallback,useContext}from'react';import'react/jsx-runtime';var L=createContext(null);function d(){let e=useContext(L);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function S(){let{config:e}=d(),[c,g]=useState(null),[u,f]=useState(true),[y,m]=useState(null),s=useRef(true),a=useRef(e.apiBaseUrl);a.current=e.apiBaseUrl;let l=async()=>{try{s.current&&(f(!0),m(null));let i=await fetch(`${a.current}/api/keys/pricing`);if(!i.ok){let t=`Pricing unavailable (${i.status})`;try{let r=await i.json();r.error&&(t=r.error);}catch{}throw new Error(t)}let n=await i.json();s.current&&g(n);}catch(i){s.current&&m(i instanceof Error?i.message:"Failed to fetch pricing");}finally{s.current&&f(false);}};return useEffect(()=>{s.current=true,l();let i=setInterval(l,6e4);return ()=>{s.current=false,clearInterval(i);}},[]),{pricing:c,loading:u,error:y,refresh:l}}function M(e){return {id:e.id||"",keyIndex:e.keyIndex??e.key_index??null,key:e.key||e.keyPrefix||"",userId:e.userId||e.user_id||"",status:e.status||"active",tokenBalance:e.tokenBalance??e.currentTokenBalance??e.current_token_balance??0,maxTokens:e.maxTokens??e.initialTokenBalance??e.initial_token_balance??0,createdAt:String(e.createdAt??e.created_at??""),expiresAt:e.expiresAt,label:e.label||e.keyPrefix||e.key_prefix||void 0,paperWork:e.paperWork||e.paper_work||void 0,stackId:e.stackId,stackName:e.stackName}}function N(){let{config:e}=d(),[c,g]=useState([]),[u,f]=useState(true),[y,m]=useState(null),s=useRef(true),a=e.apiBaseUrl,l=useCallback(async()=>{try{f(!0),m(null);let n=await fetch(`${a}/api/keys`);if(!n.ok){let o=`Failed to fetch keys (${n.status})`;try{let p=await n.json();p.error&&(o=p.error);}catch{}throw new Error(o)}let t=await n.json(),r=Array.isArray(t)?t:t.keys??[];s.current&&g(r.map(M));}catch(n){s.current&&m(n instanceof Error?n.message:"Failed to fetch keys");}finally{s.current&&f(false);}},[a]);useEffect(()=>(s.current=true,l(),()=>{s.current=false;}),[l]);let i=c.reduce((n,t)=>n+t.tokenBalance,0);return {keys:c,totalBalance:i,loading:u,error:y,refresh:l}}function O(e){let{config:c}=d(),[g,u]=useState([]),[f,y]=useState(false),[m,s]=useState(null),a=useRef(true),l=c.apiBaseUrl,i=useCallback(async()=>{if(e)try{y(!0),s(null);let n=await fetch(`${l}/api/keys/${e}/ledger`);if(!n.ok){let r=`Failed to fetch ledger (${n.status})`;try{let o=await n.json();o.error&&(r=o.error);}catch{}throw new Error(r)}let t=await n.json();a.current&&u(Array.isArray(t)?t:t.entries??[]);}catch(n){a.current&&s(n instanceof Error?n.message:"Failed to fetch ledger");}finally{a.current&&y(false);}},[l,e]);return useEffect(()=>(a.current=true,i(),()=>{a.current=false;}),[i]),{entries:g,loading:f,error:m,refresh:i}}function J(){let{config:e,callbacks:c}=d(),[g,u]=useState(false),[f,y]=useState(null),[m,s]=useState(null);return {mint:useCallback(async(l,i,n=1)=>{try{u(!0),s(null),c.onPaymentComplete?.(l,i);let t=await fetch(`${e.apiBaseUrl}/api/keys/mint`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({paymentMethod:l,paymentRef:i,quantity:n})});if(!t.ok){let k="Key generation failed";try{let C=await t.json();C.error&&(k=C.error);}catch{}throw new Error(k)}let r=await t.json(),o=r.keys?.[0]||r,p={success:!0,key:{id:o.keyId||o.id||"",key:o.key||"",userId:o.userId||"",status:"active",tokenBalance:o.tokenBalance??o.currentTokenBalance??0,maxTokens:o.initialTokenBalance??o.tokenBalance??0,createdAt:String(o.createdAt||Date.now())},transactionId:i};return y(p),c.onMintSuccess?.(p),p}catch(t){let r=t instanceof Error?t:new Error("Key generation failed");return s(r.message),c.onMintError?.(r),{success:false,error:r.message}}finally{u(false);}},[e.apiBaseUrl,c]),minting:g,result:f,error:m}}function q(){let{config:e,callbacks:c}=d(),[g,u]=useState(false),[f,y]=useState(null),[m,s]=useState(null),a=useRef(true),l=useCallback(async(n,t)=>{try{u(!0),s(null);let r=await fetch(`${e.apiBaseUrl}/api/keys/${n}/list`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({askPriceCents:t,stackId:e.stackId,stackName:e.stackName})});if(!r.ok){let p=`Listing failed (${r.status})`;try{let k=await r.json();k.error&&(p=k.error);}catch{}throw new Error(p)}let o=await r.json();return a.current&&(y(o),c.onListingCreated?.(o)),o}catch(r){let o=r instanceof Error?r.message:"Listing failed";return a.current&&s(o),null}finally{a.current&&u(false);}},[e.apiBaseUrl,e.stackId,e.stackName,c]),i=useCallback(async n=>{try{u(!0),s(null);let t=await fetch(`${e.apiBaseUrl}/api/keys/${n}/list`,{method:"DELETE"});if(!t.ok){let r=`Delist failed (${t.status})`;try{let o=await t.json();o.error&&(r=o.error);}catch{}throw new Error(r)}return a.current&&y(null),!0}catch(t){let r=t instanceof Error?t.message:"Delist failed";return a.current&&s(r),false}finally{a.current&&u(false);}},[e.apiBaseUrl]);return {listKey:l,delistKey:i,listing:g,result:f,error:m}}function G(){let{config:e}=d(),[c,g]=useState(false),[u,f]=useState(null),y=useRef(true);return {createSession:useCallback(async(s,a)=>{try{g(!0),f(null);let l=await fetch(`${e.apiBaseUrl}/api/keys/stripe-session`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({priceCents:s,quantity:a,stackId:e.stackId,referrerUrl:window.location.href})});if(!l.ok){let n=`Checkout failed (${l.status})`;try{let t=await l.json();t.error&&(n=t.error);}catch{}throw new Error(n)}let{url:i}=await l.json();if(i){try{sessionStorage.setItem("keyutils_stripe_pending","1");}catch{}window.location.href=i;}else throw new Error("No checkout URL returned")}catch(l){if(y.current){let i=l instanceof Error?l.message:"Checkout failed";f(i),g(false);}}},[e.apiBaseUrl,e.stackId]),loading:c,error:u}}function X(){let{config:e,callbacks:c}=d(),[g,u]=useState(false),[f,y]=useState(null),[m,s]=useState(null),a=useRef(true);return {transferKey:useCallback(async(i,n)=>{try{u(!0),s(null);let t=await fetch(`${e.apiBaseUrl}/api/keys/${i}/transfer`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({recipientId:n})});if(!t.ok){let o=`Transfer failed (${t.status})`;try{let p=await t.json();p.error&&(o=p.error);}catch{}throw new Error(o)}let r=await t.json();return a.current&&(y(r),c.onTransferComplete?.(r)),r}catch(t){let r=t instanceof Error?t.message:"Transfer failed";return a.current&&s(r),null}finally{a.current&&u(false);}},[e.apiBaseUrl,c]),transferring:g,result:f,error:m}}export{O as useKeyLedger,N as useKeys,q as useListKey,J as useMintKey,S as usePricing,G as useStripeCheckout,X as useTransferKey};
1
+ import {createContext,useState,useRef,useEffect,useCallback,useContext}from'react';import'react/jsx-runtime';var I=createContext(null);function g(){let e=useContext(I);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function $(){let{config:e}=g(),[c,d]=useState(null),[u,f]=useState(true),[y,m]=useState(null),s=useRef(true),a=useRef(e.apiBaseUrl);a.current=e.apiBaseUrl;let l=async()=>{try{s.current&&(f(!0),m(null));let i=await fetch(`${a.current}/api/keys/pricing`,{credentials:"include"});if(!i.ok){let t=`Pricing unavailable (${i.status})`;try{let r=await i.json();r.error&&(t=r.error);}catch{}throw new Error(t)}let n=await i.json();s.current&&d(n);}catch(i){s.current&&m(i instanceof Error?i.message:"Failed to fetch pricing");}finally{s.current&&f(false);}};return useEffect(()=>{s.current=true,l();let i=setInterval(l,6e4);return ()=>{s.current=false,clearInterval(i);}},[]),{pricing:c,loading:u,error:y,refresh:l}}function N(e){return {id:e.id||"",keyIndex:e.keyIndex??e.key_index??null,key:e.key||e.keyPrefix||"",userId:e.userId||e.user_id||"",status:e.status||"active",tokenBalance:e.tokenBalance??e.currentTokenBalance??e.current_token_balance??0,maxTokens:e.maxTokens??e.initialTokenBalance??e.initial_token_balance??0,createdAt:String(e.createdAt??e.created_at??""),expiresAt:e.expiresAt,label:e.label||e.keyPrefix||e.key_prefix||void 0,paperWork:e.paperWork||e.paper_work||void 0,stackId:e.stackId,stackName:e.stackName}}function _(){let{config:e}=g(),[c,d]=useState([]),[u,f]=useState(true),[y,m]=useState(null),s=useRef(true),a=e.apiBaseUrl,l=useCallback(async()=>{try{f(!0),m(null);let n=await fetch(`${a}/api/keys`,{credentials:"include"});if(!n.ok){let o=`Failed to fetch keys (${n.status})`;try{let p=await n.json();p.error&&(o=p.error);}catch{}throw new Error(o)}let t=await n.json(),r=Array.isArray(t)?t:t.keys??[];s.current&&d(r.map(N));}catch(n){s.current&&m(n instanceof Error?n.message:"Failed to fetch keys");}finally{s.current&&f(false);}},[a]);useEffect(()=>(s.current=true,l(),()=>{s.current=false;}),[l]);let i=c.reduce((n,t)=>n+t.tokenBalance,0);return {keys:c,totalBalance:i,loading:u,error:y,refresh:l}}function F(e){let{config:c}=g(),[d,u]=useState([]),[f,y]=useState(false),[m,s]=useState(null),a=useRef(true),l=c.apiBaseUrl,i=useCallback(async()=>{if(e)try{y(!0),s(null);let n=await fetch(`${l}/api/keys/${e}/ledger`,{credentials:"include"});if(!n.ok){let r=`Failed to fetch ledger (${n.status})`;try{let o=await n.json();o.error&&(r=o.error);}catch{}throw new Error(r)}let t=await n.json();a.current&&u(Array.isArray(t)?t:t.entries??[]);}catch(n){a.current&&s(n instanceof Error?n.message:"Failed to fetch ledger");}finally{a.current&&y(false);}},[l,e]);return useEffect(()=>(a.current=true,i(),()=>{a.current=false;}),[i]),{entries:d,loading:f,error:m,refresh:i}}function k(){if(typeof document>"u")return {};let e=document.cookie.match(/(?:^|;\s*)__csrf=([^;]*)/);return e?{"x-csrf-token":e[1]}:{}}function J(){let{config:e,callbacks:c}=g(),[d,u]=useState(false),[f,y]=useState(null),[m,s]=useState(null);return {mint:useCallback(async(l,i,n=1)=>{try{u(!0),s(null),c.onPaymentComplete?.(l,i);let t=await fetch(`${e.apiBaseUrl}/api/keys/mint`,{method:"POST",headers:{"Content-Type":"application/json",...k()},credentials:"include",body:JSON.stringify({paymentMethod:l,paymentRef:i,quantity:n})});if(!t.ok){let h="Key generation failed";try{let P=await t.json();P.error&&(h=P.error);}catch{}throw new Error(h)}let r=await t.json(),o=r.keys?.[0]||r,p={success:!0,key:{id:o.keyId||o.id||"",key:o.key||"",userId:o.userId||"",status:"active",tokenBalance:o.tokenBalance??o.currentTokenBalance??0,maxTokens:o.initialTokenBalance??o.tokenBalance??0,createdAt:String(o.createdAt||Date.now())},transactionId:i};return y(p),c.onMintSuccess?.(p),p}catch(t){let r=t instanceof Error?t:new Error("Key generation failed");return s(r.message),c.onMintError?.(r),{success:false,error:r.message}}finally{u(false);}},[e.apiBaseUrl,c]),minting:d,result:f,error:m}}function q(){let{config:e,callbacks:c}=g(),[d,u]=useState(false),[f,y]=useState(null),[m,s]=useState(null),a=useRef(true),l=useCallback(async(n,t)=>{try{u(!0),s(null);let r=await fetch(`${e.apiBaseUrl}/api/keys/${n}/list`,{method:"POST",headers:{"Content-Type":"application/json",...k()},credentials:"include",body:JSON.stringify({askPriceCents:t,stackId:e.stackId,stackName:e.stackName})});if(!r.ok){let p=`Listing failed (${r.status})`;try{let h=await r.json();h.error&&(p=h.error);}catch{}throw new Error(p)}let o=await r.json();return a.current&&(y(o),c.onListingCreated?.(o)),o}catch(r){let o=r instanceof Error?r.message:"Listing failed";return a.current&&s(o),null}finally{a.current&&u(false);}},[e.apiBaseUrl,e.stackId,e.stackName,c]),i=useCallback(async n=>{try{u(!0),s(null);let t=await fetch(`${e.apiBaseUrl}/api/keys/${n}/list`,{method:"DELETE",headers:{...k()},credentials:"include"});if(!t.ok){let r=`Delist failed (${t.status})`;try{let o=await t.json();o.error&&(r=o.error);}catch{}throw new Error(r)}return a.current&&y(null),!0}catch(t){let r=t instanceof Error?t.message:"Delist failed";return a.current&&s(r),false}finally{a.current&&u(false);}},[e.apiBaseUrl]);return {listKey:l,delistKey:i,listing:d,result:f,error:m}}function G(){let{config:e}=g(),[c,d]=useState(false),[u,f]=useState(null),y=useRef(true);return {createSession:useCallback(async(s,a)=>{try{d(!0),f(null);let l=await fetch(`${e.apiBaseUrl}/api/keys/stripe-session`,{method:"POST",headers:{"Content-Type":"application/json",...k()},credentials:"include",body:JSON.stringify({priceCents:s,quantity:a,stackId:e.stackId,referrerUrl:window.location.href})});if(!l.ok){let n=`Checkout failed (${l.status})`;try{let t=await l.json();t.error&&(n=t.error);}catch{}throw new Error(n)}let{url:i}=await l.json();if(i){try{sessionStorage.setItem("keyutils_stripe_pending","1");}catch{}window.location.href=i;}else throw new Error("No checkout URL returned")}catch(l){if(y.current){let i=l instanceof Error?l.message:"Checkout failed";f(i),d(false);}}},[e.apiBaseUrl,e.stackId]),loading:c,error:u}}function Y(){let{config:e,callbacks:c}=g(),[d,u]=useState(false),[f,y]=useState(null),[m,s]=useState(null),a=useRef(true);return {transferKey:useCallback(async(i,n)=>{try{u(!0),s(null);let t=await fetch(`${e.apiBaseUrl}/api/keys/${i}/transfer`,{method:"POST",headers:{"Content-Type":"application/json",...k()},credentials:"include",body:JSON.stringify({recipientId:n})});if(!t.ok){let o=`Transfer failed (${t.status})`;try{let p=await t.json();p.error&&(o=p.error);}catch{}throw new Error(o)}let r=await t.json();return a.current&&(y(r),c.onTransferComplete?.(r)),r}catch(t){let r=t instanceof Error?t.message:"Transfer failed";return a.current&&s(r),null}finally{a.current&&u(false);}},[e.apiBaseUrl,c]),transferring:d,result:f,error:m}}export{F as useKeyLedger,_ as useKeys,q as useListKey,J as useMintKey,$ as usePricing,G as useStripeCheckout,Y as useTransferKey};
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- 'use strict';var clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),Kt=require('react'),jsxRuntime=require('react/jsx-runtime'),lucideReact=require('lucide-react');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var Kt__default=/*#__PURE__*/_interopDefault(Kt);function u(...e){return tailwindMerge.twMerge(clsx.clsx(e))}function I(e){return e==null?"0":e>=1e9?`${(e/1e9).toFixed(1)}B`:e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:e.toLocaleString()}function Be(e,t){return t<=0?0:Math.min(100,Math.round(e/t*100))}function Ie(e){return e>=70?"bg-green-500":e>=30?"bg-yellow-500":"bg-red-500"}function Y(e){let t=typeof e=="string"&&/^\d+$/.test(e)?Number(e):e,r=new Date(t);return isNaN(r.getTime())?String(e):r.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}function Le(){if(typeof navigator>"u")return "mac";let e=navigator.userAgent.toLowerCase();return /iphone|ipad|ipod/.test(e)?"ios":/android/.test(e)?"android":/win/.test(e)?"windows":/linux/.test(e)?"linux":"mac"}var Ee=Kt.createContext(null);function C(){let e=Kt.useContext(Ee);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function oe({config:e,callbacks:t={},children:r}){typeof e.apiBaseUrl!="string"&&console.error("[KeyUtils] apiBaseUrl must be a string");let s=Kt.useMemo(()=>({config:e,callbacks:t}),[e,t]);return jsxRuntime.jsx(Ee.Provider,{value:s,children:r})}function ie(){let{config:e}=C(),[t,r]=Kt.useState(null),[s,x]=Kt.useState(true),[m,f]=Kt.useState(null),a=Kt.useRef(true),n=Kt.useRef(e.apiBaseUrl);n.current=e.apiBaseUrl;let c=async()=>{try{a.current&&(x(!0),f(null));let d=await fetch(`${n.current}/api/keys/pricing`);if(!d.ok){let i=`Pricing unavailable (${d.status})`;try{let o=await d.json();o.error&&(i=o.error);}catch{}throw new Error(i)}let p=await d.json();a.current&&r(p);}catch(d){a.current&&f(d instanceof Error?d.message:"Failed to fetch pricing");}finally{a.current&&x(false);}};return Kt.useEffect(()=>{a.current=true,c();let d=setInterval(c,6e4);return ()=>{a.current=false,clearInterval(d);}},[]),{pricing:t,loading:s,error:m,refresh:c}}function lt(e){return {id:e.id||"",keyIndex:e.keyIndex??e.key_index??null,key:e.key||e.keyPrefix||"",userId:e.userId||e.user_id||"",status:e.status||"active",tokenBalance:e.tokenBalance??e.currentTokenBalance??e.current_token_balance??0,maxTokens:e.maxTokens??e.initialTokenBalance??e.initial_token_balance??0,createdAt:String(e.createdAt??e.created_at??""),expiresAt:e.expiresAt,label:e.label||e.keyPrefix||e.key_prefix||void 0,paperWork:e.paperWork||e.paper_work||void 0,stackId:e.stackId,stackName:e.stackName}}function G(){let{config:e}=C(),[t,r]=Kt.useState([]),[s,x]=Kt.useState(true),[m,f]=Kt.useState(null),a=Kt.useRef(true),n=e.apiBaseUrl,c=Kt.useCallback(async()=>{try{x(!0),f(null);let p=await fetch(`${n}/api/keys`);if(!p.ok){let l=`Failed to fetch keys (${p.status})`;try{let b=await p.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let i=await p.json(),o=Array.isArray(i)?i:i.keys??[];a.current&&r(o.map(lt));}catch(p){a.current&&f(p instanceof Error?p.message:"Failed to fetch keys");}finally{a.current&&x(false);}},[n]);Kt.useEffect(()=>(a.current=true,c(),()=>{a.current=false;}),[c]);let d=t.reduce((p,i)=>p+i.tokenBalance,0);return {keys:t,totalBalance:d,loading:s,error:m,refresh:c}}function de(e){let{config:t}=C(),[r,s]=Kt.useState([]),[x,m]=Kt.useState(false),[f,a]=Kt.useState(null),n=Kt.useRef(true),c=t.apiBaseUrl,d=Kt.useCallback(async()=>{if(e)try{m(!0),a(null);let p=await fetch(`${c}/api/keys/${e}/ledger`);if(!p.ok){let o=`Failed to fetch ledger (${p.status})`;try{let l=await p.json();l.error&&(o=l.error);}catch{}throw new Error(o)}let i=await p.json();n.current&&s(Array.isArray(i)?i:i.entries??[]);}catch(p){n.current&&a(p instanceof Error?p.message:"Failed to fetch ledger");}finally{n.current&&m(false);}},[c,e]);return Kt.useEffect(()=>(n.current=true,d(),()=>{n.current=false;}),[d]),{entries:r,loading:x,error:f,refresh:d}}function me(){let{config:e,callbacks:t}=C(),[r,s]=Kt.useState(false),[x,m]=Kt.useState(null),[f,a]=Kt.useState(null);return {mint:Kt.useCallback(async(c,d,p=1)=>{try{s(!0),a(null),t.onPaymentComplete?.(c,d);let i=await fetch(`${e.apiBaseUrl}/api/keys/mint`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({paymentMethod:c,paymentRef:d,quantity:p})});if(!i.ok){let w="Key generation failed";try{let P=await i.json();P.error&&(w=P.error);}catch{}throw new Error(w)}let o=await i.json(),l=o.keys?.[0]||o,b={success:!0,key:{id:l.keyId||l.id||"",key:l.key||"",userId:l.userId||"",status:"active",tokenBalance:l.tokenBalance??l.currentTokenBalance??0,maxTokens:l.initialTokenBalance??l.tokenBalance??0,createdAt:String(l.createdAt||Date.now())},transactionId:d};return m(b),t.onMintSuccess?.(b),b}catch(i){let o=i instanceof Error?i:new Error("Key generation failed");return a(o.message),t.onMintError?.(o),{success:false,error:o.message}}finally{s(false);}},[e.apiBaseUrl,t]),minting:r,result:x,error:f}}function pe(){let{config:e,callbacks:t}=C(),[r,s]=Kt.useState(false),[x,m]=Kt.useState(null),[f,a]=Kt.useState(null),n=Kt.useRef(true),c=Kt.useCallback(async(p,i)=>{try{s(!0),a(null);let o=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({askPriceCents:i,stackId:e.stackId,stackName:e.stackName})});if(!o.ok){let b=`Listing failed (${o.status})`;try{let w=await o.json();w.error&&(b=w.error);}catch{}throw new Error(b)}let l=await o.json();return n.current&&(m(l),t.onListingCreated?.(l)),l}catch(o){let l=o instanceof Error?o.message:"Listing failed";return n.current&&a(l),null}finally{n.current&&s(false);}},[e.apiBaseUrl,e.stackId,e.stackName,t]),d=Kt.useCallback(async p=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"DELETE"});if(!i.ok){let o=`Delist failed (${i.status})`;try{let l=await i.json();l.error&&(o=l.error);}catch{}throw new Error(o)}return n.current&&m(null),!0}catch(i){let o=i instanceof Error?i.message:"Delist failed";return n.current&&a(o),false}finally{n.current&&s(false);}},[e.apiBaseUrl]);return {listKey:c,delistKey:d,listing:r,result:x,error:f}}function xe(){let{config:e}=C(),[t,r]=Kt.useState(false),[s,x]=Kt.useState(null),m=Kt.useRef(true);return {createSession:Kt.useCallback(async(a,n)=>{try{r(!0),x(null);let c=await fetch(`${e.apiBaseUrl}/api/keys/stripe-session`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({priceCents:a,quantity:n,stackId:e.stackId,referrerUrl:window.location.href})});if(!c.ok){let p=`Checkout failed (${c.status})`;try{let i=await c.json();i.error&&(p=i.error);}catch{}throw new Error(p)}let{url:d}=await c.json();if(d){try{sessionStorage.setItem("keyutils_stripe_pending","1");}catch{}window.location.href=d;}else throw new Error("No checkout URL returned")}catch(c){if(m.current){let d=c instanceof Error?c.message:"Checkout failed";x(d),r(false);}}},[e.apiBaseUrl,e.stackId]),loading:t,error:s}}function ye(){let{config:e,callbacks:t}=C(),[r,s]=Kt.useState(false),[x,m]=Kt.useState(null),[f,a]=Kt.useState(null),n=Kt.useRef(true);return {transferKey:Kt.useCallback(async(d,p)=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${d}/transfer`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({recipientId:p})});if(!i.ok){let l=`Transfer failed (${i.status})`;try{let b=await i.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let o=await i.json();return n.current&&(m(o),t.onTransferComplete?.(o)),o}catch(i){let o=i instanceof Error?i.message:"Transfer failed";return n.current&&a(o),null}finally{n.current&&s(false);}},[e.apiBaseUrl,t]),transferring:r,result:x,error:f}}var $e=/^[1-9A-HJ-NP-Za-km-z]{32,44}$/;function Ne({amountSol:e,onSuccess:t,onError:r,disabled:s,className:x,style:m}){let{config:f}=C(),[a,n]=Kt.useState(false),[c,d]=Kt.useState(null),p=!!(f.merchantWallet&&$e.test(f.merchantWallet)),i=Kt.useCallback(async()=>{if(p)try{n(!0),d(null);let{Connection:o,PublicKey:l,Transaction:b,SystemProgram:w,LAMPORTS_PER_SOL:P}=await import('@solana/web3.js'),T=typeof window<"u"?window.solana:void 0;if(!T||typeof T!="object"||!T.isPhantom)throw new Error("Phantom wallet not found. Please install Phantom.");let j=T,k;try{k=new l(f.merchantWallet);}catch{throw new Error("Invalid merchant wallet address.")}let z=await j.connect(),_=new l(z.publicKey.toString()),K=new o(f.solanaRpcUrl||"https://api.mainnet-beta.solana.com"),{blockhash:F}=await K.getLatestBlockhash(),W=BigInt(Math.floor(e*1e9)),Z=f.protocolTreasuryWallet,B=f.protocolFeeBps??500,D=new b({recentBlockhash:F,feePayer:_});if(Z&&$e.test(Z)&&B>0){let X=W*BigInt(B)/10000n,Je=W-X,Ze=new l(Z);D.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(Je)}),w.transfer({fromPubkey:_,toPubkey:Ze,lamports:Number(X)}));}else D.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(W)}));let{signature:re}=await j.signAndSendTransaction(D);t(re);}catch(o){let l=o instanceof Error?o:new Error("Payment failed");d(l.message),r?.(l);}finally{n(false);}},[e,f.merchantWallet,p,t,r]);return jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("button",{onClick:i,disabled:s||a||!p,"aria-label":`Pay ${e.toFixed(4)} SOL`,className:u("flex w-full items-center justify-center gap-2 rounded-lg bg-purple-600 px-4 py-6 font-medium text-white transition-colors hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed",x),style:m,children:a?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Loader2,{className:"h-4 w-4 animate-spin"}),"Processing..."]}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:["Pay ",e.toFixed(4)," SOL"]})}),c&&jsxRuntime.jsx("p",{className:"mt-2 text-center text-xs text-red-500",children:c})]})}function ve({result:e,className:t,style:r}){let[s,x]=Kt.useState(false),m=Kt.useRef(null);Kt.useEffect(()=>()=>{m.current&&clearTimeout(m.current);},[]);let f=Kt.useCallback(()=>{e.key?.key&&(navigator.clipboard.writeText(e.key.key),x(true),m.current&&clearTimeout(m.current),m.current=setTimeout(()=>x(false),2e3));},[e.key?.key]);return !e.success||!e.key?null:jsxRuntime.jsxs("div",{className:u("rounded-lg border border-green-500/20 bg-green-500/10 p-6 text-center",t),style:r,children:[jsxRuntime.jsx(lucideReact.CheckCircle,{className:"mx-auto mb-3 h-12 w-12 text-green-500"}),jsxRuntime.jsx("h3",{className:"mb-2 text-lg font-semibold text-foreground",children:"Key Generated!"}),jsxRuntime.jsx("p",{className:"mb-4 text-sm text-muted-foreground",children:"Your node key has been successfully generated."}),jsxRuntime.jsxs("div",{className:"mx-auto flex max-w-md items-center gap-2 rounded-md border bg-background p-3",children:[jsxRuntime.jsx("code",{className:"flex-1 truncate text-xs text-foreground",children:e.key.key}),jsxRuntime.jsx("button",{onClick:f,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",children:s?jsxRuntime.jsx(lucideReact.Check,{className:"h-4 w-4 text-green-500"}):jsxRuntime.jsx(lucideReact.Copy,{className:"h-4 w-4"})})]})]})}function A({className:e}){return jsxRuntime.jsx("div",{className:u("animate-pulse rounded-xl bg-muted",e)})}function ke(){return jsxRuntime.jsxs("div",{className:"space-y-6",children:[jsxRuntime.jsxs("div",{className:"px-6 py-10 flex flex-col items-center gap-3",children:[jsxRuntime.jsx(A,{className:"h-14 w-48"}),jsxRuntime.jsx(A,{className:"h-5 w-64"})]}),jsxRuntime.jsx(A,{className:"h-[72px] w-full rounded-2xl"}),jsxRuntime.jsx(A,{className:"h-[68px] w-full rounded-2xl"}),jsxRuntime.jsx(A,{className:"h-[60px] w-full rounded-2xl"})]})}function J({count:e=3}){return jsxRuntime.jsx("div",{className:"space-y-3",children:Array.from({length:e}).map((t,r)=>jsxRuntime.jsxs("div",{className:"rounded-xl border p-4 space-y-3",children:[jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsx(A,{className:"h-4 w-32"}),jsxRuntime.jsx(A,{className:"h-4 w-16"})]}),jsxRuntime.jsx(A,{className:"h-2 w-full rounded-full"}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx(A,{className:"h-3 w-24"}),jsxRuntime.jsx(A,{className:"h-3 w-20"})]})]},r))})}function jt({quantity:e,max:t,onChange:r}){return jsxRuntime.jsxs("div",{className:"flex items-center justify-between rounded-2xl bg-muted/20 px-6 py-6",children:[jsxRuntime.jsx("span",{className:"text-sm font-medium text-foreground",children:"Quantity"}),jsxRuntime.jsxs("div",{className:"flex items-center gap-0 rounded-xl bg-background",children:[jsxRuntime.jsx("button",{onClick:()=>r(Math.max(1,e-1)),disabled:e<=1,"aria-label":"Decrease quantity",className:"flex h-12 w-12 items-center justify-center rounded-l-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsxRuntime.jsx(lucideReact.Minus,{className:"h-5 w-5"})}),jsxRuntime.jsx("span",{className:"flex h-12 w-14 items-center justify-center border-x text-xl font-bold text-foreground","aria-live":"polite",children:e}),jsxRuntime.jsx("button",{onClick:()=>r(Math.min(t,e+1)),disabled:e>=t,"aria-label":"Increase quantity",className:"flex h-12 w-12 items-center justify-center rounded-r-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsxRuntime.jsx(lucideReact.Plus,{className:"h-5 w-5"})})]})]})}function Fe({pricing:e,quantity:t}){let[r,s]=Kt.useState(false),x=e.priceUsd*t;return jsxRuntime.jsxs("div",{className:"rounded-2xl border bg-background",children:[jsxRuntime.jsxs("button",{onClick:()=>s(!r),"aria-expanded":r,className:"flex w-full items-center justify-between px-6 py-6 text-left",children:[jsxRuntime.jsxs("span",{className:"text-foreground",children:[jsxRuntime.jsxs("span",{className:"text-xl font-bold",children:["$",x.toFixed(2)]})," ",jsxRuntime.jsx("span",{className:"text-sm text-muted-foreground",children:"total fees included"})]}),r?jsxRuntime.jsx(lucideReact.ChevronUp,{className:"h-5 w-5 text-muted-foreground"}):jsxRuntime.jsx(lucideReact.ChevronDown,{className:"h-5 w-5 text-muted-foreground"})]}),r&&jsxRuntime.jsxs("div",{className:"border-t px-6 pb-8 pt-4 space-y-3 text-sm",children:[jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsxs("span",{className:"text-muted-foreground",children:["Node Key \xD7 ",t]}),jsxRuntime.jsxs("span",{className:"text-foreground",children:["$",(e.priceUsd*t).toFixed(2)]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Keys sold"}),jsxRuntime.jsx("span",{className:"text-foreground",children:e.keysSold})]}),e.daysUntilHalving>0&&jsxRuntime.jsxs("div",{className:"flex justify-between text-muted-foreground",children:[jsxRuntime.jsx("span",{children:"Next refresh"}),jsxRuntime.jsxs("span",{children:[e.daysUntilHalving," day",e.daysUntilHalving!==1?"s":""]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between border-t pt-3 font-semibold",children:[jsxRuntime.jsx("span",{className:"text-foreground",children:"Total"}),jsxRuntime.jsxs("span",{className:"text-foreground",children:["$",x.toFixed(2)]})]})]})]})}function we({className:e,style:t}){let{config:r}=C(),{pricing:s,loading:x,error:m,refresh:f}=ie(),{mint:a,minting:n,result:c,error:d}=me(),{createSession:p,loading:i,error:o}=xe(),[l,b]=Kt.useState(1),[w,P]=Kt.useState(r.paymentMethods?.includes("stripe")?"stripe":"solana"),[T,j]=Kt.useState(0),[k,z]=Kt.useState(false),_=Kt__default.default.useRef(l);_.current=l;let K=Math.max(1,r.maxQuantity||5),F=[...r.paymentMethods||["solana"]].sort((B,D)=>B==="stripe"?-1:D==="stripe"?1:0);if(Kt.useEffect(()=>{if(typeof window>"u")return;let D=new URLSearchParams(window.location.search).get("session_id");if(!D){try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}return}if(/^cs_(test|live)_/.test(D)&&!k&&!c?.success){let re=false;try{re=sessionStorage.getItem("keyutils_stripe_pending")==="1";}catch{}if(!re)return;try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}z(true);let X=new URL(window.location.href);X.searchParams.delete("session_id"),window.history.replaceState({},"",X.toString()),a("stripe",D,_.current);}},[k,c,a]),c?.success)return jsxRuntime.jsx("div",{className:u("flex flex-col items-center justify-center",e),style:t,children:jsxRuntime.jsx(ve,{result:c})});if(k||n)return jsxRuntime.jsx("div",{className:u("flex flex-col",e),style:t,children:jsxRuntime.jsx(ke,{})});if(x)return jsxRuntime.jsx("div",{className:u("flex flex-col",e),style:t,children:jsxRuntime.jsx(ke,{})});if(m||!s)return jsxRuntime.jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-24",e),style:t,children:[jsxRuntime.jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load pricing"}),jsxRuntime.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m||"Please check your connection and try again."})]}),jsxRuntime.jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let W=async B=>{j(2),await a(w,B,l);},Z=()=>{p(s.priceCents,l);};return jsxRuntime.jsx("div",{className:u("flex flex-col",e),style:t,children:jsxRuntime.jsxs("div",{className:"space-y-6",children:[T===0&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[r.keyImage&&jsxRuntime.jsx("img",{src:r.keyImage,alt:"Node Key",className:r.keyImageClass||"w-1/2 mx-auto"}),jsxRuntime.jsxs("div",{className:"px-6 py-10 text-center",children:[jsxRuntime.jsxs("p",{className:"text-5xl font-bold tracking-tight text-foreground md:text-6xl",children:["$",s.priceUsd.toFixed(2)]}),jsxRuntime.jsxs("p",{className:"mt-2 text-base text-muted-foreground",children:["per key \xB7 ",s.tokenAllocationFormatted||I(s.tokenAllocation)," tokens included"]})]}),jsxRuntime.jsx(jt,{quantity:l,max:K,onChange:b}),jsxRuntime.jsx(Fe,{pricing:s,quantity:l}),jsxRuntime.jsx("button",{onClick:()=>j(1),className:"w-full rounded-2xl bg-foreground py-6 text-center text-base font-semibold text-background transition-colors hover:bg-foreground/90",children:"Continue to Payment"})]}),T===1&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[F.length>1&&jsxRuntime.jsx("div",{role:"tablist",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:F.map(B=>jsxRuntime.jsxs("button",{role:"tab","aria-selected":w===B,onClick:()=>P(B),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-4 text-sm font-medium transition-colors",w===B?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:[B==="stripe"?jsxRuntime.jsx(lucideReact.CreditCard,{className:"h-5 w-5"}):jsxRuntime.jsx(lucideReact.Wallet,{className:"h-5 w-5"}),B==="stripe"?"Credit Card":"Crypto"]},B))}),jsxRuntime.jsx(Fe,{pricing:s,quantity:l}),w==="stripe"?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("button",{onClick:Z,disabled:i,className:"flex w-full items-center justify-center gap-2 rounded-2xl bg-foreground py-6 text-base font-semibold text-background transition-colors hover:bg-foreground/90 disabled:opacity-50",children:i?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Loader2,{className:"h-5 w-5 animate-spin"}),"Redirecting to Stripe..."]}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.CreditCard,{className:"h-5 w-5"}),"Pay with Card"]})}),o&&jsxRuntime.jsx("p",{className:"text-center text-sm text-red-500",children:o})]}):w==="solana"?jsxRuntime.jsx(Ne,{amountSol:s.priceSol??0,onSuccess:W,className:"rounded-2xl py-5 text-base"}):null,d&&jsxRuntime.jsx("p",{className:"text-center text-sm text-red-500",children:d}),jsxRuntime.jsx("button",{onClick:()=>j(0),className:"w-full py-3 text-center text-sm text-muted-foreground hover:text-foreground transition-colors",children:"\u2190 Back"})]})]})})}var $t={ios:"iOS",android:"Android",windows:"Windows",mac:"macOS",linux:"Linux"},Dt=["mac","windows","linux","ios","android"];function Pe({downloads:e,className:t,style:r}){let{config:s}=C(),x=Kt.useMemo(()=>Le(),[]),m=e||Dt.map(n=>({platform:n,label:$t[n],url:"#",compatible:n===x})),f=m.find(n=>n.compatible)||m[0],a=m.filter(n=>n.platform!==f.platform);return jsxRuntime.jsxs("div",{className:u("space-y-8",t),style:r,children:[jsxRuntime.jsxs("div",{className:"flex flex-col items-center gap-6 pt-4 mt-4",children:[s.aispImage&&jsxRuntime.jsx("img",{src:s.aispImage,alt:"aiSP",className:"w-full sm:w-1/2 mx-auto px-4 sm:px-0"}),jsxRuntime.jsxs("div",{className:"text-center",children:[jsxRuntime.jsx("p",{className:"text-lg sm:text-2xl font-medium text-foreground",children:"Download the AI Service Provider App"}),jsxRuntime.jsx("p",{className:"mt-1 text-sm sm:text-base text-muted-foreground",children:"Load your keys and run your node."})]}),jsxRuntime.jsxs("a",{href:f.url,className:"inline-flex items-center gap-3 rounded-full px-10 py-4 text-lg font-semibold text-white transition-colors hover:opacity-90",style:{backgroundColor:"#0900f4"},children:[jsxRuntime.jsx(lucideReact.Download,{className:"h-5 w-5"}),"Get aiSP for ",f.label]})]}),jsxRuntime.jsxs("p",{className:"text-center text-sm text-muted-foreground",children:["aiSP is also available on"," ",a.map((n,c)=>jsxRuntime.jsxs(Kt__default.default.Fragment,{children:[c>0&&(c===a.length-1?" and ":", "),jsxRuntime.jsx("a",{href:n.url,className:"font-medium underline transition-colors hover:text-foreground",style:{color:"#066bff"},children:n.label})]},n.platform)),"."]}),jsxRuntime.jsxs("div",{className:"flex flex-col items-center gap-2 mt-12",children:[jsxRuntime.jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["Source code is available on",jsxRuntime.jsx("a",{href:"https://github.com/stack-net",target:"_blank",rel:"noopener noreferrer",className:"text-foreground underline hover:text-foreground/80 color-[#0900f4]",children:"Github"})]}),jsxRuntime.jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["By downloading, you agree to the",jsxRuntime.jsx("a",{href:s.termsUrl||"/terms",className:"text-foreground underline hover:text-foreground/80",children:"Open Source Applications Terms"})]})]})]})}function q({current:e,max:t,className:r,style:s,showLabel:x=true}){let m=Be(e,t),f=Ie(m);return jsxRuntime.jsxs("div",{className:u("w-full",r),style:s,children:[x&&jsxRuntime.jsxs("div",{className:"mb-1 flex items-center justify-between text-xs text-muted-foreground",children:[jsxRuntime.jsxs("span",{children:[I(e)," / ",I(t)]}),jsxRuntime.jsxs("span",{children:[m,"%"]})]}),jsxRuntime.jsx("div",{className:"h-2 w-full overflow-hidden rounded-full bg-muted",children:jsxRuntime.jsx("div",{className:u("h-full rounded-full transition-all duration-500",f),style:{width:`${m}%`}})})]})}function Ft({nodeKey:e,selected:t,onSelect:r}){return jsxRuntime.jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsxRuntime.jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsxRuntime.jsx(lucideReact.Check,{className:"h-3 w-3 text-background"})}),jsxRuntime.jsxs("div",{className:"min-w-0 flex-1",children:[jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsxRuntime.jsx("span",{className:u("text-xs font-medium capitalize",e.status==="active"?"text-green-500":"text-muted-foreground"),children:e.status})]}),jsxRuntime.jsx(q,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function Se({className:e,style:t}){let{config:r}=C(),{keys:s,loading:x,error:m,refresh:f}=G(),{listKey:a,listing:n,result:c,error:d}=pe(),[p,i]=Kt.useState(null),[o,l]=Kt.useState(""),[b,w]=Kt.useState(false),P=s.find(K=>K.id===p),T=parseInt(o.replace(/[^0-9]/g,""),10)||0,j=T>0&&Number.isFinite(T),k=!!P&&j&&b&&!n,z=async()=>{if(!k||!P)return;let K=T*100;await a(P.id,K)&&f();};if(c)return jsxRuntime.jsxs("div",{className:u("flex flex-col items-center gap-4 rounded-xl bg-green-500/10 py-12",e),style:t,children:[jsxRuntime.jsx(lucideReact.CheckCircle,{className:"h-12 w-12 text-green-500"}),jsxRuntime.jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Key Listed!"}),jsxRuntime.jsx("p",{className:"text-sm text-muted-foreground",children:"Your key is now on the Global Open AI Network marketplace."}),jsxRuntime.jsxs("p",{className:"text-xs text-muted-foreground",children:["Listing ID: ",jsxRuntime.jsx("code",{children:c.listingId})]}),jsxRuntime.jsxs("a",{href:`https://market.stacknet.org/keys/${c.keyId}`,target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-2 rounded-xl bg-foreground px-6 py-3 text-sm font-semibold text-background transition-colors hover:bg-foreground/90",children:[jsxRuntime.jsx(lucideReact.ExternalLink,{className:"h-4 w-4"}),"View Listing"]})]});if(x)return jsxRuntime.jsxs("div",{className:u("space-y-5 px-1",e),style:t,children:[jsxRuntime.jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsxRuntime.jsx(J,{count:2})]});if(m)return jsxRuntime.jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-16",e),style:t,children:[jsxRuntime.jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsxRuntime.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m})]}),jsxRuntime.jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let _=s.filter(K=>K.status==="active");return _.length===0?jsxRuntime.jsxs("div",{className:u("flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed py-16",e),style:t,children:[jsxRuntime.jsx(lucideReact.AlertTriangle,{className:"h-8 w-8 text-muted-foreground"}),jsxRuntime.jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys to sell."})]}):jsxRuntime.jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsxRuntime.jsx("div",{className:"space-y-2",children:_.map(K=>jsxRuntime.jsx(Ft,{nodeKey:K,selected:p===K.id,onSelect:()=>i(K.id)},K.id))})]}),P&&jsxRuntime.jsxs("div",{className:"rounded-xl border bg-muted/30 p-5 space-y-2 text-sm",children:[P.keyIndex&&jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Key #"}),jsxRuntime.jsxs("span",{className:"text-foreground font-semibold",children:["#",P.keyIndex]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Key ID"}),jsxRuntime.jsx("code",{className:"text-xs text-foreground",children:P.id})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Originating Stack"}),jsxRuntime.jsx("span",{className:"text-foreground",children:r.stackName||"Unknown"})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Tokens (remaining / total)"}),jsxRuntime.jsxs("span",{className:"text-foreground",children:[I(P.tokenBalance)," / ",I(P.maxTokens)]})]}),P.paperWork&&jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Paper earned"}),jsxRuntime.jsx("span",{className:"text-foreground",children:P.paperWork})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Created"}),jsxRuntime.jsx("span",{className:"text-foreground",children:Y(P.createdAt)})]})]}),jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("label",{htmlFor:"listing-price",className:"mb-2 block text-sm sm:text-lg font-semibold text-foreground",children:"Listing Price (USD)"}),jsxRuntime.jsxs("div",{className:"relative",children:[jsxRuntime.jsx("span",{className:"absolute left-4 top-1/2 -translate-y-1/2 text-2xl font-bold text-muted-foreground",children:"$"}),jsxRuntime.jsx("input",{id:"listing-price",type:"text",inputMode:"numeric",value:o,onChange:K=>{let F=K.target.value.replace(/[^0-9]/g,""),W=parseInt(F,10);l(isNaN(W)?"":W.toLocaleString("en-US"));},placeholder:"0",className:"w-full rounded-xl border bg-background py-6 pl-10 pr-4 text-3xl font-bold text-foreground placeholder:text-muted-foreground/30 focus:outline-none focus:ring-2 focus:ring-foreground/20"})]})]}),jsxRuntime.jsxs("div",{className:"flex items-start gap-3",children:[jsxRuntime.jsx("button",{type:"button",role:"checkbox","aria-checked":b,onClick:()=>w(!b),className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded border-2 transition-colors cursor-pointer",b?"border-foreground bg-foreground":"border-muted-foreground/40"),children:b&&jsxRuntime.jsx(lucideReact.Check,{className:"h-3 w-3 text-background"})}),jsxRuntime.jsxs("span",{className:"text-xs text-muted-foreground leading-relaxed",children:["I agree to list this key on the Global Open AI Network marketplace. The key will be deactivated upon sale and transferred to the buyer. Listing fees may apply."," ",jsxRuntime.jsx("a",{href:r.termsUrl||"/terms",className:"text-foreground underline",target:"_blank",rel:"noopener noreferrer",children:"Terms"})]})]}),d&&jsxRuntime.jsx("p",{className:"text-sm text-red-500",children:d}),jsxRuntime.jsxs("button",{onClick:z,disabled:!k,className:u("flex w-full items-center justify-center gap-2 rounded-xl py-4 text-sm font-semibold transition-colors",k?"bg-foreground text-background hover:bg-foreground/90":"bg-muted text-muted-foreground cursor-not-allowed"),children:[jsxRuntime.jsx(lucideReact.ExternalLink,{className:"h-4 w-4"}),n?"Listing...":"List on Marketplace"]})]})}function zt({nodeKey:e,selected:t,onSelect:r}){return jsxRuntime.jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsxRuntime.jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsxRuntime.jsx(lucideReact.Check,{className:"h-3 w-3 text-background"})}),jsxRuntime.jsxs("div",{className:"min-w-0 flex-1",children:[jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsxRuntime.jsx("span",{className:"text-xs font-medium capitalize text-green-500",children:e.status})]}),jsxRuntime.jsx(q,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function Re({className:e,style:t}){let{keys:r,loading:s}=G(),{transferKey:x,transferring:m,result:f,error:a}=ye(),[n,c]=Kt.useState(null),[d,p]=Kt.useState(""),[i,o]=Kt.useState(false),l=r.filter(k=>k.status==="active"),b=l.find(k=>k.id===n),w=b&&d.trim()===b.userId,P=n&&d.trim().length>0&&i&&!w&&!m,T=async()=>{!n||!d.trim()||await x(n,d.trim());},j=()=>{c(null),p(""),o(false);};return f?jsxRuntime.jsxs("div",{className:u("flex flex-col items-center gap-4 py-8",e),style:t,children:[jsxRuntime.jsx(lucideReact.CheckCircle,{className:"h-12 w-12 text-green-500"}),jsxRuntime.jsxs("div",{className:"text-center",children:[jsxRuntime.jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Transfer Complete"}),jsxRuntime.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"Key transferred successfully"})]}),jsxRuntime.jsxs("div",{className:"w-full max-w-sm space-y-2 rounded-xl border border-border bg-muted/30 p-4 text-sm",children:[jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Key"}),jsxRuntime.jsxs("span",{className:"font-mono text-foreground",children:[f.keyId.slice(0,20),"..."]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Recipient"}),jsxRuntime.jsxs("span",{className:"font-mono text-foreground",children:[f.toUserId.slice(0,20),"..."]})]})]}),jsxRuntime.jsx("button",{onClick:j,className:"mt-2 rounded-lg border border-border px-4 py-2 text-sm font-medium text-foreground hover:bg-muted/50 transition-colors",children:"Transfer Another"})]}):jsxRuntime.jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("h3",{className:"mb-3 text-sm font-medium text-foreground",children:"Select Key to Transfer"}),s?jsxRuntime.jsx(J,{count:2}):l.length===0?jsxRuntime.jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys available for transfer."}):jsxRuntime.jsx("div",{className:"space-y-2",children:l.map(k=>jsxRuntime.jsx(zt,{nodeKey:k,selected:n===k.id,onSelect:()=>c(k.id)},k.id))})]}),n&&jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("label",{className:"mb-1.5 block text-sm font-medium text-foreground",children:"Recipient User ID"}),jsxRuntime.jsx("input",{type:"text",value:d,onChange:k=>{p(k.target.value),o(false);},placeholder:"Enter recipient's user ID or global ID",className:"w-full rounded-lg border border-border bg-background px-3 py-2.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-foreground/30 focus:outline-none focus:ring-1 focus:ring-foreground/10"}),w&&jsxRuntime.jsx("p",{className:"mt-1.5 text-xs text-red-500",children:"Cannot transfer a key to yourself"})]}),b&&d.trim().length>0&&!w&&jsxRuntime.jsx("div",{className:"rounded-xl border border-amber-500/30 bg-amber-500/5 p-4",children:jsxRuntime.jsxs("div",{className:"flex items-start gap-3",children:[jsxRuntime.jsx(lucideReact.AlertTriangle,{className:"mt-0.5 h-5 w-5 shrink-0 text-amber-500"}),jsxRuntime.jsxs("div",{className:"space-y-3",children:[jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Confirm Transfer"}),jsxRuntime.jsxs("p",{className:"mt-1 text-xs text-muted-foreground",children:["You are about to transfer key"," ",jsxRuntime.jsx("span",{className:"font-mono font-medium",children:b.keyIndex?`#${b.keyIndex}`:b.id.slice(0,12)})," ","(",I(b.tokenBalance)," tokens) to"," ",jsxRuntime.jsxs("span",{className:"font-mono font-medium",children:[d.trim().slice(0,20),"..."]})]})]}),jsxRuntime.jsxs("label",{className:"flex items-start gap-2 cursor-pointer",children:[jsxRuntime.jsx("input",{type:"checkbox",checked:i,onChange:k=>o(k.target.checked),className:"mt-0.5 h-4 w-4 rounded border-border"}),jsxRuntime.jsx("span",{className:"text-xs text-muted-foreground",children:"I confirm this transfer is permanent and cannot be undone."})]})]})]})}),a&&jsxRuntime.jsx("p",{className:"text-sm text-red-500",children:a}),jsxRuntime.jsx("button",{onClick:T,disabled:!P,className:u("flex w-full items-center justify-center gap-2 rounded-lg px-4 py-3 text-sm font-medium transition-all",P?"bg-foreground text-background hover:opacity-90":"bg-muted text-muted-foreground cursor-not-allowed"),children:m?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("div",{className:"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent"}),"Transferring..."]}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Send,{className:"h-4 w-4"}),"Transfer Key"]})})]})}var Jt=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"},{id:"transfer",label:"Transfer"}];function Zt({active:e,onChange:t}){return jsxRuntime.jsx("div",{role:"tablist","aria-label":"Key actions",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:Jt.map(({id:r,label:s})=>jsxRuntime.jsx("button",{role:"tab","aria-selected":e===r,"aria-controls":`panel-${r}`,id:`tab-${r}`,onClick:()=>t(r),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium transition-all",e===r?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:jsxRuntime.jsx("span",{className:"inline",children:s})},r))})}function Xt({defaultTab:e="buy",className:t,style:r}){let[s,x]=Kt.useState(e);return jsxRuntime.jsxs("div",{className:u("flex flex-col",t),style:r,children:[jsxRuntime.jsx("div",{className:"sticky top-0 z-10 bg-background/80 px-5 pb-3 pt-2 sm:pt-5 backdrop-blur-sm sm:px-10 md:px-16 lg:px-20",children:jsxRuntime.jsx("div",{className:"mx-auto max-w-xl",children:jsxRuntime.jsx(Zt,{active:s,onChange:x})})}),jsxRuntime.jsx("div",{className:"flex flex-1 flex-col px-5 pb-8 sm:px-10 md:px-16 md:pb-12 lg:px-20",children:jsxRuntime.jsx("div",{className:"mx-auto w-full max-w-xl flex-1",children:jsxRuntime.jsxs("div",{role:"tabpanel",id:`panel-${s}`,"aria-labelledby":`tab-${s}`,children:[s==="buy"&&jsxRuntime.jsx(we,{className:"flex-1"}),s==="use"&&jsxRuntime.jsx(Pe,{className:"flex-1"}),s==="sell"&&jsxRuntime.jsx(Se,{className:"flex-1"}),s==="transfer"&&jsxRuntime.jsx(Re,{className:"flex-1"})]})})})]})}function Ht({apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:x,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p,onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P,defaultTab:T,className:j,style:k}){return jsxRuntime.jsx(oe,{config:{apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:x,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p},callbacks:{onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P},children:jsxRuntime.jsx(Xt,{defaultTab:T,className:j,style:k})})}var Te=20;function Ue({nodeKey:e,className:t,style:r}){let[s,x]=Kt.useState(false),[m,f]=Kt.useState(false),a=Kt.useRef(null),{entries:n,loading:c}=de(s?e.id:null);Kt.useEffect(()=>()=>{a.current&&clearTimeout(a.current);},[]);let d=Kt.useCallback(()=>{e.key&&(navigator.clipboard.writeText(e.key),f(true),a.current&&clearTimeout(a.current),a.current=setTimeout(()=>f(false),2e3));},[e.key]),p=e.status==="active"?"text-green-500":e.status==="expired"?"text-red-500":"text-yellow-500",i=n.slice(0,Te);return jsxRuntime.jsxs("div",{className:u("rounded-lg border bg-background",t),style:r,children:[jsxRuntime.jsxs("div",{className:"p-4",children:[jsxRuntime.jsxs("div",{className:"mb-3 flex items-center justify-between",children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsx("button",{onClick:()=>x(!s),"aria-expanded":s,"aria-label":s?"Collapse ledger":"Expand ledger",className:"text-muted-foreground hover:text-foreground",children:s?jsxRuntime.jsx(lucideReact.ChevronDown,{className:"h-4 w-4"}):jsxRuntime.jsx(lucideReact.ChevronRight,{className:"h-4 w-4"})}),jsxRuntime.jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]})]}),jsxRuntime.jsx("span",{className:u("text-xs font-medium capitalize",p),children:e.status})]}),e.key&&jsxRuntime.jsxs("div",{className:"mb-3 flex items-center gap-2",children:[jsxRuntime.jsx("code",{className:"flex-1 truncate rounded bg-muted px-2 py-1 text-xs text-muted-foreground",children:e.key}),jsxRuntime.jsx("button",{onClick:d,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground",children:m?jsxRuntime.jsx(lucideReact.Check,{className:"h-3.5 w-3.5 text-green-500"}):jsxRuntime.jsx(lucideReact.Copy,{className:"h-3.5 w-3.5"})})]}),jsxRuntime.jsx(q,{current:e.tokenBalance,max:e.maxTokens}),jsxRuntime.jsxs("div",{className:"mt-2 flex items-center justify-between text-xs text-muted-foreground",children:[jsxRuntime.jsxs("span",{children:["Created ",Y(e.createdAt)]}),e.expiresAt&&jsxRuntime.jsxs("span",{children:["Expires ",Y(e.expiresAt)]})]})]}),s&&jsxRuntime.jsxs("div",{className:"border-t px-4 py-3",children:[jsxRuntime.jsx("h4",{className:"mb-2 text-xs font-medium text-muted-foreground",children:"Ledger"}),c?jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:"Loading..."}):i.length===0?jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:"No ledger entries."}):jsxRuntime.jsxs("div",{className:"space-y-1.5",children:[i.map(o=>jsxRuntime.jsxs("div",{className:"flex items-center justify-between text-xs",children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsxs("span",{className:u("font-medium",o.type==="credit"||o.type==="reward"?"text-green-500":"text-red-500"),children:[o.type==="credit"||o.type==="reward"?"+":"-",I(Math.abs(o.amount))]}),jsxRuntime.jsx("span",{className:"text-muted-foreground",children:o.description})]}),jsxRuntime.jsx("span",{className:"text-muted-foreground",children:Y(o.createdAt)})]},o.id)),n.length>Te&&jsxRuntime.jsxs("p",{className:"pt-1 text-xs text-muted-foreground",children:["Showing ",Te," of ",n.length," entries"]})]})]})]})}var lr=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"}];function ne({baseHref:e}){return jsxRuntime.jsx("div",{className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5 mb-6",children:lr.map(({id:t,label:r})=>jsxRuntime.jsx("a",{href:`${e}?tab=${t}`,className:"flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium text-muted-foreground hover:text-foreground transition-all",children:r},t))})}function cr({getKeyHref:e="/keys/get",showTabs:t=true,className:r,style:s}){let{keys:x,totalBalance:m,loading:f,error:a,refresh:n}=G();return f?jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(ne,{baseHref:e}),jsxRuntime.jsx(J,{count:3})]}):a?jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(ne,{baseHref:e}),jsxRuntime.jsxs("div",{className:"flex flex-col items-center justify-center gap-4 py-12",children:[jsxRuntime.jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsxRuntime.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:a})]}),jsxRuntime.jsx("button",{onClick:()=>n(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]})]}):x.length===0?jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(ne,{baseHref:e}),jsxRuntime.jsxs("div",{className:"flex flex-col items-center justify-center gap-4 rounded-lg border border-dashed py-12",children:[jsxRuntime.jsx(lucideReact.KeyRound,{className:"h-10 w-10 text-muted-foreground"}),jsxRuntime.jsxs("div",{className:"text-center",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"No keys yet"}),jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:"Get your first node key to start earning."})]}),e&&jsxRuntime.jsx("a",{href:e,className:"rounded-lg bg-foreground px-4 py-2 text-sm font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]})]}):jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(ne,{baseHref:e}),jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsxs("p",{className:"text-sm text-muted-foreground",children:[x.length," key",x.length!==1?"s":""," \xB7 Total balance: ",I(m)]}),e&&jsxRuntime.jsx("a",{href:e,className:"rounded-md bg-foreground px-3 py-1.5 text-xs font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]}),x.map(c=>jsxRuntime.jsx(Ue,{nodeKey:c},c.id))]})}
2
- exports.BuyKeyWidget=Ht;exports.BuyPanel=we;exports.KeyBalanceBar=q;exports.KeyCard=Ue;exports.KeyList=cr;exports.KeyUtilsProvider=oe;exports.MintSuccess=ve;exports.SellPanel=Se;exports.SolanaPayButton=Ne;exports.TransferPanel=Re;exports.UsePanel=Pe;exports.calculateBalancePercentage=Be;exports.cn=u;exports.detectPlatform=Le;exports.formatDate=Y;exports.formatTokens=I;exports.getBalanceColor=Ie;exports.useKeyLedger=de;exports.useKeyUtilsContext=C;exports.useKeys=G;exports.useListKey=pe;exports.useMintKey=me;exports.usePricing=ie;exports.useStripeCheckout=xe;exports.useTransferKey=ye;
1
+ 'use strict';var clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),Rt=require('react'),jsxRuntime=require('react/jsx-runtime'),lucideReact=require('lucide-react');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var Rt__default=/*#__PURE__*/_interopDefault(Rt);function A(){if(typeof document>"u")return {};let e=document.cookie.match(/(?:^|;\s*)__csrf=([^;]*)/);return e?{"x-csrf-token":e[1]}:{}}function u(...e){return tailwindMerge.twMerge(clsx.clsx(e))}function I(e){return e==null?"0":e>=1e9?`${(e/1e9).toFixed(1)}B`:e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:e.toLocaleString()}function Ie(e,t){return t<=0?0:Math.min(100,Math.round(e/t*100))}function Le(e){return e>=70?"bg-green-500":e>=30?"bg-yellow-500":"bg-red-500"}function H(e){let t=typeof e=="string"&&/^\d+$/.test(e)?Number(e):e,r=new Date(t);return isNaN(r.getTime())?String(e):r.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}function Ee(){if(typeof navigator>"u")return "mac";let e=navigator.userAgent.toLowerCase();return /iphone|ipad|ipod/.test(e)?"ios":/android/.test(e)?"android":/win/.test(e)?"windows":/linux/.test(e)?"linux":"mac"}var je=Rt.createContext(null);function C(){let e=Rt.useContext(je);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function ae({config:e,callbacks:t={},children:r}){typeof e.apiBaseUrl!="string"&&console.error("[KeyUtils] apiBaseUrl must be a string");let s=Rt.useMemo(()=>({config:e,callbacks:t}),[e,t]);return jsxRuntime.jsx(je.Provider,{value:s,children:r})}function le(){let{config:e}=C(),[t,r]=Rt.useState(null),[s,x]=Rt.useState(true),[m,f]=Rt.useState(null),a=Rt.useRef(true),n=Rt.useRef(e.apiBaseUrl);n.current=e.apiBaseUrl;let c=async()=>{try{a.current&&(x(!0),f(null));let d=await fetch(`${n.current}/api/keys/pricing`,{credentials:"include"});if(!d.ok){let i=`Pricing unavailable (${d.status})`;try{let o=await d.json();o.error&&(i=o.error);}catch{}throw new Error(i)}let p=await d.json();a.current&&r(p);}catch(d){a.current&&f(d instanceof Error?d.message:"Failed to fetch pricing");}finally{a.current&&x(false);}};return Rt.useEffect(()=>{a.current=true,c();let d=setInterval(c,6e4);return ()=>{a.current=false,clearInterval(d);}},[]),{pricing:t,loading:s,error:m,refresh:c}}function ct(e){return {id:e.id||"",keyIndex:e.keyIndex??e.key_index??null,key:e.key||e.keyPrefix||"",userId:e.userId||e.user_id||"",status:e.status||"active",tokenBalance:e.tokenBalance??e.currentTokenBalance??e.current_token_balance??0,maxTokens:e.maxTokens??e.initialTokenBalance??e.initial_token_balance??0,createdAt:String(e.createdAt??e.created_at??""),expiresAt:e.expiresAt,label:e.label||e.keyPrefix||e.key_prefix||void 0,paperWork:e.paperWork||e.paper_work||void 0,stackId:e.stackId,stackName:e.stackName}}function Q(){let{config:e}=C(),[t,r]=Rt.useState([]),[s,x]=Rt.useState(true),[m,f]=Rt.useState(null),a=Rt.useRef(true),n=e.apiBaseUrl,c=Rt.useCallback(async()=>{try{x(!0),f(null);let p=await fetch(`${n}/api/keys`,{credentials:"include"});if(!p.ok){let l=`Failed to fetch keys (${p.status})`;try{let b=await p.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let i=await p.json(),o=Array.isArray(i)?i:i.keys??[];a.current&&r(o.map(ct));}catch(p){a.current&&f(p instanceof Error?p.message:"Failed to fetch keys");}finally{a.current&&x(false);}},[n]);Rt.useEffect(()=>(a.current=true,c(),()=>{a.current=false;}),[c]);let d=t.reduce((p,i)=>p+i.tokenBalance,0);return {keys:t,totalBalance:d,loading:s,error:m,refresh:c}}function ue(e){let{config:t}=C(),[r,s]=Rt.useState([]),[x,m]=Rt.useState(false),[f,a]=Rt.useState(null),n=Rt.useRef(true),c=t.apiBaseUrl,d=Rt.useCallback(async()=>{if(e)try{m(!0),a(null);let p=await fetch(`${c}/api/keys/${e}/ledger`,{credentials:"include"});if(!p.ok){let o=`Failed to fetch ledger (${p.status})`;try{let l=await p.json();l.error&&(o=l.error);}catch{}throw new Error(o)}let i=await p.json();n.current&&s(Array.isArray(i)?i:i.entries??[]);}catch(p){n.current&&a(p instanceof Error?p.message:"Failed to fetch ledger");}finally{n.current&&m(false);}},[c,e]);return Rt.useEffect(()=>(n.current=true,d(),()=>{n.current=false;}),[d]),{entries:r,loading:x,error:f,refresh:d}}function fe(){let{config:e,callbacks:t}=C(),[r,s]=Rt.useState(false),[x,m]=Rt.useState(null),[f,a]=Rt.useState(null);return {mint:Rt.useCallback(async(c,d,p=1)=>{try{s(!0),a(null),t.onPaymentComplete?.(c,d);let i=await fetch(`${e.apiBaseUrl}/api/keys/mint`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({paymentMethod:c,paymentRef:d,quantity:p})});if(!i.ok){let w="Key generation failed";try{let P=await i.json();P.error&&(w=P.error);}catch{}throw new Error(w)}let o=await i.json(),l=o.keys?.[0]||o,b={success:!0,key:{id:l.keyId||l.id||"",key:l.key||"",userId:l.userId||"",status:"active",tokenBalance:l.tokenBalance??l.currentTokenBalance??0,maxTokens:l.initialTokenBalance??l.tokenBalance??0,createdAt:String(l.createdAt||Date.now())},transactionId:d};return m(b),t.onMintSuccess?.(b),b}catch(i){let o=i instanceof Error?i:new Error("Key generation failed");return a(o.message),t.onMintError?.(o),{success:false,error:o.message}}finally{s(false);}},[e.apiBaseUrl,t]),minting:r,result:x,error:f}}function xe(){let{config:e,callbacks:t}=C(),[r,s]=Rt.useState(false),[x,m]=Rt.useState(null),[f,a]=Rt.useState(null),n=Rt.useRef(true),c=Rt.useCallback(async(p,i)=>{try{s(!0),a(null);let o=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({askPriceCents:i,stackId:e.stackId,stackName:e.stackName})});if(!o.ok){let b=`Listing failed (${o.status})`;try{let w=await o.json();w.error&&(b=w.error);}catch{}throw new Error(b)}let l=await o.json();return n.current&&(m(l),t.onListingCreated?.(l)),l}catch(o){let l=o instanceof Error?o.message:"Listing failed";return n.current&&a(l),null}finally{n.current&&s(false);}},[e.apiBaseUrl,e.stackId,e.stackName,t]),d=Rt.useCallback(async p=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"DELETE",headers:{...A()},credentials:"include"});if(!i.ok){let o=`Delist failed (${i.status})`;try{let l=await i.json();l.error&&(o=l.error);}catch{}throw new Error(o)}return n.current&&m(null),!0}catch(i){let o=i instanceof Error?i.message:"Delist failed";return n.current&&a(o),false}finally{n.current&&s(false);}},[e.apiBaseUrl]);return {listKey:c,delistKey:d,listing:r,result:x,error:f}}function ge(){let{config:e}=C(),[t,r]=Rt.useState(false),[s,x]=Rt.useState(null),m=Rt.useRef(true);return {createSession:Rt.useCallback(async(a,n)=>{try{r(!0),x(null);let c=await fetch(`${e.apiBaseUrl}/api/keys/stripe-session`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({priceCents:a,quantity:n,stackId:e.stackId,referrerUrl:window.location.href})});if(!c.ok){let p=`Checkout failed (${c.status})`;try{let i=await c.json();i.error&&(p=i.error);}catch{}throw new Error(p)}let{url:d}=await c.json();if(d){try{sessionStorage.setItem("keyutils_stripe_pending","1");}catch{}window.location.href=d;}else throw new Error("No checkout URL returned")}catch(c){if(m.current){let d=c instanceof Error?c.message:"Checkout failed";x(d),r(false);}}},[e.apiBaseUrl,e.stackId]),loading:t,error:s}}function be(){let{config:e,callbacks:t}=C(),[r,s]=Rt.useState(false),[x,m]=Rt.useState(null),[f,a]=Rt.useState(null),n=Rt.useRef(true);return {transferKey:Rt.useCallback(async(d,p)=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${d}/transfer`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({recipientId:p})});if(!i.ok){let l=`Transfer failed (${i.status})`;try{let b=await i.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let o=await i.json();return n.current&&(m(o),t.onTransferComplete?.(o)),o}catch(i){let o=i instanceof Error?i.message:"Transfer failed";return n.current&&a(o),null}finally{n.current&&s(false);}},[e.apiBaseUrl,t]),transferring:r,result:x,error:f}}var De=/^[1-9A-HJ-NP-Za-km-z]{32,44}$/;function ve({amountSol:e,onSuccess:t,onError:r,disabled:s,className:x,style:m}){let{config:f}=C(),[a,n]=Rt.useState(false),[c,d]=Rt.useState(null),p=!!(f.merchantWallet&&De.test(f.merchantWallet)),i=Rt.useCallback(async()=>{if(p)try{n(!0),d(null);let{Connection:o,PublicKey:l,Transaction:b,SystemProgram:w,LAMPORTS_PER_SOL:P}=await import('@solana/web3.js'),T=typeof window<"u"?window.solana:void 0;if(!T||typeof T!="object"||!T.isPhantom)throw new Error("Phantom wallet not found. Please install Phantom.");let j=T,k;try{k=new l(f.merchantWallet);}catch{throw new Error("Invalid merchant wallet address.")}let Y=await j.connect(),_=new l(Y.publicKey.toString()),K=new o(f.solanaRpcUrl||"https://api.mainnet-beta.solana.com"),{blockhash:G}=await K.getLatestBlockhash(),F=BigInt(Math.floor(e*1e9)),Z=f.protocolTreasuryWallet,B=f.protocolFeeBps??500,O=new b({recentBlockhash:G,feePayer:_});if(Z&&De.test(Z)&&B>0){let X=F*BigInt(B)/10000n,Je=F-X,Ze=new l(Z);O.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(Je)}),w.transfer({fromPubkey:_,toPubkey:Ze,lamports:Number(X)}));}else O.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(F)}));let{signature:se}=await j.signAndSendTransaction(O);t(se);}catch(o){let l=o instanceof Error?o:new Error("Payment failed");d(l.message),r?.(l);}finally{n(false);}},[e,f.merchantWallet,p,t,r]);return jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("button",{onClick:i,disabled:s||a||!p,"aria-label":`Pay ${e.toFixed(4)} SOL`,className:u("flex w-full items-center justify-center gap-2 rounded-lg bg-purple-600 px-4 py-6 font-medium text-white transition-colors hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed",x),style:m,children:a?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Loader2,{className:"h-4 w-4 animate-spin"}),"Processing..."]}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:["Pay ",e.toFixed(4)," SOL"]})}),c&&jsxRuntime.jsx("p",{className:"mt-2 text-center text-xs text-red-500",children:c})]})}function ke({result:e,className:t,style:r}){let[s,x]=Rt.useState(false),m=Rt.useRef(null);Rt.useEffect(()=>()=>{m.current&&clearTimeout(m.current);},[]);let f=Rt.useCallback(()=>{e.key?.key&&(navigator.clipboard.writeText(e.key.key),x(true),m.current&&clearTimeout(m.current),m.current=setTimeout(()=>x(false),2e3));},[e.key?.key]);return !e.success||!e.key?null:jsxRuntime.jsxs("div",{className:u("rounded-lg border border-green-500/20 bg-green-500/10 p-6 text-center",t),style:r,children:[jsxRuntime.jsx(lucideReact.CheckCircle,{className:"mx-auto mb-3 h-12 w-12 text-green-500"}),jsxRuntime.jsx("h3",{className:"mb-2 text-lg font-semibold text-foreground",children:"Key Generated!"}),jsxRuntime.jsx("p",{className:"mb-4 text-sm text-muted-foreground",children:"Your node key has been successfully generated."}),jsxRuntime.jsxs("div",{className:"mx-auto flex max-w-md items-center gap-2 rounded-md border bg-background p-3",children:[jsxRuntime.jsx("code",{className:"flex-1 truncate text-xs text-foreground",children:e.key.key}),jsxRuntime.jsx("button",{onClick:f,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",children:s?jsxRuntime.jsx(lucideReact.Check,{className:"h-4 w-4 text-green-500"}):jsxRuntime.jsx(lucideReact.Copy,{className:"h-4 w-4"})})]})]})}function $({className:e}){return jsxRuntime.jsx("div",{className:u("animate-pulse rounded-xl bg-muted",e)})}function we(){return jsxRuntime.jsxs("div",{className:"space-y-6",children:[jsxRuntime.jsxs("div",{className:"px-6 py-10 flex flex-col items-center gap-3",children:[jsxRuntime.jsx($,{className:"h-14 w-48"}),jsxRuntime.jsx($,{className:"h-5 w-64"})]}),jsxRuntime.jsx($,{className:"h-[72px] w-full rounded-2xl"}),jsxRuntime.jsx($,{className:"h-[68px] w-full rounded-2xl"}),jsxRuntime.jsx($,{className:"h-[60px] w-full rounded-2xl"})]})}function J({count:e=3}){return jsxRuntime.jsx("div",{className:"space-y-3",children:Array.from({length:e}).map((t,r)=>jsxRuntime.jsxs("div",{className:"rounded-xl border p-4 space-y-3",children:[jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsx($,{className:"h-4 w-32"}),jsxRuntime.jsx($,{className:"h-4 w-16"})]}),jsxRuntime.jsx($,{className:"h-2 w-full rounded-full"}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx($,{className:"h-3 w-24"}),jsxRuntime.jsx($,{className:"h-3 w-20"})]})]},r))})}function Mt({quantity:e,max:t,onChange:r}){return jsxRuntime.jsxs("div",{className:"flex items-center justify-between rounded-2xl bg-muted/20 px-6 py-6",children:[jsxRuntime.jsx("span",{className:"text-sm font-medium text-foreground",children:"Quantity"}),jsxRuntime.jsxs("div",{className:"flex items-center gap-0 rounded-xl bg-background",children:[jsxRuntime.jsx("button",{onClick:()=>r(Math.max(1,e-1)),disabled:e<=1,"aria-label":"Decrease quantity",className:"flex h-12 w-12 items-center justify-center rounded-l-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsxRuntime.jsx(lucideReact.Minus,{className:"h-5 w-5"})}),jsxRuntime.jsx("span",{className:"flex h-12 w-14 items-center justify-center border-x text-xl font-bold text-foreground","aria-live":"polite",children:e}),jsxRuntime.jsx("button",{onClick:()=>r(Math.min(t,e+1)),disabled:e>=t,"aria-label":"Increase quantity",className:"flex h-12 w-12 items-center justify-center rounded-r-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsxRuntime.jsx(lucideReact.Plus,{className:"h-5 w-5"})})]})]})}function Ge({pricing:e,quantity:t}){let[r,s]=Rt.useState(false),x=e.priceUsd*t;return jsxRuntime.jsxs("div",{className:"rounded-2xl border bg-background",children:[jsxRuntime.jsxs("button",{onClick:()=>s(!r),"aria-expanded":r,className:"flex w-full items-center justify-between px-6 py-6 text-left",children:[jsxRuntime.jsxs("span",{className:"text-foreground",children:[jsxRuntime.jsxs("span",{className:"text-xl font-bold",children:["$",x.toFixed(2)]})," ",jsxRuntime.jsx("span",{className:"text-sm text-muted-foreground",children:"total fees included"})]}),r?jsxRuntime.jsx(lucideReact.ChevronUp,{className:"h-5 w-5 text-muted-foreground"}):jsxRuntime.jsx(lucideReact.ChevronDown,{className:"h-5 w-5 text-muted-foreground"})]}),r&&jsxRuntime.jsxs("div",{className:"border-t px-6 pb-8 pt-4 space-y-3 text-sm",children:[jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsxs("span",{className:"text-muted-foreground",children:["Node Key \xD7 ",t]}),jsxRuntime.jsxs("span",{className:"text-foreground",children:["$",(e.priceUsd*t).toFixed(2)]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Keys sold"}),jsxRuntime.jsx("span",{className:"text-foreground",children:e.keysSold})]}),e.daysUntilHalving>0&&jsxRuntime.jsxs("div",{className:"flex justify-between text-muted-foreground",children:[jsxRuntime.jsx("span",{children:"Next refresh"}),jsxRuntime.jsxs("span",{children:[e.daysUntilHalving," day",e.daysUntilHalving!==1?"s":""]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between border-t pt-3 font-semibold",children:[jsxRuntime.jsx("span",{className:"text-foreground",children:"Total"}),jsxRuntime.jsxs("span",{className:"text-foreground",children:["$",x.toFixed(2)]})]})]})]})}function Pe({className:e,style:t}){let{config:r}=C(),{pricing:s,loading:x,error:m,refresh:f}=le(),{mint:a,minting:n,result:c,error:d}=fe(),{createSession:p,loading:i,error:o}=ge(),[l,b]=Rt.useState(1),[w,P]=Rt.useState(r.paymentMethods?.includes("stripe")?"stripe":"solana"),[T,j]=Rt.useState(0),[k,Y]=Rt.useState(false),_=Rt__default.default.useRef(l);_.current=l;let K=Math.max(1,r.maxQuantity||5),G=[...r.paymentMethods||["solana"]].sort((B,O)=>B==="stripe"?-1:O==="stripe"?1:0);if(Rt.useEffect(()=>{if(typeof window>"u")return;let O=new URLSearchParams(window.location.search).get("session_id");if(!O){try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}return}if(/^cs_(test|live)_/.test(O)&&!k&&!c?.success){let se=false;try{se=sessionStorage.getItem("keyutils_stripe_pending")==="1";}catch{}if(!se)return;try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}Y(true);let X=new URL(window.location.href);X.searchParams.delete("session_id"),window.history.replaceState({},"",X.toString()),a("stripe",O,_.current);}},[k,c,a]),c?.success)return jsxRuntime.jsx("div",{className:u("flex flex-col items-center justify-center",e),style:t,children:jsxRuntime.jsx(ke,{result:c})});if(k||n)return jsxRuntime.jsx("div",{className:u("flex flex-col",e),style:t,children:jsxRuntime.jsx(we,{})});if(x)return jsxRuntime.jsx("div",{className:u("flex flex-col",e),style:t,children:jsxRuntime.jsx(we,{})});if(m||!s)return jsxRuntime.jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-24",e),style:t,children:[jsxRuntime.jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load pricing"}),jsxRuntime.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m||"Please check your connection and try again."})]}),jsxRuntime.jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let F=async B=>{j(2),await a(w,B,l);},Z=()=>{p(s.priceCents,l);};return jsxRuntime.jsx("div",{className:u("flex flex-col",e),style:t,children:jsxRuntime.jsxs("div",{className:"space-y-6",children:[T===0&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[r.keyImage&&jsxRuntime.jsx("img",{src:r.keyImage,alt:"Node Key",className:r.keyImageClass||"w-1/2 mx-auto"}),jsxRuntime.jsxs("div",{className:"px-6 py-10 text-center",children:[jsxRuntime.jsxs("p",{className:"text-5xl font-bold tracking-tight text-foreground md:text-6xl",children:["$",s.priceUsd.toFixed(2)]}),jsxRuntime.jsxs("p",{className:"mt-2 text-base text-muted-foreground",children:["per key \xB7 ",s.tokenAllocationFormatted||I(s.tokenAllocation)," tokens included"]})]}),jsxRuntime.jsx(Mt,{quantity:l,max:K,onChange:b}),jsxRuntime.jsx(Ge,{pricing:s,quantity:l}),jsxRuntime.jsx("button",{onClick:()=>j(1),className:"w-full rounded-2xl bg-foreground py-6 text-center text-base font-semibold text-background transition-colors hover:bg-foreground/90",children:"Continue to Payment"})]}),T===1&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[G.length>1&&jsxRuntime.jsx("div",{role:"tablist",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:G.map(B=>jsxRuntime.jsxs("button",{role:"tab","aria-selected":w===B,onClick:()=>P(B),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-4 text-sm font-medium transition-colors",w===B?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:[B==="stripe"?jsxRuntime.jsx(lucideReact.CreditCard,{className:"h-5 w-5"}):jsxRuntime.jsx(lucideReact.Wallet,{className:"h-5 w-5"}),B==="stripe"?"Credit Card":"Crypto"]},B))}),jsxRuntime.jsx(Ge,{pricing:s,quantity:l}),w==="stripe"?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("button",{onClick:Z,disabled:i,className:"flex w-full items-center justify-center gap-2 rounded-2xl bg-foreground py-6 text-base font-semibold text-background transition-colors hover:bg-foreground/90 disabled:opacity-50",children:i?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Loader2,{className:"h-5 w-5 animate-spin"}),"Redirecting to Stripe..."]}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.CreditCard,{className:"h-5 w-5"}),"Pay with Card"]})}),o&&jsxRuntime.jsx("p",{className:"text-center text-sm text-red-500",children:o})]}):w==="solana"?jsxRuntime.jsx(ve,{amountSol:s.priceSol??0,onSuccess:F,className:"rounded-2xl py-5 text-base"}):null,d&&jsxRuntime.jsx("p",{className:"text-center text-sm text-red-500",children:d}),jsxRuntime.jsx("button",{onClick:()=>j(0),className:"w-full py-3 text-center text-sm text-muted-foreground hover:text-foreground transition-colors",children:"\u2190 Back"})]})]})})}var Dt={ios:"iOS",android:"Android",windows:"Windows",mac:"macOS",linux:"Linux"},Ot=["mac","windows","linux","ios","android"];function Ce({downloads:e,className:t,style:r}){let{config:s}=C(),x=Rt.useMemo(()=>Ee(),[]),m=e||Ot.map(n=>({platform:n,label:Dt[n],url:"#",compatible:n===x})),f=m.find(n=>n.compatible)||m[0],a=m.filter(n=>n.platform!==f.platform);return jsxRuntime.jsxs("div",{className:u("space-y-8",t),style:r,children:[jsxRuntime.jsxs("div",{className:"flex flex-col items-center gap-6 pt-4 mt-4",children:[s.aispImage&&jsxRuntime.jsx("img",{src:s.aispImage,alt:"aiSP",className:"w-full sm:w-1/2 mx-auto px-4 sm:px-0"}),jsxRuntime.jsxs("div",{className:"text-center",children:[jsxRuntime.jsx("p",{className:"text-lg sm:text-2xl font-medium text-foreground",children:"Download the AI Service Provider App"}),jsxRuntime.jsx("p",{className:"mt-1 text-sm sm:text-base text-muted-foreground",children:"Load your keys and run your node."})]}),jsxRuntime.jsxs("a",{href:f.url,className:"inline-flex items-center gap-3 rounded-full px-10 py-4 text-lg font-semibold text-white transition-colors hover:opacity-90",style:{backgroundColor:"#0900f4"},children:[jsxRuntime.jsx(lucideReact.Download,{className:"h-5 w-5"}),"Get aiSP for ",f.label]})]}),jsxRuntime.jsxs("p",{className:"text-center text-sm text-muted-foreground",children:["aiSP is also available on"," ",a.map((n,c)=>jsxRuntime.jsxs(Rt__default.default.Fragment,{children:[c>0&&(c===a.length-1?" and ":", "),jsxRuntime.jsx("a",{href:n.url,className:"font-medium underline transition-colors hover:text-foreground",style:{color:"#066bff"},children:n.label})]},n.platform)),"."]}),jsxRuntime.jsxs("div",{className:"flex flex-col items-center gap-2 mt-12",children:[jsxRuntime.jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["Source code is available on",jsxRuntime.jsx("a",{href:"https://github.com/stack-net",target:"_blank",rel:"noopener noreferrer",className:"text-foreground underline hover:text-foreground/80 color-[#0900f4]",children:"Github"})]}),jsxRuntime.jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["By downloading, you agree to the",jsxRuntime.jsx("a",{href:s.termsUrl||"/terms",className:"text-foreground underline hover:text-foreground/80",children:"Open Source Applications Terms"})]})]})]})}function z({current:e,max:t,className:r,style:s,showLabel:x=true}){let m=Ie(e,t),f=Le(m);return jsxRuntime.jsxs("div",{className:u("w-full",r),style:s,children:[x&&jsxRuntime.jsxs("div",{className:"mb-1 flex items-center justify-between text-xs text-muted-foreground",children:[jsxRuntime.jsxs("span",{children:[I(e)," / ",I(t)]}),jsxRuntime.jsxs("span",{children:[m,"%"]})]}),jsxRuntime.jsx("div",{className:"h-2 w-full overflow-hidden rounded-full bg-muted",children:jsxRuntime.jsx("div",{className:u("h-full rounded-full transition-all duration-500",f),style:{width:`${m}%`}})})]})}function Gt({nodeKey:e,selected:t,onSelect:r}){return jsxRuntime.jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsxRuntime.jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsxRuntime.jsx(lucideReact.Check,{className:"h-3 w-3 text-background"})}),jsxRuntime.jsxs("div",{className:"min-w-0 flex-1",children:[jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsxRuntime.jsx("span",{className:u("text-xs font-medium capitalize",e.status==="active"?"text-green-500":"text-muted-foreground"),children:e.status})]}),jsxRuntime.jsx(z,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function Ke({className:e,style:t}){let{config:r}=C(),{keys:s,loading:x,error:m,refresh:f}=Q(),{listKey:a,listing:n,result:c,error:d}=xe(),[p,i]=Rt.useState(null),[o,l]=Rt.useState(""),[b,w]=Rt.useState(false),P=s.find(K=>K.id===p),T=parseInt(o.replace(/[^0-9]/g,""),10)||0,j=T>0&&Number.isFinite(T),k=!!P&&j&&b&&!n,Y=async()=>{if(!k||!P)return;let K=T*100;await a(P.id,K)&&f();};if(c)return jsxRuntime.jsxs("div",{className:u("flex flex-col items-center gap-4 rounded-xl bg-green-500/10 py-12",e),style:t,children:[jsxRuntime.jsx(lucideReact.CheckCircle,{className:"h-12 w-12 text-green-500"}),jsxRuntime.jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Key Listed!"}),jsxRuntime.jsx("p",{className:"text-sm text-muted-foreground",children:"Your key is now on the Global Open AI Network marketplace."}),jsxRuntime.jsxs("p",{className:"text-xs text-muted-foreground",children:["Listing ID: ",jsxRuntime.jsx("code",{children:c.listingId})]}),jsxRuntime.jsxs("a",{href:`https://market.stacknet.org/keys/${c.keyId}`,target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-2 rounded-xl bg-foreground px-6 py-3 text-sm font-semibold text-background transition-colors hover:bg-foreground/90",children:[jsxRuntime.jsx(lucideReact.ExternalLink,{className:"h-4 w-4"}),"View Listing"]})]});if(x)return jsxRuntime.jsxs("div",{className:u("space-y-5 px-1",e),style:t,children:[jsxRuntime.jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsxRuntime.jsx(J,{count:2})]});if(m)return jsxRuntime.jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-16",e),style:t,children:[jsxRuntime.jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsxRuntime.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m})]}),jsxRuntime.jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let _=s.filter(K=>K.status==="active");return _.length===0?jsxRuntime.jsxs("div",{className:u("flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed py-16",e),style:t,children:[jsxRuntime.jsx(lucideReact.AlertTriangle,{className:"h-8 w-8 text-muted-foreground"}),jsxRuntime.jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys to sell."})]}):jsxRuntime.jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsxRuntime.jsx("div",{className:"space-y-2",children:_.map(K=>jsxRuntime.jsx(Gt,{nodeKey:K,selected:p===K.id,onSelect:()=>i(K.id)},K.id))})]}),P&&jsxRuntime.jsxs("div",{className:"rounded-xl border bg-muted/30 p-5 space-y-2 text-sm",children:[P.keyIndex&&jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Key #"}),jsxRuntime.jsxs("span",{className:"text-foreground font-semibold",children:["#",P.keyIndex]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Key ID"}),jsxRuntime.jsx("code",{className:"text-xs text-foreground",children:P.id})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Originating Stack"}),jsxRuntime.jsx("span",{className:"text-foreground",children:r.stackName||"Unknown"})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Tokens (remaining / total)"}),jsxRuntime.jsxs("span",{className:"text-foreground",children:[I(P.tokenBalance)," / ",I(P.maxTokens)]})]}),P.paperWork&&jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Paper earned"}),jsxRuntime.jsx("span",{className:"text-foreground",children:P.paperWork})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Created"}),jsxRuntime.jsx("span",{className:"text-foreground",children:H(P.createdAt)})]})]}),jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("label",{htmlFor:"listing-price",className:"mb-2 block text-sm sm:text-lg font-semibold text-foreground",children:"Listing Price (USD)"}),jsxRuntime.jsxs("div",{className:"relative",children:[jsxRuntime.jsx("span",{className:"absolute left-4 top-1/2 -translate-y-1/2 text-2xl font-bold text-muted-foreground",children:"$"}),jsxRuntime.jsx("input",{id:"listing-price",type:"text",inputMode:"numeric",value:o,onChange:K=>{let G=K.target.value.replace(/[^0-9]/g,""),F=parseInt(G,10);l(isNaN(F)?"":F.toLocaleString("en-US"));},placeholder:"0",className:"w-full rounded-xl border bg-background py-6 pl-10 pr-4 text-3xl font-bold text-foreground placeholder:text-muted-foreground/30 focus:outline-none focus:ring-2 focus:ring-foreground/20"})]})]}),jsxRuntime.jsxs("div",{className:"flex items-start gap-3",children:[jsxRuntime.jsx("button",{type:"button",role:"checkbox","aria-checked":b,onClick:()=>w(!b),className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded border-2 transition-colors cursor-pointer",b?"border-foreground bg-foreground":"border-muted-foreground/40"),children:b&&jsxRuntime.jsx(lucideReact.Check,{className:"h-3 w-3 text-background"})}),jsxRuntime.jsxs("span",{className:"text-xs text-muted-foreground leading-relaxed",children:["I agree to list this key on the Global Open AI Network marketplace. The key will be deactivated upon sale and transferred to the buyer. Listing fees may apply."," ",jsxRuntime.jsx("a",{href:r.termsUrl||"/terms",className:"text-foreground underline",target:"_blank",rel:"noopener noreferrer",children:"Terms"})]})]}),d&&jsxRuntime.jsx("p",{className:"text-sm text-red-500",children:d}),jsxRuntime.jsxs("button",{onClick:Y,disabled:!k,className:u("flex w-full items-center justify-center gap-2 rounded-xl py-4 text-sm font-semibold transition-colors",k?"bg-foreground text-background hover:bg-foreground/90":"bg-muted text-muted-foreground cursor-not-allowed"),children:[jsxRuntime.jsx(lucideReact.ExternalLink,{className:"h-4 w-4"}),n?"Listing...":"List on Marketplace"]})]})}function Yt({nodeKey:e,selected:t,onSelect:r}){return jsxRuntime.jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsxRuntime.jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsxRuntime.jsx(lucideReact.Check,{className:"h-3 w-3 text-background"})}),jsxRuntime.jsxs("div",{className:"min-w-0 flex-1",children:[jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsxRuntime.jsx("span",{className:"text-xs font-medium capitalize text-green-500",children:e.status})]}),jsxRuntime.jsx(z,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function Te({className:e,style:t}){let{keys:r,loading:s}=Q(),{transferKey:x,transferring:m,result:f,error:a}=be(),[n,c]=Rt.useState(null),[d,p]=Rt.useState(""),[i,o]=Rt.useState(false),l=r.filter(k=>k.status==="active"),b=l.find(k=>k.id===n),w=b&&d.trim()===b.userId,P=n&&d.trim().length>0&&i&&!w&&!m,T=async()=>{!n||!d.trim()||await x(n,d.trim());},j=()=>{c(null),p(""),o(false);};return f?jsxRuntime.jsxs("div",{className:u("flex flex-col items-center gap-4 py-8",e),style:t,children:[jsxRuntime.jsx(lucideReact.CheckCircle,{className:"h-12 w-12 text-green-500"}),jsxRuntime.jsxs("div",{className:"text-center",children:[jsxRuntime.jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Transfer Complete"}),jsxRuntime.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"Key transferred successfully"})]}),jsxRuntime.jsxs("div",{className:"w-full max-w-sm space-y-2 rounded-xl border border-border bg-muted/30 p-4 text-sm",children:[jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Key"}),jsxRuntime.jsxs("span",{className:"font-mono text-foreground",children:[f.keyId.slice(0,20),"..."]})]}),jsxRuntime.jsxs("div",{className:"flex justify-between",children:[jsxRuntime.jsx("span",{className:"text-muted-foreground",children:"Recipient"}),jsxRuntime.jsxs("span",{className:"font-mono text-foreground",children:[f.toUserId.slice(0,20),"..."]})]})]}),jsxRuntime.jsx("button",{onClick:j,className:"mt-2 rounded-lg border border-border px-4 py-2 text-sm font-medium text-foreground hover:bg-muted/50 transition-colors",children:"Transfer Another"})]}):jsxRuntime.jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("h3",{className:"mb-3 text-sm font-medium text-foreground",children:"Select Key to Transfer"}),s?jsxRuntime.jsx(J,{count:2}):l.length===0?jsxRuntime.jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys available for transfer."}):jsxRuntime.jsx("div",{className:"space-y-2",children:l.map(k=>jsxRuntime.jsx(Yt,{nodeKey:k,selected:n===k.id,onSelect:()=>c(k.id)},k.id))})]}),n&&jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("label",{className:"mb-1.5 block text-sm font-medium text-foreground",children:"Recipient User ID"}),jsxRuntime.jsx("input",{type:"text",value:d,onChange:k=>{p(k.target.value),o(false);},placeholder:"Enter recipient's user ID or global ID",className:"w-full rounded-lg border border-border bg-background px-3 py-2.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-foreground/30 focus:outline-none focus:ring-1 focus:ring-foreground/10"}),w&&jsxRuntime.jsx("p",{className:"mt-1.5 text-xs text-red-500",children:"Cannot transfer a key to yourself"})]}),b&&d.trim().length>0&&!w&&jsxRuntime.jsx("div",{className:"rounded-xl border border-amber-500/30 bg-amber-500/5 p-4",children:jsxRuntime.jsxs("div",{className:"flex items-start gap-3",children:[jsxRuntime.jsx(lucideReact.AlertTriangle,{className:"mt-0.5 h-5 w-5 shrink-0 text-amber-500"}),jsxRuntime.jsxs("div",{className:"space-y-3",children:[jsxRuntime.jsxs("div",{children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Confirm Transfer"}),jsxRuntime.jsxs("p",{className:"mt-1 text-xs text-muted-foreground",children:["You are about to transfer key"," ",jsxRuntime.jsx("span",{className:"font-mono font-medium",children:b.keyIndex?`#${b.keyIndex}`:b.id.slice(0,12)})," ","(",I(b.tokenBalance)," tokens) to"," ",jsxRuntime.jsxs("span",{className:"font-mono font-medium",children:[d.trim().slice(0,20),"..."]})]})]}),jsxRuntime.jsxs("label",{className:"flex items-start gap-2 cursor-pointer",children:[jsxRuntime.jsx("input",{type:"checkbox",checked:i,onChange:k=>o(k.target.checked),className:"mt-0.5 h-4 w-4 rounded border-border"}),jsxRuntime.jsx("span",{className:"text-xs text-muted-foreground",children:"I confirm this transfer is permanent and cannot be undone."})]})]})]})}),a&&jsxRuntime.jsx("p",{className:"text-sm text-red-500",children:a}),jsxRuntime.jsx("button",{onClick:T,disabled:!P,className:u("flex w-full items-center justify-center gap-2 rounded-lg px-4 py-3 text-sm font-medium transition-all",P?"bg-foreground text-background hover:opacity-90":"bg-muted text-muted-foreground cursor-not-allowed"),children:m?jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("div",{className:"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent"}),"Transferring..."]}):jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Send,{className:"h-4 w-4"}),"Transfer Key"]})})]})}var Jt=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"},{id:"transfer",label:"Transfer"}];function Zt({active:e,onChange:t}){return jsxRuntime.jsx("div",{role:"tablist","aria-label":"Key actions",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:Jt.map(({id:r,label:s})=>jsxRuntime.jsx("button",{role:"tab","aria-selected":e===r,"aria-controls":`panel-${r}`,id:`tab-${r}`,onClick:()=>t(r),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium transition-all",e===r?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:jsxRuntime.jsx("span",{className:"inline",children:s})},r))})}function Xt({defaultTab:e="buy",className:t,style:r}){let[s,x]=Rt.useState(e);return jsxRuntime.jsxs("div",{className:u("flex flex-col",t),style:r,children:[jsxRuntime.jsx("div",{className:"sticky top-0 z-10 bg-background/80 px-5 pb-3 pt-2 sm:pt-5 backdrop-blur-sm sm:px-10 md:px-16 lg:px-20",children:jsxRuntime.jsx("div",{className:"mx-auto max-w-xl",children:jsxRuntime.jsx(Zt,{active:s,onChange:x})})}),jsxRuntime.jsx("div",{className:"flex flex-1 flex-col px-5 pb-8 sm:px-10 md:px-16 md:pb-12 lg:px-20",children:jsxRuntime.jsx("div",{className:"mx-auto w-full max-w-xl flex-1",children:jsxRuntime.jsxs("div",{role:"tabpanel",id:`panel-${s}`,"aria-labelledby":`tab-${s}`,children:[s==="buy"&&jsxRuntime.jsx(Pe,{className:"flex-1"}),s==="use"&&jsxRuntime.jsx(Ce,{className:"flex-1"}),s==="sell"&&jsxRuntime.jsx(Ke,{className:"flex-1"}),s==="transfer"&&jsxRuntime.jsx(Te,{className:"flex-1"})]})})})]})}function er({apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:x,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p,onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P,defaultTab:T,className:j,style:k}){return jsxRuntime.jsx(ae,{config:{apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:x,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p},callbacks:{onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P},children:jsxRuntime.jsx(Xt,{defaultTab:T,className:j,style:k})})}var Ue=20;function Be({nodeKey:e,className:t,style:r}){let[s,x]=Rt.useState(false),[m,f]=Rt.useState(false),a=Rt.useRef(null),{entries:n,loading:c}=ue(s?e.id:null);Rt.useEffect(()=>()=>{a.current&&clearTimeout(a.current);},[]);let d=Rt.useCallback(()=>{e.key&&(navigator.clipboard.writeText(e.key),f(true),a.current&&clearTimeout(a.current),a.current=setTimeout(()=>f(false),2e3));},[e.key]),p=e.status==="active"?"text-green-500":e.status==="expired"?"text-red-500":"text-yellow-500",i=n.slice(0,Ue);return jsxRuntime.jsxs("div",{className:u("rounded-lg border bg-background",t),style:r,children:[jsxRuntime.jsxs("div",{className:"p-4",children:[jsxRuntime.jsxs("div",{className:"mb-3 flex items-center justify-between",children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsx("button",{onClick:()=>x(!s),"aria-expanded":s,"aria-label":s?"Collapse ledger":"Expand ledger",className:"text-muted-foreground hover:text-foreground",children:s?jsxRuntime.jsx(lucideReact.ChevronDown,{className:"h-4 w-4"}):jsxRuntime.jsx(lucideReact.ChevronRight,{className:"h-4 w-4"})}),jsxRuntime.jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]})]}),jsxRuntime.jsx("span",{className:u("text-xs font-medium capitalize",p),children:e.status})]}),e.key&&jsxRuntime.jsxs("div",{className:"mb-3 flex items-center gap-2",children:[jsxRuntime.jsx("code",{className:"flex-1 truncate rounded bg-muted px-2 py-1 text-xs text-muted-foreground",children:e.key}),jsxRuntime.jsx("button",{onClick:d,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground",children:m?jsxRuntime.jsx(lucideReact.Check,{className:"h-3.5 w-3.5 text-green-500"}):jsxRuntime.jsx(lucideReact.Copy,{className:"h-3.5 w-3.5"})})]}),jsxRuntime.jsx(z,{current:e.tokenBalance,max:e.maxTokens}),jsxRuntime.jsxs("div",{className:"mt-2 flex items-center justify-between text-xs text-muted-foreground",children:[jsxRuntime.jsxs("span",{children:["Created ",H(e.createdAt)]}),e.expiresAt&&jsxRuntime.jsxs("span",{children:["Expires ",H(e.expiresAt)]})]})]}),s&&jsxRuntime.jsxs("div",{className:"border-t px-4 py-3",children:[jsxRuntime.jsx("h4",{className:"mb-2 text-xs font-medium text-muted-foreground",children:"Ledger"}),c?jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:"Loading..."}):i.length===0?jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:"No ledger entries."}):jsxRuntime.jsxs("div",{className:"space-y-1.5",children:[i.map(o=>jsxRuntime.jsxs("div",{className:"flex items-center justify-between text-xs",children:[jsxRuntime.jsxs("div",{className:"flex items-center gap-2",children:[jsxRuntime.jsxs("span",{className:u("font-medium",o.type==="credit"||o.type==="reward"?"text-green-500":"text-red-500"),children:[o.type==="credit"||o.type==="reward"?"+":"-",I(Math.abs(o.amount))]}),jsxRuntime.jsx("span",{className:"text-muted-foreground",children:o.description})]}),jsxRuntime.jsx("span",{className:"text-muted-foreground",children:H(o.createdAt)})]},o.id)),n.length>Ue&&jsxRuntime.jsxs("p",{className:"pt-1 text-xs text-muted-foreground",children:["Showing ",Ue," of ",n.length," entries"]})]})]})]})}var cr=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"}];function oe({baseHref:e}){return jsxRuntime.jsx("div",{className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5 mb-6",children:cr.map(({id:t,label:r})=>jsxRuntime.jsx("a",{href:`${e}?tab=${t}`,className:"flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium text-muted-foreground hover:text-foreground transition-all",children:r},t))})}function dr({getKeyHref:e="/keys/get",showTabs:t=true,className:r,style:s}){let{keys:x,totalBalance:m,loading:f,error:a,refresh:n}=Q();return f?jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(oe,{baseHref:e}),jsxRuntime.jsx(J,{count:3})]}):a?jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(oe,{baseHref:e}),jsxRuntime.jsxs("div",{className:"flex flex-col items-center justify-center gap-4 py-12",children:[jsxRuntime.jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsxRuntime.jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:a})]}),jsxRuntime.jsx("button",{onClick:()=>n(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]})]}):x.length===0?jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(oe,{baseHref:e}),jsxRuntime.jsxs("div",{className:"flex flex-col items-center justify-center gap-4 rounded-lg border border-dashed py-12",children:[jsxRuntime.jsx(lucideReact.KeyRound,{className:"h-10 w-10 text-muted-foreground"}),jsxRuntime.jsxs("div",{className:"text-center",children:[jsxRuntime.jsx("p",{className:"text-sm font-medium text-foreground",children:"No keys yet"}),jsxRuntime.jsx("p",{className:"text-xs text-muted-foreground",children:"Get your first node key to start earning."})]}),e&&jsxRuntime.jsx("a",{href:e,className:"rounded-lg bg-foreground px-4 py-2 text-sm font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]})]}):jsxRuntime.jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsxRuntime.jsx(oe,{baseHref:e}),jsxRuntime.jsxs("div",{className:"flex items-center justify-between",children:[jsxRuntime.jsxs("p",{className:"text-sm text-muted-foreground",children:[x.length," key",x.length!==1?"s":""," \xB7 Total balance: ",I(m)]}),e&&jsxRuntime.jsx("a",{href:e,className:"rounded-md bg-foreground px-3 py-1.5 text-xs font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]}),x.map(c=>jsxRuntime.jsx(Be,{nodeKey:c},c.id))]})}
2
+ exports.BuyKeyWidget=er;exports.BuyPanel=Pe;exports.KeyBalanceBar=z;exports.KeyCard=Be;exports.KeyList=dr;exports.KeyUtilsProvider=ae;exports.MintSuccess=ke;exports.SellPanel=Ke;exports.SolanaPayButton=ve;exports.TransferPanel=Te;exports.UsePanel=Ce;exports.calculateBalancePercentage=Ie;exports.cn=u;exports.csrfHeaders=A;exports.detectPlatform=Ee;exports.formatDate=H;exports.formatTokens=I;exports.getBalanceColor=Le;exports.useKeyLedger=ue;exports.useKeyUtilsContext=C;exports.useKeys=Q;exports.useListKey=xe;exports.useMintKey=fe;exports.usePricing=le;exports.useStripeCheckout=ge;exports.useTransferKey=be;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { DirectTransferResult, KeyListing, KeyUtilsCallbacks, KeyUtilsConfig, KeyWidgetTab, LedgerEntry, ListingResult, MintResult, NodeKeyInfo, PaymentMethod, Platform, PlatformDownload, PricingInfo } from './types/index.cjs';
2
- export { calculateBalancePercentage, cn, detectPlatform, formatDate, formatTokens, getBalanceColor } from './utils/index.cjs';
2
+ export { calculateBalancePercentage, cn, csrfHeaders, detectPlatform, formatDate, formatTokens, getBalanceColor } from './utils/index.cjs';
3
3
  export { useKeyLedger, useKeys, useListKey, useMintKey, usePricing, useStripeCheckout, useTransferKey } from './hooks/index.cjs';
4
4
  export { BuyKeyWidget, BuyKeyWidgetProps, BuyPanel, BuyPanelProps, KeyBalanceBar, KeyBalanceBarProps, KeyCard, KeyCardProps, KeyList, KeyListProps, KeyUtilsProvider, KeyUtilsProviderProps, MintSuccess, MintSuccessProps, SellPanel, SellPanelProps, SolanaPayButton, SolanaPayButtonProps, TransferPanel, TransferPanelProps, UsePanel, UsePanelProps, useKeyUtilsContext } from './components/index.cjs';
5
5
  import 'clsx';
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { DirectTransferResult, KeyListing, KeyUtilsCallbacks, KeyUtilsConfig, KeyWidgetTab, LedgerEntry, ListingResult, MintResult, NodeKeyInfo, PaymentMethod, Platform, PlatformDownload, PricingInfo } from './types/index.js';
2
- export { calculateBalancePercentage, cn, detectPlatform, formatDate, formatTokens, getBalanceColor } from './utils/index.js';
2
+ export { calculateBalancePercentage, cn, csrfHeaders, detectPlatform, formatDate, formatTokens, getBalanceColor } from './utils/index.js';
3
3
  export { useKeyLedger, useKeys, useListKey, useMintKey, usePricing, useStripeCheckout, useTransferKey } from './hooks/index.js';
4
4
  export { BuyKeyWidget, BuyKeyWidgetProps, BuyPanel, BuyPanelProps, KeyBalanceBar, KeyBalanceBarProps, KeyCard, KeyCardProps, KeyList, KeyListProps, KeyUtilsProvider, KeyUtilsProviderProps, MintSuccess, MintSuccessProps, SellPanel, SellPanelProps, SolanaPayButton, SolanaPayButtonProps, TransferPanel, TransferPanelProps, UsePanel, UsePanelProps, useKeyUtilsContext } from './components/index.js';
5
5
  import 'clsx';
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import Kt,{createContext,useContext,useMemo,useState,useRef,useEffect,useCallback}from'react';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {Loader2,CheckCircle,Check,Copy,CreditCard,Wallet,Download,ExternalLink,AlertTriangle,Send,ChevronDown,ChevronRight,KeyRound,Minus,Plus,ChevronUp}from'lucide-react';function u(...e){return twMerge(clsx(e))}function I(e){return e==null?"0":e>=1e9?`${(e/1e9).toFixed(1)}B`:e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:e.toLocaleString()}function Be(e,t){return t<=0?0:Math.min(100,Math.round(e/t*100))}function Ie(e){return e>=70?"bg-green-500":e>=30?"bg-yellow-500":"bg-red-500"}function Y(e){let t=typeof e=="string"&&/^\d+$/.test(e)?Number(e):e,r=new Date(t);return isNaN(r.getTime())?String(e):r.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}function Le(){if(typeof navigator>"u")return "mac";let e=navigator.userAgent.toLowerCase();return /iphone|ipad|ipod/.test(e)?"ios":/android/.test(e)?"android":/win/.test(e)?"windows":/linux/.test(e)?"linux":"mac"}var Ee=createContext(null);function C(){let e=useContext(Ee);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function oe({config:e,callbacks:t={},children:r}){typeof e.apiBaseUrl!="string"&&console.error("[KeyUtils] apiBaseUrl must be a string");let s=useMemo(()=>({config:e,callbacks:t}),[e,t]);return jsx(Ee.Provider,{value:s,children:r})}function ie(){let{config:e}=C(),[t,r]=useState(null),[s,x]=useState(true),[m,f]=useState(null),a=useRef(true),n=useRef(e.apiBaseUrl);n.current=e.apiBaseUrl;let c=async()=>{try{a.current&&(x(!0),f(null));let d=await fetch(`${n.current}/api/keys/pricing`);if(!d.ok){let i=`Pricing unavailable (${d.status})`;try{let o=await d.json();o.error&&(i=o.error);}catch{}throw new Error(i)}let p=await d.json();a.current&&r(p);}catch(d){a.current&&f(d instanceof Error?d.message:"Failed to fetch pricing");}finally{a.current&&x(false);}};return useEffect(()=>{a.current=true,c();let d=setInterval(c,6e4);return ()=>{a.current=false,clearInterval(d);}},[]),{pricing:t,loading:s,error:m,refresh:c}}function lt(e){return {id:e.id||"",keyIndex:e.keyIndex??e.key_index??null,key:e.key||e.keyPrefix||"",userId:e.userId||e.user_id||"",status:e.status||"active",tokenBalance:e.tokenBalance??e.currentTokenBalance??e.current_token_balance??0,maxTokens:e.maxTokens??e.initialTokenBalance??e.initial_token_balance??0,createdAt:String(e.createdAt??e.created_at??""),expiresAt:e.expiresAt,label:e.label||e.keyPrefix||e.key_prefix||void 0,paperWork:e.paperWork||e.paper_work||void 0,stackId:e.stackId,stackName:e.stackName}}function G(){let{config:e}=C(),[t,r]=useState([]),[s,x]=useState(true),[m,f]=useState(null),a=useRef(true),n=e.apiBaseUrl,c=useCallback(async()=>{try{x(!0),f(null);let p=await fetch(`${n}/api/keys`);if(!p.ok){let l=`Failed to fetch keys (${p.status})`;try{let b=await p.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let i=await p.json(),o=Array.isArray(i)?i:i.keys??[];a.current&&r(o.map(lt));}catch(p){a.current&&f(p instanceof Error?p.message:"Failed to fetch keys");}finally{a.current&&x(false);}},[n]);useEffect(()=>(a.current=true,c(),()=>{a.current=false;}),[c]);let d=t.reduce((p,i)=>p+i.tokenBalance,0);return {keys:t,totalBalance:d,loading:s,error:m,refresh:c}}function de(e){let{config:t}=C(),[r,s]=useState([]),[x,m]=useState(false),[f,a]=useState(null),n=useRef(true),c=t.apiBaseUrl,d=useCallback(async()=>{if(e)try{m(!0),a(null);let p=await fetch(`${c}/api/keys/${e}/ledger`);if(!p.ok){let o=`Failed to fetch ledger (${p.status})`;try{let l=await p.json();l.error&&(o=l.error);}catch{}throw new Error(o)}let i=await p.json();n.current&&s(Array.isArray(i)?i:i.entries??[]);}catch(p){n.current&&a(p instanceof Error?p.message:"Failed to fetch ledger");}finally{n.current&&m(false);}},[c,e]);return useEffect(()=>(n.current=true,d(),()=>{n.current=false;}),[d]),{entries:r,loading:x,error:f,refresh:d}}function me(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[x,m]=useState(null),[f,a]=useState(null);return {mint:useCallback(async(c,d,p=1)=>{try{s(!0),a(null),t.onPaymentComplete?.(c,d);let i=await fetch(`${e.apiBaseUrl}/api/keys/mint`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({paymentMethod:c,paymentRef:d,quantity:p})});if(!i.ok){let w="Key generation failed";try{let P=await i.json();P.error&&(w=P.error);}catch{}throw new Error(w)}let o=await i.json(),l=o.keys?.[0]||o,b={success:!0,key:{id:l.keyId||l.id||"",key:l.key||"",userId:l.userId||"",status:"active",tokenBalance:l.tokenBalance??l.currentTokenBalance??0,maxTokens:l.initialTokenBalance??l.tokenBalance??0,createdAt:String(l.createdAt||Date.now())},transactionId:d};return m(b),t.onMintSuccess?.(b),b}catch(i){let o=i instanceof Error?i:new Error("Key generation failed");return a(o.message),t.onMintError?.(o),{success:false,error:o.message}}finally{s(false);}},[e.apiBaseUrl,t]),minting:r,result:x,error:f}}function pe(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[x,m]=useState(null),[f,a]=useState(null),n=useRef(true),c=useCallback(async(p,i)=>{try{s(!0),a(null);let o=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({askPriceCents:i,stackId:e.stackId,stackName:e.stackName})});if(!o.ok){let b=`Listing failed (${o.status})`;try{let w=await o.json();w.error&&(b=w.error);}catch{}throw new Error(b)}let l=await o.json();return n.current&&(m(l),t.onListingCreated?.(l)),l}catch(o){let l=o instanceof Error?o.message:"Listing failed";return n.current&&a(l),null}finally{n.current&&s(false);}},[e.apiBaseUrl,e.stackId,e.stackName,t]),d=useCallback(async p=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"DELETE"});if(!i.ok){let o=`Delist failed (${i.status})`;try{let l=await i.json();l.error&&(o=l.error);}catch{}throw new Error(o)}return n.current&&m(null),!0}catch(i){let o=i instanceof Error?i.message:"Delist failed";return n.current&&a(o),false}finally{n.current&&s(false);}},[e.apiBaseUrl]);return {listKey:c,delistKey:d,listing:r,result:x,error:f}}function xe(){let{config:e}=C(),[t,r]=useState(false),[s,x]=useState(null),m=useRef(true);return {createSession:useCallback(async(a,n)=>{try{r(!0),x(null);let c=await fetch(`${e.apiBaseUrl}/api/keys/stripe-session`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({priceCents:a,quantity:n,stackId:e.stackId,referrerUrl:window.location.href})});if(!c.ok){let p=`Checkout failed (${c.status})`;try{let i=await c.json();i.error&&(p=i.error);}catch{}throw new Error(p)}let{url:d}=await c.json();if(d){try{sessionStorage.setItem("keyutils_stripe_pending","1");}catch{}window.location.href=d;}else throw new Error("No checkout URL returned")}catch(c){if(m.current){let d=c instanceof Error?c.message:"Checkout failed";x(d),r(false);}}},[e.apiBaseUrl,e.stackId]),loading:t,error:s}}function ye(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[x,m]=useState(null),[f,a]=useState(null),n=useRef(true);return {transferKey:useCallback(async(d,p)=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${d}/transfer`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({recipientId:p})});if(!i.ok){let l=`Transfer failed (${i.status})`;try{let b=await i.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let o=await i.json();return n.current&&(m(o),t.onTransferComplete?.(o)),o}catch(i){let o=i instanceof Error?i.message:"Transfer failed";return n.current&&a(o),null}finally{n.current&&s(false);}},[e.apiBaseUrl,t]),transferring:r,result:x,error:f}}var $e=/^[1-9A-HJ-NP-Za-km-z]{32,44}$/;function Ne({amountSol:e,onSuccess:t,onError:r,disabled:s,className:x,style:m}){let{config:f}=C(),[a,n]=useState(false),[c,d]=useState(null),p=!!(f.merchantWallet&&$e.test(f.merchantWallet)),i=useCallback(async()=>{if(p)try{n(!0),d(null);let{Connection:o,PublicKey:l,Transaction:b,SystemProgram:w,LAMPORTS_PER_SOL:P}=await import('@solana/web3.js'),T=typeof window<"u"?window.solana:void 0;if(!T||typeof T!="object"||!T.isPhantom)throw new Error("Phantom wallet not found. Please install Phantom.");let j=T,k;try{k=new l(f.merchantWallet);}catch{throw new Error("Invalid merchant wallet address.")}let z=await j.connect(),_=new l(z.publicKey.toString()),K=new o(f.solanaRpcUrl||"https://api.mainnet-beta.solana.com"),{blockhash:F}=await K.getLatestBlockhash(),W=BigInt(Math.floor(e*1e9)),Z=f.protocolTreasuryWallet,B=f.protocolFeeBps??500,D=new b({recentBlockhash:F,feePayer:_});if(Z&&$e.test(Z)&&B>0){let X=W*BigInt(B)/10000n,Je=W-X,Ze=new l(Z);D.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(Je)}),w.transfer({fromPubkey:_,toPubkey:Ze,lamports:Number(X)}));}else D.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(W)}));let{signature:re}=await j.signAndSendTransaction(D);t(re);}catch(o){let l=o instanceof Error?o:new Error("Payment failed");d(l.message),r?.(l);}finally{n(false);}},[e,f.merchantWallet,p,t,r]);return jsxs("div",{children:[jsx("button",{onClick:i,disabled:s||a||!p,"aria-label":`Pay ${e.toFixed(4)} SOL`,className:u("flex w-full items-center justify-center gap-2 rounded-lg bg-purple-600 px-4 py-6 font-medium text-white transition-colors hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed",x),style:m,children:a?jsxs(Fragment,{children:[jsx(Loader2,{className:"h-4 w-4 animate-spin"}),"Processing..."]}):jsxs(Fragment,{children:["Pay ",e.toFixed(4)," SOL"]})}),c&&jsx("p",{className:"mt-2 text-center text-xs text-red-500",children:c})]})}function ve({result:e,className:t,style:r}){let[s,x]=useState(false),m=useRef(null);useEffect(()=>()=>{m.current&&clearTimeout(m.current);},[]);let f=useCallback(()=>{e.key?.key&&(navigator.clipboard.writeText(e.key.key),x(true),m.current&&clearTimeout(m.current),m.current=setTimeout(()=>x(false),2e3));},[e.key?.key]);return !e.success||!e.key?null:jsxs("div",{className:u("rounded-lg border border-green-500/20 bg-green-500/10 p-6 text-center",t),style:r,children:[jsx(CheckCircle,{className:"mx-auto mb-3 h-12 w-12 text-green-500"}),jsx("h3",{className:"mb-2 text-lg font-semibold text-foreground",children:"Key Generated!"}),jsx("p",{className:"mb-4 text-sm text-muted-foreground",children:"Your node key has been successfully generated."}),jsxs("div",{className:"mx-auto flex max-w-md items-center gap-2 rounded-md border bg-background p-3",children:[jsx("code",{className:"flex-1 truncate text-xs text-foreground",children:e.key.key}),jsx("button",{onClick:f,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",children:s?jsx(Check,{className:"h-4 w-4 text-green-500"}):jsx(Copy,{className:"h-4 w-4"})})]})]})}function A({className:e}){return jsx("div",{className:u("animate-pulse rounded-xl bg-muted",e)})}function ke(){return jsxs("div",{className:"space-y-6",children:[jsxs("div",{className:"px-6 py-10 flex flex-col items-center gap-3",children:[jsx(A,{className:"h-14 w-48"}),jsx(A,{className:"h-5 w-64"})]}),jsx(A,{className:"h-[72px] w-full rounded-2xl"}),jsx(A,{className:"h-[68px] w-full rounded-2xl"}),jsx(A,{className:"h-[60px] w-full rounded-2xl"})]})}function J({count:e=3}){return jsx("div",{className:"space-y-3",children:Array.from({length:e}).map((t,r)=>jsxs("div",{className:"rounded-xl border p-4 space-y-3",children:[jsxs("div",{className:"flex items-center justify-between",children:[jsx(A,{className:"h-4 w-32"}),jsx(A,{className:"h-4 w-16"})]}),jsx(A,{className:"h-2 w-full rounded-full"}),jsxs("div",{className:"flex justify-between",children:[jsx(A,{className:"h-3 w-24"}),jsx(A,{className:"h-3 w-20"})]})]},r))})}function jt({quantity:e,max:t,onChange:r}){return jsxs("div",{className:"flex items-center justify-between rounded-2xl bg-muted/20 px-6 py-6",children:[jsx("span",{className:"text-sm font-medium text-foreground",children:"Quantity"}),jsxs("div",{className:"flex items-center gap-0 rounded-xl bg-background",children:[jsx("button",{onClick:()=>r(Math.max(1,e-1)),disabled:e<=1,"aria-label":"Decrease quantity",className:"flex h-12 w-12 items-center justify-center rounded-l-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsx(Minus,{className:"h-5 w-5"})}),jsx("span",{className:"flex h-12 w-14 items-center justify-center border-x text-xl font-bold text-foreground","aria-live":"polite",children:e}),jsx("button",{onClick:()=>r(Math.min(t,e+1)),disabled:e>=t,"aria-label":"Increase quantity",className:"flex h-12 w-12 items-center justify-center rounded-r-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsx(Plus,{className:"h-5 w-5"})})]})]})}function Fe({pricing:e,quantity:t}){let[r,s]=useState(false),x=e.priceUsd*t;return jsxs("div",{className:"rounded-2xl border bg-background",children:[jsxs("button",{onClick:()=>s(!r),"aria-expanded":r,className:"flex w-full items-center justify-between px-6 py-6 text-left",children:[jsxs("span",{className:"text-foreground",children:[jsxs("span",{className:"text-xl font-bold",children:["$",x.toFixed(2)]})," ",jsx("span",{className:"text-sm text-muted-foreground",children:"total fees included"})]}),r?jsx(ChevronUp,{className:"h-5 w-5 text-muted-foreground"}):jsx(ChevronDown,{className:"h-5 w-5 text-muted-foreground"})]}),r&&jsxs("div",{className:"border-t px-6 pb-8 pt-4 space-y-3 text-sm",children:[jsxs("div",{className:"flex justify-between",children:[jsxs("span",{className:"text-muted-foreground",children:["Node Key \xD7 ",t]}),jsxs("span",{className:"text-foreground",children:["$",(e.priceUsd*t).toFixed(2)]})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Keys sold"}),jsx("span",{className:"text-foreground",children:e.keysSold})]}),e.daysUntilHalving>0&&jsxs("div",{className:"flex justify-between text-muted-foreground",children:[jsx("span",{children:"Next refresh"}),jsxs("span",{children:[e.daysUntilHalving," day",e.daysUntilHalving!==1?"s":""]})]}),jsxs("div",{className:"flex justify-between border-t pt-3 font-semibold",children:[jsx("span",{className:"text-foreground",children:"Total"}),jsxs("span",{className:"text-foreground",children:["$",x.toFixed(2)]})]})]})]})}function we({className:e,style:t}){let{config:r}=C(),{pricing:s,loading:x,error:m,refresh:f}=ie(),{mint:a,minting:n,result:c,error:d}=me(),{createSession:p,loading:i,error:o}=xe(),[l,b]=useState(1),[w,P]=useState(r.paymentMethods?.includes("stripe")?"stripe":"solana"),[T,j]=useState(0),[k,z]=useState(false),_=Kt.useRef(l);_.current=l;let K=Math.max(1,r.maxQuantity||5),F=[...r.paymentMethods||["solana"]].sort((B,D)=>B==="stripe"?-1:D==="stripe"?1:0);if(useEffect(()=>{if(typeof window>"u")return;let D=new URLSearchParams(window.location.search).get("session_id");if(!D){try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}return}if(/^cs_(test|live)_/.test(D)&&!k&&!c?.success){let re=false;try{re=sessionStorage.getItem("keyutils_stripe_pending")==="1";}catch{}if(!re)return;try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}z(true);let X=new URL(window.location.href);X.searchParams.delete("session_id"),window.history.replaceState({},"",X.toString()),a("stripe",D,_.current);}},[k,c,a]),c?.success)return jsx("div",{className:u("flex flex-col items-center justify-center",e),style:t,children:jsx(ve,{result:c})});if(k||n)return jsx("div",{className:u("flex flex-col",e),style:t,children:jsx(ke,{})});if(x)return jsx("div",{className:u("flex flex-col",e),style:t,children:jsx(ke,{})});if(m||!s)return jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-24",e),style:t,children:[jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load pricing"}),jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m||"Please check your connection and try again."})]}),jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let W=async B=>{j(2),await a(w,B,l);},Z=()=>{p(s.priceCents,l);};return jsx("div",{className:u("flex flex-col",e),style:t,children:jsxs("div",{className:"space-y-6",children:[T===0&&jsxs(Fragment,{children:[r.keyImage&&jsx("img",{src:r.keyImage,alt:"Node Key",className:r.keyImageClass||"w-1/2 mx-auto"}),jsxs("div",{className:"px-6 py-10 text-center",children:[jsxs("p",{className:"text-5xl font-bold tracking-tight text-foreground md:text-6xl",children:["$",s.priceUsd.toFixed(2)]}),jsxs("p",{className:"mt-2 text-base text-muted-foreground",children:["per key \xB7 ",s.tokenAllocationFormatted||I(s.tokenAllocation)," tokens included"]})]}),jsx(jt,{quantity:l,max:K,onChange:b}),jsx(Fe,{pricing:s,quantity:l}),jsx("button",{onClick:()=>j(1),className:"w-full rounded-2xl bg-foreground py-6 text-center text-base font-semibold text-background transition-colors hover:bg-foreground/90",children:"Continue to Payment"})]}),T===1&&jsxs(Fragment,{children:[F.length>1&&jsx("div",{role:"tablist",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:F.map(B=>jsxs("button",{role:"tab","aria-selected":w===B,onClick:()=>P(B),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-4 text-sm font-medium transition-colors",w===B?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:[B==="stripe"?jsx(CreditCard,{className:"h-5 w-5"}):jsx(Wallet,{className:"h-5 w-5"}),B==="stripe"?"Credit Card":"Crypto"]},B))}),jsx(Fe,{pricing:s,quantity:l}),w==="stripe"?jsxs(Fragment,{children:[jsx("button",{onClick:Z,disabled:i,className:"flex w-full items-center justify-center gap-2 rounded-2xl bg-foreground py-6 text-base font-semibold text-background transition-colors hover:bg-foreground/90 disabled:opacity-50",children:i?jsxs(Fragment,{children:[jsx(Loader2,{className:"h-5 w-5 animate-spin"}),"Redirecting to Stripe..."]}):jsxs(Fragment,{children:[jsx(CreditCard,{className:"h-5 w-5"}),"Pay with Card"]})}),o&&jsx("p",{className:"text-center text-sm text-red-500",children:o})]}):w==="solana"?jsx(Ne,{amountSol:s.priceSol??0,onSuccess:W,className:"rounded-2xl py-5 text-base"}):null,d&&jsx("p",{className:"text-center text-sm text-red-500",children:d}),jsx("button",{onClick:()=>j(0),className:"w-full py-3 text-center text-sm text-muted-foreground hover:text-foreground transition-colors",children:"\u2190 Back"})]})]})})}var $t={ios:"iOS",android:"Android",windows:"Windows",mac:"macOS",linux:"Linux"},Dt=["mac","windows","linux","ios","android"];function Pe({downloads:e,className:t,style:r}){let{config:s}=C(),x=useMemo(()=>Le(),[]),m=e||Dt.map(n=>({platform:n,label:$t[n],url:"#",compatible:n===x})),f=m.find(n=>n.compatible)||m[0],a=m.filter(n=>n.platform!==f.platform);return jsxs("div",{className:u("space-y-8",t),style:r,children:[jsxs("div",{className:"flex flex-col items-center gap-6 pt-4 mt-4",children:[s.aispImage&&jsx("img",{src:s.aispImage,alt:"aiSP",className:"w-full sm:w-1/2 mx-auto px-4 sm:px-0"}),jsxs("div",{className:"text-center",children:[jsx("p",{className:"text-lg sm:text-2xl font-medium text-foreground",children:"Download the AI Service Provider App"}),jsx("p",{className:"mt-1 text-sm sm:text-base text-muted-foreground",children:"Load your keys and run your node."})]}),jsxs("a",{href:f.url,className:"inline-flex items-center gap-3 rounded-full px-10 py-4 text-lg font-semibold text-white transition-colors hover:opacity-90",style:{backgroundColor:"#0900f4"},children:[jsx(Download,{className:"h-5 w-5"}),"Get aiSP for ",f.label]})]}),jsxs("p",{className:"text-center text-sm text-muted-foreground",children:["aiSP is also available on"," ",a.map((n,c)=>jsxs(Kt.Fragment,{children:[c>0&&(c===a.length-1?" and ":", "),jsx("a",{href:n.url,className:"font-medium underline transition-colors hover:text-foreground",style:{color:"#066bff"},children:n.label})]},n.platform)),"."]}),jsxs("div",{className:"flex flex-col items-center gap-2 mt-12",children:[jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["Source code is available on",jsx("a",{href:"https://github.com/stack-net",target:"_blank",rel:"noopener noreferrer",className:"text-foreground underline hover:text-foreground/80 color-[#0900f4]",children:"Github"})]}),jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["By downloading, you agree to the",jsx("a",{href:s.termsUrl||"/terms",className:"text-foreground underline hover:text-foreground/80",children:"Open Source Applications Terms"})]})]})]})}function q({current:e,max:t,className:r,style:s,showLabel:x=true}){let m=Be(e,t),f=Ie(m);return jsxs("div",{className:u("w-full",r),style:s,children:[x&&jsxs("div",{className:"mb-1 flex items-center justify-between text-xs text-muted-foreground",children:[jsxs("span",{children:[I(e)," / ",I(t)]}),jsxs("span",{children:[m,"%"]})]}),jsx("div",{className:"h-2 w-full overflow-hidden rounded-full bg-muted",children:jsx("div",{className:u("h-full rounded-full transition-all duration-500",f),style:{width:`${m}%`}})})]})}function Ft({nodeKey:e,selected:t,onSelect:r}){return jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsx(Check,{className:"h-3 w-3 text-background"})}),jsxs("div",{className:"min-w-0 flex-1",children:[jsxs("div",{className:"flex items-center justify-between",children:[jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsx("span",{className:u("text-xs font-medium capitalize",e.status==="active"?"text-green-500":"text-muted-foreground"),children:e.status})]}),jsx(q,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function Se({className:e,style:t}){let{config:r}=C(),{keys:s,loading:x,error:m,refresh:f}=G(),{listKey:a,listing:n,result:c,error:d}=pe(),[p,i]=useState(null),[o,l]=useState(""),[b,w]=useState(false),P=s.find(K=>K.id===p),T=parseInt(o.replace(/[^0-9]/g,""),10)||0,j=T>0&&Number.isFinite(T),k=!!P&&j&&b&&!n,z=async()=>{if(!k||!P)return;let K=T*100;await a(P.id,K)&&f();};if(c)return jsxs("div",{className:u("flex flex-col items-center gap-4 rounded-xl bg-green-500/10 py-12",e),style:t,children:[jsx(CheckCircle,{className:"h-12 w-12 text-green-500"}),jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Key Listed!"}),jsx("p",{className:"text-sm text-muted-foreground",children:"Your key is now on the Global Open AI Network marketplace."}),jsxs("p",{className:"text-xs text-muted-foreground",children:["Listing ID: ",jsx("code",{children:c.listingId})]}),jsxs("a",{href:`https://market.stacknet.org/keys/${c.keyId}`,target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-2 rounded-xl bg-foreground px-6 py-3 text-sm font-semibold text-background transition-colors hover:bg-foreground/90",children:[jsx(ExternalLink,{className:"h-4 w-4"}),"View Listing"]})]});if(x)return jsxs("div",{className:u("space-y-5 px-1",e),style:t,children:[jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsx(J,{count:2})]});if(m)return jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-16",e),style:t,children:[jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m})]}),jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let _=s.filter(K=>K.status==="active");return _.length===0?jsxs("div",{className:u("flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed py-16",e),style:t,children:[jsx(AlertTriangle,{className:"h-8 w-8 text-muted-foreground"}),jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys to sell."})]}):jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxs("div",{children:[jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsx("div",{className:"space-y-2",children:_.map(K=>jsx(Ft,{nodeKey:K,selected:p===K.id,onSelect:()=>i(K.id)},K.id))})]}),P&&jsxs("div",{className:"rounded-xl border bg-muted/30 p-5 space-y-2 text-sm",children:[P.keyIndex&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key #"}),jsxs("span",{className:"text-foreground font-semibold",children:["#",P.keyIndex]})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key ID"}),jsx("code",{className:"text-xs text-foreground",children:P.id})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Originating Stack"}),jsx("span",{className:"text-foreground",children:r.stackName||"Unknown"})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Tokens (remaining / total)"}),jsxs("span",{className:"text-foreground",children:[I(P.tokenBalance)," / ",I(P.maxTokens)]})]}),P.paperWork&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Paper earned"}),jsx("span",{className:"text-foreground",children:P.paperWork})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Created"}),jsx("span",{className:"text-foreground",children:Y(P.createdAt)})]})]}),jsxs("div",{children:[jsx("label",{htmlFor:"listing-price",className:"mb-2 block text-sm sm:text-lg font-semibold text-foreground",children:"Listing Price (USD)"}),jsxs("div",{className:"relative",children:[jsx("span",{className:"absolute left-4 top-1/2 -translate-y-1/2 text-2xl font-bold text-muted-foreground",children:"$"}),jsx("input",{id:"listing-price",type:"text",inputMode:"numeric",value:o,onChange:K=>{let F=K.target.value.replace(/[^0-9]/g,""),W=parseInt(F,10);l(isNaN(W)?"":W.toLocaleString("en-US"));},placeholder:"0",className:"w-full rounded-xl border bg-background py-6 pl-10 pr-4 text-3xl font-bold text-foreground placeholder:text-muted-foreground/30 focus:outline-none focus:ring-2 focus:ring-foreground/20"})]})]}),jsxs("div",{className:"flex items-start gap-3",children:[jsx("button",{type:"button",role:"checkbox","aria-checked":b,onClick:()=>w(!b),className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded border-2 transition-colors cursor-pointer",b?"border-foreground bg-foreground":"border-muted-foreground/40"),children:b&&jsx(Check,{className:"h-3 w-3 text-background"})}),jsxs("span",{className:"text-xs text-muted-foreground leading-relaxed",children:["I agree to list this key on the Global Open AI Network marketplace. The key will be deactivated upon sale and transferred to the buyer. Listing fees may apply."," ",jsx("a",{href:r.termsUrl||"/terms",className:"text-foreground underline",target:"_blank",rel:"noopener noreferrer",children:"Terms"})]})]}),d&&jsx("p",{className:"text-sm text-red-500",children:d}),jsxs("button",{onClick:z,disabled:!k,className:u("flex w-full items-center justify-center gap-2 rounded-xl py-4 text-sm font-semibold transition-colors",k?"bg-foreground text-background hover:bg-foreground/90":"bg-muted text-muted-foreground cursor-not-allowed"),children:[jsx(ExternalLink,{className:"h-4 w-4"}),n?"Listing...":"List on Marketplace"]})]})}function zt({nodeKey:e,selected:t,onSelect:r}){return jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsx(Check,{className:"h-3 w-3 text-background"})}),jsxs("div",{className:"min-w-0 flex-1",children:[jsxs("div",{className:"flex items-center justify-between",children:[jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsx("span",{className:"text-xs font-medium capitalize text-green-500",children:e.status})]}),jsx(q,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function Re({className:e,style:t}){let{keys:r,loading:s}=G(),{transferKey:x,transferring:m,result:f,error:a}=ye(),[n,c]=useState(null),[d,p]=useState(""),[i,o]=useState(false),l=r.filter(k=>k.status==="active"),b=l.find(k=>k.id===n),w=b&&d.trim()===b.userId,P=n&&d.trim().length>0&&i&&!w&&!m,T=async()=>{!n||!d.trim()||await x(n,d.trim());},j=()=>{c(null),p(""),o(false);};return f?jsxs("div",{className:u("flex flex-col items-center gap-4 py-8",e),style:t,children:[jsx(CheckCircle,{className:"h-12 w-12 text-green-500"}),jsxs("div",{className:"text-center",children:[jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Transfer Complete"}),jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"Key transferred successfully"})]}),jsxs("div",{className:"w-full max-w-sm space-y-2 rounded-xl border border-border bg-muted/30 p-4 text-sm",children:[jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key"}),jsxs("span",{className:"font-mono text-foreground",children:[f.keyId.slice(0,20),"..."]})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Recipient"}),jsxs("span",{className:"font-mono text-foreground",children:[f.toUserId.slice(0,20),"..."]})]})]}),jsx("button",{onClick:j,className:"mt-2 rounded-lg border border-border px-4 py-2 text-sm font-medium text-foreground hover:bg-muted/50 transition-colors",children:"Transfer Another"})]}):jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxs("div",{children:[jsx("h3",{className:"mb-3 text-sm font-medium text-foreground",children:"Select Key to Transfer"}),s?jsx(J,{count:2}):l.length===0?jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys available for transfer."}):jsx("div",{className:"space-y-2",children:l.map(k=>jsx(zt,{nodeKey:k,selected:n===k.id,onSelect:()=>c(k.id)},k.id))})]}),n&&jsxs("div",{children:[jsx("label",{className:"mb-1.5 block text-sm font-medium text-foreground",children:"Recipient User ID"}),jsx("input",{type:"text",value:d,onChange:k=>{p(k.target.value),o(false);},placeholder:"Enter recipient's user ID or global ID",className:"w-full rounded-lg border border-border bg-background px-3 py-2.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-foreground/30 focus:outline-none focus:ring-1 focus:ring-foreground/10"}),w&&jsx("p",{className:"mt-1.5 text-xs text-red-500",children:"Cannot transfer a key to yourself"})]}),b&&d.trim().length>0&&!w&&jsx("div",{className:"rounded-xl border border-amber-500/30 bg-amber-500/5 p-4",children:jsxs("div",{className:"flex items-start gap-3",children:[jsx(AlertTriangle,{className:"mt-0.5 h-5 w-5 shrink-0 text-amber-500"}),jsxs("div",{className:"space-y-3",children:[jsxs("div",{children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Confirm Transfer"}),jsxs("p",{className:"mt-1 text-xs text-muted-foreground",children:["You are about to transfer key"," ",jsx("span",{className:"font-mono font-medium",children:b.keyIndex?`#${b.keyIndex}`:b.id.slice(0,12)})," ","(",I(b.tokenBalance)," tokens) to"," ",jsxs("span",{className:"font-mono font-medium",children:[d.trim().slice(0,20),"..."]})]})]}),jsxs("label",{className:"flex items-start gap-2 cursor-pointer",children:[jsx("input",{type:"checkbox",checked:i,onChange:k=>o(k.target.checked),className:"mt-0.5 h-4 w-4 rounded border-border"}),jsx("span",{className:"text-xs text-muted-foreground",children:"I confirm this transfer is permanent and cannot be undone."})]})]})]})}),a&&jsx("p",{className:"text-sm text-red-500",children:a}),jsx("button",{onClick:T,disabled:!P,className:u("flex w-full items-center justify-center gap-2 rounded-lg px-4 py-3 text-sm font-medium transition-all",P?"bg-foreground text-background hover:opacity-90":"bg-muted text-muted-foreground cursor-not-allowed"),children:m?jsxs(Fragment,{children:[jsx("div",{className:"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent"}),"Transferring..."]}):jsxs(Fragment,{children:[jsx(Send,{className:"h-4 w-4"}),"Transfer Key"]})})]})}var Jt=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"},{id:"transfer",label:"Transfer"}];function Zt({active:e,onChange:t}){return jsx("div",{role:"tablist","aria-label":"Key actions",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:Jt.map(({id:r,label:s})=>jsx("button",{role:"tab","aria-selected":e===r,"aria-controls":`panel-${r}`,id:`tab-${r}`,onClick:()=>t(r),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium transition-all",e===r?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:jsx("span",{className:"inline",children:s})},r))})}function Xt({defaultTab:e="buy",className:t,style:r}){let[s,x]=useState(e);return jsxs("div",{className:u("flex flex-col",t),style:r,children:[jsx("div",{className:"sticky top-0 z-10 bg-background/80 px-5 pb-3 pt-2 sm:pt-5 backdrop-blur-sm sm:px-10 md:px-16 lg:px-20",children:jsx("div",{className:"mx-auto max-w-xl",children:jsx(Zt,{active:s,onChange:x})})}),jsx("div",{className:"flex flex-1 flex-col px-5 pb-8 sm:px-10 md:px-16 md:pb-12 lg:px-20",children:jsx("div",{className:"mx-auto w-full max-w-xl flex-1",children:jsxs("div",{role:"tabpanel",id:`panel-${s}`,"aria-labelledby":`tab-${s}`,children:[s==="buy"&&jsx(we,{className:"flex-1"}),s==="use"&&jsx(Pe,{className:"flex-1"}),s==="sell"&&jsx(Se,{className:"flex-1"}),s==="transfer"&&jsx(Re,{className:"flex-1"})]})})})]})}function Ht({apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:x,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p,onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P,defaultTab:T,className:j,style:k}){return jsx(oe,{config:{apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:x,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p},callbacks:{onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P},children:jsx(Xt,{defaultTab:T,className:j,style:k})})}var Te=20;function Ue({nodeKey:e,className:t,style:r}){let[s,x]=useState(false),[m,f]=useState(false),a=useRef(null),{entries:n,loading:c}=de(s?e.id:null);useEffect(()=>()=>{a.current&&clearTimeout(a.current);},[]);let d=useCallback(()=>{e.key&&(navigator.clipboard.writeText(e.key),f(true),a.current&&clearTimeout(a.current),a.current=setTimeout(()=>f(false),2e3));},[e.key]),p=e.status==="active"?"text-green-500":e.status==="expired"?"text-red-500":"text-yellow-500",i=n.slice(0,Te);return jsxs("div",{className:u("rounded-lg border bg-background",t),style:r,children:[jsxs("div",{className:"p-4",children:[jsxs("div",{className:"mb-3 flex items-center justify-between",children:[jsxs("div",{className:"flex items-center gap-2",children:[jsx("button",{onClick:()=>x(!s),"aria-expanded":s,"aria-label":s?"Collapse ledger":"Expand ledger",className:"text-muted-foreground hover:text-foreground",children:s?jsx(ChevronDown,{className:"h-4 w-4"}):jsx(ChevronRight,{className:"h-4 w-4"})}),jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]})]}),jsx("span",{className:u("text-xs font-medium capitalize",p),children:e.status})]}),e.key&&jsxs("div",{className:"mb-3 flex items-center gap-2",children:[jsx("code",{className:"flex-1 truncate rounded bg-muted px-2 py-1 text-xs text-muted-foreground",children:e.key}),jsx("button",{onClick:d,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground",children:m?jsx(Check,{className:"h-3.5 w-3.5 text-green-500"}):jsx(Copy,{className:"h-3.5 w-3.5"})})]}),jsx(q,{current:e.tokenBalance,max:e.maxTokens}),jsxs("div",{className:"mt-2 flex items-center justify-between text-xs text-muted-foreground",children:[jsxs("span",{children:["Created ",Y(e.createdAt)]}),e.expiresAt&&jsxs("span",{children:["Expires ",Y(e.expiresAt)]})]})]}),s&&jsxs("div",{className:"border-t px-4 py-3",children:[jsx("h4",{className:"mb-2 text-xs font-medium text-muted-foreground",children:"Ledger"}),c?jsx("p",{className:"text-xs text-muted-foreground",children:"Loading..."}):i.length===0?jsx("p",{className:"text-xs text-muted-foreground",children:"No ledger entries."}):jsxs("div",{className:"space-y-1.5",children:[i.map(o=>jsxs("div",{className:"flex items-center justify-between text-xs",children:[jsxs("div",{className:"flex items-center gap-2",children:[jsxs("span",{className:u("font-medium",o.type==="credit"||o.type==="reward"?"text-green-500":"text-red-500"),children:[o.type==="credit"||o.type==="reward"?"+":"-",I(Math.abs(o.amount))]}),jsx("span",{className:"text-muted-foreground",children:o.description})]}),jsx("span",{className:"text-muted-foreground",children:Y(o.createdAt)})]},o.id)),n.length>Te&&jsxs("p",{className:"pt-1 text-xs text-muted-foreground",children:["Showing ",Te," of ",n.length," entries"]})]})]})]})}var lr=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"}];function ne({baseHref:e}){return jsx("div",{className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5 mb-6",children:lr.map(({id:t,label:r})=>jsx("a",{href:`${e}?tab=${t}`,className:"flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium text-muted-foreground hover:text-foreground transition-all",children:r},t))})}function cr({getKeyHref:e="/keys/get",showTabs:t=true,className:r,style:s}){let{keys:x,totalBalance:m,loading:f,error:a,refresh:n}=G();return f?jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(ne,{baseHref:e}),jsx(J,{count:3})]}):a?jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(ne,{baseHref:e}),jsxs("div",{className:"flex flex-col items-center justify-center gap-4 py-12",children:[jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:a})]}),jsx("button",{onClick:()=>n(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]})]}):x.length===0?jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(ne,{baseHref:e}),jsxs("div",{className:"flex flex-col items-center justify-center gap-4 rounded-lg border border-dashed py-12",children:[jsx(KeyRound,{className:"h-10 w-10 text-muted-foreground"}),jsxs("div",{className:"text-center",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"No keys yet"}),jsx("p",{className:"text-xs text-muted-foreground",children:"Get your first node key to start earning."})]}),e&&jsx("a",{href:e,className:"rounded-lg bg-foreground px-4 py-2 text-sm font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]})]}):jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(ne,{baseHref:e}),jsxs("div",{className:"flex items-center justify-between",children:[jsxs("p",{className:"text-sm text-muted-foreground",children:[x.length," key",x.length!==1?"s":""," \xB7 Total balance: ",I(m)]}),e&&jsx("a",{href:e,className:"rounded-md bg-foreground px-3 py-1.5 text-xs font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]}),x.map(c=>jsx(Ue,{nodeKey:c},c.id))]})}
2
- export{Ht as BuyKeyWidget,we as BuyPanel,q as KeyBalanceBar,Ue as KeyCard,cr as KeyList,oe as KeyUtilsProvider,ve as MintSuccess,Se as SellPanel,Ne as SolanaPayButton,Re as TransferPanel,Pe as UsePanel,Be as calculateBalancePercentage,u as cn,Le as detectPlatform,Y as formatDate,I as formatTokens,Ie as getBalanceColor,de as useKeyLedger,C as useKeyUtilsContext,G as useKeys,pe as useListKey,me as useMintKey,ie as usePricing,xe as useStripeCheckout,ye as useTransferKey};
1
+ import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import Rt,{createContext,useContext,useMemo,useState,useRef,useEffect,useCallback}from'react';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {Loader2,CheckCircle,Check,Copy,CreditCard,Wallet,Download,ExternalLink,AlertTriangle,Send,ChevronDown,ChevronRight,KeyRound,Minus,Plus,ChevronUp}from'lucide-react';function A(){if(typeof document>"u")return {};let e=document.cookie.match(/(?:^|;\s*)__csrf=([^;]*)/);return e?{"x-csrf-token":e[1]}:{}}function u(...e){return twMerge(clsx(e))}function I(e){return e==null?"0":e>=1e9?`${(e/1e9).toFixed(1)}B`:e>=1e6?`${(e/1e6).toFixed(1)}M`:e>=1e3?`${(e/1e3).toFixed(1)}K`:e.toLocaleString()}function Ie(e,t){return t<=0?0:Math.min(100,Math.round(e/t*100))}function Le(e){return e>=70?"bg-green-500":e>=30?"bg-yellow-500":"bg-red-500"}function H(e){let t=typeof e=="string"&&/^\d+$/.test(e)?Number(e):e,r=new Date(t);return isNaN(r.getTime())?String(e):r.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}function Ee(){if(typeof navigator>"u")return "mac";let e=navigator.userAgent.toLowerCase();return /iphone|ipad|ipod/.test(e)?"ios":/android/.test(e)?"android":/win/.test(e)?"windows":/linux/.test(e)?"linux":"mac"}var je=createContext(null);function C(){let e=useContext(je);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function ae({config:e,callbacks:t={},children:r}){typeof e.apiBaseUrl!="string"&&console.error("[KeyUtils] apiBaseUrl must be a string");let s=useMemo(()=>({config:e,callbacks:t}),[e,t]);return jsx(je.Provider,{value:s,children:r})}function le(){let{config:e}=C(),[t,r]=useState(null),[s,x]=useState(true),[m,f]=useState(null),a=useRef(true),n=useRef(e.apiBaseUrl);n.current=e.apiBaseUrl;let c=async()=>{try{a.current&&(x(!0),f(null));let d=await fetch(`${n.current}/api/keys/pricing`,{credentials:"include"});if(!d.ok){let i=`Pricing unavailable (${d.status})`;try{let o=await d.json();o.error&&(i=o.error);}catch{}throw new Error(i)}let p=await d.json();a.current&&r(p);}catch(d){a.current&&f(d instanceof Error?d.message:"Failed to fetch pricing");}finally{a.current&&x(false);}};return useEffect(()=>{a.current=true,c();let d=setInterval(c,6e4);return ()=>{a.current=false,clearInterval(d);}},[]),{pricing:t,loading:s,error:m,refresh:c}}function ct(e){return {id:e.id||"",keyIndex:e.keyIndex??e.key_index??null,key:e.key||e.keyPrefix||"",userId:e.userId||e.user_id||"",status:e.status||"active",tokenBalance:e.tokenBalance??e.currentTokenBalance??e.current_token_balance??0,maxTokens:e.maxTokens??e.initialTokenBalance??e.initial_token_balance??0,createdAt:String(e.createdAt??e.created_at??""),expiresAt:e.expiresAt,label:e.label||e.keyPrefix||e.key_prefix||void 0,paperWork:e.paperWork||e.paper_work||void 0,stackId:e.stackId,stackName:e.stackName}}function Q(){let{config:e}=C(),[t,r]=useState([]),[s,x]=useState(true),[m,f]=useState(null),a=useRef(true),n=e.apiBaseUrl,c=useCallback(async()=>{try{x(!0),f(null);let p=await fetch(`${n}/api/keys`,{credentials:"include"});if(!p.ok){let l=`Failed to fetch keys (${p.status})`;try{let b=await p.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let i=await p.json(),o=Array.isArray(i)?i:i.keys??[];a.current&&r(o.map(ct));}catch(p){a.current&&f(p instanceof Error?p.message:"Failed to fetch keys");}finally{a.current&&x(false);}},[n]);useEffect(()=>(a.current=true,c(),()=>{a.current=false;}),[c]);let d=t.reduce((p,i)=>p+i.tokenBalance,0);return {keys:t,totalBalance:d,loading:s,error:m,refresh:c}}function ue(e){let{config:t}=C(),[r,s]=useState([]),[x,m]=useState(false),[f,a]=useState(null),n=useRef(true),c=t.apiBaseUrl,d=useCallback(async()=>{if(e)try{m(!0),a(null);let p=await fetch(`${c}/api/keys/${e}/ledger`,{credentials:"include"});if(!p.ok){let o=`Failed to fetch ledger (${p.status})`;try{let l=await p.json();l.error&&(o=l.error);}catch{}throw new Error(o)}let i=await p.json();n.current&&s(Array.isArray(i)?i:i.entries??[]);}catch(p){n.current&&a(p instanceof Error?p.message:"Failed to fetch ledger");}finally{n.current&&m(false);}},[c,e]);return useEffect(()=>(n.current=true,d(),()=>{n.current=false;}),[d]),{entries:r,loading:x,error:f,refresh:d}}function fe(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[x,m]=useState(null),[f,a]=useState(null);return {mint:useCallback(async(c,d,p=1)=>{try{s(!0),a(null),t.onPaymentComplete?.(c,d);let i=await fetch(`${e.apiBaseUrl}/api/keys/mint`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({paymentMethod:c,paymentRef:d,quantity:p})});if(!i.ok){let w="Key generation failed";try{let P=await i.json();P.error&&(w=P.error);}catch{}throw new Error(w)}let o=await i.json(),l=o.keys?.[0]||o,b={success:!0,key:{id:l.keyId||l.id||"",key:l.key||"",userId:l.userId||"",status:"active",tokenBalance:l.tokenBalance??l.currentTokenBalance??0,maxTokens:l.initialTokenBalance??l.tokenBalance??0,createdAt:String(l.createdAt||Date.now())},transactionId:d};return m(b),t.onMintSuccess?.(b),b}catch(i){let o=i instanceof Error?i:new Error("Key generation failed");return a(o.message),t.onMintError?.(o),{success:false,error:o.message}}finally{s(false);}},[e.apiBaseUrl,t]),minting:r,result:x,error:f}}function xe(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[x,m]=useState(null),[f,a]=useState(null),n=useRef(true),c=useCallback(async(p,i)=>{try{s(!0),a(null);let o=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({askPriceCents:i,stackId:e.stackId,stackName:e.stackName})});if(!o.ok){let b=`Listing failed (${o.status})`;try{let w=await o.json();w.error&&(b=w.error);}catch{}throw new Error(b)}let l=await o.json();return n.current&&(m(l),t.onListingCreated?.(l)),l}catch(o){let l=o instanceof Error?o.message:"Listing failed";return n.current&&a(l),null}finally{n.current&&s(false);}},[e.apiBaseUrl,e.stackId,e.stackName,t]),d=useCallback(async p=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${p}/list`,{method:"DELETE",headers:{...A()},credentials:"include"});if(!i.ok){let o=`Delist failed (${i.status})`;try{let l=await i.json();l.error&&(o=l.error);}catch{}throw new Error(o)}return n.current&&m(null),!0}catch(i){let o=i instanceof Error?i.message:"Delist failed";return n.current&&a(o),false}finally{n.current&&s(false);}},[e.apiBaseUrl]);return {listKey:c,delistKey:d,listing:r,result:x,error:f}}function ge(){let{config:e}=C(),[t,r]=useState(false),[s,x]=useState(null),m=useRef(true);return {createSession:useCallback(async(a,n)=>{try{r(!0),x(null);let c=await fetch(`${e.apiBaseUrl}/api/keys/stripe-session`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({priceCents:a,quantity:n,stackId:e.stackId,referrerUrl:window.location.href})});if(!c.ok){let p=`Checkout failed (${c.status})`;try{let i=await c.json();i.error&&(p=i.error);}catch{}throw new Error(p)}let{url:d}=await c.json();if(d){try{sessionStorage.setItem("keyutils_stripe_pending","1");}catch{}window.location.href=d;}else throw new Error("No checkout URL returned")}catch(c){if(m.current){let d=c instanceof Error?c.message:"Checkout failed";x(d),r(false);}}},[e.apiBaseUrl,e.stackId]),loading:t,error:s}}function be(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[x,m]=useState(null),[f,a]=useState(null),n=useRef(true);return {transferKey:useCallback(async(d,p)=>{try{s(!0),a(null);let i=await fetch(`${e.apiBaseUrl}/api/keys/${d}/transfer`,{method:"POST",headers:{"Content-Type":"application/json",...A()},credentials:"include",body:JSON.stringify({recipientId:p})});if(!i.ok){let l=`Transfer failed (${i.status})`;try{let b=await i.json();b.error&&(l=b.error);}catch{}throw new Error(l)}let o=await i.json();return n.current&&(m(o),t.onTransferComplete?.(o)),o}catch(i){let o=i instanceof Error?i.message:"Transfer failed";return n.current&&a(o),null}finally{n.current&&s(false);}},[e.apiBaseUrl,t]),transferring:r,result:x,error:f}}var De=/^[1-9A-HJ-NP-Za-km-z]{32,44}$/;function ve({amountSol:e,onSuccess:t,onError:r,disabled:s,className:x,style:m}){let{config:f}=C(),[a,n]=useState(false),[c,d]=useState(null),p=!!(f.merchantWallet&&De.test(f.merchantWallet)),i=useCallback(async()=>{if(p)try{n(!0),d(null);let{Connection:o,PublicKey:l,Transaction:b,SystemProgram:w,LAMPORTS_PER_SOL:P}=await import('@solana/web3.js'),T=typeof window<"u"?window.solana:void 0;if(!T||typeof T!="object"||!T.isPhantom)throw new Error("Phantom wallet not found. Please install Phantom.");let j=T,k;try{k=new l(f.merchantWallet);}catch{throw new Error("Invalid merchant wallet address.")}let Y=await j.connect(),_=new l(Y.publicKey.toString()),K=new o(f.solanaRpcUrl||"https://api.mainnet-beta.solana.com"),{blockhash:G}=await K.getLatestBlockhash(),F=BigInt(Math.floor(e*1e9)),Z=f.protocolTreasuryWallet,B=f.protocolFeeBps??500,O=new b({recentBlockhash:G,feePayer:_});if(Z&&De.test(Z)&&B>0){let X=F*BigInt(B)/10000n,Je=F-X,Ze=new l(Z);O.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(Je)}),w.transfer({fromPubkey:_,toPubkey:Ze,lamports:Number(X)}));}else O.add(w.transfer({fromPubkey:_,toPubkey:k,lamports:Number(F)}));let{signature:se}=await j.signAndSendTransaction(O);t(se);}catch(o){let l=o instanceof Error?o:new Error("Payment failed");d(l.message),r?.(l);}finally{n(false);}},[e,f.merchantWallet,p,t,r]);return jsxs("div",{children:[jsx("button",{onClick:i,disabled:s||a||!p,"aria-label":`Pay ${e.toFixed(4)} SOL`,className:u("flex w-full items-center justify-center gap-2 rounded-lg bg-purple-600 px-4 py-6 font-medium text-white transition-colors hover:bg-purple-700 disabled:opacity-50 disabled:cursor-not-allowed",x),style:m,children:a?jsxs(Fragment,{children:[jsx(Loader2,{className:"h-4 w-4 animate-spin"}),"Processing..."]}):jsxs(Fragment,{children:["Pay ",e.toFixed(4)," SOL"]})}),c&&jsx("p",{className:"mt-2 text-center text-xs text-red-500",children:c})]})}function ke({result:e,className:t,style:r}){let[s,x]=useState(false),m=useRef(null);useEffect(()=>()=>{m.current&&clearTimeout(m.current);},[]);let f=useCallback(()=>{e.key?.key&&(navigator.clipboard.writeText(e.key.key),x(true),m.current&&clearTimeout(m.current),m.current=setTimeout(()=>x(false),2e3));},[e.key?.key]);return !e.success||!e.key?null:jsxs("div",{className:u("rounded-lg border border-green-500/20 bg-green-500/10 p-6 text-center",t),style:r,children:[jsx(CheckCircle,{className:"mx-auto mb-3 h-12 w-12 text-green-500"}),jsx("h3",{className:"mb-2 text-lg font-semibold text-foreground",children:"Key Generated!"}),jsx("p",{className:"mb-4 text-sm text-muted-foreground",children:"Your node key has been successfully generated."}),jsxs("div",{className:"mx-auto flex max-w-md items-center gap-2 rounded-md border bg-background p-3",children:[jsx("code",{className:"flex-1 truncate text-xs text-foreground",children:e.key.key}),jsx("button",{onClick:f,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",children:s?jsx(Check,{className:"h-4 w-4 text-green-500"}):jsx(Copy,{className:"h-4 w-4"})})]})]})}function $({className:e}){return jsx("div",{className:u("animate-pulse rounded-xl bg-muted",e)})}function we(){return jsxs("div",{className:"space-y-6",children:[jsxs("div",{className:"px-6 py-10 flex flex-col items-center gap-3",children:[jsx($,{className:"h-14 w-48"}),jsx($,{className:"h-5 w-64"})]}),jsx($,{className:"h-[72px] w-full rounded-2xl"}),jsx($,{className:"h-[68px] w-full rounded-2xl"}),jsx($,{className:"h-[60px] w-full rounded-2xl"})]})}function J({count:e=3}){return jsx("div",{className:"space-y-3",children:Array.from({length:e}).map((t,r)=>jsxs("div",{className:"rounded-xl border p-4 space-y-3",children:[jsxs("div",{className:"flex items-center justify-between",children:[jsx($,{className:"h-4 w-32"}),jsx($,{className:"h-4 w-16"})]}),jsx($,{className:"h-2 w-full rounded-full"}),jsxs("div",{className:"flex justify-between",children:[jsx($,{className:"h-3 w-24"}),jsx($,{className:"h-3 w-20"})]})]},r))})}function Mt({quantity:e,max:t,onChange:r}){return jsxs("div",{className:"flex items-center justify-between rounded-2xl bg-muted/20 px-6 py-6",children:[jsx("span",{className:"text-sm font-medium text-foreground",children:"Quantity"}),jsxs("div",{className:"flex items-center gap-0 rounded-xl bg-background",children:[jsx("button",{onClick:()=>r(Math.max(1,e-1)),disabled:e<=1,"aria-label":"Decrease quantity",className:"flex h-12 w-12 items-center justify-center rounded-l-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsx(Minus,{className:"h-5 w-5"})}),jsx("span",{className:"flex h-12 w-14 items-center justify-center border-x text-xl font-bold text-foreground","aria-live":"polite",children:e}),jsx("button",{onClick:()=>r(Math.min(t,e+1)),disabled:e>=t,"aria-label":"Increase quantity",className:"flex h-12 w-12 items-center justify-center rounded-r-xl text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-30",children:jsx(Plus,{className:"h-5 w-5"})})]})]})}function Ge({pricing:e,quantity:t}){let[r,s]=useState(false),x=e.priceUsd*t;return jsxs("div",{className:"rounded-2xl border bg-background",children:[jsxs("button",{onClick:()=>s(!r),"aria-expanded":r,className:"flex w-full items-center justify-between px-6 py-6 text-left",children:[jsxs("span",{className:"text-foreground",children:[jsxs("span",{className:"text-xl font-bold",children:["$",x.toFixed(2)]})," ",jsx("span",{className:"text-sm text-muted-foreground",children:"total fees included"})]}),r?jsx(ChevronUp,{className:"h-5 w-5 text-muted-foreground"}):jsx(ChevronDown,{className:"h-5 w-5 text-muted-foreground"})]}),r&&jsxs("div",{className:"border-t px-6 pb-8 pt-4 space-y-3 text-sm",children:[jsxs("div",{className:"flex justify-between",children:[jsxs("span",{className:"text-muted-foreground",children:["Node Key \xD7 ",t]}),jsxs("span",{className:"text-foreground",children:["$",(e.priceUsd*t).toFixed(2)]})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Keys sold"}),jsx("span",{className:"text-foreground",children:e.keysSold})]}),e.daysUntilHalving>0&&jsxs("div",{className:"flex justify-between text-muted-foreground",children:[jsx("span",{children:"Next refresh"}),jsxs("span",{children:[e.daysUntilHalving," day",e.daysUntilHalving!==1?"s":""]})]}),jsxs("div",{className:"flex justify-between border-t pt-3 font-semibold",children:[jsx("span",{className:"text-foreground",children:"Total"}),jsxs("span",{className:"text-foreground",children:["$",x.toFixed(2)]})]})]})]})}function Pe({className:e,style:t}){let{config:r}=C(),{pricing:s,loading:x,error:m,refresh:f}=le(),{mint:a,minting:n,result:c,error:d}=fe(),{createSession:p,loading:i,error:o}=ge(),[l,b]=useState(1),[w,P]=useState(r.paymentMethods?.includes("stripe")?"stripe":"solana"),[T,j]=useState(0),[k,Y]=useState(false),_=Rt.useRef(l);_.current=l;let K=Math.max(1,r.maxQuantity||5),G=[...r.paymentMethods||["solana"]].sort((B,O)=>B==="stripe"?-1:O==="stripe"?1:0);if(useEffect(()=>{if(typeof window>"u")return;let O=new URLSearchParams(window.location.search).get("session_id");if(!O){try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}return}if(/^cs_(test|live)_/.test(O)&&!k&&!c?.success){let se=false;try{se=sessionStorage.getItem("keyutils_stripe_pending")==="1";}catch{}if(!se)return;try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}Y(true);let X=new URL(window.location.href);X.searchParams.delete("session_id"),window.history.replaceState({},"",X.toString()),a("stripe",O,_.current);}},[k,c,a]),c?.success)return jsx("div",{className:u("flex flex-col items-center justify-center",e),style:t,children:jsx(ke,{result:c})});if(k||n)return jsx("div",{className:u("flex flex-col",e),style:t,children:jsx(we,{})});if(x)return jsx("div",{className:u("flex flex-col",e),style:t,children:jsx(we,{})});if(m||!s)return jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-24",e),style:t,children:[jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load pricing"}),jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m||"Please check your connection and try again."})]}),jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let F=async B=>{j(2),await a(w,B,l);},Z=()=>{p(s.priceCents,l);};return jsx("div",{className:u("flex flex-col",e),style:t,children:jsxs("div",{className:"space-y-6",children:[T===0&&jsxs(Fragment,{children:[r.keyImage&&jsx("img",{src:r.keyImage,alt:"Node Key",className:r.keyImageClass||"w-1/2 mx-auto"}),jsxs("div",{className:"px-6 py-10 text-center",children:[jsxs("p",{className:"text-5xl font-bold tracking-tight text-foreground md:text-6xl",children:["$",s.priceUsd.toFixed(2)]}),jsxs("p",{className:"mt-2 text-base text-muted-foreground",children:["per key \xB7 ",s.tokenAllocationFormatted||I(s.tokenAllocation)," tokens included"]})]}),jsx(Mt,{quantity:l,max:K,onChange:b}),jsx(Ge,{pricing:s,quantity:l}),jsx("button",{onClick:()=>j(1),className:"w-full rounded-2xl bg-foreground py-6 text-center text-base font-semibold text-background transition-colors hover:bg-foreground/90",children:"Continue to Payment"})]}),T===1&&jsxs(Fragment,{children:[G.length>1&&jsx("div",{role:"tablist",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:G.map(B=>jsxs("button",{role:"tab","aria-selected":w===B,onClick:()=>P(B),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-4 text-sm font-medium transition-colors",w===B?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:[B==="stripe"?jsx(CreditCard,{className:"h-5 w-5"}):jsx(Wallet,{className:"h-5 w-5"}),B==="stripe"?"Credit Card":"Crypto"]},B))}),jsx(Ge,{pricing:s,quantity:l}),w==="stripe"?jsxs(Fragment,{children:[jsx("button",{onClick:Z,disabled:i,className:"flex w-full items-center justify-center gap-2 rounded-2xl bg-foreground py-6 text-base font-semibold text-background transition-colors hover:bg-foreground/90 disabled:opacity-50",children:i?jsxs(Fragment,{children:[jsx(Loader2,{className:"h-5 w-5 animate-spin"}),"Redirecting to Stripe..."]}):jsxs(Fragment,{children:[jsx(CreditCard,{className:"h-5 w-5"}),"Pay with Card"]})}),o&&jsx("p",{className:"text-center text-sm text-red-500",children:o})]}):w==="solana"?jsx(ve,{amountSol:s.priceSol??0,onSuccess:F,className:"rounded-2xl py-5 text-base"}):null,d&&jsx("p",{className:"text-center text-sm text-red-500",children:d}),jsx("button",{onClick:()=>j(0),className:"w-full py-3 text-center text-sm text-muted-foreground hover:text-foreground transition-colors",children:"\u2190 Back"})]})]})})}var Dt={ios:"iOS",android:"Android",windows:"Windows",mac:"macOS",linux:"Linux"},Ot=["mac","windows","linux","ios","android"];function Ce({downloads:e,className:t,style:r}){let{config:s}=C(),x=useMemo(()=>Ee(),[]),m=e||Ot.map(n=>({platform:n,label:Dt[n],url:"#",compatible:n===x})),f=m.find(n=>n.compatible)||m[0],a=m.filter(n=>n.platform!==f.platform);return jsxs("div",{className:u("space-y-8",t),style:r,children:[jsxs("div",{className:"flex flex-col items-center gap-6 pt-4 mt-4",children:[s.aispImage&&jsx("img",{src:s.aispImage,alt:"aiSP",className:"w-full sm:w-1/2 mx-auto px-4 sm:px-0"}),jsxs("div",{className:"text-center",children:[jsx("p",{className:"text-lg sm:text-2xl font-medium text-foreground",children:"Download the AI Service Provider App"}),jsx("p",{className:"mt-1 text-sm sm:text-base text-muted-foreground",children:"Load your keys and run your node."})]}),jsxs("a",{href:f.url,className:"inline-flex items-center gap-3 rounded-full px-10 py-4 text-lg font-semibold text-white transition-colors hover:opacity-90",style:{backgroundColor:"#0900f4"},children:[jsx(Download,{className:"h-5 w-5"}),"Get aiSP for ",f.label]})]}),jsxs("p",{className:"text-center text-sm text-muted-foreground",children:["aiSP is also available on"," ",a.map((n,c)=>jsxs(Rt.Fragment,{children:[c>0&&(c===a.length-1?" and ":", "),jsx("a",{href:n.url,className:"font-medium underline transition-colors hover:text-foreground",style:{color:"#066bff"},children:n.label})]},n.platform)),"."]}),jsxs("div",{className:"flex flex-col items-center gap-2 mt-12",children:[jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["Source code is available on",jsx("a",{href:"https://github.com/stack-net",target:"_blank",rel:"noopener noreferrer",className:"text-foreground underline hover:text-foreground/80 color-[#0900f4]",children:"Github"})]}),jsxs("p",{className:"text-center text-xs text-muted-foreground flex justify-center gap-0.5 flex-wrap",children:["By downloading, you agree to the",jsx("a",{href:s.termsUrl||"/terms",className:"text-foreground underline hover:text-foreground/80",children:"Open Source Applications Terms"})]})]})]})}function z({current:e,max:t,className:r,style:s,showLabel:x=true}){let m=Ie(e,t),f=Le(m);return jsxs("div",{className:u("w-full",r),style:s,children:[x&&jsxs("div",{className:"mb-1 flex items-center justify-between text-xs text-muted-foreground",children:[jsxs("span",{children:[I(e)," / ",I(t)]}),jsxs("span",{children:[m,"%"]})]}),jsx("div",{className:"h-2 w-full overflow-hidden rounded-full bg-muted",children:jsx("div",{className:u("h-full rounded-full transition-all duration-500",f),style:{width:`${m}%`}})})]})}function Gt({nodeKey:e,selected:t,onSelect:r}){return jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsx(Check,{className:"h-3 w-3 text-background"})}),jsxs("div",{className:"min-w-0 flex-1",children:[jsxs("div",{className:"flex items-center justify-between",children:[jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsx("span",{className:u("text-xs font-medium capitalize",e.status==="active"?"text-green-500":"text-muted-foreground"),children:e.status})]}),jsx(z,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function Ke({className:e,style:t}){let{config:r}=C(),{keys:s,loading:x,error:m,refresh:f}=Q(),{listKey:a,listing:n,result:c,error:d}=xe(),[p,i]=useState(null),[o,l]=useState(""),[b,w]=useState(false),P=s.find(K=>K.id===p),T=parseInt(o.replace(/[^0-9]/g,""),10)||0,j=T>0&&Number.isFinite(T),k=!!P&&j&&b&&!n,Y=async()=>{if(!k||!P)return;let K=T*100;await a(P.id,K)&&f();};if(c)return jsxs("div",{className:u("flex flex-col items-center gap-4 rounded-xl bg-green-500/10 py-12",e),style:t,children:[jsx(CheckCircle,{className:"h-12 w-12 text-green-500"}),jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Key Listed!"}),jsx("p",{className:"text-sm text-muted-foreground",children:"Your key is now on the Global Open AI Network marketplace."}),jsxs("p",{className:"text-xs text-muted-foreground",children:["Listing ID: ",jsx("code",{children:c.listingId})]}),jsxs("a",{href:`https://market.stacknet.org/keys/${c.keyId}`,target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-2 rounded-xl bg-foreground px-6 py-3 text-sm font-semibold text-background transition-colors hover:bg-foreground/90",children:[jsx(ExternalLink,{className:"h-4 w-4"}),"View Listing"]})]});if(x)return jsxs("div",{className:u("space-y-5 px-1",e),style:t,children:[jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsx(J,{count:2})]});if(m)return jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 py-16",e),style:t,children:[jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:m})]}),jsx("button",{onClick:()=>f(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let _=s.filter(K=>K.status==="active");return _.length===0?jsxs("div",{className:u("flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed py-16",e),style:t,children:[jsx(AlertTriangle,{className:"h-8 w-8 text-muted-foreground"}),jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys to sell."})]}):jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxs("div",{children:[jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsx("div",{className:"space-y-2",children:_.map(K=>jsx(Gt,{nodeKey:K,selected:p===K.id,onSelect:()=>i(K.id)},K.id))})]}),P&&jsxs("div",{className:"rounded-xl border bg-muted/30 p-5 space-y-2 text-sm",children:[P.keyIndex&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key #"}),jsxs("span",{className:"text-foreground font-semibold",children:["#",P.keyIndex]})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key ID"}),jsx("code",{className:"text-xs text-foreground",children:P.id})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Originating Stack"}),jsx("span",{className:"text-foreground",children:r.stackName||"Unknown"})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Tokens (remaining / total)"}),jsxs("span",{className:"text-foreground",children:[I(P.tokenBalance)," / ",I(P.maxTokens)]})]}),P.paperWork&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Paper earned"}),jsx("span",{className:"text-foreground",children:P.paperWork})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Created"}),jsx("span",{className:"text-foreground",children:H(P.createdAt)})]})]}),jsxs("div",{children:[jsx("label",{htmlFor:"listing-price",className:"mb-2 block text-sm sm:text-lg font-semibold text-foreground",children:"Listing Price (USD)"}),jsxs("div",{className:"relative",children:[jsx("span",{className:"absolute left-4 top-1/2 -translate-y-1/2 text-2xl font-bold text-muted-foreground",children:"$"}),jsx("input",{id:"listing-price",type:"text",inputMode:"numeric",value:o,onChange:K=>{let G=K.target.value.replace(/[^0-9]/g,""),F=parseInt(G,10);l(isNaN(F)?"":F.toLocaleString("en-US"));},placeholder:"0",className:"w-full rounded-xl border bg-background py-6 pl-10 pr-4 text-3xl font-bold text-foreground placeholder:text-muted-foreground/30 focus:outline-none focus:ring-2 focus:ring-foreground/20"})]})]}),jsxs("div",{className:"flex items-start gap-3",children:[jsx("button",{type:"button",role:"checkbox","aria-checked":b,onClick:()=>w(!b),className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded border-2 transition-colors cursor-pointer",b?"border-foreground bg-foreground":"border-muted-foreground/40"),children:b&&jsx(Check,{className:"h-3 w-3 text-background"})}),jsxs("span",{className:"text-xs text-muted-foreground leading-relaxed",children:["I agree to list this key on the Global Open AI Network marketplace. The key will be deactivated upon sale and transferred to the buyer. Listing fees may apply."," ",jsx("a",{href:r.termsUrl||"/terms",className:"text-foreground underline",target:"_blank",rel:"noopener noreferrer",children:"Terms"})]})]}),d&&jsx("p",{className:"text-sm text-red-500",children:d}),jsxs("button",{onClick:Y,disabled:!k,className:u("flex w-full items-center justify-center gap-2 rounded-xl py-4 text-sm font-semibold transition-colors",k?"bg-foreground text-background hover:bg-foreground/90":"bg-muted text-muted-foreground cursor-not-allowed"),children:[jsx(ExternalLink,{className:"h-4 w-4"}),n?"Listing...":"List on Marketplace"]})]})}function Yt({nodeKey:e,selected:t,onSelect:r}){return jsxs("button",{onClick:r,className:u("flex w-full items-start gap-3 rounded-xl border p-4 text-left transition-all",t?"border-foreground/30 bg-foreground/5 ring-1 ring-foreground/10":"border-border hover:border-foreground/20"),children:[jsx("div",{className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full border-2 transition-colors",t?"border-foreground bg-foreground":"border-muted-foreground/40"),children:t&&jsx(Check,{className:"h-3 w-3 text-background"})}),jsxs("div",{className:"min-w-0 flex-1",children:[jsxs("div",{className:"flex items-center justify-between",children:[jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsx("span",{className:"text-xs font-medium capitalize text-green-500",children:e.status})]}),jsx(z,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function Te({className:e,style:t}){let{keys:r,loading:s}=Q(),{transferKey:x,transferring:m,result:f,error:a}=be(),[n,c]=useState(null),[d,p]=useState(""),[i,o]=useState(false),l=r.filter(k=>k.status==="active"),b=l.find(k=>k.id===n),w=b&&d.trim()===b.userId,P=n&&d.trim().length>0&&i&&!w&&!m,T=async()=>{!n||!d.trim()||await x(n,d.trim());},j=()=>{c(null),p(""),o(false);};return f?jsxs("div",{className:u("flex flex-col items-center gap-4 py-8",e),style:t,children:[jsx(CheckCircle,{className:"h-12 w-12 text-green-500"}),jsxs("div",{className:"text-center",children:[jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Transfer Complete"}),jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"Key transferred successfully"})]}),jsxs("div",{className:"w-full max-w-sm space-y-2 rounded-xl border border-border bg-muted/30 p-4 text-sm",children:[jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key"}),jsxs("span",{className:"font-mono text-foreground",children:[f.keyId.slice(0,20),"..."]})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Recipient"}),jsxs("span",{className:"font-mono text-foreground",children:[f.toUserId.slice(0,20),"..."]})]})]}),jsx("button",{onClick:j,className:"mt-2 rounded-lg border border-border px-4 py-2 text-sm font-medium text-foreground hover:bg-muted/50 transition-colors",children:"Transfer Another"})]}):jsxs("div",{className:u("space-y-5",e),style:t,children:[jsxs("div",{children:[jsx("h3",{className:"mb-3 text-sm font-medium text-foreground",children:"Select Key to Transfer"}),s?jsx(J,{count:2}):l.length===0?jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys available for transfer."}):jsx("div",{className:"space-y-2",children:l.map(k=>jsx(Yt,{nodeKey:k,selected:n===k.id,onSelect:()=>c(k.id)},k.id))})]}),n&&jsxs("div",{children:[jsx("label",{className:"mb-1.5 block text-sm font-medium text-foreground",children:"Recipient User ID"}),jsx("input",{type:"text",value:d,onChange:k=>{p(k.target.value),o(false);},placeholder:"Enter recipient's user ID or global ID",className:"w-full rounded-lg border border-border bg-background px-3 py-2.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-foreground/30 focus:outline-none focus:ring-1 focus:ring-foreground/10"}),w&&jsx("p",{className:"mt-1.5 text-xs text-red-500",children:"Cannot transfer a key to yourself"})]}),b&&d.trim().length>0&&!w&&jsx("div",{className:"rounded-xl border border-amber-500/30 bg-amber-500/5 p-4",children:jsxs("div",{className:"flex items-start gap-3",children:[jsx(AlertTriangle,{className:"mt-0.5 h-5 w-5 shrink-0 text-amber-500"}),jsxs("div",{className:"space-y-3",children:[jsxs("div",{children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Confirm Transfer"}),jsxs("p",{className:"mt-1 text-xs text-muted-foreground",children:["You are about to transfer key"," ",jsx("span",{className:"font-mono font-medium",children:b.keyIndex?`#${b.keyIndex}`:b.id.slice(0,12)})," ","(",I(b.tokenBalance)," tokens) to"," ",jsxs("span",{className:"font-mono font-medium",children:[d.trim().slice(0,20),"..."]})]})]}),jsxs("label",{className:"flex items-start gap-2 cursor-pointer",children:[jsx("input",{type:"checkbox",checked:i,onChange:k=>o(k.target.checked),className:"mt-0.5 h-4 w-4 rounded border-border"}),jsx("span",{className:"text-xs text-muted-foreground",children:"I confirm this transfer is permanent and cannot be undone."})]})]})]})}),a&&jsx("p",{className:"text-sm text-red-500",children:a}),jsx("button",{onClick:T,disabled:!P,className:u("flex w-full items-center justify-center gap-2 rounded-lg px-4 py-3 text-sm font-medium transition-all",P?"bg-foreground text-background hover:opacity-90":"bg-muted text-muted-foreground cursor-not-allowed"),children:m?jsxs(Fragment,{children:[jsx("div",{className:"h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent"}),"Transferring..."]}):jsxs(Fragment,{children:[jsx(Send,{className:"h-4 w-4"}),"Transfer Key"]})})]})}var Jt=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"},{id:"transfer",label:"Transfer"}];function Zt({active:e,onChange:t}){return jsx("div",{role:"tablist","aria-label":"Key actions",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:Jt.map(({id:r,label:s})=>jsx("button",{role:"tab","aria-selected":e===r,"aria-controls":`panel-${r}`,id:`tab-${r}`,onClick:()=>t(r),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium transition-all",e===r?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:jsx("span",{className:"inline",children:s})},r))})}function Xt({defaultTab:e="buy",className:t,style:r}){let[s,x]=useState(e);return jsxs("div",{className:u("flex flex-col",t),style:r,children:[jsx("div",{className:"sticky top-0 z-10 bg-background/80 px-5 pb-3 pt-2 sm:pt-5 backdrop-blur-sm sm:px-10 md:px-16 lg:px-20",children:jsx("div",{className:"mx-auto max-w-xl",children:jsx(Zt,{active:s,onChange:x})})}),jsx("div",{className:"flex flex-1 flex-col px-5 pb-8 sm:px-10 md:px-16 md:pb-12 lg:px-20",children:jsx("div",{className:"mx-auto w-full max-w-xl flex-1",children:jsxs("div",{role:"tabpanel",id:`panel-${s}`,"aria-labelledby":`tab-${s}`,children:[s==="buy"&&jsx(Pe,{className:"flex-1"}),s==="use"&&jsx(Ce,{className:"flex-1"}),s==="sell"&&jsx(Ke,{className:"flex-1"}),s==="transfer"&&jsx(Te,{className:"flex-1"})]})})})]})}function er({apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:x,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p,onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P,defaultTab:T,className:j,style:k}){return jsx(ae,{config:{apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:x,stripePublicKey:m,theme:f,maxQuantity:a,keyImage:n,keyImageClass:c,aispImage:d,termsUrl:p},callbacks:{onMintSuccess:i,onMintError:o,onPaymentStart:l,onPaymentComplete:b,onListingCreated:w,onTransferComplete:P},children:jsx(Xt,{defaultTab:T,className:j,style:k})})}var Ue=20;function Be({nodeKey:e,className:t,style:r}){let[s,x]=useState(false),[m,f]=useState(false),a=useRef(null),{entries:n,loading:c}=ue(s?e.id:null);useEffect(()=>()=>{a.current&&clearTimeout(a.current);},[]);let d=useCallback(()=>{e.key&&(navigator.clipboard.writeText(e.key),f(true),a.current&&clearTimeout(a.current),a.current=setTimeout(()=>f(false),2e3));},[e.key]),p=e.status==="active"?"text-green-500":e.status==="expired"?"text-red-500":"text-yellow-500",i=n.slice(0,Ue);return jsxs("div",{className:u("rounded-lg border bg-background",t),style:r,children:[jsxs("div",{className:"p-4",children:[jsxs("div",{className:"mb-3 flex items-center justify-between",children:[jsxs("div",{className:"flex items-center gap-2",children:[jsx("button",{onClick:()=>x(!s),"aria-expanded":s,"aria-label":s?"Collapse ledger":"Expand ledger",className:"text-muted-foreground hover:text-foreground",children:s?jsx(ChevronDown,{className:"h-4 w-4"}):jsx(ChevronRight,{className:"h-4 w-4"})}),jsxs("span",{className:"text-sm font-medium text-foreground",children:[e.keyIndex?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]})]}),jsx("span",{className:u("text-xs font-medium capitalize",p),children:e.status})]}),e.key&&jsxs("div",{className:"mb-3 flex items-center gap-2",children:[jsx("code",{className:"flex-1 truncate rounded bg-muted px-2 py-1 text-xs text-muted-foreground",children:e.key}),jsx("button",{onClick:d,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground",children:m?jsx(Check,{className:"h-3.5 w-3.5 text-green-500"}):jsx(Copy,{className:"h-3.5 w-3.5"})})]}),jsx(z,{current:e.tokenBalance,max:e.maxTokens}),jsxs("div",{className:"mt-2 flex items-center justify-between text-xs text-muted-foreground",children:[jsxs("span",{children:["Created ",H(e.createdAt)]}),e.expiresAt&&jsxs("span",{children:["Expires ",H(e.expiresAt)]})]})]}),s&&jsxs("div",{className:"border-t px-4 py-3",children:[jsx("h4",{className:"mb-2 text-xs font-medium text-muted-foreground",children:"Ledger"}),c?jsx("p",{className:"text-xs text-muted-foreground",children:"Loading..."}):i.length===0?jsx("p",{className:"text-xs text-muted-foreground",children:"No ledger entries."}):jsxs("div",{className:"space-y-1.5",children:[i.map(o=>jsxs("div",{className:"flex items-center justify-between text-xs",children:[jsxs("div",{className:"flex items-center gap-2",children:[jsxs("span",{className:u("font-medium",o.type==="credit"||o.type==="reward"?"text-green-500":"text-red-500"),children:[o.type==="credit"||o.type==="reward"?"+":"-",I(Math.abs(o.amount))]}),jsx("span",{className:"text-muted-foreground",children:o.description})]}),jsx("span",{className:"text-muted-foreground",children:H(o.createdAt)})]},o.id)),n.length>Ue&&jsxs("p",{className:"pt-1 text-xs text-muted-foreground",children:["Showing ",Ue," of ",n.length," entries"]})]})]})]})}var cr=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"sell",label:"Sell"}];function oe({baseHref:e}){return jsx("div",{className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5 mb-6",children:cr.map(({id:t,label:r})=>jsx("a",{href:`${e}?tab=${t}`,className:"flex flex-1 items-center justify-center gap-2.5 rounded-xl py-3.5 text-sm font-medium text-muted-foreground hover:text-foreground transition-all",children:r},t))})}function dr({getKeyHref:e="/keys/get",showTabs:t=true,className:r,style:s}){let{keys:x,totalBalance:m,loading:f,error:a,refresh:n}=Q();return f?jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(oe,{baseHref:e}),jsx(J,{count:3})]}):a?jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(oe,{baseHref:e}),jsxs("div",{className:"flex flex-col items-center justify-center gap-4 py-12",children:[jsxs("div",{className:"rounded-xl border border-red-500/20 bg-red-500/5 px-6 py-5 text-center max-w-sm",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"Unable to load your keys"}),jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:a})]}),jsx("button",{onClick:()=>n(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]})]}):x.length===0?jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(oe,{baseHref:e}),jsxs("div",{className:"flex flex-col items-center justify-center gap-4 rounded-lg border border-dashed py-12",children:[jsx(KeyRound,{className:"h-10 w-10 text-muted-foreground"}),jsxs("div",{className:"text-center",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"No keys yet"}),jsx("p",{className:"text-xs text-muted-foreground",children:"Get your first node key to start earning."})]}),e&&jsx("a",{href:e,className:"rounded-lg bg-foreground px-4 py-2 text-sm font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]})]}):jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(oe,{baseHref:e}),jsxs("div",{className:"flex items-center justify-between",children:[jsxs("p",{className:"text-sm text-muted-foreground",children:[x.length," key",x.length!==1?"s":""," \xB7 Total balance: ",I(m)]}),e&&jsx("a",{href:e,className:"rounded-md bg-foreground px-3 py-1.5 text-xs font-medium text-background transition-colors hover:bg-foreground/90",children:"Get a Key"})]}),x.map(c=>jsx(Be,{nodeKey:c},c.id))]})}
2
+ export{er as BuyKeyWidget,Pe as BuyPanel,z as KeyBalanceBar,Be as KeyCard,dr as KeyList,ae as KeyUtilsProvider,ke as MintSuccess,Ke as SellPanel,ve as SolanaPayButton,Te as TransferPanel,Ce as UsePanel,Ie as calculateBalancePercentage,u as cn,A as csrfHeaders,Ee as detectPlatform,H as formatDate,I as formatTokens,Le as getBalanceColor,ue as useKeyLedger,C as useKeyUtilsContext,Q as useKeys,xe as useListKey,fe as useMintKey,le as usePricing,ge as useStripeCheckout,be as useTransferKey};
@@ -1 +1 @@
1
- 'use strict';var clsx=require('clsx'),tailwindMerge=require('tailwind-merge');function f(...r){return tailwindMerge.twMerge(clsx.clsx(r))}function a(r){return r==null?"0":r>=1e9?`${(r/1e9).toFixed(1)}B`:r>=1e6?`${(r/1e6).toFixed(1)}M`:r>=1e3?`${(r/1e3).toFixed(1)}K`:r.toLocaleString()}function s(r,e){return e<=0?0:Math.min(100,Math.round(r/e*100))}function l(r){return r>=70?"bg-green-500":r>=30?"bg-yellow-500":"bg-red-500"}function c(r){let e=typeof r=="string"&&/^\d+$/.test(r)?Number(r):r,t=new Date(e);return isNaN(t.getTime())?String(r):t.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}function m(){if(typeof navigator>"u")return "mac";let r=navigator.userAgent.toLowerCase();return /iphone|ipad|ipod/.test(r)?"ios":/android/.test(r)?"android":/win/.test(r)?"windows":/linux/.test(r)?"linux":"mac"}exports.calculateBalancePercentage=s;exports.cn=f;exports.detectPlatform=m;exports.formatDate=c;exports.formatTokens=a;exports.getBalanceColor=l;
1
+ 'use strict';var clsx=require('clsx'),tailwindMerge=require('tailwind-merge');function n(){if(typeof document>"u")return {};let r=document.cookie.match(/(?:^|;\s*)__csrf=([^;]*)/);return r?{"x-csrf-token":r[1]}:{}}function c(...r){return tailwindMerge.twMerge(clsx.clsx(r))}function a(r){return r==null?"0":r>=1e9?`${(r/1e9).toFixed(1)}B`:r>=1e6?`${(r/1e6).toFixed(1)}M`:r>=1e3?`${(r/1e3).toFixed(1)}K`:r.toLocaleString()}function l(r,e){return e<=0?0:Math.min(100,Math.round(r/e*100))}function d(r){return r>=70?"bg-green-500":r>=30?"bg-yellow-500":"bg-red-500"}function m(r){let e=typeof r=="string"&&/^\d+$/.test(r)?Number(r):r,t=new Date(e);return isNaN(t.getTime())?String(r):t.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}function p(){if(typeof navigator>"u")return "mac";let r=navigator.userAgent.toLowerCase();return /iphone|ipad|ipod/.test(r)?"ios":/android/.test(r)?"android":/win/.test(r)?"windows":/linux/.test(r)?"linux":"mac"}exports.calculateBalancePercentage=l;exports.cn=c;exports.csrfHeaders=n;exports.detectPlatform=p;exports.formatDate=m;exports.formatTokens=a;exports.getBalanceColor=d;
@@ -1,6 +1,9 @@
1
1
  import { ClassValue } from 'clsx';
2
2
  import { Platform } from '../types/index.cjs';
3
3
 
4
+ /** Read __csrf cookie and return as x-csrf-token header for mutations */
5
+ declare function csrfHeaders(): Record<string, string>;
6
+
4
7
  declare function cn(...inputs: ClassValue[]): string;
5
8
  declare function formatTokens(amount: number | undefined | null): string;
6
9
  declare function calculateBalancePercentage(current: number, max: number): number;
@@ -8,4 +11,4 @@ declare function getBalanceColor(percentage: number): string;
8
11
  declare function formatDate(dateString: string | number): string;
9
12
  declare function detectPlatform(): Platform;
10
13
 
11
- export { calculateBalancePercentage, cn, detectPlatform, formatDate, formatTokens, getBalanceColor };
14
+ export { calculateBalancePercentage, cn, csrfHeaders, detectPlatform, formatDate, formatTokens, getBalanceColor };
@@ -1,6 +1,9 @@
1
1
  import { ClassValue } from 'clsx';
2
2
  import { Platform } from '../types/index.js';
3
3
 
4
+ /** Read __csrf cookie and return as x-csrf-token header for mutations */
5
+ declare function csrfHeaders(): Record<string, string>;
6
+
4
7
  declare function cn(...inputs: ClassValue[]): string;
5
8
  declare function formatTokens(amount: number | undefined | null): string;
6
9
  declare function calculateBalancePercentage(current: number, max: number): number;
@@ -8,4 +11,4 @@ declare function getBalanceColor(percentage: number): string;
8
11
  declare function formatDate(dateString: string | number): string;
9
12
  declare function detectPlatform(): Platform;
10
13
 
11
- export { calculateBalancePercentage, cn, detectPlatform, formatDate, formatTokens, getBalanceColor };
14
+ export { calculateBalancePercentage, cn, csrfHeaders, detectPlatform, formatDate, formatTokens, getBalanceColor };
@@ -1 +1 @@
1
- import {clsx}from'clsx';import {twMerge}from'tailwind-merge';function f(...r){return twMerge(clsx(r))}function a(r){return r==null?"0":r>=1e9?`${(r/1e9).toFixed(1)}B`:r>=1e6?`${(r/1e6).toFixed(1)}M`:r>=1e3?`${(r/1e3).toFixed(1)}K`:r.toLocaleString()}function s(r,e){return e<=0?0:Math.min(100,Math.round(r/e*100))}function l(r){return r>=70?"bg-green-500":r>=30?"bg-yellow-500":"bg-red-500"}function c(r){let e=typeof r=="string"&&/^\d+$/.test(r)?Number(r):r,t=new Date(e);return isNaN(t.getTime())?String(r):t.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}function m(){if(typeof navigator>"u")return "mac";let r=navigator.userAgent.toLowerCase();return /iphone|ipad|ipod/.test(r)?"ios":/android/.test(r)?"android":/win/.test(r)?"windows":/linux/.test(r)?"linux":"mac"}export{s as calculateBalancePercentage,f as cn,m as detectPlatform,c as formatDate,a as formatTokens,l as getBalanceColor};
1
+ import {clsx}from'clsx';import {twMerge}from'tailwind-merge';function n(){if(typeof document>"u")return {};let r=document.cookie.match(/(?:^|;\s*)__csrf=([^;]*)/);return r?{"x-csrf-token":r[1]}:{}}function c(...r){return twMerge(clsx(r))}function a(r){return r==null?"0":r>=1e9?`${(r/1e9).toFixed(1)}B`:r>=1e6?`${(r/1e6).toFixed(1)}M`:r>=1e3?`${(r/1e3).toFixed(1)}K`:r.toLocaleString()}function l(r,e){return e<=0?0:Math.min(100,Math.round(r/e*100))}function d(r){return r>=70?"bg-green-500":r>=30?"bg-yellow-500":"bg-red-500"}function m(r){let e=typeof r=="string"&&/^\d+$/.test(r)?Number(r):r,t=new Date(e);return isNaN(t.getTime())?String(r):t.toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"})}function p(){if(typeof navigator>"u")return "mac";let r=navigator.userAgent.toLowerCase();return /iphone|ipad|ipod/.test(r)?"ios":/android/.test(r)?"android":/win/.test(r)?"windows":/linux/.test(r)?"linux":"mac"}export{l as calculateBalancePercentage,c as cn,n as csrfHeaders,p as detectPlatform,m as formatDate,a as formatTokens,d as getBalanceColor};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stacknet/keyutils",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "Reusable components for buying and managing StackNet node keys",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",