@dexterai/x402 3.12.0 → 3.13.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.
@@ -1,6 +1,6 @@
1
1
  import { W as WalletSet, S as SettlementProbe, a as SolanaWallet, E as EvmWallet, A as AccessPassClientConfig, P as PaymentAccept } from '../types-xQu1U4xk.cjs';
2
2
  export { e as AccessPassInfo, d as AccessPassTier, C as ChainAdapter, X as X402Error, b as createEvmAdapter, c as createSolanaAdapter } from '../types-xQu1U4xk.cjs';
3
- import { T as Tab } from '../types-D1HhKTg7.cjs';
3
+ import { T as Tab } from '../types-DEnVPFxF.cjs';
4
4
  import { SIWxSigner } from '@x402/extensions/sign-in-with-x';
5
5
  import { Keypair } from '@solana/web3.js';
6
6
  export { P as PaymentReceipt, d as X402Client, X as X402ClientConfig, c as createX402Client, f as fireImpressionBeacon, b as getPaymentReceipt, a as getSponsoredAccessInfo, g as getSponsoredRecommendations } from '../x402-client-DmRbvqoc.cjs';
@@ -1,6 +1,6 @@
1
1
  import { W as WalletSet, S as SettlementProbe, a as SolanaWallet, E as EvmWallet, A as AccessPassClientConfig, P as PaymentAccept } from '../types-xQu1U4xk.js';
2
2
  export { e as AccessPassInfo, d as AccessPassTier, C as ChainAdapter, X as X402Error, b as createEvmAdapter, c as createSolanaAdapter } from '../types-xQu1U4xk.js';
3
- import { T as Tab } from '../types-D1HhKTg7.js';
3
+ import { T as Tab } from '../types-DEnVPFxF.js';
4
4
  import { SIWxSigner } from '@x402/extensions/sign-in-with-x';
5
5
  import { Keypair } from '@solana/web3.js';
6
6
  export { P as PaymentReceipt, d as X402Client, X as X402ClientConfig, c as createX402Client, f as fireImpressionBeacon, b as getPaymentReceipt, a as getSponsoredAccessInfo, g as getSponsoredRecommendations } from '../x402-client-Ug0vrj74.js';
@@ -1,6 +1,6 @@
1
1
  import * as _solana_web3_js from '@solana/web3.js';
2
2
  import { PublicKey, Connection, Signer, ConfirmOptions } from '@solana/web3.js';
3
- import { V as VaultAdapter } from '../../../types-D1HhKTg7.cjs';
3
+ import { V as VaultAdapter } from '../../../types-DEnVPFxF.cjs';
4
4
  import '@dexterai/vault/types';
5
5
 
