@sip-protocol/sdk 0.7.3 → 0.7.4

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 (264) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +267 -0
  3. package/dist/{TransportWebUSB-TQ7WZ4LE.mjs → TransportWebUSB-YQMAGJAJ.mjs} +12 -9
  4. package/dist/browser.d.mts +10 -4
  5. package/dist/browser.d.ts +10 -4
  6. package/dist/browser.js +47556 -19603
  7. package/dist/browser.mjs +628 -48
  8. package/dist/chunk-4GRJ5MAW.mjs +152 -0
  9. package/dist/chunk-5D7A3L3W.mjs +717 -0
  10. package/dist/chunk-64AYA5F5.mjs +7834 -0
  11. package/dist/chunk-GMDGB22A.mjs +379 -0
  12. package/dist/chunk-I534WKN7.mjs +328 -0
  13. package/dist/chunk-IBZVA5Y7.mjs +1003 -0
  14. package/dist/chunk-PRRZAWJE.mjs +223 -0
  15. package/dist/{chunk-UJCSKKID.mjs → chunk-XGB3TDIC.mjs} +13 -1
  16. package/dist/{chunk-3M3HNQCW.mjs → chunk-YWGJ77A2.mjs} +28656 -13103
  17. package/dist/{chunk-6WGN57S2.mjs → chunk-Z3K7W5S3.mjs} +48 -0
  18. package/dist/constants-LHAAUC2T.mjs +51 -0
  19. package/dist/dist-2OGQ7FED.mjs +3957 -0
  20. package/dist/dist-IFHPYLDX.mjs +254 -0
  21. package/dist/fulfillment_proof-ANHVPKTB.mjs +21 -0
  22. package/dist/funding_proof-ICFZ5LHY.mjs +21 -0
  23. package/dist/{index-DIBZHOOQ.d.ts → index-DXh2IGkz.d.ts} +21239 -10304
  24. package/dist/{index-8MQz13eJ.d.mts → index-DeE1ZzA4.d.mts} +21239 -10304
  25. package/dist/index.d.mts +9 -3
  26. package/dist/index.d.ts +9 -3
  27. package/dist/index.js +48396 -19623
  28. package/dist/index.mjs +537 -19
  29. package/dist/interface-Bf7w1PLW.d.mts +679 -0
  30. package/dist/interface-Bf7w1PLW.d.ts +679 -0
  31. package/dist/{noir-DKfEzWy9.d.mts → noir-kzbLVTei.d.mts} +31 -21
  32. package/dist/{noir-DKfEzWy9.d.ts → noir-kzbLVTei.d.ts} +31 -21
  33. package/dist/proofs/halo2.d.mts +151 -0
  34. package/dist/proofs/halo2.d.ts +151 -0
  35. package/dist/proofs/halo2.js +350 -0
  36. package/dist/proofs/halo2.mjs +11 -0
  37. package/dist/proofs/kimchi.d.mts +160 -0
  38. package/dist/proofs/kimchi.d.ts +160 -0
  39. package/dist/proofs/kimchi.js +431 -0
  40. package/dist/proofs/kimchi.mjs +13 -0
  41. package/dist/proofs/noir.d.mts +1 -1
  42. package/dist/proofs/noir.d.ts +1 -1
  43. package/dist/proofs/noir.js +74 -18
  44. package/dist/proofs/noir.mjs +84 -24
  45. package/dist/solana-U3MEGU7W.mjs +280 -0
  46. package/dist/validity_proof-3POXLPNY.mjs +21 -0
  47. package/package.json +54 -21
  48. package/src/adapters/index.ts +41 -0
  49. package/src/adapters/jupiter.ts +571 -0
  50. package/src/adapters/near-intents.ts +135 -0
  51. package/src/advisor/advisor.ts +653 -0
  52. package/src/advisor/index.ts +54 -0
  53. package/src/advisor/tools.ts +303 -0
  54. package/src/advisor/types.ts +164 -0
  55. package/src/chains/ethereum/announcement.ts +536 -0
  56. package/src/chains/ethereum/bnb-optimizations.ts +474 -0
  57. package/src/chains/ethereum/commitment.ts +522 -0
  58. package/src/chains/ethereum/constants.ts +462 -0
  59. package/src/chains/ethereum/deployment.ts +596 -0
  60. package/src/chains/ethereum/gas-estimation.ts +538 -0
  61. package/src/chains/ethereum/index.ts +268 -0
  62. package/src/chains/ethereum/optimizations.ts +614 -0
  63. package/src/chains/ethereum/privacy-adapter.ts +855 -0
  64. package/src/chains/ethereum/registry.ts +584 -0
  65. package/src/chains/ethereum/rpc.ts +905 -0
  66. package/src/chains/ethereum/stealth.ts +491 -0
  67. package/src/chains/ethereum/token.ts +790 -0
  68. package/src/chains/ethereum/transfer.ts +637 -0
  69. package/src/chains/ethereum/types.ts +456 -0
  70. package/src/chains/ethereum/viewing-key.ts +455 -0
  71. package/src/chains/near/commitment.ts +608 -0
  72. package/src/chains/near/constants.ts +284 -0
  73. package/src/chains/near/function-call.ts +871 -0
  74. package/src/chains/near/history.ts +654 -0
  75. package/src/chains/near/implicit-account.ts +840 -0
  76. package/src/chains/near/index.ts +393 -0
  77. package/src/chains/near/native-transfer.ts +658 -0
  78. package/src/chains/near/nep141.ts +775 -0
  79. package/src/chains/near/privacy-adapter.ts +889 -0
  80. package/src/chains/near/resolver.ts +971 -0
  81. package/src/chains/near/rpc.ts +1016 -0
  82. package/src/chains/near/stealth.ts +419 -0
  83. package/src/chains/near/types.ts +317 -0
  84. package/src/chains/near/viewing-key.ts +876 -0
  85. package/src/chains/solana/anchor-transfer.ts +386 -0
  86. package/src/chains/solana/commitment.ts +577 -0
  87. package/src/chains/solana/constants.ts +126 -12
  88. package/src/chains/solana/ephemeral-keys.ts +543 -0
  89. package/src/chains/solana/index.ts +252 -1
  90. package/src/chains/solana/key-derivation.ts +418 -0
  91. package/src/chains/solana/kit-compat.ts +334 -0
  92. package/src/chains/solana/optimizations.ts +560 -0
  93. package/src/chains/solana/privacy-adapter.ts +605 -0
  94. package/src/chains/solana/providers/generic.ts +47 -6
  95. package/src/chains/solana/providers/helius-enhanced-types.ts +336 -0
  96. package/src/chains/solana/providers/helius-enhanced.ts +623 -0
  97. package/src/chains/solana/providers/helius.ts +186 -33
  98. package/src/chains/solana/providers/index.ts +31 -0
  99. package/src/chains/solana/providers/interface.ts +61 -18
  100. package/src/chains/solana/providers/quicknode.ts +409 -0
  101. package/src/chains/solana/providers/triton.ts +426 -0
  102. package/src/chains/solana/providers/webhook.ts +338 -67
  103. package/src/chains/solana/rpc-client.ts +1150 -0
  104. package/src/chains/solana/scan.ts +83 -66
  105. package/src/chains/solana/sol-transfer.ts +732 -0
  106. package/src/chains/solana/spl-transfer.ts +886 -0
  107. package/src/chains/solana/stealth-scanner.ts +703 -0
  108. package/src/chains/solana/sunspot-verifier.ts +453 -0
  109. package/src/chains/solana/transaction-builder.ts +755 -0
  110. package/src/chains/solana/transfer.ts +74 -5
  111. package/src/chains/solana/types.ts +57 -6
  112. package/src/chains/solana/utils.ts +110 -0
  113. package/src/chains/solana/viewing-key.ts +807 -0
  114. package/src/compliance/fireblocks.ts +921 -0
  115. package/src/compliance/index.ts +23 -0
  116. package/src/compliance/range-sas.ts +398 -33
  117. package/src/config/endpoints.ts +100 -0
  118. package/src/crypto.ts +11 -8
  119. package/src/errors.ts +82 -0
  120. package/src/evm/erc4337-relayer.ts +830 -0
  121. package/src/evm/index.ts +47 -0
  122. package/src/fees/calculator.ts +396 -0
  123. package/src/fees/index.ts +87 -0
  124. package/src/fees/near-contract.ts +429 -0
  125. package/src/fees/types.ts +268 -0
  126. package/src/index.ts +686 -1
  127. package/src/intent.ts +6 -3
  128. package/src/logger.ts +324 -0
  129. package/src/network/index.ts +80 -0
  130. package/src/network/proxy.ts +691 -0
  131. package/src/optimizations/index.ts +541 -0
  132. package/src/oracle/types.ts +1 -0
  133. package/src/privacy-backends/arcium-types.ts +727 -0
  134. package/src/privacy-backends/arcium.ts +719 -0
  135. package/src/privacy-backends/combined-privacy.ts +866 -0
  136. package/src/privacy-backends/cspl-token.ts +595 -0
  137. package/src/privacy-backends/cspl-types.ts +512 -0
  138. package/src/privacy-backends/cspl.ts +907 -0
  139. package/src/privacy-backends/health.ts +488 -0
  140. package/src/privacy-backends/inco-types.ts +323 -0
  141. package/src/privacy-backends/inco.ts +616 -0
  142. package/src/privacy-backends/index.ts +254 -4
  143. package/src/privacy-backends/interface.ts +649 -6
  144. package/src/privacy-backends/lru-cache.ts +343 -0
  145. package/src/privacy-backends/magicblock.ts +458 -0
  146. package/src/privacy-backends/mock.ts +258 -0
  147. package/src/privacy-backends/privacycash.ts +13 -17
  148. package/src/privacy-backends/private-swap.ts +570 -0
  149. package/src/privacy-backends/rate-limiter.ts +683 -0
  150. package/src/privacy-backends/registry.ts +414 -2
  151. package/src/privacy-backends/router.ts +283 -3
  152. package/src/privacy-backends/shadowwire.ts +449 -0
  153. package/src/privacy-backends/sip-native.ts +3 -0
  154. package/src/privacy-logger.ts +191 -0
  155. package/src/production-safety.ts +373 -0
  156. package/src/proofs/aggregator.ts +1029 -0
  157. package/src/proofs/browser-composer.ts +1150 -0
  158. package/src/proofs/browser.ts +113 -25
  159. package/src/proofs/cache/index.ts +127 -0
  160. package/src/proofs/cache/interface.ts +545 -0
  161. package/src/proofs/cache/key-generator.ts +188 -0
  162. package/src/proofs/cache/lru-cache.ts +481 -0
  163. package/src/proofs/cache/multi-tier-cache.ts +575 -0
  164. package/src/proofs/cache/persistent-cache.ts +788 -0
  165. package/src/proofs/compliance-proof.ts +872 -0
  166. package/src/proofs/composer/base.ts +923 -0
  167. package/src/proofs/composer/index.ts +25 -0
  168. package/src/proofs/composer/interface.ts +518 -0
  169. package/src/proofs/composer/types.ts +383 -0
  170. package/src/proofs/converters/halo2.ts +452 -0
  171. package/src/proofs/converters/index.ts +208 -0
  172. package/src/proofs/converters/interface.ts +363 -0
  173. package/src/proofs/converters/kimchi.ts +462 -0
  174. package/src/proofs/converters/noir.ts +451 -0
  175. package/src/proofs/fallback.ts +888 -0
  176. package/src/proofs/halo2.ts +42 -0
  177. package/src/proofs/index.ts +471 -0
  178. package/src/proofs/interface.ts +13 -0
  179. package/src/proofs/kimchi.ts +42 -0
  180. package/src/proofs/lazy.ts +1004 -0
  181. package/src/proofs/mock.ts +25 -1
  182. package/src/proofs/noir.ts +110 -29
  183. package/src/proofs/orchestrator.ts +960 -0
  184. package/src/proofs/parallel/concurrency.ts +297 -0
  185. package/src/proofs/parallel/dependency-graph.ts +602 -0
  186. package/src/proofs/parallel/executor.ts +420 -0
  187. package/src/proofs/parallel/index.ts +131 -0
  188. package/src/proofs/parallel/interface.ts +685 -0
  189. package/src/proofs/parallel/worker-pool.ts +644 -0
  190. package/src/proofs/providers/halo2.ts +560 -0
  191. package/src/proofs/providers/index.ts +34 -0
  192. package/src/proofs/providers/kimchi.ts +641 -0
  193. package/src/proofs/validator.ts +881 -0
  194. package/src/proofs/verifier.ts +867 -0
  195. package/src/quantum/index.ts +112 -0
  196. package/src/quantum/winternitz-vault.ts +639 -0
  197. package/src/quantum/wots.ts +611 -0
  198. package/src/settlement/backends/direct-chain.ts +1 -0
  199. package/src/settlement/index.ts +9 -0
  200. package/src/settlement/router.ts +732 -46
  201. package/src/solana/index.ts +72 -0
  202. package/src/solana/jito-relayer.ts +687 -0
  203. package/src/solana/noir-verifier-types.ts +430 -0
  204. package/src/solana/noir-verifier.ts +816 -0
  205. package/src/stealth/address-derivation.ts +193 -0
  206. package/src/stealth/ed25519.ts +431 -0
  207. package/src/stealth/index.ts +233 -0
  208. package/src/stealth/meta-address.ts +221 -0
  209. package/src/stealth/secp256k1.ts +368 -0
  210. package/src/stealth/utils.ts +194 -0
  211. package/src/stealth.ts +50 -1504
  212. package/src/sync/index.ts +106 -0
  213. package/src/sync/manager.ts +504 -0
  214. package/src/sync/mock-provider.ts +318 -0
  215. package/src/sync/oblivious.ts +625 -0
  216. package/src/tokens/index.ts +15 -0
  217. package/src/tokens/registry.ts +301 -0
  218. package/src/utils/deprecation.ts +94 -0
  219. package/src/utils/index.ts +9 -0
  220. package/src/wallet/ethereum/index.ts +68 -0
  221. package/src/wallet/ethereum/metamask-privacy.ts +420 -0
  222. package/src/wallet/ethereum/multi-wallet.ts +646 -0
  223. package/src/wallet/ethereum/privacy-adapter.ts +700 -0
  224. package/src/wallet/ethereum/types.ts +3 -1
  225. package/src/wallet/ethereum/walletconnect-adapter.ts +675 -0
  226. package/src/wallet/hardware/index.ts +10 -0
  227. package/src/wallet/hardware/ledger-privacy.ts +414 -0
  228. package/src/wallet/index.ts +71 -0
  229. package/src/wallet/near/adapter.ts +626 -0
  230. package/src/wallet/near/index.ts +86 -0
  231. package/src/wallet/near/meteor-wallet.ts +1153 -0
  232. package/src/wallet/near/my-near-wallet.ts +790 -0
  233. package/src/wallet/near/wallet-selector.ts +702 -0
  234. package/src/wallet/solana/adapter.ts +6 -4
  235. package/src/wallet/solana/index.ts +13 -0
  236. package/src/wallet/solana/privacy-adapter.ts +567 -0
  237. package/src/wallet/sui/types.ts +6 -4
  238. package/src/zcash/rpc-client.ts +13 -6
  239. package/dist/chunk-2XIVXWHA.mjs +0 -1930
  240. package/dist/chunk-3INS3PR5.mjs +0 -884
  241. package/dist/chunk-3OVABDRH.mjs +0 -17096
  242. package/dist/chunk-7RFRWDCW.mjs +0 -1504
  243. package/dist/chunk-DLDWZFYC.mjs +0 -1495
  244. package/dist/chunk-E6SZWREQ.mjs +0 -57
  245. package/dist/chunk-F6F73W35.mjs +0 -16166
  246. package/dist/chunk-G33LB27A.mjs +0 -16166
  247. package/dist/chunk-HGU6HZRC.mjs +0 -231
  248. package/dist/chunk-L2K34JCU.mjs +0 -1496
  249. package/dist/chunk-OFDBEIEK.mjs +0 -16166
  250. package/dist/chunk-SF7YSLF5.mjs +0 -1515
  251. package/dist/chunk-SN4ZDTVW.mjs +0 -16166
  252. package/dist/chunk-WWUSGOXE.mjs +0 -17129
  253. package/dist/constants-VOI7BSLK.mjs +0 -27
  254. package/dist/index-B71aXVzk.d.ts +0 -13264
  255. package/dist/index-BYZbDjal.d.ts +0 -11390
  256. package/dist/index-CHB3KuOB.d.mts +0 -11859
  257. package/dist/index-CzWPI6Le.d.ts +0 -11859
  258. package/dist/index-pOIIuwfV.d.mts +0 -13264
  259. package/dist/index-xbWjohNq.d.mts +0 -11390
  260. package/dist/solana-4O4K45VU.mjs +0 -46
  261. package/dist/solana-5EMCTPTS.mjs +0 -46
  262. package/dist/solana-NDABAZ6P.mjs +0 -56
  263. package/dist/solana-Q4NAVBTS.mjs +0 -46
  264. package/dist/solana-ZYO63LY5.mjs +0 -46
