@stacknet/userutils 0.6.6 → 0.6.10
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 +59 -1
- package/dist/components/index.d.ts +59 -1
- package/dist/components/index.js +2 -2
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/server/index.cjs +1 -1
- package/dist/server/index.d.cts +6 -2
- package/dist/server/index.d.ts +6 -2
- package/dist/server/index.js +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -3,7 +3,7 @@ export { M as MPCNode, P as PublicSession, S as Session } from './auth-c1d7Eji2.
|
|
|
3
3
|
export { BillingPlan, BillingRecord, PrepaidCheckoutResult, PrepaidVerifyResult, ProfileScope, ProfileUpdateInput, Subscription, UsageSummary, UserProfile, UserUtilsCallbacks, UserUtilsConfig } from './types/index.cjs';
|
|
4
4
|
export { cn, decodeJwtPayloadClient, formatTokens, readCSRFCookie, readSessionCookie, safeUrl, validateRedirectUrl } from './utils/index.cjs';
|
|
5
5
|
export { BridgeIdentity, GoogleOneTapConfig, StackPublicConfig, UseJoinCodeConfig, UseJoinCodeResult, WalletState, useAuthBridge, useBillingHistory, useCSRFToken, useGoogleOneTap, useJoinCode, usePlans, usePrepaidCheckout, useProfile, useSession, useStackAuth, useStackConfig, useSubscription, useUsage, useWeb3Wallet } from './hooks/index.cjs';
|
|
6
|
-
export { AppleIcon, ConnectWidget, ConnectWidgetProps, DiscordIcon, EthereumIcon, GoogleIcon, MetaMaskIcon, OTPInput, OTPInputProps, PhantomIcon, ProfileSettings, ProfileSettingsProps, SolanaIcon, TelegramIcon, TwitterIcon, UserUtilsProvider, UserUtilsProviderProps, useUserUtilsContext } from './components/index.cjs';
|
|
6
|
+
export { AppleIcon, ClientRateLimitConfig, ClientRateLimitDecision, ConnectWidget, ConnectWidgetProps, DiscordIcon, EthereumIcon, GoogleIcon, MetaMaskIcon, OTPInput, OTPInputProps, PhantomIcon, ProfileSettings, ProfileSettingsProps, SolanaIcon, TelegramIcon, TwitterIcon, UserUtilsProvider, UserUtilsProviderProps, createClientRateLimiter, useUserUtilsContext } from './components/index.cjs';
|
|
7
7
|
export { createAuthClient } from './core/index.cjs';
|
|
8
8
|
export { A as AuthClient, a as AuthClientConfig, b as AuthTransport } from './types-B_Vj6cr4.cjs';
|
|
9
9
|
export { SecureStorage, createNativeTransport, createWebTransport } from './adapters/index.cjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { M as MPCNode, P as PublicSession, S as Session } from './auth-c1d7Eji2.
|
|
|
3
3
|
export { BillingPlan, BillingRecord, PrepaidCheckoutResult, PrepaidVerifyResult, ProfileScope, ProfileUpdateInput, Subscription, UsageSummary, UserProfile, UserUtilsCallbacks, UserUtilsConfig } from './types/index.js';
|
|
4
4
|
export { cn, decodeJwtPayloadClient, formatTokens, readCSRFCookie, readSessionCookie, safeUrl, validateRedirectUrl } from './utils/index.js';
|
|
5
5
|
export { BridgeIdentity, GoogleOneTapConfig, StackPublicConfig, UseJoinCodeConfig, UseJoinCodeResult, WalletState, useAuthBridge, useBillingHistory, useCSRFToken, useGoogleOneTap, useJoinCode, usePlans, usePrepaidCheckout, useProfile, useSession, useStackAuth, useStackConfig, useSubscription, useUsage, useWeb3Wallet } from './hooks/index.js';
|
|
6
|
-
export { AppleIcon, ConnectWidget, ConnectWidgetProps, DiscordIcon, EthereumIcon, GoogleIcon, MetaMaskIcon, OTPInput, OTPInputProps, PhantomIcon, ProfileSettings, ProfileSettingsProps, SolanaIcon, TelegramIcon, TwitterIcon, UserUtilsProvider, UserUtilsProviderProps, useUserUtilsContext } from './components/index.js';
|
|
6
|
+
export { AppleIcon, ClientRateLimitConfig, ClientRateLimitDecision, ConnectWidget, ConnectWidgetProps, DiscordIcon, EthereumIcon, GoogleIcon, MetaMaskIcon, OTPInput, OTPInputProps, PhantomIcon, ProfileSettings, ProfileSettingsProps, SolanaIcon, TelegramIcon, TwitterIcon, UserUtilsProvider, UserUtilsProviderProps, createClientRateLimiter, useUserUtilsContext } from './components/index.js';
|
|
7
7
|
export { createAuthClient } from './core/index.js';
|
|
8
8
|
export { A as AuthClient, a as AuthClientConfig, b as AuthTransport } from './types-Cu0do-w-.js';
|
|
9
9
|
export { SecureStorage, createNativeTransport, createWebTransport } from './adapters/index.js';
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {createContext,useState,useCallback,useEffect,useRef,useContext}from'react';import {jsx,jsxs,Fragment}from'react/jsx-runtime';function Et(...e){return twMerge(clsx(e))}function Rt(e){return e>=1e12?`${(e/1e12).toFixed(e%1e12===0?0:1)}T`:e>=1e9?`${(e/1e9).toFixed(e%1e9===0?0:1)}B`:e>=1e6?`${(e/1e6).toFixed(e%1e6===0?0:1)}M`:e>=1e3?`${(e/1e3).toFixed(0)}K`:e.toLocaleString()}function _t(e,t){if(!e)return "/";if(e.startsWith("/")&&!e.startsWith("//"))return e;try{let r=new URL(e,t);return r.origin!==t?"/":r.pathname+r.search+r.hash}catch{return "/"}}function ne(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 d=new URL(r);if(d.protocol==="http:"||d.protocol==="https:")return d.toString()}catch{}return t}function $t(e){try{let t=e.split(".");if(t.length!==3)return null;let r=atob(t[1].replace(/-/g,"+").replace(/_/g,"/"));return JSON.parse(r)}catch{return null}}function oe(){if(typeof document>"u")return null;try{let e=document.cookie.split(";").map(r=>r.trim()).find(r=>r.startsWith("stackauth_session="));if(!e)return null;let t=e.slice(18);return JSON.parse(atob(t.replace(/-/g,"+").replace(/_/g,"/")))}catch{return null}}function J(e="__csrf"){if(typeof document>"u")return null;let t=document.cookie.split(";").map(r=>r.trim()).find(r=>r.startsWith(`${e}=`));return t?t.slice(e.length+1):null}function re(){let[e,t]=useState(null),[r,d]=useState(true),u=useCallback(()=>{let a=oe();a&&a.expiresAt>Date.now()?t({userId:a.userId,address:a.address,chain:a.chain,expiresAt:a.expiresAt,planId:a.planId,authMethod:a.authMethod}):t(null),d(false);},[]);useEffect(()=>{u();},[u]);let y=useCallback(async(a="")=>{try{let l=await fetch(`${a}/api/auth/session`);if(l.ok){let c=await l.json();if(c.session)return t(c.session),c.session}return t(null),null}catch{return null}},[]),m=!!e&&e.expiresAt>Date.now();return {session:e,loading:r,isAuthenticated:m,refresh:y,readSession:u}}function Pe(e="__csrf",t="x-csrf-token"){let[r,d]=useState(null);useEffect(()=>{d(J(e));},[e]);let u=r?{[t]:r}:{};return {token:r,headers:u}}function Ie(){let[e,t]=useState({connected:false,address:null,chain:null,provider:null}),[r,d]=useState(null),u=useCallback(async(l="phantom")=>{d(null);try{let c=typeof window<"u"?window:null,h=l==="phantom"?c?.phantom?.solana||c?.solana:c?.solflare;if(!h)return d(`${l} wallet not found`),null;let i=(await h.connect()).publicKey.toString();return t({connected:!0,address:i,chain:"solana",provider:l}),i}catch(c){return d(c.message||"Failed to connect wallet"),null}},[]),y=useCallback(async()=>{d(null);try{let c=(typeof window<"u"?window:null)?.ethereum;if(!c)return d("MetaMask not found"),null;let h=c;c.providers?.length&&(h=c.providers.find(n=>n.isMetaMask)||c);let i=(await h.request({method:"eth_requestAccounts"}))[0];return i?(t({connected:!0,address:i,chain:"ethereum",provider:"metamask"}),i):(d("No account selected"),null)}catch(l){return d(l.message||"Failed to connect wallet"),null}},[]),m=useCallback(async(l,c)=>{d(null);let h=c?.chain||e.chain,o=c?.provider||e.provider,i=c?.address||e.address;try{if(h==="solana"){let n=typeof window<"u"?window:null,g=o==="solflare"?n?.solflare:n?.phantom?.solana||n?.solana;if(!g)throw new Error("Wallet not available");let s=new TextEncoder().encode(l),k=await g.signMessage(s,"utf8"),C=new Uint8Array(k.signature||k),w="";for(let L=0;L<C.byteLength;L++)w+=String.fromCharCode(C[L]);return btoa(w)}if(h==="ethereum"){let g=(typeof window<"u"?window:null)?.ethereum;if(g?.providers?.length&&(g=g.providers.find(k=>k.isMetaMask)||g),!g)throw new Error("MetaMask not available");return await g.request({method:"personal_sign",params:[l,i]})}throw new Error("No wallet connected")}catch(n){return d(n.message||"Signing failed"),null}},[e]),a=useCallback(()=>{t({connected:false,address:null,chain:null,provider:null}),d(null);},[]);return {wallet:e,error:r,connectSolana:u,connectEVM:y,signMessage:m,disconnect:a}}var Jt="https://stacknet.magma-rpc.com/auth/bridge",fe="stacknet-auth-bridge";function Ae(e){let t=e?.bridgeUrl||Jt,r=e?.disabled||false,d=useRef(null),[u,y]=useState({ready:false,known:false,identity:null,identityCount:0,resolvedStackId:null}),m=useRef([]),a=useRef(false),l=useCallback(n=>{let g={...n,protocol:fe};a.current&&d.current?.contentWindow?d.current.contentWindow.postMessage(g,new URL(t).origin):m.current.push(g);},[t]);useEffect(()=>{if(r)return;let n=s=>{if(!(!s.data||s.data.protocol!==fe)){try{if(s.origin!==new URL(t).origin)return}catch{return}switch(s.data.type){case "bridge:ready":a.current=true,y(k=>({...k,ready:true}));for(let k of m.current)d.current?.contentWindow?.postMessage(k,s.origin);m.current=[],d.current?.contentWindow?.postMessage({protocol:fe,type:"auth:check"},s.origin),d.current?.contentWindow?.postMessage({protocol:fe,type:"auth:resolve-stack"},s.origin);break;case "auth:status":y(k=>({...k,known:s.data.known,identity:s.data.identity,identityCount:s.data.identityCount||0}));break;case "auth:resolved-stack":y(k=>({...k,resolvedStackId:s.data.stackId||null}));break;}}};window.addEventListener("message",n);let g=document.createElement("iframe");return g.src=t,g.style.display="none",g.setAttribute("aria-hidden","true"),g.setAttribute("tabindex","-1"),g.setAttribute("sandbox","allow-scripts allow-same-origin"),document.body.appendChild(g),d.current=g,()=>{window.removeEventListener("message",n),g.parentNode&&g.parentNode.removeChild(g),d.current=null,a.current=false;}},[t,r]);let c=useCallback(n=>{l({type:"auth:connected",...n});},[l]),h=useCallback(n=>{l({type:"auth:disconnected",...n});},[l]),o=useCallback(()=>{l({type:"auth:clear"}),y({ready:u.ready,known:false,identity:null,identityCount:0,resolvedStackId:null});},[l,u.ready]),i=useCallback(()=>{l({type:"auth:check"});},[l]);return {...u,reportConnected:c,reportDisconnected:h,clearAll:o,refresh:i}}async function ut(e,t,r,d){let u=e.apiVersion||"v2",y=`${e.baseUrl}/api/${u}${r}`;try{let m=await fetch(y,{method:t,headers:{"Content-Type":"application/json"},body:d?JSON.stringify(d):void 0}),a=await m.json();return m.ok?a.success&&a.data!==void 0?{success:!0,data:a.data}:{success:!0,data:a}:{success:!1,error:a.error||{code:"UNKNOWN_ERROR",message:"Unknown error"}}}catch(m){return {success:false,error:{code:"NETWORK_ERROR",message:m instanceof Error?m.message:"Network error"}}}}function Me(e){return {getNetworkStatus:()=>ut(e,"GET","/network/status"),getWeb3Challenge:(t,r)=>ut(e,"POST",`/stacks/${encodeURIComponent(e.stackId)}/auth/web3/challenge`,{chain:t,address:r})}}function Le(e={apiBaseUrl:""}){let{wallet:t,connectSolana:r,connectEVM:d,signMessage:u,disconnect:y}=Ie(),{session:m,isAuthenticated:a,refresh:l,readSession:c}=re(),{headers:h}=Pe(),o=Ae({disabled:typeof window>"u"}),[i,n]=useState(false),[g,s]=useState(null),[k,C]=useState(false),w=e.apiBaseUrl||"",L=e.stacknetUrl||"https://stacknet.magma-rpc.com",I=e.stackId||o.resolvedStackId||"",v=Me({baseUrl:L,stackId:I}),$=useCallback(async(P,S,N,R)=>{n(true),s(null);try{let A=S;if(!A){let Y=await N();if(!Y)return n(!1),!1;A=Y;}let D=await v.getWeb3Challenge(P,A);if(!D.success||!D.data)return s("Failed to get challenge"),n(!1),!1;let E=await u(D.data.message,{chain:P,provider:R,address:A});if(!E)return n(!1),!1;let G={chain:P,message:D.data.message,signature:E,stackId:I};P==="solana"&&(G.publicKey=A);let B=await fetch(`${w}/api/auth/callback`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(G)});if(!B.ok){let Y=await B.json().catch(()=>({}));return s(Y.error||"Authentication failed"),n(!1),!1}return o.reportConnected({address:A,chain:P,method:R||(P==="solana"?"phantom":"metamask"),stackId:I}),c(),n(!1),!0}catch(A){return s(A.message||"Authentication failed"),n(false),false}},[w,v,u,c,o,I]),U=useCallback(async(P="phantom")=>{let S=await r(P);return S?$("solana",S,()=>r(P),P):false},[r,$]),z=useCallback(async()=>{let P=await d();return P?$("ethereum",P,d,"metamask"):false},[d,$]),b=useCallback(async P=>{n(true),s(null);try{let S=await fetch(`${w}/api/auth/otp`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({code:P})});if(!S.ok){let N=await S.json().catch(()=>({}));return s(N.error||"Invalid code"),n(!1),!1}return c(),n(!1),!0}catch(S){return s(S.message||"OTP verification failed"),n(false),false}},[w,c]),T=useCallback(async(P,S)=>{n(true),s(null);try{let N=S||`${window.location.origin}/api/auth/oauth/callback`,R=new URLSearchParams({provider:P,redirectUri:N,stackId:I}),A=await fetch(`${w}/api/auth/oauth/start?${R}`,{credentials:"include"});if(!A.ok){let E=await A.json().catch(()=>({}));return s(E.error||"Failed to start OAuth flow"),n(!1),!1}let D=await A.json();if(D.redirect_url){let E;try{E=new URL(D.redirect_url);}catch{return s("Invalid OAuth redirect URL"),n(!1),!1}let G=[/(^|\.)accounts\.google\.com$/,/(^|\.)discord\.com$/,/(^|\.)github\.com$/,/(^|\.)x\.com$/,/(^|\.)twitter\.com$/,/(^|\.)apple\.com$/];return E.protocol!=="https:"||!G.some(B=>B.test(E.hostname))?(s(`Refusing to redirect to non-OAuth host: ${E.hostname}`),n(!1),!1):(typeof sessionStorage<"u"&&(sessionStorage.setItem("oauth_state",D.state||""),sessionStorage.setItem("oauth_provider",P)),window.location.href=E.toString(),!0)}return s("No redirect URL returned"),n(!1),!1}catch(N){return s(N.message||"OAuth flow failed"),n(false),false}},[w,I]),O=useCallback(async(P,S,N)=>{n(true),s(null);try{if(typeof sessionStorage<"u"){let A=sessionStorage.getItem("oauth_state"),D=sessionStorage.getItem("oauth_provider");if(sessionStorage.removeItem("oauth_state"),sessionStorage.removeItem("oauth_provider"),!A||A!==N)return s("OAuth state mismatch \u2014 refusing to complete login"),n(!1),!1;if(D&&D!==P)return s("OAuth provider mismatch \u2014 refusing to complete login"),n(!1),!1}let R=await fetch(`${w}/api/auth/oauth/callback`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({provider:P,code:S,state:N,stackId:I})});if(!R.ok){let A=await R.json().catch(()=>({}));return s(A.error||"OAuth authentication failed"),n(!1),!1}return c(),n(!1),!0}catch(R){return s(R.message||"OAuth callback failed"),n(false),false}},[w,I,c]),F=useCallback(async()=>{t.address&&t.chain&&o.reportDisconnected({address:t.address,chain:t.chain,stackId:I});try{await fetch(`${w}/api/auth/logout`,{method:"POST",headers:h,credentials:"include"});}catch{}y(),c();},[w,h,y,c,t,o,I]);return useEffect(()=>{if(!e.autoConnect||k||a||!o.ready||!o.known||!o.identity)return;C(true);let{chain:P,method:S}=o.identity;P==="solana"&&(S==="phantom"||S==="solflare")?U(S):P==="ethereum"&&z();},[e.autoConnect,k,a,o,U,z]),{session:m,isAuthenticated:a,wallet:t,loading:i,error:g,authenticateSolana:U,authenticateEVM:z,authenticateOTP:b,authenticateOAuth:T,authenticateOAuthCallback:O,logout:F,refresh:()=>l(w),stackId:I,bridge:{ready:o.ready,known:o.known,identity:o.identity,identityCount:o.identityCount,resolvedStackId:o.resolvedStackId}}}function ie(e,t="https://stacknet.magma-rpc.com"){let[r,d]=useState(null),[u,y]=useState(false),[m,a]=useState(null),l=useCallback(async h=>{y(true),a(null);try{let o=await fetch(`${t}/api/v2/stacks/${h}`);if(!o.ok)return a("Stack not found"),y(!1),null;let i=await o.json(),n=i.data?.stack||i.stack||i,g={id:n.id,name:n.name,displayName:n.displayName||n.name,description:n.description,logoUrl:n.logoUrl,webPageUrl:n.webPageUrl,allowedChains:n.allowedChains||[],features:n.features,stripeProvider:n.stripeProvider,oauthProviders:n.oauthProviders?.map(s=>({provider:s.provider,clientId:s.clientId,enabled:s.enabled!==!1}))};return d(g),y(!1),g}catch(o){return a(o.message),y(false),null}},[t]);useEffect(()=>{e&&l(e);},[e,l]);let c=r?Yt(r):[];return {config:r,loading:u,error:m,identityProviders:c,fetchConfig:l}}function Yt(e){let t=[];if(e.features?.web3Auth!==false&&(e.allowedChains.includes("solana")&&(t.push({type:"wallet",id:"phantom",name:"Phantom",chain:"solana"}),t.push({type:"wallet",id:"solflare",name:"Solflare",chain:"solana"})),(e.allowedChains.includes("ethereum")||e.allowedChains.includes("polygon")||e.allowedChains.includes("base"))&&t.push({type:"wallet",id:"metamask",name:"MetaMask",chain:"ethereum"})),e.features?.apiKeyAuth!==false&&t.push({type:"otp",id:"otp",name:"Access Code"}),e.features?.oauthAuth&&e.oauthProviders)for(let r of e.oauthProviders)r.enabled&&t.push({type:"oauth",id:r.provider,name:r.provider});return t}function Xt(e=""){let[t,r]=useState([]),[d,u]=useState(true),[y,m]=useState(null),a=useCallback(async()=>{try{let l=await fetch(`${e}/api/billing/plans`);if(l.ok){let c=await l.json();r(c.plans||c||[]);}}catch(l){m(l.message);}finally{u(false);}},[e]);return useEffect(()=>{a();},[a]),{plans:t,loading:d,error:y,refresh:a}}function tn(e=""){let[t,r]=useState(null),[d,u]=useState(true),[y,m]=useState(null),a=useCallback(async()=>{try{let h=await fetch(`${e}/api/billing/subscription`);if(h.ok){let o=await h.json();r(o.plan?o:null);}}catch(h){m(h.message);}finally{u(false);}},[e]);useEffect(()=>{a();},[a]);let l=useCallback(async h=>{let o=J(),n=await(await fetch(`${e}/api/billing/subscribe`,{method:"POST",headers:{"Content-Type":"application/json",...o?{"x-csrf-token":o}:{}},body:JSON.stringify({planId:h})})).json();return n.url||n.checkoutUrl||null},[e]),c=useCallback(async()=>{let h=J();return (await fetch(`${e}/api/billing/cancel`,{method:"POST",headers:h?{"x-csrf-token":h}:{}})).ok?(await a(),true):false},[e,a]);return {subscription:t,loading:d,error:y,refresh:a,subscribe:l,cancel:c}}function rn(e=""){let[t,r]=useState(null),[d,u]=useState(true),[y,m]=useState(null),a=useCallback(async()=>{try{let l=await fetch(`${e}/api/billing/usage`);if(l.ok){let c=await l.json();r(c);}}catch(l){m(l.message);}finally{u(false);}},[e]);return useEffect(()=>{a();},[a]),{usage:t,loading:d,error:y,refresh:a}}function sn(e=""){let[t,r]=useState(false),[d,u]=useState(null),y=useCallback(async a=>{r(true),u(null);try{let l=J(),c=await fetch(`${e}/api/billing/prepaid`,{method:"POST",headers:{"Content-Type":"application/json",...l?{"x-csrf-token":l}:{}},body:JSON.stringify({amountCents:a})}),h=await c.json();return c.ok?h.url||null:(u(h.error||"Purchase failed"),null)}catch(l){return u(l.message),null}finally{r(false);}},[e]),m=useCallback(async a=>{r(true),u(null);try{let l=J(),c=await fetch(`${e}/api/billing/verify-prepaid`,{method:"POST",headers:{"Content-Type":"application/json",...l?{"x-csrf-token":l}:{}},body:JSON.stringify({sessionId:a})}),h=await c.json();return c.ok?h:(u(h.error||"Verification failed"),null)}catch(l){return u(l.message),null}finally{r(false);}},[e]);return {purchase:y,verifySession:m,loading:t,error:d}}function cn(e="",t){let[r,d]=useState([]),[u,y]=useState(true),[m,a]=useState(null),l=t?.limit||50,c=t?.offset||0,h=useCallback(async()=>{try{let o=await fetch(`${e}/api/billing/history?limit=${l}&offset=${c}`);if(o.ok){let i=await o.json();d(i.records||i.history||(Array.isArray(i)?i:[]));}}catch(o){a(o.message);}finally{y(false);}},[e,l,c]);return useEffect(()=>{h();},[h]),{records:r,loading:u,error:m,refresh:h}}function un(){if(typeof document>"u")return null;let e=document.cookie.split(";").map(t=>t.trim()).find(t=>t.startsWith("__csrf="));return e?e.slice(7):null}function _e(e,t){let[r,d]=useState(null),[u,y]=useState(true),[m,a]=useState(false),[l,c]=useState(null),h=t?.apiBaseUrl??"",o=t?.scope===void 0||t?.scope==="global"?"global":`stack:${t.scope.stackId}`,i=useCallback(s=>{let k=encodeURIComponent(s);if(o==="global")return `${h}/api/user/profile/${k}`;let C=o.slice(6);return `${h}/api/v2/stacks/${encodeURIComponent(C)}/members/${k}/profile`},[h,o]),n=useCallback(async()=>{if(!e){d(null),y(false);return}y(true),c(null);try{let s=await fetch(i(e));if(s.ok){let k=await s.json(),C=k.profile||k.data?.profile||k;d({mid:C.mid||e,username:C.username||"",avatarUrl:C.avatar_url||C.avatarUrl,bio:C.bio,paymentAddress:C.payment_address||C.paymentAddress,createdAt:C.created_at||C.createdAt,updatedAt:C.updated_at||C.updatedAt});}else if(s.status===404)d({mid:e,username:""});else throw new Error(`${s.status}`)}catch(s){c(s instanceof Error?s.message:"Failed to load profile");}finally{y(false);}},[e,i]);useEffect(()=>{n();},[n]);let g=useCallback(async s=>{if(!e)return false;a(true),c(null);try{let k=un(),C={};s.username!==void 0&&(C.username=s.username),s.avatarUrl!==void 0&&(C.avatar_url=s.avatarUrl),s.bio!==void 0&&(C.bio=s.bio),s.paymentAddress!==void 0&&(C.payment_address=s.paymentAddress);let w=await fetch(i(e),{method:"PUT",headers:{"Content-Type":"application/json",...k?{"x-csrf-token":k}:{}},credentials:"same-origin",body:JSON.stringify(C)});if(!w.ok){let v=await w.json().catch(()=>({}));throw new Error(v.error||v.message||`Update failed: ${w.status}`)}let L=await w.json(),I=L.profile||L.data?.profile||L;return d(v=>({mid:v?.mid||e,username:s.username??v?.username??"",avatarUrl:s.avatarUrl??v?.avatarUrl,bio:s.bio??v?.bio,paymentAddress:s.paymentAddress??I.payment_address??I.paymentAddress??v?.paymentAddress,createdAt:v?.createdAt,updatedAt:I.updated_at||I.updatedAt||Date.now()})),!0}catch(k){return c(k instanceof Error?k.message:"Update failed"),false}finally{a(false);}},[e,i]);return {profile:r,loading:u,saving:m,error:l,updateProfile:g,refresh:n}}var mt="google-identity-services",pn="https://accounts.google.com/gsi/client";function fn({stackId:e,stacknetUrl:t="https://stacknet.magma-rpc.com",apiBaseUrl:r="",autoPrompt:d=true,cancelOnTapOutside:u=true,onSuccess:y,onError:m,disabled:a=false}){let{config:l}=ie(e,t),{isAuthenticated:c,loading:h,readSession:o}=re(),[i,n]=useState(false),[g,s]=useState(null),[k,C]=useState(false),w=useRef(false),L=useRef(false),v=l?.oauthProviders?.find(b=>b.provider==="google"&&b.enabled&&b.clientId)?.clientId||null;useEffect(()=>{if(a||!v||typeof window>"u")return;if(document.getElementById(mt)){C(true);return}let b=document.createElement("script");b.id=mt,b.src=pn,b.async=true,b.defer=true,b.onload=()=>C(true),b.onerror=()=>{s("Failed to load Google sign-in"),m?.("Failed to load Google Identity Services script");},document.head.appendChild(b);},[a,v,m]);let $=useCallback(async b=>{n(true),s(null);try{let T=await fetch(`${r}/api/auth/google/one-tap`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({credential:b.credential,stackId:e})});if(!T.ok){let F=(await T.json().catch(()=>({}))).error||"Google sign-in failed";s(F),m?.(F),n(!1);return}o(),n(!1),y?.();}catch(T){let O=T.message||"Google sign-in failed";s(O),m?.(O),n(false);}},[r,e,o,y,m]);useEffect(()=>{if(a){console.debug("[GoogleOneTap] Disabled");return}if(!k){console.debug("[GoogleOneTap] Script not loaded yet, clientId:",v);return}if(!v){console.debug("[GoogleOneTap] No Google clientId from stack config");return}if(h){console.debug("[GoogleOneTap] Session still loading");return}if(c){console.debug("[GoogleOneTap] User already authenticated, skipping");return}if(!window.google?.accounts?.id){console.debug("[GoogleOneTap] GIS library not available on window");return}w.current||(console.debug("[GoogleOneTap] Initializing with clientId:",v),w.current=true,window.google.accounts.id.initialize({client_id:v,callback:$,auto_select:true,cancel_on_tap_outside:u}),d&&!L.current&&(L.current=true,console.debug("[GoogleOneTap] Showing prompt..."),window.google.accounts.id.prompt(b=>{b.isDisplayed?.()&&console.debug("[GoogleOneTap] Prompt displayed"),b.isNotDisplayed?.()&&console.debug("[GoogleOneTap] Not displayed:",b.getNotDisplayedReason?.()),b.isSkippedMoment?.()&&console.debug("[GoogleOneTap] Skipped:",b.getSkippedReason?.()),b.isDismissedMoment?.()&&console.debug("[GoogleOneTap] Dismissed:",b.getDismissedReason?.());})));},[a,k,v,h,c,$,d,u]),useEffect(()=>()=>{window.google?.accounts?.id&&w.current&&window.google.accounts.id.cancel();},[]);let U=useCallback(()=>{!window.google?.accounts?.id||!w.current||window.google.accounts.id.prompt();},[]),z=useCallback((b,T)=>{!b||!window.google?.accounts?.id||!w.current||window.google.accounts.id.renderButton(b,{theme:T?.theme||"filled_black",size:T?.size||"large",text:T?.text||"signin_with",width:T?.width});},[]);return {available:!!v,ready:k&&!!v,loading:i,error:g,prompt:U,renderButton:z,clientId:v}}var mn="/api";function hn(e,t){return `${(t||(typeof window<"u"?window.location.origin:"")).replace(/\/$/,"")}/?ref=${encodeURIComponent(e)}`}function yn(e={}){let{shareBaseUrl:t,autoMint:r=true}=e,[d,u]=useState(null),[y,m]=useState(true),[a,l]=useState(null),c=useCallback(async()=>{m(true),l(null);try{let i=r?"POST":"GET",n=await fetch(`${mn}/social/join-code`,{method:i,credentials:"include"});if(!n.ok){u(null),n.status===401?l("not_authenticated"):l(`HTTP ${n.status}`);return}let g=await n.json();u(g?.code??null);}catch(i){l(i?.message||"network_error"),u(null);}finally{m(false);}},[r]);useEffect(()=>{c();},[c]);let h=d?hn(d,t):null,o=useCallback(async()=>{if(!h)return false;try{if(typeof navigator<"u"&&navigator.clipboard?.writeText)return await navigator.clipboard.writeText(h),!0}catch{}return false},[h]);return {code:d,shareUrl:h,loading:y,error:a,refresh:c,copyShareLink:o}}var yt=createContext(null);function wn(){let e=useContext(yt);if(!e)throw new Error("useUserUtilsContext must be used within <UserUtilsProvider>");return e}function Cn({config:e,callbacks:t,children:r}){return jsx(yt.Provider,{value:{config:e,callbacks:t},children:r})}function ae({length:e=6,onComplete:t,disabled:r=false,error:d,className:u="",inputClassName:y=""}){let [m,a]=useState(Array(e).fill("")),l=useCallback((o,i)=>{if(i.length>1){let g=i.replace(/\D/g,"").slice(0,e).split(""),s=[...m];g.forEach((C,w)=>{o+w<e&&(s[o+w]=C);}),a(s);let k=Math.min(o+g.length,e-1);document.getElementById(`userutils-otp-${k}`)?.focus(),s.every(C=>C!=="")&&setTimeout(()=>t(s.join("")),100);return}if(!/^\d?$/.test(i))return;let n=[...m];n[o]=i,a(n),i&&o<e-1&&document.getElementById(`userutils-otp-${o+1}`)?.focus(),i&&o===e-1&&n.every(g=>g!=="")&&setTimeout(()=>t(n.join("")),100);},[m,e,t]),c=useCallback((o,i)=>{if(i.key==="Backspace"&&!m[o]&&o>0){document.getElementById(`userutils-otp-${o-1}`)?.focus();let n=[...m];n[o-1]="",a(n);}if(i.key==="Enter"){let n=m.join("");n.length===e&&t(n);}},[m,e,t]);useCallback(()=>{a(Array(e).fill("")),document.getElementById("userutils-otp-0")?.focus();},[e]);return jsxs("div",{className:u,children:[jsx("div",{className:"flex gap-2 justify-center",children:m.map((o,i)=>jsx("input",{id:`userutils-otp-${i}`,type:"text",inputMode:"numeric",maxLength:e,value:o,onChange:n=>l(i,n.target.value),onKeyDown:n=>c(i,n),disabled:r,autoFocus:i===0,className:`w-12 h-14 text-center text-xl font-mono bg-secondary border border-primary/10 text-foreground focus:outline-none focus:border-primary/30 disabled:opacity-50 ${y}`},i))}),d&&jsx("p",{className:"text-center text-sm text-red-400 mt-2",children:d})]})}ae.displayName="OTPInput";var Pn="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTA4IiBoZWlnaHQ9IjEwOCIgdmlld0JveD0iMCAwIDEwOCAxMDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMDgiIGhlaWdodD0iMTA4IiByeD0iMjYiIGZpbGw9IiNBQjlGRjIiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00Ni41MjY3IDY5LjkyMjlDNDIuMDA1NCA3Ni44NTA5IDM0LjQyOTIgODUuNjE4MiAyNC4zNDggODUuNjE4MkMxOS41ODI0IDg1LjYxODIgMTUgODMuNjU2MyAxNSA3NS4xMzQyQzE1IDUzLjQzMDUgNDQuNjMyNiAxOS44MzI3IDcyLjEyNjggMTkuODMyN0M4Ny43NjggMTkuODMyNyA5NCAzMC42ODQ2IDk0IDQzLjAwNzlDOTQgNTguODI1OCA4My43MzU1IDc2LjkxMjIgNzMuNTMyMSA3Ni45MTIyQzcwLjI5MzkgNzYuOTEyMiA2OC43MDUzIDc1LjEzNDIgNjguNzA1MyA3Mi4zMTRDNjguNzA1MyA3MS41NzgzIDY4LjgyNzUgNzAuNzgxMiA2OS4wNzE5IDY5LjkyMjlDNjUuNTg5MyA3NS44Njk5IDU4Ljg2ODUgODEuMzg3OCA1Mi41NzU0IDgxLjM4NzhDNDcuOTkzIDgxLjM4NzggNDUuNjcxMyA3OC41MDYzIDQ1LjY3MTMgNzQuNDU5OEM0NS42NzEzIDcyLjk4ODQgNDUuOTc2OCA3MS40NTU2IDQ2LjUyNjcgNjkuOTIyOVpNODMuNjc2MSA0Mi41Nzk0QzgzLjY3NjEgNDYuMTcwNCA4MS41NTc1IDQ3Ljk2NTggNzkuMTg3NSA0Ny45NjU4Qzc2Ljc4MTYgNDcuOTY1OCA3NC42OTg5IDQ2LjE3MDQgNzQuNjk4OSA0Mi41Nzk0Qzc0LjY5ODkgMzguOTg4NSA3Ni43ODE2IDM3LjE5MzEgNzkuMTg3NSAzNy4xOTMxQzgxLjU1NzUgMzcuMTkzMSA4My42NzYxIDM4Ljk4ODUgODMuNjc2MSA0Mi41Nzk0Wk03MC4yMTAzIDQyLjU3OTVDNzAuMjEwMyA0Ni4xNzA0IDY4LjA5MTYgNDcuOTY1OCA2NS43MjE2IDQ3Ljk2NThDNjMuMzE1NyA0Ny45NjU4IDYxLjIzMyA0Ni4xNzA0IDYxLjIzMyA0Mi41Nzk1QzYxLjIzMyAzOC45ODg1IDYzLjMxNTcgMzcuMTkzMSA2NS43MjE2IDM3LjE5MzFDNjguMDkxNiAzNy4xOTMxIDcwLjIxMDMgMzguOTg4NSA3MC4yMTAzIDQyLjU3OTVaIiBmaWxsPSIjRkZGREY4Ii8+Cjwvc3ZnPgo=";function me({className:e,style:t}){return jsx("img",{src:Pn,alt:"Phantom",className:e,style:t})}function he({className:e,style:t}){return jsxs("svg",{className:e,style:t,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 507.83 470.86",children:[jsx("polygon",{fill:"#e2761b",stroke:"#e2761b",strokeLinecap:"round",strokeLinejoin:"round",points:"482.09 0.5 284.32 147.38 320.9 60.72 482.09 0.5"}),jsx("polygon",{fill:"#e4761b",stroke:"#e4761b",strokeLinecap:"round",strokeLinejoin:"round",points:"25.54 0.5 221.72 148.77 186.93 60.72 25.54 0.5"}),jsx("polygon",{fill:"#e4761b",stroke:"#e4761b",strokeLinecap:"round",strokeLinejoin:"round",points:"410.93 340.97 358.26 421.67 470.96 452.67 503.36 342.76 410.93 340.97"}),jsx("polygon",{fill:"#e4761b",stroke:"#e4761b",strokeLinecap:"round",strokeLinejoin:"round",points:"4.67 342.76 36.87 452.67 149.57 421.67 96.9 340.97 4.67 342.76"}),jsx("polygon",{fill:"#e4761b",stroke:"#e4761b",strokeLinecap:"round",strokeLinejoin:"round",points:"143.21 204.62 111.8 252.13 223.7 257.1 219.73 136.85 143.21 204.62"}),jsx("polygon",{fill:"#e4761b",stroke:"#e4761b",strokeLinecap:"round",strokeLinejoin:"round",points:"364.42 204.62 286.91 135.46 284.32 257.1 396.03 252.13 364.42 204.62"}),jsx("polygon",{fill:"#e4761b",stroke:"#e4761b",strokeLinecap:"round",strokeLinejoin:"round",points:"149.57 421.67 216.75 388.87 158.71 343.55 149.57 421.67"}),jsx("polygon",{fill:"#e4761b",stroke:"#e4761b",strokeLinecap:"round",strokeLinejoin:"round",points:"290.88 388.87 358.26 421.67 348.92 343.55 290.88 388.87"}),jsx("polygon",{fill:"#d7c1b3",stroke:"#d7c1b3",strokeLinecap:"round",strokeLinejoin:"round",points:"358.26 421.67 290.88 388.87 296.25 432.8 295.65 451.28 358.26 421.67"}),jsx("polygon",{fill:"#d7c1b3",stroke:"#d7c1b3",strokeLinecap:"round",strokeLinejoin:"round",points:"149.57 421.67 212.18 451.28 211.78 432.8 216.75 388.87 149.57 421.67"}),jsx("polygon",{fill:"#233447",stroke:"#233447",strokeLinecap:"round",strokeLinejoin:"round",points:"213.17 314.54 157.12 298.04 196.67 279.95 213.17 314.54"}),jsx("polygon",{fill:"#233447",stroke:"#233447",strokeLinecap:"round",strokeLinejoin:"round",points:"294.46 314.54 310.96 279.95 350.71 298.04 294.46 314.54"}),jsx("polygon",{fill:"#cd6116",stroke:"#cd6116",strokeLinecap:"round",strokeLinejoin:"round",points:"149.57 421.67 159.11 340.97 96.9 342.76 149.57 421.67"}),jsx("polygon",{fill:"#cd6116",stroke:"#cd6116",strokeLinecap:"round",strokeLinejoin:"round",points:"348.72 340.97 358.26 421.67 410.93 342.76 348.72 340.97"}),jsx("polygon",{fill:"#cd6116",stroke:"#cd6116",strokeLinecap:"round",strokeLinejoin:"round",points:"396.03 252.13 284.32 257.1 294.66 314.54 311.16 279.95 350.91 298.04 396.03 252.13"}),jsx("polygon",{fill:"#cd6116",stroke:"#cd6116",strokeLinecap:"round",strokeLinejoin:"round",points:"157.12 298.04 196.87 279.95 213.17 314.54 223.7 257.1 111.8 252.13 157.12 298.04"}),jsx("polygon",{fill:"#e4751f",stroke:"#e4751f",strokeLinecap:"round",strokeLinejoin:"round",points:"111.8 252.13 158.71 343.55 157.12 298.04 111.8 252.13"}),jsx("polygon",{fill:"#e4751f",stroke:"#e4751f",strokeLinecap:"round",strokeLinejoin:"round",points:"350.91 298.04 348.92 343.55 396.03 252.13 350.91 298.04"}),jsx("polygon",{fill:"#e4751f",stroke:"#e4751f",strokeLinecap:"round",strokeLinejoin:"round",points:"223.7 257.1 213.17 314.54 226.29 382.31 229.27 293.07 223.7 257.1"}),jsx("polygon",{fill:"#e4751f",stroke:"#e4751f",strokeLinecap:"round",strokeLinejoin:"round",points:"284.32 257.1 278.96 292.87 281.34 382.31 294.66 314.54 284.32 257.1"}),jsx("polygon",{fill:"#f6851b",stroke:"#f6851b",strokeLinecap:"round",strokeLinejoin:"round",points:"294.66 314.54 281.34 382.31 290.88 388.87 348.92 343.55 350.91 298.04 294.66 314.54"}),jsx("polygon",{fill:"#f6851b",stroke:"#f6851b",strokeLinecap:"round",strokeLinejoin:"round",points:"157.12 298.04 158.71 343.55 216.75 388.87 226.29 382.31 213.17 314.54 157.12 298.04"}),jsx("polygon",{fill:"#c0ad9e",stroke:"#c0ad9e",strokeLinecap:"round",strokeLinejoin:"round",points:"295.65 451.28 296.25 432.8 291.28 428.42 216.35 428.42 211.78 432.8 212.18 451.28 149.57 421.67 171.43 439.55 215.75 470.36 291.88 470.36 336.4 439.55 358.26 421.67 295.65 451.28"}),jsx("polygon",{fill:"#161616",stroke:"#161616",strokeLinecap:"round",strokeLinejoin:"round",points:"290.88 388.87 281.34 382.31 226.29 382.31 216.75 388.87 211.78 432.8 216.35 428.42 291.28 428.42 296.25 432.8 290.88 388.87"}),jsx("polygon",{fill:"#763d16",stroke:"#763d16",strokeLinecap:"round",strokeLinejoin:"round",points:"490.44 156.92 507.33 75.83 482.09 0.5 290.88 142.41 364.42 204.62 468.37 235.03 491.43 208.2 481.49 201.05 497.39 186.54 485.07 177 500.97 164.87 490.44 156.92"}),jsx("polygon",{fill:"#763d16",stroke:"#763d16",strokeLinecap:"round",strokeLinejoin:"round",points:"0.5 75.83 17.39 156.92 6.66 164.87 22.56 177 10.44 186.54 26.34 201.05 16.4 208.2 39.26 235.03 143.21 204.62 216.75 142.41 25.54 0.5 0.5 75.83"}),jsx("polygon",{fill:"#f6851b",stroke:"#f6851b",strokeLinecap:"round",strokeLinejoin:"round",points:"468.37 235.03 364.42 204.62 396.03 252.13 348.92 343.55 410.93 342.76 503.36 342.76 468.37 235.03"}),jsx("polygon",{fill:"#f6851b",stroke:"#f6851b",strokeLinecap:"round",strokeLinejoin:"round",points:"143.21 204.62 39.26 235.03 4.67 342.76 96.9 342.76 158.71 343.55 111.8 252.13 143.21 204.62"}),jsx("polygon",{fill:"#f6851b",stroke:"#f6851b",strokeLinecap:"round",strokeLinejoin:"round",points:"284.32 257.1 290.88 142.41 321.1 60.72 186.93 60.72 216.75 142.41 223.7 257.1 226.09 293.27 226.29 382.31 281.34 382.31 281.74 293.27 284.32 257.1"})]})}function Je({className:e,style:t}){return jsxs("svg",{className:e,style:t,viewBox:"0 0 33 32",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{x:"0.5",width:"32",height:"32",rx:"4",fill:"#F1F2F9"}),jsx("path",{d:"M26.1001 16.2273C26.1001 15.5182 26.0365 14.8364 25.9183 14.1818H16.5001V18.05H21.8819C21.6501 19.3 20.9456 20.3591 19.8865 21.0682V23.5773H23.1183C25.0092 21.8364 26.1001 19.2727 26.1001 16.2273Z",fill:"#4285F4"}),jsx("path",{d:"M16.5001 26C19.2001 26 21.4637 25.1046 23.1182 23.5773L19.8864 21.0682C18.991 21.6682 17.8455 22.0227 16.5001 22.0227C13.8955 22.0227 11.691 20.2637 10.9046 17.9H7.56372V20.4909C9.20917 23.7591 12.591 26 16.5001 26Z",fill:"#34A853"}),jsx("path",{d:"M10.9047 17.8999C10.7047 17.2999 10.591 16.659 10.591 15.9999C10.591 15.3408 10.7047 14.6999 10.9047 14.0999V11.509H7.56376C6.86376 12.9025 6.49951 14.4405 6.50012 15.9999C6.50012 17.6136 6.88649 19.1408 7.56376 20.4908L10.9047 17.8999Z",fill:"#FBBC05"}),jsx("path",{d:"M16.5001 9.97726C17.9682 9.97726 19.2864 10.4818 20.3228 11.4727L23.191 8.60454C21.4591 6.99091 19.1955 6 16.5001 6C12.591 6 9.20917 8.2409 7.56372 11.5091L10.9046 14.1C11.691 11.7364 13.8955 9.97726 16.5001 9.97726Z",fill:"#EA4335"})]})}function Qe({className:e,style:t}){return jsxs("svg",{className:e,style:t,viewBox:"0 0 33 32",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{x:"0.5",width:"32",height:"32",rx:"4",fill:"#5462EB"}),jsx("path",{d:"M23.5433 8.87438C22.2479 8.26174 20.8587 7.81038 19.4063 7.55187C19.3799 7.54688 19.3534 7.55934 19.3398 7.58428C19.1612 7.91179 18.9633 8.33905 18.8247 8.67487C17.2625 8.43382 15.7084 8.43382 14.1782 8.67487C14.0396 8.33158 13.8345 7.91179 13.6551 7.58428C13.6414 7.56018 13.615 7.54771 13.5886 7.55187C12.1369 7.80955 10.7478 8.26092 9.45159 8.87438C9.44037 8.87937 9.43075 8.88769 9.42437 8.89849C6.78947 12.9558 6.06766 16.9134 6.42176 20.8219C6.42336 20.841 6.43378 20.8593 6.4482 20.871C8.18663 22.1868 9.87059 22.9857 11.5233 23.5152C11.5497 23.5235 11.5778 23.5135 11.5946 23.491C11.9855 22.9408 12.334 22.3606 12.6328 21.7504C12.6505 21.7147 12.6336 21.6723 12.5976 21.6581C12.0448 21.442 11.5185 21.1785 11.0122 20.8793C10.9721 20.8552 10.9689 20.7961 11.0058 20.7679C11.1123 20.6856 11.2189 20.6 11.3206 20.5135C11.339 20.4977 11.3647 20.4944 11.3863 20.5044C14.7125 22.0696 18.3136 22.0696 21.6006 20.5044C21.6222 20.4936 21.6479 20.4969 21.6671 20.5127C21.7688 20.5991 21.8754 20.6856 21.9827 20.7679C22.0196 20.7961 22.0172 20.8552 21.9771 20.8793C21.4708 21.1843 20.9445 21.442 20.3909 21.6573C20.3548 21.6715 20.3388 21.7147 20.3564 21.7504C20.6617 22.3597 21.0101 22.9399 21.3939 23.4902C21.4099 23.5135 21.4387 23.5235 21.4652 23.5152C23.1259 22.9857 24.8099 22.1868 26.5483 20.871C26.5635 20.8593 26.5731 20.8419 26.5747 20.8228C26.9985 16.3041 25.8649 12.3789 23.5697 8.89931C23.5641 8.88769 23.5545 8.87937 23.5433 8.87438Z",fill:"#F7F7F7"})]})}function Ve({className:e,style:t}){return jsxs("svg",{className:e,style:t,viewBox:"0 0 33 32",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{x:"0.5",width:"32",height:"32",rx:"4",fill:"black"}),jsx("path",{d:"M8.53901 8L14.7164 16.2153L8.5 22.8947H9.89907L15.3415 17.0468L19.7389 22.8947H24.5L17.975 14.2173L23.7612 8H22.3621L17.3499 13.3858L13.3001 8H8.53901ZM10.5964 9.02501H12.7837L22.4422 21.8695H20.255L10.5964 9.02501Z",fill:"#F7F7F7"})]})}function Ze({className:e,style:t}){return jsxs("svg",{className:e,style:t,viewBox:"0 0 33 32",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{x:"0.5",width:"32",height:"32",rx:"4",fill:"#000000"}),jsx("path",{d:"M21.3611 16.7384C21.3807 18.9244 23.2792 19.6519 23.3001 19.661C23.2841 19.7124 22.9971 20.6962 22.3005 21.7115C21.6987 22.5892 21.0742 23.4636 20.0904 23.4816C19.1237 23.4994 18.8127 22.9098 17.7076 22.9098C16.6029 22.9098 16.2574 23.4636 15.3423 23.4994C14.3928 23.5352 13.6694 22.5504 13.0626 21.676C11.8226 19.8879 10.8747 16.6229 12.1471 14.4182C12.7791 13.3234 13.9087 12.6304 15.1346 12.6126C16.0668 12.5948 16.9468 13.2378 17.5167 13.2378C18.0865 13.2378 19.1555 12.4647 20.2795 12.579C20.7501 12.5986 22.0715 12.7692 22.9207 14.0122C22.852 14.0549 21.3453 14.9328 21.3611 16.7384ZM19.5432 11.392C20.0472 10.7809 20.3862 9.93 20.2939 9.08325C19.5709 9.11221 18.6961 9.56574 18.1749 10.1763C17.708 10.717 17.2995 11.582 17.4096 12.4111C18.2158 12.4736 19.0391 12.003 19.5432 11.392Z",fill:"#FFFFFF"})]})}function Un({config:e,onSuccess:t,title:r="Log in or Sign up",showWallets:d,showOTP:u,hideHeader:y,onOTPSubmit:m,otpLabel:a="Access Code",showPreviewCode:l=false,onPreviewCodeSubmit:c,previewCodeLabel:h="Preview Code",oauthInline:o,oauthFirst:i,className:n=""}){let g=Le(e),{isAuthenticated:s,wallet:k,loading:C,error:w,authenticateSolana:L,authenticateEVM:I,authenticateOTP:v,authenticateOAuth:$,bridge:U,stackId:z}=g,b=!e.stackId&&!z,T=e.stacknetUrl||"https://stacknet.magma-rpc.com",{config:O,identityProviders:F,loading:P}=ie(z||e.stackId||null,T),[S,N]=useState(b?"stack-select":"select"),[R,A]=useState(null),[D,E]=useState(false),[G,B]=useState("idle"),[Y,we]=useState(""),[et,Ce]=useState(false),[Se,K]=useState("idle"),[vt,de]=useState(""),[tt,Pt]=useState([]),[It,nt]=useState(e.stackId||null),[ue,Nt]=useState(false),[At,Mt]=useState(false);useEffect(()=>{if(typeof window>"u")return;let p=()=>{let Q=window;Nt(!!(Q.phantom?.solana?.isPhantom||Q.solana?.isPhantom));let ee=Q.ethereum;Mt(!!(ee?.isMetaMask||ee?.providers?.some(te=>te.isMetaMask)));};p(),window.addEventListener("ethereum#initialized",p);let H=setTimeout(p,500);return ()=>{window.removeEventListener("ethereum#initialized",p),clearTimeout(H);}},[]),useEffect(()=>{S==="stack-select"&&z&&(nt(z),N("select"));},[S,z]),useEffect(()=>{if(!(!U.ready||!b)&&U.identity){let p=[];U.resolvedStackId&&p.push({stackId:U.resolvedStackId,domain:typeof window<"u"?window.location.origin:""}),Promise.all(p.map(async H=>{try{let Q=await fetch(`${T}/api/v2/stacks/${H.stackId}`);if(Q.ok){let ee=await Q.json(),te=ee.data?.stack||ee;H.name=te.displayName||te.name,H.logoUrl=te.logoUrl;}}catch{}return H})).then(Pt);}},[U.ready,U.identity,U.resolvedStackId,b,T]),useEffect(()=>{s&&S==="success"&&t?.();},[s,S,t]);let ot=d||(F.length>0?F.filter(p=>p.type==="wallet").map(p=>p.id):["phantom","metamask"]),rt=u!==void 0?u:F.length>0?F.some(p=>p.type==="otp"):true,X=F.filter(p=>p.type==="oauth"),xe=new Set(i||[]),st=X.filter(p=>xe.has(p.id)),ve=o?X.filter(p=>!xe.has(p.id)):X,it=async p=>{A(p),N("connecting"),await $(p)||N("error");},Tt=async()=>{A("phantom"),N("connecting");let p=await L("phantom");N(p?"success":"error");},Lt=async()=>{A("metamask"),N("connecting");let p=await I();N(p?"success":"error");},Ut=async p=>{B("verifying"),we(""),await(m||v)(p)?(B("success"),N("success")):(B("error"),we("Invalid or expired code"),setTimeout(()=>B("idle"),2e3));},Ot=async p=>{if(!/^\d{6}$/.test(p))return false;try{return (await fetch("/api/auth/preview-code",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({code:p})})).ok?(typeof window<"u"&&window.localStorage&&window.localStorage.setItem("stacknet-api-key",`pc_${p}`),!0):!1}catch{return false}},jt=async p=>{K("verifying"),de(""),await(c||Ot)(p)?(K("success"),N("success"),t?.()):(K("error"),de("Invalid or expired preview code"),setTimeout(()=>K("idle"),2e3));},at=()=>{N(b&&!It?"stack-select":"select"),A(null),E(false),B("idle"),we(""),Ce(false),K("idle"),de("");};return jsxs("div",{className:`w-full max-w-md space-y-3 ${n}`,children:[!y&&jsxs("div",{className:"mb-6 text-center",children:[O?.logoUrl&&S!=="stack-select"&&jsx("img",{src:ne(O.logoUrl),alt:O.displayName||"",className:"h-16 w-16 mx-auto mb-4 rounded-xl"}),O?.displayName&&jsx("p",{className:"text-sm text-zinc-400 mb-2",children:O.displayName}),jsx("h1",{className:"font-semibold text-2xl text-white",children:"Log in or Sign up"})]}),S==="stack-select"&&jsxs("div",{className:"space-y-3",children:[jsx("p",{className:"text-center text-sm text-zinc-400 mb-4",children:tt.length>0?"Select a network to continue":"No previous connections found. Enter a Stack ID to continue."}),tt.map(p=>jsxs("button",{onClick:()=>{nt(p.stackId),N("select");},className:"flex w-full cursor-pointer items-center gap-4 rounded-xl border border-zinc-800 bg-[#25252f] p-4 transition-colors hover:bg-[#2d2d3a]",children:[p.logoUrl?jsx("img",{src:ne(p.logoUrl),alt:"",className:"h-10 w-10 flex-shrink-0"}):jsx("div",{className:"h-10 w-10 flex-shrink-0 bg-zinc-700 flex items-center justify-center text-zinc-400 text-sm font-mono",children:p.name?.[0]?.toUpperCase()||"S"}),jsxs("div",{className:"flex-1 text-left",children:[jsx("span",{className:"font-medium text-white",children:p.name||p.stackId}),jsx("p",{className:"text-xs text-zinc-500",children:p.domain})]}),jsx("span",{className:"text-xs text-zinc-600",children:"Previously connected"})]},p.stackId)),U.ready&&!U.known&&jsx("p",{className:"text-center text-xs text-zinc-600 mt-4",children:"Connect to a stack for the first time to get started."})]}),S==="select"&&P&&jsx("div",{className:"flex items-center justify-center py-8",children:jsx("div",{className:"h-6 w-6 border-2 border-zinc-600 border-t-white animate-spin",style:{borderRadius:"50%"}})}),w&&S==="error"&&jsxs("div",{className:"mb-4 border border-red-500/30 bg-red-500/10 p-4",children:[jsx("p",{className:"text-center text-red-400 text-sm",children:w}),jsx("button",{className:"mt-3 w-full text-sm text-zinc-400 hover:text-white",onClick:at,children:"Try Again"})]}),S==="success"&&jsxs("div",{className:"border border-green-500/30 bg-green-500/10 p-6 text-center",children:[jsx("p",{className:"font-medium text-green-400 text-sm",children:"Connected!"}),jsx("p",{className:"mt-1 text-xs text-zinc-400",children:"Redirecting..."})]}),S==="connecting"&&C&&jsxs("div",{style:{border:"1px solid #27272a",background:"#25252f",padding:24,textAlign:"center"},children:[jsxs("div",{style:{width:40,height:40,margin:"0 auto 12px"},children:[R==="phantom"&&jsx(me,{style:W}),R==="metamask"&&jsx(he,{style:W})]}),jsx("p",{style:{fontWeight:500,fontSize:14,color:"#fff"},children:k.connected?"Signing message...":"Connecting wallet..."}),jsx("p",{style:{marginTop:4,fontSize:12,color:"#71717a"},children:"Please confirm in your wallet"}),jsx("button",{style:{marginTop:16,fontSize:14,color:"#71717a",background:"none",border:"none",cursor:"pointer"},onClick:at,children:"Cancel"})]}),S==="select"&&!C&&!P&&jsxs(Fragment,{children:[st.map(p=>jsxs("button",{onClick:()=>it(p.id),style:q,children:[jsx(Ct,{provider:p.id}),jsx("span",{style:{fontWeight:500,color:"#fff"},children:St(p.id,p.name)})]},p.id)),ot.includes("phantom")&&jsxs("button",{onClick:Tt,disabled:!ue,style:{...q,opacity:ue?1:.5,cursor:ue?"pointer":"not-allowed"},children:[jsx(me,{style:{...W,borderRadius:8}}),jsx("span",{style:{flex:1,textAlign:"left",fontWeight:500,color:"#fff"},children:"Phantom"}),!ue&&jsx("span",{style:{fontSize:12,color:"#71717a"},children:"Not installed"})]}),ot.includes("metamask")&&At&&jsxs("button",{onClick:Lt,style:q,children:[jsx(he,{style:W}),jsx("span",{style:{flex:1,textAlign:"left",fontWeight:500,color:"#fff"},children:"MetaMask"})]}),rt&&!D&&jsxs("button",{onClick:()=>E(true),style:q,children:[jsx("div",{style:{...W,display:"flex",alignItems:"center",justifyContent:"center",borderRadius:8,border:"1px solid #3f3f46",background:"#2a2a3e"},children:jsx("svg",{xmlns:"http://www.w3.org/2000/svg",height:"20px",viewBox:"0 -960 960 960",width:"20px",fill:"#a1a1aa",children:jsx("path",{d:"M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h640q33 0 56.5 23.5T880-720v480q0 33-23.5 56.5T800-160H160Z"})})}),jsx("span",{style:{flex:1,textAlign:"left",fontWeight:500,color:"#fff"},children:a})]}),l&&!et&&jsxs("button",{onClick:()=>Ce(true),style:q,children:[jsx("div",{style:{...W,display:"flex",alignItems:"center",justifyContent:"center",borderRadius:8,border:"1px solid #3f3f46",background:"#2a2a3e"},children:jsx("svg",{xmlns:"http://www.w3.org/2000/svg",height:"20px",viewBox:"0 -960 960 960",width:"20px",fill:"#a1a1aa",children:jsx("path",{d:"M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm80-80h400v-40H280v40Zm0-120h400v-240H280v240Z"})})}),jsx("span",{style:{flex:1,textAlign:"left",fontWeight:500,color:"#fff"},children:h})]}),l&&et&&jsxs("div",{style:{borderRadius:12,border:"1px solid #27272a",background:"#25252f",padding:24},children:[jsx("p",{style:{textAlign:"center",fontSize:14,color:"#a1a1aa",marginBottom:16},children:"Enter your 6-digit preview code"}),jsx(ae,{onComplete:jt,disabled:Se==="verifying",error:vt}),Se==="verifying"&&jsx("p",{style:{textAlign:"center",fontSize:14,color:"#a1a1aa",marginTop:16},children:"Verifying..."}),Se==="success"&&jsx("p",{style:{textAlign:"center",fontSize:14,color:"#4ade80",marginTop:16},children:"Verified!"}),jsx("button",{onClick:()=>{Ce(false),K("idle"),de("");},style:{display:"block",marginTop:16,marginLeft:"auto",marginRight:"auto",fontSize:13,color:"#71717a",background:"none",border:"none",cursor:"pointer"},children:"Cancel"})]}),rt&&D&&jsxs("div",{style:{borderRadius:12,border:"1px solid #27272a",background:"#25252f",padding:24},children:[jsx("p",{style:{textAlign:"center",fontSize:14,color:"#a1a1aa",marginBottom:16},children:"Enter your 6-digit access code"}),jsx(ae,{onComplete:Ut,disabled:G==="verifying",error:Y}),G==="verifying"&&jsx("p",{style:{textAlign:"center",fontSize:14,color:"#a1a1aa",marginTop:16},children:"Verifying..."}),G==="success"&&jsx("p",{style:{textAlign:"center",fontSize:14,color:"#4ade80",marginTop:16},children:"Verified!"}),O?.webPageUrl&&G==="idle"&&(ne(O.webPageUrl)==="#"?null:jsx(Fragment,{}))]}),(o?ve:X).length>0&&(!o||ve.length>0)&&jsxs(Fragment,{children:[!o&&st.length===0&&jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,padding:"4px 0"},children:[jsx("div",{style:{flex:1,borderTop:"1px solid #27272a"}}),jsx("span",{style:{fontSize:12,color:"#52525b"},children:"or continue with"}),jsx("div",{style:{flex:1,borderTop:"1px solid #27272a"}})]}),(o?ve:X.filter(p=>!xe.has(p.id))).map(p=>jsxs("button",{onClick:()=>it(p.id),style:q,children:[jsx(Ct,{provider:p.id}),jsx("span",{style:{fontWeight:500,color:"#fff"},children:St(p.id,p.name)})]},p.id))]})]})]})}var W={width:40,height:40,flexShrink:0},q={display:"flex",width:"100%",alignItems:"center",gap:12,borderRadius:12,border:"1px solid #27272a",background:"#25252f",padding:16,cursor:"pointer",transition:"background 0.15s"};function Ct({provider:e}){switch(e){case "google":return jsx(Je,{style:{...W,borderRadius:8}});case "discord":return jsx(Qe,{style:{...W,borderRadius:8}});case "twitter":return jsx(Ve,{style:{...W,borderRadius:8}});case "apple":return jsx(Ze,{style:{...W,borderRadius:8}});default:return jsx("div",{style:{...W,display:"flex",alignItems:"center",justifyContent:"center",borderRadius:8,border:"1px solid #3f3f46",background:"#2a2a3e",fontSize:14,color:"#a1a1aa",fontFamily:"monospace"},children:e[0]?.toUpperCase()})}}function St(e,t){return {google:"Google",discord:"Discord",twitter:"Twitter",apple:"Apple"}[e]||t||e}function Dn({mid:e,apiBaseUrl:t="",scope:r,onSave:d,className:u}){let{profile:y,loading:m,saving:a,error:l,updateProfile:c}=_e(e,{apiBaseUrl:t,scope:r}),[h,o]=useState(null),[i,n]=useState(null),[g,s]=useState(null),k=useRef(null),[C,w]=useState(false),L=h??y?.username??"",I=i??y?.bio??"",v=g??y?.avatarUrl,$=useCallback(b=>{let T=b.target.files?.[0];if(!T)return;let O=new FileReader;O.onload=()=>{s(O.result),w(true);},O.readAsDataURL(T);},[]),U=async()=>{await c({username:L||void 0,avatarUrl:g??y?.avatarUrl,bio:I||void 0})&&(w(false),d?.());};if(m)return jsxs("div",{className:u,style:{display:"grid",gap:"1.5rem"},children:[jsx("div",{style:{height:40,background:"var(--x-color-neutral-800, #333)",animation:"pulse 2s infinite"}}),jsx("div",{style:{height:40,background:"var(--x-color-neutral-800, #333)",animation:"pulse 2s infinite"}})]});let z=r==="global"||!r?"Global profile":`Stack profile (${r.stackId})`;return jsxs("div",{className:u,style:{display:"grid",gap:"1.5rem"},children:[jsx("p",{style:{fontSize:11,color:"var(--x-color-neutral-500, #91918D)",textTransform:"uppercase",letterSpacing:"0.05em"},children:z}),jsxs("div",{style:{display:"grid",gap:"1.5rem",gridTemplateColumns:"1fr 1fr"},children:[jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"0.5rem"},children:[jsx("label",{style:{fontSize:14,color:"var(--x-color-neutral-400, #91918D)"},children:"Username"}),jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.75rem"},children:[jsx("button",{type:"button",onClick:()=>k.current?.click(),style:{width:40,height:40,flexShrink:0,cursor:"pointer",overflow:"hidden",background:"var(--x-color-neutral-800, #262625)",border:"none",position:"relative",display:"flex",alignItems:"center",justifyContent:"center"},children:v?jsx("img",{src:v,alt:"",style:{width:"100%",height:"100%",objectFit:"cover"}}):jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",style:{color:"var(--x-color-neutral-500, #91918D)"},children:[jsx("path",{d:"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"}),jsx("circle",{cx:"12",cy:"7",r:"4"})]})}),jsx("input",{type:"text",value:L,onChange:b=>{o(b.target.value),w(true);},placeholder:"Enter username",maxLength:30,style:{flex:1,padding:"0.75rem 1rem",fontSize:14,background:"var(--x-color-neutral-800, #262625)",color:"var(--x-color-neutral-100, #FAFAF7)",border:"none",outline:"none"}})]}),jsx("input",{ref:k,type:"file",accept:"image/*",onChange:$,style:{display:"none"}})]}),jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"0.5rem"},children:[jsx("label",{style:{fontSize:14,color:"var(--x-color-neutral-400, #91918D)"},children:"Bio"}),jsx("input",{type:"text",value:I,onChange:b=>{n(b.target.value),w(true);},placeholder:"Tell us about yourself",maxLength:200,style:{width:"100%",padding:"0.75rem 1rem",fontSize:14,background:"var(--x-color-neutral-800, #262625)",color:"var(--x-color-neutral-100, #FAFAF7)",border:"none",outline:"none"}})]})]}),l&&jsx("p",{style:{fontSize:13,color:"var(--x-color-red-500, #BF4D43)"},children:l}),C&&jsxs("div",{style:{display:"flex",gap:"0.5rem"},children:[jsx("button",{onClick:U,disabled:a,style:{padding:"0.5rem 1.25rem",fontSize:13,fontWeight:700,background:"var(--x-color-blue-600, #165DFC)",color:"#FFF",border:"none",cursor:a?"wait":"pointer",opacity:a?.6:1},children:a?"Saving...":"Save"}),jsx("button",{onClick:()=>{o(null),n(null),s(null),w(false);},style:{padding:"0.5rem 1.25rem",fontSize:13,background:"var(--x-color-neutral-800, #262625)",color:"var(--x-color-neutral-400, #91918D)",border:"none",cursor:"pointer"},children:"Cancel"}),jsx("p",{style:{fontSize:11,color:"var(--x-color-neutral-500, #666663)",alignSelf:"center",marginLeft:"0.5rem"},children:"Profile updates cost 10M tokens"})]})]})}function zn({className:e}){return jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",className:e||"h-5 w-5",children:[jsxs("linearGradient",{id:"sol-g",x1:"7.233",x2:"24.766",y1:"24.766",y2:"7.234",gradientUnits:"userSpaceOnUse",children:[jsx("stop",{offset:"0",stopColor:"#9945ff"}),jsx("stop",{offset:"0.2",stopColor:"#7962e7"}),jsx("stop",{offset:"1",stopColor:"#00d18c"})]}),jsx("path",{fill:"#10111a",d:"M0 0h32v32H0z"}),jsx("path",{fill:"url(#sol-g)",fillRule:"evenodd",d:"M9.873 20.41a.65.65 0 0 1 .476-.21l14.662.012a.323.323 0 0 1 .238.54l-3.123 3.438a.64.64 0 0 1-.475.21l-14.662-.012a.323.323 0 0 1-.238-.54zm15.376-2.862a.322.322 0 0 1-.238.54l-14.662.012a.64.64 0 0 1-.476-.21l-3.122-3.44a.323.323 0 0 1 .238-.54l14.662-.012a.64.64 0 0 1 .475.21zM9.873 7.81a.64.64 0 0 1 .476-.21l14.662.012a.322.322 0 0 1 .238.54l-3.123 3.438a.64.64 0 0 1-.475.21l-14.662-.012a.323.323 0 0 1-.238-.54z",clipRule:"evenodd"})]})}function En({className:e}){return jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",className:e||"h-5 w-5",children:[jsx("rect",{width:"20",height:"20",rx:"4",fill:"#627EEA",fillOpacity:"0.2"}),jsx("path",{fill:"#627EEA",d:"M10 3l-4 6.5 4 2.5 4-2.5L10 3z"}),jsx("path",{fill:"#627EEA",fillOpacity:"0.6",d:"M6 9.5L10 12l4-2.5L10 17 6 9.5z"})]})}function _n({className:e}){return jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512",className:e||"h-8 w-8",children:[jsx("rect",{width:"512",height:"512",rx:"15%",fill:"#37aee2"}),jsx("path",{fill:"#c8daea",d:"M199 404c-11 0-10-4-13-14l-32-105 245-144"}),jsx("path",{fill:"#a9c9dd",d:"M199 404c7 0 11-4 16-8l45-43-56-34"}),jsx("path",{fill:"#f6fbfe",d:"M204 319l135 99c14 9 26 4 30-14l55-258c5-22-9-32-24-25L79 245c-21 8-21 21-4 26l83 26 190-121c9-5 17-3 11 4"})]})}function Wn(e){let{apiBaseUrl:t,stacknetUrl:r="https://stacknet.magma-rpc.com",stackId:d="",transport:u,serviceKey:y,onAuthSuccess:m,onAuthError:a,onLogout:l}=e;async function c(o){if(!o.ok){let s=await o.json().catch(()=>({})),k=new Error(s.error||`Authentication failed (${o.status})`);throw a?.(k),k}let i=await o.json(),n=i.token||i.jwt,g=i.session||{userId:i.user?.id||i.userId||i.sub||"",address:i.user?.address||i.address,chain:i.user?.chain||i.chain,expiresAt:i.expiresAt||Date.now()+10080*60*1e3,authMethod:i.authMethod||i.method};return n&&await u.storeCredentials(n,g),m?.(g),g}return {async login(o,i){let n=await fetch(`${t}/api/auth/callback/credentials`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:o,password:i})});return c(n)},async loginWeb3({chain:o,address:i,message:n,signature:g}){let s={chain:o,message:n,signature:g,stackId:d};o==="solana"&&(s.publicKey=i);let k=await fetch(`${t}/api/auth/callback`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(s)});return c(k)},async loginOTP(o){let i=await fetch(`${t}/api/auth/otp`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:o})});return c(i)},async getSession(){let o=await u.getStoredSession();if(o&&o.expiresAt>Date.now())return o;try{let i=await u.getHeaders(),n=await fetch(`${t}/api/auth/session`,{headers:i});if(n.ok){let g=await n.json();if(g.session)return g.session}}catch{if(o)return o}return null},async checkSession(){let o=await u.getToken();if(!o)return false;try{let i=await fetch(`${t}/api/history?limit=1`,{headers:{Authorization:`Bearer ${o}`}});return i.ok?!0:i.status===401?(await u.clear(),!1):!0}catch{return true}},async getChallenge(o,i){let g=`${r}/api/v2/stacks/${encodeURIComponent(d)}/auth/web3/challenge`,s=await fetch(g,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chain:o,address:i})});if(!s.ok)throw new Error("Failed to get challenge");let k=await s.json();return k.data||k},async logout(){try{let o=await u.getHeaders();await fetch(`${t}/api/auth/logout`,{method:"POST",headers:o});}catch{}await u.clear(),l?.();},async getHeaders(){let o=await u.getHeaders();return Object.keys(o).length>0?o:y?{Authorization:`Bearer ${y}`}:{}},async getToken(){return u.getToken()}}}function Fn(){return {async storeCredentials(e,t){},async getToken(){return null},async getHeaders(){return {}},async getStoredSession(){let e=oe();return !e||e.expiresAt<=Date.now()?null:{userId:e.userId,address:e.address,chain:e.chain,expiresAt:e.expiresAt,planId:e.planId,authMethod:e.authMethod}},async clear(){}}}var qe="stackauth_token",Xe="stackauth_session";function Bn(e){return {async storeCredentials(t,r){await e.setItemAsync(qe,t),await e.setItemAsync(Xe,JSON.stringify(r));},async getToken(){try{return await e.getItemAsync(qe)}catch{return null}},async getHeaders(){let t=await this.getToken();return t?{Authorization:`Bearer ${t}`}:{}},async getStoredSession(){try{let t=await e.getItemAsync(Xe);return t?JSON.parse(t):null}catch{return null}},async clear(){await e.deleteItemAsync(qe).catch(()=>{}),await e.deleteItemAsync(Xe).catch(()=>{});}}}
|
|
2
|
-
export{
|
|
1
|
+
import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {createContext,useState,useCallback,useEffect,useRef,useContext,useMemo}from'react';import {jsx,jsxs,Fragment}from'react/jsx-runtime';function Ht(...e){return twMerge(clsx(e))}function Gt(e){return e>=1e12?`${(e/1e12).toFixed(e%1e12===0?0:1)}T`:e>=1e9?`${(e/1e9).toFixed(e%1e9===0?0:1)}B`:e>=1e6?`${(e/1e6).toFixed(e%1e6===0?0:1)}M`:e>=1e3?`${(e/1e3).toFixed(0)}K`:e.toLocaleString()}function Jt(e,t){if(!e)return "/";if(e.startsWith("/")&&!e.startsWith("//"))return e;try{let r=new URL(e,t);return r.origin!==t?"/":r.pathname+r.search+r.hash}catch{return "/"}}function oe(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 d=new URL(r);if(d.protocol==="http:"||d.protocol==="https:")return d.toString()}catch{}return t}function Qt(e){try{let t=e.split(".");if(t.length!==3)return null;let r=atob(t[1].replace(/-/g,"+").replace(/_/g,"/"));return JSON.parse(r)}catch{return null}}function re(){if(typeof document>"u")return null;try{let e=document.cookie.split(";").map(r=>r.trim()).find(r=>r.startsWith("stackauth_session="));if(!e)return null;let t=e.slice(18);return JSON.parse(atob(t.replace(/-/g,"+").replace(/_/g,"/")))}catch{return null}}function Q(e="__csrf"){if(typeof document>"u")return null;let t=document.cookie.split(";").map(r=>r.trim()).find(r=>r.startsWith(`${e}=`));return t?t.slice(e.length+1):null}function se(){let[e,t]=useState(null),[r,d]=useState(true),u=useCallback(()=>{let a=re();a&&a.expiresAt>Date.now()?t({userId:a.userId,address:a.address,chain:a.chain,expiresAt:a.expiresAt,planId:a.planId,authMethod:a.authMethod}):t(null),d(false);},[]);useEffect(()=>{u();},[u]);let h=useCallback(async(a="")=>{try{let s=await fetch(`${a}/api/auth/session`);if(s.ok){let c=await s.json();if(c.session)return t(c.session),c.session}return t(null),null}catch{return null}},[]),y=!!e&&e.expiresAt>Date.now();return {session:e,loading:r,isAuthenticated:y,refresh:h,readSession:u}}function Ae(e="__csrf",t="x-csrf-token"){let[r,d]=useState(null);useEffect(()=>{d(Q(e));},[e]);let u=r?{[t]:r}:{};return {token:r,headers:u}}function Ne(){let[e,t]=useState({connected:false,address:null,chain:null,provider:null}),[r,d]=useState(null),u=useCallback(async(s="phantom")=>{d(null);try{let c=typeof window<"u"?window:null,g=s==="phantom"?c?.phantom?.solana||c?.solana:c?.solflare;if(!g)return d(`${s} wallet not found`),null;let l=(await g.connect()).publicKey.toString();return t({connected:!0,address:l,chain:"solana",provider:s}),l}catch(c){return d(c.message||"Failed to connect wallet"),null}},[]),h=useCallback(async()=>{d(null);try{let c=(typeof window<"u"?window:null)?.ethereum;if(!c)return d("MetaMask not found"),null;let g=c;c.providers?.length&&(g=c.providers.find(n=>n.isMetaMask)||c);let l=(await g.request({method:"eth_requestAccounts"}))[0];return l?(t({connected:!0,address:l,chain:"ethereum",provider:"metamask"}),l):(d("No account selected"),null)}catch(s){return d(s.message||"Failed to connect wallet"),null}},[]),y=useCallback(async(s,c)=>{d(null);let g=c?.chain||e.chain,o=c?.provider||e.provider,l=c?.address||e.address;try{if(g==="solana"){let n=typeof window<"u"?window:null,m=o==="solflare"?n?.solflare:n?.phantom?.solana||n?.solana;if(!m)throw new Error("Wallet not available");let i=new TextEncoder().encode(s),w=await m.signMessage(i,"utf8"),S=new Uint8Array(w.signature||w),b="";for(let L=0;L<S.byteLength;L++)b+=String.fromCharCode(S[L]);return btoa(b)}if(g==="ethereum"){let m=(typeof window<"u"?window:null)?.ethereum;if(m?.providers?.length&&(m=m.providers.find(w=>w.isMetaMask)||m),!m)throw new Error("MetaMask not available");return await m.request({method:"personal_sign",params:[s,l]})}throw new Error("No wallet connected")}catch(n){return d(n.message||"Signing failed"),null}},[e]),a=useCallback(()=>{t({connected:false,address:null,chain:null,provider:null}),d(null);},[]);return {wallet:e,error:r,connectSolana:u,connectEVM:h,signMessage:y,disconnect:a}}var Xt="https://stacknet.magma-rpc.com/auth/bridge",me="stacknet-auth-bridge";function Te(e){let t=e?.bridgeUrl||Xt,r=e?.disabled||false,d=useRef(null),[u,h]=useState({ready:false,known:false,identity:null,identityCount:0,resolvedStackId:null}),y=useRef([]),a=useRef(false),s=useCallback(n=>{let m={...n,protocol:me};a.current&&d.current?.contentWindow?d.current.contentWindow.postMessage(m,new URL(t).origin):y.current.push(m);},[t]);useEffect(()=>{if(r)return;let n=i=>{if(!(!i.data||i.data.protocol!==me)){try{if(i.origin!==new URL(t).origin)return}catch{return}switch(i.data.type){case "bridge:ready":a.current=true,h(w=>({...w,ready:true}));for(let w of y.current)d.current?.contentWindow?.postMessage(w,i.origin);y.current=[],d.current?.contentWindow?.postMessage({protocol:me,type:"auth:check"},i.origin),d.current?.contentWindow?.postMessage({protocol:me,type:"auth:resolve-stack"},i.origin);break;case "auth:status":h(w=>({...w,known:i.data.known,identity:i.data.identity,identityCount:i.data.identityCount||0}));break;case "auth:resolved-stack":h(w=>({...w,resolvedStackId:i.data.stackId||null}));break;}}};window.addEventListener("message",n);let m=document.createElement("iframe");return m.src=t,m.style.display="none",m.setAttribute("aria-hidden","true"),m.setAttribute("tabindex","-1"),m.setAttribute("sandbox","allow-scripts allow-same-origin"),document.body.appendChild(m),d.current=m,()=>{window.removeEventListener("message",n),m.parentNode&&m.parentNode.removeChild(m),d.current=null,a.current=false;}},[t,r]);let c=useCallback(n=>{s({type:"auth:connected",...n});},[s]),g=useCallback(n=>{s({type:"auth:disconnected",...n});},[s]),o=useCallback(()=>{s({type:"auth:clear"}),h({ready:u.ready,known:false,identity:null,identityCount:0,resolvedStackId:null});},[s,u.ready]),l=useCallback(()=>{s({type:"auth:check"});},[s]);return {...u,reportConnected:c,reportDisconnected:g,clearAll:o,refresh:l}}async function yt(e,t,r,d){let u=e.apiVersion||"v2",h=`${e.baseUrl}/api/${u}${r}`;try{let y=await fetch(h,{method:t,headers:{"Content-Type":"application/json"},body:d?JSON.stringify(d):void 0}),a=await y.json();return y.ok?a.success&&a.data!==void 0?{success:!0,data:a.data}:{success:!0,data:a}:{success:!1,error:a.error||{code:"UNKNOWN_ERROR",message:"Unknown error"}}}catch(y){return {success:false,error:{code:"NETWORK_ERROR",message:y instanceof Error?y.message:"Network error"}}}}function Le(e){return {getNetworkStatus:()=>yt(e,"GET","/network/status"),getWeb3Challenge:(t,r)=>yt(e,"POST",`/stacks/${encodeURIComponent(e.stackId)}/auth/web3/challenge`,{chain:t,address:r})}}function Oe(e={apiBaseUrl:""}){let{wallet:t,connectSolana:r,connectEVM:d,signMessage:u,disconnect:h}=Ne(),{session:y,isAuthenticated:a,refresh:s,readSession:c}=se(),{headers:g}=Ae(),o=Te({disabled:typeof window>"u"}),[l,n]=useState(false),[m,i]=useState(null),[w,S]=useState(false),b=e.apiBaseUrl||"",L=e.stacknetUrl||"https://stacknet.magma-rpc.com",I=e.stackId||o.resolvedStackId||"",v=Le({baseUrl:L,stackId:I}),F=useCallback(async(P,C,A,$)=>{n(true),i(null);try{let N=C;if(!N){let X=await A();if(!X)return n(!1),!1;N=X;}let R=await v.getWeb3Challenge(P,N);if(!R.success||!R.data)return i("Failed to get challenge"),n(!1),!1;let E=await u(R.data.message,{chain:P,provider:$,address:N});if(!E)return n(!1),!1;let J={chain:P,message:R.data.message,signature:E,stackId:I};P==="solana"&&(J.publicKey=N);let W=await fetch(`${b}/api/auth/callback`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify(J)});if(!W.ok){let X=await W.json().catch(()=>({}));return i(X.error||"Authentication failed"),n(!1),!1}return o.reportConnected({address:N,chain:P,method:$||(P==="solana"?"phantom":"metamask"),stackId:I}),c(),n(!1),!0}catch(N){return i(N.message||"Authentication failed"),n(false),false}},[b,v,u,c,o,I]),U=useCallback(async(P="phantom")=>{let C=await r(P);return C?F("solana",C,()=>r(P),P):false},[r,F]),z=useCallback(async()=>{let P=await d();return P?F("ethereum",P,d,"metamask"):false},[d,F]),k=useCallback(async P=>{n(true),i(null);try{let C=await fetch(`${b}/api/auth/otp`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({code:P})});if(!C.ok){let A=await C.json().catch(()=>({}));return i(A.error||"Invalid code"),n(!1),!1}return c(),n(!1),!0}catch(C){return i(C.message||"OTP verification failed"),n(false),false}},[b,c]),T=useCallback(async(P,C)=>{n(true),i(null);try{let A=C||`${window.location.origin}/api/auth/oauth/callback`,$=new URLSearchParams({provider:P,redirectUri:A,stackId:I}),N=await fetch(`${b}/api/auth/oauth/start?${$}`,{credentials:"include"});if(!N.ok){let E=await N.json().catch(()=>({}));return i(E.error||"Failed to start OAuth flow"),n(!1),!1}let R=await N.json();if(R.redirect_url){let E;try{E=new URL(R.redirect_url);}catch{return i("Invalid OAuth redirect URL"),n(!1),!1}let J=[/(^|\.)accounts\.google\.com$/,/(^|\.)discord\.com$/,/(^|\.)github\.com$/,/(^|\.)x\.com$/,/(^|\.)twitter\.com$/,/(^|\.)apple\.com$/];return E.protocol!=="https:"||!J.some(W=>W.test(E.hostname))?(i(`Refusing to redirect to non-OAuth host: ${E.hostname}`),n(!1),!1):(typeof sessionStorage<"u"&&(sessionStorage.setItem("oauth_state",R.state||""),sessionStorage.setItem("oauth_provider",P)),window.location.href=E.toString(),!0)}return i("No redirect URL returned"),n(!1),!1}catch(A){return i(A.message||"OAuth flow failed"),n(false),false}},[b,I]),O=useCallback(async(P,C,A)=>{n(true),i(null);try{if(typeof sessionStorage<"u"){let N=sessionStorage.getItem("oauth_state"),R=sessionStorage.getItem("oauth_provider");if(sessionStorage.removeItem("oauth_state"),sessionStorage.removeItem("oauth_provider"),!N||N!==A)return i("OAuth state mismatch \u2014 refusing to complete login"),n(!1),!1;if(R&&R!==P)return i("OAuth provider mismatch \u2014 refusing to complete login"),n(!1),!1}let $=await fetch(`${b}/api/auth/oauth/callback`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({provider:P,code:C,state:A,stackId:I})});if(!$.ok){let N=await $.json().catch(()=>({}));return i(N.error||"OAuth authentication failed"),n(!1),!1}return c(),n(!1),!0}catch($){return i($.message||"OAuth callback failed"),n(false),false}},[b,I,c]),G=useCallback(async()=>{t.address&&t.chain&&o.reportDisconnected({address:t.address,chain:t.chain,stackId:I});try{await fetch(`${b}/api/auth/logout`,{method:"POST",headers:g,credentials:"include"});}catch{}h(),c();},[b,g,h,c,t,o,I]);return useEffect(()=>{if(!e.autoConnect||w||a||!o.ready||!o.known||!o.identity)return;S(true);let{chain:P,method:C}=o.identity;P==="solana"&&(C==="phantom"||C==="solflare")?U(C):P==="ethereum"&&z();},[e.autoConnect,w,a,o,U,z]),{session:y,isAuthenticated:a,wallet:t,loading:l,error:m,authenticateSolana:U,authenticateEVM:z,authenticateOTP:k,authenticateOAuth:T,authenticateOAuthCallback:O,logout:G,refresh:()=>s(b),stackId:I,bridge:{ready:o.ready,known:o.known,identity:o.identity,identityCount:o.identityCount,resolvedStackId:o.resolvedStackId}}}function ae(e,t="https://stacknet.magma-rpc.com"){let[r,d]=useState(null),[u,h]=useState(false),[y,a]=useState(null),s=useCallback(async g=>{h(true),a(null);try{let o=await fetch(`${t}/api/v2/stacks/${g}`);if(!o.ok)return a("Stack not found"),h(!1),null;let l=await o.json(),n=l.data?.stack||l.stack||l,m={id:n.id,name:n.name,displayName:n.displayName||n.name,description:n.description,logoUrl:n.logoUrl,webPageUrl:n.webPageUrl,allowedChains:n.allowedChains||[],features:n.features,stripeProvider:n.stripeProvider,oauthProviders:n.oauthProviders?.map(i=>({provider:i.provider,clientId:i.clientId,enabled:i.enabled!==!1}))};return d(m),h(!1),m}catch(o){return a(o.message),h(false),null}},[t]);useEffect(()=>{e&&s(e);},[e,s]);let c=r?on(r):[];return {config:r,loading:u,error:y,identityProviders:c,fetchConfig:s}}function on(e){let t=[];if(e.features?.web3Auth!==false&&(e.allowedChains.includes("solana")&&(t.push({type:"wallet",id:"phantom",name:"Phantom",chain:"solana"}),t.push({type:"wallet",id:"solflare",name:"Solflare",chain:"solana"})),(e.allowedChains.includes("ethereum")||e.allowedChains.includes("polygon")||e.allowedChains.includes("base"))&&t.push({type:"wallet",id:"metamask",name:"MetaMask",chain:"ethereum"})),e.features?.apiKeyAuth!==false&&t.push({type:"otp",id:"otp",name:"Access Code"}),e.features?.oauthAuth&&e.oauthProviders)for(let r of e.oauthProviders)r.enabled&&t.push({type:"oauth",id:r.provider,name:r.provider});return t}function an(e=""){let[t,r]=useState([]),[d,u]=useState(true),[h,y]=useState(null),a=useCallback(async()=>{try{let s=await fetch(`${e}/api/billing/plans`);if(s.ok){let c=await s.json();r(c.plans||c||[]);}}catch(s){y(s.message);}finally{u(false);}},[e]);return useEffect(()=>{a();},[a]),{plans:t,loading:d,error:h,refresh:a}}function cn(e=""){let[t,r]=useState(null),[d,u]=useState(true),[h,y]=useState(null),a=useCallback(async()=>{try{let g=await fetch(`${e}/api/billing/subscription`);if(g.ok){let o=await g.json();r(o.plan?o:null);}}catch(g){y(g.message);}finally{u(false);}},[e]);useEffect(()=>{a();},[a]);let s=useCallback(async g=>{let o=Q(),n=await(await fetch(`${e}/api/billing/subscribe`,{method:"POST",headers:{"Content-Type":"application/json",...o?{"x-csrf-token":o}:{}},body:JSON.stringify({planId:g})})).json();return n.url||n.checkoutUrl||null},[e]),c=useCallback(async()=>{let g=Q();return (await fetch(`${e}/api/billing/cancel`,{method:"POST",headers:g?{"x-csrf-token":g}:{}})).ok?(await a(),true):false},[e,a]);return {subscription:t,loading:d,error:h,refresh:a,subscribe:s,cancel:c}}function fn(e=""){let[t,r]=useState(null),[d,u]=useState(true),[h,y]=useState(null),a=useCallback(async()=>{try{let s=await fetch(`${e}/api/billing/usage`);if(s.ok){let c=await s.json();r(c);}}catch(s){y(s.message);}finally{u(false);}},[e]);return useEffect(()=>{a();},[a]),{usage:t,loading:d,error:h,refresh:a}}function pn(e=""){let[t,r]=useState(false),[d,u]=useState(null),h=useCallback(async a=>{r(true),u(null);try{let s=Q(),c=await fetch(`${e}/api/billing/prepaid`,{method:"POST",headers:{"Content-Type":"application/json",...s?{"x-csrf-token":s}:{}},body:JSON.stringify({amountCents:a})}),g=await c.json();return c.ok?g.url||null:(u(g.error||"Purchase failed"),null)}catch(s){return u(s.message),null}finally{r(false);}},[e]),y=useCallback(async a=>{r(true),u(null);try{let s=Q(),c=await fetch(`${e}/api/billing/verify-prepaid`,{method:"POST",headers:{"Content-Type":"application/json",...s?{"x-csrf-token":s}:{}},body:JSON.stringify({sessionId:a})}),g=await c.json();return c.ok?g:(u(g.error||"Verification failed"),null)}catch(s){return u(s.message),null}finally{r(false);}},[e]);return {purchase:h,verifySession:y,loading:t,error:d}}function yn(e="",t){let[r,d]=useState([]),[u,h]=useState(true),[y,a]=useState(null),s=t?.limit||50,c=t?.offset||0,g=useCallback(async()=>{try{let o=await fetch(`${e}/api/billing/history?limit=${s}&offset=${c}`);if(o.ok){let l=await o.json();d(l.records||l.history||(Array.isArray(l)?l:[]));}}catch(o){a(o.message);}finally{h(false);}},[e,s,c]);return useEffect(()=>{g();},[g]),{records:r,loading:u,error:y,refresh:g}}function wn(){if(typeof document>"u")return null;let e=document.cookie.split(";").map(t=>t.trim()).find(t=>t.startsWith("__csrf="));return e?e.slice(7):null}function We(e,t){let[r,d]=useState(null),[u,h]=useState(true),[y,a]=useState(false),[s,c]=useState(null),g=t?.apiBaseUrl??"",o=t?.scope===void 0||t?.scope==="global"?"global":`stack:${t.scope.stackId}`,l=useCallback(i=>{let w=encodeURIComponent(i);if(o==="global")return `${g}/api/user/profile/${w}`;let S=o.slice(6);return `${g}/api/v2/stacks/${encodeURIComponent(S)}/members/${w}/profile`},[g,o]),n=useCallback(async()=>{if(!e){d(null),h(false);return}h(true),c(null);try{let i=await fetch(l(e));if(i.ok){let w=await i.json(),S=w.profile||w.data?.profile||w;d({mid:S.mid||e,username:S.username||"",avatarUrl:S.avatar_url||S.avatarUrl,bio:S.bio,paymentAddress:S.payment_address||S.paymentAddress,createdAt:S.created_at||S.createdAt,updatedAt:S.updated_at||S.updatedAt});}else if(i.status===404)d({mid:e,username:""});else throw new Error(`${i.status}`)}catch(i){c(i instanceof Error?i.message:"Failed to load profile");}finally{h(false);}},[e,l]);useEffect(()=>{n();},[n]);let m=useCallback(async i=>{if(!e)return false;a(true),c(null);try{let w=wn(),S={};i.username!==void 0&&(S.username=i.username),i.avatarUrl!==void 0&&(S.avatar_url=i.avatarUrl),i.bio!==void 0&&(S.bio=i.bio),i.paymentAddress!==void 0&&(S.payment_address=i.paymentAddress);let b=await fetch(l(e),{method:"PUT",headers:{"Content-Type":"application/json",...w?{"x-csrf-token":w}:{}},credentials:"same-origin",body:JSON.stringify(S)});if(!b.ok){let v=await b.json().catch(()=>({}));throw new Error(v.error||v.message||`Update failed: ${b.status}`)}let L=await b.json(),I=L.profile||L.data?.profile||L;return d(v=>({mid:v?.mid||e,username:i.username??v?.username??"",avatarUrl:i.avatarUrl??v?.avatarUrl,bio:i.bio??v?.bio,paymentAddress:i.paymentAddress??I.payment_address??I.paymentAddress??v?.paymentAddress,createdAt:v?.createdAt,updatedAt:I.updated_at||I.updatedAt||Date.now()})),!0}catch(w){return c(w instanceof Error?w.message:"Update failed"),false}finally{a(false);}},[e,l]);return {profile:r,loading:u,saving:y,error:s,updateProfile:m,refresh:n}}var bt="google-identity-services",kn="https://accounts.google.com/gsi/client";function bn({stackId:e,stacknetUrl:t="https://stacknet.magma-rpc.com",apiBaseUrl:r="",autoPrompt:d=true,cancelOnTapOutside:u=true,onSuccess:h,onError:y,disabled:a=false}){let{config:s}=ae(e,t),{isAuthenticated:c,loading:g,readSession:o}=se(),[l,n]=useState(false),[m,i]=useState(null),[w,S]=useState(false),b=useRef(false),L=useRef(false),v=s?.oauthProviders?.find(k=>k.provider==="google"&&k.enabled&&k.clientId)?.clientId||null;useEffect(()=>{if(a||!v||typeof window>"u")return;if(document.getElementById(bt)){S(true);return}let k=document.createElement("script");k.id=bt,k.src=kn,k.async=true,k.defer=true,k.onload=()=>S(true),k.onerror=()=>{i("Failed to load Google sign-in"),y?.("Failed to load Google Identity Services script");},document.head.appendChild(k);},[a,v,y]);let F=useCallback(async k=>{n(true),i(null);try{let T=await fetch(`${r}/api/auth/google/one-tap`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({credential:k.credential,stackId:e})});if(!T.ok){let G=(await T.json().catch(()=>({}))).error||"Google sign-in failed";i(G),y?.(G),n(!1);return}o(),n(!1),h?.();}catch(T){let O=T.message||"Google sign-in failed";i(O),y?.(O),n(false);}},[r,e,o,h,y]);useEffect(()=>{if(a){console.debug("[GoogleOneTap] Disabled");return}if(!w){console.debug("[GoogleOneTap] Script not loaded yet, clientId:",v);return}if(!v){console.debug("[GoogleOneTap] No Google clientId from stack config");return}if(g){console.debug("[GoogleOneTap] Session still loading");return}if(c){console.debug("[GoogleOneTap] User already authenticated, skipping");return}if(!window.google?.accounts?.id){console.debug("[GoogleOneTap] GIS library not available on window");return}b.current||(console.debug("[GoogleOneTap] Initializing with clientId:",v),b.current=true,window.google.accounts.id.initialize({client_id:v,callback:F,auto_select:true,cancel_on_tap_outside:u}),d&&!L.current&&(L.current=true,console.debug("[GoogleOneTap] Showing prompt..."),window.google.accounts.id.prompt(k=>{k.isDisplayed?.()&&console.debug("[GoogleOneTap] Prompt displayed"),k.isNotDisplayed?.()&&console.debug("[GoogleOneTap] Not displayed:",k.getNotDisplayedReason?.()),k.isSkippedMoment?.()&&console.debug("[GoogleOneTap] Skipped:",k.getSkippedReason?.()),k.isDismissedMoment?.()&&console.debug("[GoogleOneTap] Dismissed:",k.getDismissedReason?.());})));},[a,w,v,g,c,F,d,u]),useEffect(()=>()=>{window.google?.accounts?.id&&b.current&&window.google.accounts.id.cancel();},[]);let U=useCallback(()=>{!window.google?.accounts?.id||!b.current||window.google.accounts.id.prompt();},[]),z=useCallback((k,T)=>{!k||!window.google?.accounts?.id||!b.current||window.google.accounts.id.renderButton(k,{theme:T?.theme||"filled_black",size:T?.size||"large",text:T?.text||"signin_with",width:T?.width});},[]);return {available:!!v,ready:w&&!!v,loading:l,error:m,prompt:U,renderButton:z,clientId:v}}var Cn="/api";function xn(e,t){return `${(t||(typeof window<"u"?window.location.origin:"")).replace(/\/$/,"")}/?ref=${encodeURIComponent(e)}`}function vn(e={}){let{shareBaseUrl:t,autoMint:r=true}=e,[d,u]=useState(null),[h,y]=useState(true),[a,s]=useState(null),c=useCallback(async()=>{y(true),s(null);try{let l=r?"POST":"GET",n=await fetch(`${Cn}/social/join-code`,{method:l,credentials:"include"});if(!n.ok){u(null),n.status===401?s("not_authenticated"):s(`HTTP ${n.status}`);return}let m=await n.json();u(m?.code??null);}catch(l){s(l?.message||"network_error"),u(null);}finally{y(false);}},[r]);useEffect(()=>{c();},[c]);let g=d?xn(d,t):null,o=useCallback(async()=>{if(!g)return false;try{if(typeof navigator<"u"&&navigator.clipboard?.writeText)return await navigator.clipboard.writeText(g),!0}catch{}return false},[g]);return {code:d,shareUrl:g,loading:h,error:a,refresh:c,copyShareLink:o}}var Ct=createContext(null);function An(){let e=useContext(Ct);if(!e)throw new Error("useUserUtilsContext must be used within <UserUtilsProvider>");return e}function Nn({config:e,callbacks:t,children:r}){return jsx(Ct.Provider,{value:{config:e,callbacks:t},children:r})}function le({length:e=6,onComplete:t,disabled:r=false,error:d,className:u="",inputClassName:h=""}){let [y,a]=useState(Array(e).fill("")),s=useCallback((o,l)=>{if(l.length>1){let m=l.replace(/\D/g,"").slice(0,e).split(""),i=[...y];m.forEach((S,b)=>{o+b<e&&(i[o+b]=S);}),a(i);let w=Math.min(o+m.length,e-1);document.getElementById(`userutils-otp-${w}`)?.focus(),i.every(S=>S!=="")&&setTimeout(()=>t(i.join("")),100);return}if(!/^\d?$/.test(l))return;let n=[...y];n[o]=l,a(n),l&&o<e-1&&document.getElementById(`userutils-otp-${o+1}`)?.focus(),l&&o===e-1&&n.every(m=>m!=="")&&setTimeout(()=>t(n.join("")),100);},[y,e,t]),c=useCallback((o,l)=>{if(l.key==="Backspace"&&!y[o]&&o>0){document.getElementById(`userutils-otp-${o-1}`)?.focus();let n=[...y];n[o-1]="",a(n);}if(l.key==="Enter"){let n=y.join("");n.length===e&&t(n);}},[y,e,t]);useCallback(()=>{a(Array(e).fill("")),document.getElementById("userutils-otp-0")?.focus();},[e]);return jsxs("div",{className:u,children:[jsx("div",{className:"flex gap-2 justify-center",children:y.map((o,l)=>jsx("input",{id:`userutils-otp-${l}`,type:"text",inputMode:"numeric",maxLength:e,value:o,onChange:n=>s(l,n.target.value),onKeyDown:n=>c(l,n),disabled:r,autoFocus:l===0,className:`w-12 h-14 text-center text-xl font-mono bg-secondary border border-primary/10 text-foreground focus:outline-none focus:border-primary/30 disabled:opacity-50 ${h}`},l))}),d&&jsx("p",{className:"text-center text-sm text-red-400 mt-2",children:d})]})}le.displayName="OTPInput";var Un="stacknet:rl";function Ve(){return typeof window<"u"&&typeof window.localStorage<"u"}var ce=new Map;function xt(e){if(!Ve())return ce.get(e)??null;try{let t=window.localStorage.getItem(e);if(!t)return null;let r=JSON.parse(t);return typeof r?.count=="number"&&typeof r?.windowStart=="number"?{count:r.count,windowStart:r.windowStart}:null}catch{return null}}function On(e,t){if(!Ve()){ce.set(e,t);return}try{window.localStorage.setItem(e,JSON.stringify(t));}catch{ce.set(e,t);}}function jn(e){if(!Ve()){ce.delete(e);return}try{window.localStorage.removeItem(e);}catch{ce.delete(e);}}function Dn(e,t){return `${e}:${t}`}function he(e,t){let r=t.storagePrefix||Un,d=Dn(r,e);return {peek:()=>{let a=Date.now(),s=xt(d);if(!s||a-s.windowStart>=t.windowMs)return {allowed:true,remaining:t.maxAttempts,retryAfterSecs:0};let c=Math.max(0,t.maxAttempts-s.count);return c>0?{allowed:true,remaining:c,retryAfterSecs:0}:{allowed:false,remaining:0,retryAfterSecs:Math.max(1,Math.ceil((s.windowStart+t.windowMs-a)/1e3))}},consume:()=>{let a=Date.now(),s=xt(d);return (!s||a-s.windowStart>=t.windowMs)&&(s={count:0,windowStart:a}),s.count>=t.maxAttempts?{allowed:false,remaining:0,retryAfterSecs:Math.max(1,Math.ceil((s.windowStart+t.windowMs-a)/1e3))}:(s.count+=1,On(d,s),{allowed:true,remaining:Math.max(0,t.maxAttempts-s.count),retryAfterSecs:0})},reset:()=>jn(d)}}var Rn="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTA4IiBoZWlnaHQ9IjEwOCIgdmlld0JveD0iMCAwIDEwOCAxMDgiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIxMDgiIGhlaWdodD0iMTA4IiByeD0iMjYiIGZpbGw9IiNBQjlGRjIiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00Ni41MjY3IDY5LjkyMjlDNDIuMDA1NCA3Ni44NTA5IDM0LjQyOTIgODUuNjE4MiAyNC4zNDggODUuNjE4MkMxOS41ODI0IDg1LjYxODIgMTUgODMuNjU2MyAxNSA3NS4xMzQyQzE1IDUzLjQzMDUgNDQuNjMyNiAxOS44MzI3IDcyLjEyNjggMTkuODMyN0M4Ny43NjggMTkuODMyNyA5NCAzMC42ODQ2IDk0IDQzLjAwNzlDOTQgNTguODI1OCA4My43MzU1IDc2LjkxMjIgNzMuNTMyMSA3Ni45MTIyQzcwLjI5MzkgNzYuOTEyMiA2OC43MDUzIDc1LjEzNDIgNjguNzA1MyA3Mi4zMTRDNjguNzA1MyA3MS41NzgzIDY4LjgyNzUgNzAuNzgxMiA2OS4wNzE5IDY5LjkyMjlDNjUuNTg5MyA3NS44Njk5IDU4Ljg2ODUgODEuMzg3OCA1Mi41NzU0IDgxLjM4NzhDNDcuOTkzIDgxLjM4NzggNDUuNjcxMyA3OC41MDYzIDQ1LjY3MTMgNzQuNDU5OEM0NS42NzEzIDcyLjk4ODQgNDUuOTc2OCA3MS40NTU2IDQ2LjUyNjcgNjkuOTIyOVpNODMuNjc2MSA0Mi41Nzk0QzgzLjY3NjEgNDYuMTcwNCA4MS41NTc1IDQ3Ljk2NTggNzkuMTg3NSA0Ny45NjU4Qzc2Ljc4MTYgNDcuOTY1OCA3NC42OTg5IDQ2LjE3MDQgNzQuNjk4OSA0Mi41Nzk0Qzc0LjY5ODkgMzguOTg4NSA3Ni43ODE2IDM3LjE5MzEgNzkuMTg3NSAzNy4xOTMxQzgxLjU1NzUgMzcuMTkzMSA4My42NzYxIDM4Ljk4ODUgODMuNjc2MSA0Mi41Nzk0Wk03MC4yMTAzIDQyLjU3OTVDNzAuMjEwMyA0Ni4xNzA0IDY4LjA5MTYgNDcuOTY1OCA2NS43MjE2IDQ3Ljk2NThDNjMuMzE1NyA0Ny45NjU4IDYxLjIzMyA0Ni4xNzA0IDYxLjIzMyA0Mi41Nzk1QzYxLjIzMyAzOC45ODg1IDYzLjMxNTcgMzcuMTkzMSA2NS43MjE2IDM3LjE5MzFDNjguMDkxNiAzNy4xOTMxIDcwLjIxMDMgMzguOTg4NSA3MC4yMTAzIDQyLjU3OTVaIiBmaWxsPSIjRkZGREY4Ii8+Cjwvc3ZnPgo=";function we({className:e,style:t}){return jsx("img",{src:Rn,alt:"Phantom",className:e,style:t})}function ke({className:e,style:t}){return jsxs("svg",{className:e,style:t,xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 507.83 470.86",children:[jsx("polygon",{fill:"#e2761b",stroke:"#e2761b",strokeLinecap:"round",strokeLinejoin:"round",points:"482.09 0.5 284.32 147.38 320.9 60.72 482.09 0.5"}),jsx("polygon",{fill:"#e4761b",stroke:"#e4761b",strokeLinecap:"round",strokeLinejoin:"round",points:"25.54 0.5 221.72 148.77 186.93 60.72 25.54 0.5"}),jsx("polygon",{fill:"#e4761b",stroke:"#e4761b",strokeLinecap:"round",strokeLinejoin:"round",points:"410.93 340.97 358.26 421.67 470.96 452.67 503.36 342.76 410.93 340.97"}),jsx("polygon",{fill:"#e4761b",stroke:"#e4761b",strokeLinecap:"round",strokeLinejoin:"round",points:"4.67 342.76 36.87 452.67 149.57 421.67 96.9 340.97 4.67 342.76"}),jsx("polygon",{fill:"#e4761b",stroke:"#e4761b",strokeLinecap:"round",strokeLinejoin:"round",points:"143.21 204.62 111.8 252.13 223.7 257.1 219.73 136.85 143.21 204.62"}),jsx("polygon",{fill:"#e4761b",stroke:"#e4761b",strokeLinecap:"round",strokeLinejoin:"round",points:"364.42 204.62 286.91 135.46 284.32 257.1 396.03 252.13 364.42 204.62"}),jsx("polygon",{fill:"#e4761b",stroke:"#e4761b",strokeLinecap:"round",strokeLinejoin:"round",points:"149.57 421.67 216.75 388.87 158.71 343.55 149.57 421.67"}),jsx("polygon",{fill:"#e4761b",stroke:"#e4761b",strokeLinecap:"round",strokeLinejoin:"round",points:"290.88 388.87 358.26 421.67 348.92 343.55 290.88 388.87"}),jsx("polygon",{fill:"#d7c1b3",stroke:"#d7c1b3",strokeLinecap:"round",strokeLinejoin:"round",points:"358.26 421.67 290.88 388.87 296.25 432.8 295.65 451.28 358.26 421.67"}),jsx("polygon",{fill:"#d7c1b3",stroke:"#d7c1b3",strokeLinecap:"round",strokeLinejoin:"round",points:"149.57 421.67 212.18 451.28 211.78 432.8 216.75 388.87 149.57 421.67"}),jsx("polygon",{fill:"#233447",stroke:"#233447",strokeLinecap:"round",strokeLinejoin:"round",points:"213.17 314.54 157.12 298.04 196.67 279.95 213.17 314.54"}),jsx("polygon",{fill:"#233447",stroke:"#233447",strokeLinecap:"round",strokeLinejoin:"round",points:"294.46 314.54 310.96 279.95 350.71 298.04 294.46 314.54"}),jsx("polygon",{fill:"#cd6116",stroke:"#cd6116",strokeLinecap:"round",strokeLinejoin:"round",points:"149.57 421.67 159.11 340.97 96.9 342.76 149.57 421.67"}),jsx("polygon",{fill:"#cd6116",stroke:"#cd6116",strokeLinecap:"round",strokeLinejoin:"round",points:"348.72 340.97 358.26 421.67 410.93 342.76 348.72 340.97"}),jsx("polygon",{fill:"#cd6116",stroke:"#cd6116",strokeLinecap:"round",strokeLinejoin:"round",points:"396.03 252.13 284.32 257.1 294.66 314.54 311.16 279.95 350.91 298.04 396.03 252.13"}),jsx("polygon",{fill:"#cd6116",stroke:"#cd6116",strokeLinecap:"round",strokeLinejoin:"round",points:"157.12 298.04 196.87 279.95 213.17 314.54 223.7 257.1 111.8 252.13 157.12 298.04"}),jsx("polygon",{fill:"#e4751f",stroke:"#e4751f",strokeLinecap:"round",strokeLinejoin:"round",points:"111.8 252.13 158.71 343.55 157.12 298.04 111.8 252.13"}),jsx("polygon",{fill:"#e4751f",stroke:"#e4751f",strokeLinecap:"round",strokeLinejoin:"round",points:"350.91 298.04 348.92 343.55 396.03 252.13 350.91 298.04"}),jsx("polygon",{fill:"#e4751f",stroke:"#e4751f",strokeLinecap:"round",strokeLinejoin:"round",points:"223.7 257.1 213.17 314.54 226.29 382.31 229.27 293.07 223.7 257.1"}),jsx("polygon",{fill:"#e4751f",stroke:"#e4751f",strokeLinecap:"round",strokeLinejoin:"round",points:"284.32 257.1 278.96 292.87 281.34 382.31 294.66 314.54 284.32 257.1"}),jsx("polygon",{fill:"#f6851b",stroke:"#f6851b",strokeLinecap:"round",strokeLinejoin:"round",points:"294.66 314.54 281.34 382.31 290.88 388.87 348.92 343.55 350.91 298.04 294.66 314.54"}),jsx("polygon",{fill:"#f6851b",stroke:"#f6851b",strokeLinecap:"round",strokeLinejoin:"round",points:"157.12 298.04 158.71 343.55 216.75 388.87 226.29 382.31 213.17 314.54 157.12 298.04"}),jsx("polygon",{fill:"#c0ad9e",stroke:"#c0ad9e",strokeLinecap:"round",strokeLinejoin:"round",points:"295.65 451.28 296.25 432.8 291.28 428.42 216.35 428.42 211.78 432.8 212.18 451.28 149.57 421.67 171.43 439.55 215.75 470.36 291.88 470.36 336.4 439.55 358.26 421.67 295.65 451.28"}),jsx("polygon",{fill:"#161616",stroke:"#161616",strokeLinecap:"round",strokeLinejoin:"round",points:"290.88 388.87 281.34 382.31 226.29 382.31 216.75 388.87 211.78 432.8 216.35 428.42 291.28 428.42 296.25 432.8 290.88 388.87"}),jsx("polygon",{fill:"#763d16",stroke:"#763d16",strokeLinecap:"round",strokeLinejoin:"round",points:"490.44 156.92 507.33 75.83 482.09 0.5 290.88 142.41 364.42 204.62 468.37 235.03 491.43 208.2 481.49 201.05 497.39 186.54 485.07 177 500.97 164.87 490.44 156.92"}),jsx("polygon",{fill:"#763d16",stroke:"#763d16",strokeLinecap:"round",strokeLinejoin:"round",points:"0.5 75.83 17.39 156.92 6.66 164.87 22.56 177 10.44 186.54 26.34 201.05 16.4 208.2 39.26 235.03 143.21 204.62 216.75 142.41 25.54 0.5 0.5 75.83"}),jsx("polygon",{fill:"#f6851b",stroke:"#f6851b",strokeLinecap:"round",strokeLinejoin:"round",points:"468.37 235.03 364.42 204.62 396.03 252.13 348.92 343.55 410.93 342.76 503.36 342.76 468.37 235.03"}),jsx("polygon",{fill:"#f6851b",stroke:"#f6851b",strokeLinecap:"round",strokeLinejoin:"round",points:"143.21 204.62 39.26 235.03 4.67 342.76 96.9 342.76 158.71 343.55 111.8 252.13 143.21 204.62"}),jsx("polygon",{fill:"#f6851b",stroke:"#f6851b",strokeLinecap:"round",strokeLinejoin:"round",points:"284.32 257.1 290.88 142.41 321.1 60.72 186.93 60.72 216.75 142.41 223.7 257.1 226.09 293.27 226.29 382.31 281.34 382.31 281.74 293.27 284.32 257.1"})]})}function Ze({className:e,style:t}){return jsxs("svg",{className:e,style:t,viewBox:"0 0 33 32",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{x:"0.5",width:"32",height:"32",rx:"4",fill:"#F1F2F9"}),jsx("path",{d:"M26.1001 16.2273C26.1001 15.5182 26.0365 14.8364 25.9183 14.1818H16.5001V18.05H21.8819C21.6501 19.3 20.9456 20.3591 19.8865 21.0682V23.5773H23.1183C25.0092 21.8364 26.1001 19.2727 26.1001 16.2273Z",fill:"#4285F4"}),jsx("path",{d:"M16.5001 26C19.2001 26 21.4637 25.1046 23.1182 23.5773L19.8864 21.0682C18.991 21.6682 17.8455 22.0227 16.5001 22.0227C13.8955 22.0227 11.691 20.2637 10.9046 17.9H7.56372V20.4909C9.20917 23.7591 12.591 26 16.5001 26Z",fill:"#34A853"}),jsx("path",{d:"M10.9047 17.8999C10.7047 17.2999 10.591 16.659 10.591 15.9999C10.591 15.3408 10.7047 14.6999 10.9047 14.0999V11.509H7.56376C6.86376 12.9025 6.49951 14.4405 6.50012 15.9999C6.50012 17.6136 6.88649 19.1408 7.56376 20.4908L10.9047 17.8999Z",fill:"#FBBC05"}),jsx("path",{d:"M16.5001 9.97726C17.9682 9.97726 19.2864 10.4818 20.3228 11.4727L23.191 8.60454C21.4591 6.99091 19.1955 6 16.5001 6C12.591 6 9.20917 8.2409 7.56372 11.5091L10.9046 14.1C11.691 11.7364 13.8955 9.97726 16.5001 9.97726Z",fill:"#EA4335"})]})}function Ye({className:e,style:t}){return jsxs("svg",{className:e,style:t,viewBox:"0 0 33 32",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{x:"0.5",width:"32",height:"32",rx:"4",fill:"#5462EB"}),jsx("path",{d:"M23.5433 8.87438C22.2479 8.26174 20.8587 7.81038 19.4063 7.55187C19.3799 7.54688 19.3534 7.55934 19.3398 7.58428C19.1612 7.91179 18.9633 8.33905 18.8247 8.67487C17.2625 8.43382 15.7084 8.43382 14.1782 8.67487C14.0396 8.33158 13.8345 7.91179 13.6551 7.58428C13.6414 7.56018 13.615 7.54771 13.5886 7.55187C12.1369 7.80955 10.7478 8.26092 9.45159 8.87438C9.44037 8.87937 9.43075 8.88769 9.42437 8.89849C6.78947 12.9558 6.06766 16.9134 6.42176 20.8219C6.42336 20.841 6.43378 20.8593 6.4482 20.871C8.18663 22.1868 9.87059 22.9857 11.5233 23.5152C11.5497 23.5235 11.5778 23.5135 11.5946 23.491C11.9855 22.9408 12.334 22.3606 12.6328 21.7504C12.6505 21.7147 12.6336 21.6723 12.5976 21.6581C12.0448 21.442 11.5185 21.1785 11.0122 20.8793C10.9721 20.8552 10.9689 20.7961 11.0058 20.7679C11.1123 20.6856 11.2189 20.6 11.3206 20.5135C11.339 20.4977 11.3647 20.4944 11.3863 20.5044C14.7125 22.0696 18.3136 22.0696 21.6006 20.5044C21.6222 20.4936 21.6479 20.4969 21.6671 20.5127C21.7688 20.5991 21.8754 20.6856 21.9827 20.7679C22.0196 20.7961 22.0172 20.8552 21.9771 20.8793C21.4708 21.1843 20.9445 21.442 20.3909 21.6573C20.3548 21.6715 20.3388 21.7147 20.3564 21.7504C20.6617 22.3597 21.0101 22.9399 21.3939 23.4902C21.4099 23.5135 21.4387 23.5235 21.4652 23.5152C23.1259 22.9857 24.8099 22.1868 26.5483 20.871C26.5635 20.8593 26.5731 20.8419 26.5747 20.8228C26.9985 16.3041 25.8649 12.3789 23.5697 8.89931C23.5641 8.88769 23.5545 8.87937 23.5433 8.87438Z",fill:"#F7F7F7"})]})}function Ke({className:e,style:t}){return jsxs("svg",{className:e,style:t,viewBox:"0 0 33 32",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{x:"0.5",width:"32",height:"32",rx:"4",fill:"black"}),jsx("path",{d:"M8.53901 8L14.7164 16.2153L8.5 22.8947H9.89907L15.3415 17.0468L19.7389 22.8947H24.5L17.975 14.2173L23.7612 8H22.3621L17.3499 13.3858L13.3001 8H8.53901ZM10.5964 9.02501H12.7837L22.4422 21.8695H20.255L10.5964 9.02501Z",fill:"#F7F7F7"})]})}function qe({className:e,style:t}){return jsxs("svg",{className:e,style:t,viewBox:"0 0 33 32",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[jsx("rect",{x:"0.5",width:"32",height:"32",rx:"4",fill:"#000000"}),jsx("path",{d:"M21.3611 16.7384C21.3807 18.9244 23.2792 19.6519 23.3001 19.661C23.2841 19.7124 22.9971 20.6962 22.3005 21.7115C21.6987 22.5892 21.0742 23.4636 20.0904 23.4816C19.1237 23.4994 18.8127 22.9098 17.7076 22.9098C16.6029 22.9098 16.2574 23.4636 15.3423 23.4994C14.3928 23.5352 13.6694 22.5504 13.0626 21.676C11.8226 19.8879 10.8747 16.6229 12.1471 14.4182C12.7791 13.3234 13.9087 12.6304 15.1346 12.6126C16.0668 12.5948 16.9468 13.2378 17.5167 13.2378C18.0865 13.2378 19.1555 12.4647 20.2795 12.579C20.7501 12.5986 22.0715 12.7692 22.9207 14.0122C22.852 14.0549 21.3453 14.9328 21.3611 16.7384ZM19.5432 11.392C20.0472 10.7809 20.3862 9.93 20.2939 9.08325C19.5709 9.11221 18.6961 9.56574 18.1749 10.1763C17.708 10.717 17.2995 11.582 17.4096 12.4111C18.2158 12.4736 19.0391 12.003 19.5432 11.392Z",fill:"#FFFFFF"})]})}function Fn({config:e,onSuccess:t,title:r="Log in or Sign up",showWallets:d,showOTP:u,hideHeader:h,onOTPSubmit:y,otpLabel:a="Access Code",showPreviewCode:s=false,onPreviewCodeSubmit:c,previewCodeLabel:g="Preview Code",oauthInline:o,oauthFirst:l,className:n=""}){let m=Oe(e),{isAuthenticated:i,wallet:w,loading:S,error:b,authenticateSolana:L,authenticateEVM:I,authenticateOTP:v,authenticateOAuth:F,bridge:U,stackId:z}=m,k=!e.stackId&&!z,T=e.stacknetUrl||"https://stacknet.magma-rpc.com",{config:O,identityProviders:G,loading:P}=ae(z||e.stackId||null,T),[C,A]=useState(k?"stack-select":"select"),[$,N]=useState(null),[R,E]=useState(false),[J,W]=useState("idle"),[X,fe]=useState(""),[ot,xe]=useState(false),[ve,V]=useState("idle"),[Lt,te]=useState(""),[rt,Ut]=useState([]),[Ot,st]=useState(e.stackId||null),it=useMemo(()=>he("otp",{maxAttempts:3,windowMs:5*6e4}),[]),at=useMemo(()=>he("preview-code",{maxAttempts:3,windowMs:6e4}),[]),[pe,jt]=useState(false),[Dt,Rt]=useState(false);useEffect(()=>{if(typeof window>"u")return;let f=()=>{let Z=window;jt(!!(Z.phantom?.solana?.isPhantom||Z.solana?.isPhantom));let K=Z.ethereum;Rt(!!(K?.isMetaMask||K?.providers?.some(_=>_.isMetaMask)));};f(),window.addEventListener("ethereum#initialized",f);let j=setTimeout(f,500);return ()=>{window.removeEventListener("ethereum#initialized",f),clearTimeout(j);}},[]),useEffect(()=>{C==="stack-select"&&z&&(st(z),A("select"));},[C,z]),useEffect(()=>{if(!(!U.ready||!k)&&U.identity){let f=[];U.resolvedStackId&&f.push({stackId:U.resolvedStackId,domain:typeof window<"u"?window.location.origin:""}),Promise.all(f.map(async j=>{try{let Z=await fetch(`${T}/api/v2/stacks/${j.stackId}`);if(Z.ok){let K=await Z.json(),_=K.data?.stack||K;j.name=_.displayName||_.name,j.logoUrl=_.logoUrl;}}catch{}return j})).then(Ut);}},[U.ready,U.identity,U.resolvedStackId,k,T]),useEffect(()=>{i&&C==="success"&&t?.();},[i,C,t]);let lt=d||(G.length>0?G.filter(f=>f.type==="wallet").map(f=>f.id):["phantom","metamask"]),ct=u!==void 0?u:G.length>0?G.some(f=>f.type==="otp"):true,ne=G.filter(f=>f.type==="oauth"),Pe=new Set(l||[]),dt=ne.filter(f=>Pe.has(f.id)),Ie=o?ne.filter(f=>!Pe.has(f.id)):ne,ut=async f=>{N(f),A("connecting"),await F(f)||A("error");},zt=async()=>{N("phantom"),A("connecting");let f=await L("phantom");A(f?"success":"error");},Et=async()=>{N("metamask"),A("connecting");let f=await I();A(f?"success":"error");},_t=async f=>{let j=it.consume();if(!j.allowed){W("error"),fe(`Too many attempts. Try again in ${j.retryAfterSecs}s.`),setTimeout(()=>W("idle"),3e3);return}if(W("verifying"),fe(""),await(y||v)(f))it.reset(),W("success"),A("success");else {W("error");let _=j.remaining;fe(_>0?`Invalid or expired code. ${_} attempt${_===1?"":"s"} left.`:"Invalid or expired code."),setTimeout(()=>W("idle"),2e3);}},$t=async f=>{if(!/^\d{6}$/.test(f))return false;try{return (await fetch("/api/auth/preview-code",{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({code:f})})).ok?(typeof window<"u"&&window.localStorage&&window.localStorage.setItem("stacknet-api-key",`pc_${f}`),!0):!1}catch{return false}},Wt=async f=>{let j=at.consume();if(!j.allowed){V("error"),te(`Too many attempts. Try again in ${j.retryAfterSecs}s.`),setTimeout(()=>V("idle"),3e3);return}if(V("verifying"),te(""),await(c||$t)(f))at.reset(),V("success"),A("success"),t?.();else {V("error");let _=j.remaining;te(_>0?`Invalid or expired preview code. ${_} attempt${_===1?"":"s"} left.`:"Invalid or expired preview code."),setTimeout(()=>V("idle"),2e3);}},ft=()=>{A(k&&!Ot?"stack-select":"select"),N(null),E(false),W("idle"),fe(""),xe(false),V("idle"),te("");};return jsxs("div",{className:`w-full max-w-md space-y-3 ${n}`,children:[!h&&jsxs("div",{className:"mb-6 text-center",children:[O?.logoUrl&&C!=="stack-select"&&jsx("img",{src:oe(O.logoUrl),alt:O.displayName||"",className:"h-16 w-16 mx-auto mb-4 rounded-xl"}),O?.displayName&&jsx("p",{className:"text-sm text-zinc-400 mb-2",children:O.displayName}),jsx("h1",{className:"font-semibold text-2xl text-white",children:"Log in or Sign up"})]}),C==="stack-select"&&jsxs("div",{className:"space-y-3",children:[jsx("p",{className:"text-center text-sm text-zinc-400 mb-4",children:rt.length>0?"Select a network to continue":"No previous connections found. Enter a Stack ID to continue."}),rt.map(f=>jsxs("button",{onClick:()=>{st(f.stackId),A("select");},className:"flex w-full cursor-pointer items-center gap-4 rounded-xl border border-zinc-800 bg-[#25252f] p-4 transition-colors hover:bg-[#2d2d3a]",children:[f.logoUrl?jsx("img",{src:oe(f.logoUrl),alt:"",className:"h-10 w-10 flex-shrink-0"}):jsx("div",{className:"h-10 w-10 flex-shrink-0 bg-zinc-700 flex items-center justify-center text-zinc-400 text-sm font-mono",children:f.name?.[0]?.toUpperCase()||"S"}),jsxs("div",{className:"flex-1 text-left",children:[jsx("span",{className:"font-medium text-white",children:f.name||f.stackId}),jsx("p",{className:"text-xs text-zinc-500",children:f.domain})]}),jsx("span",{className:"text-xs text-zinc-600",children:"Previously connected"})]},f.stackId)),U.ready&&!U.known&&jsx("p",{className:"text-center text-xs text-zinc-600 mt-4",children:"Connect to a stack for the first time to get started."})]}),C==="select"&&P&&jsx("div",{className:"flex items-center justify-center py-8",children:jsx("div",{className:"h-6 w-6 border-2 border-zinc-600 border-t-white animate-spin",style:{borderRadius:"50%"}})}),b&&C==="error"&&jsxs("div",{className:"mb-4 border border-red-500/30 bg-red-500/10 p-4",children:[jsx("p",{className:"text-center text-red-400 text-sm",children:b}),jsx("button",{className:"mt-3 w-full text-sm text-zinc-400 hover:text-white",onClick:ft,children:"Try Again"})]}),C==="success"&&jsxs("div",{className:"border border-green-500/30 bg-green-500/10 p-6 text-center",children:[jsx("p",{className:"font-medium text-green-400 text-sm",children:"Connected!"}),jsx("p",{className:"mt-1 text-xs text-zinc-400",children:"Redirecting..."})]}),C==="connecting"&&S&&jsxs("div",{style:{border:"1px solid #27272a",background:"#25252f",padding:24,textAlign:"center"},children:[jsxs("div",{style:{width:40,height:40,margin:"0 auto 12px"},children:[$==="phantom"&&jsx(we,{style:H}),$==="metamask"&&jsx(ke,{style:H})]}),jsx("p",{style:{fontWeight:500,fontSize:14,color:"#fff"},children:w.connected?"Signing message...":"Connecting wallet..."}),jsx("p",{style:{marginTop:4,fontSize:12,color:"#71717a"},children:"Please confirm in your wallet"}),jsx("button",{style:{marginTop:16,fontSize:14,color:"#71717a",background:"none",border:"none",cursor:"pointer"},onClick:ft,children:"Cancel"})]}),C==="select"&&!S&&!P&&jsxs(Fragment,{children:[dt.map(f=>jsxs("button",{onClick:()=>ut(f.id),style:ee,children:[jsx(Nt,{provider:f.id}),jsx("span",{style:{fontWeight:500,color:"#fff"},children:Mt(f.id,f.name)})]},f.id)),lt.includes("phantom")&&jsxs("button",{onClick:zt,disabled:!pe,style:{...ee,opacity:pe?1:.5,cursor:pe?"pointer":"not-allowed"},children:[jsx(we,{style:{...H,borderRadius:8}}),jsx("span",{style:{flex:1,textAlign:"left",fontWeight:500,color:"#fff"},children:"Phantom"}),!pe&&jsx("span",{style:{fontSize:12,color:"#71717a"},children:"Not installed"})]}),lt.includes("metamask")&&Dt&&jsxs("button",{onClick:Et,style:ee,children:[jsx(ke,{style:H}),jsx("span",{style:{flex:1,textAlign:"left",fontWeight:500,color:"#fff"},children:"MetaMask"})]}),ct&&!R&&jsxs("button",{onClick:()=>E(true),style:ee,children:[jsx("div",{style:{...H,display:"flex",alignItems:"center",justifyContent:"center",borderRadius:8,border:"1px solid #3f3f46",background:"#2a2a3e"},children:jsx("svg",{xmlns:"http://www.w3.org/2000/svg",height:"20px",viewBox:"0 -960 960 960",width:"20px",fill:"#a1a1aa",children:jsx("path",{d:"M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h640q33 0 56.5 23.5T880-720v480q0 33-23.5 56.5T800-160H160Z"})})}),jsx("span",{style:{flex:1,textAlign:"left",fontWeight:500,color:"#fff"},children:a})]}),s&&!ot&&jsxs("button",{onClick:()=>xe(true),style:ee,children:[jsx("div",{style:{...H,display:"flex",alignItems:"center",justifyContent:"center",borderRadius:8,border:"1px solid #3f3f46",background:"#2a2a3e"},children:jsx("svg",{xmlns:"http://www.w3.org/2000/svg",height:"20px",viewBox:"0 -960 960 960",width:"20px",fill:"#a1a1aa",children:jsx("path",{d:"M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h560q33 0 56.5 23.5T840-760v560q0 33-23.5 56.5T760-120H200Zm0-80h560v-560H200v560Zm80-80h400v-40H280v40Zm0-120h400v-240H280v240Z"})})}),jsx("span",{style:{flex:1,textAlign:"left",fontWeight:500,color:"#fff"},children:g})]}),s&&ot&&jsxs("div",{style:{borderRadius:12,border:"1px solid #27272a",background:"#25252f",padding:24},children:[jsx("p",{style:{textAlign:"center",fontSize:14,color:"#a1a1aa",marginBottom:16},children:"Enter your 6-digit preview code"}),jsx(le,{onComplete:Wt,disabled:ve==="verifying",error:Lt}),ve==="verifying"&&jsx("p",{style:{textAlign:"center",fontSize:14,color:"#a1a1aa",marginTop:16},children:"Verifying..."}),ve==="success"&&jsx("p",{style:{textAlign:"center",fontSize:14,color:"#4ade80",marginTop:16},children:"Verified!"}),jsx("button",{onClick:()=>{xe(false),V("idle"),te("");},style:{display:"block",marginTop:16,marginLeft:"auto",marginRight:"auto",fontSize:13,color:"#71717a",background:"none",border:"none",cursor:"pointer"},children:"Cancel"})]}),ct&&R&&jsxs("div",{style:{borderRadius:12,border:"1px solid #27272a",background:"#25252f",padding:24},children:[jsx("p",{style:{textAlign:"center",fontSize:14,color:"#a1a1aa",marginBottom:16},children:"Enter your 6-digit access code"}),jsx(le,{onComplete:_t,disabled:J==="verifying",error:X}),J==="verifying"&&jsx("p",{style:{textAlign:"center",fontSize:14,color:"#a1a1aa",marginTop:16},children:"Verifying..."}),J==="success"&&jsx("p",{style:{textAlign:"center",fontSize:14,color:"#4ade80",marginTop:16},children:"Verified!"}),O?.webPageUrl&&J==="idle"&&(oe(O.webPageUrl)==="#"?null:jsx(Fragment,{}))]}),(o?Ie:ne).length>0&&(!o||Ie.length>0)&&jsxs(Fragment,{children:[!o&&dt.length===0&&jsxs("div",{style:{display:"flex",alignItems:"center",gap:12,padding:"4px 0"},children:[jsx("div",{style:{flex:1,borderTop:"1px solid #27272a"}}),jsx("span",{style:{fontSize:12,color:"#52525b"},children:"or continue with"}),jsx("div",{style:{flex:1,borderTop:"1px solid #27272a"}})]}),(o?Ie:ne.filter(f=>!Pe.has(f.id))).map(f=>jsxs("button",{onClick:()=>ut(f.id),style:ee,children:[jsx(Nt,{provider:f.id}),jsx("span",{style:{fontWeight:500,color:"#fff"},children:Mt(f.id,f.name)})]},f.id))]})]})]})}var H={width:40,height:40,flexShrink:0},ee={display:"flex",width:"100%",alignItems:"center",gap:12,borderRadius:12,border:"1px solid #27272a",background:"#25252f",padding:16,cursor:"pointer",transition:"background 0.15s"};function Nt({provider:e}){switch(e){case "google":return jsx(Ze,{style:{...H,borderRadius:8}});case "discord":return jsx(Ye,{style:{...H,borderRadius:8}});case "twitter":return jsx(Ke,{style:{...H,borderRadius:8}});case "apple":return jsx(qe,{style:{...H,borderRadius:8}});default:return jsx("div",{style:{...H,display:"flex",alignItems:"center",justifyContent:"center",borderRadius:8,border:"1px solid #3f3f46",background:"#2a2a3e",fontSize:14,color:"#a1a1aa",fontFamily:"monospace"},children:e[0]?.toUpperCase()})}}function Mt(e,t){return {google:"Google",discord:"Discord",twitter:"Twitter",apple:"Apple"}[e]||t||e}function Jn({mid:e,apiBaseUrl:t="",scope:r,onSave:d,className:u}){let{profile:h,loading:y,saving:a,error:s,updateProfile:c}=We(e,{apiBaseUrl:t,scope:r}),[g,o]=useState(null),[l,n]=useState(null),[m,i]=useState(null),w=useRef(null),[S,b]=useState(false),L=g??h?.username??"",I=l??h?.bio??"",v=m??h?.avatarUrl,F=useCallback(k=>{let T=k.target.files?.[0];if(!T)return;let O=new FileReader;O.onload=()=>{i(O.result),b(true);},O.readAsDataURL(T);},[]),U=async()=>{await c({username:L||void 0,avatarUrl:m??h?.avatarUrl,bio:I||void 0})&&(b(false),d?.());};if(y)return jsxs("div",{className:u,style:{display:"grid",gap:"1.5rem"},children:[jsx("div",{style:{height:40,background:"var(--x-color-neutral-800, #333)",animation:"pulse 2s infinite"}}),jsx("div",{style:{height:40,background:"var(--x-color-neutral-800, #333)",animation:"pulse 2s infinite"}})]});let z=r==="global"||!r?"Global profile":`Stack profile (${r.stackId})`;return jsxs("div",{className:u,style:{display:"grid",gap:"1.5rem"},children:[jsx("p",{style:{fontSize:11,color:"var(--x-color-neutral-500, #91918D)",textTransform:"uppercase",letterSpacing:"0.05em"},children:z}),jsxs("div",{style:{display:"grid",gap:"1.5rem",gridTemplateColumns:"1fr 1fr"},children:[jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"0.5rem"},children:[jsx("label",{style:{fontSize:14,color:"var(--x-color-neutral-400, #91918D)"},children:"Username"}),jsxs("div",{style:{display:"flex",alignItems:"center",gap:"0.75rem"},children:[jsx("button",{type:"button",onClick:()=>w.current?.click(),style:{width:40,height:40,flexShrink:0,cursor:"pointer",overflow:"hidden",background:"var(--x-color-neutral-800, #262625)",border:"none",position:"relative",display:"flex",alignItems:"center",justifyContent:"center"},children:v?jsx("img",{src:v,alt:"",style:{width:"100%",height:"100%",objectFit:"cover"}}):jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",style:{color:"var(--x-color-neutral-500, #91918D)"},children:[jsx("path",{d:"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"}),jsx("circle",{cx:"12",cy:"7",r:"4"})]})}),jsx("input",{type:"text",value:L,onChange:k=>{o(k.target.value),b(true);},placeholder:"Enter username",maxLength:30,style:{flex:1,padding:"0.75rem 1rem",fontSize:14,background:"var(--x-color-neutral-800, #262625)",color:"var(--x-color-neutral-100, #FAFAF7)",border:"none",outline:"none"}})]}),jsx("input",{ref:w,type:"file",accept:"image/*",onChange:F,style:{display:"none"}})]}),jsxs("div",{style:{display:"flex",flexDirection:"column",gap:"0.5rem"},children:[jsx("label",{style:{fontSize:14,color:"var(--x-color-neutral-400, #91918D)"},children:"Bio"}),jsx("input",{type:"text",value:I,onChange:k=>{n(k.target.value),b(true);},placeholder:"Tell us about yourself",maxLength:200,style:{width:"100%",padding:"0.75rem 1rem",fontSize:14,background:"var(--x-color-neutral-800, #262625)",color:"var(--x-color-neutral-100, #FAFAF7)",border:"none",outline:"none"}})]})]}),s&&jsx("p",{style:{fontSize:13,color:"var(--x-color-red-500, #BF4D43)"},children:s}),S&&jsxs("div",{style:{display:"flex",gap:"0.5rem"},children:[jsx("button",{onClick:U,disabled:a,style:{padding:"0.5rem 1.25rem",fontSize:13,fontWeight:700,background:"var(--x-color-blue-600, #165DFC)",color:"#FFF",border:"none",cursor:a?"wait":"pointer",opacity:a?.6:1},children:a?"Saving...":"Save"}),jsx("button",{onClick:()=>{o(null),n(null),i(null),b(false);},style:{padding:"0.5rem 1.25rem",fontSize:13,background:"var(--x-color-neutral-800, #262625)",color:"var(--x-color-neutral-400, #91918D)",border:"none",cursor:"pointer"},children:"Cancel"}),jsx("p",{style:{fontSize:11,color:"var(--x-color-neutral-500, #666663)",alignSelf:"center",marginLeft:"0.5rem"},children:"Profile updates cost 10M tokens"})]})]})}function Qn({className:e}){return jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",className:e||"h-5 w-5",children:[jsxs("linearGradient",{id:"sol-g",x1:"7.233",x2:"24.766",y1:"24.766",y2:"7.234",gradientUnits:"userSpaceOnUse",children:[jsx("stop",{offset:"0",stopColor:"#9945ff"}),jsx("stop",{offset:"0.2",stopColor:"#7962e7"}),jsx("stop",{offset:"1",stopColor:"#00d18c"})]}),jsx("path",{fill:"#10111a",d:"M0 0h32v32H0z"}),jsx("path",{fill:"url(#sol-g)",fillRule:"evenodd",d:"M9.873 20.41a.65.65 0 0 1 .476-.21l14.662.012a.323.323 0 0 1 .238.54l-3.123 3.438a.64.64 0 0 1-.475.21l-14.662-.012a.323.323 0 0 1-.238-.54zm15.376-2.862a.322.322 0 0 1-.238.54l-14.662.012a.64.64 0 0 1-.476-.21l-3.122-3.44a.323.323 0 0 1 .238-.54l14.662-.012a.64.64 0 0 1 .475.21zM9.873 7.81a.64.64 0 0 1 .476-.21l14.662.012a.322.322 0 0 1 .238.54l-3.123 3.438a.64.64 0 0 1-.475.21l-14.662-.012a.323.323 0 0 1-.238-.54z",clipRule:"evenodd"})]})}function Vn({className:e}){return jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 20 20",className:e||"h-5 w-5",children:[jsx("rect",{width:"20",height:"20",rx:"4",fill:"#627EEA",fillOpacity:"0.2"}),jsx("path",{fill:"#627EEA",d:"M10 3l-4 6.5 4 2.5 4-2.5L10 3z"}),jsx("path",{fill:"#627EEA",fillOpacity:"0.6",d:"M6 9.5L10 12l4-2.5L10 17 6 9.5z"})]})}function Yn({className:e}){return jsxs("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 512 512",className:e||"h-8 w-8",children:[jsx("rect",{width:"512",height:"512",rx:"15%",fill:"#37aee2"}),jsx("path",{fill:"#c8daea",d:"M199 404c-11 0-10-4-13-14l-32-105 245-144"}),jsx("path",{fill:"#a9c9dd",d:"M199 404c7 0 11-4 16-8l45-43-56-34"}),jsx("path",{fill:"#f6fbfe",d:"M204 319l135 99c14 9 26 4 30-14l55-258c5-22-9-32-24-25L79 245c-21 8-21 21-4 26l83 26 190-121c9-5 17-3 11 4"})]})}function qn(e){let{apiBaseUrl:t,stacknetUrl:r="https://stacknet.magma-rpc.com",stackId:d="",transport:u,serviceKey:h,onAuthSuccess:y,onAuthError:a,onLogout:s}=e;async function c(o){if(!o.ok){let i=await o.json().catch(()=>({})),w=new Error(i.error||`Authentication failed (${o.status})`);throw a?.(w),w}let l=await o.json(),n=l.token||l.jwt,m=l.session||{userId:l.user?.id||l.userId||l.sub||"",address:l.user?.address||l.address,chain:l.user?.chain||l.chain,expiresAt:l.expiresAt||Date.now()+10080*60*1e3,authMethod:l.authMethod||l.method};return n&&await u.storeCredentials(n,m),y?.(m),m}return {async login(o,l){let n=await fetch(`${t}/api/auth/callback/credentials`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:o,password:l})});return c(n)},async loginWeb3({chain:o,address:l,message:n,signature:m}){let i={chain:o,message:n,signature:m,stackId:d};o==="solana"&&(i.publicKey=l);let w=await fetch(`${t}/api/auth/callback`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(i)});return c(w)},async loginOTP(o){let l=await fetch(`${t}/api/auth/otp`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:o})});return c(l)},async getSession(){let o=await u.getStoredSession();if(o&&o.expiresAt>Date.now())return o;try{let l=await u.getHeaders(),n=await fetch(`${t}/api/auth/session`,{headers:l});if(n.ok){let m=await n.json();if(m.session)return m.session}}catch{if(o)return o}return null},async checkSession(){let o=await u.getToken();if(!o)return false;try{let l=await fetch(`${t}/api/history?limit=1`,{headers:{Authorization:`Bearer ${o}`}});return l.ok?!0:l.status===401?(await u.clear(),!1):!0}catch{return true}},async getChallenge(o,l){let m=`${r}/api/v2/stacks/${encodeURIComponent(d)}/auth/web3/challenge`,i=await fetch(m,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({chain:o,address:l})});if(!i.ok)throw new Error("Failed to get challenge");let w=await i.json();return w.data||w},async logout(){try{let o=await u.getHeaders();await fetch(`${t}/api/auth/logout`,{method:"POST",headers:o});}catch{}await u.clear(),s?.();},async getHeaders(){let o=await u.getHeaders();return Object.keys(o).length>0?o:h?{Authorization:`Bearer ${h}`}:{}},async getToken(){return u.getToken()}}}function Xn(){return {async storeCredentials(e,t){},async getToken(){return null},async getHeaders(){return {}},async getStoredSession(){let e=re();return !e||e.expiresAt<=Date.now()?null:{userId:e.userId,address:e.address,chain:e.chain,expiresAt:e.expiresAt,planId:e.planId,authMethod:e.authMethod}},async clear(){}}}var tt="stackauth_token",nt="stackauth_session";function eo(e){return {async storeCredentials(t,r){await e.setItemAsync(tt,t),await e.setItemAsync(nt,JSON.stringify(r));},async getToken(){try{return await e.getItemAsync(tt)}catch{return null}},async getHeaders(){let t=await this.getToken();return t?{Authorization:`Bearer ${t}`}:{}},async getStoredSession(){try{let t=await e.getItemAsync(nt);return t?JSON.parse(t):null}catch{return null}},async clear(){await e.deleteItemAsync(tt).catch(()=>{}),await e.deleteItemAsync(nt).catch(()=>{});}}}
|
|
2
|
+
export{qe as AppleIcon,Fn as ConnectWidget,Ye as DiscordIcon,Vn as EthereumIcon,Ze as GoogleIcon,ke as MetaMaskIcon,le as OTPInput,we as PhantomIcon,Jn as ProfileSettings,Qn as SolanaIcon,Yn as TelegramIcon,Ke as TwitterIcon,Nn as UserUtilsProvider,Ht as cn,qn as createAuthClient,he as createClientRateLimiter,eo as createNativeTransport,Le as createStackNetClient,Xn as createWebTransport,Qt as decodeJwtPayloadClient,Gt as formatTokens,Q as readCSRFCookie,re as readSessionCookie,oe as safeUrl,Te as useAuthBridge,yn as useBillingHistory,Ae as useCSRFToken,bn as useGoogleOneTap,vn as useJoinCode,an as usePlans,pn as usePrepaidCheckout,We as useProfile,se as useSession,Oe as useStackAuth,ae as useStackConfig,cn as useSubscription,fn as useUsage,An as useUserUtilsContext,Ne as useWeb3Wallet,Jt as validateRedirectUrl};
|
package/dist/server/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var crypto=require('crypto');function Z(e){return Buffer.from(e).toString("base64url")}function se(e){return Buffer.from(e,"base64url").toString()}function N(e){try{let r=e.split(".");return r.length!==3?null:JSON.parse(se(r[1]))}catch{return null}}function j(e,r){let t=Z(JSON.stringify({alg:"HS256",typ:"JWT"})),n=Z(JSON.stringify(e)),s=crypto.createHmac("sha256",r).update(`${t}.${n}`).digest("base64url");return `${t}.${n}.${s}`}function X(e,r){try{let t=e.split(".");if(t.length!==3)return !1;let[n,s,i]=t,c=crypto.createHmac("sha256",r).update(`${n}.${s}`).digest("base64url"),w=Buffer.from(i),m=Buffer.from(c);return w.length!==m.length?!1:crypto.timingSafeEqual(w,m)}catch{return false}}function C(e,r){if(!X(e,r))return null;let t=N(e);return !t||t.exp&&t.exp<Math.floor(Date.now()/1e3)?null:t}function E(e,r,t=900,n=300){let s=C(e,r);return !s?.exp||s.exp*1e3-Date.now()>n*1e3?null:j({...s,exp:Math.floor(Date.now()/1e3)+t},r)}function F(e=32){return crypto.randomBytes(e).toString("hex")}function T(e,r={}){let t=r.trustedProxyCount??1,n=r.trustRealIpHeader===true;if(r.customExtractor){let s=r.customExtractor(e);if(s)return s}if(t>0){let s=e.headers.get("x-forwarded-for");if(s){let i=s.split(",").map(w=>w.trim()).filter(Boolean),c=i.length-t;if(c>=0&&c<i.length)return i[c]}}if(n){let s=e.headers.get("x-real-ip");if(s)return s.trim()}return "unknown"}var ne="__csrf",ae="x-csrf-token",ie=/^[A-Za-z_$][A-Za-z0-9_$-]{0,63}$/,ce=/^[A-Za-z][A-Za-z0-9-]{0,63}$/;function b(e={}){let r=e.cookieName||ne,t=e.headerName||ae,n=e.tokenLength||32,s=e.secure!==false;if(!ie.test(r))throw new Error(`createCSRFProtection: invalid cookieName "${r}"`);if(!ce.test(t))throw new Error(`createCSRFProtection: invalid headerName "${t}"`);if(n<16||n>128)throw new Error("createCSRFProtection: tokenLength must be between 16 and 128 bytes");return {generateToken(i){let c=F(n),w=[`${r}=${c}`,"Path=/","SameSite=Lax"];return s&&w.push("Secure"),i.append("Set-Cookie",w.join("; ")),c},validateRequest(i){let c=i.headers.get("cookie");if(!c)return {valid:false,error:"No cookies present"};let w=c.split(";").map(g=>g.trim()).find(g=>g.startsWith(`${r}=`))?.slice(r.length+1);if(!w)return {valid:false,error:"CSRF cookie missing"};let m=i.headers.get(t);if(!m)return {valid:false,error:"CSRF header missing"};try{let g=Buffer.from(w),u=Buffer.from(m);return g.length!==u.length?{valid:!1,error:"CSRF token mismatch"}:crypto.timingSafeEqual(g,u)?{valid:!0}:{valid:!1,error:"CSRF token mismatch"}}catch{return {valid:false,error:"CSRF validation failed"}}},cookieName:r,headerName:t}}function v(e){let r=new Map,t=setInterval(()=>{let n=Date.now();for(let[s,i]of r)n>=i.resetAt&&r.delete(s);},6e4);return typeof t=="object"&&"unref"in t&&t.unref(),{async check(n){let s=Date.now(),i=r.get(n);return (!i||s>=i.resetAt)&&(i={count:0,resetAt:s+e.windowMs},r.set(n,i)),i.count++,i.count>e.maxRequests?{allowed:false,remaining:0,retryAfter:Math.ceil((i.resetAt-s)/1e3)}:{allowed:true,remaining:e.maxRequests-i.count}}}}function ue(){let e=new Map,r=setInterval(()=>{let t=Date.now();for(let[n,s]of e)t>=s&&e.delete(n);},6e4);return typeof r=="object"&&"unref"in r&&r.unref(),{async has(t){let n=e.get(t);return n?Date.now()>=n?(e.delete(t),false):true:false},async set(t,n){e.set(t,Date.now()+n*1e3);}}}function pe(e,r){let t=r?.rateLimiter||v({maxRequests:10,windowMs:6e4}),n=b({secure:e.secureCookies!==false}),s=e.jwtExpiry||900,i=e.sessionMaxAge||604800,c=e.stacknetJwtSecret||e.authSecret;return async function(m){let g=T(m,e.ipConfig),u=await t.check(`auth:${g}`);if(!u.allowed)return Response.json({error:"Too many login attempts. Please wait."},{status:429,headers:{"Retry-After":String(u.retryAfter||60)}});let d;try{d=await m.json();}catch{return Response.json({error:"Invalid request body"},{status:400})}let{chain:l,message:f,signature:o,publicKey:a,otp:p,code:h,redirectUrl:S,stackId:k}=d,y=k||e.stackId,x;if(l&&f&&o){let ee={"Content-Type":"application/json"},J=await fetch(`${e.stacknetUrl}/api/v2/stacks/${encodeURIComponent(y)}/auth/web3/verify`,{method:"POST",headers:ee,body:JSON.stringify({chain:l,message:f,signature:o,public_key:a}),signal:AbortSignal.timeout(1e4)});if(!J.ok){let B=await J.json().catch(()=>({})),W=B?.error?.message||B?.message||B?.error||`StackNet returned ${J.status}`;return console.error(`[auth-callback] Verify failed: ${J.status}`,W),Response.json({error:"Wallet verification failed",detail:typeof W=="string"?W:void 0},{status:401})}let U=await J.json();x=U.data?.session||U.session||U.data||U,console.log(`[auth-callback] Verify OK, sessionData keys: ${Object.keys(x||{}).join(", ")}`);}else return p||h?Response.json({error:"Use /api/auth/otp for OTP verification"},{status:400}):Response.json({error:"Provide wallet signature or OTP code"},{status:400});if(!x?.jwt)return Response.json({error:"Authentication failed \u2014 no session returned"},{status:401});let R=C(x.jwt,c);if(!R)return Response.json({error:"Upstream session JWT failed verification"},{status:502});let P=Math.floor(Date.now()/1e3),I={...R,exp:P+s,iat:P},A=j(I,e.authSecret),O={userId:R.sub||R.user_id||R.session_id||R.global_id||"",address:x.address||R.address,chain:x.chain||l,expiresAt:Date.now()+i*1e3,authMethod:l?`web3:${l}`:"otp"},$=new Headers({"Content-Type":"application/json"}),H=e.secureCookies!==false?"; Secure":"",_=e.cookieDomain?`; Domain=${e.cookieDomain}`:"";$.append("Set-Cookie",`stackauth_jwt=${A}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${i}${H}${_}`);let q=Buffer.from(JSON.stringify(O)).toString("base64url");return $.append("Set-Cookie",`stackauth_session=${q}; Path=/; SameSite=Lax; Max-Age=${i}${H}${_}`),n.generateToken($),new Response(JSON.stringify({user:O}),{status:200,headers:$})}}function Q(e,r){if(!r)return null;try{let t=N(e);if(!t||t.exp&&t.exp<Math.floor(Date.now()/1e3))return null;let n=Buffer.from(JSON.stringify({alg:"HS256",typ:"JWT"})).toString("base64url"),s=Buffer.from(JSON.stringify(t)).toString("base64url"),i=crypto.createHmac("sha256",r).update(`${n}.${s}`).digest("base64url");return `${n}.${s}.${i}`}catch{return null}}var le=/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/;function Y(e){return typeof e!="string"||e.length===0||e.length>8192?null:le.test(e)?e:null}function D(e,r){let t=Q(e,r),n=t&&Y(t);if(n)return {Cookie:`stackauth_jwt=${n}`};let s=Y(e);return s?{Cookie:`stackauth_jwt=${s}`}:{}}function M(e){let r=e.headers.get("cookie");if(r){let n=r.split(";").map(s=>s.trim()).find(s=>s.startsWith("stackauth_jwt="));if(n)return n.slice(14)}let t=e.headers.get("authorization");return t?.startsWith("Bearer ")?t.slice(7):null}function fe(e){return !e.authSecret&&typeof console<"u"&&console.warn("[userutils] createLogoutHandler called without authSecret \u2014 upstream session revocation is disabled. Pass authSecret to enable it safely."),async function(t){let n=M(t);if(n&&e.authSecret){let w=C(n,e.authSecret),m=w?.session_id||w?.sub;if(m&&typeof m=="string")try{await fetch(`${e.stacknetUrl}/api/v2/sessions/${encodeURIComponent(m)}`,{method:"DELETE",signal:AbortSignal.timeout(5e3)});}catch{}}let s=e.secureCookies!==false?"; Secure":"",i=e.cookieDomain?`; Domain=${e.cookieDomain}`:"",c=new Headers({"Content-Type":"application/json"});return c.append("Set-Cookie",`stackauth_jwt=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0${s}${i}`),c.append("Set-Cookie",`stackauth_session=; Path=/; SameSite=Lax; Max-Age=0${s}${i}`),c.append("Set-Cookie",`__csrf=; Path=/; SameSite=Lax; Max-Age=0${s}${i}`),new Response(JSON.stringify({success:true}),{status:200,headers:c})}}function me(e){let r=e.jwtExpiry||900,t=e.sessionMaxAge||604800;return async function(s){let i=M(s);if(!i)return Response.json({session:null},{status:200});let c=C(i,e.authSecret);if(!c)return Response.json({session:null},{status:200});let m={userId:c.sub||c.user_id||c.session_id||c.global_id||"",address:c.address,chain:c.chain,expiresAt:c.session_expires_at||(c.exp?c.exp*1e3:Date.now()+t*1e3),planId:c.plan_id,authMethod:c.auth_method},g=new Headers({"Content-Type":"application/json"}),u=E(i,e.authSecret,r,300);if(u){let d=e.secureCookies!==false?"; Secure":"",l=e.cookieDomain?`; Domain=${e.cookieDomain}`:"";g.append("Set-Cookie",`stackauth_jwt=${u}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${t}${d}${l}`);}return new Response(JSON.stringify({session:m}),{status:200,headers:g})}}function ye(e,r){if(e.length!==r.length)return false;try{return crypto.timingSafeEqual(Buffer.from(e),Buffer.from(r))}catch{return false}}function we(e){let r=e.rateLimiter||v({maxRequests:5,windowMs:3e5}),t=b({secure:e.secureCookies!==false}),n=e.jwtExpiry||900,s=e.sessionMaxAge||604800;return async function(c){let w=T(c,e.ipConfig),m=await r.check(`otp:${w}`);if(!m.allowed)return Response.json({error:"Too many attempts. Please wait."},{status:429,headers:{"Retry-After":String(m.retryAfter||300)}});let g;try{g=await c.json();}catch{return Response.json({error:"Invalid request body"},{status:400})}let{code:u}=g;if(!u||typeof u!="string"||u.length!==6)return Response.json({error:"Invalid code format"},{status:400});if(!ye(u,e.otpSecret))return Response.json({error:"Invalid code"},{status:401});let d=Math.floor(Date.now()/1e3),f={sub:`preview:otp:${crypto.createHash("sha256").update(`otp:${u}:${Date.now()}`).digest("hex").slice(0,32)}`,scope:"preview",auth_method:"otp",credentials:["otp"],iat:d,exp:d+n},o=j(f,e.authSecret),a={userId:f.sub,expiresAt:Date.now()+s*1e3,authMethod:"otp",scope:"preview"},p=new Headers({"Content-Type":"application/json"}),h=e.secureCookies!==false?"; Secure":"",S=e.cookieDomain?`; Domain=${e.cookieDomain}`:"";p.append("Set-Cookie",`stackauth_jwt=${o}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${s}${h}${S}`);let k=Buffer.from(JSON.stringify(a)).toString("base64url");return p.append("Set-Cookie",`stackauth_session=${k}; Path=/; SameSite=Lax; Max-Age=${s}${h}${S}`),t.generateToken(p),new Response(JSON.stringify({success:true,data:{user:a}}),{status:200,headers:p})}}function Se(e,r){let t=r?.rateLimiter||v({maxRequests:10,windowMs:6e4}),n=b({secure:e.secureCookies!==false}),s=e.jwtExpiry||900,i=e.sessionMaxAge||604800,c=e.stacknetJwtSecret||e.authSecret;async function w(g){let u=new URL(g.url),d=u.searchParams.get("provider"),l=u.searchParams.get("redirectUri")||u.searchParams.get("redirect_uri"),f=u.searchParams.get("stackId")||e.stackId;if(!d)return Response.json({error:"Missing provider parameter"},{status:400});if(!l)return Response.json({error:"Missing redirectUri parameter"},{status:400});if(!/^[a-z][a-z0-9_-]{0,32}$/.test(d))return Response.json({error:"Invalid provider name"},{status:400});if(!f||!/^[a-zA-Z0-9_-]{1,64}$/.test(f))return Response.json({error:"Invalid stackId"},{status:400});try{let o=await fetch(`${e.stacknetUrl}/api/v2/stacks/${encodeURIComponent(f)}/auth/oauth/${encodeURIComponent(d)}/initiate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({redirectUrl:l}),signal:AbortSignal.timeout(1e4)});if(!o.ok){let h=await o.json().catch(()=>({}));return Response.json({error:h.error?.message||`Failed to start OAuth flow: ${o.statusText}`},{status:o.status})}let a=await o.json(),p=a.data||a;return Response.json({redirect_url:p.url,state:p.state})}catch(o){return Response.json({error:o.message||"Failed to start OAuth flow"},{status:500})}}async function m(g){let u=T(g,e.ipConfig),d=await t.check(`oauth:${u}`);if(!d.allowed)return Response.json({error:"Too many attempts. Please wait."},{status:429,headers:{"Retry-After":String(d.retryAfter||60)}});let l;try{l=await g.json();}catch{return Response.json({error:"Invalid request body"},{status:400})}let{provider:f,code:o,state:a,stackId:p}=l,h=p||e.stackId;if(!f||!o||!a)return Response.json({error:"Missing provider, code, or state"},{status:400});if(!/^[a-z][a-z0-9_-]{0,32}$/.test(f))return Response.json({error:"Invalid provider name"},{status:400});if(!h||!/^[a-zA-Z0-9_-]{1,64}$/.test(h))return Response.json({error:"Invalid stackId"},{status:400});try{let S=await fetch(`${e.stacknetUrl}/api/v2/stacks/${encodeURIComponent(h)}/auth/oauth/${encodeURIComponent(f)}/callback`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:o,state:a}),signal:AbortSignal.timeout(1e4)});if(!S.ok){let _=await S.json().catch(()=>({}));return Response.json({error:_.error?.message||`OAuth verification failed: ${S.statusText}`},{status:401})}let k=await S.json(),y=k.data?.session||k.session||k.data||k;if(!y?.jwt)return Response.json({error:"OAuth authentication failed \u2014 no session returned"},{status:401});let x=C(y.jwt,c);if(!x)return Response.json({error:"Upstream session JWT failed verification"},{status:502});let R=Math.floor(Date.now()/1e3),P=j({...x,exp:R+s,iat:R},e.authSecret),A={userId:x.sub||x.user_id||x.session_id||x.global_id||"",address:y.address||x.address,chain:void 0,expiresAt:Date.now()+i*1e3,authMethod:`oauth:${f}`},L=new Headers({"Content-Type":"application/json"}),O=e.secureCookies!==!1?"; Secure":"",$=e.cookieDomain?`; Domain=${e.cookieDomain}`:"";L.append("Set-Cookie",`stackauth_jwt=${P}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${i}${O}${$}`);let H=Buffer.from(JSON.stringify(A)).toString("base64url");return L.append("Set-Cookie",`stackauth_session=${H}; Path=/; SameSite=Lax; Max-Age=${i}${O}${$}`),n.generateToken(L),new Response(JSON.stringify({user:A}),{status:200,headers:L})}catch(S){return Response.json({error:S.message||"OAuth callback failed"},{status:500})}}return {startFlow:w,handleCallback:m}}function ke(e,r){let t=r?.rateLimiter||v({maxRequests:10,windowMs:6e4}),n=b({secure:e.secureCookies!==false}),s=e.jwtExpiry||900,i=e.sessionMaxAge||604800,c=e.stacknetJwtSecret||e.authSecret;return async function(m){let g=T(m,e.ipConfig),u=await t.check(`google-onetap:${g}`);if(!u.allowed)return Response.json({error:"Too many attempts. Please wait."},{status:429,headers:{"Retry-After":String(u.retryAfter||60)}});let d;try{d=await m.json();}catch{return Response.json({error:"Invalid request body"},{status:400})}let{credential:l,stackId:f}=d,o=f||e.stackId;if(!l)return Response.json({error:"Missing credential"},{status:400});if(l.split(".").length!==3)return Response.json({error:"Invalid credential format"},{status:400});let a;try{let y=await fetch(`https://oauth2.googleapis.com/tokeninfo?id_token=${encodeURIComponent(l)}`,{signal:AbortSignal.timeout(1e4)});if(!y.ok)return Response.json({error:"Google credential verification failed"},{status:401});a=await y.json();}catch{return Response.json({error:"Failed to verify Google credential"},{status:500})}if(!a.sub||!a.email)return Response.json({error:"Invalid Google token \u2014 missing user info"},{status:401});if(a.iss!=="https://accounts.google.com"&&a.iss!=="accounts.google.com")return Response.json({error:"Invalid Google token issuer"},{status:401});let p=typeof a.exp=="string"?parseInt(a.exp,10):Number(a.exp);if(!Number.isFinite(p)||p<Math.floor(Date.now()/1e3))return Response.json({error:"Google token expired"},{status:401});let h=e.googleClientIds||(e.googleClientId?[e.googleClientId]:[]);if(h.length===0)return Response.json({error:"Google One Tap not configured \u2014 set ServerConfig.googleClientId(s)"},{status:500});if(!a.aud||!h.includes(a.aud))return Response.json({error:"Invalid Google token audience"},{status:401});if(!(a.email_verified===true||a.email_verified==="true"))return Response.json({error:"Google email is not verified"},{status:401});let k={sub:a.sub,email:a.email,name:a.name,picture:a.picture};try{let y=await fetch(`${e.stacknetUrl}/api/v2/stacks/${encodeURIComponent(o)}/auth/oauth/google/callback`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({credential:l,google_id:k.sub,email:k.email,name:k.name,picture:k.picture,one_tap:!0}),signal:AbortSignal.timeout(1e4)});if(!y.ok){let P=await y.json().catch(()=>({}));return Response.json({error:P?.error?.message||"Google sign-in failed"},{status:y.status})}let x=await y.json(),R=x.data?.session||x.session||x.data||x;if(R?.jwt){let P=C(R.jwt,c);if(!P)return Response.json({error:"Upstream session JWT failed verification"},{status:502});let I=Math.floor(Date.now()/1e3),A=j({...P,exp:I+s,iat:I},e.authSecret),O={userId:P.sub||P.user_id||k.sub,address:k.email||R.address,chain:void 0,expiresAt:Date.now()+i*1e3,authMethod:"oauth:google"},$=new Headers({"Content-Type":"application/json"}),H=e.secureCookies!==!1?"; Secure":"",_=e.cookieDomain?`; Domain=${e.cookieDomain}`:"";$.append("Set-Cookie",`stackauth_jwt=${A}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${i}${H}${_}`);let q=Buffer.from(JSON.stringify(O)).toString("base64url");return $.append("Set-Cookie",`stackauth_session=${q}; Path=/; SameSite=Lax; Max-Age=${i}${H}${_}`),n.generateToken($),new Response(JSON.stringify({user:O}),{status:200,headers:$})}return Response.json({error:"No session returned"},{status:401})}catch(y){return Response.json({error:y.message||"Google One Tap authentication failed"},{status:500})}}}function xe(e,r){let t=r?.rateLimiter||v({maxRequests:10,windowMs:6e4}),n=b({secure:e.secureCookies!==false}),s=r?.sessionMaxAge??3600;return async function(c){let w=T(c,e.ipConfig),m=await t.check(`preview-code:${w}`);if(!m.allowed)return Response.json({error:"Too many preview-code attempts. Please wait."},{status:429,headers:{"Retry-After":String(m.retryAfter||60)}});let g;try{g=await c.json();}catch{return Response.json({error:"Invalid request body"},{status:400})}let u=typeof g?.code=="string"?g.code.trim():"";if(!/^\d{6}$/.test(u))return Response.json({error:"Code must be 6 digits"},{status:400});let d;try{let y=await fetch(`${e.stacknetUrl.replace(/\/$/,"")}/v1/preview-codes/${encodeURIComponent(u)}`,{method:"GET",headers:{Accept:"application/json"},signal:AbortSignal.timeout(5e3)});if(y.status===404)return Response.json({error:"Preview code not found"},{status:404});if(!y.ok)return Response.json({error:`Upstream returned ${y.status}`},{status:502});d=await y.json();}catch{return Response.json({error:"Upstream validation failed"},{status:502})}if(!d||d.code!==u)return Response.json({error:"Preview code not found"},{status:404});if(d.revoked===true)return Response.json({error:"Preview code has been revoked"},{status:401});if(typeof d.expiresAt=="number"&&d.expiresAt<=Date.now())return Response.json({error:"Preview code has expired"},{status:401});if(typeof d.tokensRemaining=="number"&&d.tokensRemaining<=0)return Response.json({error:"Preview code is exhausted"},{status:402});let l=Math.floor(Date.now()/1e3),f=`preview_${u}`,o=j({sub:f,global_id:f,auth_method:"preview_code",preview_code:u,exp:l+s,iat:l},e.authSecret),a={userId:f,expiresAt:Date.now()+s*1e3,authMethod:"preview_code"},p=new Headers({"Content-Type":"application/json"}),h=e.secureCookies!==false?"; Secure":"",S=e.cookieDomain?`; Domain=${e.cookieDomain}`:"";p.append("Set-Cookie",`stackauth_jwt=${o}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${s}${h}${S}`);let k=Buffer.from(JSON.stringify(a)).toString("base64url");return p.append("Set-Cookie",`stackauth_session=${k}; Path=/; SameSite=Lax; Max-Age=${s}${h}${S}`),n.generateToken(p),new Response(JSON.stringify({user:a,name:d.name??null}),{status:200,headers:p})}}function Re(e){let r=b({secure:e.secureCookies!==false}),t=e.rateLimiter||v({maxRequests:20,windowMs:6e4}),n=e.stacknetJwtSecret||e.authSecret,s=e.jwtExpiry||900,i=e.sessionMaxAge||604800,c=null;if(e.canonicalOrigin){let o;try{o=new URL(e.canonicalOrigin);}catch{throw new Error(`createBillingProxy: canonicalOrigin "${e.canonicalOrigin}" is not a valid URL`)}if(o.protocol!=="http:"&&o.protocol!=="https:")throw new Error(`createBillingProxy: canonicalOrigin must be http or https (got "${o.protocol}")`);if(o.pathname!=="/"&&o.pathname!=="")throw new Error(`createBillingProxy: canonicalOrigin must have no path (got "${o.pathname}")`);c=o.origin;}let w=false;function m(o){if(c)return c;w||(w=true,console.warn("[userutils] createBillingProxy: canonicalOrigin not set \u2014 falling back to request origin. Set canonicalOrigin to the public URL of this app to prevent Host-header spoofing of Stripe success URLs."));try{let a=new URL(o.url);return a.protocol!=="http:"&&a.protocol!=="https:"?null:a.origin}catch{return null}}function g(o){let a=M(o);if(!a)return null;let p=C(a,e.authSecret);return p?{jwt:a,payload:p}:null}function u(o,a){let p=E(o,e.authSecret,s,300);if(p){let h=e.secureCookies!==false?"; Secure":"",S=e.cookieDomain?`; Domain=${e.cookieDomain}`:"";a.append("Set-Cookie",`stackauth_jwt=${p}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${i}${h}${S}`);}}async function d(o,a){let p=g(o);if(!p)return Response.json({error:"Unauthorized"},{status:401});let h=D(p.jwt,n),S=await fetch(`${e.stacknetUrl}${a}`,{headers:h,signal:AbortSignal.timeout(15e3)}),k=await S.json().catch(()=>({})),y=new Headers({"Content-Type":"application/json"});return u(p.jwt,y),new Response(JSON.stringify(k),{status:S.status,headers:y})}async function l(o,a,p){let h=g(o);if(!h)return Response.json({error:"Unauthorized"},{status:401});let S=r.validateRequest(o);if(!S.valid)return Response.json({error:S.error||"CSRF validation failed"},{status:403});let k=h.payload.sub||h.payload.user_id||"unknown";if(!(await t.check(`billing:${k}`)).allowed)return Response.json({error:"Too many requests"},{status:429});let x=await o.json().catch(()=>({})),R=D(h.jwt,n);R["Content-Type"]="application/json";let P=await fetch(`${e.stacknetUrl}${a}`,{method:"POST",headers:R,body:JSON.stringify({...x,...p}),signal:AbortSignal.timeout(15e3)}),I=await P.json().catch(()=>({})),A=new Headers({"Content-Type":"application/json"});return u(h.jwt,A),new Response(JSON.stringify(I),{status:P.status,headers:A})}let f=`/api/v2/stacks/${encodeURIComponent(e.stackId)}`;return {plans:{GET:async o=>{let a=await fetch(`${e.stacknetUrl}${f}/plans`,{signal:AbortSignal.timeout(1e4)}),p=await a.json().catch(()=>({}));return Response.json(p,{status:a.status})}},subscription:{GET:(o=>d(o,`${f}/subscription`))},subscribe:{POST:(o=>{let a=m(o);return a?l(o,`${f}/subscribe`,{successUrl:`${a}/billing/success?session_id={CHECKOUT_SESSION_ID}`,cancelUrl:`${a}/pricing`}):Promise.resolve(Response.json({error:"Invalid request origin for checkout"},{status:400}))})},cancel:{POST:(o=>l(o,`${f}/cancel-subscription`))},usage:{GET:(o=>d(o,"/v1/account/usage"))},history:{GET:(o=>d(o,`${f}/billing`))},prepaid:{POST:(o=>{let a=m(o);return a?l(o,`${f}/prepaid`,{successUrl:`${a}/pricing/prepaid/success?session_id={CHECKOUT_SESSION_ID}`,cancelUrl:`${a}/pricing/prepaid`}):Promise.resolve(Response.json({error:"Invalid request origin for checkout"},{status:400}))})},verifyPrepaid:{POST:(o=>l(o,`${f}/verify-prepaid`))},verifySession:{POST:(o=>l(o,`${f}/verify-session`))},subscribeSol:{POST:(o=>l(o,`${f}/subscribe-sol`))},prepaidSol:{POST:(o=>l(o,`${f}/prepaid-sol`))},topup:{POST:(o=>l(o,"/v1/account/topup"))}}}function Pe(e){return async function(t){let n=t.headers.get("stripe-signature");if(!n)return Response.json({error:"Missing Stripe signature"},{status:400});try{let s=await t.text(),i=await fetch(`${e.stacknetUrl}/api/v2/stacks/${encodeURIComponent(e.stackId)}/webhook/stripe`,{method:"POST",headers:{"Content-Type":"application/json","stripe-signature":n},body:s,signal:AbortSignal.timeout(1e4)}),c=await i.json().catch(()=>({received:!0}));return Response.json(c,{status:i.status})}catch{return Response.json({error:"Webhook processing failed"},{status:502})}}}function G(){return {"Strict-Transport-Security":"max-age=63072000; includeSubDomains; preload","X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","X-XSS-Protection":"0","Referrer-Policy":"strict-origin-when-cross-origin","Permissions-Policy":"camera=(), microphone=(), geolocation=()"}}function Ce(e){return async r=>{let t=await e(r),n=G(),s=new Headers(t.headers);for(let[i,c]of Object.entries(n))s.set(i,c);return new Response(t.body,{status:t.status,statusText:t.statusText,headers:s})}}function be(){return Object.entries(G()).map(([e,r])=>({key:e,value:r}))}function z(e){return {"Content-Type":"application/json",...D(e.jwt,e.stacknetJwtSecret)}}async function ve(e,r){let t=await fetch(`${e.stacknetBaseUrl}/v1/preview-codes`,{method:"POST",headers:z(e),body:JSON.stringify({token_budget:r.tokenBudget,code:r.code,expires_at:r.expiresAt,name:r.name})});return t.ok?await t.json():{error:await t.text().catch(()=>"")||`HTTP ${t.status}`,status:t.status}}async function $e(e){let r=await fetch(`${e.stacknetBaseUrl}/v1/preview-codes`,{method:"GET",headers:z(e)});return r.ok?(await r.json()).codes:{error:await r.text().catch(()=>"")||`HTTP ${r.status}`,status:r.status}}async function je(e,r){let t=await fetch(`${e}/v1/preview-codes/${encodeURIComponent(r)}`,{method:"GET"});return t.status===404||!t.ok?null:await t.json()}async function Te(e,r){let t=await fetch(`${e.stacknetBaseUrl}/v1/preview-codes/${encodeURIComponent(r)}`,{method:"DELETE",headers:z(e)});return t.ok?await t.json():{error:await t.text().catch(()=>"")||`HTTP ${t.status}`,status:t.status}}async function Ae(e,r,t){let n=await fetch(`${e}/v1/preview-codes/${encodeURIComponent(r)}/redeem`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({tokens:t})});return n.ok?await n.json():{error:await n.text().catch(()=>"")||`HTTP ${n.status}`,status:n.status}}var V=["127924fc17182f69cb463d9977348c482d2e784dfdd16f9e6eecc4db07fb04c3","HxLBLBjKbSrJSFCE7LGs9FxMA6M5bztmpNoLuB43HTFs"];function Oe(e){return e?V.includes(e):false}var Ie=V[0];
|
|
1
|
+
'use strict';var crypto=require('crypto');function Z(e){return Buffer.from(e).toString("base64url")}function se(e){return Buffer.from(e,"base64url").toString()}function N(e){try{let r=e.split(".");return r.length!==3?null:JSON.parse(se(r[1]))}catch{return null}}function j(e,r){let t=Z(JSON.stringify({alg:"HS256",typ:"JWT"})),n=Z(JSON.stringify(e)),s=crypto.createHmac("sha256",r).update(`${t}.${n}`).digest("base64url");return `${t}.${n}.${s}`}function X(e,r){try{let t=e.split(".");if(t.length!==3)return !1;let[n,s,i]=t,c=crypto.createHmac("sha256",r).update(`${n}.${s}`).digest("base64url"),w=Buffer.from(i),m=Buffer.from(c);return w.length!==m.length?!1:crypto.timingSafeEqual(w,m)}catch{return false}}function C(e,r){if(!X(e,r))return null;let t=N(e);return !t||t.exp&&t.exp<Math.floor(Date.now()/1e3)?null:t}function E(e,r,t=900,n=300){let s=C(e,r);return !s?.exp||s.exp*1e3-Date.now()>n*1e3?null:j({...s,exp:Math.floor(Date.now()/1e3)+t},r)}function F(e=32){return crypto.randomBytes(e).toString("hex")}function T(e,r={}){let t=r.trustedProxyCount??1,n=r.trustRealIpHeader===true;if(r.customExtractor){let s=r.customExtractor(e);if(s)return s}if(t>0){let s=e.headers.get("x-forwarded-for");if(s){let i=s.split(",").map(w=>w.trim()).filter(Boolean),c=i.length-t;if(c>=0&&c<i.length)return i[c]}}if(n){let s=e.headers.get("x-real-ip");if(s)return s.trim()}return "unknown"}var ne="__csrf",ae="x-csrf-token",ie=/^[A-Za-z_$][A-Za-z0-9_$-]{0,63}$/,ce=/^[A-Za-z][A-Za-z0-9-]{0,63}$/;function b(e={}){let r=e.cookieName||ne,t=e.headerName||ae,n=e.tokenLength||32,s=e.secure!==false;if(!ie.test(r))throw new Error(`createCSRFProtection: invalid cookieName "${r}"`);if(!ce.test(t))throw new Error(`createCSRFProtection: invalid headerName "${t}"`);if(n<16||n>128)throw new Error("createCSRFProtection: tokenLength must be between 16 and 128 bytes");return {generateToken(i){let c=F(n),w=[`${r}=${c}`,"Path=/","SameSite=Lax"];return s&&w.push("Secure"),i.append("Set-Cookie",w.join("; ")),c},validateRequest(i){let c=i.headers.get("cookie");if(!c)return {valid:false,error:"No cookies present"};let w=c.split(";").map(g=>g.trim()).find(g=>g.startsWith(`${r}=`))?.slice(r.length+1);if(!w)return {valid:false,error:"CSRF cookie missing"};let m=i.headers.get(t);if(!m)return {valid:false,error:"CSRF header missing"};try{let g=Buffer.from(w),u=Buffer.from(m);return g.length!==u.length?{valid:!1,error:"CSRF token mismatch"}:crypto.timingSafeEqual(g,u)?{valid:!0}:{valid:!1,error:"CSRF token mismatch"}}catch{return {valid:false,error:"CSRF validation failed"}}},cookieName:r,headerName:t}}function v(e){let r=new Map,t=setInterval(()=>{let n=Date.now();for(let[s,i]of r)n>=i.resetAt&&r.delete(s);},6e4);return typeof t=="object"&&"unref"in t&&t.unref(),{async check(n){let s=Date.now(),i=r.get(n);return (!i||s>=i.resetAt)&&(i={count:0,resetAt:s+e.windowMs},r.set(n,i)),i.count++,i.count>e.maxRequests?{allowed:false,remaining:0,retryAfter:Math.ceil((i.resetAt-s)/1e3)}:{allowed:true,remaining:e.maxRequests-i.count}}}}function ue(){let e=new Map,r=setInterval(()=>{let t=Date.now();for(let[n,s]of e)t>=s&&e.delete(n);},6e4);return typeof r=="object"&&"unref"in r&&r.unref(),{async has(t){let n=e.get(t);return n?Date.now()>=n?(e.delete(t),false):true:false},async set(t,n){e.set(t,Date.now()+n*1e3);}}}function pe(e,r){let t=r?.rateLimiter||v({maxRequests:10,windowMs:6e4}),n=b({secure:e.secureCookies!==false}),s=e.jwtExpiry||900,i=e.sessionMaxAge||604800,c=e.stacknetJwtSecret||e.authSecret;return async function(m){let g=T(m,e.ipConfig),u=await t.check(`auth:${g}`);if(!u.allowed)return Response.json({error:"Too many login attempts. Please wait."},{status:429,headers:{"Retry-After":String(u.retryAfter||60)}});let d;try{d=await m.json();}catch{return Response.json({error:"Invalid request body"},{status:400})}let{chain:l,message:f,signature:o,publicKey:a,otp:p,code:h,redirectUrl:S,stackId:k}=d,y=k||e.stackId,x;if(l&&f&&o){let ee={"Content-Type":"application/json"},J=await fetch(`${e.stacknetUrl}/api/v2/stacks/${encodeURIComponent(y)}/auth/web3/verify`,{method:"POST",headers:ee,body:JSON.stringify({chain:l,message:f,signature:o,public_key:a}),signal:AbortSignal.timeout(1e4)});if(!J.ok){let B=await J.json().catch(()=>({})),W=B?.error?.message||B?.message||B?.error||`StackNet returned ${J.status}`;return console.error(`[auth-callback] Verify failed: ${J.status}`,W),Response.json({error:"Wallet verification failed",detail:typeof W=="string"?W:void 0},{status:401})}let U=await J.json();x=U.data?.session||U.session||U.data||U,console.log(`[auth-callback] Verify OK, sessionData keys: ${Object.keys(x||{}).join(", ")}`);}else return p||h?Response.json({error:"Use /api/auth/otp for OTP verification"},{status:400}):Response.json({error:"Provide wallet signature or OTP code"},{status:400});if(!x?.jwt)return Response.json({error:"Authentication failed \u2014 no session returned"},{status:401});let R=C(x.jwt,c);if(!R)return Response.json({error:"Upstream session JWT failed verification"},{status:502});let P=Math.floor(Date.now()/1e3),I={...R,exp:P+s,iat:P},A=j(I,e.authSecret),O={userId:R.sub||R.user_id||R.session_id||R.global_id||"",address:x.address||R.address,chain:x.chain||l,expiresAt:Date.now()+i*1e3,authMethod:l?`web3:${l}`:"otp"},$=new Headers({"Content-Type":"application/json"}),H=e.secureCookies!==false?"; Secure":"",_=e.cookieDomain?`; Domain=${e.cookieDomain}`:"";$.append("Set-Cookie",`stackauth_jwt=${A}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${i}${H}${_}`);let q=Buffer.from(JSON.stringify(O)).toString("base64url");return $.append("Set-Cookie",`stackauth_session=${q}; Path=/; SameSite=Lax; Max-Age=${i}${H}${_}`),n.generateToken($),new Response(JSON.stringify({user:O}),{status:200,headers:$})}}function Q(e,r){if(!r)return null;try{let t=N(e);if(!t||t.exp&&t.exp<Math.floor(Date.now()/1e3))return null;let n=Buffer.from(JSON.stringify({alg:"HS256",typ:"JWT"})).toString("base64url"),s=Buffer.from(JSON.stringify(t)).toString("base64url"),i=crypto.createHmac("sha256",r).update(`${n}.${s}`).digest("base64url");return `${n}.${s}.${i}`}catch{return null}}var le=/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/;function Y(e){return typeof e!="string"||e.length===0||e.length>8192?null:le.test(e)?e:null}function D(e,r){let t=Q(e,r),n=t&&Y(t);if(n)return {Cookie:`stackauth_jwt=${n}`};let s=Y(e);return s?{Cookie:`stackauth_jwt=${s}`}:{}}function M(e){let r=e.headers.get("cookie");if(r){let n=r.split(";").map(s=>s.trim()).find(s=>s.startsWith("stackauth_jwt="));if(n)return n.slice(14)}let t=e.headers.get("authorization");return t?.startsWith("Bearer ")?t.slice(7):null}function fe(e){return !e.authSecret&&typeof console<"u"&&console.warn("[userutils] createLogoutHandler called without authSecret \u2014 upstream session revocation is disabled. Pass authSecret to enable it safely."),async function(t){let n=M(t);if(n&&e.authSecret){let w=C(n,e.authSecret),m=w?.session_id||w?.sub;if(m&&typeof m=="string")try{await fetch(`${e.stacknetUrl}/api/v2/sessions/${encodeURIComponent(m)}`,{method:"DELETE",signal:AbortSignal.timeout(5e3)});}catch{}}let s=e.secureCookies!==false?"; Secure":"",i=e.cookieDomain?`; Domain=${e.cookieDomain}`:"",c=new Headers({"Content-Type":"application/json"});return c.append("Set-Cookie",`stackauth_jwt=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0${s}${i}`),c.append("Set-Cookie",`stackauth_session=; Path=/; SameSite=Lax; Max-Age=0${s}${i}`),c.append("Set-Cookie",`__csrf=; Path=/; SameSite=Lax; Max-Age=0${s}${i}`),new Response(JSON.stringify({success:true}),{status:200,headers:c})}}function me(e){let r=e.jwtExpiry||900,t=e.sessionMaxAge||604800;return async function(s){let i=M(s);if(!i)return Response.json({session:null},{status:200});let c=C(i,e.authSecret);if(!c)return Response.json({session:null},{status:200});let m={userId:c.sub||c.user_id||c.session_id||c.global_id||"",address:c.address,chain:c.chain,expiresAt:c.session_expires_at||(c.exp?c.exp*1e3:Date.now()+t*1e3),planId:c.plan_id,authMethod:c.auth_method},g=new Headers({"Content-Type":"application/json"}),u=E(i,e.authSecret,r,300);if(u){let d=e.secureCookies!==false?"; Secure":"",l=e.cookieDomain?`; Domain=${e.cookieDomain}`:"";g.append("Set-Cookie",`stackauth_jwt=${u}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${t}${d}${l}`);}return new Response(JSON.stringify({session:m}),{status:200,headers:g})}}function ye(e,r){if(e.length!==r.length)return false;try{return crypto.timingSafeEqual(Buffer.from(e),Buffer.from(r))}catch{return false}}function we(e){let r=e.rateLimiter||v({maxRequests:3,windowMs:3e5}),t=b({secure:e.secureCookies!==false}),n=e.jwtExpiry||900,s=e.sessionMaxAge||604800;return async function(c){let w=T(c,e.ipConfig),m=await r.check(`otp:${w}`);if(!m.allowed)return Response.json({error:"Too many attempts. Please wait."},{status:429,headers:{"Retry-After":String(m.retryAfter||300)}});let g;try{g=await c.json();}catch{return Response.json({error:"Invalid request body"},{status:400})}let{code:u}=g;if(!u||typeof u!="string"||u.length!==6)return Response.json({error:"Invalid code format"},{status:400});if(!ye(u,e.otpSecret))return Response.json({error:"Invalid code"},{status:401});let d=Math.floor(Date.now()/1e3),f={sub:`preview:otp:${crypto.createHash("sha256").update(`otp:${u}:${Date.now()}`).digest("hex").slice(0,32)}`,scope:"preview",auth_method:"otp",credentials:["otp"],iat:d,exp:d+n},o=j(f,e.authSecret),a={userId:f.sub,expiresAt:Date.now()+s*1e3,authMethod:"otp",scope:"preview"},p=new Headers({"Content-Type":"application/json"}),h=e.secureCookies!==false?"; Secure":"",S=e.cookieDomain?`; Domain=${e.cookieDomain}`:"";p.append("Set-Cookie",`stackauth_jwt=${o}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${s}${h}${S}`);let k=Buffer.from(JSON.stringify(a)).toString("base64url");return p.append("Set-Cookie",`stackauth_session=${k}; Path=/; SameSite=Lax; Max-Age=${s}${h}${S}`),t.generateToken(p),new Response(JSON.stringify({success:true,data:{user:a}}),{status:200,headers:p})}}function Se(e,r){let t=r?.rateLimiter||v({maxRequests:10,windowMs:6e4}),n=b({secure:e.secureCookies!==false}),s=e.jwtExpiry||900,i=e.sessionMaxAge||604800,c=e.stacknetJwtSecret||e.authSecret;async function w(g){let u=new URL(g.url),d=u.searchParams.get("provider"),l=u.searchParams.get("redirectUri")||u.searchParams.get("redirect_uri"),f=u.searchParams.get("stackId")||e.stackId;if(!d)return Response.json({error:"Missing provider parameter"},{status:400});if(!l)return Response.json({error:"Missing redirectUri parameter"},{status:400});if(!/^[a-z][a-z0-9_-]{0,32}$/.test(d))return Response.json({error:"Invalid provider name"},{status:400});if(!f||!/^[a-zA-Z0-9_-]{1,64}$/.test(f))return Response.json({error:"Invalid stackId"},{status:400});try{let o=await fetch(`${e.stacknetUrl}/api/v2/stacks/${encodeURIComponent(f)}/auth/oauth/${encodeURIComponent(d)}/initiate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({redirectUrl:l}),signal:AbortSignal.timeout(1e4)});if(!o.ok){let h=await o.json().catch(()=>({}));return Response.json({error:h.error?.message||`Failed to start OAuth flow: ${o.statusText}`},{status:o.status})}let a=await o.json(),p=a.data||a;return Response.json({redirect_url:p.url,state:p.state})}catch(o){return Response.json({error:o.message||"Failed to start OAuth flow"},{status:500})}}async function m(g){let u=T(g,e.ipConfig),d=await t.check(`oauth:${u}`);if(!d.allowed)return Response.json({error:"Too many attempts. Please wait."},{status:429,headers:{"Retry-After":String(d.retryAfter||60)}});let l;try{l=await g.json();}catch{return Response.json({error:"Invalid request body"},{status:400})}let{provider:f,code:o,state:a,stackId:p}=l,h=p||e.stackId;if(!f||!o||!a)return Response.json({error:"Missing provider, code, or state"},{status:400});if(!/^[a-z][a-z0-9_-]{0,32}$/.test(f))return Response.json({error:"Invalid provider name"},{status:400});if(!h||!/^[a-zA-Z0-9_-]{1,64}$/.test(h))return Response.json({error:"Invalid stackId"},{status:400});try{let S=await fetch(`${e.stacknetUrl}/api/v2/stacks/${encodeURIComponent(h)}/auth/oauth/${encodeURIComponent(f)}/callback`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:o,state:a}),signal:AbortSignal.timeout(1e4)});if(!S.ok){let _=await S.json().catch(()=>({}));return Response.json({error:_.error?.message||`OAuth verification failed: ${S.statusText}`},{status:401})}let k=await S.json(),y=k.data?.session||k.session||k.data||k;if(!y?.jwt)return Response.json({error:"OAuth authentication failed \u2014 no session returned"},{status:401});let x=C(y.jwt,c);if(!x)return Response.json({error:"Upstream session JWT failed verification"},{status:502});let R=Math.floor(Date.now()/1e3),P=j({...x,exp:R+s,iat:R},e.authSecret),A={userId:x.sub||x.user_id||x.session_id||x.global_id||"",address:y.address||x.address,chain:void 0,expiresAt:Date.now()+i*1e3,authMethod:`oauth:${f}`},L=new Headers({"Content-Type":"application/json"}),O=e.secureCookies!==!1?"; Secure":"",$=e.cookieDomain?`; Domain=${e.cookieDomain}`:"";L.append("Set-Cookie",`stackauth_jwt=${P}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${i}${O}${$}`);let H=Buffer.from(JSON.stringify(A)).toString("base64url");return L.append("Set-Cookie",`stackauth_session=${H}; Path=/; SameSite=Lax; Max-Age=${i}${O}${$}`),n.generateToken(L),new Response(JSON.stringify({user:A}),{status:200,headers:L})}catch(S){return Response.json({error:S.message||"OAuth callback failed"},{status:500})}}return {startFlow:w,handleCallback:m}}function ke(e,r){let t=r?.rateLimiter||v({maxRequests:10,windowMs:6e4}),n=b({secure:e.secureCookies!==false}),s=e.jwtExpiry||900,i=e.sessionMaxAge||604800,c=e.stacknetJwtSecret||e.authSecret;return async function(m){let g=T(m,e.ipConfig),u=await t.check(`google-onetap:${g}`);if(!u.allowed)return Response.json({error:"Too many attempts. Please wait."},{status:429,headers:{"Retry-After":String(u.retryAfter||60)}});let d;try{d=await m.json();}catch{return Response.json({error:"Invalid request body"},{status:400})}let{credential:l,stackId:f}=d,o=f||e.stackId;if(!l)return Response.json({error:"Missing credential"},{status:400});if(l.split(".").length!==3)return Response.json({error:"Invalid credential format"},{status:400});let a;try{let y=await fetch(`https://oauth2.googleapis.com/tokeninfo?id_token=${encodeURIComponent(l)}`,{signal:AbortSignal.timeout(1e4)});if(!y.ok)return Response.json({error:"Google credential verification failed"},{status:401});a=await y.json();}catch{return Response.json({error:"Failed to verify Google credential"},{status:500})}if(!a.sub||!a.email)return Response.json({error:"Invalid Google token \u2014 missing user info"},{status:401});if(a.iss!=="https://accounts.google.com"&&a.iss!=="accounts.google.com")return Response.json({error:"Invalid Google token issuer"},{status:401});let p=typeof a.exp=="string"?parseInt(a.exp,10):Number(a.exp);if(!Number.isFinite(p)||p<Math.floor(Date.now()/1e3))return Response.json({error:"Google token expired"},{status:401});let h=e.googleClientIds||(e.googleClientId?[e.googleClientId]:[]);if(h.length===0)return Response.json({error:"Google One Tap not configured \u2014 set ServerConfig.googleClientId(s)"},{status:500});if(!a.aud||!h.includes(a.aud))return Response.json({error:"Invalid Google token audience"},{status:401});if(!(a.email_verified===true||a.email_verified==="true"))return Response.json({error:"Google email is not verified"},{status:401});let k={sub:a.sub,email:a.email,name:a.name,picture:a.picture};try{let y=await fetch(`${e.stacknetUrl}/api/v2/stacks/${encodeURIComponent(o)}/auth/oauth/google/callback`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({credential:l,google_id:k.sub,email:k.email,name:k.name,picture:k.picture,one_tap:!0}),signal:AbortSignal.timeout(1e4)});if(!y.ok){let P=await y.json().catch(()=>({}));return Response.json({error:P?.error?.message||"Google sign-in failed"},{status:y.status})}let x=await y.json(),R=x.data?.session||x.session||x.data||x;if(R?.jwt){let P=C(R.jwt,c);if(!P)return Response.json({error:"Upstream session JWT failed verification"},{status:502});let I=Math.floor(Date.now()/1e3),A=j({...P,exp:I+s,iat:I},e.authSecret),O={userId:P.sub||P.user_id||k.sub,address:k.email||R.address,chain:void 0,expiresAt:Date.now()+i*1e3,authMethod:"oauth:google"},$=new Headers({"Content-Type":"application/json"}),H=e.secureCookies!==!1?"; Secure":"",_=e.cookieDomain?`; Domain=${e.cookieDomain}`:"";$.append("Set-Cookie",`stackauth_jwt=${A}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${i}${H}${_}`);let q=Buffer.from(JSON.stringify(O)).toString("base64url");return $.append("Set-Cookie",`stackauth_session=${q}; Path=/; SameSite=Lax; Max-Age=${i}${H}${_}`),n.generateToken($),new Response(JSON.stringify({user:O}),{status:200,headers:$})}return Response.json({error:"No session returned"},{status:401})}catch(y){return Response.json({error:y.message||"Google One Tap authentication failed"},{status:500})}}}function xe(e,r){let t=r?.rateLimiter||v({maxRequests:3,windowMs:6e4}),n=b({secure:e.secureCookies!==false}),s=r?.sessionMaxAge??3600;return async function(c){let w=T(c,e.ipConfig),m=await t.check(`preview-code:${w}`);if(!m.allowed)return Response.json({error:"Too many preview-code attempts. Please wait."},{status:429,headers:{"Retry-After":String(m.retryAfter||60)}});let g;try{g=await c.json();}catch{return Response.json({error:"Invalid request body"},{status:400})}let u=typeof g?.code=="string"?g.code.trim():"";if(!/^\d{6}$/.test(u))return Response.json({error:"Code must be 6 digits"},{status:400});let d;try{let y=await fetch(`${e.stacknetUrl.replace(/\/$/,"")}/v1/preview-codes/${encodeURIComponent(u)}`,{method:"GET",headers:{Accept:"application/json"},signal:AbortSignal.timeout(5e3)});if(y.status===404)return Response.json({error:"Preview code not found"},{status:404});if(!y.ok)return Response.json({error:`Upstream returned ${y.status}`},{status:502});d=await y.json();}catch{return Response.json({error:"Upstream validation failed"},{status:502})}if(!d||d.code!==u)return Response.json({error:"Preview code not found"},{status:404});if(d.revoked===true)return Response.json({error:"Preview code has been revoked"},{status:401});if(typeof d.expiresAt=="number"&&d.expiresAt<=Date.now())return Response.json({error:"Preview code has expired"},{status:401});if(typeof d.tokensRemaining=="number"&&d.tokensRemaining<=0)return Response.json({error:"Preview code is exhausted"},{status:402});let l=Math.floor(Date.now()/1e3),f=`preview_${u}`,o=j({sub:f,global_id:f,auth_method:"preview_code",preview_code:u,exp:l+s,iat:l},e.authSecret),a={userId:f,expiresAt:Date.now()+s*1e3,authMethod:"preview_code"},p=new Headers({"Content-Type":"application/json"}),h=e.secureCookies!==false?"; Secure":"",S=e.cookieDomain?`; Domain=${e.cookieDomain}`:"";p.append("Set-Cookie",`stackauth_jwt=${o}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${s}${h}${S}`);let k=Buffer.from(JSON.stringify(a)).toString("base64url");return p.append("Set-Cookie",`stackauth_session=${k}; Path=/; SameSite=Lax; Max-Age=${s}${h}${S}`),n.generateToken(p),new Response(JSON.stringify({user:a,name:d.name??null}),{status:200,headers:p})}}function Re(e){let r=b({secure:e.secureCookies!==false}),t=e.rateLimiter||v({maxRequests:20,windowMs:6e4}),n=e.stacknetJwtSecret||e.authSecret,s=e.jwtExpiry||900,i=e.sessionMaxAge||604800,c=null;if(e.canonicalOrigin){let o;try{o=new URL(e.canonicalOrigin);}catch{throw new Error(`createBillingProxy: canonicalOrigin "${e.canonicalOrigin}" is not a valid URL`)}if(o.protocol!=="http:"&&o.protocol!=="https:")throw new Error(`createBillingProxy: canonicalOrigin must be http or https (got "${o.protocol}")`);if(o.pathname!=="/"&&o.pathname!=="")throw new Error(`createBillingProxy: canonicalOrigin must have no path (got "${o.pathname}")`);c=o.origin;}let w=false;function m(o){if(c)return c;w||(w=true,console.warn("[userutils] createBillingProxy: canonicalOrigin not set \u2014 falling back to request origin. Set canonicalOrigin to the public URL of this app to prevent Host-header spoofing of Stripe success URLs."));try{let a=new URL(o.url);return a.protocol!=="http:"&&a.protocol!=="https:"?null:a.origin}catch{return null}}function g(o){let a=M(o);if(!a)return null;let p=C(a,e.authSecret);return p?{jwt:a,payload:p}:null}function u(o,a){let p=E(o,e.authSecret,s,300);if(p){let h=e.secureCookies!==false?"; Secure":"",S=e.cookieDomain?`; Domain=${e.cookieDomain}`:"";a.append("Set-Cookie",`stackauth_jwt=${p}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${i}${h}${S}`);}}async function d(o,a){let p=g(o);if(!p)return Response.json({error:"Unauthorized"},{status:401});let h=D(p.jwt,n),S=await fetch(`${e.stacknetUrl}${a}`,{headers:h,signal:AbortSignal.timeout(15e3)}),k=await S.json().catch(()=>({})),y=new Headers({"Content-Type":"application/json"});return u(p.jwt,y),new Response(JSON.stringify(k),{status:S.status,headers:y})}async function l(o,a,p){let h=g(o);if(!h)return Response.json({error:"Unauthorized"},{status:401});let S=r.validateRequest(o);if(!S.valid)return Response.json({error:S.error||"CSRF validation failed"},{status:403});let k=h.payload.sub||h.payload.user_id||"unknown";if(!(await t.check(`billing:${k}`)).allowed)return Response.json({error:"Too many requests"},{status:429});let x=await o.json().catch(()=>({})),R=D(h.jwt,n);R["Content-Type"]="application/json";let P=await fetch(`${e.stacknetUrl}${a}`,{method:"POST",headers:R,body:JSON.stringify({...x,...p}),signal:AbortSignal.timeout(15e3)}),I=await P.json().catch(()=>({})),A=new Headers({"Content-Type":"application/json"});return u(h.jwt,A),new Response(JSON.stringify(I),{status:P.status,headers:A})}let f=`/api/v2/stacks/${encodeURIComponent(e.stackId)}`;return {plans:{GET:async o=>{let a=await fetch(`${e.stacknetUrl}${f}/plans`,{signal:AbortSignal.timeout(1e4)}),p=await a.json().catch(()=>({}));return Response.json(p,{status:a.status})}},subscription:{GET:(o=>d(o,`${f}/subscription`))},subscribe:{POST:(o=>{let a=m(o);return a?l(o,`${f}/subscribe`,{successUrl:`${a}/billing/success?session_id={CHECKOUT_SESSION_ID}`,cancelUrl:`${a}/pricing`}):Promise.resolve(Response.json({error:"Invalid request origin for checkout"},{status:400}))})},cancel:{POST:(o=>l(o,`${f}/cancel-subscription`))},usage:{GET:(o=>d(o,"/v1/account/usage"))},history:{GET:(o=>d(o,`${f}/billing`))},prepaid:{POST:(o=>{let a=m(o);return a?l(o,`${f}/prepaid`,{successUrl:`${a}/pricing/prepaid/success?session_id={CHECKOUT_SESSION_ID}`,cancelUrl:`${a}/pricing/prepaid`}):Promise.resolve(Response.json({error:"Invalid request origin for checkout"},{status:400}))})},verifyPrepaid:{POST:(o=>l(o,`${f}/verify-prepaid`))},verifySession:{POST:(o=>l(o,`${f}/verify-session`))},subscribeSol:{POST:(o=>l(o,`${f}/subscribe-sol`))},prepaidSol:{POST:(o=>l(o,`${f}/prepaid-sol`))},topup:{POST:(o=>l(o,"/v1/account/topup"))}}}function Pe(e){return async function(t){let n=t.headers.get("stripe-signature");if(!n)return Response.json({error:"Missing Stripe signature"},{status:400});try{let s=await t.text(),i=await fetch(`${e.stacknetUrl}/api/v2/stacks/${encodeURIComponent(e.stackId)}/webhook/stripe`,{method:"POST",headers:{"Content-Type":"application/json","stripe-signature":n},body:s,signal:AbortSignal.timeout(1e4)}),c=await i.json().catch(()=>({received:!0}));return Response.json(c,{status:i.status})}catch{return Response.json({error:"Webhook processing failed"},{status:502})}}}function G(){return {"Strict-Transport-Security":"max-age=63072000; includeSubDomains; preload","X-Content-Type-Options":"nosniff","X-Frame-Options":"DENY","X-XSS-Protection":"0","Referrer-Policy":"strict-origin-when-cross-origin","Permissions-Policy":"camera=(), microphone=(), geolocation=()"}}function Ce(e){return async r=>{let t=await e(r),n=G(),s=new Headers(t.headers);for(let[i,c]of Object.entries(n))s.set(i,c);return new Response(t.body,{status:t.status,statusText:t.statusText,headers:s})}}function be(){return Object.entries(G()).map(([e,r])=>({key:e,value:r}))}function z(e){return {"Content-Type":"application/json",...D(e.jwt,e.stacknetJwtSecret)}}async function ve(e,r){let t=await fetch(`${e.stacknetBaseUrl}/v1/preview-codes`,{method:"POST",headers:z(e),body:JSON.stringify({token_budget:r.tokenBudget,code:r.code,expires_at:r.expiresAt,name:r.name})});return t.ok?await t.json():{error:await t.text().catch(()=>"")||`HTTP ${t.status}`,status:t.status}}async function $e(e){let r=await fetch(`${e.stacknetBaseUrl}/v1/preview-codes`,{method:"GET",headers:z(e)});return r.ok?(await r.json()).codes:{error:await r.text().catch(()=>"")||`HTTP ${r.status}`,status:r.status}}async function je(e,r){let t=await fetch(`${e}/v1/preview-codes/${encodeURIComponent(r)}`,{method:"GET"});return t.status===404||!t.ok?null:await t.json()}async function Te(e,r){let t=await fetch(`${e.stacknetBaseUrl}/v1/preview-codes/${encodeURIComponent(r)}`,{method:"DELETE",headers:z(e)});return t.ok?await t.json():{error:await t.text().catch(()=>"")||`HTTP ${t.status}`,status:t.status}}async function Ae(e,r,t){let n=await fetch(`${e}/v1/preview-codes/${encodeURIComponent(r)}/redeem`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({tokens:t})});return n.ok?await n.json():{error:await n.text().catch(()=>"")||`HTTP ${n.status}`,status:n.status}}var V=["127924fc17182f69cb463d9977348c482d2e784dfdd16f9e6eecc4db07fb04c3","HxLBLBjKbSrJSFCE7LGs9FxMA6M5bztmpNoLuB43HTFs"];function Oe(e){return e?V.includes(e):false}var Ie=V[0];
|
|
2
2
|
exports.PREVIEW_CODE_ADMIN_GLOBAL_ID=Ie;exports.PREVIEW_CODE_ADMIN_GLOBAL_IDS=V;exports.buildStackNetHeaders=D;exports.createAuthCallback=pe;exports.createBillingProxy=Re;exports.createCSRFProtection=b;exports.createGoogleOneTapHandler=ke;exports.createInMemoryRateLimiter=v;exports.createInMemoryReplayStore=ue;exports.createLogoutHandler=fe;exports.createOAuthHandlers=Se;exports.createOTPHandler=we;exports.createPreviewCodeHandler=xe;exports.createSessionHandler=me;exports.createWebhookHandler=Pe;exports.decodeJWTPayload=N;exports.extractIP=T;exports.extractJwt=M;exports.generateToken=F;exports.getPreviewCode=je;exports.isPreviewCodeAdmin=Oe;exports.listPreviewCodes=$e;exports.maybeRefreshJWT=E;exports.mintPreviewCode=ve;exports.nextSecurityHeaders=be;exports.redeemPreviewCode=Ae;exports.resignForStackNet=Q;exports.revokePreviewCode=Te;exports.securityHeaders=G;exports.signJWT=j;exports.verifyJWT=C;exports.verifyJWTSignature=X;exports.withSecurityHeaders=Ce;
|
package/dist/server/index.d.cts
CHANGED
|
@@ -175,7 +175,10 @@ declare function createSessionHandler(config: Pick<ServerConfig, 'authSecret' |
|
|
|
175
175
|
interface OTPHandlerConfig extends Pick<ServerConfig, 'authSecret' | 'secureCookies' | 'cookieDomain' | 'sessionMaxAge' | 'jwtExpiry'> {
|
|
176
176
|
/** The OTP secret to validate against */
|
|
177
177
|
otpSecret: string;
|
|
178
|
-
/** Rate limiter (default:
|
|
178
|
+
/** Rate limiter (default: 3 attempts per 5 min per IP).
|
|
179
|
+
* Tightened from 5 → 3 to match the hard cap stacknet enforces on
|
|
180
|
+
* the preview-code lookup path; treats both surfaces consistently
|
|
181
|
+
* so a "3 strikes" UX message is honest end-to-end. */
|
|
179
182
|
rateLimiter?: RateLimiter;
|
|
180
183
|
/** How to extract the real client IP for rate-limit keys. Defaults to
|
|
181
184
|
* `{ trustedProxyCount: 1 }`. Set `trustedProxyCount: 0` if the handler
|
|
@@ -244,7 +247,8 @@ interface PreviewCodeHandlerOptions {
|
|
|
244
247
|
* bearer drives direct stacknet API calls from the browser.
|
|
245
248
|
*
|
|
246
249
|
* Security:
|
|
247
|
-
* - Rate-limited per IP (
|
|
250
|
+
* - Rate-limited per IP (3 attempts / minute by default; matches
|
|
251
|
+
* the cap stacknet enforces on `GET /v1/preview-codes/:code`).
|
|
248
252
|
* - Format guard: only 6-digit numeric codes reach the upstream
|
|
249
253
|
* validator so nothing weird hits stacknet.
|
|
250
254
|
* - No upstream JWT is trusted — the stacknet response is a
|
package/dist/server/index.d.ts
CHANGED
|
@@ -175,7 +175,10 @@ declare function createSessionHandler(config: Pick<ServerConfig, 'authSecret' |
|
|
|
175
175
|
interface OTPHandlerConfig extends Pick<ServerConfig, 'authSecret' | 'secureCookies' | 'cookieDomain' | 'sessionMaxAge' | 'jwtExpiry'> {
|
|
176
176
|
/** The OTP secret to validate against */
|
|
177
177
|
otpSecret: string;
|
|
178
|
-
/** Rate limiter (default:
|
|
178
|
+
/** Rate limiter (default: 3 attempts per 5 min per IP).
|
|
179
|
+
* Tightened from 5 → 3 to match the hard cap stacknet enforces on
|
|
180
|
+
* the preview-code lookup path; treats both surfaces consistently
|
|
181
|
+
* so a "3 strikes" UX message is honest end-to-end. */
|
|
179
182
|
rateLimiter?: RateLimiter;
|
|
180
183
|
/** How to extract the real client IP for rate-limit keys. Defaults to
|
|
181
184
|
* `{ trustedProxyCount: 1 }`. Set `trustedProxyCount: 0` if the handler
|
|
@@ -244,7 +247,8 @@ interface PreviewCodeHandlerOptions {
|
|
|
244
247
|
* bearer drives direct stacknet API calls from the browser.
|
|
245
248
|
*
|
|
246
249
|
* Security:
|
|
247
|
-
* - Rate-limited per IP (
|
|
250
|
+
* - Rate-limited per IP (3 attempts / minute by default; matches
|
|
251
|
+
* the cap stacknet enforces on `GET /v1/preview-codes/:code`).
|
|
248
252
|
* - Format guard: only 6-digit numeric codes reach the upstream
|
|
249
253
|
* validator so nothing weird hits stacknet.
|
|
250
254
|
* - No upstream JWT is trusted — the stacknet response is a
|