6
6
  /**
@@ -1,6 +1,6 @@
1
1
  import * as _solana_web3_js from '@solana/web3.js';
2
2
  import { PublicKey, Connection, Signer, ConfirmOptions } from '@solana/web3.js';
3
- import { V as VaultAdapter } from '../../../types-D1HhKTg7.js';
3
+ import { V as VaultAdapter } from '../../../types-DEnVPFxF.js';
4
4
  import '@dexterai/vault/types';
5
5
 
6
6
  /**
@@ -1,6 +1,6 @@
1
- "use strict";var E=Object.create;var S=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var O=Object.getPrototypeOf,_=Object.prototype.hasOwnProperty;var H=(e,t)=>{for(var n in t)S(e,n,{get:t[n],enumerable:!0})},I=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of $(t))!_.call(e,o)&&o!==n&&S(e,o,{get:()=>t[o],enumerable:!(r=N(t,o))||r.enumerable});return e};var M=(e,t,n)=>(n=e!=null?E(O(e)):{},I(t||!e||!e.__esModule?S(n,"default",{value:e,enumerable:!0}):n,e)),B=e=>I(S({},"__esModule",{value:!0}),e);var z={};H(z,{DEFAULT_FACILITATOR_URL:()=>v,DEXTER_VAULT_PROGRAM_ID:()=>c.DEXTER_VAULT_PROGRAM_ID,INSTRUCTIONS_SYSVAR_ID:()=>c.INSTRUCTIONS_SYSVAR_ID,SECP256R1_PROGRAM_ID:()=>c.SECP256R1_PROGRAM_ID,SessionScopeExceededError:()=>p,TabClosedError:()=>u,UnsupportedNetworkError:()=>d,atomicToHuman:()=>b,buildRegisterSessionKeyInstruction:()=>h.buildRegisterSessionKeyInstruction,buildRevokeSessionKeyInstruction:()=>h.buildRevokeSessionKeyInstruction,buildSecp256r1VerifyInstruction:()=>T.buildSecp256r1VerifyInstruction,buildVoucherMessage:()=>a.buildVoucherMessage,humanToAtomic:()=>y,openTab:()=>C,resumeTab:()=>k,sessionRegisterMessage:()=>a.sessionRegisterMessage,sessionRevokeMessage:()=>a.sessionRevokeMessage,voucherPayloadMessage:()=>a.voucherPayloadMessage,voucherToHeader:()=>x});module.exports=B(z);var d=class extends Error{constructor(n){super(`Network ${n} is not yet supported by @dexterai/x402/tab`);this.network=n;this.name="UnsupportedNetworkError"}},p=class extends Error{constructor(n,r){super(`Session scope exceeded: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="SessionScopeExceededError"}},u=class extends Error{constructor(n){super(`Tab ${n} is already closed`);this.channelId=n;this.name="TabClosedError"}};var f=require("@solana/web3.js"),l=require("@noble/hashes/utils");var D=M(require("tweetnacl"),1);var a=require("@dexterai/vault/messages");var R=require("@noble/hashes/sha256");function U(e){let t=new Uint8Array(8);new DataView(t.buffer).setBigUint64(0,e.nonce,!0);let n=new TextEncoder().encode(e.sellerUrl),r=R.sha256.create();return r.update(e.vaultPda.toBytes()),r.update(n),r.update(t),r.digest()}var q=3600,v="https://x402.dexter.cash",V=6;function y(e,t=V){if(!/^\d+(\.\d+)?$/.test(e))throw new Error(`amount must be a non-negative decimal string, got "${e}"`);let[n,r=""]=e.split(".");if(r.length>t)throw new Error(`amount "${e}" has more than ${t} decimals`);let o=r.padEnd(t,"0"),s=`${n}${o}`.replace(/^0+(?=\d)/,"");return s===""?"0":s}function b(e,t=V){if(!/^\d+$/.test(e))throw new Error(`atomic must be a non-negative integer string, got "${e}"`);let n=e.padStart(t+1,"0"),r=n.slice(0,-t).replace(/^0+(?=\d)/,"")||"0",o=n.slice(-t).replace(/0+$/,"");return o?`${r}.${o}`:r}var w=class{channelId;network;counterparty;internals;cumulativeAtomic=0n;sequenceNumber=0;closed=!1;lastSignedVoucher=null;previousSignedVoucher=null;constructor(t){this.internals=t,this.channelId=t.channelIdHex,this.network=t.network,this.counterparty=t.counterparty}get state(){let t=this.internals.totalCapAtomic-this.cumulativeAtomic,n=Math.floor(Date.now()/1e3);return{isOpen:!this.closed,spent:b(this.cumulativeAtomic.toString()),remaining:b(t.toString()),expiresInSec:Math.max(0,this.internals.expiresAtUnix-n)}}async signNextVoucher(t){if(this.closed)throw new u(this.channelId);let n=BigInt(t);if(n<=0n)throw new Error(`voucher increment must be > 0, got ${t}`);if(n>this.internals.perUnitCapAtomic)throw new p("cap_exceeded",`single voucher increment ${n} exceeds perUnitCap ${this.internals.perUnitCapAtomic}`);let r=this.cumulativeAtomic+n;if(r>this.internals.totalCapAtomic)throw new p("cap_exceeded",`cumulative ${r} would exceed totalCap ${this.internals.totalCapAtomic}`);let o=this.sequenceNumber+1,s={channelId:this.channelId,cumulativeAmount:r.toString(),sequenceNumber:o},i=await this.internals.vault.signWithSession(this.internals.session,s);return this.previousSignedVoucher=this.lastSignedVoucher,this.lastSignedVoucher=i,this.sequenceNumber=o,this.cumulativeAtomic=r,i}rollbackVoucher(t){let n=this.lastSignedVoucher;if(!n||n.payload.sequenceNumber!==t.payload.sequenceNumber||n.payload.cumulativeAmount!==t.payload.cumulativeAmount)return!1;let r=this.previousSignedVoucher;if(r)this.sequenceNumber=r.payload.sequenceNumber,this.cumulativeAtomic=BigInt(r.payload.cumulativeAmount),this.lastSignedVoucher=r;else if(n.payload.sequenceNumber===1)this.sequenceNumber=0,this.cumulativeAtomic=0n,this.lastSignedVoucher=null;else return!1;return this.previousSignedVoucher=null,!0}async stream(t,n){if(this.closed)throw new u(this.channelId);let r=await this.signNextVoucher(this.internals.perUnitCapAtomic.toString()),o=new Headers(n?.headers);o.set("X-Tab-Voucher",x(r)),o.set("Accept","text/event-stream");let s=await fetch(t,{...n,headers:o});if(!s.ok){let i=await s.text().catch(()=>"");throw new Error(`tab.stream HTTP ${s.status}: ${i.slice(0,500)}`)}if(!s.body)throw new Error("tab.stream response has no body");return J(s.body)}async close(){if(this.closed)throw new u(this.channelId);let t="";return this.lastSignedVoucher&&this.cumulativeAtomic>0n&&(t=await L(this.internals.facilitatorUrl,this.lastSignedVoucher,this.internals.network)),await this.internals.vault.signCloseTab(this.internals.session,this.channelId,this.cumulativeAtomic.toString()),this.closed=!0,this.internals.session.privateKey.fill(0),{settledAmount:b(this.cumulativeAtomic.toString()),settleTx:t}}};function x(e){return Buffer.from(JSON.stringify({payload:e.payload,sessionPublicKey:(0,l.bytesToHex)(e.sessionPublicKey),sessionRegistration:(0,l.bytesToHex)(e.sessionRegistration),sessionSignature:(0,l.bytesToHex)(e.sessionSignature)}),"utf8").toString("base64")}async function L(e,t,n){let r=`${e.replace(/\/$/,"")}/tab/settle`,o={channelId:t.payload.channelId,cumulativeAmount:t.payload.cumulativeAmount,sequenceNumber:t.payload.sequenceNumber,sessionPublicKey:(0,l.bytesToHex)(t.sessionPublicKey),sessionSignature:(0,l.bytesToHex)(t.sessionSignature),sessionRegistration:(0,l.bytesToHex)(t.sessionRegistration),network:n},s=await fetch(r,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(o)}),i=await s.text();if(!s.ok)throw new Error(`tab settle ${s.status}: ${i.slice(0,500)}`);let m;try{m=JSON.parse(i)}catch{throw new Error(`tab settle returned non-JSON: ${i.slice(0,200)}`)}if(!m.settleTx)throw new Error(`tab settle returned no settleTx: ${i.slice(0,200)}`);return m.settleTx}async function C(e){if(e.network!==e.vault.network)throw new d(`options.network (${e.network}) doesn't match vault.network (${e.vault.network})`);if(e.network!=="solana:mainnet")throw new d(e.network);let t=BigInt(Math.floor(Math.random()*4294967295)),n=new f.PublicKey(e.vault.vaultPda),r=U({vaultPda:n,sellerUrl:e.seller,nonce:BigInt(t)}),o=(0,l.bytesToHex)(r),s=BigInt(y(e.perUnitCap)),i=BigInt(y(e.totalCap));if(s<=0n)throw new Error("perUnitCap must be > 0");if(i<s)throw new Error("totalCap must be >= perUnitCap");if(e.revolvingCapacity!==void 0&&BigInt(y(e.revolvingCapacity))<=0n)throw new Error("revolvingCapacity must be > 0");let m=e.sessionDuration??q,g=Math.floor(Date.now()/1e3)+m,A=F(e.seller),P={channelId:o,maxAmountAtomic:i.toString(),revolvingCapacityAtomic:e.revolvingCapacity?y(e.revolvingCapacity):i.toString(),expiresAtUnix:g,allowedCounterparty:A},K=await e.vault.authorizeSession(P);return new w({vault:e.vault,network:e.network,seller:e.seller,counterparty:A,session:K,channelIdHex:o,channelIdBytes:r,perUnitCapAtomic:s,totalCapAtomic:i,expiresAtUnix:g,facilitatorUrl:e.facilitatorUrl??v})}async function k(e){throw new Error("resumeTab is Phase 3 work. Session keys are memory-only by design; recovery requires reading active_session on chain and re-authorizing. Tracked in dexter-vault roadmap.")}function F(e){if(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(e))try{return new f.PublicKey(e),e}catch{}throw new Error(`seller must be a base58 Solana pubkey for Phase 2 (got "${e}"). URL-based counterparty resolution lands in Phase 3 (seller middleware).`)}async function*J(e){let t=e.getReader(),n=new TextDecoder,r="";try{for(;;){let{done:o,value:s}=await t.read();if(o)break;r+=n.decode(s,{stream:!0});let i;for(;(i=r.indexOf(`
1
+ "use strict";var E=Object.create;var S=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var O=Object.getPrototypeOf,_=Object.prototype.hasOwnProperty;var H=(e,t)=>{for(var n in t)S(e,n,{get:t[n],enumerable:!0})},I=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of $(t))!_.call(e,o)&&o!==n&&S(e,o,{get:()=>t[o],enumerable:!(r=N(t,o))||r.enumerable});return e};var M=(e,t,n)=>(n=e!=null?E(O(e)):{},I(t||!e||!e.__esModule?S(n,"default",{value:e,enumerable:!0}):n,e)),B=e=>I(S({},"__esModule",{value:!0}),e);var z={};H(z,{DEFAULT_FACILITATOR_URL:()=>v,DEXTER_VAULT_PROGRAM_ID:()=>l.DEXTER_VAULT_PROGRAM_ID,INSTRUCTIONS_SYSVAR_ID:()=>l.INSTRUCTIONS_SYSVAR_ID,SECP256R1_PROGRAM_ID:()=>l.SECP256R1_PROGRAM_ID,SessionScopeExceededError:()=>g,TabClosedError:()=>m,UnsupportedNetworkError:()=>p,atomicToHuman:()=>A,buildRegisterSessionKeyInstruction:()=>h.buildRegisterSessionKeyInstruction,buildRevokeSessionKeyInstruction:()=>h.buildRevokeSessionKeyInstruction,buildSecp256r1VerifyInstruction:()=>T.buildSecp256r1VerifyInstruction,buildVoucherMessage:()=>u.buildVoucherMessage,humanToAtomic:()=>y,openTab:()=>V,resumeTab:()=>C,sessionRegisterMessage:()=>u.sessionRegisterMessage,sessionRevokeMessage:()=>u.sessionRevokeMessage,voucherPayloadMessage:()=>u.voucherPayloadMessage,voucherToHeader:()=>x});module.exports=B(z);var p=class extends Error{constructor(n){super(`Network ${n} is not yet supported by @dexterai/x402/tab`);this.network=n;this.name="UnsupportedNetworkError"}},g=class extends Error{constructor(n,r){super(`Session scope exceeded: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="SessionScopeExceededError"}},m=class extends Error{constructor(n){super(`Tab ${n} is already closed`);this.channelId=n;this.name="TabClosedError"}};var w=require("@solana/web3.js"),d=require("@noble/hashes/utils");var D=M(require("tweetnacl"),1);var u=require("@dexterai/vault/messages");var R=require("@noble/hashes/sha256");function U(e){let t=new Uint8Array(8);new DataView(t.buffer).setBigUint64(0,e.nonce,!0);let n=new TextEncoder().encode(e.sellerUrl),r=R.sha256.create();return r.update(e.vaultPda.toBytes()),r.update(n),r.update(t),r.digest()}var q=3600,v="https://x402.dexter.cash",k=6;function y(e,t=k){if(!/^\d+(\.\d+)?$/.test(e))throw new Error(`amount must be a non-negative decimal string, got "${e}"`);let[n,r=""]=e.split(".");if(r.length>t)throw new Error(`amount "${e}" has more than ${t} decimals`);let o=r.padEnd(t,"0"),s=`${n}${o}`.replace(/^0+(?=\d)/,"");return s===""?"0":s}function A(e,t=k){if(!/^\d+$/.test(e))throw new Error(`atomic must be a non-negative integer string, got "${e}"`);let n=e.padStart(t+1,"0"),r=n.slice(0,-t).replace(/^0+(?=\d)/,"")||"0",o=n.slice(-t).replace(/0+$/,"");return o?`${r}.${o}`:r}var f=class{channelId;network;counterparty;internals;cumulativeAtomic=0n;sequenceNumber=0;closed=!1;lastSignedVoucher=null;previousSignedVoucher=null;constructor(t){this.internals=t,this.channelId=t.channelIdHex,this.network=t.network,this.counterparty=t.counterparty}get state(){let t=this.internals.totalCapAtomic-this.cumulativeAtomic,n=Math.floor(Date.now()/1e3);return{isOpen:!this.closed,spent:A(this.cumulativeAtomic.toString()),remaining:A(t.toString()),expiresInSec:Math.max(0,this.internals.expiresAtUnix-n)}}async signNextVoucher(t){if(this.closed)throw new m(this.channelId);let n=BigInt(t);if(n<=0n)throw new Error(`voucher increment must be > 0, got ${t}`);if(n>this.internals.perUnitCapAtomic)throw new g("cap_exceeded",`single voucher increment ${n} exceeds perUnitCap ${this.internals.perUnitCapAtomic}`);let r=this.cumulativeAtomic+n;if(r>this.internals.totalCapAtomic)throw new g("cap_exceeded",`cumulative ${r} would exceed totalCap ${this.internals.totalCapAtomic}`);let o=this.sequenceNumber+1,s={channelId:this.channelId,cumulativeAmount:r.toString(),sequenceNumber:o},i=await this.internals.vault.signWithSession(this.internals.session,s);return this.previousSignedVoucher=this.lastSignedVoucher,this.lastSignedVoucher=i,this.sequenceNumber=o,this.cumulativeAtomic=r,i}rollbackVoucher(t){let n=this.lastSignedVoucher;if(!n||n.payload.sequenceNumber!==t.payload.sequenceNumber||n.payload.cumulativeAmount!==t.payload.cumulativeAmount)return!1;let r=this.previousSignedVoucher;if(r)this.sequenceNumber=r.payload.sequenceNumber,this.cumulativeAtomic=BigInt(r.payload.cumulativeAmount),this.lastSignedVoucher=r;else if(n.payload.sequenceNumber===1)this.sequenceNumber=0,this.cumulativeAtomic=0n,this.lastSignedVoucher=null;else return!1;return this.previousSignedVoucher=null,!0}async stream(t,n){if(this.closed)throw new m(this.channelId);let r=await this.signNextVoucher(this.internals.perUnitCapAtomic.toString()),o=new Headers(n?.headers);o.set("X-Tab-Voucher",x(r)),o.set("Accept","text/event-stream");let s=await fetch(t,{...n,headers:o});if(!s.ok){let i=await s.text().catch(()=>"");throw new Error(`tab.stream HTTP ${s.status}: ${i.slice(0,500)}`)}if(!s.body)throw new Error("tab.stream response has no body");return J(s.body)}async close(){if(this.closed)throw new m(this.channelId);let t={settleTx:""};return this.lastSignedVoucher&&this.cumulativeAtomic>0n&&(t=await L(this.internals.facilitatorUrl,this.lastSignedVoucher,this.internals.network)),await this.internals.vault.signCloseTab(this.internals.session,this.channelId,this.cumulativeAtomic.toString()),this.closed=!0,this.internals.session.privateKey.fill(0),{settledAmount:A(this.cumulativeAtomic.toString()),...t}}};function x(e){return Buffer.from(JSON.stringify({payload:e.payload,sessionPublicKey:(0,d.bytesToHex)(e.sessionPublicKey),sessionRegistration:(0,d.bytesToHex)(e.sessionRegistration),sessionSignature:(0,d.bytesToHex)(e.sessionSignature)}),"utf8").toString("base64")}async function L(e,t,n){let r=`${e.replace(/\/$/,"")}/tab/settle`,o={channelId:t.payload.channelId,cumulativeAmount:t.payload.cumulativeAmount,sequenceNumber:t.payload.sequenceNumber,sessionPublicKey:(0,d.bytesToHex)(t.sessionPublicKey),sessionSignature:(0,d.bytesToHex)(t.sessionSignature),sessionRegistration:(0,d.bytesToHex)(t.sessionRegistration),network:n},s=await fetch(r,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(o)}),i=await s.text();if(!s.ok)throw new Error(`tab settle ${s.status}: ${i.slice(0,500)}`);let a;try{a=JSON.parse(i)}catch{throw new Error(`tab settle returned non-JSON: ${i.slice(0,200)}`)}if(!a.settleTx)throw new Error(`tab settle returned no settleTx: ${i.slice(0,200)}`);let c={settleTx:a.settleTx};return typeof a.grossAmount=="string"&&(c.grossAmount=a.grossAmount),typeof a.feeAmount=="string"&&(c.feeAmount=a.feeAmount),typeof a.netAmount=="string"&&(c.netAmount=a.netAmount),c}async function V(e){if(e.network!==e.vault.network)throw new p(`options.network (${e.network}) doesn't match vault.network (${e.vault.network})`);if(e.network!=="solana:mainnet")throw new p(e.network);let t=BigInt(Math.floor(Math.random()*4294967295)),n=new w.PublicKey(e.vault.vaultPda),r=U({vaultPda:n,sellerUrl:e.seller,nonce:BigInt(t)}),o=(0,d.bytesToHex)(r),s=BigInt(y(e.perUnitCap)),i=BigInt(y(e.totalCap));if(s<=0n)throw new Error("perUnitCap must be > 0");if(i<s)throw new Error("totalCap must be >= perUnitCap");if(e.revolvingCapacity!==void 0&&BigInt(y(e.revolvingCapacity))<=0n)throw new Error("revolvingCapacity must be > 0");let a=e.sessionDuration??q,c=Math.floor(Date.now()/1e3)+a,b=F(e.seller),P={channelId:o,maxAmountAtomic:i.toString(),revolvingCapacityAtomic:e.revolvingCapacity?y(e.revolvingCapacity):i.toString(),expiresAtUnix:c,allowedCounterparty:b},K=await e.vault.authorizeSession(P);return new f({vault:e.vault,network:e.network,seller:e.seller,counterparty:b,session:K,channelIdHex:o,channelIdBytes:r,perUnitCapAtomic:s,totalCapAtomic:i,expiresAtUnix:c,facilitatorUrl:e.facilitatorUrl??v})}async function C(e){throw new Error("resumeTab is Phase 3 work. Session keys are memory-only by design; recovery requires reading active_session on chain and re-authorizing. Tracked in dexter-vault roadmap.")}function F(e){if(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(e))try{return new w.PublicKey(e),e}catch{}throw new Error(`seller must be a base58 Solana pubkey for Phase 2 (got "${e}"). URL-based counterparty resolution lands in Phase 3 (seller middleware).`)}async function*J(e){let t=e.getReader(),n=new TextDecoder,r="";try{for(;;){let{done:o,value:s}=await t.read();if(o)break;r+=n.decode(s,{stream:!0});let i;for(;(i=r.indexOf(`
2
2
 
3
- `))!==-1;){let m=r.slice(0,i);r=r.slice(i+2);let g=W(m);if(g.eventName==="end")return;if(g.data!==null){let A=g.data.replace(/\\n/g,`
4
- `);yield new TextEncoder().encode(A)}}}}finally{t.releaseLock()}}function W(e){let t=null,n=[];for(let r of e.split(`
3
+ `))!==-1;){let a=r.slice(0,i);r=r.slice(i+2);let c=W(a);if(c.eventName==="end")return;if(c.data!==null){let b=c.data.replace(/\\n/g,`
4
+ `);yield new TextEncoder().encode(b)}}}}finally{t.releaseLock()}}function W(e){let t=null,n=[];for(let r of e.split(`
5
5
  `))r.startsWith("event:")?t=r.slice(6).trim():r.startsWith("data:")&&n.push(r.slice(5).trimStart());return{eventName:t,data:n.length?n.join(`
6
- `):null}}var h=require("@dexterai/vault/instructions"),T=require("@dexterai/vault/precompile"),c=require("@dexterai/vault/constants");0&&(module.exports={DEFAULT_FACILITATOR_URL,DEXTER_VAULT_PROGRAM_ID,INSTRUCTIONS_SYSVAR_ID,SECP256R1_PROGRAM_ID,SessionScopeExceededError,TabClosedError,UnsupportedNetworkError,atomicToHuman,buildRegisterSessionKeyInstruction,buildRevokeSessionKeyInstruction,buildSecp256r1VerifyInstruction,buildVoucherMessage,humanToAtomic,openTab,resumeTab,sessionRegisterMessage,sessionRevokeMessage,voucherPayloadMessage,voucherToHeader});
6
+ `):null}}var h=require("@dexterai/vault/instructions"),T=require("@dexterai/vault/precompile"),l=require("@dexterai/vault/constants");0&&(module.exports={DEFAULT_FACILITATOR_URL,DEXTER_VAULT_PROGRAM_ID,INSTRUCTIONS_SYSVAR_ID,SECP256R1_PROGRAM_ID,SessionScopeExceededError,TabClosedError,UnsupportedNetworkError,atomicToHuman,buildRegisterSessionKeyInstruction,buildRevokeSessionKeyInstruction,buildSecp256r1VerifyInstruction,buildVoucherMessage,humanToAtomic,openTab,resumeTab,sessionRegisterMessage,sessionRevokeMessage,voucherPayloadMessage,voucherToHeader});
@@ -1,5 +1,5 @@
1
- import { O as OpenTabOptions, T as Tab, R as ResumeTabOptions } from '../types-D1HhKTg7.cjs';
2
- export { S as SessionScopeExceededError, b as TabCloseResult, c as TabClosedError, a as TabState, U as UnsupportedNetworkError, V as VaultAdapter } from '../types-D1HhKTg7.cjs';
1
+ import { O as OpenTabOptions, T as Tab, R as ResumeTabOptions } from '../types-DEnVPFxF.cjs';
2
+ export { S as SessionScopeExceededError, b as TabCloseResult, c as TabClosedError, a as TabState, U as UnsupportedNetworkError, V as VaultAdapter } from '../types-DEnVPFxF.cjs';
3
3
  import { HumanAmount, AtomicAmount, SignedVoucher } from '@dexterai/vault/types';
4
4
  export { AtomicAmount, HumanAmount, SessionKey, SessionScope, SignedVoucher, TabNetworkId, VoucherPayload } from '@dexterai/vault/types';
5
5
  export { SessionRegisterMessageArgs, SessionRevokeMessageArgs, VoucherPayloadBytes, buildVoucherMessage, sessionRegisterMessage, sessionRevokeMessage, voucherPayloadMessage } from '@dexterai/vault/messages';
@@ -1,5 +1,5 @@
1
- import { O as OpenTabOptions, T as Tab, R as ResumeTabOptions } from '../types-D1HhKTg7.js';
2
- export { S as SessionScopeExceededError, b as TabCloseResult, c as TabClosedError, a as TabState, U as UnsupportedNetworkError, V as VaultAdapter } from '../types-D1HhKTg7.js';
1
+ import { O as OpenTabOptions, T as Tab, R as ResumeTabOptions } from '../types-DEnVPFxF.js';
2
+ export { S as SessionScopeExceededError, b as TabCloseResult, c as TabClosedError, a as TabState, U as UnsupportedNetworkError, V as VaultAdapter } from '../types-DEnVPFxF.js';
3
3
  import { HumanAmount, AtomicAmount, SignedVoucher } from '@dexterai/vault/types';
4
4
  export { AtomicAmount, HumanAmount, SessionKey, SessionScope, SignedVoucher, TabNetworkId, VoucherPayload } from '@dexterai/vault/types';
5
5
  export { SessionRegisterMessageArgs, SessionRevokeMessageArgs, VoucherPayloadBytes, buildVoucherMessage, sessionRegisterMessage, sessionRevokeMessage, voucherPayloadMessage } from '@dexterai/vault/messages';
package/dist/tab/index.js CHANGED
@@ -1,6 +1,6 @@
1
- var m=class extends Error{constructor(r){super(`Network ${r} is not yet supported by @dexterai/x402/tab`);this.network=r;this.name="UnsupportedNetworkError"}},d=class extends Error{constructor(r,n){super(`Session scope exceeded: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="SessionScopeExceededError"}},c=class extends Error{constructor(r){super(`Tab ${r} is already closed`);this.channelId=r;this.name="TabClosedError"}};import{PublicKey as S}from"@solana/web3.js";import{bytesToHex as u}from"@noble/hashes/utils";import z from"tweetnacl";import{sessionRegisterMessage as I,sessionRevokeMessage as R,voucherPayloadMessage as b,buildVoucherMessage as U}from"@dexterai/vault/messages";import{sha256 as V}from"@noble/hashes/sha256";function A(e){let t=new Uint8Array(8);new DataView(t.buffer).setBigUint64(0,e.nonce,!0);let r=new TextEncoder().encode(e.sellerUrl),n=V.create();return n.update(e.vaultPda.toBytes()),n.update(r),n.update(t),n.digest()}var C=3600,w="https://x402.dexter.cash",f=6;function p(e,t=f){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 s=n.padEnd(t,"0"),o=`${r}${s}`.replace(/^0+(?=\d)/,"");return o===""?"0":o}function g(e,t=f){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",s=r.slice(-t).replace(/0+$/,"");return s?`${n}.${s}`:n}var y=class{channelId;network;counterparty;internals;cumulativeAtomic=0n;sequenceNumber=0;closed=!1;lastSignedVoucher=null;previousSignedVoucher=null;constructor(t){this.internals=t,this.channelId=t.channelIdHex,this.network=t.network,this.counterparty=t.counterparty}get state(){let t=this.internals.totalCapAtomic-this.cumulativeAtomic,r=Math.floor(Date.now()/1e3);return{isOpen:!this.closed,spent:g(this.cumulativeAtomic.toString()),remaining:g(t.toString()),expiresInSec:Math.max(0,this.internals.expiresAtUnix-r)}}async signNextVoucher(t){if(this.closed)throw new c(this.channelId);let r=BigInt(t);if(r<=0n)throw new Error(`voucher increment must be > 0, got ${t}`);if(r>this.internals.perUnitCapAtomic)throw new d("cap_exceeded",`single voucher increment ${r} exceeds perUnitCap ${this.internals.perUnitCapAtomic}`);let n=this.cumulativeAtomic+r;if(n>this.internals.totalCapAtomic)throw new d("cap_exceeded",`cumulative ${n} would exceed totalCap ${this.internals.totalCapAtomic}`);let s=this.sequenceNumber+1,o={channelId:this.channelId,cumulativeAmount:n.toString(),sequenceNumber:s},i=await this.internals.vault.signWithSession(this.internals.session,o);return this.previousSignedVoucher=this.lastSignedVoucher,this.lastSignedVoucher=i,this.sequenceNumber=s,this.cumulativeAtomic=n,i}rollbackVoucher(t){let r=this.lastSignedVoucher;if(!r||r.payload.sequenceNumber!==t.payload.sequenceNumber||r.payload.cumulativeAmount!==t.payload.cumulativeAmount)return!1;let n=this.previousSignedVoucher;if(n)this.sequenceNumber=n.payload.sequenceNumber,this.cumulativeAtomic=BigInt(n.payload.cumulativeAmount),this.lastSignedVoucher=n;else if(r.payload.sequenceNumber===1)this.sequenceNumber=0,this.cumulativeAtomic=0n,this.lastSignedVoucher=null;else return!1;return this.previousSignedVoucher=null,!0}async stream(t,r){if(this.closed)throw new c(this.channelId);let n=await this.signNextVoucher(this.internals.perUnitCapAtomic.toString()),s=new Headers(r?.headers);s.set("X-Tab-Voucher",v(n)),s.set("Accept","text/event-stream");let o=await fetch(t,{...r,headers:s});if(!o.ok){let i=await o.text().catch(()=>"");throw new Error(`tab.stream HTTP ${o.status}: ${i.slice(0,500)}`)}if(!o.body)throw new Error("tab.stream response has no body");return N(o.body)}async close(){if(this.closed)throw new c(this.channelId);let t="";return this.lastSignedVoucher&&this.cumulativeAtomic>0n&&(t=await k(this.internals.facilitatorUrl,this.lastSignedVoucher,this.internals.network)),await this.internals.vault.signCloseTab(this.internals.session,this.channelId,this.cumulativeAtomic.toString()),this.closed=!0,this.internals.session.privateKey.fill(0),{settledAmount:g(this.cumulativeAtomic.toString()),settleTx:t}}};function v(e){return Buffer.from(JSON.stringify({payload:e.payload,sessionPublicKey:u(e.sessionPublicKey),sessionRegistration:u(e.sessionRegistration),sessionSignature:u(e.sessionSignature)}),"utf8").toString("base64")}async function k(e,t,r){let n=`${e.replace(/\/$/,"")}/tab/settle`,s={channelId:t.payload.channelId,cumulativeAmount:t.payload.cumulativeAmount,sequenceNumber:t.payload.sequenceNumber,sessionPublicKey:u(t.sessionPublicKey),sessionSignature:u(t.sessionSignature),sessionRegistration:u(t.sessionRegistration),network:r},o=await fetch(n,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)}),i=await o.text();if(!o.ok)throw new Error(`tab settle ${o.status}: ${i.slice(0,500)}`);let a;try{a=JSON.parse(i)}catch{throw new Error(`tab settle returned non-JSON: ${i.slice(0,200)}`)}if(!a.settleTx)throw new Error(`tab settle returned no settleTx: ${i.slice(0,200)}`);return a.settleTx}async function P(e){if(e.network!==e.vault.network)throw new m(`options.network (${e.network}) doesn't match vault.network (${e.vault.network})`);if(e.network!=="solana:mainnet")throw new m(e.network);let t=BigInt(Math.floor(Math.random()*4294967295)),r=new S(e.vault.vaultPda),n=A({vaultPda:r,sellerUrl:e.seller,nonce:BigInt(t)}),s=u(n),o=BigInt(p(e.perUnitCap)),i=BigInt(p(e.totalCap));if(o<=0n)throw new Error("perUnitCap must be > 0");if(i<o)throw new Error("totalCap must be >= perUnitCap");if(e.revolvingCapacity!==void 0&&BigInt(p(e.revolvingCapacity))<=0n)throw new Error("revolvingCapacity must be > 0");let a=e.sessionDuration??C,l=Math.floor(Date.now()/1e3)+a,h=E(e.seller),x={channelId:s,maxAmountAtomic:i.toString(),revolvingCapacityAtomic:e.revolvingCapacity?p(e.revolvingCapacity):i.toString(),expiresAtUnix:l,allowedCounterparty:h},T=await e.vault.authorizeSession(x);return new y({vault:e.vault,network:e.network,seller:e.seller,counterparty:h,session:T,channelIdHex:s,channelIdBytes:n,perUnitCapAtomic:o,totalCapAtomic:i,expiresAtUnix:l,facilitatorUrl:e.facilitatorUrl??w})}async function K(e){throw new Error("resumeTab is Phase 3 work. Session keys are memory-only by design; recovery requires reading active_session on chain and re-authorizing. Tracked in dexter-vault roadmap.")}function E(e){if(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(e))try{return new S(e),e}catch{}throw new Error(`seller must be a base58 Solana pubkey for Phase 2 (got "${e}"). URL-based counterparty resolution lands in Phase 3 (seller middleware).`)}async function*N(e){let t=e.getReader(),r=new TextDecoder,n="";try{for(;;){let{done:s,value:o}=await t.read();if(s)break;n+=r.decode(o,{stream:!0});let i;for(;(i=n.indexOf(`
1
+ var m=class extends Error{constructor(r){super(`Network ${r} is not yet supported by @dexterai/x402/tab`);this.network=r;this.name="UnsupportedNetworkError"}},d=class extends Error{constructor(r,n){super(`Session scope exceeded: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="SessionScopeExceededError"}},c=class extends Error{constructor(r){super(`Tab ${r} is already closed`);this.channelId=r;this.name="TabClosedError"}};import{PublicKey as S}from"@solana/web3.js";import{bytesToHex as l}from"@noble/hashes/utils";import z from"tweetnacl";import{sessionRegisterMessage as I,sessionRevokeMessage as R,voucherPayloadMessage as A,buildVoucherMessage as U}from"@dexterai/vault/messages";import{sha256 as k}from"@noble/hashes/sha256";function b(e){let t=new Uint8Array(8);new DataView(t.buffer).setBigUint64(0,e.nonce,!0);let r=new TextEncoder().encode(e.sellerUrl),n=k.create();return n.update(e.vaultPda.toBytes()),n.update(r),n.update(t),n.digest()}var V=3600,f="https://x402.dexter.cash",w=6;function p(e,t=w){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 s=n.padEnd(t,"0"),o=`${r}${s}`.replace(/^0+(?=\d)/,"");return o===""?"0":o}function h(e,t=w){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",s=r.slice(-t).replace(/0+$/,"");return s?`${n}.${s}`:n}var y=class{channelId;network;counterparty;internals;cumulativeAtomic=0n;sequenceNumber=0;closed=!1;lastSignedVoucher=null;previousSignedVoucher=null;constructor(t){this.internals=t,this.channelId=t.channelIdHex,this.network=t.network,this.counterparty=t.counterparty}get state(){let t=this.internals.totalCapAtomic-this.cumulativeAtomic,r=Math.floor(Date.now()/1e3);return{isOpen:!this.closed,spent:h(this.cumulativeAtomic.toString()),remaining:h(t.toString()),expiresInSec:Math.max(0,this.internals.expiresAtUnix-r)}}async signNextVoucher(t){if(this.closed)throw new c(this.channelId);let r=BigInt(t);if(r<=0n)throw new Error(`voucher increment must be > 0, got ${t}`);if(r>this.internals.perUnitCapAtomic)throw new d("cap_exceeded",`single voucher increment ${r} exceeds perUnitCap ${this.internals.perUnitCapAtomic}`);let n=this.cumulativeAtomic+r;if(n>this.internals.totalCapAtomic)throw new d("cap_exceeded",`cumulative ${n} would exceed totalCap ${this.internals.totalCapAtomic}`);let s=this.sequenceNumber+1,o={channelId:this.channelId,cumulativeAmount:n.toString(),sequenceNumber:s},i=await this.internals.vault.signWithSession(this.internals.session,o);return this.previousSignedVoucher=this.lastSignedVoucher,this.lastSignedVoucher=i,this.sequenceNumber=s,this.cumulativeAtomic=n,i}rollbackVoucher(t){let r=this.lastSignedVoucher;if(!r||r.payload.sequenceNumber!==t.payload.sequenceNumber||r.payload.cumulativeAmount!==t.payload.cumulativeAmount)return!1;let n=this.previousSignedVoucher;if(n)this.sequenceNumber=n.payload.sequenceNumber,this.cumulativeAtomic=BigInt(n.payload.cumulativeAmount),this.lastSignedVoucher=n;else if(r.payload.sequenceNumber===1)this.sequenceNumber=0,this.cumulativeAtomic=0n,this.lastSignedVoucher=null;else return!1;return this.previousSignedVoucher=null,!0}async stream(t,r){if(this.closed)throw new c(this.channelId);let n=await this.signNextVoucher(this.internals.perUnitCapAtomic.toString()),s=new Headers(r?.headers);s.set("X-Tab-Voucher",v(n)),s.set("Accept","text/event-stream");let o=await fetch(t,{...r,headers:s});if(!o.ok){let i=await o.text().catch(()=>"");throw new Error(`tab.stream HTTP ${o.status}: ${i.slice(0,500)}`)}if(!o.body)throw new Error("tab.stream response has no body");return N(o.body)}async close(){if(this.closed)throw new c(this.channelId);let t={settleTx:""};return this.lastSignedVoucher&&this.cumulativeAtomic>0n&&(t=await C(this.internals.facilitatorUrl,this.lastSignedVoucher,this.internals.network)),await this.internals.vault.signCloseTab(this.internals.session,this.channelId,this.cumulativeAtomic.toString()),this.closed=!0,this.internals.session.privateKey.fill(0),{settledAmount:h(this.cumulativeAtomic.toString()),...t}}};function v(e){return Buffer.from(JSON.stringify({payload:e.payload,sessionPublicKey:l(e.sessionPublicKey),sessionRegistration:l(e.sessionRegistration),sessionSignature:l(e.sessionSignature)}),"utf8").toString("base64")}async function C(e,t,r){let n=`${e.replace(/\/$/,"")}/tab/settle`,s={channelId:t.payload.channelId,cumulativeAmount:t.payload.cumulativeAmount,sequenceNumber:t.payload.sequenceNumber,sessionPublicKey:l(t.sessionPublicKey),sessionSignature:l(t.sessionSignature),sessionRegistration:l(t.sessionRegistration),network:r},o=await fetch(n,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)}),i=await o.text();if(!o.ok)throw new Error(`tab settle ${o.status}: ${i.slice(0,500)}`);let a;try{a=JSON.parse(i)}catch{throw new Error(`tab settle returned non-JSON: ${i.slice(0,200)}`)}if(!a.settleTx)throw new Error(`tab settle returned no settleTx: ${i.slice(0,200)}`);let u={settleTx:a.settleTx};return typeof a.grossAmount=="string"&&(u.grossAmount=a.grossAmount),typeof a.feeAmount=="string"&&(u.feeAmount=a.feeAmount),typeof a.netAmount=="string"&&(u.netAmount=a.netAmount),u}async function P(e){if(e.network!==e.vault.network)throw new m(`options.network (${e.network}) doesn't match vault.network (${e.vault.network})`);if(e.network!=="solana:mainnet")throw new m(e.network);let t=BigInt(Math.floor(Math.random()*4294967295)),r=new S(e.vault.vaultPda),n=b({vaultPda:r,sellerUrl:e.seller,nonce:BigInt(t)}),s=l(n),o=BigInt(p(e.perUnitCap)),i=BigInt(p(e.totalCap));if(o<=0n)throw new Error("perUnitCap must be > 0");if(i<o)throw new Error("totalCap must be >= perUnitCap");if(e.revolvingCapacity!==void 0&&BigInt(p(e.revolvingCapacity))<=0n)throw new Error("revolvingCapacity must be > 0");let a=e.sessionDuration??V,u=Math.floor(Date.now()/1e3)+a,g=E(e.seller),x={channelId:s,maxAmountAtomic:i.toString(),revolvingCapacityAtomic:e.revolvingCapacity?p(e.revolvingCapacity):i.toString(),expiresAtUnix:u,allowedCounterparty:g},T=await e.vault.authorizeSession(x);return new y({vault:e.vault,network:e.network,seller:e.seller,counterparty:g,session:T,channelIdHex:s,channelIdBytes:n,perUnitCapAtomic:o,totalCapAtomic:i,expiresAtUnix:u,facilitatorUrl:e.facilitatorUrl??f})}async function K(e){throw new Error("resumeTab is Phase 3 work. Session keys are memory-only by design; recovery requires reading active_session on chain and re-authorizing. Tracked in dexter-vault roadmap.")}function E(e){if(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(e))try{return new S(e),e}catch{}throw new Error(`seller must be a base58 Solana pubkey for Phase 2 (got "${e}"). URL-based counterparty resolution lands in Phase 3 (seller middleware).`)}async function*N(e){let t=e.getReader(),r=new TextDecoder,n="";try{for(;;){let{done:s,value:o}=await t.read();if(s)break;n+=r.decode(o,{stream:!0});let i;for(;(i=n.indexOf(`
2
2
 
3
- `))!==-1;){let a=n.slice(0,i);n=n.slice(i+2);let l=$(a);if(l.eventName==="end")return;if(l.data!==null){let h=l.data.replace(/\\n/g,`
4
- `);yield new TextEncoder().encode(h)}}}}finally{t.releaseLock()}}function $(e){let t=null,r=[];for(let n of e.split(`
3
+ `))!==-1;){let a=n.slice(0,i);n=n.slice(i+2);let u=$(a);if(u.eventName==="end")return;if(u.data!==null){let g=u.data.replace(/\\n/g,`
4
+ `);yield new TextEncoder().encode(g)}}}}finally{t.releaseLock()}}function $(e){let t=null,r=[];for(let n of e.split(`
5
5
  `))n.startsWith("event:")?t=n.slice(6).trim():n.startsWith("data:")&&r.push(n.slice(5).trimStart());return{eventName:t,data:r.length?r.join(`
6
- `):null}}import{buildRegisterSessionKeyInstruction as O,buildRevokeSessionKeyInstruction as _,deriveSwigWalletAddress as oe}from"@dexterai/vault/instructions";import{buildSecp256r1VerifyInstruction as H}from"@dexterai/vault/precompile";import{DEXTER_VAULT_PROGRAM_ID as M,SECP256R1_PROGRAM_ID as B,INSTRUCTIONS_SYSVAR_ID as D}from"@dexterai/vault/constants";export{w as DEFAULT_FACILITATOR_URL,M as DEXTER_VAULT_PROGRAM_ID,D as INSTRUCTIONS_SYSVAR_ID,B as SECP256R1_PROGRAM_ID,d as SessionScopeExceededError,c as TabClosedError,m as UnsupportedNetworkError,g as atomicToHuman,O as buildRegisterSessionKeyInstruction,_ as buildRevokeSessionKeyInstruction,H as buildSecp256r1VerifyInstruction,U as buildVoucherMessage,p as humanToAtomic,P as openTab,K as resumeTab,I as sessionRegisterMessage,R as sessionRevokeMessage,b as voucherPayloadMessage,v as voucherToHeader};
6
+ `):null}}import{buildRegisterSessionKeyInstruction as O,buildRevokeSessionKeyInstruction as _,deriveSwigWalletAddress as oe}from"@dexterai/vault/instructions";import{buildSecp256r1VerifyInstruction as H}from"@dexterai/vault/precompile";import{DEXTER_VAULT_PROGRAM_ID as M,SECP256R1_PROGRAM_ID as B,INSTRUCTIONS_SYSVAR_ID as D}from"@dexterai/vault/constants";export{f as DEFAULT_FACILITATOR_URL,M as DEXTER_VAULT_PROGRAM_ID,D as INSTRUCTIONS_SYSVAR_ID,B as SECP256R1_PROGRAM_ID,d as SessionScopeExceededError,c as TabClosedError,m as UnsupportedNetworkError,h as atomicToHuman,O as buildRegisterSessionKeyInstruction,_ as buildRevokeSessionKeyInstruction,H as buildSecp256r1VerifyInstruction,U as buildVoucherMessage,p as humanToAtomic,P as openTab,K as resumeTab,I as sessionRegisterMessage,R as sessionRevokeMessage,A as voucherPayloadMessage,v as voucherToHeader};
@@ -1,6 +1,6 @@
1
- "use strict";var te=Object.create;var P=Object.defineProperty;var ne=Object.getOwnPropertyDescriptor;var re=Object.getOwnPropertyNames;var oe=Object.getPrototypeOf,ie=Object.prototype.hasOwnProperty;var se=(e,t)=>{for(var n in t)P(e,n,{get:t[n],enumerable:!0})},L=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of re(t))!ie.call(e,o)&&o!==n&&P(e,o,{get:()=>t[o],enumerable:!(r=ne(t,o))||r.enumerable});return e};var F=(e,t,n)=>(n=e!=null?te(oe(e)):{},L(t||!e||!e.__esModule?P(n,"default",{value:e,enumerable:!0}):n,e)),ae=e=>L(P({},"__esModule",{value:!0}),e);var Se={};se(Se,{FileVoucherStore:()=>U,InMemoryVoucherStore:()=>v,InvalidRegistrationError:()=>d,InvalidVoucherError:()=>m,InvalidVoucherSignatureError:()=>h,OnChainVerificationError:()=>y,ScopeViolationError:()=>u,TAB_VOUCHER_HEADER:()=>E,enforceScope:()=>C,openSse:()=>Q,parseRegistration:()=>I,readVaultState:()=>N,requireTab:()=>Z,tabMiddleware:()=>Y,verifyRegistrationOnChain:()=>V,verifyVoucherSignature:()=>k});module.exports=ae(Se);var m=class extends Error{constructor(n,r){super(`Invalid voucher: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="InvalidVoucherError"}};var X=require("@solana/web3.js");var G=F(require("tweetnacl"),1),ue=require("@noble/hashes/sha256"),le=require("@noble/curves/p256"),T=require("@solana/web3.js");var w=require("@dexterai/vault/messages");var K=require("@dexterai/vault/instructions"),ce=require("@dexterai/vault/precompile"),b=require("@dexterai/vault/constants");var O="OTS_SESSION_REGISTER_V2",d=class extends Error{constructor(n,r){super(`Invalid registration: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="InvalidRegistrationError"}};function I(e){if(e.length!==188)throw new d("wrong_length",`expected 188, got ${e.length}`);let t=new TextDecoder().decode(e.slice(0,O.length));if(t!==O)throw new d("wrong_domain",`got "${t}"`);for(let a=O.length;a<32;a++)if(e[a]!==0)throw new d("wrong_domain",`non-NUL padding at byte ${a}`);let n=new DataView(e.buffer,e.byteOffset,e.byteLength),r=new T.PublicKey(e.slice(32,64)),o=new T.PublicKey(e.slice(64,96)),l=e.slice(96,128),p=n.getBigUint64(128,!0),f=n.getBigInt64(136,!0),i=new T.PublicKey(e.slice(144,176)),c=n.getUint32(176,!0),g=n.getBigUint64(180,!0);if(!r.equals(b.DEXTER_VAULT_PROGRAM_ID))throw new d("wrong_program",`${r.toBase58()} is not ${b.DEXTER_VAULT_PROGRAM_ID.toBase58()}`);if(p===0n)throw new d("cap_zero");let s=BigInt(Math.floor(Date.now()/1e3));if(f<=s)throw new d("expiry_in_past",`expires_at=${f}, now=${s}`);return{programId:r,vaultPda:o,sessionPubkey:new Uint8Array(l),maxAmount:p,expiresAt:f,allowedCounterparty:i,nonce:c,maxRevolvingCapacity:g}}var j=10,y=class extends Error{constructor(n,r){super(`On-chain verification failed: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="OnChainVerificationError"}};async function N(e,t){let n=await e.getAccountInfo(t,"finalized");if(!n)throw new y("vault_not_found",t.toBase58());if(!n.owner.equals(b.DEXTER_VAULT_PROGRAM_ID))throw new y("wrong_program",`owner ${n.owner.toBase58()} is not the vault program`);let r=n.data,o=new Uint8Array(r.slice(j,j+33)),c=84+(r[83]===1?48:0)+32+32;if(r[c]!==1)return{passkeyPubkey:o,activeSessionPubkey:null};let s=c+1,a=new Uint8Array(r.slice(s,s+32));return{passkeyPubkey:o,activeSessionPubkey:a}}async function V(e,t){let n=await N(e,t.vaultPda);if(n.activeSessionPubkey===null)throw new y("session_not_active","vault has no active_session \u2014 was it revoked?");if(!me(n.activeSessionPubkey,t.sessionPubkey))throw new y("session_pubkey_mismatch",`on-chain ${J(n.activeSessionPubkey)} != registration ${J(t.sessionPubkey)}`);return{passkeyPubkey:n.passkeyPubkey}}var h=class extends Error{constructor(t){super(`Invalid voucher signature${t?`: ${t}`:""}`),this.name="InvalidVoucherSignatureError"}};function k(e,t){if(t.length!==32)throw new h(`channelIdBytes must be 32 bytes, got ${t.length}`);if(e.sessionPublicKey.length!==32)throw new h(`sessionPublicKey must be 32 bytes, got ${e.sessionPublicKey.length}`);if(e.sessionSignature.length!==64)throw new h(`sessionSignature must be 64 bytes, got ${e.sessionSignature.length}`);let n=(0,w.voucherPayloadMessage)({channelId:t,cumulativeAmount:BigInt(e.payload.cumulativeAmount),sequenceNumber:e.payload.sequenceNumber});if(!G.default.sign.detached.verify(n,e.sessionSignature,e.sessionPublicKey))throw new h("ed25519 verify rejected")}var u=class extends Error{constructor(n,r){super(`Scope violation: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="ScopeViolationError"}};function C(e){let t=BigInt(e.voucher.payload.cumulativeAmount);if(t>e.registration.maxAmount)throw new u("cumulative_exceeds_cap",`${t} > ${e.registration.maxAmount}`);let n=BigInt(Math.floor(Date.now()/1e3));if(n>=e.registration.expiresAt)throw new u("session_expired",`now=${n} >= expiresAt=${e.registration.expiresAt}`);if(!e.registration.allowedCounterparty.equals(e.expectedCounterparty))throw new u("wrong_counterparty",`${e.registration.allowedCounterparty.toBase58()} != ${e.expectedCounterparty.toBase58()}`);if(e.previousCumulativeAtomic!==void 0){let r=BigInt(e.previousCumulativeAtomic);if(t<=r)throw new u("non_monotonic",`cumulative=${t} not > previous=${r}`)}}function me(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}function J(e){let t="";for(let n of e)t+=n.toString(16).padStart(2,"0");return t}var S=require("fs"),_=require("path");function de(e){return{payload:e.payload,sessionPublicKey:H(e.sessionPublicKey),sessionRegistration:H(e.sessionRegistration),sessionSignature:H(e.sessionSignature)}}function pe(e){return{payload:e.payload,sessionPublicKey:B(e.sessionPublicKey),sessionRegistration:B(e.sessionRegistration),sessionSignature:B(e.sessionSignature)}}function H(e){let t="";for(let n of e)t+=n.toString(16).padStart(2,"0");return t}function B(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 n=0;n<t.length;n++)t[n]=parseInt(e.substr(n*2,2),16);return t}var v=class{map=new Map;async get(t){return this.map.get(t)??null}async set(t,n){this.map.set(t,n)}async delete(t){this.map.delete(t)}},U=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,_.join)(this.dir,`${t}.json`)}async get(t){try{let n=await S.promises.readFile(this.pathFor(t),"utf8");return pe(JSON.parse(n))}catch(n){if(n?.code==="ENOENT")return null;throw n}}async set(t,n){let r=this.pathFor(t);await S.promises.mkdir((0,_.dirname)(r),{recursive:!0});let o=`${r}.tmp`;await S.promises.writeFile(o,JSON.stringify(de(n))),await S.promises.rename(o,r)}async delete(t){try{await S.promises.unlink(this.pathFor(t))}catch(n){if(n?.code!=="ENOENT")throw n}}};var ye=require("@solana/web3.js"),fe=require("@noble/hashes/utils");var ge=F(require("tweetnacl"),1);var he=require("@noble/hashes/sha256");var W=6;function A(e,t=W){if(!/^\d+(\.\d+)?$/.test(e))throw new Error(`amount must be a non-negative decimal string, got "${e}"`);let[n,r=""]=e.split(".");if(r.length>t)throw new Error(`amount "${e}" has more than ${t} decimals`);let o=r.padEnd(t,"0"),l=`${n}${o}`.replace(/^0+(?=\d)/,"");return l===""?"0":l}function x(e,t=W){if(!/^\d+$/.test(e))throw new Error(`atomic must be a non-negative integer string, got "${e}"`);let n=e.padStart(t+1,"0"),r=n.slice(0,-t).replace(/^0+(?=\d)/,"")||"0",o=n.slice(-t).replace(/0+$/,"");return o?`${r}.${o}`:r}var E="x-tab-voucher",M=class{map=new Map;get(t){return this.map.get(t)}set(t,n){this.map.set(t,n)}update(t,n){let r=this.map.get(t);r&&(r.lastCumulativeAtomic=n)}delete(t){this.map.delete(t)}},q=class{constructor(t,n,r,o){this.chargeImpl=o;this.channelId=t,this.network=n,this.cumulativeAtomic=r}channelId;network;sessionPublicKey=null;cumulativeAtomic;cumulative(){return x(this.cumulativeAtomic.toString())}bumpCumulative(t){this.cumulativeAtomic=t}setSessionPublicKey(t){this.sessionPublicKey=t}async charge(t){return this.chargeImpl(t)}};function we(e){if(typeof e!="string"||e.length===0)throw new m("signature_invalid",`missing ${E} header`);let t;try{t=Buffer.from(e,"base64").toString("utf8")}catch{throw new m("signature_invalid","malformed base64")}let n;try{n=JSON.parse(t)}catch{throw new m("signature_invalid","malformed JSON")}if(!n||typeof n!="object"||!n.payload||!n.sessionPublicKey)throw new m("signature_invalid","missing required fields");return{payload:n.payload,sessionPublicKey:$(n.sessionPublicKey),sessionRegistration:$(n.sessionRegistration),sessionSignature:$(n.sessionSignature)}}function $(e){if(typeof e!="string"||e.length%2!==0)throw new m("signature_invalid",`bad hex: ${typeof e}`);let t=new Uint8Array(e.length/2);for(let n=0;n<t.length;n++)t[n]=parseInt(e.substr(n*2,2),16);return t}function be(e){if(!/^[0-9a-f]{64}$/i.test(e))throw new m("signature_invalid",`channelId must be 64-char hex, got "${e}"`);return $(e)}function Y(e){let t=e.store??new v,n=new M,r=typeof e.sellerPubkey=="string"?new X.PublicKey(e.sellerPubkey):e.sellerPubkey,o=e.maxPerVoucherAtomic?BigInt(e.maxPerVoucherAtomic):BigInt(A(e.perUnit))*100n;return async(l,p,f)=>{try{let i=we(l.headers[E]),c=i.payload.channelId,g=be(c),s=n.get(c);if(!s){let R=I(i.sessionRegistration);await V(e.connection,R),s={registration:R,lastCumulativeAtomic:"0"},n.set(c,s)}k(i,g),C({registration:s.registration,voucher:i,expectedCounterparty:r,previousCumulativeAtomic:s.lastCumulativeAtomic});let a=BigInt(i.payload.cumulativeAmount),ee=BigInt(s.lastCumulativeAtomic),D=a-ee;if(D>o)throw new u("cumulative_exceeds_cap",`single voucher increment ${D} exceeds maxPerVoucherAtomic ${o}`);await t.set(c,i),n.update(c,i.payload.cumulativeAmount);let z=new q(c,e.network,a,async R=>{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.")});z.setSessionPublicKey(i.sessionPublicKey),l.tab=z,f()}catch(i){if(i instanceof m||i instanceof d||i instanceof y||i instanceof h||i instanceof u){p.status(402).json({error:"invalid_voucher",reason:i.reason??"unknown",detail:i.message});return}f(i)}}}function Z(e){if(!e.tab)throw new Error("req.tab is missing \u2014 did tabMiddleware run on this route?");return e.tab}function Q(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 n=t.tab,r=BigInt(A(n.cumulative())),o=t.perUnit?BigInt(A(t.perUnit)):null,l=0n,p=!1;function f(g=1){if(p)return Promise.reject(new Error("meter ended"));if(o===null)return Promise.reject(new Error("charge() needs options.perUnit"));let s=o*BigInt(g),a=l+s;return a>r?Promise.reject(new u("cumulative_exceeds_cap",`chunk would push request total to ${x(a.toString())} beyond voucher-authorized budget ${x(r.toString())}`)):(l=a,Promise.resolve())}function i(g){if(p)throw new Error("meter ended");let a=(typeof g=="string"?g:Buffer.from(g).toString("utf8")).replace(/\n/g,"\\n");e.write(`data: ${a}
1
+ "use strict";var te=Object.create;var P=Object.defineProperty;var ne=Object.getOwnPropertyDescriptor;var re=Object.getOwnPropertyNames;var oe=Object.getPrototypeOf,ie=Object.prototype.hasOwnProperty;var se=(e,t)=>{for(var n in t)P(e,n,{get:t[n],enumerable:!0})},L=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of re(t))!ie.call(e,o)&&o!==n&&P(e,o,{get:()=>t[o],enumerable:!(r=ne(t,o))||r.enumerable});return e};var F=(e,t,n)=>(n=e!=null?te(oe(e)):{},L(t||!e||!e.__esModule?P(n,"default",{value:e,enumerable:!0}):n,e)),ae=e=>L(P({},"__esModule",{value:!0}),e);var Se={};se(Se,{FileVoucherStore:()=>U,InMemoryVoucherStore:()=>A,InvalidRegistrationError:()=>d,InvalidVoucherError:()=>m,InvalidVoucherSignatureError:()=>h,OnChainVerificationError:()=>y,ScopeViolationError:()=>c,TAB_VOUCHER_HEADER:()=>$,enforceScope:()=>C,openSse:()=>Q,parseRegistration:()=>I,readVaultState:()=>N,requireTab:()=>Z,tabMiddleware:()=>Y,verifyRegistrationOnChain:()=>V,verifyVoucherSignature:()=>k});module.exports=ae(Se);var m=class extends Error{constructor(n,r){super(`Invalid voucher: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="InvalidVoucherError"}};var X=require("@solana/web3.js");var G=F(require("tweetnacl"),1),ce=require("@noble/hashes/sha256"),le=require("@noble/curves/p256"),T=require("@solana/web3.js");var w=require("@dexterai/vault/messages");var K=require("@dexterai/vault/instructions"),ue=require("@dexterai/vault/precompile"),b=require("@dexterai/vault/constants");var O="OTS_SESSION_REGISTER_V2",d=class extends Error{constructor(n,r){super(`Invalid registration: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="InvalidRegistrationError"}};function I(e){if(e.length!==188)throw new d("wrong_length",`expected 188, got ${e.length}`);let t=new TextDecoder().decode(e.slice(0,O.length));if(t!==O)throw new d("wrong_domain",`got "${t}"`);for(let a=O.length;a<32;a++)if(e[a]!==0)throw new d("wrong_domain",`non-NUL padding at byte ${a}`);let n=new DataView(e.buffer,e.byteOffset,e.byteLength),r=new T.PublicKey(e.slice(32,64)),o=new T.PublicKey(e.slice(64,96)),l=e.slice(96,128),p=n.getBigUint64(128,!0),f=n.getBigInt64(136,!0),i=new T.PublicKey(e.slice(144,176)),u=n.getUint32(176,!0),g=n.getBigUint64(180,!0);if(!r.equals(b.DEXTER_VAULT_PROGRAM_ID))throw new d("wrong_program",`${r.toBase58()} is not ${b.DEXTER_VAULT_PROGRAM_ID.toBase58()}`);if(p===0n)throw new d("cap_zero");let s=BigInt(Math.floor(Date.now()/1e3));if(f<=s)throw new d("expiry_in_past",`expires_at=${f}, now=${s}`);return{programId:r,vaultPda:o,sessionPubkey:new Uint8Array(l),maxAmount:p,expiresAt:f,allowedCounterparty:i,nonce:u,maxRevolvingCapacity:g}}var j=10,y=class extends Error{constructor(n,r){super(`On-chain verification failed: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="OnChainVerificationError"}};async function N(e,t){let n=await e.getAccountInfo(t,"finalized");if(!n)throw new y("vault_not_found",t.toBase58());if(!n.owner.equals(b.DEXTER_VAULT_PROGRAM_ID))throw new y("wrong_program",`owner ${n.owner.toBase58()} is not the vault program`);let r=n.data,o=new Uint8Array(r.slice(j,j+33)),u=84+(r[83]===1?48:0)+32+32;if(r[u]!==1)return{passkeyPubkey:o,activeSessionPubkey:null};let s=u+1,a=new Uint8Array(r.slice(s,s+32));return{passkeyPubkey:o,activeSessionPubkey:a}}async function V(e,t){let n=await N(e,t.vaultPda);if(n.activeSessionPubkey===null)throw new y("session_not_active","vault has no active_session \u2014 was it revoked?");if(!me(n.activeSessionPubkey,t.sessionPubkey))throw new y("session_pubkey_mismatch",`on-chain ${J(n.activeSessionPubkey)} != registration ${J(t.sessionPubkey)}`);return{passkeyPubkey:n.passkeyPubkey}}var h=class extends Error{constructor(t){super(`Invalid voucher signature${t?`: ${t}`:""}`),this.name="InvalidVoucherSignatureError"}};function k(e,t){if(t.length!==32)throw new h(`channelIdBytes must be 32 bytes, got ${t.length}`);if(e.sessionPublicKey.length!==32)throw new h(`sessionPublicKey must be 32 bytes, got ${e.sessionPublicKey.length}`);if(e.sessionSignature.length!==64)throw new h(`sessionSignature must be 64 bytes, got ${e.sessionSignature.length}`);let n=(0,w.voucherPayloadMessage)({channelId:t,cumulativeAmount:BigInt(e.payload.cumulativeAmount),sequenceNumber:e.payload.sequenceNumber});if(!G.default.sign.detached.verify(n,e.sessionSignature,e.sessionPublicKey))throw new h("ed25519 verify rejected")}var c=class extends Error{constructor(n,r){super(`Scope violation: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="ScopeViolationError"}};function C(e){let t=BigInt(e.voucher.payload.cumulativeAmount);if(t>e.registration.maxAmount)throw new c("cumulative_exceeds_cap",`${t} > ${e.registration.maxAmount}`);let n=BigInt(Math.floor(Date.now()/1e3));if(n>=e.registration.expiresAt)throw new c("session_expired",`now=${n} >= expiresAt=${e.registration.expiresAt}`);if(!e.registration.allowedCounterparty.equals(e.expectedCounterparty))throw new c("wrong_counterparty",`${e.registration.allowedCounterparty.toBase58()} != ${e.expectedCounterparty.toBase58()}`);if(e.previousCumulativeAtomic!==void 0){let r=BigInt(e.previousCumulativeAtomic);if(t<=r)throw new c("non_monotonic",`cumulative=${t} not > previous=${r}`)}}function me(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}function J(e){let t="";for(let n of e)t+=n.toString(16).padStart(2,"0");return t}var S=require("fs"),_=require("path");function de(e){return{payload:e.payload,sessionPublicKey:H(e.sessionPublicKey),sessionRegistration:H(e.sessionRegistration),sessionSignature:H(e.sessionSignature)}}function pe(e){return{payload:e.payload,sessionPublicKey:B(e.sessionPublicKey),sessionRegistration:B(e.sessionRegistration),sessionSignature:B(e.sessionSignature)}}function H(e){let t="";for(let n of e)t+=n.toString(16).padStart(2,"0");return t}function B(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 n=0;n<t.length;n++)t[n]=parseInt(e.substr(n*2,2),16);return t}var A=class{map=new Map;async get(t){return this.map.get(t)??null}async set(t,n){this.map.set(t,n)}async delete(t){this.map.delete(t)}},U=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,_.join)(this.dir,`${t}.json`)}async get(t){try{let n=await S.promises.readFile(this.pathFor(t),"utf8");return pe(JSON.parse(n))}catch(n){if(n?.code==="ENOENT")return null;throw n}}async set(t,n){let r=this.pathFor(t);await S.promises.mkdir((0,_.dirname)(r),{recursive:!0});let o=`${r}.tmp`;await S.promises.writeFile(o,JSON.stringify(de(n))),await S.promises.rename(o,r)}async delete(t){try{await S.promises.unlink(this.pathFor(t))}catch(n){if(n?.code!=="ENOENT")throw n}}};var ye=require("@solana/web3.js"),fe=require("@noble/hashes/utils");var ge=F(require("tweetnacl"),1);var he=require("@noble/hashes/sha256");var W=6;function v(e,t=W){if(!/^\d+(\.\d+)?$/.test(e))throw new Error(`amount must be a non-negative decimal string, got "${e}"`);let[n,r=""]=e.split(".");if(r.length>t)throw new Error(`amount "${e}" has more than ${t} decimals`);let o=r.padEnd(t,"0"),l=`${n}${o}`.replace(/^0+(?=\d)/,"");return l===""?"0":l}function x(e,t=W){if(!/^\d+$/.test(e))throw new Error(`atomic must be a non-negative integer string, got "${e}"`);let n=e.padStart(t+1,"0"),r=n.slice(0,-t).replace(/^0+(?=\d)/,"")||"0",o=n.slice(-t).replace(/0+$/,"");return o?`${r}.${o}`:r}var $="x-tab-voucher",M=class{map=new Map;get(t){return this.map.get(t)}set(t,n){this.map.set(t,n)}update(t,n){let r=this.map.get(t);r&&(r.lastCumulativeAtomic=n)}delete(t){this.map.delete(t)}},q=class{constructor(t,n,r,o){this.chargeImpl=o;this.channelId=t,this.network=n,this.cumulativeAtomic=r}channelId;network;sessionPublicKey=null;cumulativeAtomic;cumulative(){return x(this.cumulativeAtomic.toString())}bumpCumulative(t){this.cumulativeAtomic=t}setSessionPublicKey(t){this.sessionPublicKey=t}async charge(t){return this.chargeImpl(t)}};function we(e){if(typeof e!="string"||e.length===0)throw new m("signature_invalid",`missing ${$} header`);let t;try{t=Buffer.from(e,"base64").toString("utf8")}catch{throw new m("signature_invalid","malformed base64")}let n;try{n=JSON.parse(t)}catch{throw new m("signature_invalid","malformed JSON")}if(!n||typeof n!="object"||!n.payload||!n.sessionPublicKey)throw new m("signature_invalid","missing required fields");return{payload:n.payload,sessionPublicKey:R(n.sessionPublicKey),sessionRegistration:R(n.sessionRegistration),sessionSignature:R(n.sessionSignature)}}function R(e){if(typeof e!="string"||e.length%2!==0)throw new m("signature_invalid",`bad hex: ${typeof e}`);let t=new Uint8Array(e.length/2);for(let n=0;n<t.length;n++)t[n]=parseInt(e.substr(n*2,2),16);return t}function be(e){if(!/^[0-9a-f]{64}$/i.test(e))throw new m("signature_invalid",`channelId must be 64-char hex, got "${e}"`);return R(e)}function Y(e){let t=e.store??new A,n=new M,r=typeof e.sellerPubkey=="string"?new X.PublicKey(e.sellerPubkey):e.sellerPubkey,o=e.maxPerVoucherAtomic?BigInt(e.maxPerVoucherAtomic):BigInt(v(e.perUnit))*100n;return async(l,p,f)=>{try{let i=we(l.headers[$]),u=i.payload.channelId,g=be(u),s=n.get(u);if(!s){let E=I(i.sessionRegistration);await V(e.connection,E),s={registration:E,lastCumulativeAtomic:"0"},n.set(u,s)}k(i,g),C({registration:s.registration,voucher:i,expectedCounterparty:r,previousCumulativeAtomic:s.lastCumulativeAtomic});let a=BigInt(i.payload.cumulativeAmount),ee=BigInt(s.lastCumulativeAtomic),D=a-ee;if(D>o)throw new c("cumulative_exceeds_cap",`single voucher increment ${D} exceeds maxPerVoucherAtomic ${o}`);await t.set(u,i),n.update(u,i.payload.cumulativeAmount);let z=new q(u,e.network,a,async E=>{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.")});z.setSessionPublicKey(i.sessionPublicKey),l.tab=z,f()}catch(i){if(i instanceof m||i instanceof d||i instanceof y||i instanceof h||i instanceof c){p.status(402).json({error:"invalid_voucher",reason:i.reason??"unknown",detail:i.message});return}f(i)}}}function Z(e){if(!e.tab)throw new Error("req.tab is missing \u2014 did tabMiddleware run on this route?");return e.tab}function Q(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 n=t.tab,r=BigInt(v(n.cumulative())),o=t.perUnit?BigInt(v(t.perUnit)):null,l=0n,p=!1;function f(g=1){if(p)return Promise.reject(new Error("meter ended"));if(o===null)return Promise.reject(new Error("charge() needs options.perUnit"));let s=o*BigInt(g),a=l+s;return a>r?Promise.reject(new c("cumulative_exceeds_cap",`chunk would push request total to ${x(a.toString())} beyond voucher-authorized budget ${x(r.toString())}`)):(l=a,Promise.resolve())}function i(g){if(p)throw new Error("meter ended");let a=(typeof g=="string"?g:Buffer.from(g).toString("utf8")).replace(/\n/g,"\\n");e.write(`data: ${a}
2
2
 
3
- `)}function c(){p||(p=!0,e.write(`event: end
3
+ `)}function u(){p||(p=!0,e.write(`event: end
4
4
  data: {"chargedAtomic":"${l}"}
5
5
 
6
- `),e.end())}return{charge:f,send:i,end:c}}0&&(module.exports={FileVoucherStore,InMemoryVoucherStore,InvalidRegistrationError,InvalidVoucherError,InvalidVoucherSignatureError,OnChainVerificationError,ScopeViolationError,TAB_VOUCHER_HEADER,enforceScope,openSse,parseRegistration,readVaultState,requireTab,tabMiddleware,verifyRegistrationOnChain,verifyVoucherSignature});
6
+ `),e.end())}return{charge:f,send:i,end:u}}0&&(module.exports={FileVoucherStore,InMemoryVoucherStore,InvalidRegistrationError,InvalidVoucherError,InvalidVoucherSignatureError,OnChainVerificationError,ScopeViolationError,TAB_VOUCHER_HEADER,enforceScope,openSse,parseRegistration,readVaultState,requireTab,tabMiddleware,verifyRegistrationOnChain,verifyVoucherSignature});
@@ -1,6 +1,6 @@
1
- var m=class extends Error{constructor(n,r){super(`Invalid voucher: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="InvalidVoucherError"}};import{PublicKey as Y}from"@solana/web3.js";import F from"tweetnacl";import{sha256 as ve}from"@noble/hashes/sha256";import{p256 as xe}from"@noble/curves/p256";import{PublicKey as I}from"@solana/web3.js";import{sessionRegisterMessage as se,sessionRevokeMessage as ae,voucherPayloadMessage as T,buildVoucherMessage as ce}from"@dexterai/vault/messages";import{buildRegisterSessionKeyInstruction as me,buildRevokeSessionKeyInstruction as de,deriveSwigWalletAddress as pe}from"@dexterai/vault/instructions";import{buildSecp256r1VerifyInstruction as he}from"@dexterai/vault/precompile";import{DEXTER_VAULT_PROGRAM_ID as A,SECP256R1_PROGRAM_ID as fe,INSTRUCTIONS_SYSVAR_ID as we}from"@dexterai/vault/constants";var V="OTS_SESSION_REGISTER_V2",d=class extends Error{constructor(n,r){super(`Invalid registration: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="InvalidRegistrationError"}};function k(e){if(e.length!==188)throw new d("wrong_length",`expected 188, got ${e.length}`);let t=new TextDecoder().decode(e.slice(0,V.length));if(t!==V)throw new d("wrong_domain",`got "${t}"`);for(let a=V.length;a<32;a++)if(e[a]!==0)throw new d("wrong_domain",`non-NUL padding at byte ${a}`);let n=new DataView(e.buffer,e.byteOffset,e.byteLength),r=new I(e.slice(32,64)),i=new I(e.slice(64,96)),u=e.slice(96,128),p=n.getBigUint64(128,!0),h=n.getBigInt64(136,!0),o=new I(e.slice(144,176)),c=n.getUint32(176,!0),g=n.getBigUint64(180,!0);if(!r.equals(A))throw new d("wrong_program",`${r.toBase58()} is not ${A.toBase58()}`);if(p===0n)throw new d("cap_zero");let s=BigInt(Math.floor(Date.now()/1e3));if(h<=s)throw new d("expiry_in_past",`expires_at=${h}, now=${s}`);return{programId:r,vaultPda:i,sessionPubkey:new Uint8Array(u),maxAmount:p,expiresAt:h,allowedCounterparty:o,nonce:c,maxRevolvingCapacity:g}}var M=10,f=class extends Error{constructor(n,r){super(`On-chain verification failed: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="OnChainVerificationError"}};async function D(e,t){let n=await e.getAccountInfo(t,"finalized");if(!n)throw new f("vault_not_found",t.toBase58());if(!n.owner.equals(A))throw new f("wrong_program",`owner ${n.owner.toBase58()} is not the vault program`);let r=n.data,i=new Uint8Array(r.slice(M,M+33)),c=84+(r[83]===1?48:0)+32+32;if(r[c]!==1)return{passkeyPubkey:i,activeSessionPubkey:null};let s=c+1,a=new Uint8Array(r.slice(s,s+32));return{passkeyPubkey:i,activeSessionPubkey:a}}async function C(e,t){let n=await D(e,t.vaultPda);if(n.activeSessionPubkey===null)throw new f("session_not_active","vault has no active_session \u2014 was it revoked?");if(!j(n.activeSessionPubkey,t.sessionPubkey))throw new f("session_pubkey_mismatch",`on-chain ${q(n.activeSessionPubkey)} != registration ${q(t.sessionPubkey)}`);return{passkeyPubkey:n.passkeyPubkey}}var y=class extends Error{constructor(t){super(`Invalid voucher signature${t?`: ${t}`:""}`),this.name="InvalidVoucherSignatureError"}};function U(e,t){if(t.length!==32)throw new y(`channelIdBytes must be 32 bytes, got ${t.length}`);if(e.sessionPublicKey.length!==32)throw new y(`sessionPublicKey must be 32 bytes, got ${e.sessionPublicKey.length}`);if(e.sessionSignature.length!==64)throw new y(`sessionSignature must be 64 bytes, got ${e.sessionSignature.length}`);let n=T({channelId:t,cumulativeAmount:BigInt(e.payload.cumulativeAmount),sequenceNumber:e.payload.sequenceNumber});if(!F.sign.detached.verify(n,e.sessionSignature,e.sessionPublicKey))throw new y("ed25519 verify rejected")}var l=class extends Error{constructor(n,r){super(`Scope violation: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="ScopeViolationError"}};function _(e){let t=BigInt(e.voucher.payload.cumulativeAmount);if(t>e.registration.maxAmount)throw new l("cumulative_exceeds_cap",`${t} > ${e.registration.maxAmount}`);let n=BigInt(Math.floor(Date.now()/1e3));if(n>=e.registration.expiresAt)throw new l("session_expired",`now=${n} >= expiresAt=${e.registration.expiresAt}`);if(!e.registration.allowedCounterparty.equals(e.expectedCounterparty))throw new l("wrong_counterparty",`${e.registration.allowedCounterparty.toBase58()} != ${e.expectedCounterparty.toBase58()}`);if(e.previousCumulativeAtomic!==void 0){let r=BigInt(e.previousCumulativeAtomic);if(t<=r)throw new l("non_monotonic",`cumulative=${t} not > previous=${r}`)}}function j(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}function q(e){let t="";for(let n of e)t+=n.toString(16).padStart(2,"0");return t}import{promises as w}from"fs";import{join as J,dirname as G}from"path";function W(e){return{payload:e.payload,sessionPublicKey:$(e.sessionPublicKey),sessionRegistration:$(e.sessionRegistration),sessionSignature:$(e.sessionSignature)}}function X(e){return{payload:e.payload,sessionPublicKey:E(e.sessionPublicKey),sessionRegistration:E(e.sessionRegistration),sessionSignature:E(e.sessionSignature)}}function $(e){let t="";for(let n of e)t+=n.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 n=0;n<t.length;n++)t[n]=parseInt(e.substr(n*2,2),16);return t}var b=class{map=new Map;async get(t){return this.map.get(t)??null}async set(t,n){this.map.set(t,n)}async delete(t){this.map.delete(t)}},R=class{constructor(t){this.dir=t}pathFor(t){if(!/^[a-z0-9_-]+$/i.test(t))throw new Error(`unsafe channelId for filesystem: ${t}`);return J(this.dir,`${t}.json`)}async get(t){try{let n=await w.readFile(this.pathFor(t),"utf8");return X(JSON.parse(n))}catch(n){if(n?.code==="ENOENT")return null;throw n}}async set(t,n){let r=this.pathFor(t);await w.mkdir(G(r),{recursive:!0});let i=`${r}.tmp`;await w.writeFile(i,JSON.stringify(W(n))),await w.rename(i,r)}async delete(t){try{await w.unlink(this.pathFor(t))}catch(n){if(n?.code!=="ENOENT")throw n}}};import{PublicKey as Le}from"@solana/web3.js";import{bytesToHex as je}from"@noble/hashes/utils";import Re from"tweetnacl";import{sha256 as Ne}from"@noble/hashes/sha256";var z=6;function S(e,t=z){if(!/^\d+(\.\d+)?$/.test(e))throw new Error(`amount must be a non-negative decimal string, got "${e}"`);let[n,r=""]=e.split(".");if(r.length>t)throw new Error(`amount "${e}" has more than ${t} decimals`);let i=r.padEnd(t,"0"),u=`${n}${i}`.replace(/^0+(?=\d)/,"");return u===""?"0":u}function v(e,t=z){if(!/^\d+$/.test(e))throw new Error(`atomic must be a non-negative integer string, got "${e}"`);let n=e.padStart(t+1,"0"),r=n.slice(0,-t).replace(/^0+(?=\d)/,"")||"0",i=n.slice(-t).replace(/0+$/,"");return i?`${r}.${i}`:r}var N="x-tab-voucher",K=class{map=new Map;get(t){return this.map.get(t)}set(t,n){this.map.set(t,n)}update(t,n){let r=this.map.get(t);r&&(r.lastCumulativeAtomic=n)}delete(t){this.map.delete(t)}},O=class{constructor(t,n,r,i){this.chargeImpl=i;this.channelId=t,this.network=n,this.cumulativeAtomic=r}channelId;network;sessionPublicKey=null;cumulativeAtomic;cumulative(){return v(this.cumulativeAtomic.toString())}bumpCumulative(t){this.cumulativeAtomic=t}setSessionPublicKey(t){this.sessionPublicKey=t}async charge(t){return this.chargeImpl(t)}};function Z(e){if(typeof e!="string"||e.length===0)throw new m("signature_invalid",`missing ${N} header`);let t;try{t=Buffer.from(e,"base64").toString("utf8")}catch{throw new m("signature_invalid","malformed base64")}let n;try{n=JSON.parse(t)}catch{throw new m("signature_invalid","malformed JSON")}if(!n||typeof n!="object"||!n.payload||!n.sessionPublicKey)throw new m("signature_invalid","missing required fields");return{payload:n.payload,sessionPublicKey:x(n.sessionPublicKey),sessionRegistration:x(n.sessionRegistration),sessionSignature:x(n.sessionSignature)}}function x(e){if(typeof e!="string"||e.length%2!==0)throw new m("signature_invalid",`bad hex: ${typeof e}`);let t=new Uint8Array(e.length/2);for(let n=0;n<t.length;n++)t[n]=parseInt(e.substr(n*2,2),16);return t}function Q(e){if(!/^[0-9a-f]{64}$/i.test(e))throw new m("signature_invalid",`channelId must be 64-char hex, got "${e}"`);return x(e)}function ee(e){let t=e.store??new b,n=new K,r=typeof e.sellerPubkey=="string"?new Y(e.sellerPubkey):e.sellerPubkey,i=e.maxPerVoucherAtomic?BigInt(e.maxPerVoucherAtomic):BigInt(S(e.perUnit))*100n;return async(u,p,h)=>{try{let o=Z(u.headers[N]),c=o.payload.channelId,g=Q(c),s=n.get(c);if(!s){let P=k(o.sessionRegistration);await C(e.connection,P),s={registration:P,lastCumulativeAtomic:"0"},n.set(c,s)}U(o,g),_({registration:s.registration,voucher:o,expectedCounterparty:r,previousCumulativeAtomic:s.lastCumulativeAtomic});let a=BigInt(o.payload.cumulativeAmount),L=BigInt(s.lastCumulativeAtomic),H=a-L;if(H>i)throw new l("cumulative_exceeds_cap",`single voucher increment ${H} exceeds maxPerVoucherAtomic ${i}`);await t.set(c,o),n.update(c,o.payload.cumulativeAmount);let B=new O(c,e.network,a,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.")});B.setSessionPublicKey(o.sessionPublicKey),u.tab=B,h()}catch(o){if(o instanceof m||o instanceof d||o instanceof f||o instanceof y||o instanceof l){p.status(402).json({error:"invalid_voucher",reason:o.reason??"unknown",detail:o.message});return}h(o)}}}function te(e){if(!e.tab)throw new Error("req.tab is missing \u2014 did tabMiddleware run on this route?");return e.tab}function ne(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 n=t.tab,r=BigInt(S(n.cumulative())),i=t.perUnit?BigInt(S(t.perUnit)):null,u=0n,p=!1;function h(g=1){if(p)return Promise.reject(new Error("meter ended"));if(i===null)return Promise.reject(new Error("charge() needs options.perUnit"));let s=i*BigInt(g),a=u+s;return a>r?Promise.reject(new l("cumulative_exceeds_cap",`chunk would push request total to ${v(a.toString())} beyond voucher-authorized budget ${v(r.toString())}`)):(u=a,Promise.resolve())}function o(g){if(p)throw new Error("meter ended");let a=(typeof g=="string"?g:Buffer.from(g).toString("utf8")).replace(/\n/g,"\\n");e.write(`data: ${a}
1
+ var m=class extends Error{constructor(n,r){super(`Invalid voucher: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="InvalidVoucherError"}};import{PublicKey as Y}from"@solana/web3.js";import F from"tweetnacl";import{sha256 as Ae}from"@noble/hashes/sha256";import{p256 as xe}from"@noble/curves/p256";import{PublicKey as I}from"@solana/web3.js";import{sessionRegisterMessage as se,sessionRevokeMessage as ae,voucherPayloadMessage as T,buildVoucherMessage as ue}from"@dexterai/vault/messages";import{buildRegisterSessionKeyInstruction as me,buildRevokeSessionKeyInstruction as de,deriveSwigWalletAddress as pe}from"@dexterai/vault/instructions";import{buildSecp256r1VerifyInstruction as he}from"@dexterai/vault/precompile";import{DEXTER_VAULT_PROGRAM_ID as v,SECP256R1_PROGRAM_ID as fe,INSTRUCTIONS_SYSVAR_ID as we}from"@dexterai/vault/constants";var V="OTS_SESSION_REGISTER_V2",d=class extends Error{constructor(n,r){super(`Invalid registration: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="InvalidRegistrationError"}};function k(e){if(e.length!==188)throw new d("wrong_length",`expected 188, got ${e.length}`);let t=new TextDecoder().decode(e.slice(0,V.length));if(t!==V)throw new d("wrong_domain",`got "${t}"`);for(let a=V.length;a<32;a++)if(e[a]!==0)throw new d("wrong_domain",`non-NUL padding at byte ${a}`);let n=new DataView(e.buffer,e.byteOffset,e.byteLength),r=new I(e.slice(32,64)),i=new I(e.slice(64,96)),c=e.slice(96,128),p=n.getBigUint64(128,!0),h=n.getBigInt64(136,!0),o=new I(e.slice(144,176)),u=n.getUint32(176,!0),g=n.getBigUint64(180,!0);if(!r.equals(v))throw new d("wrong_program",`${r.toBase58()} is not ${v.toBase58()}`);if(p===0n)throw new d("cap_zero");let s=BigInt(Math.floor(Date.now()/1e3));if(h<=s)throw new d("expiry_in_past",`expires_at=${h}, now=${s}`);return{programId:r,vaultPda:i,sessionPubkey:new Uint8Array(c),maxAmount:p,expiresAt:h,allowedCounterparty:o,nonce:u,maxRevolvingCapacity:g}}var M=10,f=class extends Error{constructor(n,r){super(`On-chain verification failed: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="OnChainVerificationError"}};async function D(e,t){let n=await e.getAccountInfo(t,"finalized");if(!n)throw new f("vault_not_found",t.toBase58());if(!n.owner.equals(v))throw new f("wrong_program",`owner ${n.owner.toBase58()} is not the vault program`);let r=n.data,i=new Uint8Array(r.slice(M,M+33)),u=84+(r[83]===1?48:0)+32+32;if(r[u]!==1)return{passkeyPubkey:i,activeSessionPubkey:null};let s=u+1,a=new Uint8Array(r.slice(s,s+32));return{passkeyPubkey:i,activeSessionPubkey:a}}async function C(e,t){let n=await D(e,t.vaultPda);if(n.activeSessionPubkey===null)throw new f("session_not_active","vault has no active_session \u2014 was it revoked?");if(!j(n.activeSessionPubkey,t.sessionPubkey))throw new f("session_pubkey_mismatch",`on-chain ${q(n.activeSessionPubkey)} != registration ${q(t.sessionPubkey)}`);return{passkeyPubkey:n.passkeyPubkey}}var y=class extends Error{constructor(t){super(`Invalid voucher signature${t?`: ${t}`:""}`),this.name="InvalidVoucherSignatureError"}};function U(e,t){if(t.length!==32)throw new y(`channelIdBytes must be 32 bytes, got ${t.length}`);if(e.sessionPublicKey.length!==32)throw new y(`sessionPublicKey must be 32 bytes, got ${e.sessionPublicKey.length}`);if(e.sessionSignature.length!==64)throw new y(`sessionSignature must be 64 bytes, got ${e.sessionSignature.length}`);let n=T({channelId:t,cumulativeAmount:BigInt(e.payload.cumulativeAmount),sequenceNumber:e.payload.sequenceNumber});if(!F.sign.detached.verify(n,e.sessionSignature,e.sessionPublicKey))throw new y("ed25519 verify rejected")}var l=class extends Error{constructor(n,r){super(`Scope violation: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="ScopeViolationError"}};function _(e){let t=BigInt(e.voucher.payload.cumulativeAmount);if(t>e.registration.maxAmount)throw new l("cumulative_exceeds_cap",`${t} > ${e.registration.maxAmount}`);let n=BigInt(Math.floor(Date.now()/1e3));if(n>=e.registration.expiresAt)throw new l("session_expired",`now=${n} >= expiresAt=${e.registration.expiresAt}`);if(!e.registration.allowedCounterparty.equals(e.expectedCounterparty))throw new l("wrong_counterparty",`${e.registration.allowedCounterparty.toBase58()} != ${e.expectedCounterparty.toBase58()}`);if(e.previousCumulativeAtomic!==void 0){let r=BigInt(e.previousCumulativeAtomic);if(t<=r)throw new l("non_monotonic",`cumulative=${t} not > previous=${r}`)}}function j(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}function q(e){let t="";for(let n of e)t+=n.toString(16).padStart(2,"0");return t}import{promises as w}from"fs";import{join as J,dirname as G}from"path";function W(e){return{payload:e.payload,sessionPublicKey:R(e.sessionPublicKey),sessionRegistration:R(e.sessionRegistration),sessionSignature:R(e.sessionSignature)}}function X(e){return{payload:e.payload,sessionPublicKey:$(e.sessionPublicKey),sessionRegistration:$(e.sessionRegistration),sessionSignature:$(e.sessionSignature)}}function R(e){let t="";for(let n of e)t+=n.toString(16).padStart(2,"0");return t}function $(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 n=0;n<t.length;n++)t[n]=parseInt(e.substr(n*2,2),16);return t}var b=class{map=new Map;async get(t){return this.map.get(t)??null}async set(t,n){this.map.set(t,n)}async delete(t){this.map.delete(t)}},E=class{constructor(t){this.dir=t}pathFor(t){if(!/^[a-z0-9_-]+$/i.test(t))throw new Error(`unsafe channelId for filesystem: ${t}`);return J(this.dir,`${t}.json`)}async get(t){try{let n=await w.readFile(this.pathFor(t),"utf8");return X(JSON.parse(n))}catch(n){if(n?.code==="ENOENT")return null;throw n}}async set(t,n){let r=this.pathFor(t);await w.mkdir(G(r),{recursive:!0});let i=`${r}.tmp`;await w.writeFile(i,JSON.stringify(W(n))),await w.rename(i,r)}async delete(t){try{await w.unlink(this.pathFor(t))}catch(n){if(n?.code!=="ENOENT")throw n}}};import{PublicKey as Le}from"@solana/web3.js";import{bytesToHex as je}from"@noble/hashes/utils";import Ee from"tweetnacl";import{sha256 as Ne}from"@noble/hashes/sha256";var z=6;function S(e,t=z){if(!/^\d+(\.\d+)?$/.test(e))throw new Error(`amount must be a non-negative decimal string, got "${e}"`);let[n,r=""]=e.split(".");if(r.length>t)throw new Error(`amount "${e}" has more than ${t} decimals`);let i=r.padEnd(t,"0"),c=`${n}${i}`.replace(/^0+(?=\d)/,"");return c===""?"0":c}function A(e,t=z){if(!/^\d+$/.test(e))throw new Error(`atomic must be a non-negative integer string, got "${e}"`);let n=e.padStart(t+1,"0"),r=n.slice(0,-t).replace(/^0+(?=\d)/,"")||"0",i=n.slice(-t).replace(/0+$/,"");return i?`${r}.${i}`:r}var N="x-tab-voucher",K=class{map=new Map;get(t){return this.map.get(t)}set(t,n){this.map.set(t,n)}update(t,n){let r=this.map.get(t);r&&(r.lastCumulativeAtomic=n)}delete(t){this.map.delete(t)}},O=class{constructor(t,n,r,i){this.chargeImpl=i;this.channelId=t,this.network=n,this.cumulativeAtomic=r}channelId;network;sessionPublicKey=null;cumulativeAtomic;cumulative(){return A(this.cumulativeAtomic.toString())}bumpCumulative(t){this.cumulativeAtomic=t}setSessionPublicKey(t){this.sessionPublicKey=t}async charge(t){return this.chargeImpl(t)}};function Z(e){if(typeof e!="string"||e.length===0)throw new m("signature_invalid",`missing ${N} header`);let t;try{t=Buffer.from(e,"base64").toString("utf8")}catch{throw new m("signature_invalid","malformed base64")}let n;try{n=JSON.parse(t)}catch{throw new m("signature_invalid","malformed JSON")}if(!n||typeof n!="object"||!n.payload||!n.sessionPublicKey)throw new m("signature_invalid","missing required fields");return{payload:n.payload,sessionPublicKey:x(n.sessionPublicKey),sessionRegistration:x(n.sessionRegistration),sessionSignature:x(n.sessionSignature)}}function x(e){if(typeof e!="string"||e.length%2!==0)throw new m("signature_invalid",`bad hex: ${typeof e}`);let t=new Uint8Array(e.length/2);for(let n=0;n<t.length;n++)t[n]=parseInt(e.substr(n*2,2),16);return t}function Q(e){if(!/^[0-9a-f]{64}$/i.test(e))throw new m("signature_invalid",`channelId must be 64-char hex, got "${e}"`);return x(e)}function ee(e){let t=e.store??new b,n=new K,r=typeof e.sellerPubkey=="string"?new Y(e.sellerPubkey):e.sellerPubkey,i=e.maxPerVoucherAtomic?BigInt(e.maxPerVoucherAtomic):BigInt(S(e.perUnit))*100n;return async(c,p,h)=>{try{let o=Z(c.headers[N]),u=o.payload.channelId,g=Q(u),s=n.get(u);if(!s){let P=k(o.sessionRegistration);await C(e.connection,P),s={registration:P,lastCumulativeAtomic:"0"},n.set(u,s)}U(o,g),_({registration:s.registration,voucher:o,expectedCounterparty:r,previousCumulativeAtomic:s.lastCumulativeAtomic});let a=BigInt(o.payload.cumulativeAmount),L=BigInt(s.lastCumulativeAtomic),H=a-L;if(H>i)throw new l("cumulative_exceeds_cap",`single voucher increment ${H} exceeds maxPerVoucherAtomic ${i}`);await t.set(u,o),n.update(u,o.payload.cumulativeAmount);let B=new O(u,e.network,a,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.")});B.setSessionPublicKey(o.sessionPublicKey),c.tab=B,h()}catch(o){if(o instanceof m||o instanceof d||o instanceof f||o instanceof y||o instanceof l){p.status(402).json({error:"invalid_voucher",reason:o.reason??"unknown",detail:o.message});return}h(o)}}}function te(e){if(!e.tab)throw new Error("req.tab is missing \u2014 did tabMiddleware run on this route?");return e.tab}function ne(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 n=t.tab,r=BigInt(S(n.cumulative())),i=t.perUnit?BigInt(S(t.perUnit)):null,c=0n,p=!1;function h(g=1){if(p)return Promise.reject(new Error("meter ended"));if(i===null)return Promise.reject(new Error("charge() needs options.perUnit"));let s=i*BigInt(g),a=c+s;return a>r?Promise.reject(new l("cumulative_exceeds_cap",`chunk would push request total to ${A(a.toString())} beyond voucher-authorized budget ${A(r.toString())}`)):(c=a,Promise.resolve())}function o(g){if(p)throw new Error("meter ended");let a=(typeof g=="string"?g:Buffer.from(g).toString("utf8")).replace(/\n/g,"\\n");e.write(`data: ${a}
2
2
 
3
- `)}function c(){p||(p=!0,e.write(`event: end
4
- data: {"chargedAtomic":"${u}"}
3
+ `)}function u(){p||(p=!0,e.write(`event: end
4
+ data: {"chargedAtomic":"${c}"}
5
5
 
6
- `),e.end())}return{charge:h,send:o,end:c}}export{R as FileVoucherStore,b as InMemoryVoucherStore,d as InvalidRegistrationError,m as InvalidVoucherError,y as InvalidVoucherSignatureError,f as OnChainVerificationError,l as ScopeViolationError,N as TAB_VOUCHER_HEADER,_ as enforceScope,ne as openSse,k as parseRegistration,D as readVaultState,te as requireTab,ee as tabMiddleware,C as verifyRegistrationOnChain,U as verifyVoucherSignature};
6
+ `),e.end())}return{charge:h,send:o,end:u}}export{E as FileVoucherStore,b as InMemoryVoucherStore,d as InvalidRegistrationError,m as InvalidVoucherError,y as InvalidVoucherSignatureError,f as OnChainVerificationError,l as ScopeViolationError,N as TAB_VOUCHER_HEADER,_ as enforceScope,ne as openSse,k as parseRegistration,D as readVaultState,te as requireTab,ee as tabMiddleware,C as verifyRegistrationOnChain,U as verifyVoucherSignature};
@@ -115,6 +115,13 @@ interface TabCloseResult {
115
115
  settledAmount: HumanAmount;
116
116
  /** Facilitator's on-chain settlement signature. */
