@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,318 @@
1
+ /**
2
+ * Mock Oblivious Sync Provider
3
+ *
4
+ * Reference implementation for testing oblivious sync.
5
+ * NOT for production use - provides no actual blockchain data.
6
+ *
7
+ * @module sync/mock-provider
8
+ */
9
+
10
+ import type { HexString } from '@sip-protocol/types'
11
+ import { bytesToHex, randomBytes } from '@noble/hashes/utils'
12
+ import type {
13
+ ObliviousSyncProvider,
14
+ ChainId,
15
+ BlockRange,
16
+ EncryptedNote,
17
+ ObliviousNullifier,
18
+ MerkleProof,
19
+ ObliviousSyncQuery,
20
+ ObliviousSyncResponse,
21
+ SyncServiceHealth,
22
+ } from './oblivious'
23
+
24
+ /**
25
+ * Configuration for mock provider
26
+ */
27
+ export interface MockSyncProviderConfig {
28
+ /** Chains to simulate */
29
+ chains: ChainId[]
30
+ /** Simulated latency (ms) */
31
+ latencyMs: number
32
+ /** Probability of returning notes (0-1) */
33
+ noteProbability: number
34
+ /** Simulated block height */
35
+ blockHeight: bigint
36
+ /** Fail probability for testing error handling */
37
+ failProbability: number
38
+ }
39
+
40
+ /**
41
+ * Default mock configuration
42
+ */
43
+ export const DEFAULT_MOCK_CONFIG: MockSyncProviderConfig = {
44
+ chains: ['ethereum', 'solana', 'near'],
45
+ latencyMs: 100,
46
+ noteProbability: 0.3,
47
+ blockHeight: 10_000n, // Reasonable default for testing (not 1M blocks)
48
+ failProbability: 0,
49
+ }
50
+
51
+ /**
52
+ * Mock Oblivious Sync Provider
53
+ *
54
+ * Simulates an oblivious sync service for testing.
55
+ * Demonstrates the interface contract without real blockchain data.
56
+ */
57
+ export class MockObliviousSyncProvider implements ObliviousSyncProvider {
58
+ readonly name = 'mock-oblivious-sync'
59
+ readonly supportedChains: ChainId[]
60
+
61
+ private config: MockSyncProviderConfig
62
+ private initialized = false
63
+ private subscriptions = new Map<string, Set<(notes: EncryptedNote[]) => void>>()
64
+ private mockNullifierSpentStatus = new Map<HexString, boolean>()
65
+
66
+ constructor(config: Partial<MockSyncProviderConfig> = {}) {
67
+ this.config = { ...DEFAULT_MOCK_CONFIG, ...config }
68
+ this.supportedChains = this.config.chains
69
+ }
70
+
71
+ async initialize(): Promise<void> {
72
+ await this.simulateLatency()
73
+ this.initialized = true
74
+ }
75
+
76
+ async getHealth(chainId: ChainId): Promise<SyncServiceHealth> {
77
+ this.checkInitialized()
78
+ await this.simulateLatency()
79
+
80
+ if (!this.supportedChains.includes(chainId)) {
81
+ return {
82
+ available: false,
83
+ currentHeight: 0n,
84
+ chainId,
85
+ latencyMs: 0,
86
+ }
87
+ }
88
+
89
+ return {
90
+ available: true,
91
+ currentHeight: this.config.blockHeight,
92
+ chainId,
93
+ latencyMs: this.config.latencyMs,
94
+ lastSuccessfulSync: Date.now(),
95
+ }
96
+ }
97
+
98
+ async scanForNotes(
99
+ _viewingKeyPublic: HexString,
100
+ blockRange: BlockRange
101
+ ): Promise<EncryptedNote[]> {
102
+ this.checkInitialized()
103
+ await this.simulateLatency()
104
+ this.maybeSimulateFail()
105
+
106
+ if (!this.supportedChains.includes(blockRange.chainId)) {
107
+ throw new Error(`Chain ${blockRange.chainId} not supported`)
108
+ }
109
+
110
+ // Simulate finding some notes probabilistically
111
+ const notes: EncryptedNote[] = []
112
+ const numBlocks = Number(blockRange.endBlock - blockRange.startBlock)
113
+ const expectedNotes = Math.floor(numBlocks * this.config.noteProbability)
114
+
115
+ for (let i = 0; i < expectedNotes; i++) {
116
+ notes.push(this.generateMockNote(blockRange))
117
+ }
118
+
119
+ return notes
120
+ }
121
+
122
+ async checkNullifiers(
123
+ nullifiers: ObliviousNullifier[]
124
+ ): Promise<Map<HexString, boolean>> {
125
+ this.checkInitialized()
126
+ await this.simulateLatency()
127
+ this.maybeSimulateFail()
128
+
129
+ const results = new Map<HexString, boolean>()
130
+
131
+ for (const nullifier of nullifiers) {
132
+ // Check mock spent status, default to not spent
133
+ const spent = this.mockNullifierSpentStatus.get(nullifier.nullifier) ?? false
134
+ results.set(nullifier.nullifier, spent)
135
+ }
136
+
137
+ return results
138
+ }
139
+
140
+ async getMerkleProofs(
141
+ commitments: HexString[],
142
+ _chainId: ChainId
143
+ ): Promise<Map<HexString, MerkleProof>> {
144
+ this.checkInitialized()
145
+ await this.simulateLatency()
146
+ this.maybeSimulateFail()
147
+
148
+ const proofs = new Map<HexString, MerkleProof>()
149
+
150
+ for (const commitment of commitments) {
151
+ proofs.set(commitment, this.generateMockMerkleProof(commitment))
152
+ }
153
+
154
+ return proofs
155
+ }
156
+
157
+ async executeObliviousQuery(
158
+ query: ObliviousSyncQuery
159
+ ): Promise<ObliviousSyncResponse> {
160
+ this.checkInitialized()
161
+ await this.simulateLatency()
162
+ this.maybeSimulateFail()
163
+
164
+ // Simulate scanning for notes
165
+ const notes = await this.scanForNotes(
166
+ '0x00' as HexString, // Query is encrypted, we can't read it
167
+ query.blockRange
168
+ )
169
+
170
+ // Get merkle proofs for found notes
171
+ const merkleProofs: MerkleProof[] = []
172
+ for (const note of notes) {
173
+ merkleProofs.push(this.generateMockMerkleProof(note.commitment))
174
+ }
175
+
176
+ return {
177
+ encryptedNotes: notes,
178
+ merkleProofs,
179
+ syncHeight: this.config.blockHeight,
180
+ timestamp: Date.now(),
181
+ queryHash: `0x${bytesToHex(randomBytes(32))}` as HexString,
182
+ }
183
+ }
184
+
185
+ async getCurrentHeight(chainId: ChainId): Promise<bigint> {
186
+ this.checkInitialized()
187
+ await this.simulateLatency()
188
+
189
+ if (!this.supportedChains.includes(chainId)) {
190
+ throw new Error(`Chain ${chainId} not supported`)
191
+ }
192
+
193
+ return this.config.blockHeight
194
+ }
195
+
196
+ subscribeToNotes(
197
+ viewingKeyPublic: HexString,
198
+ chainId: ChainId,
199
+ callback: (notes: EncryptedNote[]) => void
200
+ ): () => void {
201
+ this.checkInitialized()
202
+
203
+ const key = `${chainId}:${viewingKeyPublic}`
204
+ if (!this.subscriptions.has(key)) {
205
+ this.subscriptions.set(key, new Set())
206
+ }
207
+ this.subscriptions.get(key)!.add(callback)
208
+
209
+ // Return unsubscribe function
210
+ return () => {
211
+ const subs = this.subscriptions.get(key)
212
+ if (subs) {
213
+ subs.delete(callback)
214
+ if (subs.size === 0) {
215
+ this.subscriptions.delete(key)
216
+ }
217
+ }
218
+ }
219
+ }
220
+
221
+ async shutdown(): Promise<void> {
222
+ this.subscriptions.clear()
223
+ this.initialized = false
224
+ }
225
+
226
+ // ─── Test Helpers ─────────────────────────────────────────────────────────────
227
+
228
+ /**
229
+ * Simulate a nullifier being spent (for testing)
230
+ */
231
+ markNullifierSpent(nullifier: HexString): void {
232
+ this.mockNullifierSpentStatus.set(nullifier, true)
233
+ }
234
+
235
+ /**
236
+ * Simulate new notes arriving (for testing subscriptions)
237
+ */
238
+ simulateNewNotes(chainId: ChainId, viewingKeyPublic: HexString): void {
239
+ const key = `${chainId}:${viewingKeyPublic}`
240
+ const subscribers = this.subscriptions.get(key)
241
+
242
+ if (subscribers && subscribers.size > 0) {
243
+ const mockNote = this.generateMockNote({
244
+ startBlock: this.config.blockHeight,
245
+ endBlock: this.config.blockHeight + 1n,
246
+ chainId,
247
+ })
248
+
249
+ for (const callback of subscribers) {
250
+ callback([mockNote])
251
+ }
252
+ }
253
+ }
254
+
255
+ /**
256
+ * Set simulated block height
257
+ */
258
+ setBlockHeight(height: bigint): void {
259
+ this.config.blockHeight = height
260
+ }
261
+
262
+ // ─── Private Helpers ──────────────────────────────────────────────────────────
263
+
264
+ private checkInitialized(): void {
265
+ if (!this.initialized) {
266
+ throw new Error('Provider not initialized. Call initialize() first.')
267
+ }
268
+ }
269
+
270
+ private async simulateLatency(): Promise<void> {
271
+ if (this.config.latencyMs > 0) {
272
+ await new Promise(resolve => setTimeout(resolve, this.config.latencyMs))
273
+ }
274
+ }
275
+
276
+ private maybeSimulateFail(): void {
277
+ if (this.config.failProbability > 0 && Math.random() < this.config.failProbability) {
278
+ throw new Error('Simulated failure')
279
+ }
280
+ }
281
+
282
+ private generateMockNote(blockRange: BlockRange): EncryptedNote {
283
+ const blockNumber = blockRange.startBlock +
284
+ BigInt(Math.floor(Math.random() * Number(blockRange.endBlock - blockRange.startBlock)))
285
+
286
+ return {
287
+ commitment: `0x${bytesToHex(randomBytes(32))}` as HexString,
288
+ encryptedData: `0x${bytesToHex(randomBytes(128))}` as HexString,
289
+ blockNumber,
290
+ txHash: `0x${bytesToHex(randomBytes(32))}` as HexString,
291
+ chainId: blockRange.chainId,
292
+ }
293
+ }
294
+
295
+ private generateMockMerkleProof(leaf: HexString): MerkleProof {
296
+ // Generate mock 20-level Merkle proof
297
+ const siblings: HexString[] = []
298
+ for (let i = 0; i < 20; i++) {
299
+ siblings.push(`0x${bytesToHex(randomBytes(32))}` as HexString)
300
+ }
301
+
302
+ return {
303
+ leaf,
304
+ siblings,
305
+ index: BigInt(Math.floor(Math.random() * 1_000_000)),
306
+ root: `0x${bytesToHex(randomBytes(32))}` as HexString,
307
+ }
308
+ }
309
+ }
310
+
311
+ /**
312
+ * Create a mock oblivious sync provider for testing
313
+ */
314
+ export function createMockSyncProvider(
315
+ config?: Partial<MockSyncProviderConfig>
316
+ ): MockObliviousSyncProvider {
317
+ return new MockObliviousSyncProvider(config)
318
+ }