@dexterai/x402 5.3.0 → 5.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- "use strict";var W=Object.create;var P=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var L=Object.getOwnPropertyNames;var F=Object.getPrototypeOf,z=Object.prototype.hasOwnProperty;var G=(e,t)=>{for(var n in t)P(e,n,{get:t[n],enumerable:!0})},I=(e,t,n,i)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of L(t))!z.call(e,r)&&r!==n&&P(e,r,{get:()=>t[r],enumerable:!(i=H(t,r))||i.enumerable});return e};var C=(e,t,n)=>(n=e!=null?W(F(e)):{},I(t||!e||!e.__esModule?P(n,"default",{value:e,enumerable:!0}):n,e)),j=e=>I(P({},"__esModule",{value:!0}),e);var ie={};G(ie,{buildAdapterRegisterInstruction:()=>J,createSolanaVaultAdapter:()=>Z,deriveChannelId:()=>M,passkeySignerFromP256Keypair:()=>_});module.exports=j(ie);var o=require("@solana/web3.js");var y=require("@dexterai/vault/instructions"),b=require("@dexterai/vault/precompile"),m=require("@dexterai/vault/constants");var s=require("@dexterai/vault/messages");var x=C(require("tweetnacl"),1);var B=require("@noble/hashes/sha256");function R(){let e=x.default.sign.keyPair();return{publicKey:e.publicKey,privateKey:e.secretKey}}function D(e,t,n){return{publicKey:e.publicKey,privateKey:e.privateKey,scope:t,registration:n}}function V(e,t,n){if(n.length!==32)throw new Error(`channelIdBytes must be 32 bytes, got ${n.length}`);let i=BigInt(t.cumulativeAmount),r=BigInt(e.scope.maxAmountAtomic);if(i>r)throw new Error(`voucher cumulative ${i} exceeds session cap ${r}`);let a=Math.floor(Date.now()/1e3);if(a>=e.scope.expiresAtUnix)throw new Error(`session expired at ${e.scope.expiresAtUnix}, now ${a}`);let c=(0,s.voucherPayloadMessage)({channelId:n,cumulativeAmount:i,sequenceNumber:t.sequenceNumber}),l=x.default.sign.detached(c,e.privateKey);return{payload:t,sessionPublicKey:e.publicKey,sessionRegistration:e.registration,sessionSignature:l}}function K(e){if(!/^\d+$/.test(e))throw new Error(`atomic amount must be a non-negative integer string, got "${e}"`);return BigInt(e)}function M(e){let t=new Uint8Array(8);new DataView(t.buffer).setBigUint64(0,e.nonce,!0);let n=new TextEncoder().encode(e.sellerUrl),i=B.sha256.create();return i.update(e.vaultPda.toBytes()),i.update(n),i.update(t),i.digest()}var u=require("@dexterai/vault/session"),U=require("@noble/hashes/sha256");var T=require("@noble/curves/p256"),g=require("@noble/hashes/sha256"),N="dexter.cash";function q(e){return Buffer.from(e).toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function X(e,t=`https://${N}`){let i={type:"webauthn.get",challenge:q(e),origin:t,crossOrigin:!1};return new TextEncoder().encode(JSON.stringify(i))}function Y(e=1){let t=(0,g.sha256)(new TextEncoder().encode(N)),n=new Uint8Array(37);return n.set(t,0),n[32]=5,new DataView(n.buffer).setUint32(33,e,!1),n}function Q(e,t){let n=X(t),i=Y(1),r=new Uint8Array(i.length+32);r.set(i,0),r.set((0,g.sha256)(n),i.length);let a=(0,g.sha256)(r);return{signature:T.p256.sign(a,e.privateKey,{lowS:!0}).toCompactRawBytes(),clientDataJSON:n,authenticatorData:i}}function _(e){return{credentialId:new Uint8Array(0),publicKey:e.publicKey,signOperation:async t=>Q(e,(0,g.sha256)(t))}}function J(e){return(0,y.buildRegisterSessionKeyInstruction)({vaultPda:e.vaultPda,sessionPubkey:e.sessionPubkey,maxAmount:e.maxAmount,maxRevolvingCapacity:e.maxRevolvingCapacity,expiresAt:e.expiresAt,allowedCounterparty:e.allowedCounterparty,nonce:e.nonce,swigAddress:e.swigAddress,vaultUsdcAta:e.vaultUsdcAta,clientDataJSON:e.clientDataJSON,authenticatorData:e.authenticatorData,payer:e.payer,siblingSessionPdas:e.siblingSessionPdas})}var k=class{network="solana:mainnet";swigAddress;vaultPda;connection;vaultPdaKey;passkey;feePayer;confirmOptions;constructor(t){this.connection=t.connection,this.swigAddress=typeof t.swigAddress=="string"?t.swigAddress:t.swigAddress.toBase58(),this.vaultPdaKey=typeof t.vaultPda=="string"?new o.PublicKey(t.vaultPda):t.vaultPda,this.vaultPda=this.vaultPdaKey.toBase58(),this.passkey=t.passkeySigner,this.feePayer=t.feePayer,this.confirmOptions=t.confirmOptions??{commitment:"confirmed"}}async authorizeSession(t){let n=new o.PublicKey(t.allowedCounterparty),i=K(t.revolvingCapacityAtomic??t.maxAmountAtomic),r=R(),a=ee(),c=(0,s.sessionRegisterMessage)({programId:m.DEXTER_VAULT_PROGRAM_ID,vaultPda:this.vaultPdaKey,sessionPubkey:r.publicKey,maxAmount:K(t.maxAmountAtomic),maxRevolvingCapacity:i,expiresAt:BigInt(t.expiresAtUnix),allowedCounterparty:n,nonce:a}),{signature:l,clientDataJSON:d,authenticatorData:h}=await this.passkey.signOperation(c),S=E(h,(0,U.sha256)(d)),p=(0,b.buildSecp256r1VerifyInstruction)(this.passkey.publicKey,l,S),A=(0,u.sessionPdasOf)(await(0,u.fetchVaultSessionAccounts)(this.connection,this.vaultPdaKey)),w=await(0,u.resolveVaultUsdcAta)(this.connection,new o.PublicKey(this.swigAddress)),v=J({vaultPda:this.vaultPdaKey,swigAddress:new o.PublicKey(this.swigAddress),sessionPubkey:r.publicKey,maxAmount:K(t.maxAmountAtomic),maxRevolvingCapacity:i,expiresAt:BigInt(t.expiresAtUnix),allowedCounterparty:n,nonce:a,clientDataJSON:d,authenticatorData:h,payer:this.feePayer.publicKey,siblingSessionPdas:A,vaultUsdcAta:w}),f=new o.Transaction().add(p,v);f.feePayer=this.feePayer.publicKey;let{blockhash:O}=await this.connection.getLatestBlockhash(this.confirmOptions.commitment);f.recentBlockhash=O,f.sign(this.feePayer);let $=await this.connection.sendRawTransaction(f.serialize(),{skipPreflight:!1,preflightCommitment:this.confirmOptions.preflightCommitment??this.confirmOptions.commitment});return await this.connection.confirmTransaction({signature:$,blockhash:O,lastValidBlockHeight:(await this.connection.getLatestBlockhash(this.confirmOptions.commitment)).lastValidBlockHeight},this.confirmOptions.commitment),await(0,u.waitForSession)(this.connection,this.vaultPdaKey,n,{expectedSessionPubkey:r.publicKey,timeoutMs:2e4}),D(r,t,c)}async signWithSession(t,n){let i=await te(n.channelId);return V(t,n,i)}async signOpenTab(t,n){return t.registration}async signCloseTab(t,n,i){let r=(0,s.sessionRevokeMessage)({programId:m.DEXTER_VAULT_PROGRAM_ID,vaultPda:this.vaultPdaKey,sessionPubkey:t.publicKey}),{signature:a,clientDataJSON:c,authenticatorData:l}=await this.passkey.signOperation(r),d=E(l,(0,U.sha256)(c)),h=(0,b.buildSecp256r1VerifyInstruction)(this.passkey.publicKey,a,d),S=(0,y.buildRevokeSessionKeyInstruction)({vaultPda:this.vaultPdaKey,allowedCounterparty:new o.PublicKey(t.scope.allowedCounterparty),clientDataJSON:c,authenticatorData:l}),p=new o.Transaction().add(h,S);p.feePayer=this.feePayer.publicKey;let{blockhash:A,lastValidBlockHeight:w}=await this.connection.getLatestBlockhash(this.confirmOptions.commitment);p.recentBlockhash=A,p.sign(this.feePayer);let v=await this.connection.sendRawTransaction(p.serialize(),{skipPreflight:!1,preflightCommitment:this.confirmOptions.preflightCommitment??this.confirmOptions.commitment});return await this.connection.confirmTransaction({signature:v,blockhash:A,lastValidBlockHeight:w},this.confirmOptions.commitment),r}};function Z(e){return new k(e)}function E(e,t){let n=new Uint8Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n}function ee(){return Math.floor(Math.random()*4294967295)>>>0}async function te(e){if(/^[0-9a-f]{64}$/i.test(e))return ne(e);let{sha256:t}=await import("@noble/hashes/sha256");return t(new TextEncoder().encode(e))}function ne(e){let t=new Uint8Array(e.length/2);for(let n=0;n<t.length;n++)t[n]=parseInt(e.substr(n*2,2),16);return t}0&&(module.exports={buildAdapterRegisterInstruction,createSolanaVaultAdapter,deriveChannelId,passkeySignerFromP256Keypair});
1
+ "use strict";var me=Object.create;var M=Object.defineProperty;var de=Object.getOwnPropertyDescriptor;var ye=Object.getOwnPropertyNames;var ge=Object.getPrototypeOf,he=Object.prototype.hasOwnProperty;var Ae=(e,t)=>{for(var n in t)M(e,n,{get:t[n],enumerable:!0})},Y=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of ye(t))!he.call(e,i)&&i!==n&&M(e,i,{get:()=>t[i],enumerable:!(s=de(t,i))||s.enumerable});return e};var q=(e,t,n)=>(n=e!=null?me(ge(e)):{},Y(t||!e||!e.__esModule?M(n,"default",{value:e,enumerable:!0}):n,e)),fe=e=>Y(M({},"__esModule",{value:!0}),e);var Ie={};Ae(Ie,{LiveSessionExistsError:()=>R,TX_SIZE_LIMIT_BYTES:()=>$,buildAdapterRegisterInstruction:()=>pe,collectAltAddresses:()=>F,compileComposeV0:()=>J,createSelfPayingComposeSend:()=>N,createSolanaVaultAdapter:()=>Te,deriveChannelId:()=>te,passkeySignerFromP256Keypair:()=>ce});module.exports=fe(Ie);var v=require("@solana/web3.js");var R=class extends Error{constructor(n){super(`a LIVE session already exists for counterparty ${n.allowedCounterparty} (session ${n.sessionPubkeyHex.slice(0,16)}\u2026, expires ${n.expiresAtUnix}; on-chain spent=${n.spentAtomic}, crystallized=${n.crystallizedCumulativeAtomic}, frontier=${n.frontierAtomic}). Replacing it voids any signed-but-unsettled vouchers beyond the frontier. Settle the old tab first (tab.close() or POST its last voucher to /tab/settle), or pass onLiveSession: 'replace' to atomically revoke-then-register over it.`);this.details=n;this.name="LiveSessionExistsError"}};var O=require("@dexterai/vault/instructions"),V=require("@dexterai/vault/precompile"),I=require("@dexterai/vault/constants");var P=require("@dexterai/vault/messages");var z=q(require("tweetnacl"),1);var ee=require("@noble/hashes/sha256");function G(){let e=z.default.sign.keyPair();return{publicKey:e.publicKey,privateKey:e.secretKey}}function Z(e,t,n){return{publicKey:e.publicKey,privateKey:e.privateKey,scope:t,registration:n}}function Q(e,t,n){if(n.length!==32)throw new Error(`channelIdBytes must be 32 bytes, got ${n.length}`);let s=BigInt(t.cumulativeAmount),i=BigInt(e.scope.maxAmountAtomic);if(s>i)throw new Error(`voucher cumulative ${s} exceeds session cap ${i}`);let m=Math.floor(Date.now()/1e3);if(m>=e.scope.expiresAtUnix)throw new Error(`session expired at ${e.scope.expiresAtUnix}, now ${m}`);let r=(0,P.voucherPayloadMessage)({channelId:n,cumulativeAmount:s,sequenceNumber:t.sequenceNumber}),a=z.default.sign.detached(r,e.privateKey);return{payload:t,sessionPublicKey:e.publicKey,sessionRegistration:e.registration,sessionSignature:a}}function E(e){if(!/^\d+$/.test(e))throw new Error(`atomic amount must be a non-negative integer string, got "${e}"`);return BigInt(e)}function te(e){let t=new Uint8Array(8);new DataView(t.buffer).setBigUint64(0,e.nonce,!0);let n=new TextEncoder().encode(e.sellerUrl),s=ee.sha256.create();return s.update(e.vaultPda.toBytes()),s.update(n),s.update(t),s.digest()}var g=require("@dexterai/vault/session"),W=require("@noble/hashes/sha256"),ue=require("@noble/hashes/utils");var f=require("@solana/web3.js"),$=1232,Se=40,ne=20,se=4,be=20,_=1e4,we=1e6,B=4,L="[tab/solana/compose]";function F(e,t){let n=new Set,s=[],i=t.toBase58();for(let m of e)for(let r of m.keys){if(r.isSigner)continue;let a=r.pubkey.toBase58();a===i||n.has(a)||(n.add(a),s.push(r.pubkey))}return s}function J(e,t,n,s){let i=new f.TransactionMessage({payerKey:t,recentBlockhash:n,instructions:e}).compileToV0Message([s]);return new f.VersionedTransaction(i)}async function ie(e){try{let t=(await e.getRecentPrioritizationFees()).map(s=>s.prioritizationFee).filter(s=>s>0).sort((s,i)=>s-i);if(t.length===0)return _;let n=t[Math.floor(.75*(t.length-1))]??_;return Math.max(_,Math.min(n,we))}catch{return _}}function Pe(e){let t=e,n=String(t?.message??e??""),s=Array.isArray(t?.logs)?t.logs.join(" "):"";return/already in use/i.test(n)||/already in use/i.test(s)}function oe(e){let t=e;return(Array.isArray(t?.logs)?t.logs:[]).length===0&&/block height exceeded|has expired|blockhash not found/i.test(String(t?.message??e))}var H=e=>new Promise(t=>setTimeout(t,e));function N(e,t,n={}){let s=n.commitment??"confirmed",i=n.altWarmupPollMs??400,m=n.altReadbackPollMs??400,r=n.altCollisionPollMs??500,a=null,l=null;async function d(p,u){let c=await ie(e),b=[f.ComputeBudgetProgram.setComputeUnitPrice({microLamports:c}),...p],S;for(let y=0;y<B;y+=1){let{blockhash:A,lastValidBlockHeight:C}=await e.getLatestBlockhash(s),w=new f.Transaction().add(...b);w.feePayer=t.publicKey,w.recentBlockhash=A,w.sign(t);try{let o=await e.sendRawTransaction(w.serialize(),{skipPreflight:!1,maxRetries:5}),k=await e.confirmTransaction({signature:o,blockhash:A,lastValidBlockHeight:C},s);if(k.value.err)throw new Error(`${u} tx failed on-chain: ${JSON.stringify(k.value.err)}`);return o}catch(o){if(oe(o)&&y<B-1){console.warn(`${L} ${u} tx expired before landing (attempt ${y+1}) \u2014 rebroadcasting with a fresh blockhash`),S=o;continue}throw o}}throw S??new Error(`${u} tx did not land after rebroadcast attempts`)}async function K(p){for(let u=0;u<be;u+=1){let c=await e.getSlot("finalized");if(c>p)return c;await H(r)}throw new Error(`ALT collision retry: finalized slot never advanced past ${p}`)}async function h(p){for(let u=0;u<Se;u+=1){if(await e.getSlot(s)>p)return;await H(i)}throw new Error(`ALT warmup timed out: preflight (${s}) slot never passed lastExtendedSlot ${p}`)}async function x(p){if(a)return a;let u=F(p,t.publicKey),c=null,b=null,S=-1;for(let A=0;A<se;A+=1){let C=S<0?await e.getSlot("finalized"):await K(S),[w,o]=f.AddressLookupTableProgram.createLookupTable({authority:t.publicKey,payer:t.publicKey,recentSlot:C}),k=f.AddressLookupTableProgram.extendLookupTable({payer:t.publicKey,authority:t.publicKey,lookupTable:o,addresses:u});try{b=await d([w,k],"ALT create/extend"),c=o;break}catch(j){if(Pe(j)&&A<se-1){S=C,console.warn(`${L} ALT address collision at slot ${C} (attempt ${A+1}) \u2014 retrying create with a fresh finalized slot`);continue}throw j}}if(!c||!b)throw new Error("ALT create exhausted retries after repeated address collisions");let y=await e.getAddressLookupTable(c);for(let A=0;A<ne&&!y.value;A+=1)await H(m),y=await e.getAddressLookupTable(c);if(!y.value)throw new Error(`ALT ${c.toBase58()} not visible after ${ne} read polls (${b})`);return await h(y.value.state.lastExtendedSlot),a=y.value,l=c,console.info(`${L} ephemeral compose ALT ready: ${c.toBase58()} (${u.length} addresses, createTx ${b})`),a}async function T(p){let u=await ie(e),c=[f.ComputeBudgetProgram.setComputeUnitPrice({microLamports:u}),...p],b=await x(c),S;for(let y=0;y<B;y+=1){let{blockhash:A,lastValidBlockHeight:C}=await e.getLatestBlockhash(s),w;try{let o=J(c,t.publicKey,A,b);o.sign([t]),w=o.serialize()}catch(o){throw/overrun|too large/i.test(String(o?.message??o))?new Error(`composed revoke-then-register v0 tx exceeds the ${$}B wire cap \u2014 too many sibling PDAs outside the lookup table`):o}if(w.length>$)throw new Error(`composed revoke-then-register v0 tx ${w.length}B exceeds the ${$}B wire cap \u2014 too many sibling PDAs outside the lookup table`);try{let o=await e.sendRawTransaction(w,{skipPreflight:!1,maxRetries:5}),k=await e.confirmTransaction({signature:o,blockhash:A,lastValidBlockHeight:C},s);if(k.value.err)throw new Error(`composed tx failed on-chain: ${JSON.stringify(k.value.err)}`);return o}catch(o){if(oe(o)&&y<B-1){console.warn(`${L} compose tx expired before landing (attempt ${y+1}, priorityFee ${u}) \u2014 rebroadcasting with a fresh blockhash`),S=o;continue}let k=Array.isArray(o?.logs)?o.logs:[];throw k.length?new Error(`${o?.message??o} | ${k.join(" | ")}`):o}}throw S instanceof Error?S:new Error("compose tx did not land after rebroadcast attempts")}async function U(){if(l)try{let p=f.AddressLookupTableProgram.deactivateLookupTable({lookupTable:l,authority:t.publicKey}),u=await d([p],"ALT deactivate");console.info(`${L} ephemeral compose ALT deactivated: ${l.toBase58()} (${u}) \u2014 rent reclaimable via close_lookup_table after the deactivation cooldown`)}catch(p){console.warn(`${L} ALT deactivate failed for ${l?.toBase58()} \u2014 rent parks until a later cleanup retries (the compose already landed): ${String(p?.message??p)}`)}}return{send:T,getAltAddress:()=>l,deactivateAlt:U}}var re=require("@noble/curves/p256"),D=require("@noble/hashes/sha256"),ae="dexter.cash";function ve(e){return Buffer.from(e).toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function xe(e,t=`https://${ae}`){let s={type:"webauthn.get",challenge:ve(e),origin:t,crossOrigin:!1};return new TextEncoder().encode(JSON.stringify(s))}function ke(e=1){let t=(0,D.sha256)(new TextEncoder().encode(ae)),n=new Uint8Array(37);return n.set(t,0),n[32]=5,new DataView(n.buffer).setUint32(33,e,!1),n}function Ke(e,t){let n=xe(t),s=ke(1),i=new Uint8Array(s.length+32);i.set(s,0),i.set((0,D.sha256)(n),s.length);let m=(0,D.sha256)(i);return{signature:re.p256.sign(m,e.privateKey,{lowS:!0}).toCompactRawBytes(),clientDataJSON:n,authenticatorData:s}}function ce(e){return{credentialId:new Uint8Array(0),publicKey:e.publicKey,signOperation:async t=>Ke(e,(0,D.sha256)(t))}}function pe(e){return(0,O.buildRegisterSessionKeyInstruction)({vaultPda:e.vaultPda,sessionPubkey:e.sessionPubkey,maxAmount:e.maxAmount,maxRevolvingCapacity:e.maxRevolvingCapacity,expiresAt:e.expiresAt,allowedCounterparty:e.allowedCounterparty,nonce:e.nonce,swigAddress:e.swigAddress,vaultUsdcAta:e.vaultUsdcAta,clientDataJSON:e.clientDataJSON,authenticatorData:e.authenticatorData,payer:e.payer,siblingSessionPdas:e.siblingSessionPdas})}var X=class{network="solana:mainnet";swigAddress;vaultPda;connection;vaultPdaKey;passkey;feePayer;confirmOptions;seams;constructor(t){this.connection=t.connection,this.swigAddress=typeof t.swigAddress=="string"?t.swigAddress:t.swigAddress.toBase58(),this.vaultPdaKey=typeof t.vaultPda=="string"?new v.PublicKey(t.vaultPda):t.vaultPda,this.vaultPda=this.vaultPdaKey.toBase58(),this.passkey=t.passkeySigner,this.feePayer=t.feePayer,this.confirmOptions=t.confirmOptions??{commitment:"confirmed"},this.seams=t.seams??{}}async authorizeSession(t,n){let s=new v.PublicKey(t.allowedCounterparty),i=E(t.revolvingCapacityAtomic??t.maxAmountAtomic),r=await(this.seams.fetchSession??g.fetchSessionAccount)(this.connection,this.vaultPdaKey,s),a=r!==null&&(0,g.isSessionLive)(r);if(a&&(n?.onLiveSession??"error")!=="replace"){let T=r.session.spent,U=r.session.crystallizedCumulative;throw new R({allowedCounterparty:t.allowedCounterparty,sessionPubkeyHex:(0,ue.bytesToHex)(r.session.sessionPubkey),expiresAtUnix:r.session.expiresAt,spentAtomic:T.toString(),crystallizedCumulativeAtomic:U.toString(),currentOutstandingAtomic:r.session.currentOutstanding.toString(),frontierAtomic:(T>U?T:U).toString()})}let l=G(),d=Ue(),K=(0,P.sessionRegisterMessage)({programId:I.DEXTER_VAULT_PROGRAM_ID,vaultPda:this.vaultPdaKey,sessionPubkey:l.publicKey,maxAmount:E(t.maxAmountAtomic),maxRevolvingCapacity:i,expiresAt:BigInt(t.expiresAtUnix),allowedCounterparty:s,nonce:d}),h=await this.passkey.signOperation(K);return a?await this.sendAtomicReplace(r,t,s,l.publicKey,d,i,h):await this.sendBareRegister(t,s,l.publicKey,d,i,h),await(this.seams.waitForSession??g.waitForSession)(this.connection,this.vaultPdaKey,s,{expectedSessionPubkey:l.publicKey,timeoutMs:2e4}),Z(l,t,K)}async sendBareRegister(t,n,s,i,m,r){let{signature:a,clientDataJSON:l,authenticatorData:d}=r,K=le(d,(0,W.sha256)(l)),h=(0,V.buildSecp256r1VerifyInstruction)(this.passkey.publicKey,a,K),x=this.seams.fetchSessions??g.fetchVaultSessionAccounts,T=(0,g.sessionPdasOf)(await x(this.connection,this.vaultPdaKey)),p=await(this.seams.resolveUsdcAta??g.resolveVaultUsdcAta)(this.connection,new v.PublicKey(this.swigAddress)),u=pe({vaultPda:this.vaultPdaKey,swigAddress:new v.PublicKey(this.swigAddress),sessionPubkey:s,maxAmount:E(t.maxAmountAtomic),maxRevolvingCapacity:m,expiresAt:BigInt(t.expiresAtUnix),allowedCounterparty:n,nonce:i,clientDataJSON:l,authenticatorData:d,payer:this.feePayer.publicKey,siblingSessionPdas:T,vaultUsdcAta:p}),c=new v.Transaction().add(h,u);c.feePayer=this.feePayer.publicKey;let{blockhash:b}=await this.connection.getLatestBlockhash(this.confirmOptions.commitment);c.recentBlockhash=b,c.sign(this.feePayer);let S=await this.connection.sendRawTransaction(c.serialize(),{skipPreflight:!1,preflightCommitment:this.confirmOptions.preflightCommitment??this.confirmOptions.commitment});await this.connection.confirmTransaction({signature:S,blockhash:b,lastValidBlockHeight:(await this.connection.getLatestBlockhash(this.confirmOptions.commitment)).lastValidBlockHeight},this.confirmOptions.commitment)}async sendAtomicReplace(t,n,s,i,m,r,a){let l=(0,P.sessionRevokeMessage)({programId:I.DEXTER_VAULT_PROGRAM_ID,vaultPda:this.vaultPdaKey,sessionPubkey:t.session.sessionPubkey}),d=await this.passkey.signOperation(l),h=await(this.seams.resolveUsdcAta??g.resolveVaultUsdcAta)(this.connection,new v.PublicKey(this.swigAddress)),x=this.seams.composeSend?{send:this.seams.composeSend,deactivateAlt:async()=>{}}:N(this.connection,this.feePayer,{commitment:this.confirmOptions.commitment});try{await(0,g.composeRevokeThenRegister)({connection:this.connection,vaultPda:this.vaultPdaKey,allowedCounterparty:s,registerArgs:{sessionPubkey:i,maxAmount:E(n.maxAmountAtomic),maxRevolvingCapacity:r,expiresAt:BigInt(n.expiresAtUnix),nonce:m,swigAddress:new v.PublicKey(this.swigAddress),vaultUsdcAta:h,payer:this.feePayer.publicKey},registerCeremony:{clientDataJSON:a.clientDataJSON,authenticatorData:a.authenticatorData,signature:a.signature},revokeCeremony:{clientDataJSON:d.clientDataJSON,authenticatorData:d.authenticatorData,signature:d.signature},credentialPublicKey:this.passkey.publicKey,send:x.send,fetchSession:this.seams.fetchSession,fetchSessions:this.seams.fetchSessions})}finally{x.deactivateAlt()}}async signWithSession(t,n){let s=await Ce(n.channelId);return Q(t,n,s)}async signOpenTab(t,n){return t.registration}async signCloseTab(t,n,s){let i=(0,P.sessionRevokeMessage)({programId:I.DEXTER_VAULT_PROGRAM_ID,vaultPda:this.vaultPdaKey,sessionPubkey:t.publicKey}),{signature:m,clientDataJSON:r,authenticatorData:a}=await this.passkey.signOperation(i),l=le(a,(0,W.sha256)(r)),d=(0,V.buildSecp256r1VerifyInstruction)(this.passkey.publicKey,m,l),K=(0,O.buildRevokeSessionKeyInstruction)({vaultPda:this.vaultPdaKey,allowedCounterparty:new v.PublicKey(t.scope.allowedCounterparty),clientDataJSON:r,authenticatorData:a}),h=new v.Transaction().add(d,K);h.feePayer=this.feePayer.publicKey;let{blockhash:x,lastValidBlockHeight:T}=await this.connection.getLatestBlockhash(this.confirmOptions.commitment);h.recentBlockhash=x,h.sign(this.feePayer);let U=await this.connection.sendRawTransaction(h.serialize(),{skipPreflight:!1,preflightCommitment:this.confirmOptions.preflightCommitment??this.confirmOptions.commitment});return await this.connection.confirmTransaction({signature:U,blockhash:x,lastValidBlockHeight:T},this.confirmOptions.commitment),i}};function Te(e){return new X(e)}function le(e,t){let n=new Uint8Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n}function Ue(){return Math.floor(Math.random()*4294967295)>>>0}async function Ce(e){if(/^[0-9a-f]{64}$/i.test(e))return Oe(e);let{sha256:t}=await import("@noble/hashes/sha256");return t(new TextEncoder().encode(e))}function Oe(e){let t=new Uint8Array(e.length/2);for(let n=0;n<t.length;n++)t[n]=parseInt(e.substr(n*2,2),16);return t}0&&(module.exports={LiveSessionExistsError,TX_SIZE_LIMIT_BYTES,buildAdapterRegisterInstruction,collectAltAddresses,compileComposeV0,createSelfPayingComposeSend,createSolanaVaultAdapter,deriveChannelId,passkeySignerFromP256Keypair});
@@ -1,6 +1,7 @@
1
- import * as _solana_web3_js from '@solana/web3.js';
2
- import { PublicKey, Connection, Signer, ConfirmOptions } from '@solana/web3.js';
3
- import { V as VaultAdapter } from '../../../types-D5eKDMvo.cjs';
1
+ import { PublicKey, Connection, Signer, Commitment, TransactionInstruction, AddressLookupTableAccount, VersionedTransaction, ConfirmOptions } from '@solana/web3.js';
2
+ import { V as VaultAdapter } from '../../../types-CSuISjXA.cjs';
3
+ export { A as AuthorizeSessionOptions, L as LiveSessionDetails, d as LiveSessionExistsError } from '../../../types-CSuISjXA.cjs';
4
+ import { fetchSessionAccount, fetchVaultSessionAccounts, resolveVaultUsdcAta, waitForSession } from '@dexterai/vault/session';
4
5
  import { PasskeySignerWithPublicKey } from '@dexterai/vault/signers';
5
6
  export { PasskeySignerWithPublicKey as PasskeySigner } from '@dexterai/vault/signers';
6
7
  import '@dexterai/vault/types';
@@ -72,6 +73,133 @@ interface P256Keypair {
72
73
  */
73
74
  declare function passkeySignerFromP256Keypair(kp: P256Keypair): PasskeySignerWithPublicKey;
74
75
 
76
+ /**
77
+ * createSelfPayingComposeSend — the CLIENT-SIDE v0 + Address-Lookup-Table
78
+ * transport for the atomic revoke-then-register compose (K-T4e).
79
+ *
80
+ * WHY THIS EXISTS: K-T4a proved the atomic single-tx revoke-then-register
81
+ * ([secp(revoke), revoke, secp(register), register]) OVERFLOWS the legacy
82
+ * 1232-byte wire cap even at ZERO siblings — it measures 1347 B and web3.js
83
+ * `Transaction.serialize()` itself throws (size proof:
84
+ * dexter-vault-sdk tests/session.composeTxSize.test.ts; constants reused
85
+ * here, not re-derived). The LIVE (revoke-composed) path must therefore
86
+ * assemble a v0 `VersionedTransaction` with an ephemeral address lookup
87
+ * table holding every non-signer account of the composed instructions
88
+ * (vault, target session PDA, vaultUsdcAta, swig, swig wallet PDA, sysvar,
89
+ * system program, sibling session PDAs) — 1166–1174 B on-chain-proven. The
90
+ * register-only (not-live) path stays on the adapter's legacy send (937 B)
91
+ * and never routes here.
92
+ *
93
+ * SELF-PAYING vs SPONSORED: this is the buyer-side twin of dexter-api's
94
+ * sponsor-owned K-T4b transport (dexter-api src/vault/revokeRegisterCompose.ts,
95
+ * mainnet-hardened 2026-07-06). Here the adapter's `feePayer` — the buyer's
96
+ * own key on the loop's self-paying path, or a sponsor key when a caller
97
+ * routes one in — pays the fee AND owns the ephemeral ALT. Either way the
98
+ * payer holds ZERO authority over the vault: register/revoke authorize on
99
+ * the passkey secp siblings, and the program validates every account by
100
+ * seeds/address constraint, so the ALT is an encoding optimization, not a
101
+ * trust surface.
102
+ *
103
+ * MAINNET-HARDENING mirrored from the proven K-T4b transport (each was
104
+ * forced by a live failure on 2026-07-06):
105
+ * - PRIORITY FEE (p75 of recent, floored/capped): a fee-less compose is
106
+ * dropped under congestion and expires unlanded — a CU limit alone buys
107
+ * nothing, only a price does.
108
+ * - FRESH-BLOCKHASH REBROADCAST on expiry-only: an expired-blockhash
109
+ * signature is permanently dead on Solana, so rebroadcasting under a new
110
+ * blockhash cannot double-land. On-chain errors (logs present) surface
111
+ * immediately — deterministic failures are never retried.
112
+ * - ALT READ-BACK POLL: the create+extend confirms, but the ALT ACCOUNT can
113
+ * lag a load-balanced RPC — a one-shot read spuriously fails a legitimate
114
+ * replace.
115
+ * - ALT-ADDRESS COLLISION RETRY: createLookupTable derives from
116
+ * [authority, recentSlot]; two concurrent composes reading the same
117
+ * finalized slot collide — retry with a fresh finalized slot.
118
+ *
119
+ * TWO PREFLIGHT-BANK RULES (K-T4a, honored verbatim):
120
+ * (a) the ALT-extend must be OBSERVED by the bank preflight simulates
121
+ * against, or the compose preflights "invalid index" — poll getSlot at
122
+ * the preflight commitment until it passes lastExtendedSlot;
123
+ * (b) the v0 blockhash must be fetched AT the preflight commitment, or the
124
+ * preflight bank reports "Blockhash not found".
125
+ */
126
+
127
+ /** Solana's hard on-the-wire transaction cap (IPv6 MTU 1280 − 48). */
128
+ declare const TX_SIZE_LIMIT_BYTES = 1232;
129
+ interface SelfPayingComposeSendOptions {
130
+ /** Commitment the preflight bank rules key on. Default 'confirmed' —
131
+ * matching the adapter's default confirm options. */
132
+ commitment?: Commitment;
133
+ /** Poll intervals (test seams; production defaults match K-T4b). */
134
+ altWarmupPollMs?: number;
135
+ altReadbackPollMs?: number;
136
+ altCollisionPollMs?: number;
137
+ }
138
+ interface SelfPayingComposeSend {
139
+ /**
140
+ * `send` transport for `composeRevokeThenRegister`: receives the FULL
141
+ * composed instruction list, lazily provisions + warms the ephemeral ALT
142
+ * on the first call (reused on retries), builds the v0 tx, sends with
143
+ * preflight ON, confirms, and returns the signature. Throws with the
144
+ * program error text + simulation logs intact (registerSessionWithRetry's
145
+ * IncompleteSessionSet / SessionAccountsNotSorted matcher needs them).
146
+ */
147
+ send: (instructions: TransactionInstruction[]) => Promise<string>;
148
+ /** The ephemeral ALT address once created, else null. */
149
+ getAltAddress: () => PublicKey | null;
150
+ /**
151
+ * Fire-and-forget cleanup: deactivate the ephemeral ALT so its rent
152
+ * becomes reclaimable by a later `close_lookup_table` (close requires the
153
+ * ~513-slot deactivation cooldown, so it cannot run inline). No-op when no
154
+ * ALT was created. NEVER throws — cleanup failure must not fail the
155
+ * money op that already landed.
156
+ */
157
+ deactivateAlt: () => Promise<void>;
158
+ }
159
+ /**
160
+ * The accounts the ephemeral ALT must hold: every NON-SIGNER account meta
161
+ * referenced by the composed instructions, deduped, minus the fee payer.
162
+ * Extracting straight from the instruction list is exact-by-construction —
163
+ * no re-derivation of vault accounts in this module. Signers MUST stay
164
+ * static; invoked program ids are never in `ix.keys`, so they never enter
165
+ * the ALT (and web3.js keeps invoked programs static regardless).
166
+ */
167
+ declare function collectAltAddresses(instructions: TransactionInstruction[], feePayer: PublicKey): PublicKey[];
168
+ /** Compile the composed instruction list into a v0 tx backed by `alt`. */
169
+ declare function compileComposeV0(instructions: TransactionInstruction[], feePayer: PublicKey, recentBlockhash: string, alt: AddressLookupTableAccount): VersionedTransaction;
170
+ /**
171
+ * Build a self-paying LIVE-compose transport bound to `conn` + `feePayer`.
172
+ * The ALT is created from the FIRST attempt's account set and reused across
173
+ * registerSessionWithRetry retries; a sibling that appears between the
174
+ * ALT-extend and a later attempt rides as a static key (+33 B) — still
175
+ * within cap below a couple of unlisted siblings.
176
+ */
177
+ declare function createSelfPayingComposeSend(conn: Connection, feePayer: Signer, options?: SelfPayingComposeSendOptions): SelfPayingComposeSend;
178
+
179
+ /**
180
+ * Solana VaultAdapter — production implementation against the deployed
181
+ * dexter-vault v2 program on Solana mainnet.
182
+ *
183
+ * Two passkey signing paths are supported via the `passkeySigner` field,
184
+ * both conforming to vault's canonical `PasskeySignerWithPublicKey`:
185
+ * - CLI/Node: a noble-curves P-256 signer wrapping a local keypair
186
+ * (`passkeySignerFromP256Keypair` in `./passkey-noble.ts`).
187
+ * - Browser: vault's `DexterApiBrowserPasskeySigner` drops in with no shim.
188
+ *
189
+ * The adapter's job is to (a) take the buyer's session scope, (b) get a
190
+ * passkey signature endorsing it, (c) submit the on-chain
191
+ * register_session_key tx so the seller can verify the endorsement, (d)
192
+ * expose voucher signing for the session, and (e) tear the session down
193
+ * at close.
194
+ *
195
+ * The adapter does NOT touch pending_voucher_count. That counter belongs
196
+ * to the facilitator's dexter_authority and is decremented inside the
197
+ * facilitator's `POST /tab/settle` tx (via the new vault.settle_tab_voucher
198
+ * instruction) atomically with the USDC transfer. The SDK's `Tab.close()`
199
+ * POSTs the final voucher to the facilitator; this adapter only owns the
200
+ * passkey-signed session register/revoke layer.
201
+ */
202
+
75
203
  interface CreateSolanaVaultAdapterOptions {
76
204
  /** RPC the adapter uses to submit txs. The buyer can pass their own
77
205
  * connection (browser wallet RPC, Helius URL, etc.) — the adapter has
@@ -95,6 +223,23 @@ interface CreateSolanaVaultAdapterOptions {
95
223
  * match production code (FE/API). For test suites, override to
96
224
  * 'finalized' — see reference_anchor_test_commitment in repo memory. */
97
225
  confirmOptions?: ConfirmOptions;
226
+ /** Testing/production seams (default: the real chain readers + the
227
+ * self-paying v0+ALT compose transport). Same seam idiom as
228
+ * @dexterai/vault's session helpers. */
229
+ seams?: SolanaAdapterSeams;
230
+ }
231
+ /** Injectable chain-reader/transport seams for the Solana adapter. */
232
+ interface SolanaAdapterSeams {
233
+ fetchSession?: typeof fetchSessionAccount;
234
+ fetchSessions?: typeof fetchVaultSessionAccounts;
235
+ resolveUsdcAta?: typeof resolveVaultUsdcAta;
236
+ waitForSession?: typeof waitForSession;
237
+ /** Atomic-compose transport override: receives the FULL composed
238
+ * instruction list ([secp(revoke), revoke, secp(register), register]),
239
+ * must send + confirm ATOMICALLY in one transaction. Production default:
240
+ * `createSelfPayingComposeSend` (v0+ALT — the compose does NOT fit a
241
+ * legacy transaction, K-T4a). */
242
+ composeSend?: (instructions: TransactionInstruction[]) => Promise<string>;
98
243
  }
99
244
  interface AdapterRegisterIxParams {
100
245
  vaultPda: PublicKey;
@@ -118,8 +263,8 @@ interface AdapterRegisterIxParams {
118
263
  * the derive-and-probe decision. The adapter no longer derives it locally. */
119
264
  vaultUsdcAta: PublicKey | null;
120
265
  }
121
- declare function buildAdapterRegisterInstruction(p: AdapterRegisterIxParams): _solana_web3_js.TransactionInstruction;
266
+ declare function buildAdapterRegisterInstruction(p: AdapterRegisterIxParams): TransactionInstruction;
122
267
  /** Factory entry point. */
123
268
  declare function createSolanaVaultAdapter(opts: CreateSolanaVaultAdapterOptions): VaultAdapter;
124
269
 
125
- export { type AdapterRegisterIxParams, type CreateSolanaVaultAdapterOptions, buildAdapterRegisterInstruction, createSolanaVaultAdapter, deriveChannelId, passkeySignerFromP256Keypair };
270
+ export { type AdapterRegisterIxParams, type CreateSolanaVaultAdapterOptions, type SelfPayingComposeSend, type SelfPayingComposeSendOptions, type SolanaAdapterSeams, TX_SIZE_LIMIT_BYTES, buildAdapterRegisterInstruction, collectAltAddresses, compileComposeV0, createSelfPayingComposeSend, createSolanaVaultAdapter, deriveChannelId, passkeySignerFromP256Keypair };
@@ -1,6 +1,7 @@
1
- import * as _solana_web3_js from '@solana/web3.js';
2
- import { PublicKey, Connection, Signer, ConfirmOptions } from '@solana/web3.js';
3
- import { V as VaultAdapter } from '../../../types-D5eKDMvo.js';
1
+ import { PublicKey, Connection, Signer, Commitment, TransactionInstruction, AddressLookupTableAccount, VersionedTransaction, ConfirmOptions } from '@solana/web3.js';
2
+ import { V as VaultAdapter } from '../../../types-CSuISjXA.js';
3
+ export { A as AuthorizeSessionOptions, L as LiveSessionDetails, d as LiveSessionExistsError } from '../../../types-CSuISjXA.js';
4
+ import { fetchSessionAccount, fetchVaultSessionAccounts, resolveVaultUsdcAta, waitForSession } from '@dexterai/vault/session';
4
5
  import { PasskeySignerWithPublicKey } from '@dexterai/vault/signers';
5
6
  export { PasskeySignerWithPublicKey as PasskeySigner } from '@dexterai/vault/signers';
6
7
  import '@dexterai/vault/types';
@@ -72,6 +73,133 @@ interface P256Keypair {
72
73
  */
73
74
  declare function passkeySignerFromP256Keypair(kp: P256Keypair): PasskeySignerWithPublicKey;
74
75
 
76
+ /**
77
+ * createSelfPayingComposeSend — the CLIENT-SIDE v0 + Address-Lookup-Table
78
+ * transport for the atomic revoke-then-register compose (K-T4e).
79
+ *
80
+ * WHY THIS EXISTS: K-T4a proved the atomic single-tx revoke-then-register
81
+ * ([secp(revoke), revoke, secp(register), register]) OVERFLOWS the legacy
82
+ * 1232-byte wire cap even at ZERO siblings — it measures 1347 B and web3.js
83
+ * `Transaction.serialize()` itself throws (size proof:
84
+ * dexter-vault-sdk tests/session.composeTxSize.test.ts; constants reused
85
+ * here, not re-derived). The LIVE (revoke-composed) path must therefore
86
+ * assemble a v0 `VersionedTransaction` with an ephemeral address lookup
87
+ * table holding every non-signer account of the composed instructions
88
+ * (vault, target session PDA, vaultUsdcAta, swig, swig wallet PDA, sysvar,
89
+ * system program, sibling session PDAs) — 1166–1174 B on-chain-proven. The
90
+ * register-only (not-live) path stays on the adapter's legacy send (937 B)
91
+ * and never routes here.
92
+ *
93
+ * SELF-PAYING vs SPONSORED: this is the buyer-side twin of dexter-api's
94
+ * sponsor-owned K-T4b transport (dexter-api src/vault/revokeRegisterCompose.ts,
95
+ * mainnet-hardened 2026-07-06). Here the adapter's `feePayer` — the buyer's
96
+ * own key on the loop's self-paying path, or a sponsor key when a caller
97
+ * routes one in — pays the fee AND owns the ephemeral ALT. Either way the
98
+ * payer holds ZERO authority over the vault: register/revoke authorize on
99
+ * the passkey secp siblings, and the program validates every account by
100
+ * seeds/address constraint, so the ALT is an encoding optimization, not a
101
+ * trust surface.
102
+ *
103
+ * MAINNET-HARDENING mirrored from the proven K-T4b transport (each was
104
+ * forced by a live failure on 2026-07-06):
105
+ * - PRIORITY FEE (p75 of recent, floored/capped): a fee-less compose is
106
+ * dropped under congestion and expires unlanded — a CU limit alone buys
107
+ * nothing, only a price does.
108
+ * - FRESH-BLOCKHASH REBROADCAST on expiry-only: an expired-blockhash
109
+ * signature is permanently dead on Solana, so rebroadcasting under a new
110
+ * blockhash cannot double-land. On-chain errors (logs present) surface
111
+ * immediately — deterministic failures are never retried.
112
+ * - ALT READ-BACK POLL: the create+extend confirms, but the ALT ACCOUNT can
113
+ * lag a load-balanced RPC — a one-shot read spuriously fails a legitimate
114
+ * replace.
115
+ * - ALT-ADDRESS COLLISION RETRY: createLookupTable derives from
116
+ * [authority, recentSlot]; two concurrent composes reading the same
117
+ * finalized slot collide — retry with a fresh finalized slot.
118
+ *
119
+ * TWO PREFLIGHT-BANK RULES (K-T4a, honored verbatim):
120
+ * (a) the ALT-extend must be OBSERVED by the bank preflight simulates
121
+ * against, or the compose preflights "invalid index" — poll getSlot at
122
+ * the preflight commitment until it passes lastExtendedSlot;
123
+ * (b) the v0 blockhash must be fetched AT the preflight commitment, or the
124
+ * preflight bank reports "Blockhash not found".
125
+ */
126
+
127
+ /** Solana's hard on-the-wire transaction cap (IPv6 MTU 1280 − 48). */
128
+ declare const TX_SIZE_LIMIT_BYTES = 1232;
129
+ interface SelfPayingComposeSendOptions {
130
+ /** Commitment the preflight bank rules key on. Default 'confirmed' —
131
+ * matching the adapter's default confirm options. */
132
+ commitment?: Commitment;
133
+ /** Poll intervals (test seams; production defaults match K-T4b). */
134
+ altWarmupPollMs?: number;
135
+ altReadbackPollMs?: number;
136
+ altCollisionPollMs?: number;
137
+ }
138
+ interface SelfPayingComposeSend {
139
+ /**
140
+ * `send` transport for `composeRevokeThenRegister`: receives the FULL
141
+ * composed instruction list, lazily provisions + warms the ephemeral ALT
142
+ * on the first call (reused on retries), builds the v0 tx, sends with
143
+ * preflight ON, confirms, and returns the signature. Throws with the
144
+ * program error text + simulation logs intact (registerSessionWithRetry's
145
+ * IncompleteSessionSet / SessionAccountsNotSorted matcher needs them).
146
+ */
147
+ send: (instructions: TransactionInstruction[]) => Promise<string>;
148
+ /** The ephemeral ALT address once created, else null. */
149
+ getAltAddress: () => PublicKey | null;
150
+ /**
151
+ * Fire-and-forget cleanup: deactivate the ephemeral ALT so its rent
152
+ * becomes reclaimable by a later `close_lookup_table` (close requires the
153
+ * ~513-slot deactivation cooldown, so it cannot run inline). No-op when no
154
+ * ALT was created. NEVER throws — cleanup failure must not fail the
155
+ * money op that already landed.
156
+ */
157
+ deactivateAlt: () => Promise<void>;
158
+ }
159
+ /**
160
+ * The accounts the ephemeral ALT must hold: every NON-SIGNER account meta
161
+ * referenced by the composed instructions, deduped, minus the fee payer.
162
+ * Extracting straight from the instruction list is exact-by-construction —
163
+ * no re-derivation of vault accounts in this module. Signers MUST stay
164
+ * static; invoked program ids are never in `ix.keys`, so they never enter
165
+ * the ALT (and web3.js keeps invoked programs static regardless).
166
+ */
167
+ declare function collectAltAddresses(instructions: TransactionInstruction[], feePayer: PublicKey): PublicKey[];
168
+ /** Compile the composed instruction list into a v0 tx backed by `alt`. */
169
+ declare function compileComposeV0(instructions: TransactionInstruction[], feePayer: PublicKey, recentBlockhash: string, alt: AddressLookupTableAccount): VersionedTransaction;
170
+ /**
171
+ * Build a self-paying LIVE-compose transport bound to `conn` + `feePayer`.
172
+ * The ALT is created from the FIRST attempt's account set and reused across
173
+ * registerSessionWithRetry retries; a sibling that appears between the
174
+ * ALT-extend and a later attempt rides as a static key (+33 B) — still
175
+ * within cap below a couple of unlisted siblings.
176
+ */
177
+ declare function createSelfPayingComposeSend(conn: Connection, feePayer: Signer, options?: SelfPayingComposeSendOptions): SelfPayingComposeSend;
178
+
179
+ /**
180
+ * Solana VaultAdapter — production implementation against the deployed
181
+ * dexter-vault v2 program on Solana mainnet.
182
+ *
183
+ * Two passkey signing paths are supported via the `passkeySigner` field,
184
+ * both conforming to vault's canonical `PasskeySignerWithPublicKey`:
185
+ * - CLI/Node: a noble-curves P-256 signer wrapping a local keypair
186
+ * (`passkeySignerFromP256Keypair` in `./passkey-noble.ts`).
187
+ * - Browser: vault's `DexterApiBrowserPasskeySigner` drops in with no shim.
188
+ *
189
+ * The adapter's job is to (a) take the buyer's session scope, (b) get a
190
+ * passkey signature endorsing it, (c) submit the on-chain
191
+ * register_session_key tx so the seller can verify the endorsement, (d)
192
+ * expose voucher signing for the session, and (e) tear the session down
193
+ * at close.
194
+ *
195
+ * The adapter does NOT touch pending_voucher_count. That counter belongs
196
+ * to the facilitator's dexter_authority and is decremented inside the
197
+ * facilitator's `POST /tab/settle` tx (via the new vault.settle_tab_voucher
198
+ * instruction) atomically with the USDC transfer. The SDK's `Tab.close()`
199
+ * POSTs the final voucher to the facilitator; this adapter only owns the
200
+ * passkey-signed session register/revoke layer.
201
+ */
202
+
75
203
  interface CreateSolanaVaultAdapterOptions {
76
204
  /** RPC the adapter uses to submit txs. The buyer can pass their own
77
205
  * connection (browser wallet RPC, Helius URL, etc.) — the adapter has
@@ -95,6 +223,23 @@ interface CreateSolanaVaultAdapterOptions {
95
223
  * match production code (FE/API). For test suites, override to
96
224
  * 'finalized' — see reference_anchor_test_commitment in repo memory. */
97
225
  confirmOptions?: ConfirmOptions;
226
+ /** Testing/production seams (default: the real chain readers + the
227
+ * self-paying v0+ALT compose transport). Same seam idiom as
228
+ * @dexterai/vault's session helpers. */
229
+ seams?: SolanaAdapterSeams;
230
+ }
231
+ /** Injectable chain-reader/transport seams for the Solana adapter. */
232
+ interface SolanaAdapterSeams {
233
+ fetchSession?: typeof fetchSessionAccount;
234
+ fetchSessions?: typeof fetchVaultSessionAccounts;
235
+ resolveUsdcAta?: typeof resolveVaultUsdcAta;
236
+ waitForSession?: typeof waitForSession;
237
+ /** Atomic-compose transport override: receives the FULL composed
238
+ * instruction list ([secp(revoke), revoke, secp(register), register]),
239
+ * must send + confirm ATOMICALLY in one transaction. Production default:
240
+ * `createSelfPayingComposeSend` (v0+ALT — the compose does NOT fit a
241
+ * legacy transaction, K-T4a). */
242
+ composeSend?: (instructions: TransactionInstruction[]) => Promise<string>;
98
243
  }
99
244
  interface AdapterRegisterIxParams {
100
245
  vaultPda: PublicKey;
@@ -118,8 +263,8 @@ interface AdapterRegisterIxParams {
118
263
  * the derive-and-probe decision. The adapter no longer derives it locally. */
119
264
  vaultUsdcAta: PublicKey | null;
120
265
  }
121
- declare function buildAdapterRegisterInstruction(p: AdapterRegisterIxParams): _solana_web3_js.TransactionInstruction;
266
+ declare function buildAdapterRegisterInstruction(p: AdapterRegisterIxParams): TransactionInstruction;
122
267
  /** Factory entry point. */
123
268
  declare function createSolanaVaultAdapter(opts: CreateSolanaVaultAdapterOptions): VaultAdapter;
124
269
 
125
- export { type AdapterRegisterIxParams, type CreateSolanaVaultAdapterOptions, buildAdapterRegisterInstruction, createSolanaVaultAdapter, deriveChannelId, passkeySignerFromP256Keypair };
270
+ export { type AdapterRegisterIxParams, type CreateSolanaVaultAdapterOptions, type SelfPayingComposeSend, type SelfPayingComposeSendOptions, type SolanaAdapterSeams, TX_SIZE_LIMIT_BYTES, buildAdapterRegisterInstruction, collectAltAddresses, compileComposeV0, createSelfPayingComposeSend, createSolanaVaultAdapter, deriveChannelId, passkeySignerFromP256Keypair };
@@ -1 +1 @@
1
- import{PublicKey as u,Transaction as V}from"@solana/web3.js";import{buildRegisterSessionKeyInstruction as w,buildRevokeSessionKeyInstruction as v,deriveSwigWalletAddress as te}from"@dexterai/vault/instructions";import{buildSecp256r1VerifyInstruction as P}from"@dexterai/vault/precompile";import{DEXTER_VAULT_PROGRAM_ID as b,SECP256R1_PROGRAM_ID as re,INSTRUCTIONS_SYSVAR_ID as se}from"@dexterai/vault/constants";import{sessionRegisterMessage as x,sessionRevokeMessage as U,voucherPayloadMessage as k,buildVoucherMessage as ce}from"@dexterai/vault/messages";import O from"tweetnacl";import{sha256 as N}from"@noble/hashes/sha256";function I(){let e=O.sign.keyPair();return{publicKey:e.publicKey,privateKey:e.secretKey}}function C(e,t,n){return{publicKey:e.publicKey,privateKey:e.privateKey,scope:t,registration:n}}function R(e,t,n){if(n.length!==32)throw new Error(`channelIdBytes must be 32 bytes, got ${n.length}`);let i=BigInt(t.cumulativeAmount),r=BigInt(e.scope.maxAmountAtomic);if(i>r)throw new Error(`voucher cumulative ${i} exceeds session cap ${r}`);let s=Math.floor(Date.now()/1e3);if(s>=e.scope.expiresAtUnix)throw new Error(`session expired at ${e.scope.expiresAtUnix}, now ${s}`);let a=k({channelId:n,cumulativeAmount:i,sequenceNumber:t.sequenceNumber}),o=O.sign.detached(a,e.privateKey);return{payload:t,sessionPublicKey:e.publicKey,sessionRegistration:e.registration,sessionSignature:o}}function g(e){if(!/^\d+$/.test(e))throw new Error(`atomic amount must be a non-negative integer string, got "${e}"`);return BigInt(e)}function _(e){let t=new Uint8Array(8);new DataView(t.buffer).setBigUint64(0,e.nonce,!0);let n=new TextEncoder().encode(e.sellerUrl),i=N.create();return i.update(e.vaultPda.toBytes()),i.update(n),i.update(t),i.digest()}import{fetchVaultSessionAccounts as F,sessionPdasOf as z,waitForSession as G,resolveVaultUsdcAta as j}from"@dexterai/vault/session";import{sha256 as B}from"@noble/hashes/sha256";import{p256 as E}from"@noble/curves/p256";import{sha256 as d}from"@noble/hashes/sha256";var D="dexter.cash";function J(e){return Buffer.from(e).toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function $(e,t=`https://${D}`){let i={type:"webauthn.get",challenge:J(e),origin:t,crossOrigin:!1};return new TextEncoder().encode(JSON.stringify(i))}function W(e=1){let t=d(new TextEncoder().encode(D)),n=new Uint8Array(37);return n.set(t,0),n[32]=5,new DataView(n.buffer).setUint32(33,e,!1),n}function H(e,t){let n=$(t),i=W(1),r=new Uint8Array(i.length+32);r.set(i,0),r.set(d(n),i.length);let s=d(r);return{signature:E.sign(s,e.privateKey,{lowS:!0}).toCompactRawBytes(),clientDataJSON:n,authenticatorData:i}}function L(e){return{credentialId:new Uint8Array(0),publicKey:e.publicKey,signOperation:async t=>H(e,d(t))}}function q(e){return w({vaultPda:e.vaultPda,sessionPubkey:e.sessionPubkey,maxAmount:e.maxAmount,maxRevolvingCapacity:e.maxRevolvingCapacity,expiresAt:e.expiresAt,allowedCounterparty:e.allowedCounterparty,nonce:e.nonce,swigAddress:e.swigAddress,vaultUsdcAta:e.vaultUsdcAta,clientDataJSON:e.clientDataJSON,authenticatorData:e.authenticatorData,payer:e.payer,siblingSessionPdas:e.siblingSessionPdas})}var K=class{network="solana:mainnet";swigAddress;vaultPda;connection;vaultPdaKey;passkey;feePayer;confirmOptions;constructor(t){this.connection=t.connection,this.swigAddress=typeof t.swigAddress=="string"?t.swigAddress:t.swigAddress.toBase58(),this.vaultPdaKey=typeof t.vaultPda=="string"?new u(t.vaultPda):t.vaultPda,this.vaultPda=this.vaultPdaKey.toBase58(),this.passkey=t.passkeySigner,this.feePayer=t.feePayer,this.confirmOptions=t.confirmOptions??{commitment:"confirmed"}}async authorizeSession(t){let n=new u(t.allowedCounterparty),i=g(t.revolvingCapacityAtomic??t.maxAmountAtomic),r=I(),s=X(),a=x({programId:b,vaultPda:this.vaultPdaKey,sessionPubkey:r.publicKey,maxAmount:g(t.maxAmountAtomic),maxRevolvingCapacity:i,expiresAt:BigInt(t.expiresAtUnix),allowedCounterparty:n,nonce:s}),{signature:o,clientDataJSON:l,authenticatorData:y}=await this.passkey.signOperation(a),h=M(y,B(l)),c=P(this.passkey.publicKey,o,h),p=z(await F(this.connection,this.vaultPdaKey)),A=await j(this.connection,new u(this.swigAddress)),f=q({vaultPda:this.vaultPdaKey,swigAddress:new u(this.swigAddress),sessionPubkey:r.publicKey,maxAmount:g(t.maxAmountAtomic),maxRevolvingCapacity:i,expiresAt:BigInt(t.expiresAtUnix),allowedCounterparty:n,nonce:s,clientDataJSON:l,authenticatorData:y,payer:this.feePayer.publicKey,siblingSessionPdas:p,vaultUsdcAta:A}),m=new V().add(c,f);m.feePayer=this.feePayer.publicKey;let{blockhash:S}=await this.connection.getLatestBlockhash(this.confirmOptions.commitment);m.recentBlockhash=S,m.sign(this.feePayer);let T=await this.connection.sendRawTransaction(m.serialize(),{skipPreflight:!1,preflightCommitment:this.confirmOptions.preflightCommitment??this.confirmOptions.commitment});return await this.connection.confirmTransaction({signature:T,blockhash:S,lastValidBlockHeight:(await this.connection.getLatestBlockhash(this.confirmOptions.commitment)).lastValidBlockHeight},this.confirmOptions.commitment),await G(this.connection,this.vaultPdaKey,n,{expectedSessionPubkey:r.publicKey,timeoutMs:2e4}),C(r,t,a)}async signWithSession(t,n){let i=await Y(n.channelId);return R(t,n,i)}async signOpenTab(t,n){return t.registration}async signCloseTab(t,n,i){let r=U({programId:b,vaultPda:this.vaultPdaKey,sessionPubkey:t.publicKey}),{signature:s,clientDataJSON:a,authenticatorData:o}=await this.passkey.signOperation(r),l=M(o,B(a)),y=P(this.passkey.publicKey,s,l),h=v({vaultPda:this.vaultPdaKey,allowedCounterparty:new u(t.scope.allowedCounterparty),clientDataJSON:a,authenticatorData:o}),c=new V().add(y,h);c.feePayer=this.feePayer.publicKey;let{blockhash:p,lastValidBlockHeight:A}=await this.connection.getLatestBlockhash(this.confirmOptions.commitment);c.recentBlockhash=p,c.sign(this.feePayer);let f=await this.connection.sendRawTransaction(c.serialize(),{skipPreflight:!1,preflightCommitment:this.confirmOptions.preflightCommitment??this.confirmOptions.commitment});return await this.connection.confirmTransaction({signature:f,blockhash:p,lastValidBlockHeight:A},this.confirmOptions.commitment),r}};function we(e){return new K(e)}function M(e,t){let n=new Uint8Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n}function X(){return Math.floor(Math.random()*4294967295)>>>0}async function Y(e){if(/^[0-9a-f]{64}$/i.test(e))return Q(e);let{sha256:t}=await import("@noble/hashes/sha256");return t(new TextEncoder().encode(e))}function Q(e){let t=new Uint8Array(e.length/2);for(let n=0;n<t.length;n++)t[n]=parseInt(e.substr(n*2,2),16);return t}export{q as buildAdapterRegisterInstruction,we as createSolanaVaultAdapter,_ as deriveChannelId,L as passkeySignerFromP256Keypair};
1
+ import{PublicKey as K,Transaction as ie}from"@solana/web3.js";var U=class extends Error{constructor(n){super(`a LIVE session already exists for counterparty ${n.allowedCounterparty} (session ${n.sessionPubkeyHex.slice(0,16)}\u2026, expires ${n.expiresAtUnix}; on-chain spent=${n.spentAtomic}, crystallized=${n.crystallizedCumulativeAtomic}, frontier=${n.frontierAtomic}). Replacing it voids any signed-but-unsettled vouchers beyond the frontier. Settle the old tab first (tab.close() or POST its last voucher to /tab/settle), or pass onLiveSession: 'replace' to atomically revoke-then-register over it.`);this.details=n;this.name="LiveSessionExistsError"}};import{buildRegisterSessionKeyInstruction as z,buildRevokeSessionKeyInstruction as H,deriveSwigWalletAddress as Me}from"@dexterai/vault/instructions";import{buildSecp256r1VerifyInstruction as $}from"@dexterai/vault/precompile";import{DEXTER_VAULT_PROGRAM_ID as O,SECP256R1_PROGRAM_ID as Be,INSTRUCTIONS_SYSVAR_ID as Ne}from"@dexterai/vault/constants";import{sessionRegisterMessage as F,sessionRevokeMessage as D,voucherPayloadMessage as J,buildVoucherMessage as Fe}from"@dexterai/vault/messages";import W from"tweetnacl";import{sha256 as ce}from"@noble/hashes/sha256";function X(){let t=W.sign.keyPair();return{publicKey:t.publicKey,privateKey:t.secretKey}}function j(t,e,n){return{publicKey:t.publicKey,privateKey:t.privateKey,scope:e,registration:n}}function Y(t,e,n){if(n.length!==32)throw new Error(`channelIdBytes must be 32 bytes, got ${n.length}`);let s=BigInt(e.cumulativeAmount),o=BigInt(t.scope.maxAmountAtomic);if(s>o)throw new Error(`voucher cumulative ${s} exceeds session cap ${o}`);let m=Math.floor(Date.now()/1e3);if(m>=t.scope.expiresAtUnix)throw new Error(`session expired at ${t.scope.expiresAtUnix}, now ${m}`);let r=J({channelId:n,cumulativeAmount:s,sequenceNumber:e.sequenceNumber}),a=W.sign.detached(r,t.privateKey);return{payload:e,sessionPublicKey:t.publicKey,sessionRegistration:t.registration,sessionSignature:a}}function C(t){if(!/^\d+$/.test(t))throw new Error(`atomic amount must be a non-negative integer string, got "${t}"`);return BigInt(t)}function le(t){let e=new Uint8Array(8);new DataView(e.buffer).setBigUint64(0,t.nonce,!0);let n=new TextEncoder().encode(t.sellerUrl),s=ce.create();return s.update(t.vaultPda.toBytes()),s.update(n),s.update(e),s.digest()}import{fetchVaultSessionAccounts as ve,fetchSessionAccount as xe,isSessionLive as ke,sessionPdasOf as Ke,waitForSession as Te,resolveVaultUsdcAta as oe,composeRevokeThenRegister as Ue}from"@dexterai/vault/session";import{sha256 as re}from"@noble/hashes/sha256";import{bytesToHex as Ce}from"@noble/hashes/utils";import{AddressLookupTableProgram as M,ComputeBudgetProgram as q,Transaction as ue,TransactionMessage as pe,VersionedTransaction as me}from"@solana/web3.js";var L=1232,de=40,G=20,Z=4,ye=20,I=1e4,ge=1e6,R=4,T="[tab/solana/compose]";function te(t,e){let n=new Set,s=[],o=e.toBase58();for(let m of t)for(let r of m.keys){if(r.isSigner)continue;let a=r.pubkey.toBase58();a===o||n.has(a)||(n.add(a),s.push(r.pubkey))}return s}function ne(t,e,n,s){let o=new pe({payerKey:e,recentBlockhash:n,instructions:t}).compileToV0Message([s]);return new me(o)}async function Q(t){try{let e=(await t.getRecentPrioritizationFees()).map(s=>s.prioritizationFee).filter(s=>s>0).sort((s,o)=>s-o);if(e.length===0)return I;let n=e[Math.floor(.75*(e.length-1))]??I;return Math.max(I,Math.min(n,ge))}catch{return I}}function he(t){let e=t,n=String(e?.message??t??""),s=Array.isArray(e?.logs)?e.logs.join(" "):"";return/already in use/i.test(n)||/already in use/i.test(s)}function ee(t){let e=t;return(Array.isArray(e?.logs)?e.logs:[]).length===0&&/block height exceeded|has expired|blockhash not found/i.test(String(e?.message??t))}var V=t=>new Promise(e=>setTimeout(e,t));function _(t,e,n={}){let s=n.commitment??"confirmed",o=n.altWarmupPollMs??400,m=n.altReadbackPollMs??400,r=n.altCollisionPollMs??500,a=null,l=null;async function d(p,u){let c=await Q(t),f=[q.setComputeUnitPrice({microLamports:c}),...p],A;for(let y=0;y<R;y+=1){let{blockhash:h,lastValidBlockHeight:k}=await t.getLatestBlockhash(s),S=new ue().add(...f);S.feePayer=e.publicKey,S.recentBlockhash=h,S.sign(e);try{let i=await t.sendRawTransaction(S.serialize(),{skipPreflight:!1,maxRetries:5}),w=await t.confirmTransaction({signature:i,blockhash:h,lastValidBlockHeight:k},s);if(w.value.err)throw new Error(`${u} tx failed on-chain: ${JSON.stringify(w.value.err)}`);return i}catch(i){if(ee(i)&&y<R-1){console.warn(`${T} ${u} tx expired before landing (attempt ${y+1}) \u2014 rebroadcasting with a fresh blockhash`),A=i;continue}throw i}}throw A??new Error(`${u} tx did not land after rebroadcast attempts`)}async function P(p){for(let u=0;u<ye;u+=1){let c=await t.getSlot("finalized");if(c>p)return c;await V(r)}throw new Error(`ALT collision retry: finalized slot never advanced past ${p}`)}async function g(p){for(let u=0;u<de;u+=1){if(await t.getSlot(s)>p)return;await V(o)}throw new Error(`ALT warmup timed out: preflight (${s}) slot never passed lastExtendedSlot ${p}`)}async function b(p){if(a)return a;let u=te(p,e.publicKey),c=null,f=null,A=-1;for(let h=0;h<Z;h+=1){let k=A<0?await t.getSlot("finalized"):await P(A),[S,i]=M.createLookupTable({authority:e.publicKey,payer:e.publicKey,recentSlot:k}),w=M.extendLookupTable({payer:e.publicKey,authority:e.publicKey,lookupTable:i,addresses:u});try{f=await d([S,w],"ALT create/extend"),c=i;break}catch(N){if(he(N)&&h<Z-1){A=k,console.warn(`${T} ALT address collision at slot ${k} (attempt ${h+1}) \u2014 retrying create with a fresh finalized slot`);continue}throw N}}if(!c||!f)throw new Error("ALT create exhausted retries after repeated address collisions");let y=await t.getAddressLookupTable(c);for(let h=0;h<G&&!y.value;h+=1)await V(m),y=await t.getAddressLookupTable(c);if(!y.value)throw new Error(`ALT ${c.toBase58()} not visible after ${G} read polls (${f})`);return await g(y.value.state.lastExtendedSlot),a=y.value,l=c,console.info(`${T} ephemeral compose ALT ready: ${c.toBase58()} (${u.length} addresses, createTx ${f})`),a}async function v(p){let u=await Q(t),c=[q.setComputeUnitPrice({microLamports:u}),...p],f=await b(c),A;for(let y=0;y<R;y+=1){let{blockhash:h,lastValidBlockHeight:k}=await t.getLatestBlockhash(s),S;try{let i=ne(c,e.publicKey,h,f);i.sign([e]),S=i.serialize()}catch(i){throw/overrun|too large/i.test(String(i?.message??i))?new Error(`composed revoke-then-register v0 tx exceeds the ${L}B wire cap \u2014 too many sibling PDAs outside the lookup table`):i}if(S.length>L)throw new Error(`composed revoke-then-register v0 tx ${S.length}B exceeds the ${L}B wire cap \u2014 too many sibling PDAs outside the lookup table`);try{let i=await t.sendRawTransaction(S,{skipPreflight:!1,maxRetries:5}),w=await t.confirmTransaction({signature:i,blockhash:h,lastValidBlockHeight:k},s);if(w.value.err)throw new Error(`composed tx failed on-chain: ${JSON.stringify(w.value.err)}`);return i}catch(i){if(ee(i)&&y<R-1){console.warn(`${T} compose tx expired before landing (attempt ${y+1}, priorityFee ${u}) \u2014 rebroadcasting with a fresh blockhash`),A=i;continue}let w=Array.isArray(i?.logs)?i.logs:[];throw w.length?new Error(`${i?.message??i} | ${w.join(" | ")}`):i}}throw A instanceof Error?A:new Error("compose tx did not land after rebroadcast attempts")}async function x(){if(l)try{let p=M.deactivateLookupTable({lookupTable:l,authority:e.publicKey}),u=await d([p],"ALT deactivate");console.info(`${T} ephemeral compose ALT deactivated: ${l.toBase58()} (${u}) \u2014 rent reclaimable via close_lookup_table after the deactivation cooldown`)}catch(p){console.warn(`${T} ALT deactivate failed for ${l?.toBase58()} \u2014 rent parks until a later cleanup retries (the compose already landed): ${String(p?.message??p)}`)}}return{send:v,getAltAddress:()=>l,deactivateAlt:x}}import{p256 as Ae}from"@noble/curves/p256";import{sha256 as E}from"@noble/hashes/sha256";var se="dexter.cash";function fe(t){return Buffer.from(t).toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function Se(t,e=`https://${se}`){let s={type:"webauthn.get",challenge:fe(t),origin:e,crossOrigin:!1};return new TextEncoder().encode(JSON.stringify(s))}function be(t=1){let e=E(new TextEncoder().encode(se)),n=new Uint8Array(37);return n.set(e,0),n[32]=5,new DataView(n.buffer).setUint32(33,t,!1),n}function we(t,e){let n=Se(e),s=be(1),o=new Uint8Array(s.length+32);o.set(s,0),o.set(E(n),s.length);let m=E(o);return{signature:Ae.sign(m,t.privateKey,{lowS:!0}).toCompactRawBytes(),clientDataJSON:n,authenticatorData:s}}function Pe(t){return{credentialId:new Uint8Array(0),publicKey:t.publicKey,signOperation:async e=>we(t,E(e))}}function Oe(t){return z({vaultPda:t.vaultPda,sessionPubkey:t.sessionPubkey,maxAmount:t.maxAmount,maxRevolvingCapacity:t.maxRevolvingCapacity,expiresAt:t.expiresAt,allowedCounterparty:t.allowedCounterparty,nonce:t.nonce,swigAddress:t.swigAddress,vaultUsdcAta:t.vaultUsdcAta,clientDataJSON:t.clientDataJSON,authenticatorData:t.authenticatorData,payer:t.payer,siblingSessionPdas:t.siblingSessionPdas})}var B=class{network="solana:mainnet";swigAddress;vaultPda;connection;vaultPdaKey;passkey;feePayer;confirmOptions;seams;constructor(e){this.connection=e.connection,this.swigAddress=typeof e.swigAddress=="string"?e.swigAddress:e.swigAddress.toBase58(),this.vaultPdaKey=typeof e.vaultPda=="string"?new K(e.vaultPda):e.vaultPda,this.vaultPda=this.vaultPdaKey.toBase58(),this.passkey=e.passkeySigner,this.feePayer=e.feePayer,this.confirmOptions=e.confirmOptions??{commitment:"confirmed"},this.seams=e.seams??{}}async authorizeSession(e,n){let s=new K(e.allowedCounterparty),o=C(e.revolvingCapacityAtomic??e.maxAmountAtomic),r=await(this.seams.fetchSession??xe)(this.connection,this.vaultPdaKey,s),a=r!==null&&ke(r);if(a&&(n?.onLiveSession??"error")!=="replace"){let v=r.session.spent,x=r.session.crystallizedCumulative;throw new U({allowedCounterparty:e.allowedCounterparty,sessionPubkeyHex:Ce(r.session.sessionPubkey),expiresAtUnix:r.session.expiresAt,spentAtomic:v.toString(),crystallizedCumulativeAtomic:x.toString(),currentOutstandingAtomic:r.session.currentOutstanding.toString(),frontierAtomic:(v>x?v:x).toString()})}let l=X(),d=Ie(),P=F({programId:O,vaultPda:this.vaultPdaKey,sessionPubkey:l.publicKey,maxAmount:C(e.maxAmountAtomic),maxRevolvingCapacity:o,expiresAt:BigInt(e.expiresAtUnix),allowedCounterparty:s,nonce:d}),g=await this.passkey.signOperation(P);return a?await this.sendAtomicReplace(r,e,s,l.publicKey,d,o,g):await this.sendBareRegister(e,s,l.publicKey,d,o,g),await(this.seams.waitForSession??Te)(this.connection,this.vaultPdaKey,s,{expectedSessionPubkey:l.publicKey,timeoutMs:2e4}),j(l,e,P)}async sendBareRegister(e,n,s,o,m,r){let{signature:a,clientDataJSON:l,authenticatorData:d}=r,P=ae(d,re(l)),g=$(this.passkey.publicKey,a,P),b=this.seams.fetchSessions??ve,v=Ke(await b(this.connection,this.vaultPdaKey)),p=await(this.seams.resolveUsdcAta??oe)(this.connection,new K(this.swigAddress)),u=Oe({vaultPda:this.vaultPdaKey,swigAddress:new K(this.swigAddress),sessionPubkey:s,maxAmount:C(e.maxAmountAtomic),maxRevolvingCapacity:m,expiresAt:BigInt(e.expiresAtUnix),allowedCounterparty:n,nonce:o,clientDataJSON:l,authenticatorData:d,payer:this.feePayer.publicKey,siblingSessionPdas:v,vaultUsdcAta:p}),c=new ie().add(g,u);c.feePayer=this.feePayer.publicKey;let{blockhash:f}=await this.connection.getLatestBlockhash(this.confirmOptions.commitment);c.recentBlockhash=f,c.sign(this.feePayer);let A=await this.connection.sendRawTransaction(c.serialize(),{skipPreflight:!1,preflightCommitment:this.confirmOptions.preflightCommitment??this.confirmOptions.commitment});await this.connection.confirmTransaction({signature:A,blockhash:f,lastValidBlockHeight:(await this.connection.getLatestBlockhash(this.confirmOptions.commitment)).lastValidBlockHeight},this.confirmOptions.commitment)}async sendAtomicReplace(e,n,s,o,m,r,a){let l=D({programId:O,vaultPda:this.vaultPdaKey,sessionPubkey:e.session.sessionPubkey}),d=await this.passkey.signOperation(l),g=await(this.seams.resolveUsdcAta??oe)(this.connection,new K(this.swigAddress)),b=this.seams.composeSend?{send:this.seams.composeSend,deactivateAlt:async()=>{}}:_(this.connection,this.feePayer,{commitment:this.confirmOptions.commitment});try{await Ue({connection:this.connection,vaultPda:this.vaultPdaKey,allowedCounterparty:s,registerArgs:{sessionPubkey:o,maxAmount:C(n.maxAmountAtomic),maxRevolvingCapacity:r,expiresAt:BigInt(n.expiresAtUnix),nonce:m,swigAddress:new K(this.swigAddress),vaultUsdcAta:g,payer:this.feePayer.publicKey},registerCeremony:{clientDataJSON:a.clientDataJSON,authenticatorData:a.authenticatorData,signature:a.signature},revokeCeremony:{clientDataJSON:d.clientDataJSON,authenticatorData:d.authenticatorData,signature:d.signature},credentialPublicKey:this.passkey.publicKey,send:b.send,fetchSession:this.seams.fetchSession,fetchSessions:this.seams.fetchSessions})}finally{b.deactivateAlt()}}async signWithSession(e,n){let s=await Re(n.channelId);return Y(e,n,s)}async signOpenTab(e,n){return e.registration}async signCloseTab(e,n,s){let o=D({programId:O,vaultPda:this.vaultPdaKey,sessionPubkey:e.publicKey}),{signature:m,clientDataJSON:r,authenticatorData:a}=await this.passkey.signOperation(o),l=ae(a,re(r)),d=$(this.passkey.publicKey,m,l),P=H({vaultPda:this.vaultPdaKey,allowedCounterparty:new K(e.scope.allowedCounterparty),clientDataJSON:r,authenticatorData:a}),g=new ie().add(d,P);g.feePayer=this.feePayer.publicKey;let{blockhash:b,lastValidBlockHeight:v}=await this.connection.getLatestBlockhash(this.confirmOptions.commitment);g.recentBlockhash=b,g.sign(this.feePayer);let x=await this.connection.sendRawTransaction(g.serialize(),{skipPreflight:!1,preflightCommitment:this.confirmOptions.preflightCommitment??this.confirmOptions.commitment});return await this.connection.confirmTransaction({signature:x,blockhash:b,lastValidBlockHeight:v},this.confirmOptions.commitment),o}};function yt(t){return new B(t)}function ae(t,e){let n=new Uint8Array(t.length+e.length);return n.set(t,0),n.set(e,t.length),n}function Ie(){return Math.floor(Math.random()*4294967295)>>>0}async function Re(t){if(/^[0-9a-f]{64}$/i.test(t))return Le(t);let{sha256:e}=await import("@noble/hashes/sha256");return e(new TextEncoder().encode(t))}function Le(t){let e=new Uint8Array(t.length/2);for(let n=0;n<e.length;n++)e[n]=parseInt(t.substr(n*2,2),16);return e}export{U as LiveSessionExistsError,L as TX_SIZE_LIMIT_BYTES,Oe as buildAdapterRegisterInstruction,te as collectAltAddresses,ne as compileComposeV0,_ as createSelfPayingComposeSend,yt as createSolanaVaultAdapter,le as deriveChannelId,Pe as passkeySignerFromP256Keypair};