117
117
  settleTx: string;
118
+ /** Atomic amount moved by the final settle, before any facilitator fee.
119
+ * Absent when the facilitator predates fee support. */
120
+ grossAmount?: string;
121
+ /** Atomic facilitator fee deducted from the final settle. */
122
+ feeAmount?: string;
123
+ /** Atomic amount the seller actually received from the final settle. */
124
+ netAmount?: string;
118
125
  }
119
126
  /**
120
127
  * Options for `openTab` — the buyer's session-opening call.
@@ -115,6 +115,13 @@ interface TabCloseResult {
115
115
  settledAmount: HumanAmount;
116
116
  /** Facilitator's on-chain settlement signature. */
117
117
  settleTx: string;
118
+ /** Atomic amount moved by the final settle, before any facilitator fee.
119
+ * Absent when the facilitator predates fee support. */
120
+ grossAmount?: string;
121
+ /** Atomic facilitator fee deducted from the final settle. */
122
+ feeAmount?: string;
123
+ /** Atomic amount the seller actually received from the final settle. */
124
+ netAmount?: string;
118
125
  }
119
126
  /**
120
127
  * Options for `openTab` — the buyer's session-opening call.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dexterai/x402",
3
- "version": "3.12.0",
3
+ "version": "3.13.0",
4
4
  "description": "Full-stack x402 SDK - add paid API monetization to any endpoint. Express middleware, React hooks, Access Pass, dynamic pricing. Solana, Base, Polygon, Arbitrum, Optimism, Avalanche, SKALE.",
5
5
  "author": "Dexter",
6
6
  "license": "MIT",
@@ -83,9 +83,9 @@
83
83
  "@noble/hashes": "^1.8.0",
84
84
  "@solana/spl-token": "^0.4.9",
85
85
  "@solana/web3.js": "^1.98.0",
86
- "@x402/core": "^2.12.0",
87
- "@x402/evm": "^2.12.0",
88
- "@x402/extensions": "^2.12.0",
86
+ "@x402/core": "2.12.0",
87
+ "@x402/evm": "2.12.0",
88
+ "@x402/extensions": "2.12.0",
89
89
  "tweetnacl": "^1.0.3"
90
90
  },
91
91
  "devDependencies": {