@nexus-cross/onramp 1.3.3-beta.1 → 1.3.3-beta.2
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/adapters/alchemypay/index.js +1 -1
- package/dist/{chunk-U66BKMXR.js → chunk-HTGBDHNZ.js} +1 -1
- package/dist/chunk-I7XK67RS.js +1 -0
- package/dist/{chunk-PBPJO43F.js → chunk-KDY5DJD6.js} +1 -1
- package/dist/index.js +1 -1
- package/dist/react/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-5MH4I7ZN.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a,b as m}from"../../chunk-
|
|
1
|
+
import{a,b as m}from"../../chunk-KDY5DJD6.js";import{c as e,d as y,e as r,i as o}from"../../chunk-I7XK67RS.js";export{a as ALCHEMY_PAY_RAMP_BASE_URL,o as AlchemyPayBrowserAdapter,m as buildAlchemyPayUrl,y as mapCryptoToAlchemyPay,r as mapFiatToAlchemyPay,e as mapNetworkToAlchemyPay};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as n,i as m}from"./chunk-
|
|
1
|
+
import{a as n,i as m}from"./chunk-I7XK67RS.js";var a=class{constructor(t,i,s){this.port=t;this.walletState=i;this.networks=s}async execute(t){let i=t.address??this.walletState.getAddress();if(!i)throw new n("MISSING_ADDRESS","Wallet address is not available");if(!t.network||!t.network.trim())throw new n("UNSUPPORTED_NETWORK","Network identifier is empty");if(!t.crypto||!t.crypto.trim())throw new n("UNSUPPORTED_CRYPTO","Crypto symbol is empty");if(!this.networks.findByIdentifier(t.network))throw new n("UNSUPPORTED_NETWORK",`Unknown network "${t.network}"`,{network:t.network});let o=typeof t.fiatAmount=="number"&&t.fiatAmount>0,p=typeof t.cryptoAmount=="number"&&t.cryptoAmount>0;if(t.fiatAmount!==void 0&&!o)throw new n("INVALID_AMOUNT","fiatAmount must be a positive number");if(t.cryptoAmount!==void 0&&!p)throw new n("INVALID_AMOUNT","cryptoAmount must be a positive number");let e=await this.port.getEligibility({network:t.network});if(!e.allowed)throw new n("PROVIDER_DISABLED",e.message??"On-ramp is not available in this region",{reason:e.reason,country:e.country});return this.port.open({...t,address:i})}};var O={findByIdentifier(r){if(!(!r||!r.trim()))return{id:r,name:r}}},R={getAddress:()=>{}};function f(r){let{walletState:t=R,networks:i=O,...s}=r,o=new m(s),p=new a(o,t,i);return{port:o,getEligibility:e=>o.getEligibility(e),open:e=>p.execute(e),onStatus:e=>o.onStatus?o.onStatus(e):(()=>{})}}export{a,f as b};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var p=class extends Error{constructor(e,t,n){super(t),this.name="OnRampError",this.code=e,this.details=n}};function L(i){return["unsupported_country","unsupported_region","sanctioned","kyc_required","provider_outage","unknown"].includes(i)?i:"unknown"}var O={cross:"CROSS","cross-testnet":"CROSS",ethereum:"ETH",eth:"ETH",bsc:"BSC","bnb-chain":"BSC","bsc-testnet":"BSC",polygon:"MATIC",matic:"MATIC",arbitrum:"ARBITRUM",optimism:"OPTIMISM",base:"BASE",1:"ETH",56:"BSC",97:"BSC",137:"MATIC",42161:"ARBITRUM",10:"OPTIMISM",8453:"BASE",612044:"CROSS",612055:"CROSS"};function y(i){let e=i.trim().toLowerCase();return O[e]??i.toUpperCase()}function h(i){return i.trim().toUpperCase()}function N(i){return i.trim().toUpperCase()}var b={dev:"https://dev-embedded-wallet-gateway.crosstoken.io/api/v1",stage:"https://stg-embedded-wallet-gateway.crosstoken.io/api/v1",production:"https://embedded-wallet-gateway.crosstoken.io/api/v1"},g={eligibility:"/onramp/allowed",sign:"/onramp/url"};function R(i){try{return import.meta.env?.[i]}catch{return}}function m(i){if(!(typeof process>"u"||!process.env))switch(i){case"NEXT_PUBLIC_CROSSX_ENVIRONMENT":return process.env.NEXT_PUBLIC_CROSSX_ENVIRONMENT;case"CROSSX_ENVIRONMENT":return process.env.CROSSX_ENVIRONMENT;case"NEXT_PUBLIC_CROSSX_ONRAMP_BASE_URL":return process.env.NEXT_PUBLIC_CROSSX_ONRAMP_BASE_URL;default:return}}function E(){switch((R("VITE_CROSSX_ENVIRONMENT")??m("NEXT_PUBLIC_CROSSX_ENVIRONMENT")??m("CROSSX_ENVIRONMENT"))?.toLowerCase()){case"dev":case"development":return"dev";case"stage":case"staging":case"stg":return"stage";default:return"production"}}function f(){let i=R("VITE_CROSSX_ONRAMP_BASE_URL")??m("NEXT_PUBLIC_CROSSX_ONRAMP_BASE_URL"),e=E(),t=i??b[e];return v(t),t}function v(i){let e;try{e=new URL(i)}catch{throw new Error(`[onramp] Invalid base URL: ${i}`)}if(e.protocol==="https:")return;let t=e.hostname==="localhost"||e.hostname==="127.0.0.1"||e.hostname.endsWith(".local");if(!(e.protocol==="http:"&&t))throw new Error(`[onramp] base URL must be https (or http://localhost for dev). Got: ${i}`)}var T=5e3,I=1e4,d=class{constructor(e){if(!e.projectId||!e.projectId.trim())throw new Error("[HttpOnRampRepository] projectId is required");this.projectId=e.projectId,this.appId=e.appId,this.appType=e.appType,this.baseUrl=(e.baseUrl??f()).replace(/\/+$/,""),this.paths={eligibility:e.paths?.eligibility??g.eligibility,sign:e.paths?.sign??g.sign},this.eligibilityTimeoutMs=e.eligibilityTimeoutMs??T,this.signTimeoutMs=e.signTimeoutMs??I,this.fallbackProvider=e.fallbackProvider??"alchemypay"}async fetchEligibility(e){let t=this.baseUrl+this.paths.eligibility,n={provider:this.fallbackProvider,allowed:!1,reason:"unknown"},o;try{let r=new AbortController,s=setTimeout(()=>r.abort(),this.eligibilityTimeoutMs),a=await fetch(t,{method:"GET",signal:r.signal,headers:this.buildHeaders({accept:!0}),credentials:"include"});if(clearTimeout(s),!a.ok)return n;o=await a.json()}catch{return n}return this.parseEligibility(o)}async requestSignedUrl(e){let t=this.baseUrl+this.paths.sign,n=new AbortController,o=setTimeout(()=>n.abort(),this.signTimeoutMs);try{let r=e.params,s={address:r.address};r.redirectUrl&&(s.redirect_url=r.redirectUrl),r.crypto&&r.crypto.trim()&&(s.crypto=h(r.crypto)),r.network&&r.network.trim()&&(s.network=y(r.network)),r.fiat&&r.fiat.trim()&&(s.fiat=r.fiat.trim()),typeof r.cryptoAmount=="number"&&r.cryptoAmount>0?s.crypto_amount=r.cryptoAmount:typeof r.fiatAmount=="number"&&r.fiatAmount>0&&(s.fiat_amount=r.fiatAmount);let a=await fetch(t,{method:"POST",signal:n.signal,headers:this.buildHeaders({accept:!0,contentType:!0,idempotency:!0}),credentials:"include",body:JSON.stringify(s)});if(!a.ok)throw new p("SIGN_FAILED",`Sign endpoint returned ${a.status}`);let c=await a.json(),l=c&&typeof c=="object"&&c.data&&typeof c.data=="object"?c.data:c,u=l?l.url:void 0;if(typeof u!="string"||!u)throw new p("SIGN_FAILED","Sign response missing url");return u}finally{clearTimeout(o)}}buildHeaders(e){let t={"X-Project-Id":this.projectId};return e.accept&&(t.Accept="application/json"),e.contentType&&(t["Content-Type"]="application/json"),e.idempotency&&(t["Idempotency-Key"]=S()),this.appId&&(t["X-App-Id"]=this.appId),this.appType&&(t["X-App-Type"]=this.appType),t}parseEligibility(e){if(!e||typeof e!="object")return{provider:this.fallbackProvider,allowed:!1,reason:"unknown"};let t=e,n=t.data&&typeof t.data=="object"?t.data:t,o=n.isAllowed===!0,r={provider:this.fallbackProvider,allowed:o};return typeof n.countCode=="string"&&(r.country=n.countCode),o||(r.reason="unknown"),r}};function S(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`idem_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,10)}`}var _=300*1e3,P="width=480,height=720,popup=yes",A=500,U=300,M=["https://ramp.alchemypay.org","https://ramptest.alchemypay.org","https://ramp-sandbox.alchemypay.org"],w=class{constructor(e){this.provider="alchemypay";this.cache=new Map;this.statusListeners=new Set;this.activeWatch=null;this.cancelGraceTimer=null;if(e.repository)this.repository=e.repository;else{if(!e.projectId||!e.projectId.trim())throw new Error("[AlchemyPayBrowserAdapter] projectId is required when repository is not provided");this.repository=new d({projectId:e.projectId,appId:e.appId,appType:e.appType})}this.eligibilityTtlMs=e.eligibilityTtlMs??_,this.windowFeatures=e.windowFeatures??P,this.trustedOrigins=e.trustedOrigins??M,this.popupPollIntervalMs=e.popupPollIntervalMs??A,this.cancelGraceMs=e.cancelGraceMs??U}async getEligibility(e){let t=`network:${e?.network??""}`,n=this.cache.get(t);if(n&&n.expiresAt>Date.now())return n.value;let o;try{o=await this.repository.fetchEligibility({network:e?.network})}catch{o={provider:this.provider,allowed:!1,reason:"unknown"}}return this.storeCache(t,o),o}storeCache(e,t){let n=typeof t.expiresAt=="number"?t.expiresAt:Date.now()+this.eligibilityTtlMs;this.cache.set(e,{value:t,expiresAt:n})}onStatus(e){return this.statusListeners.add(e),()=>{this.statusListeners.delete(e)}}async close(e){if(this.activeWatch?.sessionId===e){try{this.activeWatch.popup.close()}catch{}this.stopWatching()}}emit(e){for(let t of this.statusListeners)try{t(e)}catch(n){console.error("[onramp] onStatus listener threw:",n)}}startWatching(e,t){this.stopWatching(),console.debug("[onramp] watching popup",{sessionId:e,trustedOrigins:this.trustedOrigins});let n=setInterval(()=>{t.closed&&(clearInterval(n),console.debug("[onramp] popup closed, waiting grace",{sessionId:e,graceMs:this.cancelGraceMs}),this.cancelGraceTimer=setTimeout(()=>{this.cancelGraceTimer=null,console.debug("[onramp] grace expired \u2192 cancelled",{sessionId:e}),this.emit({sessionId:e,status:"cancelled"}),this.stopWatching()},this.cancelGraceMs))},this.popupPollIntervalMs),o=r=>{if(!this.trustedOrigins.includes(r.origin))return;console.debug("[onramp] message from trusted origin",{sessionId:e,origin:r.origin,data:r.data});let s=r.data;if(!s||typeof s!="object")return;let a=String(s.status??s.type??"").toLowerCase(),c=typeof s.txHash=="string"?s.txHash:void 0,l=typeof s.message=="string"?s.message:void 0;/complete|success|paid|pay-success/.test(a)?(console.debug("[onramp] message \u2192 completed",{sessionId:e,status:a,txHash:c}),this.emit({sessionId:e,status:"completed",txHash:c}),this.stopWatching()):/cancel/.test(a)?(console.debug("[onramp] message \u2192 cancelled",{sessionId:e,status:a}),this.emit({sessionId:e,status:"cancelled"}),this.stopWatching()):/fail|error/.test(a)?(console.debug("[onramp] message \u2192 failed",{sessionId:e,status:a,errorMessage:l}),this.emit({sessionId:e,status:"failed",errorMessage:l}),this.stopWatching()):/pending|processing/.test(a)?(console.debug("[onramp] message \u2192 pending",{sessionId:e,status:a}),this.emit({sessionId:e,status:"pending"})):console.debug("[onramp] message ignored (unknown status)",{sessionId:e,rawStatus:a,data:r.data})};window.addEventListener("message",o),this.activeWatch={sessionId:e,popup:t,cleanup:()=>{clearInterval(n),window.removeEventListener("message",o)}}}stopWatching(){this.cancelGraceTimer&&(clearTimeout(this.cancelGraceTimer),this.cancelGraceTimer=null),this.activeWatch&&(this.activeWatch.cleanup(),this.activeWatch=null)}async open(e){if(!e.address)throw new p("MISSING_ADDRESS","address is required");let t;try{t=await this.repository.requestSignedUrl({params:e})}catch(r){throw r instanceof p?r:new p("SIGN_FAILED",r instanceof Error?r.message:"Failed to obtain signed URL",{cause:String(r)})}if(typeof window>"u")throw new p("POPUP_BLOCKED","window is not available (SSR)");let n=window.open(t,"_blank",this.windowFeatures);if(!n)throw new p("POPUP_BLOCKED","Popup window was blocked by the browser");let o=k();return this.startWatching(o,n),{sessionId:o,url:t,provider:this.provider,openedAt:Date.now()}}};function k(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`ses_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,10)}`}export{p as a,L as b,y as c,h as d,N as e,g as f,f as g,d as h,w as i};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as o,d as a,e as s}from"./chunk-
|
|
1
|
+
import{c as o,d as a,e as s}from"./chunk-I7XK67RS.js";var n="https://ramp.alchemypay.org";function m(r){if(r.preSignedUrl)return i(r.preSignedUrl,"preSignedUrl");if(!r.appId)throw new Error("[AlchemyPay] appId or preSignedUrl is required to build a URL");if(!r.address)throw new Error("[AlchemyPay] address is required");let t={appId:r.appId,crypto:a(r.crypto),network:o(r.network),address:r.address};r.fiat&&r.fiat.trim()&&(t.fiat=s(r.fiat)),typeof r.cryptoAmount=="number"&&r.cryptoAmount>0?t.cryptoAmount=String(r.cryptoAmount):typeof r.fiatAmount=="number"&&r.fiatAmount>0&&(t.fiatAmount=String(r.fiatAmount)),r.redirectUrl&&(t.redirectUrl=r.redirectUrl);let e=new URLSearchParams(t).toString();return`${n}/?${e}`}function i(r,t){try{if(new URL(r).protocol!=="https:")throw new Error(`${t} must use https`);return r}catch{throw new Error(`${t} is not a valid URL: ${r}`)}}export{n as a,m as b};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as u,b as P}from"./chunk-
|
|
1
|
+
import{a as u,b as P}from"./chunk-HTGBDHNZ.js";import{a as s}from"./chunk-KDY5DJD6.js";import{a as i,b as O,c as d,d as g,e as R,f as b,g as h,h as w}from"./chunk-I7XK67RS.js";var l=class{constructor(e){this.port=e}execute(e){return this.port.getEligibility(e)}};var f="__crossx_mock_onramp_warning__",c=class{constructor(e={}){this.appId=e.appId,this.appSecret=e.appSecret,this.provider=e.provider??"alchemypay";let t=e.eligibility;this.eligibilityFn=typeof t=="function"?t:()=>t??{allowed:!0,country:"KR"};let o=e.signMode??(e.appSecret?"hmac":"unsigned");this.signMode=o==="hmac"&&!e.appSecret?"unsigned":o,this.warnOnce()}warnOnce(){if(typeof globalThis>"u")return;let e=globalThis;e[f]||(e[f]=!0,console.warn("[onramp] MockOnRampRepository active \u2014 appSecret may be exposed in this bundle. Use only for dev/demo, never in production."))}async fetchEligibility(e){let t=this.eligibilityFn(e);return{provider:t.provider??this.provider,allowed:t.allowed??!0,country:t.country,reason:t.allowed===!1?t.reason??"unknown":t.reason,message:t.message,expiresAt:t.expiresAt}}async requestSignedUrl(e){let{params:t}=e;if(!t.address)throw new i("MISSING_ADDRESS","address is required");if(this.signMode==="log-only"){let r=`${s}/?mock=log-only&address=${encodeURIComponent(t.address)}`;return console.log("[onramp:mock] log-only sign \u2014 would open:",r),r}let o=this.buildAlchemyPayParams(t),n=Object.keys(o).sort().map(r=>`${r}=${encodeURIComponent(o[r])}`).join("&");if(this.signMode==="unsigned")return`${s}/?${n}`;let a=await A(this.appSecret,n);return`${s}/?${n}&sign=${encodeURIComponent(a)}`}buildAlchemyPayParams(e){let t={crypto:g(e.crypto),network:d(e.network),address:e.address,timestamp:String(Date.now())};return this.appId&&(t.appId=this.appId),e.fiat&&e.fiat.trim()&&(t.fiat=R(e.fiat)),typeof e.cryptoAmount=="number"&&e.cryptoAmount>0?t.cryptoAmount=String(e.cryptoAmount):typeof e.fiatAmount=="number"&&e.fiatAmount>0&&(t.fiatAmount=String(e.fiatAmount)),typeof e.redirectUrl=="string"&&e.redirectUrl&&(t.redirectUrl=e.redirectUrl),t}};async function A(p,e){if(typeof crypto>"u"||!crypto.subtle)throw new i("SIGN_FAILED","Web Crypto (crypto.subtle) not available \u2014 cannot HMAC in this environment");let t=new TextEncoder,o=await crypto.subtle.importKey("raw",t.encode(p),{name:"HMAC",hash:"SHA-256"},!1,["sign"]),n=await crypto.subtle.sign("HMAC",o,t.encode(e)),a=new Uint8Array(n),r="";for(let m=0;m<a.length;m++)r+=String.fromCharCode(a[m]);if(typeof btoa=="function")return btoa(r);let y=globalThis.Buffer;if(y)return y.from(r,"binary").toString("base64");throw new i("SIGN_FAILED","No base64 encoder available")}export{b as DEFAULT_ONRAMP_PATHS,l as GetOnRampEligibilityUseCase,w as HttpOnRampRepository,c as MockOnRampRepository,i as OnRampError,u as OpenOnRampUseCase,P as createOnRamp,h as getOnRampBaseUrl,O as normalizeDisallowReason};
|
package/dist/react/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as h}from"../chunk-
|
|
1
|
+
import{b as h}from"../chunk-HTGBDHNZ.js";import{a as g}from"../chunk-I7XK67RS.js";import{useMemo as I}from"react";import{createContext as T,useContext as V}from"react";var O=T(null);function w(){let e=V(O);if(!e)throw new Error("useOnRamp must be used within <OnRampProvider>");return e}import{jsx as F}from"react/jsx-runtime";function _({config:e,children:i}){let a=I(()=>({onramp:h(e)}),[e.projectId,e.appId,e.appType,e.repository,e.eligibilityTtlMs,e.windowFeatures,e.walletState,e.networks]);return F(O.Provider,{value:a,children:i})}import{useCallback as W,useEffect as Y,useRef as B,useState as v}from"react";import{useCallback as k,useEffect as N,useRef as P,useState as U}from"react";var x={maxAttempts:12,initialDelayMs:500,maxDelayMs:3e3,factor:1.5,enabled:!0};function M(e={}){let{onramp:i}=w(),[a,f]=U(void 0),[c,d]=U(!0),s={maxAttempts:e.retry?.maxAttempts??x.maxAttempts,initialDelayMs:e.retry?.initialDelayMs??x.initialDelayMs,maxDelayMs:e.retry?.maxDelayMs??x.maxDelayMs,factor:e.retry?.factor??x.factor,enabled:e.retry?.enabled??x.enabled},R=P(s);R.current=s;let o=P(null),m=p=>!!p&&p.allowed===!1&&p.reason==="unknown",r=k(async p=>{o.current&&(o.current.cancelled=!0);let n={cancelled:!1};o.current=n,d(!0);let t=R.current,u=0,y=t.initialDelayMs;for(;!n.cancelled;){u+=1;let l;try{l=await i.getEligibility({network:p})}catch{l={provider:"alchemypay",allowed:!1,reason:"unknown"}}if(n.cancelled)return;if(!(t.enabled&&m(l)&&u<t.maxAttempts)){f(l),d(!1);return}await new Promise(C=>{let D=setTimeout(C,y)}),y=Math.min(Math.round(y*t.factor),t.maxDelayMs)}},[i]),b=k(async()=>{await r(e.network)},[r,e.network]);return N(()=>(r(e.network),()=>{o.current&&(o.current.cancelled=!0)}),[r,e.network]),{isAvailable:!0,eligibility:a,isLoading:c,refresh:b}}function H(e={}){let{onramp:i}=w(),a=M({network:e.network}),[f,c]=v(!1),[d,s]=v(null),[R,o]=v(null),[m,r]=v(null),b=B(e.onStatus);b.current=e.onStatus,Y(()=>i.onStatus(n=>{r(n),b.current?.(n)}),[i]);let p=W(async n=>{s(null),c(!0);try{let t=await i.open(n);return o(t),t}catch(t){let u=t instanceof g?t:new g("PROVIDER_DISABLED",t instanceof Error?t.message:"On-ramp failed");throw s(u),u}finally{c(!1)}},[i]);return{...a,open:p,isOpening:f,error:d,lastSession:R,lastStatus:m}}import{useContext as q}from"react";function z(){return q(O)?.onramp??null}import{useCallback as A,useContext as G,useEffect as J,useRef as L,useState as j}from"react";var E={maxAttempts:12,initialDelayMs:500,maxDelayMs:3e3,factor:1.5,enabled:!0};function K(e={}){let a=G(O)?.onramp??null,[f,c]=j(void 0),[d,s]=j(!!a),R={maxAttempts:e.retry?.maxAttempts??E.maxAttempts,initialDelayMs:e.retry?.initialDelayMs??E.initialDelayMs,maxDelayMs:e.retry?.maxDelayMs??E.maxDelayMs,factor:e.retry?.factor??E.factor,enabled:e.retry?.enabled??E.enabled},o=L(R);o.current=R;let m=L(null),r=A(async p=>{if(!a){c(void 0),s(!1);return}m.current&&(m.current.cancelled=!0);let n={cancelled:!1};m.current=n,s(!0);let t=o.current,u=0,y=t.initialDelayMs;for(;!n.cancelled;){u+=1;let l;try{l=await a.getEligibility({network:p})}catch{l={provider:"alchemypay",allowed:!1,reason:"unknown"}}if(n.cancelled)return;let S=l.allowed===!1&&l.reason==="unknown";if(!(t.enabled&&S&&u<t.maxAttempts)){c(l),s(!1);return}await new Promise(D=>setTimeout(D,y)),y=Math.min(Math.round(y*t.factor),t.maxDelayMs)}},[a]),b=A(async()=>{await r(e.network)},[r,e.network]);return J(()=>(r(e.network),()=>{m.current&&(m.current.cancelled=!0)}),[r,e.network]),{isAvailable:!!a,eligibility:f,isLoading:d,refresh:b}}export{g as OnRampError,_ as OnRampProvider,H as useOnRamp,M as useOnRampEligibility,z as useOptionalOnRamp,K as useOptionalOnRampEligibility};
|
package/package.json
CHANGED
package/dist/chunk-5MH4I7ZN.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var p=class extends Error{constructor(e,t,n){super(t),this.name="OnRampError",this.code=e,this.details=n}};function L(i){return["unsupported_country","unsupported_region","sanctioned","kyc_required","provider_outage","unknown"].includes(i)?i:"unknown"}var b={cross:"CROSS","cross-testnet":"CROSS",ethereum:"ETH",eth:"ETH",bsc:"BSC","bnb-chain":"BSC","bsc-testnet":"BSC",polygon:"MATIC",matic:"MATIC",arbitrum:"ARBITRUM",optimism:"OPTIMISM",base:"BASE",1:"ETH",56:"BSC",97:"BSC",137:"MATIC",42161:"ARBITRUM",10:"OPTIMISM",8453:"BASE",612044:"CROSS",612055:"CROSS"};function y(i){let e=i.trim().toLowerCase();return b[e]??i.toUpperCase()}function h(i){return i.trim().toUpperCase()}function D(i){return i.trim().toUpperCase()}var O={dev:"https://dev-embedded-wallet-gateway.crosstoken.io/api/v1",stage:"https://stg-embedded-wallet-gateway.crosstoken.io/api/v1",production:"https://embedded-wallet-gateway.crosstoken.io/api/v1"},g={eligibility:"/onramp/allowed",sign:"/onramp/url"};function f(i){try{return import.meta.env?.[i]}catch{return}}function m(i){if(!(typeof process>"u"))return process.env?.[i]}function v(){switch((f("VITE_CROSSX_ENVIRONMENT")??m("NEXT_PUBLIC_CROSSX_ENVIRONMENT")??m("CROSSX_ENVIRONMENT"))?.toLowerCase()){case"dev":case"development":return"dev";case"stage":case"staging":case"stg":return"stage";default:return"production"}}function R(){let i=f("VITE_CROSSX_ONRAMP_BASE_URL")??m("NEXT_PUBLIC_CROSSX_ONRAMP_BASE_URL"),e=v(),t=i??O[e];return E(t),t}function E(i){let e;try{e=new URL(i)}catch{throw new Error(`[onramp] Invalid base URL: ${i}`)}if(e.protocol==="https:")return;let t=e.hostname==="localhost"||e.hostname==="127.0.0.1"||e.hostname.endsWith(".local");if(!(e.protocol==="http:"&&t))throw new Error(`[onramp] base URL must be https (or http://localhost for dev). Got: ${i}`)}var T=5e3,I=1e4,d=class{constructor(e){if(!e.projectId||!e.projectId.trim())throw new Error("[HttpOnRampRepository] projectId is required");this.projectId=e.projectId,this.appId=e.appId,this.appType=e.appType,this.baseUrl=(e.baseUrl??R()).replace(/\/+$/,""),this.paths={eligibility:e.paths?.eligibility??g.eligibility,sign:e.paths?.sign??g.sign},this.eligibilityTimeoutMs=e.eligibilityTimeoutMs??T,this.signTimeoutMs=e.signTimeoutMs??I,this.fallbackProvider=e.fallbackProvider??"alchemypay"}async fetchEligibility(e){let t=this.baseUrl+this.paths.eligibility,n={provider:this.fallbackProvider,allowed:!1,reason:"unknown"},o;try{let r=new AbortController,a=setTimeout(()=>r.abort(),this.eligibilityTimeoutMs),s=await fetch(t,{method:"GET",signal:r.signal,headers:this.buildHeaders({accept:!0}),credentials:"include"});if(clearTimeout(a),!s.ok)return n;o=await s.json()}catch{return n}return this.parseEligibility(o)}async requestSignedUrl(e){let t=this.baseUrl+this.paths.sign,n=new AbortController,o=setTimeout(()=>n.abort(),this.signTimeoutMs);try{let r=e.params,a={address:r.address};r.redirectUrl&&(a.redirect_url=r.redirectUrl),r.crypto&&r.crypto.trim()&&(a.crypto=h(r.crypto)),r.network&&r.network.trim()&&(a.network=y(r.network)),r.fiat&&r.fiat.trim()&&(a.fiat=r.fiat.trim()),typeof r.cryptoAmount=="number"&&r.cryptoAmount>0?a.crypto_amount=r.cryptoAmount:typeof r.fiatAmount=="number"&&r.fiatAmount>0&&(a.fiat_amount=r.fiatAmount);let s=await fetch(t,{method:"POST",signal:n.signal,headers:this.buildHeaders({accept:!0,contentType:!0,idempotency:!0}),credentials:"include",body:JSON.stringify(a)});if(!s.ok)throw new p("SIGN_FAILED",`Sign endpoint returned ${s.status}`);let c=await s.json(),l=c&&typeof c=="object"&&c.data&&typeof c.data=="object"?c.data:c,u=l?l.url:void 0;if(typeof u!="string"||!u)throw new p("SIGN_FAILED","Sign response missing url");return u}finally{clearTimeout(o)}}buildHeaders(e){let t={"X-Project-Id":this.projectId};return e.accept&&(t.Accept="application/json"),e.contentType&&(t["Content-Type"]="application/json"),e.idempotency&&(t["Idempotency-Key"]=P()),this.appId&&(t["X-App-Id"]=this.appId),this.appType&&(t["X-App-Type"]=this.appType),t}parseEligibility(e){if(!e||typeof e!="object")return{provider:this.fallbackProvider,allowed:!1,reason:"unknown"};let t=e,n=t.data&&typeof t.data=="object"?t.data:t,o=n.isAllowed===!0,r={provider:this.fallbackProvider,allowed:o};return typeof n.countCode=="string"&&(r.country=n.countCode),o||(r.reason="unknown"),r}};function P(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`idem_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,10)}`}var S=300*1e3,A="width=480,height=720,popup=yes",_=500,U=300,M=["https://ramp.alchemypay.org","https://ramptest.alchemypay.org","https://ramp-sandbox.alchemypay.org"],w=class{constructor(e){this.provider="alchemypay";this.cache=new Map;this.statusListeners=new Set;this.activeWatch=null;this.cancelGraceTimer=null;if(e.repository)this.repository=e.repository;else{if(!e.projectId||!e.projectId.trim())throw new Error("[AlchemyPayBrowserAdapter] projectId is required when repository is not provided");this.repository=new d({projectId:e.projectId,appId:e.appId,appType:e.appType})}this.eligibilityTtlMs=e.eligibilityTtlMs??S,this.windowFeatures=e.windowFeatures??A,this.trustedOrigins=e.trustedOrigins??M,this.popupPollIntervalMs=e.popupPollIntervalMs??_,this.cancelGraceMs=e.cancelGraceMs??U}async getEligibility(e){let t=`network:${e?.network??""}`,n=this.cache.get(t);if(n&&n.expiresAt>Date.now())return n.value;let o;try{o=await this.repository.fetchEligibility({network:e?.network})}catch{o={provider:this.provider,allowed:!1,reason:"unknown"}}return this.storeCache(t,o),o}storeCache(e,t){let n=typeof t.expiresAt=="number"?t.expiresAt:Date.now()+this.eligibilityTtlMs;this.cache.set(e,{value:t,expiresAt:n})}onStatus(e){return this.statusListeners.add(e),()=>{this.statusListeners.delete(e)}}async close(e){if(this.activeWatch?.sessionId===e){try{this.activeWatch.popup.close()}catch{}this.stopWatching()}}emit(e){for(let t of this.statusListeners)try{t(e)}catch(n){console.error("[onramp] onStatus listener threw:",n)}}startWatching(e,t){this.stopWatching(),console.debug("[onramp] watching popup",{sessionId:e,trustedOrigins:this.trustedOrigins});let n=setInterval(()=>{t.closed&&(clearInterval(n),console.debug("[onramp] popup closed, waiting grace",{sessionId:e,graceMs:this.cancelGraceMs}),this.cancelGraceTimer=setTimeout(()=>{this.cancelGraceTimer=null,console.debug("[onramp] grace expired \u2192 cancelled",{sessionId:e}),this.emit({sessionId:e,status:"cancelled"}),this.stopWatching()},this.cancelGraceMs))},this.popupPollIntervalMs),o=r=>{if(!this.trustedOrigins.includes(r.origin))return;console.debug("[onramp] message from trusted origin",{sessionId:e,origin:r.origin,data:r.data});let a=r.data;if(!a||typeof a!="object")return;let s=String(a.status??a.type??"").toLowerCase(),c=typeof a.txHash=="string"?a.txHash:void 0,l=typeof a.message=="string"?a.message:void 0;/complete|success|paid|pay-success/.test(s)?(console.debug("[onramp] message \u2192 completed",{sessionId:e,status:s,txHash:c}),this.emit({sessionId:e,status:"completed",txHash:c}),this.stopWatching()):/cancel/.test(s)?(console.debug("[onramp] message \u2192 cancelled",{sessionId:e,status:s}),this.emit({sessionId:e,status:"cancelled"}),this.stopWatching()):/fail|error/.test(s)?(console.debug("[onramp] message \u2192 failed",{sessionId:e,status:s,errorMessage:l}),this.emit({sessionId:e,status:"failed",errorMessage:l}),this.stopWatching()):/pending|processing/.test(s)?(console.debug("[onramp] message \u2192 pending",{sessionId:e,status:s}),this.emit({sessionId:e,status:"pending"})):console.debug("[onramp] message ignored (unknown status)",{sessionId:e,rawStatus:s,data:r.data})};window.addEventListener("message",o),this.activeWatch={sessionId:e,popup:t,cleanup:()=>{clearInterval(n),window.removeEventListener("message",o)}}}stopWatching(){this.cancelGraceTimer&&(clearTimeout(this.cancelGraceTimer),this.cancelGraceTimer=null),this.activeWatch&&(this.activeWatch.cleanup(),this.activeWatch=null)}async open(e){if(!e.address)throw new p("MISSING_ADDRESS","address is required");let t;try{t=await this.repository.requestSignedUrl({params:e})}catch(r){throw r instanceof p?r:new p("SIGN_FAILED",r instanceof Error?r.message:"Failed to obtain signed URL",{cause:String(r)})}if(typeof window>"u")throw new p("POPUP_BLOCKED","window is not available (SSR)");let n=window.open(t,"_blank",this.windowFeatures);if(!n)throw new p("POPUP_BLOCKED","Popup window was blocked by the browser");let o=k();return this.startWatching(o,n),{sessionId:o,url:t,provider:this.provider,openedAt:Date.now()}}};function k(){return typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():`ses_${Date.now().toString(36)}_${Math.random().toString(36).slice(2,10)}`}export{p as a,L as b,y as c,h as d,D as e,g as f,R as g,d as h,w as i};
|