@tbookdev/vault-sdk 0.1.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,894 @@
1
+ import { Connection, PublicKey, Transaction, Commitment } from '@solana/web3.js';
2
+ import { Program } from '@coral-xyz/anchor';
3
+
4
+ /**
5
+ * Transaction history for vault user accounts.
6
+ *
7
+ * Fetches and classifies on-chain vault interactions (deposits, redeems,
8
+ * claims, cancel-deposits) by reading Solana transaction signatures and
9
+ * matching Anchor instruction discriminators.
10
+ *
11
+ * @module history
12
+ */
13
+
14
+ interface VaultTransaction {
15
+ /** Transaction signature (base58). */
16
+ signature: string;
17
+ /** Classified instruction type. */
18
+ type: "deposit" | "redeem" | "claim" | "cancel_deposit" | "unknown";
19
+ /** Unix timestamp (seconds). 0 if unavailable. */
20
+ timestamp: number;
21
+ /** Slot number of the transaction. */
22
+ slot: number;
23
+ /** Whether the transaction succeeded. */
24
+ success: boolean;
25
+ /** Human-readable description. */
26
+ description: string;
27
+ }
28
+ interface TransactionHistoryOptions {
29
+ /** Maximum number of transactions to return (default: 20). */
30
+ limit?: number;
31
+ /** Pagination cursor: signature to start searching before. */
32
+ before?: string;
33
+ }
34
+ /**
35
+ * Fetch vault transaction history for a user.
36
+ *
37
+ * Uses `getSignaturesForAddress` on the user's UserAccount PDA to find
38
+ * relevant transactions, then batch-fetches parsed transaction data
39
+ * to classify each one by its Anchor instruction discriminator.
40
+ *
41
+ * @param connection - Solana RPC connection
42
+ * @param userPda - The user's UserAccount PDA address
43
+ * @param programId - The vault program ID (used to identify vault instructions)
44
+ * @param options - Pagination options
45
+ * @returns Array of classified vault transactions, newest first
46
+ */
47
+ declare function fetchTransactionHistory(connection: Connection, userPda: PublicKey, programId: PublicKey, options?: TransactionHistoryOptions): Promise<VaultTransaction[]>;
48
+
49
+ /**
50
+ * Core type definitions for the TBook Vault Gateway SDK.
51
+ *
52
+ * @module types
53
+ */
54
+
55
+ /** Supported Solana networks. */
56
+ type SolanaNetwork = "devnet" | "mainnet-beta";
57
+ /** Options for initializing a {@link TBookVault} client instance. */
58
+ interface TBookVaultOptions {
59
+ /** Solana network to connect to. */
60
+ network: SolanaNetwork;
61
+ /**
62
+ * Custom Solana RPC endpoint URL.
63
+ * Falls back to a sensible public default for the chosen network.
64
+ */
65
+ rpcUrl?: string;
66
+ /**
67
+ * TBook API key for accessing the hosted API layer.
68
+ * When provided, queries are routed through the cached TBook API
69
+ * (higher rate limits, lower latency). Without a key the SDK reads
70
+ * directly from the Solana RPC.
71
+ */
72
+ apiKey?: string;
73
+ /**
74
+ * Default timeout for RPC calls in milliseconds.
75
+ * Applies to all on-chain reads and transaction building.
76
+ * Default: 30_000 (30 seconds).
77
+ */
78
+ timeoutMs?: number;
79
+ }
80
+ /** Metadata for a single vault available in the TBook ecosystem. */
81
+ interface VaultDescriptor {
82
+ /** Unique identifier for this vault, e.g. `"rcUSDP"`. */
83
+ id: string;
84
+ /** Human-readable name. */
85
+ name: string;
86
+ /** Short description of the vault strategy. */
87
+ description: string;
88
+ /** Solana program ID that manages this vault. */
89
+ programId: string;
90
+ /** Network this vault is deployed on. */
91
+ network: SolanaNetwork;
92
+ /** USDC mint address accepted by the vault. */
93
+ usdcMint: string;
94
+ /** Share token details. */
95
+ shareToken: {
96
+ symbol: string;
97
+ decimals: number;
98
+ };
99
+ /** Current vault status. */
100
+ status: "active" | "paused" | "deprecated";
101
+ }
102
+ /** Epoch lifecycle status. */
103
+ type EpochStatus = "Open" | "Frozen" | "Bridging" | "Settled" | "RolledBack";
104
+ /** Numeric → EpochStatus mapping for manual deserialization. */
105
+ declare const STATUS_MAP: Record<number, EpochStatus>;
106
+ /** Global vault state from VaultMirror PDA. All amounts are human-readable. */
107
+ interface VaultInfo {
108
+ /** Authority (governance) public key. */
109
+ admin: string;
110
+ /** Curator multisig public key. */
111
+ curator: string;
112
+ /** Operator multisig public key. */
113
+ operator: string;
114
+ /** Total shares outstanding across all users. */
115
+ totalShares: number;
116
+ /** Current deposit epoch number. */
117
+ currentDepositEpoch: number;
118
+ /** Current redeem epoch number. */
119
+ currentRedeemEpoch: number;
120
+ /** Maximum USDC allowed per deposit epoch. */
121
+ maxEpochDeposit: number;
122
+ /** Minimum single deposit amount in USDC. */
123
+ minDeposit: number;
124
+ /** Whether the vault is paused (claim always works even when paused). */
125
+ paused: boolean;
126
+ /** USDC mint public key. */
127
+ usdcMint: PublicKey;
128
+ /** Current USDC balance held in the vault token account. */
129
+ vaultUsdcBalance: number;
130
+ /** Estimated TVL in USDC. */
131
+ tvlEstimate: number;
132
+ /** Cancellation fee in basis points (default 10 = 0.1%). */
133
+ cancelFeeBps: number;
134
+ }
135
+ /** Current deposit epoch on-chain state. */
136
+ interface DepositEpochInfo {
137
+ epoch: number;
138
+ status: EpochStatus;
139
+ /** Total USDC deposited in this epoch. */
140
+ totalDepositUsdc: number;
141
+ /** Number of unique users who deposited in this epoch. */
142
+ depositUserCount: number;
143
+ /** Shares minted for this epoch after settlement. */
144
+ settledSharesMinted: number;
145
+ }
146
+ /** Current redeem epoch on-chain state. */
147
+ interface RedeemEpochInfo {
148
+ epoch: number;
149
+ status: EpochStatus;
150
+ /** Total shares queued for redemption. */
151
+ totalRedeemShares: number;
152
+ /** Number of unique users who requested redemption. */
153
+ redeemUserCount: number;
154
+ /** USDC distributed for this epoch after settlement. */
155
+ settledUsdcForRedeems: number;
156
+ }
157
+ /**
158
+ * Per-user on-chain account state.
159
+ * All amounts are human-readable (divided by 10^decimals).
160
+ */
161
+ interface UserAccount {
162
+ /** Settled share balance. */
163
+ shares: number;
164
+ /** USDC pending in an open deposit epoch. */
165
+ pendingDepositUsdc: number;
166
+ /** Which deposit epoch the pending deposit belongs to. */
167
+ pendingDepositEpoch: number;
168
+ /** Shares pending in an open redeem epoch. */
169
+ pendingRedeemShares: number;
170
+ /** Which redeem epoch the pending redeem belongs to. */
171
+ pendingRedeemEpoch: number;
172
+ /** USDC available to claim. */
173
+ claimableUsdc: number;
174
+ /**
175
+ * Effective share balance including not-yet-lazy-settled deposits.
176
+ * This is what the user "really" owns.
177
+ */
178
+ effectiveShares: number;
179
+ /**
180
+ * Effective claimable USDC including not-yet-lazy-settled redeems.
181
+ */
182
+ effectiveClaimableUsdc: number;
183
+ /**
184
+ * Estimated portfolio value in USDC (effectiveShares * sharePrice).
185
+ * Only present when share price is available.
186
+ */
187
+ portfolioValueUsdc?: number;
188
+ }
189
+ /** Share price data from the NAV oracle. */
190
+ interface SharePriceData {
191
+ /** Human-readable price string, e.g. "1.000214". */
192
+ price: string;
193
+ /** Price as a number for calculations. */
194
+ priceNum: number;
195
+ /** Annualized yield percentage, e.g. "8.30". */
196
+ apy: string;
197
+ /** Date of the NAV snapshot (ISO date string). */
198
+ date: string;
199
+ /** ISO timestamp when the data was last fetched. */
200
+ fetchedAt: string;
201
+ /** Where this price data came from. */
202
+ source?: "api" | "cache" | "on-chain";
203
+ /** Whether the data is stale (older than the freshness window). */
204
+ stale?: boolean;
205
+ }
206
+ /**
207
+ * Result of a transaction-building operation.
208
+ * Contains both the raw Transaction object and a pre-serialized base58
209
+ * string for direct use with Wallet-as-a-Service APIs.
210
+ */
211
+ interface TransactionResult {
212
+ /** Unsigned Solana Transaction object. */
213
+ transaction: Transaction;
214
+ /**
215
+ * Base58-encoded serialized transaction.
216
+ * Can be sent directly to WaaS providers (Crossmint, Privy, etc.)
217
+ * or deserialized back into a Transaction for wallet adapters.
218
+ */
219
+ serialized: string;
220
+ /** Human-readable description of the transaction. */
221
+ message: string;
222
+ /** Blockhash used in the transaction (needed for confirmation). */
223
+ blockhash: string;
224
+ /** Last valid block height for the blockhash (needed for expiry detection). */
225
+ lastValidBlockHeight: number;
226
+ }
227
+ /** Parameters for building a deposit transaction. */
228
+ interface DepositParams {
229
+ /** User's Solana public key. */
230
+ user: PublicKey;
231
+ /** Amount of USDC to deposit (human-readable, e.g. 100 for $100). */
232
+ amountUsdc: number;
233
+ }
234
+ /** Parameters for building a redeem transaction. */
235
+ interface RedeemParams {
236
+ /** User's Solana public key. */
237
+ user: PublicKey;
238
+ /** Number of vault shares to redeem (human-readable). */
239
+ shares: number;
240
+ }
241
+ /** Parameters for building a claim or cancel transaction. */
242
+ interface UserTxParams {
243
+ /** User's Solana public key. */
244
+ user: PublicKey;
245
+ }
246
+ /** Full vault information including current epochs. */
247
+ interface VaultInfoResult {
248
+ vault: VaultInfo | null;
249
+ depositEpoch: DepositEpochInfo | null;
250
+ redeemEpoch: RedeemEpochInfo | null;
251
+ }
252
+
253
+ /**
254
+ * Main SDK client for TBook Vault Gateway.
255
+ *
256
+ * ```typescript
257
+ * import { TBookVault } from "@tbookdev/vault-sdk";
258
+ *
259
+ * const vault = new TBookVault({ network: "mainnet-beta" });
260
+ *
261
+ * // Read vault state (no wallet needed)
262
+ * const info = await vault.getVaultInfo();
263
+ * const price = await vault.getSharePrice();
264
+ *
265
+ * // Build unsigned transactions
266
+ * const { transaction, serialized } = await vault.buildDeposit({
267
+ * user: userPublicKey,
268
+ * amountUsdc: 100,
269
+ * });
270
+ * // Send `serialized` to WaaS or `transaction` to wallet adapter
271
+ * ```
272
+ *
273
+ * @module client
274
+ */
275
+
276
+ /**
277
+ * TBook Vault SDK client.
278
+ *
279
+ * Provides a unified interface for reading on-chain state and building
280
+ * unsigned transactions. Framework-agnostic — works in browsers and Node.js.
281
+ *
282
+ * The client is lightweight and stateless. Each method makes independent
283
+ * RPC calls, so instances can be shared across components safely.
284
+ */
285
+ declare class TBookVault {
286
+ /** Solana RPC connection. */
287
+ readonly connection: Connection;
288
+ /** Active network. */
289
+ readonly network: TBookVaultOptions["network"];
290
+ /** Default timeout for RPC calls in milliseconds. */
291
+ readonly timeoutMs: number;
292
+ private readonly apiKey?;
293
+ /** Cache of Anchor programs, keyed by vault ID. */
294
+ private readonly programs;
295
+ /** Timestamps of when each cached program was created. */
296
+ private readonly programCreatedAt;
297
+ /** Maximum age for cached programs (5 minutes). */
298
+ private static readonly PROGRAM_CACHE_TTL_MS;
299
+ constructor(options: TBookVaultOptions);
300
+ /**
301
+ * List all available vaults on the current network.
302
+ *
303
+ * Currently returns built-in vaults only. In the future, this will
304
+ * also query the TBook API for dynamically registered vaults.
305
+ */
306
+ listVaults(): Promise<VaultDescriptor[]>;
307
+ /**
308
+ * Fetch global vault state and current epoch info.
309
+ *
310
+ * @param vaultId - Vault identifier (default: "rcUSDP")
311
+ */
312
+ getVaultInfo(vaultId?: string): Promise<VaultInfoResult>;
313
+ /**
314
+ * Fetch a user's vault account with effective balances.
315
+ *
316
+ * Returns `null` if the user has never interacted with the vault.
317
+ *
318
+ * @param user - User's Solana public key (string or PublicKey)
319
+ * @param vaultId - Vault identifier (default: "rcUSDP")
320
+ */
321
+ getUserAccount(user: string | PublicKey, vaultId?: string): Promise<UserAccount | null>;
322
+ /**
323
+ * Fetch current share price from the NAV oracle.
324
+ *
325
+ * Uses a 3-layer fallback: fresh cache -> API fetch -> stale cache.
326
+ * The API endpoint (NAV oracle) is the authoritative price source.
327
+ *
328
+ * @param vaultId - Vault identifier. Currently all registered vaults share
329
+ * one NAV source; per-vault price URLs land with the multi-asset registry
330
+ * (VaultConfig.sharePriceUrl) in 0.2.0.
331
+ */
332
+ getSharePrice(vaultId?: string): Promise<SharePriceData>;
333
+ /**
334
+ * Build an unsigned deposit transaction.
335
+ *
336
+ * @param params - Deposit parameters (user + amount)
337
+ * @param vaultId - Vault identifier (default: "rcUSDP")
338
+ * @returns Unsigned transaction + base58 serialization + description
339
+ */
340
+ buildDeposit(params: DepositParams, vaultId?: string): Promise<TransactionResult>;
341
+ /**
342
+ * Build an unsigned redeem transaction.
343
+ *
344
+ * @param params - Redeem parameters (user + shares)
345
+ * @param vaultId - Vault identifier (default: "rcUSDP")
346
+ */
347
+ buildRedeem(params: RedeemParams, vaultId?: string): Promise<TransactionResult>;
348
+ /**
349
+ * Build an unsigned claim transaction.
350
+ * Claim always works even when the vault is paused.
351
+ *
352
+ * @param params - User parameters
353
+ * @param vaultId - Vault identifier (default: "rcUSDP")
354
+ */
355
+ buildClaim(params: UserTxParams, vaultId?: string): Promise<TransactionResult>;
356
+ /**
357
+ * Build an unsigned cancel-deposit transaction.
358
+ * Returns pending USDC minus 0.1% fee.
359
+ *
360
+ * @param params - User parameters
361
+ * @param vaultId - Vault identifier (default: "rcUSDP")
362
+ */
363
+ buildCancelDeposit(params: UserTxParams, vaultId?: string): Promise<TransactionResult>;
364
+ /**
365
+ * Fetch vault transaction history for a user.
366
+ *
367
+ * Returns classified transactions (deposit, redeem, claim, cancel_deposit)
368
+ * by querying the user's PDA account for signatures and parsing instruction data.
369
+ *
370
+ * @param userAddress - User's Solana wallet address (string or PublicKey)
371
+ * @param options - Pagination options (limit, before cursor)
372
+ * @param vaultId - Vault identifier (default: "rcUSDP")
373
+ * @returns Array of classified vault transactions, newest first
374
+ */
375
+ getTransactionHistory(userAddress: string | PublicKey, options?: TransactionHistoryOptions, vaultId?: string): Promise<VaultTransaction[]>;
376
+ /**
377
+ * Estimate the number of shares that a USDC deposit would yield
378
+ * at the current share price.
379
+ *
380
+ * @param amountUsdc - USDC amount (human-readable)
381
+ * @returns Estimated shares as a string, or null if price unavailable
382
+ */
383
+ estimateShares(amountUsdc: number): Promise<string | null>;
384
+ /**
385
+ * Estimate the USDC value of a given number of shares
386
+ * at the current share price.
387
+ *
388
+ * @param shares - Number of shares (human-readable)
389
+ * @returns Estimated USDC value as a string, or null if price unavailable
390
+ */
391
+ estimateUsdc(shares: number): Promise<string | null>;
392
+ /**
393
+ * Resolve a vault config by ID, falling back to the default vault.
394
+ * @throws {UnknownVaultError} If the vault ID is not registered
395
+ */
396
+ private resolveVault;
397
+ /**
398
+ * Get or create a cached Anchor Program instance for a vault.
399
+ *
400
+ * Uses a read-only provider (no signer) since the SDK only builds
401
+ * transactions — it never signs or submits them.
402
+ */
403
+ private getProgram;
404
+ /**
405
+ * Resolve the Anchor IDL for a given vault configuration.
406
+ * Currently only the built-in rcUSDP devnet IDL is supported.
407
+ */
408
+ private resolveIdl;
409
+ }
410
+
411
+ /**
412
+ * Network-specific configuration and vault registry.
413
+ *
414
+ * The SDK ships with built-in configuration for the rcUSDP vault on both
415
+ * devnet and mainnet. Future vaults will be dynamically loaded via the
416
+ * TBook API.
417
+ *
418
+ * @module config
419
+ */
420
+
421
+ /** USDC uses 6 decimal places on Solana. */
422
+ declare const USDC_DECIMALS = 6;
423
+ /** Vault shares use 6 decimal places (matching Sui vault share token). */
424
+ declare const SHARE_DECIMALS = 6;
425
+ /** 1 USDC in raw units (10^6). */
426
+ declare const ONE_USDC = 1000000;
427
+ /** 1 share in raw units (10^6). */
428
+ declare const ONE_SHARE = 1000000;
429
+ /** Default cancellation fee in basis points (0.1%). */
430
+ declare const DEFAULT_CANCEL_FEE_BPS = 10;
431
+ /**
432
+ * Return a default public RPC URL for the given network.
433
+ * In production, consumers should supply their own dedicated RPC
434
+ * (e.g. Helius, Triton) for reliability and rate-limit headroom.
435
+ */
436
+ declare function getDefaultRpcUrl(network: SolanaNetwork): string;
437
+ /** Build a Solana Explorer URL for an address or transaction. */
438
+ declare function explorerUrl(type: "address" | "tx", value: string, network: SolanaNetwork): string;
439
+ /**
440
+ * Per-vault on-chain configuration.
441
+ * Contains the program ID and known account addresses needed to
442
+ * interact with a specific vault deployment.
443
+ */
444
+ interface VaultConfig {
445
+ /** Vault identifier. */
446
+ id: string;
447
+ /** Anchor program ID. */
448
+ programId: PublicKey;
449
+ /** USDC mint used by this vault. */
450
+ usdcMint: PublicKey;
451
+ /** Network this config applies to. */
452
+ network: SolanaNetwork;
453
+ }
454
+ /**
455
+ * Resolve a vault config by id and network.
456
+ * Returns `undefined` if the vault is not registered.
457
+ */
458
+ declare function getVaultConfig(vaultId: string, network: SolanaNetwork): VaultConfig | undefined;
459
+ /**
460
+ * List all built-in vault descriptors for a given network.
461
+ */
462
+ declare function listBuiltInVaults(network: SolanaNetwork): VaultDescriptor[];
463
+ /** Default vault ID used when no vaultId is specified. */
464
+ declare const DEFAULT_VAULT_ID = "rcUSDP";
465
+
466
+ /**
467
+ * PDA (Program Derived Address) derivation for Vault Gateway accounts.
468
+ *
469
+ * Each vault has a set of deterministic PDAs derived from the program ID:
470
+ * - VaultMirror: global singleton
471
+ * - UserAccount: per-user state
472
+ * - DepositEpoch / RedeemEpoch: per-epoch batch tracking
473
+ * - UsdcVault: SPL token account for vault USDC
474
+ *
475
+ * All functions are pure and synchronous — no RPC calls needed.
476
+ *
477
+ * @module pda
478
+ */
479
+
480
+ /**
481
+ * Derive the VaultMirror PDA (global vault state).
482
+ * Seeds: `["vault_mirror"]`
483
+ */
484
+ declare function getVaultMirrorPda(programId: PublicKey): [PublicKey, number];
485
+ /**
486
+ * Derive the USDC vault token account PDA.
487
+ * Seeds: `["usdc_vault", vaultMirror]`
488
+ */
489
+ declare function getUsdcVaultPda(vaultMirror: PublicKey, programId: PublicKey): [PublicKey, number];
490
+ /**
491
+ * Derive a user's account PDA.
492
+ * Seeds: `["user", vaultMirror, userPubkey]`
493
+ */
494
+ declare function getUserPda(vaultMirror: PublicKey, user: PublicKey, programId: PublicKey): [PublicKey, number];
495
+ /**
496
+ * Derive a deposit epoch PDA.
497
+ * Seeds: `["deposit_epoch", vaultMirror, epochNumber (u64 LE)]`
498
+ */
499
+ declare function getDepositEpochPda(vaultMirror: PublicKey, epoch: number, programId: PublicKey): [PublicKey, number];
500
+ /**
501
+ * Derive a redeem epoch PDA.
502
+ * Seeds: `["redeem_epoch", vaultMirror, epochNumber (u64 LE)]`
503
+ */
504
+ declare function getRedeemEpochPda(vaultMirror: PublicKey, epoch: number, programId: PublicKey): [PublicKey, number];
505
+
506
+ /**
507
+ * On-chain state query functions.
508
+ *
509
+ * Reads VaultMirror, UserAccount, and Epoch PDAs from Solana.
510
+ * Supports both Anchor-based and raw byte deserialization for
511
+ * maximum compatibility (the latter works without a wallet).
512
+ *
513
+ * @module queries
514
+ */
515
+
516
+ /**
517
+ * Fetch global vault state and current epoch info.
518
+ *
519
+ * Tries Anchor deserialization first (requires a Program instance),
520
+ * then falls back to manual byte parsing (works with just a Connection).
521
+ *
522
+ * @param connection - Solana RPC connection
523
+ * @param programId - Vault Gateway program ID
524
+ * @param program - Optional Anchor program (enables richer deserialization)
525
+ */
526
+ declare function fetchVaultInfo(connection: Connection, programId: PublicKey, program?: Program): Promise<VaultInfoResult>;
527
+ /**
528
+ * Fetch a user's vault account with effective balances.
529
+ *
530
+ * Effective balances account for settled epochs that haven't been
531
+ * lazy-settled yet — the user's "real" balance even before their
532
+ * next on-chain interaction.
533
+ *
534
+ * @param connection - Solana RPC connection
535
+ * @param programId - Vault Gateway program ID
536
+ * @param user - User's public key
537
+ * @param program - Optional Anchor program
538
+ * @returns User account state, or null if user has never interacted
539
+ */
540
+ declare function fetchUserAccount(connection: Connection, programId: PublicKey, user: PublicKey, program?: Program): Promise<UserAccount | null>;
541
+
542
+ /**
543
+ * Share price fetching with 3-layer fallback:
544
+ *
545
+ * 1. Fresh cache — return immediately if within freshness window
546
+ * 2. API fetch — NAV oracle endpoint, with timeout + circuit breaker
547
+ * 3. Stale cache — return expired cache with `stale: true` flag
548
+ * 4. All fail — throw SharePriceUnavailableError
549
+ *
550
+ * NOTE: On-chain calculation (vaultUsdcBalance / totalShares) was removed
551
+ * because it only reflects Solana-side USDC, not bridged assets on Sui.
552
+ * This would produce dangerously low prices (e.g., $0.02 when real price
553
+ * is ~$1.00). The API endpoint is the only reliable price source.
554
+ *
555
+ * @module share-price
556
+ */
557
+
558
+ /**
559
+ * Options for {@link fetchSharePrice}.
560
+ */
561
+ interface FetchSharePriceOptions {
562
+ /** Override the default API endpoint. */
563
+ apiUrl?: string;
564
+ }
565
+ /**
566
+ * Fetch the current share price using a 3-layer fallback strategy.
567
+ *
568
+ * @param options - Optional overrides for API URL
569
+ * @returns Share price data with `source` indicating where it came from
570
+ * @throws {SharePriceUnavailableError} If all layers fail
571
+ */
572
+ declare function fetchSharePrice(options?: FetchSharePriceOptions | string): Promise<SharePriceData>;
573
+
574
+ /**
575
+ * Transaction builders for vault operations.
576
+ *
577
+ * All builders return an **unsigned** {@link TransactionResult} containing:
578
+ * - `transaction`: a Solana `Transaction` object for wallet adapters
579
+ * - `serialized`: a base58 string for WaaS provider APIs
580
+ * - `message`: human-readable description
581
+ *
582
+ * The SDK never signs or submits transactions. Signing is the
583
+ * responsibility of the integrating app (via wallet adapter, WaaS, etc.).
584
+ *
585
+ * @module transactions
586
+ */
587
+
588
+ /**
589
+ * Build an unsigned deposit transaction.
590
+ *
591
+ * Validates vault state (not paused, epoch open, min/max amounts)
592
+ * before building. Lazy settlement remaining_accounts are computed
593
+ * automatically.
594
+ *
595
+ * @param program - Initialized Anchor program (readonly, no signer needed)
596
+ * @param params - Deposit parameters (user pubkey + USDC amount)
597
+ * @returns Unsigned transaction ready for signing
598
+ *
599
+ * @throws {VaultPausedError} If the vault is paused
600
+ * @throws {MinDepositError} If amount is below minimum
601
+ * @throws {MaxEpochDepositError} If amount exceeds epoch limit
602
+ * @throws {EpochNotOpenError} If deposit epoch is not open
603
+ * @throws {RpcError} If an RPC call fails
604
+ */
605
+ declare function buildDepositTx(program: Program, params: DepositParams, options?: {
606
+ timeoutMs?: number;
607
+ }): Promise<TransactionResult>;
608
+ /**
609
+ * Build an unsigned request-redeem transaction.
610
+ *
611
+ * Locks the specified shares for redemption in the current epoch.
612
+ * The actual USDC payout happens after the curator settles the epoch.
613
+ *
614
+ * @param program - Initialized Anchor program
615
+ * @param params - Redeem parameters (user pubkey + share amount)
616
+ * @returns Unsigned transaction ready for signing
617
+ *
618
+ * @throws {VaultPausedError} If the vault is paused
619
+ * @throws {RpcError} If an RPC call fails
620
+ */
621
+ declare function buildRedeemTx(program: Program, params: RedeemParams, options?: {
622
+ timeoutMs?: number;
623
+ }): Promise<TransactionResult>;
624
+ /**
625
+ * Build an unsigned claim transaction.
626
+ *
627
+ * Withdraws any claimable USDC to the user's wallet.
628
+ * Claim always works even when the vault is paused.
629
+ *
630
+ * @param program - Initialized Anchor program
631
+ * @param params - User parameters (user pubkey)
632
+ * @returns Unsigned transaction ready for signing
633
+ */
634
+ declare function buildClaimTx(program: Program, params: UserTxParams, options?: {
635
+ timeoutMs?: number;
636
+ }): Promise<TransactionResult>;
637
+ /**
638
+ * Build an unsigned cancel-deposit transaction.
639
+ *
640
+ * Cancels a pending deposit and returns USDC minus a 0.1% fee.
641
+ *
642
+ * @param program - Initialized Anchor program
643
+ * @param params - User parameters (user pubkey)
644
+ * @returns Unsigned transaction ready for signing
645
+ */
646
+ declare function buildCancelDepositTx(program: Program, params: UserTxParams, options?: {
647
+ timeoutMs?: number;
648
+ }): Promise<TransactionResult>;
649
+
650
+ /**
651
+ * RPC utilities: timeout wrapper and transaction confirmation with retry.
652
+ *
653
+ * These utilities work in both browser and Node.js environments
654
+ * (no external dependencies, uses standard AbortController).
655
+ *
656
+ * @module rpc-utils
657
+ */
658
+
659
+ /**
660
+ * Wait for the given number of milliseconds.
661
+ */
662
+ declare function sleep(ms: number): Promise<void>;
663
+ /**
664
+ * Race a promise against a timeout. If the promise doesn't resolve
665
+ * within `ms` milliseconds, throws {@link RpcTimeoutError}.
666
+ *
667
+ * Uses `AbortController` which is available in browsers and Node 16+.
668
+ *
669
+ * @param promise - The async operation to wrap
670
+ * @param ms - Timeout in milliseconds
671
+ * @param label - Human-readable label for error messages (e.g., "getLatestBlockhash")
672
+ * @returns The resolved value of the promise
673
+ * @throws {RpcTimeoutError} If the timeout fires before the promise resolves
674
+ */
675
+ declare function withTimeout<T>(promise: Promise<T>, ms: number, label: string): Promise<T>;
676
+ /** Options for {@link confirmTransactionWithRetry}. */
677
+ interface ConfirmTxOptions {
678
+ /** Solana RPC connection. */
679
+ connection: Connection;
680
+ /** Transaction signature (base58). */
681
+ signature: string;
682
+ /** Blockhash used when the transaction was built. */
683
+ blockhash: string;
684
+ /** Last valid block height for the blockhash. */
685
+ lastValidBlockHeight: number;
686
+ /** Desired commitment level. Default: "confirmed". */
687
+ commitment?: Commitment;
688
+ /** Maximum total wait time in milliseconds. Default: 60_000. */
689
+ timeoutMs?: number;
690
+ /** Initial polling interval in milliseconds. Default: 2_000 (scales up with 1.5x backoff, max 5s). */
691
+ initialIntervalMs?: number;
692
+ }
693
+ /**
694
+ * Confirm a transaction with exponential-backoff polling.
695
+ *
696
+ * Unlike `connection.confirmTransaction()` which can silently hang,
697
+ * this implementation:
698
+ * - Polls `getSignatureStatuses` with configurable backoff
699
+ * - Checks `getBlockHeight` to detect expired blockhashes
700
+ * - Throws typed errors for timeout, expiry, and on-chain failures
701
+ *
702
+ * @throws {TransactionExpiredError} If the blockhash expires before confirmation
703
+ * @throws {TransactionFailedError} If the transaction fails on-chain
704
+ * @throws {RpcTimeoutError} If the overall timeout is exceeded
705
+ */
706
+ declare function confirmTransactionWithRetry(opts: ConfirmTxOptions): Promise<void>;
707
+
708
+ /**
709
+ * In-memory share price cache with circuit breaker.
710
+ *
711
+ * Avoids redundant API calls and provides graceful degradation
712
+ * when the NAV oracle is temporarily unreachable.
713
+ *
714
+ * @module share-price-cache
715
+ */
716
+
717
+ /**
718
+ * In-memory cache for share price data with a simple circuit breaker
719
+ * to avoid hammering a failing API endpoint.
720
+ */
721
+ declare class SharePriceCache {
722
+ /** Maximum age (in ms) before cached data is considered stale. */
723
+ readonly maxStaleMs: number;
724
+ private data;
725
+ private storedAt;
726
+ private failureCount;
727
+ private readonly failureThreshold;
728
+ private circuitOpenedAt;
729
+ private readonly circuitResetMs;
730
+ constructor(opts?: {
731
+ maxStaleMs?: number;
732
+ failureThreshold?: number;
733
+ circuitResetMs?: number;
734
+ });
735
+ /**
736
+ * Return cached data if it is fresher than `maxAge` milliseconds.
737
+ * Returns `null` if the cache is empty or the data is too old.
738
+ *
739
+ * @param maxAge - Override the default freshness window (pass `Infinity` for stale-ok)
740
+ */
741
+ get(maxAge?: number): SharePriceData | null;
742
+ /** Store fresh share price data. */
743
+ set(data: SharePriceData): void;
744
+ /** Whether the circuit breaker is currently open (API calls should be skipped). */
745
+ isCircuitOpen(): boolean;
746
+ /** Record a failed API call. Opens the circuit after the threshold is reached. */
747
+ recordFailure(): void;
748
+ /** Record a successful API call. Resets the circuit breaker. */
749
+ recordSuccess(): void;
750
+ }
751
+ /** Shared singleton cache instance used by {@link fetchSharePrice}. */
752
+ declare const sharePriceCache: SharePriceCache;
753
+
754
+ /**
755
+ * Typed error classes for the TBook Vault SDK.
756
+ *
757
+ * All SDK errors extend {@link VaultSdkError} so consumers can catch
758
+ * SDK-specific errors in a single catch block:
759
+ *
760
+ * ```typescript
761
+ * try {
762
+ * await vault.buildDeposit({ ... });
763
+ * } catch (err) {
764
+ * if (err instanceof VaultSdkError) {
765
+ * console.error(`SDK error [${err.code}]: ${err.message}`);
766
+ * }
767
+ * }
768
+ * ```
769
+ *
770
+ * @module errors
771
+ */
772
+ /** Base error class for all vault SDK errors. */
773
+ declare class VaultSdkError extends Error {
774
+ /** Machine-readable error code. */
775
+ readonly code: string;
776
+ /** Non-technical message suitable for displaying to end users. */
777
+ readonly userFriendlyMessage: string;
778
+ constructor(code: string, message: string, userFriendlyMessage?: string);
779
+ }
780
+ /**
781
+ * Thrown when the vault is paused and an operation that requires
782
+ * an active vault is attempted (deposit, redeem).
783
+ * Note: `claim` always works even when paused.
784
+ */
785
+ declare class VaultPausedError extends VaultSdkError {
786
+ constructor();
787
+ }
788
+ /** Thrown when the deposit amount is below the vault's minimum. */
789
+ declare class MinDepositError extends VaultSdkError {
790
+ /** The minimum required deposit in USDC. */
791
+ readonly minDeposit: number;
792
+ constructor(minDeposit: number);
793
+ }
794
+ /** Thrown when the deposit amount would exceed the epoch's maximum. */
795
+ declare class MaxEpochDepositError extends VaultSdkError {
796
+ readonly maxEpochDeposit: number;
797
+ constructor(maxEpochDeposit: number);
798
+ }
799
+ /** Thrown when the deposit epoch is not in an "Open" state. */
800
+ declare class EpochNotOpenError extends VaultSdkError {
801
+ constructor(epochType: "deposit" | "redeem", status: string);
802
+ }
803
+ /** Thrown when the VaultMirror PDA cannot be found on-chain. */
804
+ declare class VaultNotFoundError extends VaultSdkError {
805
+ constructor();
806
+ }
807
+ /** Thrown when a user account PDA is expected but does not exist. */
808
+ declare class UserAccountNotFoundError extends VaultSdkError {
809
+ constructor(pubkey: string);
810
+ }
811
+ /** Thrown when an unsupported or unknown vault ID is requested. */
812
+ declare class UnknownVaultError extends VaultSdkError {
813
+ constructor(vaultId: string);
814
+ }
815
+ /** Thrown when the share price API is unreachable or returns invalid data. */
816
+ declare class SharePriceUnavailableError extends VaultSdkError {
817
+ constructor(reason?: string);
818
+ }
819
+ /** Thrown when a cancel-deposit is attempted but the user has no pending deposit. */
820
+ declare class NoPendingDepositError extends VaultSdkError {
821
+ constructor();
822
+ }
823
+ /** Thrown when an RPC call fails. */
824
+ declare class RpcError extends VaultSdkError {
825
+ /** The underlying error from the RPC library. */
826
+ readonly cause: unknown;
827
+ constructor(operation: string, cause: unknown);
828
+ }
829
+ /** Thrown when an RPC call exceeds the configured timeout. */
830
+ declare class RpcTimeoutError extends VaultSdkError {
831
+ /** The timeout duration in milliseconds. */
832
+ readonly timeoutMs: number;
833
+ constructor(operation: string, timeoutMs: number);
834
+ }
835
+ /** Thrown when a transaction's blockhash expires before confirmation. */
836
+ declare class TransactionExpiredError extends VaultSdkError {
837
+ /** The transaction signature. */
838
+ readonly signature: string;
839
+ constructor(signature: string);
840
+ }
841
+ /** Thrown when a transaction fails on-chain (e.g., program error). */
842
+ declare class TransactionFailedError extends VaultSdkError {
843
+ /** The transaction signature. */
844
+ readonly signature: string;
845
+ /** The on-chain error object. */
846
+ readonly txError: unknown;
847
+ constructor(signature: string, txError: unknown);
848
+ }
849
+
850
+ /**
851
+ * Formatting, validation, and conversion utilities.
852
+ *
853
+ * @module utils
854
+ */
855
+ /** Truncate a number to N decimal places without rounding. */
856
+ declare function truncateNumber(value: number, decimals: number): number;
857
+ /** Truncate and format a number to a fixed-decimal string. */
858
+ declare function formatTruncated(value: number, decimals: number): string;
859
+ /** Format a number with locale-aware thousand separators (truncated, not rounded). */
860
+ declare function formatNumber(value: number, decimals?: number): string;
861
+ /** Format a number as USD currency (truncated). */
862
+ declare function formatCurrency(value: number, currency?: string): string;
863
+ /** Format a percentage value. */
864
+ declare function formatPercentage(value: number, decimals?: number): string;
865
+ /** Shorten a Solana address for display: "AbCd...xYz". */
866
+ declare function shortenAddress(address: string, chars?: number): string;
867
+ /** Format a raw USDC amount (6 decimals) to a human-readable string. */
868
+ declare function formatUsdc(raw: number | bigint): string;
869
+ /** Format a raw share amount (6 decimals) to a human-readable string. */
870
+ declare function formatShares(raw: number | bigint): string;
871
+ /** Convert raw u64 to human-readable UI amount. */
872
+ declare function rawToUi(raw: number | bigint, decimals: number): number;
873
+ /** Convert human-readable UI amount to raw u64. Uses truncation (not rounding). */
874
+ declare function uiToRaw(ui: number, decimals: number): number;
875
+ /** Result of an input validation check. */
876
+ interface ValidationResult {
877
+ valid: boolean;
878
+ error?: string;
879
+ }
880
+ /**
881
+ * Validate an amount for deposit or redeem operations.
882
+ *
883
+ * @param amount - The amount as a string (from user input)
884
+ * @param balance - User's available balance
885
+ * @param action - Action name for error messages (e.g. "deposit")
886
+ * @param token - Token name for error messages (e.g. "USDC")
887
+ * @param min - Minimum allowed amount
888
+ * @param max - Maximum allowed amount
889
+ */
890
+ declare function validateAmount(amount: string, balance: number, action: string, token: string, min?: number, max?: number): ValidationResult;
891
+ /** Check if a string is a valid numeric input (numbers and single decimal point). */
892
+ declare function isValidAmountInput(value: string): boolean;
893
+
894
+ export { type ConfirmTxOptions, DEFAULT_CANCEL_FEE_BPS, DEFAULT_VAULT_ID, type DepositEpochInfo, type DepositParams, EpochNotOpenError, type EpochStatus, MaxEpochDepositError, MinDepositError, NoPendingDepositError, ONE_SHARE, ONE_USDC, type RedeemEpochInfo, type RedeemParams, RpcError, RpcTimeoutError, SHARE_DECIMALS, STATUS_MAP, SharePriceCache, type SharePriceData, SharePriceUnavailableError, type SolanaNetwork, TBookVault, type TBookVaultOptions, TransactionExpiredError, TransactionFailedError, type TransactionHistoryOptions, type TransactionResult, USDC_DECIMALS, UnknownVaultError, type UserAccount, UserAccountNotFoundError, type UserTxParams, type ValidationResult, type VaultConfig, type VaultDescriptor, type VaultInfo, type VaultInfoResult, VaultNotFoundError, VaultPausedError, VaultSdkError, type VaultTransaction, buildCancelDepositTx, buildClaimTx, buildDepositTx, buildRedeemTx, confirmTransactionWithRetry, explorerUrl, fetchSharePrice, fetchTransactionHistory, fetchUserAccount, fetchVaultInfo, formatCurrency, formatNumber, formatPercentage, formatShares, formatTruncated, formatUsdc, getDefaultRpcUrl, getDepositEpochPda, getRedeemEpochPda, getUsdcVaultPda, getUserPda, getVaultConfig, getVaultMirrorPda, isValidAmountInput, listBuiltInVaults, rawToUi, sharePriceCache, shortenAddress, sleep, truncateNumber, uiToRaw, validateAmount, withTimeout };