@dexterai/x402 5.4.2 → 6.0.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +19 -4
  2. package/REFERENCE.md +79 -8
  3. package/dist/adapters/index.d.cts +3 -3
  4. package/dist/adapters/index.d.ts +3 -3
  5. package/dist/batch-settlement/index.d.cts +3 -3
  6. package/dist/batch-settlement/index.d.ts +3 -3
  7. package/dist/batch-settlement/seller/index.d.cts +4 -4
  8. package/dist/batch-settlement/seller/index.d.ts +4 -4
  9. package/dist/client/index.cjs +1 -1
  10. package/dist/client/index.d.cts +6 -6
  11. package/dist/client/index.d.ts +6 -6
  12. package/dist/client/index.js +1 -1
  13. package/dist/{constants-Icc4CXNG.d.cts → constants-BLvApMMl.d.cts} +1 -1
  14. package/dist/{constants-Icc4CXNG.d.ts → constants-BLvApMMl.d.ts} +1 -1
  15. package/dist/react/index.cjs +1 -1
  16. package/dist/react/index.d.cts +4 -4
  17. package/dist/react/index.d.ts +4 -4
  18. package/dist/react/index.js +1 -1
  19. package/dist/server/index.cjs +1 -1
  20. package/dist/server/index.d.cts +5 -5
  21. package/dist/server/index.d.ts +5 -5
  22. package/dist/server/index.js +1 -1
  23. package/dist/{sessions-BG2OYLBi.d.cts → sessions-rPdO1CgK.d.cts} +35 -3
  24. package/dist/{sessions-BG2OYLBi.d.ts → sessions-rPdO1CgK.d.ts} +35 -3
  25. package/dist/tab/adapters/solana/index.cjs +1 -1
  26. package/dist/tab/adapters/solana/index.d.cts +178 -26
  27. package/dist/tab/adapters/solana/index.d.ts +178 -26
  28. package/dist/tab/adapters/solana/index.js +1 -1
  29. package/dist/tab/index.cjs +5 -5
  30. package/dist/tab/index.d.cts +117 -16
  31. package/dist/tab/index.d.ts +117 -16
  32. package/dist/tab/index.js +4 -4
  33. package/dist/tab/seller/index.cjs +3 -3
  34. package/dist/tab/seller/index.d.cts +4 -4
  35. package/dist/tab/seller/index.d.ts +4 -4
  36. package/dist/tab/seller/index.js +3 -3
  37. package/dist/{types-CSuISjXA.d.cts → types-45M9fb5M.d.cts} +109 -6
  38. package/dist/{types-CSuISjXA.d.ts → types-45M9fb5M.d.ts} +109 -6
  39. package/dist/{types-BdS_uvNs.d.cts → types-BbvuPNXl.d.cts} +2 -2
  40. package/dist/{types-Co5YYhVB.d.ts → types-BhXu7cgi.d.ts} +3 -3
  41. package/dist/{types-xQu1U4xk.d.cts → types-BvQpNtFw.d.cts} +9 -1
  42. package/dist/{types-xQu1U4xk.d.ts → types-BvQpNtFw.d.ts} +9 -1
  43. package/dist/{types-CZHPdVkg.d.cts → types-C6z04Mxr.d.cts} +3 -3
  44. package/dist/{types-DY8xKheW.d.ts → types-CkcNYx1Q.d.ts} +2 -2
  45. package/dist/{types-_wdHzVG-.d.ts → types-DwVhPqOZ.d.ts} +2 -2
  46. package/dist/{types-WMqs5xII.d.cts → types-JpkrtFbZ.d.cts} +2 -2
  47. package/dist/utils/index.d.cts +1 -1
  48. package/dist/utils/index.d.ts +1 -1
  49. package/dist/{x402-client-BQKDeNxq.d.cts → x402-client-B8zdDeat.d.cts} +2 -2
  50. package/dist/{x402-client-BQKDeNxq.d.ts → x402-client-B8zdDeat.d.ts} +2 -2
  51. package/package.json +7 -6
