@dexterai/vault 0.4.2 → 0.6.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.
@@ -0,0 +1,631 @@
1
+ // src/instructions/initialize.ts
2
+ import {
3
+ TransactionInstruction,
4
+ SystemProgram
5
+ } from "@solana/web3.js";
6
+
7
+ // src/constants/index.ts
8
+ import { PublicKey } from "@solana/web3.js";
9
+ var DEXTER_VAULT_PROGRAM_ID = new PublicKey(
10
+ "Hg3wRaydFtJhYrdvYrKECacpJYDsC9Px7yKmpncj2fhc"
11
+ );
12
+ var SWIG_PROGRAM_ID = new PublicKey(
13
+ "swigypWHEksbC64pWKwah1WTeh9JXwx8H1rJHLdbQMB"
14
+ );
15
+ var SECP256R1_PROGRAM_ID = new PublicKey(
16
+ "Secp256r1SigVerify1111111111111111111111111"
17
+ );
18
+ var ED25519_PROGRAM_ID = new PublicKey(
19
+ "Ed25519SigVerify111111111111111111111111111"
20
+ );
21
+ var INSTRUCTIONS_SYSVAR_ID = new PublicKey(
22
+ "Sysvar1nstructions1111111111111111111111111"
23
+ );
24
+ var USDC_MAINNET = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
25
+ var VAULT_SEED_PREFIX = Buffer.from("vault");
26
+ var LOCKED_CLAIM_SEED = Buffer.from("locked-claim");
27
+ var DISCRIMINATORS = Object.freeze({
28
+ initialize_vault: Uint8Array.from([48, 191, 163, 44, 71, 129, 63, 164]),
29
+ set_swig: Uint8Array.from([253, 229, 89, 206, 192, 118, 137, 165]),
30
+ settle_voucher: Uint8Array.from([144, 176, 128, 220, 156, 79, 41, 54]),
31
+ request_withdrawal: Uint8Array.from([251, 85, 121, 205, 56, 201, 12, 177]),
32
+ finalize_withdrawal: Uint8Array.from([178, 87, 206, 68, 201, 186, 164, 232]),
33
+ force_release: Uint8Array.from([122, 190, 243, 252, 54, 202, 208, 234]),
34
+ rotate_passkey: Uint8Array.from([28, 134, 49, 89, 196, 34, 58, 174]),
35
+ rotate_dexter_authority: Uint8Array.from([145, 60, 4, 119, 180, 205, 236, 134]),
36
+ prove_passkey: Uint8Array.from([35, 175, 41, 143, 201, 118, 49, 184]),
37
+ settle_tab_voucher: Uint8Array.from([173, 22, 98, 31, 110, 129, 59, 161]),
38
+ register_session_key: Uint8Array.from([69, 94, 60, 44, 49, 199, 183, 233]),
39
+ revoke_session_key: Uint8Array.from([81, 192, 32, 110, 104, 116, 144, 151]),
40
+ lock_voucher: Uint8Array.from([91, 138, 5, 227, 119, 239, 48, 254]),
41
+ settle_locked_voucher: Uint8Array.from([44, 80, 216, 43, 247, 253, 101, 45]),
42
+ transfer_lock_ownership: Uint8Array.from([193, 13, 131, 134, 95, 25, 229, 157]),
43
+ recover_abandoned_lock: Uint8Array.from([169, 213, 107, 64, 229, 49, 43, 234]),
44
+ open_standby: Uint8Array.from([234, 184, 232, 135, 246, 191, 90, 250]),
45
+ draw_credit: Uint8Array.from([20, 84, 47, 211, 78, 117, 195, 210]),
46
+ repay_credit: Uint8Array.from([38, 113, 240, 182, 109, 179, 154, 245]),
47
+ seize_collateral: Uint8Array.from([40, 250, 7, 243, 168, 184, 116, 154]),
48
+ migrate_v4_to_v5: Uint8Array.from([226, 105, 140, 184, 101, 39, 235, 116])
49
+ });
50
+ var OTS_SESSION_REGISTER_V1_DOMAIN = (() => {
51
+ const buf = new Uint8Array(32);
52
+ buf.set(new TextEncoder().encode("OTS_SESSION_REGISTER_V1"), 0);
53
+ return buf;
54
+ })();
55
+ var OTS_SESSION_REGISTER_V2_DOMAIN = (() => {
56
+ const buf = new Uint8Array(32);
57
+ buf.set(new TextEncoder().encode("OTS_SESSION_REGISTER_V2"), 0);
58
+ return buf;
59
+ })();
60
+ var OTS_SESSION_REVOKE_V1_DOMAIN = (() => {
61
+ const buf = new Uint8Array(32);
62
+ buf.set(new TextEncoder().encode("OTS_SESSION_REVOKE_V1"), 0);
63
+ return buf;
64
+ })();
65
+
66
+ // src/instructions/setSwig.ts
67
+ import {
68
+ TransactionInstruction as TransactionInstruction2,
69
+ SYSVAR_INSTRUCTIONS_PUBKEY
70
+ } from "@solana/web3.js";
71
+
72
+ // src/instructions/setSwigAtomic.ts
73
+ import {
74
+ PublicKey as PublicKey5,
75
+ TransactionInstruction as TransactionInstruction3,
76
+ SystemProgram as SystemProgram2,
77
+ SYSVAR_INSTRUCTIONS_PUBKEY as SYSVAR_INSTRUCTIONS_PUBKEY2
78
+ } from "@solana/web3.js";
79
+
80
+ // src/instructions/swigBundle.ts
81
+ import { createHmac } from "crypto";
82
+ import {
83
+ getInstructionsFromContext,
84
+ findSwigPda,
85
+ fetchNullableSwig
86
+ } from "@swig-wallet/kit";
87
+ import {
88
+ Actions,
89
+ createProgramExecAuthorityInfo,
90
+ createEd25519AuthorityInfo,
91
+ createEd25519SessionAuthorityInfo,
92
+ getCreateSwigWithMultipleAuthoritiesInstructionContextBuilder
93
+ } from "@swig-wallet/lib";
94
+ import { address, createSolanaRpc } from "@solana/kit";
95
+ import * as bs58Module from "bs58";
96
+ import { PublicKey as PublicKey4 } from "@solana/web3.js";
97
+ var DEFAULT_SESSION_TTL_SECONDS = BigInt(30 * 24 * 60 * 60);
98
+ var DEFAULT_SPEND_LIMIT_ATOMIC = BigInt(1e9);
99
+ var SWIG_PROGRAM_EXEC_PREFIX = new Uint8Array([
100
+ 178,
101
+ 87,
102
+ 206,
103
+ 68,
104
+ 201,
105
+ 186,
106
+ 164,
107
+ 232
108
+ ]);
109
+ var SWIG_PROGRAM_EXEC_PREFIX_SETTLE_TAB = new Uint8Array([
110
+ 173,
111
+ 22,
112
+ 98,
113
+ 31,
114
+ 110,
115
+ 129,
116
+ 59,
117
+ 161
118
+ ]);
119
+
120
+ // src/instructions/setSwigAtomic.ts
121
+ var SET_SWIG_ATOMIC_DISCRIMINATOR = new Uint8Array([
122
+ 119,
123
+ 111,
124
+ 247,
125
+ 215,
126
+ 190,
127
+ 3,
128
+ 170,
129
+ 23
130
+ ]);
131
+
132
+ // src/instructions/registerSession.ts
133
+ import { TransactionInstruction as TransactionInstruction5 } from "@solana/web3.js";
134
+
135
+ // src/instructions/withdraw.ts
136
+ import {
137
+ PublicKey as PublicKey6,
138
+ TransactionInstruction as TransactionInstruction4,
139
+ SYSVAR_INSTRUCTIONS_PUBKEY as SYSVAR_INSTRUCTIONS_PUBKEY3
140
+ } from "@solana/web3.js";
141
+ function deriveSwigWalletAddress(swigAddress) {
142
+ const [pda] = PublicKey6.findProgramAddressSync(
143
+ [Buffer.from("swig-wallet-address"), swigAddress.toBuffer()],
144
+ SWIG_PROGRAM_ID
145
+ );
146
+ return pda;
147
+ }
148
+
149
+ // src/instructions/revokeSession.ts
150
+ import { TransactionInstruction as TransactionInstruction6 } from "@solana/web3.js";
151
+
152
+ // src/instructions/settleVoucher.ts
153
+ import { TransactionInstruction as TransactionInstruction7 } from "@solana/web3.js";
154
+ function encodeU64(value) {
155
+ const out = Buffer.alloc(8);
156
+ out.writeBigUInt64LE(value, 0);
157
+ return out;
158
+ }
159
+ function encodeBool(value) {
160
+ return Buffer.from([value ? 1 : 0]);
161
+ }
162
+ function buildSettleVoucherInstruction(p) {
163
+ const argsBuf = Buffer.concat([encodeU64(p.amount), encodeBool(p.increment)]);
164
+ const data = Buffer.concat([Buffer.from(DISCRIMINATORS.settle_voucher), argsBuf]);
165
+ return new TransactionInstruction7({
166
+ programId: DEXTER_VAULT_PROGRAM_ID,
167
+ keys: [
168
+ { pubkey: p.vaultPda, isSigner: false, isWritable: true },
169
+ { pubkey: p.dexterAuthority, isSigner: true, isWritable: false }
170
+ ],
171
+ data
172
+ });
173
+ }
174
+
175
+ // src/instructions/settleTabVoucher.ts
176
+ import {
177
+ TransactionInstruction as TransactionInstruction8,
178
+ SYSVAR_INSTRUCTIONS_PUBKEY as SYSVAR_INSTRUCTIONS_PUBKEY4
179
+ } from "@solana/web3.js";
180
+ function encodeFixedBytes(buf, len) {
181
+ if (buf.length !== len) {
182
+ throw new Error(`expected ${len} bytes, got ${buf.length}`);
183
+ }
184
+ return Buffer.from(buf);
185
+ }
186
+ function encodeU642(value) {
187
+ const out = Buffer.alloc(8);
188
+ out.writeBigUInt64LE(value, 0);
189
+ return out;
190
+ }
191
+ function encodeU32(value) {
192
+ const out = Buffer.alloc(4);
193
+ out.writeUInt32LE(value >>> 0, 0);
194
+ return out;
195
+ }
196
+ function buildSettleTabVoucherInstruction(p) {
197
+ if (p.channelId.length !== 32) {
198
+ throw new Error(`channelId must be 32 bytes, got ${p.channelId.length}`);
199
+ }
200
+ const argsBuf = Buffer.concat([
201
+ encodeFixedBytes(p.channelId, 32),
202
+ encodeU642(p.cumulativeAmount),
203
+ encodeU32(p.sequenceNumber)
204
+ ]);
205
+ const data = Buffer.concat([Buffer.from(DISCRIMINATORS.settle_tab_voucher), argsBuf]);
206
+ const swigWalletAddress = deriveSwigWalletAddress(p.swigAddress);
207
+ return new TransactionInstruction8({
208
+ programId: DEXTER_VAULT_PROGRAM_ID,
209
+ keys: [
210
+ { pubkey: p.swigAddress, isSigner: false, isWritable: false },
211
+ { pubkey: swigWalletAddress, isSigner: false, isWritable: false },
212
+ { pubkey: p.vaultPda, isSigner: false, isWritable: true },
213
+ { pubkey: p.dexterAuthority, isSigner: true, isWritable: false },
214
+ { pubkey: SYSVAR_INSTRUCTIONS_PUBKEY4, isSigner: false, isWritable: false }
215
+ ],
216
+ data
217
+ });
218
+ }
219
+
220
+ // src/instructions/rotate.ts
221
+ import {
222
+ TransactionInstruction as TransactionInstruction9,
223
+ SYSVAR_INSTRUCTIONS_PUBKEY as SYSVAR_INSTRUCTIONS_PUBKEY5
224
+ } from "@solana/web3.js";
225
+
226
+ // src/instructions/provePasskey.ts
227
+ import {
228
+ TransactionInstruction as TransactionInstruction10,
229
+ SYSVAR_INSTRUCTIONS_PUBKEY as SYSVAR_INSTRUCTIONS_PUBKEY6
230
+ } from "@solana/web3.js";
231
+
232
+ // src/instructions/lockedClaim.ts
233
+ import { PublicKey as PublicKey13, SystemProgram as SystemProgram3, TransactionInstruction as TransactionInstruction11 } from "@solana/web3.js";
234
+
235
+ // src/instructions/credit.ts
236
+ import { SystemProgram as SystemProgram4, TransactionInstruction as TransactionInstruction12 } from "@solana/web3.js";
237
+ function encodeU643(value) {
238
+ const out = Buffer.alloc(8);
239
+ out.writeBigUInt64LE(value, 0);
240
+ return out;
241
+ }
242
+ function encodeI64(value) {
243
+ const out = Buffer.alloc(8);
244
+ out.writeBigInt64LE(value, 0);
245
+ return out;
246
+ }
247
+ function buildDrawCreditInstruction(p) {
248
+ const data = Buffer.concat([
249
+ Buffer.from(DISCRIMINATORS.draw_credit),
250
+ encodeU643(p.amount),
251
+ encodeI64(p.recoveryWindowSeconds)
252
+ ]);
253
+ const financierSwigWalletAddress = deriveSwigWalletAddress(p.financierSwig);
254
+ return new TransactionInstruction12({
255
+ programId: DEXTER_VAULT_PROGRAM_ID,
256
+ keys: [
257
+ { pubkey: p.financierSwig, isSigner: false, isWritable: false },
258
+ { pubkey: financierSwigWalletAddress, isSigner: false, isWritable: false },
259
+ { pubkey: p.vaultPda, isSigner: false, isWritable: true },
260
+ { pubkey: p.dexterAuthority, isSigner: true, isWritable: false },
261
+ { pubkey: INSTRUCTIONS_SYSVAR_ID, isSigner: false, isWritable: false }
262
+ ],
263
+ data
264
+ });
265
+ }
266
+ function buildRepayCreditInstruction(p) {
267
+ const data = Buffer.concat([
268
+ Buffer.from(DISCRIMINATORS.repay_credit),
269
+ encodeU643(p.amount)
270
+ ]);
271
+ const swigWalletAddress = deriveSwigWalletAddress(p.swigAddress);
272
+ return new TransactionInstruction12({
273
+ programId: DEXTER_VAULT_PROGRAM_ID,
274
+ keys: [
275
+ { pubkey: p.swigAddress, isSigner: false, isWritable: false },
276
+ { pubkey: swigWalletAddress, isSigner: false, isWritable: false },
277
+ { pubkey: p.vaultPda, isSigner: false, isWritable: true },
278
+ { pubkey: p.dexterAuthority, isSigner: true, isWritable: false },
279
+ { pubkey: INSTRUCTIONS_SYSVAR_ID, isSigner: false, isWritable: false }
280
+ ],
281
+ data
282
+ });
283
+ }
284
+ function buildSeizeCollateralInstruction(p) {
285
+ const data = Buffer.from(DISCRIMINATORS.seize_collateral);
286
+ const swigWalletAddress = deriveSwigWalletAddress(p.swigAddress);
287
+ return new TransactionInstruction12({
288
+ programId: DEXTER_VAULT_PROGRAM_ID,
289
+ keys: [
290
+ { pubkey: p.swigAddress, isSigner: false, isWritable: false },
291
+ { pubkey: swigWalletAddress, isSigner: false, isWritable: false },
292
+ { pubkey: p.vaultPda, isSigner: false, isWritable: true },
293
+ { pubkey: p.dexterAuthority, isSigner: true, isWritable: false },
294
+ { pubkey: INSTRUCTIONS_SYSVAR_ID, isSigner: false, isWritable: false }
295
+ ],
296
+ data
297
+ });
298
+ }
299
+
300
+ // src/tab/openTab.ts
301
+ async function openTab(p) {
302
+ const ix = buildSettleVoucherInstruction({
303
+ vaultPda: p.vaultPda,
304
+ amount: p.amount,
305
+ increment: true,
306
+ dexterAuthority: p.dexterAuthority
307
+ });
308
+ return [ix];
309
+ }
310
+
311
+ // src/messages/voucher.ts
312
+ function voucherPayloadMessage(p) {
313
+ if (p.channelId.length !== 32) {
314
+ throw new Error(`channelId must be 32 bytes, got ${p.channelId.length}`);
315
+ }
316
+ const buf = new Uint8Array(44);
317
+ const view = new DataView(buf.buffer);
318
+ buf.set(p.channelId, 0);
319
+ view.setBigUint64(32, p.cumulativeAmount, true);
320
+ view.setUint32(40, p.sequenceNumber >>> 0, true);
321
+ return buf;
322
+ }
323
+
324
+ // src/messages/operations.ts
325
+ import { PublicKey as PublicKey15 } from "@solana/web3.js";
326
+
327
+ // src/precompile/secp256r1.ts
328
+ import { TransactionInstruction as TransactionInstruction13 } from "@solana/web3.js";
329
+
330
+ // src/precompile/ed25519.ts
331
+ import { TransactionInstruction as TransactionInstruction14 } from "@solana/web3.js";
332
+ function buildEd25519VerifyInstruction(pubkey, signature, message) {
333
+ if (pubkey.length !== 32) throw new Error("pubkey must be 32 bytes");
334
+ if (signature.length !== 64) throw new Error("signature must be 64 bytes");
335
+ const NUM_SIG = 1;
336
+ const PADDING = 0;
337
+ const HEADER_LEN = 2;
338
+ const OFFSETS_LEN = 14;
339
+ const DATA_START = HEADER_LEN + OFFSETS_LEN;
340
+ const data = Buffer.alloc(DATA_START + pubkey.length + signature.length + message.length);
341
+ let off = 0;
342
+ data.writeUInt8(NUM_SIG, off);
343
+ off += 1;
344
+ data.writeUInt8(PADDING, off);
345
+ off += 1;
346
+ const pubkeyOffset = DATA_START;
347
+ const signatureOffset = pubkeyOffset + pubkey.length;
348
+ const messageOffset = signatureOffset + signature.length;
349
+ data.writeUInt16LE(signatureOffset, off);
350
+ off += 2;
351
+ data.writeUInt16LE(65535, off);
352
+ off += 2;
353
+ data.writeUInt16LE(pubkeyOffset, off);
354
+ off += 2;
355
+ data.writeUInt16LE(65535, off);
356
+ off += 2;
357
+ data.writeUInt16LE(messageOffset, off);
358
+ off += 2;
359
+ data.writeUInt16LE(message.length, off);
360
+ off += 2;
361
+ data.writeUInt16LE(65535, off);
362
+ off += 2;
363
+ Buffer.from(pubkey).copy(data, pubkeyOffset);
364
+ Buffer.from(signature).copy(data, signatureOffset);
365
+ Buffer.from(message).copy(data, messageOffset);
366
+ return new TransactionInstruction14({
367
+ programId: ED25519_PROGRAM_ID,
368
+ keys: [],
369
+ data
370
+ });
371
+ }
372
+
373
+ // src/reader/accountReader.ts
374
+ import { PublicKey as PublicKey16 } from "@solana/web3.js";
375
+ var VERSION_OFFSET = 8;
376
+ var SWIG_ADDRESS_OFFSET = 43;
377
+ var PENDING_VOUCHER_COUNT_OFFSET = 79;
378
+ var PENDING_WITHDRAWAL_TAG_OFFSET = 83;
379
+ var PENDING_WITHDRAWAL_BODY_LEN = 48;
380
+ var PENDING_WITHDRAWAL_BODY_START = PENDING_WITHDRAWAL_TAG_OFFSET + 1;
381
+ var IDENTITY_CLAIM_LEN = 32;
382
+ var PUBKEY_LEN = 32;
383
+ var ACTIVE_SESSION_BODY_LEN = 92;
384
+ var EMPTY_FULL = {
385
+ exists: false,
386
+ version: 0,
387
+ swigAddress: null,
388
+ dexterAuthority: null,
389
+ pendingVoucherCount: 0,
390
+ activeSession: null
391
+ };
392
+ async function readVaultFull(conn, vaultPda) {
393
+ const account = await conn.getAccountInfo(vaultPda, "confirmed");
394
+ if (!account) return EMPTY_FULL;
395
+ const data = account.data;
396
+ if (data.length < SWIG_ADDRESS_OFFSET + PUBKEY_LEN) return EMPTY_FULL;
397
+ const version = data.readUInt8(VERSION_OFFSET);
398
+ const swigAddress = new PublicKey16(
399
+ data.subarray(SWIG_ADDRESS_OFFSET, SWIG_ADDRESS_OFFSET + PUBKEY_LEN)
400
+ ).toBase58();
401
+ const pendingVoucherCount = data.readUInt32LE(PENDING_VOUCHER_COUNT_OFFSET);
402
+ const withdrawalTag = data[PENDING_WITHDRAWAL_TAG_OFFSET];
403
+ const afterWithdrawal = PENDING_WITHDRAWAL_BODY_START + (withdrawalTag === 1 ? PENDING_WITHDRAWAL_BODY_LEN : 0);
404
+ const dexterAuthorityOffset = afterWithdrawal + IDENTITY_CLAIM_LEN;
405
+ if (data.length < dexterAuthorityOffset + PUBKEY_LEN) {
406
+ return { ...EMPTY_FULL, exists: true, version, swigAddress, pendingVoucherCount };
407
+ }
408
+ const dexterAuthority = new PublicKey16(
409
+ data.subarray(dexterAuthorityOffset, dexterAuthorityOffset + PUBKEY_LEN)
410
+ ).toBase58();
411
+ const activeSessionTagOffset = dexterAuthorityOffset + PUBKEY_LEN;
412
+ let activeSession = null;
413
+ if (data.length > activeSessionTagOffset && data[activeSessionTagOffset] === 1) {
414
+ const bodyStart = activeSessionTagOffset + 1;
415
+ if (data.length >= bodyStart + ACTIVE_SESSION_BODY_LEN) {
416
+ activeSession = {
417
+ sessionPubkey: new Uint8Array(data.subarray(bodyStart, bodyStart + 32)),
418
+ maxAmount: data.readBigUInt64LE(bodyStart + 32),
419
+ expiresAt: Number(data.readBigInt64LE(bodyStart + 40)),
420
+ allowedCounterparty: new PublicKey16(
421
+ data.subarray(bodyStart + 48, bodyStart + 80)
422
+ ).toBase58(),
423
+ nonce: data.readUInt32LE(bodyStart + 80),
424
+ spent: data.readBigUInt64LE(bodyStart + 84)
425
+ };
426
+ }
427
+ }
428
+ return {
429
+ exists: true,
430
+ version,
431
+ swigAddress,
432
+ dexterAuthority,
433
+ pendingVoucherCount,
434
+ activeSession
435
+ };
436
+ }
437
+
438
+ // src/tab/assembleSignV2.ts
439
+ import { PublicKey as PublicKey18 } from "@solana/web3.js";
440
+ import { fetchSwig, getSignInstructions, getSwigWalletAddress } from "@swig-wallet/kit";
441
+ import { address as kitAddress } from "@solana/kit";
442
+ import { getTransferCheckedInstruction } from "@solana-program/token";
443
+ import { getAssociatedTokenAddressSync } from "@solana/spl-token";
444
+
445
+ // src/kit/index.ts
446
+ import { PublicKey as PublicKey17, TransactionInstruction as TransactionInstruction15 } from "@solana/web3.js";
447
+ import { createSolanaRpc as createSolanaRpc2 } from "@solana/kit";
448
+ function kitInstructionsToWeb3(kitInstructions) {
449
+ return kitInstructions.map((ix) => {
450
+ const accounts = (ix.accounts ?? []).map((acc) => {
451
+ const role = acc.role;
452
+ const hasBooleanShape = typeof acc.signer === "boolean" || typeof acc.writable === "boolean";
453
+ let isSigner = false;
454
+ let isWritable = false;
455
+ if (hasBooleanShape) {
456
+ isSigner = Boolean(acc.signer);
457
+ isWritable = Boolean(acc.writable);
458
+ } else if (typeof role === "number") {
459
+ isSigner = role >= 2;
460
+ isWritable = role % 2 === 1;
461
+ } else if (typeof role === "string") {
462
+ const r = role.toLowerCase();
463
+ isSigner = r.endsWith("signer");
464
+ isWritable = r.startsWith("writable");
465
+ }
466
+ const addressSource = acc.address ?? acc.publicKey;
467
+ const pubkey = addressSource instanceof PublicKey17 ? addressSource : typeof addressSource === "string" ? new PublicKey17(addressSource) : new PublicKey17(String(addressSource));
468
+ return { pubkey, isSigner, isWritable };
469
+ });
470
+ return new TransactionInstruction15({
471
+ programId: new PublicKey17(ix.programAddress ?? ix.programId),
472
+ keys: accounts,
473
+ data: Buffer.from(ix.data ?? [])
474
+ });
475
+ });
476
+ }
477
+ function getRpc(connection) {
478
+ const endpoint = connection._rpcEndpoint ?? connection.rpcEndpoint;
479
+ if (!endpoint) throw new Error("kit: cannot extract RPC endpoint from connection");
480
+ return createSolanaRpc2(endpoint);
481
+ }
482
+
483
+ // src/tab/assembleSignV2.ts
484
+ var VAULT_PROGRAM_EXEC_ROLE_ID = 1;
485
+ var USDC_DECIMALS = 6;
486
+ var defaultAssembleSignV2 = async (a) => {
487
+ const rpc = getRpc(a.connection);
488
+ const swig = await fetchSwig(rpc, kitAddress(a.swigAddress.toBase58()));
489
+ if (!swig) throw new Error(`tab: swig not found on-chain: ${a.swigAddress.toBase58()}`);
490
+ const swigWalletKitAddr = await getSwigWalletAddress(swig);
491
+ const swigWalletPda = new PublicKey18(String(swigWalletKitAddr));
492
+ const usdcMint = new PublicKey18(USDC_MAINNET);
493
+ const sourceAta = getAssociatedTokenAddressSync(usdcMint, swigWalletPda, true);
494
+ const transferIxs = a.transfers.map(
495
+ (t) => getTransferCheckedInstruction({
496
+ source: kitAddress(sourceAta.toBase58()),
497
+ mint: kitAddress(usdcMint.toBase58()),
498
+ destination: kitAddress(t.destinationAta.toBase58()),
499
+ authority: swigWalletKitAddr,
500
+ amount: t.amount,
501
+ decimals: USDC_DECIMALS
502
+ })
503
+ );
504
+ const signIx = await getSignInstructions(
505
+ swig,
506
+ VAULT_PROGRAM_EXEC_ROLE_ID,
507
+ transferIxs,
508
+ false,
509
+ { payer: kitAddress(a.feePayer.toBase58()), preInstructions: [a.vaultIx] }
510
+ );
511
+ return kitInstructionsToWeb3(signIx);
512
+ };
513
+
514
+ // src/tab/settleTab.ts
515
+ var defaultReadPriorSpent = async (connection, vaultPda) => {
516
+ const vault = await readVaultFull(connection, vaultPda);
517
+ const session = vault.activeSession;
518
+ if (!session) throw new Error("settleTab: no active session on vault");
519
+ return session.spent;
520
+ };
521
+ async function settleTab(p) {
522
+ const readPrior = p.readPriorSpent ?? defaultReadPriorSpent;
523
+ const priorSpent = await readPrior(p.connection, p.vaultPda);
524
+ if (p.cumulativeAmount <= priorSpent) {
525
+ throw new Error(
526
+ `settleTab: non-monotonic cumulative \u2014 ${p.cumulativeAmount} <= prior spent ${priorSpent}`
527
+ );
528
+ }
529
+ const delta = p.cumulativeAmount - priorSpent;
530
+ const message = voucherPayloadMessage({
531
+ channelId: p.channelId,
532
+ cumulativeAmount: p.cumulativeAmount,
533
+ sequenceNumber: p.sequenceNumber
534
+ });
535
+ const signature = await p.sessionSigner.sign(message);
536
+ const precompileIx = buildEd25519VerifyInstruction(
537
+ p.sessionSigner.publicKey,
538
+ signature,
539
+ message
540
+ );
541
+ const vaultIx = buildSettleTabVoucherInstruction({
542
+ vaultPda: p.vaultPda,
543
+ swigAddress: p.swigAddress,
544
+ dexterAuthority: p.dexterAuthority,
545
+ channelId: p.channelId,
546
+ cumulativeAmount: p.cumulativeAmount,
547
+ sequenceNumber: p.sequenceNumber
548
+ });
549
+ const assemble = p.assembleSignV2 ?? defaultAssembleSignV2;
550
+ const signV2Ixs = await assemble({
551
+ connection: p.connection,
552
+ swigAddress: p.swigAddress,
553
+ feePayer: p.feePayer,
554
+ vaultIx,
555
+ transfers: [{ destinationAta: p.sellerAta, amount: delta }]
556
+ });
557
+ return [precompileIx, vaultIx, ...signV2Ixs];
558
+ }
559
+
560
+ // src/tab/readTabMeter.ts
561
+ async function readTabMeter(connection, vaultPda, read = readVaultFull) {
562
+ const vault = await read(connection, vaultPda);
563
+ const session = vault.activeSession;
564
+ if (!session) throw new Error("readTabMeter: no active session on vault");
565
+ const { spent, maxAmount } = session;
566
+ const raw = maxAmount - spent;
567
+ const remaining = raw > 0n ? raw : 0n;
568
+ return { spent, maxAmount, remaining };
569
+ }
570
+
571
+ // src/tab/credit.ts
572
+ async function drawCredit(p) {
573
+ const vaultIx = buildDrawCreditInstruction({
574
+ financierSwig: p.financierSwig,
575
+ vaultPda: p.userVaultPda,
576
+ dexterAuthority: p.dexterAuthority,
577
+ amount: p.amount,
578
+ recoveryWindowSeconds: p.recoveryWindowSeconds
579
+ });
580
+ const assemble = p.assembleSignV2 ?? defaultAssembleSignV2;
581
+ const signV2Ixs = await assemble({
582
+ connection: p.connection,
583
+ swigAddress: p.financierSwig,
584
+ feePayer: p.feePayer,
585
+ vaultIx,
586
+ transfers: [{ destinationAta: p.sellerAta, amount: p.amount }]
587
+ });
588
+ return [vaultIx, ...signV2Ixs];
589
+ }
590
+ async function repayCredit(p) {
591
+ const vaultIx = buildRepayCreditInstruction({
592
+ swigAddress: p.userSwig,
593
+ vaultPda: p.userVaultPda,
594
+ dexterAuthority: p.dexterAuthority,
595
+ amount: p.amount
596
+ });
597
+ const assemble = p.assembleSignV2 ?? defaultAssembleSignV2;
598
+ const signV2Ixs = await assemble({
599
+ connection: p.connection,
600
+ swigAddress: p.userSwig,
601
+ feePayer: p.feePayer,
602
+ vaultIx,
603
+ transfers: [{ destinationAta: p.financierAta, amount: p.amount }]
604
+ });
605
+ return [vaultIx, ...signV2Ixs];
606
+ }
607
+ async function seizeCollateral(p) {
608
+ const vaultIx = buildSeizeCollateralInstruction({
609
+ swigAddress: p.userSwig,
610
+ vaultPda: p.userVaultPda,
611
+ dexterAuthority: p.dexterAuthority
612
+ });
613
+ const assemble = p.assembleSignV2 ?? defaultAssembleSignV2;
614
+ const signV2Ixs = await assemble({
615
+ connection: p.connection,
616
+ swigAddress: p.userSwig,
617
+ feePayer: p.feePayer,
618
+ vaultIx,
619
+ transfers: [{ destinationAta: p.financierAta, amount: p.seizeAmount }]
620
+ });
621
+ return [vaultIx, ...signV2Ixs];
622
+ }
623
+ export {
624
+ defaultAssembleSignV2,
625
+ drawCredit,
626
+ openTab,
627
+ readTabMeter,
628
+ repayCredit,
629
+ seizeCollateral,
630
+ settleTab
631
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dexterai/vault",
3
- "version": "0.4.2",
3
+ "version": "0.6.0",
4
4
  "description": "Canonical off-chain mirror of the dexter-vault Solana Anchor program — Solana instruction builders, byte-precise message encoders, account decoders, secp256r1/Ed25519 precompile helpers, counterfactual Swig derivation, and signer interfaces. The single source of truth for any TypeScript code that produces bytes the on-chain program will verify.",
5
5
  "author": "Dexter",
6
6
  "license": "MIT",
@@ -26,11 +26,21 @@
26
26
  "import": "./dist/counterfactual.js",
27
27
  "require": "./dist/counterfactual.cjs"
28
28
  },
