@stacknet/keyutils 0.3.5 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/index.cjs +2 -2
- package/dist/components/index.d.cts +30 -2
- package/dist/components/index.d.ts +30 -2
- package/dist/components/index.js +2 -2
- package/dist/core/index.cjs +1 -0
- package/dist/core/index.d.cts +53 -0
- package/dist/core/index.d.ts +53 -0
- package/dist/core/index.js +1 -0
- package/dist/hooks/index.cjs +2 -2
- package/dist/hooks/index.d.cts +35 -2
- package/dist/hooks/index.d.ts +35 -2
- package/dist/hooks/index.js +2 -2
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +2 -2
- package/dist/types/index.d.cts +21 -1
- package/dist/types/index.d.ts +21 -1
- package/dist/utils/index.cjs +1 -1
- package/dist/utils/index.d.cts +27 -1
- package/dist/utils/index.d.ts +27 -1
- package/dist/utils/index.js +1 -1
- package/package.json +6 -1
package/dist/components/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import Et,{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,X,ArrowLeft,KeyRound,ExternalLink,AlertTriangle,ChevronDown,ChevronRight,Send,Minus,Plus,ChevronUp,FileText}from'lucide-react';var _e=createContext(null);function K(){let e=useContext(_e);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function ge({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(_e.Provider,{value:s,children:r})}function O(){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 R(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 De(e,t){return t<=0?0:Math.min(100,Math.round(e/t*100))}function $e(e){return e>=70?"bg-green-500":e>=30?"bg-yellow-500":"bg-red-500"}function V(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 Fe(){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 Oe(){let{config:e}=K(),[t,r]=useState(null),[s,g]=useState(true),[x,c]=useState(null),d=useRef(true),o=useRef(e.apiBaseUrl);o.current=e.apiBaseUrl;let n=async()=>{try{d.current&&(g(!0),c(null));let m=await fetch(`${o.current}/api/keys/pricing`,{credentials:"include"});if(!m.ok){let p=`Pricing unavailable (${m.status})`;try{let a=await m.json();a.error&&(p=a.error);}catch{}throw new Error(p)}let f=await m.json();d.current&&r(f);}catch(m){d.current&&c(m instanceof Error?m.message:"Failed to fetch pricing");}finally{d.current&&g(false);}};return useEffect(()=>{d.current=true,n();let m=setInterval(n,6e4);return ()=>{d.current=false,clearInterval(m);}},[]),{pricing:t,loading:s,error:x,refresh:n}}function Ve(){let{config:e,callbacks:t}=K(),[r,s]=useState(false),[g,x]=useState(null),[c,d]=useState(null);return {mint:useCallback(async(n,m,f=1)=>{try{s(!0),d(null),t.onPaymentComplete?.(n,m);let p=await fetch(`${e.apiBaseUrl}/api/keys/mint`,{method:"POST",headers:{"Content-Type":"application/json",...O()},credentials:"include",body:JSON.stringify({paymentMethod:n,paymentRef:m,quantity:f})});if(!p.ok){let P="Key generation failed";try{let C=await p.json();C.error&&(P=C.error);}catch{}throw new Error(P)}let a=await p.json(),l=a.keys?.[0]||a,y={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:m};return x(y),t.onMintSuccess?.(y),y}catch(p){let a=p instanceof Error?p:new Error("Key generation failed");return d(a.message),t.onMintError?.(a),{success:false,error:a.message}}finally{s(false);}},[e.apiBaseUrl,t]),minting:r,result:g,error:c}}function ze(){let{config:e}=K(),[t,r]=useState(false),[s,g]=useState(null),x=useRef(true);return {createSession:useCallback(async(d,o)=>{try{r(!0),g(null);let n=await fetch(`${e.apiBaseUrl}/api/keys/stripe-session`,{method:"POST",headers:{"Content-Type":"application/json",...O()},credentials:"include",body:JSON.stringify({priceCents:d,quantity:o,stackId:e.stackId,referrerUrl:window.location.href})});if(!n.ok){let f=`Checkout failed (${n.status})`;try{let p=await n.json();p.error&&(f=p.error);}catch{}throw new Error(f)}let{url:m}=await n.json();if(m){try{sessionStorage.setItem("keyutils_stripe_pending","1");}catch{}window.location.href=m;}else throw new Error("No checkout URL returned")}catch(n){if(x.current){let m=n instanceof Error?n.message:"Checkout failed";g(m),r(false);}}},[e.apiBaseUrl,e.stackId]),loading:t,error:s}}var qe=/^[1-9A-HJ-NP-Za-km-z]{32,44}$/;function he({amountSol:e,onSuccess:t,onError:r,disabled:s,className:g,style:x}){let{config:c}=K(),[d,o]=useState(false),[n,m]=useState(null),f=!!(c.merchantWallet&&qe.test(c.merchantWallet)),p=useCallback(async()=>{if(f)try{o(!0),m(null);let{Connection:a,PublicKey:l,Transaction:y,SystemProgram:P,LAMPORTS_PER_SOL:C}=await import('@solana/web3.js'),L=typeof window<"u"?window.solana:void 0;if(!L||typeof L!="object"||!L.isPhantom)throw new Error("Phantom wallet not found. Please install Phantom.");let D=L,S;try{S=new l(c.merchantWallet);}catch{throw new Error("Invalid merchant wallet address.")}let se=await D.connect(),F=new l(se.publicKey.toString()),I=new a(c.solanaRpcUrl||"https://api.mainnet-beta.solana.com"),{blockhash:Z}=await I.getLatestBlockhash(),H=BigInt(Math.floor(e*1e9)),oe=c.protocolTreasuryWallet,j=c.protocolFeeBps??500,Y=new y({recentBlockhash:Z,feePayer:F});if(oe&&qe.test(oe)&&j>0){let ne=H*BigInt(j)/10000n,ft=H-ne,pt=new l(oe);Y.add(P.transfer({fromPubkey:F,toPubkey:S,lamports:Number(ft)}),P.transfer({fromPubkey:F,toPubkey:pt,lamports:Number(ne)}));}else Y.add(P.transfer({fromPubkey:F,toPubkey:S,lamports:Number(H)}));let{signature:de}=await D.signAndSendTransaction(Y);t(de);}catch(a){let l=a instanceof Error?a:new Error("Payment failed");m(l.message),r?.(l);}finally{o(false);}},[e,c.merchantWallet,f,t,r]);return jsxs("div",{children:[jsx("button",{onClick:p,disabled:s||d||!f,"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:x,children:d?jsxs(Fragment,{children:[jsx(Loader2,{className:"h-4 w-4 animate-spin"}),"Processing..."]}):jsxs(Fragment,{children:["Pay ",e.toFixed(4)," SOL"]})}),n&&jsx("p",{className:"mt-2 text-center text-xs text-red-500",children:n})]})}function ke({result:e,className:t,style:r}){let[s,g]=useState(false),x=useRef(null);useEffect(()=>()=>{x.current&&clearTimeout(x.current);},[]);let c=useCallback(()=>{e.key?.key&&(navigator.clipboard.writeText(e.key.key),g(true),x.current&&clearTimeout(x.current),x.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:c,"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 G({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(G,{className:"h-14 w-48"}),jsx(G,{className:"h-5 w-64"})]}),jsx(G,{className:"h-[72px] w-full rounded-2xl"}),jsx(G,{className:"h-[68px] w-full rounded-2xl"}),jsx(G,{className:"h-[60px] w-full rounded-2xl"})]})}function Q({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(G,{className:"h-4 w-32"}),jsx(G,{className:"h-4 w-16"})]}),jsx(G,{className:"h-2 w-full rounded-full"}),jsxs("div",{className:"flex justify-between",children:[jsx(G,{className:"h-3 w-24"}),jsx(G,{className:"h-3 w-20"})]})]},r))})}function Wt({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 Ze({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}=K(),{pricing:s,loading:g,error:x,refresh:c}=Oe(),{mint:d,minting:o,result:n,error:m}=Ve(),{createSession:f,loading:p,error:a}=ze(),[l,y]=useState(1),[P,C]=useState(r.paymentMethods?.includes("stripe")?"stripe":"solana"),[L,D]=useState(0),[S,se]=useState(false),F=Et.useRef(l);F.current=l;let I=Math.max(1,r.maxQuantity||5),Z=[...r.paymentMethods||["solana"]].sort((j,Y)=>j==="stripe"?-1:Y==="stripe"?1:0);if(useEffect(()=>{if(typeof window>"u")return;let Y=new URLSearchParams(window.location.search).get("session_id");if(!Y){try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}return}if(/^cs_(test|live)_/.test(Y)&&!S&&!n?.success){let de=false;try{de=sessionStorage.getItem("keyutils_stripe_pending")==="1";}catch{}if(!de)return;try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}se(true);let ne=new URL(window.location.href);ne.searchParams.delete("session_id"),window.history.replaceState({},"",ne.toString()),d("stripe",Y,F.current);}},[S,n,d]),n?.success)return jsx("div",{className:u("flex flex-col items-center justify-center",e),style:t,children:jsx(ke,{result:n})});if(S||o)return jsx("div",{className:u("flex flex-col",e),style:t,children:jsx(we,{})});if(g)return jsx("div",{className:u("flex flex-col",e),style:t,children:jsx(we,{})});if(x||!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:x||"Please check your connection and try again."})]}),jsx("button",{onClick:()=>c(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let H=async j=>{D(2),await d(P,j,l);},oe=()=>{f(s.priceCents,l);};return jsx("div",{className:u("flex flex-col",e),style:t,children:jsxs("div",{className:"space-y-6",children:[L===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||R(s.tokenAllocation)," tokens included"]})]}),jsx(Wt,{quantity:l,max:I,onChange:y}),jsx(Ze,{pricing:s,quantity:l}),jsx("button",{onClick:()=>D(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"})]}),L===1&&jsxs(Fragment,{children:[Z.length>1&&jsx("div",{role:"tablist",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:Z.map(j=>jsxs("button",{role:"tab","aria-selected":P===j,onClick:()=>C(j),className:u("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-4 text-sm font-medium transition-colors",P===j?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:[j==="stripe"?jsx(CreditCard,{className:"h-5 w-5"}):jsx(Wallet,{className:"h-5 w-5"}),j==="stripe"?"Credit Card":"Crypto"]},j))}),jsx(Ze,{pricing:s,quantity:l}),P==="stripe"?jsxs(Fragment,{children:[jsx("button",{onClick:oe,disabled:p,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:p?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"]})}),a&&jsx("p",{className:"text-center text-sm text-red-500",children:a})]}):P==="solana"?jsx(he,{amountSol:s.priceSol??0,onSuccess:H,className:"rounded-2xl py-5 text-base"}):null,m&&jsx("p",{className:"text-center text-sm text-red-500",children:m}),jsx("button",{onClick:()=>D(0),className:"w-full py-3 text-center text-sm text-muted-foreground hover:text-foreground transition-colors",children:"\u2190 Back"})]})]})})}var zt={ios:"iOS",android:"Android",windows:"Windows",mac:"macOS",linux:"Linux"},Yt=["mac","windows","linux","ios","android"];function Ce({downloads:e,className:t,style:r}){let{config:s}=K(),g=useMemo(()=>Fe(),[]),x=e||Yt.map(o=>({platform:o,label:zt[o],url:"#",compatible:o===g})),c=x.find(o=>o.compatible)||x[0],d=x.filter(o=>o.platform!==c.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:c.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 ",c.label]})]}),jsxs("p",{className:"text-center text-sm text-muted-foreground",children:["aiSP is also available on"," ",d.map((o,n)=>jsxs(Et.Fragment,{children:[n>0&&(n===d.length-1?" and ":", "),jsx("a",{href:o.url,className:"font-medium underline transition-colors hover:text-foreground",style:{color:"#066bff"},children:o.label})]},o.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}=K(),[t,r]=useState([]),[s,g]=useState(true),[x,c]=useState(null),d=useRef(true),o=e.apiBaseUrl,n=useCallback(async()=>{try{g(!0),c(null);let f=await fetch(`${o}/api/keys`,{credentials:"include"});if(!f.ok){let l=`Failed to fetch keys (${f.status})`;try{let y=await f.json();y.error&&(l=y.error);}catch{}throw new Error(l)}let p=await f.json(),a=Array.isArray(p)?p:p.keys??[];d.current&&r(a.map(Jt));}catch(f){d.current&&c(f instanceof Error?f.message:"Failed to fetch keys");}finally{d.current&&g(false);}},[o]);useEffect(()=>(d.current=true,n(),()=>{d.current=false;}),[n]);let m=t.reduce((f,p)=>f+p.tokenBalance,0);return {keys:t,totalBalance:m,loading:s,error:x,refresh:n}}function W({current:e,max:t,className:r,style:s,showLabel:g=true}){let x=De(e,t),c=$e(x);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:[R(e)," / ",R(t)]}),jsxs("span",{children:[x,"%"]})]}),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",c),style:{width:`${x}%`}})})]})}function me(){let{config:e,callbacks:t}=K(),[r,s]=useState(false),[g,x]=useState(null),[c,d]=useState(null),o=useRef(true),n=useCallback(async(f,p)=>{try{s(!0),d(null);let a=await fetch(`${e.apiBaseUrl}/api/keys/${f}/list`,{method:"POST",headers:{"Content-Type":"application/json",...O()},credentials:"include",body:JSON.stringify({askPriceCents:p,stackId:e.stackId,stackName:e.stackName})});if(!a.ok){let y=`Listing failed (${a.status})`;try{let P=await a.json();P.error&&(y=P.error);}catch{}throw new Error(y)}let l=await a.json();return o.current&&(x(l),t.onListingCreated?.(l)),l}catch(a){let l=a instanceof Error?a.message:"Listing failed";return o.current&&d(l),null}finally{o.current&&s(false);}},[e.apiBaseUrl,e.stackId,e.stackName,t]),m=useCallback(async f=>{try{s(!0),d(null);let p=await fetch(`${e.apiBaseUrl}/api/keys/${f}/list`,{method:"DELETE",headers:{...O()},credentials:"include"});if(!p.ok){let a=`Delist failed (${p.status})`;try{let l=await p.json();l.error&&(a=l.error);}catch{}throw new Error(a)}return o.current&&x(null),!0}catch(p){let a=p instanceof Error?p.message:"Delist failed";return o.current&&d(a),false}finally{o.current&&s(false);}},[e.apiBaseUrl]);return {listKey:n,delistKey:m,listing:r,result:g,error:c}}function fe(){let{config:e,callbacks:t}=K(),[r,s]=useState(false),[g,x]=useState(null),[c,d]=useState(null),o=useRef(true);return {transferKey:useCallback(async(m,f)=>{try{s(!0),d(null);let p=await fetch(`${e.apiBaseUrl}/api/keys/${m}/transfer`,{method:"POST",headers:{"Content-Type":"application/json",...O()},credentials:"include",body:JSON.stringify({recipientId:f})});if(!p.ok){let l=`Transfer failed (${p.status})`;try{let y=await p.json();y.error&&(l=y.error);}catch{}throw new Error(l)}let a=await p.json();return o.current&&(x(a),t.onTransferComplete?.(a)),a}catch(p){let a=p instanceof Error?p.message:"Transfer failed";return o.current&&d(a),null}finally{o.current&&s(false);}},[e.apiBaseUrl,t]),transferring:r,result:g,error:c}}function pe(e){let{config:t}=K(),[r,s]=useState([]),[g,x]=useState(false),[c,d]=useState(null),o=useRef(true),n=t.apiBaseUrl,m=useCallback(async()=>{if(e)try{x(!0),d(null);let f=await fetch(`${n}/api/keys/${e}/ledger`,{credentials:"include"});if(!f.ok){let a=`Failed to fetch ledger (${f.status})`;try{let l=await f.json();l.error&&(a=l.error);}catch{}throw new Error(a)}let p=await f.json();o.current&&s(Array.isArray(p)?p:p.entries??[]);}catch(f){o.current&&d(f instanceof Error?f.message:"Failed to fetch ledger");}finally{o.current&&x(false);}},[n,e]);return useEffect(()=>(o.current=true,m(),()=>{o.current=false;}),[m]),{entries:r,loading:g,error:c,refresh:m}}function ce({open:e,onClose:t,title:r,children:s}){let g=useRef(null),[x,c]=useState(false),[d,o]=useState(false),n=useCallback(m=>{m.key==="Escape"&&t();},[t]);return useEffect(()=>{if(e)c(true),document.addEventListener("keydown",n),document.body.style.overflow="hidden",requestAnimationFrame(()=>{requestAnimationFrame(()=>o(true));});else {o(false);let m=setTimeout(()=>{c(false),document.body.style.overflow="";},300);return document.removeEventListener("keydown",n),()=>clearTimeout(m)}return ()=>{document.removeEventListener("keydown",n);}},[e,n]),x?jsxs("div",{className:"fixed inset-0 z-50 flex items-end justify-center",children:[jsx("div",{className:"absolute inset-0 bg-black/50 backdrop-blur-sm transition-opacity duration-300",style:{opacity:d?1:0},onClick:t}),jsxs("div",{ref:g,className:u("relative z-10 w-full max-w-xl rounded-t-2xl bg-background shadow-2xl","max-h-[85vh] flex flex-col","transition-transform duration-300 ease-out"),style:{transform:d?"translateY(0)":"translateY(100%)"},children:[jsx("div",{className:"flex justify-center pt-3 pb-1",children:jsx("div",{className:"h-1 w-10 rounded-full bg-muted-foreground/30"})}),r&&jsxs("div",{className:"flex items-center justify-between px-5 pb-3 pt-1",children:[jsx("h3",{className:"text-lg font-semibold text-foreground",children:r}),jsx("button",{onClick:t,className:"rounded-full p-1.5 text-muted-foreground hover:bg-muted hover:text-foreground transition-colors","aria-label":"Close",children:jsx(X,{className:"h-5 w-5"})})]}),jsx("div",{className:"flex-1 overflow-y-auto px-5 pb-8",children:s})]})]}):null}function mr({nodeKey:e,onSuccess:t}){let{transferKey:r,transferring:s,result:g,error:x}=fe(),[c,d]=useState(""),[o,n]=useState(false),m=c.trim()===e.userId,f=c.trim().length>0&&o&&!m&&!s,p=async()=>{if(!f)return;await r(e.id,c.trim())&&t();};return g?jsxs("div",{className:"flex flex-col items-center gap-4 py-8",children:[jsx(CheckCircle,{className:"h-12 w-12 text-green-500"}),jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Transfer Complete"}),jsx("p",{className:"text-sm text-muted-foreground",children:"Key transferred successfully"})]}):jsxs("div",{className:"space-y-5",children:[jsxs("div",{children:[jsx("label",{className:"mb-1.5 block text-sm font-semibold text-foreground",children:"Recipient User ID"}),jsx("input",{type:"text",value:c,onChange:a=>{d(a.target.value),n(false);},placeholder:"Enter recipient's user ID or global ID",className:"w-full rounded-xl border border-border bg-background px-4 py-3 text-sm text-foreground placeholder:text-muted-foreground focus:border-foreground/30 focus:outline-none focus:ring-1 focus:ring-foreground/10"}),m&&jsx("p",{className:"mt-1.5 text-xs text-red-500",children:"Cannot transfer a key to yourself"})]}),c.trim().length>0&&!m&&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:["Transferring key"," ",jsx("span",{className:"font-mono font-medium",children:e.keyIndex?`#${e.keyIndex}`:e.id.slice(0,12)})," ","(",R(e.tokenBalance)," tokens) to"," ",jsxs("span",{className:"font-mono font-medium",children:[c.trim().slice(0,20),c.trim().length>20?"...":""]})]})]}),jsxs("label",{className:"flex items-start gap-2 cursor-pointer",children:[jsx("input",{type:"checkbox",checked:o,onChange:a=>n(a.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."})]})]})]})}),x&&jsx("p",{className:"text-sm text-red-500",children:x}),jsx("button",{onClick:p,disabled:!f,className:u("flex w-full items-center justify-center gap-2 rounded-xl py-4 text-sm font-semibold transition-colors",f?"bg-foreground text-background hover:bg-foreground/90":"bg-muted text-muted-foreground cursor-not-allowed"),children:s?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"]})})]})}function fr({nodeKey:e,onSuccess:t}){let{config:r}=K(),{listKey:s,listing:g,result:x,error:c}=me(),[d,o]=useState(""),[n,m]=useState(false),f=parseInt(d.replace(/[^0-9]/g,""),10)||0,a=f>0&&Number.isFinite(f)&&n&&!g,l=async()=>{if(!a)return;let y=f*100;await s(e.id,y)&&t();};return x?jsxs("div",{className:"flex flex-col items-center gap-4 py-8",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 marketplace."}),jsxs("p",{className:"text-xs text-muted-foreground",children:["Listing ID: ",jsx("code",{children:x.listingId})]})]}):jsxs("div",{className:"space-y-5",children:[jsxs("div",{children:[jsx("label",{htmlFor:"listing-price",className:"mb-2 block text-sm 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:d,onChange:y=>{let P=y.target.value.replace(/[^0-9]/g,""),C=parseInt(P,10);o(isNaN(C)?"":C.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":n,onClick:()=>m(!n),className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded border-2 transition-colors cursor-pointer",n?"border-foreground bg-foreground":"border-muted-foreground/40"),children:n&&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"})]})]}),c&&jsx("p",{className:"text-sm text-red-500",children:c}),jsxs("button",{onClick:l,disabled:!a,className:u("flex w-full items-center justify-center gap-2 rounded-xl py-4 text-sm font-semibold transition-colors",a?"bg-foreground text-background hover:bg-foreground/90":"bg-muted text-muted-foreground cursor-not-allowed"),children:[jsx(ExternalLink,{className:"h-4 w-4"}),g?"Listing...":"List on Marketplace"]})]})}function pr({nodeKey:e}){let[t,r]=useState(false);if(!e.paperWork)return jsxs("div",{className:"flex flex-col items-center gap-3 py-12",children:[jsx(FileText,{className:"h-10 w-10 text-muted-foreground"}),jsx("p",{className:"text-sm text-muted-foreground",children:"This key has no paperwork to file."})]});let s=()=>{navigator.clipboard.writeText(e.paperWork||""),r(true),setTimeout(()=>r(false),2e3);};return jsxs("div",{className:"space-y-5",children:[jsxs("div",{children:[jsx("label",{className:"mb-2 block text-sm font-semibold text-foreground",children:"Paperwork"}),jsxs("div",{className:"relative rounded-xl border bg-muted/30 p-4",children:[jsx("pre",{className:"whitespace-pre-wrap break-all text-sm text-foreground font-mono",children:e.paperWork}),jsx("button",{onClick:s,className:"absolute top-3 right-3 rounded-lg p-1.5 text-muted-foreground hover:bg-muted hover:text-foreground transition-colors","aria-label":"Copy paperwork",children:t?jsx(Check,{className:"h-4 w-4 text-green-500"}):jsx(Copy,{className:"h-4 w-4"})})]})]}),jsx("p",{className:"text-xs text-muted-foreground",children:"Filing paperwork submits the key's documentation on-chain for permanent record."}),jsxs("button",{disabled:true,className:"flex w-full items-center justify-center gap-2 rounded-xl bg-muted py-4 text-sm font-semibold text-muted-foreground cursor-not-allowed",children:[jsx(FileText,{className:"h-4 w-4"}),"File Paperwork (Coming Soon)"]})]})}function Ue({nodeKey:e,onBack:t,onKeysChanged:r,className:s,style:g}){let{config:x}=K(),{entries:c,loading:d}=pe(e.id),[o,n]=useState(null),[m,f]=useState(false),p=()=>{n(null),r?.();},a=()=>{e.key&&(navigator.clipboard.writeText(e.key),f(true),setTimeout(()=>f(false),2e3));},l=e.status==="active"?"text-green-500":e.status==="expired"?"text-red-500":"text-yellow-500";return jsxs("div",{className:u("space-y-5",s),style:g,children:[jsxs("button",{onClick:t,className:"flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors",children:[jsx(ArrowLeft,{className:"h-4 w-4"}),"Back to Keys"]}),jsx("div",{className:"space-y-1",children:jsxs("div",{className:"flex items-center justify-between",children:[jsx("h2",{className:"text-2xl font-bold text-foreground",children:e.keyIndex?`Key #${e.keyIndex}`:e.label||e.id.slice(0,16)}),jsx("span",{className:u("text-sm font-medium capitalize",l),children:e.status})]})}),e.key&&jsxs("div",{className:"flex items-center gap-2",children:[jsx("code",{className:"flex-1 truncate rounded-lg bg-muted px-3 py-2 text-xs text-muted-foreground",children:e.key}),jsx("button",{onClick:a,"aria-label":"Copy key",className:"shrink-0 rounded-lg p-2 text-muted-foreground hover:bg-muted hover:text-foreground transition-colors",children:m?jsx(Check,{className:"h-4 w-4 text-green-500"}):jsx(Copy,{className:"h-4 w-4"})})]}),jsx(W,{current:e.tokenBalance,max:e.maxTokens,showLabel:true}),jsxs("div",{className:"rounded-xl bg-muted/30 p-5 space-y-2.5 text-sm",children:[e.keyIndex&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key #"}),jsxs("span",{className:"text-foreground font-semibold",children:["#",e.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:e.id})]}),(x.stackName||e.stackName)&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Stack"}),jsx("span",{className:"text-foreground",children:e.stackName||x.stackName})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Tokens"}),jsxs("span",{className:"text-foreground",children:[R(e.tokenBalance)," / ",R(e.maxTokens)]})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Created"}),jsx("span",{className:"text-foreground",children:V(e.createdAt)})]}),e.expiresAt&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Expires"}),jsx("span",{className:"text-foreground",children:V(e.expiresAt)})]})]}),e.paperWork&&jsxs("div",{className:"rounded-xl border bg-muted/30 p-5",children:[jsx("h3",{className:"text-sm font-semibold text-foreground mb-2",children:"Paperwork"}),jsx("pre",{className:"whitespace-pre-wrap break-all text-xs text-muted-foreground font-mono",children:e.paperWork})]}),e.status==="active"&&jsxs("div",{className:"grid grid-cols-3 gap-3",children:[jsx("button",{onClick:()=>n("transfer"),className:"flex items-center justify-center rounded-xl border border-border p-4 text-sm font-medium text-foreground hover:bg-muted/50 transition-colors",children:"Transfer"}),jsx("button",{onClick:()=>n("sell"),className:"flex items-center justify-center rounded-xl border border-border p-4 text-sm font-medium text-foreground hover:bg-muted/50 transition-colors",children:"Sell"}),jsx("button",{onClick:()=>n("file"),className:u("flex items-center justify-center rounded-xl border border-border p-4 text-sm font-medium transition-colors",e.paperWork?"text-foreground hover:bg-muted/50":"text-muted-foreground cursor-not-allowed opacity-50"),disabled:!e.paperWork,children:"File"})]}),jsxs("div",{children:[jsx("h3",{className:"text-sm font-semibold text-foreground mb-3",children:"Ledger"}),d?jsx("p",{className:"text-xs text-muted-foreground",children:"Loading ledger..."}):c.length===0?jsx("p",{className:"text-xs text-muted-foreground",children:"No ledger entries."}):jsxs("div",{className:"space-y-1.5",children:[c.slice(0,20).map(y=>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",y.type==="credit"||y.type==="reward"?"text-green-500":"text-red-500"),children:[y.type==="credit"||y.type==="reward"?"+":"-",R(Math.abs(y.amount))]}),jsx("span",{className:"text-muted-foreground",children:y.description})]}),jsx("span",{className:"text-muted-foreground",children:V(y.createdAt)})]},y.id)),c.length>20&&jsxs("p",{className:"pt-1 text-xs text-muted-foreground",children:["Showing 20 of ",c.length," entries"]})]})]}),jsx(ce,{open:o==="transfer",onClose:()=>n(null),title:"Transfer Key",children:jsx(mr,{nodeKey:e,onSuccess:p})}),jsx(ce,{open:o==="sell",onClose:()=>n(null),title:"Sell Key",children:jsx(fr,{nodeKey:e,onSuccess:p})}),jsx(ce,{open:o==="file",onClose:()=>n(null),title:"File Paperwork",children:jsx(pr,{nodeKey:e})})]})}function xr({nodeKey:e,onClick:t}){let r=e.status==="active"?"text-green-500":e.status==="expired"?"text-red-500":"text-yellow-500";return jsx("button",{onClick:t,className:"flex w-full items-start gap-3 rounded-xl border border-border p-4 text-left transition-all hover:border-foreground/20 hover:bg-muted/30",children: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",r),children:e.status})]}),jsx(W,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"}),e.paperWork&&jsx("span",{className:"mt-1.5 inline-block text-xs text-muted-foreground",children:"Has paperwork"})]})})}function Le({className:e,style:t}){let{keys:r,loading:g,error:x,refresh:c}=J(),[d,o]=useState(null),[n,m]=useState("active"),f=r.filter(l=>l.status===n),p=f.reduce((l,y)=>l+y.tokenBalance,0),a=r.find(l=>l.id===d);return a?jsx(Ue,{nodeKey:a,onBack:()=>o(null),onKeysChanged:()=>{o(null),c();},className:e,style:t}):g?jsxs("div",{className:u("space-y-4",e),style:t,children:[jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsx(Q,{count:3})]}):x?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:x})]}),jsx("button",{onClick:()=>c(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]}):r.length===0?jsxs("div",{className:u("flex flex-col items-center justify-center gap-4 rounded-xl border border-dashed py-16",e),style:t,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."})]})]}):jsxs("div",{className:u("space-y-4",e),style:t,children:[jsxs("div",{className:"flex items-center justify-between mt-3",children:[jsx("h3",{className:"text-2xl font-semibold text-foreground",children:"Your Keys"}),jsxs("span",{className:"text-xs text-muted-foreground",children:[f.length," key",f.length!==1?"s":""," \xB7 ",R(p)," tokens"]}),jsx("div",{className:"flex gap-1 rounded-lg bg-muted/50 p-1",children:["active","listed"].map(l=>jsx("button",{onClick:()=>m(l),className:u("rounded-md px-3 py-1 text-xs font-medium capitalize transition-all",n===l?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:l},l))})]}),f.length===0?jsxs("div",{className:"flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed py-12",children:[jsx(KeyRound,{className:"h-8 w-8 text-muted-foreground"}),jsxs("p",{className:"text-sm text-muted-foreground",children:["No ",n," keys."]})]}):jsx("div",{className:"space-y-2",children:f.map(l=>jsx(xr,{nodeKey:l,onClick:()=>o(l.id)},l.id))})]})}var yr=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"keys",label:"Keys"}];function br({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:yr.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 Nr({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(br,{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(Ce,{className:"flex-1"}),s==="keys"&&jsx(Le,{className:"flex-1"})]})})})]})}function vr({apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:g,stripePublicKey:x,theme:c,maxQuantity:d,keyImage:o,keyImageClass:n,aispImage:m,termsUrl:f,onMintSuccess:p,onMintError:a,onPaymentStart:l,onPaymentComplete:y,onListingCreated:P,onTransferComplete:C,defaultTab:L,className:D,style:S}){return jsx(ge,{config:{apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:g,stripePublicKey:x,theme:c,maxQuantity:d,keyImage:o,keyImageClass:n,aispImage:m,termsUrl:f},callbacks:{onMintSuccess:p,onMintError:a,onPaymentStart:l,onPaymentComplete:y,onListingCreated:P,onTransferComplete:C},children:jsx(Nr,{defaultTab:L,className:D,style:S})})}function wr({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(W,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function Pr({className:e,style:t}){let{config:r}=K(),{keys:s,loading:g,error:x,refresh:c}=J(),{listKey:d,listing:o,result:n,error:m}=me(),[f,p]=useState(null),[a,l]=useState(""),[y,P]=useState(false),C=s.find(I=>I.id===f),L=parseInt(a.replace(/[^0-9]/g,""),10)||0,D=L>0&&Number.isFinite(L),S=!!C&&D&&y&&!o,se=async()=>{if(!S||!C)return;let I=L*100;await d(C.id,I)&&c();};if(n)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:n.listingId})]}),jsxs("a",{href:`https://market.stacknet.org/keys/${n.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(Q,{count:2})]});if(x)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:x})]}),jsx("button",{onClick:()=>c(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let F=s.filter(I=>I.status==="active");return F.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:F.map(I=>jsx(wr,{nodeKey:I,selected:f===I.id,onSelect:()=>p(I.id)},I.id))})]}),C&&jsxs("div",{className:"rounded-xl border bg-muted/30 p-5 space-y-2 text-sm",children:[C.keyIndex&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key #"}),jsxs("span",{className:"text-foreground font-semibold",children:["#",C.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:C.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:[R(C.tokenBalance)," / ",R(C.maxTokens)]})]}),C.paperWork&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Paper earned"}),jsx("span",{className:"text-foreground",children:C.paperWork})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Created"}),jsx("span",{className:"text-foreground",children:V(C.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:a,onChange:I=>{let Z=I.target.value.replace(/[^0-9]/g,""),H=parseInt(Z,10);l(isNaN(H)?"":H.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":y,onClick:()=>P(!y),className:u("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded border-2 transition-colors cursor-pointer",y?"border-foreground bg-foreground":"border-muted-foreground/40"),children:y&&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"})]})]}),m&&jsx("p",{className:"text-sm text-red-500",children:m}),jsxs("button",{onClick:se,disabled:!S,className:u("flex w-full items-center justify-center gap-2 rounded-xl py-4 text-sm font-semibold transition-colors",S?"bg-foreground text-background hover:bg-foreground/90":"bg-muted text-muted-foreground cursor-not-allowed"),children:[jsx(ExternalLink,{className:"h-4 w-4"}),o?"Listing...":"List on Marketplace"]})]})}var je=20;function Ae({nodeKey:e,className:t,style:r}){let[s,g]=useState(false),[x,c]=useState(false),d=useRef(null),{entries:o,loading:n}=pe(s?e.id:null);useEffect(()=>()=>{d.current&&clearTimeout(d.current);},[]);let m=useCallback(()=>{e.key&&(navigator.clipboard.writeText(e.key),c(true),d.current&&clearTimeout(d.current),d.current=setTimeout(()=>c(false),2e3));},[e.key]),f=e.status==="active"?"text-green-500":e.status==="expired"?"text-red-500":"text-yellow-500",p=o.slice(0,je);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",f),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:m,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground",children:x?jsx(Check,{className:"h-3.5 w-3.5 text-green-500"}):jsx(Copy,{className:"h-3.5 w-3.5"})})]}),jsx(W,{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 ",V(e.createdAt)]}),e.expiresAt&&jsxs("span",{children:["Expires ",V(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"}),n?jsx("p",{className:"text-xs text-muted-foreground",children:"Loading..."}):p.length===0?jsx("p",{className:"text-xs text-muted-foreground",children:"No ledger entries."}):jsxs("div",{className:"space-y-1.5",children:[p.map(a=>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",a.type==="credit"||a.type==="reward"?"text-green-500":"text-red-500"),children:[a.type==="credit"||a.type==="reward"?"+":"-",R(Math.abs(a.amount))]}),jsx("span",{className:"text-muted-foreground",children:a.description})]}),jsx("span",{className:"text-muted-foreground",children:V(a.createdAt)})]},a.id)),o.length>je&&jsxs("p",{className:"pt-1 text-xs text-muted-foreground",children:["Showing ",je," of ",o.length," entries"]})]})]})]})}var Lr=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"keys",label:"Keys"}];function xe({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 Er({getKeyHref:e="/keys/get",showTabs:t=true,className:r,style:s}){let{keys:g,totalBalance:x,loading:c,error:d,refresh:o}=J();return c?jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(xe,{baseHref:e}),jsx(Q,{count:3})]}):d?jsxs("div",{className:u("space-y-4",r),style:s,children:[t&&e&&jsx(xe,{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:d})]}),jsx("button",{onClick:()=>o(),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(xe,{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(xe,{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: ",R(x)]}),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(n=>jsx(Ae,{nodeKey:n},n.id))]})}function Dr({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(W,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"})]})]})}function $r({className:e,style:t}){let{keys:r,loading:s}=J(),{transferKey:g,transferring:x,result:c,error:d}=fe(),[o,n]=useState(null),[m,f]=useState(""),[p,a]=useState(false),l=r.filter(S=>S.status==="active"),y=l.find(S=>S.id===o),P=y&&m.trim()===y.userId,C=o&&m.trim().length>0&&p&&!P&&!x,L=async()=>{!o||!m.trim()||await g(o,m.trim());},D=()=>{n(null),f(""),a(false);};return c?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:[c.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:[c.toUserId.slice(0,20),"..."]})]})]}),jsx("button",{onClick:D,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(Q,{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(S=>jsx(Dr,{nodeKey:S,selected:o===S.id,onSelect:()=>n(S.id)},S.id))})]}),o&&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:m,onChange:S=>{f(S.target.value),a(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"}),P&&jsx("p",{className:"mt-1.5 text-xs text-red-500",children:"Cannot transfer a key to yourself"})]}),y&&m.trim().length>0&&!P&&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:y.keyIndex?`#${y.keyIndex}`:y.id.slice(0,12)})," ","(",R(y.tokenBalance)," tokens) to"," ",jsxs("span",{className:"font-mono font-medium",children:[m.trim().slice(0,20),"..."]})]})]}),jsxs("label",{className:"flex items-start gap-2 cursor-pointer",children:[jsx("input",{type:"checkbox",checked:p,onChange:S=>a(S.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."})]})]})]})}),d&&jsx("p",{className:"text-sm text-red-500",children:d}),jsx("button",{onClick:L,disabled:!C,className:u("flex w-full items-center justify-center gap-2 rounded-lg px-4 py-3 text-sm font-medium transition-all",C?"bg-foreground text-background hover:opacity-90":"bg-muted text-muted-foreground cursor-not-allowed"),children:x?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"]})})]})}
|
|
2
|
-
export{
|
|
1
|
+
import Ht,{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,X as X$1,ArrowLeft,KeyRound,ExternalLink,AlertTriangle,ChevronDown,ChevronRight,Send,CheckCircle2,AlertCircle,Info,FileText,Minus,Plus,ChevronUp}from'lucide-react';var Qe=createContext(null);function C(){let e=useContext(Qe);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function Se({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(Qe.Provider,{value:s,children:r})}function z(){if(typeof document>"u")return {};let e=document.cookie.match(/(?:^|;\s*)__csrf=([^;]*)/);return e?{"x-csrf-token":e[1]}:{}}function Je(e,t){if(typeof e!="string"||e.length===0)return t;let r=e.replace(/[\u0000-\u001F\u007F]/g," ");return r.length>500?r.slice(0,500)+"\u2026":r}async function E(e,t){try{let r=await e.json();if(r&&typeof r=="object"&&"error"in r)return Je(r.error,t)}catch{}return t}function D(e,t="#"){if(!e||typeof e!="string")return t;let r=e.trim();if(r===""||r==="#")return t;if(r.startsWith("/")||r.startsWith("./")||r.startsWith("../"))return r;try{let s=new URL(r);if(s.protocol==="http:"||s.protocol==="https:")return s.toString()}catch{}return t}function l(...e){return twMerge(clsx(e))}function R(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 Xe(e,t){return t<=0?0:Math.min(100,Math.round(e/t*100))}function Ze(e){return e>=70?"bg-green-500":e>=30?"bg-yellow-500":"bg-red-500"}function G(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 et(){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 rt(){let{config:e}=C(),[t,r]=useState(null),[s,g]=useState(true),[u,a]=useState(null),i=useRef(true),o=useRef(e.apiBaseUrl);o.current=e.apiBaseUrl;let n=async()=>{try{i.current&&(g(!0),a(null));let f=await fetch(`${o.current}/api/keys/pricing`,{credentials:"include"});if(!f.ok)throw new Error(await E(f,`Pricing unavailable (${f.status})`));let m=await f.json();i.current&&r(m);}catch(f){i.current&&a(f instanceof Error?f.message:"Failed to fetch pricing");}finally{i.current&&g(false);}};return useEffect(()=>{i.current=true,n();let f=setInterval(n,6e4);return ()=>{i.current=false,clearInterval(f);}},[]),{pricing:t,loading:s,error:u,refresh:n}}function st(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[g,u]=useState(null),[a,i]=useState(null);return {mint:useCallback(async(n,f,m=1)=>{try{s(!0),i(null),t.onPaymentComplete?.(n,f);let p=await fetch(`${e.apiBaseUrl}/api/keys/mint`,{method:"POST",headers:{"Content-Type":"application/json",...z()},credentials:"include",body:JSON.stringify({paymentMethod:n,paymentRef:f,quantity:m,stackId:e.stackId})});if(!p.ok)throw new Error(await E(p,`Key generation failed (${p.status})`));let d=await p.json(),x=d.keys?.[0]||d,N={success:!0,key:{id:x.keyId||x.id||"",key:x.key||"",userId:x.userId||"",status:"active",tokenBalance:x.tokenBalance??x.currentTokenBalance??0,maxTokens:x.initialTokenBalance??x.tokenBalance??0,createdAt:String(x.createdAt||Date.now())},transactionId:f};return u(N),t.onMintSuccess?.(N),N}catch(p){let d=p instanceof Error?p:new Error("Key generation failed");return i(d.message),t.onMintError?.(d),{success:false,error:d.message}}finally{s(false);}},[e.apiBaseUrl,t]),minting:r,result:g,error:a}}function nt(){let{config:e}=C(),[t,r]=useState(false),[s,g]=useState(null),u=useRef(true);return {createSession:useCallback(async(i,o)=>{try{r(!0),g(null);let n=await fetch(`${e.apiBaseUrl}/api/keys/stripe-session`,{method:"POST",headers:{"Content-Type":"application/json",...z()},credentials:"include",body:JSON.stringify({priceCents:i,quantity:o,stackId:e.stackId,referrerUrl:window.location.href})});if(!n.ok)throw new Error(await E(n,`Checkout failed (${n.status})`));let{url:f}=await n.json();if(!f)throw new Error("No checkout URL returned");let m;try{m=new URL(f);}catch{throw new Error("Invalid checkout URL")}if(m.protocol!=="https:"||!/(^|\.)stripe\.com$/.test(m.hostname))throw new Error("Refusing to redirect to non-Stripe URL");try{sessionStorage.setItem("keyutils_stripe_pending","1"),sessionStorage.setItem("keyutils_stripe_quantity",String(o));}catch{}window.location.href=m.toString();}catch(n){if(u.current){let f=n instanceof Error?n.message:"Checkout failed";g(f),r(false);}}},[e.apiBaseUrl,e.stackId]),loading:t,error:s}}var it=/^[1-9A-HJ-NP-Za-km-z]{32,44}$/;function Ue({amountSol:e,onSuccess:t,onError:r,disabled:s,className:g,style:u}){let{config:a}=C(),[i,o]=useState(false),[n,f]=useState(null),m=!!(a.merchantWallet&&it.test(a.merchantWallet)),p=useCallback(async()=>{if(m)try{o(!0),f(null);let{Connection:d,PublicKey:x,Transaction:N,SystemProgram:I,LAMPORTS_PER_SOL:w}=await import('@solana/web3.js'),L=typeof window<"u"?window.solana:void 0;if(!L||typeof L!="object"||!L.isPhantom)throw new Error("Phantom wallet not found. Please install Phantom.");let A=L,P;try{P=new x(a.merchantWallet);}catch{throw new Error("Invalid merchant wallet address.")}let re=await A.connect(),M=new x(re.publicKey.toString()),F="https://api.mainnet-beta.solana.com",se=D(a.solanaRpcUrl,F),de=se==="#"?F:se,Ce=new d(de),{blockhash:O}=await Ce.getLatestBlockhash(),ee=BigInt(Math.floor(e*1e9)),ce=a.protocolTreasuryWallet,me=a.protocolFeeBps??500,ue=new N({recentBlockhash:O,feePayer:M});if(ce&&it.test(ce)&&me>0){let He=ee*BigInt(me)/10000n,Tt=ee-He,Kt=new x(ce);ue.add(I.transfer({fromPubkey:M,toPubkey:P,lamports:Number(Tt)}),I.transfer({fromPubkey:M,toPubkey:Kt,lamports:Number(He)}));}else ue.add(I.transfer({fromPubkey:M,toPubkey:P,lamports:Number(ee)}));let{signature:ye}=await A.signAndSendTransaction(ue);t(ye);}catch(d){let x=d instanceof Error?d:new Error("Payment failed");f(x.message),r?.(x);}finally{o(false);}},[e,a.merchantWallet,m,t,r]);return jsxs("div",{children:[jsx("button",{onClick:p,disabled:s||i||!m,"aria-label":`Pay ${e.toFixed(4)} SOL`,className:l("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:u,children:i?jsxs(Fragment,{children:[jsx(Loader2,{className:"h-4 w-4 animate-spin"}),"Processing..."]}):jsxs(Fragment,{children:["Pay ",e.toFixed(4)," SOL"]})}),n&&jsx("p",{className:"mt-2 text-center text-xs text-red-500",children:n})]})}function Be({result:e,className:t,style:r}){let[s,g]=useState(false),u=useRef(null);useEffect(()=>()=>{u.current&&clearTimeout(u.current);},[]);let a=useCallback(()=>{e.key?.key&&(navigator.clipboard.writeText(e.key.key),g(true),u.current&&clearTimeout(u.current),u.current=setTimeout(()=>g(false),2e3));},[e.key?.key]);return !e.success||!e.key?null:jsxs("div",{className:l("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:a,"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 X({className:e}){return jsx("div",{className:l("animate-pulse rounded-xl bg-muted",e)})}function Le(){return jsxs("div",{className:"space-y-6",children:[jsxs("div",{className:"px-6 py-10 flex flex-col items-center gap-3",children:[jsx(X,{className:"h-14 w-48"}),jsx(X,{className:"h-5 w-64"})]}),jsx(X,{className:"h-[72px] w-full rounded-2xl"}),jsx(X,{className:"h-[68px] w-full rounded-2xl"}),jsx(X,{className:"h-[60px] w-full rounded-2xl"})]})}function oe({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(X,{className:"h-4 w-32"}),jsx(X,{className:"h-4 w-16"})]}),jsx(X,{className:"h-2 w-full rounded-full"}),jsxs("div",{className:"flex justify-between",children:[jsx(X,{className:"h-3 w-24"}),jsx(X,{className:"h-3 w-20"})]})]},r))})}function sr({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 ut({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 Ee({className:e,style:t}){let{config:r}=C(),{pricing:s,loading:g,error:u,refresh:a}=rt(),{mint:i,minting:o,result:n,error:f}=st(),{createSession:m,loading:p,error:d}=nt(),[x,N]=useState(1),[I,w]=useState(r.paymentMethods?.includes("stripe")?"stripe":"solana"),[L,A]=useState(0),[P,re]=useState(false),M=Ht.useRef(x);M.current=x;let F=Math.max(1,r.maxQuantity||5),se=[...r.paymentMethods||["solana"]].sort((O,ee)=>O==="stripe"?-1:ee==="stripe"?1:0);if(useEffect(()=>{if(typeof window>"u")return;let ee=new URLSearchParams(window.location.search).get("session_id");if(!ee){try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}return}if(/^cs_(test|live)_/.test(ee)&&!P&&!n?.success){let ce=false;try{ce=sessionStorage.getItem("keyutils_stripe_pending")==="1";}catch{}if(!ce)return;try{sessionStorage.removeItem("keyutils_stripe_pending");}catch{}re(true);let me=new URL(window.location.href);me.searchParams.delete("session_id"),window.history.replaceState({},"",me.toString());let ue=M.current;try{let ye=sessionStorage.getItem("keyutils_stripe_quantity");ye&&(ue=parseInt(ye,10)||1,sessionStorage.removeItem("keyutils_stripe_quantity"));}catch{}i("stripe",ee,ue);}},[P,n,i]),n?.success)return jsx("div",{className:l("flex flex-col items-center justify-center",e),style:t,children:jsx(Be,{result:n})});if(P||o)return jsx("div",{className:l("flex flex-col",e),style:t,children:jsx(Le,{})});if(g)return jsx("div",{className:l("flex flex-col",e),style:t,children:jsx(Le,{})});if(u||!s)return jsxs("div",{className:l("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:u||"Please check your connection and try again."})]}),jsx("button",{onClick:()=>a(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let de=async O=>{A(2),await i(I,O,x);},Ce=()=>{m(s.priceCents,x);};return jsx("div",{className:l("flex flex-col",e),style:t,children:jsxs("div",{className:"space-y-6",children:[L===0&&jsxs(Fragment,{children:[r.keyImage&&jsx("img",{src:D(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||R(s.tokenAllocation)," tokens included"]})]}),jsx(sr,{quantity:x,max:F,onChange:N}),jsx(ut,{pricing:s,quantity:x}),jsx("button",{onClick:()=>A(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"})]}),L===1&&jsxs(Fragment,{children:[se.length>1&&jsx("div",{role:"tablist",className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5",children:se.map(O=>jsxs("button",{role:"tab","aria-selected":I===O,onClick:()=>w(O),className:l("flex flex-1 items-center justify-center gap-2.5 rounded-xl py-4 text-sm font-medium transition-colors",I===O?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:[O==="stripe"?jsx(CreditCard,{className:"h-5 w-5"}):jsx(Wallet,{className:"h-5 w-5"}),O==="stripe"?"Credit Card":"Crypto"]},O))}),jsx(ut,{pricing:s,quantity:x}),I==="stripe"?jsxs(Fragment,{children:[jsx("button",{onClick:Ce,disabled:p,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:p?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"]})}),d&&jsx("p",{className:"text-center text-sm text-red-500",children:d})]}):I==="solana"?jsx(Ue,{amountSol:s.priceSol??0,onSuccess:de,className:"rounded-2xl py-5 text-base"}):null,f&&jsx("p",{className:"text-center text-sm text-red-500",children:f}),jsx("button",{onClick:()=>A(0),className:"w-full py-3 text-center text-sm text-muted-foreground hover:text-foreground transition-colors",children:"\u2190 Back"})]})]})})}var ir={ios:"iOS",android:"Android",windows:"Windows",mac:"macOS",linux:"Linux"},lr=["mac","windows","linux","ios","android"];function je({downloads:e,className:t,style:r}){let{config:s}=C(),g=useMemo(()=>et(),[]),u=e||lr.map(o=>({platform:o,label:ir[o],url:"#",compatible:o===g})),a=u.find(o=>o.compatible)||u[0],i=u.filter(o=>o.platform!==a.platform);return jsxs("div",{className:l("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:D(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:D(a.url),target:"_blank",rel:"noopener noreferrer",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 ",a.label]})]}),jsxs("p",{className:"text-center text-sm text-muted-foreground",children:["aiSP is also available on"," ",i.map((o,n)=>jsxs(Ht.Fragment,{children:[n>0&&(n===i.length-1?" and ":", "),jsx("a",{href:D(o.url),target:"_blank",rel:"noopener noreferrer",className:"font-medium underline transition-colors hover:text-foreground",style:{color:"#066bff"},children:o.label})]},o.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:D(s.termsUrl,"/terms"),target:"_blank",rel:"noopener noreferrer",className:"text-foreground underline hover:text-foreground/80",children:"Open Source Applications Terms"})]})]})]})}function mr(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 H(){let{config:e}=C(),[t,r]=useState([]),[s,g]=useState(true),[u,a]=useState(null),i=useRef(true),o=e.apiBaseUrl,n=useCallback(async()=>{try{g(!0),a(null);let m=await fetch(`${o}/api/keys`,{credentials:"include"});if(!m.ok)throw new Error(await E(m,`Failed to fetch keys (${m.status})`));let p=await m.json(),d=Array.isArray(p)?p:p.keys??[];i.current&&r(d.map(mr));}catch(m){i.current&&a(m instanceof Error?m.message:"Failed to fetch keys");}finally{i.current&&g(false);}},[o]);useEffect(()=>(i.current=true,n(),()=>{i.current=false;}),[n]);let f=t.reduce((m,p)=>m+p.tokenBalance,0);return {keys:t,totalBalance:f,loading:s,error:u,refresh:n}}function Q({current:e,max:t,className:r,style:s,showLabel:g=true}){let u=Xe(e,t),a=Ze(u);return jsxs("div",{className:l("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:[R(e)," / ",R(t)]}),jsxs("span",{children:[u,"%"]})]}),jsx("div",{className:"h-2 w-full overflow-hidden rounded-full bg-muted",children:jsx("div",{className:l("h-full rounded-full transition-all duration-500",a),style:{width:`${u}%`}})})]})}function Ne(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[g,u]=useState(null),[a,i]=useState(null),o=useRef(true),n=useCallback(async(m,p)=>{try{s(!0),i(null);let d=await fetch(`${e.apiBaseUrl}/api/keys/${encodeURIComponent(m)}/list`,{method:"POST",headers:{"Content-Type":"application/json",...z()},credentials:"include",body:JSON.stringify({askPriceCents:p,stackId:e.stackId,stackName:e.stackName})});if(!d.ok)throw new Error(await E(d,`Listing failed (${d.status})`));let x=await d.json();return o.current&&(u(x),t.onListingCreated?.(x)),x}catch(d){let x=d instanceof Error?d.message:"Listing failed";return o.current&&i(x),null}finally{o.current&&s(false);}},[e.apiBaseUrl,e.stackId,e.stackName,t]),f=useCallback(async m=>{try{s(!0),i(null);let p=await fetch(`${e.apiBaseUrl}/api/keys/${encodeURIComponent(m)}/list`,{method:"DELETE",headers:{...z()},credentials:"include"});if(!p.ok)throw new Error(await E(p,`Delist failed (${p.status})`));return o.current&&u(null),!0}catch(p){let d=p instanceof Error?p.message:"Delist failed";return o.current&&i(d),false}finally{o.current&&s(false);}},[e.apiBaseUrl]);return {listKey:n,delistKey:f,listing:r,result:g,error:a}}function ve(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[g,u]=useState(null),[a,i]=useState(null),o=useRef(true);return {transferKey:useCallback(async(f,m)=>{try{s(!0),i(null);let p=await fetch(`${e.apiBaseUrl}/api/keys/${encodeURIComponent(f)}/transfer`,{method:"POST",headers:{"Content-Type":"application/json",...z()},credentials:"include",body:JSON.stringify({recipientId:m})});if(!p.ok)throw new Error(await E(p,`Transfer failed (${p.status})`));let d=await p.json();return o.current&&(u(d),t.onTransferComplete?.(d)),d}catch(p){let d=p instanceof Error?p.message:"Transfer failed";return o.current&&i(d),null}finally{o.current&&s(false);}},[e.apiBaseUrl,t]),transferring:r,result:g,error:a}}function he(e){let{config:t}=C(),[r,s]=useState([]),[g,u]=useState(false),[a,i]=useState(null),o=useRef(true),n=t.apiBaseUrl,f=useCallback(async()=>{if(e)try{u(!0),i(null);let m=await fetch(`${n}/api/keys/${encodeURIComponent(e)}/ledger`,{credentials:"include"});if(!m.ok)throw new Error(await E(m,`Failed to fetch ledger (${m.status})`));let p=await m.json();o.current&&s(Array.isArray(p)?p:p.entries??[]);}catch(m){o.current&&i(m instanceof Error?m.message:"Failed to fetch ledger");}finally{o.current&&u(false);}},[n,e]);return useEffect(()=>(o.current=true,f(),()=>{o.current=false;}),[f]),{entries:r,loading:g,error:a,refresh:f}}function ge({open:e,onClose:t,title:r,children:s}){let g=useRef(null),[u,a]=useState(false),[i,o]=useState(false),n=useCallback(f=>{f.key==="Escape"&&t();},[t]);return useEffect(()=>{if(e)a(true),document.addEventListener("keydown",n),document.body.style.overflow="hidden",requestAnimationFrame(()=>{requestAnimationFrame(()=>o(true));});else {o(false);let f=setTimeout(()=>{a(false),document.body.style.overflow="";},300);return document.removeEventListener("keydown",n),()=>clearTimeout(f)}return ()=>{document.removeEventListener("keydown",n);}},[e,n]),u?jsxs("div",{className:"fixed inset-0 z-50 flex items-end justify-center",children:[jsx("div",{className:"absolute inset-0 bg-black/50 backdrop-blur-sm transition-opacity duration-300",style:{opacity:i?1:0},onClick:t}),jsxs("div",{ref:g,className:l("relative z-10 w-full max-w-xl rounded-t-2xl bg-background shadow-2xl","max-h-[85vh] flex flex-col","transition-transform duration-300 ease-out"),style:{transform:i?"translateY(0)":"translateY(100%)"},children:[jsx("div",{className:"flex justify-center pt-3 pb-1",children:jsx("div",{className:"h-1 w-10 rounded-full bg-muted-foreground/30"})}),r&&jsxs("div",{className:"flex items-center justify-between px-5 pb-3 pt-1",children:[jsx("h3",{className:"text-lg font-semibold text-foreground",children:r}),jsx("button",{onClick:t,className:"rounded-full p-1.5 text-muted-foreground hover:bg-muted hover:text-foreground transition-colors","aria-label":"Close",children:jsx(X$1,{className:"h-5 w-5"})})]}),jsx("div",{className:"flex-1 overflow-y-auto px-5 pb-8",children:s})]})]}):null}function Rr({nodeKey:e,onSuccess:t}){let{transferKey:r,transferring:s,result:g,error:u}=ve(),[a,i]=useState(""),[o,n]=useState(false),f=a.trim()===e.userId,m=a.trim().length>0&&o&&!f&&!s,p=async()=>{if(!m)return;await r(e.id,a.trim())&&t();};return g?jsxs("div",{className:"flex flex-col items-center gap-4 py-8",children:[jsx(CheckCircle,{className:"h-12 w-12 text-green-500"}),jsx("h3",{className:"text-lg font-semibold text-foreground",children:"Transfer Complete"}),jsx("p",{className:"text-sm text-muted-foreground",children:"Key transferred successfully"})]}):jsxs("div",{className:"space-y-5",children:[jsxs("div",{children:[jsx("label",{className:"mb-1.5 block text-sm font-semibold text-foreground",children:"Recipient User ID"}),jsx("input",{type:"text",value:a,onChange:d=>{i(d.target.value),n(false);},placeholder:"Enter recipient's user ID or global ID",className:"w-full rounded-xl border border-border bg-background px-4 py-3 text-sm text-foreground placeholder:text-muted-foreground focus:border-foreground/30 focus:outline-none focus:ring-1 focus:ring-foreground/10"}),f&&jsx("p",{className:"mt-1.5 text-xs text-red-500",children:"Cannot transfer a key to yourself"})]}),a.trim().length>0&&!f&&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:["Transferring key"," ",jsx("span",{className:"font-mono font-medium",children:e.keyIndex?`#${e.keyIndex}`:e.id.slice(0,12)})," ","(",R(e.tokenBalance)," tokens) to"," ",jsxs("span",{className:"font-mono font-medium",children:[a.trim().slice(0,20),a.trim().length>20?"...":""]})]})]}),jsxs("label",{className:"flex items-start gap-2 cursor-pointer",children:[jsx("input",{type:"checkbox",checked:o,onChange:d=>n(d.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."})]})]})]})}),u&&jsx("p",{className:"text-sm text-red-500",children:u}),jsx("button",{onClick:p,disabled:!m,className:l("flex w-full items-center justify-center gap-2 rounded-xl py-4 text-sm font-semibold transition-colors",m?"bg-foreground text-background hover:bg-foreground/90":"bg-muted text-muted-foreground cursor-not-allowed"),children:s?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"]})})]})}function Tr({nodeKey:e,onSuccess:t}){let{config:r}=C(),{listKey:s,listing:g,result:u,error:a}=Ne(),[i,o]=useState(""),[n,f]=useState(false),m=parseInt(i.replace(/[^0-9]/g,""),10)||0,d=m>0&&Number.isFinite(m)&&n&&!g,x=async()=>{if(!d)return;let N=m*100;await s(e.id,N)&&t();};return u?jsxs("div",{className:"flex flex-col items-center gap-4 py-8",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 marketplace."}),jsxs("p",{className:"text-xs text-muted-foreground",children:["Listing ID: ",jsx("code",{children:u.listingId})]})]}):jsxs("div",{className:"space-y-5",children:[jsxs("div",{children:[jsx("label",{htmlFor:"listing-price",className:"mb-2 block text-sm 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:i,onChange:N=>{let I=N.target.value.replace(/[^0-9]/g,""),w=parseInt(I,10);o(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":n,onClick:()=>f(!n),className:l("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded border-2 transition-colors cursor-pointer",n?"border-foreground bg-foreground":"border-muted-foreground/40"),children:n&&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:D(r.termsUrl,"/terms"),className:"text-foreground underline",target:"_blank",rel:"noopener noreferrer",children:"Terms"})]})]}),a&&jsx("p",{className:"text-sm text-red-500",children:a}),jsxs("button",{onClick:x,disabled:!d,className:l("flex w-full items-center justify-center gap-2 rounded-xl py-4 text-sm font-semibold transition-colors",d?"bg-foreground text-background hover:bg-foreground/90":"bg-muted text-muted-foreground cursor-not-allowed"),children:[jsx(ExternalLink,{className:"h-4 w-4"}),g?"Listing...":"List on Marketplace"]})]})}function Kr({nodeKey:e}){let[t,r]=useState(false);if(!e.paperWork)return jsxs("div",{className:"flex flex-col items-center gap-3 py-12",children:[jsx(FileText,{className:"h-10 w-10 text-muted-foreground"}),jsx("p",{className:"text-sm text-muted-foreground",children:"This key has no paperwork to file."})]});let s=()=>{navigator.clipboard.writeText(e.paperWork||""),r(true),setTimeout(()=>r(false),2e3);};return jsxs("div",{className:"space-y-5",children:[jsxs("div",{children:[jsx("label",{className:"mb-2 block text-sm font-semibold text-foreground",children:"Paperwork"}),jsxs("div",{className:"relative rounded-xl border bg-muted/30 p-4",children:[jsx("pre",{className:"whitespace-pre-wrap break-all text-sm text-foreground font-mono",children:e.paperWork}),jsx("button",{onClick:s,className:"absolute top-3 right-3 rounded-lg p-1.5 text-muted-foreground hover:bg-muted hover:text-foreground transition-colors","aria-label":"Copy paperwork",children:t?jsx(Check,{className:"h-4 w-4 text-green-500"}):jsx(Copy,{className:"h-4 w-4"})})]})]}),jsx("p",{className:"text-xs text-muted-foreground",children:"Filing paperwork submits the key's documentation on-chain for permanent record."}),jsxs("button",{disabled:true,className:"flex w-full items-center justify-center gap-2 rounded-xl bg-muted py-4 text-sm font-semibold text-muted-foreground cursor-not-allowed",children:[jsx(FileText,{className:"h-4 w-4"}),"File Paperwork (Coming Soon)"]})]})}function We({nodeKey:e,onBack:t,onKeysChanged:r,className:s,style:g}){let{config:u}=C(),{entries:a,loading:i}=he(e.id),[o,n]=useState(null),[f,m]=useState(false),p=()=>{n(null),r?.();},d=()=>{e.key&&(navigator.clipboard.writeText(e.key),m(true),setTimeout(()=>m(false),2e3));},x=e.status==="active"?"text-green-500":e.status==="expired"?"text-red-500":"text-yellow-500";return jsxs("div",{className:l("space-y-5",s),style:g,children:[jsxs("button",{onClick:t,className:"flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors",children:[jsx(ArrowLeft,{className:"h-4 w-4"}),"Back to Keys"]}),jsx("div",{className:"space-y-1",children:jsxs("div",{className:"flex items-center justify-between",children:[jsx("h2",{className:"text-2xl font-bold text-foreground",children:e.keyIndex?`Key #${e.keyIndex}`:e.label||e.id.slice(0,16)}),jsx("span",{className:l("text-sm font-medium capitalize",x),children:e.status})]})}),e.key&&jsxs("div",{className:"flex items-center gap-2",children:[jsx("code",{className:"flex-1 truncate rounded-lg bg-muted px-3 py-2 text-xs text-muted-foreground",children:e.key}),jsx("button",{onClick:d,"aria-label":"Copy key",className:"shrink-0 rounded-lg p-2 text-muted-foreground hover:bg-muted hover:text-foreground transition-colors",children:f?jsx(Check,{className:"h-4 w-4 text-green-500"}):jsx(Copy,{className:"h-4 w-4"})})]}),jsx(Q,{current:e.tokenBalance,max:e.maxTokens,showLabel:true}),jsxs("div",{className:"rounded-xl bg-muted/30 p-5 space-y-2.5 text-sm",children:[e.keyIndex&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key #"}),jsxs("span",{className:"text-foreground font-semibold",children:["#",e.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:e.id})]}),(u.stackName||e.stackName)&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Stack"}),jsx("span",{className:"text-foreground",children:e.stackName||u.stackName})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Tokens"}),jsxs("span",{className:"text-foreground",children:[R(e.tokenBalance)," / ",R(e.maxTokens)]})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Created"}),jsx("span",{className:"text-foreground",children:G(e.createdAt)})]}),e.expiresAt&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Expires"}),jsx("span",{className:"text-foreground",children:G(e.expiresAt)})]})]}),e.paperWork&&jsxs("div",{className:"rounded-xl border bg-muted/30 p-5",children:[jsx("h3",{className:"text-sm font-semibold text-foreground mb-2",children:"Paperwork"}),jsx("pre",{className:"whitespace-pre-wrap break-all text-xs text-muted-foreground font-mono",children:e.paperWork})]}),e.status==="active"&&jsxs("div",{className:"grid grid-cols-3 gap-3",children:[jsx("button",{onClick:()=>n("transfer"),className:"flex items-center justify-center rounded-xl border border-border p-4 text-sm font-medium text-foreground hover:bg-muted/50 transition-colors",children:"Transfer"}),jsx("button",{onClick:()=>n("sell"),className:"flex items-center justify-center rounded-xl border border-border p-4 text-sm font-medium text-foreground hover:bg-muted/50 transition-colors",children:"Sell"}),jsx("button",{onClick:()=>n("file"),className:l("flex items-center justify-center rounded-xl border border-border p-4 text-sm font-medium transition-colors",e.paperWork?"text-foreground hover:bg-muted/50":"text-muted-foreground cursor-not-allowed opacity-50"),disabled:!e.paperWork,children:"File"})]}),jsxs("div",{children:[jsx("h3",{className:"text-sm font-semibold text-foreground mb-3",children:"Ledger"}),i?jsx("p",{className:"text-xs text-muted-foreground",children:"Loading ledger..."}):a.length===0?jsx("p",{className:"text-xs text-muted-foreground",children:"No ledger entries."}):jsxs("div",{className:"space-y-1.5",children:[a.slice(0,20).map(N=>jsxs("div",{className:"flex items-center justify-between text-xs",children:[jsxs("div",{className:"flex items-center gap-2",children:[jsxs("span",{className:l("font-medium",N.type==="credit"||N.type==="reward"?"text-green-500":"text-red-500"),children:[N.type==="credit"||N.type==="reward"?"+":"-",R(Math.abs(N.amount))]}),jsx("span",{className:"text-muted-foreground",children:N.description})]}),jsx("span",{className:"text-muted-foreground",children:G(N.createdAt)})]},N.id)),a.length>20&&jsxs("p",{className:"pt-1 text-xs text-muted-foreground",children:["Showing 20 of ",a.length," entries"]})]})]}),jsx(ge,{open:o==="transfer",onClose:()=>n(null),title:"Transfer Key",children:jsx(Rr,{nodeKey:e,onSuccess:p})}),jsx(ge,{open:o==="sell",onClose:()=>n(null),title:"Sell Key",children:jsx(Tr,{nodeKey:e,onSuccess:p})}),jsx(ge,{open:o==="file",onClose:()=>n(null),title:"File Paperwork",children:jsx(Kr,{nodeKey:e})})]})}function Ir({nodeKey:e,onClick:t}){let r=e.status==="active"?"text-green-500":e.status==="expired"?"text-red-500":"text-yellow-500";return jsx("button",{onClick:t,className:"flex w-full items-start gap-3 rounded-xl border border-border p-4 text-left transition-all hover:border-foreground/20 hover:bg-muted/30",children: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:l("text-xs font-medium capitalize",r),children:e.status})]}),jsx(Q,{current:e.tokenBalance,max:e.maxTokens,className:"mt-2"}),e.paperWork&&jsx("span",{className:"mt-1.5 inline-block text-xs text-muted-foreground",children:"Has paperwork"})]})})}function Oe({className:e,style:t}){let{keys:r,loading:g,error:u,refresh:a}=H(),[i,o]=useState(null),[n,f]=useState("active"),m=r.filter(x=>x.status===n),p=m.reduce((x,N)=>x+N.tokenBalance,0),d=r.find(x=>x.id===i);return d?jsx(We,{nodeKey:d,onBack:()=>o(null),onKeysChanged:()=>{o(null),a();},className:e,style:t}):g?jsxs("div",{className:l("space-y-4",e),style:t,children:[jsx("h3",{className:"text-2xl mt-3 mb-2 font-semibold text-foreground",children:"Your Keys"}),jsx(oe,{count:3})]}):u?jsxs("div",{className:l("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:u})]}),jsx("button",{onClick:()=>a(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]}):r.length===0?jsxs("div",{className:l("flex flex-col items-center justify-center gap-4 rounded-xl border border-dashed py-16",e),style:t,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."})]})]}):jsxs("div",{className:l("space-y-4",e),style:t,children:[jsxs("div",{className:"flex items-center justify-between mt-3",children:[jsx("h3",{className:"text-2xl font-semibold text-foreground",children:"Your Keys"}),jsxs("span",{className:"text-xs text-muted-foreground",children:[m.length," key",m.length!==1?"s":""," \xB7 ",R(p)," tokens"]}),jsx("div",{className:"flex gap-1 rounded-lg bg-muted/50 p-1",children:["active","listed"].map(x=>jsx("button",{onClick:()=>f(x),className:l("rounded-md px-3 py-1 text-xs font-medium capitalize transition-all",n===x?"bg-background text-foreground shadow-sm":"text-muted-foreground hover:text-foreground"),children:x},x))})]}),m.length===0?jsxs("div",{className:"flex flex-col items-center justify-center gap-3 rounded-xl border border-dashed py-12",children:[jsx(KeyRound,{className:"h-8 w-8 text-muted-foreground"}),jsxs("p",{className:"text-sm text-muted-foreground",children:["No ",n," keys."]})]}):jsx("div",{className:"space-y-2",children:m.map(x=>jsx(Ir,{nodeKey:x,onClick:()=>o(x.id)},x.id))})]})}var Br=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"keys",label:"Keys"}];function Lr({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:Br.map(({id:r,label:s})=>jsx("button",{role:"tab","aria-selected":e===r,"aria-controls":`panel-${r}`,id:`tab-${r}`,onClick:()=>t(r),className:l("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 Er({defaultTab:e="buy",className:t,style:r}){let[s,g]=useState(e);return jsxs("div",{className:l("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(Lr,{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(Ee,{className:"flex-1"}),s==="use"&&jsx(je,{className:"flex-1"}),s==="keys"&&jsx(Oe,{className:"flex-1"})]})})})]})}function jr({apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:g,stripePublicKey:u,theme:a,maxQuantity:i,keyImage:o,keyImageClass:n,aispImage:f,termsUrl:m,onMintSuccess:p,onMintError:d,onPaymentStart:x,onPaymentComplete:N,onListingCreated:I,onTransferComplete:w,defaultTab:L,className:A,style:P}){return jsx(Se,{config:{apiBaseUrl:e,stackId:t,stackName:r,paymentMethods:s,merchantWallet:g,stripePublicKey:u,theme:a,maxQuantity:i,keyImage:o,keyImageClass:n,aispImage:f,termsUrl:m},callbacks:{onMintSuccess:p,onMintError:d,onPaymentStart:x,onPaymentComplete:N,onListingCreated:I,onTransferComplete:w},children:jsx(Er,{defaultTab:L,className:A,style:P})})}function _r({nodeKey:e,selected:t,onSelect:r}){return jsxs("button",{onClick:r,className:l("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:l("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:l("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 Ar({className:e,style:t}){let{config:r}=C(),{keys:s,loading:g,error:u,refresh:a}=H(),{listKey:i,listing:o,result:n,error:f}=Ne(),[m,p]=useState(null),[d,x]=useState(""),[N,I]=useState(false),w=s.find(F=>F.id===m),L=parseInt(d.replace(/[^0-9]/g,""),10)||0,A=L>0&&Number.isFinite(L),P=!!w&&A&&N&&!o,re=async()=>{if(!P||!w)return;let F=L*100;await i(w.id,F)&&a();};if(n)return jsxs("div",{className:l("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:n.listingId})]}),jsxs("a",{href:`https://market.stacknet.org/keys/${encodeURIComponent(n.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:l("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(oe,{count:2})]});if(u)return jsxs("div",{className:l("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:u})]}),jsx("button",{onClick:()=>a(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]});let M=s.filter(F=>F.status==="active");return M.length===0?jsxs("div",{className:l("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:l("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:M.map(F=>jsx(_r,{nodeKey:F,selected:m===F.id,onSelect:()=>p(F.id)},F.id))})]}),w&&jsxs("div",{className:"rounded-xl border bg-muted/30 p-5 space-y-2 text-sm",children:[w.keyIndex&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key #"}),jsxs("span",{className:"text-foreground font-semibold",children:["#",w.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:w.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:[R(w.tokenBalance)," / ",R(w.maxTokens)]})]}),w.paperWork&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Paper earned"}),jsx("span",{className:"text-foreground",children:w.paperWork})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Created"}),jsx("span",{className:"text-foreground",children:G(w.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:d,onChange:F=>{let se=F.target.value.replace(/[^0-9]/g,""),de=parseInt(se,10);x(isNaN(de)?"":de.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":N,onClick:()=>I(!N),className:l("mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded border-2 transition-colors cursor-pointer",N?"border-foreground bg-foreground":"border-muted-foreground/40"),children:N&&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:D(r.termsUrl,"/terms"),className:"text-foreground underline",target:"_blank",rel:"noopener noreferrer",children:"Terms"})]})]}),f&&jsx("p",{className:"text-sm text-red-500",children:f}),jsxs("button",{onClick:re,disabled:!P,className:l("flex w-full items-center justify-center gap-2 rounded-xl py-4 text-sm font-semibold transition-colors",P?"bg-foreground text-background hover:bg-foreground/90":"bg-muted text-muted-foreground cursor-not-allowed"),children:[jsx(ExternalLink,{className:"h-4 w-4"}),o?"Listing...":"List on Marketplace"]})]})}var Ye=20;function ze({nodeKey:e,className:t,style:r}){let[s,g]=useState(false),[u,a]=useState(false),i=useRef(null),{entries:o,loading:n}=he(s?e.id:null);useEffect(()=>()=>{i.current&&clearTimeout(i.current);},[]);let f=useCallback(()=>{e.key&&(navigator.clipboard.writeText(e.key),a(true),i.current&&clearTimeout(i.current),i.current=setTimeout(()=>a(false),2e3));},[e.key]),m=e.status==="active"?"text-green-500":e.status==="expired"?"text-red-500":"text-yellow-500",p=o.slice(0,Ye);return jsxs("div",{className:l("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:l("text-xs font-medium capitalize",m),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:f,"aria-label":"Copy key to clipboard",className:"shrink-0 rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground",children:u?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 ",G(e.createdAt)]}),e.expiresAt&&jsxs("span",{children:["Expires ",G(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"}),n?jsx("p",{className:"text-xs text-muted-foreground",children:"Loading..."}):p.length===0?jsx("p",{className:"text-xs text-muted-foreground",children:"No ledger entries."}):jsxs("div",{className:"space-y-1.5",children:[p.map(d=>jsxs("div",{className:"flex items-center justify-between text-xs",children:[jsxs("div",{className:"flex items-center gap-2",children:[jsxs("span",{className:l("font-medium",d.type==="credit"||d.type==="reward"?"text-green-500":"text-red-500"),children:[d.type==="credit"||d.type==="reward"?"+":"-",R(Math.abs(d.amount))]}),jsx("span",{className:"text-muted-foreground",children:d.description})]}),jsx("span",{className:"text-muted-foreground",children:G(d.createdAt)})]},d.id)),o.length>Ye&&jsxs("p",{className:"pt-1 text-xs text-muted-foreground",children:["Showing ",Ye," of ",o.length," entries"]})]})]})]})}var qr=[{id:"buy",label:"Buy"},{id:"use",label:"Use"},{id:"keys",label:"Keys"}];function ke({baseHref:e}){return jsx("div",{className:"flex gap-1 rounded-2xl bg-muted/50 p-1.5 mb-6",children:qr.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 Hr({getKeyHref:e="/keys/get",showTabs:t=true,className:r,style:s}){let{keys:g,totalBalance:u,loading:a,error:i,refresh:o}=H();return a?jsxs("div",{className:l("space-y-4",r),style:s,children:[t&&e&&jsx(ke,{baseHref:e}),jsx(oe,{count:3})]}):i?jsxs("div",{className:l("space-y-4",r),style:s,children:[t&&e&&jsx(ke,{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:i})]}),jsx("button",{onClick:()=>o(),className:"text-sm text-muted-foreground hover:text-foreground transition-colors",children:"Try again"})]})]}):g.length===0?jsxs("div",{className:l("space-y-4",r),style:s,children:[t&&e&&jsx(ke,{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:l("space-y-4",r),style:s,children:[t&&e&&jsx(ke,{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: ",R(u)]}),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(n=>jsx(ze,{nodeKey:n},n.id))]})}function es({nodeKey:e,selected:t,onSelect:r}){return jsxs("button",{onClick:r,className:l("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:l("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 ts({className:e,style:t}){let{keys:r,loading:s}=H(),{transferKey:g,transferring:u,result:a,error:i}=ve(),[o,n]=useState(null),[f,m]=useState(""),[p,d]=useState(false),x=r.filter(P=>P.status==="active"),N=x.find(P=>P.id===o),I=N&&f.trim()===N.userId,w=o&&f.trim().length>0&&p&&!I&&!u,L=async()=>{!o||!f.trim()||await g(o,f.trim());},A=()=>{n(null),m(""),d(false);};return a?jsxs("div",{className:l("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:[a.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:[a.toUserId.slice(0,20),"..."]})]})]}),jsx("button",{onClick:A,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:l("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(oe,{count:2}):x.length===0?jsx("p",{className:"text-sm text-muted-foreground",children:"No active keys available for transfer."}):jsx("div",{className:"space-y-2",children:x.map(P=>jsx(es,{nodeKey:P,selected:o===P.id,onSelect:()=>n(P.id)},P.id))})]}),o&&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:f,onChange:P=>{m(P.target.value),d(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"}),I&&jsx("p",{className:"mt-1.5 text-xs text-red-500",children:"Cannot transfer a key to yourself"})]}),N&&f.trim().length>0&&!I&&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:N.keyIndex?`#${N.keyIndex}`:N.id.slice(0,12)})," ","(",R(N.tokenBalance)," tokens) to"," ",jsxs("span",{className:"font-mono font-medium",children:[f.trim().slice(0,20),"..."]})]})]}),jsxs("label",{className:"flex items-start gap-2 cursor-pointer",children:[jsx("input",{type:"checkbox",checked:p,onChange:P=>d(P.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."})]})]})]})}),i&&jsx("p",{className:"text-sm text-red-500",children:i}),jsx("button",{onClick:L,disabled:!w,className:l("flex w-full items-center justify-center gap-2 rounded-lg px-4 py-3 text-sm font-medium transition-all",w?"bg-foreground text-background hover:opacity-90":"bg-muted text-muted-foreground cursor-not-allowed"),children:u?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"]})})]})}function Rt(){let{config:e,callbacks:t}=C(),[r,s]=useState(false),[g,u]=useState(null),[a,i]=useState(null),o=useRef(true),n=useCallback(async m=>{try{s(!0),i(null);let p=await fetch(`${e.apiBaseUrl}/api/keys/${encodeURIComponent(m)}/file`,{method:"POST",headers:{"Content-Type":"application/json",...z()},credentials:"include",body:JSON.stringify({stackId:e.stackId})});if(!p.ok)throw new Error(await E(p,`Filing failed (${p.status})`));let d=await p.json();return o.current&&(u(d),t.onFilingComplete?.(d)),d}catch(p){let d=p instanceof Error?p:new Error("Filing failed");return o.current&&i(d.message),t.onFilingError?.(d),null}finally{o.current&&s(false);}},[e.apiBaseUrl,e.stackId,t]),f=useCallback(()=>{u(null),i(null);},[]);return {filePaperwork:n,filing:r,result:g,error:a,reset:f}}function Pe(e,t=6,r=6){return !e||e.length<=t+r+1?e:`${e.slice(0,t)}\u2026${e.slice(-r)}`}function as({nodeKey:e,stackName:t}){let r=Math.max(0,e.maxTokens-e.tokenBalance);return jsxs("div",{className:"bg-muted/30 p-5 space-y-2 text-sm",children:[e.keyIndex!=null&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Key #"}),jsxs("span",{className:"text-foreground font-semibold",children:["#",e.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:Pe(e.id,8,8)})]}),t&&jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Originating Stack"}),jsx("span",{className:"text-foreground",children:t})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Compute tokens used"}),jsxs("span",{className:"text-foreground",children:[R(r)," / ",R(e.maxTokens)]})]}),jsxs("div",{className:"flex justify-between",children:[jsx("span",{className:"text-muted-foreground",children:"Created"}),jsx("span",{className:"text-foreground",children:G(e.createdAt)})]})]})}function we(){return jsxs("div",{className:"bg-stacknet-blue text-white p-8 lg:w-2/5 flex flex-col justify-between min-h-[260px]",children:[jsxs("div",{className:"space-y-3",children:[jsx("p",{className:"text-sm font-mono opacity-80",children:"stacknet | filing"}),jsx("h2",{className:"text-2xl font-semibold leading-snug",children:"File paperwork to redeem Paper."}),jsx("p",{className:"text-sm opacity-80 leading-relaxed",children:"Filing submits your prepared paperwork on chain. Once validated, Paper is sent to your registered payment address."})]}),jsx("p",{className:"text-xs opacity-60 mt-8",children:"Powered by StackNet"})]})}function is({keyId:e,paymentAddress:t,onComplete:r,onConfigurePayment:s,onBack:g,className:u,style:a}){let{config:i}=C(),{keys:o,loading:n,error:f,refresh:m}=H(),{filePaperwork:p,filing:d,result:x,error:N,reset:I}=Rt(),w=o.find(M=>M.id===e),L=!!w?.paperWork&&w.paperWork.length>0,A=!!t&&t.length>0,P=L&&A&&!d&&!x,re=async()=>{if(!P||!w)return;let M=await p(w.id);M&&(m(),r?.(M));};return x?jsxs("div",{className:l("flex flex-col lg:flex-row",u),style:a,children:[jsx(we,{}),jsxs("div",{className:"flex-1 bg-background p-8 space-y-6",children:[jsxs("div",{className:"flex items-center gap-3",children:[jsx(CheckCircle2,{className:"h-7 w-7 text-green-500","aria-hidden":true}),jsx("h3",{className:"text-2xl font-semibold text-foreground",children:"Paperwork filed"})]}),jsx("p",{className:"text-sm text-muted-foreground",children:"Your filing has been submitted. Paper will be released to your payment address once the watcher network validates the proof."}),jsxs("div",{className:"bg-muted/30 p-5 space-y-3 text-sm",children:[jsxs("div",{className:"flex justify-between gap-4",children:[jsx("span",{className:"text-muted-foreground",children:"Status"}),jsx("span",{className:"text-foreground capitalize",children:x.status})]}),jsxs("div",{className:"flex justify-between gap-4",children:[jsx("span",{className:"text-muted-foreground",children:"Paper amount"}),jsxs("span",{className:"text-foreground tabular-nums",children:[(x.paperAmount/1e6).toLocaleString(void 0,{maximumFractionDigits:6})," Paper"]})]}),jsxs("div",{className:"flex justify-between gap-4",children:[jsx("span",{className:"text-muted-foreground",children:"File hash"}),jsx("code",{className:"text-xs text-foreground break-all",children:Pe(x.fileHash,10,10)})]}),x.txSignature&&jsxs("div",{className:"flex justify-between gap-4",children:[jsx("span",{className:"text-muted-foreground",children:"Tx"}),jsx("a",{href:`https://solscan.io/tx/${encodeURIComponent(x.txSignature)}`,target:"_blank",rel:"noopener noreferrer",className:"text-xs text-foreground underline underline-offset-4",children:Pe(x.txSignature,8,8)})]}),jsxs("div",{className:"flex justify-between gap-4",children:[jsx("span",{className:"text-muted-foreground",children:"Beneficiary"}),jsx("code",{className:"text-xs text-foreground",children:Pe(x.beneficiary,6,6)})]})]}),g&&jsx("button",{type:"button",onClick:()=>{I(),g();},className:"w-full bg-foreground text-background py-4 text-sm font-semibold hover:bg-foreground/90 transition-colors",children:"Back to dashboard"})]})]}):n?jsxs("div",{className:l("flex flex-col lg:flex-row",u),style:a,children:[jsx(we,{}),jsxs("div",{className:"flex-1 bg-background p-8 space-y-4",children:[jsx("div",{className:"h-7 w-48 bg-muted animate-pulse"}),jsx("div",{className:"h-32 w-full bg-muted animate-pulse"}),jsx("div",{className:"h-12 w-full bg-muted animate-pulse"})]})]}):f||!w?jsxs("div",{className:l("flex flex-col lg:flex-row",u),style:a,children:[jsx(we,{}),jsxs("div",{className:"flex-1 bg-background p-8 space-y-4",children:[jsxs("div",{className:"flex items-center gap-3",children:[jsx(AlertCircle,{className:"h-6 w-6 text-red-500","aria-hidden":true}),jsx("h3",{className:"text-xl font-semibold text-foreground",children:f?"Unable to load keys":"Key not found"})]}),jsx("p",{className:"text-sm text-muted-foreground",children:f||`No key with id ${e} on this account.`}),jsx("button",{type:"button",onClick:()=>m(),className:"bg-foreground text-background px-4 py-3 text-sm font-semibold hover:bg-foreground/90 transition-colors",children:"Try again"})]})]}):jsxs("div",{className:l("flex flex-col lg:flex-row",u),style:a,children:[jsx(we,{}),jsxs("div",{className:"flex-1 bg-background p-8 space-y-6",children:[jsxs("div",{children:[jsx("h2",{className:"text-2xl font-semibold text-foreground",children:"File paperwork"}),jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"Review the key and beneficiary, then submit your filing."})]}),jsx(as,{nodeKey:w,stackName:i.stackName}),!L&&jsx("div",{className:"bg-muted/30 p-4 text-sm text-muted-foreground",children:"This key has no pending paperwork. Run your node to earn Paper, then return to file."}),jsxs("div",{className:"space-y-2",children:[jsx("p",{className:"text-xs uppercase tracking-wide text-muted-foreground",children:"Beneficiary (payment address)"}),A?jsx("div",{className:"bg-muted/30 p-4",children:jsx("code",{className:"text-xs text-foreground break-all",children:t})}):jsxs("div",{className:"bg-muted/30 p-4 space-y-3",children:[jsx("p",{className:"text-sm text-foreground",children:"You haven't set a payment address yet."}),s&&jsx("button",{type:"button",onClick:s,className:"bg-foreground text-background px-4 py-3 text-sm font-semibold hover:bg-foreground/90 transition-colors",children:"Set payment address"})]})]}),jsxs("div",{className:"bg-muted/30 p-4 flex gap-3",children:[jsx(Info,{className:"h-5 w-5 shrink-0 text-foreground mt-0.5","aria-hidden":true}),jsxs("p",{className:"text-sm text-foreground leading-relaxed",children:[jsx("span",{className:"font-semibold",children:"Important."})," ","Filing is one-time per key. Paper will be sent to the address above and cannot be reversed. Double-check the address before submitting."]})]}),N&&jsx("p",{className:"text-sm text-red-500",children:N}),jsx("button",{type:"button",onClick:re,disabled:!P,className:l("w-full py-4 text-sm font-semibold transition-colors",P?"bg-foreground text-background hover:bg-foreground/90":"bg-muted text-muted-foreground cursor-not-allowed"),children:d?"Filing\u2026":"File Paperwork"})]})]})}function cs(e){return typeof e.paperWork=="string"&&e.paperWork.length>0}function us({count:e=3}){return jsx("div",{className:"space-y-2",children:Array.from({length:e}).map((t,r)=>jsxs("div",{className:"bg-muted/30 p-4 space-y-3",children:[jsxs("div",{className:"flex items-center justify-between",children:[jsx("div",{className:"h-4 w-40 bg-muted animate-pulse"}),jsx("div",{className:"h-4 w-16 bg-muted animate-pulse"})]}),jsx("div",{className:"h-3 w-32 bg-muted animate-pulse"})]},r))})}function ms({nodeKey:e,onSelect:t}){let r=Math.max(0,e.maxTokens-e.tokenBalance);return jsxs("button",{type:"button",onClick:t,className:"group flex w-full items-center gap-4 bg-muted/30 p-4 text-left transition-colors hover:bg-muted/50",children:[jsxs("div",{className:"min-w-0 flex-1 space-y-1",children:[jsxs("div",{className:"flex items-center gap-3",children:[jsxs("span",{className:"text-sm font-semibold text-foreground",children:[e.keyIndex!=null?`#${e.keyIndex} `:"",e.label||e.id.slice(0,16)]}),jsx("span",{className:"text-xs text-muted-foreground",children:e.stackName||""})]}),jsxs("div",{className:"flex items-center gap-4 text-xs text-muted-foreground",children:[jsxs("span",{className:"tabular-nums",children:[R(r)," / ",R(e.maxTokens)," compute used"]}),jsx("span",{className:"text-foreground",children:"Eligible"})]})]}),jsx(ChevronRight,{className:"h-5 w-5 shrink-0 text-muted-foreground transition-transform group-hover:translate-x-0.5","aria-hidden":true})]})}function fs({onSelect:e,className:t,style:r}){let{keys:s,loading:g,error:u,refresh:a}=H();if(g)return jsx("div",{className:l("space-y-3",t),style:r,children:jsx(us,{count:3})});if(u)return jsx("div",{className:l("space-y-3",t),style:r,children:jsxs("div",{className:"bg-muted/30 p-5 text-center",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:u}),jsx("button",{type:"button",onClick:()=>a(),className:"mt-3 bg-foreground text-background px-4 py-2 text-xs font-semibold hover:bg-foreground/90 transition-colors",children:"Try again"})]})});let i=s.filter(cs);return i.length===0?jsxs("div",{className:l("flex flex-col items-center justify-center gap-3 bg-muted/20 py-16",t),style:r,children:[jsx(FileText,{className:"h-10 w-10 text-muted-foreground","aria-hidden":true}),jsxs("div",{className:"text-center",children:[jsx("p",{className:"text-sm font-medium text-foreground",children:"No keys with pending paperwork"}),jsx("p",{className:"mt-1 text-xs text-muted-foreground",children:"Run a node to earn Paper, then return here to file."})]})]}):jsx("div",{className:l("space-y-2",t),style:r,children:i.map(o=>jsx(ms,{nodeKey:o,onSelect:()=>e(o.id)},o.id))})}
|
|
2
|
+
export{ge as BottomSheet,jr as BuyKeyWidget,Ee as BuyPanel,fs as FilePaperworkList,is as FilePaperworkView,Q as KeyBalanceBar,ze as KeyCard,We as KeyDetailView,Hr as KeyList,Se as KeyUtilsProvider,Oe as KeysPanel,Be as MintSuccess,Ar as SellPanel,Ue as SolanaPayButton,ts as TransferPanel,je as UsePanel,C as useKeyUtilsContext};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
'use strict';function m(e,i){if(typeof e!="string"||e.length===0)return i;let r=e.replace(/[\u0000-\u001F\u007F]/g," ");return r.length>500?r.slice(0,500)+"\u2026":r}async function u(e,i){try{let r=await e.json();if(r&&typeof r=="object"&&"error"in r)return m(r.error,i)}catch{}return i}function l(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}}async function f(e){if(!e)return {};let i=e();return i instanceof Promise?await i:i}async function d(e,i={}){let{getHeaders:r,...g}=i,a=await f(r),n=await fetch(e,{...g,headers:{"Content-Type":"application/json",...a,...g.headers},credentials:"include"});if(!n.ok)throw new Error(await u(n,`Request failed (${n.status})`));return n.json()}function p(e){let{apiBaseUrl:i,stackId:r,stackName:g,getHeaders:a}=e,n=`${i}/api/keys`;return {async getKeys(){let t=await d(n,{getHeaders:a});return (Array.isArray(t)?t:t.keys??[]).map(l)},async getLedger(t){let s=await d(`${n}/${encodeURIComponent(t)}/ledger`,{getHeaders:a});return Array.isArray(s)?s:s.entries??[]},async getPricing(){return d(`${n}/pricing`,{getHeaders:a})},async mint(t,s,y=1){try{let c=await d(n+"/mint",{method:"POST",body:JSON.stringify({paymentMethod:t,paymentRef:s,quantity:y,stackId:r}),getHeaders:a}),o=c.keys?.[0]||c;return {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:s}}catch(c){return {success:false,error:c instanceof Error?c.message:"Key generation failed"}}},async listKey(t,s){return d(`${n}/${encodeURIComponent(t)}/list`,{method:"POST",body:JSON.stringify({askPriceCents:s,stackId:r,stackName:g}),getHeaders:a})},async delistKey(t){await d(`${n}/${encodeURIComponent(t)}/list`,{method:"DELETE",getHeaders:a});},async transferKey(t,s){return d(`${n}/${encodeURIComponent(t)}/transfer`,{method:"POST",body:JSON.stringify({recipientId:s}),getHeaders:a})},async createStripeSession(t,s,y){return d(`${n}/stripe-session`,{method:"POST",body:JSON.stringify({priceCents:t,quantity:s,stackId:r,referrerUrl:y}),getHeaders:a})}}}exports.createKeyClient=p;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { NodeKeyInfo, LedgerEntry, PricingInfo, PaymentMethod, MintResult, ListingResult, DirectTransferResult } from '../types/index.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Optional header provider for auth and CSRF.
|
|
5
|
+
* On web, cookies handle auth automatically — pass csrfHeaders for mutations.
|
|
6
|
+
* On native, pass the auth client's getHeaders for Bearer token injection.
|
|
7
|
+
*/
|
|
8
|
+
type HeaderProvider = () => Promise<Record<string, string>> | Record<string, string>;
|
|
9
|
+
interface KeyClientConfig {
|
|
10
|
+
/** API base URL (e.g. http://localhost:3000 or https://app.example.com) */
|
|
11
|
+
apiBaseUrl: string;
|
|
12
|
+
/** Stack identifier */
|
|
13
|
+
stackId?: string;
|
|
14
|
+
stackName?: string;
|
|
15
|
+
/** Provides auth + CSRF headers for requests */
|
|
16
|
+
getHeaders?: HeaderProvider;
|
|
17
|
+
}
|
|
18
|
+
interface KeyClient {
|
|
19
|
+
/** Fetch all keys for the authenticated user */
|
|
20
|
+
getKeys(): Promise<NodeKeyInfo[]>;
|
|
21
|
+
/** Fetch ledger entries for a specific key */
|
|
22
|
+
getLedger(keyId: string): Promise<LedgerEntry[]>;
|
|
23
|
+
/** Fetch current pricing info */
|
|
24
|
+
getPricing(): Promise<PricingInfo>;
|
|
25
|
+
/** Mint a new key after payment */
|
|
26
|
+
mint(paymentMethod: PaymentMethod, transactionId: string, quantity?: number): Promise<MintResult>;
|
|
27
|
+
/** List a key on the marketplace */
|
|
28
|
+
listKey(keyId: string, askPriceCents: number): Promise<ListingResult>;
|
|
29
|
+
/** Delist a key from the marketplace */
|
|
30
|
+
delistKey(keyId: string): Promise<void>;
|
|
31
|
+
/** Transfer a key to another user */
|
|
32
|
+
transferKey(keyId: string, recipientId: string): Promise<DirectTransferResult>;
|
|
33
|
+
/** Create a Stripe checkout session */
|
|
34
|
+
createStripeSession(priceCents: number, quantity: number, referrerUrl: string): Promise<{
|
|
35
|
+
url: string;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Platform-agnostic key client.
|
|
40
|
+
*
|
|
41
|
+
* Extracts all HTTP logic from React hooks so it can be used from
|
|
42
|
+
* any environment (React Native, Node, tests, etc.).
|
|
43
|
+
*
|
|
44
|
+
* Usage:
|
|
45
|
+
* const keys = createKeyClient({
|
|
46
|
+
* apiBaseUrl: 'https://app.example.com',
|
|
47
|
+
* getHeaders: () => auth.getHeaders(), // inject auth
|
|
48
|
+
* });
|
|
49
|
+
* const myKeys = await keys.getKeys();
|
|
50
|
+
*/
|
|
51
|
+
declare function createKeyClient(config: KeyClientConfig): KeyClient;
|
|
52
|
+
|
|
53
|
+
export { type HeaderProvider, type KeyClient, type KeyClientConfig, createKeyClient };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { NodeKeyInfo, LedgerEntry, PricingInfo, PaymentMethod, MintResult, ListingResult, DirectTransferResult } from '../types/index.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Optional header provider for auth and CSRF.
|
|
5
|
+
* On web, cookies handle auth automatically — pass csrfHeaders for mutations.
|
|
6
|
+
* On native, pass the auth client's getHeaders for Bearer token injection.
|
|
7
|
+
*/
|
|
8
|
+
type HeaderProvider = () => Promise<Record<string, string>> | Record<string, string>;
|
|
9
|
+
interface KeyClientConfig {
|
|
10
|
+
/** API base URL (e.g. http://localhost:3000 or https://app.example.com) */
|
|
11
|
+
apiBaseUrl: string;
|
|
12
|
+
/** Stack identifier */
|
|
13
|
+
stackId?: string;
|
|
14
|
+
stackName?: string;
|
|
15
|
+
/** Provides auth + CSRF headers for requests */
|
|
16
|
+
getHeaders?: HeaderProvider;
|
|
17
|
+
}
|
|
18
|
+
interface KeyClient {
|
|
19
|
+
/** Fetch all keys for the authenticated user */
|
|
20
|
+
getKeys(): Promise<NodeKeyInfo[]>;
|
|
21
|
+
/** Fetch ledger entries for a specific key */
|
|
22
|
+
getLedger(keyId: string): Promise<LedgerEntry[]>;
|
|
23
|
+
/** Fetch current pricing info */
|
|
24
|
+
getPricing(): Promise<PricingInfo>;
|
|
25
|
+
/** Mint a new key after payment */
|
|
26
|
+
mint(paymentMethod: PaymentMethod, transactionId: string, quantity?: number): Promise<MintResult>;
|
|
27
|
+
/** List a key on the marketplace */
|
|
28
|
+
listKey(keyId: string, askPriceCents: number): Promise<ListingResult>;
|
|
29
|
+
/** Delist a key from the marketplace */
|
|
30
|
+
delistKey(keyId: string): Promise<void>;
|
|
31
|
+
/** Transfer a key to another user */
|
|
32
|
+
transferKey(keyId: string, recipientId: string): Promise<DirectTransferResult>;
|
|
33
|
+
/** Create a Stripe checkout session */
|
|
34
|
+
createStripeSession(priceCents: number, quantity: number, referrerUrl: string): Promise<{
|
|
35
|
+
url: string;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Platform-agnostic key client.
|
|
40
|
+
*
|
|
41
|
+
* Extracts all HTTP logic from React hooks so it can be used from
|
|
42
|
+
* any environment (React Native, Node, tests, etc.).
|
|
43
|
+
*
|
|
44
|
+
* Usage:
|
|
45
|
+
* const keys = createKeyClient({
|
|
46
|
+
* apiBaseUrl: 'https://app.example.com',
|
|
47
|
+
* getHeaders: () => auth.getHeaders(), // inject auth
|
|
48
|
+
* });
|
|
49
|
+
* const myKeys = await keys.getKeys();
|
|
50
|
+
*/
|
|
51
|
+
declare function createKeyClient(config: KeyClientConfig): KeyClient;
|
|
52
|
+
|
|
53
|
+
export { type HeaderProvider, type KeyClient, type KeyClientConfig, createKeyClient };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function m(e,i){if(typeof e!="string"||e.length===0)return i;let r=e.replace(/[\u0000-\u001F\u007F]/g," ");return r.length>500?r.slice(0,500)+"\u2026":r}async function u(e,i){try{let r=await e.json();if(r&&typeof r=="object"&&"error"in r)return m(r.error,i)}catch{}return i}function l(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}}async function f(e){if(!e)return {};let i=e();return i instanceof Promise?await i:i}async function d(e,i={}){let{getHeaders:r,...g}=i,a=await f(r),n=await fetch(e,{...g,headers:{"Content-Type":"application/json",...a,...g.headers},credentials:"include"});if(!n.ok)throw new Error(await u(n,`Request failed (${n.status})`));return n.json()}function p(e){let{apiBaseUrl:i,stackId:r,stackName:g,getHeaders:a}=e,n=`${i}/api/keys`;return {async getKeys(){let t=await d(n,{getHeaders:a});return (Array.isArray(t)?t:t.keys??[]).map(l)},async getLedger(t){let s=await d(`${n}/${encodeURIComponent(t)}/ledger`,{getHeaders:a});return Array.isArray(s)?s:s.entries??[]},async getPricing(){return d(`${n}/pricing`,{getHeaders:a})},async mint(t,s,y=1){try{let c=await d(n+"/mint",{method:"POST",body:JSON.stringify({paymentMethod:t,paymentRef:s,quantity:y,stackId:r}),getHeaders:a}),o=c.keys?.[0]||c;return {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:s}}catch(c){return {success:false,error:c instanceof Error?c.message:"Key generation failed"}}},async listKey(t,s){return d(`${n}/${encodeURIComponent(t)}/list`,{method:"POST",body:JSON.stringify({askPriceCents:s,stackId:r,stackName:g}),getHeaders:a})},async delistKey(t){await d(`${n}/${encodeURIComponent(t)}/list`,{method:"DELETE",getHeaders:a});},async transferKey(t,s){return d(`${n}/${encodeURIComponent(t)}/transfer`,{method:"POST",body:JSON.stringify({recipientId:s}),getHeaders:a})},async createStripeSession(t,s,y){return d(`${n}/stripe-session`,{method:"POST",body:JSON.stringify({priceCents:t,quantity:s,stackId:r,referrerUrl:y}),getHeaders:a})}}}export{p as createKeyClient};
|
package/dist/hooks/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var react=require('react');require('react/jsx-runtime');var O=react.createContext(null);function p(){let e=react.useContext(O);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function F(){let{config:e}=p(),[c,m]=react.useState(null),[u,f]=react.useState(true),[d,g]=react.useState(null),s=react.useRef(true),o=react.useRef(e.apiBaseUrl);o.current=e.apiBaseUrl;let l=async()=>{try{s.current&&(f(!0),g(null));let i=await fetch(`${o.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&&m(n);}catch(i){s.current&&g(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:d,refresh:l}}function q(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 z(){let{config:e}=p(),[c,m]=react.useState([]),[u,f]=react.useState(true),[d,g]=react.useState(null),s=react.useRef(true),o=e.apiBaseUrl,l=react.useCallback(async()=>{try{f(!0),g(null);let n=await fetch(`${o}/api/keys`,{credentials:"include"});if(!n.ok){let a=`Failed to fetch keys (${n.status})`;try{let y=await n.json();y.error&&(a=y.error);}catch{}throw new Error(a)}let t=await n.json(),r=Array.isArray(t)?t:t.keys??[];s.current&&m(r.map(q));}catch(n){s.current&&g(n instanceof Error?n.message:"Failed to fetch keys");}finally{s.current&&f(false);}},[o]);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:d,refresh:l}}function Q(e){let{config:c}=p(),[m,u]=react.useState([]),[f,d]=react.useState(false),[g,s]=react.useState(null),o=react.useRef(true),l=c.apiBaseUrl,i=react.useCallback(async()=>{if(e)try{d(!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 a=await n.json();a.error&&(r=a.error);}catch{}throw new Error(r)}let t=await n.json();o.current&&u(Array.isArray(t)?t:t.entries??[]);}catch(n){o.current&&s(n instanceof Error?n.message:"Failed to fetch ledger");}finally{o.current&&d(false);}},[l,e]);return react.useEffect(()=>(o.current=true,i(),()=>{o.current=false;}),[i]),{entries:m,loading:f,error:g,refresh:i}}function k(){if(typeof document>"u")return {};let e=document.cookie.match(/(?:^|;\s*)__csrf=([^;]*)/);return e?{"x-csrf-token":e[1]}:{}}function ee(){let{config:e,callbacks:c}=p(),[m,u]=react.useState(false),[f,d]=react.useState(null),[g,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 K=await t.json();K.error&&(h=K.error);}catch{}throw new Error(h)}let r=await t.json(),a=r.keys?.[0]||r,y={success:!0,key:{id:a.keyId||a.id||"",key:a.key||"",userId:a.userId||"",status:"active",tokenBalance:a.tokenBalance??a.currentTokenBalance??0,maxTokens:a.initialTokenBalance??a.tokenBalance??0,createdAt:String(a.createdAt||Date.now())},transactionId:i};return d(y),c.onMintSuccess?.(y),y}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:m,result:f,error:g}}function re(){let{config:e,callbacks:c}=p(),[m,u]=react.useState(false),[f,d]=react.useState(null),[g,s]=react.useState(null),o=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 y=`Listing failed (${r.status})`;try{let h=await r.json();h.error&&(y=h.error);}catch{}throw new Error(y)}let a=await r.json();return o.current&&(d(a),c.onListingCreated?.(a)),a}catch(r){let a=r instanceof Error?r.message:"Listing failed";return o.current&&s(a),null}finally{o.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 a=await t.json();a.error&&(r=a.error);}catch{}throw new Error(r)}return o.current&&d(null),!0}catch(t){let r=t instanceof Error?t.message:"Delist failed";return o.current&&s(r),false}finally{o.current&&u(false);}},[e.apiBaseUrl]);return {listKey:l,delistKey:i,listing:m,result:f,error:g}}function oe(){let{config:e}=p(),[c,m]=react.useState(false),[u,f]=react.useState(null),d=react.useRef(true);return {createSession:react.useCallback(async(s,o)=>{try{m(!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:o,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(d.current){let i=l instanceof Error?l.message:"Checkout failed";f(i),m(false);}}},[e.apiBaseUrl,e.stackId]),loading:c,error:u}}var j=/^[1-9A-HJ-NP-Za-km-z]{32,44}$/;function ae(){let{config:e}=p(),[c,m]=react.useState(false),[u,f]=react.useState(null);return {pay:react.useCallback(async g=>{if(!e.merchantWallet||!j.test(e.merchantWallet))throw new Error("Merchant wallet not configured");try{m(!0),f(null);let{Connection:s,PublicKey:o,Transaction:l,SystemProgram:i}=await import('@solana/web3.js'),n=typeof window<"u"?window.solana:void 0;if(!n||typeof n!="object"||!n.isPhantom)throw new Error("Phantom wallet not found. Please install Phantom.");let t=n,r=new o(e.merchantWallet),a=await t.connect(),y=new o(a.publicKey.toString()),h=new s(e.solanaRpcUrl||"https://api.mainnet-beta.solana.com"),{blockhash:K}=await h.getLatestBlockhash(),b=BigInt(Math.floor(g*1e9)),R=e.protocolTreasuryWallet,S=e.protocolFeeBps??500,U=new l({recentBlockhash:K,feePayer:y});if(R&&j.test(R)&&S>0){let T=b*BigInt(S)/10000n,M=b-T,_=new o(R);U.add(i.transfer({fromPubkey:y,toPubkey:r,lamports:Number(M)}),i.transfer({fromPubkey:y,toPubkey:_,lamports:Number(T)}));}else U.add(i.transfer({fromPubkey:y,toPubkey:r,lamports:Number(b)}));let{signature:v}=await t.signAndSendTransaction(U);return v}catch(s){let o=s instanceof Error?s:new Error("SOL payment failed");throw f(o.message),o}finally{m(false);}},[e.merchantWallet,e.protocolTreasuryWallet,e.protocolFeeBps,e.solanaRpcUrl]),processing:c,error:u}}function ue(){let{config:e,callbacks:c}=p(),[m,u]=react.useState(false),[f,d]=react.useState(null),[g,s]=react.useState(null),o=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 a=`Transfer failed (${t.status})`;try{let y=await t.json();y.error&&(a=y.error);}catch{}throw new Error(a)}let r=await t.json();return o.current&&(d(r),c.onTransferComplete?.(r)),r}catch(t){let r=t instanceof Error?t.message:"Transfer failed";return o.current&&s(r),null}finally{o.current&&u(false);}},[e.apiBaseUrl,c]),transferring:m,result:f,error:g}}
|
|
2
|
-
exports.useKeyLedger=
|
|
1
|
+
'use strict';var react=require('react');require('react/jsx-runtime');var z=react.createContext(null);function d(){let e=react.useContext(z);if(!e)throw new Error("useKeyUtilsContext must be used within a KeyUtilsProvider");return e}function Y(e,a){if(typeof e!="string"||e.length===0)return a;let i=e.replace(/[\u0000-\u001F\u007F]/g," ");return i.length>500?i.slice(0,500)+"\u2026":i}async function y(e,a){try{let i=await e.json();if(i&&typeof i=="object"&&"error"in i)return Y(i.error,a)}catch{}return a}function G(){let{config:e}=d(),[a,i]=react.useState(null),[u,f]=react.useState(true),[m,p]=react.useState(null),r=react.useRef(true),o=react.useRef(e.apiBaseUrl);o.current=e.apiBaseUrl;let c=async()=>{try{r.current&&(f(!0),p(null));let s=await fetch(`${o.current}/api/keys/pricing`,{credentials:"include"});if(!s.ok)throw new Error(await y(s,`Pricing unavailable (${s.status})`));let n=await s.json();r.current&&i(n);}catch(s){r.current&&p(s instanceof Error?s.message:"Failed to fetch pricing");}finally{r.current&&f(false);}};return react.useEffect(()=>{r.current=true,c();let s=setInterval(c,6e4);return ()=>{r.current=false,clearInterval(s);}},[]),{pricing:a,loading:u,error:m,refresh:c}}function re(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 ne(){let{config:e}=d(),[a,i]=react.useState([]),[u,f]=react.useState(true),[m,p]=react.useState(null),r=react.useRef(true),o=e.apiBaseUrl,c=react.useCallback(async()=>{try{f(!0),p(null);let n=await fetch(`${o}/api/keys`,{credentials:"include"});if(!n.ok)throw new Error(await y(n,`Failed to fetch keys (${n.status})`));let t=await n.json(),l=Array.isArray(t)?t:t.keys??[];r.current&&i(l.map(re));}catch(n){r.current&&p(n instanceof Error?n.message:"Failed to fetch keys");}finally{r.current&&f(false);}},[o]);react.useEffect(()=>(r.current=true,c(),()=>{r.current=false;}),[c]);let s=a.reduce((n,t)=>n+t.tokenBalance,0);return {keys:a,totalBalance:s,loading:u,error:m,refresh:c}}function ae(e){let{config:a}=d(),[i,u]=react.useState([]),[f,m]=react.useState(false),[p,r]=react.useState(null),o=react.useRef(true),c=a.apiBaseUrl,s=react.useCallback(async()=>{if(e)try{m(!0),r(null);let n=await fetch(`${c}/api/keys/${encodeURIComponent(e)}/ledger`,{credentials:"include"});if(!n.ok)throw new Error(await y(n,`Failed to fetch ledger (${n.status})`));let t=await n.json();o.current&&u(Array.isArray(t)?t:t.entries??[]);}catch(n){o.current&&r(n instanceof Error?n.message:"Failed to fetch ledger");}finally{o.current&&m(false);}},[c,e]);return react.useEffect(()=>(o.current=true,s(),()=>{o.current=false;}),[s]),{entries:i,loading:f,error:p,refresh:s}}function k(){if(typeof document>"u")return {};let e=document.cookie.match(/(?:^|;\s*)__csrf=([^;]*)/);return e?{"x-csrf-token":e[1]}:{}}function ce(){let{config:e,callbacks:a}=d(),[i,u]=react.useState(false),[f,m]=react.useState(null),[p,r]=react.useState(null);return {mint:react.useCallback(async(c,s,n=1)=>{try{u(!0),r(null),a.onPaymentComplete?.(c,s);let t=await fetch(`${e.apiBaseUrl}/api/keys/mint`,{method:"POST",headers:{"Content-Type":"application/json",...k()},credentials:"include",body:JSON.stringify({paymentMethod:c,paymentRef:s,quantity:n,stackId:e.stackId})});if(!t.ok)throw new Error(await y(t,`Key generation failed (${t.status})`));let l=await t.json(),g=l.keys?.[0]||l,h={success:!0,key:{id:g.keyId||g.id||"",key:g.key||"",userId:g.userId||"",status:"active",tokenBalance:g.tokenBalance??g.currentTokenBalance??0,maxTokens:g.initialTokenBalance??g.tokenBalance??0,createdAt:String(g.createdAt||Date.now())},transactionId:s};return m(h),a.onMintSuccess?.(h),h}catch(t){let l=t instanceof Error?t:new Error("Key generation failed");return r(l.message),a.onMintError?.(l),{success:false,error:l.message}}finally{u(false);}},[e.apiBaseUrl,a]),minting:i,result:f,error:p}}function fe(){let{config:e,callbacks:a}=d(),[i,u]=react.useState(false),[f,m]=react.useState(null),[p,r]=react.useState(null),o=react.useRef(true),c=react.useCallback(async(n,t)=>{try{u(!0),r(null);let l=await fetch(`${e.apiBaseUrl}/api/keys/${encodeURIComponent(n)}/list`,{method:"POST",headers:{"Content-Type":"application/json",...k()},credentials:"include",body:JSON.stringify({askPriceCents:t,stackId:e.stackId,stackName:e.stackName})});if(!l.ok)throw new Error(await y(l,`Listing failed (${l.status})`));let g=await l.json();return o.current&&(m(g),a.onListingCreated?.(g)),g}catch(l){let g=l instanceof Error?l.message:"Listing failed";return o.current&&r(g),null}finally{o.current&&u(false);}},[e.apiBaseUrl,e.stackId,e.stackName,a]),s=react.useCallback(async n=>{try{u(!0),r(null);let t=await fetch(`${e.apiBaseUrl}/api/keys/${encodeURIComponent(n)}/list`,{method:"DELETE",headers:{...k()},credentials:"include"});if(!t.ok)throw new Error(await y(t,`Delist failed (${t.status})`));return o.current&&m(null),!0}catch(t){let l=t instanceof Error?t.message:"Delist failed";return o.current&&r(l),false}finally{o.current&&u(false);}},[e.apiBaseUrl]);return {listKey:c,delistKey:s,listing:i,result:f,error:p}}function de(){let{config:e}=d(),[a,i]=react.useState(false),[u,f]=react.useState(null),m=react.useRef(true);return {createSession:react.useCallback(async(r,o)=>{try{i(!0),f(null);let c=await fetch(`${e.apiBaseUrl}/api/keys/stripe-session`,{method:"POST",headers:{"Content-Type":"application/json",...k()},credentials:"include",body:JSON.stringify({priceCents:r,quantity:o,stackId:e.stackId,referrerUrl:window.location.href})});if(!c.ok)throw new Error(await y(c,`Checkout failed (${c.status})`));let{url:s}=await c.json();if(!s)throw new Error("No checkout URL returned");let n;try{n=new URL(s);}catch{throw new Error("Invalid checkout URL")}if(n.protocol!=="https:"||!/(^|\.)stripe\.com$/.test(n.hostname))throw new Error("Refusing to redirect to non-Stripe URL");try{sessionStorage.setItem("keyutils_stripe_pending","1"),sessionStorage.setItem("keyutils_stripe_quantity",String(o));}catch{}window.location.href=n.toString();}catch(c){if(m.current){let s=c instanceof Error?c.message:"Checkout failed";f(s),i(false);}}},[e.apiBaseUrl,e.stackId]),loading:a,error:u}}function _(e,a="#"){if(!e||typeof e!="string")return a;let i=e.trim();if(i===""||i==="#")return a;if(i.startsWith("/")||i.startsWith("./")||i.startsWith("../"))return i;try{let u=new URL(i);if(u.protocol==="http:"||u.protocol==="https:")return u.toString()}catch{}return a}var A=/^[1-9A-HJ-NP-Za-km-z]{32,44}$/;function ge(){let{config:e}=d(),[a,i]=react.useState(false),[u,f]=react.useState(null);return {pay:react.useCallback(async p=>{if(!e.merchantWallet||!A.test(e.merchantWallet))throw new Error("Merchant wallet not configured");try{i(!0),f(null);let{Connection:r,PublicKey:o,Transaction:c,SystemProgram:s}=await import('@solana/web3.js'),n=typeof window<"u"?window.solana:void 0;if(!n||typeof n!="object"||!n.isPhantom)throw new Error("Phantom wallet not found. Please install Phantom.");let t=n,l=new o(e.merchantWallet),g=await t.connect(),h=new o(g.publicKey.toString()),B="https://api.mainnet-beta.solana.com",I=_(e.solanaRpcUrl,B),H=I==="#"?B:I,O=new r(H),{blockhash:W}=await O.getLatestBlockhash(),R=BigInt(Math.floor(p*1e9)),U=e.protocolTreasuryWallet,T=e.protocolFeeBps??500,w=new c({recentBlockhash:W,feePayer:h});if(U&&A.test(U)&&T>0){let F=R*BigInt(T)/10000n,J=R-F,V=new o(U);w.add(s.transfer({fromPubkey:h,toPubkey:l,lamports:Number(J)}),s.transfer({fromPubkey:h,toPubkey:V,lamports:Number(F)}));}else w.add(s.transfer({fromPubkey:h,toPubkey:l,lamports:Number(R)}));let{signature:D}=await t.signAndSendTransaction(w);return D}catch(r){let o=r instanceof Error?r:new Error("SOL payment failed");throw f(o.message),o}finally{i(false);}},[e.merchantWallet,e.protocolTreasuryWallet,e.protocolFeeBps,e.solanaRpcUrl]),processing:a,error:u}}function Re(){let{config:e,callbacks:a}=d(),[i,u]=react.useState(false),[f,m]=react.useState(null),[p,r]=react.useState(null),o=react.useRef(true);return {transferKey:react.useCallback(async(s,n)=>{try{u(!0),r(null);let t=await fetch(`${e.apiBaseUrl}/api/keys/${encodeURIComponent(s)}/transfer`,{method:"POST",headers:{"Content-Type":"application/json",...k()},credentials:"include",body:JSON.stringify({recipientId:n})});if(!t.ok)throw new Error(await y(t,`Transfer failed (${t.status})`));let l=await t.json();return o.current&&(m(l),a.onTransferComplete?.(l)),l}catch(t){let l=t instanceof Error?t.message:"Transfer failed";return o.current&&r(l),null}finally{o.current&&u(false);}},[e.apiBaseUrl,a]),transferring:i,result:f,error:p}}function we(){let{config:e,callbacks:a}=d(),[i,u]=react.useState(false),[f,m]=react.useState(null),[p,r]=react.useState(null),o=react.useRef(true),c=react.useCallback(async n=>{try{u(!0),r(null);let t=await fetch(`${e.apiBaseUrl}/api/keys/${encodeURIComponent(n)}/file`,{method:"POST",headers:{"Content-Type":"application/json",...k()},credentials:"include",body:JSON.stringify({stackId:e.stackId})});if(!t.ok)throw new Error(await y(t,`Filing failed (${t.status})`));let l=await t.json();return o.current&&(m(l),a.onFilingComplete?.(l)),l}catch(t){let l=t instanceof Error?t:new Error("Filing failed");return o.current&&r(l.message),a.onFilingError?.(l),null}finally{o.current&&u(false);}},[e.apiBaseUrl,e.stackId,a]),s=react.useCallback(()=>{m(null),r(null);},[]);return {filePaperwork:c,filing:i,result:f,error:p,reset:s}}function Ke(){let{config:e}=d(),[a,i]=react.useState([]),[u,f]=react.useState(true),[m,p]=react.useState(null),r=react.useRef(true),o=e.apiBaseUrl,c=react.useCallback(async()=>{try{f(!0),p(null);let s=await fetch(`${o}/api/keys/filings`,{credentials:"include"});if(!s.ok)throw new Error(await y(s,`Failed to fetch filings (${s.status})`));let n=await s.json(),t=Array.isArray(n)?n:n.filings??[];r.current&&i(t);}catch(s){r.current&&p(s instanceof Error?s.message:"Failed to fetch filings");}finally{r.current&&f(false);}},[o]);return react.useEffect(()=>(r.current=true,c(),()=>{r.current=false;}),[c]),{entries:a,loading:u,error:m,refresh:c}}
|
|
2
|
+
exports.useFilePaperwork=we;exports.useFilingHistory=Ke;exports.useKeyLedger=ae;exports.useKeys=ne;exports.useListKey=fe;exports.useMintKey=ce;exports.usePricing=G;exports.useSolanaPayment=ge;exports.useStripeCheckout=de;exports.useTransferKey=Re;
|
package/dist/hooks/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PricingInfo, NodeKeyInfo, LedgerEntry, PaymentMethod, MintResult, ListingResult, DirectTransferResult } from '../types/index.cjs';
|
|
1
|
+
import { PricingInfo, NodeKeyInfo, LedgerEntry, PaymentMethod, MintResult, ListingResult, DirectTransferResult, FilingResult, FilingHistoryEntry } from '../types/index.cjs';
|
|
2
2
|
|
|
3
3
|
interface UsePricingReturn {
|
|
4
4
|
pricing: PricingInfo | null;
|
|
@@ -71,4 +71,37 @@ interface UseTransferKeyReturn {
|
|
|
71
71
|
}
|
|
72
72
|
declare function useTransferKey(): UseTransferKeyReturn;
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
interface UseFilePaperworkReturn {
|
|
75
|
+
filePaperwork: (keyId: string) => Promise<FilingResult | null>;
|
|
76
|
+
filing: boolean;
|
|
77
|
+
result: FilingResult | null;
|
|
78
|
+
error: string | null;
|
|
79
|
+
reset: () => void;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* File paperwork against an eligible NodeKey to redeem Paper.
|
|
83
|
+
*
|
|
84
|
+
* Backend contract: POST {apiBaseUrl}/api/keys/{keyId}/file
|
|
85
|
+
* Response: FilingResult JSON
|
|
86
|
+
*
|
|
87
|
+
* The backend reads the prepared paperWork blob attached to the key,
|
|
88
|
+
* submits the on-chain prove instruction, and triggers the multisig
|
|
89
|
+
* payout to the user's stack-scoped payment_address.
|
|
90
|
+
*/
|
|
91
|
+
declare function useFilePaperwork(): UseFilePaperworkReturn;
|
|
92
|
+
|
|
93
|
+
interface UseFilingHistoryReturn {
|
|
94
|
+
entries: FilingHistoryEntry[];
|
|
95
|
+
loading: boolean;
|
|
96
|
+
error: string | null;
|
|
97
|
+
refresh: () => Promise<void>;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Fetch the current user's filing history (paperwork that has been filed).
|
|
101
|
+
*
|
|
102
|
+
* Backend contract: GET {apiBaseUrl}/api/keys/filings
|
|
103
|
+
* Response: { filings: FilingHistoryEntry[] } | FilingHistoryEntry[]
|
|
104
|
+
*/
|
|
105
|
+
declare function useFilingHistory(): UseFilingHistoryReturn;
|
|
106
|
+
|
|
107
|
+
export { useFilePaperwork, useFilingHistory, useKeyLedger, useKeys, useListKey, useMintKey, usePricing, useSolanaPayment, useStripeCheckout, useTransferKey };
|