@dexterai/x402 5.2.0 → 5.3.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.
- package/dist/client/index.cjs +1 -1
- package/dist/client/index.js +1 -1
- package/dist/tab/index.cjs +4 -4
- package/dist/tab/index.js +4 -4
- package/dist/tab/seller/index.cjs +4 -4
- package/dist/tab/seller/index.d.cts +22 -2
- package/dist/tab/seller/index.d.ts +22 -2
- package/dist/tab/seller/index.js +4 -4
- package/package.json +1 -1
package/dist/tab/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
var me=class extends Error{constructor(n){super(`Network ${n} is not yet supported by @dexterai/x402/tab`);this.network=n;this.name="UnsupportedNetworkError"}},pe=class extends Error{constructor(n,r){super(`Session scope exceeded: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="SessionScopeExceededError"}},Q=class extends Error{constructor(n){super(`Tab ${n} is already closed`);this.channelId=n;this.name="TabClosedError"}};import{PublicKey as
|
|
1
|
+
var me=class extends Error{constructor(n){super(`Network ${n} is not yet supported by @dexterai/x402/tab`);this.network=n;this.name="UnsupportedNetworkError"}},pe=class extends Error{constructor(n,r){super(`Session scope exceeded: ${n}${r?` (${r})`:""}`);this.reason=n;this.name="SessionScopeExceededError"}},Q=class extends Error{constructor(n){super(`Tab ${n} is already closed`);this.channelId=n;this.name="TabClosedError"}};import{PublicKey as Rt}from"@solana/web3.js";import{bytesToHex as ee}from"@noble/hashes/utils";import jt from"tweetnacl";import{sessionRegisterMessage as mt,sessionRevokeMessage as Ht,voucherPayloadMessage as pt,buildVoucherMessage as Ft}from"@dexterai/vault/messages";import{sha256 as Jt}from"@noble/hashes/sha256";function vt(t,e,n){return{publicKey:t.publicKey,privateKey:t.privateKey,scope:e,registration:n}}function Pt(t,e,n){if(n.length!==32)throw new Error(`channelIdBytes must be 32 bytes, got ${n.length}`);let r=BigInt(e.cumulativeAmount),s=BigInt(t.scope.maxAmountAtomic);if(r>s)throw new Error(`voucher cumulative ${r} exceeds session cap ${s}`);let a=Math.floor(Date.now()/1e3);if(a>=t.scope.expiresAtUnix)throw new Error(`session expired at ${t.scope.expiresAtUnix}, now ${a}`);let o=pt({channelId:n,cumulativeAmount:r,sequenceNumber:e.sequenceNumber}),i=jt.sign.detached(o,t.privateKey);return{payload:e,sessionPublicKey:t.publicKey,sessionRegistration:t.registration,sessionSignature:i}}function Ge(t){if(!/^\d+$/.test(t))throw new Error(`atomic amount must be a non-negative integer string, got "${t}"`);return BigInt(t)}function Xe(t){let e=new Uint8Array(8);new DataView(e.buffer).setBigUint64(0,t.nonce,!0);let n=new TextEncoder().encode(t.sellerUrl),r=Jt.create();return r.update(t.vaultPda.toBytes()),r.update(n),r.update(e),r.digest()}var Gt=3600,Pe="https://x402.dexter.cash",_t=6;function Z(t,e=_t){if(!/^\d+(\.\d+)?$/.test(t))throw new Error(`amount must be a non-negative decimal string, got "${t}"`);let[n,r=""]=t.split(".");if(r.length>e)throw new Error(`amount "${t}" has more than ${e} decimals`);let s=r.padEnd(e,"0"),a=`${n}${s}`.replace(/^0+(?=\d)/,"");return a===""?"0":a}function de(t,e=_t){if(!/^\d+$/.test(t))throw new Error(`atomic must be a non-negative integer string, got "${t}"`);let n=t.padStart(e+1,"0"),r=n.slice(0,-e).replace(/^0+(?=\d)/,"")||"0",s=n.slice(-e).replace(/0+$/,"");return s?`${r}.${s}`:r}var Re=class{channelId;network;counterparty;internals;initialCumulativeAtomic;cumulativeAtomic;sequenceNumber=0;closed=!1;lastSignedVoucher=null;previousSignedVoucher=null;constructor(e){this.internals=e,this.channelId=e.channelIdHex,this.network=e.network,this.counterparty=e.counterparty,this.initialCumulativeAtomic=e.initialCumulativeAtomic??0n,this.cumulativeAtomic=this.initialCumulativeAtomic}get state(){let e=this.internals.totalCapAtomic-this.cumulativeAtomic,n=Math.floor(Date.now()/1e3);return{isOpen:!this.closed,spent:de(this.cumulativeAtomic.toString()),remaining:de(e.toString()),expiresInSec:Math.max(0,this.internals.expiresAtUnix-n)}}async signNextVoucher(e){if(this.closed)throw new Q(this.channelId);let n=BigInt(e);if(n<=0n)throw new Error(`voucher increment must be > 0, got ${e}`);if(n>this.internals.perUnitCapAtomic)throw new pe("cap_exceeded",`single voucher increment ${n} exceeds perUnitCap ${this.internals.perUnitCapAtomic}`);let r=this.cumulativeAtomic+n;if(r>this.internals.totalCapAtomic)throw new pe("cap_exceeded",`cumulative ${r} would exceed totalCap ${this.internals.totalCapAtomic}`);let s=this.sequenceNumber+1,a={channelId:this.channelId,cumulativeAmount:r.toString(),sequenceNumber:s},o=await this.internals.vault.signWithSession(this.internals.session,a);return this.previousSignedVoucher=this.lastSignedVoucher,this.lastSignedVoucher=o,this.sequenceNumber=s,this.cumulativeAtomic=r,o}rollbackVoucher(e){let n=this.lastSignedVoucher;if(!n||n.payload.sequenceNumber!==e.payload.sequenceNumber||n.payload.cumulativeAmount!==e.payload.cumulativeAmount)return!1;let r=this.previousSignedVoucher;if(r)this.sequenceNumber=r.payload.sequenceNumber,this.cumulativeAtomic=BigInt(r.payload.cumulativeAmount),this.lastSignedVoucher=r;else if(n.payload.sequenceNumber===1)this.sequenceNumber=0,this.cumulativeAtomic=this.initialCumulativeAtomic,this.lastSignedVoucher=null;else return!1;return this.previousSignedVoucher=null,!0}async stream(e,n){if(this.closed)throw new Q(this.channelId);let r=await this.signNextVoucher(this.internals.perUnitCapAtomic.toString()),s=new Headers(n?.headers);s.set("X-Tab-Voucher",Ye(r)),s.set("Accept","text/event-stream");let a=await fetch(e,{...n,headers:s});if(!a.ok){let o=await a.text().catch(()=>"");throw new Error(`tab.stream HTTP ${a.status}: ${o.slice(0,500)}`)}if(!a.body)throw new Error("tab.stream response has no body");return Zt(a.body)}async close(){if(this.closed)throw new Q(this.channelId);let e={settleTx:""};this.lastSignedVoucher&&this.cumulativeAtomic>0n&&(e=await Yt(this.internals.facilitatorUrl,this.lastSignedVoucher,this.internals.network));let n=(this.internals.closeMode??"revoke")==="revoke";return n&&await this.internals.vault.signCloseTab(this.internals.session,this.channelId,this.cumulativeAtomic.toString()),this.closed=!0,this.internals.session.privateKey.fill(0),{settledAmount:de(this.cumulativeAtomic.toString()),sessionRevoked:n,...e}}};function Ye(t){return Buffer.from(JSON.stringify({payload:t.payload,sessionPublicKey:ee(t.sessionPublicKey),sessionRegistration:ee(t.sessionRegistration),sessionSignature:ee(t.sessionSignature)}),"utf8").toString("base64")}function fe(t){return typeof t!="string"||!/^\d+$/.test(t)?null:BigInt(t)}function Xt(t){let e;try{e=JSON.parse(t)}catch{return!1}if(typeof e!="object"||e===null)return!1;let n="non_monotonic_cumulative";if(e.error!==n&&e.reason!==n)return!1;let r=fe(e.attempted_cumulative),s=fe(e.on_chain_spent),a=fe(e.frontier);return r===null||s===null||a===null?!1:r>s&&r<=a}async function Yt(t,e,n){let r=`${t.replace(/\/$/,"")}/tab/settle`,s={channelId:e.payload.channelId,cumulativeAmount:e.payload.cumulativeAmount,sequenceNumber:e.payload.sequenceNumber,sessionPublicKey:ee(e.sessionPublicKey),sessionSignature:ee(e.sessionSignature),sessionRegistration:ee(e.sessionRegistration),network:n},a=await fetch(r,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(s)}),o=await a.text();if(!a.ok){if(a.status===409&&Xt(o))return{settleTx:""};throw new Error(`tab settle ${a.status}: ${o.slice(0,500)}`)}let i;try{i=JSON.parse(o)}catch{throw new Error(`tab settle returned non-JSON: ${o.slice(0,200)}`)}if(i.reason==="covered_by_frontier"){let u=fe(i.attemptedCumulative),p=fe(i.onChainSpent),d=fe(i.frontier);if(u!==null&&p!==null&&d!==null&&u>p&&u<=d)return{settleTx:""}}if(!i.settleTx)throw new Error(`tab settle returned no settleTx: ${o.slice(0,200)}`);let c={settleTx:i.settleTx};return typeof i.grossAmount=="string"&&(c.grossAmount=i.grossAmount),typeof i.feeAmount=="string"&&(c.feeAmount=i.feeAmount),typeof i.netAmount=="string"&&(c.netAmount=i.netAmount),c}async function dt(t,e,n,r,s){let a=`${t.replace(/\/$/,"")}/tab/open`,o=await fetch(a,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({buyer_swig_address:e,seller:s,max_amount_atomic:n.toString(),network:r})}),i=await o.json().catch(()=>({}));if(!o.ok||!i.success||!i.armed)throw new Error(`tab_open_unprotected: ${i.error??`http_${o.status}`}`);return{armed:!0,signature:i.signature??""}}async function ft(t){if(t.network!==t.vault.network)throw new me(`options.network (${t.network}) doesn't match vault.network (${t.vault.network})`);if(t.network!=="solana:mainnet")throw new me(t.network);let e=BigInt(Math.floor(Math.random()*4294967295)),n=new Rt(t.vault.vaultPda),r=Xe({vaultPda:n,sellerUrl:t.seller,nonce:BigInt(e)}),s=ee(r),a=BigInt(Z(t.perUnitCap)),o=BigInt(Z(t.totalCap));if(a<=0n)throw new Error("perUnitCap must be > 0");if(o<a)throw new Error("totalCap must be >= perUnitCap");if(t.revolvingCapacity!==void 0&&BigInt(Z(t.revolvingCapacity))<=0n)throw new Error("revolvingCapacity must be > 0");let i=t.sessionDuration??Gt,c=Math.floor(Date.now()/1e3)+i,u=Qt(t.seller),p={channelId:s,maxAmountAtomic:o.toString(),revolvingCapacityAtomic:t.revolvingCapacity?Z(t.revolvingCapacity):o.toString(),expiresAtUnix:c,allowedCounterparty:u},d=await t.vault.authorizeSession(p);return await dt(t.facilitatorUrl??Pe,t.vault.swigAddress,o,t.network,u),new Re({vault:t.vault,network:t.network,seller:t.seller,counterparty:u,session:d,channelIdHex:s,channelIdBytes:r,perUnitCapAtomic:a,totalCapAtomic:o,expiresAtUnix:c,facilitatorUrl:t.facilitatorUrl??Pe})}async function zt(t){throw new Error("resumeTab is Phase 3 work. Session keys are memory-only by design; recovery requires reading active_session on chain and re-authorizing. Tracked in dexter-vault roadmap.")}function Qt(t){if(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(t))try{return new Rt(t),t}catch{}throw new Error(`seller must be a base58 Solana pubkey for Phase 2 (got "${t}"). URL-based counterparty resolution lands in Phase 3 (seller middleware).`)}async function*Zt(t){let e=t.getReader(),n=new TextDecoder,r="";try{for(;;){let{done:s,value:a}=await e.read();if(s)break;r+=n.decode(a,{stream:!0});let o;for(;(o=r.indexOf(`
|
|
2
2
|
|
|
3
|
-
`))!==-1;){let i=r.slice(0,o);r=r.slice(o+2);let c=
|
|
4
|
-
`);yield new TextEncoder().encode(u)}}}}finally{e.releaseLock()}}function
|
|
3
|
+
`))!==-1;){let i=r.slice(0,o);r=r.slice(o+2);let c=en(i);if(c.eventName==="end")return;if(c.data!==null){let u=c.data.replace(/\\n/g,`
|
|
4
|
+
`);yield new TextEncoder().encode(u)}}}}finally{e.releaseLock()}}function en(t){let e=null,n=[];for(let r of t.split(`
|
|
5
5
|
`))r.startsWith("event:")?e=r.slice(6).trim():r.startsWith("data:")&&n.push(r.slice(5).trimStart());return{eventName:e,data:n.length?n.join(`
|
|
6
|
-
`):null}}import _e from"tweetnacl";import{Connection as sn,PublicKey as Re}from"@solana/web3.js";import{bytesToHex as an}from"@noble/hashes/utils";import{fetchSessionAccount as on,isSessionLive as cn}from"@dexterai/vault/session";import{readVaultFull as ln}from"@dexterai/vault/reader";import{buildRegisterSessionKeyInstruction as Zt,buildRevokeSessionKeyInstruction as en,deriveSwigWalletAddress as nr}from"@dexterai/vault/instructions";import{buildSecp256r1VerifyInstruction as tn}from"@dexterai/vault/precompile";import{DEXTER_VAULT_PROGRAM_ID as ft,SECP256R1_PROGRAM_ID as nn,INSTRUCTIONS_SYSVAR_ID as rn}from"@dexterai/vault/constants";var gt="solana:mainnet";async function un(t){let e=t.facilitatorUrl??ve,n=t.programId??ft,r=new Re(t.vaultPda),s=new Re(t.params.counterparty),a=Je(t.perUnitCapAtomic);if(a<=0n)throw new Error(`perUnitCapAtomic must be > 0, got ${t.perUnitCapAtomic}`);let o=Je(t.params.maxAmountAtomic),i=Je(t.params.maxRevolvingCapacityAtomic),c=mn(t.sessionSecretKey),u=new Re(t.params.sessionPubkey).toBytes();if(!_t(c.publicKey,u))throw new Error(`tab_session_key_mismatch: the supplied secret derives ${new Re(c.publicKey).toBase58()} but params.sessionPubkey is ${t.params.sessionPubkey} \u2014 wrong key handed to this process`);let p=_e.randomBytes(32),g=_e.sign.detached(p,c.secretKey);if(!_e.sign.detached.verify(p,g,u))throw new Error("tab_session_key_mismatch: secret key failed the sign/verify self-check against params.sessionPubkey \u2014 the seed half does not sign for the granted pubkey");let d=ut({programId:n,vaultPda:r,sessionPubkey:c.publicKey,maxAmount:o,expiresAt:BigInt(t.params.expiresAtUnix),allowedCounterparty:s,nonce:t.params.nonce,maxRevolvingCapacity:i}),x=typeof t.connection=="string"?new sn(t.connection,"confirmed"):t.connection,l=await on(x,r,s,n);if(!l||l.version===0)throw new Error("tab_session_not_live: no live SessionAccount PDA for this (vault, counterparty) \u2014 revoked, expiry-swept, or never registered");if(!cn(l))throw new Error(l.version!==1?`tab_session_not_live: SessionAccount has unsupported version ${l.version} \u2014 not a live v1 session`:`tab_session_not_live: SessionAccount is present but expired (expiresAt=${l.session.expiresAt})`);if(!_t(l.session.sessionPubkey,c.publicKey))throw new Error(`tab_session_pubkey_mismatch: the on-chain session carries ${new Re(l.session.sessionPubkey).toBase58()} \u2014 the grant this key belongs to was replaced by a newer registration`);if(l.session.maxAmount!==o||l.session.expiresAt!==t.params.expiresAtUnix||l.session.nonce!==t.params.nonce||l.session.maxRevolvingCapacity!==i)throw new Error(`tab_grant_params_stale: params disagree with the on-chain session scope (chain: maxAmount=${l.session.maxAmount} expiresAt=${l.session.expiresAt} nonce=${l.session.nonce} revolving=${l.session.maxRevolvingCapacity}; params: ${t.params.maxAmountAtomic}/${t.params.expiresAtUnix}/${t.params.nonce}/${t.params.maxRevolvingCapacityAtomic}) \u2014 refresh the grant hand-off`);let P=l.session.spent>l.session.crystallizedCumulative?l.session.spent:l.session.crystallizedCumulative;if(P>=o)throw new Error(`tab_exhausted: on-chain frontier ${P} has consumed the session cap ${o} \u2014 no voucher can strictly exceed it; open a new grant`);let T=t.sellerUrl??t.params.counterparty,y=BigInt(Math.floor(Math.random()*4294967295)),f=Ge({vaultPda:r,sellerUrl:T,nonce:y}),S=an(f),k=t.swigAddress;if(!k){let O=await ln(x,r);if(!O.exists||!O.swigAddress)throw new Error(`tab_vault_unreadable: vault ${r.toBase58()} has no readable swig_address on chain \u2014 pass options.swigAddress explicitly`);k=O.swigAddress}await pt(e,k,o,gt,t.params.counterparty);let U={channelId:S,maxAmountAtomic:t.params.maxAmountAtomic,revolvingCapacityAtomic:t.params.maxRevolvingCapacityAtomic,expiresAtUnix:t.params.expiresAtUnix,allowedCounterparty:t.params.counterparty},K=Et({publicKey:c.publicKey,privateKey:c.secretKey},U,d),$={network:gt,swigAddress:k,vaultPda:r.toBase58(),authorizeSession:async()=>{throw new Error("grant_tab_no_passkey: a grant-held tab cannot authorize sessions \u2014 session birth requires the wallet owner's passkey ceremony")},signWithSession:async(O,D)=>vt(O,D,f),signOpenTab:async O=>O.registration,signCloseTab:async()=>{throw new Error("grant_tab_cannot_revoke: session revocation is passkey-signed and belongs to the wallet owner's surfaces \u2014 a grant-held tab closes settle-only")}};return new Pe({vault:$,network:gt,seller:T,counterparty:t.params.counterparty,session:K,channelIdHex:S,channelIdBytes:f,perUnitCapAtomic:a,totalCapAtomic:o,expiresAtUnix:t.params.expiresAtUnix,facilitatorUrl:e,initialCumulativeAtomic:P,closeMode:"settle-only"})}function mn(t){if(t.length===64)return _e.sign.keyPair.fromSecretKey(t);if(t.length===32)return _e.sign.keyPair.fromSeed(t);throw new Error(`tab_session_key_invalid: expected a 64-byte nacl secretKey or a 32-byte ed25519 seed, got ${t.length} bytes`)}function _t(t,e){if(t.length!==e.length)return!1;let n=0;for(let r=0;r<t.length;r++)n|=t[r]^e[r];return n===0}import{PublicKey as gn}from"@solana/web3.js";var kt=[{caip2:"eip155:8453",bare:"base",family:"evm"},{caip2:"eip155:1",bare:"ethereum",family:"evm"},{caip2:"eip155:137",bare:"polygon",family:"evm"},{caip2:"eip155:42161",bare:"arbitrum",family:"evm"},{caip2:"eip155:10",bare:"optimism",family:"evm"},{caip2:"eip155:43114",bare:"avalanche",family:"evm"},{caip2:"eip155:56",bare:"bsc",family:"evm"},{caip2:"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",bare:"solana",family:"svm"}],pn=new Map(kt.map(t=>[t.caip2.toLowerCase(),t])),dn=new Map(kt.map(t=>[t.bare.toLowerCase(),t]));function ke(t){if(!t)return null;let e=t.toLowerCase(),n=pn.get(e)||dn.get(e);return n?{caip2:n.caip2,bare:n.bare,family:n.family}:null}function yt(t){let e=t.replace(/-/g,"+").replace(/_/g,"/"),n=e+"=".repeat((4-(e.length%4||4))%4);return JSON.parse(Buffer.from(n,"base64").toString("utf8"))}function fn(t){let e=[];for(let n of t){if(!n||typeof n!="object")continue;let r=n,s=ke(String(r.network??""));s&&e.push({scheme:String(r.scheme??"exact"),network:s,amount:String(r.amount??r.maxAmountRequired??"0"),asset:String(r.asset??""),payTo:String(r.payTo??""),maxTimeoutSeconds:typeof r.maxTimeoutSeconds=="number"?r.maxTimeoutSeconds:void 0,extra:r.extra&&typeof r.extra=="object"?r.extra:void 0})}return e}async function Ye(t){let e=t.headers.get("payment-required");if(!e)return null;let n;try{n=yt(e)}catch{return null}let r=Array.isArray(n.accepts)?n.accepts:[];return r.length===0?null:{x402Version:2,options:fn(r),resourceUrl:n.resource&&typeof n.resource=="object"?String(n.resource.url??""):void 0}}async function Ce(t,e={},n=fetch){let r={method:e.method??"GET",headers:e.headers};typeof e.body=="string"&&(r.body=e.body);let s;try{s=await n(t,r)}catch(i){return{kind:"error",detail:`probe failed: ${i?.message??String(i)}`}}if(s.status!==402)return s.ok?{kind:"free",response:s}:{kind:"error",detail:`probe returned HTTP ${s.status}`};let a=await Ye(s);if(!a)return{kind:"error",detail:"the 402 carries no x402 v2 PAYMENT-REQUIRED challenge"};let o=a.options.find(i=>i.scheme==="tab"&&i.network.family==="svm");if(!o)return{kind:"no_tab",schemesOffered:a.options.map(i=>i.scheme)};try{new gn(o.payTo)}catch{return{kind:"error",detail:`tab option payTo is not a valid Solana pubkey: "${o.payTo}"`}}return{kind:"offer",offer:{payTo:o.payTo,amountAtomic:o.amount,asset:o.asset,networkCaip2:o.network.caip2,resourceUrl:a.resourceUrl}}}var Ie="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",ze="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",Qe="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z",te=Ie,Ne=ze,Oe=Qe,ne="eip155:8453",fe="eip155:84532",ge="eip155:42161",ye="eip155:137",he="eip155:10",Ae="eip155:43114",be="eip155:56",Se="eip155:1187947933",we="eip155:324705682",xe="eip155:1",re=ne,Ze=fe,Ue=ge,Be=ye,De=he,Me=Ae,$e=be,Ke=Se,Le=we,Ve=xe,We="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",Ct="4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",It="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",ht="0x55d398326f99059fF775485246999027B3197955",et="0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",tt={[be]:et,[ne]:It,[fe]:"0x036CbD53842c5426634e7929541eC2318f3dCF7e",[ge]:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831",[ye]:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",[he]:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",[Ae]:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",[Se]:"0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",[we]:"0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",[xe]:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},nt={[ht]:{symbol:"USDT",decimals:18},[et]:{symbol:"USDC",decimals:18}};var G="0x000000000022D473030F116dDEE9F6B43aC78BA3",qe="0x402085c248EeA27D92E8b30b2C58ed07f9E20001",He={[be]:56,[ne]:8453,[fe]:84532,[ge]:42161,[ye]:137,[he]:10,[Ae]:43114,[Se]:1187947933,[we]:324705682,[xe]:1},se={[Ie]:"https://api.dexter.cash/api/solana/rpc",[ze]:"https://api.devnet.solana.com",[Qe]:"https://api.testnet.solana.com"},B={[be]:"https://api.dexter.cash/api/evm/bsc/rpc",[ne]:"https://api.dexter.cash/api/base/rpc",[fe]:"https://sepolia.base.org",[ge]:"https://api.dexter.cash/api/evm/arbitrum/rpc",[ye]:"https://api.dexter.cash/api/evm/polygon/rpc",[he]:"https://api.dexter.cash/api/evm/optimism/rpc",[Ae]:"https://api.dexter.cash/api/evm/avalanche/rpc",[Se]:"https://skale-base.skalenodes.com/v1/base",[we]:"https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",[xe]:"https://eth.llamarpc.com"};var I=class t extends Error{code;details;constructor(e,n,r){super(n),this.name="X402Error",this.code=e,this.details=r,Object.setPrototypeOf(this,t.prototype)}};import{PublicKey as ae,Connection as At,TransactionMessage as yn,VersionedTransaction as hn,ComputeBudgetProgram as Nt}from"@solana/web3.js";import{getAssociatedTokenAddress as bt,getAccount as An,createTransferCheckedInstruction as bn,getMint as Sn,TOKEN_PROGRAM_ID as Ot,TOKEN_2022_PROGRAM_ID as rt}from"@solana/spl-token";var wn=12e3,xn=1;function oe(t){if(!t||typeof t!="object")return!1;let e=t;return"publicKey"in e&&"signTransaction"in e&&typeof e.signTransaction=="function"}var st=class{name="Solana";networks=[te,Ne,Oe];config;log;constructor(e={}){this.config=e,this.log=e.verbose?console.log.bind(console,"[x402:solana]"):()=>{}}canHandle(e){return!!(this.networks.includes(e)||e==="solana"||e==="solana-devnet"||e==="solana-testnet"||e.startsWith("solana:"))}getDefaultRpcUrl(e){return this.config.rpcUrls?.[e]?this.config.rpcUrls[e]:se[e]?se[e]:e==="solana"?se[te]:e==="solana-devnet"?se[Ne]:e==="solana-testnet"?se[Oe]:se[te]}getAddress(e){return oe(e)?e.publicKey?.toBase58()??null:null}isConnected(e){return oe(e)?e.publicKey!==null:!1}async getBalance(e,n,r){if(!oe(n)||!n.publicKey)return 0;let s=r||this.getDefaultRpcUrl(e.network),a=new At(s,"confirmed"),o=new ae(n.publicKey.toBase58()),i=new ae(e.asset);try{let u=(await a.getAccountInfo(i,"confirmed"))?.owner.toBase58()===rt.toBase58()?rt:Ot,p=await bt(i,o,!1,u),g=await An(a,p,void 0,u),d=e.extra?.decimals??6;return Number(g.amount)/Math.pow(10,d)}catch(c){if(c&&typeof c=="object"&&"name"in c&&(c.name==="TokenAccountNotFoundError"||c.name==="TokenInvalidAccountOwnerError"))return 0;throw c}}async buildTransaction(e,n,r){if(!oe(n))throw new Error("Invalid Solana wallet");if(!n.publicKey)throw new Error("Wallet not connected");let s=r||this.getDefaultRpcUrl(e.network),a=new At(s,"confirmed"),o=new ae(n.publicKey.toBase58()),{payTo:i,asset:c,extra:u}=e,p=e.amount??e.maxAmountRequired;if(!p)throw new Error("Missing amount in payment requirements");if(!u?.feePayer)throw new Error("Missing feePayer in payment requirements");let g=new ae(u.feePayer),d=new ae(c),x=new ae(i);this.log("Building transaction:",{from:o.toBase58(),to:i,amount:p,asset:c,feePayer:u.feePayer});let l=[];l.push(Nt.setComputeUnitLimit({units:wn})),l.push(Nt.setComputeUnitPrice({microLamports:xn}));let P=await a.getAccountInfo(d,"confirmed");if(!P)throw new Error(`Token mint ${c} not found`);let T=P.owner.toBase58()===rt.toBase58()?rt:Ot,y=await Sn(a,d,void 0,T);typeof u?.decimals=="number"&&y.decimals!==u.decimals&&this.log(`Decimals mismatch: requirements say ${u.decimals}, mint says ${y.decimals}`);let f=await bt(d,o,!1,T),S=await bt(d,x,!0,T);if(!await a.getAccountInfo(f,"confirmed"))throw new Error(`No token account found for ${c}. Please ensure you have USDC in your wallet.`);if(!await a.getAccountInfo(S,"confirmed"))throw new Error(`Seller token account not found. The seller (${i}) must have a USDC account.`);let K=BigInt(p);l.push(bn(f,d,S,o,K,y.decimals,[],T));let{blockhash:$}=await a.getLatestBlockhash("confirmed"),O=new yn({payerKey:g,recentBlockhash:$,instructions:l}).compileToV0Message(),D=new hn(O),h=await n.signTransaction(D);return this.log("Transaction signed successfully"),{serialized:Buffer.from(h.serialize()).toString("base64"),settlementProbe:{kind:"solana",sourceAta:f.toBase58(),destinationAta:S.toBase58(),asset:c,amount:p,blockhash:$}}}async confirmSettlement(e,n){if(e.kind!=="solana")throw new Error(`SolanaAdapter.confirmSettlement cannot handle probe kind "${e.kind}"`);let r=new At(n,"confirmed"),s=new ae(e.destinationAta),a=await r.getSignaturesForAddress(s,{limit:25});if(a.length===0)return{settled:!1};let o=BigInt(e.amount);for(let i of a){if(i.err)continue;let c=await r.getTransaction(i.signature,{commitment:"confirmed",maxSupportedTransactionVersion:0});if(!c?.meta)continue;let u=c.transaction.message.getAccountKeys().keySegments().flat(),p=c.meta.preTokenBalances??[],g=c.meta.postTokenBalances??[];for(let d of g){if(d.mint!==e.asset)continue;let x=u[d.accountIndex];if(!x||!x.equals(s))continue;let l=p.find(y=>y.accountIndex===d.accountIndex),P=BigInt(l?.uiTokenAmount.amount??"0");if(BigInt(d.uiTokenAmount.amount??"0")-P===o)return{settled:!0,txSignature:i.signature}}}return{settled:!1}}};function X(t){return new st(t)}var Tn={PermitWitnessTransferFrom:[{name:"permitted",type:"TokenPermissions"},{name:"spender",type:"address"},{name:"nonce",type:"uint256"},{name:"deadline",type:"uint256"},{name:"witness",type:"Witness"}],TokenPermissions:[{name:"token",type:"address"},{name:"amount",type:"uint256"}],Witness:[{name:"to",type:"address"},{name:"validAfter",type:"uint256"}]},Ut=BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");function ie(t){if(!t||typeof t!="object")return!1;let e=t;return"address"in e&&typeof e.address=="string"&&e.address.startsWith("0x")}var at=class{name="EVM";networks=[$e,re,Ze,Ve,Ue,Be,De,Me,Ke,Le];config;log;constructor(e={}){this.config=e,this.log=e.verbose?console.log.bind(console,"[x402:evm]"):()=>{}}canHandle(e){return!!(this.networks.includes(e)||e==="base"||e==="bsc"||e==="ethereum"||e==="arbitrum"||e==="polygon"||e==="optimism"||e==="avalanche"||e==="skale-base"||e==="skale-base-sepolia"||e.startsWith("eip155:"))}getDefaultRpcUrl(e){return this.config.rpcUrls?.[e]?this.config.rpcUrls[e]:B[e]?B[e]:e==="base"?B[re]:e==="bsc"?B[$e]:e==="ethereum"?B[Ve]:e==="arbitrum"?B[Ue]:e==="polygon"?B[Be]:e==="optimism"?B[De]:e==="avalanche"?B[Me]:e==="skale-base"?B[Ke]:e==="skale-base-sepolia"?B[Le]:B[re]}getAddress(e){return ie(e)?e.address:null}isConnected(e){return ie(e)?!!e.address:!1}getChainId(e){if(He[e])return He[e];if(e.startsWith("eip155:")){let n=e.split(":")[1];return parseInt(n,10)}return e==="base"?8453:e==="bsc"?56:e==="ethereum"?1:e==="arbitrum"?42161:8453}async getBalance(e,n,r){if(!ie(n)||!n.address)return 0;let s=r||this.getDefaultRpcUrl(e.network);try{let a=this.encodeBalanceOf(n.address),o=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_call",params:[{to:e.asset,data:a},"latest"]})});if(!o.ok)throw new Error(`RPC request failed: ${o.status}`);let i=await o.json();if(i.error)throw new Error(`RPC error: ${JSON.stringify(i.error)}`);if(!i.result||i.result==="0x")return 0;let c=BigInt(i.result),u=e.extra?.decimals??6;return Number(c)/Math.pow(10,u)}catch(a){throw a}}encodeBalanceOf(e){let n="0x70a08231",r=e.slice(2).toLowerCase().padStart(64,"0");return n+r}async confirmSettlement(e,n){if(e.kind==="eip3009"){let r="0xe94a0102",s=e.from.slice(2).toLowerCase().padStart(64,"0"),a=e.nonce.slice(2).toLowerCase().padStart(64,"0"),o=r+s+a,i=await this.ethCall(n,e.asset,o);return{settled:BigInt(i)!==0n}}if(e.kind==="permit2"){let r="0x4fe02b44",s=BigInt(e.nonce),a=s>>8n,o=s&0xffn,i=e.from.slice(2).toLowerCase().padStart(64,"0"),c=a.toString(16).padStart(64,"0"),u=r+i+c,p=await this.ethCall(n,G,u);return{settled:(BigInt(p)>>o&1n)===1n}}throw new Error(`EvmAdapter.confirmSettlement cannot handle probe kind "${e.kind}"`)}async ethCall(e,n,r){let s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_call",params:[{to:n,data:r},"latest"]})});if(!s.ok)throw new Error(`RPC request failed: ${s.status}`);let a=await s.json();if(a.error)throw new Error(`RPC error: ${JSON.stringify(a.error)}`);if(!a.result||a.result==="0x")throw new Error("RPC returned an empty result");return a.result}async buildTransaction(e,n,r){if(!ie(n))throw new Error("Invalid EVM wallet");if(!n.address)throw new Error("Wallet not connected");if(e.scheme==="exact-approval")return this.buildApprovalTransaction(e,n,r);if(e.extra?.assetTransferMethod==="permit2")return this.buildPermit2Transaction(e,n,r);let{payTo:s,asset:a,extra:o}=e,i=e.amount??e.maxAmountRequired;if(!i)throw new Error("Missing amount in payment requirements");this.log("Building EVM transaction:",{from:n.address,to:s,amount:i,asset:a,network:e.network});let c=this.getChainId(e.network),u={name:o?.name??"USD Coin",version:o?.version??"2",chainId:BigInt(c),verifyingContract:a},p={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},g=new Uint8Array(32);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(g);let d="0x"+[...g].map(f=>f.toString(16).padStart(2,"0")).join(""),x=Math.floor(Date.now()/1e3),l={from:n.address,to:s,value:i,validAfter:String(x-600),validBefore:String(x+(e.maxTimeoutSeconds||60)),nonce:d},P={from:n.address,to:s,value:BigInt(i),validAfter:BigInt(x-600),validBefore:BigInt(x+(e.maxTimeoutSeconds||60)),nonce:d};if(!n.signTypedData)throw new Error("Wallet does not support signTypedData (EIP-712)");let T=await n.signTypedData({domain:u,types:p,primaryType:"TransferWithAuthorization",message:P});return this.log("EIP-712 signature obtained"),{serialized:JSON.stringify({authorization:l,signature:T}),signature:T,settlementProbe:{kind:"eip3009",from:n.address,nonce:d,asset:a,chainId:c}}}async buildApprovalTransaction(e,n,r){let{payTo:s,asset:a,extra:o}=e,i=e.amount??e.maxAmountRequired;if(!i)throw new Error("Missing amount in payment requirements");let c=o?.facilitatorContract;if(!c)throw new Error("exact-approval scheme requires extra.facilitatorContract from the facilitator. The /supported endpoint should provide this.");if(!n.signTypedData)throw new Error("Wallet does not support signTypedData (EIP-712)");this.log("Building approval-based transaction:",{from:n.address,to:s,amount:i,asset:a,network:e.network,facilitatorContract:c});let u=r||this.getDefaultRpcUrl(e.network),p=o?.fee??"0",g=BigInt(i)+BigInt(p),d=await this.readAllowance(u,a,n.address,c);if(d<g){if(!n.sendTransaction)throw new Error("BSC payments require a wallet that supports sendTransaction for the one-time token approval. Use createEvmKeypairWallet() or a browser wallet with transaction support.");let D=this.calculateApprovalAmount(i,p,o?.approvalStrategy);this.log(`Approving ${D} for ${c} (current allowance: ${d})`);let h=await n.sendTransaction({to:a,data:this.encodeApprove(c,D),value:0n});this.log(`Approval tx sent: ${h}`),await this.waitForReceipt(u,h),this.log("Approval confirmed")}else this.log("Sufficient allowance, skipping approval");let x=new Uint8Array(16);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(x);let l=[...x].reduce((D,h)=>D*256n+BigInt(h),0n).toString(),P=new Uint8Array(32);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(P);let T="0x"+[...P].map(D=>D.toString(16).padStart(2,"0")).join(""),f=Math.floor(Date.now()/1e3)+(e.maxTimeoutSeconds||300),S=o?.eip712Domain,k=S?{name:S.name,version:S.version,chainId:BigInt(S.chainId),verifyingContract:S.verifyingContract}:{name:"DexterBSCFacilitator",version:"1",chainId:BigInt(this.getChainId(e.network)),verifyingContract:c},U=o?.eip712Types??{Payment:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"token",type:"address"},{name:"amount",type:"uint256"},{name:"fee",type:"uint256"},{name:"nonce",type:"uint256"},{name:"deadline",type:"uint256"},{name:"paymentId",type:"bytes32"}]},K={from:n.address,to:s,token:a,amount:BigInt(i),fee:BigInt(p),nonce:BigInt(l),deadline:BigInt(f),paymentId:T},$=await n.signTypedData({domain:k,types:U,primaryType:"Payment",message:K});this.log("EIP-712 Payment signature obtained");let O={from:n.address,to:s,token:a,amount:i,fee:p,nonce:l,deadline:f,paymentId:T,signature:$};return{serialized:JSON.stringify(O),signature:$}}async buildPermit2Transaction(e,n,r){let{payTo:s,asset:a}=e,o=e.amount??e.maxAmountRequired;if(!o)throw new Error("Missing amount in payment requirements");if(!n.signTypedData)throw new Error("Wallet does not support signTypedData (EIP-712)");this.log("Building Permit2 transaction:",{from:n.address,to:s,amount:o,asset:a,network:e.network});let i=r||this.getDefaultRpcUrl(e.network),c=await this.readAllowance(i,a,n.address,G),u;if(c<BigInt(o)){let k=this.encodeApprove(G,Ut);if(n.signTransaction){this.log(`Signing Permit2 approval for relay (current allowance: ${c})`);let U=this.getChainId(e.network),K=await this.readGasPrice(i),$=await this.readNonce(i,n.address),O=await n.signTransaction({to:a,data:k,chainId:U,gas:50000n,gasPrice:K,nonce:$});u={erc20ApprovalGasSponsoring:{info:{from:n.address,asset:a,spender:G,amount:Ut.toString(),signedTransaction:O,version:"1"}}},this.log("Permit2 approval signed for facilitator relay")}else if(n.sendTransaction){this.log(`Approving Permit2 directly (current allowance: ${c})`);let U=await n.sendTransaction({to:a,data:k,value:0n});this.log(`Permit2 approval tx sent: ${U}`),await this.waitForReceipt(i,U),this.log("Permit2 approval confirmed")}else throw new Error("Permit2 payments require a wallet that supports signTransaction or sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support.")}else this.log("Sufficient Permit2 allowance, skipping approval");let p=new Uint8Array(32);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(p);let g=[...p].reduce((k,U)=>k*256n+BigInt(U),0n),d=Math.floor(Date.now()/1e3),x=d-600,l=d+(e.maxTimeoutSeconds||300),P=this.getChainId(e.network),T={name:"Permit2",chainId:BigInt(P),verifyingContract:G},y={permitted:{token:a,amount:BigInt(o)},spender:qe,nonce:g,deadline:BigInt(l),witness:{to:s,validAfter:BigInt(x)}},f=await n.signTypedData({domain:T,types:Tn,primaryType:"PermitWitnessTransferFrom",message:y});this.log("Permit2 PermitWitnessTransferFrom signature obtained");let S={signature:f,permit2Authorization:{from:n.address,permitted:{token:a,amount:o},spender:qe,nonce:g.toString(),deadline:String(l),witness:{to:s,validAfter:String(x)}}};return{serialized:JSON.stringify(S),signature:f,extensions:u,settlementProbe:{kind:"permit2",from:n.address,nonce:g.toString(),chainId:P}}}async readAllowance(e,n,r,s){let a="0xdd62ed3e",o=r.slice(2).toLowerCase().padStart(64,"0"),i=s.slice(2).toLowerCase().padStart(64,"0"),c=a+o+i;try{let p=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_call",params:[{to:n,data:c},"latest"]})})).json();return p.error||!p.result||p.result==="0x"?0n:BigInt(p.result)}catch{return 0n}}encodeApprove(e,n){let r="0x095ea7b3",s=e.slice(2).toLowerCase().padStart(64,"0"),a=n.toString(16).padStart(64,"0");return r+s+a}async waitForReceipt(e,n,r=3e4){let s=Date.now();for(;Date.now()-s<r;){try{let o=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_getTransactionReceipt",params:[n]})})).json();if(o.result){if(o.result.status==="0x0")throw new Error(`Approval transaction reverted: ${n}`);return}}catch(a){if(a instanceof Error&&a.message.includes("reverted"))throw a}await new Promise(a=>setTimeout(a,2e3))}throw new Error(`Approval transaction receipt timeout after ${r}ms: ${n}`)}async readGasPrice(e){try{let r=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_gasPrice",params:[]})})).json();return r.result?BigInt(r.result):50000000n}catch{return 50000000n}}async readNonce(e,n){try{let s=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_getTransactionCount",params:[n,"latest"]})})).json();return s.result?parseInt(s.result,16):0}catch{return 0}}calculateApprovalAmount(e,n,r){let s=BigInt(e)+BigInt(n);if(!r||r.mode==="exact")return s;let a=BigInt(r.defaultMultiple??10),o=s*a;if(r.maxCapUsd){let i=this.inferDecimals(e),c=BigInt(Math.floor(r.maxCapUsd*Math.pow(10,i)));if(o>c)return c}if(r.exactAboveUsd){let i=this.inferDecimals(e),c=BigInt(Math.floor(r.exactAboveUsd*Math.pow(10,i)));if(BigInt(e)>c)return s}return o}inferDecimals(e){return e.length>12?18:6}};function Te(t){return new at(t)}function St(t){if(t===We||t===Ct)return!0;let e=t.toLowerCase();for(let n of Object.values(tt))if(n.toLowerCase()===e)return!0;for(let n of Object.keys(nt))if(n.toLowerCase()===e)return!0;return!1}function En(t){return{[Ie]:"Solana",[ze]:"Solana Devnet",[Qe]:"Solana Testnet",solana:"Solana","solana-devnet":"Solana Devnet","solana-testnet":"Solana Testnet",[ne]:"Base",[fe]:"Base Sepolia",[xe]:"Ethereum",[ge]:"Arbitrum",[ye]:"Polygon",[he]:"Optimism",[Ae]:"Avalanche",[be]:"BSC",[Se]:"SKALE Base",[we]:"SKALE Base Sepolia",base:"Base","base-sepolia":"Base Sepolia",ethereum:"Ethereum",arbitrum:"Arbitrum",polygon:"Polygon",optimism:"Optimism",avalanche:"Avalanche",bsc:"BSC","skale-base":"SKALE Base","skale-base-sepolia":"SKALE Base Sepolia"}[t]||t}function Bt(t,e){let n=En(t);return n===t?e:n}async function vn(t,e){if(typeof t=="string")return[t,e];if(t instanceof URL)return[t.href,e];let n=t,r=new Headers(n.headers);e?.headers&&new Headers(e.headers).forEach((o,i)=>r.set(i,o));let s={method:e?.method??n.method,headers:r,signal:e?.signal??n.signal,redirect:e?.redirect??n.redirect,credentials:e?.credentials??n.credentials},a=(s.method??"GET").toUpperCase();return e&&"body"in e?s.body=e.body:a!=="GET"&&a!=="HEAD"&&n.body&&(s.body=await n.arrayBuffer()),[n.url,s]}var Pn=new WeakMap;function Dt(t){let{adapters:e=[X({verbose:t.verbose}),Te({verbose:t.verbose})],wallets:n,wallet:r,preferredNetwork:s,rpcUrls:a={},maxAmountAtomic:o,fetch:i=globalThis.fetch,verbose:c=!1,accessPass:u,onPaymentRequired:p,onPaymentDispatched:g,maxRetries:d=0,retryDelayMs:x=500}=t,l=c?console.log.bind(console,"[x402]"):()=>{};async function P(h,w){let E;for(let A=0;A<=d;A++)try{let v=await i(h,w);if(v.status>=502&&v.status<=504&&A<d){l(`Retry ${A+1}/${d}: server returned ${v.status}`),await new Promise(R=>setTimeout(R,x*Math.pow(2,A)));continue}return v}catch(v){E=v,A<d&&(l(`Retry ${A+1}/${d}: ${v instanceof Error?v.message:"network error"}`),await new Promise(R=>setTimeout(R,x*Math.pow(2,A))))}throw E}let T=new Map;function y(h){try{let w=new URL(h).host,E=T.get(w);if(E&&E.expiresAt>Date.now()/1e3+10)return E.jwt;E&&T.delete(w)}catch{}return null}function f(h,w){try{let E=new URL(h).host,A=w.split(".");if(A.length===3){let v=JSON.parse(atob(A[1].replace(/-/g,"+").replace(/_/g,"/"))),R=Math.floor(Date.now()/1e3),_=R+86400,L=Math.min(typeof v.exp=="number"?v.exp:R,_);T.set(E,{jwt:w,expiresAt:L}),l("Access pass cached for",E,"| expires:",new Date(L*1e3).toISOString())}}catch{l("Failed to cache access pass")}}let S=n||{};r&&!S.solana&&oe(r)&&(S.solana=r),r&&!S.evm&&ie(r)&&(S.evm=r);function k(h){let w=[];for(let E of h){let A=E.scheme??"exact";if(A!=="exact"&&A!=="exact-approval")continue;let v=e.find(_=>_.canHandle(E.network));if(!v)continue;let R;v.name==="Solana"?R=S.solana:v.name==="EVM"&&(R=S.evm),R&&v.isConnected(R)&&w.push({accept:E,adapter:v,wallet:R})}if(w.length===0)return null;if(s){let E=w.find(A=>A.accept.network===s);if(E)return E}return w[0]}function U(h,w){return Bt(h,w)}function K(h,w){return a[h]||w.getDefaultRpcUrl(h)}async function $(h,w,E,A,v){let R="";if(u?.preferTier&&A.tiers){let m=A.tiers.find(b=>b.id===u.preferTier);if(m){if(u.maxSpend&&parseFloat(m.price)>parseFloat(u.maxSpend))throw new I("access_pass_exceeds_max_spend",`Access pass tier "${m.id}" costs $${m.price}, exceeds max spend $${u.maxSpend}`);R=`tier=${m.id}`}}else if(u?.preferDuration&&A.ratePerHour)R=`duration=${u.preferDuration}`;else if(A.tiers&&A.tiers.length>0){let m=A.tiers[0];if(u?.maxSpend&&parseFloat(m.price)>parseFloat(u.maxSpend))throw new I("access_pass_exceeds_max_spend",`Cheapest access pass costs $${m.price}, exceeds max spend $${u?.maxSpend}`);R=`tier=${m.id}`}let _=R?v.includes("?")?`${v}&${R}`:`${v}?${R}`:v;l("Purchasing access pass:",R||"default tier");let L=E.headers.get("PAYMENT-REQUIRED");if(!L)return null;let M;try{M=JSON.parse(atob(L))}catch{return null}let N=k(M.accepts);if(!N)return null;let{accept:C,adapter:W,wallet:ce}=N;if(W.name==="Solana"&&!C.extra?.feePayer)return null;let H=C.extra?.decimals??(St(C.asset)?6:void 0);if(typeof H!="number")return null;let Ee=C.amount??C.maxAmountRequired;if(!Ee)return null;let F=K(C.network,W);try{let m=await W.getBalance(C,ce,F),b=Number(Ee)/Math.pow(10,H);if(m<b){let lt=U(C.network,W.name);throw new I("insufficient_balance",`Insufficient balance for access pass on ${lt}. Have $${m.toFixed(4)}, need $${b.toFixed(4)}`)}}catch(m){if(m instanceof I)throw m}let j=await W.buildTransaction(C,ce,F),le;W.name==="EVM"?le=JSON.parse(j.serialized):le={transaction:j.serialized};let Y=typeof h=="string"?h:h instanceof URL?h.href:h.url,ue=M.resource;if(typeof M.resource=="string")try{let m=new URL(M.resource,Y);["http:","https:"].includes(m.protocol)&&(ue=m.toString())}catch{}else if(M.resource&&typeof M.resource=="object"&&"url"in M.resource){let m=M.resource;try{let b=new URL(m.url,Y);["http:","https:"].includes(b.protocol)&&(ue={...m,url:b.toString()})}catch{}}let je={x402Version:C.x402Version??2,resource:ue,accepted:C,payload:le};j.extensions&&(je.extensions=j.extensions);let J=btoa(JSON.stringify(je)),z=await i(_,{...w,method:"POST",headers:{...w?.headers||{},"Content-Type":"application/json","PAYMENT-SIGNATURE":J}});if(!z.ok)return l("Pass purchase failed:",z.status),null;let V=z.headers.get("ACCESS-PASS");return V&&(f(v,V),l("Access pass purchased and cached")),z}async function O(h,w){let E=h;if(l("Making request:",E),u){let m=y(E);if(m){l("Using cached access pass");let b=await i(h,{...w,headers:{...w?.headers||{},Authorization:`Bearer ${m}`}});if(b.status!==401&&b.status!==402)return b;l("Cached pass rejected (status",b.status,"), purchasing new pass");try{T.delete(new URL(E).host)}catch{}}}let A=await P(h,w);if(A.status!==402)return A;l("Received 402 Payment Required");let v=A.headers.get("X-ACCESS-PASS-TIERS");if(u&&v){l("Server offers access passes, purchasing...");try{let m=JSON.parse(atob(v)),b=await $(h,w,A,m,E);if(b)return b}catch(m){l("Access pass purchase failed, falling back to per-request payment:",m)}}let R=A.headers.get("PAYMENT-REQUIRED");if(!R)throw new I("missing_payment_required_header","Server returned 402 but no PAYMENT-REQUIRED header");let _;try{let m=atob(R);_=JSON.parse(m)}catch{throw new I("invalid_payment_required","Failed to decode PAYMENT-REQUIRED header")}l("Payment requirements:",_);let L=A.headers.get("X-Quote-Hash");L&&l("Quote hash received:",L);let M=k(_.accepts);if(!M){let m=_.accepts.map(b=>b.network).join(", ");throw new I("no_matching_payment_option",`No connected wallet for any available network: ${m}`)}let{accept:N,adapter:C,wallet:W}=M;if(l(`Using ${C.name} for ${N.network}`),C.name==="Solana"&&!N.extra?.feePayer)throw new I("missing_fee_payer","Solana payment option missing feePayer in extra");let ce=N.extra?.decimals??(St(N.asset)?6:void 0);if(typeof ce!="number")throw new I("missing_decimals","Payment option missing decimals - provide in extra or use a known stablecoin");let H=N.amount??N.maxAmountRequired;if(!H)throw new I("missing_amount","Payment option missing amount");if(o&&BigInt(H)>BigInt(o))throw new I("amount_exceeds_max",`Payment amount ${H} exceeds maximum ${o}`);let Ee=K(N.network,C);l("Checking balance...");try{let m=await C.getBalance(N,W,Ee),b=Number(H)/Math.pow(10,ce);if(m<b){let lt=U(N.network,C.name);throw new I("insufficient_balance",`Insufficient balance on ${lt}. Have $${m.toFixed(4)}, need $${b.toFixed(4)}`)}l(`Balance OK: $${m.toFixed(4)} >= $${b.toFixed(4)}`)}catch(m){if(m instanceof I)throw m;l("Balance check failed (RPC error), proceeding with transaction attempt")}if(p&&!await p(N))throw new I("payment_rejected","Payment rejected by onPaymentRequired callback");l("Building transaction...");let F=await C.buildTransaction(N,W,Ee);l("Transaction signed");let j;C.name==="EVM"?j=JSON.parse(F.serialized):j={transaction:F.serialized};let le=h,Y=_.resource;if(typeof _.resource=="string")try{let m=new URL(_.resource,le).toString();m!==_.resource&&l("Resolved relative resource URL:",_.resource,"\u2192",m),Y=m}catch{Y=_.resource}else if(_.resource&&typeof _.resource=="object"&&"url"in _.resource){let m=_.resource;try{let b=new URL(m.url,le).toString();b!==m.url&&(l("Resolved relative resource URL:",m.url,"\u2192",b),Y={...m,url:b})}catch{}}let ue={x402Version:N.x402Version??2,resource:Y,accepted:N,payload:j};F.extensions&&(ue.extensions=F.extensions);let je=btoa(JSON.stringify(ue));if(g)try{g(N,F.settlementProbe)}catch{}l("Retrying request with payment...");let J=await P(h,{...w,headers:{...w?.headers||{},"PAYMENT-SIGNATURE":je,...L?{"X-Quote-Hash":L}:{}}});if(l("Retry response status:",J.status),J.status===402){let m="unknown";try{let b=await J.clone().json();m=String(b.error||b.message||JSON.stringify(b)),l("Rejection reason:",m)}catch{}throw new I("payment_rejected",`Payment was rejected by the server: ${m}`)}let z=J.headers.get("PAYMENT-RESPONSE"),V;if(z)try{V=JSON.parse(atob(z))}catch{}return V??={},V.amountAtomic=H,V.assetDecimals=ce,Pn.set(J,V),V.extensions&&l("Settlement extensions:",Object.keys(V.extensions).join(", ")),J}async function D(h,w){let[E,A]=await vn(h,w);return O(E,A)}return{fetch:D}}function q(t){if(t instanceof Error){if(t.message&&t.message.length>0)return t.message;if(t.name&&t.name.length>0)return t.name}let e=String(t);return e.length>0?e:"unknown error"}async function Fe(t){let e="";try{e=(await t.clone().text()).slice(0,600)}catch{}let n=e.toLowerCase(),r=n.includes("settle")||n.includes("facilitator"),s=e;try{let a=JSON.parse(e),o=[a.error,a.detail,a.message].filter(i=>typeof i=="string"&&i.length>0);o.length>0&&(s=o.join(" \u2014 "))}catch{}return s||(s=`HTTP ${t.status}`),{reason:r?"settlement_failed":"merchant_rejected",detail:`merchant HTTP ${t.status}: ${s}`}}var ot="Payment authorization was sent, but the merchant did not respond within the timeout. ",it=" Do not retry without checking \u2014 inspect the funding wallet for a transfer to the merchant before attempting payment again.";async function ct(t,e,n){if(!t)return{confirmed:!1,detail:ot+"This payment scheme has no on-chain confirmation check, so the SDK cannot verify whether it settled."+it};try{if(t.kind==="solana"){let o=X(),i=n??o.getDefaultRpcUrl(e.caip2);if(!o.confirmSettlement)return $t();let c=await o.confirmSettlement(t,i);return c.settled?{confirmed:!0,txSignature:c.txSignature}:Mt()}let r=Te(),s=r.getDefaultRpcUrl(e.caip2);if(!r.confirmSettlement)return $t();let a=await r.confirmSettlement(t,s);return a.settled?{confirmed:!0,txSignature:a.txSignature}:Mt()}catch(r){return{confirmed:!1,detail:ot+`On-chain confirmation could not be completed (${q(r)}).`+it}}}function Mt(){return{confirmed:!1,detail:ot+"On-chain confirmation found no matching settlement yet \u2014 the payment may still be pending, or may not have settled."+it}}function $t(){return{confirmed:!1,detail:ot+"The chain adapter does not support on-chain confirmation."+it}}var Rn=new Set(["exact","exact-approval"]);async function _n(t,e,n,r){let s;try{s=await r.signNextVoucher(n.amount)}catch{return null}let a=new Headers(e.headers??void 0);a.set("X-Tab-Voucher",Xe(s));let o={method:e.method??"GET",headers:a};e.signal&&(o.signal=e.signal),typeof e.body=="string"&&(o.body=e.body);let i;try{i=await fetch(t,o)}catch(c){return{ok:!1,reason:"error",detail:c?.message??String(c)}}return i.status===402?(r.rollbackVoucher?.call(r,s),null):i.ok?{ok:!0,paid:!0,response:i,amountPaid:n.amount,network:n.network}:{ok:!1,...await Fe(i)}}var Kt={version:2,async parseChallenge(t){return Ye(t)},async pay(t,e,n,r,s){if(s.tab){let y=n.options.find(f=>f.scheme==="tab"&&f.network.family==="svm"&&f.payTo===s.tab.counterparty);if(y){let f=await _n(t,e,y,s.tab);if(f)return f}}let a=n.options.filter(y=>Rn.has(y.scheme));if(a.length===0)return{ok:!1,reason:"no_payment_options",detail:`no generically payable scheme offered (got: ${n.options.map(y=>y.scheme).join(", ")})`};let o=a.find(y=>y.network.family==="evm"?!!r.evm:y.network.family==="svm"?!!r.solana:!1);if(!o)return{ok:!1,reason:"unsupported_network"};let i=s.timeoutMs??15e3,c=s.responseTimeoutMs??12e4,u=new AbortController,p=setTimeout(()=>u.abort(),i),g=!1,d,x=(y,f)=>{g=!0,d=f,clearTimeout(p),p=setTimeout(()=>u.abort(),c)},l=Dt({wallets:r,preferredNetwork:o.network.caip2,maxAmountAtomic:s.maxAmountAtomic,fetch:globalThis.fetch,onPaymentDispatched:x}),P=e.signal?AbortSignal.any([e.signal,u.signal]):u.signal,T={method:e.method??"GET",headers:e.headers,signal:P};typeof e.body=="string"&&(T.body=e.body);try{let y=await l.fetch(t,T);if(clearTimeout(p),!y.ok)return{ok:!1,...await Fe(y)};let f,S=y.headers.get("PAYMENT-RESPONSE");if(S)try{let k=yt(S);k&&typeof k.transaction=="string"&&(f=k.transaction)}catch{}return{ok:!0,paid:!0,response:y,amountPaid:o.amount,network:o.network,txSignature:f}}catch(y){clearTimeout(p);let f=y;if(f?.name==="AbortError"){if(!g)return{ok:!1,reason:"timeout"};let S=await ct(d,o.network,s.solanaRpcUrl);return S.confirmed?{ok:!0,paid:!0,response:void 0,amountPaid:o.amount,network:o.network,txSignature:S.txSignature}:{ok:!1,reason:"payment_unconfirmed",detail:S.detail}}return{ok:!1,reason:"error",detail:f?.message??String(y)}}}};import{getAddress as kn}from"viem";var Cn={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]};async function In(){let t=globalThis.crypto??(await import("crypto")).webcrypto,e=new Uint8Array(32);return t.getRandomValues(e),"0x"+Array.from(e,n=>n.toString(16).padStart(2,"0")).join("")}async function Nn(t,e,n){if(typeof t.signTypedData!="function")throw new Error("EVM wallet does not support signTypedData");let r=Math.floor(Date.now()/1e3),s=String(r-600),a=String(r+(e.maxTimeoutSeconds??60)),o={from:t.address,to:e.payTo,value:e.amount,validAfter:s,validBefore:a,nonce:await In()},i=He[e.network.caip2];if(i===void 0)throw new Error(`unknown chain id for network ${e.network.caip2}`);let c=e.extra,u=await t.signTypedData({domain:{name:c.name,version:c.version,chainId:i,verifyingContract:kn(e.asset)},types:Cn,primaryType:"TransferWithAuthorization",message:o});return{payment:{x402Version:1,scheme:e.scheme,network:n,payload:{signature:u,authorization:o}},settlementProbe:{kind:"eip3009",from:o.from,nonce:o.nonce,asset:e.asset,chainId:i}}}async function wt(t,e,n){try{let r;for(let s of t.options){let a=s.network.family==="evm"&&!!e.evm||s.network.family==="svm"&&!!e.solana;if(s.scheme!=="exact"){a&&(r=s.scheme);continue}if(s.network.family==="evm"&&e.evm){let o=await e.evm;return await On(s,o,n)}if(s.network.family==="svm"&&e.solana){let o=await e.solana;return await Un(s,o,n)}}return r!==void 0?{ok:!1,reason:"merchant_rejected",detail:`v1 supports only the 'exact' scheme, got '${r}'`}:{ok:!1,reason:"unsupported_network"}}catch(r){return{ok:!1,reason:"error",detail:q(r)}}}async function On(t,e,n){if(n.maxAmountAtomic!==void 0&&BigInt(t.amount)>BigInt(n.maxAmountAtomic))return{ok:!1,reason:"budget_exceeded"};let r=t.extra??{},s=r.name,a=r.version;if(typeof s!="string"||s.length===0||typeof a!="string"||a.length===0)return{ok:!1,reason:"merchant_rejected",detail:"v1 challenge missing exact-scheme EIP-712 domain (extra.name / extra.version)"};let o=t.network.bare,{payment:i,settlementProbe:c}=await Nn(e,t,o);return{ok:!0,headerValue:Buffer.from(JSON.stringify(i),"utf8").toString("base64"),option:t,settlementProbe:c}}async function Un(t,e,n){if(n.maxAmountAtomic!==void 0&&BigInt(t.amount)>BigInt(n.maxAmountAtomic))return{ok:!1,reason:"budget_exceeded"};if(t.scheme!=="exact")return{ok:!1,reason:"merchant_rejected",detail:`v1 SVM supports only the 'exact' scheme, got '${t.scheme}'`};let r=t.extra??{};if(typeof r.feePayer!="string"||r.feePayer.length===0)return{ok:!1,reason:"merchant_rejected",detail:"v1 SVM challenge missing extra.feePayer (required as the transaction fee payer)"};let s=t.network.bare,a={x402Version:1,scheme:t.scheme,network:s,asset:t.asset,payTo:t.payTo,amount:t.amount,maxAmountRequired:t.amount,maxTimeoutSeconds:t.maxTimeoutSeconds??60,extra:r},i=await X().buildTransaction(a,e,n.solanaRpcUrl),c={x402Version:1,scheme:t.scheme,network:s,payload:{transaction:i.serialized}};return{ok:!0,headerValue:Buffer.from(JSON.stringify(c),"utf8").toString("base64"),option:t,settlementProbe:i.settlementProbe}}function Bn(t){let e=[];for(let n of t){if(!n||typeof n!="object")continue;let r=n,s=ke(String(r.network??""));s&&e.push({scheme:String(r.scheme??"exact"),network:s,amount:String(r.maxAmountRequired??r.amount??"0"),asset:String(r.asset??""),payTo:String(r.payTo??""),maxTimeoutSeconds:typeof r.maxTimeoutSeconds=="number"?r.maxTimeoutSeconds:void 0,extra:r.extra&&typeof r.extra=="object"?r.extra:void 0})}return e}var Lt={version:1,async parseChallenge(t){if(t.headers.get("payment-required"))return null;let e;try{e=await t.clone().json()}catch{return null}let n=Array.isArray(e.accepts)?e.accepts:[];if(n.length===0)return null;let r=Bn(n);return r.length===0?null:{x402Version:1,options:r}},async pay(t,e,n,r,s){let a,o=new AbortController,i=!1,c,u;try{let p=s.timeoutMs??15e3;a=setTimeout(()=>o.abort(),p);let g=await wt(n,r,s);if(!g.ok)return{ok:!1,reason:g.reason,detail:g.detail};let d=g.headerValue,x=g.option;u=x,c=g.settlementProbe;let l=new Headers(e.headers??void 0);l.set("X-PAYMENT",d);let P=e.signal!=null?AbortSignal.any([e.signal,o.signal]):o.signal,T={method:e.method,headers:l,signal:P};typeof e.body=="string"&&(T.body=e.body),i=!0,clearTimeout(a);let y=s.responseTimeoutMs??12e4;a=setTimeout(()=>o.abort(),y);let f=await fetch(t,T);return f.ok?{ok:!0,paid:!0,response:f,amountPaid:x.amount,network:x.network,txSignature:Dn(f)}:{ok:!1,...await Fe(f)}}catch(p){if(p instanceof Error&&p.name==="AbortError"){if(!i)return{ok:!1,reason:"timeout"};let g=await ct(c,u.network,s.solanaRpcUrl);return g.confirmed?{ok:!0,paid:!0,response:void 0,amountPaid:u.amount,network:u.network,txSignature:g.txSignature}:{ok:!1,reason:"payment_unconfirmed",detail:g.detail}}return{ok:!1,reason:"error",detail:q(p)}}finally{a!==void 0&&clearTimeout(a)}}};function Dn(t){let e=t.headers.get("x-payment-response")??t.headers.get("X-PAYMENT-RESPONSE");if(e)try{let n=JSON.parse(Buffer.from(e,"base64").toString("utf8")),r=n.transaction??n.txHash??n.transactionHash;return typeof r=="string"?r:void 0}catch{return}}import*as Wt from"tweetnacl";import{Keypair as ds,VersionedTransaction as fs,Transaction as gs}from"@solana/web3.js";var Vt=Symbol.for("x402:keypair");function xt(t){let e=t.evm;if(e&&typeof e.signMessage=="function"&&typeof e.address=="string")return{address:e.address,signMessage:e.signMessage};let n=t.solana;if(n){let r=n[Vt];if(r&&r.secretKey&&r.publicKey)return{publicKey:r.publicKey,signMessage:async s=>Wt.sign.detached(s,r.secretKey)}}return null}var Mn=[Kt,Lt];async function $n(t){let e=xt(t);if(!e)return fetch;try{return(await import("@x402/extensions/sign-in-with-x")).wrapFetchWithSIWx(fetch,e)}catch(n){return console.warn(`[x402] SIW-X unavailable \u2014 @x402/extensions failed to load; SIW-X merchants will not authenticate. ${q(n)}`),fetch}}async function Tt(t,e,n,r){if(e.body!==void 0&&e.body!==null&&typeof e.body!="string")return{ok:!1,reason:"error",detail:"payAndFetch requires a string body; non-string bodies (Buffer, FormData, URLSearchParams, ReadableStream) cannot be safely re-sent on the paid retry"};let s;try{s=await(await $n(n))(t,{...e})}catch(a){return{ok:!1,reason:"error",detail:q(a)}}if(s.status!==402)return{ok:!0,paid:!1,response:s};for(let a of Mn){let o=await a.parseChallenge(s.clone());if(o)return a.pay(t,e,o,n,r)}return{ok:!1,reason:"no_payment_options"}}async function Kn(t,e={},n){let r=await Ce(t,e);if(r.kind==="free")return{result:{ok:!0,paid:!1,response:r.response},tab:null};if(r.kind==="no_tab")return{result:{ok:!1,reason:"no_payment_options",detail:`no tab option offered (schemes: ${r.schemesOffered.join(", ")})`},tab:null};if(r.kind==="error")return{result:{ok:!1,reason:"error",detail:r.detail},tab:null};let{offer:s}=r,a=BigInt(Z(n.perUnitCap));if(BigInt(s.amountAtomic)>a)return{result:{ok:!1,reason:"budget_exceeded",detail:`seller quotes ${s.amountAtomic} atomic; perUnitCap allows ${a}`},tab:null};let o=n.tabs?.get(s.payTo);return(!o||!o.state.isOpen)&&(o=await dt({vault:n.vault,network:"solana:mainnet",seller:s.payTo,perUnitCap:n.perUnitCap,totalCap:n.totalCap,sessionDuration:n.sessionDuration,facilitatorUrl:n.facilitatorUrl}),n.tabs?.set(s.payTo,o)),{result:await Tt(t,e,{},{tab:o}),tab:o}}function Ln(t){return{counterparty:t.payTo,perRequest:{atomic:t.amountAtomic,human:de(t.amountAtomic)},asset:t.asset,network:{caip2:t.networkCaip2},scheme:"tab",settlement:{custody:"non-custodial",protection:"lock",settleOn:"close"},credit:null,...t.resourceUrl!==void 0?{resourceUrl:t.resourceUrl}:{}}}async function Vn(t,e={},n={}){let r=n.cache?.get(t);if(r)return{kind:"terms",terms:r};let s=await Ce(t,e,n.fetchImpl??fetch);if(s.kind!=="offer")return s;if(s.offer.asset!==We)return{kind:"error",detail:`tab offer asset is not USDC ("${s.offer.asset}"); refusing to render a human price`};let a=Ln(s.offer);return n.cache?.set(t,a),{kind:"terms",terms:a}}export{ve as DEFAULT_FACILITATOR_URL,ft as DEXTER_VAULT_PROGRAM_ID,rn as INSTRUCTIONS_SYSVAR_ID,nn as SECP256R1_PROGRAM_ID,pe as SessionScopeExceededError,Q as TabClosedError,me as UnsupportedNetworkError,de as atomicToHuman,Zt as buildRegisterSessionKeyInstruction,en as buildRevokeSessionKeyInstruction,tn as buildSecp256r1VerifyInstruction,Ht as buildVoucherMessage,Z as humanToAtomic,dt as openTab,Kn as payUrlWithTab,Ce as resolveTabOffer,Vn as resolveTabTerms,Xt as resumeTab,ut as sessionRegisterMessage,qt as sessionRevokeMessage,un as tabFromGrant,mt as voucherPayloadMessage,Xe as voucherToHeader};
|
|
6
|
+
`):null}}import ke from"tweetnacl";import{Connection as on,PublicKey as _e}from"@solana/web3.js";import{bytesToHex as cn}from"@noble/hashes/utils";import{fetchSessionAccount as ln,isSessionLive as un}from"@dexterai/vault/session";import{readVaultFull as mn}from"@dexterai/vault/reader";import{buildRegisterSessionKeyInstruction as tn,buildRevokeSessionKeyInstruction as nn,deriveSwigWalletAddress as sr}from"@dexterai/vault/instructions";import{buildSecp256r1VerifyInstruction as rn}from"@dexterai/vault/precompile";import{DEXTER_VAULT_PROGRAM_ID as gt,SECP256R1_PROGRAM_ID as sn,INSTRUCTIONS_SYSVAR_ID as an}from"@dexterai/vault/constants";var yt="solana:mainnet";async function pn(t){let e=t.facilitatorUrl??Pe,n=t.programId??gt,r=new _e(t.vaultPda),s=new _e(t.params.counterparty),a=Ge(t.perUnitCapAtomic);if(a<=0n)throw new Error(`perUnitCapAtomic must be > 0, got ${t.perUnitCapAtomic}`);let o=Ge(t.params.maxAmountAtomic),i=Ge(t.params.maxRevolvingCapacityAtomic),c=dn(t.sessionSecretKey),u=new _e(t.params.sessionPubkey).toBytes();if(!kt(c.publicKey,u))throw new Error(`tab_session_key_mismatch: the supplied secret derives ${new _e(c.publicKey).toBase58()} but params.sessionPubkey is ${t.params.sessionPubkey} \u2014 wrong key handed to this process`);let p=ke.randomBytes(32),d=ke.sign.detached(p,c.secretKey);if(!ke.sign.detached.verify(p,d,u))throw new Error("tab_session_key_mismatch: secret key failed the sign/verify self-check against params.sessionPubkey \u2014 the seed half does not sign for the granted pubkey");let f=mt({programId:n,vaultPda:r,sessionPubkey:c.publicKey,maxAmount:o,expiresAt:BigInt(t.params.expiresAtUnix),allowedCounterparty:s,nonce:t.params.nonce,maxRevolvingCapacity:i}),T=typeof t.connection=="string"?new on(t.connection,"confirmed"):t.connection,l=await ln(T,r,s,n);if(!l||l.version===0)throw new Error("tab_session_not_live: no live SessionAccount PDA for this (vault, counterparty) \u2014 revoked, expiry-swept, or never registered");if(!un(l))throw new Error(l.version!==1?`tab_session_not_live: SessionAccount has unsupported version ${l.version} \u2014 not a live v1 session`:`tab_session_not_live: SessionAccount is present but expired (expiresAt=${l.session.expiresAt})`);if(!kt(l.session.sessionPubkey,c.publicKey))throw new Error(`tab_session_pubkey_mismatch: the on-chain session carries ${new _e(l.session.sessionPubkey).toBase58()} \u2014 the grant this key belongs to was replaced by a newer registration`);if(l.session.maxAmount!==o||l.session.expiresAt!==t.params.expiresAtUnix||l.session.nonce!==t.params.nonce||l.session.maxRevolvingCapacity!==i)throw new Error(`tab_grant_params_stale: params disagree with the on-chain session scope (chain: maxAmount=${l.session.maxAmount} expiresAt=${l.session.expiresAt} nonce=${l.session.nonce} revolving=${l.session.maxRevolvingCapacity}; params: ${t.params.maxAmountAtomic}/${t.params.expiresAtUnix}/${t.params.nonce}/${t.params.maxRevolvingCapacityAtomic}) \u2014 refresh the grant hand-off`);let P=l.session.spent>l.session.crystallizedCumulative?l.session.spent:l.session.crystallizedCumulative;if(P>=o)throw new Error(`tab_exhausted: on-chain frontier ${P} has consumed the session cap ${o} \u2014 no voucher can strictly exceed it; open a new grant`);let x=t.sellerUrl??t.params.counterparty,y=BigInt(Math.floor(Math.random()*4294967295)),g=Xe({vaultPda:r,sellerUrl:x,nonce:y}),S=cn(g),k=t.swigAddress;if(!k){let O=await mn(T,r);if(!O.exists||!O.swigAddress)throw new Error(`tab_vault_unreadable: vault ${r.toBase58()} has no readable swig_address on chain \u2014 pass options.swigAddress explicitly`);k=O.swigAddress}await dt(e,k,o,yt,t.params.counterparty);let U={channelId:S,maxAmountAtomic:t.params.maxAmountAtomic,revolvingCapacityAtomic:t.params.maxRevolvingCapacityAtomic,expiresAtUnix:t.params.expiresAtUnix,allowedCounterparty:t.params.counterparty},K=vt({publicKey:c.publicKey,privateKey:c.secretKey},U,f),$={network:yt,swigAddress:k,vaultPda:r.toBase58(),authorizeSession:async()=>{throw new Error("grant_tab_no_passkey: a grant-held tab cannot authorize sessions \u2014 session birth requires the wallet owner's passkey ceremony")},signWithSession:async(O,D)=>Pt(O,D,g),signOpenTab:async O=>O.registration,signCloseTab:async()=>{throw new Error("grant_tab_cannot_revoke: session revocation is passkey-signed and belongs to the wallet owner's surfaces \u2014 a grant-held tab closes settle-only")}};return new Re({vault:$,network:yt,seller:x,counterparty:t.params.counterparty,session:K,channelIdHex:S,channelIdBytes:g,perUnitCapAtomic:a,totalCapAtomic:o,expiresAtUnix:t.params.expiresAtUnix,facilitatorUrl:e,initialCumulativeAtomic:P,closeMode:"settle-only"})}function dn(t){if(t.length===64)return ke.sign.keyPair.fromSecretKey(t);if(t.length===32)return ke.sign.keyPair.fromSeed(t);throw new Error(`tab_session_key_invalid: expected a 64-byte nacl secretKey or a 32-byte ed25519 seed, got ${t.length} bytes`)}function kt(t,e){if(t.length!==e.length)return!1;let n=0;for(let r=0;r<t.length;r++)n|=t[r]^e[r];return n===0}import{PublicKey as hn}from"@solana/web3.js";var Ct=[{caip2:"eip155:8453",bare:"base",family:"evm"},{caip2:"eip155:1",bare:"ethereum",family:"evm"},{caip2:"eip155:137",bare:"polygon",family:"evm"},{caip2:"eip155:42161",bare:"arbitrum",family:"evm"},{caip2:"eip155:10",bare:"optimism",family:"evm"},{caip2:"eip155:43114",bare:"avalanche",family:"evm"},{caip2:"eip155:56",bare:"bsc",family:"evm"},{caip2:"solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",bare:"solana",family:"svm"}],fn=new Map(Ct.map(t=>[t.caip2.toLowerCase(),t])),gn=new Map(Ct.map(t=>[t.bare.toLowerCase(),t]));function Ce(t){if(!t)return null;let e=t.toLowerCase(),n=fn.get(e)||gn.get(e);return n?{caip2:n.caip2,bare:n.bare,family:n.family}:null}function ht(t){let e=t.replace(/-/g,"+").replace(/_/g,"/"),n=e+"=".repeat((4-(e.length%4||4))%4);return JSON.parse(Buffer.from(n,"base64").toString("utf8"))}function yn(t){let e=[];for(let n of t){if(!n||typeof n!="object")continue;let r=n,s=Ce(String(r.network??""));s&&e.push({scheme:String(r.scheme??"exact"),network:s,amount:String(r.amount??r.maxAmountRequired??"0"),asset:String(r.asset??""),payTo:String(r.payTo??""),maxTimeoutSeconds:typeof r.maxTimeoutSeconds=="number"?r.maxTimeoutSeconds:void 0,extra:r.extra&&typeof r.extra=="object"?r.extra:void 0})}return e}async function ze(t){let e=t.headers.get("payment-required");if(!e)return null;let n;try{n=ht(e)}catch{return null}let r=Array.isArray(n.accepts)?n.accepts:[];return r.length===0?null:{x402Version:2,options:yn(r),resourceUrl:n.resource&&typeof n.resource=="object"?String(n.resource.url??""):void 0}}async function Ie(t,e={},n=fetch){let r={method:e.method??"GET",headers:e.headers};typeof e.body=="string"&&(r.body=e.body);let s;try{s=await n(t,r)}catch(i){return{kind:"error",detail:`probe failed: ${i?.message??String(i)}`}}if(s.status!==402)return s.ok?{kind:"free",response:s}:{kind:"error",detail:`probe returned HTTP ${s.status}`};let a=await ze(s);if(!a)return{kind:"error",detail:"the 402 carries no x402 v2 PAYMENT-REQUIRED challenge"};let o=a.options.find(i=>i.scheme==="tab"&&i.network.family==="svm");if(!o)return{kind:"no_tab",schemesOffered:a.options.map(i=>i.scheme)};try{new hn(o.payTo)}catch{return{kind:"error",detail:`tab option payTo is not a valid Solana pubkey: "${o.payTo}"`}}return{kind:"offer",offer:{payTo:o.payTo,amountAtomic:o.amount,asset:o.asset,networkCaip2:o.network.caip2,resourceUrl:a.resourceUrl}}}var Ne="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",Qe="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",Ze="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z",te=Ne,Oe=Qe,Ue=Ze,ne="eip155:8453",ge="eip155:84532",ye="eip155:42161",he="eip155:137",Ae="eip155:10",be="eip155:43114",Se="eip155:56",we="eip155:1187947933",Te="eip155:324705682",xe="eip155:1",re=ne,et=ge,Be=ye,De=he,Me=Ae,$e=be,Ke=Se,Le=we,Ve=Te,We=xe,qe="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",It="4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU",Nt="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",At="0x55d398326f99059fF775485246999027B3197955",tt="0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",nt={[Se]:tt,[ne]:Nt,[ge]:"0x036CbD53842c5426634e7929541eC2318f3dCF7e",[ye]:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831",[he]:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",[Ae]:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",[be]:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",[we]:"0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",[Te]:"0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",[xe]:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},rt={[At]:{symbol:"USDT",decimals:18},[tt]:{symbol:"USDC",decimals:18}};var G="0x000000000022D473030F116dDEE9F6B43aC78BA3",He="0x402085c248EeA27D92E8b30b2C58ed07f9E20001",Fe={[Se]:56,[ne]:8453,[ge]:84532,[ye]:42161,[he]:137,[Ae]:10,[be]:43114,[we]:1187947933,[Te]:324705682,[xe]:1},se={[Ne]:"https://api.dexter.cash/api/solana/rpc",[Qe]:"https://api.devnet.solana.com",[Ze]:"https://api.testnet.solana.com"},B={[Se]:"https://api.dexter.cash/api/evm/bsc/rpc",[ne]:"https://api.dexter.cash/api/base/rpc",[ge]:"https://sepolia.base.org",[ye]:"https://api.dexter.cash/api/evm/arbitrum/rpc",[he]:"https://api.dexter.cash/api/evm/polygon/rpc",[Ae]:"https://api.dexter.cash/api/evm/optimism/rpc",[be]:"https://api.dexter.cash/api/evm/avalanche/rpc",[we]:"https://skale-base.skalenodes.com/v1/base",[Te]:"https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",[xe]:"https://eth.llamarpc.com"};var I=class t extends Error{code;details;constructor(e,n,r){super(n),this.name="X402Error",this.code=e,this.details=r,Object.setPrototypeOf(this,t.prototype)}};import{PublicKey as ae,Connection as bt,TransactionMessage as An,VersionedTransaction as bn,ComputeBudgetProgram as Ot}from"@solana/web3.js";import{getAssociatedTokenAddress as St,getAccount as Sn,createTransferCheckedInstruction as wn,getMint as Tn,TOKEN_PROGRAM_ID as Ut,TOKEN_2022_PROGRAM_ID as st}from"@solana/spl-token";var xn=12e3,En=1;function oe(t){if(!t||typeof t!="object")return!1;let e=t;return"publicKey"in e&&"signTransaction"in e&&typeof e.signTransaction=="function"}var at=class{name="Solana";networks=[te,Oe,Ue];config;log;constructor(e={}){this.config=e,this.log=e.verbose?console.log.bind(console,"[x402:solana]"):()=>{}}canHandle(e){return!!(this.networks.includes(e)||e==="solana"||e==="solana-devnet"||e==="solana-testnet"||e.startsWith("solana:"))}getDefaultRpcUrl(e){return this.config.rpcUrls?.[e]?this.config.rpcUrls[e]:se[e]?se[e]:e==="solana"?se[te]:e==="solana-devnet"?se[Oe]:e==="solana-testnet"?se[Ue]:se[te]}getAddress(e){return oe(e)?e.publicKey?.toBase58()??null:null}isConnected(e){return oe(e)?e.publicKey!==null:!1}async getBalance(e,n,r){if(!oe(n)||!n.publicKey)return 0;let s=r||this.getDefaultRpcUrl(e.network),a=new bt(s,"confirmed"),o=new ae(n.publicKey.toBase58()),i=new ae(e.asset);try{let u=(await a.getAccountInfo(i,"confirmed"))?.owner.toBase58()===st.toBase58()?st:Ut,p=await St(i,o,!1,u),d=await Sn(a,p,void 0,u),f=e.extra?.decimals??6;return Number(d.amount)/Math.pow(10,f)}catch(c){if(c&&typeof c=="object"&&"name"in c&&(c.name==="TokenAccountNotFoundError"||c.name==="TokenInvalidAccountOwnerError"))return 0;throw c}}async buildTransaction(e,n,r){if(!oe(n))throw new Error("Invalid Solana wallet");if(!n.publicKey)throw new Error("Wallet not connected");let s=r||this.getDefaultRpcUrl(e.network),a=new bt(s,"confirmed"),o=new ae(n.publicKey.toBase58()),{payTo:i,asset:c,extra:u}=e,p=e.amount??e.maxAmountRequired;if(!p)throw new Error("Missing amount in payment requirements");if(!u?.feePayer)throw new Error("Missing feePayer in payment requirements");let d=new ae(u.feePayer),f=new ae(c),T=new ae(i);this.log("Building transaction:",{from:o.toBase58(),to:i,amount:p,asset:c,feePayer:u.feePayer});let l=[];l.push(Ot.setComputeUnitLimit({units:xn})),l.push(Ot.setComputeUnitPrice({microLamports:En}));let P=await a.getAccountInfo(f,"confirmed");if(!P)throw new Error(`Token mint ${c} not found`);let x=P.owner.toBase58()===st.toBase58()?st:Ut,y=await Tn(a,f,void 0,x);typeof u?.decimals=="number"&&y.decimals!==u.decimals&&this.log(`Decimals mismatch: requirements say ${u.decimals}, mint says ${y.decimals}`);let g=await St(f,o,!1,x),S=await St(f,T,!0,x);if(!await a.getAccountInfo(g,"confirmed"))throw new Error(`No token account found for ${c}. Please ensure you have USDC in your wallet.`);if(!await a.getAccountInfo(S,"confirmed"))throw new Error(`Seller token account not found. The seller (${i}) must have a USDC account.`);let K=BigInt(p);l.push(wn(g,f,S,o,K,y.decimals,[],x));let{blockhash:$}=await a.getLatestBlockhash("confirmed"),O=new An({payerKey:d,recentBlockhash:$,instructions:l}).compileToV0Message(),D=new bn(O),h=await n.signTransaction(D);return this.log("Transaction signed successfully"),{serialized:Buffer.from(h.serialize()).toString("base64"),settlementProbe:{kind:"solana",sourceAta:g.toBase58(),destinationAta:S.toBase58(),asset:c,amount:p,blockhash:$}}}async confirmSettlement(e,n){if(e.kind!=="solana")throw new Error(`SolanaAdapter.confirmSettlement cannot handle probe kind "${e.kind}"`);let r=new bt(n,"confirmed"),s=new ae(e.destinationAta),a=await r.getSignaturesForAddress(s,{limit:25});if(a.length===0)return{settled:!1};let o=BigInt(e.amount);for(let i of a){if(i.err)continue;let c=await r.getTransaction(i.signature,{commitment:"confirmed",maxSupportedTransactionVersion:0});if(!c?.meta)continue;let u=c.transaction.message.getAccountKeys().keySegments().flat(),p=c.meta.preTokenBalances??[],d=c.meta.postTokenBalances??[];for(let f of d){if(f.mint!==e.asset)continue;let T=u[f.accountIndex];if(!T||!T.equals(s))continue;let l=p.find(y=>y.accountIndex===f.accountIndex),P=BigInt(l?.uiTokenAmount.amount??"0");if(BigInt(f.uiTokenAmount.amount??"0")-P===o)return{settled:!0,txSignature:i.signature}}}return{settled:!1}}};function X(t){return new at(t)}var vn={PermitWitnessTransferFrom:[{name:"permitted",type:"TokenPermissions"},{name:"spender",type:"address"},{name:"nonce",type:"uint256"},{name:"deadline",type:"uint256"},{name:"witness",type:"Witness"}],TokenPermissions:[{name:"token",type:"address"},{name:"amount",type:"uint256"}],Witness:[{name:"to",type:"address"},{name:"validAfter",type:"uint256"}]},Bt=BigInt("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");function ie(t){if(!t||typeof t!="object")return!1;let e=t;return"address"in e&&typeof e.address=="string"&&e.address.startsWith("0x")}var ot=class{name="EVM";networks=[Ke,re,et,We,Be,De,Me,$e,Le,Ve];config;log;constructor(e={}){this.config=e,this.log=e.verbose?console.log.bind(console,"[x402:evm]"):()=>{}}canHandle(e){return!!(this.networks.includes(e)||e==="base"||e==="bsc"||e==="ethereum"||e==="arbitrum"||e==="polygon"||e==="optimism"||e==="avalanche"||e==="skale-base"||e==="skale-base-sepolia"||e.startsWith("eip155:"))}getDefaultRpcUrl(e){return this.config.rpcUrls?.[e]?this.config.rpcUrls[e]:B[e]?B[e]:e==="base"?B[re]:e==="bsc"?B[Ke]:e==="ethereum"?B[We]:e==="arbitrum"?B[Be]:e==="polygon"?B[De]:e==="optimism"?B[Me]:e==="avalanche"?B[$e]:e==="skale-base"?B[Le]:e==="skale-base-sepolia"?B[Ve]:B[re]}getAddress(e){return ie(e)?e.address:null}isConnected(e){return ie(e)?!!e.address:!1}getChainId(e){if(Fe[e])return Fe[e];if(e.startsWith("eip155:")){let n=e.split(":")[1];return parseInt(n,10)}return e==="base"?8453:e==="bsc"?56:e==="ethereum"?1:e==="arbitrum"?42161:8453}async getBalance(e,n,r){if(!ie(n)||!n.address)return 0;let s=r||this.getDefaultRpcUrl(e.network);try{let a=this.encodeBalanceOf(n.address),o=await fetch(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_call",params:[{to:e.asset,data:a},"latest"]})});if(!o.ok)throw new Error(`RPC request failed: ${o.status}`);let i=await o.json();if(i.error)throw new Error(`RPC error: ${JSON.stringify(i.error)}`);if(!i.result||i.result==="0x")return 0;let c=BigInt(i.result),u=e.extra?.decimals??6;return Number(c)/Math.pow(10,u)}catch(a){throw a}}encodeBalanceOf(e){let n="0x70a08231",r=e.slice(2).toLowerCase().padStart(64,"0");return n+r}async confirmSettlement(e,n){if(e.kind==="eip3009"){let r="0xe94a0102",s=e.from.slice(2).toLowerCase().padStart(64,"0"),a=e.nonce.slice(2).toLowerCase().padStart(64,"0"),o=r+s+a,i=await this.ethCall(n,e.asset,o);return{settled:BigInt(i)!==0n}}if(e.kind==="permit2"){let r="0x4fe02b44",s=BigInt(e.nonce),a=s>>8n,o=s&0xffn,i=e.from.slice(2).toLowerCase().padStart(64,"0"),c=a.toString(16).padStart(64,"0"),u=r+i+c,p=await this.ethCall(n,G,u);return{settled:(BigInt(p)>>o&1n)===1n}}throw new Error(`EvmAdapter.confirmSettlement cannot handle probe kind "${e.kind}"`)}async ethCall(e,n,r){let s=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_call",params:[{to:n,data:r},"latest"]})});if(!s.ok)throw new Error(`RPC request failed: ${s.status}`);let a=await s.json();if(a.error)throw new Error(`RPC error: ${JSON.stringify(a.error)}`);if(!a.result||a.result==="0x")throw new Error("RPC returned an empty result");return a.result}async buildTransaction(e,n,r){if(!ie(n))throw new Error("Invalid EVM wallet");if(!n.address)throw new Error("Wallet not connected");if(e.scheme==="exact-approval")return this.buildApprovalTransaction(e,n,r);if(e.extra?.assetTransferMethod==="permit2")return this.buildPermit2Transaction(e,n,r);let{payTo:s,asset:a,extra:o}=e,i=e.amount??e.maxAmountRequired;if(!i)throw new Error("Missing amount in payment requirements");this.log("Building EVM transaction:",{from:n.address,to:s,amount:i,asset:a,network:e.network});let c=this.getChainId(e.network),u={name:o?.name??"USD Coin",version:o?.version??"2",chainId:BigInt(c),verifyingContract:a},p={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]},d=new Uint8Array(32);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(d);let f="0x"+[...d].map(g=>g.toString(16).padStart(2,"0")).join(""),T=Math.floor(Date.now()/1e3),l={from:n.address,to:s,value:i,validAfter:String(T-600),validBefore:String(T+(e.maxTimeoutSeconds||60)),nonce:f},P={from:n.address,to:s,value:BigInt(i),validAfter:BigInt(T-600),validBefore:BigInt(T+(e.maxTimeoutSeconds||60)),nonce:f};if(!n.signTypedData)throw new Error("Wallet does not support signTypedData (EIP-712)");let x=await n.signTypedData({domain:u,types:p,primaryType:"TransferWithAuthorization",message:P});return this.log("EIP-712 signature obtained"),{serialized:JSON.stringify({authorization:l,signature:x}),signature:x,settlementProbe:{kind:"eip3009",from:n.address,nonce:f,asset:a,chainId:c}}}async buildApprovalTransaction(e,n,r){let{payTo:s,asset:a,extra:o}=e,i=e.amount??e.maxAmountRequired;if(!i)throw new Error("Missing amount in payment requirements");let c=o?.facilitatorContract;if(!c)throw new Error("exact-approval scheme requires extra.facilitatorContract from the facilitator. The /supported endpoint should provide this.");if(!n.signTypedData)throw new Error("Wallet does not support signTypedData (EIP-712)");this.log("Building approval-based transaction:",{from:n.address,to:s,amount:i,asset:a,network:e.network,facilitatorContract:c});let u=r||this.getDefaultRpcUrl(e.network),p=o?.fee??"0",d=BigInt(i)+BigInt(p),f=await this.readAllowance(u,a,n.address,c);if(f<d){if(!n.sendTransaction)throw new Error("BSC payments require a wallet that supports sendTransaction for the one-time token approval. Use createEvmKeypairWallet() or a browser wallet with transaction support.");let D=this.calculateApprovalAmount(i,p,o?.approvalStrategy);this.log(`Approving ${D} for ${c} (current allowance: ${f})`);let h=await n.sendTransaction({to:a,data:this.encodeApprove(c,D),value:0n});this.log(`Approval tx sent: ${h}`),await this.waitForReceipt(u,h),this.log("Approval confirmed")}else this.log("Sufficient allowance, skipping approval");let T=new Uint8Array(16);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(T);let l=[...T].reduce((D,h)=>D*256n+BigInt(h),0n).toString(),P=new Uint8Array(32);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(P);let x="0x"+[...P].map(D=>D.toString(16).padStart(2,"0")).join(""),g=Math.floor(Date.now()/1e3)+(e.maxTimeoutSeconds||300),S=o?.eip712Domain,k=S?{name:S.name,version:S.version,chainId:BigInt(S.chainId),verifyingContract:S.verifyingContract}:{name:"DexterBSCFacilitator",version:"1",chainId:BigInt(this.getChainId(e.network)),verifyingContract:c},U=o?.eip712Types??{Payment:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"token",type:"address"},{name:"amount",type:"uint256"},{name:"fee",type:"uint256"},{name:"nonce",type:"uint256"},{name:"deadline",type:"uint256"},{name:"paymentId",type:"bytes32"}]},K={from:n.address,to:s,token:a,amount:BigInt(i),fee:BigInt(p),nonce:BigInt(l),deadline:BigInt(g),paymentId:x},$=await n.signTypedData({domain:k,types:U,primaryType:"Payment",message:K});this.log("EIP-712 Payment signature obtained");let O={from:n.address,to:s,token:a,amount:i,fee:p,nonce:l,deadline:g,paymentId:x,signature:$};return{serialized:JSON.stringify(O),signature:$}}async buildPermit2Transaction(e,n,r){let{payTo:s,asset:a}=e,o=e.amount??e.maxAmountRequired;if(!o)throw new Error("Missing amount in payment requirements");if(!n.signTypedData)throw new Error("Wallet does not support signTypedData (EIP-712)");this.log("Building Permit2 transaction:",{from:n.address,to:s,amount:o,asset:a,network:e.network});let i=r||this.getDefaultRpcUrl(e.network),c=await this.readAllowance(i,a,n.address,G),u;if(c<BigInt(o)){let k=this.encodeApprove(G,Bt);if(n.signTransaction){this.log(`Signing Permit2 approval for relay (current allowance: ${c})`);let U=this.getChainId(e.network),K=await this.readGasPrice(i),$=await this.readNonce(i,n.address),O=await n.signTransaction({to:a,data:k,chainId:U,gas:50000n,gasPrice:K,nonce:$});u={erc20ApprovalGasSponsoring:{info:{from:n.address,asset:a,spender:G,amount:Bt.toString(),signedTransaction:O,version:"1"}}},this.log("Permit2 approval signed for facilitator relay")}else if(n.sendTransaction){this.log(`Approving Permit2 directly (current allowance: ${c})`);let U=await n.sendTransaction({to:a,data:k,value:0n});this.log(`Permit2 approval tx sent: ${U}`),await this.waitForReceipt(i,U),this.log("Permit2 approval confirmed")}else throw new Error("Permit2 payments require a wallet that supports signTransaction or sendTransaction for the one-time Permit2 approval. Use createEvmKeypairWallet() or a browser wallet with transaction support.")}else this.log("Sufficient Permit2 allowance, skipping approval");let p=new Uint8Array(32);(globalThis.crypto??(await import("crypto")).webcrypto).getRandomValues(p);let d=[...p].reduce((k,U)=>k*256n+BigInt(U),0n),f=Math.floor(Date.now()/1e3),T=f-600,l=f+(e.maxTimeoutSeconds||300),P=this.getChainId(e.network),x={name:"Permit2",chainId:BigInt(P),verifyingContract:G},y={permitted:{token:a,amount:BigInt(o)},spender:He,nonce:d,deadline:BigInt(l),witness:{to:s,validAfter:BigInt(T)}},g=await n.signTypedData({domain:x,types:vn,primaryType:"PermitWitnessTransferFrom",message:y});this.log("Permit2 PermitWitnessTransferFrom signature obtained");let S={signature:g,permit2Authorization:{from:n.address,permitted:{token:a,amount:o},spender:He,nonce:d.toString(),deadline:String(l),witness:{to:s,validAfter:String(T)}}};return{serialized:JSON.stringify(S),signature:g,extensions:u,settlementProbe:{kind:"permit2",from:n.address,nonce:d.toString(),chainId:P}}}async readAllowance(e,n,r,s){let a="0xdd62ed3e",o=r.slice(2).toLowerCase().padStart(64,"0"),i=s.slice(2).toLowerCase().padStart(64,"0"),c=a+o+i;try{let p=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_call",params:[{to:n,data:c},"latest"]})})).json();return p.error||!p.result||p.result==="0x"?0n:BigInt(p.result)}catch{return 0n}}encodeApprove(e,n){let r="0x095ea7b3",s=e.slice(2).toLowerCase().padStart(64,"0"),a=n.toString(16).padStart(64,"0");return r+s+a}async waitForReceipt(e,n,r=3e4){let s=Date.now();for(;Date.now()-s<r;){try{let o=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_getTransactionReceipt",params:[n]})})).json();if(o.result){if(o.result.status==="0x0")throw new Error(`Approval transaction reverted: ${n}`);return}}catch(a){if(a instanceof Error&&a.message.includes("reverted"))throw a}await new Promise(a=>setTimeout(a,2e3))}throw new Error(`Approval transaction receipt timeout after ${r}ms: ${n}`)}async readGasPrice(e){try{let r=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_gasPrice",params:[]})})).json();return r.result?BigInt(r.result):50000000n}catch{return 50000000n}}async readNonce(e,n){try{let s=await(await fetch(e,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({jsonrpc:"2.0",id:1,method:"eth_getTransactionCount",params:[n,"latest"]})})).json();return s.result?parseInt(s.result,16):0}catch{return 0}}calculateApprovalAmount(e,n,r){let s=BigInt(e)+BigInt(n);if(!r||r.mode==="exact")return s;let a=BigInt(r.defaultMultiple??10),o=s*a;if(r.maxCapUsd){let i=this.inferDecimals(e),c=BigInt(Math.floor(r.maxCapUsd*Math.pow(10,i)));if(o>c)return c}if(r.exactAboveUsd){let i=this.inferDecimals(e),c=BigInt(Math.floor(r.exactAboveUsd*Math.pow(10,i)));if(BigInt(e)>c)return s}return o}inferDecimals(e){return e.length>12?18:6}};function Ee(t){return new ot(t)}function wt(t){if(t===qe||t===It)return!0;let e=t.toLowerCase();for(let n of Object.values(nt))if(n.toLowerCase()===e)return!0;for(let n of Object.keys(rt))if(n.toLowerCase()===e)return!0;return!1}function Pn(t){return{[Ne]:"Solana",[Qe]:"Solana Devnet",[Ze]:"Solana Testnet",solana:"Solana","solana-devnet":"Solana Devnet","solana-testnet":"Solana Testnet",[ne]:"Base",[ge]:"Base Sepolia",[xe]:"Ethereum",[ye]:"Arbitrum",[he]:"Polygon",[Ae]:"Optimism",[be]:"Avalanche",[Se]:"BSC",[we]:"SKALE Base",[Te]:"SKALE Base Sepolia",base:"Base","base-sepolia":"Base Sepolia",ethereum:"Ethereum",arbitrum:"Arbitrum",polygon:"Polygon",optimism:"Optimism",avalanche:"Avalanche",bsc:"BSC","skale-base":"SKALE Base","skale-base-sepolia":"SKALE Base Sepolia"}[t]||t}function Dt(t,e){let n=Pn(t);return n===t?e:n}async function Rn(t,e){if(typeof t=="string")return[t,e];if(t instanceof URL)return[t.href,e];let n=t,r=new Headers(n.headers);e?.headers&&new Headers(e.headers).forEach((o,i)=>r.set(i,o));let s={method:e?.method??n.method,headers:r,signal:e?.signal??n.signal,redirect:e?.redirect??n.redirect,credentials:e?.credentials??n.credentials},a=(s.method??"GET").toUpperCase();return e&&"body"in e?s.body=e.body:a!=="GET"&&a!=="HEAD"&&n.body&&(s.body=await n.arrayBuffer()),[n.url,s]}var _n=new WeakMap;function Mt(t){let{adapters:e=[X({verbose:t.verbose}),Ee({verbose:t.verbose})],wallets:n,wallet:r,preferredNetwork:s,rpcUrls:a={},maxAmountAtomic:o,fetch:i=globalThis.fetch,verbose:c=!1,accessPass:u,onPaymentRequired:p,onPaymentDispatched:d,maxRetries:f=0,retryDelayMs:T=500}=t,l=c?console.log.bind(console,"[x402]"):()=>{};async function P(h,w){let E;for(let A=0;A<=f;A++)try{let v=await i(h,w);if(v.status>=502&&v.status<=504&&A<f){l(`Retry ${A+1}/${f}: server returned ${v.status}`),await new Promise(R=>setTimeout(R,T*Math.pow(2,A)));continue}return v}catch(v){E=v,A<f&&(l(`Retry ${A+1}/${f}: ${v instanceof Error?v.message:"network error"}`),await new Promise(R=>setTimeout(R,T*Math.pow(2,A))))}throw E}let x=new Map;function y(h){try{let w=new URL(h).host,E=x.get(w);if(E&&E.expiresAt>Date.now()/1e3+10)return E.jwt;E&&x.delete(w)}catch{}return null}function g(h,w){try{let E=new URL(h).host,A=w.split(".");if(A.length===3){let v=JSON.parse(atob(A[1].replace(/-/g,"+").replace(/_/g,"/"))),R=Math.floor(Date.now()/1e3),_=R+86400,L=Math.min(typeof v.exp=="number"?v.exp:R,_);x.set(E,{jwt:w,expiresAt:L}),l("Access pass cached for",E,"| expires:",new Date(L*1e3).toISOString())}}catch{l("Failed to cache access pass")}}let S=n||{};r&&!S.solana&&oe(r)&&(S.solana=r),r&&!S.evm&&ie(r)&&(S.evm=r);function k(h){let w=[];for(let E of h){let A=E.scheme??"exact";if(A!=="exact"&&A!=="exact-approval")continue;let v=e.find(_=>_.canHandle(E.network));if(!v)continue;let R;v.name==="Solana"?R=S.solana:v.name==="EVM"&&(R=S.evm),R&&v.isConnected(R)&&w.push({accept:E,adapter:v,wallet:R})}if(w.length===0)return null;if(s){let E=w.find(A=>A.accept.network===s);if(E)return E}return w[0]}function U(h,w){return Dt(h,w)}function K(h,w){return a[h]||w.getDefaultRpcUrl(h)}async function $(h,w,E,A,v){let R="";if(u?.preferTier&&A.tiers){let m=A.tiers.find(b=>b.id===u.preferTier);if(m){if(u.maxSpend&&parseFloat(m.price)>parseFloat(u.maxSpend))throw new I("access_pass_exceeds_max_spend",`Access pass tier "${m.id}" costs $${m.price}, exceeds max spend $${u.maxSpend}`);R=`tier=${m.id}`}}else if(u?.preferDuration&&A.ratePerHour)R=`duration=${u.preferDuration}`;else if(A.tiers&&A.tiers.length>0){let m=A.tiers[0];if(u?.maxSpend&&parseFloat(m.price)>parseFloat(u.maxSpend))throw new I("access_pass_exceeds_max_spend",`Cheapest access pass costs $${m.price}, exceeds max spend $${u?.maxSpend}`);R=`tier=${m.id}`}let _=R?v.includes("?")?`${v}&${R}`:`${v}?${R}`:v;l("Purchasing access pass:",R||"default tier");let L=E.headers.get("PAYMENT-REQUIRED");if(!L)return null;let M;try{M=JSON.parse(atob(L))}catch{return null}let N=k(M.accepts);if(!N)return null;let{accept:C,adapter:W,wallet:ce}=N;if(W.name==="Solana"&&!C.extra?.feePayer)return null;let H=C.extra?.decimals??(wt(C.asset)?6:void 0);if(typeof H!="number")return null;let ve=C.amount??C.maxAmountRequired;if(!ve)return null;let F=K(C.network,W);try{let m=await W.getBalance(C,ce,F),b=Number(ve)/Math.pow(10,H);if(m<b){let ut=U(C.network,W.name);throw new I("insufficient_balance",`Insufficient balance for access pass on ${ut}. Have $${m.toFixed(4)}, need $${b.toFixed(4)}`)}}catch(m){if(m instanceof I)throw m}let j=await W.buildTransaction(C,ce,F),le;W.name==="EVM"?le=JSON.parse(j.serialized):le={transaction:j.serialized};let Y=typeof h=="string"?h:h instanceof URL?h.href:h.url,ue=M.resource;if(typeof M.resource=="string")try{let m=new URL(M.resource,Y);["http:","https:"].includes(m.protocol)&&(ue=m.toString())}catch{}else if(M.resource&&typeof M.resource=="object"&&"url"in M.resource){let m=M.resource;try{let b=new URL(m.url,Y);["http:","https:"].includes(b.protocol)&&(ue={...m,url:b.toString()})}catch{}}let Je={x402Version:C.x402Version??2,resource:ue,accepted:C,payload:le};j.extensions&&(Je.extensions=j.extensions);let J=btoa(JSON.stringify(Je)),z=await i(_,{...w,method:"POST",headers:{...w?.headers||{},"Content-Type":"application/json","PAYMENT-SIGNATURE":J}});if(!z.ok)return l("Pass purchase failed:",z.status),null;let V=z.headers.get("ACCESS-PASS");return V&&(g(v,V),l("Access pass purchased and cached")),z}async function O(h,w){let E=h;if(l("Making request:",E),u){let m=y(E);if(m){l("Using cached access pass");let b=await i(h,{...w,headers:{...w?.headers||{},Authorization:`Bearer ${m}`}});if(b.status!==401&&b.status!==402)return b;l("Cached pass rejected (status",b.status,"), purchasing new pass");try{x.delete(new URL(E).host)}catch{}}}let A=await P(h,w);if(A.status!==402)return A;l("Received 402 Payment Required");let v=A.headers.get("X-ACCESS-PASS-TIERS");if(u&&v){l("Server offers access passes, purchasing...");try{let m=JSON.parse(atob(v)),b=await $(h,w,A,m,E);if(b)return b}catch(m){l("Access pass purchase failed, falling back to per-request payment:",m)}}let R=A.headers.get("PAYMENT-REQUIRED");if(!R)throw new I("missing_payment_required_header","Server returned 402 but no PAYMENT-REQUIRED header");let _;try{let m=atob(R);_=JSON.parse(m)}catch{throw new I("invalid_payment_required","Failed to decode PAYMENT-REQUIRED header")}l("Payment requirements:",_);let L=A.headers.get("X-Quote-Hash");L&&l("Quote hash received:",L);let M=k(_.accepts);if(!M){let m=_.accepts.map(b=>b.network).join(", ");throw new I("no_matching_payment_option",`No connected wallet for any available network: ${m}`)}let{accept:N,adapter:C,wallet:W}=M;if(l(`Using ${C.name} for ${N.network}`),C.name==="Solana"&&!N.extra?.feePayer)throw new I("missing_fee_payer","Solana payment option missing feePayer in extra");let ce=N.extra?.decimals??(wt(N.asset)?6:void 0);if(typeof ce!="number")throw new I("missing_decimals","Payment option missing decimals - provide in extra or use a known stablecoin");let H=N.amount??N.maxAmountRequired;if(!H)throw new I("missing_amount","Payment option missing amount");if(o&&BigInt(H)>BigInt(o))throw new I("amount_exceeds_max",`Payment amount ${H} exceeds maximum ${o}`);let ve=K(N.network,C);l("Checking balance...");try{let m=await C.getBalance(N,W,ve),b=Number(H)/Math.pow(10,ce);if(m<b){let ut=U(N.network,C.name);throw new I("insufficient_balance",`Insufficient balance on ${ut}. Have $${m.toFixed(4)}, need $${b.toFixed(4)}`)}l(`Balance OK: $${m.toFixed(4)} >= $${b.toFixed(4)}`)}catch(m){if(m instanceof I)throw m;l("Balance check failed (RPC error), proceeding with transaction attempt")}if(p&&!await p(N))throw new I("payment_rejected","Payment rejected by onPaymentRequired callback");l("Building transaction...");let F=await C.buildTransaction(N,W,ve);l("Transaction signed");let j;C.name==="EVM"?j=JSON.parse(F.serialized):j={transaction:F.serialized};let le=h,Y=_.resource;if(typeof _.resource=="string")try{let m=new URL(_.resource,le).toString();m!==_.resource&&l("Resolved relative resource URL:",_.resource,"\u2192",m),Y=m}catch{Y=_.resource}else if(_.resource&&typeof _.resource=="object"&&"url"in _.resource){let m=_.resource;try{let b=new URL(m.url,le).toString();b!==m.url&&(l("Resolved relative resource URL:",m.url,"\u2192",b),Y={...m,url:b})}catch{}}let ue={x402Version:N.x402Version??2,resource:Y,accepted:N,payload:j};F.extensions&&(ue.extensions=F.extensions);let Je=btoa(JSON.stringify(ue));if(d)try{d(N,F.settlementProbe)}catch{}l("Retrying request with payment...");let J=await P(h,{...w,headers:{...w?.headers||{},"PAYMENT-SIGNATURE":Je,...L?{"X-Quote-Hash":L}:{}}});if(l("Retry response status:",J.status),J.status===402){let m="unknown";try{let b=await J.clone().json();m=String(b.error||b.message||JSON.stringify(b)),l("Rejection reason:",m)}catch{}throw new I("payment_rejected",`Payment was rejected by the server: ${m}`)}let z=J.headers.get("PAYMENT-RESPONSE"),V;if(z)try{V=JSON.parse(atob(z))}catch{}return V??={},V.amountAtomic=H,V.assetDecimals=ce,_n.set(J,V),V.extensions&&l("Settlement extensions:",Object.keys(V.extensions).join(", ")),J}async function D(h,w){let[E,A]=await Rn(h,w);return O(E,A)}return{fetch:D}}function q(t){if(t instanceof Error){if(t.message&&t.message.length>0)return t.message;if(t.name&&t.name.length>0)return t.name}let e=String(t);return e.length>0?e:"unknown error"}async function je(t){let e="";try{e=(await t.clone().text()).slice(0,600)}catch{}let n=e.toLowerCase(),r=n.includes("settle")||n.includes("facilitator"),s=e;try{let a=JSON.parse(e),o=[a.error,a.detail,a.message].filter(i=>typeof i=="string"&&i.length>0);o.length>0&&(s=o.join(" \u2014 "))}catch{}return s||(s=`HTTP ${t.status}`),{reason:r?"settlement_failed":"merchant_rejected",detail:`merchant HTTP ${t.status}: ${s}`}}var it="Payment authorization was sent, but the merchant did not respond within the timeout. ",ct=" Do not retry without checking \u2014 inspect the funding wallet for a transfer to the merchant before attempting payment again.";async function lt(t,e,n){if(!t)return{confirmed:!1,detail:it+"This payment scheme has no on-chain confirmation check, so the SDK cannot verify whether it settled."+ct};try{if(t.kind==="solana"){let o=X(),i=n??o.getDefaultRpcUrl(e.caip2);if(!o.confirmSettlement)return Kt();let c=await o.confirmSettlement(t,i);return c.settled?{confirmed:!0,txSignature:c.txSignature}:$t()}let r=Ee(),s=r.getDefaultRpcUrl(e.caip2);if(!r.confirmSettlement)return Kt();let a=await r.confirmSettlement(t,s);return a.settled?{confirmed:!0,txSignature:a.txSignature}:$t()}catch(r){return{confirmed:!1,detail:it+`On-chain confirmation could not be completed (${q(r)}).`+ct}}}function $t(){return{confirmed:!1,detail:it+"On-chain confirmation found no matching settlement yet \u2014 the payment may still be pending, or may not have settled."+ct}}function Kt(){return{confirmed:!1,detail:it+"The chain adapter does not support on-chain confirmation."+ct}}var kn=new Set(["exact","exact-approval"]);async function Cn(t,e,n,r){let s;try{s=await r.signNextVoucher(n.amount)}catch{return null}let a=new Headers(e.headers??void 0);a.set("X-Tab-Voucher",Ye(s));let o={method:e.method??"GET",headers:a};e.signal&&(o.signal=e.signal),typeof e.body=="string"&&(o.body=e.body);let i;try{i=await fetch(t,o)}catch(c){return{ok:!1,reason:"error",detail:c?.message??String(c)}}return i.status===402?(r.rollbackVoucher?.call(r,s),null):i.ok?{ok:!0,paid:!0,response:i,amountPaid:n.amount,network:n.network}:{ok:!1,...await je(i)}}var Lt={version:2,async parseChallenge(t){return ze(t)},async pay(t,e,n,r,s){if(s.tab){let y=n.options.find(g=>g.scheme==="tab"&&g.network.family==="svm"&&g.payTo===s.tab.counterparty);if(y){let g=await Cn(t,e,y,s.tab);if(g)return g}}let a=n.options.filter(y=>kn.has(y.scheme));if(a.length===0)return{ok:!1,reason:"no_payment_options",detail:`no generically payable scheme offered (got: ${n.options.map(y=>y.scheme).join(", ")})`};let o=a.find(y=>y.network.family==="evm"?!!r.evm:y.network.family==="svm"?!!r.solana:!1);if(!o)return{ok:!1,reason:"unsupported_network"};let i=s.timeoutMs??15e3,c=s.responseTimeoutMs??12e4,u=new AbortController,p=setTimeout(()=>u.abort(),i),d=!1,f,T=(y,g)=>{d=!0,f=g,clearTimeout(p),p=setTimeout(()=>u.abort(),c)},l=Mt({wallets:r,preferredNetwork:o.network.caip2,maxAmountAtomic:s.maxAmountAtomic,fetch:globalThis.fetch,onPaymentDispatched:T}),P=e.signal?AbortSignal.any([e.signal,u.signal]):u.signal,x={method:e.method??"GET",headers:e.headers,signal:P};typeof e.body=="string"&&(x.body=e.body);try{let y=await l.fetch(t,x);if(clearTimeout(p),!y.ok)return{ok:!1,...await je(y)};let g,S=y.headers.get("PAYMENT-RESPONSE");if(S)try{let k=ht(S);k&&typeof k.transaction=="string"&&(g=k.transaction)}catch{}return{ok:!0,paid:!0,response:y,amountPaid:o.amount,network:o.network,txSignature:g}}catch(y){clearTimeout(p);let g=y;if(g?.name==="AbortError"){if(!d)return{ok:!1,reason:"timeout"};let S=await lt(f,o.network,s.solanaRpcUrl);return S.confirmed?{ok:!0,paid:!0,response:void 0,amountPaid:o.amount,network:o.network,txSignature:S.txSignature}:{ok:!1,reason:"payment_unconfirmed",detail:S.detail}}return{ok:!1,reason:"error",detail:g?.message??String(y)}}}};import{getAddress as In}from"viem";var Nn={TransferWithAuthorization:[{name:"from",type:"address"},{name:"to",type:"address"},{name:"value",type:"uint256"},{name:"validAfter",type:"uint256"},{name:"validBefore",type:"uint256"},{name:"nonce",type:"bytes32"}]};async function On(){let t=globalThis.crypto??(await import("crypto")).webcrypto,e=new Uint8Array(32);return t.getRandomValues(e),"0x"+Array.from(e,n=>n.toString(16).padStart(2,"0")).join("")}async function Un(t,e,n){if(typeof t.signTypedData!="function")throw new Error("EVM wallet does not support signTypedData");let r=Math.floor(Date.now()/1e3),s=String(r-600),a=String(r+(e.maxTimeoutSeconds??60)),o={from:t.address,to:e.payTo,value:e.amount,validAfter:s,validBefore:a,nonce:await On()},i=Fe[e.network.caip2];if(i===void 0)throw new Error(`unknown chain id for network ${e.network.caip2}`);let c=e.extra,u=await t.signTypedData({domain:{name:c.name,version:c.version,chainId:i,verifyingContract:In(e.asset)},types:Nn,primaryType:"TransferWithAuthorization",message:o});return{payment:{x402Version:1,scheme:e.scheme,network:n,payload:{signature:u,authorization:o}},settlementProbe:{kind:"eip3009",from:o.from,nonce:o.nonce,asset:e.asset,chainId:i}}}async function Tt(t,e,n){try{let r;for(let s of t.options){let a=s.network.family==="evm"&&!!e.evm||s.network.family==="svm"&&!!e.solana;if(s.scheme!=="exact"){a&&(r=s.scheme);continue}if(s.network.family==="evm"&&e.evm){let o=await e.evm;return await Bn(s,o,n)}if(s.network.family==="svm"&&e.solana){let o=await e.solana;return await Dn(s,o,n)}}return r!==void 0?{ok:!1,reason:"merchant_rejected",detail:`v1 supports only the 'exact' scheme, got '${r}'`}:{ok:!1,reason:"unsupported_network"}}catch(r){return{ok:!1,reason:"error",detail:q(r)}}}async function Bn(t,e,n){if(n.maxAmountAtomic!==void 0&&BigInt(t.amount)>BigInt(n.maxAmountAtomic))return{ok:!1,reason:"budget_exceeded"};let r=t.extra??{},s=r.name,a=r.version;if(typeof s!="string"||s.length===0||typeof a!="string"||a.length===0)return{ok:!1,reason:"merchant_rejected",detail:"v1 challenge missing exact-scheme EIP-712 domain (extra.name / extra.version)"};let o=t.network.bare,{payment:i,settlementProbe:c}=await Un(e,t,o);return{ok:!0,headerValue:Buffer.from(JSON.stringify(i),"utf8").toString("base64"),option:t,settlementProbe:c}}async function Dn(t,e,n){if(n.maxAmountAtomic!==void 0&&BigInt(t.amount)>BigInt(n.maxAmountAtomic))return{ok:!1,reason:"budget_exceeded"};if(t.scheme!=="exact")return{ok:!1,reason:"merchant_rejected",detail:`v1 SVM supports only the 'exact' scheme, got '${t.scheme}'`};let r=t.extra??{};if(typeof r.feePayer!="string"||r.feePayer.length===0)return{ok:!1,reason:"merchant_rejected",detail:"v1 SVM challenge missing extra.feePayer (required as the transaction fee payer)"};let s=t.network.bare,a={x402Version:1,scheme:t.scheme,network:s,asset:t.asset,payTo:t.payTo,amount:t.amount,maxAmountRequired:t.amount,maxTimeoutSeconds:t.maxTimeoutSeconds??60,extra:r},i=await X().buildTransaction(a,e,n.solanaRpcUrl),c={x402Version:1,scheme:t.scheme,network:s,payload:{transaction:i.serialized}};return{ok:!0,headerValue:Buffer.from(JSON.stringify(c),"utf8").toString("base64"),option:t,settlementProbe:i.settlementProbe}}function Mn(t){let e=[];for(let n of t){if(!n||typeof n!="object")continue;let r=n,s=Ce(String(r.network??""));s&&e.push({scheme:String(r.scheme??"exact"),network:s,amount:String(r.maxAmountRequired??r.amount??"0"),asset:String(r.asset??""),payTo:String(r.payTo??""),maxTimeoutSeconds:typeof r.maxTimeoutSeconds=="number"?r.maxTimeoutSeconds:void 0,extra:r.extra&&typeof r.extra=="object"?r.extra:void 0})}return e}var Vt={version:1,async parseChallenge(t){if(t.headers.get("payment-required"))return null;let e;try{e=await t.clone().json()}catch{return null}let n=Array.isArray(e.accepts)?e.accepts:[];if(n.length===0)return null;let r=Mn(n);return r.length===0?null:{x402Version:1,options:r}},async pay(t,e,n,r,s){let a,o=new AbortController,i=!1,c,u;try{let p=s.timeoutMs??15e3;a=setTimeout(()=>o.abort(),p);let d=await Tt(n,r,s);if(!d.ok)return{ok:!1,reason:d.reason,detail:d.detail};let f=d.headerValue,T=d.option;u=T,c=d.settlementProbe;let l=new Headers(e.headers??void 0);l.set("X-PAYMENT",f);let P=e.signal!=null?AbortSignal.any([e.signal,o.signal]):o.signal,x={method:e.method,headers:l,signal:P};typeof e.body=="string"&&(x.body=e.body),i=!0,clearTimeout(a);let y=s.responseTimeoutMs??12e4;a=setTimeout(()=>o.abort(),y);let g=await fetch(t,x);return g.ok?{ok:!0,paid:!0,response:g,amountPaid:T.amount,network:T.network,txSignature:$n(g)}:{ok:!1,...await je(g)}}catch(p){if(p instanceof Error&&p.name==="AbortError"){if(!i)return{ok:!1,reason:"timeout"};let d=await lt(c,u.network,s.solanaRpcUrl);return d.confirmed?{ok:!0,paid:!0,response:void 0,amountPaid:u.amount,network:u.network,txSignature:d.txSignature}:{ok:!1,reason:"payment_unconfirmed",detail:d.detail}}return{ok:!1,reason:"error",detail:q(p)}}finally{a!==void 0&&clearTimeout(a)}}};function $n(t){let e=t.headers.get("x-payment-response")??t.headers.get("X-PAYMENT-RESPONSE");if(e)try{let n=JSON.parse(Buffer.from(e,"base64").toString("utf8")),r=n.transaction??n.txHash??n.transactionHash;return typeof r=="string"?r:void 0}catch{return}}import*as qt from"tweetnacl";import{Keypair as gs,VersionedTransaction as ys,Transaction as hs}from"@solana/web3.js";var Wt=Symbol.for("x402:keypair");function xt(t){let e=t.evm;if(e&&typeof e.signMessage=="function"&&typeof e.address=="string")return{address:e.address,signMessage:e.signMessage};let n=t.solana;if(n){let r=n[Wt];if(r&&r.secretKey&&r.publicKey)return{publicKey:r.publicKey,signMessage:async s=>qt.sign.detached(s,r.secretKey)}}return null}var Kn=[Lt,Vt];async function Ln(t){let e=xt(t);if(!e)return fetch;try{return(await import("@x402/extensions/sign-in-with-x")).wrapFetchWithSIWx(fetch,e)}catch(n){return console.warn(`[x402] SIW-X unavailable \u2014 @x402/extensions failed to load; SIW-X merchants will not authenticate. ${q(n)}`),fetch}}async function Et(t,e,n,r){if(e.body!==void 0&&e.body!==null&&typeof e.body!="string")return{ok:!1,reason:"error",detail:"payAndFetch requires a string body; non-string bodies (Buffer, FormData, URLSearchParams, ReadableStream) cannot be safely re-sent on the paid retry"};let s;try{s=await(await Ln(n))(t,{...e})}catch(a){return{ok:!1,reason:"error",detail:q(a)}}if(s.status!==402)return{ok:!0,paid:!1,response:s};for(let a of Kn){let o=await a.parseChallenge(s.clone());if(o)return a.pay(t,e,o,n,r)}return{ok:!1,reason:"no_payment_options"}}async function Vn(t,e={},n){let r=await Ie(t,e);if(r.kind==="free")return{result:{ok:!0,paid:!1,response:r.response},tab:null};if(r.kind==="no_tab")return{result:{ok:!1,reason:"no_payment_options",detail:`no tab option offered (schemes: ${r.schemesOffered.join(", ")})`},tab:null};if(r.kind==="error")return{result:{ok:!1,reason:"error",detail:r.detail},tab:null};let{offer:s}=r,a=BigInt(Z(n.perUnitCap));if(BigInt(s.amountAtomic)>a)return{result:{ok:!1,reason:"budget_exceeded",detail:`seller quotes ${s.amountAtomic} atomic; perUnitCap allows ${a}`},tab:null};let o=n.tabs?.get(s.payTo);return(!o||!o.state.isOpen)&&(o=await ft({vault:n.vault,network:"solana:mainnet",seller:s.payTo,perUnitCap:n.perUnitCap,totalCap:n.totalCap,sessionDuration:n.sessionDuration,facilitatorUrl:n.facilitatorUrl}),n.tabs?.set(s.payTo,o)),{result:await Et(t,e,{},{tab:o}),tab:o}}function Wn(t){return{counterparty:t.payTo,perRequest:{atomic:t.amountAtomic,human:de(t.amountAtomic)},asset:t.asset,network:{caip2:t.networkCaip2},scheme:"tab",settlement:{custody:"non-custodial",protection:"lock",settleOn:"close"},credit:null,...t.resourceUrl!==void 0?{resourceUrl:t.resourceUrl}:{}}}async function qn(t,e={},n={}){let r=n.cache?.get(t);if(r)return{kind:"terms",terms:r};let s=await Ie(t,e,n.fetchImpl??fetch);if(s.kind!=="offer")return s;if(s.offer.asset!==qe)return{kind:"error",detail:`tab offer asset is not USDC ("${s.offer.asset}"); refusing to render a human price`};let a=Wn(s.offer);return n.cache?.set(t,a),{kind:"terms",terms:a}}export{Pe as DEFAULT_FACILITATOR_URL,gt as DEXTER_VAULT_PROGRAM_ID,an as INSTRUCTIONS_SYSVAR_ID,sn as SECP256R1_PROGRAM_ID,pe as SessionScopeExceededError,Q as TabClosedError,me as UnsupportedNetworkError,de as atomicToHuman,tn as buildRegisterSessionKeyInstruction,nn as buildRevokeSessionKeyInstruction,rn as buildSecp256r1VerifyInstruction,Ft as buildVoucherMessage,Z as humanToAtomic,ft as openTab,Vn as payUrlWithTab,Ie as resolveTabOffer,qn as resolveTabTerms,zt as resumeTab,mt as sessionRegisterMessage,Ht as sessionRevokeMessage,pn as tabFromGrant,pt as voucherPayloadMessage,Ye as voucherToHeader};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";var it=Object.create;var J=Object.defineProperty;var st=Object.getOwnPropertyDescriptor;var ot=Object.getOwnPropertyNames;var at=Object.getPrototypeOf,ct=Object.prototype.hasOwnProperty;var lt=(e,t)=>{for(var r in t)J(e,r,{get:t[r],enumerable:!0})},Ve=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of ot(t))!ct.call(e,i)&&i!==r&&J(e,i,{get:()=>t[i],enumerable:!(n=st(t,i))||n.enumerable});return e};var $e=(e,t,r)=>(r=e!=null?it(at(e)):{},Ve(t||!e||!e.__esModule?J(r,"default",{value:e,enumerable:!0}):r,e)),ut=e=>Ve(J({},"__esModule",{value:!0}),e);var kt={};lt(kt,{FileChannelLedger:()=>Y,FileVoucherStore:()=>ce,InMemoryChannelLedger:()=>V,InMemoryVoucherStore:()=>ae,InvalidRegistrationError:()=>E,InvalidVoucherError:()=>S,InvalidVoucherSignatureError:()=>P,OnChainVerificationError:()=>R,ScopeViolationError:()=>x,TAB_VOUCHER_HEADER:()=>N,enforceScope:()=>ne,openSse:()=>We,parseRegistration:()=>ee,requireTab:()=>ze,tabChallengeMiddleware:()=>et,tabMiddleware:()=>oe,tabOrExactMiddleware:()=>rt,verifyRegistrationOnChain:()=>te,verifyVoucherSignature:()=>re});module.exports=ut(kt);var S=class extends Error{constructor(r,n){super(`Invalid voucher: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="InvalidVoucherError"}};var O=require("fs"),G=require("path"),Be=new Map;function T(e,t){let n=(Be.get(e)??Promise.resolve()).then(()=>t(),()=>t());return Be.set(e,n.then(()=>{},()=>{})),n}var V=class{map=new Map;async get(t){return this.map.get(t)??null}async set(t,r){this.map.set(t,r)}async delete(t){this.map.delete(t)}async tryAcquireLease(t,r){return T(t,async()=>{let n=this.map.get(t),i=Date.now();if(n?.lease&&n.lease.heldUntilUnixMs>i)return!1;let s=n??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return this.map.set(t,{...s,lease:{heldUntilUnixMs:i+r}}),!0})}async releaseLease(t){await T(t,async()=>{let r=this.map.get(t);r&&this.map.set(t,{...r,lease:void 0})})}};function Ee(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}function Ce(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 mt(e){return{lastVoucher:e.lastVoucher?{payload:e.lastVoucher.payload,sessionPublicKey:Ee(e.lastVoucher.sessionPublicKey),sessionRegistration:Ee(e.lastVoucher.sessionRegistration),sessionSignature:Ee(e.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:e.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:e.lastCrystallizedCumulativeAtomic,onChain:e.onChain,lease:e.lease}}function pt(e){return{lastVoucher:e.lastVoucher?{payload:e.lastVoucher.payload,sessionPublicKey:Ce(e.lastVoucher.sessionPublicKey),sessionRegistration:Ce(e.lastVoucher.sessionRegistration),sessionSignature:Ce(e.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:e.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:e.lastCrystallizedCumulativeAtomic??"0",onChain:e.onChain,lease:e.lease}}var Y=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,G.join)(this.dir,`${t}.json`)}async get(t){try{let r=await O.promises.readFile(this.pathFor(t),"utf8");return pt(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(t,r){let n=this.pathFor(t);await O.promises.mkdir((0,G.dirname)(n),{recursive:!0});let i=`${n}.tmp`;await O.promises.writeFile(i,JSON.stringify(mt(r))),await O.promises.rename(i,n)}async delete(t){try{await O.promises.unlink(this.pathFor(t))}catch(r){if(r?.code!=="ENOENT")throw r}}async tryAcquireLease(t,r){return T(t,async()=>{let n=await this.get(t),i=Date.now();if(n?.lease&&n.lease.heldUntilUnixMs>i)return!1;let s=n??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return await this.set(t,{...s,lease:{heldUntilUnixMs:i+r}}),!0})}async releaseLease(t){await T(t,async()=>{let r=await this.get(t);r&&await this.set(t,{...r,lease:void 0})})}};var qe=require("@solana/web3.js");var Me=$e(require("tweetnacl"),1),gt=require("@noble/hashes/sha256"),ht=require("@noble/curves/p256"),Z=require("@solana/web3.js");var I=require("@dexterai/vault/messages");var Pe=require("@dexterai/vault/instructions"),dt=require("@dexterai/vault/precompile"),$=require("@dexterai/vault/constants");var Q=require("@dexterai/vault/session"),Te="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(e){if(e.length!==188)throw new E("wrong_length",`expected 188, got ${e.length}`);let t=new TextDecoder().decode(e.slice(0,Te.length));if(t!==Te)throw new E("wrong_domain",`got "${t}"`);for(let y=Te.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 Z.PublicKey(e.slice(32,64)),i=new Z.PublicKey(e.slice(64,96)),s=e.slice(96,128),p=r.getBigUint64(128,!0),u=r.getBigInt64(136,!0),o=new Z.PublicKey(e.slice(144,176)),d=r.getUint32(176,!0),c=r.getBigUint64(180,!0);if(!n.equals($.DEXTER_VAULT_PROGRAM_ID))throw new E("wrong_program",`${n.toBase58()} is not ${$.DEXTER_VAULT_PROGRAM_ID.toBase58()}`);if(p===0n)throw new E("cap_zero");let a=BigInt(Math.floor(Date.now()/1e3));if(u<=a)throw new E("expiry_in_past",`expires_at=${u}, now=${a}`);return{programId:n,vaultPda:i,sessionPubkey:new Uint8Array(s),maxAmount:p,expiresAt:u,allowedCounterparty:o,nonce:d,maxRevolvingCapacity:c}}var R=class extends Error{constructor(r,n){super(`On-chain verification failed: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="OnChainVerificationError"}};async function te(e,t){let r=await(0,Q.fetchSessionAccount)(e,t.vaultPda,t.allowedCounterparty);if(!r||r.version===0)throw new R("session_not_active","no live SessionAccount PDA for this (vault, counterparty) \u2014 revoked, expiry-swept, or never registered");if(!(0,Q.isSessionLive)(r))throw new R("session_not_active","SessionAccount PDA is present but expired");if(!yt(r.session.sessionPubkey,t.sessionPubkey))throw new R("session_pubkey_mismatch",`on-chain ${Ke(r.session.sessionPubkey)} != registration ${Ke(t.sessionPubkey)}`)}var P=class extends Error{constructor(t){super(`Invalid voucher signature${t?`: ${t}`:""}`),this.name="InvalidVoucherSignatureError"}};function re(e,t){if(t.length!==32)throw new P(`channelIdBytes must be 32 bytes, got ${t.length}`);if(e.sessionPublicKey.length!==32)throw new P(`sessionPublicKey must be 32 bytes, got ${e.sessionPublicKey.length}`);if(e.sessionSignature.length!==64)throw new P(`sessionSignature must be 64 bytes, got ${e.sessionSignature.length}`);let r=(0,I.voucherPayloadMessage)({channelId:t,cumulativeAmount:BigInt(e.payload.cumulativeAmount),sequenceNumber:e.payload.sequenceNumber});if(!Me.default.sign.detached.verify(r,e.sessionSignature,e.sessionPublicKey))throw new P("ed25519 verify rejected")}var x=class extends Error{constructor(r,n){super(`Scope violation: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="ScopeViolationError"}};function ne(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 yt(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 Ke(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}var bt=require("@solana/web3.js"),wt=require("@noble/hashes/utils");var ft=$e(require("tweetnacl"),1);var At=require("@noble/hashes/sha256");var Le="https://x402.dexter.cash",De=6;function C(e,t=De){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 U(e,t=De){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 ie=require("@noble/hashes/utils"),vt=15e3;async function Re(e,t,r,n,i=fetch){let s=e.lastVoucher;if(!s)return{crystallized:!1};if(s.payload.channelId!==t)return{crystallized:!1,error:"channel_id_mismatch"};try{let p=`${r.replace(/\/$/,"")}/tab/lock`,u={channelId:s.payload.channelId,cumulativeAmount:s.payload.cumulativeAmount,sequenceNumber:s.payload.sequenceNumber,sessionPublicKey:(0,ie.bytesToHex)(s.sessionPublicKey),sessionSignature:(0,ie.bytesToHex)(s.sessionSignature),sessionRegistration:(0,ie.bytesToHex)(s.sessionRegistration),network:n},o=await i(p,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(u),signal:AbortSignal.timeout(vt)}),d=await o.text();if(!o.ok)return{crystallized:!1,error:`tab lock ${o.status}: ${d.slice(0,200)}`};let c;try{let a=JSON.parse(d);a&&typeof a.claimPda=="string"&&(c=a.claimPda)}catch{}return{crystallized:!0,claimPda:c}}catch(p){return{crystallized:!1,error:String(p?.message??p)}}}async function He(e,t,r,n,i,s={}){let p=BigInt(e.deliveredCumulativeAtomic),u=BigInt(e.lastCrystallizedCumulativeAtomic??"0"),o=BigInt(i.thresholdAtomic);if(p-u<o)return{crystallized:!1};let d=e.lastVoucher?.payload.cumulativeAmount,c=await Re(e,t,r,n,s.fetchImpl);return c.crystallized&&d!==void 0&&(e.lastCrystallizedCumulativeAtomic=d),c}var N="x-tab-voucher",_e=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)}},Ne=class{constructor(t,r,n,i,s,p){this.recordDeliveredImpl=s;this.chargeImpl=p;this.channelId=t,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(t){return this.recordDeliveredImpl(t)}bumpCumulative(t){this.cumulativeAtomic=t}setSessionPublicKey(t){this.sessionPublicKey=t}async charge(t){return this.chargeImpl(t)}};function St(e){if(typeof e!="string"||e.length===0)throw new S("signature_invalid",`missing ${N} 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:se(r.sessionPublicKey),sessionRegistration:se(r.sessionRegistration),sessionSignature:se(r.sessionSignature)}}function se(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 xt(e){if(!/^[0-9a-f]{64}$/i.test(e))throw new S("signature_invalid",`channelId must be 64-char hex, got "${e}"`);return se(e)}function oe(e){let t=e.ledger??new V,r=new _e,n=typeof e.sellerPubkey=="string"?new qe.PublicKey(e.sellerPubkey):e.sellerPubkey,i=e.maxPerVoucherAtomic?BigInt(e.maxPerVoucherAtomic):BigInt(C(e.perUnit))*100n,s=e.facilitatorUrl??Le,p={thresholdAtomic:e.lockCadence?.thresholdAtomic??C("0.10"),onClose:e.lockCadence?.onClose??!0};return async(u,o,d)=>{try{let c=St(u.headers[N]),a=c.payload.channelId,y=xt(a),m=r.get(a);if(!m){let g=ee(c.sessionRegistration);await te(e.connection,g),m={registration:g,lastCumulativeAtomic:"0"},r.set(a,m)}re(c,y),ne({registration:m.registration,voucher:c,expectedCounterparty:n,previousCumulativeAtomic:m.lastCumulativeAtomic});let f=BigInt(c.payload.cumulativeAmount),w=BigInt(m.lastCumulativeAtomic),k=f-w;if(k>i)throw new x("cumulative_exceeds_cap",`single voucher increment ${k} exceeds maxPerVoucherAtomic ${i}`);let W=e.leaseTtlMs??3e5;if(!await t.tryAcquireLease(a,W))throw new S("channel_busy","another stream is live on this channel; tabs serve one stream at a time");let F=!1,K=()=>{F||(F=!0,t.releaseLease(a).catch(g=>{console.error("[tab/seller] failed to release channel lease:",g)}))};o.on("close",K),o.on("finish",K);let xe=async g=>{let v=g.lastCrystallizedCumulativeAtomic??"0";await He(g,a,s,e.network,p),g.lastCrystallizedCumulativeAtomic!==v&&await T(a,async()=>{let b=await t.get(a);b&&await t.set(a,{...b,lastCrystallizedCumulativeAtomic:g.lastCrystallizedCumulativeAtomic})}).catch(()=>{})},j=!1,X=()=>{!p.onClose||j||(j=!0,(async()=>{let g=await t.get(a);if(!g||!g.lastVoucher)return;let v=g.lastVoucher.payload.cumulativeAmount;(await Re(g,a,s,e.network)).crystallized&&await T(a,async()=>{let M=await t.get(a);M&&await t.set(a,{...M,lastCrystallizedCumulativeAtomic:v})})})().catch(()=>{}))};o.on("close",X),o.on("finish",X);let l=await t.get(a),h=l?BigInt(l.deliveredCumulativeAtomic):0n;await T(a,async()=>{let g=await t.get(a);await t.set(a,{...g,lastVoucher:c,deliveredCumulativeAtomic:g?g.deliveredCumulativeAtomic:"0"})}),r.update(a,c.payload.cumulativeAmount);let A=new Ne(a,e.network,f,h,async g=>{let v=null;await T(a,async()=>{let b=await t.get(a),M=b?BigInt(b.deliveredCumulativeAtomic):0n,ke=BigInt(g),nt=ke>0n?M+ke:M,Oe={...b,lastVoucher:b?.lastVoucher??c,deliveredCumulativeAtomic:nt.toString(),lastCrystallizedCumulativeAtomic:b?.lastCrystallizedCumulativeAtomic??"0"};await t.set(a,Oe),v=Oe}),v&&xe(v).catch(()=>{})},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.")});A.setSessionPublicKey(c.sessionPublicKey),u.tab=A,d()}catch(c){if(c instanceof S||c instanceof E||c instanceof R||c instanceof P||c instanceof x){o.status(402).json({error:"invalid_voucher",reason:c.reason??"unknown",detail:c.message});return}d(c)}}}function ze(e){if(!e.tab)throw new Error("req.tab is missing \u2014 did tabMiddleware run on this route?");return e.tab}function We(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(C(r.cumulative())),i=BigInt(C(r.deliveredCumulative())),s=n-i;s<0n&&(s=0n);let p=t.perUnit?BigInt(C(t.perUnit)):null,u=0n,o=!1;async function d(){await r.recordDelivered(u.toString())}e.on("close",()=>{o||(o=!0,d().catch(m=>{console.error("[tab/seller] terminal persist failed on disconnect:",m)}))});async function c(m=1){if(o)throw new Error("meter ended");if(p===null)throw new Error("charge() needs options.perUnit");let f=p*BigInt(m),w=u+f;if(w>s)throw o=!0,await d(),new x("cumulative_exceeds_cap",`chunk would push delivered to ${U((i+w).toString())} beyond signed cumulative ${U(n.toString())} (per-request budget ${U(s.toString())})`);u=w}function a(m){if(o)throw new Error("meter ended");let w=(typeof m=="string"?m:Buffer.from(m).toString("utf8")).replace(/\n/g,"\\n");e.write(`data: ${w}
|
|
1
|
+
"use strict";var ct=Object.create;var G=Object.defineProperty;var lt=Object.getOwnPropertyDescriptor;var ut=Object.getOwnPropertyNames;var mt=Object.getPrototypeOf,dt=Object.prototype.hasOwnProperty;var pt=(e,t)=>{for(var r in t)G(e,r,{get:t[r],enumerable:!0})},Ke=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of ut(t))!dt.call(e,i)&&i!==r&&G(e,i,{get:()=>t[i],enumerable:!(n=lt(t,i))||n.enumerable});return e};var Me=(e,t,r)=>(r=e!=null?ct(mt(e)):{},Ke(t||!e||!e.__esModule?G(r,"default",{value:e,enumerable:!0}):r,e)),ht=e=>Ke(G({},"__esModule",{value:!0}),e);var Mt={};pt(Mt,{FileChannelLedger:()=>Z,FileVoucherStore:()=>ue,InMemoryChannelLedger:()=>B,InMemoryVoucherStore:()=>le,InvalidRegistrationError:()=>C,InvalidVoucherError:()=>v,InvalidVoucherSignatureError:()=>P,OnChainVerificationError:()=>_,ScopeViolationError:()=>S,TAB_VOUCHER_HEADER:()=>I,enforceScope:()=>se,openSse:()=>Je,parseRegistration:()=>re,requireTab:()=>Xe,tabChallengeMiddleware:()=>it,tabMiddleware:()=>ce,tabOrExactMiddleware:()=>ot,verifyRegistrationOnChain:()=>ne,verifyVoucherSignature:()=>ie});module.exports=ht(Mt);var v=class extends Error{constructor(r,n){super(`Invalid voucher: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="InvalidVoucherError"}};var V=require("fs"),Q=require("path"),Le=new Map;function T(e,t){let n=(Le.get(e)??Promise.resolve()).then(()=>t(),()=>t());return Le.set(e,n.then(()=>{},()=>{})),n}var B=class{map=new Map;async get(t){return this.map.get(t)??null}async set(t,r){this.map.set(t,r)}async delete(t){this.map.delete(t)}async tryAcquireLease(t,r){return T(t,async()=>{let n=this.map.get(t),i=Date.now();if(n?.lease&&n.lease.heldUntilUnixMs>i)return!1;let s=n??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return this.map.set(t,{...s,lease:{heldUntilUnixMs:i+r}}),!0})}async releaseLease(t){await T(t,async()=>{let r=this.map.get(t);r&&this.map.set(t,{...r,lease:void 0})})}};function Te(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}function _e(e){if(e.length%2!==0)throw new Error(`hex length must be even, got ${e.length}`);let t=new Uint8Array(e.length/2);for(let r=0;r<t.length;r++)t[r]=parseInt(e.substr(r*2,2),16);return t}function gt(e){return{lastVoucher:e.lastVoucher?{payload:e.lastVoucher.payload,sessionPublicKey:Te(e.lastVoucher.sessionPublicKey),sessionRegistration:Te(e.lastVoucher.sessionRegistration),sessionSignature:Te(e.lastVoucher.sessionSignature)}:null,deliveredCumulativeAtomic:e.deliveredCumulativeAtomic,lastCrystallizedCumulativeAtomic:e.lastCrystallizedCumulativeAtomic,onChain:e.onChain,lease:e.lease}}function yt(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",onChain:e.onChain,lease:e.lease}}var Z=class{constructor(t){this.dir=t}pathFor(t){if(!/^[a-z0-9_-]+$/i.test(t))throw new Error(`unsafe channelId for filesystem: ${t}`);return(0,Q.join)(this.dir,`${t}.json`)}async get(t){try{let r=await V.promises.readFile(this.pathFor(t),"utf8");return yt(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(t,r){let n=this.pathFor(t);await V.promises.mkdir((0,Q.dirname)(n),{recursive:!0});let i=`${n}.tmp`;await V.promises.writeFile(i,JSON.stringify(gt(r))),await V.promises.rename(i,n)}async delete(t){try{await V.promises.unlink(this.pathFor(t))}catch(r){if(r?.code!=="ENOENT")throw r}}async tryAcquireLease(t,r){return T(t,async()=>{let n=await this.get(t),i=Date.now();if(n?.lease&&n.lease.heldUntilUnixMs>i)return!1;let s=n??{lastVoucher:null,deliveredCumulativeAtomic:"0",lastCrystallizedCumulativeAtomic:"0"};return await this.set(t,{...s,lease:{heldUntilUnixMs:i+r}}),!0})}async releaseLease(t){await T(t,async()=>{let r=await this.get(t);r&&await this.set(t,{...r,lease:void 0})})}};var je=require("@solana/web3.js");var qe=Me(require("tweetnacl"),1),At=require("@noble/hashes/sha256"),bt=require("@noble/curves/p256"),ee=require("@solana/web3.js");var O=require("@dexterai/vault/messages");var Re=require("@dexterai/vault/instructions"),ft=require("@dexterai/vault/precompile"),K=require("@dexterai/vault/constants");var te=require("@dexterai/vault/session"),Ne="OTS_SESSION_REGISTER_V2",C=class extends Error{constructor(r,n){super(`Invalid registration: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="InvalidRegistrationError"}};function re(e){if(e.length!==188)throw new C("wrong_length",`expected 188, got ${e.length}`);let t=new TextDecoder().decode(e.slice(0,Ne.length));if(t!==Ne)throw new C("wrong_domain",`got "${t}"`);for(let g=Ne.length;g<32;g++)if(e[g]!==0)throw new C("wrong_domain",`non-NUL padding at byte ${g}`);let r=new DataView(e.buffer,e.byteOffset,e.byteLength),n=new ee.PublicKey(e.slice(32,64)),i=new ee.PublicKey(e.slice(64,96)),s=e.slice(96,128),h=r.getBigUint64(128,!0),c=r.getBigInt64(136,!0),o=new ee.PublicKey(e.slice(144,176)),d=r.getUint32(176,!0),l=r.getBigUint64(180,!0);if(!n.equals(K.DEXTER_VAULT_PROGRAM_ID))throw new C("wrong_program",`${n.toBase58()} is not ${K.DEXTER_VAULT_PROGRAM_ID.toBase58()}`);if(h===0n)throw new C("cap_zero");let a=BigInt(Math.floor(Date.now()/1e3));if(c<=a)throw new C("expiry_in_past",`expires_at=${c}, now=${a}`);return{programId:n,vaultPda:i,sessionPubkey:new Uint8Array(s),maxAmount:h,expiresAt:c,allowedCounterparty:o,nonce:d,maxRevolvingCapacity:l}}var _=class extends Error{constructor(r,n){super(`On-chain verification failed: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="OnChainVerificationError"}};async function ne(e,t){let r=await(0,te.fetchSessionAccount)(e,t.vaultPda,t.allowedCounterparty);if(!r||r.version===0)throw new _("session_not_active","no live SessionAccount PDA for this (vault, counterparty) \u2014 revoked, expiry-swept, or never registered");if(!(0,te.isSessionLive)(r))throw new _("session_not_active","SessionAccount PDA is present but expired");if(!wt(r.session.sessionPubkey,t.sessionPubkey))throw new _("session_pubkey_mismatch",`on-chain ${De(r.session.sessionPubkey)} != registration ${De(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 P=class extends Error{constructor(t){super(`Invalid voucher signature${t?`: ${t}`:""}`),this.name="InvalidVoucherSignatureError"}};function ie(e,t){if(t.length!==32)throw new P(`channelIdBytes must be 32 bytes, got ${t.length}`);if(e.sessionPublicKey.length!==32)throw new P(`sessionPublicKey must be 32 bytes, got ${e.sessionPublicKey.length}`);if(e.sessionSignature.length!==64)throw new P(`sessionSignature must be 64 bytes, got ${e.sessionSignature.length}`);let r=(0,O.voucherPayloadMessage)({channelId:t,cumulativeAmount:BigInt(e.payload.cumulativeAmount),sequenceNumber:e.payload.sequenceNumber});if(!qe.default.sign.detached.verify(r,e.sessionSignature,e.sessionPublicKey))throw new P("ed25519 verify rejected")}var S=class extends Error{constructor(r,n){super(`Scope violation: ${r}${n?` (${n})`:""}`);this.reason=r;this.name="ScopeViolationError"}};function se(e){let t=BigInt(e.voucher.payload.cumulativeAmount);if(t>e.registration.maxAmount)throw new S("cumulative_exceeds_cap",`${t} > ${e.registration.maxAmount}`);let r=BigInt(Math.floor(Date.now()/1e3));if(r>=e.registration.expiresAt)throw new S("session_expired",`now=${r} >= expiresAt=${e.registration.expiresAt}`);if(!e.registration.allowedCounterparty.equals(e.expectedCounterparty))throw new S("wrong_counterparty",`${e.registration.allowedCounterparty.toBase58()} != ${e.expectedCounterparty.toBase58()}`);if(e.previousCumulativeAtomic!==void 0){let n=BigInt(e.previousCumulativeAtomic);if(t<=n)throw new S("non_monotonic",`cumulative=${t} not > previous=${n}`)}}function wt(e,t){if(e.length!==t.length)return!1;for(let r=0;r<e.length;r++)if(e[r]!==t[r])return!1;return!0}function De(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}var xt=require("@solana/web3.js"),Ct=require("@noble/hashes/utils");var vt=Me(require("tweetnacl"),1);var St=require("@noble/hashes/sha256");var ze="https://x402.dexter.cash",He=6;function E(e,t=He){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 $(e,t=He){if(!/^\d+$/.test(e))throw new Error(`atomic must be a non-negative integer string, got "${e}"`);let r=e.padStart(t+1,"0"),n=r.slice(0,-t).replace(/^0+(?=\d)/,"")||"0",i=r.slice(-t).replace(/0+$/,"");return i?`${n}.${i}`:n}var oe=require("@noble/hashes/utils"),Et=15e3,Pt=["claim_already_exists","non_monotonic_cumulative"];function Tt(e){return`${e.slice(0,16)}\u2026`}function Fe(e,t,r,n){let i=Tt(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(Pt.some(s=>n.error.includes(s))){console.warn(`[tab/seller] crystallize duplicate channel=${i} cumulative=${t} seq=${r}: ${n.error} \u2014 voucher already secured on-chain (benign, no action)`);return}console.error(`[tab/seller] crystallize FAILED channel=${i} cumulative=${t} seq=${r}: ${n.error} \u2014 lock NOT secured (degraded: best-effort path, no watermark advance, retries at next threshold/close; seller exposure stays unsecured until it lands)`)}}async function Ie(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 Fe(t,s.payload.cumulativeAmount,s.payload.sequenceNumber,c),c}let h=c=>(Fe(t,s.payload.cumulativeAmount,s.payload.sequenceNumber,c),c);try{let c=`${r.replace(/\/$/,"")}/tab/lock`,o={channelId:s.payload.channelId,cumulativeAmount:s.payload.cumulativeAmount,sequenceNumber:s.payload.sequenceNumber,sessionPublicKey:(0,oe.bytesToHex)(s.sessionPublicKey),sessionSignature:(0,oe.bytesToHex)(s.sessionSignature),sessionRegistration:(0,oe.bytesToHex)(s.sessionRegistration),network:n},d=await i(c,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(o),signal:AbortSignal.timeout(Et)}),l=await d.text();if(!d.ok)return h({crystallized:!1,error:`tab lock ${d.status}: ${l.slice(0,200)}`});let a;try{let g=JSON.parse(l);g&&typeof g.claimPda=="string"&&(a=g.claimPda)}catch{}return h({crystallized:!0,claimPda:a})}catch(c){return h({crystallized:!1,error:String(c?.message??c)})}}async function We(e,t,r,n,i,s={}){let h=BigInt(e.deliveredCumulativeAtomic),c=BigInt(e.lastCrystallizedCumulativeAtomic??"0"),o=BigInt(i.thresholdAtomic);if(h-c<o)return{crystallized:!1};let d=e.lastVoucher?.payload.cumulativeAmount,l=await Ie(e,t,r,n,s.fetchImpl);return l.crystallized&&d!==void 0&&(e.lastCrystallizedCumulativeAtomic=d),l}var I="x-tab-voucher",ke=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)}},Ue=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 $(this.cumulativeAtomic.toString())}deliveredCumulative(){return $(this.deliveredBaselineAtomic.toString())}async recordDelivered(t){return this.recordDeliveredImpl(t)}bumpCumulative(t){this.cumulativeAtomic=t}setSessionPublicKey(t){this.sessionPublicKey=t}async charge(t){return this.chargeImpl(t)}};function _t(e){if(typeof e!="string"||e.length===0)throw new v("signature_invalid",`missing ${I} header`);let t;try{t=Buffer.from(e,"base64").toString("utf8")}catch{throw new v("signature_invalid","malformed base64")}let r;try{r=JSON.parse(t)}catch{throw new v("signature_invalid","malformed JSON")}if(!r||typeof r!="object"||!r.payload||!r.sessionPublicKey)throw new v("signature_invalid","missing required fields");return{payload:r.payload,sessionPublicKey:ae(r.sessionPublicKey),sessionRegistration:ae(r.sessionRegistration),sessionSignature:ae(r.sessionSignature)}}function ae(e){if(typeof e!="string"||e.length%2!==0)throw new v("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 Rt(e){if(!/^[0-9a-f]{64}$/i.test(e))throw new v("signature_invalid",`channelId must be 64-char hex, got "${e}"`);return ae(e)}function ce(e){let t=e.ledger??new B,r=new ke,n=typeof e.sellerPubkey=="string"?new je.PublicKey(e.sellerPubkey):e.sellerPubkey,i=e.maxPerVoucherAtomic?BigInt(e.maxPerVoucherAtomic):BigInt(E(e.perUnit))*100n,s=e.facilitatorUrl??ze,h={thresholdAtomic:e.lockCadence?.thresholdAtomic??E("0.10"),onClose:e.lockCadence?.onClose??!0};return async(c,o,d)=>{try{let l=_t(c.headers[I]),a=l.payload.channelId,g=Rt(a),m=r.get(a),f=null;if(!m){let y=re(l.sessionRegistration);f=(await ne(e.connection,y))?.frontierAtomic??null,m={registration:y,lastCumulativeAtomic:"0"},r.set(a,m)}ie(l,g),se({registration:m.registration,voucher:l,expectedCounterparty:n,previousCumulativeAtomic:m.lastCumulativeAtomic});let b=BigInt(l.payload.cumulativeAmount),L=BigInt(m.lastCumulativeAtomic),D=b-L;if(D>i)throw new S("cumulative_exceeds_cap",`single voucher increment ${D} exceeds maxPerVoucherAtomic ${i}`);let Ee=e.leaseTtlMs??3e5;if(!await t.tryAcquireLease(a,Ee))throw new v("channel_busy","another stream is live on this channel; tabs serve one stream at a time");let q=!1,J=()=>{q||(q=!0,t.releaseLease(a).catch(y=>{console.error("[tab/seller] failed to release channel lease:",y)}))};o.on("close",J),o.on("finish",J);let Pe=async y=>{let N=y.lastCrystallizedCumulativeAtomic??"0";await We(y,a,s,e.network,h),y.lastCrystallizedCumulativeAtomic!==N&&await T(a,async()=>{let w=await t.get(a);w&&await t.set(a,{...w,lastCrystallizedCumulativeAtomic:y.lastCrystallizedCumulativeAtomic})}).catch(w=>{console.error(`[tab/seller] crystallize watermark persist FAILED channel=${a.slice(0,16)}\u2026 (lock landed; expect a duplicate-lock warn on the next request):`,w)})},Y=!1,u=()=>{!h.onClose||Y||(Y=!0,(async()=>{let y=await t.get(a);if(!y||!y.lastVoucher)return;let N=y.lastVoucher.payload.cumulativeAmount;(await Ie(y,a,s,e.network)).crystallized&&await T(a,async()=>{let z=await t.get(a);z&&await t.set(a,{...z,lastCrystallizedCumulativeAtomic:N})})})().catch(y=>{console.error(`[tab/seller] close-path crystallize CRASHED channel=${a.slice(0,16)}\u2026 (final voucher NOT locked; exposure unsecured until the next request retries):`,y)}))};o.on("close",u),o.on("finish",u);let p=await t.get(a),A=!p?.lastVoucher&&BigInt(p?.deliveredCumulativeAtomic??"0")===0n,x=f!==null&&A&&BigInt(f)>0n?f:null;x!==null&&console.info(`[tab/seller] channel ${a.slice(0,16)}\u2026 resumed: seeding delivered baseline from chain frontier ${x} (session already settled/locked up to it \u2014 that span is not deliverable budget)`);let k=x!==null?BigInt(x):p?BigInt(p.deliveredCumulativeAtomic):0n;await T(a,async()=>{let y=await t.get(a);await t.set(a,{...y,lastVoucher:l,deliveredCumulativeAtomic:x??(y?y.deliveredCumulativeAtomic:"0"),lastCrystallizedCumulativeAtomic:x??y?.lastCrystallizedCumulativeAtomic??"0"})}),r.update(a,l.payload.cumulativeAmount);let U=new Ue(a,e.network,b,k,async y=>{let N=null;await T(a,async()=>{let w=await t.get(a),z=w?BigInt(w.deliveredCumulativeAtomic):0n,Ve=BigInt(y),at=Ve>0n?z+Ve:z,Be={...w,lastVoucher:w?.lastVoucher??l,deliveredCumulativeAtomic:at.toString(),lastCrystallizedCumulativeAtomic:w?.lastCrystallizedCumulativeAtomic??"0"};await t.set(a,Be),N=Be}),N&&Pe(N).catch(w=>{console.error(`[tab/seller] crystallize cadence CRASHED channel=${a.slice(0,16)}\u2026 (threshold lock not attempted; retries at the next delivery):`,w)})},async y=>{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 v||l instanceof C||l instanceof _||l instanceof P||l instanceof S){o.status(402).json({error:"invalid_voucher",reason:l.reason??"unknown",detail:l.message});return}d(l)}}}function Xe(e){if(!e.tab)throw new Error("req.tab is missing \u2014 did tabMiddleware run on this route?");return e.tab}function Je(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(E(r.cumulative())),i=BigInt(E(r.deliveredCumulative())),s=n-i;s<0n&&(s=0n);let h=t.perUnit?BigInt(E(t.perUnit)):null,c=0n,o=!1;async function d(){await r.recordDelivered(c.toString())}e.on("close",()=>{o||(o=!0,d().catch(m=>{console.error("[tab/seller] terminal persist failed on disconnect:",m)}))});async function l(m=1){if(o)throw new Error("meter ended");if(h===null)throw new Error("charge() needs options.perUnit");let f=h*BigInt(m),b=c+f;if(b>s)throw o=!0,await d(),new S("cumulative_exceeds_cap",`chunk would push delivered to ${$((i+b).toString())} beyond signed cumulative ${$(n.toString())} (per-request budget ${$(s.toString())})`);c=b}function a(m){if(o)throw new Error("meter ended");let b=(typeof m=="string"?m:Buffer.from(m).toString("utf8")).replace(/\n/g,"\\n");e.write(`data: ${b}
|
|
2
2
|
|
|
3
|
-
`)}async function
|
|
4
|
-
data: {"chargedAtomic":"${
|
|
3
|
+
`)}async function g(){o||(o=!0,await d(),e.write(`event: end
|
|
4
|
+
data: {"chargedAtomic":"${c}"}
|
|
5
5
|
|
|
6
|
-
`),e.end())}return{charge:c,send:a,end:y}}var B=require("fs"),le=require("path");function Et(e){return{payload:e.payload,sessionPublicKey:Ie(e.sessionPublicKey),sessionRegistration:Ie(e.sessionRegistration),sessionSignature:Ie(e.sessionSignature)}}function Ct(e){return{payload:e.payload,sessionPublicKey:Ue(e.sessionPublicKey),sessionRegistration:Ue(e.sessionRegistration),sessionSignature:Ue(e.sessionSignature)}}function Ie(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}function Ue(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)}},ce=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,le.join)(this.dir,`${t}.json`)}async get(t){try{let r=await B.promises.readFile(this.pathFor(t),"utf8");return Ct(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(t,r){let n=this.pathFor(t);await B.promises.mkdir((0,le.dirname)(n),{recursive:!0});let i=`${n}.tmp`;await B.promises.writeFile(i,JSON.stringify(Et(r))),await B.promises.rename(i,n)}async delete(t){try{await B.promises.unlink(this.pathFor(t))}catch(r){if(r?.code!=="ENOENT")throw r}}};var Qe=require("@solana/web3.js");var _="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",Fe="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",je="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";var L="eip155:8453",ue="eip155:84532",me="eip155:42161",pe="eip155:137",de="eip155:10",ge="eip155:43114",he="eip155:56",ye="eip155:1187947933",fe="eip155:324705682",Ae="eip155:1";var be="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";var Xe="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",Pt="0x55d398326f99059fF775485246999027B3197955",Je="0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",Ye={[he]:Je,[L]:Xe,[ue]:"0x036CbD53842c5426634e7929541eC2318f3dCF7e",[me]:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831",[pe]:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",[de]:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",[ge]:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",[ye]:"0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",[fe]:"0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",[Ae]:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},Ge={[Pt]:{symbol:"USDT",decimals:18},[Je]:{symbol:"USDC",decimals:18}};var mr={[he]:56,[L]:8453,[ue]:84532,[me]:42161,[pe]:137,[de]:10,[ge]:43114,[ye]:1187947933,[fe]:324705682,[Ae]:1},pr={[_]:"https://api.dexter.cash/api/solana/rpc",[Fe]:"https://api.devnet.solana.com",[je]:"https://api.testnet.solana.com"},dr={[he]:"https://api.dexter.cash/api/evm/bsc/rpc",[L]:"https://api.dexter.cash/api/base/rpc",[ue]:"https://sepolia.base.org",[me]:"https://api.dexter.cash/api/evm/arbitrum/rpc",[pe]:"https://api.dexter.cash/api/evm/polygon/rpc",[de]:"https://api.dexter.cash/api/evm/optimism/rpc",[ge]:"https://api.dexter.cash/api/evm/avalanche/rpc",[ye]:"https://skale-base.skalenodes.com/v1/base",[fe]:"https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",[Ae]:"https://eth.llamarpc.com"},D="https://x402.dexter.cash";function we(e){return e.startsWith("solana:")||e==="solana"}function Tt(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 Rt(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 ve(e){return Tt(JSON.stringify(e))}function H(e){return JSON.parse(Rt(e))}function _t(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 q=class extends Error{status;body;constructor(t,r){super(`HTTP ${t}`),this.status=t,this.body=r}},Se=class{facilitatorUrl;cachedSupported=null;cacheTime=0;CACHE_TTL_MS=6e4;timeoutMs;maxRetries;retryBaseMs;constructor(t=D,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 q(s.status,await s.text());return s}catch(s){if(n=s,i<this.maxRetries-1&&_t(s)){let p=this.retryBaseMs*Math.pow(2,i);await new Promise(u=>setTimeout(u,p));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=H(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 q?`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=H(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 q?`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 Nt(e){if(we(e))return{address:be,decimals:6};let t=Ye[e];if(t){let r=Ge[t]?.decimals??6;return{address:t,decimals:r}}return{address:be,decimals:6}}function Ze(e){try{let t=H(e);return t?.accepted?.amount??t?.accepted?.maxAmountRequired}catch{return}}function z(e){let{payTo:t,facilitatorUrl:r=D,network:n=_,defaultTimeoutSeconds:i=60}=e,s=e.asset??Nt(n),p=e.scheme??"exact";if(p==="tab"&&!we(n))throw new Error(`scheme 'tab' is SVM-only; got network "${n}"`);let u=new Se(r),o=null,d=new Map,c=3e4,a=Date.now();function y(l){let h=(l.maxTimeoutSeconds||i)*1e3;if(d.set(l.payTo,{accept:l,expiresAt:Date.now()+h}),Date.now()-a>c){let A=Date.now();for(let[g,v]of d)v.expiresAt<A&&d.delete(g);a=A}}function m(l){let h=d.get(l);if(h){if(h.expiresAt<Date.now()){d.delete(l);return}return h.accept}}async function f(l){return typeof t=="string"?t:t(l||{})}async function w(){if(o||(o=await u.getNetworkExtra(n)),we(n)&&!o?.feePayer)throw new Error(`Facilitator does not provide feePayer for network "${n}"`);return{...o?.feePayer?{feePayer:o.feePayer}:{},decimals:o?.decimals??s.decimals,name:o?.name,version:o?.version,...p==="batch-settlement"&&o?.receiverAuthorizer?{receiverAuthorizer:o.receiverAuthorizer}:{},...p==="tab"?{voucherHeader:"x-tab-voucher",registrationEncoding:"base64(188-byte sessionRegisterMessage)"}:{}}}async function k(l,h){let{amountAtomic:A,timeoutSeconds:g=i}=h,v=await w(),b={scheme:p,network:n,amount:A,maxAmountRequired:A,asset:s.address,payTo:l,maxTimeoutSeconds:g,extra:v};return y(b),b}async function W(l){let h=await f({amountAtomic:l.amountAtomic,resourceUrl:l.resourceUrl});return k(h,l)}async function F(l){let{resourceUrl:h,description:A,mimeType:g="application/json"}=l,v={url:h,description:A,mimeType:g},b=await W(l);return{x402Version:2,resource:v,accepts:[b],error:"Payment required"}}function K(l){return ve(l)}function xe(l){return{status:402,headers:{"PAYMENT-REQUIRED":K(l)},body:{}}}async function j(l,h){if(!h){let A=await f({paymentHeader:l});h=m(A),h||(h=await k(A,{amountAtomic:Ze(l)??"0",resourceUrl:""}))}return u.verifyPayment(l,h)}async function X(l,h){if(!h){let A=await f({paymentHeader:l});h=m(A),h||(h=await k(A,{amountAtomic:Ze(l)??"0",resourceUrl:""}))}return u.settlePayment(l,h)}return{buildRequirements:F,encodeRequirements:K,create402Response:xe,verifyPayment:j,settlePayment:X,getPaymentAccept:W,network:n,assetDecimals:s.decimals,facilitator:u}}var It={"solana:mainnet":_};function et(e){let t=It[e.network];if(!t)throw new Error(`tabChallengeMiddleware: unsupported network "${e.network}"`);let r=typeof e.sellerPubkey=="string"?e.sellerPubkey:e.sellerPubkey.toBase58();new Qe.PublicKey(r);let n=z({payTo:r,network:t,scheme:"tab",facilitatorUrl:e.facilitatorUrl}),i=C(e.perUnit);return async(s,p,u)=>{if(s.headers[N])return u();try{let o=`${s.protocol}://${s.get("host")}${s.originalUrl}`,d=await n.buildRequirements({amountAtomic:i,resourceUrl:o,description:e.description}),c=n.create402Response(d);p.set(c.headers).status(c.status).json(c.body)}catch(o){let d=o?.message??String(o);p.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:d})}}}var tt=require("@solana/web3.js");var Ut={"solana:mainnet":_};function rt(e){let t=Ut[e.network];if(!t)throw new Error(`tabOrExactMiddleware: unsupported network "${e.network}"`);let r=typeof e.sellerPubkey=="string"?e.sellerPubkey:e.sellerPubkey.toBase58();new tt.PublicKey(r);let n=z({payTo:r,network:t,scheme:"tab",facilitatorUrl:e.facilitatorUrl}),i=z({payTo:r,network:t,scheme:"exact",facilitatorUrl:e.facilitatorUrl}),s=C(e.perUnit),p=oe({connection:e.connection,sellerPubkey:r,network:e.network,perUnit:e.perUnit,settle:"on-close",facilitatorUrl:e.facilitatorUrl});return async(u,o,d)=>{if(u.headers[N])return p(u,o,d);let c=`${u.protocol}://${u.get("host")}${u.originalUrl}`,a=u.headers["payment-signature"];if(a){let y;try{y=await i.getPaymentAccept({amountAtomic:s,resourceUrl:c,description:e.description})}catch(m){let f=m?.message??String(m);o.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:f});return}try{let m=await i.verifyPayment(a,y);if(!m.isValid){o.status(402).json({error:"Payment verification failed",reason:m.invalidReason});return}let f=await i.settlePayment(a,y);if(!f.success){o.status(402).json({error:"Payment settlement failed",reason:f.errorReason});return}return u.x402={transaction:f.transaction,payer:m.payer??"",network:f.network||t},o.setHeader("PAYMENT-RESPONSE",ve({success:!0,transaction:f.transaction,network:f.network||t,payer:m.payer??""})),d()}catch{o.status(500).json({error:"Payment processing error"});return}}try{let y={amountAtomic:s,resourceUrl:c,description:e.description},[m,f]=await Promise.all([n.buildRequirements(y),i.buildRequirements(y)]),w={...m,accepts:[...m.accepts,...f.accepts]};o.set({"PAYMENT-REQUIRED":n.encodeRequirements(w)}).status(402).json({error:"Payment required",accepts:w.accepts,resource:w.resource})}catch(y){let m=y?.message??String(y);o.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:m})}}}0&&(module.exports={FileChannelLedger,FileVoucherStore,InMemoryChannelLedger,InMemoryVoucherStore,InvalidRegistrationError,InvalidVoucherError,InvalidVoucherSignatureError,OnChainVerificationError,ScopeViolationError,TAB_VOUCHER_HEADER,enforceScope,openSse,parseRegistration,requireTab,tabChallengeMiddleware,tabMiddleware,tabOrExactMiddleware,verifyRegistrationOnChain,verifyVoucherSignature});
|
|
6
|
+
`),e.end())}return{charge:l,send:a,end:g}}var M=require("fs"),me=require("path");function Nt(e){return{payload:e.payload,sessionPublicKey:Oe(e.sessionPublicKey),sessionRegistration:Oe(e.sessionRegistration),sessionSignature:Oe(e.sessionSignature)}}function It(e){return{payload:e.payload,sessionPublicKey:$e(e.sessionPublicKey),sessionRegistration:$e(e.sessionRegistration),sessionSignature:$e(e.sessionSignature)}}function Oe(e){let t="";for(let r of e)t+=r.toString(16).padStart(2,"0");return t}function $e(e){if(e.length%2!==0)throw new Error(`hex length must be even, got ${e.length}`);let t=new Uint8Array(e.length/2);for(let r=0;r<t.length;r++)t[r]=parseInt(e.substr(r*2,2),16);return t}var le=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)}},ue=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,me.join)(this.dir,`${t}.json`)}async get(t){try{let r=await M.promises.readFile(this.pathFor(t),"utf8");return It(JSON.parse(r))}catch(r){if(r?.code==="ENOENT")return null;throw r}}async set(t,r){let n=this.pathFor(t);await M.promises.mkdir((0,me.dirname)(n),{recursive:!0});let i=`${n}.tmp`;await M.promises.writeFile(i,JSON.stringify(Nt(r))),await M.promises.rename(i,n)}async delete(t){try{await M.promises.unlink(this.pathFor(t))}catch(r){if(r?.code!=="ENOENT")throw r}}};var nt=require("@solana/web3.js");var R="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",Ye="solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",Ge="solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z";var H="eip155:8453",de="eip155:84532",pe="eip155:42161",he="eip155:137",ge="eip155:10",ye="eip155:43114",fe="eip155:56",Ae="eip155:1187947933",be="eip155:324705682",we="eip155:1";var ve="EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";var Ze="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",kt="0x55d398326f99059fF775485246999027B3197955",Qe="0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",et={[fe]:Qe,[H]:Ze,[de]:"0x036CbD53842c5426634e7929541eC2318f3dCF7e",[pe]:"0xaf88d065e77c8cC2239327C5EDb3A432268e5831",[he]:"0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",[ge]:"0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",[ye]:"0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",[Ae]:"0x85889c8c714505E0c94b30fcfcF64fE3Ac8FCb20",[be]:"0x2e08028E3C4c2356572E096d8EF835cD5C6030bD",[we]:"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"},tt={[kt]:{symbol:"USDT",decimals:18},[Qe]:{symbol:"USDC",decimals:18}};var fr={[fe]:56,[H]:8453,[de]:84532,[pe]:42161,[he]:137,[ge]:10,[ye]:43114,[Ae]:1187947933,[be]:324705682,[we]:1},Ar={[R]:"https://api.dexter.cash/api/solana/rpc",[Ye]:"https://api.devnet.solana.com",[Ge]:"https://api.testnet.solana.com"},br={[fe]:"https://api.dexter.cash/api/evm/bsc/rpc",[H]:"https://api.dexter.cash/api/base/rpc",[de]:"https://sepolia.base.org",[pe]:"https://api.dexter.cash/api/evm/arbitrum/rpc",[he]:"https://api.dexter.cash/api/evm/polygon/rpc",[ge]:"https://api.dexter.cash/api/evm/optimism/rpc",[ye]:"https://api.dexter.cash/api/evm/avalanche/rpc",[Ae]:"https://skale-base.skalenodes.com/v1/base",[be]:"https://base-sepolia-testnet.skalenodes.com/v1/jubilant-horrible-ancha",[we]:"https://eth.llamarpc.com"},F="https://x402.dexter.cash";function Se(e){return e.startsWith("solana:")||e==="solana"}function Ut(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 Ot(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 xe(e){return Ut(JSON.stringify(e))}function W(e){return JSON.parse(Ot(e))}function $t(e){if(e instanceof TypeError)return!0;if(e&&typeof e=="object"&&"status"in e){let t=e.status;return t>=500&&t<600}return!1}var j=class extends Error{status;body;constructor(t,r){super(`HTTP ${t}`),this.status=t,this.body=r}},Ce=class{facilitatorUrl;cachedSupported=null;cacheTime=0;CACHE_TTL_MS=6e4;timeoutMs;maxRetries;retryBaseMs;constructor(t=F,r){this.facilitatorUrl=t.replace(/\/$/,""),this.timeoutMs=r?.timeoutMs??1e4,this.maxRetries=r?.maxRetries??3,this.retryBaseMs=r?.retryBaseMs??500}async fetchWithTimeout(t,r){let n=new AbortController,i=setTimeout(()=>n.abort(),this.timeoutMs);try{return await fetch(t,{...r,signal:n.signal})}finally{clearTimeout(i)}}async fetchWithRetry(t,r){let n;for(let i=0;i<this.maxRetries;i++)try{let s=await this.fetchWithTimeout(t,r);if(!s.ok&&s.status>=500)throw new j(s.status,await s.text());return s}catch(s){if(n=s,i<this.maxRetries-1&&$t(s)){let h=this.retryBaseMs*Math.pow(2,i);await new Promise(c=>setTimeout(c,h));continue}throw s}throw n}async getSupported(){let t=Date.now();if(this.cachedSupported&&t-this.cacheTime<this.CACHE_TTL_MS)return this.cachedSupported;let r=await this.fetchWithTimeout(`${this.facilitatorUrl}/supported`);if(!r.ok)throw new Error(`Facilitator /supported returned ${r.status}`);return this.cachedSupported=await r.json(),this.cacheTime=t,this.cachedSupported}async getFeePayer(t){let n=(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval")&&i.network===t);if(!n)throw new Error(`Facilitator does not support network "${t}" with a recognized scheme`);return n.extra?.feePayer}async getNetworkExtra(t){return(await this.getSupported()).kinds.find(i=>i.x402Version===2&&(i.scheme==="exact"||i.scheme==="exact-approval"||i.scheme==="batch-settlement")&&i.network===t)?.extra}async verifyPayment(t,r){try{let n=W(t),i=await this.fetchWithRetry(`${this.facilitatorUrl}/verify`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:n,paymentRequirements:r})});return i.ok?await i.json():{isValid:!1,invalidReason:`facilitator_error_${i.status}`}}catch(n){return{isValid:!1,invalidReason:n instanceof j?`facilitator_error_${n.status}`:n instanceof Error&&n.name==="AbortError"?"facilitator_timeout":n instanceof Error?n.message:"unexpected_verify_error"}}}async settlePayment(t,r){try{let n=W(t),i=await this.fetchWithRetry(`${this.facilitatorUrl}/settle`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({x402Version:2,paymentPayload:n,paymentRequirements:r})});return i.ok?{...await i.json(),network:r.network}:{success:!1,network:r.network,errorReason:`facilitator_error_${i.status}`}}catch(n){let i=n instanceof j?`facilitator_error_${n.status}`:n instanceof Error&&n.name==="AbortError"?"facilitator_timeout":n instanceof Error?n.message:"unexpected_settle_error";return{success:!1,network:r.network,errorReason:i}}}};function Vt(e){if(Se(e))return{address:ve,decimals:6};let t=et[e];if(t){let r=tt[t]?.decimals??6;return{address:t,decimals:r}}return{address:ve,decimals:6}}function rt(e){try{let t=W(e);return t?.accepted?.amount??t?.accepted?.maxAmountRequired}catch{return}}function X(e){let{payTo:t,facilitatorUrl:r=F,network:n=R,defaultTimeoutSeconds:i=60}=e,s=e.asset??Vt(n),h=e.scheme??"exact";if(h==="tab"&&!Se(n))throw new Error(`scheme 'tab' is SVM-only; got network "${n}"`);let c=new Ce(r),o=null,d=new Map,l=3e4,a=Date.now();function g(u){let p=(u.maxTimeoutSeconds||i)*1e3;if(d.set(u.payTo,{accept:u,expiresAt:Date.now()+p}),Date.now()-a>l){let A=Date.now();for(let[x,k]of d)k.expiresAt<A&&d.delete(x);a=A}}function m(u){let p=d.get(u);if(p){if(p.expiresAt<Date.now()){d.delete(u);return}return p.accept}}async function f(u){return typeof t=="string"?t:t(u||{})}async function b(){if(o||(o=await c.getNetworkExtra(n)),Se(n)&&!o?.feePayer)throw new Error(`Facilitator does not provide feePayer for network "${n}"`);return{...o?.feePayer?{feePayer:o.feePayer}:{},decimals:o?.decimals??s.decimals,name:o?.name,version:o?.version,...h==="batch-settlement"&&o?.receiverAuthorizer?{receiverAuthorizer:o.receiverAuthorizer}:{},...h==="tab"?{voucherHeader:"x-tab-voucher",registrationEncoding:"base64(188-byte sessionRegisterMessage)"}:{}}}async function L(u,p){let{amountAtomic:A,timeoutSeconds:x=i}=p,k=await b(),U={scheme:h,network:n,amount:A,maxAmountRequired:A,asset:s.address,payTo:u,maxTimeoutSeconds:x,extra:k};return g(U),U}async function D(u){let p=await f({amountAtomic:u.amountAtomic,resourceUrl:u.resourceUrl});return L(p,u)}async function Ee(u){let{resourceUrl:p,description:A,mimeType:x="application/json"}=u,k={url:p,description:A,mimeType:x},U=await D(u);return{x402Version:2,resource:k,accepts:[U],error:"Payment required"}}function q(u){return xe(u)}function J(u){return{status:402,headers:{"PAYMENT-REQUIRED":q(u)},body:{}}}async function Pe(u,p){if(!p){let A=await f({paymentHeader:u});p=m(A),p||(p=await L(A,{amountAtomic:rt(u)??"0",resourceUrl:""}))}return c.verifyPayment(u,p)}async function Y(u,p){if(!p){let A=await f({paymentHeader:u});p=m(A),p||(p=await L(A,{amountAtomic:rt(u)??"0",resourceUrl:""}))}return c.settlePayment(u,p)}return{buildRequirements:Ee,encodeRequirements:q,create402Response:J,verifyPayment:Pe,settlePayment:Y,getPaymentAccept:D,network:n,assetDecimals:s.decimals,facilitator:c}}var Bt={"solana:mainnet":R};function it(e){let t=Bt[e.network];if(!t)throw new Error(`tabChallengeMiddleware: unsupported network "${e.network}"`);let r=typeof e.sellerPubkey=="string"?e.sellerPubkey:e.sellerPubkey.toBase58();new nt.PublicKey(r);let n=X({payTo:r,network:t,scheme:"tab",facilitatorUrl:e.facilitatorUrl}),i=E(e.perUnit);return async(s,h,c)=>{if(s.headers[I])return c();try{let o=`${s.protocol}://${s.get("host")}${s.originalUrl}`,d=await n.buildRequirements({amountAtomic:i,resourceUrl:o,description:e.description}),l=n.create402Response(d);h.set(l.headers).status(l.status).json(l.body)}catch(o){let d=o?.message??String(o);h.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:d})}}}var st=require("@solana/web3.js");var Kt={"solana:mainnet":R};function ot(e){let t=Kt[e.network];if(!t)throw new Error(`tabOrExactMiddleware: unsupported network "${e.network}"`);let r=typeof e.sellerPubkey=="string"?e.sellerPubkey:e.sellerPubkey.toBase58();new st.PublicKey(r);let n=X({payTo:r,network:t,scheme:"tab",facilitatorUrl:e.facilitatorUrl}),i=X({payTo:r,network:t,scheme:"exact",facilitatorUrl:e.facilitatorUrl}),s=E(e.perUnit),h=ce({connection:e.connection,sellerPubkey:r,network:e.network,perUnit:e.perUnit,settle:"on-close",facilitatorUrl:e.facilitatorUrl,lockCadence:e.lockCadence});return async(c,o,d)=>{if(c.headers[I])return h(c,o,d);let l=`${c.protocol}://${c.get("host")}${c.originalUrl}`,a=c.headers["payment-signature"];if(a){let g;try{g=await i.getPaymentAccept({amountAtomic:s,resourceUrl:l,description:e.description})}catch(m){let f=m?.message??String(m);o.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:f});return}try{let m=await i.verifyPayment(a,g);if(!m.isValid){o.status(402).json({error:"Payment verification failed",reason:m.invalidReason});return}let f=await i.settlePayment(a,g);if(!f.success){o.status(402).json({error:"Payment settlement failed",reason:f.errorReason});return}return c.x402={transaction:f.transaction,payer:m.payer??"",network:f.network||t},o.setHeader("PAYMENT-RESPONSE",xe({success:!0,transaction:f.transaction,network:f.network||t,payer:m.payer??""})),d()}catch{o.status(500).json({error:"Payment processing error"});return}}try{let g={amountAtomic:s,resourceUrl:l,description:e.description},[m,f]=await Promise.all([n.buildRequirements(g),i.buildRequirements(g)]),b={...m,accepts:[...m.accepts,...f.accepts]};o.set({"PAYMENT-REQUIRED":n.encodeRequirements(b)}).status(402).json({error:"Payment required",accepts:b.accepts,resource:b.resource})}catch(g){let m=g?.message??String(g);o.status(503).set({"Retry-After":"5"}).json({error:"challenge_unavailable",detail:m})}}}0&&(module.exports={FileChannelLedger,FileVoucherStore,InMemoryChannelLedger,InMemoryVoucherStore,InvalidRegistrationError,InvalidVoucherError,InvalidVoucherSignatureError,OnChainVerificationError,ScopeViolationError,TAB_VOUCHER_HEADER,enforceScope,openSse,parseRegistration,requireTab,tabChallengeMiddleware,tabMiddleware,tabOrExactMiddleware,verifyRegistrationOnChain,verifyVoucherSignature});
|
|
@@ -401,8 +401,19 @@ declare class OnChainVerificationError extends Error {
|
|
|
401
401
|
readonly reason: 'vault_not_found' | 'session_not_active' | 'session_pubkey_mismatch' | 'wrong_program';
|
|
402
402
|
constructor(reason: 'vault_not_found' | 'session_not_active' | 'session_pubkey_mismatch' | 'wrong_program', detail?: string);
|
|
403
403
|
}
|
|
404
|
+
/** The session's on-chain terminal odometers, read as a by-product of the
|
|
405
|
+
* first-voucher verification. `frontierAtomic` = max(spent, crystallized) —
|
|
406
|
+
* the floor below which no voucher can ever settle or lock again. The
|
|
407
|
+
* middleware seeds a FRESH channel's delivered baseline from it so a resumed
|
|
408
|
+
* session can't re-consume budget that already settled/crystallized. */
|
|
409
|
+
interface OnChainSessionFrontier {
|
|
410
|
+
frontierAtomic: AtomicAmount;
|
|
411
|
+
spentAtomic: AtomicAmount;
|
|
412
|
+
crystallizedCumulativeAtomic: AtomicAmount;
|
|
413
|
+
}
|
|
404
414
|
/**
|
|
405
|
-
* Verify a registration against on-chain state. Throws on any mismatch
|
|
415
|
+
* Verify a registration against on-chain state. Throws on any mismatch;
|
|
416
|
+
* on success returns the session's terminal odometers (frontier).
|
|
406
417
|
*
|
|
407
418
|
* V6: a session is its own PDA ([b"session", vault, allowed_counterparty]),
|
|
408
419
|
* NOT an inline field on the vault. We read that SessionAccount and confirm it
|
|
@@ -416,7 +427,7 @@ declare class OnChainVerificationError extends Error {
|
|
|
416
427
|
* configured at the commitment the buyer's registration was confirmed to (the
|
|
417
428
|
* adapter waits for visibility before openTab returns).
|
|
418
429
|
*/
|
|
419
|
-
declare function verifyRegistrationOnChain(connection: Connection, registration: ParsedRegistration): Promise<
|
|
430
|
+
declare function verifyRegistrationOnChain(connection: Connection, registration: ParsedRegistration): Promise<OnChainSessionFrontier>;
|
|
420
431
|
declare class InvalidVoucherSignatureError extends Error {
|
|
421
432
|
constructor(detail?: string);
|
|
422
433
|
}
|
|
@@ -504,6 +515,15 @@ interface TabOrExactConfig {
|
|
|
504
515
|
perUnit: HumanAmount;
|
|
505
516
|
facilitatorUrl?: string;
|
|
506
517
|
description?: string;
|
|
518
|
+
/**
|
|
519
|
+
* Keyless crystallization cadence for the tab rail — forwarded verbatim to
|
|
520
|
+
* `tabMiddleware` (see `TabMiddlewareOptions.lockCadence`). This is the
|
|
521
|
+
* seller's on-chain LockVoucher dial (mid-stream protection). Omitted → armed
|
|
522
|
+
* by default (`thresholdAtomic: humanToAtomic('0.10'), onClose: true`). Pass
|
|
523
|
+
* `{ onClose: false }` to disarm the close-time lock, or `{ thresholdAtomic }`
|
|
524
|
+
* to change the threshold cadence.
|
|
525
|
+
*/
|
|
526
|
+
lockCadence?: TabMiddlewareOptions['lockCadence'];
|
|
507
527
|
}
|
|
508
528
|
declare function tabOrExactMiddleware(config: TabOrExactConfig): RequestHandler;
|
|
509
529
|
|
|
@@ -401,8 +401,19 @@ declare class OnChainVerificationError extends Error {
|
|
|
401
401
|
readonly reason: 'vault_not_found' | 'session_not_active' | 'session_pubkey_mismatch' | 'wrong_program';
|
|
402
402
|
constructor(reason: 'vault_not_found' | 'session_not_active' | 'session_pubkey_mismatch' | 'wrong_program', detail?: string);
|
|
403
403
|
}
|
|
404
|
+
/** The session's on-chain terminal odometers, read as a by-product of the
|
|
405
|
+
* first-voucher verification. `frontierAtomic` = max(spent, crystallized) —
|
|
406
|
+
* the floor below which no voucher can ever settle or lock again. The
|
|
407
|
+
* middleware seeds a FRESH channel's delivered baseline from it so a resumed
|
|
408
|
+
* session can't re-consume budget that already settled/crystallized. */
|
|
409
|
+
interface OnChainSessionFrontier {
|
|
410
|
+
frontierAtomic: AtomicAmount;
|
|
411
|
+
spentAtomic: AtomicAmount;
|
|
412
|
+
crystallizedCumulativeAtomic: AtomicAmount;
|
|
413
|
+
}
|
|
404
414
|
/**
|
|
405
|
-
* Verify a registration against on-chain state. Throws on any mismatch
|
|
415
|
+
* Verify a registration against on-chain state. Throws on any mismatch;
|
|
416
|
+
* on success returns the session's terminal odometers (frontier).
|
|
406
417
|
*
|
|
407
418
|
* V6: a session is its own PDA ([b"session", vault, allowed_counterparty]),
|
|
408
419
|
* NOT an inline field on the vault. We read that SessionAccount and confirm it
|
|
@@ -416,7 +427,7 @@ declare class OnChainVerificationError extends Error {
|
|
|
416
427
|
* configured at the commitment the buyer's registration was confirmed to (the
|
|
417
428
|
* adapter waits for visibility before openTab returns).
|
|
418
429
|
*/
|
|
419
|
-
declare function verifyRegistrationOnChain(connection: Connection, registration: ParsedRegistration): Promise<
|
|
430
|
+
declare function verifyRegistrationOnChain(connection: Connection, registration: ParsedRegistration): Promise<OnChainSessionFrontier>;
|
|
420
431
|
declare class InvalidVoucherSignatureError extends Error {
|
|
421
432
|
constructor(detail?: string);
|
|
422
433
|
}
|
|
@@ -504,6 +515,15 @@ interface TabOrExactConfig {
|
|
|
504
515
|
perUnit: HumanAmount;
|
|
505
516
|
facilitatorUrl?: string;
|
|
506
517
|
description?: string;
|
|
518
|
+
/**
|
|
519
|
+
* Keyless crystallization cadence for the tab rail — forwarded verbatim to
|
|
520
|
+
* `tabMiddleware` (see `TabMiddlewareOptions.lockCadence`). This is the
|
|
521
|
+
* seller's on-chain LockVoucher dial (mid-stream protection). Omitted → armed
|
|
522
|
+
* by default (`thresholdAtomic: humanToAtomic('0.10'), onClose: true`). Pass
|
|
523
|
+
* `{ onClose: false }` to disarm the close-time lock, or `{ thresholdAtomic }`
|
|
524
|
+
* to change the threshold cadence.
|
|
525
|
+
*/
|
|
526
|
+
lockCadence?: TabMiddlewareOptions['lockCadence'];
|
|
507
527
|
}
|
|
508
528
|
declare function tabOrExactMiddleware(config: TabOrExactConfig): RequestHandler;
|
|
509
529
|
|