@@ -1,8 +1,9 @@
1
- import { Connection, Signer, Commitment, TransactionInstruction, PublicKey, 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
- export { d as deriveChannelId } from '../../../sessions-BG2OYLBi.js';
1
+ import { PublicKey, Connection, TransactionInstruction, Commitment, AddressLookupTableAccount, VersionedTransaction, Signer, ConfirmOptions } from '@solana/web3.js';
2
+ import { F as FinalVoucherV2ReservationInput, a as FinalVoucherV2ReservationReceipt, V as VerifyFinalVoucherV2Reservation, b as VaultAdapter } from '../../../types-45M9fb5M.js';
3
+ export { A as AuthorizeSessionOptions, L as LiveSessionDetails, c as LiveSessionExistsError } from '../../../types-45M9fb5M.js';
4
+ export { d as deriveChannelId } from '../../../sessions-rPdO1CgK.js';
5
5
  import { fetchSessionAccount, fetchVaultSessionAccounts, resolveVaultUsdcAta, waitForSession } from '@dexterai/vault/session';
6
+ import { fetchPasskeyAuthorizationState } from '@dexterai/vault';
6
7
  import { PasskeySignerWithPublicKey } from '@dexterai/vault/signers';
7
8
  export { PasskeySignerWithPublicKey as PasskeySigner } from '@dexterai/vault/signers';
8
9
  import '@dexterai/vault/types';
@@ -19,8 +20,10 @@ import '@dexterai/vault/types';
19
20
  *
20
21
  * From the on-chain program's perspective the two paths are
21
22
  * indistinguishable: both produce a 64-byte (r||s) low-S secp256r1
22
- * signature over `authenticatorData || sha256(clientDataJSON)`, where
23
- * `clientDataJSON.challenge` base64url-decodes to sha256(operation_msg).
23
+ * signature over `authenticatorData || sha256(clientDataJSON)`. For V7,
24
+ * `clientDataJSON.challenge` is the canonical 200-byte authorization envelope
25
+ * binding program, vault, monotonic guard nonce, operation hash, and fresh
26
+ * ceremony entropy.
24
27
  *
25
28
  * This module mirrors the helper at
26
29
  * dexter-vault/tests/helpers/secp256r1.ts (signOperationWithPasskey).
@@ -33,12 +36,34 @@ interface P256Keypair {
33
36
  /** 32-byte raw scalar. NEVER persist this anywhere user-readable. */
34
37
  privateKey: Uint8Array;
35
38
  }
39
+ interface NodePasskeyAuthorizationContext {
40
+ programId: PublicKey;
41
+ vault: PublicKey;
42
+ nonce: bigint;
43
+ }
44
+ interface NodePasskeySignerOptions {
45
+ /**
46
+ * Optional authoritative nonce resolver for operations whose wire format
47
+ * does not itself carry enough guard-generation context. The session V2
48
+ * register/replace/revoke messages are recognized locally; callers using
49
+ * this development signer for any other V7 operation should provide this.
50
+ */
51
+ resolveAuthorizationContext?: (operationMessage: Uint8Array) => Promise<NodePasskeyAuthorizationContext>;
52
+ /**
53
+ * Explicit opt-in for pre-V7 development fixtures whose challenge was the
54
+ * bare sha256(operation). The safe default is false: an unknown operation
55
+ * must never be signed under a weaker authorization envelope merely because
56
+ * the node helper did not recognize its wire format.
57
+ */
58
+ allowLegacyOperationHash?: boolean;
59
+ /** Deterministic test seam. Production defaults to fresh random 32 bytes. */
60
+ ceremonyNonce?: () => Uint8Array;
61
+ }
36
62
  /**
37
- * Build a unified `PasskeySignerWithPublicKey` (vault's canonical 0.19 shape)
63
+ * Build a unified `PasskeySignerWithPublicKey` (Vault 0.43.1's canonical shape)
38
64
  * from a locally-held P-256 keypair — the node/CLI path. Returns
39
65
  * `{ credentialId, publicKey, signOperation(operationMessage) }`. The signer
40
- * owns the hashing locus: it computes `challenge = sha256(operationMessage)`
41
- * internally (mirroring vault's `DexterApiBrowserPasskeySigner.signOperation`),
66
+ * owns canonical challenge construction for recognized V7 session operations,
42
67
  * so the adapter hands it the RAW operation message and never pre-hashes.
43
68
  * The adapter still rebuilds the precompile message from the returned bytes.
44
69
  *
@@ -47,18 +72,104 @@ interface P256Keypair {
47
72
  * secp256r1 precompile over the clientDataJSON/authenticatorData, not the
48
73
  * credentialId, so an empty value is correct here.
49
74
  */
50
- declare function passkeySignerFromP256Keypair(kp: P256Keypair): PasskeySignerWithPublicKey;
75
+ declare function passkeySignerFromP256Keypair(kp: P256Keypair, options?: NodePasskeySignerOptions): PasskeySignerWithPublicKey;
76
+
77
+ /**
78
+ * Independent Solana proof for a FINAL Native Tab V2 reservation.
79
+ *
80
+ * The transaction must contain exactly two top-level instructions: the exact
81
+ * Vault `settle_voucher(increment=true)` reservation followed by an SPL Memo
82
+ * carrying the domain-separated digest of the complete FINAL voucher and its
83
+ * reservation identity. The Vault's recorded Dexter authority must sign both
84
+ * instruction accounts. The provider receipt is still checked as durable
85
+ * lifecycle evidence, but it is no longer the only voucher-to-transaction
86
+ * binding.
87
+ */
88
+
89
+ declare class SolanaFinalVoucherV2ReservationError extends Error {
90
+ readonly code: string;
91
+ constructor(code: string, detail?: string);
92
+ }
93
+ interface TransactionAccountEvidence {
94
+ address: string;
95
+ signer: boolean;
96
+ writable: boolean;
97
+ }
98
+ interface TransactionInstructionEvidence {
99
+ programId: string;
100
+ accounts: string[];
101
+ data: Uint8Array;
102
+ }
103
+ interface SolanaReservationTransactionEvidence {
104
+ slot: number;
105
+ err: unknown | null;
106
+ signatures: string[];
107
+ accountKeys: TransactionAccountEvidence[];
108
+ instructions: TransactionInstructionEvidence[];
109
+ }
110
+ interface SolanaReservationPostStateEvidence {
111
+ contextSlot: number;
112
+ binding: {
113
+ address: string;
114
+ owner: string;
115
+ version: number;
116
+ bump: number;
117
+ swig: string;
118
+ vault: string;
119
+ };
120
+ vault: {
121
+ owner: string;
122
+ exists: boolean;
123
+ version: number;
124
+ swigAddress: string | null;
125
+ dexterAuthority: string | null;
126
+ pendingVoucherCount: number;
127
+ };
128
+ session: {
129
+ owner: string;
130
+ version: number;
131
+ bump: number;
132
+ vault: string;
133
+ sessionPublicKey: string;
134
+ maxAmount: bigint;
135
+ expiresAt: number;
136
+ seller: string;
137
+ nonce: number;
138
+ spent: bigint;
139
+ currentOutstanding: bigint;
140
+ maxRevolvingCapacity: bigint;
141
+ crystallizedCumulative: bigint;
142
+ };
143
+ }
144
+ interface ReadTransactionArgs {
145
+ connection: Connection;
146
+ signature: string;
147
+ commitment: 'finalized';
148
+ }
149
+ interface ReadPostStateArgs {
150
+ connection: Connection;
151
+ input: FinalVoucherV2ReservationInput;
152
+ receipt: FinalVoucherV2ReservationReceipt;
153
+ }
154
+ interface SolanaReservationVerifierSeams {
155
+ readTransaction?: (args: ReadTransactionArgs) => Promise<SolanaReservationTransactionEvidence | null>;
156
+ readPostState?: (args: ReadPostStateArgs) => Promise<SolanaReservationPostStateEvidence>;
157
+ }
158
+ declare function verifySolanaFinalVoucherV2Reservation(connection: Connection, input: FinalVoucherV2ReservationInput, receipt: FinalVoucherV2ReservationReceipt, seams?: SolanaReservationVerifierSeams): Promise<void>;
159
+ declare function createSolanaFinalVoucherV2ReservationVerifier(connection: Connection, seams?: SolanaReservationVerifierSeams): VerifyFinalVoucherV2Reservation;
160
+ /** Production program ID is exported here only as a caller-side convenience;
161
+ * verification itself always uses the programId explicitly bound in input. */
162
+ declare const SOLANA_FINAL_VOUCHER_V2_PROGRAM_ID: PublicKey;
163
+ declare const SOLANA_FINAL_VOUCHER_V2_MEMO_PROGRAM_ID: PublicKey;
51
164
 
52
165
  /**
53
166
  * createSelfPayingComposeSend — the CLIENT-SIDE v0 + Address-Lookup-Table
54
167
  * transport for the atomic revoke-then-register compose (K-T4e).
55
168
  *
56
- * WHY THIS EXISTS: K-T4a proved the atomic single-tx revoke-then-register
57
- * ([secp(revoke), revoke, secp(register), register]) OVERFLOWS the legacy
58
- * 1232-byte wire cap even at ZERO siblings it measures 1347 B and web3.js
59
- * `Transaction.serialize()` itself throws (size proof:
60
- * dexter-vault-sdk tests/session.composeTxSize.test.ts; constants reused
61
- * here, not re-derived). The LIVE (revoke-composed) path must therefore
169
+ * WHY THIS EXISTS: the live replacement carries a large, fully bound operation
170
+ * plus the V7 account set. The compatibility compose routes it through a v0
171
+ * transaction and address lookup table instead of relying on the legacy
172
+ * 1232-byte wire envelope. The LIVE replacement path therefore
62
173
  * assemble a v0 `VersionedTransaction` with an ephemeral address lookup
63
174
  * table holding every non-signer account of the composed instructions
64
175
  * (vault, target session PDA, vaultUsdcAta, swig, swig wallet PDA, sysvar,
@@ -168,12 +279,11 @@ declare function createSelfPayingComposeSend(conn: Connection, feePayer: Signer,
168
279
  * expose voucher signing for the session, and (e) tear the session down
169
280
  * at close.
170
281
  *
171
- * The adapter does NOT touch pending_voucher_count. That counter belongs
282
+ * The adapter does NOT mutate pending_voucher_count. That counter belongs
172
283
  * to the facilitator's dexter_authority and is decremented inside the
173
- * facilitator's `POST /tab/settle` tx (via the new vault.settle_tab_voucher
174
- * instruction) atomically with the USDC transfer. The SDK's `Tab.close()`
175
- * POSTs the final voucher to the facilitator; this adapter only owns the
176
- * passkey-signed session register/revoke layer.
284
+ * facilitator's `POST /tab/settle` tx atomically with the USDC transfer.
285
+ * After that POST lands, the adapter reads the Vault counter and SessionAccount
286
+ * in one RPC context and binds both into the passkey-signed V3 revocation.
177
287
  */
178
288
 
179
289
  interface CreateSolanaVaultAdapterOptions {
@@ -195,9 +305,10 @@ interface CreateSolanaVaultAdapterOptions {
195
305
  * vault account is not a signer for register/revoke (the passkey
196
306
  * signature in the precompile sibling is the authorization). */
197
307
  feePayer: Signer;
198
- /** Confirmation options for sendAndConfirm. Defaults to 'confirmed' to
199
- * match production code (FE/API). For test suites, override to
200
- * 'finalized' see reference_anchor_test_commitment in repo memory. */
308
+ /** Confirmation/preflight options for registration and replacement.
309
+ * Defaults to `confirmed` to match those existing paths. Session close is
310
+ * stricter: it always proves the exact revoke at `finalized` before the SDK
311
+ * reports the credential revoked or allows the key to be wiped. */
201
312
  confirmOptions?: ConfirmOptions;
202
313
  /** Testing/production seams (default: the real chain readers + the
203
314
  * self-paying v0+ALT compose transport). Same seam idiom as
@@ -208,15 +319,56 @@ interface CreateSolanaVaultAdapterOptions {
208
319
  interface SolanaAdapterSeams {
209
320
  fetchSession?: typeof fetchSessionAccount;
210
321
  fetchSessions?: typeof fetchVaultSessionAccounts;
322
+ fetchPasskeyAuthorization?: typeof fetchPasskeyAuthorizationState;
323
+ readCloseRevocationSnapshot?: ReadCloseRevocationSnapshot;
324
+ /** Full target-state reader used by close retry reconciliation. Unlike the
325
+ * legacy snapshot seam, this can prove that the old credential is already
326
+ * cleared or has been replaced without ever targeting the replacement. */
327
+ readCloseRevocationTargetState?: ReadCloseRevocationTargetState;
211
328
  resolveUsdcAta?: typeof resolveVaultUsdcAta;
212
329
  waitForSession?: typeof waitForSession;
213
330
  /** Atomic-compose transport override: receives the FULL composed
214
- * instruction list ([secp(revoke), revoke, secp(register), register]),
331
+ * instruction list ([secp(replace), replace] for a live V7 target),
215
332
  * must send + confirm ATOMICALLY in one transaction. Production default:
216
333
  * `createSelfPayingComposeSend` (v0+ALT — the compose does NOT fit a
217
334
  * legacy transaction, K-T4a). */
218
335
  composeSend?: (instructions: TransactionInstruction[]) => Promise<string>;
219
336
  }
337
+ interface CloseRevocationSnapshot {
338
+ contextSlot: number;
339
+ programId: PublicKey;
340
+ vaultPda: PublicKey;
341
+ sessionPda: PublicKey;
342
+ sessionPubkey: Uint8Array;
343
+ maxAmount: bigint;
344
+ expiresAt: bigint;
345
+ allowedCounterparty: PublicKey;
346
+ nonce: number;
347
+ spent: bigint;
348
+ currentOutstanding: bigint;
349
+ maxRevolvingCapacity: bigint;
350
+ crystallizedCumulative: bigint;
351
+ lastLockedSequence: number;
352
+ expectedPendingVoucherCount: number;
353
+ }
354
+ interface ReadCloseRevocationSnapshotArgs {
355
+ connection: Connection;
356
+ vaultPda: PublicKey;
357
+ allowedCounterparty: PublicKey;
358
+ programId?: PublicKey;
359
+ commitment?: Commitment;
360
+ }
361
+ type ReadCloseRevocationSnapshot = (args: ReadCloseRevocationSnapshotArgs) => Promise<CloseRevocationSnapshot>;
362
+ type CloseRevocationTargetState = {
363
+ kind: 'live';
364
+ snapshot: CloseRevocationSnapshot;
365
+ } | {
366
+ kind: 'invalidated';
367
+ contextSlot: number;
368
+ sessionPda: PublicKey;
369
+ reason: 'absent' | 'cleared';
370
+ };
371
+ type ReadCloseRevocationTargetState = (args: ReadCloseRevocationSnapshotArgs) => Promise<CloseRevocationTargetState>;
220
372
  interface AdapterRegisterIxParams {
221
373
  vaultPda: PublicKey;
222
374
  /** Swig STATE account (== vault.swig_address). */
@@ -243,4 +395,4 @@ declare function buildAdapterRegisterInstruction(p: AdapterRegisterIxParams): Tr
243
395
  /** Factory entry point. */
244
396
  declare function createSolanaVaultAdapter(opts: CreateSolanaVaultAdapterOptions): VaultAdapter;
245
397
 
246
- export { type AdapterRegisterIxParams, type CreateSolanaVaultAdapterOptions, type SelfPayingComposeSend, type SelfPayingComposeSendOptions, type SolanaAdapterSeams, TX_SIZE_LIMIT_BYTES, buildAdapterRegisterInstruction, collectAltAddresses, compileComposeV0, createSelfPayingComposeSend, createSolanaVaultAdapter, passkeySignerFromP256Keypair };
398
+ export { type AdapterRegisterIxParams, type CreateSolanaVaultAdapterOptions, SOLANA_FINAL_VOUCHER_V2_MEMO_PROGRAM_ID, SOLANA_FINAL_VOUCHER_V2_PROGRAM_ID, type SelfPayingComposeSend, type SelfPayingComposeSendOptions, type SolanaAdapterSeams, SolanaFinalVoucherV2ReservationError, type SolanaReservationPostStateEvidence, type SolanaReservationTransactionEvidence, type SolanaReservationVerifierSeams, TX_SIZE_LIMIT_BYTES, buildAdapterRegisterInstruction, collectAltAddresses, compileComposeV0, createSelfPayingComposeSend, createSolanaFinalVoucherV2ReservationVerifier, createSolanaVaultAdapter, passkeySignerFromP256Keypair, verifySolanaFinalVoucherV2Reservation };
@@ -1 +1 @@
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};
1
+ import{PublicKey as K,Transaction as Je}from"@solana/web3.js";import qt from"bs58";var F=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"}details};import{buildRegisterSessionKeyInstruction as ye,buildRevokeSessionKeyInstruction as he,deriveSwigWalletAddress as ln}from"@dexterai/vault/instructions";import{buildSecp256r1VerifyInstruction as Z}from"@dexterai/vault/precompile";import{DEXTER_VAULT_PROGRAM_ID as I,SECP256R1_PROGRAM_ID as mn,INSTRUCTIONS_SYSVAR_ID as gn}from"@dexterai/vault/constants";import{sessionRegisterMessage as fe,sessionReplaceV1Message as ve,sessionRevokeMessage as Ae,sessionVoucherV2Nonce as be,sessionVoucherV2AuthorizationNonce as hn,finalVoucherV2Sequence as fn,voucherV2SequenceOrdinal as vn,voucherPayloadMessage as Q,buildVoucherMessage as An}from"@dexterai/vault/messages";import z from"tweetnacl";import{PublicKey as D}from"@solana/web3.js";import{contextBoundVoucherV2Message as Ye,finalVoucherV2Sequence as Ze,sessionRegisterMessage as Qe,sessionVoucherV2AuthorizationNonce as et}from"@dexterai/vault/messages";import{deriveSessionPda as tt}from"@dexterai/vault/session";import{sha256 as st}from"@noble/hashes/sha256";function we(){let e=z.sign.keyPair();return{publicKey:e.publicKey,privateKey:e.secretKey}}function Se(e,t,n){return{publicKey:e.publicKey,privateKey:e.privateKey,scope:t,registration:n}}function Pe(e,t,n){if(n.length!==32)throw new Error(`channelIdBytes must be 32 bytes, got ${n.length}`);if(e.registration.length===188&&new DataView(e.registration.buffer,e.registration.byteOffset,e.registration.byteLength).getUint32(176,!0)>=2147483648)throw new Error("context-bound V2 sessions require signContextBoundFinalVoucherV2 and a durable reservation");let o=BigInt(t.cumulativeAmount),i=BigInt(e.scope.maxAmountAtomic);if(o>i)throw new Error(`voucher cumulative ${o} exceeds session cap ${i}`);let r=Math.floor(Date.now()/1e3);if(r>=e.scope.expiresAtUnix)throw new Error(`session expired at ${e.scope.expiresAtUnix}, now ${r}`);let s=Q({channelId:n,cumulativeAmount:o,sequenceNumber:t.sequenceNumber}),a=z.sign.detached(s,e.privateKey);return{payload:t,sessionPublicKey:e.publicKey,sessionRegistration:e.registration,sessionSignature:a}}var nt=/^[0-9a-f]{64}$/,ot=(1n<<64n)-1n;function ee(e){return Buffer.from(e).toString("hex")}function it(e){return Uint8Array.from(Buffer.from(e,"hex"))}function te(e,t){if(e.length!==t.length)return!1;let n=0;for(let o=0;o<e.length;o+=1)n|=(e[o]??0)^(t[o]??0);return n===0}function xe(e){if(!nt.test(e.channelId)||e.sessionPublicKey.length!==32||e.sessionPrivateKey.length!==64||e.sessionRegistration.length!==188||!/^[1-9][0-9]*$/.test(e.cumulativeAmountAtomic))throw new Error("native_tab_v2_signing_input_invalid");let t=BigInt(e.cumulativeAmountAtomic);if(t>ot)throw new Error("native_tab_v2_cumulative_amount_invalid");let n=new D(e.programId),o=new D(e.vaultPda),i=new D(e.sessionPda),r=new D(e.seller),[s]=tt(o,r,n);if(!i.equals(s))throw new Error("native_tab_v2_session_pda_mismatch");let a=e.sessionRegistration,u=new DataView(a.buffer,a.byteOffset,a.byteLength),d=u.getBigUint64(128,!0),m=u.getBigInt64(136,!0),v=u.getBigUint64(180,!0),g=e.nowUnixSeconds??Math.floor(Date.now()/1e3);if(!Number.isSafeInteger(g)||g<0)throw new Error("native_tab_v2_signing_time_invalid");if(!te(a,Qe({programId:n,vaultPda:o,sessionPubkey:e.sessionPublicKey,maxAmount:d,expiresAt:m,allowedCounterparty:r,nonce:e.sessionNonce,maxRevolvingCapacity:v})))throw new Error("native_tab_v2_registration_identity_mismatch");if(d===0n||v===0n||v>d||m<=BigInt(g)||m>0x7fffffffffffffffn-604800n||t>d)throw new Error("native_tab_v2_registration_semantics_invalid");et(e.sessionNonce);let y=z.sign.keyPair.fromSeed(e.sessionPrivateKey.subarray(0,32)),h=!1;try{h=te(y.publicKey,e.sessionPublicKey)&&te(e.sessionPrivateKey.subarray(32,64),e.sessionPublicKey)}finally{y.secretKey.fill(0)}if(!h)throw new Error("native_tab_v2_session_key_mismatch");let f=Ze(e.sequenceOrdinal),p=Ye({programId:n,vaultPda:o,sessionPda:i,seller:r,sessionNonce:e.sessionNonce,channelId:it(e.channelId),cumulativeAmount:t,sequenceNumber:f}),x=z.sign.detached(p,e.sessionPrivateKey);return{channelId:e.channelId,cumulativeAmount:e.cumulativeAmountAtomic,sequenceNumber:f,sessionPublicKey:ee(e.sessionPublicKey),sessionSignature:ee(x),sessionRegistration:ee(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 rt(e){let t=new Uint8Array(8);new DataView(t.buffer).setBigUint64(0,e.nonce,!0);let n=new TextEncoder().encode(e.sellerUrl),o=st.create();return o.update(e.vaultPda.toBytes()),o.update(n),o.update(t),o.digest()}import{fetchVaultSessionAccounts as Ht,fetchSessionAccount as Gt,decodeSessionAccount as Jt,deriveSessionPda as Y,isSessionLive as Wt,sessionPdasOf as Xt,waitForSession as jt,resolveVaultUsdcAta as We,composeRevokeThenRegister as Yt}from"@dexterai/vault/session";import{decodeVaultFull as Zt}from"@dexterai/vault/reader";import{fetchPasskeyAuthorizationState as Qt,validatePasskeyAuthorizationClientData as en}from"@dexterai/vault";import Cn from"tweetnacl";import{sha256 as kn}from"@noble/hashes/sha256";import{p256 as Tn}from"@noble/curves/p256";import{PublicKey as ne}from"@solana/web3.js";import{deriveSessionPda as $n,fetchSessionAccount as Fn,isSessionLive as Ln}from"@dexterai/vault/session";import{contextBoundVoucherV2Message as zn,sessionVoucherV2AuthorizationNonce as Mn,voucherV2SequenceOrdinal as qn}from"@dexterai/vault/messages";var oe="OTS_SESSION_REGISTER_V2",O=class extends Error{constructor(n,o){super(`Invalid registration: ${n}${o?` (${o})`:""}`);this.reason=n;this.name="InvalidRegistrationError"}reason};function M(e){if(e.length!==188)throw new O("wrong_length",`expected 188, got ${e.length}`);let t=new TextDecoder().decode(e.slice(0,oe.length));if(t!==oe)throw new O("wrong_domain",`got "${t}"`);for(let v=oe.length;v<32;v++)if(e[v]!==0)throw new O("wrong_domain",`non-NUL padding at byte ${v}`);let n=new DataView(e.buffer,e.byteOffset,e.byteLength),o=new ne(e.slice(32,64)),i=new ne(e.slice(64,96)),r=e.slice(96,128),s=n.getBigUint64(128,!0),a=n.getBigInt64(136,!0),u=new ne(e.slice(144,176)),d=n.getUint32(176,!0),m=n.getBigUint64(180,!0);if(!o.equals(I))throw new O("wrong_program",`${o.toBase58()} is not ${I.toBase58()}`);if(s===0n)throw new O("cap_zero");return{programId:o,vaultPda:i,sessionPubkey:new Uint8Array(r),maxAmount:s,expiresAt:a,allowedCounterparty:u,nonce:d,maxRevolvingCapacity:m}}import{sha256 as Xe}from"@noble/hashes/sha256";import{bytesToHex as me}from"@noble/hashes/utils";import{AddressLookupTableProgram as ie,ComputeBudgetProgram as _e,Transaction as at,TransactionMessage as ct,VersionedTransaction as lt}from"@solana/web3.js";var G=1232,ut=40,Re=20,Ie=4,dt=20,q=1e4,mt=1e6,H=4,U="[tab/solana/compose]";function ke(e,t){let n=new Set,o=[],i=t.toBase58();for(let r of e)for(let s of r.keys){if(s.isSigner)continue;let a=s.pubkey.toBase58();a===i||n.has(a)||(n.add(a),o.push(s.pubkey))}return o}function Ke(e,t,n,o){let i=new ct({payerKey:t,recentBlockhash:n,instructions:e}).compileToV0Message([o]);return new lt(i)}async function Ce(e){try{let t=(await e.getRecentPrioritizationFees()).map(o=>o.prioritizationFee).filter(o=>o>0).sort((o,i)=>o-i);if(t.length===0)return q;let n=t[Math.floor(.75*(t.length-1))]??q;return Math.max(q,Math.min(n,mt))}catch{return q}}function gt(e){let t=e,n=String(t?.message??e??""),o=Array.isArray(t?.logs)?t.logs.join(" "):"";return/already in use/i.test(n)||/already in use/i.test(o)}function Ve(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 se=e=>new Promise(t=>setTimeout(t,e));function re(e,t,n={}){let o=n.commitment??"confirmed",i=n.altWarmupPollMs??400,r=n.altReadbackPollMs??400,s=n.altCollisionPollMs??500,a=null,u=null;async function d(h,f){let p=await Ce(e),x=[_e.setComputeUnitPrice({microLamports:p}),...h],w;for(let S=0;S<H;S+=1){let{blockhash:b,lastValidBlockHeight:k}=await e.getLatestBlockhash(o),_=new at().add(...x);_.feePayer=t.publicKey,_.recentBlockhash=b,_.sign(t);try{let c=await e.sendRawTransaction(_.serialize(),{skipPreflight:!1,maxRetries:5}),A=await e.confirmTransaction({signature:c,blockhash:b,lastValidBlockHeight:k},o);if(A.value.err)throw new Error(`${f} tx failed on-chain: ${JSON.stringify(A.value.err)}`);return c}catch(c){if(Ve(c)&&S<H-1){console.warn(`${U} ${f} tx expired before landing (attempt ${S+1}) \u2014 rebroadcasting with a fresh blockhash`),w=c;continue}throw c}}throw w??new Error(`${f} tx did not land after rebroadcast attempts`)}async function m(h){for(let f=0;f<dt;f+=1){let p=await e.getSlot("finalized");if(p>h)return p;await se(s)}throw new Error(`ALT collision retry: finalized slot never advanced past ${h}`)}async function v(h){for(let f=0;f<ut;f+=1){if(await e.getSlot(o)>h)return;await se(i)}throw new Error(`ALT warmup timed out: preflight (${o}) slot never passed lastExtendedSlot ${h}`)}async function g(h){if(a)return a;let f=ke(h,t.publicKey),p=null,x=null,w=-1;for(let b=0;b<Ie;b+=1){let k=w<0?await e.getSlot("finalized"):await m(w),[_,c]=ie.createLookupTable({authority:t.publicKey,payer:t.publicKey,recentSlot:k}),A=ie.extendLookupTable({payer:t.publicKey,authority:t.publicKey,lookupTable:c,addresses:f});try{x=await d([_,A],"ALT create/extend"),p=c;break}catch(B){if(gt(B)&&b<Ie-1){w=k,console.warn(`${U} ALT address collision at slot ${k} (attempt ${b+1}) \u2014 retrying create with a fresh finalized slot`);continue}throw B}}if(!p||!x)throw new Error("ALT create exhausted retries after repeated address collisions");let S=await e.getAddressLookupTable(p);for(let b=0;b<Re&&!S.value;b+=1)await se(r),S=await e.getAddressLookupTable(p);if(!S.value)throw new Error(`ALT ${p.toBase58()} not visible after ${Re} read polls (${x})`);return await v(S.value.state.lastExtendedSlot),a=S.value,u=p,console.info(`${U} ephemeral compose ALT ready: ${p.toBase58()} (${f.length} addresses, createTx ${x})`),a}async function P(h){let f=await Ce(e),p=[_e.setComputeUnitPrice({microLamports:f}),...h],x=await g(p),w;for(let S=0;S<H;S+=1){let{blockhash:b,lastValidBlockHeight:k}=await e.getLatestBlockhash(o),_;try{let c=Ke(p,t.publicKey,b,x);c.sign([t]),_=c.serialize()}catch(c){throw/overrun|too large/i.test(String(c?.message??c))?new Error(`composed revoke-then-register v0 tx exceeds the ${G}B wire cap \u2014 too many sibling PDAs outside the lookup table`):c}if(_.length>G)throw new Error(`composed revoke-then-register v0 tx ${_.length}B exceeds the ${G}B wire cap \u2014 too many sibling PDAs outside the lookup table`);try{let c=await e.sendRawTransaction(_,{skipPreflight:!1,maxRetries:5}),A=await e.confirmTransaction({signature:c,blockhash:b,lastValidBlockHeight:k},o);if(A.value.err)throw new Error(`composed tx failed on-chain: ${JSON.stringify(A.value.err)}`);return c}catch(c){if(Ve(c)&&S<H-1){console.warn(`${U} compose tx expired before landing (attempt ${S+1}, priorityFee ${f}) \u2014 rebroadcasting with a fresh blockhash`),w=c;continue}let A=Array.isArray(c?.logs)?c.logs:[];throw A.length?new Error(`${c?.message??c} | ${A.join(" | ")}`):c}}throw w instanceof Error?w:new Error("compose tx did not land after rebroadcast attempts")}async function y(){if(u)try{let h=ie.deactivateLookupTable({lookupTable:u,authority:t.publicKey}),f=await d([h],"ALT deactivate");console.info(`${U} ephemeral compose ALT deactivated: ${u.toBase58()} (${f}) \u2014 rent reclaimable via close_lookup_table after the deactivation cooldown`)}catch(h){console.warn(`${U} ALT deactivate failed for ${u?.toBase58()} \u2014 rent parks until a later cleanup retries (the compose already landed): ${String(h?.message??h)}`)}}return{send:P,getAltAddress:()=>u,deactivateAlt:y}}import{PublicKey as T}from"@solana/web3.js";import{bytesToHex as le}from"@noble/hashes/utils";import{deriveGraphConfigPda as vt,deriveSwigVaultBindingPda as ue}from"@dexterai/vault/credit";import{DEXTER_VAULT_PROGRAM_ID as De,DISCRIMINATORS as At}from"@dexterai/vault/constants";import{deriveSwigWalletAddress as bt}from"@dexterai/vault/instructions";import{decodeVaultFull as wt}from"@dexterai/vault/reader";import{decodeSessionAccount as St,deriveSessionPda as de}from"@dexterai/vault/session";import{sha256 as Be}from"@noble/hashes/sha256";import{bytesToHex as N}from"@noble/hashes/utils";var Te=/^[0-9a-f]{64}$/,Ee=/^[A-Za-z0-9][A-Za-z0-9._:-]{0,199}$/,pt=/^[1-9A-HJ-NP-Za-km-z]{32,100}$/,Oe="solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",Ue="dexter-native-tab-v2-reservation/v1",yt=`${Ue}:`;function ae(e){if(e===null||typeof e=="string"||typeof e=="boolean")return e;if(typeof e=="number"){if(!Number.isFinite(e))throw new Error("canonical_non_finite_number");return e}if(typeof e=="bigint")return e.toString();if(Array.isArray(e))return e.map(ae);if(typeof e=="object")return Object.fromEntries(Object.entries(e).filter(([,t])=>t!==void 0).sort(([t],[n])=>t.localeCompare(n)).map(([t,n])=>[t,ae(n)]));throw new Error("canonical_value_unsupported")}function Ne(e){return JSON.stringify(ae(e))}function ce(e){if(e==="solana:mainnet"||e===Oe)return Oe;throw new Error("native_tab_v2_reservation_network_unsupported")}function $e(e){return N(Be(new TextEncoder().encode(Ne({channelId:e.payload.channelId,cumulativeAmount:e.payload.cumulativeAmount,sequenceNumber:e.payload.sequenceNumber,sessionPublicKey:N(e.sessionPublicKey),sessionSignature:N(e.sessionSignature),sessionRegistration:N(e.sessionRegistration)}))))}function ht(e){return N(Be(new TextEncoder().encode(Ne({contract:Ue,network:ce(e.network),programId:e.programId,buyerSwigAddress:e.buyerSwigAddress,vaultPda:e.vaultPda,sessionPda:e.sessionPda,seller:e.seller,channelId:e.channelId,sessionNonce:e.sessionNonce,reservationAmountAtomic:e.reservationAmountAtomic,previousCumulativeAtomic:e.previousCumulativeAtomic,voucherDigest:e.voucherDigest,cumulativeAmountAtomic:e.cumulativeAmountAtomic,sequenceNumber:e.sequenceNumber}))))}function ft(e){let t=$e(e.voucher);return ht({network:e.network,programId:e.programId,buyerSwigAddress:e.buyerSwigAddress,vaultPda:e.vaultPda,sessionPda:e.sessionPda,seller:e.seller,channelId:e.channelId,sessionNonce:e.sessionNonce,reservationAmountAtomic:e.reservationAmountAtomic,previousCumulativeAtomic:e.previousCumulativeAtomic,voucherDigest:t,cumulativeAmountAtomic:e.voucher.payload.cumulativeAmount,sequenceNumber:e.voucher.payload.sequenceNumber})}function Fe(e){return`${yt}${ft(e)}`}function R(e){throw new Error(`native_tab_v2_reservation_receipt_invalid:${e}`)}function J(e,t){(!Number.isSafeInteger(e)||e<0)&&R(t)}function Le(e,t){(!t||typeof t!="object")&&R("missing");let n=$e(e.voucher);(!Te.test(e.voucherDigest)||e.voucherDigest!==n)&&R("input_voucher_digest"),e.idempotencyKey!==`native-tab-v2:${n}`&&R("input_idempotency_identity");let o=BigInt(e.voucher.payload.cumulativeAmount),i=BigInt(e.previousCumulativeAtomic),r=BigInt(e.reservationAmountAtomic);(o<=i||o-i!==r||r<=0n)&&R("input_reservation_delta"),(e.voucher.payload.channelId!==e.channelId||(e.voucher.payload.sequenceNumber&2147483648)===0||(e.sessionNonce&2147483648)===0||e.voucher.sessionPublicKey.length!==32||e.voucher.sessionSignature.length!==64||e.voucher.sessionRegistration.length!==188)&&R("input_voucher_identity"),t.contract!=="dexter-native-tab-open-receipt/v1"&&t.contract!=="dexter-native-tab-open-receipt/v2"&&R("contract"),Te.test(t.operationId)||R("operation_id"),Ee.test(t.callerOperationId)||R("caller_operation_id"),pt.test(t.transaction)||R("transaction"),t.commitment!=="finalized"&&R("commitment"),J(t.confirmationSlot,"confirmation_slot"),J(t.postStateSlot,"post_state_slot"),(t.confirmationSlot===0||t.postStateSlot<t.confirmationSlot)&&R("post_state_slot");let s,a;try{s=ce(e.network),a=ce(t.network)}catch{return R("network")}(a!==s||t.buyerSwigAddress!==e.buyerSwigAddress||t.vaultPda!==e.vaultPda||t.sessionPda!==e.sessionPda||t.seller!==e.seller||t.channelId!==e.channelId||t.sessionPublicKey!==N(e.voucher.sessionPublicKey)||t.voucherDigest!==n||t.cumulativeAmountAtomic!==e.voucher.payload.cumulativeAmount||t.sequenceNumber!==e.voucher.payload.sequenceNumber||!Ee.test(t.providerReceiptId)||t.reservationAmountAtomic!==e.reservationAmountAtomic||t.currentOutstandingBeforeAtomic!=="0"||t.currentOutstandingAfterAtomic!==e.reservationAmountAtomic)&&R("economic_identity"),J(t.pendingVoucherCountBefore,"pending_voucher_count_before"),J(t.pendingVoucherCountAfter,"pending_voucher_count_after"),t.contract==="dexter-native-tab-open-receipt/v1"?t.callerOperationId!==e.idempotencyKey&&R("idempotency_key"):(t.rootOperationId!==e.idempotencyKey||!Number.isSafeInteger(t.generation)||Number(t.generation)<2||!t.predecessorCallerOperationId||!t.predecessorLifecycleOperationId||!t.predecessorReleaseDigest||!t.stableReservationId||!t.economicEffectDigest)&&R("successor_identity")}var Pt=Uint8Array.from([56,67,4,209,238,143,0,129]),xt=74,ze=new Set([1,2]),_t=188,Me=new T("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"),Rt=(()=>{let e=Buffer.alloc(32);return e.write("OTS_SESSION_REGISTER_V2","ascii"),e})(),W=class extends Error{constructor(n,o){super(`native_tab_v2_solana_reservation_invalid:${n}`+(o?`:${o}`:""));this.code=n;this.name="SolanaFinalVoucherV2ReservationError"}code};function l(e,t){throw new W(e,t)}function C(e,t){try{return new T(e)}catch{return l(t)}}function X(e,t){return e.length===t.length&&e.every((n,o)=>n===t[o])}async function It(e){let t=await e.connection.getTransaction(e.signature,{commitment:e.commitment,maxSupportedTransactionVersion:0});if(!t)return null;t.meta||l("transaction_meta_missing");let n=t.transaction.message,o=n.version===0?n.getAccountKeys({accountKeysFromLookups:t.meta.loadedAddresses??null}):n.getAccountKeys(),i=(r,s)=>{let a=o.get(r);return a||l(s),a};return{slot:t.slot,err:t.meta.err,signatures:[...t.transaction.signatures],accountKeys:Array.from({length:o.length},(r,s)=>({address:i(s,"transaction_account_key").toBase58(),signer:n.isAccountSigner(s),writable:n.isAccountWritable(s)})),instructions:n.compiledInstructions.map(r=>({programId:i(r.programIdIndex,"transaction_program_id").toBase58(),accounts:r.accountKeyIndexes.map(s=>i(s,"transaction_instruction_account").toBase58()),data:Uint8Array.from(r.data)}))}}function Ct(e,t,n,o){o.length!==xt&&l("binding_length"),X(o.subarray(0,8),Pt)||l("binding_discriminator");let i=o.readUInt8(8),r=o.readUInt8(9);return ze.has(i)||l("binding_version"),r!==t&&l("binding_bump"),{address:e.toBase58(),owner:n.toBase58(),version:i,bump:r,swig:new T(o.subarray(10,42)).toBase58(),vault:new T(o.subarray(42,74)).toBase58()}}async function Vt(e){let t=C(e.input.programId,"program_id"),n=C(e.input.buyerSwigAddress,"buyer_swig"),o=C(e.input.vaultPda,"vault_pda"),i=C(e.input.seller,"seller"),[r,s]=ue(n,t),[a]=de(o,i,t),u=await e.connection.getMultipleAccountsInfoAndContext([r,o,a],{commitment:e.receipt.commitment,minContextSlot:e.receipt.postStateSlot}),[d,m,v]=u.value;d||l("binding_missing"),m||l("vault_missing"),v||l("session_missing");let g,P;try{g=wt(Buffer.from(m.data)),P=St(a,v.data)}catch(h){return l("post_state_decode",h instanceof Error?h.message:String(h))}let y=P.session;return{contextSlot:u.context.slot,binding:Ct(r,s,d.owner,Buffer.from(d.data)),vault:{owner:m.owner.toBase58(),exists:g.exists,version:g.version,swigAddress:g.swigAddress,dexterAuthority:g.dexterAuthority,pendingVoucherCount:g.pendingVoucherCount},session:{owner:v.owner.toBase58(),version:P.version,bump:P.bump,vault:P.vault,sessionPublicKey:le(y.sessionPubkey),maxAmount:y.maxAmount,expiresAt:y.expiresAt,seller:y.allowedCounterparty,nonce:y.nonce,spent:y.spent,currentOutstanding:y.currentOutstanding,maxRevolvingCapacity:y.maxRevolvingCapacity,crystallizedCumulative:y.crystallizedCumulative}}}function kt(e){let t=Buffer.from(e.voucher.sessionRegistration);return t.length!==_t&&l("registration_length"),X(t.subarray(0,32),Rt)||l("registration_domain"),{programId:new T(t.subarray(32,64)).toBase58(),vaultPda:new T(t.subarray(64,96)).toBase58(),sessionPublicKey:le(t.subarray(96,128)),maxAmount:t.readBigUInt64LE(128),expiresAt:t.readBigInt64LE(136),seller:new T(t.subarray(144,176)).toBase58(),nonce:t.readUInt32LE(176),maxRevolvingCapacity:t.readBigUInt64LE(180)}}function $(e,t,n){let o=e.accountKeys.filter(i=>i.address===t);return o.length!==1&&l(`${n}_account_key`),o[0]}function Kt(e,t,n){(!Number.isSafeInteger(n.slot)||n.slot<=0)&&l("transaction_slot"),n.slot!==t.confirmationSlot&&l("transaction_confirmation_slot"),n.err!==null&&l("transaction_failed"),n.signatures[0]!==t.transaction&&l("transaction_signature"),n.instructions.length!==2&&l("transaction_instruction_count");let o=C(e.programId,"program_id"),i=C(e.buyerSwigAddress,"buyer_swig"),r=C(e.vaultPda,"vault_pda"),s=C(e.seller,"seller"),a=C(e.sessionPda,"session_pda"),[u]=de(r,s,o),d=ue(i,o)[0],m=bt(i),v=vt(o)[0];a.equals(u)||l("session_pda_derivation");let g=Buffer.from(At.settle_voucher),P=n.instructions.filter(c=>{if(c.programId!==e.programId)return!1;let A=c.data;return A.length>=g.length&&X(A.subarray(0,g.length),g)});P.length!==1&&l("settle_voucher_instruction_count");let y=P[0];n.instructions[0]!==y&&l("settle_voucher_instruction_order");let h=Buffer.from(y.data);h.length!==49&&l("settle_voucher_instruction_length"),h.readBigUInt64LE(8).toString()!==e.reservationAmountAtomic&&l("settle_voucher_amount"),h.readUInt8(16)!==1&&l("settle_voucher_increment"),new T(h.subarray(17,49)).equals(s)||l("settle_voucher_seller"),y.accounts.length<8&&l("settle_voucher_accounts"),[r.toBase58(),null,a.toBase58(),null,i.toBase58(),m.toBase58(),d.toBase58(),v.toBase58()].forEach((c,A)=>{c!==null&&y.accounts[A]!==c&&l(`settle_voucher_account_${A}`)});let p=y.accounts[1];p||l("dexter_authority");let x=$(n,y.accounts[0],"vault"),w=$(n,p,"dexter_authority"),S=$(n,y.accounts[2],"session");(!x.writable||x.signer)&&l("vault_privileges"),w.signer||l("dexter_authority_signature"),(!S.writable||S.signer)&&l("session_privileges");for(let c=3;c<Math.min(y.accounts.length,8);c+=1)$(n,y.accounts[c],`account_${c}`).signer&&l(`settle_voucher_account_${c}_signer`);for(let c=8;c<y.accounts.length;c+=1){let A=$(n,y.accounts[c],`sibling_${c-8}`);(!A.writable||A.signer)&&l("settle_voucher_sibling_privileges")}let b=n.instructions[1];b.programId!==Me.toBase58()&&l("reservation_memo_program"),(b.accounts.length!==1||b.accounts[0]!==p)&&l("reservation_memo_authority"),$(n,p,"reservation_memo_authority").signer||l("reservation_memo_authority_signature");let _=new TextEncoder().encode(Fe(e));return X(b.data,_)||l("reservation_memo_digest"),p}function Tt(e,t,n,o){let i=C(e.programId,"program_id"),r=C(e.buyerSwigAddress,"buyer_swig"),s=C(e.vaultPda,"vault_pda"),a=C(e.seller,"seller"),[u,d]=ue(r,i),[m,v]=de(s,a,i);(!Number.isSafeInteger(o.contextSlot)||o.contextSlot<t.postStateSlot||o.contextSlot<t.confirmationSlot)&&l("post_state_slot"),(o.binding.address!==u.toBase58()||o.binding.owner!==e.programId||o.binding.bump!==d||!ze.has(o.binding.version)||o.binding.swig!==e.buyerSwigAddress||o.binding.vault!==e.vaultPda)&&l("binding_identity"),(o.vault.owner!==e.programId||!o.vault.exists||o.vault.version!==7||o.vault.swigAddress!==e.buyerSwigAddress||o.vault.dexterAuthority!==n)&&l("vault_post_state"),(e.sessionPda!==m.toBase58()||o.session.owner!==e.programId||o.session.version!==1||o.session.bump!==v||o.session.vault!==e.vaultPda||o.session.sessionPublicKey!==le(e.voucher.sessionPublicKey)||o.session.seller!==e.seller||o.session.nonce!==e.sessionNonce||o.session.currentOutstanding.toString()!==e.reservationAmountAtomic)&&l("session_post_state");let g=kt(e);(g.programId!==e.programId||g.vaultPda!==e.vaultPda||g.sessionPublicKey!==o.session.sessionPublicKey||g.seller!==e.seller||g.nonce!==e.sessionNonce||g.maxAmount!==o.session.maxAmount||g.expiresAt!==BigInt(o.session.expiresAt)||g.maxRevolvingCapacity!==o.session.maxRevolvingCapacity)&&l("registration_post_state"),(o.session.spent>o.session.crystallizedCumulative?o.session.spent:o.session.crystallizedCumulative).toString()!==e.previousCumulativeAtomic&&l("session_frontier")}async function j(e,t,n,o={}){try{Le(t,n)}catch(a){return l("provider_receipt",a instanceof Error?a.message:String(a))}t.network!=="solana:mainnet"&&l("network"),t.programId!==De.toBase58()&&l("program_id");let i=await(o.readTransaction??It)({connection:e,signature:n.transaction,commitment:n.commitment});i||l("transaction_missing");let r=Kt(t,n,i),s=await(o.readPostState??Vt)({connection:e,input:t,receipt:n});Tt(t,n,r,s)}function Et(e,t={}){return(n,o)=>j(e,n,o,t)}var Ot=De,Bt=Me;import{p256 as He}from"@noble/curves/p256";import{sha256 as L}from"@noble/hashes/sha256";import{buildPasskeyAuthorizationChallenge as Ut,classifyPasskeyAuthorizationOperation as Nt}from"@dexterai/vault";import{sessionVoucherV2AuthorizationNonce as $t}from"@dexterai/vault/messages";var Ge="dexter.cash";function Ft(e){return Buffer.from(e).toString("base64").replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function Lt(e,t=`https://${Ge}`){let o={type:"webauthn.get",challenge:Ft(e),origin:t,crossOrigin:!1};return new TextEncoder().encode(JSON.stringify(o))}function Dt(e=1){let t=L(new TextEncoder().encode(Ge)),n=new Uint8Array(37);return n.set(t,0),n[32]=5,new DataView(n.buffer).setUint32(33,e,!1),n}function qe(e,t){let n=Lt(t),o=Dt(1),i=new Uint8Array(o.length+32);i.set(o,0),i.set(L(n),o.length);let r=L(i);return{signature:He.sign(r,e.privateKey,{lowS:!0}).toCompactRawBytes(),clientDataJSON:n,authenticatorData:o}}function zt(e,t={}){return{credentialId:new Uint8Array(0),publicKey:e.publicKey,signOperation:async n=>{let o=t.resolveAuthorizationContext?await t.resolveAuthorizationContext(n.slice()):Mt(n);if(!o){if(t.allowLegacyOperationHash===!0)return qe(e,L(n));throw new Error("passkey_authorization_context_required")}let i=t.ceremonyNonce?t.ceremonyNonce():He.utils.randomPrivateKey();if(i.length!==32)throw new Error("ceremonyNonce must be exactly 32 bytes");let r=Ut({programId:o.programId,vault:o.vault,nonce:o.nonce,operationHash:L(n),ceremonyNonce:i});return qe(e,r)}}}function Mt(e){let t=Nt(e);return t.kind==="session_register_v2"?{programId:t.fields.programId,vault:t.fields.vault,nonce:BigInt($t(t.fields.registrationNonce))}:t.kind==="session_replace_v1"?{programId:t.fields.programId,vault:t.fields.vault,nonce:t.fields.authorizationNonce}:null}async function tn({connection:e,vaultPda:t,allowedCounterparty:n,programId:o=I,commitment:i="finalized"}){let[r]=Y(t,n,o),s=await e.getMultipleAccountsInfoAndContext([t,r],{commitment:i}),[a,u]=s.value;if(!a)throw new Error("close revocation: vault account not found");if(!a.owner.equals(o))throw new Error("close revocation: vault has the wrong owner");let d=Zt(Buffer.from(a.data));if(!d.exists||d.version!==7)throw new Error("close revocation: Vault V7 required");if(!u)return{kind:"invalidated",contextSlot:s.context.slot,sessionPda:r,reason:"absent"};if(!u.owner.equals(o))throw new Error("close revocation: session has the wrong owner");let m=Jt(r,u.data);if(m.version===0)return{kind:"invalidated",contextSlot:s.context.slot,sessionPda:r,reason:"cleared"};if(m.version!==1)throw new Error("close revocation: live SessionAccount required");if(m.vault!==t.toBase58())throw new Error("close revocation: session belongs to a different vault");if(m.session.allowedCounterparty!==n.toBase58())throw new Error("close revocation: session counterparty mismatch");return{kind:"live",snapshot:{contextSlot:s.context.slot,programId:new K(o),vaultPda:new K(t),sessionPda:r,sessionPubkey:Uint8Array.from(m.session.sessionPubkey),maxAmount:m.session.maxAmount,expiresAt:Buffer.from(u.data).readBigInt64LE(82),allowedCounterparty:new K(n),nonce:m.session.nonce,spent:m.session.spent,currentOutstanding:m.session.currentOutstanding,maxRevolvingCapacity:m.session.maxRevolvingCapacity,crystallizedCumulative:m.session.crystallizedCumulative,lastLockedSequence:m.session.lastLockedSequence,expectedPendingVoucherCount:d.pendingVoucherCount}}}function nn(e){return ye({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 ge=class{network="solana:mainnet";sessionVoucherVersion=2;swigAddress;vaultPda;connection;vaultPdaKey;passkey;feePayer;confirmOptions;seams;pendingCloseRevocations=new Map;completedCloseRevocations=new Map;constructor(t){this.connection=t.connection,this.swigAddress=typeof t.swigAddress=="string"?t.swigAddress:t.swigAddress.toBase58(),this.vaultPdaKey=typeof t.vaultPda=="string"?new K(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??{}}closeRevocationKey(t){let n=M(t.registration),[o]=Y(this.vaultPdaKey,n.allowedCounterparty,I);return[o.toBase58(),me(n.sessionPubkey),n.nonce.toString()].join(":")}async readCloseTargetState(t){let n={connection:this.connection,vaultPda:this.vaultPdaKey,allowedCounterparty:t,programId:I,commitment:"finalized"};if(this.seams.readCloseRevocationTargetState)return this.seams.readCloseRevocationTargetState(n);if(this.seams.readCloseRevocationSnapshot)try{return{kind:"live",snapshot:await this.seams.readCloseRevocationSnapshot(n)}}catch{return null}return tn(n)}targetInvalidated(t,n){if(t.kind==="invalidated")return!0;let o=t.snapshot,[i]=Y(this.vaultPdaKey,n.allowedCounterparty,I);if(!o.programId.equals(I)||!o.vaultPda.equals(this.vaultPdaKey)||!o.sessionPda.equals(i)||!o.allowedCounterparty.equals(n.allowedCounterparty))throw new Error("session revocation snapshot identity mismatch");if(!Buffer.from(o.sessionPubkey).equals(Buffer.from(n.sessionPubkey))||o.nonce!==n.nonce)return!0;if(o.maxAmount!==n.maxAmount||o.expiresAt!==n.expiresAt||o.maxRevolvingCapacity!==n.maxRevolvingCapacity)throw new Error("session revocation snapshot identity mismatch");return!1}rememberCompletedClose(t,n){let o=Uint8Array.from(n);return this.pendingCloseRevocations.delete(t),this.completedCloseRevocations.set(t,o),Uint8Array.from(o)}async reconcilePendingClose(t,n,o){let i=!1,r=null;try{let u=await this.connection.getSignatureStatuses([t.signature],{searchTransactionHistory:!0});if(i=!0,r=u.value[0]??null,r?.confirmationStatus==="finalized")return r.err===null?"complete":"fresh_allowed"}catch{}let s=!1;try{let u=await this.connection.getTransaction(t.signature,{commitment:"finalized",maxSupportedTransactionVersion:0});if(s=!0,u)return!u.meta||!Object.prototype.hasOwnProperty.call(u.meta,"err")?"unresolved":u.meta.err===null?"complete":"fresh_allowed"}catch{}let a=await this.readCloseTargetState(n.allowedCounterparty).catch(()=>null);if(a&&this.targetInvalidated(a,n))return"complete";if(o&&i&&r===null)try{if((await this.connection.isBlockhashValid(t.blockhash,{commitment:"confirmed"})).value)return await this.connection.sendRawTransaction(t.serializedTransaction,{skipPreflight:!1,preflightCommitment:this.confirmOptions.preflightCommitment??this.confirmOptions.commitment})!==t.signature?"unresolved":(await this.connection.confirmTransaction({signature:t.signature,blockhash:t.blockhash,lastValidBlockHeight:t.lastValidBlockHeight},"finalized")).value.err===null?"complete":"fresh_allowed"}catch{}if(i&&r!==null||!i||!s||t.finalizedHistoryFloorSlot===null)return"unresolved";try{let[u,d]=await Promise.all([this.connection.getBlockHeight("finalized"),this.connection.getMinimumLedgerSlot()]);if(u>t.lastValidBlockHeight&&d<=t.finalizedHistoryFloorSlot)return"fresh_allowed"}catch{}return"unresolved"}async authorizeSession(t,n){let o=new K(t.allowedCounterparty),i=E(t.revolvingCapacityAtomic??t.maxAmountAtomic),s=await(this.seams.fetchSession??Gt)(this.connection,this.vaultPdaKey,o),a=s!==null&&Wt(s);if(a&&(n?.onLiveSession??"error")!=="replace"){let f=s.session.spent,p=s.session.crystallizedCumulative;throw new F({allowedCounterparty:t.allowedCounterparty,sessionPubkeyHex:me(s.session.sessionPubkey),expiresAtUnix:s.session.expiresAt,spentAtomic:f.toString(),crystallizedCumulativeAtomic:p.toString(),currentOutstandingAtomic:s.session.currentOutstanding.toString(),frontierAtomic:(f>p?f:p).toString()})}let d=await(this.seams.fetchPasskeyAuthorization??Qt)(this.connection,this.vaultPdaKey,I);if(d===null||d.version!==1||!d.vault.equals(this.vaultPdaKey))throw new Error("passkey_authorization_guard_unavailable");let m=we(),v=be(d.nonce),g=fe({programId:I,vaultPda:this.vaultPdaKey,sessionPubkey:m.publicKey,maxAmount:E(t.maxAmountAtomic),maxRevolvingCapacity:i,expiresAt:BigInt(t.expiresAtUnix),allowedCounterparty:o,nonce:v}),P=a?ve({programId:I,vaultPda:this.vaultPdaKey,sessionPda:new K(s.address),authorizationNonce:d.nonce,retired:{sessionPubkey:s.session.sessionPubkey,maxAmount:s.session.maxAmount,expiresAt:BigInt(s.session.expiresAt),allowedCounterparty:new K(s.session.allowedCounterparty),nonce:s.session.nonce,spent:s.session.spent,currentOutstanding:s.session.currentOutstanding,maxRevolvingCapacity:s.session.maxRevolvingCapacity,crystallizedCumulative:s.session.crystallizedCumulative,lastLockedSequence:s.session.lastLockedSequence},replacement:{sessionPubkey:m.publicKey,maxAmount:E(t.maxAmountAtomic),expiresAt:BigInt(t.expiresAtUnix),allowedCounterparty:o,nonce:v,maxRevolvingCapacity:i}}):g,y=await this.passkey.signOperation(P);if(a)await this.sendAtomicReplace(t,o,m.publicKey,v,i,y);else{if(en({clientDataJSON:y.clientDataJSON,operationMessage:P,expectedVault:this.vaultPdaKey,expectedProgramId:I}).nonce!==d.nonce)throw new Error("passkey_authorization_guard_changed");await this.sendBareRegister(t,o,m.publicKey,v,i,y)}return await(this.seams.waitForSession??jt)(this.connection,this.vaultPdaKey,o,{expectedSessionPubkey:m.publicKey,timeoutMs:2e4}),Se(m,t,g)}async sendBareRegister(t,n,o,i,r,s){let{signature:a,clientDataJSON:u,authenticatorData:d}=s,m=je(d,Xe(u)),v=Z(this.passkey.publicKey,a,m),g=this.seams.fetchSessions??Ht,P=Xt(await g(this.connection,this.vaultPdaKey)),h=await(this.seams.resolveUsdcAta??We)(this.connection,new K(this.swigAddress)),f=nn({vaultPda:this.vaultPdaKey,swigAddress:new K(this.swigAddress),sessionPubkey:o,maxAmount:E(t.maxAmountAtomic),maxRevolvingCapacity:r,expiresAt:BigInt(t.expiresAtUnix),allowedCounterparty:n,nonce:i,clientDataJSON:u,authenticatorData:d,payer:this.feePayer.publicKey,siblingSessionPdas:P,vaultUsdcAta:h}),p=new Je().add(v,f);p.feePayer=this.feePayer.publicKey;let{blockhash:x}=await this.connection.getLatestBlockhash(this.confirmOptions.commitment);p.recentBlockhash=x,p.sign(this.feePayer);let w=await this.connection.sendRawTransaction(p.serialize(),{skipPreflight:!1,preflightCommitment:this.confirmOptions.preflightCommitment??this.confirmOptions.commitment});await this.connection.confirmTransaction({signature:w,blockhash:x,lastValidBlockHeight:(await this.connection.getLatestBlockhash(this.confirmOptions.commitment)).lastValidBlockHeight},this.confirmOptions.commitment)}async sendAtomicReplace(t,n,o,i,r,s){let u=await(this.seams.resolveUsdcAta??We)(this.connection,new K(this.swigAddress)),d=this.seams.composeSend?{send:this.seams.composeSend,deactivateAlt:async()=>{}}:re(this.connection,this.feePayer,{commitment:this.confirmOptions.commitment});try{await Yt({connection:this.connection,vaultPda:this.vaultPdaKey,allowedCounterparty:n,registerArgs:{sessionPubkey:o,maxAmount:E(t.maxAmountAtomic),maxRevolvingCapacity:r,expiresAt:BigInt(t.expiresAtUnix),nonce:i,swigAddress:new K(this.swigAddress),vaultUsdcAta:u,payer:this.feePayer.publicKey},registerCeremony:{clientDataJSON:s.clientDataJSON,authenticatorData:s.authenticatorData,signature:s.signature},credentialPublicKey:this.passkey.publicKey,send:d.send,fetchSession:this.seams.fetchSession,fetchSessions:this.seams.fetchSessions,fetchPasskeyAuthorization:this.seams.fetchPasskeyAuthorization})}finally{d.deactivateAlt()}}async signWithSession(t,n){let o=await on(n.channelId),i=M(t.registration);if((i.nonce&2147483648)!==0){let[r]=Y(i.vaultPda,i.allowedCounterparty,i.programId),s=xe({programId:i.programId.toBase58(),vaultPda:i.vaultPda.toBase58(),sessionPda:r.toBase58(),seller:i.allowedCounterparty.toBase58(),sessionNonce:i.nonce,channelId:me(o),cumulativeAmountAtomic:n.cumulativeAmount,sequenceOrdinal:n.sequenceNumber,sessionPrivateKey:t.privateKey,sessionPublicKey:t.publicKey,sessionRegistration:t.registration});return{payload:{channelId:s.channelId,cumulativeAmount:s.cumulativeAmount,sequenceNumber:s.sequenceNumber},sessionPublicKey:Uint8Array.from(Buffer.from(s.sessionPublicKey,"hex")),sessionSignature:Uint8Array.from(Buffer.from(s.sessionSignature,"hex")),sessionRegistration:Uint8Array.from(Buffer.from(s.sessionRegistration,"hex"))}}return Pe(t,n,o)}async signOpenTab(t,n){return t.registration}async verifyFinalVoucherV2Reservation(t,n){await j(this.connection,t,n)}async signCloseTab(t,n,o){let i=M(t.registration);if(!i.vaultPda.equals(this.vaultPdaKey)||!Buffer.from(i.sessionPubkey).equals(Buffer.from(t.publicKey)))throw new Error("session registration identity mismatch");let r=this.closeRevocationKey(t),s=this.completedCloseRevocations.get(r);if(s)return Uint8Array.from(s);let a=this.pendingCloseRevocations.get(r);if(a){let V=await this.reconcilePendingClose(a,i,!0);if(V==="complete")return this.rememberCompletedClose(r,a.message);if(V==="unresolved")throw new Error(`session revoke finality unresolved for ${a.signature}; retry close`);this.pendingCloseRevocations.delete(r)}let u=await this.readCloseTargetState(i.allowedCounterparty);if(!u)throw new Error("close revocation target state unavailable");if(u.kind==="invalidated"||this.targetInvalidated(u,i))return this.rememberCompletedClose(r,t.registration);let d=u.snapshot,m=E(o);if((d.spent>d.crystallizedCumulative?d.spent:d.crystallizedCumulative)<m)throw new Error("session revocation snapshot is behind final settlement");let g=Ae(d),{signature:P,clientDataJSON:y,authenticatorData:h}=await this.passkey.signOperation(g),f=je(h,Xe(y)),p=Z(this.passkey.publicKey,P,f),x=he({vaultPda:this.vaultPdaKey,allowedCounterparty:d.allowedCounterparty,expectedPendingVoucherCount:d.expectedPendingVoucherCount,clientDataJSON:y,authenticatorData:h}),w=new Je().add(p,x);w.feePayer=this.feePayer.publicKey;let S=null;try{let V=await this.connection.getSlot("finalized");S=Number.isSafeInteger(V)&&V>=0?V:null}catch{}let{blockhash:b,lastValidBlockHeight:k}=await this.connection.getLatestBlockhash(this.confirmOptions.commitment);if(w.recentBlockhash=b,w.sign(this.feePayer),!w.signature)throw new Error("session revoke transaction is unsigned");let _=Uint8Array.from(w.serialize()),c=qt.encode(w.signature),A={key:r,message:Uint8Array.from(g),serializedTransaction:_,signature:c,blockhash:b,lastValidBlockHeight:k,finalizedHistoryFloorSlot:S};this.pendingCloseRevocations.set(r,A);let B;try{let V=await this.connection.sendRawTransaction(_,{skipPreflight:!1,preflightCommitment:this.confirmOptions.preflightCommitment??this.confirmOptions.commitment});if(V!==c)throw new Error(`session revoke signature mismatch expected=${c} returned=${V}`);B=await this.connection.confirmTransaction({signature:c,blockhash:b,lastValidBlockHeight:k},"finalized")}catch(V){let pe=await this.reconcilePendingClose(A,i,!1);if(pe==="complete")return this.rememberCompletedClose(r,g);throw pe==="fresh_allowed"?(this.pendingCloseRevocations.delete(r),new Error("session revoke transaction finalized without effect; retry close",{cause:V})):new Error(`session revoke finality unresolved for ${c}; retry close`,{cause:V})}if(B.value.err)throw this.pendingCloseRevocations.delete(r),new Error(`session revoke transaction failed: ${JSON.stringify(B.value.err)}`);return this.rememberCompletedClose(r,g)}};function To(e){return new ge(e)}function je(e,t){let n=new Uint8Array(e.length+t.length);return n.set(e,0),n.set(t,e.length),n}async function on(e){if(/^[0-9a-f]{64}$/i.test(e))return sn(e);let{sha256:t}=await import("@noble/hashes/sha256");return t(new TextEncoder().encode(e))}function sn(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{F as LiveSessionExistsError,Bt as SOLANA_FINAL_VOUCHER_V2_MEMO_PROGRAM_ID,Ot as SOLANA_FINAL_VOUCHER_V2_PROGRAM_ID,W as SolanaFinalVoucherV2ReservationError,G as TX_SIZE_LIMIT_BYTES,nn as buildAdapterRegisterInstruction,ke as collectAltAddresses,Ke as compileComposeV0,re as createSelfPayingComposeSend,Et as createSolanaFinalVoucherV2ReservationVerifier,To as createSolanaVaultAdapter,rt as deriveChannelId,zt as passkeySignerFromP256Keypair,j as verifySolanaFinalVoucherV2Reservation};