@gvnrdao/dh-sdk 0.0.219 → 0.0.221

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.
@@ -12,7 +12,7 @@ import type { BigNumber } from "ethers";
12
12
  * Based on contracts/src/interfaces/IPositionManager.sol
13
13
  */
14
14
  export interface PositionManager extends ethers5.Contract {
15
- createPosition(pkpId: string, validatorSignature: string, mainnetVaultAddress: string, regtestVaultAddress: string, selectedTermMonths: number | BigNumber, validatorVersion: number | BigNumber): Promise<ethers5.ContractTransaction>;
15
+ createPosition(pkpId: string, validatorSignature: string, mainnetVaultAddress: string, regtestVaultAddress: string, selectedTermMonths: number | BigNumber, validatorVersion: number | BigNumber, pkpPublicKey: string): Promise<ethers5.ContractTransaction>;
16
16
  mintUCD(positionId: string, mintAmount: BigNumber, mintFee: BigNumber, newDebt: BigNumber, newCollateral: BigNumber, btcPrice: BigNumber, authorizedSpendsHash: string, ucdDebtHash: string, contractHash: string, quantumTimestamp: BigNumber, mintValidatorSignature: string): Promise<ethers5.ContractTransaction>;
17
17
  liquidatePosition(positionId: string, btcPrice: BigNumber, quantumTimestamp: BigNumber, liquidationValidatorSignature: string): Promise<ethers5.ContractTransaction>;
18
18
  getPosition(positionId: string): Promise<{
@@ -184,19 +184,11 @@ export declare class BitcoinOperations {
184
184
  /**
185
185
  * Get balance cache statistics
186
186
  */
187
- getBalanceCacheStats(): {
188
- size: number;
189
- maxSize: number;
190
- ttlMs: number;
191
- } | null;
187
+ getBalanceCacheStats(): import("../cache/cache-manager.module").CacheStats | null;
192
188
  /**
193
189
  * Get address cache statistics
194
190
  */
195
- getAddressCacheStats(): {
196
- size: number;
197
- maxSize: number;
198
- ttlMs: number;
199
- } | null;
191
+ getAddressCacheStats(): import("../cache/cache-manager.module").CacheStats | null;
200
192
  /**
201
193
  * Get current network configuration
202
194
  */
@@ -1,74 +1,228 @@
1
1
  /**
2
- * Cache Manager Module
2
+ * Generic Cache Manager Module
3
3
  *
4
- * Provides a simple cache factory for SDK modules.
5
- * Each cache is an independent LRU cache with TTL support.
4
+ * Provides a type-safe, generic LRU cache with TTL support.
5
+ * Can be used for any data type (Bitcoin balances, addresses, query results, etc.)
6
+ *
7
+ * Features:
8
+ * - Generic type support
9
+ * - TTL-based expiration
10
+ * - LRU eviction policy
11
+ * - Hit/miss statistics
12
+ * - Memory-efficient
13
+ * - Thread-safe operations
6
14
  */
7
- export interface CacheConfig {
8
- maxSize: number;
9
- ttlMs: number;
15
+ import { Result } from '../../types/result';
16
+ import { SDKError } from '../../utils/error-handler';
17
+ /**
18
+ * Cache entry with metadata
19
+ */
20
+ interface CacheEntry<T> {
21
+ /** Cached value */
22
+ value: T;
23
+ /** Unix timestamp when entry was created (ms) */
24
+ timestamp: number;
25
+ /** Number of times this entry was accessed */
26
+ hits: number;
27
+ /** Unix timestamp of last access (ms) */
28
+ lastAccessed: number;
10
29
  }
30
+ /**
31
+ * Cache statistics
32
+ */
11
33
  export interface CacheStats {
34
+ /** Current number of entries in cache */
12
35
  size: number;
13
- maxSize: number;
14
- ttlMs: number;
36
+ /** Total cache hits */
37
+ hits: number;
38
+ /** Total cache misses */
39
+ misses: number;
40
+ /** Total evictions performed */
41
+ evictions: number;
42
+ /** Timestamp of oldest entry (ms) */
43
+ oldestEntry: number;
44
+ /** Timestamp of newest entry (ms) */
45
+ newestEntry: number;
46
+ /** Hit rate as percentage (0-100) */
47
+ hitRate: number;
48
+ }
49
+ /**
50
+ * Cache configuration
51
+ */
52
+ export interface CacheConfig {
53
+ /** Maximum number of entries (default: 1000) */
54
+ maxSize?: number;
55
+ /** Time-to-live in milliseconds (default: 60000 = 1 minute) */
56
+ ttlMs?: number;
57
+ /** Enable debug logging (default: false) */
58
+ debug?: boolean;
59
+ /** Cache name for logging (default: 'Cache') */
60
+ name?: string;
15
61
  }
16
62
  /**
17
- * Simple LRU Cache with TTL support
63
+ * Generic LRU Cache with TTL support
64
+ *
65
+ * @template K - Key type (usually string)
66
+ * @template V - Value type
67
+ *
68
+ * @example
69
+ * ```typescript
70
+ * // Create a cache for Bitcoin balances
71
+ * const balanceCache = new LRUCache<string, BitcoinBalance>({
72
+ * maxSize: 500,
73
+ * ttlMs: 60000,
74
+ * name: 'BitcoinBalance'
75
+ * });
76
+ *
77
+ * // Set value
78
+ * balanceCache.set('bc1q...', { balance: Satoshis(50000000n) });
79
+ *
80
+ * // Get value
81
+ * const balance = balanceCache.get('bc1q...');
82
+ * if (balance) {
83
+ * console.log('Cached balance:', balance.balance);
84
+ * }
85
+ * ```
18
86
  */
19
- export declare class Cache<T = any> {
87
+ export declare class LRUCache<K, V> {
20
88
  private cache;
21
89
  private readonly maxSize;
22
90
  private readonly ttlMs;
23
- constructor(config: CacheConfig);
91
+ private readonly debug;
92
+ private readonly name;
93
+ private stats;
94
+ constructor(config?: CacheConfig);
24
95
  /**
25
96
  * Get value from cache
97
+ *
98
+ * Returns null if:
99
+ * - Key not found
100
+ * - Entry has expired
101
+ *
102
+ * @param key - Cache key
103
+ * @returns Cached value or null
104
+ */
105
+ get(key: K): V | null;
106
+ /**
107
+ * Get value from cache with Result wrapper
108
+ *
109
+ * Useful when you want to distinguish between "not found" and "expired"
26
110
  */
27
- get(key: string): T | undefined;
111
+ getResult(key: K): Result<V, SDKError>;
28
112
  /**
29
113
  * Set value in cache
114
+ *
115
+ * If cache is full, evicts the least recently used entry
116
+ *
117
+ * @param key - Cache key
118
+ * @param value - Value to cache
119
+ * @param ttl - Optional custom TTL for this entry (ms)
30
120
  */
31
- set(key: string, value: T, ttl?: number): void;
121
+ set(key: K, value: V, ttl?: number): void;
32
122
  /**
33
- * Check if key exists in cache
123
+ * Set value in cache with Result wrapper
34
124
  */
35
- has(key: string): boolean;
125
+ setResult(key: K, value: V, ttl?: number): Result<void, SDKError>;
36
126
  /**
37
- * Delete key from cache
127
+ * Check if key exists in cache (without affecting stats)
38
128
  */
39
- delete(key: string): boolean;
129
+ has(key: K): boolean;
130
+ /**
131
+ * Delete specific key from cache
132
+ */
133
+ delete(key: K): boolean;
40
134
  /**
41
- * Clear all cache entries
135
+ * Clear entire cache
42
136
  */
43
137
  clear(): void;
44
138
  /**
45
- * Clean expired entries
139
+ * Get current cache size
46
140
  */
47
- cleanExpired(): number;
141
+ size(): number;
48
142
  /**
49
143
  * Get cache statistics
50
144
  */
51
- getStats(): {
52
- size: number;
53
- maxSize: number;
54
- ttlMs: number;
55
- };
145
+ getStats(): CacheStats;
146
+ /**
147
+ * Get hit rate percentage
148
+ */
149
+ getHitRate(): number;
150
+ /**
151
+ * Get all cached keys (for debugging)
152
+ */
153
+ getKeys(): K[];
154
+ /**
155
+ * Get all cached values (for debugging)
156
+ */
157
+ getValues(): V[];
158
+ /**
159
+ * Get all cache entries with metadata (for debugging)
160
+ */
161
+ getEntries(): Array<{
162
+ key: K;
163
+ value: V;
164
+ metadata: Omit<CacheEntry<V>, 'value'>;
165
+ }>;
166
+ /**
167
+ * Clean up expired entries
168
+ *
169
+ * Useful for periodic maintenance
170
+ *
171
+ * @returns Number of entries cleaned
172
+ */
173
+ cleanExpired(): number;
174
+ /**
175
+ * Check if cache entry is expired
176
+ */
177
+ private isExpired;
178
+ /**
179
+ * Evict least recently used entry
180
+ */
181
+ private evictLRU;
182
+ /**
183
+ * Get or compute value
184
+ *
185
+ * If key exists in cache, returns cached value.
186
+ * Otherwise, computes value using provided function and caches it.
187
+ *
188
+ * @param key - Cache key
189
+ * @param compute - Function to compute value if not in cache
190
+ * @param ttl - Optional custom TTL for this entry
191
+ * @returns Cached or computed value
192
+ */
193
+ getOrCompute(key: K, compute: () => Promise<V>, ttl?: number): Promise<V>;
194
+ /**
195
+ * Get or compute value with Result wrapper
196
+ */
197
+ getOrComputeResult(key: K, compute: () => Promise<Result<V, SDKError>>, ttl?: number): Promise<Result<V, SDKError>>;
56
198
  }
57
199
  /**
58
- * Cache Manager
59
- *
60
- * Factory for creating named caches with specific configurations
200
+ * Generic cache interface for type safety
201
+ */
202
+ export interface Cache<T> {
203
+ get(key: string): T | null | undefined;
204
+ set(key: string, value: T): void;
205
+ delete(key: string): boolean;
206
+ clear(): void;
207
+ has(key: string): boolean;
208
+ size(): number;
209
+ getStats(): CacheStats;
210
+ }
211
+ /**
212
+ * Cache Manager - Factory for creating specialized caches
61
213
  */
62
214
  export declare class CacheManager {
63
215
  private caches;
64
- private readonly debug;
65
- constructor(config?: {
66
- debug?: boolean;
67
- });
216
+ private readonly globalConfig;
217
+ constructor(globalConfig?: CacheConfig);
68
218
  /**
69
- * Get or create a cache instance
219
+ * Create or get a named cache
220
+ *
221
+ * @param name - Unique cache name
222
+ * @param config - Optional cache-specific configuration
223
+ * @returns LRU cache instance
70
224
  */
71
- getCache<T = any>(name: string, config: CacheConfig): Cache<T>;
225
+ getCache<K, V>(name: string, config?: CacheConfig): LRUCache<K, V>;
72
226
  /**
73
227
  * Clear all caches
74
228
  */
@@ -80,13 +234,18 @@ export declare class CacheManager {
80
234
  /**
81
235
  * Get statistics for all caches
82
236
  */
83
- getAllStats(): Record<string, ReturnType<Cache["getStats"]>>;
237
+ getAllStats(): Record<string, CacheStats>;
238
+ /**
239
+ * Get list of all cache names
240
+ */
241
+ getCacheNames(): string[];
84
242
  /**
85
- * Destroy cache manager
243
+ * Delete a named cache
86
244
  */
87
- destroy(): void;
245
+ deleteCache(name: string): boolean;
88
246
  }
89
- export { Cache as LRUCache };
90
- export declare function createCacheManager(config?: {
91
- debug?: boolean;
92
- }): CacheManager;
247
+ /**
248
+ * Factory function to create a CacheManager instance
249
+ */
250
+ export declare function createCacheManager(config?: CacheConfig): CacheManager;
251
+ export {};
@@ -563,11 +563,7 @@ export declare class DiamondHandsSDK {
563
563
  /**
564
564
  * Get cache statistics
565
565
  */
566
- getCacheStats(): Record<string, {
567
- size: number;
568
- maxSize: number;
569
- ttlMs: number;
570
- }>;
566
+ getCacheStats(): Record<string, import("./cache/cache-manager.module").CacheStats>;
571
567
  /**
572
568
  * Get contract manager (for advanced usage)
573
569
  */
@@ -593,6 +589,11 @@ export declare class DiamondHandsSDK {
593
589
  * Will be integrated into core methods in Round 2
594
590
  */
595
591
  private extractLitActionError;
592
+ /**
593
+ * Build the Chipotle service-mode fallback config for getPKPPublicKeyFromTokenId.
594
+ * Returns undefined in standalone mode so the helper falls back to throwing.
595
+ */
596
+ private getChipotlePublicKeyFallback;
596
597
  /**
597
598
  * Get provider or throw error
598
599
  */
@@ -196,11 +196,7 @@ export declare class LoanQuery {
196
196
  /**
197
197
  * Get cache statistics
198
198
  */
199
- getCacheStats(): {
200
- size: number;
201
- maxSize: number;
202
- ttlMs: number;
203
- } | null;
199
+ getCacheStats(): import("../cache/cache-manager.module").CacheStats | null;
204
200
  }
205
201
  /**
206
202
  * Factory function to create a LoanQuery instance
@@ -124,11 +124,7 @@ export declare class PKPManager {
124
124
  /**
125
125
  * Get cache statistics
126
126
  */
127
- getCacheStats(): {
128
- size: number;
129
- maxSize: number;
130
- ttlMs: number;
131
- } | null;
127
+ getCacheStats(): import("../cache/cache-manager.module").CacheStats | null;
132
128
  }
133
129
  /**
134
130
  * Factory function to create a PKPManager instance
@@ -132,24 +132,40 @@ export declare function generatePaymentAuthorization(positionId: string, amount:
132
132
  * - LIT Action validates recovered address === position owner
133
133
  */
134
134
  export declare function generateExtendAuthorization(positionId: string, selectedTerm: number, chainId: number, signer: ethers5.Signer): Promise<ExtendOwnerAuthorization>;
135
+ /**
136
+ * Optional Chipotle service fallback for `getPKPPublicKeyFromTokenId`.
137
+ *
138
+ * Chipotle PKPs have no on-chain `getPubkey(tokenId)` lookup, so when the
139
+ * SDK's in-memory `pkp-data` cache is empty (page reload, new device, cleared
140
+ * browser data) we recover the public key by re-running pkp-validator via the
141
+ * lit-ops-server `/api/lit/pkp/derive-public-key` endpoint. Chipotle key
142
+ * derivation is deterministic from `pkpId`, so this returns the same key.
143
+ */
144
+ export interface ChipotleServiceFallback {
145
+ serviceEndpoint: string;
146
+ serviceAuthToken?: string;
147
+ borrowerAddress?: string;
148
+ timeoutMs?: number;
149
+ debug?: boolean;
150
+ }
135
151
  /**
136
152
  * Get PKP public key from PKP token ID.
137
153
  *
138
- * Only valid for datil/naga-era PKPs minted as NFTs on Chronicle Yellowstone.
139
- * The caller must supply both the provider (connected to the PKP NFT's chain)
140
- * and the PKP NFT contract address for that chain.
154
+ * For datil/naga-era PKPs minted as NFTs on Chronicle Yellowstone: looks up
155
+ * via `getPubkey(tokenId)` on the supplied PKP NFT contract.
141
156
  *
142
- * Chipotle PKPs are wallet addresses returned by the Chipotle REST API — they
143
- * are not NFTs and cannot be looked up via this function. Passing a Chipotle
144
- * pkpId (ABI-encoded ETH address, e.g. 0x000...00<20-byte-addr>) throws an
145
- * explicit error so callers surface a clear diagnostic.
157
+ * For Chipotle PKPs (ABI-encoded ETH address): there is no on-chain lookup, so
158
+ * if `chipotleFallback.serviceEndpoint` is configured, the public key is
159
+ * derived by calling lit-ops-server. If the fallback is not configured, this
160
+ * throws with a clear diagnostic.
146
161
  *
147
162
  * @param pkpTokenId - PKP token ID (bytes32 hex string)
148
- * @param provider - Ethereum provider connected to the PKP NFT chain
149
- * @param pkpNftContractAddress - PKP NFT contract address on that chain (required)
163
+ * @param provider - Ethereum provider connected to the PKP NFT chain (datil/naga only)
164
+ * @param pkpNftContractAddress - PKP NFT contract address on that chain (datil/naga only)
165
+ * @param chipotleFallback - Service-mode fallback used when pkpTokenId is a Chipotle id
150
166
  * @returns PKP public key as hex string with '0x' prefix
151
167
  */
152
- export declare function getPKPPublicKeyFromTokenId(pkpTokenId: string, provider?: ethers5.providers.Provider, pkpNftContractAddress?: string): Promise<string>;
168
+ export declare function getPKPPublicKeyFromTokenId(pkpTokenId: string, provider?: ethers5.providers.Provider, pkpNftContractAddress?: string, chipotleFallback?: ChipotleServiceFallback): Promise<string>;
153
169
  /**
154
170
  * Withdraw Owner Authorization Interface (matches lit-actions)
155
171
  */
@@ -132,7 +132,7 @@ export declare function formatBalanceConfirmationFailureMessage(loanId: string):
132
132
  * @param loanId - Position/loan ID
133
133
  * @returns Formatted message string
134
134
  */
135
- export declare function formatBTCWithdrawalSuccessMessage(withdrawalAmount: number | string, btcVault: string, btcDestinationAddress: string, loanId: string): string;
135
+ export declare function formatBTCWithdrawalSuccessMessage(withdrawalAmount: number | string, btcVault: string, btcDestinationAddress: string, loanId: string, btcTxId?: string): string;
136
136
  /**
137
137
  * Format a liquidation skipped notification message
138
138
  *
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "@gvnrdao/dh-sdk",
3
- "version": "0.0.219",
3
+ "version": "0.0.221",
4
4
  "description": "TypeScript SDK for Diamond Hands Protocol - Bitcoin-backed lending with LIT Protocol PKPs",
5
5
  "main": "dist/index.js",
6
- "types": "dist/sdk/src/index.d.ts",
6
+ "types": "dist/index.d.ts",
7
7
  "module": "dist/index.mjs",
8
8
  "exports": {
9
9
  ".": {
10
- "types": "./dist/sdk/src/index.d.ts",
10
+ "types": "./dist/index.d.ts",
11
11
  "browser": "./dist/index.mjs",
12
12
  "import": "./dist/index.mjs",
13
13
  "require": "./dist/index.js"
14
14
  },
15
15
  "./server": {
16
- "types": "./dist/sdk/src/server.d.ts",
16
+ "types": "./dist/server.d.ts",
17
17
  "import": "./dist/server.mjs",
18
18
  "require": "./dist/server.js"
19
19
  }
@@ -70,8 +70,8 @@
70
70
  },
71
71
  "sideEffects": false,
72
72
  "dependencies": {
73
- "@gvnrdao/dh-lit-actions": "^0.0.283",
74
- "@gvnrdao/dh-lit-ops": "^0.0.256",
73
+ "@gvnrdao/dh-lit-actions": "^0.0.285",
74
+ "@gvnrdao/dh-lit-ops": "^0.0.258",
75
75
  "@noble/hashes": "^1.5.0",
76
76
  "axios": "^1.15.2",
77
77
  "bech32": "^2.0.0",