@dexterai/x402 5.4.2 → 6.0.0-rc.0

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.
Files changed (51) hide show
  1. package/README.md +19 -4
  2. package/REFERENCE.md +79 -8
  3. package/dist/adapters/index.d.cts +3 -3
  4. package/dist/adapters/index.d.ts +3 -3
  5. package/dist/batch-settlement/index.d.cts +3 -3
  6. package/dist/batch-settlement/index.d.ts +3 -3
  7. package/dist/batch-settlement/seller/index.d.cts +4 -4
  8. package/dist/batch-settlement/seller/index.d.ts +4 -4
  9. package/dist/client/index.cjs +1 -1
  10. package/dist/client/index.d.cts +6 -6
  11. package/dist/client/index.d.ts +6 -6
  12. package/dist/client/index.js +1 -1
  13. package/dist/{constants-Icc4CXNG.d.cts → constants-BLvApMMl.d.cts} +1 -1
  14. package/dist/{constants-Icc4CXNG.d.ts → constants-BLvApMMl.d.ts} +1 -1
  15. package/dist/react/index.cjs +1 -1
  16. package/dist/react/index.d.cts +4 -4
  17. package/dist/react/index.d.ts +4 -4
  18. package/dist/react/index.js +1 -1
  19. package/dist/server/index.cjs +1 -1
  20. package/dist/server/index.d.cts +5 -5
  21. package/dist/server/index.d.ts +5 -5
  22. package/dist/server/index.js +1 -1
  23. package/dist/{sessions-BG2OYLBi.d.cts → sessions-rPdO1CgK.d.cts} +35 -3
  24. package/dist/{sessions-BG2OYLBi.d.ts → sessions-rPdO1CgK.d.ts} +35 -3
  25. package/dist/tab/adapters/solana/index.cjs +1 -1
  26. package/dist/tab/adapters/solana/index.d.cts +178 -26
  27. package/dist/tab/adapters/solana/index.d.ts +178 -26
  28. package/dist/tab/adapters/solana/index.js +1 -1
  29. package/dist/tab/index.cjs +5 -5
  30. package/dist/tab/index.d.cts +117 -16
  31. package/dist/tab/index.d.ts +117 -16
  32. package/dist/tab/index.js +4 -4
  33. package/dist/tab/seller/index.cjs +3 -3
  34. package/dist/tab/seller/index.d.cts +4 -4
  35. package/dist/tab/seller/index.d.ts +4 -4
  36. package/dist/tab/seller/index.js +3 -3
  37. package/dist/{types-CSuISjXA.d.cts → types-45M9fb5M.d.cts} +109 -6
  38. package/dist/{types-CSuISjXA.d.ts → types-45M9fb5M.d.ts} +109 -6
  39. package/dist/{types-BdS_uvNs.d.cts → types-BbvuPNXl.d.cts} +2 -2
  40. package/dist/{types-Co5YYhVB.d.ts → types-BhXu7cgi.d.ts} +3 -3
  41. package/dist/{types-xQu1U4xk.d.cts → types-BvQpNtFw.d.cts} +9 -1
  42. package/dist/{types-xQu1U4xk.d.ts → types-BvQpNtFw.d.ts} +9 -1
  43. package/dist/{types-CZHPdVkg.d.cts → types-C6z04Mxr.d.cts} +3 -3
  44. package/dist/{types-DY8xKheW.d.ts → types-CkcNYx1Q.d.ts} +2 -2
  45. package/dist/{types-_wdHzVG-.d.ts → types-DwVhPqOZ.d.ts} +2 -2
  46. package/dist/{types-WMqs5xII.d.cts → types-JpkrtFbZ.d.cts} +2 -2
  47. package/dist/utils/index.d.cts +1 -1
  48. package/dist/utils/index.d.ts +1 -1
  49. package/dist/{x402-client-BQKDeNxq.d.cts → x402-client-B8zdDeat.d.cts} +2 -2
  50. package/dist/{x402-client-BQKDeNxq.d.ts → x402-client-B8zdDeat.d.ts} +2 -2
  51. package/package.json +7 -6
