@dexterai/x402 5.3.1 → 5.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -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:()=>w,InvalidVoucherSignatureError:()=>_,OnChainVerificationError:()=>I,ScopeViolationError:()=>S,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 w=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 S=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 S("cumulative_exceeds_cap",`${t} > ${e.registration.maxAmount}`);let r=BigInt(Math.floor(Date.now()/1e3));if(r>=e.registration.expiresAt)throw new S("session_expired",`now=${r} >= expiresAt=${e.registration.expiresAt}`);if(!e.registration.allowedCounterparty.equals(e.expectedCounterparty))throw new S("wrong_counterparty",`${e.registration.allowedCounterparty.toBase58()} != ${e.expectedCounterparty.toBase58()}`);if(e.previousCumulativeAtomic!==void 0){let n=BigInt(e.previousCumulativeAtomic);if(t<=n)throw new S("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 w("signature_invalid",`missing ${k} header`);let t;try{t=Buffer.from(e,"base64").toString("utf8")}catch{throw new w("signature_invalid","malformed base64")}let r;try{r=JSON.parse(t)}catch{throw new w("signature_invalid","malformed JSON")}if(!r||typeof r!="object"||!r.payload||!r.sessionPublicKey)throw new w("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 w("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 w("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,d={registration:p,lastCumulativeAtomic:"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 S("cumulative_exceeds_cap",`single voucher increment ${z} exceeds maxPerVoucherAtomic ${i}`);let Re=e.leaseTtlMs??3e5;if(!await t.tryAcquireLease(o,Re))throw new w("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",C=p.gateRefusedCumulativeAtomic;await je(p,o,s,e.network,h),(p.lastCrystallizedCumulativeAtomic!==P||p.gateRefusedCumulativeAtomic!==C)&&await T(o,async()=>{let v=await t.get(o);v&&await t.set(o,{...v,lastCrystallizedCumulativeAtomic:p.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:p.gateRefusedCumulativeAtomic})}).catch(v=>{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):`,v)})},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 C=await ke(p,o,s,e.network);C.crystallized?await T(o,async()=>{let v=await t.get(o);v&&await t.set(o,{...v,lastCrystallizedCumulativeAtomic:P,gateRefusedCumulativeAtomic:void 0})}):ae(C.error)&&await T(o,async()=>{let v=await t.get(o);v&&await t.set(o,{...v,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,x=f!==null&&A&&BigInt(f)>0n?f:null;x!==null&&console.info(`[tab/seller] channel ${o.slice(0,16)}\u2026 resumed: seeding delivered baseline from chain frontier ${x} (session already settled/locked up to it \u2014 that span is not deliverable budget)`);let U=x!==null?BigInt(x):g?BigInt(g.deliveredCumulativeAtomic):0n;await T(o,async()=>{let p=await t.get(o);await t.set(o,{...p,lastVoucher:l,deliveredCumulativeAtomic:x??(p?p.deliveredCumulativeAtomic:"0"),lastCrystallizedCumulativeAtomic:x??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 C=await t.get(o),v=C?BigInt(C.deliveredCumulativeAtomic):0n,Be=BigInt(p),ct=Be>0n?v+Be:v,Le={...C,lastVoucher:C?.lastVoucher??l,deliveredCumulativeAtomic:ct.toString(),lastCrystallizedCumulativeAtomic:C?.lastCrystallizedCumulativeAtomic??"0"};await t.set(o,Le),P=Le}),P&&Pe(P).catch(C=>{console.error(`[tab/seller] crystallize cadence CRASHED channel=${o.slice(0,16)}\u2026 (threshold lock not attempted; retries at the next delivery):`,C)})},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 w||l instanceof E||l instanceof I||l instanceof _||l instanceof S){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 S("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 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}
|
|
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[x,U]of m)U.expiresAt<A&&m.delete(x);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:x=i}=g,U=await b(),O={scheme:h,network:n,amount:A,maxAmountRequired:A,asset:s.address,payTo:u,maxTimeoutSeconds:x,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:x="application/json"}=u,U={url:g,description:A,mimeType:x},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"),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});
|
package/dist/tab/seller/index.js
CHANGED
|
@@ -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,d={registration:p,lastCumulativeAtomic:"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",S=p.gateRefusedCumulativeAtomic;await Ke(p,o,s,e.network,h),(p.lastCrystallizedCumulativeAtomic!==P||p.gateRefusedCumulativeAtomic!==S)&&await T(o,async()=>{let v=await t.get(o);v&&await t.set(o,{...v,lastCrystallizedCumulativeAtomic:p.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:p.gateRefusedCumulativeAtomic})}).catch(v=>{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):`,v)})},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 S=await Ce(p,o,s,e.network);S.crystallized?await T(o,async()=>{let v=await t.get(o);v&&await t.set(o,{...v,lastCrystallizedCumulativeAtomic:P,gateRefusedCumulativeAtomic:void 0})}):J(S.error)&&await T(o,async()=>{let v=await t.get(o);v&&await t.set(o,{...v,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,w=f!==null&&A&&BigInt(f)>0n?f:null;w!==null&&console.info(`[tab/seller] channel ${o.slice(0,16)}\u2026 resumed: seeding delivered baseline from chain frontier ${w} (session already settled/locked up to it \u2014 that span is not deliverable budget)`);let k=w!==null?BigInt(w):g?BigInt(g.deliveredCumulativeAtomic):0n;await T(o,async()=>{let p=await t.get(o);await t.set(o,{...p,lastVoucher:l,deliveredCumulativeAtomic:w??(p?p.deliveredCumulativeAtomic:"0"),lastCrystallizedCumulativeAtomic:w??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 S=await t.get(o),v=S?BigInt(S.deliveredCumulativeAtomic):0n,ke=BigInt(p),je=ke>0n?v+ke:v,Ue={...S,lastVoucher:S?.lastVoucher??l,deliveredCumulativeAtomic:je.toString(),lastCrystallizedCumulativeAtomic:S?.lastCrystallizedCumulativeAtomic??"0"};await t.set(o,Ue),P=Ue}),P&&me(P).catch(S=>{console.error(`[tab/seller] crystallize cadence CRASHED channel=${o.slice(0,16)}\u2026 (threshold lock not attempted; retries at the next delivery):`,S)})},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 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}
|
|
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}}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[w,k]of m)k.expiresAt<A&&m.delete(w);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:w=i}=g,k=await b(),U={scheme:h,network:n,amount:A,maxAmountRequired:A,asset:s.address,payTo:u,maxTimeoutSeconds:w,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:w="application/json"}=u,k={url:g,description:A,mimeType:w},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
|
+
`),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};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dexterai/x402",
|
|
3
|
-
"version": "5.3.
|
|
3
|
+
"version": "5.3.2",
|
|
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",
|
|
@@ -89,7 +89,7 @@
|
|
|
89
89
|
"tweetnacl": "^1.0.3"
|
|
90
90
|
},
|
|
91
91
|
"devDependencies": {
|
|
92
|
-
"@dexterai/vault": "^0.
|
|
92
|
+
"@dexterai/vault": "^0.37.0",
|
|
93
93
|
"@types/aws-lambda": "^8.10.161",
|
|
94
94
|
"@types/express": "^5.0.6",
|
|
95
95
|
"@types/node": "^22.10.0",
|