29
+ "./factoring": {
30
+ "types": "./dist/factoring/index.d.ts",
31
+ "import": "./dist/factoring/index.js",
32
+ "require": "./dist/factoring/index.cjs"
33
+ },
29
34
  "./instructions": {
30
35
  "types": "./dist/instructions/index.d.ts",
31
36
  "import": "./dist/instructions/index.js",
32
37
  "require": "./dist/instructions/index.cjs"
33
38
  },
39
+ "./kit": {
40
+ "types": "./dist/kit/index.d.ts",
41
+ "import": "./dist/kit/index.js",
42
+ "require": "./dist/kit/index.cjs"
43
+ },
34
44
  "./messages": {
35
45
  "types": "./dist/messages/index.d.ts",
36
46
  "import": "./dist/messages/index.js",
@@ -61,6 +71,16 @@
61
71
  "import": "./dist/signers/browser/index.js",
62
72
  "require": "./dist/signers/browser/index.cjs"
63
73
  },
74
+ "./tab": {
75
+ "types": "./dist/tab/index.d.ts",
76
+ "import": "./dist/tab/index.js",
77
+ "require": "./dist/tab/index.cjs"
78
+ },
79
+ "./connect": {
80
+ "types": "./dist/connect/index.d.ts",
81
+ "import": "./dist/connect/index.js",
82
+ "require": "./dist/connect/index.cjs"
83
+ },
64
84
  "./idl/dexter_vault.json": "./dist/idl/dexter_vault.json"
65
85
  },
66
86
  "files": [
@@ -83,6 +103,8 @@
83
103
  "dependencies": {
84
104
  "@noble/curves": "^1.9.7",
85
105
  "@noble/hashes": "^1.8.0",
106
+ "@solana-program/token": "^0.5.1",
107
+ "@solana/kit": "^2.3.0",
86
108
  "@solana/spl-token": "^0.4.9",
87
109
  "@solana/web3.js": "^1.98.0",
88
110
  "@swig-wallet/kit": "^1.9.0",