@@ -0,0 +1,575 @@
1
+ /**
2
+ * Multi-Tier Cache Implementation for Proof Caching
3
+ *
4
+ * @module proofs/cache/multi-tier-cache
5
+ * @description Combines in-memory LRU and persistent caching with write/read-through
6
+ *
7
+ * M20-13: Implement proof caching layer (#313)
8
+ */
9
+
10
+ import type { SingleProof } from '@sip-protocol/types'
11
+ import type {
12
+ CacheKey,
13
+ CacheKeyComponents,
14
+ CacheLookupResult,
15
+ ProofCacheStats,
16
+ CacheEvent,
17
+ CacheEventListener,
18
+ MultiTierCacheConfig,
19
+ CacheWarmingConfig,
20
+ WarmingResult,
21
+ InvalidationRule,
22
+ ILRUCache,
23
+ IPersistentCache,
24
+ IMultiTierCache,
25
+ } from './interface'
26
+ import { DEFAULT_MULTI_TIER_CONFIG, DEFAULT_WARMING_CONFIG } from './interface'
27
+ import { LRUCache } from './lru-cache'
28
+ import { createPersistentCache } from './persistent-cache'
29
+
30
+ // ─── Multi-Tier Cache Implementation ─────────────────────────────────────────
31
+
32
+ /**
33
+ * Multi-tier cache combining in-memory LRU with optional persistent storage
34
+ */
35
+ export class MultiTierCache<T = SingleProof> implements IMultiTierCache<T> {
36
+ private readonly config: MultiTierCacheConfig
37
+ private readonly memoryCache: ILRUCache<T>
38
+ private readonly persistentCache: IPersistentCache<T> | null = null
39
+ private readonly listeners: Set<CacheEventListener> = new Set()
40
+
41
+ private warmingConfig: CacheWarmingConfig = DEFAULT_WARMING_CONFIG
42
+ private warmingInterval: ReturnType<typeof setInterval> | null = null
43
+ private warmingGenerator: ((key: CacheKeyComponents) => Promise<T>) | null = null
44
+
45
+ // Track access patterns for warming predictions
46
+ private accessHistory: Array<{ key: string; timestamp: number }> = []
47
+ private readonly maxHistorySize = 1000
48
+
49
+ constructor(
50
+ config: Partial<MultiTierCacheConfig> = {},
51
+ persistentConfig?: Parameters<typeof createPersistentCache>[0]
52
+ ) {
53
+ this.config = { ...DEFAULT_MULTI_TIER_CONFIG, ...config }
54
+
55
+ // Initialize memory cache
56
+ this.memoryCache = new LRUCache<T>(this.config.memory)
57
+
58
+ // Initialize persistent cache if configured
59
+ if (this.config.persistent || persistentConfig) {
60
+ try {
61
+ this.persistentCache = createPersistentCache<T>(
62
+ persistentConfig ?? this.config.persistent
63
+ )
64
+ } catch {
65
+ // Persistent cache not available in this environment
66
+ this.persistentCache = null
67
+ }
68
+ }
69
+
70
+ // Forward events from memory cache
71
+ this.memoryCache.addEventListener((event) => {
72
+ this.emitEvent(event)
73
+ })
74
+
75
+ // Forward events from persistent cache
76
+ if (this.persistentCache) {
77
+ this.persistentCache.addEventListener((event) => {
78
+ this.emitEvent({ ...event, data: { ...event.data, tier: 'persistent' } })
79
+ })
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Initialize the multi-tier cache
85
+ */
86
+ async initialize(): Promise<void> {
87
+ if (this.persistentCache) {
88
+ await this.persistentCache.initialize()
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Get an entry from the cache
94
+ */
95
+ async get(key: CacheKey | string): Promise<CacheLookupResult<T>> {
96
+ const keyStr = typeof key === 'string' ? key : key.key
97
+
98
+ // Track access for warming predictions
99
+ this.trackAccess(keyStr)
100
+
101
+ // Try memory cache first
102
+ const memoryResult = await this.memoryCache.get(key)
103
+ if (memoryResult.hit) {
104
+ return memoryResult
105
+ }
106
+
107
+ // Try persistent cache if read-through enabled
108
+ if (this.config.readThrough && this.persistentCache) {
109
+ const persistentResult = await this.persistentCache.get(key)
110
+
111
+ if (persistentResult.hit && persistentResult.entry) {
112
+ // Promote to memory cache if configured
113
+ if (this.config.promoteOnAccess) {
114
+ await this.memoryCache.set(
115
+ key,
116
+ persistentResult.entry.value,
117
+ persistentResult.entry.metadata.ttlMs
118
+ )
119
+ }
120
+
121
+ return persistentResult
122
+ }
123
+ }
124
+
125
+ return {
126
+ hit: false,
127
+ missReason: 'not_found',
128
+ lookupTimeMs: memoryResult.lookupTimeMs,
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Set an entry in the cache
134
+ */
135
+ async set(key: CacheKey | string, value: T, ttlMs?: number): Promise<boolean> {
136
+ // Always set in memory cache
137
+ const memorySuccess = await this.memoryCache.set(key, value, ttlMs)
138
+
139
+ // Write-through to persistent cache if enabled
140
+ if (this.config.writeThrough && this.persistentCache) {
141
+ await this.persistentCache.set(key, value, ttlMs)
142
+ }
143
+
144
+ return memorySuccess
145
+ }
146
+
147
+ /**
148
+ * Delete an entry from the cache
149
+ */
150
+ async delete(key: CacheKey | string): Promise<boolean> {
151
+ const memoryDeleted = await this.memoryCache.delete(key)
152
+
153
+ // Also delete from persistent cache
154
+ if (this.persistentCache) {
155
+ await this.persistentCache.delete(key)
156
+ }
157
+
158
+ return memoryDeleted
159
+ }
160
+
161
+ /**
162
+ * Check if an entry exists
163
+ */
164
+ async has(key: CacheKey | string): Promise<boolean> {
165
+ // Check memory first
166
+ if (await this.memoryCache.has(key)) {
167
+ return true
168
+ }
169
+
170
+ // Check persistent
171
+ if (this.persistentCache) {
172
+ return this.persistentCache.has(key)
173
+ }
174
+
175
+ return false
176
+ }
177
+
178
+ /**
179
+ * Clear all entries
180
+ */
181
+ async clear(): Promise<void> {
182
+ await this.memoryCache.clear()
183
+
184
+ if (this.persistentCache) {
185
+ await this.persistentCache.clear()
186
+ }
187
+ }
188
+
189
+ /**
190
+ * Get cache statistics (combined from both tiers)
191
+ */
192
+ getStats(): ProofCacheStats {
193
+ const memoryStats = this.memoryCache.getStats()
194
+
195
+ if (!this.persistentCache) {
196
+ return memoryStats
197
+ }
198
+
199
+ const persistentStats = this.persistentCache.getStats()
200
+
201
+ // Combine statistics
202
+ return {
203
+ totalLookups: memoryStats.totalLookups, // Memory handles all lookups
204
+ hits: memoryStats.hits + persistentStats.hits,
205
+ misses: memoryStats.misses - persistentStats.hits, // Adjust for persistent hits
206
+ hitRate:
207
+ memoryStats.totalLookups > 0
208
+ ? (memoryStats.hits + persistentStats.hits) / memoryStats.totalLookups
209
+ : 0,
210
+ entryCount: memoryStats.entryCount, // Memory is the authoritative count
211
+ sizeBytes: memoryStats.sizeBytes,
212
+ maxSizeBytes: memoryStats.maxSizeBytes,
213
+ evictions: memoryStats.evictions,
214
+ expirations: memoryStats.expirations + persistentStats.expirations,
215
+ avgLookupTimeMs: memoryStats.avgLookupTimeMs,
216
+ avgEntryAgeMs: memoryStats.avgEntryAgeMs,
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Get all keys matching a pattern
222
+ */
223
+ async keys(pattern?: string): Promise<string[]> {
224
+ const memoryKeys = await this.memoryCache.keys(pattern)
225
+ const persistentKeys = this.persistentCache
226
+ ? await this.persistentCache.keys(pattern)
227
+ : []
228
+
229
+ // Combine and deduplicate
230
+ const allKeys = new Set([...memoryKeys, ...persistentKeys])
231
+ return Array.from(allKeys)
232
+ }
233
+
234
+ addEventListener(listener: CacheEventListener): void {
235
+ this.listeners.add(listener)
236
+ }
237
+
238
+ removeEventListener(listener: CacheEventListener): void {
239
+ this.listeners.delete(listener)
240
+ }
241
+
242
+ /**
243
+ * Get the memory cache tier
244
+ */
245
+ getMemoryCache(): ILRUCache<T> {
246
+ return this.memoryCache
247
+ }
248
+
249
+ /**
250
+ * Get the persistent cache tier (if available)
251
+ */
252
+ getPersistentCache(): IPersistentCache<T> | null {
253
+ return this.persistentCache
254
+ }
255
+
256
+ /**
257
+ * Warm the cache with specific keys
258
+ */
259
+ async warm(keys: CacheKeyComponents[]): Promise<WarmingResult> {
260
+ const startTime = Date.now()
261
+ let warmed = 0
262
+ let failed = 0
263
+ const warmedKeys: string[] = []
264
+
265
+ for (const keyComponents of keys) {
266
+ try {
267
+ if (this.warmingGenerator) {
268
+ const value = await this.warmingGenerator(keyComponents)
269
+ const key = this.componentsToKey(keyComponents)
270
+
271
+ await this.set(key, value)
272
+ warmed++
273
+ warmedKeys.push(key)
274
+ this.emitEvent({ type: 'warm', key, timestamp: Date.now() })
275
+ }
276
+ } catch {
277
+ failed++
278
+ }
279
+ }
280
+
281
+ return {
282
+ warmed,
283
+ failed,
284
+ timeMs: Date.now() - startTime,
285
+ keys: warmedKeys,
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Start automatic cache warming
291
+ */
292
+ startWarming(
293
+ config?: CacheWarmingConfig,
294
+ generator?: (key: CacheKeyComponents) => Promise<T>
295
+ ): void {
296
+ this.stopWarming()
297
+
298
+ this.warmingConfig = { ...DEFAULT_WARMING_CONFIG, ...config }
299
+ this.warmingGenerator = generator ?? null
300
+
301
+ if (!this.warmingConfig.enabled || !this.warmingGenerator) {
302
+ return
303
+ }
304
+
305
+ // Warm on startup
306
+ if (this.warmingConfig.warmOnStartup.length > 0) {
307
+ this.warm(this.warmingConfig.warmOnStartup).catch(() => {})
308
+ }
309
+
310
+ // Start periodic warming
311
+ this.warmingInterval = setInterval(() => {
312
+ this.performPredictiveWarming().catch(() => {})
313
+ }, this.warmingConfig.warmIntervalMs)
314
+ }
315
+
316
+ /**
317
+ * Stop automatic cache warming
318
+ */
319
+ stopWarming(): void {
320
+ if (this.warmingInterval) {
321
+ clearInterval(this.warmingInterval)
322
+ this.warmingInterval = null
323
+ }
324
+ }
325
+
326
+ /**
327
+ * Apply invalidation rules
328
+ */
329
+ async invalidate(rules: InvalidationRule[]): Promise<number> {
330
+ // Sort rules by priority
331
+ const sortedRules = [...rules].sort((a, b) => b.priority - a.priority)
332
+ let invalidated = 0
333
+
334
+ for (const rule of sortedRules) {
335
+ switch (rule.strategy) {
336
+ case 'ttl':
337
+ invalidated += await this.invalidateByTTL(rule)
338
+ break
339
+ case 'lru':
340
+ invalidated += await this.invalidateByLRU(rule)
341
+ break
342
+ case 'size':
343
+ invalidated += await this.invalidateBySize(rule)
344
+ break
345
+ case 'manual':
346
+ if (rule.pattern) {
347
+ invalidated += await this.invalidateByPattern(rule.pattern)
348
+ }
349
+ break
350
+ default:
351
+ // FIFO, LFU not implemented yet
352
+ break
353
+ }
354
+ }
355
+
356
+ return invalidated
357
+ }
358
+
359
+ /**
360
+ * Dispose of the cache
361
+ */
362
+ async dispose(): Promise<void> {
363
+ this.stopWarming()
364
+
365
+ if (this.memoryCache instanceof LRUCache) {
366
+ this.memoryCache.dispose()
367
+ }
368
+
369
+ if (this.persistentCache) {
370
+ await this.persistentCache.close()
371
+ }
372
+
373
+ this.listeners.clear()
374
+ }
375
+
376
+ // ─── Private Methods ─────────────────────────────────────────────────────────
377
+
378
+ private trackAccess(key: string): void {
379
+ this.accessHistory.push({ key, timestamp: Date.now() })
380
+
381
+ // Trim history
382
+ if (this.accessHistory.length > this.maxHistorySize) {
383
+ this.accessHistory = this.accessHistory.slice(-this.maxHistorySize)
384
+ }
385
+ }
386
+
387
+ private async performPredictiveWarming(): Promise<void> {
388
+ if (!this.warmingGenerator) return
389
+
390
+ const keysToWarm: CacheKeyComponents[] = []
391
+ const maxEntries = this.warmingConfig.maxEntriesPerWarm
392
+
393
+ switch (this.warmingConfig.predictionModel) {
394
+ case 'recent':
395
+ // Warm recently accessed keys that might have been evicted
396
+ keysToWarm.push(...this.getRecentKeys(maxEntries))
397
+ break
398
+ case 'frequent':
399
+ // Warm frequently accessed keys
400
+ keysToWarm.push(...this.getFrequentKeys(maxEntries))
401
+ break
402
+ case 'pattern':
403
+ // Warm based on access patterns (time-of-day, etc.)
404
+ keysToWarm.push(...this.getPatternBasedKeys(maxEntries))
405
+ break
406
+ }
407
+
408
+ if (keysToWarm.length > 0) {
409
+ await this.warm(keysToWarm)
410
+ }
411
+ }
412
+
413
+ private getRecentKeys(limit: number): CacheKeyComponents[] {
414
+ // Get recent unique keys that are not in memory cache
415
+ const recentKeys = new Map<string, CacheKeyComponents>()
416
+
417
+ for (let i = this.accessHistory.length - 1; i >= 0 && recentKeys.size < limit * 2; i--) {
418
+ const access = this.accessHistory[i]
419
+ if (!recentKeys.has(access.key)) {
420
+ recentKeys.set(access.key, this.keyToComponents(access.key))
421
+ }
422
+ }
423
+
424
+ return Array.from(recentKeys.values()).slice(0, limit)
425
+ }
426
+
427
+ private getFrequentKeys(limit: number): CacheKeyComponents[] {
428
+ // Count frequency of each key
429
+ const frequency = new Map<string, number>()
430
+
431
+ for (const access of this.accessHistory) {
432
+ frequency.set(access.key, (frequency.get(access.key) ?? 0) + 1)
433
+ }
434
+
435
+ // Sort by frequency and return top keys
436
+ const sorted = Array.from(frequency.entries())
437
+ .sort((a, b) => b[1] - a[1])
438
+ .slice(0, limit)
439
+
440
+ return sorted.map(([key]) => this.keyToComponents(key))
441
+ }
442
+
443
+ private getPatternBasedKeys(_limit: number): CacheKeyComponents[] {
444
+ // TODO: Implement time-based patterns (e.g., keys accessed at similar times)
445
+ return []
446
+ }
447
+
448
+ private keyToComponents(key: string): CacheKeyComponents {
449
+ // Parse key back to components (simplified)
450
+ const parts = key.split(':')
451
+ return {
452
+ system: (parts[2] ?? 'noir') as CacheKeyComponents['system'],
453
+ circuitId: parts[3] ?? 'unknown',
454
+ privateInputsHash: parts[4] ?? '',
455
+ publicInputsHash: parts[5] ?? '',
456
+ version: parts[6],
457
+ }
458
+ }
459
+
460
+ private componentsToKey(components: CacheKeyComponents): string {
461
+ const parts = [
462
+ 'sip-proof',
463
+ 'v1',
464
+ components.system,
465
+ components.circuitId,
466
+ components.privateInputsHash,
467
+ components.publicInputsHash,
468
+ ]
469
+
470
+ if (components.version) {
471
+ parts.push(components.version)
472
+ }
473
+
474
+ return parts.join(':')
475
+ }
476
+
477
+ private async invalidateByTTL(rule: InvalidationRule): Promise<number> {
478
+ const now = Date.now()
479
+ const keys = await this.keys(rule.pattern)
480
+ let invalidated = 0
481
+
482
+ for (const key of keys) {
483
+ const result = await this.memoryCache.get(key)
484
+ if (
485
+ result.hit &&
486
+ result.entry &&
487
+ rule.ttlMs &&
488
+ now - result.entry.metadata.createdAt > rule.ttlMs
489
+ ) {
490
+ await this.delete(key)
491
+ invalidated++
492
+ }
493
+ }
494
+
495
+ return invalidated
496
+ }
497
+
498
+ private async invalidateByLRU(rule: InvalidationRule): Promise<number> {
499
+ if (!(this.memoryCache instanceof LRUCache)) {
500
+ return 0
501
+ }
502
+
503
+ const entries = this.memoryCache.getEntriesLRU()
504
+ const matching = rule.pattern
505
+ ? entries.filter((e) => this.matchesPattern(e.key.key, rule.pattern!))
506
+ : entries
507
+
508
+ // Evict the least recently used half of matching entries
509
+ const toEvict = Math.floor(matching.length / 2)
510
+ let invalidated = 0
511
+
512
+ for (let i = matching.length - 1; i >= matching.length - toEvict && i >= 0; i--) {
513
+ await this.delete(matching[i].key.key)
514
+ invalidated++
515
+ }
516
+
517
+ return invalidated
518
+ }
519
+
520
+ private async invalidateBySize(_rule: InvalidationRule): Promise<number> {
521
+ // Evict until under target size
522
+ const targetSize = Math.floor(this.config.memory.maxSizeBytes * 0.7)
523
+ let invalidated = 0
524
+
525
+ while (this.memoryCache.getSizeBytes() > targetSize) {
526
+ const evicted = this.memoryCache.evict(1)
527
+ if (evicted === 0) break
528
+ invalidated += evicted
529
+ }
530
+
531
+ return invalidated
532
+ }
533
+
534
+ private async invalidateByPattern(pattern: string): Promise<number> {
535
+ const keys = await this.keys(pattern)
536
+ let invalidated = 0
537
+
538
+ for (const key of keys) {
539
+ await this.delete(key)
540
+ invalidated++
541
+ }
542
+
543
+ return invalidated
544
+ }
545
+
546
+ private matchesPattern(key: string, pattern: string): boolean {
547
+ const regexPattern = pattern
548
+ .replace(/[.+^${}()|[\]\\]/g, '\\$&')
549
+ .replace(/\*/g, '.*')
550
+ .replace(/\?/g, '.')
551
+
552
+ const regex = new RegExp(`^${regexPattern}$`)
553
+ return regex.test(key)
554
+ }
555
+
556
+ private emitEvent(event: CacheEvent): void {
557
+ for (const listener of this.listeners) {
558
+ try {
559
+ listener(event)
560
+ } catch {
561
+ // Ignore listener errors
562
+ }
563
+ }
564
+ }
565
+ }
566
+
567
+ /**
568
+ * Create a multi-tier cache instance
569
+ */
570
+ export function createMultiTierCache<T = SingleProof>(
571
+ config?: Partial<MultiTierCacheConfig>,
572
+ persistentConfig?: Parameters<typeof createPersistentCache>[0]
573
+ ): IMultiTierCache<T> {
574
+ return new MultiTierCache<T>(config, persistentConfig)
575
+ }