@@ -1,6 +1,6 @@
1
- "use strict";var At=Object.create;var re=Object.defineProperty;var bt=Object.getOwnPropertyDescriptor;var vt=Object.getOwnPropertyNames;var wt=Object.getPrototypeOf,St=Object.prototype.hasOwnProperty;var xt=(e,t)=>{for(var r in t)re(e,r,{get:t[r],enumerable:!0})},Fe=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of vt(t))!St.call(e,i)&&i!==r&&re(e,i,{get:()=>t[i],enumerable:!(n=bt(t,i))||n.enumerable});return e};var We=(e,t,r)=>(r=e!=null?At(wt(e)):{},Fe(t||!e||!e.__esModule?re(r,"default",{value:e,enumerable:!0}):r,e)),Ct=e=>Fe(re({},"__esModule",{value:!0}),e);var Yt={};xt(Yt,{FileChannelLedger:()=>ne,FileVoucherStore:()=>be,InMemoryChannelLedger:()=>B,InMemoryVoucherStore:()=>Ae,InvalidRegistrationError:()=>E,InvalidVoucherError:()=>S,InvalidVoucherSignatureError:()=>_,OnChainVerificationError:()=>N,RedisChannelLedger:()=>ae,ScopeViolationError:()=>x,TAB_VOUCHER_HEADER:()=>I,deserializeChannelLedgerEntry:()=>oe,enforceScope:()=>pe,openSse:()=>st,parseRegistration:()=>ue,requireTab:()=>it,serializeChannelLedgerEntry:()=>se,tabChallengeMiddleware:()=>gt,tabMiddleware:()=>fe,tabOrExactMiddleware:()=>yt,verifyRegistrationOnChain:()=>me,verifyVoucherSignature:()=>de});module.exports=Ct(Yt);var S=class extends Error{constructor(r,n){super(`Invalid voucher: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="InvalidVoucherError"}};var L=require("fs"),ie=require("path"),je=new Map;function P(e,t){let n=(je.get(e)??Promise.resolve()).then(()=>t(),()=>t());return je.set(e,n.then(()=>{},()=>{})),n}var B=class{map=new Map;async get(t){return this.map.get(t)??null}async set(t,r){this.map.set(t,r)}async delete(t){this.map.delete(t)}async tryAcquireLease(t,r){return P(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 P(t,async()=>{let r=this.map.get(t);r&&this.map.set(t,{...r,lease:void 0})})}};function Ue(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 se(e){return Xe(e)}function oe(e){return Je(e)}function Xe(e){return{lastVoucher:e.lastVoucher?{payload:e.lastVoucher.payload,sessionPublicKey:Ue(e.lastVoucher.sessionPublicKey),sessionRegistration:Ue(e.lastVoucher.sessionRegistration),sessionSignature:Ue(e.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:e.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:e.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:e.gateRefusedCumulativeAtomic,onChain:e.onChain,lease:e.lease}}function Je(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 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(0,ie.join)(this.dir,`${t}.json`)}async get(t){try{let r=await L.promises.readFile(this.pathFor(t),"utf8");return Je(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(t,r){let n=this.pathFor(t);await L.promises.mkdir((0,ie.dirname)(n),{recursive:!0});let i=`${n}.tmp`;await L.promises.writeFile(i,JSON.stringify(Xe(r))),await L.promises.rename(i,n)}async delete(t){try{await L.promises.unlink(this.pathFor(t))}catch(r){if(r?.code!=="ENOENT")throw r}}async tryAcquireLease(t,r){return P(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 P(t,async()=>{let r=await this.get(t);r&&await this.set(t,{...r,lease:void 0})})}};var Ge=require("crypto");var Et='if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end',ae=class{constructor(t,r="tab:"){this.client=t;this.keyPrefix=r}leaseTokens=new Map;ledgerKey(t){return`${this.keyPrefix}ledger:${t}`}leaseKey(t){return`${this.keyPrefix}lease:${t}`}async get(t){let r=await this.client.get(this.ledgerKey(t));return r===null?null:oe(JSON.parse(r))}async set(t,r){let n=se({...r,lease:void 0});await this.client.set(this.ledgerKey(t),JSON.stringify(n))}async delete(t){this.leaseTokens.delete(t),await this.client.del(this.ledgerKey(t),this.leaseKey(t))}async tryAcquireLease(t,r){let n=(0,Ge.randomUUID)();return await this.client.set(this.leaseKey(t),n,"PX",Math.max(1,Math.floor(r)),"NX")!=="OK"?!1:(this.leaseTokens.set(t,n),!0)}async releaseLease(t){let r=this.leaseTokens.get(t);r!==void 0&&(this.leaseTokens.delete(t),await this.client.eval(Et,1,this.leaseKey(t),r))}};var nt=require("@solana/web3.js");var Ze=We(require("tweetnacl"),1),Tt=require("@noble/hashes/sha256"),Pt=require("@noble/curves/p256"),ce=require("@solana/web3.js");var $=require("@dexterai/vault/messages");var Ve=require("@dexterai/vault/instructions"),Rt=require("@dexterai/vault/precompile"),M=require("@dexterai/vault/constants");var le=require("@dexterai/vault/session"),Le="OTS_SESSION_REGISTER_V2",E=class extends Error{constructor(r,n){super(`Invalid registration: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="InvalidRegistrationError"}};function ue(e){if(e.length!==188)throw new E("wrong_length",`expected 188, got ${e.length}`);let t=new TextDecoder().decode(e.slice(0,Le.length));if(t!==Le)throw new E("wrong_domain",`got "${t}"`);for(let y=Le.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 ce.PublicKey(e.slice(32,64)),i=new ce.PublicKey(e.slice(64,96)),s=e.slice(96,128),h=r.getBigUint64(128,!0),c=r.getBigInt64(136,!0),a=new ce.PublicKey(e.slice(144,176)),m=r.getUint32(176,!0),l=r.getBigUint64(180,!0);if(!n.equals(M.DEXTER_VAULT_PROGRAM_ID))throw new E("wrong_program",`${n.toBase58()} is not ${M.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 N=class extends Error{constructor(r,n){super(`On-chain verification failed: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="OnChainVerificationError"}};async function me(e,t){let r=await(0,le.fetchSessionAccount)(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(!(0,le.isSessionLive)(r))throw new N("session_not_active","SessionAccount PDA is present but expired");if(!_t(r.session.sessionPubkey,t.sessionPubkey))throw new N("session_pubkey_mismatch",`on-chain ${Ye(r.session.sessionPubkey)} != registration ${Ye(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 de(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(!Ze.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 pe(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 _t(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 Ye(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}var It=require("@solana/web3.js"),Ot=require("@noble/hashes/utils");var Nt=We(require("tweetnacl"),1);var kt=require("@noble/hashes/sha256");var Qe="https://x402.dexter.cash",et=6;function R(e,t=et){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=et){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 ge=require("@noble/hashes/utils"),Ut=15e3,$t=["claim_already_exists","non_monotonic_cumulative"],Vt="below_lock_cadence";function he(e){return typeof e=="string"&&e.includes(Vt)}function Lt(e){return`${e.slice(0,16)}\u2026`}function tt(e,t,r,n){let i=Lt(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(he(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($t.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 Be(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 tt(t,s.payload.cumulativeAmount,s.payload.sequenceNumber,c),c}let h=c=>(tt(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,ge.bytesToHex)(s.sessionPublicKey),sessionSignature:(0,ge.bytesToHex)(s.sessionSignature),sessionRegistration:(0,ge.bytesToHex)(s.sessionRegistration),network:n},m=await i(c,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(a),signal:AbortSignal.timeout(Ut)}),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 rt(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 Be(e,t,r,n,s.fetchImpl);return o.crystallized&&m!==void 0?(e.lastCrystallizedCumulativeAtomic=m,e.gateRefusedCumulativeAtomic=void 0):he(o.error)&&m!==void 0&&(e.gateRefusedCumulativeAtomic=m),o}var I="x-tab-voucher",Me=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)}},De=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 Bt(e){if(typeof e!="string"||e.length===0)throw new S("signature_invalid",`missing ${I} header`);let t;try{t=Buffer.from(e,"base64").toString("utf8")}catch{throw new S("signature_invalid","malformed base64")}let r;try{r=JSON.parse(t)}catch{throw new S("signature_invalid","malformed JSON")}if(!r||typeof r!="object"||!r.payload||!r.sessionPublicKey)throw new S("signature_invalid","missing required fields");return{payload:r.payload,sessionPublicKey:ye(r.sessionPublicKey),sessionRegistration:ye(r.sessionRegistration),sessionSignature:ye(r.sessionSignature)}}function ye(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 Mt(e){if(!/^[0-9a-f]{64}$/i.test(e))throw new S("signature_invalid",`channelId must be 64-char hex, got "${e}"`);return ye(e)}function fe(e){let t=e.ledger??new B,r=new Me,n=typeof e.sellerPubkey=="string"?new nt.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=Bt(c.headers[I]),o=l.payload.channelId,y=Mt(o),d=r.get(o),f=null;if(!d){let p=ue(l.sessionRegistration);f=(await me(e.connection,p))?.frontierAtomic??null;let v=await t.get(o);d={registration:p,lastCumulativeAtomic:v?.lastVoucher?.payload.cumulativeAmount??"0"},r.set(o,d)}de(l,y),pe({registration:d.registration,voucher:l,expectedCounterparty:n,previousCumulativeAtomic:d.lastCumulativeAtomic});let b=BigInt(l.payload.cumulativeAmount),K=BigInt(d.lastCumulativeAtomic),z=b-K;if(z>i)throw new x("cumulative_exceeds_cap",`single voucher increment ${z} exceeds maxPerVoucherAtomic ${i}`);let Ie=e.leaseTtlMs??3e5;if(!await t.tryAcquireLease(o,Ie))throw new S("channel_busy","another stream is live on this channel; tabs serve one stream at a time");let H=!1,ee=()=>{H||(H=!0,t.releaseLease(o).catch(p=>{console.error("[tab/seller] failed to release channel lease:",p)}))};a.on("close",ee),a.on("finish",ee);let Oe=async p=>{let T=p.lastCrystallizedCumulativeAtomic??"0",v=p.gateRefusedCumulativeAtomic;await rt(p,o,s,e.network,h),(p.lastCrystallizedCumulativeAtomic!==T||p.gateRefusedCumulativeAtomic!==v)&&await P(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)})},te=!1,u=()=>{!h.onClose||te||(te=!0,(async()=>{let p=await t.get(o);if(!p||!p.lastVoucher)return;let T=p.lastVoucher.payload.cumulativeAmount;if(p.gateRefusedCumulativeAtomic!==void 0&&BigInt(T)<=BigInt(p.gateRefusedCumulativeAtomic))return;let v=await Be(p,o,s,e.network);v.crystallized?await P(o,async()=>{let w=await t.get(o);w&&await t.set(o,{...w,lastCrystallizedCumulativeAtomic:T,gateRefusedCumulativeAtomic:void 0})}):he(v.error)&&await P(o,async()=>{let w=await t.get(o);w&&await t.set(o,{...w,gateRefusedCumulativeAtomic:T})})})().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 O=C!==null?BigInt(C):g?BigInt(g.deliveredCumulativeAtomic):0n;await P(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 U=new De(o,e.network,b,O,async p=>{let T=null;await P(o,async()=>{let v=await t.get(o),w=v?BigInt(v.deliveredCumulativeAtomic):0n,He=BigInt(p),ft=He>0n?w+He:w,qe={...v,lastVoucher:v?.lastVoucher??l,deliveredCumulativeAtomic:ft.toString(),lastCrystallizedCumulativeAtomic:v?.lastCrystallizedCumulativeAtomic??"0"};await t.set(o,qe),T=qe}),T&&Oe(T).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 S||l instanceof E||l instanceof N||l instanceof _||l instanceof x){a.status(402).json({error:"invalid_voucher",reason:l.reason??"unknown",detail:l.message});return}m(l)}}}function it(e){if(!e.tab)throw new Error("req.tab is missing \u2014 did tabMiddleware run on this route?");return e.tab}function st(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(/\\/g,"\\\\").replace(/\n/g,"\\n");e.write(`data: ${b}
1
+ "use strict";var Et=Object.create;var oe=Object.defineProperty;var Ct=Object.getOwnPropertyDescriptor;var Rt=Object.getOwnPropertyNames;var Pt=Object.getPrototypeOf,Tt=Object.prototype.hasOwnProperty;var It=(t,e)=>{for(var n in e)oe(t,n,{get:e[n],enumerable:!0})},Xe=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Rt(e))!Tt.call(t,i)&&i!==n&&oe(t,i,{get:()=>e[i],enumerable:!(r=Ct(e,i))||r.enumerable});return t};var je=(t,e,n)=>(n=t!=null?Et(Pt(t)):{},Xe(e||!t||!t.__esModule?oe(n,"default",{value:t,enumerable:!0}):n,t)),Vt=t=>Xe(oe({},"__esModule",{value:!0}),t);var mn={};It(mn,{FileChannelLedger:()=>se,FileVoucherStore:()=>we,InMemoryChannelLedger:()=>L,InMemoryVoucherStore:()=>be,InvalidRegistrationError:()=>R,InvalidVoucherError:()=>S,InvalidVoucherSignatureError:()=>C,OnChainVerificationError:()=>V,RedisChannelLedger:()=>ue,ScopeViolationError:()=>_,TAB_VOUCHER_HEADER:()=>O,deserializeChannelLedgerEntry:()=>le,enforceScope:()=>ge,openSse:()=>ct,parseRegistration:()=>W,requireTab:()=>at,serializeChannelLedgerEntry:()=>ce,tabChallengeMiddleware:()=>wt,tabMiddleware:()=>ve,tabOrExactMiddleware:()=>xt,verifyRegistrationOnChain:()=>de,verifyVoucherSignature:()=>pe});module.exports=Vt(mn);var S=class extends Error{constructor(n,r){super(`Invalid voucher: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="InvalidVoucherError"}reason};var $=require("fs"),ae=require("path"),Je=new Map;function I(t,e){let r=(Je.get(t)??Promise.resolve()).then(()=>e(),()=>e());return Je.set(t,r.then(()=>{},()=>{})),r}var L=class{map=new Map;async get(e){return this.map.get(e)??null}async set(e,n){this.map.set(e,n)}async delete(e){this.map.delete(e)}async tryAcquireLease(e,n){return I(e,async()=>{let r=this.map.get(e),i=Date.now();if(r?.lease&&r.lease.heldUntilUnixMs>i)return!1;let o=r??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return this.map.set(e,{...o,lease:{heldUntilUnixMs:i+n}}),!0})}async releaseLease(e){await I(e,async()=>{let n=this.map.get(e);n&&this.map.set(e,{...n,lease:void 0})})}};function Be(t){let e="";for(let n of t)e+=n.toString(16).padStart(2,"0");return e}function De(t){if(t.length%2!==0)throw new Error(`hex length must be even, got ${t.length}`);let e=new Uint8Array(t.length/2);for(let n=0;n<e.length;n++)e[n]=parseInt(t.substr(n*2,2),16);return e}function ce(t){return Ge(t)}function le(t){return Ye(t)}function Ge(t){return{lastVoucher:t.lastVoucher?{payload:t.lastVoucher.payload,sessionPublicKey:Be(t.lastVoucher.sessionPublicKey),sessionRegistration:Be(t.lastVoucher.sessionRegistration),sessionSignature:Be(t.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:t.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:t.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:t.gateRefusedCumulativeAtomic,onChain:t.onChain,lease:t.lease}}function Ye(t){return{lastVoucher:t.lastVoucher?{payload:t.lastVoucher.payload,sessionPublicKey:De(t.lastVoucher.sessionPublicKey),sessionRegistration:De(t.lastVoucher.sessionRegistration),sessionSignature:De(t.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:t.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:t.lastCrystallizedCumulativeAtomic??"0",gateRefusedCumulativeAtomic:t.gateRefusedCumulativeAtomic,onChain:t.onChain,lease:t.lease}}var se=class{constructor(e){this.dir=e}dir;pathFor(e){if(!/^[a-z0-9_-]+$/i.test(e))throw new Error(`unsafe channelId for filesystem: ${e}`);return(0,ae.join)(this.dir,`${e}.json`)}async get(e){try{let n=await $.promises.readFile(this.pathFor(e),"utf8");return Ye(JSON.parse(n))}catch(n){if(n?.code==="ENOENT")return null;throw n}}async set(e,n){let r=this.pathFor(e);await $.promises.mkdir((0,ae.dirname)(r),{recursive:!0});let i=`${r}.tmp`;await $.promises.writeFile(i,JSON.stringify(Ge(n))),await $.promises.rename(i,r)}async delete(e){try{await $.promises.unlink(this.pathFor(e))}catch(n){if(n?.code!=="ENOENT")throw n}}async tryAcquireLease(e,n){return I(e,async()=>{let r=await this.get(e),i=Date.now();if(r?.lease&&r.lease.heldUntilUnixMs>i)return!1;let o=r??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return await this.set(e,{...o,lease:{heldUntilUnixMs:i+n}}),!0})}async releaseLease(e){await I(e,async()=>{let n=await this.get(e);n&&await this.set(e,{...n,lease:void 0})})}};var Ze=require("crypto");var Nt='if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end',ue=class{constructor(e,n="tab:"){this.client=e;this.keyPrefix=n}client;keyPrefix;leaseTokens=new Map;ledgerKey(e){return`${this.keyPrefix}ledger:${e}`}leaseKey(e){return`${this.keyPrefix}lease:${e}`}async get(e){let n=await this.client.get(this.ledgerKey(e));return n===null?null:le(JSON.parse(n))}async set(e,n){let r=ce({...n,lease:void 0});await this.client.set(this.ledgerKey(e),JSON.stringify(r))}async delete(e){this.leaseTokens.delete(e),await this.client.del(this.ledgerKey(e),this.leaseKey(e))}async tryAcquireLease(e,n){let r=(0,Ze.randomUUID)();return await this.client.set(this.leaseKey(e),r,"PX",Math.max(1,Math.floor(n)),"NX")!=="OK"?!1:(this.leaseTokens.set(e,r),!0)}async releaseLease(e){let n=this.leaseTokens.get(e);n!==void 0&&(this.leaseTokens.delete(e),await this.client.eval(Nt,1,this.leaseKey(e),n))}};var st=require("@solana/web3.js");var et=je(require("tweetnacl"),1),kt=require("@noble/hashes/sha256"),Ut=require("@noble/curves/p256"),me=require("@solana/web3.js");var x=require("@dexterai/vault/messages");var Ke=require("@dexterai/vault/instructions"),Ot=require("@dexterai/vault/precompile"),B=require("@dexterai/vault/constants");var D=require("@dexterai/vault/session"),M=require("@dexterai/vault/messages"),$e="OTS_SESSION_REGISTER_V2",R=class extends Error{constructor(n,r){super(`Invalid registration: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="InvalidRegistrationError"}reason};function W(t){if(t.length!==188)throw new R("wrong_length",`expected 188, got ${t.length}`);let e=new TextDecoder().decode(t.slice(0,$e.length));if(e!==$e)throw new R("wrong_domain",`got "${e}"`);for(let s=$e.length;s<32;s++)if(t[s]!==0)throw new R("wrong_domain",`non-NUL padding at byte ${s}`);let n=new DataView(t.buffer,t.byteOffset,t.byteLength),r=new me.PublicKey(t.slice(32,64)),i=new me.PublicKey(t.slice(64,96)),o=t.slice(96,128),u=n.getBigUint64(128,!0),c=n.getBigInt64(136,!0),a=new me.PublicKey(t.slice(144,176)),d=n.getUint32(176,!0),l=n.getBigUint64(180,!0);if(!r.equals(B.DEXTER_VAULT_PROGRAM_ID))throw new R("wrong_program",`${r.toBase58()} is not ${B.DEXTER_VAULT_PROGRAM_ID.toBase58()}`);if(u===0n)throw new R("cap_zero");return{programId:r,vaultPda:i,sessionPubkey:new Uint8Array(o),maxAmount:u,expiresAt:c,allowedCounterparty:a,nonce:d,maxRevolvingCapacity:l}}var V=class extends Error{constructor(n,r){super(`On-chain verification failed: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="OnChainVerificationError"}reason};async function de(t,e){let n=await(0,D.fetchSessionAccount)(t,e.vaultPda,e.allowedCounterparty,e.programId);if(!n||n.version===0)throw new V("session_not_active","no live SessionAccount PDA for this (vault, counterparty) \u2014 revoked, expiry-swept, or never registered");if(!(0,D.isSessionLive)(n))throw new V("session_not_active","SessionAccount PDA is present but expired");if(!tt(n.session.sessionPubkey,e.sessionPubkey))throw new V("session_pubkey_mismatch",`on-chain ${Qe(n.session.sessionPubkey)} != registration ${Qe(e.sessionPubkey)}`);let[r]=(0,D.deriveSessionPda)(e.vaultPda,e.allowedCounterparty,e.programId),i=Number.isSafeInteger(n.session.expiresAt)&&BigInt(n.session.expiresAt)===e.expiresAt;if(!(n.address===r.toBase58()&&n.vault===e.vaultPda.toBase58()&&n.session.maxAmount===e.maxAmount&&i&&n.session.allowedCounterparty===e.allowedCounterparty.toBase58()&&n.session.nonce===e.nonce&&n.session.maxRevolvingCapacity===e.maxRevolvingCapacity))throw new V("registration_state_mismatch","188-byte registration does not exactly match the active SessionAccount immutable fields");let u=n.session.spent,c=n.session.crystallizedCumulative;return{frontierAtomic:(u>c?u:c).toString(),spentAtomic:u.toString(),crystallizedCumulativeAtomic:c.toString()}}var C=class extends Error{constructor(e){super(`Invalid voucher signature${e?`: ${e}`:""}`),this.name="InvalidVoucherSignatureError"}};function pe(t,e){if(e.length!==32)throw new C(`channelIdBytes must be 32 bytes, got ${e.length}`);if(t.sessionPublicKey.length!==32)throw new C(`sessionPublicKey must be 32 bytes, got ${t.sessionPublicKey.length}`);if(t.sessionSignature.length!==64)throw new C(`sessionSignature must be 64 bytes, got ${t.sessionSignature.length}`);let n=W(t.sessionRegistration);if(!tt(n.sessionPubkey,t.sessionPublicKey))throw new C("registration session key does not match voucher session key");let r=n.nonce>=2147483648,i;if(r){(0,M.sessionVoucherV2AuthorizationNonce)(n.nonce),(0,M.voucherV2SequenceOrdinal)(t.payload.sequenceNumber);let[u]=(0,D.deriveSessionPda)(n.vaultPda,n.allowedCounterparty,n.programId);i=(0,M.contextBoundVoucherV2Message)({programId:n.programId,vaultPda:n.vaultPda,sessionPda:u,seller:n.allowedCounterparty,sessionNonce:n.nonce,channelId:e,cumulativeAmount:BigInt(t.payload.cumulativeAmount),sequenceNumber:t.payload.sequenceNumber})}else i=(0,x.voucherPayloadMessage)({channelId:e,cumulativeAmount:BigInt(t.payload.cumulativeAmount),sequenceNumber:t.payload.sequenceNumber});if(!et.default.sign.detached.verify(i,t.sessionSignature,t.sessionPublicKey))throw new C("ed25519 verify rejected")}var _=class extends Error{constructor(n,r){super(`Scope violation: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="ScopeViolationError"}reason};function ge(t){let e=BigInt(t.voucher.payload.cumulativeAmount);if(e>t.registration.maxAmount)throw new _("cumulative_exceeds_cap",`${e} > ${t.registration.maxAmount}`);let n=BigInt(Math.floor(Date.now()/1e3));if(n>=t.registration.expiresAt)throw new _("session_expired",`now=${n} >= expiresAt=${t.registration.expiresAt}`);if(!t.registration.allowedCounterparty.equals(t.expectedCounterparty))throw new _("wrong_counterparty",`${t.registration.allowedCounterparty.toBase58()} != ${t.expectedCounterparty.toBase58()}`);if(t.previousCumulativeAtomic!==void 0){let r=BigInt(t.previousCumulativeAtomic);if(e<=r)throw new _("non_monotonic",`cumulative=${e} not > previous=${r}`)}}function tt(t,e){if(t.length!==e.length)return!1;for(let n=0;n<t.length;n++)if(t[n]!==e[n])return!1;return!0}function Qe(t){let e="";for(let n of t)e+=n.toString(16).padStart(2,"0");return e}var Ft=require("@solana/web3.js"),zt=require("@noble/hashes/utils");var Bt=je(require("tweetnacl"),1),Dt=require("@solana/web3.js"),he=require("@dexterai/vault/messages"),Kt=require("@dexterai/vault/session");var $t=require("@noble/hashes/sha256");var En=(1n<<64n)-1n;var Lt=require("@noble/hashes/sha256"),Mt=require("@noble/hashes/utils");var qt="dexter-native-tab-v2-reservation/v1",Rn=`${qt}:`;var Ht=require("@dexterai/vault/session");var nt="https://x402.dexter.cash",rt=6;function P(t,e=rt){if(!/^\d+(\.\d+)?$/.test(t))throw new Error(`amount must be a non-negative decimal string, got "${t}"`);let[n,r=""]=t.split(".");if(r.length>e)throw new Error(`amount "${t}" has more than ${e} decimals`);let i=r.padEnd(e,"0"),o=`${n}${i}`.replace(/^0+(?=\d)/,"");return o===""?"0":o}function K(t,e=rt){if(!/^\d+$/.test(t))throw new Error(`atomic must be a non-negative integer string, got "${t}"`);let n=t.padStart(e+1,"0"),r=n.slice(0,-e).replace(/^0+(?=\d)/,"")||"0",i=n.slice(-e).replace(/0+$/,"");return i?`${r}.${i}`:r}var fe=require("@noble/hashes/utils"),Wt=15e3,Xt=["claim_already_exists","non_monotonic_cumulative"],jt="below_lock_cadence";function ye(t){return typeof t=="string"&&t.includes(jt)}function Jt(t){return`${t.slice(0,16)}\u2026`}function it(t,e,n,r){let i=Jt(t);if(r.crystallized){console.info(`[tab/seller] crystallize OK channel=${i} cumulative=${e} seq=${n}${r.claimPda?` claimPda=${r.claimPda}`:""} \u2014 LockVoucher landed`);return}if(r.error){if(ye(r.error)){console.warn(`[tab/seller] crystallize refused below the facilitator's cadence gate channel=${i} cumulative=${e} seq=${n}: ${r.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(Xt.some(o=>r.error.includes(o))){console.warn(`[tab/seller] crystallize duplicate channel=${i} cumulative=${e} seq=${n}: ${r.error} \u2014 voucher already secured on-chain (benign, no action)`);return}console.error(`[tab/seller] crystallize FAILED channel=${i} cumulative=${e} seq=${n}: ${r.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 Le(t,e,n,r,i=fetch){let o=t.lastVoucher;if(!o)return{crystallized:!1};if(o.payload.channelId!==e){let c={crystallized:!1,error:"channel_id_mismatch"};return it(e,o.payload.cumulativeAmount,o.payload.sequenceNumber,c),c}let u=c=>(it(e,o.payload.cumulativeAmount,o.payload.sequenceNumber,c),c);try{let c=`${n.replace(/\/$/,"")}/tab/lock`,a={channelId:o.payload.channelId,cumulativeAmount:o.payload.cumulativeAmount,sequenceNumber:o.payload.sequenceNumber,sessionPublicKey:(0,fe.bytesToHex)(o.sessionPublicKey),sessionSignature:(0,fe.bytesToHex)(o.sessionSignature),sessionRegistration:(0,fe.bytesToHex)(o.sessionRegistration),network:r},d=await i(c,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(a),signal:AbortSignal.timeout(Wt)}),l=await d.text();if(!d.ok)return u({crystallized:!1,error:`tab lock ${d.status}: ${l.slice(0,200)}`});let s;try{let y=JSON.parse(l);y&&typeof y.claimPda=="string"&&(s=y.claimPda)}catch{}return u({crystallized:!0,claimPda:s})}catch(c){return u({crystallized:!1,error:String(c?.message??c)})}}async function ot(t,e,n,r,i,o={}){let u=BigInt(t.deliveredCumulativeAtomic),c=BigInt(t.lastCrystallizedCumulativeAtomic??"0"),a=BigInt(i.thresholdAtomic);if(u-c<a)return{crystallized:!1};let d=t.lastVoucher?.payload.cumulativeAmount,l=t.gateRefusedCumulativeAtomic;if(d!==void 0&&l!==void 0&&BigInt(d)<=BigInt(l))return{crystallized:!1};let s=await Le(t,e,n,r,o.fetchImpl);return s.crystallized&&d!==void 0?(t.lastCrystallizedCumulativeAtomic=d,t.gateRefusedCumulativeAtomic=void 0):ye(s.error)&&d!==void 0&&(t.gateRefusedCumulativeAtomic=d),s}var O="x-tab-voucher",Me=class{map=new Map;get(e){return this.map.get(e)}set(e,n){this.map.set(e,n)}update(e,n){let r=this.map.get(e);r&&(r.lastCumulativeAtomic=n)}delete(e){this.map.delete(e)}},qe=class{constructor(e,n,r,i,o,u){this.recordDeliveredImpl=o;this.chargeImpl=u;this.channelId=e,this.network=n,this.cumulativeAtomic=r,this.deliveredBaselineAtomic=i}recordDeliveredImpl;chargeImpl;channelId;network;sessionPublicKey=null;cumulativeAtomic;deliveredBaselineAtomic;cumulative(){return K(this.cumulativeAtomic.toString())}deliveredCumulative(){return K(this.deliveredBaselineAtomic.toString())}async recordDelivered(e){return this.recordDeliveredImpl(e)}bumpCumulative(e){this.cumulativeAtomic=e}setSessionPublicKey(e){this.sessionPublicKey=e}async charge(e){return this.chargeImpl(e)}};function Gt(t){if(typeof t!="string"||t.length===0)throw new S("signature_invalid",`missing ${O} header`);let e;try{e=Buffer.from(t,"base64").toString("utf8")}catch{throw new S("signature_invalid","malformed base64")}let n;try{n=JSON.parse(e)}catch{throw new S("signature_invalid","malformed JSON")}if(!n||typeof n!="object"||!n.payload||!n.sessionPublicKey)throw new S("signature_invalid","missing required fields");return{payload:n.payload,sessionPublicKey:Ae(n.sessionPublicKey),sessionRegistration:Ae(n.sessionRegistration),sessionSignature:Ae(n.sessionSignature)}}function Ae(t){if(typeof t!="string"||t.length%2!==0)throw new S("signature_invalid",`bad hex: ${typeof t}`);let e=new Uint8Array(t.length/2);for(let n=0;n<e.length;n++)e[n]=parseInt(t.substr(n*2,2),16);return e}function Yt(t){if(!/^[0-9a-f]{64}$/i.test(t))throw new S("signature_invalid",`channelId must be 64-char hex, got "${t}"`);return Ae(t)}function ve(t){let e=t.ledger??new L,n=new Me,r=typeof t.sellerPubkey=="string"?new st.PublicKey(t.sellerPubkey):t.sellerPubkey,i=t.maxPerVoucherAtomic?BigInt(t.maxPerVoucherAtomic):BigInt(P(t.perUnit))*100n,o=t.facilitatorUrl??nt,u={thresholdAtomic:t.lockCadence?.thresholdAtomic??P("0.10"),onClose:t.lockCadence?.onClose??!0};return async(c,a,d)=>{try{let l=Gt(c.headers[O]),s=l.payload.channelId,y=Yt(s),p=n.get(s),f=null;if(p){if(!Zt(p.registrationBytes,l.sessionRegistration))throw new C("voucher registration does not match the channel's verified registration")}else{let g=W(l.sessionRegistration);f=(await de(t.connection,g))?.frontierAtomic??null;let b=await e.get(s);p={registration:g,registrationBytes:l.sessionRegistration.slice(),lastCumulativeAtomic:b?.lastVoucher?.payload.cumulativeAmount??"0"},n.set(s,p)}pe(l,y),ge({registration:p.registration,voucher:l,expectedCounterparty:r,previousCumulativeAtomic:p.lastCumulativeAtomic});let v=BigInt(l.payload.cumulativeAmount),F=BigInt(p.lastCumulativeAtomic),z=v-F;if(z>i)throw new _("cumulative_exceeds_cap",`single voucher increment ${z} exceeds maxPerVoucherAtomic ${i}`);let ke=t.leaseTtlMs??3e5;if(!await e.tryAcquireLease(s,ke))throw new S("channel_busy","another stream is live on this channel; tabs serve one stream at a time");let H=!1,re=()=>{H||(H=!0,e.releaseLease(s).catch(g=>{console.error("[tab/seller] failed to release channel lease:",g)}))};a.on("close",re),a.on("finish",re);let Ue=async g=>{let T=g.lastCrystallizedCumulativeAtomic??"0",b=g.gateRefusedCumulativeAtomic;await ot(g,s,o,t.network,u),(g.lastCrystallizedCumulativeAtomic!==T||g.gateRefusedCumulativeAtomic!==b)&&await I(s,async()=>{let w=await e.get(s);w&&await e.set(s,{...w,lastCrystallizedCumulativeAtomic:g.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:g.gateRefusedCumulativeAtomic})}).catch(w=>{console.error(`[tab/seller] crystallize watermark persist FAILED channel=${s.slice(0,16)}\u2026 (expect a benign duplicate/below-cadence warn on the next request):`,w)})},ie=!1,m=()=>{!u.onClose||ie||(ie=!0,(async()=>{let g=await e.get(s);if(!g||!g.lastVoucher)return;let T=g.lastVoucher.payload.cumulativeAmount;if(g.gateRefusedCumulativeAtomic!==void 0&&BigInt(T)<=BigInt(g.gateRefusedCumulativeAtomic))return;let b=await Le(g,s,o,t.network);b.crystallized?await I(s,async()=>{let w=await e.get(s);w&&await e.set(s,{...w,lastCrystallizedCumulativeAtomic:T,gateRefusedCumulativeAtomic:void 0})}):ye(b.error)&&await I(s,async()=>{let w=await e.get(s);w&&await e.set(s,{...w,gateRefusedCumulativeAtomic:T})})})().catch(g=>{console.error(`[tab/seller] close-path crystallize CRASHED channel=${s.slice(0,16)}\u2026 (final voucher NOT locked; exposure unsecured until the next request retries):`,g)}))};a.on("close",m),a.on("finish",m);let h=await e.get(s),A=!h?.lastVoucher&&BigInt(h?.deliveredCumulativeAtomic??"0")===0n,E=f!==null&&A&&BigInt(f)>0n?f:null;E!==null&&console.info(`[tab/seller] channel ${s.slice(0,16)}\u2026 resumed: seeding delivered baseline from chain frontier ${E} (session already settled/locked up to it \u2014 that span is not deliverable budget)`);let k=E!==null?BigInt(E):h?BigInt(h.deliveredCumulativeAtomic):0n;await I(s,async()=>{let g=await e.get(s);await e.set(s,{...g,lastVoucher:l,deliveredCumulativeAtomic:E??(g?g.deliveredCumulativeAtomic:"0"),lastCrystallizedCumulativeAtomic:E??g?.lastCrystallizedCumulativeAtomic??"0"})}),n.update(s,l.payload.cumulativeAmount);let U=new qe(s,t.network,v,k,async g=>{let T=null;await I(s,async()=>{let b=await e.get(s),w=b?BigInt(b.deliveredCumulativeAtomic):0n,He=BigInt(g),_t=He>0n?w+He:w,We={...b,lastVoucher:b?.lastVoucher??l,deliveredCumulativeAtomic:_t.toString(),lastCrystallizedCumulativeAtomic:b?.lastCrystallizedCumulativeAtomic??"0"};await e.set(s,We),T=We}),T&&Ue(T).catch(b=>{console.error(`[tab/seller] crystallize cadence CRASHED channel=${s.slice(0,16)}\u2026 (threshold lock not attempted; retries at the next delivery):`,b)})},async g=>{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,d()}catch(l){if(l instanceof S||l instanceof R||l instanceof V||l instanceof C||l instanceof _){a.status(402).json({error:"invalid_voucher",reason:l.reason??"unknown",detail:l.message});return}d(l)}}}function Zt(t,e){if(t.length!==e.length)return!1;let n=0;for(let r=0;r<t.length;r+=1)n|=t[r]^e[r];return n===0}function at(t){if(!t.tab)throw new Error("req.tab is missing \u2014 did tabMiddleware run on this route?");return t.tab}function ct(t,e){if(!e.tab)throw new Error("openSse requires options.tab");t.headersSent||(t.setHeader("Content-Type","text/event-stream"),t.setHeader("Cache-Control","no-cache"),t.setHeader("Connection","keep-alive"),typeof t.flushHeaders=="function"&&t.flushHeaders());let n=e.tab,r=BigInt(P(n.cumulative())),i=BigInt(P(n.deliveredCumulative())),o=r-i;o<0n&&(o=0n);let u=e.perUnit?BigInt(P(e.perUnit)):null,c=0n,a=!1;async function d(){await n.recordDelivered(c.toString())}t.on("close",()=>{a||(a=!0,d().catch(p=>{console.error("[tab/seller] terminal persist failed on disconnect:",p)}))});async function l(p=1){if(a)throw new Error("meter ended");if(u===null)throw new Error("charge() needs options.perUnit");let f=u*BigInt(p),v=c+f;if(v>o)throw a=!0,await d(),new _("cumulative_exceeds_cap",`chunk would push delivered to ${K((i+v).toString())} beyond signed cumulative ${K(r.toString())} (per-request budget ${K(o.toString())})`);c=v}function s(p){if(a)throw new Error("meter ended");let v=(typeof p=="string"?p:Buffer.from(p).toString("utf8")).replace(/\\/g,"\\\\").replace(/\n/g,"\\n");t.write(`data: ${v}
2
2
 
3
- `)}async function y(){a||(a=!0,await m(),e.write(`event: end
3
+ `)}async function y(){a||(a=!0,await d(),t.write(`event: end
4
4
  data: {"chargedAtomic":"${c}"}
5
5
 
6
- `),e.end())}return{charge:l,send:o,end:y}}var D=require("fs"),ve=require("path");function Dt(e){return{payload:e.payload,sessionPublicKey:Ke(e.sessionPublicKey),sessionRegistration:Ke(e.sessionRegistration),sessionSignature:Ke(e.sessionSignature)}}function Kt(e){return{payload:e.payload,sessionPublicKey:ze(e.sessionPublicKey),sessionRegistration:ze(e.sessionRegistration),sessionSignature:ze(e.sessionSignature)}}function Ke(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}function ze(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 Ae=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)}},be=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,ve.join)(this.dir,`${t}.json`)}async get(t){try{let r=await D.promises.readFile(this.pathFor(t),"utf8");return Kt(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(t,r){let n=this.pathFor(t);await D.promises.mkdir((0,ve.dirname)(n),{recursive:!0});let i=`${n}.tmp`;await D.promises.writeFile(i,JSON.stringify(Dt(r))),await D.promises.rename(i,n)}async delete(t){try{await D.promises.unlink(this.pathFor(t))}catch(r){if(r?.code!=="ENOENT")throw r}}};var pt=require("@solana/web3.js");var k="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",ot="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",at="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";var q="eip155:8453",we="eip155:84532",Se="eip155:42161",xe="eip155:137",Ce="eip155:10",Ee="eip155:43114",Re="eip155:56",F="eip155:480",W="eip155:143",j="eip155:4663",X="eip155:1187947933",J="eip155:324705682",Te="eip155:1";var Pe="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";var ct="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",zt="0x55d398326f99059fF775485246999027B3197955",lt="0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",Ht="0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",ut={[Re]:lt,[q]:ct,[we]:"0x036CbD53842c5426634e7929541eC2318f3dCF7e",[Se]:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831",[xe]:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",[Ce]:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",[Ee]:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",[F]:"0x79A02482A880bCE3F13e09Da970dC34db4CD24d1",[W]:"0x754704Bc059F8C67012fEd69BC8A327a5aafb603",[j]:Ht,[X]:"0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",[J]:"0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",[Te]:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},mt={[zt]:{symbol:"USDT",decimals:18},[lt]:{symbol:"USDC",decimals:18}};var kr={[F]:{name:"USDC",version:"2"},[W]:{name:"USDC",version:"2"},[j]:{name:"Global Dollar",version:"1"},[X]:{name:"Bridged USDC (SKALE Bridge)",version:"2"},[J]:{name:"Bridged USDC (SKALE Bridge)",version:"2"}};var Ir={[Re]:56,[q]:8453,[we]:84532,[Se]:42161,[xe]:137,[Ce]:10,[Ee]:43114,[F]:480,[W]:143,[j]:4663,[X]:1187947933,[J]:324705682,[Te]:1},Or={[k]:"https://api.dexter.cash/api/solana/rpc",[ot]:"https://api.devnet.solana.com",[at]:"https://api.testnet.solana.com"},qt={[Re]:"https://api.dexter.cash/api/evm/bsc/rpc",[q]:"https://api.dexter.cash/api/base/rpc",[we]:"https://sepolia.base.org",[Se]:"https://api.dexter.cash/api/evm/arbitrum/rpc",[xe]:"https://api.dexter.cash/api/evm/polygon/rpc",[Ce]:"https://api.dexter.cash/api/evm/optimism/rpc",[Ee]:"https://api.dexter.cash/api/evm/avalanche/rpc",[F]:"https://worldchain-mainnet.g.alchemy.com/public",[W]:"https://rpc.monad.xyz",[j]:"https://rpc.mainnet.chain.robinhood.com",[X]:"https://skale-base.skalenodes.com/v1/base",[J]:"https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",[Te]:"https://eth.llamarpc.com"},G="https://x402.dexter.cash";function _e(e){return e.startsWith("solana:")||e==="solana"}function Ft(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 Wt(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 Ne(e){return Ft(JSON.stringify(e))}function Y(e){return JSON.parse(Wt(e))}function jt(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 Z=class extends Error{status;body;constructor(t,r){super(`HTTP ${t}`),this.status=t,this.body=r}},ke=class{facilitatorUrl;cachedSupported=null;cacheTime=0;CACHE_TTL_MS=6e4;timeoutMs;maxRetries;retryBaseMs;constructor(t=G,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 Z(s.status,await s.text());return s}catch(s){if(n=s,i<this.maxRetries-1&&jt(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=Y(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 Z?`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=Y(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 Z?`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 Xt(e){if(_e(e))return{address:Pe,decimals:6};let t=ut[e];if(t){let r=mt[t]?.decimals??6;return{address:t,decimals:r}}return{address:Pe,decimals:6}}function dt(e){try{let t=Y(e);return t?.accepted?.amount??t?.accepted?.maxAmountRequired}catch{return}}function Q(e){let{payTo:t,facilitatorUrl:r=G,network:n=k,defaultTimeoutSeconds:i=60}=e,s=e.asset??Xt(n),h=e.scheme??"exact";if(h==="tab"&&!_e(n))throw new Error(`scheme 'tab' is SVM-only; got network "${n}"`);let c=new ke(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,O]of m)O.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)),_e(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 K(u,g){let{amountAtomic:A,timeoutSeconds:C=i}=g,O=await b(),U={scheme:h,network:n,amount:A,maxAmountRequired:A,asset:s.address,payTo:u,maxTimeoutSeconds:C,extra:O};return y(U),U}async function z(u){let g=await f({amountAtomic:u.amountAtomic,resourceUrl:u.resourceUrl});return K(g,u)}async function Ie(u){let{resourceUrl:g,description:A,mimeType:C="application/json"}=u,O={url:g,description:A,mimeType:C},U=await z(u);return{x402Version:2,resource:O,accepts:[U],error:"Payment required"}}function H(u){return Ne(u)}function ee(u){return{status:402,headers:{"PAYMENT-REQUIRED":H(u)},body:{}}}async function Oe(u,g){if(!g){let A=await f({paymentHeader:u});g=d(A),g||(g=await K(A,{amountAtomic:dt(u)??"0",resourceUrl:""}))}return c.verifyPayment(u,g)}async function te(u,g){if(!g){let A=await f({paymentHeader:u});g=d(A),g||(g=await K(A,{amountAtomic:dt(u)??"0",resourceUrl:""}))}return c.settlePayment(u,g)}return{buildRequirements:Ie,encodeRequirements:H,create402Response:ee,verifyPayment:Oe,settlePayment:te,getPaymentAccept:z,network:n,assetDecimals:s.decimals,facilitator:c}}var Jt={"solana:mainnet":k};function gt(e){let t=Jt[e.network];if(!t)throw new Error(`tabChallengeMiddleware: unsupported network "${e.network}"`);let r=typeof e.sellerPubkey=="string"?e.sellerPubkey:e.sellerPubkey.toBase58();new pt.PublicKey(r);let n=Q({payTo:r,network:t,scheme:"tab",facilitatorUrl:e.facilitatorUrl}),i=R(e.perUnit);return async(s,h,c)=>{if(s.headers[I])return c();try{let a=`${s.protocol}://${s.get("host")}${s.originalUrl}`,m=await n.buildRequirements({amountAtomic:i,resourceUrl:a,description:e.description}),l=n.create402Response(m);h.set(l.headers).status(l.status).json(l.body)}catch(a){let m=a?.message??String(a);h.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:m})}}}var ht=require("@solana/web3.js");var Gt={"solana:mainnet":k};function yt(e){let t=Gt[e.network];if(!t)throw new Error(`tabOrExactMiddleware: unsupported network "${e.network}"`);let r=typeof e.sellerPubkey=="string"?e.sellerPubkey:e.sellerPubkey.toBase58();new ht.PublicKey(r);let n=Q({payTo:r,network:t,scheme:"tab",facilitatorUrl:e.facilitatorUrl}),i=Q({payTo:r,network:t,scheme:"exact",facilitatorUrl:e.facilitatorUrl}),s=R(e.perUnit),h=fe({connection:e.connection,sellerPubkey:r,network:e.network,perUnit:e.perUnit,settle:"on-close",facilitatorUrl:e.facilitatorUrl,lockCadence:e.lockCadence});return async(c,a,m)=>{if(c.headers[I])return h(c,a,m);let l=`${c.protocol}://${c.get("host")}${c.originalUrl}`,o=c.headers["payment-signature"];if(o){let y;try{y=await i.getPaymentAccept({amountAtomic:s,resourceUrl:l,description:e.description})}catch(d){let f=d?.message??String(d);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:f});return}try{let d=await i.verifyPayment(o,y);if(!d.isValid){a.status(402).json({error:"Payment verification failed",reason:d.invalidReason});return}let f=await i.settlePayment(o,y);if(!f.success){a.status(402).json({error:"Payment settlement failed",reason:f.errorReason});return}return c.x402={transaction:f.transaction,payer:d.payer??"",network:f.network||t},a.setHeader("PAYMENT-RESPONSE",Ne({success:!0,transaction:f.transaction,network:f.network||t,payer:d.payer??""})),m()}catch{a.status(500).json({error:"Payment processing error"});return}}try{let y={amountAtomic:s,resourceUrl:l,description:e.description},[d,f]=await Promise.all([n.buildRequirements(y),i.buildRequirements(y)]),b={...d,accepts:[...d.accepts,...f.accepts]};a.set({"PAYMENT-REQUIRED":n.encodeRequirements(b)}).status(402).json({error:"Payment required",accepts:b.accepts,resource:b.resource})}catch(y){let d=y?.message??String(y);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:d})}}}0&&(module.exports={FileChannelLedger,FileVoucherStore,InMemoryChannelLedger,InMemoryVoucherStore,InvalidRegistrationError,InvalidVoucherError,InvalidVoucherSignatureError,OnChainVerificationError,RedisChannelLedger,ScopeViolationError,TAB_VOUCHER_HEADER,deserializeChannelLedgerEntry,enforceScope,openSse,parseRegistration,requireTab,serializeChannelLedgerEntry,tabChallengeMiddleware,tabMiddleware,tabOrExactMiddleware,verifyRegistrationOnChain,verifyVoucherSignature});
6
+ `),t.end())}return{charge:l,send:s,end:y}}var q=require("fs"),Se=require("path");function Qt(t){return{payload:t.payload,sessionPublicKey:Fe(t.sessionPublicKey),sessionRegistration:Fe(t.sessionRegistration),sessionSignature:Fe(t.sessionSignature)}}function en(t){return{payload:t.payload,sessionPublicKey:ze(t.sessionPublicKey),sessionRegistration:ze(t.sessionRegistration),sessionSignature:ze(t.sessionSignature)}}function Fe(t){let e="";for(let n of t)e+=n.toString(16).padStart(2,"0");return e}function ze(t){if(t.length%2!==0)throw new Error(`hex length must be even, got ${t.length}`);let e=new Uint8Array(t.length/2);for(let n=0;n<e.length;n++)e[n]=parseInt(t.substr(n*2,2),16);return e}var be=class{map=new Map;async get(e){return this.map.get(e)??null}async set(e,n){this.map.set(e,n)}async delete(e){this.map.delete(e)}},we=class{constructor(e){this.dir=e}dir;pathFor(e){if(!/^[a-z0-9_-]+$/i.test(e))throw new Error(`unsafe channelId for filesystem: ${e}`);return(0,Se.join)(this.dir,`${e}.json`)}async get(e){try{let n=await q.promises.readFile(this.pathFor(e),"utf8");return en(JSON.parse(n))}catch(n){if(n?.code==="ENOENT")return null;throw n}}async set(e,n){let r=this.pathFor(e);await q.promises.mkdir((0,Se.dirname)(r),{recursive:!0});let i=`${r}.tmp`;await q.promises.writeFile(i,JSON.stringify(Qt(n))),await q.promises.rename(i,r)}async delete(e){try{await q.promises.unlink(this.pathFor(e))}catch(n){if(n?.code!=="ENOENT")throw n}}};var bt=require("@solana/web3.js");var N="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",lt="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",ut="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";var X="eip155:8453",xe="eip155:84532",_e="eip155:42161",Ee="eip155:137",Ce="eip155:10",Re="eip155:43114",Pe="eip155:56",j="eip155:480",J="eip155:143",G="eip155:4663",Y="eip155:1187947933",Z="eip155:324705682",Te="eip155:1";var Ie="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";var mt="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",tn="0x55d398326f99059fF775485246999027B3197955",dt="0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",nn="0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",pt={[Pe]:dt,[X]:mt,[xe]:"0x036CbD53842c5426634e7929541eC2318f3dCF7e",[_e]:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831",[Ee]:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",[Ce]:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",[Re]:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",[j]:"0x79A02482A880bCE3F13e09Da970dC34db4CD24d1",[J]:"0x754704Bc059F8C67012fEd69BC8A327a5aafb603",[G]:nn,[Y]:"0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",[Z]:"0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",[Te]:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},gt={[tn]:{symbol:"USDT",decimals:18},[dt]:{symbol:"USDC",decimals:18}};var er={[j]:{name:"USDC",version:"2"},[J]:{name:"USDC",version:"2"},[G]:{name:"Global Dollar",version:"1"},[Y]:{name:"Bridged USDC (SKALE Bridge)",version:"2"},[Z]:{name:"Bridged USDC (SKALE Bridge)",version:"2"}};var tr={[Pe]:56,[X]:8453,[xe]:84532,[_e]:42161,[Ee]:137,[Ce]:10,[Re]:43114,[j]:480,[J]:143,[G]:4663,[Y]:1187947933,[Z]:324705682,[Te]:1},nr={[N]:"https://api.dexter.cash/api/solana/rpc",[lt]:"https://api.devnet.solana.com",[ut]:"https://api.testnet.solana.com"},rn={[Pe]:"https://api.dexter.cash/api/evm/bsc/rpc",[X]:"https://api.dexter.cash/api/base/rpc",[xe]:"https://sepolia.base.org",[_e]:"https://api.dexter.cash/api/evm/arbitrum/rpc",[Ee]:"https://api.dexter.cash/api/evm/polygon/rpc",[Ce]:"https://api.dexter.cash/api/evm/optimism/rpc",[Re]:"https://api.dexter.cash/api/evm/avalanche/rpc",[j]:"https://worldchain-mainnet.g.alchemy.com/public",[J]:"https://rpc.monad.xyz",[G]:"https://rpc.mainnet.chain.robinhood.com",[Y]:"https://skale-base.skalenodes.com/v1/base",[Z]:"https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",[Te]:"https://eth.llamarpc.com"},Q="https://x402.dexter.cash";var ht="dexter-tab-hosted-pay-before-delivery/v1",ft="pay_before_delivery_seller_2xx",yt="x-tab-voucher",At="base64(188-byte sessionRegisterMessage)";function Ve(t){return t.startsWith("solana:")||t==="solana"}function on(t){if(typeof Buffer<"u")return Buffer.from(t,"utf-8").toString("base64");let e=new TextEncoder().encode(t),n="";for(let r=0;r<e.length;r++)n+=String.fromCharCode(e[r]);return btoa(n)}function sn(t){if(typeof Buffer<"u")return Buffer.from(t,"base64").toString("utf-8");let e=atob(t),n=new Uint8Array(e.length);for(let r=0;r<e.length;r++)n[r]=e.charCodeAt(r);return new TextDecoder().decode(n)}function Ne(t){return on(JSON.stringify(t))}function ee(t){return JSON.parse(sn(t))}function an(t){if(t instanceof TypeError)return!0;if(t&&typeof t=="object"&&"status"in t){let e=t.status;return e>=500&&e<600}return!1}var te=class extends Error{status;body;constructor(e,n){super(`HTTP ${e}`),this.status=e,this.body=n}},Oe=class{facilitatorUrl;cachedSupported=null;cacheTime=0;CACHE_TTL_MS=6e4;timeoutMs;maxRetries;retryBaseMs;constructor(e=Q,n){this.facilitatorUrl=e.replace(/\/$/,""),this.timeoutMs=n?.timeoutMs??1e4,this.maxRetries=n?.maxRetries??3,this.retryBaseMs=n?.retryBaseMs??500}async fetchWithTimeout(e,n){let r=new AbortController,i=setTimeout(()=>r.abort(),this.timeoutMs);try{return await fetch(e,{...n,signal:r.signal})}finally{clearTimeout(i)}}async fetchWithRetry(e,n){let r;for(let i=0;i<this.maxRetries;i++)try{let o=await this.fetchWithTimeout(e,n);if(!o.ok&&o.status>=500)throw new te(o.status,await o.text());return o}catch(o){if(r=o,i<this.maxRetries-1&&an(o)){let u=this.retryBaseMs*Math.pow(2,i);await new Promise(c=>setTimeout(c,u));continue}throw o}throw r}async getSupported(){let e=Date.now();if(this.cachedSupported&&e-this.cacheTime<this.CACHE_TTL_MS)return this.cachedSupported;let n=await this.fetchWithTimeout(`${this.facilitatorUrl}/supported`);if(!n.ok)throw new Error(`Facilitator /supported returned ${n.status}`);return this.cachedSupported=await n.json(),this.cacheTime=e,this.cachedSupported}async getFeePayer(e){let r=(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval")&&i.network===e);if(!r)throw new Error(`Facilitator does not support network "${e}" with a recognized scheme`);return r.extra?.feePayer}async getNetworkExtra(e){return(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval"||i.scheme==="batch-settlement")&&i.network===e)?.extra}async verifyPayment(e,n){try{let r=ee(e),i=await this.fetchWithRetry(`${this.facilitatorUrl}/verify`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:r,paymentRequirements:n})});return i.ok?await i.json():{isValid:!1,invalidReason:`facilitator_error_${i.status}`}}catch(r){return{isValid:!1,invalidReason:r instanceof te?`facilitator_error_${r.status}`:r instanceof Error&&r.name==="AbortError"?"facilitator_timeout":r instanceof Error?r.message:"unexpected_verify_error"}}}async settlePayment(e,n){try{let r=ee(e),i=await this.fetchWithRetry(`${this.facilitatorUrl}/settle`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:r,paymentRequirements:n})});return i.ok?{...await i.json(),network:n.network}:{success:!1,network:n.network,errorReason:`facilitator_error_${i.status}`}}catch(r){let i=r instanceof te?`facilitator_error_${r.status}`:r instanceof Error&&r.name==="AbortError"?"facilitator_timeout":r instanceof Error?r.message:"unexpected_settle_error";return{success:!1,network:n.network,errorReason:i}}}};function cn(t){if(Ve(t))return{address:Ie,decimals:6};let e=pt[t];if(e){let n=gt[e]?.decimals??6;return{address:e,decimals:n}}return{address:Ie,decimals:6}}function vt(t){try{let e=ee(t);return e?.accepted?.amount??e?.accepted?.maxAmountRequired}catch{return}}function ne(t){let{payTo:e,facilitatorUrl:n=Q,network:r=N,defaultTimeoutSeconds:i=60}=t,o=t.asset??cn(r),u=t.scheme??"exact";if(u==="tab"&&!Ve(r))throw new Error(`scheme 'tab' is SVM-only; got network "${r}"`);let c=new Oe(n),a=null,d=new Map,l=3e4,s=Date.now();function y(m){let h=(m.maxTimeoutSeconds||i)*1e3;if(d.set(m.payTo,{accept:m,expiresAt:Date.now()+h}),Date.now()-s>l){let A=Date.now();for(let[E,k]of d)k.expiresAt<A&&d.delete(E);s=A}}function p(m){let h=d.get(m);if(h){if(h.expiresAt<Date.now()){d.delete(m);return}return h.accept}}async function f(m){return typeof e=="string"?e:e(m||{})}async function v(){if(a||(a=await c.getNetworkExtra(r)),Ve(r)&&!a?.feePayer)throw new Error(`Facilitator does not provide feePayer for network "${r}"`);return{...a?.feePayer?{feePayer:a.feePayer}:{},decimals:a?.decimals??o.decimals,name:a?.name,version:a?.version,...u==="batch-settlement"&&a?.receiverAuthorizer?{receiverAuthorizer:a.receiverAuthorizer}:{},...u==="tab"?{voucherHeader:yt,registrationEncoding:At,termsVersion:ht,acceptanceRule:ft}:{}}}async function F(m,h){let{amountAtomic:A,timeoutSeconds:E=i}=h,k=await v(),U={scheme:u,network:r,amount:A,maxAmountRequired:A,asset:o.address,payTo:m,maxTimeoutSeconds:E,extra:k};return y(U),U}async function z(m){let h=await f({amountAtomic:m.amountAtomic,resourceUrl:m.resourceUrl});return F(h,m)}async function ke(m){let{resourceUrl:h,description:A,mimeType:E="application/json"}=m,k={url:h,description:A,mimeType:E},U=await z(m);return{x402Version:2,resource:k,accepts:[U],error:"Payment required"}}function H(m){return Ne(m)}function re(m){return{status:402,headers:{"PAYMENT-REQUIRED":H(m)},body:{}}}async function Ue(m,h){if(!h){let A=await f({paymentHeader:m});h=p(A),h||(h=await F(A,{amountAtomic:vt(m)??"0",resourceUrl:""}))}return c.verifyPayment(m,h)}async function ie(m,h){if(!h){let A=await f({paymentHeader:m});h=p(A),h||(h=await F(A,{amountAtomic:vt(m)??"0",resourceUrl:""}))}return c.settlePayment(m,h)}return{buildRequirements:ke,encodeRequirements:H,create402Response:re,verifyPayment:Ue,settlePayment:ie,getPaymentAccept:z,network:r,assetDecimals:o.decimals,facilitator:c}}var ln={"solana:mainnet":N};function wt(t){let e=ln[t.network];if(!e)throw new Error(`tabChallengeMiddleware: unsupported network "${t.network}"`);let n=typeof t.sellerPubkey=="string"?t.sellerPubkey:t.sellerPubkey.toBase58();new bt.PublicKey(n);let r=ne({payTo:n,network:e,scheme:"tab",facilitatorUrl:t.facilitatorUrl}),i=P(t.perUnit);return async(o,u,c)=>{if(o.headers[O])return c();try{let a=`${o.protocol}://${o.get("host")}${o.originalUrl}`,d=await r.buildRequirements({amountAtomic:i,resourceUrl:a,description:t.description}),l=r.create402Response(d);u.set(l.headers).status(l.status).json(l.body)}catch(a){let d=a?.message??String(a);u.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:d})}}}var St=require("@solana/web3.js");var un={"solana:mainnet":N};function xt(t){let e=un[t.network];if(!e)throw new Error(`tabOrExactMiddleware: unsupported network "${t.network}"`);let n=typeof t.sellerPubkey=="string"?t.sellerPubkey:t.sellerPubkey.toBase58();new St.PublicKey(n);let r=ne({payTo:n,network:e,scheme:"tab",facilitatorUrl:t.facilitatorUrl}),i=ne({payTo:n,network:e,scheme:"exact",facilitatorUrl:t.facilitatorUrl}),o=P(t.perUnit),u=ve({connection:t.connection,sellerPubkey:n,network:t.network,perUnit:t.perUnit,settle:"on-close",facilitatorUrl:t.facilitatorUrl,lockCadence:t.lockCadence});return async(c,a,d)=>{if(c.headers[O])return u(c,a,d);let l=`${c.protocol}://${c.get("host")}${c.originalUrl}`,s=c.headers["payment-signature"];if(s){let y;try{y=await i.getPaymentAccept({amountAtomic:o,resourceUrl:l,description:t.description})}catch(p){let f=p?.message??String(p);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:f});return}try{let p=await i.verifyPayment(s,y);if(!p.isValid){a.status(402).json({error:"Payment verification failed",reason:p.invalidReason});return}let f=await i.settlePayment(s,y);if(!f.success){a.status(402).json({error:"Payment settlement failed",reason:f.errorReason});return}return c.x402={transaction:f.transaction,payer:p.payer??"",network:f.network||e},a.setHeader("PAYMENT-RESPONSE",Ne({success:!0,transaction:f.transaction,network:f.network||e,payer:p.payer??""})),d()}catch{a.status(500).json({error:"Payment processing error"});return}}try{let y={amountAtomic:o,resourceUrl:l,description:t.description},[p,f]=await Promise.all([r.buildRequirements(y),i.buildRequirements(y)]),v={...p,accepts:[...p.accepts,...f.accepts]};a.set({"PAYMENT-REQUIRED":r.encodeRequirements(v)}).status(402).json({error:"Payment required",accepts:v.accepts,resource:v.resource})}catch(y){let p=y?.message??String(y);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:p})}}}0&&(module.exports={FileChannelLedger,FileVoucherStore,InMemoryChannelLedger,InMemoryVoucherStore,InvalidRegistrationError,InvalidVoucherError,InvalidVoucherSignatureError,OnChainVerificationError,RedisChannelLedger,ScopeViolationError,TAB_VOUCHER_HEADER,deserializeChannelLedgerEntry,enforceScope,openSse,parseRegistration,requireTab,serializeChannelLedgerEntry,tabChallengeMiddleware,tabMiddleware,tabOrExactMiddleware,verifyRegistrationOnChain,verifyVoucherSignature});
@@ -1,5 +1,5 @@
1
1
  import { SignedVoucher, AtomicAmount, TabNetworkId, HumanAmount } from '@dexterai/vault/types';
2
- import { RequestHandler, Request, Response } from 'express';
2
+ import { Request, RequestHandler, Response } from 'express';
3
3
  import { Connection, PublicKey } from '@solana/web3.js';
4
4
 
5
5
  /**
@@ -448,7 +448,7 @@ declare class FileVoucherStore implements VoucherStore {
448
448
  * Two-layer verification:
449
449
  *
450
450
  * 1. parseRegistration(registrationBytes)
451
- * Parses the 180-byte registration message into a scope. Synchronous,
451
+ * Parses the 188-byte V2 registration message into a scope. Synchronous,
452
452
  * no I/O. This gives the seller everything they need to enforce limits
453
453
  * LOCALLY (cap, expiry, counterparty) and to know which vault to read
454
454
  * for passkey verification.
@@ -489,8 +489,8 @@ declare class InvalidRegistrationError extends Error {
489
489
  */
490
490
  declare function parseRegistration(registration: Uint8Array): ParsedRegistration;
491
491
  declare class OnChainVerificationError extends Error {
492
- readonly reason: 'vault_not_found' | 'session_not_active' | 'session_pubkey_mismatch' | 'wrong_program';
493
- constructor(reason: 'vault_not_found' | 'session_not_active' | 'session_pubkey_mismatch' | 'wrong_program', detail?: string);
492
+ readonly reason: 'vault_not_found' | 'session_not_active' | 'session_pubkey_mismatch' | 'registration_state_mismatch' | 'wrong_program';
493
+ constructor(reason: 'vault_not_found' | 'session_not_active' | 'session_pubkey_mismatch' | 'registration_state_mismatch' | 'wrong_program', detail?: string);
494
494
  }
495
495
  /** The session's on-chain terminal odometers, read as a by-product of the
496
496
  * first-voucher verification. `frontierAtomic` = max(spent, crystallized) —
@@ -1,5 +1,5 @@
1
1
  import { SignedVoucher, AtomicAmount, TabNetworkId, HumanAmount } from '@dexterai/vault/types';
2
- import { RequestHandler, Request, Response } from 'express';
2
+ import { Request, RequestHandler, Response } from 'express';
3
3
  import { Connection, PublicKey } from '@solana/web3.js';
4
4
 
5
5
  /**
@@ -448,7 +448,7 @@ declare class FileVoucherStore implements VoucherStore {
448
448
  * Two-layer verification:
449
449
  *
450
450
  * 1. parseRegistration(registrationBytes)
451
- * Parses the 180-byte registration message into a scope. Synchronous,
451
+ * Parses the 188-byte V2 registration message into a scope. Synchronous,
452
452
  * no I/O. This gives the seller everything they need to enforce limits
453
453
  * LOCALLY (cap, expiry, counterparty) and to know which vault to read
454
454
  * for passkey verification.
@@ -489,8 +489,8 @@ declare class InvalidRegistrationError extends Error {
489
489
  */
490
490
  declare function parseRegistration(registration: Uint8Array): ParsedRegistration;
491
491
  declare class OnChainVerificationError extends Error {
492
- readonly reason: 'vault_not_found' | 'session_not_active' | 'session_pubkey_mismatch' | 'wrong_program';
493
- constructor(reason: 'vault_not_found' | 'session_not_active' | 'session_pubkey_mismatch' | 'wrong_program', detail?: string);
492
+ readonly reason: 'vault_not_found' | 'session_not_active' | 'session_pubkey_mismatch' | 'registration_state_mismatch' | 'wrong_program';
493
+ constructor(reason: 'vault_not_found' | 'session_not_active' | 'session_pubkey_mismatch' | 'registration_state_mismatch' | 'wrong_program', detail?: string);
494
494
  }
495
495
  /** The session's on-chain terminal odometers, read as a by-product of the
496
496
  * first-voucher verification. `frontierAtomic` = max(spent, crystallized) —
@@ -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 M}from"fs";import{join as rt,dirname as nt}from"path";var De=new Map;function P(t,e){let n=(De.get(t)??Promise.resolve()).then(()=>e(),()=>e());return De.set(t,n.then(()=>{},()=>{})),n}var D=class{map=new Map;async get(e){return this.map.get(e)??null}async set(e,r){this.map.set(e,r)}async delete(e){this.map.delete(e)}async tryAcquireLease(e,r){return P(e,async()=>{let n=this.map.get(e),i=Date.now();if(n?.lease&&n.lease.heldUntilUnixMs>i)return!1;let s=n??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return this.map.set(e,{...s,lease:{heldUntilUnixMs:i+r}}),!0})}async releaseLease(e){await P(e,async()=>{let r=this.map.get(e);r&&this.map.set(e,{...r,lease:void 0})})}};function he(t){let e="";for(let r of t)e+=r.toString(16).padStart(2,"0");return e}function ye(t){if(t.length%2!==0)throw new Error(`hex length must be even, got ${t.length}`);let e=new Uint8Array(t.length/2);for(let r=0;r<e.length;r++)e[r]=parseInt(t.substr(r*2,2),16);return e}function Ae(t){return Ke(t)}function be(t){return ze(t)}function Ke(t){return{lastVoucher:t.lastVoucher?{payload:t.lastVoucher.payload,sessionPublicKey:he(t.lastVoucher.sessionPublicKey),sessionRegistration:he(t.lastVoucher.sessionRegistration),sessionSignature:he(t.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:t.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:t.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:t.gateRefusedCumulativeAtomic,onChain:t.onChain,lease:t.lease}}function ze(t){return{lastVoucher:t.lastVoucher?{payload:t.lastVoucher.payload,sessionPublicKey:ye(t.lastVoucher.sessionPublicKey),sessionRegistration:ye(t.lastVoucher.sessionRegistration),sessionSignature:ye(t.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:t.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:t.lastCrystallizedCumulativeAtomic??"0",gateRefusedCumulativeAtomic:t.gateRefusedCumulativeAtomic,onChain:t.onChain,lease:t.lease}}var fe=class{constructor(e){this.dir=e}pathFor(e){if(!/^[a-z0-9_-]+$/i.test(e))throw new Error(`unsafe channelId for filesystem: ${e}`);return rt(this.dir,`${e}.json`)}async get(e){try{let r=await M.readFile(this.pathFor(e),"utf8");return ze(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(e,r){let n=this.pathFor(e);await M.mkdir(nt(n),{recursive:!0});let i=`${n}.tmp`;await M.writeFile(i,JSON.stringify(Ke(r))),await M.rename(i,n)}async delete(e){try{await M.unlink(this.pathFor(e))}catch(r){if(r?.code!=="ENOENT")throw r}}async tryAcquireLease(e,r){return P(e,async()=>{let n=await this.get(e),i=Date.now();if(n?.lease&&n.lease.heldUntilUnixMs>i)return!1;let s=n??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return await this.set(e,{...s,lease:{heldUntilUnixMs:i+r}}),!0})}async releaseLease(e){await P(e,async()=>{let r=await this.get(e);r&&await this.set(e,{...r,lease:void 0})})}};import{randomUUID as it}from"crypto";var st='if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end',ve=class{constructor(e,r="tab:"){this.client=e;this.keyPrefix=r}leaseTokens=new Map;ledgerKey(e){return`${this.keyPrefix}ledger:${e}`}leaseKey(e){return`${this.keyPrefix}lease:${e}`}async get(e){let r=await this.client.get(this.ledgerKey(e));return r===null?null:be(JSON.parse(r))}async set(e,r){let n=Ae({...r,lease:void 0});await this.client.set(this.ledgerKey(e),JSON.stringify(n))}async delete(e){this.leaseTokens.delete(e),await this.client.del(this.ledgerKey(e),this.leaseKey(e))}async tryAcquireLease(e,r){let n=it();return await this.client.set(this.leaseKey(e),n,"PX",Math.max(1,Math.floor(r)),"NX")!=="OK"?!1:(this.leaseTokens.set(e,n),!0)}async releaseLease(e){let r=this.leaseTokens.get(e);r!==void 0&&(this.leaseTokens.delete(e),await this.client.eval(st,1,this.leaseKey(e),r))}};import{PublicKey as gt}from"@solana/web3.js";import ot from"tweetnacl";import{sha256 as or}from"@noble/hashes/sha256";import{p256 as cr}from"@noble/curves/p256";import{PublicKey as xe}from"@solana/web3.js";import{sessionRegisterMessage as Ft,sessionRevokeMessage as Wt,voucherPayloadMessage as we,buildVoucherMessage as jt}from"@dexterai/vault/messages";import{buildRegisterSessionKeyInstruction as Gt,buildRevokeSessionKeyInstruction as Yt,deriveSwigWalletAddress as Zt}from"@dexterai/vault/instructions";import{buildSecp256r1VerifyInstruction as er}from"@dexterai/vault/precompile";import{DEXTER_VAULT_PROGRAM_ID as Se,SECP256R1_PROGRAM_ID as rr,INSTRUCTIONS_SYSVAR_ID as nr}from"@dexterai/vault/constants";import{fetchSessionAccount as at,isSessionLive as ct}from"@dexterai/vault/session";var Ce="OTS_SESSION_REGISTER_V2",E=class extends Error{constructor(r,n){super(`Invalid registration: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="InvalidRegistrationError"}};function Ee(t){if(t.length!==188)throw new E("wrong_length",`expected 188, got ${t.length}`);let e=new TextDecoder().decode(t.slice(0,Ce.length));if(e!==Ce)throw new E("wrong_domain",`got "${e}"`);for(let y=Ce.length;y<32;y++)if(t[y]!==0)throw new E("wrong_domain",`non-NUL padding at byte ${y}`);let r=new DataView(t.buffer,t.byteOffset,t.byteLength),n=new xe(t.slice(32,64)),i=new xe(t.slice(64,96)),s=t.slice(96,128),h=r.getBigUint64(128,!0),c=r.getBigInt64(136,!0),a=new xe(t.slice(144,176)),m=r.getUint32(176,!0),l=r.getBigUint64(180,!0);if(!n.equals(Se))throw new E("wrong_program",`${n.toBase58()} is not ${Se.toBase58()}`);if(h===0n)throw new E("cap_zero");let o=BigInt(Math.floor(Date.now()/1e3));if(c<=o)throw new E("expiry_in_past",`expires_at=${c}, now=${o}`);return{programId:n,vaultPda:i,sessionPubkey:new Uint8Array(s),maxAmount:h,expiresAt:c,allowedCounterparty:a,nonce:m,maxRevolvingCapacity:l}}var k=class extends Error{constructor(r,n){super(`On-chain verification failed: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="OnChainVerificationError"}};async function Re(t,e){let r=await at(t,e.vaultPda,e.allowedCounterparty);if(!r||r.version===0)throw new k("session_not_active","no live SessionAccount PDA for this (vault, counterparty) \u2014 revoked, expiry-swept, or never registered");if(!ct(r))throw new k("session_not_active","SessionAccount PDA is present but expired");if(!lt(r.session.sessionPubkey,e.sessionPubkey))throw new k("session_pubkey_mismatch",`on-chain ${He(r.session.sessionPubkey)} != registration ${He(e.sessionPubkey)}`);let n=r.session.spent,i=r.session.crystallizedCumulative;return{frontierAtomic:(n>i?n:i).toString(),spentAtomic:n.toString(),crystallizedCumulativeAtomic:i.toString()}}var _=class extends Error{constructor(e){super(`Invalid voucher signature${e?`: ${e}`:""}`),this.name="InvalidVoucherSignatureError"}};function Te(t,e){if(e.length!==32)throw new _(`channelIdBytes must be 32 bytes, got ${e.length}`);if(t.sessionPublicKey.length!==32)throw new _(`sessionPublicKey must be 32 bytes, got ${t.sessionPublicKey.length}`);if(t.sessionSignature.length!==64)throw new _(`sessionSignature must be 64 bytes, got ${t.sessionSignature.length}`);let r=we({channelId:e,cumulativeAmount:BigInt(t.payload.cumulativeAmount),sequenceNumber:t.payload.sequenceNumber});if(!ot.sign.detached.verify(r,t.sessionSignature,t.sessionPublicKey))throw new _("ed25519 verify rejected")}var C=class extends Error{constructor(r,n){super(`Scope violation: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="ScopeViolationError"}};function Pe(t){let e=BigInt(t.voucher.payload.cumulativeAmount);if(e>t.registration.maxAmount)throw new C("cumulative_exceeds_cap",`${e} > ${t.registration.maxAmount}`);let r=BigInt(Math.floor(Date.now()/1e3));if(r>=t.registration.expiresAt)throw new C("session_expired",`now=${r} >= expiresAt=${t.registration.expiresAt}`);if(!t.registration.allowedCounterparty.equals(t.expectedCounterparty))throw new C("wrong_counterparty",`${t.registration.allowedCounterparty.toBase58()} != ${t.expectedCounterparty.toBase58()}`);if(t.previousCumulativeAtomic!==void 0){let n=BigInt(t.previousCumulativeAtomic);if(e<=n)throw new C("non_monotonic",`cumulative=${e} not > previous=${n}`)}}function lt(t,e){if(t.length!==e.length)return!1;for(let r=0;r<t.length;r++)if(t[r]!==e[r])return!1;return!0}function He(t){let e="";for(let r of t)e+=r.toString(16).padStart(2,"0");return e}import{PublicKey as Tr}from"@solana/web3.js";import{bytesToHex as _r}from"@noble/hashes/utils";import fr from"tweetnacl";import{sha256 as vr}from"@noble/hashes/sha256";var qe="https://x402.dexter.cash",Fe=6;function R(t,e=Fe){if(!/^\d+(\.\d+)?$/.test(t))throw new Error(`amount must be a non-negative decimal string, got "${t}"`);let[r,n=""]=t.split(".");if(n.length>e)throw new Error(`amount "${t}" has more than ${e} decimals`);let i=n.padEnd(e,"0"),s=`${r}${i}`.replace(/^0+(?=\d)/,"");return s===""?"0":s}function U(t,e=Fe){if(!/^\d+$/.test(t))throw new Error(`atomic must be a non-negative integer string, got "${t}"`);let r=t.padStart(e+1,"0"),n=r.slice(0,-e).replace(/^0+(?=\d)/,"")||"0",i=r.slice(-e).replace(/0+$/,"");return i?`${n}.${i}`:n}import{bytesToHex as _e}from"@noble/hashes/utils";var ut=15e3,mt=["claim_already_exists","non_monotonic_cumulative"],dt="below_lock_cadence";function ee(t){return typeof t=="string"&&t.includes(dt)}function pt(t){return`${t.slice(0,16)}\u2026`}function We(t,e,r,n){let i=pt(t);if(n.crystallized){console.info(`[tab/seller] crystallize OK channel=${i} cumulative=${e} seq=${r}${n.claimPda?` claimPda=${n.claimPda}`:""} \u2014 LockVoucher landed`);return}if(n.error){if(ee(n.error)){console.warn(`[tab/seller] crystallize refused below the facilitator's cadence gate channel=${i} cumulative=${e} seq=${r}: ${n.error} \u2014 benign: this facilitator's cadence engine owns the protection cadence for the span; gate-refused watermark advanced, re-attempts after the next signed voucher`);return}if(mt.some(s=>n.error.includes(s))){console.warn(`[tab/seller] crystallize duplicate channel=${i} cumulative=${e} seq=${r}: ${n.error} \u2014 voucher already secured on-chain (benign, no action)`);return}console.error(`[tab/seller] crystallize FAILED channel=${i} cumulative=${e} seq=${r}: ${n.error} \u2014 lock NOT secured (degraded: best-effort path, no watermark advance, retries at next threshold/close; seller exposure stays unsecured until it lands)`)}}async function Ne(t,e,r,n,i=fetch){let s=t.lastVoucher;if(!s)return{crystallized:!1};if(s.payload.channelId!==e){let c={crystallized:!1,error:"channel_id_mismatch"};return We(e,s.payload.cumulativeAmount,s.payload.sequenceNumber,c),c}let h=c=>(We(e,s.payload.cumulativeAmount,s.payload.sequenceNumber,c),c);try{let c=`${r.replace(/\/$/,"")}/tab/lock`,a={channelId:s.payload.channelId,cumulativeAmount:s.payload.cumulativeAmount,sequenceNumber:s.payload.sequenceNumber,sessionPublicKey:_e(s.sessionPublicKey),sessionSignature:_e(s.sessionSignature),sessionRegistration:_e(s.sessionRegistration),network:n},m=await i(c,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(a),signal:AbortSignal.timeout(ut)}),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(t,e,r,n,i,s={}){let h=BigInt(t.deliveredCumulativeAtomic),c=BigInt(t.lastCrystallizedCumulativeAtomic??"0"),a=BigInt(i.thresholdAtomic);if(h-c<a)return{crystallized:!1};let m=t.lastVoucher?.payload.cumulativeAmount,l=t.gateRefusedCumulativeAtomic;if(m!==void 0&&l!==void 0&&BigInt(m)<=BigInt(l))return{crystallized:!1};let o=await Ne(t,e,r,n,s.fetchImpl);return o.crystallized&&m!==void 0?(t.lastCrystallizedCumulativeAtomic=m,t.gateRefusedCumulativeAtomic=void 0):ee(o.error)&&m!==void 0&&(t.gateRefusedCumulativeAtomic=m),o}var $="x-tab-voucher",ke=class{map=new Map;get(e){return this.map.get(e)}set(e,r){this.map.set(e,r)}update(e,r){let n=this.map.get(e);n&&(n.lastCumulativeAtomic=r)}delete(e){this.map.delete(e)}},Ie=class{constructor(e,r,n,i,s,h){this.recordDeliveredImpl=s;this.chargeImpl=h;this.channelId=e,this.network=r,this.cumulativeAtomic=n,this.deliveredBaselineAtomic=i}channelId;network;sessionPublicKey=null;cumulativeAtomic;deliveredBaselineAtomic;cumulative(){return U(this.cumulativeAtomic.toString())}deliveredCumulative(){return U(this.deliveredBaselineAtomic.toString())}async recordDelivered(e){return this.recordDeliveredImpl(e)}bumpCumulative(e){this.cumulativeAtomic=e}setSessionPublicKey(e){this.sessionPublicKey=e}async charge(e){return this.chargeImpl(e)}};function ht(t){if(typeof t!="string"||t.length===0)throw new x("signature_invalid",`missing ${$} header`);let e;try{e=Buffer.from(t,"base64").toString("utf8")}catch{throw new x("signature_invalid","malformed base64")}let r;try{r=JSON.parse(e)}catch{throw new x("signature_invalid","malformed JSON")}if(!r||typeof r!="object"||!r.payload||!r.sessionPublicKey)throw new x("signature_invalid","missing required fields");return{payload:r.payload,sessionPublicKey:te(r.sessionPublicKey),sessionRegistration:te(r.sessionRegistration),sessionSignature:te(r.sessionSignature)}}function te(t){if(typeof t!="string"||t.length%2!==0)throw new x("signature_invalid",`bad hex: ${typeof t}`);let e=new Uint8Array(t.length/2);for(let r=0;r<e.length;r++)e[r]=parseInt(t.substr(r*2,2),16);return e}function yt(t){if(!/^[0-9a-f]{64}$/i.test(t))throw new x("signature_invalid",`channelId must be 64-char hex, got "${t}"`);return te(t)}function Oe(t){let e=t.ledger??new D,r=new ke,n=typeof t.sellerPubkey=="string"?new gt(t.sellerPubkey):t.sellerPubkey,i=t.maxPerVoucherAtomic?BigInt(t.maxPerVoucherAtomic):BigInt(R(t.perUnit))*100n,s=t.facilitatorUrl??qe,h={thresholdAtomic:t.lockCadence?.thresholdAtomic??R("0.10"),onClose:t.lockCadence?.onClose??!0};return async(c,a,m)=>{try{let l=ht(c.headers[$]),o=l.payload.channelId,y=yt(o),d=r.get(o),f=null;if(!d){let p=Ee(l.sessionRegistration);f=(await Re(t.connection,p))?.frontierAtomic??null;let v=await e.get(o);d={registration:p,lastCumulativeAtomic:v?.lastVoucher?.payload.cumulativeAmount??"0"},r.set(o,d)}Te(l,y),Pe({registration:d.registration,voucher:l,expectedCounterparty:n,previousCumulativeAtomic:d.lastCumulativeAtomic});let b=BigInt(l.payload.cumulativeAmount),V=BigInt(d.lastCumulativeAtomic),L=b-V;if(L>i)throw new C("cumulative_exceeds_cap",`single voucher increment ${L} exceeds maxPerVoucherAtomic ${i}`);let pe=t.leaseTtlMs??3e5;if(!await e.tryAcquireLease(o,pe))throw new x("channel_busy","another stream is live on this channel; tabs serve one stream at a time");let B=!1,Z=()=>{B||(B=!0,e.releaseLease(o).catch(p=>{console.error("[tab/seller] failed to release channel lease:",p)}))};a.on("close",Z),a.on("finish",Z);let ge=async p=>{let T=p.lastCrystallizedCumulativeAtomic??"0",v=p.gateRefusedCumulativeAtomic;await je(p,o,s,t.network,h),(p.lastCrystallizedCumulativeAtomic!==T||p.gateRefusedCumulativeAtomic!==v)&&await P(o,async()=>{let w=await e.get(o);w&&await e.set(o,{...w,lastCrystallizedCumulativeAtomic:p.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:p.gateRefusedCumulativeAtomic})}).catch(w=>{console.error(`[tab/seller] crystallize watermark persist FAILED channel=${o.slice(0,16)}\u2026 (expect a benign duplicate/below-cadence warn on the next request):`,w)})},Q=!1,u=()=>{!h.onClose||Q||(Q=!0,(async()=>{let p=await e.get(o);if(!p||!p.lastVoucher)return;let T=p.lastVoucher.payload.cumulativeAmount;if(p.gateRefusedCumulativeAtomic!==void 0&&BigInt(T)<=BigInt(p.gateRefusedCumulativeAtomic))return;let v=await Ne(p,o,s,t.network);v.crystallized?await P(o,async()=>{let w=await e.get(o);w&&await e.set(o,{...w,lastCrystallizedCumulativeAtomic:T,gateRefusedCumulativeAtomic:void 0})}):ee(v.error)&&await P(o,async()=>{let w=await e.get(o);w&&await e.set(o,{...w,gateRefusedCumulativeAtomic:T})})})().catch(p=>{console.error(`[tab/seller] close-path crystallize CRASHED channel=${o.slice(0,16)}\u2026 (final voucher NOT locked; exposure unsecured until the next request retries):`,p)}))};a.on("close",u),a.on("finish",u);let g=await e.get(o),A=!g?.lastVoucher&&BigInt(g?.deliveredCumulativeAtomic??"0")===0n,S=f!==null&&A&&BigInt(f)>0n?f:null;S!==null&&console.info(`[tab/seller] channel ${o.slice(0,16)}\u2026 resumed: seeding delivered baseline from chain frontier ${S} (session already settled/locked up to it \u2014 that span is not deliverable budget)`);let I=S!==null?BigInt(S):g?BigInt(g.deliveredCumulativeAtomic):0n;await P(o,async()=>{let p=await e.get(o);await e.set(o,{...p,lastVoucher:l,deliveredCumulativeAtomic:S??(p?p.deliveredCumulativeAtomic:"0"),lastCrystallizedCumulativeAtomic:S??p?.lastCrystallizedCumulativeAtomic??"0"})}),r.update(o,l.payload.cumulativeAmount);let O=new Ie(o,t.network,b,I,async p=>{let T=null;await P(o,async()=>{let v=await e.get(o),w=v?BigInt(v.deliveredCumulativeAtomic):0n,Be=BigInt(p),tt=Be>0n?w+Be:w,Me={...v,lastVoucher:v?.lastVoucher??l,deliveredCumulativeAtomic:tt.toString(),lastCrystallizedCumulativeAtomic:v?.lastCrystallizedCumulativeAtomic??"0"};await e.set(o,Me),T=Me}),T&&ge(T).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 x||l instanceof E||l instanceof k||l instanceof _||l instanceof C){a.status(402).json({error:"invalid_voucher",reason:l.reason??"unknown",detail:l.message});return}m(l)}}}function ft(t){if(!t.tab)throw new Error("req.tab is missing \u2014 did tabMiddleware run on this route?");return t.tab}function At(t,e){if(!e.tab)throw new Error("openSse requires options.tab");t.headersSent||(t.setHeader("Content-Type","text/event-stream"),t.setHeader("Cache-Control","no-cache"),t.setHeader("Connection","keep-alive"),typeof t.flushHeaders=="function"&&t.flushHeaders());let r=e.tab,n=BigInt(R(r.cumulative())),i=BigInt(R(r.deliveredCumulative())),s=n-i;s<0n&&(s=0n);let h=e.perUnit?BigInt(R(e.perUnit)):null,c=0n,a=!1;async function m(){await r.recordDelivered(c.toString())}t.on("close",()=>{a||(a=!0,m().catch(d=>{console.error("[tab/seller] terminal persist failed on disconnect:",d)}))});async function l(d=1){if(a)throw new Error("meter ended");if(h===null)throw new Error("charge() needs options.perUnit");let f=h*BigInt(d),b=c+f;if(b>s)throw a=!0,await m(),new C("cumulative_exceeds_cap",`chunk would push delivered to ${U((i+b).toString())} beyond signed cumulative ${U(n.toString())} (per-request budget ${U(s.toString())})`);c=b}function o(d){if(a)throw new Error("meter ended");let b=(typeof d=="string"?d:Buffer.from(d).toString("utf8")).replace(/\\/g,"\\\\").replace(/\n/g,"\\n");t.write(`data: ${b}
1
+ var x=class extends Error{constructor(n,r){super(`Invalid voucher: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="InvalidVoucherError"}reason};import{promises as $}from"fs";import{join as ct,dirname as lt}from"path";var Le=new Map;function P(t,e){let r=(Le.get(t)??Promise.resolve()).then(()=>e(),()=>e());return Le.set(t,r.then(()=>{},()=>{})),r}var L=class{map=new Map;async get(e){return this.map.get(e)??null}async set(e,n){this.map.set(e,n)}async delete(e){this.map.delete(e)}async tryAcquireLease(e,n){return P(e,async()=>{let r=this.map.get(e),i=Date.now();if(r?.lease&&r.lease.heldUntilUnixMs>i)return!1;let o=r??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return this.map.set(e,{...o,lease:{heldUntilUnixMs:i+n}}),!0})}async releaseLease(e){await P(e,async()=>{let n=this.map.get(e);n&&this.map.set(e,{...n,lease:void 0})})}};function ye(t){let e="";for(let n of t)e+=n.toString(16).padStart(2,"0");return e}function Ae(t){if(t.length%2!==0)throw new Error(`hex length must be even, got ${t.length}`);let e=new Uint8Array(t.length/2);for(let n=0;n<e.length;n++)e[n]=parseInt(t.substr(n*2,2),16);return e}function be(t){return Me(t)}function we(t){return qe(t)}function Me(t){return{lastVoucher:t.lastVoucher?{payload:t.lastVoucher.payload,sessionPublicKey:ye(t.lastVoucher.sessionPublicKey),sessionRegistration:ye(t.lastVoucher.sessionRegistration),sessionSignature:ye(t.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:t.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:t.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:t.gateRefusedCumulativeAtomic,onChain:t.onChain,lease:t.lease}}function qe(t){return{lastVoucher:t.lastVoucher?{payload:t.lastVoucher.payload,sessionPublicKey:Ae(t.lastVoucher.sessionPublicKey),sessionRegistration:Ae(t.lastVoucher.sessionRegistration),sessionSignature:Ae(t.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:t.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:t.lastCrystallizedCumulativeAtomic??"0",gateRefusedCumulativeAtomic:t.gateRefusedCumulativeAtomic,onChain:t.onChain,lease:t.lease}}var ve=class{constructor(e){this.dir=e}dir;pathFor(e){if(!/^[a-z0-9_-]+$/i.test(e))throw new Error(`unsafe channelId for filesystem: ${e}`);return ct(this.dir,`${e}.json`)}async get(e){try{let n=await $.readFile(this.pathFor(e),"utf8");return qe(JSON.parse(n))}catch(n){if(n?.code==="ENOENT")return null;throw n}}async set(e,n){let r=this.pathFor(e);await $.mkdir(lt(r),{recursive:!0});let i=`${r}.tmp`;await $.writeFile(i,JSON.stringify(Me(n))),await $.rename(i,r)}async delete(e){try{await $.unlink(this.pathFor(e))}catch(n){if(n?.code!=="ENOENT")throw n}}async tryAcquireLease(e,n){return P(e,async()=>{let r=await this.get(e),i=Date.now();if(r?.lease&&r.lease.heldUntilUnixMs>i)return!1;let o=r??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return await this.set(e,{...o,lease:{heldUntilUnixMs:i+n}}),!0})}async releaseLease(e){await P(e,async()=>{let n=await this.get(e);n&&await this.set(e,{...n,lease:void 0})})}};import{randomUUID as ut}from"crypto";var mt='if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end',Se=class{constructor(e,n="tab:"){this.client=e;this.keyPrefix=n}client;keyPrefix;leaseTokens=new Map;ledgerKey(e){return`${this.keyPrefix}ledger:${e}`}leaseKey(e){return`${this.keyPrefix}lease:${e}`}async get(e){let n=await this.client.get(this.ledgerKey(e));return n===null?null:we(JSON.parse(n))}async set(e,n){let r=be({...n,lease:void 0});await this.client.set(this.ledgerKey(e),JSON.stringify(r))}async delete(e){this.leaseTokens.delete(e),await this.client.del(this.ledgerKey(e),this.leaseKey(e))}async tryAcquireLease(e,n){let r=ut();return await this.client.set(this.leaseKey(e),r,"PX",Math.max(1,Math.floor(n)),"NX")!=="OK"?!1:(this.leaseTokens.set(e,r),!0)}async releaseLease(e){let n=this.leaseTokens.get(e);n!==void 0&&(this.leaseTokens.delete(e),await this.client.eval(mt,1,this.leaseKey(e),n))}};import{PublicKey as _t}from"@solana/web3.js";import pt from"tweetnacl";import{sha256 as Sn}from"@noble/hashes/sha256";import{p256 as _n}from"@noble/curves/p256";import{PublicKey as _e}from"@solana/web3.js";import{sessionRegisterMessage as dt,sessionReplaceV1Message as nn,sessionRevokeMessage as rn,sessionVoucherV2Nonce as on,sessionVoucherV2AuthorizationNonce as sn,finalVoucherV2Sequence as an,voucherV2SequenceOrdinal as cn,voucherPayloadMessage as xe,buildVoucherMessage as ln}from"@dexterai/vault/messages";import{buildRegisterSessionKeyInstruction as dn,buildRevokeSessionKeyInstruction as pn,deriveSwigWalletAddress as gn}from"@dexterai/vault/instructions";import{buildSecp256r1VerifyInstruction as fn}from"@dexterai/vault/precompile";import{DEXTER_VAULT_PROGRAM_ID as ee,SECP256R1_PROGRAM_ID as An,INSTRUCTIONS_SYSVAR_ID as vn}from"@dexterai/vault/constants";import{deriveSessionPda as ze,fetchSessionAccount as gt,isSessionLive as ht}from"@dexterai/vault/session";import{contextBoundVoucherV2Message as ft,sessionVoucherV2AuthorizationNonce as yt,voucherV2SequenceOrdinal as At}from"@dexterai/vault/messages";var Ee="OTS_SESSION_REGISTER_V2",T=class extends Error{constructor(n,r){super(`Invalid registration: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="InvalidRegistrationError"}reason};function te(t){if(t.length!==188)throw new T("wrong_length",`expected 188, got ${t.length}`);let e=new TextDecoder().decode(t.slice(0,Ee.length));if(e!==Ee)throw new T("wrong_domain",`got "${e}"`);for(let s=Ee.length;s<32;s++)if(t[s]!==0)throw new T("wrong_domain",`non-NUL padding at byte ${s}`);let n=new DataView(t.buffer,t.byteOffset,t.byteLength),r=new _e(t.slice(32,64)),i=new _e(t.slice(64,96)),o=t.slice(96,128),u=n.getBigUint64(128,!0),c=n.getBigInt64(136,!0),a=new _e(t.slice(144,176)),d=n.getUint32(176,!0),l=n.getBigUint64(180,!0);if(!r.equals(ee))throw new T("wrong_program",`${r.toBase58()} is not ${ee.toBase58()}`);if(u===0n)throw new T("cap_zero");return{programId:r,vaultPda:i,sessionPubkey:new Uint8Array(o),maxAmount:u,expiresAt:c,allowedCounterparty:a,nonce:d,maxRevolvingCapacity:l}}var I=class extends Error{constructor(n,r){super(`On-chain verification failed: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="OnChainVerificationError"}reason};async function Ce(t,e){let n=await gt(t,e.vaultPda,e.allowedCounterparty,e.programId);if(!n||n.version===0)throw new I("session_not_active","no live SessionAccount PDA for this (vault, counterparty) \u2014 revoked, expiry-swept, or never registered");if(!ht(n))throw new I("session_not_active","SessionAccount PDA is present but expired");if(!He(n.session.sessionPubkey,e.sessionPubkey))throw new I("session_pubkey_mismatch",`on-chain ${Fe(n.session.sessionPubkey)} != registration ${Fe(e.sessionPubkey)}`);let[r]=ze(e.vaultPda,e.allowedCounterparty,e.programId),i=Number.isSafeInteger(n.session.expiresAt)&&BigInt(n.session.expiresAt)===e.expiresAt;if(!(n.address===r.toBase58()&&n.vault===e.vaultPda.toBase58()&&n.session.maxAmount===e.maxAmount&&i&&n.session.allowedCounterparty===e.allowedCounterparty.toBase58()&&n.session.nonce===e.nonce&&n.session.maxRevolvingCapacity===e.maxRevolvingCapacity))throw new I("registration_state_mismatch","188-byte registration does not exactly match the active SessionAccount immutable fields");let u=n.session.spent,c=n.session.crystallizedCumulative;return{frontierAtomic:(u>c?u:c).toString(),spentAtomic:u.toString(),crystallizedCumulativeAtomic:c.toString()}}var E=class extends Error{constructor(e){super(`Invalid voucher signature${e?`: ${e}`:""}`),this.name="InvalidVoucherSignatureError"}};function Re(t,e){if(e.length!==32)throw new E(`channelIdBytes must be 32 bytes, got ${e.length}`);if(t.sessionPublicKey.length!==32)throw new E(`sessionPublicKey must be 32 bytes, got ${t.sessionPublicKey.length}`);if(t.sessionSignature.length!==64)throw new E(`sessionSignature must be 64 bytes, got ${t.sessionSignature.length}`);let n=te(t.sessionRegistration);if(!He(n.sessionPubkey,t.sessionPublicKey))throw new E("registration session key does not match voucher session key");let r=n.nonce>=2147483648,i;if(r){yt(n.nonce),At(t.payload.sequenceNumber);let[u]=ze(n.vaultPda,n.allowedCounterparty,n.programId);i=ft({programId:n.programId,vaultPda:n.vaultPda,sessionPda:u,seller:n.allowedCounterparty,sessionNonce:n.nonce,channelId:e,cumulativeAmount:BigInt(t.payload.cumulativeAmount),sequenceNumber:t.payload.sequenceNumber})}else i=xe({channelId:e,cumulativeAmount:BigInt(t.payload.cumulativeAmount),sequenceNumber:t.payload.sequenceNumber});if(!pt.sign.detached.verify(i,t.sessionSignature,t.sessionPublicKey))throw new E("ed25519 verify rejected")}var _=class extends Error{constructor(n,r){super(`Scope violation: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="ScopeViolationError"}reason};function Pe(t){let e=BigInt(t.voucher.payload.cumulativeAmount);if(e>t.registration.maxAmount)throw new _("cumulative_exceeds_cap",`${e} > ${t.registration.maxAmount}`);let n=BigInt(Math.floor(Date.now()/1e3));if(n>=t.registration.expiresAt)throw new _("session_expired",`now=${n} >= expiresAt=${t.registration.expiresAt}`);if(!t.registration.allowedCounterparty.equals(t.expectedCounterparty))throw new _("wrong_counterparty",`${t.registration.allowedCounterparty.toBase58()} != ${t.expectedCounterparty.toBase58()}`);if(t.previousCumulativeAtomic!==void 0){let r=BigInt(t.previousCumulativeAtomic);if(e<=r)throw new _("non_monotonic",`cumulative=${e} not > previous=${r}`)}}function He(t,e){if(t.length!==e.length)return!1;for(let n=0;n<t.length;n++)if(t[n]!==e[n])return!1;return!0}function Fe(t){let e="";for(let n of t)e+=n.toString(16).padStart(2,"0");return e}import{PublicKey as lr}from"@solana/web3.js";import{bytesToHex as mr}from"@noble/hashes/utils";import kn from"tweetnacl";import{PublicKey as Bn}from"@solana/web3.js";import{contextBoundVoucherV2Message as Kn,finalVoucherV2Sequence as $n,sessionRegisterMessage as Ln,sessionVoucherV2AuthorizationNonce as Mn}from"@dexterai/vault/messages";import{deriveSessionPda as Fn}from"@dexterai/vault/session";import{sha256 as Xn}from"@noble/hashes/sha256";var Hn=(1n<<64n)-1n;import{sha256 as Gn}from"@noble/hashes/sha256";import{bytesToHex as Zn}from"@noble/hashes/utils";var vt="dexter-native-tab-v2-reservation/v1",Qn=`${vt}:`;import{deriveSessionPda as fr}from"@dexterai/vault/session";var We="https://x402.dexter.cash",Xe=6;function C(t,e=Xe){if(!/^\d+(\.\d+)?$/.test(t))throw new Error(`amount must be a non-negative decimal string, got "${t}"`);let[n,r=""]=t.split(".");if(r.length>e)throw new Error(`amount "${t}" has more than ${e} decimals`);let i=r.padEnd(e,"0"),o=`${n}${i}`.replace(/^0+(?=\d)/,"");return o===""?"0":o}function k(t,e=Xe){if(!/^\d+$/.test(t))throw new Error(`atomic must be a non-negative integer string, got "${t}"`);let n=t.padStart(e+1,"0"),r=n.slice(0,-e).replace(/^0+(?=\d)/,"")||"0",i=n.slice(-e).replace(/0+$/,"");return i?`${r}.${i}`:r}import{bytesToHex as Te}from"@noble/hashes/utils";var bt=15e3,wt=["claim_already_exists","non_monotonic_cumulative"],St="below_lock_cadence";function ne(t){return typeof t=="string"&&t.includes(St)}function xt(t){return`${t.slice(0,16)}\u2026`}function je(t,e,n,r){let i=xt(t);if(r.crystallized){console.info(`[tab/seller] crystallize OK channel=${i} cumulative=${e} seq=${n}${r.claimPda?` claimPda=${r.claimPda}`:""} \u2014 LockVoucher landed`);return}if(r.error){if(ne(r.error)){console.warn(`[tab/seller] crystallize refused below the facilitator's cadence gate channel=${i} cumulative=${e} seq=${n}: ${r.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(wt.some(o=>r.error.includes(o))){console.warn(`[tab/seller] crystallize duplicate channel=${i} cumulative=${e} seq=${n}: ${r.error} \u2014 voucher already secured on-chain (benign, no action)`);return}console.error(`[tab/seller] crystallize FAILED channel=${i} cumulative=${e} seq=${n}: ${r.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 Ie(t,e,n,r,i=fetch){let o=t.lastVoucher;if(!o)return{crystallized:!1};if(o.payload.channelId!==e){let c={crystallized:!1,error:"channel_id_mismatch"};return je(e,o.payload.cumulativeAmount,o.payload.sequenceNumber,c),c}let u=c=>(je(e,o.payload.cumulativeAmount,o.payload.sequenceNumber,c),c);try{let c=`${n.replace(/\/$/,"")}/tab/lock`,a={channelId:o.payload.channelId,cumulativeAmount:o.payload.cumulativeAmount,sequenceNumber:o.payload.sequenceNumber,sessionPublicKey:Te(o.sessionPublicKey),sessionSignature:Te(o.sessionSignature),sessionRegistration:Te(o.sessionRegistration),network:r},d=await i(c,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(a),signal:AbortSignal.timeout(bt)}),l=await d.text();if(!d.ok)return u({crystallized:!1,error:`tab lock ${d.status}: ${l.slice(0,200)}`});let s;try{let y=JSON.parse(l);y&&typeof y.claimPda=="string"&&(s=y.claimPda)}catch{}return u({crystallized:!0,claimPda:s})}catch(c){return u({crystallized:!1,error:String(c?.message??c)})}}async function Je(t,e,n,r,i,o={}){let u=BigInt(t.deliveredCumulativeAtomic),c=BigInt(t.lastCrystallizedCumulativeAtomic??"0"),a=BigInt(i.thresholdAtomic);if(u-c<a)return{crystallized:!1};let d=t.lastVoucher?.payload.cumulativeAmount,l=t.gateRefusedCumulativeAtomic;if(d!==void 0&&l!==void 0&&BigInt(d)<=BigInt(l))return{crystallized:!1};let s=await Ie(t,e,n,r,o.fetchImpl);return s.crystallized&&d!==void 0?(t.lastCrystallizedCumulativeAtomic=d,t.gateRefusedCumulativeAtomic=void 0):ne(s.error)&&d!==void 0&&(t.gateRefusedCumulativeAtomic=d),s}var U="x-tab-voucher",Ve=class{map=new Map;get(e){return this.map.get(e)}set(e,n){this.map.set(e,n)}update(e,n){let r=this.map.get(e);r&&(r.lastCumulativeAtomic=n)}delete(e){this.map.delete(e)}},Ne=class{constructor(e,n,r,i,o,u){this.recordDeliveredImpl=o;this.chargeImpl=u;this.channelId=e,this.network=n,this.cumulativeAtomic=r,this.deliveredBaselineAtomic=i}recordDeliveredImpl;chargeImpl;channelId;network;sessionPublicKey=null;cumulativeAtomic;deliveredBaselineAtomic;cumulative(){return k(this.cumulativeAtomic.toString())}deliveredCumulative(){return k(this.deliveredBaselineAtomic.toString())}async recordDelivered(e){return this.recordDeliveredImpl(e)}bumpCumulative(e){this.cumulativeAtomic=e}setSessionPublicKey(e){this.sessionPublicKey=e}async charge(e){return this.chargeImpl(e)}};function Et(t){if(typeof t!="string"||t.length===0)throw new x("signature_invalid",`missing ${U} header`);let e;try{e=Buffer.from(t,"base64").toString("utf8")}catch{throw new x("signature_invalid","malformed base64")}let n;try{n=JSON.parse(e)}catch{throw new x("signature_invalid","malformed JSON")}if(!n||typeof n!="object"||!n.payload||!n.sessionPublicKey)throw new x("signature_invalid","missing required fields");return{payload:n.payload,sessionPublicKey:re(n.sessionPublicKey),sessionRegistration:re(n.sessionRegistration),sessionSignature:re(n.sessionSignature)}}function re(t){if(typeof t!="string"||t.length%2!==0)throw new x("signature_invalid",`bad hex: ${typeof t}`);let e=new Uint8Array(t.length/2);for(let n=0;n<e.length;n++)e[n]=parseInt(t.substr(n*2,2),16);return e}function Ct(t){if(!/^[0-9a-f]{64}$/i.test(t))throw new x("signature_invalid",`channelId must be 64-char hex, got "${t}"`);return re(t)}function Oe(t){let e=t.ledger??new L,n=new Ve,r=typeof t.sellerPubkey=="string"?new _t(t.sellerPubkey):t.sellerPubkey,i=t.maxPerVoucherAtomic?BigInt(t.maxPerVoucherAtomic):BigInt(C(t.perUnit))*100n,o=t.facilitatorUrl??We,u={thresholdAtomic:t.lockCadence?.thresholdAtomic??C("0.10"),onClose:t.lockCadence?.onClose??!0};return async(c,a,d)=>{try{let l=Et(c.headers[U]),s=l.payload.channelId,y=Ct(s),p=n.get(s),f=null;if(p){if(!Rt(p.registrationBytes,l.sessionRegistration))throw new E("voucher registration does not match the channel's verified registration")}else{let g=te(l.sessionRegistration);f=(await Ce(t.connection,g))?.frontierAtomic??null;let b=await e.get(s);p={registration:g,registrationBytes:l.sessionRegistration.slice(),lastCumulativeAtomic:b?.lastVoucher?.payload.cumulativeAmount??"0"},n.set(s,p)}Re(l,y),Pe({registration:p.registration,voucher:l,expectedCounterparty:r,previousCumulativeAtomic:p.lastCumulativeAtomic});let v=BigInt(l.payload.cumulativeAmount),B=BigInt(p.lastCumulativeAtomic),D=v-B;if(D>i)throw new _("cumulative_exceeds_cap",`single voucher increment ${D} exceeds maxPerVoucherAtomic ${i}`);let he=t.leaseTtlMs??3e5;if(!await e.tryAcquireLease(s,he))throw new x("channel_busy","another stream is live on this channel; tabs serve one stream at a time");let K=!1,Z=()=>{K||(K=!0,e.releaseLease(s).catch(g=>{console.error("[tab/seller] failed to release channel lease:",g)}))};a.on("close",Z),a.on("finish",Z);let fe=async g=>{let R=g.lastCrystallizedCumulativeAtomic??"0",b=g.gateRefusedCumulativeAtomic;await Je(g,s,o,t.network,u),(g.lastCrystallizedCumulativeAtomic!==R||g.gateRefusedCumulativeAtomic!==b)&&await P(s,async()=>{let w=await e.get(s);w&&await e.set(s,{...w,lastCrystallizedCumulativeAtomic:g.lastCrystallizedCumulativeAtomic,gateRefusedCumulativeAtomic:g.gateRefusedCumulativeAtomic})}).catch(w=>{console.error(`[tab/seller] crystallize watermark persist FAILED channel=${s.slice(0,16)}\u2026 (expect a benign duplicate/below-cadence warn on the next request):`,w)})},Q=!1,m=()=>{!u.onClose||Q||(Q=!0,(async()=>{let g=await e.get(s);if(!g||!g.lastVoucher)return;let R=g.lastVoucher.payload.cumulativeAmount;if(g.gateRefusedCumulativeAtomic!==void 0&&BigInt(R)<=BigInt(g.gateRefusedCumulativeAtomic))return;let b=await Ie(g,s,o,t.network);b.crystallized?await P(s,async()=>{let w=await e.get(s);w&&await e.set(s,{...w,lastCrystallizedCumulativeAtomic:R,gateRefusedCumulativeAtomic:void 0})}):ne(b.error)&&await P(s,async()=>{let w=await e.get(s);w&&await e.set(s,{...w,gateRefusedCumulativeAtomic:R})})})().catch(g=>{console.error(`[tab/seller] close-path crystallize CRASHED channel=${s.slice(0,16)}\u2026 (final voucher NOT locked; exposure unsecured until the next request retries):`,g)}))};a.on("close",m),a.on("finish",m);let h=await e.get(s),A=!h?.lastVoucher&&BigInt(h?.deliveredCumulativeAtomic??"0")===0n,S=f!==null&&A&&BigInt(f)>0n?f:null;S!==null&&console.info(`[tab/seller] channel ${s.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 N=S!==null?BigInt(S):h?BigInt(h.deliveredCumulativeAtomic):0n;await P(s,async()=>{let g=await e.get(s);await e.set(s,{...g,lastVoucher:l,deliveredCumulativeAtomic:S??(g?g.deliveredCumulativeAtomic:"0"),lastCrystallizedCumulativeAtomic:S??g?.lastCrystallizedCumulativeAtomic??"0"})}),n.update(s,l.payload.cumulativeAmount);let O=new Ne(s,t.network,v,N,async g=>{let R=null;await P(s,async()=>{let b=await e.get(s),w=b?BigInt(b.deliveredCumulativeAtomic):0n,Ke=BigInt(g),at=Ke>0n?w+Ke:w,$e={...b,lastVoucher:b?.lastVoucher??l,deliveredCumulativeAtomic:at.toString(),lastCrystallizedCumulativeAtomic:b?.lastCrystallizedCumulativeAtomic??"0"};await e.set(s,$e),R=$e}),R&&fe(R).catch(b=>{console.error(`[tab/seller] crystallize cadence CRASHED channel=${s.slice(0,16)}\u2026 (threshold lock not attempted; retries at the next delivery):`,b)})},async g=>{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,d()}catch(l){if(l instanceof x||l instanceof T||l instanceof I||l instanceof E||l instanceof _){a.status(402).json({error:"invalid_voucher",reason:l.reason??"unknown",detail:l.message});return}d(l)}}}function Rt(t,e){if(t.length!==e.length)return!1;let n=0;for(let r=0;r<t.length;r+=1)n|=t[r]^e[r];return n===0}function Pt(t){if(!t.tab)throw new Error("req.tab is missing \u2014 did tabMiddleware run on this route?");return t.tab}function Tt(t,e){if(!e.tab)throw new Error("openSse requires options.tab");t.headersSent||(t.setHeader("Content-Type","text/event-stream"),t.setHeader("Cache-Control","no-cache"),t.setHeader("Connection","keep-alive"),typeof t.flushHeaders=="function"&&t.flushHeaders());let n=e.tab,r=BigInt(C(n.cumulative())),i=BigInt(C(n.deliveredCumulative())),o=r-i;o<0n&&(o=0n);let u=e.perUnit?BigInt(C(e.perUnit)):null,c=0n,a=!1;async function d(){await n.recordDelivered(c.toString())}t.on("close",()=>{a||(a=!0,d().catch(p=>{console.error("[tab/seller] terminal persist failed on disconnect:",p)}))});async function l(p=1){if(a)throw new Error("meter ended");if(u===null)throw new Error("charge() needs options.perUnit");let f=u*BigInt(p),v=c+f;if(v>o)throw a=!0,await d(),new _("cumulative_exceeds_cap",`chunk would push delivered to ${k((i+v).toString())} beyond signed cumulative ${k(r.toString())} (per-request budget ${k(o.toString())})`);c=v}function s(p){if(a)throw new Error("meter ended");let v=(typeof p=="string"?p:Buffer.from(p).toString("utf8")).replace(/\\/g,"\\\\").replace(/\n/g,"\\n");t.write(`data: ${v}
2
2
 
3
- `)}async function y(){a||(a=!0,await m(),t.write(`event: end
3
+ `)}async function y(){a||(a=!0,await d(),t.write(`event: end
4
4
  data: {"chargedAtomic":"${c}"}
5
5
 
6
- `),t.end())}return{charge:l,send:o,end:y}}import{promises as K}from"fs";import{join as bt,dirname as vt}from"path";function wt(t){return{payload:t.payload,sessionPublicKey:Ue(t.sessionPublicKey),sessionRegistration:Ue(t.sessionRegistration),sessionSignature:Ue(t.sessionSignature)}}function St(t){return{payload:t.payload,sessionPublicKey:$e(t.sessionPublicKey),sessionRegistration:$e(t.sessionRegistration),sessionSignature:$e(t.sessionSignature)}}function Ue(t){let e="";for(let r of t)e+=r.toString(16).padStart(2,"0");return e}function $e(t){if(t.length%2!==0)throw new Error(`hex length must be even, got ${t.length}`);let e=new Uint8Array(t.length/2);for(let r=0;r<e.length;r++)e[r]=parseInt(t.substr(r*2,2),16);return e}var Ve=class{map=new Map;async get(e){return this.map.get(e)??null}async set(e,r){this.map.set(e,r)}async delete(e){this.map.delete(e)}},Le=class{constructor(e){this.dir=e}pathFor(e){if(!/^[a-z0-9_-]+$/i.test(e))throw new Error(`unsafe channelId for filesystem: ${e}`);return bt(this.dir,`${e}.json`)}async get(e){try{let r=await K.readFile(this.pathFor(e),"utf8");return St(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(e,r){let n=this.pathFor(e);await K.mkdir(vt(n),{recursive:!0});let i=`${n}.tmp`;await K.writeFile(i,JSON.stringify(wt(r))),await K.rename(i,n)}async delete(e){try{await K.unlink(this.pathFor(e))}catch(r){if(r?.code!=="ENOENT")throw r}}};import{PublicKey as Nt}from"@solana/web3.js";var N="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",Xe="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",Je="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";var z="eip155:8453",re="eip155:84532",ne="eip155:42161",ie="eip155:137",se="eip155:10",oe="eip155:43114",ae="eip155:56",H="eip155:480",q="eip155:143",F="eip155:4663",W="eip155:1187947933",j="eip155:324705682",ce="eip155:1";var le="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";var Ge="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",xt="0x55d398326f99059fF775485246999027B3197955",Ye="0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",Ct="0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",Ze={[ae]:Ye,[z]:Ge,[re]:"0x036CbD53842c5426634e7929541eC2318f3dCF7e",[ne]:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831",[ie]:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",[se]:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",[oe]:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",[H]:"0x79A02482A880bCE3F13e09Da970dC34db4CD24d1",[q]:"0x754704Bc059F8C67012fEd69BC8A327a5aafb603",[F]:Ct,[W]:"0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",[j]:"0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",[ce]:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},Qe={[xt]:{symbol:"USDT",decimals:18},[Ye]:{symbol:"USDC",decimals:18}};var Jr={[H]:{name:"USDC",version:"2"},[q]:{name:"USDC",version:"2"},[F]:{name:"Global Dollar",version:"1"},[W]:{name:"Bridged USDC (SKALE Bridge)",version:"2"},[j]:{name:"Bridged USDC (SKALE Bridge)",version:"2"}};var Gr={[ae]:56,[z]:8453,[re]:84532,[ne]:42161,[ie]:137,[se]:10,[oe]:43114,[H]:480,[q]:143,[F]:4663,[W]:1187947933,[j]:324705682,[ce]:1},Yr={[N]:"https://api.dexter.cash/api/solana/rpc",[Xe]:"https://api.devnet.solana.com",[Je]:"https://api.testnet.solana.com"},Et={[ae]:"https://api.dexter.cash/api/evm/bsc/rpc",[z]:"https://api.dexter.cash/api/base/rpc",[re]:"https://sepolia.base.org",[ne]:"https://api.dexter.cash/api/evm/arbitrum/rpc",[ie]:"https://api.dexter.cash/api/evm/polygon/rpc",[se]:"https://api.dexter.cash/api/evm/optimism/rpc",[oe]:"https://api.dexter.cash/api/evm/avalanche/rpc",[H]:"https://worldchain-mainnet.g.alchemy.com/public",[q]:"https://rpc.monad.xyz",[F]:"https://rpc.mainnet.chain.robinhood.com",[W]:"https://skale-base.skalenodes.com/v1/base",[j]:"https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",[ce]:"https://eth.llamarpc.com"},X="https://x402.dexter.cash";function ue(t){return t.startsWith("solana:")||t==="solana"}function Rt(t){if(typeof Buffer<"u")return Buffer.from(t,"utf-8").toString("base64");let e=new TextEncoder().encode(t),r="";for(let n=0;n<e.length;n++)r+=String.fromCharCode(e[n]);return btoa(r)}function Tt(t){if(typeof Buffer<"u")return Buffer.from(t,"base64").toString("utf-8");let e=atob(t),r=new Uint8Array(e.length);for(let n=0;n<e.length;n++)r[n]=e.charCodeAt(n);return new TextDecoder().decode(r)}function me(t){return Rt(JSON.stringify(t))}function J(t){return JSON.parse(Tt(t))}function Pt(t){if(t instanceof TypeError)return!0;if(t&&typeof t=="object"&&"status"in t){let e=t.status;return e>=500&&e<600}return!1}var G=class extends Error{status;body;constructor(e,r){super(`HTTP ${e}`),this.status=e,this.body=r}},de=class{facilitatorUrl;cachedSupported=null;cacheTime=0;CACHE_TTL_MS=6e4;timeoutMs;maxRetries;retryBaseMs;constructor(e=X,r){this.facilitatorUrl=e.replace(/\/$/,""),this.timeoutMs=r?.timeoutMs??1e4,this.maxRetries=r?.maxRetries??3,this.retryBaseMs=r?.retryBaseMs??500}async fetchWithTimeout(e,r){let n=new AbortController,i=setTimeout(()=>n.abort(),this.timeoutMs);try{return await fetch(e,{...r,signal:n.signal})}finally{clearTimeout(i)}}async fetchWithRetry(e,r){let n;for(let i=0;i<this.maxRetries;i++)try{let s=await this.fetchWithTimeout(e,r);if(!s.ok&&s.status>=500)throw new G(s.status,await s.text());return s}catch(s){if(n=s,i<this.maxRetries-1&&Pt(s)){let h=this.retryBaseMs*Math.pow(2,i);await new Promise(c=>setTimeout(c,h));continue}throw s}throw n}async getSupported(){let e=Date.now();if(this.cachedSupported&&e-this.cacheTime<this.CACHE_TTL_MS)return this.cachedSupported;let r=await this.fetchWithTimeout(`${this.facilitatorUrl}/supported`);if(!r.ok)throw new Error(`Facilitator /supported returned ${r.status}`);return this.cachedSupported=await r.json(),this.cacheTime=e,this.cachedSupported}async getFeePayer(e){let n=(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval")&&i.network===e);if(!n)throw new Error(`Facilitator does not support network "${e}" with a recognized scheme`);return n.extra?.feePayer}async getNetworkExtra(e){return(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval"||i.scheme==="batch-settlement")&&i.network===e)?.extra}async verifyPayment(e,r){try{let n=J(e),i=await this.fetchWithRetry(`${this.facilitatorUrl}/verify`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:n,paymentRequirements:r})});return i.ok?await i.json():{isValid:!1,invalidReason:`facilitator_error_${i.status}`}}catch(n){return{isValid:!1,invalidReason:n instanceof G?`facilitator_error_${n.status}`:n instanceof Error&&n.name==="AbortError"?"facilitator_timeout":n instanceof Error?n.message:"unexpected_verify_error"}}}async settlePayment(e,r){try{let n=J(e),i=await this.fetchWithRetry(`${this.facilitatorUrl}/settle`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:n,paymentRequirements:r})});return i.ok?{...await i.json(),network:r.network}:{success:!1,network:r.network,errorReason:`facilitator_error_${i.status}`}}catch(n){let i=n instanceof G?`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 _t(t){if(ue(t))return{address:le,decimals:6};let e=Ze[t];if(e){let r=Qe[e]?.decimals??6;return{address:e,decimals:r}}return{address:le,decimals:6}}function et(t){try{let e=J(t);return e?.accepted?.amount??e?.accepted?.maxAmountRequired}catch{return}}function Y(t){let{payTo:e,facilitatorUrl:r=X,network:n=N,defaultTimeoutSeconds:i=60}=t,s=t.asset??_t(n),h=t.scheme??"exact";if(h==="tab"&&!ue(n))throw new Error(`scheme 'tab' is SVM-only; got network "${n}"`);let c=new de(r),a=null,m=new Map,l=3e4,o=Date.now();function y(u){let g=(u.maxTimeoutSeconds||i)*1e3;if(m.set(u.payTo,{accept:u,expiresAt:Date.now()+g}),Date.now()-o>l){let A=Date.now();for(let[S,I]of m)I.expiresAt<A&&m.delete(S);o=A}}function d(u){let g=m.get(u);if(g){if(g.expiresAt<Date.now()){m.delete(u);return}return g.accept}}async function f(u){return typeof e=="string"?e:e(u||{})}async function b(){if(a||(a=await c.getNetworkExtra(n)),ue(n)&&!a?.feePayer)throw new Error(`Facilitator does not provide feePayer for network "${n}"`);return{...a?.feePayer?{feePayer:a.feePayer}:{},decimals:a?.decimals??s.decimals,name:a?.name,version:a?.version,...h==="batch-settlement"&&a?.receiverAuthorizer?{receiverAuthorizer:a.receiverAuthorizer}:{},...h==="tab"?{voucherHeader:"x-tab-voucher",registrationEncoding:"base64(188-byte sessionRegisterMessage)"}:{}}}async function V(u,g){let{amountAtomic:A,timeoutSeconds:S=i}=g,I=await b(),O={scheme:h,network:n,amount:A,maxAmountRequired:A,asset:s.address,payTo:u,maxTimeoutSeconds:S,extra:I};return y(O),O}async function L(u){let g=await f({amountAtomic:u.amountAtomic,resourceUrl:u.resourceUrl});return V(g,u)}async function pe(u){let{resourceUrl:g,description:A,mimeType:S="application/json"}=u,I={url:g,description:A,mimeType:S},O=await L(u);return{x402Version:2,resource:I,accepts:[O],error:"Payment required"}}function B(u){return me(u)}function Z(u){return{status:402,headers:{"PAYMENT-REQUIRED":B(u)},body:{}}}async function ge(u,g){if(!g){let A=await f({paymentHeader:u});g=d(A),g||(g=await V(A,{amountAtomic:et(u)??"0",resourceUrl:""}))}return c.verifyPayment(u,g)}async function Q(u,g){if(!g){let A=await f({paymentHeader:u});g=d(A),g||(g=await V(A,{amountAtomic:et(u)??"0",resourceUrl:""}))}return c.settlePayment(u,g)}return{buildRequirements:pe,encodeRequirements:B,create402Response:Z,verifyPayment:ge,settlePayment:Q,getPaymentAccept:L,network:n,assetDecimals:s.decimals,facilitator:c}}var kt={"solana:mainnet":N};function It(t){let e=kt[t.network];if(!e)throw new Error(`tabChallengeMiddleware: unsupported network "${t.network}"`);let r=typeof t.sellerPubkey=="string"?t.sellerPubkey:t.sellerPubkey.toBase58();new Nt(r);let n=Y({payTo:r,network:e,scheme:"tab",facilitatorUrl:t.facilitatorUrl}),i=R(t.perUnit);return async(s,h,c)=>{if(s.headers[$])return c();try{let a=`${s.protocol}://${s.get("host")}${s.originalUrl}`,m=await n.buildRequirements({amountAtomic:i,resourceUrl:a,description:t.description}),l=n.create402Response(m);h.set(l.headers).status(l.status).json(l.body)}catch(a){let m=a?.message??String(a);h.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:m})}}}import{PublicKey as Ot}from"@solana/web3.js";var Ut={"solana:mainnet":N};function $t(t){let e=Ut[t.network];if(!e)throw new Error(`tabOrExactMiddleware: unsupported network "${t.network}"`);let r=typeof t.sellerPubkey=="string"?t.sellerPubkey:t.sellerPubkey.toBase58();new Ot(r);let n=Y({payTo:r,network:e,scheme:"tab",facilitatorUrl:t.facilitatorUrl}),i=Y({payTo:r,network:e,scheme:"exact",facilitatorUrl:t.facilitatorUrl}),s=R(t.perUnit),h=Oe({connection:t.connection,sellerPubkey:r,network:t.network,perUnit:t.perUnit,settle:"on-close",facilitatorUrl:t.facilitatorUrl,lockCadence:t.lockCadence});return async(c,a,m)=>{if(c.headers[$])return h(c,a,m);let l=`${c.protocol}://${c.get("host")}${c.originalUrl}`,o=c.headers["payment-signature"];if(o){let y;try{y=await i.getPaymentAccept({amountAtomic:s,resourceUrl:l,description:t.description})}catch(d){let f=d?.message??String(d);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:f});return}try{let d=await i.verifyPayment(o,y);if(!d.isValid){a.status(402).json({error:"Payment verification failed",reason:d.invalidReason});return}let f=await i.settlePayment(o,y);if(!f.success){a.status(402).json({error:"Payment settlement failed",reason:f.errorReason});return}return c.x402={transaction:f.transaction,payer:d.payer??"",network:f.network||e},a.setHeader("PAYMENT-RESPONSE",me({success:!0,transaction:f.transaction,network:f.network||e,payer:d.payer??""})),m()}catch{a.status(500).json({error:"Payment processing error"});return}}try{let y={amountAtomic:s,resourceUrl:l,description:t.description},[d,f]=await Promise.all([n.buildRequirements(y),i.buildRequirements(y)]),b={...d,accepts:[...d.accepts,...f.accepts]};a.set({"PAYMENT-REQUIRED":n.encodeRequirements(b)}).status(402).json({error:"Payment required",accepts:b.accepts,resource:b.resource})}catch(y){let d=y?.message??String(y);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:d})}}}export{fe as FileChannelLedger,Le as FileVoucherStore,D as InMemoryChannelLedger,Ve as InMemoryVoucherStore,E as InvalidRegistrationError,x as InvalidVoucherError,_ as InvalidVoucherSignatureError,k as OnChainVerificationError,ve as RedisChannelLedger,C as ScopeViolationError,$ as TAB_VOUCHER_HEADER,be as deserializeChannelLedgerEntry,Pe as enforceScope,At as openSse,Ee as parseRegistration,ft as requireTab,Ae as serializeChannelLedgerEntry,It as tabChallengeMiddleware,Oe as tabMiddleware,$t as tabOrExactMiddleware,Re as verifyRegistrationOnChain,Te as verifyVoucherSignature};
6
+ `),t.end())}return{charge:l,send:s,end:y}}import{promises as M}from"fs";import{join as It,dirname as Vt}from"path";function Nt(t){return{payload:t.payload,sessionPublicKey:ke(t.sessionPublicKey),sessionRegistration:ke(t.sessionRegistration),sessionSignature:ke(t.sessionSignature)}}function Ot(t){return{payload:t.payload,sessionPublicKey:Ue(t.sessionPublicKey),sessionRegistration:Ue(t.sessionRegistration),sessionSignature:Ue(t.sessionSignature)}}function ke(t){let e="";for(let n of t)e+=n.toString(16).padStart(2,"0");return e}function Ue(t){if(t.length%2!==0)throw new Error(`hex length must be even, got ${t.length}`);let e=new Uint8Array(t.length/2);for(let n=0;n<e.length;n++)e[n]=parseInt(t.substr(n*2,2),16);return e}var Be=class{map=new Map;async get(e){return this.map.get(e)??null}async set(e,n){this.map.set(e,n)}async delete(e){this.map.delete(e)}},De=class{constructor(e){this.dir=e}dir;pathFor(e){if(!/^[a-z0-9_-]+$/i.test(e))throw new Error(`unsafe channelId for filesystem: ${e}`);return It(this.dir,`${e}.json`)}async get(e){try{let n=await M.readFile(this.pathFor(e),"utf8");return Ot(JSON.parse(n))}catch(n){if(n?.code==="ENOENT")return null;throw n}}async set(e,n){let r=this.pathFor(e);await M.mkdir(Vt(r),{recursive:!0});let i=`${r}.tmp`;await M.writeFile(i,JSON.stringify(Nt(n))),await M.rename(i,r)}async delete(e){try{await M.unlink(this.pathFor(e))}catch(n){if(n?.code!=="ENOENT")throw n}}};import{PublicKey as Mt}from"@solana/web3.js";var V="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",Ge="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",Ye="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";var q="eip155:8453",ie="eip155:84532",oe="eip155:42161",se="eip155:137",ae="eip155:10",ce="eip155:43114",le="eip155:56",F="eip155:480",z="eip155:143",H="eip155:4663",W="eip155:1187947933",X="eip155:324705682",ue="eip155:1";var me="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";var Ze="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",kt="0x55d398326f99059fF775485246999027B3197955",Qe="0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",Ut="0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168",et={[le]:Qe,[q]:Ze,[ie]:"0x036CbD53842c5426634e7929541eC2318f3dCF7e",[oe]:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831",[se]:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",[ae]:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",[ce]:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",[F]:"0x79A02482A880bCE3F13e09Da970dC34db4CD24d1",[z]:"0x754704Bc059F8C67012fEd69BC8A327a5aafb603",[H]:Ut,[W]:"0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",[X]:"0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",[ue]:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},tt={[kt]:{symbol:"USDT",decimals:18},[Qe]:{symbol:"USDC",decimals:18}};var Br={[F]:{name:"USDC",version:"2"},[z]:{name:"USDC",version:"2"},[H]:{name:"Global Dollar",version:"1"},[W]:{name:"Bridged USDC (SKALE Bridge)",version:"2"},[X]:{name:"Bridged USDC (SKALE Bridge)",version:"2"}};var Dr={[le]:56,[q]:8453,[ie]:84532,[oe]:42161,[se]:137,[ae]:10,[ce]:43114,[F]:480,[z]:143,[H]:4663,[W]:1187947933,[X]:324705682,[ue]:1},Kr={[V]:"https://api.dexter.cash/api/solana/rpc",[Ge]:"https://api.devnet.solana.com",[Ye]:"https://api.testnet.solana.com"},Bt={[le]:"https://api.dexter.cash/api/evm/bsc/rpc",[q]:"https://api.dexter.cash/api/base/rpc",[ie]:"https://sepolia.base.org",[oe]:"https://api.dexter.cash/api/evm/arbitrum/rpc",[se]:"https://api.dexter.cash/api/evm/polygon/rpc",[ae]:"https://api.dexter.cash/api/evm/optimism/rpc",[ce]:"https://api.dexter.cash/api/evm/avalanche/rpc",[F]:"https://worldchain-mainnet.g.alchemy.com/public",[z]:"https://rpc.monad.xyz",[H]:"https://rpc.mainnet.chain.robinhood.com",[W]:"https://skale-base.skalenodes.com/v1/base",[X]:"https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",[ue]:"https://eth.llamarpc.com"},j="https://x402.dexter.cash";var nt="dexter-tab-hosted-pay-before-delivery/v1",rt="pay_before_delivery_seller_2xx",it="x-tab-voucher",ot="base64(188-byte sessionRegisterMessage)";function de(t){return t.startsWith("solana:")||t==="solana"}function Dt(t){if(typeof Buffer<"u")return Buffer.from(t,"utf-8").toString("base64");let e=new TextEncoder().encode(t),n="";for(let r=0;r<e.length;r++)n+=String.fromCharCode(e[r]);return btoa(n)}function Kt(t){if(typeof Buffer<"u")return Buffer.from(t,"base64").toString("utf-8");let e=atob(t),n=new Uint8Array(e.length);for(let r=0;r<e.length;r++)n[r]=e.charCodeAt(r);return new TextDecoder().decode(n)}function pe(t){return Dt(JSON.stringify(t))}function J(t){return JSON.parse(Kt(t))}function $t(t){if(t instanceof TypeError)return!0;if(t&&typeof t=="object"&&"status"in t){let e=t.status;return e>=500&&e<600}return!1}var G=class extends Error{status;body;constructor(e,n){super(`HTTP ${e}`),this.status=e,this.body=n}},ge=class{facilitatorUrl;cachedSupported=null;cacheTime=0;CACHE_TTL_MS=6e4;timeoutMs;maxRetries;retryBaseMs;constructor(e=j,n){this.facilitatorUrl=e.replace(/\/$/,""),this.timeoutMs=n?.timeoutMs??1e4,this.maxRetries=n?.maxRetries??3,this.retryBaseMs=n?.retryBaseMs??500}async fetchWithTimeout(e,n){let r=new AbortController,i=setTimeout(()=>r.abort(),this.timeoutMs);try{return await fetch(e,{...n,signal:r.signal})}finally{clearTimeout(i)}}async fetchWithRetry(e,n){let r;for(let i=0;i<this.maxRetries;i++)try{let o=await this.fetchWithTimeout(e,n);if(!o.ok&&o.status>=500)throw new G(o.status,await o.text());return o}catch(o){if(r=o,i<this.maxRetries-1&&$t(o)){let u=this.retryBaseMs*Math.pow(2,i);await new Promise(c=>setTimeout(c,u));continue}throw o}throw r}async getSupported(){let e=Date.now();if(this.cachedSupported&&e-this.cacheTime<this.CACHE_TTL_MS)return this.cachedSupported;let n=await this.fetchWithTimeout(`${this.facilitatorUrl}/supported`);if(!n.ok)throw new Error(`Facilitator /supported returned ${n.status}`);return this.cachedSupported=await n.json(),this.cacheTime=e,this.cachedSupported}async getFeePayer(e){let r=(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval")&&i.network===e);if(!r)throw new Error(`Facilitator does not support network "${e}" with a recognized scheme`);return r.extra?.feePayer}async getNetworkExtra(e){return(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval"||i.scheme==="batch-settlement")&&i.network===e)?.extra}async verifyPayment(e,n){try{let r=J(e),i=await this.fetchWithRetry(`${this.facilitatorUrl}/verify`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:r,paymentRequirements:n})});return i.ok?await i.json():{isValid:!1,invalidReason:`facilitator_error_${i.status}`}}catch(r){return{isValid:!1,invalidReason:r instanceof G?`facilitator_error_${r.status}`:r instanceof Error&&r.name==="AbortError"?"facilitator_timeout":r instanceof Error?r.message:"unexpected_verify_error"}}}async settlePayment(e,n){try{let r=J(e),i=await this.fetchWithRetry(`${this.facilitatorUrl}/settle`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:r,paymentRequirements:n})});return i.ok?{...await i.json(),network:n.network}:{success:!1,network:n.network,errorReason:`facilitator_error_${i.status}`}}catch(r){let i=r instanceof G?`facilitator_error_${r.status}`:r instanceof Error&&r.name==="AbortError"?"facilitator_timeout":r instanceof Error?r.message:"unexpected_settle_error";return{success:!1,network:n.network,errorReason:i}}}};function Lt(t){if(de(t))return{address:me,decimals:6};let e=et[t];if(e){let n=tt[e]?.decimals??6;return{address:e,decimals:n}}return{address:me,decimals:6}}function st(t){try{let e=J(t);return e?.accepted?.amount??e?.accepted?.maxAmountRequired}catch{return}}function Y(t){let{payTo:e,facilitatorUrl:n=j,network:r=V,defaultTimeoutSeconds:i=60}=t,o=t.asset??Lt(r),u=t.scheme??"exact";if(u==="tab"&&!de(r))throw new Error(`scheme 'tab' is SVM-only; got network "${r}"`);let c=new ge(n),a=null,d=new Map,l=3e4,s=Date.now();function y(m){let h=(m.maxTimeoutSeconds||i)*1e3;if(d.set(m.payTo,{accept:m,expiresAt:Date.now()+h}),Date.now()-s>l){let A=Date.now();for(let[S,N]of d)N.expiresAt<A&&d.delete(S);s=A}}function p(m){let h=d.get(m);if(h){if(h.expiresAt<Date.now()){d.delete(m);return}return h.accept}}async function f(m){return typeof e=="string"?e:e(m||{})}async function v(){if(a||(a=await c.getNetworkExtra(r)),de(r)&&!a?.feePayer)throw new Error(`Facilitator does not provide feePayer for network "${r}"`);return{...a?.feePayer?{feePayer:a.feePayer}:{},decimals:a?.decimals??o.decimals,name:a?.name,version:a?.version,...u==="batch-settlement"&&a?.receiverAuthorizer?{receiverAuthorizer:a.receiverAuthorizer}:{},...u==="tab"?{voucherHeader:it,registrationEncoding:ot,termsVersion:nt,acceptanceRule:rt}:{}}}async function B(m,h){let{amountAtomic:A,timeoutSeconds:S=i}=h,N=await v(),O={scheme:u,network:r,amount:A,maxAmountRequired:A,asset:o.address,payTo:m,maxTimeoutSeconds:S,extra:N};return y(O),O}async function D(m){let h=await f({amountAtomic:m.amountAtomic,resourceUrl:m.resourceUrl});return B(h,m)}async function he(m){let{resourceUrl:h,description:A,mimeType:S="application/json"}=m,N={url:h,description:A,mimeType:S},O=await D(m);return{x402Version:2,resource:N,accepts:[O],error:"Payment required"}}function K(m){return pe(m)}function Z(m){return{status:402,headers:{"PAYMENT-REQUIRED":K(m)},body:{}}}async function fe(m,h){if(!h){let A=await f({paymentHeader:m});h=p(A),h||(h=await B(A,{amountAtomic:st(m)??"0",resourceUrl:""}))}return c.verifyPayment(m,h)}async function Q(m,h){if(!h){let A=await f({paymentHeader:m});h=p(A),h||(h=await B(A,{amountAtomic:st(m)??"0",resourceUrl:""}))}return c.settlePayment(m,h)}return{buildRequirements:he,encodeRequirements:K,create402Response:Z,verifyPayment:fe,settlePayment:Q,getPaymentAccept:D,network:r,assetDecimals:o.decimals,facilitator:c}}var qt={"solana:mainnet":V};function Ft(t){let e=qt[t.network];if(!e)throw new Error(`tabChallengeMiddleware: unsupported network "${t.network}"`);let n=typeof t.sellerPubkey=="string"?t.sellerPubkey:t.sellerPubkey.toBase58();new Mt(n);let r=Y({payTo:n,network:e,scheme:"tab",facilitatorUrl:t.facilitatorUrl}),i=C(t.perUnit);return async(o,u,c)=>{if(o.headers[U])return c();try{let a=`${o.protocol}://${o.get("host")}${o.originalUrl}`,d=await r.buildRequirements({amountAtomic:i,resourceUrl:a,description:t.description}),l=r.create402Response(d);u.set(l.headers).status(l.status).json(l.body)}catch(a){let d=a?.message??String(a);u.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:d})}}}import{PublicKey as zt}from"@solana/web3.js";var Ht={"solana:mainnet":V};function Wt(t){let e=Ht[t.network];if(!e)throw new Error(`tabOrExactMiddleware: unsupported network "${t.network}"`);let n=typeof t.sellerPubkey=="string"?t.sellerPubkey:t.sellerPubkey.toBase58();new zt(n);let r=Y({payTo:n,network:e,scheme:"tab",facilitatorUrl:t.facilitatorUrl}),i=Y({payTo:n,network:e,scheme:"exact",facilitatorUrl:t.facilitatorUrl}),o=C(t.perUnit),u=Oe({connection:t.connection,sellerPubkey:n,network:t.network,perUnit:t.perUnit,settle:"on-close",facilitatorUrl:t.facilitatorUrl,lockCadence:t.lockCadence});return async(c,a,d)=>{if(c.headers[U])return u(c,a,d);let l=`${c.protocol}://${c.get("host")}${c.originalUrl}`,s=c.headers["payment-signature"];if(s){let y;try{y=await i.getPaymentAccept({amountAtomic:o,resourceUrl:l,description:t.description})}catch(p){let f=p?.message??String(p);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:f});return}try{let p=await i.verifyPayment(s,y);if(!p.isValid){a.status(402).json({error:"Payment verification failed",reason:p.invalidReason});return}let f=await i.settlePayment(s,y);if(!f.success){a.status(402).json({error:"Payment settlement failed",reason:f.errorReason});return}return c.x402={transaction:f.transaction,payer:p.payer??"",network:f.network||e},a.setHeader("PAYMENT-RESPONSE",pe({success:!0,transaction:f.transaction,network:f.network||e,payer:p.payer??""})),d()}catch{a.status(500).json({error:"Payment processing error"});return}}try{let y={amountAtomic:o,resourceUrl:l,description:t.description},[p,f]=await Promise.all([r.buildRequirements(y),i.buildRequirements(y)]),v={...p,accepts:[...p.accepts,...f.accepts]};a.set({"PAYMENT-REQUIRED":r.encodeRequirements(v)}).status(402).json({error:"Payment required",accepts:v.accepts,resource:v.resource})}catch(y){let p=y?.message??String(y);a.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:p})}}}export{ve as FileChannelLedger,De as FileVoucherStore,L as InMemoryChannelLedger,Be as InMemoryVoucherStore,T as InvalidRegistrationError,x as InvalidVoucherError,E as InvalidVoucherSignatureError,I as OnChainVerificationError,Se as RedisChannelLedger,_ as ScopeViolationError,U as TAB_VOUCHER_HEADER,we as deserializeChannelLedgerEntry,Pe as enforceScope,Tt as openSse,te as parseRegistration,Pt as requireTab,be as serializeChannelLedgerEntry,Ft as tabChallengeMiddleware,Oe as tabMiddleware,Wt as tabOrExactMiddleware,Ce as verifyRegistrationOnChain,Re as verifyVoucherSignature};
@@ -25,10 +25,17 @@ interface VaultAdapter {
25
25
  swigAddress: string;
26
26
  /** Program/contract account holding the OTS gate state. */
27
27
  vaultPda: string;
28
+ /**
29
+ * Voucher generation this adapter issues. V6 requires `2` for buyer-side
30
+ * open/recovery. The `1` discriminator remains only so a historical adapter
31
+ * is rejected explicitly instead of being mistaken for V2 or silently
32
+ * falling through after an obligation may exist.
33
+ */
34
+ readonly sessionVoucherVersion: 1 | 2;
28
35
  /**
29
36
  * Use the ROOT signer (passkey) to authorize a fresh session key. This is
30
- * the only call that prompts the user (twice when atomically replacing a
31
- * live session one revoke ceremony + one register ceremony). Returns a
37
+ * the only call that prompts the user. V7 live replacement binds retirement
38
+ * and replacement into one ceremony. Returns a
32
39
  * session that can be passed to `signWithSession` freely until the scope's
33
40
  * cap or expiry is reached.
34
41
  *
@@ -54,7 +61,78 @@ interface VaultAdapter {
54
61
  * facilitator settles via `settle_voucher(amount, increment: false)`.
55
62
  */
56
63
  signCloseTab(session: SessionKey, channelId: string, cumulativeAmount: AtomicAmount): Promise<Uint8Array>;
64
+ /**
65
+ * V2-only independent postcondition check. The reservation provider returns
66
+ * a voucher-bound receipt; the adapter must then prove the corresponding
67
+ * finalized on-chain reservation and authority-signed voucher-binding Memo
68
+ * from its own chain connection before the voucher may leave this process.
69
+ * V1 adapters omit this method.
70
+ */
71
+ verifyFinalVoucherV2Reservation?: VerifyFinalVoucherV2Reservation;
72
+ }
73
+ /** Exact durable release fence for a buyer-signed FINAL V2 voucher. */
74
+ interface FinalVoucherV2ReservationInput {
75
+ network: TabNetworkId;
76
+ programId: string;
77
+ buyerSwigAddress: string;
78
+ vaultPda: string;
79
+ sessionPda: string;
80
+ seller: string;
81
+ channelId: string;
82
+ sessionNonce: number;
83
+ reservationAmountAtomic: AtomicAmount;
84
+ previousCumulativeAtomic: AtomicAmount;
85
+ /** SHA-256 of the canonical complete voucher identity. */
86
+ voucherDigest: string;
87
+ /** SDK retry identity. Exact-byte retries retain this value; provider
88
+ * lifecycle and receipt identities remain provider-owned and distinct. */
89
+ idempotencyKey: string;
90
+ voucher: SignedVoucher;
57
91
  }
92
+ /**
93
+ * Provider attestation returned only after its durable transaction lifecycle
94
+ * has finalized the exact reservation and read back the exact post-state.
95
+ * The SDK validates every voucher/session field and the VaultAdapter proves
96
+ * both the reservation and its authority-signed voucher-binding Memo from the
97
+ * transaction itself; this is deliberately not a boolean ack.
98
+ */
99
+ interface FinalVoucherV2ReservationReceipt {
100
+ contract: 'dexter-native-tab-open-receipt/v1' | 'dexter-native-tab-open-receipt/v2';
101
+ operationId: string;
102
+ callerOperationId: string;
103
+ network: string;
104
+ transaction: string;
105
+ /** FINAL vouchers are released only after the exact reservation transaction
106
+ * reaches Solana finalized commitment. A merely confirmed fork is not a
107
+ * durable capacity guarantee. */
108
+ commitment: 'finalized';
109
+ confirmationSlot: number;
110
+ postStateSlot: number;
111
+ buyerSwigAddress: string;
112
+ vaultPda: string;
113
+ sessionPda: string;
114
+ seller: string;
115
+ channelId: string;
116
+ sessionPublicKey: string;
117
+ voucherDigest: string;
118
+ cumulativeAmountAtomic: string;
119
+ sequenceNumber: number;
120
+ providerReceiptId: string;
121
+ reservationAmountAtomic: string;
122
+ pendingVoucherCountBefore: number;
123
+ pendingVoucherCountAfter: number;
124
+ currentOutstandingBeforeAtomic: '0';
125
+ currentOutstandingAfterAtomic: string;
126
+ rootOperationId?: string;
127
+ generation?: number;
128
+ predecessorCallerOperationId?: string;
129
+ predecessorLifecycleOperationId?: string;
130
+ predecessorReleaseDigest?: string;
131
+ stableReservationId?: string;
132
+ economicEffectDigest?: string;
133
+ }
134
+ type ReserveFinalVoucherV2 = (input: FinalVoucherV2ReservationInput) => Promise<FinalVoucherV2ReservationReceipt>;
135
+ type VerifyFinalVoucherV2Reservation = (input: FinalVoucherV2ReservationInput, receipt: FinalVoucherV2ReservationReceipt) => Promise<void>;
58
136
  /**
59
137
  * Live-session policy for `authorizeSession` / `openTab` (K-T4e).
60
138
  *
@@ -69,8 +147,7 @@ interface VaultAdapter {
69
147
  * (`tab.close()` — or POST its last signed voucher to `/tab/settle`) and
70
148
  * retries, or acknowledges the replace explicitly.
71
149
  * - `'replace'`: compose the ATOMIC same-transaction
72
- * [secp(revoke), revoke, secp(register), register] so the buyer is never
73
- * left sessionless mid-flow. Costs a second passkey ceremony. Value
150
+ * [secp(replace), replace] so the buyer is never left sessionless. Value
74
151
  * already settled or crystallized into LockedClaims survives the replace;
75
152
  * anything signed beyond the frontier is voided.
76
153
  */
@@ -106,6 +183,14 @@ interface TabState {
106
183
  interface Tab {
107
184
  /** Deterministic channel id derived from buyer/seller/scope/salt. */
108
185
  readonly channelId: string;
186
+ /**
187
+ * Voucher contract used by this live handle. V2 FINAL vouchers are fenced
188
+ * by a durable reservation and therefore may never fall through to another
189
+ * payment rail after an indeterminate signing/reservation error.
190
+ *
191
+ * Required in v6. An absent generation is not safely equivalent to V1.
192
+ */
193
+ readonly voucherVersion: 1 | 2;
109
194
  /** Which network the underlying vault lives on. */
110
195
  readonly network: TabNetworkId;
111
196
  /**
@@ -179,7 +264,7 @@ interface OpenTabOptions {
179
264
  vault: VaultAdapter;
180
265
  /** CAIP-2-style network the vault lives on; cross-checked against vault.network. */
181
266
  network: TabNetworkId;
182
- /** Seller's endpoint host (used for the counterparty binding + voucher routing). */
267
+ /** Seller's base58 Solana public key for the counterparty binding. */
183
268
  seller: string;
184
269
  /** Max amount per voucher — caps how aggressive a single charge can be. */
185
270
  perUnitCap: HumanAmount;
@@ -203,6 +288,12 @@ interface OpenTabOptions {
203
288
  * See {@link AuthorizeSessionOptions}.
204
289
  */
205
290
  onLiveSession?: 'error' | 'replace';
291
+ /**
292
+ * Required by V2-capable adapters. The callback must durably persist and
293
+ * establish the exact FINAL voucher reservation before resolving. It must
294
+ * be idempotent for identical voucher bytes; a timeout is retried exactly.
295
+ */
296
+ reserveFinalVoucherV2?: ReserveFinalVoucherV2;
206
297
  }
207
298
  /**
208
299
  * Options for `resumeTab` — open a handle to a tab that was opened by a
@@ -227,6 +318,18 @@ declare class UnsupportedNetworkError extends Error {
227
318
  readonly network: string;
228
319
  constructor(network: string);
229
320
  }
321
+ /**
322
+ * Thrown before buyer-side I/O when v6 is asked to open or reconstruct a
323
+ * historical V1 tab. The coupled v6 facilitator has no compatible V1 arming
324
+ * endpoint and the Vault-wide pending counter cannot prove which historical
325
+ * session owns an existing reservation. Seller-side verification of already
326
+ * issued V1 vouchers remains available so those obligations can be settled.
327
+ */
328
+ declare class HistoricalV1MigrationRequiredError extends Error {
329
+ readonly surface: 'armTabOpen' | 'openTab' | 'tabFromGrant';
330
+ readonly code = "native_tab_v1_migration_required";
331
+ constructor(surface: 'armTabOpen' | 'openTab' | 'tabFromGrant');
332
+ }
230
333
  /** Thrown by a buyer call when the session-key cap or expiry would be exceeded. */
231
334
  declare class SessionScopeExceededError extends Error {
232
335
  readonly reason: 'cap_exceeded' | 'expired' | 'wrong_counterparty';
@@ -277,4 +380,4 @@ declare class LiveSessionExistsError extends Error {
277
380
  constructor(details: LiveSessionDetails);
278
381
  }
279
382
 
280
- export { type AuthorizeSessionOptions as A, type LiveSessionDetails as L, type OpenTabOptions as O, type ResumeTabOptions as R, SessionScopeExceededError as S, type Tab as T, UnsupportedNetworkError as U, type VaultAdapter as V, type TabState as a, type TabCloseResult as b, TabClosedError as c, LiveSessionExistsError as d };
383
+ export { type AuthorizeSessionOptions as A, type FinalVoucherV2ReservationInput as F, HistoricalV1MigrationRequiredError as H, type LiveSessionDetails as L, type OpenTabOptions as O, type ResumeTabOptions as R, SessionScopeExceededError as S, type Tab as T, UnsupportedNetworkError as U, type VerifyFinalVoucherV2Reservation as V, type FinalVoucherV2ReservationReceipt as a, type VaultAdapter as b, LiveSessionExistsError as c, type ReserveFinalVoucherV2 as d, type TabCloseResult as e, TabClosedError as f, type TabState as g };