@dexterai/x402 5.3.2 → 5.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  "use strict";var rn=Object.create;var et=Object.defineProperty;var sn=Object.getOwnPropertyDescriptor;var on=Object.getOwnPropertyNames;var an=Object.getPrototypeOf,cn=Object.prototype.hasOwnProperty;var ln=(t,e)=>{for(var n in e)et(t,n,{get:e[n],enumerable:!0})},Ct=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of on(e))!cn.call(t,s)&&s!==n&&et(t,s,{get:()=>e[s],enumerable:!(r=sn(e,s))||r.enumerable});return t};var J=(t,e,n)=>(n=t!=null?rn(an(t)):{},Ct(e||!t||!t.__esModule?et(n,"default",{value:t,enumerable:!0}):n,t)),un=t=>Ct(et({},"__esModule",{value:!0}),t);var Kn={};ln(Kn,{DEFAULT_FACILITATOR_URL:()=>we,DEXTER_VAULT_PROGRAM_ID:()=>W.DEXTER_VAULT_PROGRAM_ID,INSTRUCTIONS_SYSVAR_ID:()=>W.INSTRUCTIONS_SYSVAR_ID,LiveSessionExistsError:()=>tt,SECP256R1_PROGRAM_ID:()=>W.SECP256R1_PROGRAM_ID,SessionScopeExceededError:()=>ce,TabClosedError:()=>Z,UnsupportedNetworkError:()=>ie,atomicToHuman:()=>le,buildRegisterSessionKeyInstruction:()=>ue.buildRegisterSessionKeyInstruction,buildRevokeSessionKeyInstruction:()=>ue.buildRevokeSessionKeyInstruction,buildSecp256r1VerifyInstruction:()=>wt.buildSecp256r1VerifyInstruction,buildVoucherMessage:()=>B.buildVoucherMessage,humanToAtomic:()=>ee,openTab:()=>st,payUrlWithTab:()=>tn,resolveTabOffer:()=>Te,resolveTabTerms:()=>nn,resumeTab:()=>Dt,sessionRegisterMessage:()=>B.sessionRegisterMessage,sessionRevokeMessage:()=>B.sessionRevokeMessage,tabFromGrant:()=>Lt,voucherPayloadMessage:()=>B.voucherPayloadMessage,voucherToHeader:()=>De});module.exports=un(Kn);var ie=class extends Error{constructor(n){super(`Network ${n} is not yet supported by @dexterai/x402/tab`);this.network=n;this.name="UnsupportedNetworkError"}},ce=class extends Error{constructor(n,r){super(`Session scope exceeded: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="SessionScopeExceededError"}},Z=class extends Error{constructor(n){super(`Tab ${n} is already closed`);this.channelId=n;this.name="TabClosedError"}},tt=class extends Error{constructor(n){super(`a LIVE session already exists for counterparty ${n.allowedCounterparty} (session ${n.sessionPubkeyHex.slice(0,16)}\u2026, expires ${n.expiresAtUnix}; on-chain spent=${n.spentAtomic}, crystallized=${n.crystallizedCumulativeAtomic}, frontier=${n.frontierAtomic}). Replacing it voids any signed-but-unsettled vouchers beyond the frontier. Settle the old tab first (tab.close() or POST its last voucher to /tab/settle), or pass onLiveSession: 'replace' to atomically revoke-then-register over it.`);this.details=n;this.name="LiveSessionExistsError"}};var bt=require("@solana/web3.js"),te=require("@noble/hashes/utils");var It=J(require("tweetnacl"),1);var B=require("@dexterai/vault/messages");var Ut=require("@noble/hashes/sha256");function Nt(t,e,n){return{publicKey:t.publicKey,privateKey:t.privateKey,scope:e,registration:n}}function Ot(t,e,n){if(n.length!==32)throw new Error(`channelIdBytes must be 32 bytes, got ${n.length}`);let r=BigInt(e.cumulativeAmount),s=BigInt(t.scope.maxAmountAtomic);if(r>s)throw new Error(`voucher cumulative ${r} exceeds session cap ${s}`);let o=Math.floor(Date.now()/1e3);if(o>=t.scope.expiresAtUnix)throw new Error(`session expired at ${t.scope.expiresAtUnix}, now ${o}`);let a=(0,B.voucherPayloadMessage)({channelId:n,cumulativeAmount:r,sequenceNumber:e.sequenceNumber}),i=It.default.sign.detached(a,t.privateKey);return{payload:e,sessionPublicKey:t.publicKey,sessionRegistration:t.registration,sessionSignature:i}}function nt(t){if(!/^\d+$/.test(t))throw new Error(`atomic amount must be a non-negative integer string, got "${t}"`);return BigInt(t)}function rt(t){let e=new Uint8Array(8);new DataView(e.buffer).setBigUint64(0,t.nonce,!0);let n=new TextEncoder().encode(t.sellerUrl),r=Ut.sha256.create();return r.update(t.vaultPda.toBytes()),r.update(n),r.update(e),r.digest()}var mn=3600,we="https://x402.dexter.cash",Bt=6;function ee(t,e=Bt){if(!/^\d+(\.\d+)?$/.test(t))throw new Error(`amount must be a non-negative decimal string, got "${t}"`);let[n,r=""]=t.split(".");if(r.length>e)throw new Error(`amount "${t}" has more than ${e} decimals`);let s=r.padEnd(e,"0"),o=`${n}${s}`.replace(/^0+(?=\d)/,"");return o===""?"0":o}function le(t,e=Bt){if(!/^\d+$/.test(t))throw new Error(`atomic must be a non-negative integer string, got "${t}"`);let n=t.padStart(e+1,"0"),r=n.slice(0,-e).replace(/^0+(?=\d)/,"")||"0",s=n.slice(-e).replace(/0+$/,"");return s?`${r}.${s}`:r}var Be=class{channelId;network;counterparty;internals;initialCumulativeAtomic;cumulativeAtomic;sequenceNumber=0;closed=!1;lastSignedVoucher=null;previousSignedVoucher=null;constructor(e){this.internals=e,this.channelId=e.channelIdHex,this.network=e.network,this.counterparty=e.counterparty,this.initialCumulativeAtomic=e.initialCumulativeAtomic??0n,this.cumulativeAtomic=this.initialCumulativeAtomic}get state(){let e=this.internals.totalCapAtomic-this.cumulativeAtomic,n=Math.floor(Date.now()/1e3);return{isOpen:!this.closed,spent:le(this.cumulativeAtomic.toString()),remaining:le(e.toString()),expiresInSec:Math.max(0,this.internals.expiresAtUnix-n)}}async signNextVoucher(e){if(this.closed)throw new Z(this.channelId);let n=BigInt(e);if(n<=0n)throw new Error(`voucher increment must be > 0, got ${e}`);if(n>this.internals.perUnitCapAtomic)throw new ce("cap_exceeded",`single voucher increment ${n} exceeds perUnitCap ${this.internals.perUnitCapAtomic}`);let r=this.cumulativeAtomic+n;if(r>this.internals.totalCapAtomic)throw new ce("cap_exceeded",`cumulative ${r} would exceed totalCap ${this.internals.totalCapAtomic}`);let s=this.sequenceNumber+1,o={channelId:this.channelId,cumulativeAmount:r.toString(),sequenceNumber:s},a=await this.internals.vault.signWithSession(this.internals.session,o);return this.previousSignedVoucher=this.lastSignedVoucher,this.lastSignedVoucher=a,this.sequenceNumber=s,this.cumulativeAtomic=r,a}rollbackVoucher(e){let n=this.lastSignedVoucher;if(!n||n.payload.sequenceNumber!==e.payload.sequenceNumber||n.payload.cumulativeAmount!==e.payload.cumulativeAmount)return!1;let r=this.previousSignedVoucher;if(r)this.sequenceNumber=r.payload.sequenceNumber,this.cumulativeAtomic=BigInt(r.payload.cumulativeAmount),this.lastSignedVoucher=r;else if(n.payload.sequenceNumber===1)this.sequenceNumber=0,this.cumulativeAtomic=this.initialCumulativeAtomic,this.lastSignedVoucher=null;else return!1;return this.previousSignedVoucher=null,!0}async stream(e,n){if(this.closed)throw new Z(this.channelId);let r=await this.signNextVoucher(this.internals.perUnitCapAtomic.toString()),s=new Headers(n?.headers);s.set("X-Tab-Voucher",De(r)),s.set("Accept","text/event-stream");let o=await fetch(e,{...n,headers:s});if(!o.ok){let a=await o.text().catch(()=>"");throw new Error(`tab.stream HTTP ${o.status}: ${a.slice(0,500)}`)}if(!o.body)throw new Error("tab.stream response has no body");return gn(o.body)}async close(){if(this.closed)throw new Z(this.channelId);let e={settleTx:""};this.lastSignedVoucher&&this.cumulativeAtomic>0n&&(e=await dn(this.internals.facilitatorUrl,this.lastSignedVoucher,this.internals.network));let n=(this.internals.closeMode??"revoke")==="revoke";return n&&await this.internals.vault.signCloseTab(this.internals.session,this.channelId,this.cumulativeAtomic.toString()),this.closed=!0,this.internals.session.privateKey.fill(0),{settledAmount:le(this.cumulativeAtomic.toString()),sessionRevoked:n,...e}}};function De(t){return Buffer.from(JSON.stringify({payload:t.payload,sessionPublicKey:(0,te.bytesToHex)(t.sessionPublicKey),sessionRegistration:(0,te.bytesToHex)(t.sessionRegistration),sessionSignature:(0,te.bytesToHex)(t.sessionSignature)}),"utf8").toString("base64")}function Se(t){return typeof t!="string"||!/^\d+$/.test(t)?null:BigInt(t)}function pn(t){let e;try{e=JSON.parse(t)}catch{return!1}if(typeof e!="object"||e===null)return!1;let n="non_monotonic_cumulative";if(e.error!==n&&e.reason!==n)return!1;let r=Se(e.attempted_cumulative),s=Se(e.on_chain_spent),o=Se(e.frontier);return r===null||s===null||o===null?!1:r>s&&r<=o}async function dn(t,e,n){let r=`${t.replace(/\/$/,"")}/tab/settle`,s={channelId:e.payload.channelId,cumulativeAmount:e.payload.cumulativeAmount,sequenceNumber:e.payload.sequenceNumber,sessionPublicKey:(0,te.bytesToHex)(e.sessionPublicKey),sessionSignature:(0,te.bytesToHex)(e.sessionSignature),sessionRegistration:(0,te.bytesToHex)(e.sessionRegistration),network:n},o=await fetch(r,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)}),a=await o.text();if(!o.ok){if(o.status===409&&pn(a))return{settleTx:""};throw new Error(`tab settle ${o.status}: ${a.slice(0,500)}`)}let i;try{i=JSON.parse(a)}catch{throw new Error(`tab settle returned non-JSON: ${a.slice(0,200)}`)}if(i.reason==="covered_by_frontier"){let u=Se(i.attemptedCumulative),p=Se(i.onChainSpent),d=Se(i.frontier);if(u!==null&&p!==null&&d!==null&&u>p&&u<=d)return{settleTx:""}}if(!i.settleTx)throw new Error(`tab settle returned no settleTx: ${a.slice(0,200)}`);let c={settleTx:i.settleTx};return typeof i.grossAmount=="string"&&(c.grossAmount=i.grossAmount),typeof i.feeAmount=="string"&&(c.feeAmount=i.feeAmount),typeof i.netAmount=="string"&&(c.netAmount=i.netAmount),c}async function St(t,e,n,r,s){let o=`${t.replace(/\/$/,"")}/tab/open`,a=await fetch(o,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({buyer_swig_address:e,seller:s,max_amount_atomic:n.toString(),network:r})}),i=await a.json().catch(()=>({}));if(!a.ok||!i.success||!i.armed)throw new Error(`tab_open_unprotected: ${i.error??`http_${a.status}`}`);return{armed:!0,signature:i.signature??""}}async function st(t){if(t.network!==t.vault.network)throw new ie(`options.network (${t.network}) doesn't match vault.network (${t.vault.network})`);if(t.network!=="solana:mainnet")throw new ie(t.network);let e=BigInt(Math.floor(Math.random()*4294967295)),n=new bt.PublicKey(t.vault.vaultPda),r=rt({vaultPda:n,sellerUrl:t.seller,nonce:BigInt(e)}),s=(0,te.bytesToHex)(r),o=BigInt(ee(t.perUnitCap)),a=BigInt(ee(t.totalCap));if(o<=0n)throw new Error("perUnitCap must be > 0");if(a<o)throw new Error("totalCap must be >= perUnitCap");if(t.revolvingCapacity!==void 0&&BigInt(ee(t.revolvingCapacity))<=0n)throw new Error("revolvingCapacity must be > 0");let i=t.sessionDuration??mn,c=Math.floor(Date.now()/1e3)+i,u=fn(t.seller),p={channelId:s,maxAmountAtomic:a.toString(),revolvingCapacityAtomic:t.revolvingCapacity?ee(t.revolvingCapacity):a.toString(),expiresAtUnix:c,allowedCounterparty:u},d=await t.vault.authorizeSession(p,{onLiveSession:t.onLiveSession});return await St(t.facilitatorUrl??we,t.vault.swigAddress,a,t.network,u),new Be({vault:t.vault,network:t.network,seller:t.seller,counterparty:u,session:d,channelIdHex:s,channelIdBytes:r,perUnitCapAtomic:o,totalCapAtomic:a,expiresAtUnix:c,facilitatorUrl:t.facilitatorUrl??we})}async function Dt(t){throw new Error("resumeTab is Phase 3 work. Session keys are memory-only by design; recovery requires reading active_session on chain and re-authorizing. Tracked in dexter-vault roadmap.")}function fn(t){if(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(t))try{return new bt.PublicKey(t),t}catch{}throw new Error(`seller must be a base58 Solana pubkey for Phase 2 (got "${t}"). URL-based counterparty resolution lands in Phase 3 (seller middleware).`)}async function*gn(t){let e=t.getReader(),n=new TextDecoder,r="";try{for(;;){let{done:s,value:o}=await e.read();if(s)break;r+=n.decode(o,{stream:!0});let a;for(;(a=r.indexOf(`
2
2
 
3
- `))!==-1;){let i=r.slice(0,a);r=r.slice(a+2);let c=yn(i);if(c.eventName==="end")return;if(c.data!==null){let u=c.data.replace(/\\n/g,`
4
- `);yield new TextEncoder().encode(u)}}}}finally{e.releaseLock()}}function yn(t){let e=null,n=[];for(let r of t.split(`
3
+ `))!==-1;){let i=r.slice(0,a);r=r.slice(a+2);let c=yn(i);if(c.eventName==="end")return;if(c.data!==null){let u=c.data.replace(/\\(\\|n)/g,(p,d)=>d==="n"?`
4
+ `:"\\");yield new TextEncoder().encode(u)}}}}finally{e.releaseLock()}}function yn(t){let e=null,n=[];for(let r of t.split(`
5
5
  `))r.startsWith("event:")?e=r.slice(6).trim():r.startsWith("data:")&&n.push(r.slice(5).trimStart());return{eventName:e,data:n.length?n.join(`
6
6
  `):null}}var xe=J(require("tweetnacl"),1),ne=require("@solana/web3.js"),$t=require("@noble/hashes/utils"),ot=require("@dexterai/vault/session"),Kt=require("@dexterai/vault/reader");var ue=require("@dexterai/vault/instructions"),wt=require("@dexterai/vault/precompile"),W=require("@dexterai/vault/constants");var xt="solana:mainnet";async function Lt(t){let e=t.facilitatorUrl??we,n=t.programId??W.DEXTER_VAULT_PROGRAM_ID,r=new ne.PublicKey(t.vaultPda),s=new ne.PublicKey(t.params.counterparty),o=nt(t.perUnitCapAtomic);if(o<=0n)throw new Error(`perUnitCapAtomic must be > 0, got ${t.perUnitCapAtomic}`);let a=nt(t.params.maxAmountAtomic),i=nt(t.params.maxRevolvingCapacityAtomic),c=hn(t.sessionSecretKey),u=new ne.PublicKey(t.params.sessionPubkey).toBytes();if(!Mt(c.publicKey,u))throw new Error(`tab_session_key_mismatch: the supplied secret derives ${new ne.PublicKey(c.publicKey).toBase58()} but params.sessionPubkey is ${t.params.sessionPubkey} \u2014 wrong key handed to this process`);let p=xe.default.randomBytes(32),d=xe.default.sign.detached(p,c.secretKey);if(!xe.default.sign.detached.verify(p,d,u))throw new Error("tab_session_key_mismatch: secret key failed the sign/verify self-check against params.sessionPubkey \u2014 the seed half does not sign for the granted pubkey");let f=(0,B.sessionRegisterMessage)({programId:n,vaultPda:r,sessionPubkey:c.publicKey,maxAmount:a,expiresAt:BigInt(t.params.expiresAtUnix),allowedCounterparty:s,nonce:t.params.nonce,maxRevolvingCapacity:i}),x=typeof t.connection=="string"?new ne.Connection(t.connection,"confirmed"):t.connection,l=await(0,ot.fetchSessionAccount)(x,r,s,n);if(!l||l.version===0)throw new Error("tab_session_not_live: no live SessionAccount PDA for this (vault, counterparty) \u2014 revoked, expiry-swept, or never registered");if(!(0,ot.isSessionLive)(l))throw new Error(l.version!==1?`tab_session_not_live: SessionAccount has unsupported version ${l.version} \u2014 not a live v1 session`:`tab_session_not_live: SessionAccount is present but expired (expiresAt=${l.session.expiresAt})`);if(!Mt(l.session.sessionPubkey,c.publicKey))throw new Error(`tab_session_pubkey_mismatch: the on-chain session carries ${new ne.PublicKey(l.session.sessionPubkey).toBase58()} \u2014 the grant this key belongs to was replaced by a newer registration`);if(l.session.maxAmount!==a||l.session.expiresAt!==t.params.expiresAtUnix||l.session.nonce!==t.params.nonce||l.session.maxRevolvingCapacity!==i)throw new Error(`tab_grant_params_stale: params disagree with the on-chain session scope (chain: maxAmount=${l.session.maxAmount} expiresAt=${l.session.expiresAt} nonce=${l.session.nonce} revolving=${l.session.maxRevolvingCapacity}; params: ${t.params.maxAmountAtomic}/${t.params.expiresAtUnix}/${t.params.nonce}/${t.params.maxRevolvingCapacityAtomic}) \u2014 refresh the grant hand-off`);let P=l.session.spent>l.session.crystallizedCumulative?l.session.spent:l.session.crystallizedCumulative;if(P>=a)throw new Error(`tab_exhausted: on-chain frontier ${P} has consumed the session cap ${a} \u2014 no voucher can strictly exceed it; open a new grant`);let T=t.sellerUrl??t.params.counterparty,y=BigInt(Math.floor(Math.random()*4294967295)),g=rt({vaultPda:r,sellerUrl:T,nonce:y}),S=(0,$t.bytesToHex)(g),k=t.swigAddress;if(!k){let D=await(0,Kt.readVaultFull)(x,r);if(!D.exists||!D.swigAddress)throw new Error(`tab_vault_unreadable: vault ${r.toBase58()} has no readable swig_address on chain \u2014 pass options.swigAddress explicitly`);k=D.swigAddress}await St(e,k,a,xt,t.params.counterparty);let M={channelId:S,maxAmountAtomic:t.params.maxAmountAtomic,revolvingCapacityAtomic:t.params.maxRevolvingCapacityAtomic,expiresAtUnix:t.params.expiresAtUnix,allowedCounterparty:t.params.counterparty},q=Nt({publicKey:c.publicKey,privateKey:c.secretKey},M,f),V={network:xt,swigAddress:k,vaultPda:r.toBase58(),authorizeSession:async()=>{throw new Error("grant_tab_no_passkey: a grant-held tab cannot authorize sessions \u2014 session birth requires the wallet owner's passkey ceremony")},signWithSession:async(D,K)=>Ot(D,K,g),signOpenTab:async D=>D.registration,signCloseTab:async()=>{throw new Error("grant_tab_cannot_revoke: session revocation is passkey-signed and belongs to the wallet owner's surfaces \u2014 a grant-held tab closes settle-only")}};return new Be({vault:V,network:xt,seller:T,counterparty:t.params.counterparty,session:q,channelIdHex:S,channelIdBytes:g,perUnitCapAtomic:o,totalCapAtomic:a,expiresAtUnix:t.params.expiresAtUnix,facilitatorUrl:e,initialCumulativeAtomic:P,closeMode:"settle-only"})}function hn(t){if(t.length===64)return xe.default.sign.keyPair.fromSecretKey(t);if(t.length===32)return xe.default.sign.keyPair.fromSeed(t);throw new Error(`tab_session_key_invalid: expected a 64-byte nacl secretKey or a 32-byte ed25519 seed, got ${t.length} bytes`)}function Mt(t,e){if(t.length!==e.length)return!1;let n=0;for(let r=0;r<t.length;r++)n|=t[r]^e[r];return n===0}var Wt=require("@solana/web3.js");var Vt=[{caip2:"eip155:8453",bare:"base",family:"evm"},{caip2:"eip155:1",bare:"ethereum",family:"evm"},{caip2:"eip155:137",bare:"polygon",family:"evm"},{caip2:"eip155:42161",bare:"arbitrum",family:"evm"},{caip2:"eip155:10",bare:"optimism",family:"evm"},{caip2:"eip155:43114",bare:"avalanche",family:"evm"},{caip2:"eip155:56",bare:"bsc",family:"evm"},{caip2:"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",bare:"solana",family:"svm"}],An=new Map(Vt.map(t=>[t.caip2.toLowerCase(),t])),bn=new Map(Vt.map(t=>[t.bare.toLowerCase(),t]));function Me(t){if(!t)return null;let e=t.toLowerCase(),n=An.get(e)||bn.get(e);return n?{caip2:n.caip2,bare:n.bare,family:n.family}:null}function Tt(t){let e=t.replace(/-/g,"+").replace(/_/g,"/"),n=e+"=".repeat((4-(e.length%4||4))%4);return JSON.parse(Buffer.from(n,"base64").toString("utf8"))}function Sn(t){let e=[];for(let n of t){if(!n||typeof n!="object")continue;let r=n,s=Me(String(r.network??""));s&&e.push({scheme:String(r.scheme??"exact"),network:s,amount:String(r.amount??r.maxAmountRequired??"0"),asset:String(r.asset??""),payTo:String(r.payTo??""),maxTimeoutSeconds:typeof r.maxTimeoutSeconds=="number"?r.maxTimeoutSeconds:void 0,extra:r.extra&&typeof r.extra=="object"?r.extra:void 0})}return e}async function at(t){let e=t.headers.get("payment-required");if(!e)return null;let n;try{n=Tt(e)}catch{return null}let r=Array.isArray(n.accepts)?n.accepts:[];return r.length===0?null:{x402Version:2,options:Sn(r),resourceUrl:n.resource&&typeof n.resource=="object"?String(n.resource.url??""):void 0}}async function Te(t,e={},n=fetch){let r={method:e.method??"GET",headers:e.headers};typeof e.body=="string"&&(r.body=e.body);let s;try{s=await n(t,r)}catch(i){return{kind:"error",detail:`probe failed: ${i?.message??String(i)}`}}if(s.status!==402)return s.ok?{kind:"free",response:s}:{kind:"error",detail:`probe returned HTTP ${s.status}`};let o=await at(s);if(!o)return{kind:"error",detail:"the 402 carries no x402 v2 PAYMENT-REQUIRED challenge"};let a=o.options.find(i=>i.scheme==="tab"&&i.network.family==="svm");if(!a)return{kind:"no_tab",schemesOffered:o.options.map(i=>i.scheme)};try{new Wt.PublicKey(a.payTo)}catch{return{kind:"error",detail:`tab option payTo is not a valid Solana pubkey: "${a.payTo}"`}}return{kind:"offer",offer:{payTo:a.payTo,amountAtomic:a.amount,asset:a.asset,networkCaip2:a.network.caip2,resourceUrl:o.resourceUrl}}}var $e="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",it="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",ct="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z",me=$e,Ke=it,Le=ct,pe="eip155:8453",ve="eip155:84532",Ee="eip155:42161",Pe="eip155:137",Re="eip155:10",_e="eip155:43114",ke="eip155:56",Ce="eip155:1187947933",Ie="eip155:324705682",Ne="eip155:1",de=pe,lt=ve,Ve=Ee,We=Pe,qe=Re,He=_e,Fe=ke,je=Ce,Je=Ie,ze=Ne,Ge="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",qt="4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",Ht="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",vt="0x55d398326f99059fF775485246999027B3197955",ut="0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",mt={[ke]:ut,[pe]:Ht,[ve]:"0x036CbD53842c5426634e7929541eC2318f3dCF7e",[Ee]:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831",[Pe]:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",[Re]:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",[_e]:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",[Ce]:"0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",[Ie]:"0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",[Ne]:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},pt={[vt]:{symbol:"USDT",decimals:18},[ut]:{symbol:"USDC",decimals:18}};var re="0x000000000022D473030F116dDEE9F6B43aC78BA3",Xe="0x402085c248EeA27D92E8b30b2C58ed07f9E20001",Ye={[ke]:56,[pe]:8453,[ve]:84532,[Ee]:42161,[Pe]:137,[Re]:10,[_e]:43114,[Ce]:1187947933,[Ie]:324705682,[Ne]:1},fe={[$e]:"https://api.dexter.cash/api/solana/rpc",[it]:"https://api.devnet.solana.com",[ct]:"https://api.testnet.solana.com"},$={[ke]:"https://api.dexter.cash/api/evm/bsc/rpc",[pe]:"https://api.dexter.cash/api/base/rpc",[ve]:"https://sepolia.base.org",[Ee]:"https://api.dexter.cash/api/evm/arbitrum/rpc",[Pe]:"https://api.dexter.cash/api/evm/polygon/rpc",[Re]:"https://api.dexter.cash/api/evm/optimism/rpc",[_e]:"https://api.dexter.cash/api/evm/avalanche/rpc",[Ce]:"https://skale-base.skalenodes.com/v1/base",[Ie]:"https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",[Ne]:"https://eth.llamarpc.com"};var I=class t extends Error{code;details;constructor(e,n,r){super(n),this.name="X402Error",this.code=e,this.details=r,Object.setPrototypeOf(this,t.prototype)}};var N=require("@solana/web3.js"),O=require("@solana/spl-token");var wn=12e3,xn=1;function ge(t){if(!t||typeof t!="object")return!1;let e=t;return"publicKey"in e&&"signTransaction"in e&&typeof e.signTransaction=="function"}var dt=class{name="Solana";networks=[me,Ke,Le];config;log;constructor(e={}){this.config=e,this.log=e.verbose?console.log.bind(console,"[x402:solana]"):()=>{}}canHandle(e){return!!(this.networks.includes(e)||e==="solana"||e==="solana-devnet"||e==="solana-testnet"||e.startsWith("solana:"))}getDefaultRpcUrl(e){return this.config.rpcUrls?.[e]?this.config.rpcUrls[e]:fe[e]?fe[e]:e==="solana"?fe[me]:e==="solana-devnet"?fe[Ke]:e==="solana-testnet"?fe[Le]:fe[me]}getAddress(e){return ge(e)?e.publicKey?.toBase58()??null:null}isConnected(e){return ge(e)?e.publicKey!==null:!1}async getBalance(e,n,r){if(!ge(n)||!n.publicKey)return 0;let s=r||this.getDefaultRpcUrl(e.network),o=new N.Connection(s,"confirmed"),a=new N.PublicKey(n.publicKey.toBase58()),i=new N.PublicKey(e.asset);try{let u=(await o.getAccountInfo(i,"confirmed"))?.owner.toBase58()===O.TOKEN_2022_PROGRAM_ID.toBase58()?O.TOKEN_2022_PROGRAM_ID:O.TOKEN_PROGRAM_ID,p=await(0,O.getAssociatedTokenAddress)(i,a,!1,u),d=await(0,O.getAccount)(o,p,void 0,u),f=e.extra?.decimals??6;return Number(d.amount)/Math.pow(10,f)}catch(c){if(c&&typeof c=="object"&&"name"in c&&(c.name==="TokenAccountNotFoundError"||c.name==="TokenInvalidAccountOwnerError"))return 0;throw c}}async buildTransaction(e,n,r){if(!ge(n))throw new Error("Invalid Solana wallet");if(!n.publicKey)throw new Error("Wallet not connected");let s=r||this.getDefaultRpcUrl(e.network),o=new N.Connection(s,"confirmed"),a=new N.PublicKey(n.publicKey.toBase58()),{payTo:i,asset:c,extra:u}=e,p=e.amount??e.maxAmountRequired;if(!p)throw new Error("Missing amount in payment requirements");if(!u?.feePayer)throw new Error("Missing feePayer in payment requirements");let d=new N.PublicKey(u.feePayer),f=new N.PublicKey(c),x=new N.PublicKey(i);this.log("Building transaction:",{from:a.toBase58(),to:i,amount:p,asset:c,feePayer:u.feePayer});let l=[];l.push(N.ComputeBudgetProgram.setComputeUnitLimit({units:wn})),l.push(N.ComputeBudgetProgram.setComputeUnitPrice({microLamports:xn}));let P=await o.getAccountInfo(f,"confirmed");if(!P)throw new Error(`Token mint ${c} not found`);let T=P.owner.toBase58()===O.TOKEN_2022_PROGRAM_ID.toBase58()?O.TOKEN_2022_PROGRAM_ID:O.TOKEN_PROGRAM_ID,y=await(0,O.getMint)(o,f,void 0,T);typeof u?.decimals=="number"&&y.decimals!==u.decimals&&this.log(`Decimals mismatch: requirements say ${u.decimals}, mint says ${y.decimals}`);let g=await(0,O.getAssociatedTokenAddress)(f,a,!1,T),S=await(0,O.getAssociatedTokenAddress)(f,x,!0,T);if(!await o.getAccountInfo(g,"confirmed"))throw new Error(`No token account found for ${c}. Please ensure you have USDC in your wallet.`);if(!await o.getAccountInfo(S,"confirmed"))throw new Error(`Seller token account not found. The seller (${i}) must have a USDC account.`);let q=BigInt(p);l.push((0,O.createTransferCheckedInstruction)(g,f,S,a,q,y.decimals,[],T));let{blockhash:V}=await o.getLatestBlockhash("confirmed"),D=new N.TransactionMessage({payerKey:d,recentBlockhash:V,instructions:l}).compileToV0Message(),K=new N.VersionedTransaction(D),h=await n.signTransaction(K);return this.log("Transaction signed successfully"),{serialized:Buffer.from(h.serialize()).toString("base64"),settlementProbe:{kind:"solana",sourceAta:g.toBase58(),destinationAta:S.toBase58(),asset:c,amount:p,blockhash:V}}}async confirmSettlement(e,n){if(e.kind!=="solana")throw new Error(`SolanaAdapter.confirmSettlement cannot handle probe kind "${e.kind}"`);let r=new N.Connection(n,"confirmed"),s=new N.PublicKey(e.destinationAta),o=await r.getSignaturesForAddress(s,{limit:25});if(o.length===0)return{settled:!1};let a=BigInt(e.amount);for(let i of o){if(i.err)continue;let c=await r.getTransaction(i.signature,{commitment:"confirmed",maxSupportedTransactionVersion:0});if(!c?.meta)continue;let u=c.transaction.message.getAccountKeys().keySegments().flat(),p=c.meta.preTokenBalances??[],d=c.meta.postTokenBalances??[];for(let f of d){if(f.mint!==e.asset)continue;let x=u[f.accountIndex];if(!x||!x.equals(s))continue;let l=p.find(y=>y.accountIndex===f.accountIndex),P=BigInt(l?.uiTokenAmount.amount??"0");if(BigInt(f.uiTokenAmount.amount??"0")-P===a)return{settled:!0,txSignature:i.signature}}}return{settled:!1}}};function se(t){return new dt(t)}var Tn={PermitWitnessTransferFrom:[{name:"permitted",type:"TokenPermissions"},{name:"spender",type:"address"},{name:"nonce",type:"uint256"},{name:"deadline",type:"uint256"},{name:"witness",type:"Witness"}],TokenPermissions:[{name:"token",type:"address"},{name:"amount",type:"uint256"}],Witness:[{name:"to",type:"address"},{name:"validAfter",type:"uint256"}]},Ft=BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");function ye(t){if(!t||typeof t!="object")return!1;let e=t;return"address"in e&&typeof e.address=="string"&&e.address.startsWith("0x")}var ft=class{name="EVM";networks=[Fe,de,lt,ze,Ve,We,qe,He,je,Je];config;log;constructor(e={}){this.config=e,this.log=e.verbose?console.log.bind(console,"[x402:evm]"):()=>{}}canHandle(e){return!!(this.networks.includes(e)||e==="base"||e==="bsc"||e==="ethereum"||e==="arbitrum"||e==="polygon"||e==="optimism"||e==="avalanche"||e==="skale-base"||e==="skale-base-sepolia"||e.startsWith("eip155:"))}getDefaultRpcUrl(e){return this.config.rpcUrls?.[e]?this.config.rpcUrls[e]:$[e]?$[e]:e==="base"?$[de]:e==="bsc"?$[Fe]:e==="ethereum"?$[ze]:e==="arbitrum"?$[Ve]:e==="polygon"?$[We]:e==="optimism"?$[qe]:e==="avalanche"?$[He]:e==="skale-base"?$[je]:e==="skale-base-sepolia"?$[Je]:$[de]}getAddress(e){return ye(e)?e.address:null}isConnected(e){return ye(e)?!!e.address:!1}getChainId(e){if(Ye[e])return Ye[e];if(e.startsWith("eip155:")){let n=e.split(":")[1];return parseInt(n,10)}return e==="base"?8453:e==="bsc"?56:e==="ethereum"?1:e==="arbitrum"?42161:8453}async getBalance(e,n,r){if(!ye(n)||!n.address)return 0;let s=r||this.getDefaultRpcUrl(e.network);try{let o=this.encodeBalanceOf(n.address),a=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_call",params:[{to:e.asset,data:o},"latest"]})});if(!a.ok)throw new Error(`RPC request failed: ${a.status}`);let i=await a.json();if(i.error)throw new Error(`RPC error: ${JSON.stringify(i.error)}`);if(!i.result||i.result==="0x")return 0;let c=BigInt(i.result),u=e.extra?.decimals??6;return Number(c)/Math.pow(10,u)}catch(o){throw o}}encodeBalanceOf(e){let n="0x70a08231",r=e.slice(2).toLowerCase().padStart(64,"0");return n+r}async confirmSettlement(e,n){if(e.kind==="eip3009"){let r="0xe94a0102",s=e.from.slice(2).toLowerCase().padStart(64,"0"),o=e.nonce.slice(2).toLowerCase().padStart(64,"0"),a=r+s+o,i=await this.ethCall(n,e.asset,a);return{settled:BigInt(i)!==0n}}if(e.kind==="permit2"){let r="0x4fe02b44",s=BigInt(e.nonce),o=s>>8n,a=s&0xffn,i=e.from.slice(2).toLowerCase().padStart(64,"0"),c=o.toString(16).padStart(64,"0"),u=r+i+c,p=await this.ethCall(n,re,u);return{settled:(BigInt(p)>>a&1n)===1n}}throw new Error(`EvmAdapter.confirmSettlement cannot handle probe kind "${e.kind}"`)}async ethCall(e,n,r){let s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_call",params:[{to:n,data:r},"latest"]})});if(!s.ok)throw new Error(`RPC request failed: ${s.status}`);let o=await s.json();if(o.error)throw new Error(`RPC error: ${JSON.stringify(o.error)}`);if(!o.result||o.result==="0x")throw new Error("RPC returned an empty result");return o.result}async buildTransaction(e,n,r){if(!ye(n))throw new Error("Invalid EVM wallet");if(!n.address)throw new Error("Wallet not connected");if(e.scheme==="exact-approval")return this.buildApprovalTransaction(e,n,r);if(e.extra?.assetTransferMethod==="permit2")return this.buildPermit2Transaction(e,n,r);let{payTo:s,asset:o,extra:a}=e,i=e.amount??e.maxAmountRequired;if(!i)throw new Error("Missing amount in payment requirements");this.log("Building EVM transaction:",{from:n.address,to:s,amount:i,asset:o,network:e.network});let c=this.getChainId(e.network),u={name:a?.name??"USD Coin",version:a?.version??"2",chainId:BigInt(c),verifyingContract:o},p={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},d=new Uint8Array(32);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(d);let f="0x"+[...d].map(g=>g.toString(16).padStart(2,"0")).join(""),x=Math.floor(Date.now()/1e3),l={from:n.address,to:s,value:i,validAfter:String(x-600),validBefore:String(x+(e.maxTimeoutSeconds||60)),nonce:f},P={from:n.address,to:s,value:BigInt(i),validAfter:BigInt(x-600),validBefore:BigInt(x+(e.maxTimeoutSeconds||60)),nonce:f};if(!n.signTypedData)throw new Error("Wallet does not support signTypedData (EIP-712)");let T=await n.signTypedData({domain:u,types:p,primaryType:"TransferWithAuthorization",message:P});return this.log("EIP-712 signature obtained"),{serialized:JSON.stringify({authorization:l,signature:T}),signature:T,settlementProbe:{kind:"eip3009",from:n.address,nonce:f,asset:o,chainId:c}}}async buildApprovalTransaction(e,n,r){let{payTo:s,asset:o,extra:a}=e,i=e.amount??e.maxAmountRequired;if(!i)throw new Error("Missing amount in payment requirements");let c=a?.facilitatorContract;if(!c)throw new Error("exact-approval scheme requires extra.facilitatorContract from the facilitator. The /supported endpoint should provide this.");if(!n.signTypedData)throw new Error("Wallet does not support signTypedData (EIP-712)");this.log("Building approval-based transaction:",{from:n.address,to:s,amount:i,asset:o,network:e.network,facilitatorContract:c});let u=r||this.getDefaultRpcUrl(e.network),p=a?.fee??"0",d=BigInt(i)+BigInt(p),f=await this.readAllowance(u,o,n.address,c);if(f<d){if(!n.sendTransaction)throw new Error("BSC payments require a wallet that supports sendTransaction for the one-time token approval. Use createEvmKeypairWallet() or a browser wallet with transaction support.");let K=this.calculateApprovalAmount(i,p,a?.approvalStrategy);this.log(`Approving ${K} for ${c} (current allowance: ${f})`);let h=await n.sendTransaction({to:o,data:this.encodeApprove(c,K),value:0n});this.log(`Approval tx sent: ${h}`),await this.waitForReceipt(u,h),this.log("Approval confirmed")}else this.log("Sufficient allowance, skipping approval");let x=new Uint8Array(16);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(x);let l=[...x].reduce((K,h)=>K*256n+BigInt(h),0n).toString(),P=new Uint8Array(32);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(P);let T="0x"+[...P].map(K=>K.toString(16).padStart(2,"0")).join(""),g=Math.floor(Date.now()/1e3)+(e.maxTimeoutSeconds||300),S=a?.eip712Domain,k=S?{name:S.name,version:S.version,chainId:BigInt(S.chainId),verifyingContract:S.verifyingContract}:{name:"DexterBSCFacilitator",version:"1",chainId:BigInt(this.getChainId(e.network)),verifyingContract:c},M=a?.eip712Types??{Payment:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"token",type:"address"},{name:"amount",type:"uint256"},{name:"fee",type:"uint256"},{name:"nonce",type:"uint256"},{name:"deadline",type:"uint256"},{name:"paymentId",type:"bytes32"}]},q={from:n.address,to:s,token:o,amount:BigInt(i),fee:BigInt(p),nonce:BigInt(l),deadline:BigInt(g),paymentId:T},V=await n.signTypedData({domain:k,types:M,primaryType:"Payment",message:q});this.log("EIP-712 Payment signature obtained");let D={from:n.address,to:s,token:o,amount:i,fee:p,nonce:l,deadline:g,paymentId:T,signature:V};return{serialized:JSON.stringify(D),signature:V}}async buildPermit2Transaction(e,n,r){let{payTo:s,asset:o}=e,a=e.amount??e.maxAmountRequired;if(!a)throw new Error("Missing amount in payment requirements");if(!n.signTypedData)throw new Error("Wallet does not support signTypedData (EIP-712)");this.log("Building Permit2 transaction:",{from:n.address,to:s,amount:a,asset:o,network:e.network});let i=r||this.getDefaultRpcUrl(e.network),c=await this.readAllowance(i,o,n.address,re),u;if(c<BigInt(a)){let k=this.encodeApprove(re,Ft);if(n.signTransaction){this.log(`Signing Permit2 approval for relay (current allowance: ${c})`);let M=this.getChainId(e.network),q=await this.readGasPrice(i),V=await this.readNonce(i,n.address),D=await n.signTransaction({to:o,data:k,chainId:M,gas:50000n,gasPrice:q,nonce:V});u={erc20ApprovalGasSponsoring:{info:{from:n.address,asset:o,spender:re,amount:Ft.toString(),signedTransaction:D,version:"1"}}},this.log("Permit2 approval signed for facilitator relay")}else if(n.sendTransaction){this.log(`Approving Permit2 directly (current allowance: ${c})`);let M=await n.sendTransaction({to:o,data:k,value:0n});this.log(`Permit2 approval tx sent: ${M}`),await this.waitForReceipt(i,M),this.log("Permit2 approval confirmed")}else throw new Error("Permit2 payments require a wallet that supports signTransaction or sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support.")}else this.log("Sufficient Permit2 allowance, skipping approval");let p=new Uint8Array(32);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(p);let d=[...p].reduce((k,M)=>k*256n+BigInt(M),0n),f=Math.floor(Date.now()/1e3),x=f-600,l=f+(e.maxTimeoutSeconds||300),P=this.getChainId(e.network),T={name:"Permit2",chainId:BigInt(P),verifyingContract:re},y={permitted:{token:o,amount:BigInt(a)},spender:Xe,nonce:d,deadline:BigInt(l),witness:{to:s,validAfter:BigInt(x)}},g=await n.signTypedData({domain:T,types:Tn,primaryType:"PermitWitnessTransferFrom",message:y});this.log("Permit2 PermitWitnessTransferFrom signature obtained");let S={signature:g,permit2Authorization:{from:n.address,permitted:{token:o,amount:a},spender:Xe,nonce:d.toString(),deadline:String(l),witness:{to:s,validAfter:String(x)}}};return{serialized:JSON.stringify(S),signature:g,extensions:u,settlementProbe:{kind:"permit2",from:n.address,nonce:d.toString(),chainId:P}}}async readAllowance(e,n,r,s){let o="0xdd62ed3e",a=r.slice(2).toLowerCase().padStart(64,"0"),i=s.slice(2).toLowerCase().padStart(64,"0"),c=o+a+i;try{let p=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_call",params:[{to:n,data:c},"latest"]})})).json();return p.error||!p.result||p.result==="0x"?0n:BigInt(p.result)}catch{return 0n}}encodeApprove(e,n){let r="0x095ea7b3",s=e.slice(2).toLowerCase().padStart(64,"0"),o=n.toString(16).padStart(64,"0");return r+s+o}async waitForReceipt(e,n,r=3e4){let s=Date.now();for(;Date.now()-s<r;){try{let a=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_getTransactionReceipt",params:[n]})})).json();if(a.result){if(a.result.status==="0x0")throw new Error(`Approval transaction reverted: ${n}`);return}}catch(o){if(o instanceof Error&&o.message.includes("reverted"))throw o}await new Promise(o=>setTimeout(o,2e3))}throw new Error(`Approval transaction receipt timeout after ${r}ms: ${n}`)}async readGasPrice(e){try{let r=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_gasPrice",params:[]})})).json();return r.result?BigInt(r.result):50000000n}catch{return 50000000n}}async readNonce(e,n){try{let s=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_getTransactionCount",params:[n,"latest"]})})).json();return s.result?parseInt(s.result,16):0}catch{return 0}}calculateApprovalAmount(e,n,r){let s=BigInt(e)+BigInt(n);if(!r||r.mode==="exact")return s;let o=BigInt(r.defaultMultiple??10),a=s*o;if(r.maxCapUsd){let i=this.inferDecimals(e),c=BigInt(Math.floor(r.maxCapUsd*Math.pow(10,i)));if(a>c)return c}if(r.exactAboveUsd){let i=this.inferDecimals(e),c=BigInt(Math.floor(r.exactAboveUsd*Math.pow(10,i)));if(BigInt(e)>c)return s}return a}inferDecimals(e){return e.length>12?18:6}};function Oe(t){return new ft(t)}function Et(t){if(t===Ge||t===qt)return!0;let e=t.toLowerCase();for(let n of Object.values(mt))if(n.toLowerCase()===e)return!0;for(let n of Object.keys(pt))if(n.toLowerCase()===e)return!0;return!1}function vn(t){return{[$e]:"Solana",[it]:"Solana Devnet",[ct]:"Solana Testnet",solana:"Solana","solana-devnet":"Solana Devnet","solana-testnet":"Solana Testnet",[pe]:"Base",[ve]:"Base Sepolia",[Ne]:"Ethereum",[Ee]:"Arbitrum",[Pe]:"Polygon",[Re]:"Optimism",[_e]:"Avalanche",[ke]:"BSC",[Ce]:"SKALE Base",[Ie]:"SKALE Base Sepolia",base:"Base","base-sepolia":"Base Sepolia",ethereum:"Ethereum",arbitrum:"Arbitrum",polygon:"Polygon",optimism:"Optimism",avalanche:"Avalanche",bsc:"BSC","skale-base":"SKALE Base","skale-base-sepolia":"SKALE Base Sepolia"}[t]||t}function jt(t,e){let n=vn(t);return n===t?e:n}async function En(t,e){if(typeof t=="string")return[t,e];if(t instanceof URL)return[t.href,e];let n=t,r=new Headers(n.headers);e?.headers&&new Headers(e.headers).forEach((a,i)=>r.set(i,a));let s={method:e?.method??n.method,headers:r,signal:e?.signal??n.signal,redirect:e?.redirect??n.redirect,credentials:e?.credentials??n.credentials},o=(s.method??"GET").toUpperCase();return e&&"body"in e?s.body=e.body:o!=="GET"&&o!=="HEAD"&&n.body&&(s.body=await n.arrayBuffer()),[n.url,s]}var Pn=new WeakMap;function Jt(t){let{adapters:e=[se({verbose:t.verbose}),Oe({verbose:t.verbose})],wallets:n,wallet:r,preferredNetwork:s,rpcUrls:o={},maxAmountAtomic:a,fetch:i=globalThis.fetch,verbose:c=!1,accessPass:u,onPaymentRequired:p,onPaymentDispatched:d,maxRetries:f=0,retryDelayMs:x=500}=t,l=c?console.log.bind(console,"[x402]"):()=>{};async function P(h,w){let v;for(let A=0;A<=f;A++)try{let E=await i(h,w);if(E.status>=502&&E.status<=504&&A<f){l(`Retry ${A+1}/${f}: server returned ${E.status}`),await new Promise(R=>setTimeout(R,x*Math.pow(2,A)));continue}return E}catch(E){v=E,A<f&&(l(`Retry ${A+1}/${f}: ${E instanceof Error?E.message:"network error"}`),await new Promise(R=>setTimeout(R,x*Math.pow(2,A))))}throw v}let T=new Map;function y(h){try{let w=new URL(h).host,v=T.get(w);if(v&&v.expiresAt>Date.now()/1e3+10)return v.jwt;v&&T.delete(w)}catch{}return null}function g(h,w){try{let v=new URL(h).host,A=w.split(".");if(A.length===3){let E=JSON.parse(atob(A[1].replace(/-/g,"+").replace(/_/g,"/"))),R=Math.floor(Date.now()/1e3),_=R+86400,H=Math.min(typeof E.exp=="number"?E.exp:R,_);T.set(v,{jwt:w,expiresAt:H}),l("Access pass cached for",v,"| expires:",new Date(H*1e3).toISOString())}}catch{l("Failed to cache access pass")}}let S=n||{};r&&!S.solana&&ge(r)&&(S.solana=r),r&&!S.evm&&ye(r)&&(S.evm=r);function k(h){let w=[];for(let v of h){let A=v.scheme??"exact";if(A!=="exact"&&A!=="exact-approval")continue;let E=e.find(_=>_.canHandle(v.network));if(!E)continue;let R;E.name==="Solana"?R=S.solana:E.name==="EVM"&&(R=S.evm),R&&E.isConnected(R)&&w.push({accept:v,adapter:E,wallet:R})}if(w.length===0)return null;if(s){let v=w.find(A=>A.accept.network===s);if(v)return v}return w[0]}function M(h,w){return jt(h,w)}function q(h,w){return o[h]||w.getDefaultRpcUrl(h)}async function V(h,w,v,A,E){let R="";if(u?.preferTier&&A.tiers){let m=A.tiers.find(b=>b.id===u.preferTier);if(m){if(u.maxSpend&&parseFloat(m.price)>parseFloat(u.maxSpend))throw new I("access_pass_exceeds_max_spend",`Access pass tier "${m.id}" costs $${m.price}, exceeds max spend $${u.maxSpend}`);R=`tier=${m.id}`}}else if(u?.preferDuration&&A.ratePerHour)R=`duration=${u.preferDuration}`;else if(A.tiers&&A.tiers.length>0){let m=A.tiers[0];if(u?.maxSpend&&parseFloat(m.price)>parseFloat(u.maxSpend))throw new I("access_pass_exceeds_max_spend",`Cheapest access pass costs $${m.price}, exceeds max spend $${u?.maxSpend}`);R=`tier=${m.id}`}let _=R?E.includes("?")?`${E}&${R}`:`${E}?${R}`:E;l("Purchasing access pass:",R||"default tier");let H=v.headers.get("PAYMENT-REQUIRED");if(!H)return null;let L;try{L=JSON.parse(atob(H))}catch{return null}let U=k(L.accepts);if(!U)return null;let{accept:C,adapter:j,wallet:he}=U;if(j.name==="Solana"&&!C.extra?.feePayer)return null;let G=C.extra?.decimals??(Et(C.asset)?6:void 0);if(typeof G!="number")return null;let Ue=C.amount??C.maxAmountRequired;if(!Ue)return null;let X=q(C.network,j);try{let m=await j.getBalance(C,he,X),b=Number(Ue)/Math.pow(10,G);if(m<b){let At=M(C.network,j.name);throw new I("insufficient_balance",`Insufficient balance for access pass on ${At}. Have $${m.toFixed(4)}, need $${b.toFixed(4)}`)}}catch(m){if(m instanceof I)throw m}let Y=await j.buildTransaction(C,he,X),Ae;j.name==="EVM"?Ae=JSON.parse(Y.serialized):Ae={transaction:Y.serialized};let oe=typeof h=="string"?h:h instanceof URL?h.href:h.url,be=L.resource;if(typeof L.resource=="string")try{let m=new URL(L.resource,oe);["http:","https:"].includes(m.protocol)&&(be=m.toString())}catch{}else if(L.resource&&typeof L.resource=="object"&&"url"in L.resource){let m=L.resource;try{let b=new URL(m.url,oe);["http:","https:"].includes(b.protocol)&&(be={...m,url:b.toString()})}catch{}}let Ze={x402Version:C.x402Version??2,resource:be,accepted:C,payload:Ae};Y.extensions&&(Ze.extensions=Y.extensions);let Q=btoa(JSON.stringify(Ze)),ae=await i(_,{...w,method:"POST",headers:{...w?.headers||{},"Content-Type":"application/json","PAYMENT-SIGNATURE":Q}});if(!ae.ok)return l("Pass purchase failed:",ae.status),null;let F=ae.headers.get("ACCESS-PASS");return F&&(g(E,F),l("Access pass purchased and cached")),ae}async function D(h,w){let v=h;if(l("Making request:",v),u){let m=y(v);if(m){l("Using cached access pass");let b=await i(h,{...w,headers:{...w?.headers||{},Authorization:`Bearer ${m}`}});if(b.status!==401&&b.status!==402)return b;l("Cached pass rejected (status",b.status,"), purchasing new pass");try{T.delete(new URL(v).host)}catch{}}}let A=await P(h,w);if(A.status!==402)return A;l("Received 402 Payment Required");let E=A.headers.get("X-ACCESS-PASS-TIERS");if(u&&E){l("Server offers access passes, purchasing...");try{let m=JSON.parse(atob(E)),b=await V(h,w,A,m,v);if(b)return b}catch(m){l("Access pass purchase failed, falling back to per-request payment:",m)}}let R=A.headers.get("PAYMENT-REQUIRED");if(!R)throw new I("missing_payment_required_header","Server returned 402 but no PAYMENT-REQUIRED header");let _;try{let m=atob(R);_=JSON.parse(m)}catch{throw new I("invalid_payment_required","Failed to decode PAYMENT-REQUIRED header")}l("Payment requirements:",_);let H=A.headers.get("X-Quote-Hash");H&&l("Quote hash received:",H);let L=k(_.accepts);if(!L){let m=_.accepts.map(b=>b.network).join(", ");throw new I("no_matching_payment_option",`No connected wallet for any available network: ${m}`)}let{accept:U,adapter:C,wallet:j}=L;if(l(`Using ${C.name} for ${U.network}`),C.name==="Solana"&&!U.extra?.feePayer)throw new I("missing_fee_payer","Solana payment option missing feePayer in extra");let he=U.extra?.decimals??(Et(U.asset)?6:void 0);if(typeof he!="number")throw new I("missing_decimals","Payment option missing decimals - provide in extra or use a known stablecoin");let G=U.amount??U.maxAmountRequired;if(!G)throw new I("missing_amount","Payment option missing amount");if(a&&BigInt(G)>BigInt(a))throw new I("amount_exceeds_max",`Payment amount ${G} exceeds maximum ${a}`);let Ue=q(U.network,C);l("Checking balance...");try{let m=await C.getBalance(U,j,Ue),b=Number(G)/Math.pow(10,he);if(m<b){let At=M(U.network,C.name);throw new I("insufficient_balance",`Insufficient balance on ${At}. Have $${m.toFixed(4)}, need $${b.toFixed(4)}`)}l(`Balance OK: $${m.toFixed(4)} >= $${b.toFixed(4)}`)}catch(m){if(m instanceof I)throw m;l("Balance check failed (RPC error), proceeding with transaction attempt")}if(p&&!await p(U))throw new I("payment_rejected","Payment rejected by onPaymentRequired callback");l("Building transaction...");let X=await C.buildTransaction(U,j,Ue);l("Transaction signed");let Y;C.name==="EVM"?Y=JSON.parse(X.serialized):Y={transaction:X.serialized};let Ae=h,oe=_.resource;if(typeof _.resource=="string")try{let m=new URL(_.resource,Ae).toString();m!==_.resource&&l("Resolved relative resource URL:",_.resource,"\u2192",m),oe=m}catch{oe=_.resource}else if(_.resource&&typeof _.resource=="object"&&"url"in _.resource){let m=_.resource;try{let b=new URL(m.url,Ae).toString();b!==m.url&&(l("Resolved relative resource URL:",m.url,"\u2192",b),oe={...m,url:b})}catch{}}let be={x402Version:U.x402Version??2,resource:oe,accepted:U,payload:Y};X.extensions&&(be.extensions=X.extensions);let Ze=btoa(JSON.stringify(be));if(d)try{d(U,X.settlementProbe)}catch{}l("Retrying request with payment...");let Q=await P(h,{...w,headers:{...w?.headers||{},"PAYMENT-SIGNATURE":Ze,...H?{"X-Quote-Hash":H}:{}}});if(l("Retry response status:",Q.status),Q.status===402){let m="unknown";try{let b=await Q.clone().json();m=String(b.error||b.message||JSON.stringify(b)),l("Rejection reason:",m)}catch{}throw new I("payment_rejected",`Payment was rejected by the server: ${m}`)}let ae=Q.headers.get("PAYMENT-RESPONSE"),F;if(ae)try{F=JSON.parse(atob(ae))}catch{}return F??={},F.amountAtomic=G,F.assetDecimals=he,Pn.set(Q,F),F.extensions&&l("Settlement extensions:",Object.keys(F.extensions).join(", ")),Q}async function K(h,w){let[v,A]=await En(h,w);return D(v,A)}return{fetch:K}}function z(t){if(t instanceof Error){if(t.message&&t.message.length>0)return t.message;if(t.name&&t.name.length>0)return t.name}let e=String(t);return e.length>0?e:"unknown error"}async function Qe(t){let e="";try{e=(await t.clone().text()).slice(0,600)}catch{}let n=e.toLowerCase(),r=n.includes("settle")||n.includes("facilitator"),s=e;try{let o=JSON.parse(e),a=[o.error,o.detail,o.message].filter(i=>typeof i=="string"&&i.length>0);a.length>0&&(s=a.join(" \u2014 "))}catch{}return s||(s=`HTTP ${t.status}`),{reason:r?"settlement_failed":"merchant_rejected",detail:`merchant HTTP ${t.status}: ${s}`}}var gt="Payment authorization was sent, but the merchant did not respond within the timeout. ",yt=" Do not retry without checking \u2014 inspect the funding wallet for a transfer to the merchant before attempting payment again.";async function ht(t,e,n){if(!t)return{confirmed:!1,detail:gt+"This payment scheme has no on-chain confirmation check, so the SDK cannot verify whether it settled."+yt};try{if(t.kind==="solana"){let a=se(),i=n??a.getDefaultRpcUrl(e.caip2);if(!a.confirmSettlement)return Gt();let c=await a.confirmSettlement(t,i);return c.settled?{confirmed:!0,txSignature:c.txSignature}:zt()}let r=Oe(),s=r.getDefaultRpcUrl(e.caip2);if(!r.confirmSettlement)return Gt();let o=await r.confirmSettlement(t,s);return o.settled?{confirmed:!0,txSignature:o.txSignature}:zt()}catch(r){return{confirmed:!1,detail:gt+`On-chain confirmation could not be completed (${z(r)}).`+yt}}}function zt(){return{confirmed:!1,detail:gt+"On-chain confirmation found no matching settlement yet \u2014 the payment may still be pending, or may not have settled."+yt}}function Gt(){return{confirmed:!1,detail:gt+"The chain adapter does not support on-chain confirmation."+yt}}var Rn=new Set(["exact","exact-approval"]);async function _n(t,e,n,r){let s;try{s=await r.signNextVoucher(n.amount)}catch{return null}let o=new Headers(e.headers??void 0);o.set("X-Tab-Voucher",De(s));let a={method:e.method??"GET",headers:o};e.signal&&(a.signal=e.signal),typeof e.body=="string"&&(a.body=e.body);let i;try{i=await fetch(t,a)}catch(c){return{ok:!1,reason:"error",detail:c?.message??String(c)}}return i.status===402?(r.rollbackVoucher?.call(r,s),null):i.ok?{ok:!0,paid:!0,response:i,amountPaid:n.amount,network:n.network}:{ok:!1,...await Qe(i)}}var Xt={version:2,async parseChallenge(t){return at(t)},async pay(t,e,n,r,s){if(s.tab){let y=n.options.find(g=>g.scheme==="tab"&&g.network.family==="svm"&&g.payTo===s.tab.counterparty);if(y){let g=await _n(t,e,y,s.tab);if(g)return g}}let o=n.options.filter(y=>Rn.has(y.scheme));if(o.length===0)return{ok:!1,reason:"no_payment_options",detail:`no generically payable scheme offered (got: ${n.options.map(y=>y.scheme).join(", ")})`};let a=o.find(y=>y.network.family==="evm"?!!r.evm:y.network.family==="svm"?!!r.solana:!1);if(!a)return{ok:!1,reason:"unsupported_network"};let i=s.timeoutMs??15e3,c=s.responseTimeoutMs??12e4,u=new AbortController,p=setTimeout(()=>u.abort(),i),d=!1,f,x=(y,g)=>{d=!0,f=g,clearTimeout(p),p=setTimeout(()=>u.abort(),c)},l=Jt({wallets:r,preferredNetwork:a.network.caip2,maxAmountAtomic:s.maxAmountAtomic,fetch:globalThis.fetch,onPaymentDispatched:x}),P=e.signal?AbortSignal.any([e.signal,u.signal]):u.signal,T={method:e.method??"GET",headers:e.headers,signal:P};typeof e.body=="string"&&(T.body=e.body);try{let y=await l.fetch(t,T);if(clearTimeout(p),!y.ok)return{ok:!1,...await Qe(y)};let g,S=y.headers.get("PAYMENT-RESPONSE");if(S)try{let k=Tt(S);k&&typeof k.transaction=="string"&&(g=k.transaction)}catch{}return{ok:!0,paid:!0,response:y,amountPaid:a.amount,network:a.network,txSignature:g}}catch(y){clearTimeout(p);let g=y;if(g?.name==="AbortError"){if(!d)return{ok:!1,reason:"timeout"};let S=await ht(f,a.network,s.solanaRpcUrl);return S.confirmed?{ok:!0,paid:!0,response:void 0,amountPaid:a.amount,network:a.network,txSignature:S.txSignature}:{ok:!1,reason:"payment_unconfirmed",detail:S.detail}}return{ok:!1,reason:"error",detail:g?.message??String(y)}}}};var Yt=require("viem");var kn={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]};async function Cn(){let t=globalThis.crypto??(await import("crypto")).webcrypto,e=new Uint8Array(32);return t.getRandomValues(e),"0x"+Array.from(e,n=>n.toString(16).padStart(2,"0")).join("")}async function In(t,e,n){if(typeof t.signTypedData!="function")throw new Error("EVM wallet does not support signTypedData");let r=Math.floor(Date.now()/1e3),s=String(r-600),o=String(r+(e.maxTimeoutSeconds??60)),a={from:t.address,to:e.payTo,value:e.amount,validAfter:s,validBefore:o,nonce:await Cn()},i=Ye[e.network.caip2];if(i===void 0)throw new Error(`unknown chain id for network ${e.network.caip2}`);let c=e.extra,u=await t.signTypedData({domain:{name:c.name,version:c.version,chainId:i,verifyingContract:(0,Yt.getAddress)(e.asset)},types:kn,primaryType:"TransferWithAuthorization",message:a});return{payment:{x402Version:1,scheme:e.scheme,network:n,payload:{signature:u,authorization:a}},settlementProbe:{kind:"eip3009",from:a.from,nonce:a.nonce,asset:e.asset,chainId:i}}}async function Pt(t,e,n){try{let r;for(let s of t.options){let o=s.network.family==="evm"&&!!e.evm||s.network.family==="svm"&&!!e.solana;if(s.scheme!=="exact"){o&&(r=s.scheme);continue}if(s.network.family==="evm"&&e.evm){let a=await e.evm;return await Nn(s,a,n)}if(s.network.family==="svm"&&e.solana){let a=await e.solana;return await On(s,a,n)}}return r!==void 0?{ok:!1,reason:"merchant_rejected",detail:`v1 supports only the 'exact' scheme, got '${r}'`}:{ok:!1,reason:"unsupported_network"}}catch(r){return{ok:!1,reason:"error",detail:z(r)}}}async function Nn(t,e,n){if(n.maxAmountAtomic!==void 0&&BigInt(t.amount)>BigInt(n.maxAmountAtomic))return{ok:!1,reason:"budget_exceeded"};let r=t.extra??{},s=r.name,o=r.version;if(typeof s!="string"||s.length===0||typeof o!="string"||o.length===0)return{ok:!1,reason:"merchant_rejected",detail:"v1 challenge missing exact-scheme EIP-712 domain (extra.name / extra.version)"};let a=t.network.bare,{payment:i,settlementProbe:c}=await In(e,t,a);return{ok:!0,headerValue:Buffer.from(JSON.stringify(i),"utf8").toString("base64"),option:t,settlementProbe:c}}async function On(t,e,n){if(n.maxAmountAtomic!==void 0&&BigInt(t.amount)>BigInt(n.maxAmountAtomic))return{ok:!1,reason:"budget_exceeded"};if(t.scheme!=="exact")return{ok:!1,reason:"merchant_rejected",detail:`v1 SVM supports only the 'exact' scheme, got '${t.scheme}'`};let r=t.extra??{};if(typeof r.feePayer!="string"||r.feePayer.length===0)return{ok:!1,reason:"merchant_rejected",detail:"v1 SVM challenge missing extra.feePayer (required as the transaction fee payer)"};let s=t.network.bare,o={x402Version:1,scheme:t.scheme,network:s,asset:t.asset,payTo:t.payTo,amount:t.amount,maxAmountRequired:t.amount,maxTimeoutSeconds:t.maxTimeoutSeconds??60,extra:r},i=await se().buildTransaction(o,e,n.solanaRpcUrl),c={x402Version:1,scheme:t.scheme,network:s,payload:{transaction:i.serialized}};return{ok:!0,headerValue:Buffer.from(JSON.stringify(c),"utf8").toString("base64"),option:t,settlementProbe:i.settlementProbe}}function Un(t){let e=[];for(let n of t){if(!n||typeof n!="object")continue;let r=n,s=Me(String(r.network??""));s&&e.push({scheme:String(r.scheme??"exact"),network:s,amount:String(r.maxAmountRequired??r.amount??"0"),asset:String(r.asset??""),payTo:String(r.payTo??""),maxTimeoutSeconds:typeof r.maxTimeoutSeconds=="number"?r.maxTimeoutSeconds:void 0,extra:r.extra&&typeof r.extra=="object"?r.extra:void 0})}return e}var Qt={version:1,async parseChallenge(t){if(t.headers.get("payment-required"))return null;let e;try{e=await t.clone().json()}catch{return null}let n=Array.isArray(e.accepts)?e.accepts:[];if(n.length===0)return null;let r=Un(n);return r.length===0?null:{x402Version:1,options:r}},async pay(t,e,n,r,s){let o,a=new AbortController,i=!1,c,u;try{let p=s.timeoutMs??15e3;o=setTimeout(()=>a.abort(),p);let d=await Pt(n,r,s);if(!d.ok)return{ok:!1,reason:d.reason,detail:d.detail};let f=d.headerValue,x=d.option;u=x,c=d.settlementProbe;let l=new Headers(e.headers??void 0);l.set("X-PAYMENT",f);let P=e.signal!=null?AbortSignal.any([e.signal,a.signal]):a.signal,T={method:e.method,headers:l,signal:P};typeof e.body=="string"&&(T.body=e.body),i=!0,clearTimeout(o);let y=s.responseTimeoutMs??12e4;o=setTimeout(()=>a.abort(),y);let g=await fetch(t,T);return g.ok?{ok:!0,paid:!0,response:g,amountPaid:x.amount,network:x.network,txSignature:Bn(g)}:{ok:!1,...await Qe(g)}}catch(p){if(p instanceof Error&&p.name==="AbortError"){if(!i)return{ok:!1,reason:"timeout"};let d=await ht(c,u.network,s.solanaRpcUrl);return d.confirmed?{ok:!0,paid:!0,response:void 0,amountPaid:u.amount,network:u.network,txSignature:d.txSignature}:{ok:!1,reason:"payment_unconfirmed",detail:d.detail}}return{ok:!1,reason:"error",detail:z(p)}}finally{o!==void 0&&clearTimeout(o)}}};function Bn(t){let e=t.headers.get("x-payment-response")??t.headers.get("X-PAYMENT-RESPONSE");if(e)try{let n=JSON.parse(Buffer.from(e,"base64").toString("utf8")),r=n.transaction??n.txHash??n.transactionHash;return typeof r=="string"?r:void 0}catch{return}}var en=J(require("tweetnacl"),1);var Rt=require("@solana/web3.js"),Zt=Symbol.for("x402:keypair");function _t(t){let e=t.evm;if(e&&typeof e.signMessage=="function"&&typeof e.address=="string")return{address:e.address,signMessage:e.signMessage};let n=t.solana;if(n){let r=n[Zt];if(r&&r.secretKey&&r.publicKey)return{publicKey:r.publicKey,signMessage:async s=>en.sign.detached(s,r.secretKey)}}return null}var Dn=[Xt,Qt];async function Mn(t){let e=_t(t);if(!e)return fetch;try{return(await import("@x402/extensions/sign-in-with-x")).wrapFetchWithSIWx(fetch,e)}catch(n){return console.warn(`[x402] SIW-X unavailable \u2014 @x402/extensions failed to load; SIW-X merchants will not authenticate. ${z(n)}`),fetch}}async function kt(t,e,n,r){if(e.body!==void 0&&e.body!==null&&typeof e.body!="string")return{ok:!1,reason:"error",detail:"payAndFetch requires a string body; non-string bodies (Buffer, FormData, URLSearchParams, ReadableStream) cannot be safely re-sent on the paid retry"};let s;try{s=await(await Mn(n))(t,{...e})}catch(o){return{ok:!1,reason:"error",detail:z(o)}}if(s.status!==402)return{ok:!0,paid:!1,response:s};for(let o of Dn){let a=await o.parseChallenge(s.clone());if(a)return o.pay(t,e,a,n,r)}return{ok:!1,reason:"no_payment_options"}}async function tn(t,e={},n){let r=await Te(t,e);if(r.kind==="free")return{result:{ok:!0,paid:!1,response:r.response},tab:null};if(r.kind==="no_tab")return{result:{ok:!1,reason:"no_payment_options",detail:`no tab option offered (schemes: ${r.schemesOffered.join(", ")})`},tab:null};if(r.kind==="error")return{result:{ok:!1,reason:"error",detail:r.detail},tab:null};let{offer:s}=r,o=BigInt(ee(n.perUnitCap));if(BigInt(s.amountAtomic)>o)return{result:{ok:!1,reason:"budget_exceeded",detail:`seller quotes ${s.amountAtomic} atomic; perUnitCap allows ${o}`},tab:null};let a=n.tabs?.get(s.payTo);return(!a||!a.state.isOpen)&&(a=await st({vault:n.vault,network:"solana:mainnet",seller:s.payTo,perUnitCap:n.perUnitCap,totalCap:n.totalCap,sessionDuration:n.sessionDuration,facilitatorUrl:n.facilitatorUrl,onLiveSession:n.onLiveSession}),n.tabs?.set(s.payTo,a)),{result:await kt(t,e,{},{tab:a}),tab:a}}function $n(t){return{counterparty:t.payTo,perRequest:{atomic:t.amountAtomic,human:le(t.amountAtomic)},asset:t.asset,network:{caip2:t.networkCaip2},scheme:"tab",settlement:{custody:"non-custodial",protection:"lock",settleOn:"close"},credit:null,...t.resourceUrl!==void 0?{resourceUrl:t.resourceUrl}:{}}}async function nn(t,e={},n={}){let r=n.cache?.get(t);if(r)return{kind:"terms",terms:r};let s=await Te(t,e,n.fetchImpl??fetch);if(s.kind!=="offer")return s;if(s.offer.asset!==Ge)return{kind:"error",detail:`tab offer asset is not USDC ("${s.offer.asset}"); refusing to render a human price`};let o=$n(s.offer);return n.cache?.set(t,o),{kind:"terms",terms:o}}0&&(module.exports={DEFAULT_FACILITATOR_URL,DEXTER_VAULT_PROGRAM_ID,INSTRUCTIONS_SYSVAR_ID,LiveSessionExistsError,SECP256R1_PROGRAM_ID,SessionScopeExceededError,TabClosedError,UnsupportedNetworkError,atomicToHuman,buildRegisterSessionKeyInstruction,buildRevokeSessionKeyInstruction,buildSecp256r1VerifyInstruction,buildVoucherMessage,humanToAtomic,openTab,payUrlWithTab,resolveTabOffer,resolveTabTerms,resumeTab,sessionRegisterMessage,sessionRevokeMessage,tabFromGrant,voucherPayloadMessage,voucherToHeader});
package/dist/tab/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  var me=class extends Error{constructor(n){super(`Network ${n} is not yet supported by @dexterai/x402/tab`);this.network=n;this.name="UnsupportedNetworkError"}},pe=class extends Error{constructor(n,r){super(`Session scope exceeded: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="SessionScopeExceededError"}},Q=class extends Error{constructor(n){super(`Tab ${n} is already closed`);this.channelId=n;this.name="TabClosedError"}},mt=class extends Error{constructor(n){super(`a LIVE session already exists for counterparty ${n.allowedCounterparty} (session ${n.sessionPubkeyHex.slice(0,16)}\u2026, expires ${n.expiresAtUnix}; on-chain spent=${n.spentAtomic}, crystallized=${n.crystallizedCumulativeAtomic}, frontier=${n.frontierAtomic}). Replacing it voids any signed-but-unsettled vouchers beyond the frontier. Settle the old tab first (tab.close() or POST its last voucher to /tab/settle), or pass onLiveSession: 'replace' to atomically revoke-then-register over it.`);this.details=n;this.name="LiveSessionExistsError"}};import{PublicKey as _t}from"@solana/web3.js";import{bytesToHex as ee}from"@noble/hashes/utils";import Jt from"tweetnacl";import{sessionRegisterMessage as pt,sessionRevokeMessage as Ft,voucherPayloadMessage as dt,buildVoucherMessage as jt}from"@dexterai/vault/messages";import{sha256 as zt}from"@noble/hashes/sha256";function Pt(t,e,n){return{publicKey:t.publicKey,privateKey:t.privateKey,scope:e,registration:n}}function Rt(t,e,n){if(n.length!==32)throw new Error(`channelIdBytes must be 32 bytes, got ${n.length}`);let r=BigInt(e.cumulativeAmount),s=BigInt(t.scope.maxAmountAtomic);if(r>s)throw new Error(`voucher cumulative ${r} exceeds session cap ${s}`);let o=Math.floor(Date.now()/1e3);if(o>=t.scope.expiresAtUnix)throw new Error(`session expired at ${t.scope.expiresAtUnix}, now ${o}`);let a=dt({channelId:n,cumulativeAmount:r,sequenceNumber:e.sequenceNumber}),i=Jt.sign.detached(a,t.privateKey);return{payload:e,sessionPublicKey:t.publicKey,sessionRegistration:t.registration,sessionSignature:i}}function ze(t){if(!/^\d+$/.test(t))throw new Error(`atomic amount must be a non-negative integer string, got "${t}"`);return BigInt(t)}function Ge(t){let e=new Uint8Array(8);new DataView(e.buffer).setBigUint64(0,t.nonce,!0);let n=new TextEncoder().encode(t.sellerUrl),r=zt.create();return r.update(t.vaultPda.toBytes()),r.update(n),r.update(e),r.digest()}var Gt=3600,Pe="https://x402.dexter.cash",kt=6;function Z(t,e=kt){if(!/^\d+(\.\d+)?$/.test(t))throw new Error(`amount must be a non-negative decimal string, got "${t}"`);let[n,r=""]=t.split(".");if(r.length>e)throw new Error(`amount "${t}" has more than ${e} decimals`);let s=r.padEnd(e,"0"),o=`${n}${s}`.replace(/^0+(?=\d)/,"");return o===""?"0":o}function de(t,e=kt){if(!/^\d+$/.test(t))throw new Error(`atomic must be a non-negative integer string, got "${t}"`);let n=t.padStart(e+1,"0"),r=n.slice(0,-e).replace(/^0+(?=\d)/,"")||"0",s=n.slice(-e).replace(/0+$/,"");return s?`${r}.${s}`:r}var Re=class{channelId;network;counterparty;internals;initialCumulativeAtomic;cumulativeAtomic;sequenceNumber=0;closed=!1;lastSignedVoucher=null;previousSignedVoucher=null;constructor(e){this.internals=e,this.channelId=e.channelIdHex,this.network=e.network,this.counterparty=e.counterparty,this.initialCumulativeAtomic=e.initialCumulativeAtomic??0n,this.cumulativeAtomic=this.initialCumulativeAtomic}get state(){let e=this.internals.totalCapAtomic-this.cumulativeAtomic,n=Math.floor(Date.now()/1e3);return{isOpen:!this.closed,spent:de(this.cumulativeAtomic.toString()),remaining:de(e.toString()),expiresInSec:Math.max(0,this.internals.expiresAtUnix-n)}}async signNextVoucher(e){if(this.closed)throw new Q(this.channelId);let n=BigInt(e);if(n<=0n)throw new Error(`voucher increment must be > 0, got ${e}`);if(n>this.internals.perUnitCapAtomic)throw new pe("cap_exceeded",`single voucher increment ${n} exceeds perUnitCap ${this.internals.perUnitCapAtomic}`);let r=this.cumulativeAtomic+n;if(r>this.internals.totalCapAtomic)throw new pe("cap_exceeded",`cumulative ${r} would exceed totalCap ${this.internals.totalCapAtomic}`);let s=this.sequenceNumber+1,o={channelId:this.channelId,cumulativeAmount:r.toString(),sequenceNumber:s},a=await this.internals.vault.signWithSession(this.internals.session,o);return this.previousSignedVoucher=this.lastSignedVoucher,this.lastSignedVoucher=a,this.sequenceNumber=s,this.cumulativeAtomic=r,a}rollbackVoucher(e){let n=this.lastSignedVoucher;if(!n||n.payload.sequenceNumber!==e.payload.sequenceNumber||n.payload.cumulativeAmount!==e.payload.cumulativeAmount)return!1;let r=this.previousSignedVoucher;if(r)this.sequenceNumber=r.payload.sequenceNumber,this.cumulativeAtomic=BigInt(r.payload.cumulativeAmount),this.lastSignedVoucher=r;else if(n.payload.sequenceNumber===1)this.sequenceNumber=0,this.cumulativeAtomic=this.initialCumulativeAtomic,this.lastSignedVoucher=null;else return!1;return this.previousSignedVoucher=null,!0}async stream(e,n){if(this.closed)throw new Q(this.channelId);let r=await this.signNextVoucher(this.internals.perUnitCapAtomic.toString()),s=new Headers(n?.headers);s.set("X-Tab-Voucher",Xe(r)),s.set("Accept","text/event-stream");let o=await fetch(e,{...n,headers:s});if(!o.ok){let a=await o.text().catch(()=>"");throw new Error(`tab.stream HTTP ${o.status}: ${a.slice(0,500)}`)}if(!o.body)throw new Error("tab.stream response has no body");return en(o.body)}async close(){if(this.closed)throw new Q(this.channelId);let e={settleTx:""};this.lastSignedVoucher&&this.cumulativeAtomic>0n&&(e=await Yt(this.internals.facilitatorUrl,this.lastSignedVoucher,this.internals.network));let n=(this.internals.closeMode??"revoke")==="revoke";return n&&await this.internals.vault.signCloseTab(this.internals.session,this.channelId,this.cumulativeAtomic.toString()),this.closed=!0,this.internals.session.privateKey.fill(0),{settledAmount:de(this.cumulativeAtomic.toString()),sessionRevoked:n,...e}}};function Xe(t){return Buffer.from(JSON.stringify({payload:t.payload,sessionPublicKey:ee(t.sessionPublicKey),sessionRegistration:ee(t.sessionRegistration),sessionSignature:ee(t.sessionSignature)}),"utf8").toString("base64")}function fe(t){return typeof t!="string"||!/^\d+$/.test(t)?null:BigInt(t)}function Xt(t){let e;try{e=JSON.parse(t)}catch{return!1}if(typeof e!="object"||e===null)return!1;let n="non_monotonic_cumulative";if(e.error!==n&&e.reason!==n)return!1;let r=fe(e.attempted_cumulative),s=fe(e.on_chain_spent),o=fe(e.frontier);return r===null||s===null||o===null?!1:r>s&&r<=o}async function Yt(t,e,n){let r=`${t.replace(/\/$/,"")}/tab/settle`,s={channelId:e.payload.channelId,cumulativeAmount:e.payload.cumulativeAmount,sequenceNumber:e.payload.sequenceNumber,sessionPublicKey:ee(e.sessionPublicKey),sessionSignature:ee(e.sessionSignature),sessionRegistration:ee(e.sessionRegistration),network:n},o=await fetch(r,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)}),a=await o.text();if(!o.ok){if(o.status===409&&Xt(a))return{settleTx:""};throw new Error(`tab settle ${o.status}: ${a.slice(0,500)}`)}let i;try{i=JSON.parse(a)}catch{throw new Error(`tab settle returned non-JSON: ${a.slice(0,200)}`)}if(i.reason==="covered_by_frontier"){let u=fe(i.attemptedCumulative),p=fe(i.onChainSpent),d=fe(i.frontier);if(u!==null&&p!==null&&d!==null&&u>p&&u<=d)return{settleTx:""}}if(!i.settleTx)throw new Error(`tab settle returned no settleTx: ${a.slice(0,200)}`);let c={settleTx:i.settleTx};return typeof i.grossAmount=="string"&&(c.grossAmount=i.grossAmount),typeof i.feeAmount=="string"&&(c.feeAmount=i.feeAmount),typeof i.netAmount=="string"&&(c.netAmount=i.netAmount),c}async function ft(t,e,n,r,s){let o=`${t.replace(/\/$/,"")}/tab/open`,a=await fetch(o,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({buyer_swig_address:e,seller:s,max_amount_atomic:n.toString(),network:r})}),i=await a.json().catch(()=>({}));if(!a.ok||!i.success||!i.armed)throw new Error(`tab_open_unprotected: ${i.error??`http_${a.status}`}`);return{armed:!0,signature:i.signature??""}}async function gt(t){if(t.network!==t.vault.network)throw new me(`options.network (${t.network}) doesn't match vault.network (${t.vault.network})`);if(t.network!=="solana:mainnet")throw new me(t.network);let e=BigInt(Math.floor(Math.random()*4294967295)),n=new _t(t.vault.vaultPda),r=Ge({vaultPda:n,sellerUrl:t.seller,nonce:BigInt(e)}),s=ee(r),o=BigInt(Z(t.perUnitCap)),a=BigInt(Z(t.totalCap));if(o<=0n)throw new Error("perUnitCap must be > 0");if(a<o)throw new Error("totalCap must be >= perUnitCap");if(t.revolvingCapacity!==void 0&&BigInt(Z(t.revolvingCapacity))<=0n)throw new Error("revolvingCapacity must be > 0");let i=t.sessionDuration??Gt,c=Math.floor(Date.now()/1e3)+i,u=Zt(t.seller),p={channelId:s,maxAmountAtomic:a.toString(),revolvingCapacityAtomic:t.revolvingCapacity?Z(t.revolvingCapacity):a.toString(),expiresAtUnix:c,allowedCounterparty:u},d=await t.vault.authorizeSession(p,{onLiveSession:t.onLiveSession});return await ft(t.facilitatorUrl??Pe,t.vault.swigAddress,a,t.network,u),new Re({vault:t.vault,network:t.network,seller:t.seller,counterparty:u,session:d,channelIdHex:s,channelIdBytes:r,perUnitCapAtomic:o,totalCapAtomic:a,expiresAtUnix:c,facilitatorUrl:t.facilitatorUrl??Pe})}async function Qt(t){throw new Error("resumeTab is Phase 3 work. Session keys are memory-only by design; recovery requires reading active_session on chain and re-authorizing. Tracked in dexter-vault roadmap.")}function Zt(t){if(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(t))try{return new _t(t),t}catch{}throw new Error(`seller must be a base58 Solana pubkey for Phase 2 (got "${t}"). URL-based counterparty resolution lands in Phase 3 (seller middleware).`)}async function*en(t){let e=t.getReader(),n=new TextDecoder,r="";try{for(;;){let{done:s,value:o}=await e.read();if(s)break;r+=n.decode(o,{stream:!0});let a;for(;(a=r.indexOf(`
2
2
 
3
- `))!==-1;){let i=r.slice(0,a);r=r.slice(a+2);let c=tn(i);if(c.eventName==="end")return;if(c.data!==null){let u=c.data.replace(/\\n/g,`
4
- `);yield new TextEncoder().encode(u)}}}}finally{e.releaseLock()}}function tn(t){let e=null,n=[];for(let r of t.split(`
3
+ `))!==-1;){let i=r.slice(0,a);r=r.slice(a+2);let c=tn(i);if(c.eventName==="end")return;if(c.data!==null){let u=c.data.replace(/\\(\\|n)/g,(p,d)=>d==="n"?`
4
+ `:"\\");yield new TextEncoder().encode(u)}}}}finally{e.releaseLock()}}function tn(t){let e=null,n=[];for(let r of t.split(`
5
5
  `))r.startsWith("event:")?e=r.slice(6).trim():r.startsWith("data:")&&n.push(r.slice(5).trimStart());return{eventName:e,data:n.length?n.join(`
6
6
  `):null}}import ke from"tweetnacl";import{Connection as cn,PublicKey as _e}from"@solana/web3.js";import{bytesToHex as ln}from"@noble/hashes/utils";import{fetchSessionAccount as un,isSessionLive as mn}from"@dexterai/vault/session";import{readVaultFull as pn}from"@dexterai/vault/reader";import{buildRegisterSessionKeyInstruction as nn,buildRevokeSessionKeyInstruction as rn,deriveSwigWalletAddress as or}from"@dexterai/vault/instructions";import{buildSecp256r1VerifyInstruction as sn}from"@dexterai/vault/precompile";import{DEXTER_VAULT_PROGRAM_ID as yt,SECP256R1_PROGRAM_ID as on,INSTRUCTIONS_SYSVAR_ID as an}from"@dexterai/vault/constants";var ht="solana:mainnet";async function dn(t){let e=t.facilitatorUrl??Pe,n=t.programId??yt,r=new _e(t.vaultPda),s=new _e(t.params.counterparty),o=ze(t.perUnitCapAtomic);if(o<=0n)throw new Error(`perUnitCapAtomic must be > 0, got ${t.perUnitCapAtomic}`);let a=ze(t.params.maxAmountAtomic),i=ze(t.params.maxRevolvingCapacityAtomic),c=fn(t.sessionSecretKey),u=new _e(t.params.sessionPubkey).toBytes();if(!Ct(c.publicKey,u))throw new Error(`tab_session_key_mismatch: the supplied secret derives ${new _e(c.publicKey).toBase58()} but params.sessionPubkey is ${t.params.sessionPubkey} \u2014 wrong key handed to this process`);let p=ke.randomBytes(32),d=ke.sign.detached(p,c.secretKey);if(!ke.sign.detached.verify(p,d,u))throw new Error("tab_session_key_mismatch: secret key failed the sign/verify self-check against params.sessionPubkey \u2014 the seed half does not sign for the granted pubkey");let f=pt({programId:n,vaultPda:r,sessionPubkey:c.publicKey,maxAmount:a,expiresAt:BigInt(t.params.expiresAtUnix),allowedCounterparty:s,nonce:t.params.nonce,maxRevolvingCapacity:i}),x=typeof t.connection=="string"?new cn(t.connection,"confirmed"):t.connection,l=await un(x,r,s,n);if(!l||l.version===0)throw new Error("tab_session_not_live: no live SessionAccount PDA for this (vault, counterparty) \u2014 revoked, expiry-swept, or never registered");if(!mn(l))throw new Error(l.version!==1?`tab_session_not_live: SessionAccount has unsupported version ${l.version} \u2014 not a live v1 session`:`tab_session_not_live: SessionAccount is present but expired (expiresAt=${l.session.expiresAt})`);if(!Ct(l.session.sessionPubkey,c.publicKey))throw new Error(`tab_session_pubkey_mismatch: the on-chain session carries ${new _e(l.session.sessionPubkey).toBase58()} \u2014 the grant this key belongs to was replaced by a newer registration`);if(l.session.maxAmount!==a||l.session.expiresAt!==t.params.expiresAtUnix||l.session.nonce!==t.params.nonce||l.session.maxRevolvingCapacity!==i)throw new Error(`tab_grant_params_stale: params disagree with the on-chain session scope (chain: maxAmount=${l.session.maxAmount} expiresAt=${l.session.expiresAt} nonce=${l.session.nonce} revolving=${l.session.maxRevolvingCapacity}; params: ${t.params.maxAmountAtomic}/${t.params.expiresAtUnix}/${t.params.nonce}/${t.params.maxRevolvingCapacityAtomic}) \u2014 refresh the grant hand-off`);let P=l.session.spent>l.session.crystallizedCumulative?l.session.spent:l.session.crystallizedCumulative;if(P>=a)throw new Error(`tab_exhausted: on-chain frontier ${P} has consumed the session cap ${a} \u2014 no voucher can strictly exceed it; open a new grant`);let T=t.sellerUrl??t.params.counterparty,y=BigInt(Math.floor(Math.random()*4294967295)),g=Ge({vaultPda:r,sellerUrl:T,nonce:y}),S=ln(g),k=t.swigAddress;if(!k){let O=await pn(x,r);if(!O.exists||!O.swigAddress)throw new Error(`tab_vault_unreadable: vault ${r.toBase58()} has no readable swig_address on chain \u2014 pass options.swigAddress explicitly`);k=O.swigAddress}await ft(e,k,a,ht,t.params.counterparty);let U={channelId:S,maxAmountAtomic:t.params.maxAmountAtomic,revolvingCapacityAtomic:t.params.maxRevolvingCapacityAtomic,expiresAtUnix:t.params.expiresAtUnix,allowedCounterparty:t.params.counterparty},K=Pt({publicKey:c.publicKey,privateKey:c.secretKey},U,f),$={network:ht,swigAddress:k,vaultPda:r.toBase58(),authorizeSession:async()=>{throw new Error("grant_tab_no_passkey: a grant-held tab cannot authorize sessions \u2014 session birth requires the wallet owner's passkey ceremony")},signWithSession:async(O,D)=>Rt(O,D,g),signOpenTab:async O=>O.registration,signCloseTab:async()=>{throw new Error("grant_tab_cannot_revoke: session revocation is passkey-signed and belongs to the wallet owner's surfaces \u2014 a grant-held tab closes settle-only")}};return new Re({vault:$,network:ht,seller:T,counterparty:t.params.counterparty,session:K,channelIdHex:S,channelIdBytes:g,perUnitCapAtomic:o,totalCapAtomic:a,expiresAtUnix:t.params.expiresAtUnix,facilitatorUrl:e,initialCumulativeAtomic:P,closeMode:"settle-only"})}function fn(t){if(t.length===64)return ke.sign.keyPair.fromSecretKey(t);if(t.length===32)return ke.sign.keyPair.fromSeed(t);throw new Error(`tab_session_key_invalid: expected a 64-byte nacl secretKey or a 32-byte ed25519 seed, got ${t.length} bytes`)}function Ct(t,e){if(t.length!==e.length)return!1;let n=0;for(let r=0;r<t.length;r++)n|=t[r]^e[r];return n===0}import{PublicKey as An}from"@solana/web3.js";var It=[{caip2:"eip155:8453",bare:"base",family:"evm"},{caip2:"eip155:1",bare:"ethereum",family:"evm"},{caip2:"eip155:137",bare:"polygon",family:"evm"},{caip2:"eip155:42161",bare:"arbitrum",family:"evm"},{caip2:"eip155:10",bare:"optimism",family:"evm"},{caip2:"eip155:43114",bare:"avalanche",family:"evm"},{caip2:"eip155:56",bare:"bsc",family:"evm"},{caip2:"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",bare:"solana",family:"svm"}],gn=new Map(It.map(t=>[t.caip2.toLowerCase(),t])),yn=new Map(It.map(t=>[t.bare.toLowerCase(),t]));function Ce(t){if(!t)return null;let e=t.toLowerCase(),n=gn.get(e)||yn.get(e);return n?{caip2:n.caip2,bare:n.bare,family:n.family}:null}function At(t){let e=t.replace(/-/g,"+").replace(/_/g,"/"),n=e+"=".repeat((4-(e.length%4||4))%4);return JSON.parse(Buffer.from(n,"base64").toString("utf8"))}function hn(t){let e=[];for(let n of t){if(!n||typeof n!="object")continue;let r=n,s=Ce(String(r.network??""));s&&e.push({scheme:String(r.scheme??"exact"),network:s,amount:String(r.amount??r.maxAmountRequired??"0"),asset:String(r.asset??""),payTo:String(r.payTo??""),maxTimeoutSeconds:typeof r.maxTimeoutSeconds=="number"?r.maxTimeoutSeconds:void 0,extra:r.extra&&typeof r.extra=="object"?r.extra:void 0})}return e}async function Ye(t){let e=t.headers.get("payment-required");if(!e)return null;let n;try{n=At(e)}catch{return null}let r=Array.isArray(n.accepts)?n.accepts:[];return r.length===0?null:{x402Version:2,options:hn(r),resourceUrl:n.resource&&typeof n.resource=="object"?String(n.resource.url??""):void 0}}async function Ie(t,e={},n=fetch){let r={method:e.method??"GET",headers:e.headers};typeof e.body=="string"&&(r.body=e.body);let s;try{s=await n(t,r)}catch(i){return{kind:"error",detail:`probe failed: ${i?.message??String(i)}`}}if(s.status!==402)return s.ok?{kind:"free",response:s}:{kind:"error",detail:`probe returned HTTP ${s.status}`};let o=await Ye(s);if(!o)return{kind:"error",detail:"the 402 carries no x402 v2 PAYMENT-REQUIRED challenge"};let a=o.options.find(i=>i.scheme==="tab"&&i.network.family==="svm");if(!a)return{kind:"no_tab",schemesOffered:o.options.map(i=>i.scheme)};try{new An(a.payTo)}catch{return{kind:"error",detail:`tab option payTo is not a valid Solana pubkey: "${a.payTo}"`}}return{kind:"offer",offer:{payTo:a.payTo,amountAtomic:a.amount,asset:a.asset,networkCaip2:a.network.caip2,resourceUrl:o.resourceUrl}}}var Ne="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",Qe="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",Ze="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z",te=Ne,Oe=Qe,Ue=Ze,ne="eip155:8453",ge="eip155:84532",ye="eip155:42161",he="eip155:137",Ae="eip155:10",be="eip155:43114",Se="eip155:56",we="eip155:1187947933",xe="eip155:324705682",Te="eip155:1",re=ne,et=ge,Be=ye,De=he,Me=Ae,$e=be,Ke=Se,Le=we,Ve=xe,We=Te,qe="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",Nt="4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",Ot="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",bt="0x55d398326f99059fF775485246999027B3197955",tt="0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",nt={[Se]:tt,[ne]:Ot,[ge]:"0x036CbD53842c5426634e7929541eC2318f3dCF7e",[ye]:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831",[he]:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",[Ae]:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",[be]:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",[we]:"0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",[xe]:"0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",[Te]:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},rt={[bt]:{symbol:"USDT",decimals:18},[tt]:{symbol:"USDC",decimals:18}};var z="0x000000000022D473030F116dDEE9F6B43aC78BA3",He="0x402085c248EeA27D92E8b30b2C58ed07f9E20001",Fe={[Se]:56,[ne]:8453,[ge]:84532,[ye]:42161,[he]:137,[Ae]:10,[be]:43114,[we]:1187947933,[xe]:324705682,[Te]:1},se={[Ne]:"https://api.dexter.cash/api/solana/rpc",[Qe]:"https://api.devnet.solana.com",[Ze]:"https://api.testnet.solana.com"},B={[Se]:"https://api.dexter.cash/api/evm/bsc/rpc",[ne]:"https://api.dexter.cash/api/base/rpc",[ge]:"https://sepolia.base.org",[ye]:"https://api.dexter.cash/api/evm/arbitrum/rpc",[he]:"https://api.dexter.cash/api/evm/polygon/rpc",[Ae]:"https://api.dexter.cash/api/evm/optimism/rpc",[be]:"https://api.dexter.cash/api/evm/avalanche/rpc",[we]:"https://skale-base.skalenodes.com/v1/base",[xe]:"https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",[Te]:"https://eth.llamarpc.com"};var I=class t extends Error{code;details;constructor(e,n,r){super(n),this.name="X402Error",this.code=e,this.details=r,Object.setPrototypeOf(this,t.prototype)}};import{PublicKey as oe,Connection as St,TransactionMessage as bn,VersionedTransaction as Sn,ComputeBudgetProgram as Ut}from"@solana/web3.js";import{getAssociatedTokenAddress as wt,getAccount as wn,createTransferCheckedInstruction as xn,getMint as Tn,TOKEN_PROGRAM_ID as Bt,TOKEN_2022_PROGRAM_ID as st}from"@solana/spl-token";var vn=12e3,En=1;function ae(t){if(!t||typeof t!="object")return!1;let e=t;return"publicKey"in e&&"signTransaction"in e&&typeof e.signTransaction=="function"}var ot=class{name="Solana";networks=[te,Oe,Ue];config;log;constructor(e={}){this.config=e,this.log=e.verbose?console.log.bind(console,"[x402:solana]"):()=>{}}canHandle(e){return!!(this.networks.includes(e)||e==="solana"||e==="solana-devnet"||e==="solana-testnet"||e.startsWith("solana:"))}getDefaultRpcUrl(e){return this.config.rpcUrls?.[e]?this.config.rpcUrls[e]:se[e]?se[e]:e==="solana"?se[te]:e==="solana-devnet"?se[Oe]:e==="solana-testnet"?se[Ue]:se[te]}getAddress(e){return ae(e)?e.publicKey?.toBase58()??null:null}isConnected(e){return ae(e)?e.publicKey!==null:!1}async getBalance(e,n,r){if(!ae(n)||!n.publicKey)return 0;let s=r||this.getDefaultRpcUrl(e.network),o=new St(s,"confirmed"),a=new oe(n.publicKey.toBase58()),i=new oe(e.asset);try{let u=(await o.getAccountInfo(i,"confirmed"))?.owner.toBase58()===st.toBase58()?st:Bt,p=await wt(i,a,!1,u),d=await wn(o,p,void 0,u),f=e.extra?.decimals??6;return Number(d.amount)/Math.pow(10,f)}catch(c){if(c&&typeof c=="object"&&"name"in c&&(c.name==="TokenAccountNotFoundError"||c.name==="TokenInvalidAccountOwnerError"))return 0;throw c}}async buildTransaction(e,n,r){if(!ae(n))throw new Error("Invalid Solana wallet");if(!n.publicKey)throw new Error("Wallet not connected");let s=r||this.getDefaultRpcUrl(e.network),o=new St(s,"confirmed"),a=new oe(n.publicKey.toBase58()),{payTo:i,asset:c,extra:u}=e,p=e.amount??e.maxAmountRequired;if(!p)throw new Error("Missing amount in payment requirements");if(!u?.feePayer)throw new Error("Missing feePayer in payment requirements");let d=new oe(u.feePayer),f=new oe(c),x=new oe(i);this.log("Building transaction:",{from:a.toBase58(),to:i,amount:p,asset:c,feePayer:u.feePayer});let l=[];l.push(Ut.setComputeUnitLimit({units:vn})),l.push(Ut.setComputeUnitPrice({microLamports:En}));let P=await o.getAccountInfo(f,"confirmed");if(!P)throw new Error(`Token mint ${c} not found`);let T=P.owner.toBase58()===st.toBase58()?st:Bt,y=await Tn(o,f,void 0,T);typeof u?.decimals=="number"&&y.decimals!==u.decimals&&this.log(`Decimals mismatch: requirements say ${u.decimals}, mint says ${y.decimals}`);let g=await wt(f,a,!1,T),S=await wt(f,x,!0,T);if(!await o.getAccountInfo(g,"confirmed"))throw new Error(`No token account found for ${c}. Please ensure you have USDC in your wallet.`);if(!await o.getAccountInfo(S,"confirmed"))throw new Error(`Seller token account not found. The seller (${i}) must have a USDC account.`);let K=BigInt(p);l.push(xn(g,f,S,a,K,y.decimals,[],T));let{blockhash:$}=await o.getLatestBlockhash("confirmed"),O=new bn({payerKey:d,recentBlockhash:$,instructions:l}).compileToV0Message(),D=new Sn(O),h=await n.signTransaction(D);return this.log("Transaction signed successfully"),{serialized:Buffer.from(h.serialize()).toString("base64"),settlementProbe:{kind:"solana",sourceAta:g.toBase58(),destinationAta:S.toBase58(),asset:c,amount:p,blockhash:$}}}async confirmSettlement(e,n){if(e.kind!=="solana")throw new Error(`SolanaAdapter.confirmSettlement cannot handle probe kind "${e.kind}"`);let r=new St(n,"confirmed"),s=new oe(e.destinationAta),o=await r.getSignaturesForAddress(s,{limit:25});if(o.length===0)return{settled:!1};let a=BigInt(e.amount);for(let i of o){if(i.err)continue;let c=await r.getTransaction(i.signature,{commitment:"confirmed",maxSupportedTransactionVersion:0});if(!c?.meta)continue;let u=c.transaction.message.getAccountKeys().keySegments().flat(),p=c.meta.preTokenBalances??[],d=c.meta.postTokenBalances??[];for(let f of d){if(f.mint!==e.asset)continue;let x=u[f.accountIndex];if(!x||!x.equals(s))continue;let l=p.find(y=>y.accountIndex===f.accountIndex),P=BigInt(l?.uiTokenAmount.amount??"0");if(BigInt(f.uiTokenAmount.amount??"0")-P===a)return{settled:!0,txSignature:i.signature}}}return{settled:!1}}};function G(t){return new ot(t)}var Pn={PermitWitnessTransferFrom:[{name:"permitted",type:"TokenPermissions"},{name:"spender",type:"address"},{name:"nonce",type:"uint256"},{name:"deadline",type:"uint256"},{name:"witness",type:"Witness"}],TokenPermissions:[{name:"token",type:"address"},{name:"amount",type:"uint256"}],Witness:[{name:"to",type:"address"},{name:"validAfter",type:"uint256"}]},Dt=BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");function ie(t){if(!t||typeof t!="object")return!1;let e=t;return"address"in e&&typeof e.address=="string"&&e.address.startsWith("0x")}var at=class{name="EVM";networks=[Ke,re,et,We,Be,De,Me,$e,Le,Ve];config;log;constructor(e={}){this.config=e,this.log=e.verbose?console.log.bind(console,"[x402:evm]"):()=>{}}canHandle(e){return!!(this.networks.includes(e)||e==="base"||e==="bsc"||e==="ethereum"||e==="arbitrum"||e==="polygon"||e==="optimism"||e==="avalanche"||e==="skale-base"||e==="skale-base-sepolia"||e.startsWith("eip155:"))}getDefaultRpcUrl(e){return this.config.rpcUrls?.[e]?this.config.rpcUrls[e]:B[e]?B[e]:e==="base"?B[re]:e==="bsc"?B[Ke]:e==="ethereum"?B[We]:e==="arbitrum"?B[Be]:e==="polygon"?B[De]:e==="optimism"?B[Me]:e==="avalanche"?B[$e]:e==="skale-base"?B[Le]:e==="skale-base-sepolia"?B[Ve]:B[re]}getAddress(e){return ie(e)?e.address:null}isConnected(e){return ie(e)?!!e.address:!1}getChainId(e){if(Fe[e])return Fe[e];if(e.startsWith("eip155:")){let n=e.split(":")[1];return parseInt(n,10)}return e==="base"?8453:e==="bsc"?56:e==="ethereum"?1:e==="arbitrum"?42161:8453}async getBalance(e,n,r){if(!ie(n)||!n.address)return 0;let s=r||this.getDefaultRpcUrl(e.network);try{let o=this.encodeBalanceOf(n.address),a=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_call",params:[{to:e.asset,data:o},"latest"]})});if(!a.ok)throw new Error(`RPC request failed: ${a.status}`);let i=await a.json();if(i.error)throw new Error(`RPC error: ${JSON.stringify(i.error)}`);if(!i.result||i.result==="0x")return 0;let c=BigInt(i.result),u=e.extra?.decimals??6;return Number(c)/Math.pow(10,u)}catch(o){throw o}}encodeBalanceOf(e){let n="0x70a08231",r=e.slice(2).toLowerCase().padStart(64,"0");return n+r}async confirmSettlement(e,n){if(e.kind==="eip3009"){let r="0xe94a0102",s=e.from.slice(2).toLowerCase().padStart(64,"0"),o=e.nonce.slice(2).toLowerCase().padStart(64,"0"),a=r+s+o,i=await this.ethCall(n,e.asset,a);return{settled:BigInt(i)!==0n}}if(e.kind==="permit2"){let r="0x4fe02b44",s=BigInt(e.nonce),o=s>>8n,a=s&0xffn,i=e.from.slice(2).toLowerCase().padStart(64,"0"),c=o.toString(16).padStart(64,"0"),u=r+i+c,p=await this.ethCall(n,z,u);return{settled:(BigInt(p)>>a&1n)===1n}}throw new Error(`EvmAdapter.confirmSettlement cannot handle probe kind "${e.kind}"`)}async ethCall(e,n,r){let s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_call",params:[{to:n,data:r},"latest"]})});if(!s.ok)throw new Error(`RPC request failed: ${s.status}`);let o=await s.json();if(o.error)throw new Error(`RPC error: ${JSON.stringify(o.error)}`);if(!o.result||o.result==="0x")throw new Error("RPC returned an empty result");return o.result}async buildTransaction(e,n,r){if(!ie(n))throw new Error("Invalid EVM wallet");if(!n.address)throw new Error("Wallet not connected");if(e.scheme==="exact-approval")return this.buildApprovalTransaction(e,n,r);if(e.extra?.assetTransferMethod==="permit2")return this.buildPermit2Transaction(e,n,r);let{payTo:s,asset:o,extra:a}=e,i=e.amount??e.maxAmountRequired;if(!i)throw new Error("Missing amount in payment requirements");this.log("Building EVM transaction:",{from:n.address,to:s,amount:i,asset:o,network:e.network});let c=this.getChainId(e.network),u={name:a?.name??"USD Coin",version:a?.version??"2",chainId:BigInt(c),verifyingContract:o},p={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},d=new Uint8Array(32);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(d);let f="0x"+[...d].map(g=>g.toString(16).padStart(2,"0")).join(""),x=Math.floor(Date.now()/1e3),l={from:n.address,to:s,value:i,validAfter:String(x-600),validBefore:String(x+(e.maxTimeoutSeconds||60)),nonce:f},P={from:n.address,to:s,value:BigInt(i),validAfter:BigInt(x-600),validBefore:BigInt(x+(e.maxTimeoutSeconds||60)),nonce:f};if(!n.signTypedData)throw new Error("Wallet does not support signTypedData (EIP-712)");let T=await n.signTypedData({domain:u,types:p,primaryType:"TransferWithAuthorization",message:P});return this.log("EIP-712 signature obtained"),{serialized:JSON.stringify({authorization:l,signature:T}),signature:T,settlementProbe:{kind:"eip3009",from:n.address,nonce:f,asset:o,chainId:c}}}async buildApprovalTransaction(e,n,r){let{payTo:s,asset:o,extra:a}=e,i=e.amount??e.maxAmountRequired;if(!i)throw new Error("Missing amount in payment requirements");let c=a?.facilitatorContract;if(!c)throw new Error("exact-approval scheme requires extra.facilitatorContract from the facilitator. The /supported endpoint should provide this.");if(!n.signTypedData)throw new Error("Wallet does not support signTypedData (EIP-712)");this.log("Building approval-based transaction:",{from:n.address,to:s,amount:i,asset:o,network:e.network,facilitatorContract:c});let u=r||this.getDefaultRpcUrl(e.network),p=a?.fee??"0",d=BigInt(i)+BigInt(p),f=await this.readAllowance(u,o,n.address,c);if(f<d){if(!n.sendTransaction)throw new Error("BSC payments require a wallet that supports sendTransaction for the one-time token approval. Use createEvmKeypairWallet() or a browser wallet with transaction support.");let D=this.calculateApprovalAmount(i,p,a?.approvalStrategy);this.log(`Approving ${D} for ${c} (current allowance: ${f})`);let h=await n.sendTransaction({to:o,data:this.encodeApprove(c,D),value:0n});this.log(`Approval tx sent: ${h}`),await this.waitForReceipt(u,h),this.log("Approval confirmed")}else this.log("Sufficient allowance, skipping approval");let x=new Uint8Array(16);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(x);let l=[...x].reduce((D,h)=>D*256n+BigInt(h),0n).toString(),P=new Uint8Array(32);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(P);let T="0x"+[...P].map(D=>D.toString(16).padStart(2,"0")).join(""),g=Math.floor(Date.now()/1e3)+(e.maxTimeoutSeconds||300),S=a?.eip712Domain,k=S?{name:S.name,version:S.version,chainId:BigInt(S.chainId),verifyingContract:S.verifyingContract}:{name:"DexterBSCFacilitator",version:"1",chainId:BigInt(this.getChainId(e.network)),verifyingContract:c},U=a?.eip712Types??{Payment:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"token",type:"address"},{name:"amount",type:"uint256"},{name:"fee",type:"uint256"},{name:"nonce",type:"uint256"},{name:"deadline",type:"uint256"},{name:"paymentId",type:"bytes32"}]},K={from:n.address,to:s,token:o,amount:BigInt(i),fee:BigInt(p),nonce:BigInt(l),deadline:BigInt(g),paymentId:T},$=await n.signTypedData({domain:k,types:U,primaryType:"Payment",message:K});this.log("EIP-712 Payment signature obtained");let O={from:n.address,to:s,token:o,amount:i,fee:p,nonce:l,deadline:g,paymentId:T,signature:$};return{serialized:JSON.stringify(O),signature:$}}async buildPermit2Transaction(e,n,r){let{payTo:s,asset:o}=e,a=e.amount??e.maxAmountRequired;if(!a)throw new Error("Missing amount in payment requirements");if(!n.signTypedData)throw new Error("Wallet does not support signTypedData (EIP-712)");this.log("Building Permit2 transaction:",{from:n.address,to:s,amount:a,asset:o,network:e.network});let i=r||this.getDefaultRpcUrl(e.network),c=await this.readAllowance(i,o,n.address,z),u;if(c<BigInt(a)){let k=this.encodeApprove(z,Dt);if(n.signTransaction){this.log(`Signing Permit2 approval for relay (current allowance: ${c})`);let U=this.getChainId(e.network),K=await this.readGasPrice(i),$=await this.readNonce(i,n.address),O=await n.signTransaction({to:o,data:k,chainId:U,gas:50000n,gasPrice:K,nonce:$});u={erc20ApprovalGasSponsoring:{info:{from:n.address,asset:o,spender:z,amount:Dt.toString(),signedTransaction:O,version:"1"}}},this.log("Permit2 approval signed for facilitator relay")}else if(n.sendTransaction){this.log(`Approving Permit2 directly (current allowance: ${c})`);let U=await n.sendTransaction({to:o,data:k,value:0n});this.log(`Permit2 approval tx sent: ${U}`),await this.waitForReceipt(i,U),this.log("Permit2 approval confirmed")}else throw new Error("Permit2 payments require a wallet that supports signTransaction or sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support.")}else this.log("Sufficient Permit2 allowance, skipping approval");let p=new Uint8Array(32);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(p);let d=[...p].reduce((k,U)=>k*256n+BigInt(U),0n),f=Math.floor(Date.now()/1e3),x=f-600,l=f+(e.maxTimeoutSeconds||300),P=this.getChainId(e.network),T={name:"Permit2",chainId:BigInt(P),verifyingContract:z},y={permitted:{token:o,amount:BigInt(a)},spender:He,nonce:d,deadline:BigInt(l),witness:{to:s,validAfter:BigInt(x)}},g=await n.signTypedData({domain:T,types:Pn,primaryType:"PermitWitnessTransferFrom",message:y});this.log("Permit2 PermitWitnessTransferFrom signature obtained");let S={signature:g,permit2Authorization:{from:n.address,permitted:{token:o,amount:a},spender:He,nonce:d.toString(),deadline:String(l),witness:{to:s,validAfter:String(x)}}};return{serialized:JSON.stringify(S),signature:g,extensions:u,settlementProbe:{kind:"permit2",from:n.address,nonce:d.toString(),chainId:P}}}async readAllowance(e,n,r,s){let o="0xdd62ed3e",a=r.slice(2).toLowerCase().padStart(64,"0"),i=s.slice(2).toLowerCase().padStart(64,"0"),c=o+a+i;try{let p=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_call",params:[{to:n,data:c},"latest"]})})).json();return p.error||!p.result||p.result==="0x"?0n:BigInt(p.result)}catch{return 0n}}encodeApprove(e,n){let r="0x095ea7b3",s=e.slice(2).toLowerCase().padStart(64,"0"),o=n.toString(16).padStart(64,"0");return r+s+o}async waitForReceipt(e,n,r=3e4){let s=Date.now();for(;Date.now()-s<r;){try{let a=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_getTransactionReceipt",params:[n]})})).json();if(a.result){if(a.result.status==="0x0")throw new Error(`Approval transaction reverted: ${n}`);return}}catch(o){if(o instanceof Error&&o.message.includes("reverted"))throw o}await new Promise(o=>setTimeout(o,2e3))}throw new Error(`Approval transaction receipt timeout after ${r}ms: ${n}`)}async readGasPrice(e){try{let r=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_gasPrice",params:[]})})).json();return r.result?BigInt(r.result):50000000n}catch{return 50000000n}}async readNonce(e,n){try{let s=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_getTransactionCount",params:[n,"latest"]})})).json();return s.result?parseInt(s.result,16):0}catch{return 0}}calculateApprovalAmount(e,n,r){let s=BigInt(e)+BigInt(n);if(!r||r.mode==="exact")return s;let o=BigInt(r.defaultMultiple??10),a=s*o;if(r.maxCapUsd){let i=this.inferDecimals(e),c=BigInt(Math.floor(r.maxCapUsd*Math.pow(10,i)));if(a>c)return c}if(r.exactAboveUsd){let i=this.inferDecimals(e),c=BigInt(Math.floor(r.exactAboveUsd*Math.pow(10,i)));if(BigInt(e)>c)return s}return a}inferDecimals(e){return e.length>12?18:6}};function ve(t){return new at(t)}function xt(t){if(t===qe||t===Nt)return!0;let e=t.toLowerCase();for(let n of Object.values(nt))if(n.toLowerCase()===e)return!0;for(let n of Object.keys(rt))if(n.toLowerCase()===e)return!0;return!1}function Rn(t){return{[Ne]:"Solana",[Qe]:"Solana Devnet",[Ze]:"Solana Testnet",solana:"Solana","solana-devnet":"Solana Devnet","solana-testnet":"Solana Testnet",[ne]:"Base",[ge]:"Base Sepolia",[Te]:"Ethereum",[ye]:"Arbitrum",[he]:"Polygon",[Ae]:"Optimism",[be]:"Avalanche",[Se]:"BSC",[we]:"SKALE Base",[xe]:"SKALE Base Sepolia",base:"Base","base-sepolia":"Base Sepolia",ethereum:"Ethereum",arbitrum:"Arbitrum",polygon:"Polygon",optimism:"Optimism",avalanche:"Avalanche",bsc:"BSC","skale-base":"SKALE Base","skale-base-sepolia":"SKALE Base Sepolia"}[t]||t}function Mt(t,e){let n=Rn(t);return n===t?e:n}async function _n(t,e){if(typeof t=="string")return[t,e];if(t instanceof URL)return[t.href,e];let n=t,r=new Headers(n.headers);e?.headers&&new Headers(e.headers).forEach((a,i)=>r.set(i,a));let s={method:e?.method??n.method,headers:r,signal:e?.signal??n.signal,redirect:e?.redirect??n.redirect,credentials:e?.credentials??n.credentials},o=(s.method??"GET").toUpperCase();return e&&"body"in e?s.body=e.body:o!=="GET"&&o!=="HEAD"&&n.body&&(s.body=await n.arrayBuffer()),[n.url,s]}var kn=new WeakMap;function $t(t){let{adapters:e=[G({verbose:t.verbose}),ve({verbose:t.verbose})],wallets:n,wallet:r,preferredNetwork:s,rpcUrls:o={},maxAmountAtomic:a,fetch:i=globalThis.fetch,verbose:c=!1,accessPass:u,onPaymentRequired:p,onPaymentDispatched:d,maxRetries:f=0,retryDelayMs:x=500}=t,l=c?console.log.bind(console,"[x402]"):()=>{};async function P(h,w){let v;for(let A=0;A<=f;A++)try{let E=await i(h,w);if(E.status>=502&&E.status<=504&&A<f){l(`Retry ${A+1}/${f}: server returned ${E.status}`),await new Promise(R=>setTimeout(R,x*Math.pow(2,A)));continue}return E}catch(E){v=E,A<f&&(l(`Retry ${A+1}/${f}: ${E instanceof Error?E.message:"network error"}`),await new Promise(R=>setTimeout(R,x*Math.pow(2,A))))}throw v}let T=new Map;function y(h){try{let w=new URL(h).host,v=T.get(w);if(v&&v.expiresAt>Date.now()/1e3+10)return v.jwt;v&&T.delete(w)}catch{}return null}function g(h,w){try{let v=new URL(h).host,A=w.split(".");if(A.length===3){let E=JSON.parse(atob(A[1].replace(/-/g,"+").replace(/_/g,"/"))),R=Math.floor(Date.now()/1e3),_=R+86400,L=Math.min(typeof E.exp=="number"?E.exp:R,_);T.set(v,{jwt:w,expiresAt:L}),l("Access pass cached for",v,"| expires:",new Date(L*1e3).toISOString())}}catch{l("Failed to cache access pass")}}let S=n||{};r&&!S.solana&&ae(r)&&(S.solana=r),r&&!S.evm&&ie(r)&&(S.evm=r);function k(h){let w=[];for(let v of h){let A=v.scheme??"exact";if(A!=="exact"&&A!=="exact-approval")continue;let E=e.find(_=>_.canHandle(v.network));if(!E)continue;let R;E.name==="Solana"?R=S.solana:E.name==="EVM"&&(R=S.evm),R&&E.isConnected(R)&&w.push({accept:v,adapter:E,wallet:R})}if(w.length===0)return null;if(s){let v=w.find(A=>A.accept.network===s);if(v)return v}return w[0]}function U(h,w){return Mt(h,w)}function K(h,w){return o[h]||w.getDefaultRpcUrl(h)}async function $(h,w,v,A,E){let R="";if(u?.preferTier&&A.tiers){let m=A.tiers.find(b=>b.id===u.preferTier);if(m){if(u.maxSpend&&parseFloat(m.price)>parseFloat(u.maxSpend))throw new I("access_pass_exceeds_max_spend",`Access pass tier "${m.id}" costs $${m.price}, exceeds max spend $${u.maxSpend}`);R=`tier=${m.id}`}}else if(u?.preferDuration&&A.ratePerHour)R=`duration=${u.preferDuration}`;else if(A.tiers&&A.tiers.length>0){let m=A.tiers[0];if(u?.maxSpend&&parseFloat(m.price)>parseFloat(u.maxSpend))throw new I("access_pass_exceeds_max_spend",`Cheapest access pass costs $${m.price}, exceeds max spend $${u?.maxSpend}`);R=`tier=${m.id}`}let _=R?E.includes("?")?`${E}&${R}`:`${E}?${R}`:E;l("Purchasing access pass:",R||"default tier");let L=v.headers.get("PAYMENT-REQUIRED");if(!L)return null;let M;try{M=JSON.parse(atob(L))}catch{return null}let N=k(M.accepts);if(!N)return null;let{accept:C,adapter:W,wallet:ce}=N;if(W.name==="Solana"&&!C.extra?.feePayer)return null;let H=C.extra?.decimals??(xt(C.asset)?6:void 0);if(typeof H!="number")return null;let Ee=C.amount??C.maxAmountRequired;if(!Ee)return null;let F=K(C.network,W);try{let m=await W.getBalance(C,ce,F),b=Number(Ee)/Math.pow(10,H);if(m<b){let ut=U(C.network,W.name);throw new I("insufficient_balance",`Insufficient balance for access pass on ${ut}. Have $${m.toFixed(4)}, need $${b.toFixed(4)}`)}}catch(m){if(m instanceof I)throw m}let j=await W.buildTransaction(C,ce,F),le;W.name==="EVM"?le=JSON.parse(j.serialized):le={transaction:j.serialized};let X=typeof h=="string"?h:h instanceof URL?h.href:h.url,ue=M.resource;if(typeof M.resource=="string")try{let m=new URL(M.resource,X);["http:","https:"].includes(m.protocol)&&(ue=m.toString())}catch{}else if(M.resource&&typeof M.resource=="object"&&"url"in M.resource){let m=M.resource;try{let b=new URL(m.url,X);["http:","https:"].includes(b.protocol)&&(ue={...m,url:b.toString()})}catch{}}let Je={x402Version:C.x402Version??2,resource:ue,accepted:C,payload:le};j.extensions&&(Je.extensions=j.extensions);let J=btoa(JSON.stringify(Je)),Y=await i(_,{...w,method:"POST",headers:{...w?.headers||{},"Content-Type":"application/json","PAYMENT-SIGNATURE":J}});if(!Y.ok)return l("Pass purchase failed:",Y.status),null;let V=Y.headers.get("ACCESS-PASS");return V&&(g(E,V),l("Access pass purchased and cached")),Y}async function O(h,w){let v=h;if(l("Making request:",v),u){let m=y(v);if(m){l("Using cached access pass");let b=await i(h,{...w,headers:{...w?.headers||{},Authorization:`Bearer ${m}`}});if(b.status!==401&&b.status!==402)return b;l("Cached pass rejected (status",b.status,"), purchasing new pass");try{T.delete(new URL(v).host)}catch{}}}let A=await P(h,w);if(A.status!==402)return A;l("Received 402 Payment Required");let E=A.headers.get("X-ACCESS-PASS-TIERS");if(u&&E){l("Server offers access passes, purchasing...");try{let m=JSON.parse(atob(E)),b=await $(h,w,A,m,v);if(b)return b}catch(m){l("Access pass purchase failed, falling back to per-request payment:",m)}}let R=A.headers.get("PAYMENT-REQUIRED");if(!R)throw new I("missing_payment_required_header","Server returned 402 but no PAYMENT-REQUIRED header");let _;try{let m=atob(R);_=JSON.parse(m)}catch{throw new I("invalid_payment_required","Failed to decode PAYMENT-REQUIRED header")}l("Payment requirements:",_);let L=A.headers.get("X-Quote-Hash");L&&l("Quote hash received:",L);let M=k(_.accepts);if(!M){let m=_.accepts.map(b=>b.network).join(", ");throw new I("no_matching_payment_option",`No connected wallet for any available network: ${m}`)}let{accept:N,adapter:C,wallet:W}=M;if(l(`Using ${C.name} for ${N.network}`),C.name==="Solana"&&!N.extra?.feePayer)throw new I("missing_fee_payer","Solana payment option missing feePayer in extra");let ce=N.extra?.decimals??(xt(N.asset)?6:void 0);if(typeof ce!="number")throw new I("missing_decimals","Payment option missing decimals - provide in extra or use a known stablecoin");let H=N.amount??N.maxAmountRequired;if(!H)throw new I("missing_amount","Payment option missing amount");if(a&&BigInt(H)>BigInt(a))throw new I("amount_exceeds_max",`Payment amount ${H} exceeds maximum ${a}`);let Ee=K(N.network,C);l("Checking balance...");try{let m=await C.getBalance(N,W,Ee),b=Number(H)/Math.pow(10,ce);if(m<b){let ut=U(N.network,C.name);throw new I("insufficient_balance",`Insufficient balance on ${ut}. Have $${m.toFixed(4)}, need $${b.toFixed(4)}`)}l(`Balance OK: $${m.toFixed(4)} >= $${b.toFixed(4)}`)}catch(m){if(m instanceof I)throw m;l("Balance check failed (RPC error), proceeding with transaction attempt")}if(p&&!await p(N))throw new I("payment_rejected","Payment rejected by onPaymentRequired callback");l("Building transaction...");let F=await C.buildTransaction(N,W,Ee);l("Transaction signed");let j;C.name==="EVM"?j=JSON.parse(F.serialized):j={transaction:F.serialized};let le=h,X=_.resource;if(typeof _.resource=="string")try{let m=new URL(_.resource,le).toString();m!==_.resource&&l("Resolved relative resource URL:",_.resource,"\u2192",m),X=m}catch{X=_.resource}else if(_.resource&&typeof _.resource=="object"&&"url"in _.resource){let m=_.resource;try{let b=new URL(m.url,le).toString();b!==m.url&&(l("Resolved relative resource URL:",m.url,"\u2192",b),X={...m,url:b})}catch{}}let ue={x402Version:N.x402Version??2,resource:X,accepted:N,payload:j};F.extensions&&(ue.extensions=F.extensions);let Je=btoa(JSON.stringify(ue));if(d)try{d(N,F.settlementProbe)}catch{}l("Retrying request with payment...");let J=await P(h,{...w,headers:{...w?.headers||{},"PAYMENT-SIGNATURE":Je,...L?{"X-Quote-Hash":L}:{}}});if(l("Retry response status:",J.status),J.status===402){let m="unknown";try{let b=await J.clone().json();m=String(b.error||b.message||JSON.stringify(b)),l("Rejection reason:",m)}catch{}throw new I("payment_rejected",`Payment was rejected by the server: ${m}`)}let Y=J.headers.get("PAYMENT-RESPONSE"),V;if(Y)try{V=JSON.parse(atob(Y))}catch{}return V??={},V.amountAtomic=H,V.assetDecimals=ce,kn.set(J,V),V.extensions&&l("Settlement extensions:",Object.keys(V.extensions).join(", ")),J}async function D(h,w){let[v,A]=await _n(h,w);return O(v,A)}return{fetch:D}}function q(t){if(t instanceof Error){if(t.message&&t.message.length>0)return t.message;if(t.name&&t.name.length>0)return t.name}let e=String(t);return e.length>0?e:"unknown error"}async function je(t){let e="";try{e=(await t.clone().text()).slice(0,600)}catch{}let n=e.toLowerCase(),r=n.includes("settle")||n.includes("facilitator"),s=e;try{let o=JSON.parse(e),a=[o.error,o.detail,o.message].filter(i=>typeof i=="string"&&i.length>0);a.length>0&&(s=a.join(" \u2014 "))}catch{}return s||(s=`HTTP ${t.status}`),{reason:r?"settlement_failed":"merchant_rejected",detail:`merchant HTTP ${t.status}: ${s}`}}var it="Payment authorization was sent, but the merchant did not respond within the timeout. ",ct=" Do not retry without checking \u2014 inspect the funding wallet for a transfer to the merchant before attempting payment again.";async function lt(t,e,n){if(!t)return{confirmed:!1,detail:it+"This payment scheme has no on-chain confirmation check, so the SDK cannot verify whether it settled."+ct};try{if(t.kind==="solana"){let a=G(),i=n??a.getDefaultRpcUrl(e.caip2);if(!a.confirmSettlement)return Lt();let c=await a.confirmSettlement(t,i);return c.settled?{confirmed:!0,txSignature:c.txSignature}:Kt()}let r=ve(),s=r.getDefaultRpcUrl(e.caip2);if(!r.confirmSettlement)return Lt();let o=await r.confirmSettlement(t,s);return o.settled?{confirmed:!0,txSignature:o.txSignature}:Kt()}catch(r){return{confirmed:!1,detail:it+`On-chain confirmation could not be completed (${q(r)}).`+ct}}}function Kt(){return{confirmed:!1,detail:it+"On-chain confirmation found no matching settlement yet \u2014 the payment may still be pending, or may not have settled."+ct}}function Lt(){return{confirmed:!1,detail:it+"The chain adapter does not support on-chain confirmation."+ct}}var Cn=new Set(["exact","exact-approval"]);async function In(t,e,n,r){let s;try{s=await r.signNextVoucher(n.amount)}catch{return null}let o=new Headers(e.headers??void 0);o.set("X-Tab-Voucher",Xe(s));let a={method:e.method??"GET",headers:o};e.signal&&(a.signal=e.signal),typeof e.body=="string"&&(a.body=e.body);let i;try{i=await fetch(t,a)}catch(c){return{ok:!1,reason:"error",detail:c?.message??String(c)}}return i.status===402?(r.rollbackVoucher?.call(r,s),null):i.ok?{ok:!0,paid:!0,response:i,amountPaid:n.amount,network:n.network}:{ok:!1,...await je(i)}}var Vt={version:2,async parseChallenge(t){return Ye(t)},async pay(t,e,n,r,s){if(s.tab){let y=n.options.find(g=>g.scheme==="tab"&&g.network.family==="svm"&&g.payTo===s.tab.counterparty);if(y){let g=await In(t,e,y,s.tab);if(g)return g}}let o=n.options.filter(y=>Cn.has(y.scheme));if(o.length===0)return{ok:!1,reason:"no_payment_options",detail:`no generically payable scheme offered (got: ${n.options.map(y=>y.scheme).join(", ")})`};let a=o.find(y=>y.network.family==="evm"?!!r.evm:y.network.family==="svm"?!!r.solana:!1);if(!a)return{ok:!1,reason:"unsupported_network"};let i=s.timeoutMs??15e3,c=s.responseTimeoutMs??12e4,u=new AbortController,p=setTimeout(()=>u.abort(),i),d=!1,f,x=(y,g)=>{d=!0,f=g,clearTimeout(p),p=setTimeout(()=>u.abort(),c)},l=$t({wallets:r,preferredNetwork:a.network.caip2,maxAmountAtomic:s.maxAmountAtomic,fetch:globalThis.fetch,onPaymentDispatched:x}),P=e.signal?AbortSignal.any([e.signal,u.signal]):u.signal,T={method:e.method??"GET",headers:e.headers,signal:P};typeof e.body=="string"&&(T.body=e.body);try{let y=await l.fetch(t,T);if(clearTimeout(p),!y.ok)return{ok:!1,...await je(y)};let g,S=y.headers.get("PAYMENT-RESPONSE");if(S)try{let k=At(S);k&&typeof k.transaction=="string"&&(g=k.transaction)}catch{}return{ok:!0,paid:!0,response:y,amountPaid:a.amount,network:a.network,txSignature:g}}catch(y){clearTimeout(p);let g=y;if(g?.name==="AbortError"){if(!d)return{ok:!1,reason:"timeout"};let S=await lt(f,a.network,s.solanaRpcUrl);return S.confirmed?{ok:!0,paid:!0,response:void 0,amountPaid:a.amount,network:a.network,txSignature:S.txSignature}:{ok:!1,reason:"payment_unconfirmed",detail:S.detail}}return{ok:!1,reason:"error",detail:g?.message??String(y)}}}};import{getAddress as Nn}from"viem";var On={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]};async function Un(){let t=globalThis.crypto??(await import("crypto")).webcrypto,e=new Uint8Array(32);return t.getRandomValues(e),"0x"+Array.from(e,n=>n.toString(16).padStart(2,"0")).join("")}async function Bn(t,e,n){if(typeof t.signTypedData!="function")throw new Error("EVM wallet does not support signTypedData");let r=Math.floor(Date.now()/1e3),s=String(r-600),o=String(r+(e.maxTimeoutSeconds??60)),a={from:t.address,to:e.payTo,value:e.amount,validAfter:s,validBefore:o,nonce:await Un()},i=Fe[e.network.caip2];if(i===void 0)throw new Error(`unknown chain id for network ${e.network.caip2}`);let c=e.extra,u=await t.signTypedData({domain:{name:c.name,version:c.version,chainId:i,verifyingContract:Nn(e.asset)},types:On,primaryType:"TransferWithAuthorization",message:a});return{payment:{x402Version:1,scheme:e.scheme,network:n,payload:{signature:u,authorization:a}},settlementProbe:{kind:"eip3009",from:a.from,nonce:a.nonce,asset:e.asset,chainId:i}}}async function Tt(t,e,n){try{let r;for(let s of t.options){let o=s.network.family==="evm"&&!!e.evm||s.network.family==="svm"&&!!e.solana;if(s.scheme!=="exact"){o&&(r=s.scheme);continue}if(s.network.family==="evm"&&e.evm){let a=await e.evm;return await Dn(s,a,n)}if(s.network.family==="svm"&&e.solana){let a=await e.solana;return await Mn(s,a,n)}}return r!==void 0?{ok:!1,reason:"merchant_rejected",detail:`v1 supports only the 'exact' scheme, got '${r}'`}:{ok:!1,reason:"unsupported_network"}}catch(r){return{ok:!1,reason:"error",detail:q(r)}}}async function Dn(t,e,n){if(n.maxAmountAtomic!==void 0&&BigInt(t.amount)>BigInt(n.maxAmountAtomic))return{ok:!1,reason:"budget_exceeded"};let r=t.extra??{},s=r.name,o=r.version;if(typeof s!="string"||s.length===0||typeof o!="string"||o.length===0)return{ok:!1,reason:"merchant_rejected",detail:"v1 challenge missing exact-scheme EIP-712 domain (extra.name / extra.version)"};let a=t.network.bare,{payment:i,settlementProbe:c}=await Bn(e,t,a);return{ok:!0,headerValue:Buffer.from(JSON.stringify(i),"utf8").toString("base64"),option:t,settlementProbe:c}}async function Mn(t,e,n){if(n.maxAmountAtomic!==void 0&&BigInt(t.amount)>BigInt(n.maxAmountAtomic))return{ok:!1,reason:"budget_exceeded"};if(t.scheme!=="exact")return{ok:!1,reason:"merchant_rejected",detail:`v1 SVM supports only the 'exact' scheme, got '${t.scheme}'`};let r=t.extra??{};if(typeof r.feePayer!="string"||r.feePayer.length===0)return{ok:!1,reason:"merchant_rejected",detail:"v1 SVM challenge missing extra.feePayer (required as the transaction fee payer)"};let s=t.network.bare,o={x402Version:1,scheme:t.scheme,network:s,asset:t.asset,payTo:t.payTo,amount:t.amount,maxAmountRequired:t.amount,maxTimeoutSeconds:t.maxTimeoutSeconds??60,extra:r},i=await G().buildTransaction(o,e,n.solanaRpcUrl),c={x402Version:1,scheme:t.scheme,network:s,payload:{transaction:i.serialized}};return{ok:!0,headerValue:Buffer.from(JSON.stringify(c),"utf8").toString("base64"),option:t,settlementProbe:i.settlementProbe}}function $n(t){let e=[];for(let n of t){if(!n||typeof n!="object")continue;let r=n,s=Ce(String(r.network??""));s&&e.push({scheme:String(r.scheme??"exact"),network:s,amount:String(r.maxAmountRequired??r.amount??"0"),asset:String(r.asset??""),payTo:String(r.payTo??""),maxTimeoutSeconds:typeof r.maxTimeoutSeconds=="number"?r.maxTimeoutSeconds:void 0,extra:r.extra&&typeof r.extra=="object"?r.extra:void 0})}return e}var Wt={version:1,async parseChallenge(t){if(t.headers.get("payment-required"))return null;let e;try{e=await t.clone().json()}catch{return null}let n=Array.isArray(e.accepts)?e.accepts:[];if(n.length===0)return null;let r=$n(n);return r.length===0?null:{x402Version:1,options:r}},async pay(t,e,n,r,s){let o,a=new AbortController,i=!1,c,u;try{let p=s.timeoutMs??15e3;o=setTimeout(()=>a.abort(),p);let d=await Tt(n,r,s);if(!d.ok)return{ok:!1,reason:d.reason,detail:d.detail};let f=d.headerValue,x=d.option;u=x,c=d.settlementProbe;let l=new Headers(e.headers??void 0);l.set("X-PAYMENT",f);let P=e.signal!=null?AbortSignal.any([e.signal,a.signal]):a.signal,T={method:e.method,headers:l,signal:P};typeof e.body=="string"&&(T.body=e.body),i=!0,clearTimeout(o);let y=s.responseTimeoutMs??12e4;o=setTimeout(()=>a.abort(),y);let g=await fetch(t,T);return g.ok?{ok:!0,paid:!0,response:g,amountPaid:x.amount,network:x.network,txSignature:Kn(g)}:{ok:!1,...await je(g)}}catch(p){if(p instanceof Error&&p.name==="AbortError"){if(!i)return{ok:!1,reason:"timeout"};let d=await lt(c,u.network,s.solanaRpcUrl);return d.confirmed?{ok:!0,paid:!0,response:void 0,amountPaid:u.amount,network:u.network,txSignature:d.txSignature}:{ok:!1,reason:"payment_unconfirmed",detail:d.detail}}return{ok:!1,reason:"error",detail:q(p)}}finally{o!==void 0&&clearTimeout(o)}}};function Kn(t){let e=t.headers.get("x-payment-response")??t.headers.get("X-PAYMENT-RESPONSE");if(e)try{let n=JSON.parse(Buffer.from(e,"base64").toString("utf8")),r=n.transaction??n.txHash??n.transactionHash;return typeof r=="string"?r:void 0}catch{return}}import*as Ht from"tweetnacl";import{Keypair as ys,VersionedTransaction as hs,Transaction as As}from"@solana/web3.js";var qt=Symbol.for("x402:keypair");function vt(t){let e=t.evm;if(e&&typeof e.signMessage=="function"&&typeof e.address=="string")return{address:e.address,signMessage:e.signMessage};let n=t.solana;if(n){let r=n[qt];if(r&&r.secretKey&&r.publicKey)return{publicKey:r.publicKey,signMessage:async s=>Ht.sign.detached(s,r.secretKey)}}return null}var Ln=[Vt,Wt];async function Vn(t){let e=vt(t);if(!e)return fetch;try{return(await import("@x402/extensions/sign-in-with-x")).wrapFetchWithSIWx(fetch,e)}catch(n){return console.warn(`[x402] SIW-X unavailable \u2014 @x402/extensions failed to load; SIW-X merchants will not authenticate. ${q(n)}`),fetch}}async function Et(t,e,n,r){if(e.body!==void 0&&e.body!==null&&typeof e.body!="string")return{ok:!1,reason:"error",detail:"payAndFetch requires a string body; non-string bodies (Buffer, FormData, URLSearchParams, ReadableStream) cannot be safely re-sent on the paid retry"};let s;try{s=await(await Vn(n))(t,{...e})}catch(o){return{ok:!1,reason:"error",detail:q(o)}}if(s.status!==402)return{ok:!0,paid:!1,response:s};for(let o of Ln){let a=await o.parseChallenge(s.clone());if(a)return o.pay(t,e,a,n,r)}return{ok:!1,reason:"no_payment_options"}}async function Wn(t,e={},n){let r=await Ie(t,e);if(r.kind==="free")return{result:{ok:!0,paid:!1,response:r.response},tab:null};if(r.kind==="no_tab")return{result:{ok:!1,reason:"no_payment_options",detail:`no tab option offered (schemes: ${r.schemesOffered.join(", ")})`},tab:null};if(r.kind==="error")return{result:{ok:!1,reason:"error",detail:r.detail},tab:null};let{offer:s}=r,o=BigInt(Z(n.perUnitCap));if(BigInt(s.amountAtomic)>o)return{result:{ok:!1,reason:"budget_exceeded",detail:`seller quotes ${s.amountAtomic} atomic; perUnitCap allows ${o}`},tab:null};let a=n.tabs?.get(s.payTo);return(!a||!a.state.isOpen)&&(a=await gt({vault:n.vault,network:"solana:mainnet",seller:s.payTo,perUnitCap:n.perUnitCap,totalCap:n.totalCap,sessionDuration:n.sessionDuration,facilitatorUrl:n.facilitatorUrl,onLiveSession:n.onLiveSession}),n.tabs?.set(s.payTo,a)),{result:await Et(t,e,{},{tab:a}),tab:a}}function qn(t){return{counterparty:t.payTo,perRequest:{atomic:t.amountAtomic,human:de(t.amountAtomic)},asset:t.asset,network:{caip2:t.networkCaip2},scheme:"tab",settlement:{custody:"non-custodial",protection:"lock",settleOn:"close"},credit:null,...t.resourceUrl!==void 0?{resourceUrl:t.resourceUrl}:{}}}async function Hn(t,e={},n={}){let r=n.cache?.get(t);if(r)return{kind:"terms",terms:r};let s=await Ie(t,e,n.fetchImpl??fetch);if(s.kind!=="offer")return s;if(s.offer.asset!==qe)return{kind:"error",detail:`tab offer asset is not USDC ("${s.offer.asset}"); refusing to render a human price`};let o=qn(s.offer);return n.cache?.set(t,o),{kind:"terms",terms:o}}export{Pe as DEFAULT_FACILITATOR_URL,yt as DEXTER_VAULT_PROGRAM_ID,an as INSTRUCTIONS_SYSVAR_ID,mt as LiveSessionExistsError,on as SECP256R1_PROGRAM_ID,pe as SessionScopeExceededError,Q as TabClosedError,me as UnsupportedNetworkError,de as atomicToHuman,nn as buildRegisterSessionKeyInstruction,rn as buildRevokeSessionKeyInstruction,sn as buildSecp256r1VerifyInstruction,jt as buildVoucherMessage,Z as humanToAtomic,gt as openTab,Wn as payUrlWithTab,Ie as resolveTabOffer,Hn as resolveTabTerms,Qt as resumeTab,pt as sessionRegisterMessage,Ft as sessionRevokeMessage,dn as tabFromGrant,dt as voucherPayloadMessage,Xe as voucherToHeader};
@@ -1,6 +1,6 @@
1
- "use strict";var lt=Object.create;var Y=Object.defineProperty;var ut=Object.getOwnPropertyDescriptor;var mt=Object.getOwnPropertyNames;var dt=Object.getPrototypeOf,pt=Object.prototype.hasOwnProperty;var gt=(e,t)=>{for(var r in t)Y(e,r,{get:t[r],enumerable:!0})},Ke=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of mt(t))!pt.call(e,i)&&i!==r&&Y(e,i,{get:()=>t[i],enumerable:!(n=ut(t,i))||n.enumerable});return e};var Me=(e,t,r)=>(r=e!=null?lt(dt(e)):{},Ke(t||!e||!e.__esModule?Y(r,"default",{value:e,enumerable:!0}):r,e)),ht=e=>Ke(Y({},"__esModule",{value:!0}),e);var Dt={};gt(Dt,{FileChannelLedger:()=>Z,FileVoucherStore:()=>me,InMemoryChannelLedger:()=>L,InMemoryVoucherStore:()=>ue,InvalidRegistrationError:()=>E,InvalidVoucherError:()=>S,InvalidVoucherSignatureError:()=>_,OnChainVerificationError:()=>I,ScopeViolationError:()=>x,TAB_VOUCHER_HEADER:()=>k,enforceScope:()=>se,openSse:()=>Ge,parseRegistration:()=>re,requireTab:()=>Je,tabChallengeMiddleware:()=>st,tabMiddleware:()=>le,tabOrExactMiddleware:()=>at,verifyRegistrationOnChain:()=>ne,verifyVoucherSignature:()=>ie});module.exports=ht(Dt);var S=class extends Error{constructor(r,n){super(`Invalid voucher: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="InvalidVoucherError"}};var B=require("fs"),Q=require("path"),De=new Map;function T(e,t){let n=(De.get(e)??Promise.resolve()).then(()=>t(),()=>t());return De.set(e,n.then(()=>{},()=>{})),n}var L=class{map=new Map;async get(t){return this.map.get(t)??null}async set(t,r){this.map.set(t,r)}async delete(t){this.map.delete(t)}async tryAcquireLease(t,r){return T(t,async()=>{let n=this.map.get(t),i=Date.now();if(n?.lease&&n.lease.heldUntilUnixMs>i)return!1;let s=n??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return this.map.set(t,{...s,lease:{heldUntilUnixMs:i+r}}),!0})}async releaseLease(t){await T(t,async()=>{let r=this.map.get(t);r&&this.map.set(t,{...r,lease:void 0})})}};function Te(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}function _e(e){if(e.length%2!==0)throw new Error(`hex length must be even, got ${e.length}`);let t=new Uint8Array(e.length/2);for(let r=0;r<t.length;r++)t[r]=parseInt(e.substr(r*2,2),16);return t}function yt(e){return{lastVoucher:e.lastVoucher?{payload:e.lastVoucher.payload,sessionPublicKey:Te(e.lastVoucher.sessionPublicKey),sessionRegistration:Te(e.lastVoucher.sessionRegistration),sessionSignature:Te(e.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:e.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:e.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:e.gateRefusedCumulativeAtomic,onChain:e.onChain,lease:e.lease}}function ft(e){return{lastVoucher:e.lastVoucher?{payload:e.lastVoucher.payload,sessionPublicKey:_e(e.lastVoucher.sessionPublicKey),sessionRegistration:_e(e.lastVoucher.sessionRegistration),sessionSignature:_e(e.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:e.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:e.lastCrystallizedCumulativeAtomic??"0",gateRefusedCumulativeAtomic:e.gateRefusedCumulativeAtomic,onChain:e.onChain,lease:e.lease}}var Z=class{constructor(t){this.dir=t}pathFor(t){if(!/^[a-z0-9_-]+$/i.test(t))throw new Error(`unsafe channelId for filesystem: ${t}`);return(0,Q.join)(this.dir,`${t}.json`)}async get(t){try{let r=await B.promises.readFile(this.pathFor(t),"utf8");return ft(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(t,r){let n=this.pathFor(t);await B.promises.mkdir((0,Q.dirname)(n),{recursive:!0});let i=`${n}.tmp`;await B.promises.writeFile(i,JSON.stringify(yt(r))),await B.promises.rename(i,n)}async delete(t){try{await B.promises.unlink(this.pathFor(t))}catch(r){if(r?.code!=="ENOENT")throw r}}async tryAcquireLease(t,r){return T(t,async()=>{let n=await this.get(t),i=Date.now();if(n?.lease&&n.lease.heldUntilUnixMs>i)return!1;let s=n??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return await this.set(t,{...s,lease:{heldUntilUnixMs:i+r}}),!0})}async releaseLease(t){await T(t,async()=>{let r=await this.get(t);r&&await this.set(t,{...r,lease:void 0})})}};var Xe=require("@solana/web3.js");var He=Me(require("tweetnacl"),1),bt=require("@noble/hashes/sha256"),vt=require("@noble/curves/p256"),ee=require("@solana/web3.js");var $=require("@dexterai/vault/messages");var Ie=require("@dexterai/vault/instructions"),At=require("@dexterai/vault/precompile"),K=require("@dexterai/vault/constants");var te=require("@dexterai/vault/session"),Ne="OTS_SESSION_REGISTER_V2",E=class extends Error{constructor(r,n){super(`Invalid registration: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="InvalidRegistrationError"}};function re(e){if(e.length!==188)throw new E("wrong_length",`expected 188, got ${e.length}`);let t=new TextDecoder().decode(e.slice(0,Ne.length));if(t!==Ne)throw new E("wrong_domain",`got "${t}"`);for(let y=Ne.length;y<32;y++)if(e[y]!==0)throw new E("wrong_domain",`non-NUL padding at byte ${y}`);let r=new DataView(e.buffer,e.byteOffset,e.byteLength),n=new ee.PublicKey(e.slice(32,64)),i=new ee.PublicKey(e.slice(64,96)),s=e.slice(96,128),h=r.getBigUint64(128,!0),c=r.getBigInt64(136,!0),a=new ee.PublicKey(e.slice(144,176)),m=r.getUint32(176,!0),l=r.getBigUint64(180,!0);if(!n.equals(K.DEXTER_VAULT_PROGRAM_ID))throw new E("wrong_program",`${n.toBase58()} is not ${K.DEXTER_VAULT_PROGRAM_ID.toBase58()}`);if(h===0n)throw new E("cap_zero");let o=BigInt(Math.floor(Date.now()/1e3));if(c<=o)throw new E("expiry_in_past",`expires_at=${c}, now=${o}`);return{programId:n,vaultPda:i,sessionPubkey:new Uint8Array(s),maxAmount:h,expiresAt:c,allowedCounterparty:a,nonce:m,maxRevolvingCapacity:l}}var I=class extends Error{constructor(r,n){super(`On-chain verification failed: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="OnChainVerificationError"}};async function ne(e,t){let r=await(0,te.fetchSessionAccount)(e,t.vaultPda,t.allowedCounterparty);if(!r||r.version===0)throw new I("session_not_active","no live SessionAccount PDA for this (vault, counterparty) \u2014 revoked, expiry-swept, or never registered");if(!(0,te.isSessionLive)(r))throw new I("session_not_active","SessionAccount PDA is present but expired");if(!wt(r.session.sessionPubkey,t.sessionPubkey))throw new I("session_pubkey_mismatch",`on-chain ${ze(r.session.sessionPubkey)} != registration ${ze(t.sessionPubkey)}`);let n=r.session.spent,i=r.session.crystallizedCumulative;return{frontierAtomic:(n>i?n:i).toString(),spentAtomic:n.toString(),crystallizedCumulativeAtomic:i.toString()}}var _=class extends Error{constructor(t){super(`Invalid voucher signature${t?`: ${t}`:""}`),this.name="InvalidVoucherSignatureError"}};function ie(e,t){if(t.length!==32)throw new _(`channelIdBytes must be 32 bytes, got ${t.length}`);if(e.sessionPublicKey.length!==32)throw new _(`sessionPublicKey must be 32 bytes, got ${e.sessionPublicKey.length}`);if(e.sessionSignature.length!==64)throw new _(`sessionSignature must be 64 bytes, got ${e.sessionSignature.length}`);let r=(0,$.voucherPayloadMessage)({channelId:t,cumulativeAmount:BigInt(e.payload.cumulativeAmount),sequenceNumber:e.payload.sequenceNumber});if(!He.default.sign.detached.verify(r,e.sessionSignature,e.sessionPublicKey))throw new _("ed25519 verify rejected")}var x=class extends Error{constructor(r,n){super(`Scope violation: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="ScopeViolationError"}};function se(e){let t=BigInt(e.voucher.payload.cumulativeAmount);if(t>e.registration.maxAmount)throw new x("cumulative_exceeds_cap",`${t} > ${e.registration.maxAmount}`);let r=BigInt(Math.floor(Date.now()/1e3));if(r>=e.registration.expiresAt)throw new x("session_expired",`now=${r} >= expiresAt=${e.registration.expiresAt}`);if(!e.registration.allowedCounterparty.equals(e.expectedCounterparty))throw new x("wrong_counterparty",`${e.registration.allowedCounterparty.toBase58()} != ${e.expectedCounterparty.toBase58()}`);if(e.previousCumulativeAtomic!==void 0){let n=BigInt(e.previousCumulativeAtomic);if(t<=n)throw new x("non_monotonic",`cumulative=${t} not > previous=${n}`)}}function wt(e,t){if(e.length!==t.length)return!1;for(let r=0;r<e.length;r++)if(e[r]!==t[r])return!1;return!0}function ze(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}var Ct=require("@solana/web3.js"),Et=require("@noble/hashes/utils");var St=Me(require("tweetnacl"),1);var xt=require("@noble/hashes/sha256");var qe="https://x402.dexter.cash",Fe=6;function R(e,t=Fe){if(!/^\d+(\.\d+)?$/.test(e))throw new Error(`amount must be a non-negative decimal string, got "${e}"`);let[r,n=""]=e.split(".");if(n.length>t)throw new Error(`amount "${e}" has more than ${t} decimals`);let i=n.padEnd(t,"0"),s=`${r}${i}`.replace(/^0+(?=\d)/,"");return s===""?"0":s}function V(e,t=Fe){if(!/^\d+$/.test(e))throw new Error(`atomic must be a non-negative integer string, got "${e}"`);let r=e.padStart(t+1,"0"),n=r.slice(0,-t).replace(/^0+(?=\d)/,"")||"0",i=r.slice(-t).replace(/0+$/,"");return i?`${n}.${i}`:n}var oe=require("@noble/hashes/utils"),Rt=15e3,Pt=["claim_already_exists","non_monotonic_cumulative"],Tt="below_lock_cadence";function ae(e){return typeof e=="string"&&e.includes(Tt)}function _t(e){return`${e.slice(0,16)}\u2026`}function We(e,t,r,n){let i=_t(e);if(n.crystallized){console.info(`[tab/seller] crystallize OK channel=${i} cumulative=${t} seq=${r}${n.claimPda?` claimPda=${n.claimPda}`:""} \u2014 LockVoucher landed`);return}if(n.error){if(ae(n.error)){console.warn(`[tab/seller] crystallize refused below the facilitator's cadence gate channel=${i} cumulative=${t} seq=${r}: ${n.error} \u2014 benign: this facilitator's cadence engine owns the protection cadence for the span; gate-refused watermark advanced, re-attempts after the next signed voucher`);return}if(Pt.some(s=>n.error.includes(s))){console.warn(`[tab/seller] crystallize duplicate channel=${i} cumulative=${t} seq=${r}: ${n.error} \u2014 voucher already secured on-chain (benign, no action)`);return}console.error(`[tab/seller] crystallize FAILED channel=${i} cumulative=${t} seq=${r}: ${n.error} \u2014 lock NOT secured (degraded: best-effort path, no watermark advance, retries at next threshold/close; seller exposure stays unsecured until it lands)`)}}async function ke(e,t,r,n,i=fetch){let s=e.lastVoucher;if(!s)return{crystallized:!1};if(s.payload.channelId!==t){let c={crystallized:!1,error:"channel_id_mismatch"};return We(t,s.payload.cumulativeAmount,s.payload.sequenceNumber,c),c}let h=c=>(We(t,s.payload.cumulativeAmount,s.payload.sequenceNumber,c),c);try{let c=`${r.replace(/\/$/,"")}/tab/lock`,a={channelId:s.payload.channelId,cumulativeAmount:s.payload.cumulativeAmount,sequenceNumber:s.payload.sequenceNumber,sessionPublicKey:(0,oe.bytesToHex)(s.sessionPublicKey),sessionSignature:(0,oe.bytesToHex)(s.sessionSignature),sessionRegistration:(0,oe.bytesToHex)(s.sessionRegistration),network:n},m=await i(c,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(a),signal:AbortSignal.timeout(Rt)}),l=await m.text();if(!m.ok)return h({crystallized:!1,error:`tab lock ${m.status}: ${l.slice(0,200)}`});let o;try{let y=JSON.parse(l);y&&typeof y.claimPda=="string"&&(o=y.claimPda)}catch{}return h({crystallized:!0,claimPda:o})}catch(c){return h({crystallized:!1,error:String(c?.message??c)})}}async function je(e,t,r,n,i,s={}){let h=BigInt(e.deliveredCumulativeAtomic),c=BigInt(e.lastCrystallizedCumulativeAtomic??"0"),a=BigInt(i.thresholdAtomic);if(h-c<a)return{crystallized:!1};let m=e.lastVoucher?.payload.cumulativeAmount,l=e.gateRefusedCumulativeAtomic;if(m!==void 0&&l!==void 0&&BigInt(m)<=BigInt(l))return{crystallized:!1};let o=await ke(e,t,r,n,s.fetchImpl);return o.crystallized&&m!==void 0?(e.lastCrystallizedCumulativeAtomic=m,e.gateRefusedCumulativeAtomic=void 0):ae(o.error)&&m!==void 0&&(e.gateRefusedCumulativeAtomic=m),o}var k="x-tab-voucher",Ue=class{map=new Map;get(t){return this.map.get(t)}set(t,r){this.map.set(t,r)}update(t,r){let n=this.map.get(t);n&&(n.lastCumulativeAtomic=r)}delete(t){this.map.delete(t)}},Oe=class{constructor(t,r,n,i,s,h){this.recordDeliveredImpl=s;this.chargeImpl=h;this.channelId=t,this.network=r,this.cumulativeAtomic=n,this.deliveredBaselineAtomic=i}channelId;network;sessionPublicKey=null;cumulativeAtomic;deliveredBaselineAtomic;cumulative(){return V(this.cumulativeAtomic.toString())}deliveredCumulative(){return V(this.deliveredBaselineAtomic.toString())}async recordDelivered(t){return this.recordDeliveredImpl(t)}bumpCumulative(t){this.cumulativeAtomic=t}setSessionPublicKey(t){this.sessionPublicKey=t}async charge(t){return this.chargeImpl(t)}};function It(e){if(typeof e!="string"||e.length===0)throw new S("signature_invalid",`missing ${k} header`);let t;try{t=Buffer.from(e,"base64").toString("utf8")}catch{throw new S("signature_invalid","malformed base64")}let r;try{r=JSON.parse(t)}catch{throw new S("signature_invalid","malformed JSON")}if(!r||typeof r!="object"||!r.payload||!r.sessionPublicKey)throw new S("signature_invalid","missing required fields");return{payload:r.payload,sessionPublicKey:ce(r.sessionPublicKey),sessionRegistration:ce(r.sessionRegistration),sessionSignature:ce(r.sessionSignature)}}function ce(e){if(typeof e!="string"||e.length%2!==0)throw new S("signature_invalid",`bad hex: ${typeof e}`);let t=new Uint8Array(e.length/2);for(let r=0;r<t.length;r++)t[r]=parseInt(e.substr(r*2,2),16);return t}function Nt(e){if(!/^[0-9a-f]{64}$/i.test(e))throw new S("signature_invalid",`channelId must be 64-char hex, got "${e}"`);return ce(e)}function le(e){let t=e.ledger??new L,r=new Ue,n=typeof e.sellerPubkey=="string"?new Xe.PublicKey(e.sellerPubkey):e.sellerPubkey,i=e.maxPerVoucherAtomic?BigInt(e.maxPerVoucherAtomic):BigInt(R(e.perUnit))*100n,s=e.facilitatorUrl??qe,h={thresholdAtomic:e.lockCadence?.thresholdAtomic??R("0.10"),onClose:e.lockCadence?.onClose??!0};return async(c,a,m)=>{try{let l=It(c.headers[k]),o=l.payload.channelId,y=Nt(o),d=r.get(o),f=null;if(!d){let p=re(l.sessionRegistration);f=(await ne(e.connection,p))?.frontierAtomic??null;let v=await t.get(o);d={registration:p,lastCumulativeAtomic:v?.lastVoucher?.payload.cumulativeAmount??"0"},r.set(o,d)}ie(l,y),se({registration:d.registration,voucher:l,expectedCounterparty:n,previousCumulativeAtomic:d.lastCumulativeAtomic});let b=BigInt(l.payload.cumulativeAmount),D=BigInt(d.lastCumulativeAtomic),z=b-D;if(z>i)throw new x("cumulative_exceeds_cap",`single voucher increment ${z} exceeds maxPerVoucherAtomic ${i}`);let Re=e.leaseTtlMs??3e5;if(!await t.tryAcquireLease(o,Re))throw new S("channel_busy","another stream is live on this channel; tabs serve one stream at a time");let H=!1,J=()=>{H||(H=!0,t.releaseLease(o).catch(p=>{console.error("[tab/seller] failed to release channel lease:",p)}))};a.on("close",J),a.on("finish",J);let Pe=async p=>{let P=p.lastCrystallizedCumulativeAtomic??"0",v=p.gateRefusedCumulativeAtomic;await je(p,o,s,e.network,h),(p.lastCrystallizedCumulativeAtomic!==P||p.gateRefusedCumulativeAtomic!==v)&&await T(o,async()=>{let w=await t.get(o);w&&await t.set(o,{...w,lastCrystallizedCumulativeAtomic:p.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:p.gateRefusedCumulativeAtomic})}).catch(w=>{console.error(`[tab/seller] crystallize watermark persist FAILED channel=${o.slice(0,16)}\u2026 (expect a benign duplicate/below-cadence warn on the next request):`,w)})},G=!1,u=()=>{!h.onClose||G||(G=!0,(async()=>{let p=await t.get(o);if(!p||!p.lastVoucher)return;let P=p.lastVoucher.payload.cumulativeAmount;if(p.gateRefusedCumulativeAtomic!==void 0&&BigInt(P)<=BigInt(p.gateRefusedCumulativeAtomic))return;let v=await ke(p,o,s,e.network);v.crystallized?await T(o,async()=>{let w=await t.get(o);w&&await t.set(o,{...w,lastCrystallizedCumulativeAtomic:P,gateRefusedCumulativeAtomic:void 0})}):ae(v.error)&&await T(o,async()=>{let w=await t.get(o);w&&await t.set(o,{...w,gateRefusedCumulativeAtomic:P})})})().catch(p=>{console.error(`[tab/seller] close-path crystallize CRASHED channel=${o.slice(0,16)}\u2026 (final voucher NOT locked; exposure unsecured until the next request retries):`,p)}))};a.on("close",u),a.on("finish",u);let g=await t.get(o),A=!g?.lastVoucher&&BigInt(g?.deliveredCumulativeAtomic??"0")===0n,C=f!==null&&A&&BigInt(f)>0n?f:null;C!==null&&console.info(`[tab/seller] channel ${o.slice(0,16)}\u2026 resumed: seeding delivered baseline from chain frontier ${C} (session already settled/locked up to it \u2014 that span is not deliverable budget)`);let U=C!==null?BigInt(C):g?BigInt(g.deliveredCumulativeAtomic):0n;await T(o,async()=>{let p=await t.get(o);await t.set(o,{...p,lastVoucher:l,deliveredCumulativeAtomic:C??(p?p.deliveredCumulativeAtomic:"0"),lastCrystallizedCumulativeAtomic:C??p?.lastCrystallizedCumulativeAtomic??"0"})}),r.update(o,l.payload.cumulativeAmount);let O=new Oe(o,e.network,b,U,async p=>{let P=null;await T(o,async()=>{let v=await t.get(o),w=v?BigInt(v.deliveredCumulativeAtomic):0n,Be=BigInt(p),ct=Be>0n?w+Be:w,Le={...v,lastVoucher:v?.lastVoucher??l,deliveredCumulativeAtomic:ct.toString(),lastCrystallizedCumulativeAtomic:v?.lastCrystallizedCumulativeAtomic??"0"};await t.set(o,Le),P=Le}),P&&Pe(P).catch(v=>{console.error(`[tab/seller] crystallize cadence CRASHED channel=${o.slice(0,16)}\u2026 (threshold lock not attempted; retries at the next delivery):`,v)})},async p=>{throw new Error("SellerTab.charge() is not driven by the route handler; the buyer presents a fresh voucher per chunk. Use openSse(res, tab) for the metered-stream pattern.")});O.setSessionPublicKey(l.sessionPublicKey),c.tab=O,m()}catch(l){if(l instanceof S||l instanceof E||l instanceof I||l instanceof _||l instanceof x){a.status(402).json({error:"invalid_voucher",reason:l.reason??"unknown",detail:l.message});return}m(l)}}}function Je(e){if(!e.tab)throw new Error("req.tab is missing \u2014 did tabMiddleware run on this route?");return e.tab}function Ge(e,t){if(!t.tab)throw new Error("openSse requires options.tab");e.headersSent||(e.setHeader("Content-Type","text/event-stream"),e.setHeader("Cache-Control","no-cache"),e.setHeader("Connection","keep-alive"),typeof e.flushHeaders=="function"&&e.flushHeaders());let r=t.tab,n=BigInt(R(r.cumulative())),i=BigInt(R(r.deliveredCumulative())),s=n-i;s<0n&&(s=0n);let h=t.perUnit?BigInt(R(t.perUnit)):null,c=0n,a=!1;async function m(){await r.recordDelivered(c.toString())}e.on("close",()=>{a||(a=!0,m().catch(d=>{console.error("[tab/seller] terminal persist failed on disconnect:",d)}))});async function l(d=1){if(a)throw new Error("meter ended");if(h===null)throw new Error("charge() needs options.perUnit");let f=h*BigInt(d),b=c+f;if(b>s)throw a=!0,await m(),new x("cumulative_exceeds_cap",`chunk would push delivered to ${V((i+b).toString())} beyond signed cumulative ${V(n.toString())} (per-request budget ${V(s.toString())})`);c=b}function o(d){if(a)throw new Error("meter ended");let b=(typeof d=="string"?d:Buffer.from(d).toString("utf8")).replace(/\n/g,"\\n");e.write(`data: ${b}
1
+ "use strict";var ht=Object.create;var Y=Object.defineProperty;var yt=Object.getOwnPropertyDescriptor;var ft=Object.getOwnPropertyNames;var At=Object.getPrototypeOf,bt=Object.prototype.hasOwnProperty;var vt=(e,t)=>{for(var r in t)Y(e,r,{get:t[r],enumerable:!0})},ze=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of ft(t))!bt.call(e,i)&&i!==r&&Y(e,i,{get:()=>t[i],enumerable:!(n=yt(t,i))||n.enumerable});return e};var He=(e,t,r)=>(r=e!=null?ht(At(e)):{},ze(t||!e||!e.__esModule?Y(r,"default",{value:e,enumerable:!0}):r,e)),wt=e=>ze(Y({},"__esModule",{value:!0}),e);var Wt={};vt(Wt,{FileChannelLedger:()=>Z,FileVoucherStore:()=>ge,InMemoryChannelLedger:()=>B,InMemoryVoucherStore:()=>pe,InvalidRegistrationError:()=>E,InvalidVoucherError:()=>S,InvalidVoucherSignatureError:()=>_,OnChainVerificationError:()=>k,RedisChannelLedger:()=>re,ScopeViolationError:()=>x,TAB_VOUCHER_HEADER:()=>I,deserializeChannelLedgerEntry:()=>te,enforceScope:()=>ce,openSse:()=>rt,parseRegistration:()=>se,requireTab:()=>tt,serializeChannelLedgerEntry:()=>ee,tabChallengeMiddleware:()=>mt,tabMiddleware:()=>de,tabOrExactMiddleware:()=>pt,verifyRegistrationOnChain:()=>oe,verifyVoucherSignature:()=>ae});module.exports=wt(Wt);var S=class extends Error{constructor(r,n){super(`Invalid voucher: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="InvalidVoucherError"}};var L=require("fs"),Q=require("path"),qe=new Map;function T(e,t){let n=(qe.get(e)??Promise.resolve()).then(()=>t(),()=>t());return qe.set(e,n.then(()=>{},()=>{})),n}var B=class{map=new Map;async get(t){return this.map.get(t)??null}async set(t,r){this.map.set(t,r)}async delete(t){this.map.delete(t)}async tryAcquireLease(t,r){return T(t,async()=>{let n=this.map.get(t),i=Date.now();if(n?.lease&&n.lease.heldUntilUnixMs>i)return!1;let s=n??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return this.map.set(t,{...s,lease:{heldUntilUnixMs:i+r}}),!0})}async releaseLease(t){await T(t,async()=>{let r=this.map.get(t);r&&this.map.set(t,{...r,lease:void 0})})}};function Ne(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}function Ie(e){if(e.length%2!==0)throw new Error(`hex length must be even, got ${e.length}`);let t=new Uint8Array(e.length/2);for(let r=0;r<t.length;r++)t[r]=parseInt(e.substr(r*2,2),16);return t}function ee(e){return Fe(e)}function te(e){return We(e)}function Fe(e){return{lastVoucher:e.lastVoucher?{payload:e.lastVoucher.payload,sessionPublicKey:Ne(e.lastVoucher.sessionPublicKey),sessionRegistration:Ne(e.lastVoucher.sessionRegistration),sessionSignature:Ne(e.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:e.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:e.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:e.gateRefusedCumulativeAtomic,onChain:e.onChain,lease:e.lease}}function We(e){return{lastVoucher:e.lastVoucher?{payload:e.lastVoucher.payload,sessionPublicKey:Ie(e.lastVoucher.sessionPublicKey),sessionRegistration:Ie(e.lastVoucher.sessionRegistration),sessionSignature:Ie(e.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:e.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:e.lastCrystallizedCumulativeAtomic??"0",gateRefusedCumulativeAtomic:e.gateRefusedCumulativeAtomic,onChain:e.onChain,lease:e.lease}}var Z=class{constructor(t){this.dir=t}pathFor(t){if(!/^[a-z0-9_-]+$/i.test(t))throw new Error(`unsafe channelId for filesystem: ${t}`);return(0,Q.join)(this.dir,`${t}.json`)}async get(t){try{let r=await L.promises.readFile(this.pathFor(t),"utf8");return We(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(t,r){let n=this.pathFor(t);await L.promises.mkdir((0,Q.dirname)(n),{recursive:!0});let i=`${n}.tmp`;await L.promises.writeFile(i,JSON.stringify(Fe(r))),await L.promises.rename(i,n)}async delete(t){try{await L.promises.unlink(this.pathFor(t))}catch(r){if(r?.code!=="ENOENT")throw r}}async tryAcquireLease(t,r){return T(t,async()=>{let n=await this.get(t),i=Date.now();if(n?.lease&&n.lease.heldUntilUnixMs>i)return!1;let s=n??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return await this.set(t,{...s,lease:{heldUntilUnixMs:i+r}}),!0})}async releaseLease(t){await T(t,async()=>{let r=await this.get(t);r&&await this.set(t,{...r,lease:void 0})})}};var je=require("crypto");var St='if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end',re=class{constructor(t,r="tab:"){this.client=t;this.keyPrefix=r}leaseTokens=new Map;ledgerKey(t){return`${this.keyPrefix}ledger:${t}`}leaseKey(t){return`${this.keyPrefix}lease:${t}`}async get(t){let r=await this.client.get(this.ledgerKey(t));return r===null?null:te(JSON.parse(r))}async set(t,r){let n=ee({...r,lease:void 0});await this.client.set(this.ledgerKey(t),JSON.stringify(n))}async delete(t){this.leaseTokens.delete(t),await this.client.del(this.ledgerKey(t),this.leaseKey(t))}async tryAcquireLease(t,r){let n=(0,je.randomUUID)();return await this.client.set(this.leaseKey(t),n,"PX",Math.max(1,Math.floor(r)),"NX")!=="OK"?!1:(this.leaseTokens.set(t,n),!0)}async releaseLease(t){let r=this.leaseTokens.get(t);r!==void 0&&(this.leaseTokens.delete(t),await this.client.eval(St,1,this.leaseKey(t),r))}};var et=require("@solana/web3.js");var Je=He(require("tweetnacl"),1),Ct=require("@noble/hashes/sha256"),Et=require("@noble/curves/p256"),ne=require("@solana/web3.js");var $=require("@dexterai/vault/messages");var Ue=require("@dexterai/vault/instructions"),xt=require("@dexterai/vault/precompile"),K=require("@dexterai/vault/constants");var ie=require("@dexterai/vault/session"),Oe="OTS_SESSION_REGISTER_V2",E=class extends Error{constructor(r,n){super(`Invalid registration: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="InvalidRegistrationError"}};function se(e){if(e.length!==188)throw new E("wrong_length",`expected 188, got ${e.length}`);let t=new TextDecoder().decode(e.slice(0,Oe.length));if(t!==Oe)throw new E("wrong_domain",`got "${t}"`);for(let y=Oe.length;y<32;y++)if(e[y]!==0)throw new E("wrong_domain",`non-NUL padding at byte ${y}`);let r=new DataView(e.buffer,e.byteOffset,e.byteLength),n=new ne.PublicKey(e.slice(32,64)),i=new ne.PublicKey(e.slice(64,96)),s=e.slice(96,128),h=r.getBigUint64(128,!0),c=r.getBigInt64(136,!0),a=new ne.PublicKey(e.slice(144,176)),m=r.getUint32(176,!0),l=r.getBigUint64(180,!0);if(!n.equals(K.DEXTER_VAULT_PROGRAM_ID))throw new E("wrong_program",`${n.toBase58()} is not ${K.DEXTER_VAULT_PROGRAM_ID.toBase58()}`);if(h===0n)throw new E("cap_zero");let o=BigInt(Math.floor(Date.now()/1e3));if(c<=o)throw new E("expiry_in_past",`expires_at=${c}, now=${o}`);return{programId:n,vaultPda:i,sessionPubkey:new Uint8Array(s),maxAmount:h,expiresAt:c,allowedCounterparty:a,nonce:m,maxRevolvingCapacity:l}}var k=class extends Error{constructor(r,n){super(`On-chain verification failed: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="OnChainVerificationError"}};async function oe(e,t){let r=await(0,ie.fetchSessionAccount)(e,t.vaultPda,t.allowedCounterparty);if(!r||r.version===0)throw new k("session_not_active","no live SessionAccount PDA for this (vault, counterparty) \u2014 revoked, expiry-swept, or never registered");if(!(0,ie.isSessionLive)(r))throw new k("session_not_active","SessionAccount PDA is present but expired");if(!Pt(r.session.sessionPubkey,t.sessionPubkey))throw new k("session_pubkey_mismatch",`on-chain ${Xe(r.session.sessionPubkey)} != registration ${Xe(t.sessionPubkey)}`);let n=r.session.spent,i=r.session.crystallizedCumulative;return{frontierAtomic:(n>i?n:i).toString(),spentAtomic:n.toString(),crystallizedCumulativeAtomic:i.toString()}}var _=class extends Error{constructor(t){super(`Invalid voucher signature${t?`: ${t}`:""}`),this.name="InvalidVoucherSignatureError"}};function ae(e,t){if(t.length!==32)throw new _(`channelIdBytes must be 32 bytes, got ${t.length}`);if(e.sessionPublicKey.length!==32)throw new _(`sessionPublicKey must be 32 bytes, got ${e.sessionPublicKey.length}`);if(e.sessionSignature.length!==64)throw new _(`sessionSignature must be 64 bytes, got ${e.sessionSignature.length}`);let r=(0,$.voucherPayloadMessage)({channelId:t,cumulativeAmount:BigInt(e.payload.cumulativeAmount),sequenceNumber:e.payload.sequenceNumber});if(!Je.default.sign.detached.verify(r,e.sessionSignature,e.sessionPublicKey))throw new _("ed25519 verify rejected")}var x=class extends Error{constructor(r,n){super(`Scope violation: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="ScopeViolationError"}};function ce(e){let t=BigInt(e.voucher.payload.cumulativeAmount);if(t>e.registration.maxAmount)throw new x("cumulative_exceeds_cap",`${t} > ${e.registration.maxAmount}`);let r=BigInt(Math.floor(Date.now()/1e3));if(r>=e.registration.expiresAt)throw new x("session_expired",`now=${r} >= expiresAt=${e.registration.expiresAt}`);if(!e.registration.allowedCounterparty.equals(e.expectedCounterparty))throw new x("wrong_counterparty",`${e.registration.allowedCounterparty.toBase58()} != ${e.expectedCounterparty.toBase58()}`);if(e.previousCumulativeAtomic!==void 0){let n=BigInt(e.previousCumulativeAtomic);if(t<=n)throw new x("non_monotonic",`cumulative=${t} not > previous=${n}`)}}function Pt(e,t){if(e.length!==t.length)return!1;for(let r=0;r<e.length;r++)if(e[r]!==t[r])return!1;return!0}function Xe(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}var _t=require("@solana/web3.js"),kt=require("@noble/hashes/utils");var Rt=He(require("tweetnacl"),1);var Tt=require("@noble/hashes/sha256");var Ge="https://x402.dexter.cash",Ye=6;function P(e,t=Ye){if(!/^\d+(\.\d+)?$/.test(e))throw new Error(`amount must be a non-negative decimal string, got "${e}"`);let[r,n=""]=e.split(".");if(n.length>t)throw new Error(`amount "${e}" has more than ${t} decimals`);let i=n.padEnd(t,"0"),s=`${r}${i}`.replace(/^0+(?=\d)/,"");return s===""?"0":s}function V(e,t=Ye){if(!/^\d+$/.test(e))throw new Error(`atomic must be a non-negative integer string, got "${e}"`);let r=e.padStart(t+1,"0"),n=r.slice(0,-t).replace(/^0+(?=\d)/,"")||"0",i=r.slice(-t).replace(/0+$/,"");return i?`${n}.${i}`:n}var le=require("@noble/hashes/utils"),Nt=15e3,It=["claim_already_exists","non_monotonic_cumulative"],Ut="below_lock_cadence";function ue(e){return typeof e=="string"&&e.includes(Ut)}function Ot(e){return`${e.slice(0,16)}\u2026`}function Ze(e,t,r,n){let i=Ot(e);if(n.crystallized){console.info(`[tab/seller] crystallize OK channel=${i} cumulative=${t} seq=${r}${n.claimPda?` claimPda=${n.claimPda}`:""} \u2014 LockVoucher landed`);return}if(n.error){if(ue(n.error)){console.warn(`[tab/seller] crystallize refused below the facilitator's cadence gate channel=${i} cumulative=${t} seq=${r}: ${n.error} \u2014 benign: this facilitator's cadence engine owns the protection cadence for the span; gate-refused watermark advanced, re-attempts after the next signed voucher`);return}if(It.some(s=>n.error.includes(s))){console.warn(`[tab/seller] crystallize duplicate channel=${i} cumulative=${t} seq=${r}: ${n.error} \u2014 voucher already secured on-chain (benign, no action)`);return}console.error(`[tab/seller] crystallize FAILED channel=${i} cumulative=${t} seq=${r}: ${n.error} \u2014 lock NOT secured (degraded: best-effort path, no watermark advance, retries at next threshold/close; seller exposure stays unsecured until it lands)`)}}async function $e(e,t,r,n,i=fetch){let s=e.lastVoucher;if(!s)return{crystallized:!1};if(s.payload.channelId!==t){let c={crystallized:!1,error:"channel_id_mismatch"};return Ze(t,s.payload.cumulativeAmount,s.payload.sequenceNumber,c),c}let h=c=>(Ze(t,s.payload.cumulativeAmount,s.payload.sequenceNumber,c),c);try{let c=`${r.replace(/\/$/,"")}/tab/lock`,a={channelId:s.payload.channelId,cumulativeAmount:s.payload.cumulativeAmount,sequenceNumber:s.payload.sequenceNumber,sessionPublicKey:(0,le.bytesToHex)(s.sessionPublicKey),sessionSignature:(0,le.bytesToHex)(s.sessionSignature),sessionRegistration:(0,le.bytesToHex)(s.sessionRegistration),network:n},m=await i(c,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(a),signal:AbortSignal.timeout(Nt)}),l=await m.text();if(!m.ok)return h({crystallized:!1,error:`tab lock ${m.status}: ${l.slice(0,200)}`});let o;try{let y=JSON.parse(l);y&&typeof y.claimPda=="string"&&(o=y.claimPda)}catch{}return h({crystallized:!0,claimPda:o})}catch(c){return h({crystallized:!1,error:String(c?.message??c)})}}async function Qe(e,t,r,n,i,s={}){let h=BigInt(e.deliveredCumulativeAtomic),c=BigInt(e.lastCrystallizedCumulativeAtomic??"0"),a=BigInt(i.thresholdAtomic);if(h-c<a)return{crystallized:!1};let m=e.lastVoucher?.payload.cumulativeAmount,l=e.gateRefusedCumulativeAtomic;if(m!==void 0&&l!==void 0&&BigInt(m)<=BigInt(l))return{crystallized:!1};let o=await $e(e,t,r,n,s.fetchImpl);return o.crystallized&&m!==void 0?(e.lastCrystallizedCumulativeAtomic=m,e.gateRefusedCumulativeAtomic=void 0):ue(o.error)&&m!==void 0&&(e.gateRefusedCumulativeAtomic=m),o}var I="x-tab-voucher",Ve=class{map=new Map;get(t){return this.map.get(t)}set(t,r){this.map.set(t,r)}update(t,r){let n=this.map.get(t);n&&(n.lastCumulativeAtomic=r)}delete(t){this.map.delete(t)}},Le=class{constructor(t,r,n,i,s,h){this.recordDeliveredImpl=s;this.chargeImpl=h;this.channelId=t,this.network=r,this.cumulativeAtomic=n,this.deliveredBaselineAtomic=i}channelId;network;sessionPublicKey=null;cumulativeAtomic;deliveredBaselineAtomic;cumulative(){return V(this.cumulativeAtomic.toString())}deliveredCumulative(){return V(this.deliveredBaselineAtomic.toString())}async recordDelivered(t){return this.recordDeliveredImpl(t)}bumpCumulative(t){this.cumulativeAtomic=t}setSessionPublicKey(t){this.sessionPublicKey=t}async charge(t){return this.chargeImpl(t)}};function $t(e){if(typeof e!="string"||e.length===0)throw new S("signature_invalid",`missing ${I} header`);let t;try{t=Buffer.from(e,"base64").toString("utf8")}catch{throw new S("signature_invalid","malformed base64")}let r;try{r=JSON.parse(t)}catch{throw new S("signature_invalid","malformed JSON")}if(!r||typeof r!="object"||!r.payload||!r.sessionPublicKey)throw new S("signature_invalid","missing required fields");return{payload:r.payload,sessionPublicKey:me(r.sessionPublicKey),sessionRegistration:me(r.sessionRegistration),sessionSignature:me(r.sessionSignature)}}function me(e){if(typeof e!="string"||e.length%2!==0)throw new S("signature_invalid",`bad hex: ${typeof e}`);let t=new Uint8Array(e.length/2);for(let r=0;r<t.length;r++)t[r]=parseInt(e.substr(r*2,2),16);return t}function Vt(e){if(!/^[0-9a-f]{64}$/i.test(e))throw new S("signature_invalid",`channelId must be 64-char hex, got "${e}"`);return me(e)}function de(e){let t=e.ledger??new B,r=new Ve,n=typeof e.sellerPubkey=="string"?new et.PublicKey(e.sellerPubkey):e.sellerPubkey,i=e.maxPerVoucherAtomic?BigInt(e.maxPerVoucherAtomic):BigInt(P(e.perUnit))*100n,s=e.facilitatorUrl??Ge,h={thresholdAtomic:e.lockCadence?.thresholdAtomic??P("0.10"),onClose:e.lockCadence?.onClose??!0};return async(c,a,m)=>{try{let l=$t(c.headers[I]),o=l.payload.channelId,y=Vt(o),d=r.get(o),f=null;if(!d){let p=se(l.sessionRegistration);f=(await oe(e.connection,p))?.frontierAtomic??null;let v=await t.get(o);d={registration:p,lastCumulativeAtomic:v?.lastVoucher?.payload.cumulativeAmount??"0"},r.set(o,d)}ae(l,y),ce({registration:d.registration,voucher:l,expectedCounterparty:n,previousCumulativeAtomic:d.lastCumulativeAtomic});let b=BigInt(l.payload.cumulativeAmount),D=BigInt(d.lastCumulativeAtomic),z=b-D;if(z>i)throw new x("cumulative_exceeds_cap",`single voucher increment ${z} exceeds maxPerVoucherAtomic ${i}`);let _e=e.leaseTtlMs??3e5;if(!await t.tryAcquireLease(o,_e))throw new S("channel_busy","another stream is live on this channel; tabs serve one stream at a time");let H=!1,J=()=>{H||(H=!0,t.releaseLease(o).catch(p=>{console.error("[tab/seller] failed to release channel lease:",p)}))};a.on("close",J),a.on("finish",J);let ke=async p=>{let R=p.lastCrystallizedCumulativeAtomic??"0",v=p.gateRefusedCumulativeAtomic;await Qe(p,o,s,e.network,h),(p.lastCrystallizedCumulativeAtomic!==R||p.gateRefusedCumulativeAtomic!==v)&&await T(o,async()=>{let w=await t.get(o);w&&await t.set(o,{...w,lastCrystallizedCumulativeAtomic:p.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:p.gateRefusedCumulativeAtomic})}).catch(w=>{console.error(`[tab/seller] crystallize watermark persist FAILED channel=${o.slice(0,16)}\u2026 (expect a benign duplicate/below-cadence warn on the next request):`,w)})},G=!1,u=()=>{!h.onClose||G||(G=!0,(async()=>{let p=await t.get(o);if(!p||!p.lastVoucher)return;let R=p.lastVoucher.payload.cumulativeAmount;if(p.gateRefusedCumulativeAtomic!==void 0&&BigInt(R)<=BigInt(p.gateRefusedCumulativeAtomic))return;let v=await $e(p,o,s,e.network);v.crystallized?await T(o,async()=>{let w=await t.get(o);w&&await t.set(o,{...w,lastCrystallizedCumulativeAtomic:R,gateRefusedCumulativeAtomic:void 0})}):ue(v.error)&&await T(o,async()=>{let w=await t.get(o);w&&await t.set(o,{...w,gateRefusedCumulativeAtomic:R})})})().catch(p=>{console.error(`[tab/seller] close-path crystallize CRASHED channel=${o.slice(0,16)}\u2026 (final voucher NOT locked; exposure unsecured until the next request retries):`,p)}))};a.on("close",u),a.on("finish",u);let g=await t.get(o),A=!g?.lastVoucher&&BigInt(g?.deliveredCumulativeAtomic??"0")===0n,C=f!==null&&A&&BigInt(f)>0n?f:null;C!==null&&console.info(`[tab/seller] channel ${o.slice(0,16)}\u2026 resumed: seeding delivered baseline from chain frontier ${C} (session already settled/locked up to it \u2014 that span is not deliverable budget)`);let U=C!==null?BigInt(C):g?BigInt(g.deliveredCumulativeAtomic):0n;await T(o,async()=>{let p=await t.get(o);await t.set(o,{...p,lastVoucher:l,deliveredCumulativeAtomic:C??(p?p.deliveredCumulativeAtomic:"0"),lastCrystallizedCumulativeAtomic:C??p?.lastCrystallizedCumulativeAtomic??"0"})}),r.update(o,l.payload.cumulativeAmount);let O=new Le(o,e.network,b,U,async p=>{let R=null;await T(o,async()=>{let v=await t.get(o),w=v?BigInt(v.deliveredCumulativeAtomic):0n,Me=BigInt(p),gt=Me>0n?w+Me:w,De={...v,lastVoucher:v?.lastVoucher??l,deliveredCumulativeAtomic:gt.toString(),lastCrystallizedCumulativeAtomic:v?.lastCrystallizedCumulativeAtomic??"0"};await t.set(o,De),R=De}),R&&ke(R).catch(v=>{console.error(`[tab/seller] crystallize cadence CRASHED channel=${o.slice(0,16)}\u2026 (threshold lock not attempted; retries at the next delivery):`,v)})},async p=>{throw new Error("SellerTab.charge() is not driven by the route handler; the buyer presents a fresh voucher per chunk. Use openSse(res, tab) for the metered-stream pattern.")});O.setSessionPublicKey(l.sessionPublicKey),c.tab=O,m()}catch(l){if(l instanceof S||l instanceof E||l instanceof k||l instanceof _||l instanceof x){a.status(402).json({error:"invalid_voucher",reason:l.reason??"unknown",detail:l.message});return}m(l)}}}function tt(e){if(!e.tab)throw new Error("req.tab is missing \u2014 did tabMiddleware run on this route?");return e.tab}function rt(e,t){if(!t.tab)throw new Error("openSse requires options.tab");e.headersSent||(e.setHeader("Content-Type","text/event-stream"),e.setHeader("Cache-Control","no-cache"),e.setHeader("Connection","keep-alive"),typeof e.flushHeaders=="function"&&e.flushHeaders());let r=t.tab,n=BigInt(P(r.cumulative())),i=BigInt(P(r.deliveredCumulative())),s=n-i;s<0n&&(s=0n);let h=t.perUnit?BigInt(P(t.perUnit)):null,c=0n,a=!1;async function m(){await r.recordDelivered(c.toString())}e.on("close",()=>{a||(a=!0,m().catch(d=>{console.error("[tab/seller] terminal persist failed on disconnect:",d)}))});async function l(d=1){if(a)throw new Error("meter ended");if(h===null)throw new Error("charge() needs options.perUnit");let f=h*BigInt(d),b=c+f;if(b>s)throw a=!0,await m(),new x("cumulative_exceeds_cap",`chunk would push delivered to ${V((i+b).toString())} beyond signed cumulative ${V(n.toString())} (per-request budget ${V(s.toString())})`);c=b}function o(d){if(a)throw new Error("meter ended");let b=(typeof d=="string"?d:Buffer.from(d).toString("utf8")).replace(/\\/g,"\\\\").replace(/\n/g,"\\n");e.write(`data: ${b}
2
2
 
3
3
  `)}async function y(){a||(a=!0,await m(),e.write(`event: end
4
4
  data: {"chargedAtomic":"${c}"}
5
5
 
6
- `),e.end())}return{charge:l,send:o,end:y}}var M=require("fs"),de=require("path");function kt(e){return{payload:e.payload,sessionPublicKey:$e(e.sessionPublicKey),sessionRegistration:$e(e.sessionRegistration),sessionSignature:$e(e.sessionSignature)}}function Ut(e){return{payload:e.payload,sessionPublicKey:Ve(e.sessionPublicKey),sessionRegistration:Ve(e.sessionRegistration),sessionSignature:Ve(e.sessionSignature)}}function $e(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}function Ve(e){if(e.length%2!==0)throw new Error(`hex length must be even, got ${e.length}`);let t=new Uint8Array(e.length/2);for(let r=0;r<t.length;r++)t[r]=parseInt(e.substr(r*2,2),16);return t}var ue=class{map=new Map;async get(t){return this.map.get(t)??null}async set(t,r){this.map.set(t,r)}async delete(t){this.map.delete(t)}},me=class{constructor(t){this.dir=t}pathFor(t){if(!/^[a-z0-9_-]+$/i.test(t))throw new Error(`unsafe channelId for filesystem: ${t}`);return(0,de.join)(this.dir,`${t}.json`)}async get(t){try{let r=await M.promises.readFile(this.pathFor(t),"utf8");return Ut(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(t,r){let n=this.pathFor(t);await M.promises.mkdir((0,de.dirname)(n),{recursive:!0});let i=`${n}.tmp`;await M.promises.writeFile(i,JSON.stringify(kt(r))),await M.promises.rename(i,n)}async delete(t){try{await M.promises.unlink(this.pathFor(t))}catch(r){if(r?.code!=="ENOENT")throw r}}};var it=require("@solana/web3.js");var N="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",Ye="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",Ze="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";var q="eip155:8453",pe="eip155:84532",ge="eip155:42161",he="eip155:137",ye="eip155:10",fe="eip155:43114",Ae="eip155:56",be="eip155:1187947933",ve="eip155:324705682",we="eip155:1";var Se="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";var Qe="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",Ot="0x55d398326f99059fF775485246999027B3197955",et="0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",tt={[Ae]:et,[q]:Qe,[pe]:"0x036CbD53842c5426634e7929541eC2318f3dCF7e",[ge]:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831",[he]:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",[ye]:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",[fe]:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",[be]:"0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",[ve]:"0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",[we]:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},rt={[Ot]:{symbol:"USDT",decimals:18},[et]:{symbol:"USDC",decimals:18}};var br={[Ae]:56,[q]:8453,[pe]:84532,[ge]:42161,[he]:137,[ye]:10,[fe]:43114,[be]:1187947933,[ve]:324705682,[we]:1},vr={[N]:"https://api.dexter.cash/api/solana/rpc",[Ye]:"https://api.devnet.solana.com",[Ze]:"https://api.testnet.solana.com"},wr={[Ae]:"https://api.dexter.cash/api/evm/bsc/rpc",[q]:"https://api.dexter.cash/api/base/rpc",[pe]:"https://sepolia.base.org",[ge]:"https://api.dexter.cash/api/evm/arbitrum/rpc",[he]:"https://api.dexter.cash/api/evm/polygon/rpc",[ye]:"https://api.dexter.cash/api/evm/optimism/rpc",[fe]:"https://api.dexter.cash/api/evm/avalanche/rpc",[be]:"https://skale-base.skalenodes.com/v1/base",[ve]:"https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",[we]:"https://eth.llamarpc.com"},F="https://x402.dexter.cash";function xe(e){return e.startsWith("solana:")||e==="solana"}function $t(e){if(typeof Buffer<"u")return Buffer.from(e,"utf-8").toString("base64");let t=new TextEncoder().encode(e),r="";for(let n=0;n<t.length;n++)r+=String.fromCharCode(t[n]);return btoa(r)}function Vt(e){if(typeof Buffer<"u")return Buffer.from(e,"base64").toString("utf-8");let t=atob(e),r=new Uint8Array(t.length);for(let n=0;n<t.length;n++)r[n]=t.charCodeAt(n);return new TextDecoder().decode(r)}function Ce(e){return $t(JSON.stringify(e))}function W(e){return JSON.parse(Vt(e))}function Bt(e){if(e instanceof TypeError)return!0;if(e&&typeof e=="object"&&"status"in e){let t=e.status;return t>=500&&t<600}return!1}var j=class extends Error{status;body;constructor(t,r){super(`HTTP ${t}`),this.status=t,this.body=r}},Ee=class{facilitatorUrl;cachedSupported=null;cacheTime=0;CACHE_TTL_MS=6e4;timeoutMs;maxRetries;retryBaseMs;constructor(t=F,r){this.facilitatorUrl=t.replace(/\/$/,""),this.timeoutMs=r?.timeoutMs??1e4,this.maxRetries=r?.maxRetries??3,this.retryBaseMs=r?.retryBaseMs??500}async fetchWithTimeout(t,r){let n=new AbortController,i=setTimeout(()=>n.abort(),this.timeoutMs);try{return await fetch(t,{...r,signal:n.signal})}finally{clearTimeout(i)}}async fetchWithRetry(t,r){let n;for(let i=0;i<this.maxRetries;i++)try{let s=await this.fetchWithTimeout(t,r);if(!s.ok&&s.status>=500)throw new j(s.status,await s.text());return s}catch(s){if(n=s,i<this.maxRetries-1&&Bt(s)){let h=this.retryBaseMs*Math.pow(2,i);await new Promise(c=>setTimeout(c,h));continue}throw s}throw n}async getSupported(){let t=Date.now();if(this.cachedSupported&&t-this.cacheTime<this.CACHE_TTL_MS)return this.cachedSupported;let r=await this.fetchWithTimeout(`${this.facilitatorUrl}/supported`);if(!r.ok)throw new Error(`Facilitator /supported returned ${r.status}`);return this.cachedSupported=await r.json(),this.cacheTime=t,this.cachedSupported}async getFeePayer(t){let n=(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval")&&i.network===t);if(!n)throw new Error(`Facilitator does not support network "${t}" with a recognized scheme`);return n.extra?.feePayer}async getNetworkExtra(t){return(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval"||i.scheme==="batch-settlement")&&i.network===t)?.extra}async verifyPayment(t,r){try{let n=W(t),i=await this.fetchWithRetry(`${this.facilitatorUrl}/verify`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:n,paymentRequirements:r})});return i.ok?await i.json():{isValid:!1,invalidReason:`facilitator_error_${i.status}`}}catch(n){return{isValid:!1,invalidReason:n instanceof j?`facilitator_error_${n.status}`:n instanceof Error&&n.name==="AbortError"?"facilitator_timeout":n instanceof Error?n.message:"unexpected_verify_error"}}}async settlePayment(t,r){try{let n=W(t),i=await this.fetchWithRetry(`${this.facilitatorUrl}/settle`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:n,paymentRequirements:r})});return i.ok?{...await i.json(),network:r.network}:{success:!1,network:r.network,errorReason:`facilitator_error_${i.status}`}}catch(n){let i=n instanceof j?`facilitator_error_${n.status}`:n instanceof Error&&n.name==="AbortError"?"facilitator_timeout":n instanceof Error?n.message:"unexpected_settle_error";return{success:!1,network:r.network,errorReason:i}}}};function Lt(e){if(xe(e))return{address:Se,decimals:6};let t=tt[e];if(t){let r=rt[t]?.decimals??6;return{address:t,decimals:r}}return{address:Se,decimals:6}}function nt(e){try{let t=W(e);return t?.accepted?.amount??t?.accepted?.maxAmountRequired}catch{return}}function X(e){let{payTo:t,facilitatorUrl:r=F,network:n=N,defaultTimeoutSeconds:i=60}=e,s=e.asset??Lt(n),h=e.scheme??"exact";if(h==="tab"&&!xe(n))throw new Error(`scheme 'tab' is SVM-only; got network "${n}"`);let c=new Ee(r),a=null,m=new Map,l=3e4,o=Date.now();function y(u){let g=(u.maxTimeoutSeconds||i)*1e3;if(m.set(u.payTo,{accept:u,expiresAt:Date.now()+g}),Date.now()-o>l){let A=Date.now();for(let[C,U]of m)U.expiresAt<A&&m.delete(C);o=A}}function d(u){let g=m.get(u);if(g){if(g.expiresAt<Date.now()){m.delete(u);return}return g.accept}}async function f(u){return typeof t=="string"?t:t(u||{})}async function b(){if(a||(a=await c.getNetworkExtra(n)),xe(n)&&!a?.feePayer)throw new Error(`Facilitator does not provide feePayer for network "${n}"`);return{...a?.feePayer?{feePayer:a.feePayer}:{},decimals:a?.decimals??s.decimals,name:a?.name,version:a?.version,...h==="batch-settlement"&&a?.receiverAuthorizer?{receiverAuthorizer:a.receiverAuthorizer}:{},...h==="tab"?{voucherHeader:"x-tab-voucher",registrationEncoding:"base64(188-byte sessionRegisterMessage)"}:{}}}async function D(u,g){let{amountAtomic:A,timeoutSeconds:C=i}=g,U=await b(),O={scheme:h,network:n,amount:A,maxAmountRequired:A,asset:s.address,payTo:u,maxTimeoutSeconds:C,extra:U};return y(O),O}async function z(u){let g=await f({amountAtomic:u.amountAtomic,resourceUrl:u.resourceUrl});return D(g,u)}async function Re(u){let{resourceUrl:g,description:A,mimeType:C="application/json"}=u,U={url:g,description:A,mimeType:C},O=await z(u);return{x402Version:2,resource:U,accepts:[O],error:"Payment required"}}function H(u){return Ce(u)}function J(u){return{status:402,headers:{"PAYMENT-REQUIRED":H(u)},body:{}}}async function Pe(u,g){if(!g){let A=await f({paymentHeader:u});g=d(A),g||(g=await D(A,{amountAtomic:nt(u)??"0",resourceUrl:""}))}return c.verifyPayment(u,g)}async function G(u,g){if(!g){let A=await f({paymentHeader:u});g=d(A),g||(g=await D(A,{amountAtomic:nt(u)??"0",resourceUrl:""}))}return c.settlePayment(u,g)}return{buildRequirements:Re,encodeRequirements:H,create402Response:J,verifyPayment:Pe,settlePayment:G,getPaymentAccept:z,network:n,assetDecimals:s.decimals,facilitator:c}}var Kt={"solana:mainnet":N};function st(e){let t=Kt[e.network];if(!t)throw new Error(`tabChallengeMiddleware: unsupported network "${e.network}"`);let r=typeof e.sellerPubkey=="string"?e.sellerPubkey:e.sellerPubkey.toBase58();new it.PublicKey(r);let n=X({payTo:r,network:t,scheme:"tab",facilitatorUrl:e.facilitatorUrl}),i=R(e.perUnit);return async(s,h,c)=>{if(s.headers[k])return c();try{let a=`${s.protocol}://${s.get("host")}${s.originalUrl}`,m=await n.buildRequirements({amountAtomic:i,resourceUrl:a,description:e.description}),l=n.create402Response(m);h.set(l.headers).status(l.status).json(l.body)}catch(a){let m=a?.message??String(a);h.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:m})}}}var ot=require("@solana/web3.js");var Mt={"solana:mainnet":N};function at(e){let t=Mt[e.network];if(!t)throw new Error(`tabOrExactMiddleware: unsupported network "${e.network}"`);let r=typeof e.sellerPubkey=="string"?e.sellerPubkey:e.sellerPubkey.toBase58();new ot.PublicKey(r);let n=X({payTo:r,network:t,scheme:"tab",facilitatorUrl:e.facilitatorUrl}),i=X({payTo:r,network:t,scheme:"exact",facilitatorUrl:e.facilitatorUrl}),s=R(e.perUnit),h=le({connection:e.connection,sellerPubkey:r,network:e.network,perUnit:e.perUnit,settle:"on-close",facilitatorUrl:e.facilitatorUrl,lockCadence:e.lockCadence});return async(c,a,m)=>{if(c.headers[k])return h(c,a,m);let l=`${c.protocol}://${c.get("host")}${c.originalUrl}`,o=c.headers["payment-signature"];if(o){let y;try{y=await i.getPaymentAccept({amountAtomic:s,resourceUrl:l,description:e.description})}catch(d){let f=d?.message??String(d);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:f});return}try{let d=await i.verifyPayment(o,y);if(!d.isValid){a.status(402).json({error:"Payment verification failed",reason:d.invalidReason});return}let f=await i.settlePayment(o,y);if(!f.success){a.status(402).json({error:"Payment settlement failed",reason:f.errorReason});return}return c.x402={transaction:f.transaction,payer:d.payer??"",network:f.network||t},a.setHeader("PAYMENT-RESPONSE",Ce({success:!0,transaction:f.transaction,network:f.network||t,payer:d.payer??""})),m()}catch{a.status(500).json({error:"Payment processing error"});return}}try{let y={amountAtomic:s,resourceUrl:l,description:e.description},[d,f]=await Promise.all([n.buildRequirements(y),i.buildRequirements(y)]),b={...d,accepts:[...d.accepts,...f.accepts]};a.set({"PAYMENT-REQUIRED":n.encodeRequirements(b)}).status(402).json({error:"Payment required",accepts:b.accepts,resource:b.resource})}catch(y){let d=y?.message??String(y);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:d})}}}0&&(module.exports={FileChannelLedger,FileVoucherStore,InMemoryChannelLedger,InMemoryVoucherStore,InvalidRegistrationError,InvalidVoucherError,InvalidVoucherSignatureError,OnChainVerificationError,ScopeViolationError,TAB_VOUCHER_HEADER,enforceScope,openSse,parseRegistration,requireTab,tabChallengeMiddleware,tabMiddleware,tabOrExactMiddleware,verifyRegistrationOnChain,verifyVoucherSignature});
6
+ `),e.end())}return{charge:l,send:o,end:y}}var M=require("fs"),he=require("path");function Lt(e){return{payload:e.payload,sessionPublicKey:Be(e.sessionPublicKey),sessionRegistration:Be(e.sessionRegistration),sessionSignature:Be(e.sessionSignature)}}function Bt(e){return{payload:e.payload,sessionPublicKey:Ke(e.sessionPublicKey),sessionRegistration:Ke(e.sessionRegistration),sessionSignature:Ke(e.sessionSignature)}}function Be(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}function Ke(e){if(e.length%2!==0)throw new Error(`hex length must be even, got ${e.length}`);let t=new Uint8Array(e.length/2);for(let r=0;r<t.length;r++)t[r]=parseInt(e.substr(r*2,2),16);return t}var pe=class{map=new Map;async get(t){return this.map.get(t)??null}async set(t,r){this.map.set(t,r)}async delete(t){this.map.delete(t)}},ge=class{constructor(t){this.dir=t}pathFor(t){if(!/^[a-z0-9_-]+$/i.test(t))throw new Error(`unsafe channelId for filesystem: ${t}`);return(0,he.join)(this.dir,`${t}.json`)}async get(t){try{let r=await M.promises.readFile(this.pathFor(t),"utf8");return Bt(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(t,r){let n=this.pathFor(t);await M.promises.mkdir((0,he.dirname)(n),{recursive:!0});let i=`${n}.tmp`;await M.promises.writeFile(i,JSON.stringify(Lt(r))),await M.promises.rename(i,n)}async delete(t){try{await M.promises.unlink(this.pathFor(t))}catch(r){if(r?.code!=="ENOENT")throw r}}};var ut=require("@solana/web3.js");var N="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",nt="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",it="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";var q="eip155:8453",ye="eip155:84532",fe="eip155:42161",Ae="eip155:137",be="eip155:10",ve="eip155:43114",we="eip155:56",Se="eip155:1187947933",xe="eip155:324705682",Ce="eip155:1";var Ee="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";var st="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",Kt="0x55d398326f99059fF775485246999027B3197955",ot="0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",at={[we]:ot,[q]:st,[ye]:"0x036CbD53842c5426634e7929541eC2318f3dCF7e",[fe]:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831",[Ae]:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",[be]:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",[ve]:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",[Se]:"0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",[xe]:"0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",[Ce]:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},ct={[Kt]:{symbol:"USDT",decimals:18},[ot]:{symbol:"USDC",decimals:18}};var Pr={[we]:56,[q]:8453,[ye]:84532,[fe]:42161,[Ae]:137,[be]:10,[ve]:43114,[Se]:1187947933,[xe]:324705682,[Ce]:1},Rr={[N]:"https://api.dexter.cash/api/solana/rpc",[nt]:"https://api.devnet.solana.com",[it]:"https://api.testnet.solana.com"},Tr={[we]:"https://api.dexter.cash/api/evm/bsc/rpc",[q]:"https://api.dexter.cash/api/base/rpc",[ye]:"https://sepolia.base.org",[fe]:"https://api.dexter.cash/api/evm/arbitrum/rpc",[Ae]:"https://api.dexter.cash/api/evm/polygon/rpc",[be]:"https://api.dexter.cash/api/evm/optimism/rpc",[ve]:"https://api.dexter.cash/api/evm/avalanche/rpc",[Se]:"https://skale-base.skalenodes.com/v1/base",[xe]:"https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",[Ce]:"https://eth.llamarpc.com"},F="https://x402.dexter.cash";function Pe(e){return e.startsWith("solana:")||e==="solana"}function Mt(e){if(typeof Buffer<"u")return Buffer.from(e,"utf-8").toString("base64");let t=new TextEncoder().encode(e),r="";for(let n=0;n<t.length;n++)r+=String.fromCharCode(t[n]);return btoa(r)}function Dt(e){if(typeof Buffer<"u")return Buffer.from(e,"base64").toString("utf-8");let t=atob(e),r=new Uint8Array(t.length);for(let n=0;n<t.length;n++)r[n]=t.charCodeAt(n);return new TextDecoder().decode(r)}function Re(e){return Mt(JSON.stringify(e))}function W(e){return JSON.parse(Dt(e))}function zt(e){if(e instanceof TypeError)return!0;if(e&&typeof e=="object"&&"status"in e){let t=e.status;return t>=500&&t<600}return!1}var j=class extends Error{status;body;constructor(t,r){super(`HTTP ${t}`),this.status=t,this.body=r}},Te=class{facilitatorUrl;cachedSupported=null;cacheTime=0;CACHE_TTL_MS=6e4;timeoutMs;maxRetries;retryBaseMs;constructor(t=F,r){this.facilitatorUrl=t.replace(/\/$/,""),this.timeoutMs=r?.timeoutMs??1e4,this.maxRetries=r?.maxRetries??3,this.retryBaseMs=r?.retryBaseMs??500}async fetchWithTimeout(t,r){let n=new AbortController,i=setTimeout(()=>n.abort(),this.timeoutMs);try{return await fetch(t,{...r,signal:n.signal})}finally{clearTimeout(i)}}async fetchWithRetry(t,r){let n;for(let i=0;i<this.maxRetries;i++)try{let s=await this.fetchWithTimeout(t,r);if(!s.ok&&s.status>=500)throw new j(s.status,await s.text());return s}catch(s){if(n=s,i<this.maxRetries-1&&zt(s)){let h=this.retryBaseMs*Math.pow(2,i);await new Promise(c=>setTimeout(c,h));continue}throw s}throw n}async getSupported(){let t=Date.now();if(this.cachedSupported&&t-this.cacheTime<this.CACHE_TTL_MS)return this.cachedSupported;let r=await this.fetchWithTimeout(`${this.facilitatorUrl}/supported`);if(!r.ok)throw new Error(`Facilitator /supported returned ${r.status}`);return this.cachedSupported=await r.json(),this.cacheTime=t,this.cachedSupported}async getFeePayer(t){let n=(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval")&&i.network===t);if(!n)throw new Error(`Facilitator does not support network "${t}" with a recognized scheme`);return n.extra?.feePayer}async getNetworkExtra(t){return(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval"||i.scheme==="batch-settlement")&&i.network===t)?.extra}async verifyPayment(t,r){try{let n=W(t),i=await this.fetchWithRetry(`${this.facilitatorUrl}/verify`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:n,paymentRequirements:r})});return i.ok?await i.json():{isValid:!1,invalidReason:`facilitator_error_${i.status}`}}catch(n){return{isValid:!1,invalidReason:n instanceof j?`facilitator_error_${n.status}`:n instanceof Error&&n.name==="AbortError"?"facilitator_timeout":n instanceof Error?n.message:"unexpected_verify_error"}}}async settlePayment(t,r){try{let n=W(t),i=await this.fetchWithRetry(`${this.facilitatorUrl}/settle`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:n,paymentRequirements:r})});return i.ok?{...await i.json(),network:r.network}:{success:!1,network:r.network,errorReason:`facilitator_error_${i.status}`}}catch(n){let i=n instanceof j?`facilitator_error_${n.status}`:n instanceof Error&&n.name==="AbortError"?"facilitator_timeout":n instanceof Error?n.message:"unexpected_settle_error";return{success:!1,network:r.network,errorReason:i}}}};function Ht(e){if(Pe(e))return{address:Ee,decimals:6};let t=at[e];if(t){let r=ct[t]?.decimals??6;return{address:t,decimals:r}}return{address:Ee,decimals:6}}function lt(e){try{let t=W(e);return t?.accepted?.amount??t?.accepted?.maxAmountRequired}catch{return}}function X(e){let{payTo:t,facilitatorUrl:r=F,network:n=N,defaultTimeoutSeconds:i=60}=e,s=e.asset??Ht(n),h=e.scheme??"exact";if(h==="tab"&&!Pe(n))throw new Error(`scheme 'tab' is SVM-only; got network "${n}"`);let c=new Te(r),a=null,m=new Map,l=3e4,o=Date.now();function y(u){let g=(u.maxTimeoutSeconds||i)*1e3;if(m.set(u.payTo,{accept:u,expiresAt:Date.now()+g}),Date.now()-o>l){let A=Date.now();for(let[C,U]of m)U.expiresAt<A&&m.delete(C);o=A}}function d(u){let g=m.get(u);if(g){if(g.expiresAt<Date.now()){m.delete(u);return}return g.accept}}async function f(u){return typeof t=="string"?t:t(u||{})}async function b(){if(a||(a=await c.getNetworkExtra(n)),Pe(n)&&!a?.feePayer)throw new Error(`Facilitator does not provide feePayer for network "${n}"`);return{...a?.feePayer?{feePayer:a.feePayer}:{},decimals:a?.decimals??s.decimals,name:a?.name,version:a?.version,...h==="batch-settlement"&&a?.receiverAuthorizer?{receiverAuthorizer:a.receiverAuthorizer}:{},...h==="tab"?{voucherHeader:"x-tab-voucher",registrationEncoding:"base64(188-byte sessionRegisterMessage)"}:{}}}async function D(u,g){let{amountAtomic:A,timeoutSeconds:C=i}=g,U=await b(),O={scheme:h,network:n,amount:A,maxAmountRequired:A,asset:s.address,payTo:u,maxTimeoutSeconds:C,extra:U};return y(O),O}async function z(u){let g=await f({amountAtomic:u.amountAtomic,resourceUrl:u.resourceUrl});return D(g,u)}async function _e(u){let{resourceUrl:g,description:A,mimeType:C="application/json"}=u,U={url:g,description:A,mimeType:C},O=await z(u);return{x402Version:2,resource:U,accepts:[O],error:"Payment required"}}function H(u){return Re(u)}function J(u){return{status:402,headers:{"PAYMENT-REQUIRED":H(u)},body:{}}}async function ke(u,g){if(!g){let A=await f({paymentHeader:u});g=d(A),g||(g=await D(A,{amountAtomic:lt(u)??"0",resourceUrl:""}))}return c.verifyPayment(u,g)}async function G(u,g){if(!g){let A=await f({paymentHeader:u});g=d(A),g||(g=await D(A,{amountAtomic:lt(u)??"0",resourceUrl:""}))}return c.settlePayment(u,g)}return{buildRequirements:_e,encodeRequirements:H,create402Response:J,verifyPayment:ke,settlePayment:G,getPaymentAccept:z,network:n,assetDecimals:s.decimals,facilitator:c}}var qt={"solana:mainnet":N};function mt(e){let t=qt[e.network];if(!t)throw new Error(`tabChallengeMiddleware: unsupported network "${e.network}"`);let r=typeof e.sellerPubkey=="string"?e.sellerPubkey:e.sellerPubkey.toBase58();new ut.PublicKey(r);let n=X({payTo:r,network:t,scheme:"tab",facilitatorUrl:e.facilitatorUrl}),i=P(e.perUnit);return async(s,h,c)=>{if(s.headers[I])return c();try{let a=`${s.protocol}://${s.get("host")}${s.originalUrl}`,m=await n.buildRequirements({amountAtomic:i,resourceUrl:a,description:e.description}),l=n.create402Response(m);h.set(l.headers).status(l.status).json(l.body)}catch(a){let m=a?.message??String(a);h.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:m})}}}var dt=require("@solana/web3.js");var Ft={"solana:mainnet":N};function pt(e){let t=Ft[e.network];if(!t)throw new Error(`tabOrExactMiddleware: unsupported network "${e.network}"`);let r=typeof e.sellerPubkey=="string"?e.sellerPubkey:e.sellerPubkey.toBase58();new dt.PublicKey(r);let n=X({payTo:r,network:t,scheme:"tab",facilitatorUrl:e.facilitatorUrl}),i=X({payTo:r,network:t,scheme:"exact",facilitatorUrl:e.facilitatorUrl}),s=P(e.perUnit),h=de({connection:e.connection,sellerPubkey:r,network:e.network,perUnit:e.perUnit,settle:"on-close",facilitatorUrl:e.facilitatorUrl,lockCadence:e.lockCadence});return async(c,a,m)=>{if(c.headers[I])return h(c,a,m);let l=`${c.protocol}://${c.get("host")}${c.originalUrl}`,o=c.headers["payment-signature"];if(o){let y;try{y=await i.getPaymentAccept({amountAtomic:s,resourceUrl:l,description:e.description})}catch(d){let f=d?.message??String(d);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:f});return}try{let d=await i.verifyPayment(o,y);if(!d.isValid){a.status(402).json({error:"Payment verification failed",reason:d.invalidReason});return}let f=await i.settlePayment(o,y);if(!f.success){a.status(402).json({error:"Payment settlement failed",reason:f.errorReason});return}return c.x402={transaction:f.transaction,payer:d.payer??"",network:f.network||t},a.setHeader("PAYMENT-RESPONSE",Re({success:!0,transaction:f.transaction,network:f.network||t,payer:d.payer??""})),m()}catch{a.status(500).json({error:"Payment processing error"});return}}try{let y={amountAtomic:s,resourceUrl:l,description:e.description},[d,f]=await Promise.all([n.buildRequirements(y),i.buildRequirements(y)]),b={...d,accepts:[...d.accepts,...f.accepts]};a.set({"PAYMENT-REQUIRED":n.encodeRequirements(b)}).status(402).json({error:"Payment required",accepts:b.accepts,resource:b.resource})}catch(y){let d=y?.message??String(y);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:d})}}}0&&(module.exports={FileChannelLedger,FileVoucherStore,InMemoryChannelLedger,InMemoryVoucherStore,InvalidRegistrationError,InvalidVoucherError,InvalidVoucherSignatureError,OnChainVerificationError,RedisChannelLedger,ScopeViolationError,TAB_VOUCHER_HEADER,deserializeChannelLedgerEntry,enforceScope,openSse,parseRegistration,requireTab,serializeChannelLedgerEntry,tabChallengeMiddleware,tabMiddleware,tabOrExactMiddleware,verifyRegistrationOnChain,verifyVoucherSignature});
@@ -118,6 +118,23 @@ declare class InMemoryChannelLedger implements ChannelLedger {
118
118
  tryAcquireLease(channelId: string, ttlMs: number): Promise<boolean>;
119
119
  releaseLease(channelId: string): Promise<void>;
120
120
  }
121
+ interface SerializedEntry {
122
+ lastVoucher: {
123
+ payload: SignedVoucher['payload'];
124
+ sessionPublicKey: string;
125
+ sessionRegistration: string;
126
+ sessionSignature: string;
127
+ } | null;
128
+ deliveredCumulativeAtomic: AtomicAmount;
129
+ lastCrystallizedCumulativeAtomic?: AtomicAmount;
130
+ gateRefusedCumulativeAtomic?: AtomicAmount;
131
+ onChain?: OnChainLedgerSnapshot;
132
+ lease?: {
133
+ heldUntilUnixMs: number;
134
+ };
135
+ }
136
+ declare function serializeChannelLedgerEntry(entry: ChannelLedgerEntry): SerializedEntry;
137
+ declare function deserializeChannelLedgerEntry(s: SerializedEntry): ChannelLedgerEntry;
121
138
  declare class FileChannelLedger implements ChannelLedger {
122
139
  private readonly dir;
123
140
  constructor(dir: string);
@@ -263,6 +280,57 @@ declare class InvalidVoucherError extends Error {
263
280
  constructor(reason: 'signature_invalid' | 'registration_invalid' | 'cap_exceeded' | 'session_expired' | 'wrong_counterparty' | 'non_monotonic' | 'channel_busy', detail?: string);
264
281
  }
265
282
 
283
+ /**
284
+ * Redis-backed ChannelLedger — the multi-process production ledger the
285
+ * ChannelLedger interface docs call for ("Redis SETNX"): revenue state
286
+ * survives restarts, and the single-stream lease is atomic ACROSS processes.
287
+ *
288
+ * Zero new dependencies: the constructor takes a structural `RedisLikeClient`
289
+ * (ioredis satisfies it) instead of importing a Redis library. Sellers pass
290
+ * their own client, configured to their taste — with two hard requirements:
291
+ *
292
+ * 1. FAIL-FAST client: disable unbounded offline queueing
293
+ * (`enableOfflineQueue: false` on ioredis). A Redis outage must surface
294
+ * as a thrown ledger error the seller can terminate a stream on — never
295
+ * an indefinite hang inside the payment path.
296
+ * 2. NO EVICTION on the keyspace holding these entries
297
+ * (`maxmemory-policy noeviction`, or a dedicated logical DB). Ledger
298
+ * entries are revenue state; an evicted entry silently re-grants
299
+ * delivered budget.
300
+ *
301
+ * Key layout (prefix configurable):
302
+ * <prefix>ledger:<channelId> — serialized entry, NO TTL (durable until the
303
+ * seller's end-of-life sweep deletes it)
304
+ * <prefix>lease:<channelId> — single-stream lease, PX = leaseTtlMs,
305
+ * value = per-acquire random token
306
+ *
307
+ * Lease semantics: acquire is SET NX PX (atomic across processes); release is
308
+ * a compare-and-delete Lua script on the acquire token, so an instance that
309
+ * lost its lease to TTL expiry can never delete the next holder's lease.
310
+ */
311
+
312
+ /** Structural subset of a Redis client (ioredis satisfies this). */
313
+ interface RedisLikeClient {
314
+ get(key: string): Promise<string | null>;
315
+ set(key: string, value: string, ...args: Array<string | number>): Promise<unknown>;
316
+ del(...keys: string[]): Promise<number>;
317
+ eval(script: string, numKeys: number, ...args: Array<string | number>): Promise<unknown>;
318
+ }
319
+ declare class RedisChannelLedger implements ChannelLedger {
320
+ private readonly client;
321
+ private readonly keyPrefix;
322
+ /** Tokens for leases THIS instance holds; release only compares-and-deletes its own. */
323
+ private readonly leaseTokens;
324
+ constructor(client: RedisLikeClient, keyPrefix?: string);
325
+ private ledgerKey;
326
+ private leaseKey;
327
+ get(channelId: string): Promise<ChannelLedgerEntry | null>;
328
+ set(channelId: string, entry: ChannelLedgerEntry): Promise<void>;
329
+ delete(channelId: string): Promise<void>;
330
+ tryAcquireLease(channelId: string, ttlMs: number): Promise<boolean>;
331
+ releaseLease(channelId: string): Promise<void>;
332
+ }
333
+
266
334
  /**
267
335
  * Express middleware for accepting OTS tab vouchers.
268
336
  *
@@ -553,4 +621,4 @@ interface TabOrExactConfig {
553
621
  }
554
622
  declare function tabOrExactMiddleware(config: TabOrExactConfig): RequestHandler;
555
623
 
556
- export { type ChannelLedger, type ChannelLedgerEntry, FileChannelLedger, FileVoucherStore, InMemoryChannelLedger, InMemoryVoucherStore, InvalidRegistrationError, InvalidVoucherError, InvalidVoucherSignatureError, type OnChainLedgerSnapshot, OnChainVerificationError, type OpenSseOptions, type ParsedRegistration, ScopeViolationError, type SellerTab, type SseMeter, TAB_VOUCHER_HEADER, type TabChallengeConfig, type TabMiddlewareConfig, type TabMiddlewareOptions, type TabOrExactConfig, type VoucherStore, enforceScope, openSse, parseRegistration, requireTab, tabChallengeMiddleware, tabMiddleware, tabOrExactMiddleware, verifyRegistrationOnChain, verifyVoucherSignature };
624
+ export { type ChannelLedger, type ChannelLedgerEntry, FileChannelLedger, FileVoucherStore, InMemoryChannelLedger, InMemoryVoucherStore, InvalidRegistrationError, InvalidVoucherError, InvalidVoucherSignatureError, type OnChainLedgerSnapshot, OnChainVerificationError, type OpenSseOptions, type ParsedRegistration, RedisChannelLedger, type RedisLikeClient, ScopeViolationError, type SellerTab, type SerializedEntry, type SseMeter, TAB_VOUCHER_HEADER, type TabChallengeConfig, type TabMiddlewareConfig, type TabMiddlewareOptions, type TabOrExactConfig, type VoucherStore, deserializeChannelLedgerEntry, enforceScope, openSse, parseRegistration, requireTab, serializeChannelLedgerEntry, tabChallengeMiddleware, tabMiddleware, tabOrExactMiddleware, verifyRegistrationOnChain, verifyVoucherSignature };
@@ -118,6 +118,23 @@ declare class InMemoryChannelLedger implements ChannelLedger {
118
118
  tryAcquireLease(channelId: string, ttlMs: number): Promise<boolean>;
119
119
  releaseLease(channelId: string): Promise<void>;
120
120
  }
121
+ interface SerializedEntry {
122
+ lastVoucher: {
123
+ payload: SignedVoucher['payload'];
124
+ sessionPublicKey: string;
125
+ sessionRegistration: string;
126
+ sessionSignature: string;
127
+ } | null;
128
+ deliveredCumulativeAtomic: AtomicAmount;
129
+ lastCrystallizedCumulativeAtomic?: AtomicAmount;
130
+ gateRefusedCumulativeAtomic?: AtomicAmount;
131
+ onChain?: OnChainLedgerSnapshot;
132
+ lease?: {
133
+ heldUntilUnixMs: number;
134
+ };
135
+ }
136
+ declare function serializeChannelLedgerEntry(entry: ChannelLedgerEntry): SerializedEntry;
137
+ declare function deserializeChannelLedgerEntry(s: SerializedEntry): ChannelLedgerEntry;
121
138
  declare class FileChannelLedger implements ChannelLedger {
122
139
  private readonly dir;
123
140
  constructor(dir: string);
@@ -263,6 +280,57 @@ declare class InvalidVoucherError extends Error {
263
280
  constructor(reason: 'signature_invalid' | 'registration_invalid' | 'cap_exceeded' | 'session_expired' | 'wrong_counterparty' | 'non_monotonic' | 'channel_busy', detail?: string);
264
281
  }
265
282
 
283
+ /**
284
+ * Redis-backed ChannelLedger — the multi-process production ledger the
285
+ * ChannelLedger interface docs call for ("Redis SETNX"): revenue state
286
+ * survives restarts, and the single-stream lease is atomic ACROSS processes.
287
+ *
288
+ * Zero new dependencies: the constructor takes a structural `RedisLikeClient`
289
+ * (ioredis satisfies it) instead of importing a Redis library. Sellers pass
290
+ * their own client, configured to their taste — with two hard requirements:
291
+ *
292
+ * 1. FAIL-FAST client: disable unbounded offline queueing
293
+ * (`enableOfflineQueue: false` on ioredis). A Redis outage must surface
294
+ * as a thrown ledger error the seller can terminate a stream on — never
295
+ * an indefinite hang inside the payment path.
296
+ * 2. NO EVICTION on the keyspace holding these entries
297
+ * (`maxmemory-policy noeviction`, or a dedicated logical DB). Ledger
298
+ * entries are revenue state; an evicted entry silently re-grants
299
+ * delivered budget.
300
+ *
301
+ * Key layout (prefix configurable):
302
+ * <prefix>ledger:<channelId> — serialized entry, NO TTL (durable until the
303
+ * seller's end-of-life sweep deletes it)
304
+ * <prefix>lease:<channelId> — single-stream lease, PX = leaseTtlMs,
305
+ * value = per-acquire random token
306
+ *
307
+ * Lease semantics: acquire is SET NX PX (atomic across processes); release is
308
+ * a compare-and-delete Lua script on the acquire token, so an instance that
309
+ * lost its lease to TTL expiry can never delete the next holder's lease.
310
+ */
311
+
312
+ /** Structural subset of a Redis client (ioredis satisfies this). */
313
+ interface RedisLikeClient {
314
+ get(key: string): Promise<string | null>;
315
+ set(key: string, value: string, ...args: Array<string | number>): Promise<unknown>;
316
+ del(...keys: string[]): Promise<number>;
317
+ eval(script: string, numKeys: number, ...args: Array<string | number>): Promise<unknown>;
318
+ }
319
+ declare class RedisChannelLedger implements ChannelLedger {
320
+ private readonly client;
321
+ private readonly keyPrefix;
322
+ /** Tokens for leases THIS instance holds; release only compares-and-deletes its own. */
323
+ private readonly leaseTokens;
324
+ constructor(client: RedisLikeClient, keyPrefix?: string);
325
+ private ledgerKey;
326
+ private leaseKey;
327
+ get(channelId: string): Promise<ChannelLedgerEntry | null>;
328
+ set(channelId: string, entry: ChannelLedgerEntry): Promise<void>;
329
+ delete(channelId: string): Promise<void>;
330
+ tryAcquireLease(channelId: string, ttlMs: number): Promise<boolean>;
331
+ releaseLease(channelId: string): Promise<void>;
332
+ }
333
+
266
334
  /**
267
335
  * Express middleware for accepting OTS tab vouchers.
268
336
  *
@@ -553,4 +621,4 @@ interface TabOrExactConfig {
553
621
  }
554
622
  declare function tabOrExactMiddleware(config: TabOrExactConfig): RequestHandler;
555
623
 
556
- export { type ChannelLedger, type ChannelLedgerEntry, FileChannelLedger, FileVoucherStore, InMemoryChannelLedger, InMemoryVoucherStore, InvalidRegistrationError, InvalidVoucherError, InvalidVoucherSignatureError, type OnChainLedgerSnapshot, OnChainVerificationError, type OpenSseOptions, type ParsedRegistration, ScopeViolationError, type SellerTab, type SseMeter, TAB_VOUCHER_HEADER, type TabChallengeConfig, type TabMiddlewareConfig, type TabMiddlewareOptions, type TabOrExactConfig, type VoucherStore, enforceScope, openSse, parseRegistration, requireTab, tabChallengeMiddleware, tabMiddleware, tabOrExactMiddleware, verifyRegistrationOnChain, verifyVoucherSignature };
624
+ export { type ChannelLedger, type ChannelLedgerEntry, FileChannelLedger, FileVoucherStore, InMemoryChannelLedger, InMemoryVoucherStore, InvalidRegistrationError, InvalidVoucherError, InvalidVoucherSignatureError, type OnChainLedgerSnapshot, OnChainVerificationError, type OpenSseOptions, type ParsedRegistration, RedisChannelLedger, type RedisLikeClient, ScopeViolationError, type SellerTab, type SerializedEntry, type SseMeter, TAB_VOUCHER_HEADER, type TabChallengeConfig, type TabMiddlewareConfig, type TabMiddlewareOptions, type TabOrExactConfig, type VoucherStore, deserializeChannelLedgerEntry, enforceScope, openSse, parseRegistration, requireTab, serializeChannelLedgerEntry, tabChallengeMiddleware, tabMiddleware, tabOrExactMiddleware, verifyRegistrationOnChain, verifyVoucherSignature };
@@ -1,6 +1,6 @@
1
- var x=class extends Error{constructor(r,n){super(`Invalid voucher: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="InvalidVoucherError"}};import{promises as K}from"fs";import{join as Xe,dirname as Je}from"path";var Oe=new Map;function T(e,t){let n=(Oe.get(e)??Promise.resolve()).then(()=>t(),()=>t());return Oe.set(e,n.then(()=>{},()=>{})),n}var M=class{map=new Map;async get(t){return this.map.get(t)??null}async set(t,r){this.map.set(t,r)}async delete(t){this.map.delete(t)}async tryAcquireLease(t,r){return T(t,async()=>{let n=this.map.get(t),i=Date.now();if(n?.lease&&n.lease.heldUntilUnixMs>i)return!1;let s=n??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return this.map.set(t,{...s,lease:{heldUntilUnixMs:i+r}}),!0})}async releaseLease(t){await T(t,async()=>{let r=this.map.get(t);r&&this.map.set(t,{...r,lease:void 0})})}};function de(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}function pe(e){if(e.length%2!==0)throw new Error(`hex length must be even, got ${e.length}`);let t=new Uint8Array(e.length/2);for(let r=0;r<t.length;r++)t[r]=parseInt(e.substr(r*2,2),16);return t}function Ge(e){return{lastVoucher:e.lastVoucher?{payload:e.lastVoucher.payload,sessionPublicKey:de(e.lastVoucher.sessionPublicKey),sessionRegistration:de(e.lastVoucher.sessionRegistration),sessionSignature:de(e.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:e.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:e.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:e.gateRefusedCumulativeAtomic,onChain:e.onChain,lease:e.lease}}function Ye(e){return{lastVoucher:e.lastVoucher?{payload:e.lastVoucher.payload,sessionPublicKey:pe(e.lastVoucher.sessionPublicKey),sessionRegistration:pe(e.lastVoucher.sessionRegistration),sessionSignature:pe(e.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:e.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:e.lastCrystallizedCumulativeAtomic??"0",gateRefusedCumulativeAtomic:e.gateRefusedCumulativeAtomic,onChain:e.onChain,lease:e.lease}}var ge=class{constructor(t){this.dir=t}pathFor(t){if(!/^[a-z0-9_-]+$/i.test(t))throw new Error(`unsafe channelId for filesystem: ${t}`);return Xe(this.dir,`${t}.json`)}async get(t){try{let r=await K.readFile(this.pathFor(t),"utf8");return Ye(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(t,r){let n=this.pathFor(t);await K.mkdir(Je(n),{recursive:!0});let i=`${n}.tmp`;await K.writeFile(i,JSON.stringify(Ge(r))),await K.rename(i,n)}async delete(t){try{await K.unlink(this.pathFor(t))}catch(r){if(r?.code!=="ENOENT")throw r}}async tryAcquireLease(t,r){return T(t,async()=>{let n=await this.get(t),i=Date.now();if(n?.lease&&n.lease.heldUntilUnixMs>i)return!1;let s=n??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return await this.set(t,{...s,lease:{heldUntilUnixMs:i+r}}),!0})}async releaseLease(t){await T(t,async()=>{let r=await this.get(t);r&&await this.set(t,{...r,lease:void 0})})}};import{PublicKey as ot}from"@solana/web3.js";import Ze from"tweetnacl";import{sha256 as jt}from"@noble/hashes/sha256";import{p256 as Jt}from"@noble/curves/p256";import{PublicKey as fe}from"@solana/web3.js";import{sessionRegisterMessage as kt,sessionRevokeMessage as Ut,voucherPayloadMessage as he,buildVoucherMessage as Ot}from"@dexterai/vault/messages";import{buildRegisterSessionKeyInstruction as Bt,buildRevokeSessionKeyInstruction as Lt,deriveSwigWalletAddress as Kt}from"@dexterai/vault/instructions";import{buildSecp256r1VerifyInstruction as Dt}from"@dexterai/vault/precompile";import{DEXTER_VAULT_PROGRAM_ID as ye,SECP256R1_PROGRAM_ID as Ht,INSTRUCTIONS_SYSVAR_ID as qt}from"@dexterai/vault/constants";import{fetchSessionAccount as Qe,isSessionLive as et}from"@dexterai/vault/session";var Ae="OTS_SESSION_REGISTER_V2",E=class extends Error{constructor(r,n){super(`Invalid registration: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="InvalidRegistrationError"}};function be(e){if(e.length!==188)throw new E("wrong_length",`expected 188, got ${e.length}`);let t=new TextDecoder().decode(e.slice(0,Ae.length));if(t!==Ae)throw new E("wrong_domain",`got "${t}"`);for(let y=Ae.length;y<32;y++)if(e[y]!==0)throw new E("wrong_domain",`non-NUL padding at byte ${y}`);let r=new DataView(e.buffer,e.byteOffset,e.byteLength),n=new fe(e.slice(32,64)),i=new fe(e.slice(64,96)),s=e.slice(96,128),h=r.getBigUint64(128,!0),c=r.getBigInt64(136,!0),a=new fe(e.slice(144,176)),m=r.getUint32(176,!0),l=r.getBigUint64(180,!0);if(!n.equals(ye))throw new E("wrong_program",`${n.toBase58()} is not ${ye.toBase58()}`);if(h===0n)throw new E("cap_zero");let o=BigInt(Math.floor(Date.now()/1e3));if(c<=o)throw new E("expiry_in_past",`expires_at=${c}, now=${o}`);return{programId:n,vaultPda:i,sessionPubkey:new Uint8Array(s),maxAmount:h,expiresAt:c,allowedCounterparty:a,nonce:m,maxRevolvingCapacity:l}}var N=class extends Error{constructor(r,n){super(`On-chain verification failed: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="OnChainVerificationError"}};async function ve(e,t){let r=await Qe(e,t.vaultPda,t.allowedCounterparty);if(!r||r.version===0)throw new N("session_not_active","no live SessionAccount PDA for this (vault, counterparty) \u2014 revoked, expiry-swept, or never registered");if(!et(r))throw new N("session_not_active","SessionAccount PDA is present but expired");if(!tt(r.session.sessionPubkey,t.sessionPubkey))throw new N("session_pubkey_mismatch",`on-chain ${$e(r.session.sessionPubkey)} != registration ${$e(t.sessionPubkey)}`);let n=r.session.spent,i=r.session.crystallizedCumulative;return{frontierAtomic:(n>i?n:i).toString(),spentAtomic:n.toString(),crystallizedCumulativeAtomic:i.toString()}}var _=class extends Error{constructor(t){super(`Invalid voucher signature${t?`: ${t}`:""}`),this.name="InvalidVoucherSignatureError"}};function we(e,t){if(t.length!==32)throw new _(`channelIdBytes must be 32 bytes, got ${t.length}`);if(e.sessionPublicKey.length!==32)throw new _(`sessionPublicKey must be 32 bytes, got ${e.sessionPublicKey.length}`);if(e.sessionSignature.length!==64)throw new _(`sessionSignature must be 64 bytes, got ${e.sessionSignature.length}`);let r=he({channelId:t,cumulativeAmount:BigInt(e.payload.cumulativeAmount),sequenceNumber:e.payload.sequenceNumber});if(!Ze.sign.detached.verify(r,e.sessionSignature,e.sessionPublicKey))throw new _("ed25519 verify rejected")}var C=class extends Error{constructor(r,n){super(`Scope violation: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="ScopeViolationError"}};function Se(e){let t=BigInt(e.voucher.payload.cumulativeAmount);if(t>e.registration.maxAmount)throw new C("cumulative_exceeds_cap",`${t} > ${e.registration.maxAmount}`);let r=BigInt(Math.floor(Date.now()/1e3));if(r>=e.registration.expiresAt)throw new C("session_expired",`now=${r} >= expiresAt=${e.registration.expiresAt}`);if(!e.registration.allowedCounterparty.equals(e.expectedCounterparty))throw new C("wrong_counterparty",`${e.registration.allowedCounterparty.toBase58()} != ${e.expectedCounterparty.toBase58()}`);if(e.previousCumulativeAtomic!==void 0){let n=BigInt(e.previousCumulativeAtomic);if(t<=n)throw new C("non_monotonic",`cumulative=${t} not > previous=${n}`)}}function tt(e,t){if(e.length!==t.length)return!1;for(let r=0;r<e.length;r++)if(e[r]!==t[r])return!1;return!0}function $e(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}import{PublicKey as gr}from"@solana/web3.js";import{bytesToHex as yr}from"@noble/hashes/utils";import ir from"tweetnacl";import{sha256 as ar}from"@noble/hashes/sha256";var Ve="https://x402.dexter.cash",Be=6;function R(e,t=Be){if(!/^\d+(\.\d+)?$/.test(e))throw new Error(`amount must be a non-negative decimal string, got "${e}"`);let[r,n=""]=e.split(".");if(n.length>t)throw new Error(`amount "${e}" has more than ${t} decimals`);let i=n.padEnd(t,"0"),s=`${r}${i}`.replace(/^0+(?=\d)/,"");return s===""?"0":s}function O(e,t=Be){if(!/^\d+$/.test(e))throw new Error(`atomic must be a non-negative integer string, got "${e}"`);let r=e.padStart(t+1,"0"),n=r.slice(0,-t).replace(/^0+(?=\d)/,"")||"0",i=r.slice(-t).replace(/0+$/,"");return i?`${n}.${i}`:n}import{bytesToHex as xe}from"@noble/hashes/utils";var rt=15e3,nt=["claim_already_exists","non_monotonic_cumulative"],it="below_lock_cadence";function J(e){return typeof e=="string"&&e.includes(it)}function st(e){return`${e.slice(0,16)}\u2026`}function Le(e,t,r,n){let i=st(e);if(n.crystallized){console.info(`[tab/seller] crystallize OK channel=${i} cumulative=${t} seq=${r}${n.claimPda?` claimPda=${n.claimPda}`:""} \u2014 LockVoucher landed`);return}if(n.error){if(J(n.error)){console.warn(`[tab/seller] crystallize refused below the facilitator's cadence gate channel=${i} cumulative=${t} seq=${r}: ${n.error} \u2014 benign: this facilitator's cadence engine owns the protection cadence for the span; gate-refused watermark advanced, re-attempts after the next signed voucher`);return}if(nt.some(s=>n.error.includes(s))){console.warn(`[tab/seller] crystallize duplicate channel=${i} cumulative=${t} seq=${r}: ${n.error} \u2014 voucher already secured on-chain (benign, no action)`);return}console.error(`[tab/seller] crystallize FAILED channel=${i} cumulative=${t} seq=${r}: ${n.error} \u2014 lock NOT secured (degraded: best-effort path, no watermark advance, retries at next threshold/close; seller exposure stays unsecured until it lands)`)}}async function Ce(e,t,r,n,i=fetch){let s=e.lastVoucher;if(!s)return{crystallized:!1};if(s.payload.channelId!==t){let c={crystallized:!1,error:"channel_id_mismatch"};return Le(t,s.payload.cumulativeAmount,s.payload.sequenceNumber,c),c}let h=c=>(Le(t,s.payload.cumulativeAmount,s.payload.sequenceNumber,c),c);try{let c=`${r.replace(/\/$/,"")}/tab/lock`,a={channelId:s.payload.channelId,cumulativeAmount:s.payload.cumulativeAmount,sequenceNumber:s.payload.sequenceNumber,sessionPublicKey:xe(s.sessionPublicKey),sessionSignature:xe(s.sessionSignature),sessionRegistration:xe(s.sessionRegistration),network:n},m=await i(c,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(a),signal:AbortSignal.timeout(rt)}),l=await m.text();if(!m.ok)return h({crystallized:!1,error:`tab lock ${m.status}: ${l.slice(0,200)}`});let o;try{let y=JSON.parse(l);y&&typeof y.claimPda=="string"&&(o=y.claimPda)}catch{}return h({crystallized:!0,claimPda:o})}catch(c){return h({crystallized:!1,error:String(c?.message??c)})}}async function Ke(e,t,r,n,i,s={}){let h=BigInt(e.deliveredCumulativeAtomic),c=BigInt(e.lastCrystallizedCumulativeAtomic??"0"),a=BigInt(i.thresholdAtomic);if(h-c<a)return{crystallized:!1};let m=e.lastVoucher?.payload.cumulativeAmount,l=e.gateRefusedCumulativeAtomic;if(m!==void 0&&l!==void 0&&BigInt(m)<=BigInt(l))return{crystallized:!1};let o=await Ce(e,t,r,n,s.fetchImpl);return o.crystallized&&m!==void 0?(e.lastCrystallizedCumulativeAtomic=m,e.gateRefusedCumulativeAtomic=void 0):J(o.error)&&m!==void 0&&(e.gateRefusedCumulativeAtomic=m),o}var $="x-tab-voucher",Ee=class{map=new Map;get(t){return this.map.get(t)}set(t,r){this.map.set(t,r)}update(t,r){let n=this.map.get(t);n&&(n.lastCumulativeAtomic=r)}delete(t){this.map.delete(t)}},Re=class{constructor(t,r,n,i,s,h){this.recordDeliveredImpl=s;this.chargeImpl=h;this.channelId=t,this.network=r,this.cumulativeAtomic=n,this.deliveredBaselineAtomic=i}channelId;network;sessionPublicKey=null;cumulativeAtomic;deliveredBaselineAtomic;cumulative(){return O(this.cumulativeAtomic.toString())}deliveredCumulative(){return O(this.deliveredBaselineAtomic.toString())}async recordDelivered(t){return this.recordDeliveredImpl(t)}bumpCumulative(t){this.cumulativeAtomic=t}setSessionPublicKey(t){this.sessionPublicKey=t}async charge(t){return this.chargeImpl(t)}};function at(e){if(typeof e!="string"||e.length===0)throw new x("signature_invalid",`missing ${$} header`);let t;try{t=Buffer.from(e,"base64").toString("utf8")}catch{throw new x("signature_invalid","malformed base64")}let r;try{r=JSON.parse(t)}catch{throw new x("signature_invalid","malformed JSON")}if(!r||typeof r!="object"||!r.payload||!r.sessionPublicKey)throw new x("signature_invalid","missing required fields");return{payload:r.payload,sessionPublicKey:G(r.sessionPublicKey),sessionRegistration:G(r.sessionRegistration),sessionSignature:G(r.sessionSignature)}}function G(e){if(typeof e!="string"||e.length%2!==0)throw new x("signature_invalid",`bad hex: ${typeof e}`);let t=new Uint8Array(e.length/2);for(let r=0;r<t.length;r++)t[r]=parseInt(e.substr(r*2,2),16);return t}function ct(e){if(!/^[0-9a-f]{64}$/i.test(e))throw new x("signature_invalid",`channelId must be 64-char hex, got "${e}"`);return G(e)}function Pe(e){let t=e.ledger??new M,r=new Ee,n=typeof e.sellerPubkey=="string"?new ot(e.sellerPubkey):e.sellerPubkey,i=e.maxPerVoucherAtomic?BigInt(e.maxPerVoucherAtomic):BigInt(R(e.perUnit))*100n,s=e.facilitatorUrl??Ve,h={thresholdAtomic:e.lockCadence?.thresholdAtomic??R("0.10"),onClose:e.lockCadence?.onClose??!0};return async(c,a,m)=>{try{let l=at(c.headers[$]),o=l.payload.channelId,y=ct(o),d=r.get(o),f=null;if(!d){let p=be(l.sessionRegistration);f=(await ve(e.connection,p))?.frontierAtomic??null;let v=await t.get(o);d={registration:p,lastCumulativeAtomic:v?.lastVoucher?.payload.cumulativeAmount??"0"},r.set(o,d)}we(l,y),Se({registration:d.registration,voucher:l,expectedCounterparty:n,previousCumulativeAtomic:d.lastCumulativeAtomic});let b=BigInt(l.payload.cumulativeAmount),V=BigInt(d.lastCumulativeAtomic),B=b-V;if(B>i)throw new C("cumulative_exceeds_cap",`single voucher increment ${B} exceeds maxPerVoucherAtomic ${i}`);let ue=e.leaseTtlMs??3e5;if(!await t.tryAcquireLease(o,ue))throw new x("channel_busy","another stream is live on this channel; tabs serve one stream at a time");let L=!1,j=()=>{L||(L=!0,t.releaseLease(o).catch(p=>{console.error("[tab/seller] failed to release channel lease:",p)}))};a.on("close",j),a.on("finish",j);let me=async p=>{let P=p.lastCrystallizedCumulativeAtomic??"0",v=p.gateRefusedCumulativeAtomic;await Ke(p,o,s,e.network,h),(p.lastCrystallizedCumulativeAtomic!==P||p.gateRefusedCumulativeAtomic!==v)&&await T(o,async()=>{let w=await t.get(o);w&&await t.set(o,{...w,lastCrystallizedCumulativeAtomic:p.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:p.gateRefusedCumulativeAtomic})}).catch(w=>{console.error(`[tab/seller] crystallize watermark persist FAILED channel=${o.slice(0,16)}\u2026 (expect a benign duplicate/below-cadence warn on the next request):`,w)})},X=!1,u=()=>{!h.onClose||X||(X=!0,(async()=>{let p=await t.get(o);if(!p||!p.lastVoucher)return;let P=p.lastVoucher.payload.cumulativeAmount;if(p.gateRefusedCumulativeAtomic!==void 0&&BigInt(P)<=BigInt(p.gateRefusedCumulativeAtomic))return;let v=await Ce(p,o,s,e.network);v.crystallized?await T(o,async()=>{let w=await t.get(o);w&&await t.set(o,{...w,lastCrystallizedCumulativeAtomic:P,gateRefusedCumulativeAtomic:void 0})}):J(v.error)&&await T(o,async()=>{let w=await t.get(o);w&&await t.set(o,{...w,gateRefusedCumulativeAtomic:P})})})().catch(p=>{console.error(`[tab/seller] close-path crystallize CRASHED channel=${o.slice(0,16)}\u2026 (final voucher NOT locked; exposure unsecured until the next request retries):`,p)}))};a.on("close",u),a.on("finish",u);let g=await t.get(o),A=!g?.lastVoucher&&BigInt(g?.deliveredCumulativeAtomic??"0")===0n,S=f!==null&&A&&BigInt(f)>0n?f:null;S!==null&&console.info(`[tab/seller] channel ${o.slice(0,16)}\u2026 resumed: seeding delivered baseline from chain frontier ${S} (session already settled/locked up to it \u2014 that span is not deliverable budget)`);let k=S!==null?BigInt(S):g?BigInt(g.deliveredCumulativeAtomic):0n;await T(o,async()=>{let p=await t.get(o);await t.set(o,{...p,lastVoucher:l,deliveredCumulativeAtomic:S??(p?p.deliveredCumulativeAtomic:"0"),lastCrystallizedCumulativeAtomic:S??p?.lastCrystallizedCumulativeAtomic??"0"})}),r.update(o,l.payload.cumulativeAmount);let U=new Re(o,e.network,b,k,async p=>{let P=null;await T(o,async()=>{let v=await t.get(o),w=v?BigInt(v.deliveredCumulativeAtomic):0n,ke=BigInt(p),je=ke>0n?w+ke:w,Ue={...v,lastVoucher:v?.lastVoucher??l,deliveredCumulativeAtomic:je.toString(),lastCrystallizedCumulativeAtomic:v?.lastCrystallizedCumulativeAtomic??"0"};await t.set(o,Ue),P=Ue}),P&&me(P).catch(v=>{console.error(`[tab/seller] crystallize cadence CRASHED channel=${o.slice(0,16)}\u2026 (threshold lock not attempted; retries at the next delivery):`,v)})},async p=>{throw new Error("SellerTab.charge() is not driven by the route handler; the buyer presents a fresh voucher per chunk. Use openSse(res, tab) for the metered-stream pattern.")});U.setSessionPublicKey(l.sessionPublicKey),c.tab=U,m()}catch(l){if(l instanceof x||l instanceof E||l instanceof N||l instanceof _||l instanceof C){a.status(402).json({error:"invalid_voucher",reason:l.reason??"unknown",detail:l.message});return}m(l)}}}function lt(e){if(!e.tab)throw new Error("req.tab is missing \u2014 did tabMiddleware run on this route?");return e.tab}function ut(e,t){if(!t.tab)throw new Error("openSse requires options.tab");e.headersSent||(e.setHeader("Content-Type","text/event-stream"),e.setHeader("Cache-Control","no-cache"),e.setHeader("Connection","keep-alive"),typeof e.flushHeaders=="function"&&e.flushHeaders());let r=t.tab,n=BigInt(R(r.cumulative())),i=BigInt(R(r.deliveredCumulative())),s=n-i;s<0n&&(s=0n);let h=t.perUnit?BigInt(R(t.perUnit)):null,c=0n,a=!1;async function m(){await r.recordDelivered(c.toString())}e.on("close",()=>{a||(a=!0,m().catch(d=>{console.error("[tab/seller] terminal persist failed on disconnect:",d)}))});async function l(d=1){if(a)throw new Error("meter ended");if(h===null)throw new Error("charge() needs options.perUnit");let f=h*BigInt(d),b=c+f;if(b>s)throw a=!0,await m(),new C("cumulative_exceeds_cap",`chunk would push delivered to ${O((i+b).toString())} beyond signed cumulative ${O(n.toString())} (per-request budget ${O(s.toString())})`);c=b}function o(d){if(a)throw new Error("meter ended");let b=(typeof d=="string"?d:Buffer.from(d).toString("utf8")).replace(/\n/g,"\\n");e.write(`data: ${b}
1
+ var x=class extends Error{constructor(r,n){super(`Invalid voucher: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="InvalidVoucherError"}};import{promises as K}from"fs";import{join as Qe,dirname as et}from"path";var Le=new Map;function T(t,e){let n=(Le.get(t)??Promise.resolve()).then(()=>e(),()=>e());return Le.set(t,n.then(()=>{},()=>{})),n}var M=class{map=new Map;async get(e){return this.map.get(e)??null}async set(e,r){this.map.set(e,r)}async delete(e){this.map.delete(e)}async tryAcquireLease(e,r){return T(e,async()=>{let n=this.map.get(e),i=Date.now();if(n?.lease&&n.lease.heldUntilUnixMs>i)return!1;let s=n??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return this.map.set(e,{...s,lease:{heldUntilUnixMs:i+r}}),!0})}async releaseLease(e){await T(e,async()=>{let r=this.map.get(e);r&&this.map.set(e,{...r,lease:void 0})})}};function de(t){let e="";for(let r of t)e+=r.toString(16).padStart(2,"0");return e}function pe(t){if(t.length%2!==0)throw new Error(`hex length must be even, got ${t.length}`);let e=new Uint8Array(t.length/2);for(let r=0;r<e.length;r++)e[r]=parseInt(t.substr(r*2,2),16);return e}function he(t){return Be(t)}function ye(t){return Ke(t)}function Be(t){return{lastVoucher:t.lastVoucher?{payload:t.lastVoucher.payload,sessionPublicKey:de(t.lastVoucher.sessionPublicKey),sessionRegistration:de(t.lastVoucher.sessionRegistration),sessionSignature:de(t.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:t.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:t.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:t.gateRefusedCumulativeAtomic,onChain:t.onChain,lease:t.lease}}function Ke(t){return{lastVoucher:t.lastVoucher?{payload:t.lastVoucher.payload,sessionPublicKey:pe(t.lastVoucher.sessionPublicKey),sessionRegistration:pe(t.lastVoucher.sessionRegistration),sessionSignature:pe(t.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:t.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:t.lastCrystallizedCumulativeAtomic??"0",gateRefusedCumulativeAtomic:t.gateRefusedCumulativeAtomic,onChain:t.onChain,lease:t.lease}}var ge=class{constructor(e){this.dir=e}pathFor(e){if(!/^[a-z0-9_-]+$/i.test(e))throw new Error(`unsafe channelId for filesystem: ${e}`);return Qe(this.dir,`${e}.json`)}async get(e){try{let r=await K.readFile(this.pathFor(e),"utf8");return Ke(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(e,r){let n=this.pathFor(e);await K.mkdir(et(n),{recursive:!0});let i=`${n}.tmp`;await K.writeFile(i,JSON.stringify(Be(r))),await K.rename(i,n)}async delete(e){try{await K.unlink(this.pathFor(e))}catch(r){if(r?.code!=="ENOENT")throw r}}async tryAcquireLease(e,r){return T(e,async()=>{let n=await this.get(e),i=Date.now();if(n?.lease&&n.lease.heldUntilUnixMs>i)return!1;let s=n??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return await this.set(e,{...s,lease:{heldUntilUnixMs:i+r}}),!0})}async releaseLease(e){await T(e,async()=>{let r=await this.get(e);r&&await this.set(e,{...r,lease:void 0})})}};import{randomUUID as tt}from"crypto";var rt='if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end',fe=class{constructor(e,r="tab:"){this.client=e;this.keyPrefix=r}leaseTokens=new Map;ledgerKey(e){return`${this.keyPrefix}ledger:${e}`}leaseKey(e){return`${this.keyPrefix}lease:${e}`}async get(e){let r=await this.client.get(this.ledgerKey(e));return r===null?null:ye(JSON.parse(r))}async set(e,r){let n=he({...r,lease:void 0});await this.client.set(this.ledgerKey(e),JSON.stringify(n))}async delete(e){this.leaseTokens.delete(e),await this.client.del(this.ledgerKey(e),this.leaseKey(e))}async tryAcquireLease(e,r){let n=tt();return await this.client.set(this.leaseKey(e),n,"PX",Math.max(1,Math.floor(r)),"NX")!=="OK"?!1:(this.leaseTokens.set(e,n),!0)}async releaseLease(e){let r=this.leaseTokens.get(e);r!==void 0&&(this.leaseTokens.delete(e),await this.client.eval(rt,1,this.leaseKey(e),r))}};import{PublicKey as mt}from"@solana/web3.js";import nt from"tweetnacl";import{sha256 as tr}from"@noble/hashes/sha256";import{p256 as nr}from"@noble/curves/p256";import{PublicKey as ve}from"@solana/web3.js";import{sessionRegisterMessage as Mt,sessionRevokeMessage as Dt,voucherPayloadMessage as Ae,buildVoucherMessage as zt}from"@dexterai/vault/messages";import{buildRegisterSessionKeyInstruction as Ft,buildRevokeSessionKeyInstruction as Wt,deriveSwigWalletAddress as jt}from"@dexterai/vault/instructions";import{buildSecp256r1VerifyInstruction as Jt}from"@dexterai/vault/precompile";import{DEXTER_VAULT_PROGRAM_ID as be,SECP256R1_PROGRAM_ID as Yt,INSTRUCTIONS_SYSVAR_ID as Zt}from"@dexterai/vault/constants";import{fetchSessionAccount as it,isSessionLive as st}from"@dexterai/vault/session";var we="OTS_SESSION_REGISTER_V2",E=class extends Error{constructor(r,n){super(`Invalid registration: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="InvalidRegistrationError"}};function Se(t){if(t.length!==188)throw new E("wrong_length",`expected 188, got ${t.length}`);let e=new TextDecoder().decode(t.slice(0,we.length));if(e!==we)throw new E("wrong_domain",`got "${e}"`);for(let y=we.length;y<32;y++)if(t[y]!==0)throw new E("wrong_domain",`non-NUL padding at byte ${y}`);let r=new DataView(t.buffer,t.byteOffset,t.byteLength),n=new ve(t.slice(32,64)),i=new ve(t.slice(64,96)),s=t.slice(96,128),h=r.getBigUint64(128,!0),c=r.getBigInt64(136,!0),a=new ve(t.slice(144,176)),m=r.getUint32(176,!0),l=r.getBigUint64(180,!0);if(!n.equals(be))throw new E("wrong_program",`${n.toBase58()} is not ${be.toBase58()}`);if(h===0n)throw new E("cap_zero");let o=BigInt(Math.floor(Date.now()/1e3));if(c<=o)throw new E("expiry_in_past",`expires_at=${c}, now=${o}`);return{programId:n,vaultPda:i,sessionPubkey:new Uint8Array(s),maxAmount:h,expiresAt:c,allowedCounterparty:a,nonce:m,maxRevolvingCapacity:l}}var N=class extends Error{constructor(r,n){super(`On-chain verification failed: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="OnChainVerificationError"}};async function xe(t,e){let r=await it(t,e.vaultPda,e.allowedCounterparty);if(!r||r.version===0)throw new N("session_not_active","no live SessionAccount PDA for this (vault, counterparty) \u2014 revoked, expiry-swept, or never registered");if(!st(r))throw new N("session_not_active","SessionAccount PDA is present but expired");if(!ot(r.session.sessionPubkey,e.sessionPubkey))throw new N("session_pubkey_mismatch",`on-chain ${Me(r.session.sessionPubkey)} != registration ${Me(e.sessionPubkey)}`);let n=r.session.spent,i=r.session.crystallizedCumulative;return{frontierAtomic:(n>i?n:i).toString(),spentAtomic:n.toString(),crystallizedCumulativeAtomic:i.toString()}}var _=class extends Error{constructor(e){super(`Invalid voucher signature${e?`: ${e}`:""}`),this.name="InvalidVoucherSignatureError"}};function Ce(t,e){if(e.length!==32)throw new _(`channelIdBytes must be 32 bytes, got ${e.length}`);if(t.sessionPublicKey.length!==32)throw new _(`sessionPublicKey must be 32 bytes, got ${t.sessionPublicKey.length}`);if(t.sessionSignature.length!==64)throw new _(`sessionSignature must be 64 bytes, got ${t.sessionSignature.length}`);let r=Ae({channelId:e,cumulativeAmount:BigInt(t.payload.cumulativeAmount),sequenceNumber:t.payload.sequenceNumber});if(!nt.sign.detached.verify(r,t.sessionSignature,t.sessionPublicKey))throw new _("ed25519 verify rejected")}var C=class extends Error{constructor(r,n){super(`Scope violation: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="ScopeViolationError"}};function Ee(t){let e=BigInt(t.voucher.payload.cumulativeAmount);if(e>t.registration.maxAmount)throw new C("cumulative_exceeds_cap",`${e} > ${t.registration.maxAmount}`);let r=BigInt(Math.floor(Date.now()/1e3));if(r>=t.registration.expiresAt)throw new C("session_expired",`now=${r} >= expiresAt=${t.registration.expiresAt}`);if(!t.registration.allowedCounterparty.equals(t.expectedCounterparty))throw new C("wrong_counterparty",`${t.registration.allowedCounterparty.toBase58()} != ${t.expectedCounterparty.toBase58()}`);if(t.previousCumulativeAtomic!==void 0){let n=BigInt(t.previousCumulativeAtomic);if(e<=n)throw new C("non_monotonic",`cumulative=${e} not > previous=${n}`)}}function ot(t,e){if(t.length!==e.length)return!1;for(let r=0;r<t.length;r++)if(t[r]!==e[r])return!1;return!0}function Me(t){let e="";for(let r of t)e+=r.toString(16).padStart(2,"0");return e}import{PublicKey as Sr}from"@solana/web3.js";import{bytesToHex as Cr}from"@noble/hashes/utils";import dr from"tweetnacl";import{sha256 as hr}from"@noble/hashes/sha256";var De="https://x402.dexter.cash",ze=6;function P(t,e=ze){if(!/^\d+(\.\d+)?$/.test(t))throw new Error(`amount must be a non-negative decimal string, got "${t}"`);let[r,n=""]=t.split(".");if(n.length>e)throw new Error(`amount "${t}" has more than ${e} decimals`);let i=n.padEnd(e,"0"),s=`${r}${i}`.replace(/^0+(?=\d)/,"");return s===""?"0":s}function O(t,e=ze){if(!/^\d+$/.test(t))throw new Error(`atomic must be a non-negative integer string, got "${t}"`);let r=t.padStart(e+1,"0"),n=r.slice(0,-e).replace(/^0+(?=\d)/,"")||"0",i=r.slice(-e).replace(/0+$/,"");return i?`${n}.${i}`:n}import{bytesToHex as Pe}from"@noble/hashes/utils";var at=15e3,ct=["claim_already_exists","non_monotonic_cumulative"],lt="below_lock_cadence";function J(t){return typeof t=="string"&&t.includes(lt)}function ut(t){return`${t.slice(0,16)}\u2026`}function He(t,e,r,n){let i=ut(t);if(n.crystallized){console.info(`[tab/seller] crystallize OK channel=${i} cumulative=${e} seq=${r}${n.claimPda?` claimPda=${n.claimPda}`:""} \u2014 LockVoucher landed`);return}if(n.error){if(J(n.error)){console.warn(`[tab/seller] crystallize refused below the facilitator's cadence gate channel=${i} cumulative=${e} seq=${r}: ${n.error} \u2014 benign: this facilitator's cadence engine owns the protection cadence for the span; gate-refused watermark advanced, re-attempts after the next signed voucher`);return}if(ct.some(s=>n.error.includes(s))){console.warn(`[tab/seller] crystallize duplicate channel=${i} cumulative=${e} seq=${r}: ${n.error} \u2014 voucher already secured on-chain (benign, no action)`);return}console.error(`[tab/seller] crystallize FAILED channel=${i} cumulative=${e} seq=${r}: ${n.error} \u2014 lock NOT secured (degraded: best-effort path, no watermark advance, retries at next threshold/close; seller exposure stays unsecured until it lands)`)}}async function Re(t,e,r,n,i=fetch){let s=t.lastVoucher;if(!s)return{crystallized:!1};if(s.payload.channelId!==e){let c={crystallized:!1,error:"channel_id_mismatch"};return He(e,s.payload.cumulativeAmount,s.payload.sequenceNumber,c),c}let h=c=>(He(e,s.payload.cumulativeAmount,s.payload.sequenceNumber,c),c);try{let c=`${r.replace(/\/$/,"")}/tab/lock`,a={channelId:s.payload.channelId,cumulativeAmount:s.payload.cumulativeAmount,sequenceNumber:s.payload.sequenceNumber,sessionPublicKey:Pe(s.sessionPublicKey),sessionSignature:Pe(s.sessionSignature),sessionRegistration:Pe(s.sessionRegistration),network:n},m=await i(c,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(a),signal:AbortSignal.timeout(at)}),l=await m.text();if(!m.ok)return h({crystallized:!1,error:`tab lock ${m.status}: ${l.slice(0,200)}`});let o;try{let y=JSON.parse(l);y&&typeof y.claimPda=="string"&&(o=y.claimPda)}catch{}return h({crystallized:!0,claimPda:o})}catch(c){return h({crystallized:!1,error:String(c?.message??c)})}}async function qe(t,e,r,n,i,s={}){let h=BigInt(t.deliveredCumulativeAtomic),c=BigInt(t.lastCrystallizedCumulativeAtomic??"0"),a=BigInt(i.thresholdAtomic);if(h-c<a)return{crystallized:!1};let m=t.lastVoucher?.payload.cumulativeAmount,l=t.gateRefusedCumulativeAtomic;if(m!==void 0&&l!==void 0&&BigInt(m)<=BigInt(l))return{crystallized:!1};let o=await Re(t,e,r,n,s.fetchImpl);return o.crystallized&&m!==void 0?(t.lastCrystallizedCumulativeAtomic=m,t.gateRefusedCumulativeAtomic=void 0):J(o.error)&&m!==void 0&&(t.gateRefusedCumulativeAtomic=m),o}var $="x-tab-voucher",Te=class{map=new Map;get(e){return this.map.get(e)}set(e,r){this.map.set(e,r)}update(e,r){let n=this.map.get(e);n&&(n.lastCumulativeAtomic=r)}delete(e){this.map.delete(e)}},_e=class{constructor(e,r,n,i,s,h){this.recordDeliveredImpl=s;this.chargeImpl=h;this.channelId=e,this.network=r,this.cumulativeAtomic=n,this.deliveredBaselineAtomic=i}channelId;network;sessionPublicKey=null;cumulativeAtomic;deliveredBaselineAtomic;cumulative(){return O(this.cumulativeAtomic.toString())}deliveredCumulative(){return O(this.deliveredBaselineAtomic.toString())}async recordDelivered(e){return this.recordDeliveredImpl(e)}bumpCumulative(e){this.cumulativeAtomic=e}setSessionPublicKey(e){this.sessionPublicKey=e}async charge(e){return this.chargeImpl(e)}};function dt(t){if(typeof t!="string"||t.length===0)throw new x("signature_invalid",`missing ${$} header`);let e;try{e=Buffer.from(t,"base64").toString("utf8")}catch{throw new x("signature_invalid","malformed base64")}let r;try{r=JSON.parse(e)}catch{throw new x("signature_invalid","malformed JSON")}if(!r||typeof r!="object"||!r.payload||!r.sessionPublicKey)throw new x("signature_invalid","missing required fields");return{payload:r.payload,sessionPublicKey:G(r.sessionPublicKey),sessionRegistration:G(r.sessionRegistration),sessionSignature:G(r.sessionSignature)}}function G(t){if(typeof t!="string"||t.length%2!==0)throw new x("signature_invalid",`bad hex: ${typeof t}`);let e=new Uint8Array(t.length/2);for(let r=0;r<e.length;r++)e[r]=parseInt(t.substr(r*2,2),16);return e}function pt(t){if(!/^[0-9a-f]{64}$/i.test(t))throw new x("signature_invalid",`channelId must be 64-char hex, got "${t}"`);return G(t)}function ke(t){let e=t.ledger??new M,r=new Te,n=typeof t.sellerPubkey=="string"?new mt(t.sellerPubkey):t.sellerPubkey,i=t.maxPerVoucherAtomic?BigInt(t.maxPerVoucherAtomic):BigInt(P(t.perUnit))*100n,s=t.facilitatorUrl??De,h={thresholdAtomic:t.lockCadence?.thresholdAtomic??P("0.10"),onClose:t.lockCadence?.onClose??!0};return async(c,a,m)=>{try{let l=dt(c.headers[$]),o=l.payload.channelId,y=pt(o),d=r.get(o),f=null;if(!d){let p=Se(l.sessionRegistration);f=(await xe(t.connection,p))?.frontierAtomic??null;let v=await e.get(o);d={registration:p,lastCumulativeAtomic:v?.lastVoucher?.payload.cumulativeAmount??"0"},r.set(o,d)}Ce(l,y),Ee({registration:d.registration,voucher:l,expectedCounterparty:n,previousCumulativeAtomic:d.lastCumulativeAtomic});let b=BigInt(l.payload.cumulativeAmount),V=BigInt(d.lastCumulativeAtomic),L=b-V;if(L>i)throw new C("cumulative_exceeds_cap",`single voucher increment ${L} exceeds maxPerVoucherAtomic ${i}`);let ue=t.leaseTtlMs??3e5;if(!await e.tryAcquireLease(o,ue))throw new x("channel_busy","another stream is live on this channel; tabs serve one stream at a time");let B=!1,j=()=>{B||(B=!0,e.releaseLease(o).catch(p=>{console.error("[tab/seller] failed to release channel lease:",p)}))};a.on("close",j),a.on("finish",j);let me=async p=>{let R=p.lastCrystallizedCumulativeAtomic??"0",v=p.gateRefusedCumulativeAtomic;await qe(p,o,s,t.network,h),(p.lastCrystallizedCumulativeAtomic!==R||p.gateRefusedCumulativeAtomic!==v)&&await T(o,async()=>{let w=await e.get(o);w&&await e.set(o,{...w,lastCrystallizedCumulativeAtomic:p.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:p.gateRefusedCumulativeAtomic})}).catch(w=>{console.error(`[tab/seller] crystallize watermark persist FAILED channel=${o.slice(0,16)}\u2026 (expect a benign duplicate/below-cadence warn on the next request):`,w)})},X=!1,u=()=>{!h.onClose||X||(X=!0,(async()=>{let p=await e.get(o);if(!p||!p.lastVoucher)return;let R=p.lastVoucher.payload.cumulativeAmount;if(p.gateRefusedCumulativeAtomic!==void 0&&BigInt(R)<=BigInt(p.gateRefusedCumulativeAtomic))return;let v=await Re(p,o,s,t.network);v.crystallized?await T(o,async()=>{let w=await e.get(o);w&&await e.set(o,{...w,lastCrystallizedCumulativeAtomic:R,gateRefusedCumulativeAtomic:void 0})}):J(v.error)&&await T(o,async()=>{let w=await e.get(o);w&&await e.set(o,{...w,gateRefusedCumulativeAtomic:R})})})().catch(p=>{console.error(`[tab/seller] close-path crystallize CRASHED channel=${o.slice(0,16)}\u2026 (final voucher NOT locked; exposure unsecured until the next request retries):`,p)}))};a.on("close",u),a.on("finish",u);let g=await e.get(o),A=!g?.lastVoucher&&BigInt(g?.deliveredCumulativeAtomic??"0")===0n,S=f!==null&&A&&BigInt(f)>0n?f:null;S!==null&&console.info(`[tab/seller] channel ${o.slice(0,16)}\u2026 resumed: seeding delivered baseline from chain frontier ${S} (session already settled/locked up to it \u2014 that span is not deliverable budget)`);let I=S!==null?BigInt(S):g?BigInt(g.deliveredCumulativeAtomic):0n;await T(o,async()=>{let p=await e.get(o);await e.set(o,{...p,lastVoucher:l,deliveredCumulativeAtomic:S??(p?p.deliveredCumulativeAtomic:"0"),lastCrystallizedCumulativeAtomic:S??p?.lastCrystallizedCumulativeAtomic??"0"})}),r.update(o,l.payload.cumulativeAmount);let U=new _e(o,t.network,b,I,async p=>{let R=null;await T(o,async()=>{let v=await e.get(o),w=v?BigInt(v.deliveredCumulativeAtomic):0n,$e=BigInt(p),Ze=$e>0n?w+$e:w,Ve={...v,lastVoucher:v?.lastVoucher??l,deliveredCumulativeAtomic:Ze.toString(),lastCrystallizedCumulativeAtomic:v?.lastCrystallizedCumulativeAtomic??"0"};await e.set(o,Ve),R=Ve}),R&&me(R).catch(v=>{console.error(`[tab/seller] crystallize cadence CRASHED channel=${o.slice(0,16)}\u2026 (threshold lock not attempted; retries at the next delivery):`,v)})},async p=>{throw new Error("SellerTab.charge() is not driven by the route handler; the buyer presents a fresh voucher per chunk. Use openSse(res, tab) for the metered-stream pattern.")});U.setSessionPublicKey(l.sessionPublicKey),c.tab=U,m()}catch(l){if(l instanceof x||l instanceof E||l instanceof N||l instanceof _||l instanceof C){a.status(402).json({error:"invalid_voucher",reason:l.reason??"unknown",detail:l.message});return}m(l)}}}function gt(t){if(!t.tab)throw new Error("req.tab is missing \u2014 did tabMiddleware run on this route?");return t.tab}function ht(t,e){if(!e.tab)throw new Error("openSse requires options.tab");t.headersSent||(t.setHeader("Content-Type","text/event-stream"),t.setHeader("Cache-Control","no-cache"),t.setHeader("Connection","keep-alive"),typeof t.flushHeaders=="function"&&t.flushHeaders());let r=e.tab,n=BigInt(P(r.cumulative())),i=BigInt(P(r.deliveredCumulative())),s=n-i;s<0n&&(s=0n);let h=e.perUnit?BigInt(P(e.perUnit)):null,c=0n,a=!1;async function m(){await r.recordDelivered(c.toString())}t.on("close",()=>{a||(a=!0,m().catch(d=>{console.error("[tab/seller] terminal persist failed on disconnect:",d)}))});async function l(d=1){if(a)throw new Error("meter ended");if(h===null)throw new Error("charge() needs options.perUnit");let f=h*BigInt(d),b=c+f;if(b>s)throw a=!0,await m(),new C("cumulative_exceeds_cap",`chunk would push delivered to ${O((i+b).toString())} beyond signed cumulative ${O(n.toString())} (per-request budget ${O(s.toString())})`);c=b}function o(d){if(a)throw new Error("meter ended");let b=(typeof d=="string"?d:Buffer.from(d).toString("utf8")).replace(/\\/g,"\\\\").replace(/\n/g,"\\n");t.write(`data: ${b}
2
2
 
3
- `)}async function y(){a||(a=!0,await m(),e.write(`event: end
3
+ `)}async function y(){a||(a=!0,await m(),t.write(`event: end
4
4
  data: {"chargedAtomic":"${c}"}
5
5
 
6
- `),e.end())}return{charge:l,send:o,end:y}}import{promises as D}from"fs";import{join as mt,dirname as dt}from"path";function pt(e){return{payload:e.payload,sessionPublicKey:Te(e.sessionPublicKey),sessionRegistration:Te(e.sessionRegistration),sessionSignature:Te(e.sessionSignature)}}function gt(e){return{payload:e.payload,sessionPublicKey:_e(e.sessionPublicKey),sessionRegistration:_e(e.sessionRegistration),sessionSignature:_e(e.sessionSignature)}}function Te(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}function _e(e){if(e.length%2!==0)throw new Error(`hex length must be even, got ${e.length}`);let t=new Uint8Array(e.length/2);for(let r=0;r<t.length;r++)t[r]=parseInt(e.substr(r*2,2),16);return t}var Ie=class{map=new Map;async get(t){return this.map.get(t)??null}async set(t,r){this.map.set(t,r)}async delete(t){this.map.delete(t)}},Ne=class{constructor(t){this.dir=t}pathFor(t){if(!/^[a-z0-9_-]+$/i.test(t))throw new Error(`unsafe channelId for filesystem: ${t}`);return mt(this.dir,`${t}.json`)}async get(t){try{let r=await D.readFile(this.pathFor(t),"utf8");return gt(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(t,r){let n=this.pathFor(t);await D.mkdir(dt(n),{recursive:!0});let i=`${n}.tmp`;await D.writeFile(i,JSON.stringify(pt(r))),await D.rename(i,n)}async delete(t){try{await D.unlink(this.pathFor(t))}catch(r){if(r?.code!=="ENOENT")throw r}}};import{PublicKey as vt}from"@solana/web3.js";var I="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",Me="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",De="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";var z="eip155:8453",Y="eip155:84532",Z="eip155:42161",Q="eip155:137",ee="eip155:10",te="eip155:43114",re="eip155:56",ne="eip155:1187947933",ie="eip155:324705682",se="eip155:1";var oe="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";var ze="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",ht="0x55d398326f99059fF775485246999027B3197955",He="0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",qe={[re]:He,[z]:ze,[Y]:"0x036CbD53842c5426634e7929541eC2318f3dCF7e",[Z]:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831",[Q]:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",[ee]:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",[te]:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",[ne]:"0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",[ie]:"0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",[se]:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},Fe={[ht]:{symbol:"USDT",decimals:18},[He]:{symbol:"USDC",decimals:18}};var Vr={[re]:56,[z]:8453,[Y]:84532,[Z]:42161,[Q]:137,[ee]:10,[te]:43114,[ne]:1187947933,[ie]:324705682,[se]:1},Br={[I]:"https://api.dexter.cash/api/solana/rpc",[Me]:"https://api.devnet.solana.com",[De]:"https://api.testnet.solana.com"},Lr={[re]:"https://api.dexter.cash/api/evm/bsc/rpc",[z]:"https://api.dexter.cash/api/base/rpc",[Y]:"https://sepolia.base.org",[Z]:"https://api.dexter.cash/api/evm/arbitrum/rpc",[Q]:"https://api.dexter.cash/api/evm/polygon/rpc",[ee]:"https://api.dexter.cash/api/evm/optimism/rpc",[te]:"https://api.dexter.cash/api/evm/avalanche/rpc",[ne]:"https://skale-base.skalenodes.com/v1/base",[ie]:"https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",[se]:"https://eth.llamarpc.com"},H="https://x402.dexter.cash";function ae(e){return e.startsWith("solana:")||e==="solana"}function yt(e){if(typeof Buffer<"u")return Buffer.from(e,"utf-8").toString("base64");let t=new TextEncoder().encode(e),r="";for(let n=0;n<t.length;n++)r+=String.fromCharCode(t[n]);return btoa(r)}function ft(e){if(typeof Buffer<"u")return Buffer.from(e,"base64").toString("utf-8");let t=atob(e),r=new Uint8Array(t.length);for(let n=0;n<t.length;n++)r[n]=t.charCodeAt(n);return new TextDecoder().decode(r)}function ce(e){return yt(JSON.stringify(e))}function q(e){return JSON.parse(ft(e))}function At(e){if(e instanceof TypeError)return!0;if(e&&typeof e=="object"&&"status"in e){let t=e.status;return t>=500&&t<600}return!1}var F=class extends Error{status;body;constructor(t,r){super(`HTTP ${t}`),this.status=t,this.body=r}},le=class{facilitatorUrl;cachedSupported=null;cacheTime=0;CACHE_TTL_MS=6e4;timeoutMs;maxRetries;retryBaseMs;constructor(t=H,r){this.facilitatorUrl=t.replace(/\/$/,""),this.timeoutMs=r?.timeoutMs??1e4,this.maxRetries=r?.maxRetries??3,this.retryBaseMs=r?.retryBaseMs??500}async fetchWithTimeout(t,r){let n=new AbortController,i=setTimeout(()=>n.abort(),this.timeoutMs);try{return await fetch(t,{...r,signal:n.signal})}finally{clearTimeout(i)}}async fetchWithRetry(t,r){let n;for(let i=0;i<this.maxRetries;i++)try{let s=await this.fetchWithTimeout(t,r);if(!s.ok&&s.status>=500)throw new F(s.status,await s.text());return s}catch(s){if(n=s,i<this.maxRetries-1&&At(s)){let h=this.retryBaseMs*Math.pow(2,i);await new Promise(c=>setTimeout(c,h));continue}throw s}throw n}async getSupported(){let t=Date.now();if(this.cachedSupported&&t-this.cacheTime<this.CACHE_TTL_MS)return this.cachedSupported;let r=await this.fetchWithTimeout(`${this.facilitatorUrl}/supported`);if(!r.ok)throw new Error(`Facilitator /supported returned ${r.status}`);return this.cachedSupported=await r.json(),this.cacheTime=t,this.cachedSupported}async getFeePayer(t){let n=(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval")&&i.network===t);if(!n)throw new Error(`Facilitator does not support network "${t}" with a recognized scheme`);return n.extra?.feePayer}async getNetworkExtra(t){return(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval"||i.scheme==="batch-settlement")&&i.network===t)?.extra}async verifyPayment(t,r){try{let n=q(t),i=await this.fetchWithRetry(`${this.facilitatorUrl}/verify`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:n,paymentRequirements:r})});return i.ok?await i.json():{isValid:!1,invalidReason:`facilitator_error_${i.status}`}}catch(n){return{isValid:!1,invalidReason:n instanceof F?`facilitator_error_${n.status}`:n instanceof Error&&n.name==="AbortError"?"facilitator_timeout":n instanceof Error?n.message:"unexpected_verify_error"}}}async settlePayment(t,r){try{let n=q(t),i=await this.fetchWithRetry(`${this.facilitatorUrl}/settle`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:n,paymentRequirements:r})});return i.ok?{...await i.json(),network:r.network}:{success:!1,network:r.network,errorReason:`facilitator_error_${i.status}`}}catch(n){let i=n instanceof F?`facilitator_error_${n.status}`:n instanceof Error&&n.name==="AbortError"?"facilitator_timeout":n instanceof Error?n.message:"unexpected_settle_error";return{success:!1,network:r.network,errorReason:i}}}};function bt(e){if(ae(e))return{address:oe,decimals:6};let t=qe[e];if(t){let r=Fe[t]?.decimals??6;return{address:t,decimals:r}}return{address:oe,decimals:6}}function We(e){try{let t=q(e);return t?.accepted?.amount??t?.accepted?.maxAmountRequired}catch{return}}function W(e){let{payTo:t,facilitatorUrl:r=H,network:n=I,defaultTimeoutSeconds:i=60}=e,s=e.asset??bt(n),h=e.scheme??"exact";if(h==="tab"&&!ae(n))throw new Error(`scheme 'tab' is SVM-only; got network "${n}"`);let c=new le(r),a=null,m=new Map,l=3e4,o=Date.now();function y(u){let g=(u.maxTimeoutSeconds||i)*1e3;if(m.set(u.payTo,{accept:u,expiresAt:Date.now()+g}),Date.now()-o>l){let A=Date.now();for(let[S,k]of m)k.expiresAt<A&&m.delete(S);o=A}}function d(u){let g=m.get(u);if(g){if(g.expiresAt<Date.now()){m.delete(u);return}return g.accept}}async function f(u){return typeof t=="string"?t:t(u||{})}async function b(){if(a||(a=await c.getNetworkExtra(n)),ae(n)&&!a?.feePayer)throw new Error(`Facilitator does not provide feePayer for network "${n}"`);return{...a?.feePayer?{feePayer:a.feePayer}:{},decimals:a?.decimals??s.decimals,name:a?.name,version:a?.version,...h==="batch-settlement"&&a?.receiverAuthorizer?{receiverAuthorizer:a.receiverAuthorizer}:{},...h==="tab"?{voucherHeader:"x-tab-voucher",registrationEncoding:"base64(188-byte sessionRegisterMessage)"}:{}}}async function V(u,g){let{amountAtomic:A,timeoutSeconds:S=i}=g,k=await b(),U={scheme:h,network:n,amount:A,maxAmountRequired:A,asset:s.address,payTo:u,maxTimeoutSeconds:S,extra:k};return y(U),U}async function B(u){let g=await f({amountAtomic:u.amountAtomic,resourceUrl:u.resourceUrl});return V(g,u)}async function ue(u){let{resourceUrl:g,description:A,mimeType:S="application/json"}=u,k={url:g,description:A,mimeType:S},U=await B(u);return{x402Version:2,resource:k,accepts:[U],error:"Payment required"}}function L(u){return ce(u)}function j(u){return{status:402,headers:{"PAYMENT-REQUIRED":L(u)},body:{}}}async function me(u,g){if(!g){let A=await f({paymentHeader:u});g=d(A),g||(g=await V(A,{amountAtomic:We(u)??"0",resourceUrl:""}))}return c.verifyPayment(u,g)}async function X(u,g){if(!g){let A=await f({paymentHeader:u});g=d(A),g||(g=await V(A,{amountAtomic:We(u)??"0",resourceUrl:""}))}return c.settlePayment(u,g)}return{buildRequirements:ue,encodeRequirements:L,create402Response:j,verifyPayment:me,settlePayment:X,getPaymentAccept:B,network:n,assetDecimals:s.decimals,facilitator:c}}var wt={"solana:mainnet":I};function St(e){let t=wt[e.network];if(!t)throw new Error(`tabChallengeMiddleware: unsupported network "${e.network}"`);let r=typeof e.sellerPubkey=="string"?e.sellerPubkey:e.sellerPubkey.toBase58();new vt(r);let n=W({payTo:r,network:t,scheme:"tab",facilitatorUrl:e.facilitatorUrl}),i=R(e.perUnit);return async(s,h,c)=>{if(s.headers[$])return c();try{let a=`${s.protocol}://${s.get("host")}${s.originalUrl}`,m=await n.buildRequirements({amountAtomic:i,resourceUrl:a,description:e.description}),l=n.create402Response(m);h.set(l.headers).status(l.status).json(l.body)}catch(a){let m=a?.message??String(a);h.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:m})}}}import{PublicKey as xt}from"@solana/web3.js";var Ct={"solana:mainnet":I};function Et(e){let t=Ct[e.network];if(!t)throw new Error(`tabOrExactMiddleware: unsupported network "${e.network}"`);let r=typeof e.sellerPubkey=="string"?e.sellerPubkey:e.sellerPubkey.toBase58();new xt(r);let n=W({payTo:r,network:t,scheme:"tab",facilitatorUrl:e.facilitatorUrl}),i=W({payTo:r,network:t,scheme:"exact",facilitatorUrl:e.facilitatorUrl}),s=R(e.perUnit),h=Pe({connection:e.connection,sellerPubkey:r,network:e.network,perUnit:e.perUnit,settle:"on-close",facilitatorUrl:e.facilitatorUrl,lockCadence:e.lockCadence});return async(c,a,m)=>{if(c.headers[$])return h(c,a,m);let l=`${c.protocol}://${c.get("host")}${c.originalUrl}`,o=c.headers["payment-signature"];if(o){let y;try{y=await i.getPaymentAccept({amountAtomic:s,resourceUrl:l,description:e.description})}catch(d){let f=d?.message??String(d);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:f});return}try{let d=await i.verifyPayment(o,y);if(!d.isValid){a.status(402).json({error:"Payment verification failed",reason:d.invalidReason});return}let f=await i.settlePayment(o,y);if(!f.success){a.status(402).json({error:"Payment settlement failed",reason:f.errorReason});return}return c.x402={transaction:f.transaction,payer:d.payer??"",network:f.network||t},a.setHeader("PAYMENT-RESPONSE",ce({success:!0,transaction:f.transaction,network:f.network||t,payer:d.payer??""})),m()}catch{a.status(500).json({error:"Payment processing error"});return}}try{let y={amountAtomic:s,resourceUrl:l,description:e.description},[d,f]=await Promise.all([n.buildRequirements(y),i.buildRequirements(y)]),b={...d,accepts:[...d.accepts,...f.accepts]};a.set({"PAYMENT-REQUIRED":n.encodeRequirements(b)}).status(402).json({error:"Payment required",accepts:b.accepts,resource:b.resource})}catch(y){let d=y?.message??String(y);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:d})}}}export{ge as FileChannelLedger,Ne as FileVoucherStore,M as InMemoryChannelLedger,Ie as InMemoryVoucherStore,E as InvalidRegistrationError,x as InvalidVoucherError,_ as InvalidVoucherSignatureError,N as OnChainVerificationError,C as ScopeViolationError,$ as TAB_VOUCHER_HEADER,Se as enforceScope,ut as openSse,be as parseRegistration,lt as requireTab,St as tabChallengeMiddleware,Pe as tabMiddleware,Et as tabOrExactMiddleware,ve as verifyRegistrationOnChain,we as verifyVoucherSignature};
6
+ `),t.end())}return{charge:l,send:o,end:y}}import{promises as D}from"fs";import{join as yt,dirname as ft}from"path";function At(t){return{payload:t.payload,sessionPublicKey:Ne(t.sessionPublicKey),sessionRegistration:Ne(t.sessionRegistration),sessionSignature:Ne(t.sessionSignature)}}function bt(t){return{payload:t.payload,sessionPublicKey:Ie(t.sessionPublicKey),sessionRegistration:Ie(t.sessionRegistration),sessionSignature:Ie(t.sessionSignature)}}function Ne(t){let e="";for(let r of t)e+=r.toString(16).padStart(2,"0");return e}function Ie(t){if(t.length%2!==0)throw new Error(`hex length must be even, got ${t.length}`);let e=new Uint8Array(t.length/2);for(let r=0;r<e.length;r++)e[r]=parseInt(t.substr(r*2,2),16);return e}var Ue=class{map=new Map;async get(e){return this.map.get(e)??null}async set(e,r){this.map.set(e,r)}async delete(e){this.map.delete(e)}},Oe=class{constructor(e){this.dir=e}pathFor(e){if(!/^[a-z0-9_-]+$/i.test(e))throw new Error(`unsafe channelId for filesystem: ${e}`);return yt(this.dir,`${e}.json`)}async get(e){try{let r=await D.readFile(this.pathFor(e),"utf8");return bt(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(e,r){let n=this.pathFor(e);await D.mkdir(ft(n),{recursive:!0});let i=`${n}.tmp`;await D.writeFile(i,JSON.stringify(At(r))),await D.rename(i,n)}async delete(e){try{await D.unlink(this.pathFor(e))}catch(r){if(r?.code!=="ENOENT")throw r}}};import{PublicKey as Et}from"@solana/web3.js";var k="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",Fe="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",We="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";var z="eip155:8453",Y="eip155:84532",Z="eip155:42161",Q="eip155:137",ee="eip155:10",te="eip155:43114",re="eip155:56",ne="eip155:1187947933",ie="eip155:324705682",se="eip155:1";var oe="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";var je="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",vt="0x55d398326f99059fF775485246999027B3197955",Xe="0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",Je={[re]:Xe,[z]:je,[Y]:"0x036CbD53842c5426634e7929541eC2318f3dCF7e",[Z]:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831",[Q]:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",[ee]:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",[te]:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",[ne]:"0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",[ie]:"0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",[se]:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},Ge={[vt]:{symbol:"USDT",decimals:18},[Xe]:{symbol:"USDC",decimals:18}};var qr={[re]:56,[z]:8453,[Y]:84532,[Z]:42161,[Q]:137,[ee]:10,[te]:43114,[ne]:1187947933,[ie]:324705682,[se]:1},Fr={[k]:"https://api.dexter.cash/api/solana/rpc",[Fe]:"https://api.devnet.solana.com",[We]:"https://api.testnet.solana.com"},Wr={[re]:"https://api.dexter.cash/api/evm/bsc/rpc",[z]:"https://api.dexter.cash/api/base/rpc",[Y]:"https://sepolia.base.org",[Z]:"https://api.dexter.cash/api/evm/arbitrum/rpc",[Q]:"https://api.dexter.cash/api/evm/polygon/rpc",[ee]:"https://api.dexter.cash/api/evm/optimism/rpc",[te]:"https://api.dexter.cash/api/evm/avalanche/rpc",[ne]:"https://skale-base.skalenodes.com/v1/base",[ie]:"https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",[se]:"https://eth.llamarpc.com"},H="https://x402.dexter.cash";function ae(t){return t.startsWith("solana:")||t==="solana"}function wt(t){if(typeof Buffer<"u")return Buffer.from(t,"utf-8").toString("base64");let e=new TextEncoder().encode(t),r="";for(let n=0;n<e.length;n++)r+=String.fromCharCode(e[n]);return btoa(r)}function St(t){if(typeof Buffer<"u")return Buffer.from(t,"base64").toString("utf-8");let e=atob(t),r=new Uint8Array(e.length);for(let n=0;n<e.length;n++)r[n]=e.charCodeAt(n);return new TextDecoder().decode(r)}function ce(t){return wt(JSON.stringify(t))}function q(t){return JSON.parse(St(t))}function xt(t){if(t instanceof TypeError)return!0;if(t&&typeof t=="object"&&"status"in t){let e=t.status;return e>=500&&e<600}return!1}var F=class extends Error{status;body;constructor(e,r){super(`HTTP ${e}`),this.status=e,this.body=r}},le=class{facilitatorUrl;cachedSupported=null;cacheTime=0;CACHE_TTL_MS=6e4;timeoutMs;maxRetries;retryBaseMs;constructor(e=H,r){this.facilitatorUrl=e.replace(/\/$/,""),this.timeoutMs=r?.timeoutMs??1e4,this.maxRetries=r?.maxRetries??3,this.retryBaseMs=r?.retryBaseMs??500}async fetchWithTimeout(e,r){let n=new AbortController,i=setTimeout(()=>n.abort(),this.timeoutMs);try{return await fetch(e,{...r,signal:n.signal})}finally{clearTimeout(i)}}async fetchWithRetry(e,r){let n;for(let i=0;i<this.maxRetries;i++)try{let s=await this.fetchWithTimeout(e,r);if(!s.ok&&s.status>=500)throw new F(s.status,await s.text());return s}catch(s){if(n=s,i<this.maxRetries-1&&xt(s)){let h=this.retryBaseMs*Math.pow(2,i);await new Promise(c=>setTimeout(c,h));continue}throw s}throw n}async getSupported(){let e=Date.now();if(this.cachedSupported&&e-this.cacheTime<this.CACHE_TTL_MS)return this.cachedSupported;let r=await this.fetchWithTimeout(`${this.facilitatorUrl}/supported`);if(!r.ok)throw new Error(`Facilitator /supported returned ${r.status}`);return this.cachedSupported=await r.json(),this.cacheTime=e,this.cachedSupported}async getFeePayer(e){let n=(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval")&&i.network===e);if(!n)throw new Error(`Facilitator does not support network "${e}" with a recognized scheme`);return n.extra?.feePayer}async getNetworkExtra(e){return(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval"||i.scheme==="batch-settlement")&&i.network===e)?.extra}async verifyPayment(e,r){try{let n=q(e),i=await this.fetchWithRetry(`${this.facilitatorUrl}/verify`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:n,paymentRequirements:r})});return i.ok?await i.json():{isValid:!1,invalidReason:`facilitator_error_${i.status}`}}catch(n){return{isValid:!1,invalidReason:n instanceof F?`facilitator_error_${n.status}`:n instanceof Error&&n.name==="AbortError"?"facilitator_timeout":n instanceof Error?n.message:"unexpected_verify_error"}}}async settlePayment(e,r){try{let n=q(e),i=await this.fetchWithRetry(`${this.facilitatorUrl}/settle`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:n,paymentRequirements:r})});return i.ok?{...await i.json(),network:r.network}:{success:!1,network:r.network,errorReason:`facilitator_error_${i.status}`}}catch(n){let i=n instanceof F?`facilitator_error_${n.status}`:n instanceof Error&&n.name==="AbortError"?"facilitator_timeout":n instanceof Error?n.message:"unexpected_settle_error";return{success:!1,network:r.network,errorReason:i}}}};function Ct(t){if(ae(t))return{address:oe,decimals:6};let e=Je[t];if(e){let r=Ge[e]?.decimals??6;return{address:e,decimals:r}}return{address:oe,decimals:6}}function Ye(t){try{let e=q(t);return e?.accepted?.amount??e?.accepted?.maxAmountRequired}catch{return}}function W(t){let{payTo:e,facilitatorUrl:r=H,network:n=k,defaultTimeoutSeconds:i=60}=t,s=t.asset??Ct(n),h=t.scheme??"exact";if(h==="tab"&&!ae(n))throw new Error(`scheme 'tab' is SVM-only; got network "${n}"`);let c=new le(r),a=null,m=new Map,l=3e4,o=Date.now();function y(u){let g=(u.maxTimeoutSeconds||i)*1e3;if(m.set(u.payTo,{accept:u,expiresAt:Date.now()+g}),Date.now()-o>l){let A=Date.now();for(let[S,I]of m)I.expiresAt<A&&m.delete(S);o=A}}function d(u){let g=m.get(u);if(g){if(g.expiresAt<Date.now()){m.delete(u);return}return g.accept}}async function f(u){return typeof e=="string"?e:e(u||{})}async function b(){if(a||(a=await c.getNetworkExtra(n)),ae(n)&&!a?.feePayer)throw new Error(`Facilitator does not provide feePayer for network "${n}"`);return{...a?.feePayer?{feePayer:a.feePayer}:{},decimals:a?.decimals??s.decimals,name:a?.name,version:a?.version,...h==="batch-settlement"&&a?.receiverAuthorizer?{receiverAuthorizer:a.receiverAuthorizer}:{},...h==="tab"?{voucherHeader:"x-tab-voucher",registrationEncoding:"base64(188-byte sessionRegisterMessage)"}:{}}}async function V(u,g){let{amountAtomic:A,timeoutSeconds:S=i}=g,I=await b(),U={scheme:h,network:n,amount:A,maxAmountRequired:A,asset:s.address,payTo:u,maxTimeoutSeconds:S,extra:I};return y(U),U}async function L(u){let g=await f({amountAtomic:u.amountAtomic,resourceUrl:u.resourceUrl});return V(g,u)}async function ue(u){let{resourceUrl:g,description:A,mimeType:S="application/json"}=u,I={url:g,description:A,mimeType:S},U=await L(u);return{x402Version:2,resource:I,accepts:[U],error:"Payment required"}}function B(u){return ce(u)}function j(u){return{status:402,headers:{"PAYMENT-REQUIRED":B(u)},body:{}}}async function me(u,g){if(!g){let A=await f({paymentHeader:u});g=d(A),g||(g=await V(A,{amountAtomic:Ye(u)??"0",resourceUrl:""}))}return c.verifyPayment(u,g)}async function X(u,g){if(!g){let A=await f({paymentHeader:u});g=d(A),g||(g=await V(A,{amountAtomic:Ye(u)??"0",resourceUrl:""}))}return c.settlePayment(u,g)}return{buildRequirements:ue,encodeRequirements:B,create402Response:j,verifyPayment:me,settlePayment:X,getPaymentAccept:L,network:n,assetDecimals:s.decimals,facilitator:c}}var Pt={"solana:mainnet":k};function Rt(t){let e=Pt[t.network];if(!e)throw new Error(`tabChallengeMiddleware: unsupported network "${t.network}"`);let r=typeof t.sellerPubkey=="string"?t.sellerPubkey:t.sellerPubkey.toBase58();new Et(r);let n=W({payTo:r,network:e,scheme:"tab",facilitatorUrl:t.facilitatorUrl}),i=P(t.perUnit);return async(s,h,c)=>{if(s.headers[$])return c();try{let a=`${s.protocol}://${s.get("host")}${s.originalUrl}`,m=await n.buildRequirements({amountAtomic:i,resourceUrl:a,description:t.description}),l=n.create402Response(m);h.set(l.headers).status(l.status).json(l.body)}catch(a){let m=a?.message??String(a);h.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:m})}}}import{PublicKey as Tt}from"@solana/web3.js";var _t={"solana:mainnet":k};function kt(t){let e=_t[t.network];if(!e)throw new Error(`tabOrExactMiddleware: unsupported network "${t.network}"`);let r=typeof t.sellerPubkey=="string"?t.sellerPubkey:t.sellerPubkey.toBase58();new Tt(r);let n=W({payTo:r,network:e,scheme:"tab",facilitatorUrl:t.facilitatorUrl}),i=W({payTo:r,network:e,scheme:"exact",facilitatorUrl:t.facilitatorUrl}),s=P(t.perUnit),h=ke({connection:t.connection,sellerPubkey:r,network:t.network,perUnit:t.perUnit,settle:"on-close",facilitatorUrl:t.facilitatorUrl,lockCadence:t.lockCadence});return async(c,a,m)=>{if(c.headers[$])return h(c,a,m);let l=`${c.protocol}://${c.get("host")}${c.originalUrl}`,o=c.headers["payment-signature"];if(o){let y;try{y=await i.getPaymentAccept({amountAtomic:s,resourceUrl:l,description:t.description})}catch(d){let f=d?.message??String(d);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:f});return}try{let d=await i.verifyPayment(o,y);if(!d.isValid){a.status(402).json({error:"Payment verification failed",reason:d.invalidReason});return}let f=await i.settlePayment(o,y);if(!f.success){a.status(402).json({error:"Payment settlement failed",reason:f.errorReason});return}return c.x402={transaction:f.transaction,payer:d.payer??"",network:f.network||e},a.setHeader("PAYMENT-RESPONSE",ce({success:!0,transaction:f.transaction,network:f.network||e,payer:d.payer??""})),m()}catch{a.status(500).json({error:"Payment processing error"});return}}try{let y={amountAtomic:s,resourceUrl:l,description:t.description},[d,f]=await Promise.all([n.buildRequirements(y),i.buildRequirements(y)]),b={...d,accepts:[...d.accepts,...f.accepts]};a.set({"PAYMENT-REQUIRED":n.encodeRequirements(b)}).status(402).json({error:"Payment required",accepts:b.accepts,resource:b.resource})}catch(y){let d=y?.message??String(y);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:d})}}}export{ge as FileChannelLedger,Oe as FileVoucherStore,M as InMemoryChannelLedger,Ue as InMemoryVoucherStore,E as InvalidRegistrationError,x as InvalidVoucherError,_ as InvalidVoucherSignatureError,N as OnChainVerificationError,fe as RedisChannelLedger,C as ScopeViolationError,$ as TAB_VOUCHER_HEADER,ye as deserializeChannelLedgerEntry,Ee as enforceScope,ht as openSse,Se as parseRegistration,gt as requireTab,he as serializeChannelLedgerEntry,Rt as tabChallengeMiddleware,ke as tabMiddleware,kt as tabOrExactMiddleware,xe as verifyRegistrationOnChain,Ce as verifyVoucherSignature};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dexterai/x402",
3
- "version": "5.3.2",
3
+ "version": "5.3.4",
4
4
  "description": "Full-stack x402 SDK - add paid API monetization to any endpoint. Express middleware, React hooks, Access Pass, dynamic pricing. Solana, Base, Polygon, Arbitrum, Optimism, Avalanche, SKALE.",
5
5
  "author": "Dexter",
6
6
  "license": "MIT",