@sip-protocol/sdk 0.7.2 → 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 (262) 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 +48874 -18336
  7. package/dist/browser.mjs +674 -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-YWGJ77A2.mjs +33806 -0
  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-DXh2IGkz.d.ts +24681 -0
  24. package/dist/index-DeE1ZzA4.d.mts +24681 -0
  25. package/dist/index.d.mts +9 -3
  26. package/dist/index.d.ts +9 -3
  27. package/dist/index.js +48676 -17318
  28. package/dist/index.mjs +583 -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 +276 -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 +201 -0
  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 +402 -0
  98. package/src/chains/solana/providers/index.ts +85 -0
  99. package/src/chains/solana/providers/interface.ts +221 -0
  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 +790 -0
  103. package/src/chains/solana/rpc-client.ts +1150 -0
  104. package/src/chains/solana/scan.ts +170 -73
  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 +77 -7
  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 +37 -0
  116. package/src/compliance/range-sas.ts +956 -0
  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 +785 -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 +336 -0
  143. package/src/privacy-backends/interface.ts +906 -0
  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-types.ts +278 -0
  148. package/src/privacy-backends/privacycash.ts +456 -0
  149. package/src/privacy-backends/private-swap.ts +570 -0
  150. package/src/privacy-backends/rate-limiter.ts +683 -0
  151. package/src/privacy-backends/registry.ts +690 -0
  152. package/src/privacy-backends/router.ts +626 -0
  153. package/src/privacy-backends/shadowwire.ts +449 -0
  154. package/src/privacy-backends/sip-native.ts +256 -0
  155. package/src/privacy-logger.ts +191 -0
  156. package/src/production-safety.ts +373 -0
  157. package/src/proofs/aggregator.ts +1029 -0
  158. package/src/proofs/browser-composer.ts +1150 -0
  159. package/src/proofs/browser.ts +113 -25
  160. package/src/proofs/cache/index.ts +127 -0
  161. package/src/proofs/cache/interface.ts +545 -0
  162. package/src/proofs/cache/key-generator.ts +188 -0
  163. package/src/proofs/cache/lru-cache.ts +481 -0
  164. package/src/proofs/cache/multi-tier-cache.ts +575 -0
  165. package/src/proofs/cache/persistent-cache.ts +788 -0
  166. package/src/proofs/compliance-proof.ts +872 -0
  167. package/src/proofs/composer/base.ts +923 -0
  168. package/src/proofs/composer/index.ts +25 -0
  169. package/src/proofs/composer/interface.ts +518 -0
  170. package/src/proofs/composer/types.ts +383 -0
  171. package/src/proofs/converters/halo2.ts +452 -0
  172. package/src/proofs/converters/index.ts +208 -0
  173. package/src/proofs/converters/interface.ts +363 -0
  174. package/src/proofs/converters/kimchi.ts +462 -0
  175. package/src/proofs/converters/noir.ts +451 -0
  176. package/src/proofs/fallback.ts +888 -0
  177. package/src/proofs/halo2.ts +42 -0
  178. package/src/proofs/index.ts +471 -0
  179. package/src/proofs/interface.ts +13 -0
  180. package/src/proofs/kimchi.ts +42 -0
  181. package/src/proofs/lazy.ts +1004 -0
  182. package/src/proofs/mock.ts +25 -1
  183. package/src/proofs/noir.ts +111 -30
  184. package/src/proofs/orchestrator.ts +960 -0
  185. package/src/proofs/parallel/concurrency.ts +297 -0
  186. package/src/proofs/parallel/dependency-graph.ts +602 -0
  187. package/src/proofs/parallel/executor.ts +420 -0
  188. package/src/proofs/parallel/index.ts +131 -0
  189. package/src/proofs/parallel/interface.ts +685 -0
  190. package/src/proofs/parallel/worker-pool.ts +644 -0
  191. package/src/proofs/providers/halo2.ts +560 -0
  192. package/src/proofs/providers/index.ts +34 -0
  193. package/src/proofs/providers/kimchi.ts +641 -0
  194. package/src/proofs/validator.ts +881 -0
  195. package/src/proofs/verifier.ts +867 -0
  196. package/src/quantum/index.ts +112 -0
  197. package/src/quantum/winternitz-vault.ts +639 -0
  198. package/src/quantum/wots.ts +611 -0
  199. package/src/settlement/backends/direct-chain.ts +1 -0
  200. package/src/settlement/index.ts +9 -0
  201. package/src/settlement/router.ts +732 -46
  202. package/src/solana/index.ts +72 -0
  203. package/src/solana/jito-relayer.ts +687 -0
  204. package/src/solana/noir-verifier-types.ts +430 -0
  205. package/src/solana/noir-verifier.ts +816 -0
  206. package/src/stealth/address-derivation.ts +193 -0
  207. package/src/stealth/ed25519.ts +431 -0
  208. package/src/stealth/index.ts +233 -0
  209. package/src/stealth/meta-address.ts +221 -0
  210. package/src/stealth/secp256k1.ts +368 -0
  211. package/src/stealth/utils.ts +194 -0
  212. package/src/stealth.ts +50 -1504
  213. package/src/surveillance/algorithms/address-reuse.ts +143 -0
  214. package/src/surveillance/algorithms/cluster.ts +247 -0
  215. package/src/surveillance/algorithms/exchange.ts +295 -0
  216. package/src/surveillance/algorithms/temporal.ts +337 -0
  217. package/src/surveillance/analyzer.ts +442 -0
  218. package/src/surveillance/index.ts +64 -0
  219. package/src/surveillance/scoring.ts +372 -0
  220. package/src/surveillance/types.ts +264 -0
  221. package/src/sync/index.ts +106 -0
  222. package/src/sync/manager.ts +504 -0
  223. package/src/sync/mock-provider.ts +318 -0
  224. package/src/sync/oblivious.ts +625 -0
  225. package/src/tokens/index.ts +15 -0
  226. package/src/tokens/registry.ts +301 -0
  227. package/src/utils/deprecation.ts +94 -0
  228. package/src/utils/index.ts +9 -0
  229. package/src/wallet/ethereum/index.ts +68 -0
  230. package/src/wallet/ethereum/metamask-privacy.ts +420 -0
  231. package/src/wallet/ethereum/multi-wallet.ts +646 -0
  232. package/src/wallet/ethereum/privacy-adapter.ts +700 -0
  233. package/src/wallet/ethereum/types.ts +3 -1
  234. package/src/wallet/ethereum/walletconnect-adapter.ts +675 -0
  235. package/src/wallet/hardware/index.ts +10 -0
  236. package/src/wallet/hardware/ledger-privacy.ts +414 -0
  237. package/src/wallet/index.ts +71 -0
  238. package/src/wallet/near/adapter.ts +626 -0
  239. package/src/wallet/near/index.ts +86 -0
  240. package/src/wallet/near/meteor-wallet.ts +1153 -0
  241. package/src/wallet/near/my-near-wallet.ts +790 -0
  242. package/src/wallet/near/wallet-selector.ts +702 -0
  243. package/src/wallet/solana/adapter.ts +6 -4
  244. package/src/wallet/solana/index.ts +13 -0
  245. package/src/wallet/solana/privacy-adapter.ts +567 -0
  246. package/src/wallet/sui/types.ts +6 -4
  247. package/src/zcash/rpc-client.ts +13 -6
  248. package/dist/chunk-3INS3PR5.mjs +0 -884
  249. package/dist/chunk-3OVABDRH.mjs +0 -17096
  250. package/dist/chunk-DLDWZFYC.mjs +0 -1495
  251. package/dist/chunk-E6SZWREQ.mjs +0 -57
  252. package/dist/chunk-G33LB27A.mjs +0 -16166
  253. package/dist/chunk-HGU6HZRC.mjs +0 -231
  254. package/dist/chunk-L2K34JCU.mjs +0 -1496
  255. package/dist/chunk-SN4ZDTVW.mjs +0 -16166
  256. package/dist/constants-VOI7BSLK.mjs +0 -27
  257. package/dist/index-BYZbDjal.d.ts +0 -11390
  258. package/dist/index-CHB3KuOB.d.mts +0 -11859
  259. package/dist/index-CzWPI6Le.d.ts +0 -11859
  260. package/dist/index-xbWjohNq.d.mts +0 -11390
  261. package/dist/solana-5EMCTPTS.mjs +0 -46
  262. package/dist/solana-Q4NAVBTS.mjs +0 -46
@@ -0,0 +1,639 @@
1
+ /**
2
+ * Winternitz Vault Integration for Quantum-Resistant Storage
3
+ *
4
+ * Combines SIP's privacy layer (stealth addresses, Pedersen commitments,
5
+ * viewing keys) with Winternitz vaults for post-quantum security.
6
+ *
7
+ * ## Security Model
8
+ *
9
+ * ```
10
+ * Layer 3: COMPLIANCE (Viewing Keys)
11
+ * └── Selective disclosure to auditors
12
+ * Layer 2: PRIVACY (SIP)
13
+ * └── Hidden sender/amount/recipient
14
+ * Layer 1: QUANTUM RESISTANCE (Winternitz)
15
+ * └── 128-bit post-quantum security
16
+ * ```
17
+ *
18
+ * ## Usage
19
+ *
20
+ * ```typescript
21
+ * import { WinternitzVaultAdapter } from '@sip-protocol/sdk/quantum'
22
+ *
23
+ * const adapter = new WinternitzVaultAdapter({
24
+ * connection: new Connection('https://api.mainnet-beta.solana.com'),
25
+ * })
26
+ *
27
+ * // Open quantum-safe vault
28
+ * const vault = await adapter.openVault({
29
+ * amount: 1_000_000_000n,
30
+ * recipient: recipientMetaAddress,
31
+ * viewingKey: auditorKey,
32
+ * })
33
+ *
34
+ * // Send from vault (creates new vaults)
35
+ * const { recipientVault, changeVault } = await adapter.send({
36
+ * fromVault: vault,
37
+ * toRecipient: bobMetaAddress,
38
+ * amount: 500_000_000n,
39
+ * })
40
+ * ```
41
+ *
42
+ * @module quantum/winternitz-vault
43
+ */
44
+
45
+ import { PublicKey, Connection, Transaction } from '@solana/web3.js'
46
+ import { keccak_256 } from '@noble/hashes/sha3'
47
+ import type { HexString } from '@sip-protocol/types'
48
+ import {
49
+ generateWinternitzKeypair,
50
+ wotsSign,
51
+ wotsVerify,
52
+ WotsKeyManager,
53
+ type WinternitzKeypair,
54
+ type WotsSignature,
55
+ } from './wots'
56
+
57
+ // ─── Types ────────────────────────────────────────────────────────────────────
58
+
59
+ /**
60
+ * Shielded vault combining privacy + quantum resistance
61
+ */
62
+ export interface ShieldedVault {
63
+ // === Winternitz Layer ===
64
+ /** WOTS public key merkle root (32 bytes) */
65
+ wotsMerkleRoot: Uint8Array
66
+ /** Vault PDA on Solana */
67
+ vaultAddress: PublicKey
68
+ /** Balance in lamports */
69
+ balance: bigint
70
+
71
+ // === SIP Privacy Layer ===
72
+ /** One-time stealth address */
73
+ stealthAddress: {
74
+ address: HexString
75
+ ephemeralPublicKey: HexString
76
+ viewTag: number
77
+ }
78
+ /** Pedersen commitment hiding the balance */
79
+ balanceCommitment: {
80
+ value: HexString
81
+ blindingFactor: HexString
82
+ }
83
+ /** Encrypted metadata for viewing key holders */
84
+ encryptedMetadata?: {
85
+ ciphertext: HexString
86
+ nonce: HexString
87
+ viewingKeyHash: HexString
88
+ }
89
+
90
+ // === Vault State ===
91
+ /** Vault status */
92
+ status: 'active' | 'spent'
93
+ /** Creation timestamp */
94
+ createdAt: number
95
+ /** Chain identifier */
96
+ chain: 'solana'
97
+ }
98
+
99
+ /**
100
+ * Decrypted vault metadata (visible to viewing key holders)
101
+ */
102
+ export interface ShieldedVaultMetadata {
103
+ /** Actual balance */
104
+ balance: bigint
105
+ /** Blinding factor for commitment verification */
106
+ blindingFactor: HexString
107
+ /** Original sender (if disclosed) */
108
+ sender?: HexString
109
+ /** Purpose/memo */
110
+ memo?: string
111
+ /** Timestamp */
112
+ timestamp: number
113
+ }
114
+
115
+ /**
116
+ * Parameters for opening a vault
117
+ */
118
+ export interface OpenVaultParams {
119
+ /** Amount in lamports */
120
+ amount: bigint
121
+ /** Recipient stealth meta-address */
122
+ recipientMetaAddress: {
123
+ spendingPublicKey: HexString
124
+ viewingPublicKey: HexString
125
+ }
126
+ /** Viewing key for compliance (optional) */
127
+ viewingKey?: HexString
128
+ /** Payer for transaction */
129
+ payer: PublicKey
130
+ /** Transaction signer */
131
+ signTransaction: <T extends Transaction>(tx: T) => Promise<T>
132
+ }
133
+
134
+ /**
135
+ * Parameters for splitting a vault
136
+ */
137
+ export interface SplitVaultParams {
138
+ /** Source vault */
139
+ vault: ShieldedVault
140
+ /** Amount to send */
141
+ splitAmount: bigint
142
+ /** Split recipient meta-address */
143
+ splitRecipient: {
144
+ spendingPublicKey: HexString
145
+ viewingPublicKey: HexString
146
+ }
147
+ /** Refund recipient meta-address (usually self) */
148
+ refundRecipient: {
149
+ spendingPublicKey: HexString
150
+ viewingPublicKey: HexString
151
+ }
152
+ /** WOTS private key for source vault */
153
+ wotsPrivateKey: Uint8Array
154
+ /** Viewing key */
155
+ viewingKey?: HexString
156
+ /** Payer for transaction */
157
+ payer: PublicKey
158
+ /** Transaction signer */
159
+ signTransaction: <T extends Transaction>(tx: T) => Promise<T>
160
+ }
161
+
162
+ /**
163
+ * Parameters for closing a vault
164
+ */
165
+ export interface CloseVaultParams {
166
+ /** Vault to close */
167
+ vault: ShieldedVault
168
+ /** Recipient meta-address */
169
+ recipient: {
170
+ spendingPublicKey: HexString
171
+ viewingPublicKey: HexString
172
+ }
173
+ /** WOTS private key */
174
+ wotsPrivateKey: Uint8Array
175
+ /** Viewing key */
176
+ viewingKey?: HexString
177
+ /** Payer */
178
+ payer: PublicKey
179
+ /** Transaction signer */
180
+ signTransaction: <T extends Transaction>(tx: T) => Promise<T>
181
+ }
182
+
183
+ /**
184
+ * Vault scan parameters
185
+ */
186
+ export interface ScanVaultsParams {
187
+ /** Spending private key */
188
+ spendingPrivateKey: HexString
189
+ /** Viewing private key */
190
+ viewingPrivateKey: HexString
191
+ /** Vaults to scan */
192
+ vaults: ShieldedVault[]
193
+ }
194
+
195
+ /**
196
+ * Adapter configuration
197
+ */
198
+ export interface WinternitzVaultConfig {
199
+ /** Solana connection */
200
+ connection: Connection
201
+ /** Winternitz program ID (if deployed) */
202
+ programId?: PublicKey
203
+ /** Enable debug logging */
204
+ debug?: boolean
205
+ }
206
+
207
+ // ─── Constants ────────────────────────────────────────────────────────────────
208
+
209
+ /**
210
+ * Default Winternitz program ID (placeholder - update with actual deployment)
211
+ */
212
+ export const WINTERNITZ_PROGRAM_ID = new PublicKey(
213
+ 'WntrVt1111111111111111111111111111111111111'
214
+ )
215
+
216
+ /**
217
+ * Vault account size
218
+ */
219
+ export const VAULT_ACCOUNT_SIZE = 256
220
+
221
+ // ─── WinternitzVaultAdapter ───────────────────────────────────────────────────
222
+
223
+ /**
224
+ * Quantum-resistant vault adapter
225
+ *
226
+ * Integrates Winternitz vaults with SIP privacy primitives.
227
+ */
228
+ export class WinternitzVaultAdapter {
229
+ private connection: Connection
230
+ private programId: PublicKey
231
+ private keyManager: WotsKeyManager
232
+ private debug: boolean
233
+
234
+ constructor(config: WinternitzVaultConfig) {
235
+ this.connection = config.connection
236
+ this.programId = config.programId ?? WINTERNITZ_PROGRAM_ID
237
+ this.keyManager = new WotsKeyManager()
238
+ this.debug = config.debug ?? false
239
+ }
240
+
241
+ /**
242
+ * Generate a fresh Winternitz keypair for a new vault
243
+ */
244
+ generateKeypair(): WinternitzKeypair {
245
+ const keypair = generateWinternitzKeypair()
246
+ this.keyManager.register(keypair)
247
+ return keypair
248
+ }
249
+
250
+ /**
251
+ * Derive vault PDA from merkle root
252
+ */
253
+ deriveVaultAddress(merkleRoot: Uint8Array): PublicKey {
254
+ const [vaultAddress] = PublicKey.findProgramAddressSync(
255
+ [merkleRoot],
256
+ this.programId
257
+ )
258
+ return vaultAddress
259
+ }
260
+
261
+ /**
262
+ * Open a new shielded vault (mock implementation)
263
+ *
264
+ * In production, this would interact with the deployed Winternitz program.
265
+ */
266
+ async openVault(params: OpenVaultParams): Promise<{
267
+ vault: ShieldedVault
268
+ wotsKeypair: WinternitzKeypair
269
+ }> {
270
+ const {
271
+ amount,
272
+ recipientMetaAddress,
273
+ viewingKey,
274
+ payer: _payer,
275
+ signTransaction: _signTransaction,
276
+ } = params
277
+
278
+ // Note: payer and signTransaction are used in production to send transactions
279
+ void _payer
280
+ void _signTransaction
281
+
282
+ // Generate WOTS keypair
283
+ const wotsKeypair = this.generateKeypair()
284
+ const vaultAddress = this.deriveVaultAddress(wotsKeypair.merkleRoot)
285
+
286
+ // Generate stealth address for recipient
287
+ const stealthAddress = this.generateMockStealthAddress(recipientMetaAddress)
288
+
289
+ // Generate Pedersen commitment
290
+ const commitment = this.generateMockCommitment(amount)
291
+
292
+ // Encrypt metadata if viewing key provided
293
+ let encryptedMetadata: ShieldedVault['encryptedMetadata']
294
+ if (viewingKey) {
295
+ encryptedMetadata = this.encryptMetadata(
296
+ { balance: amount, blindingFactor: commitment.blindingFactor, timestamp: Date.now() },
297
+ viewingKey
298
+ )
299
+ }
300
+
301
+ // Create vault (mock - would send transaction in production)
302
+ if (this.debug) {
303
+ console.log(`[WinternitzVault] Opening vault at ${vaultAddress.toBase58()}`)
304
+ console.log(`[WinternitzVault] Amount: ${amount} lamports`)
305
+ }
306
+
307
+ // In production: Build and send transaction to Winternitz program
308
+ // const ix = WinternitzProgram.openVault({ merkleRoot, lamports: amount })
309
+ // const tx = new Transaction().add(ix)
310
+ // await this.sendTransaction(tx, signTransaction)
311
+
312
+ const vault: ShieldedVault = {
313
+ wotsMerkleRoot: wotsKeypair.merkleRoot,
314
+ vaultAddress,
315
+ balance: amount,
316
+ stealthAddress,
317
+ balanceCommitment: commitment,
318
+ encryptedMetadata,
319
+ status: 'active',
320
+ createdAt: Date.now(),
321
+ chain: 'solana',
322
+ }
323
+
324
+ return { vault, wotsKeypair }
325
+ }
326
+
327
+ /**
328
+ * Split vault into two destinations
329
+ */
330
+ async splitVault(params: SplitVaultParams): Promise<{
331
+ splitVault: ShieldedVault
332
+ refundVault: ShieldedVault
333
+ signature: WotsSignature
334
+ }> {
335
+ const {
336
+ vault,
337
+ splitAmount,
338
+ splitRecipient,
339
+ refundRecipient,
340
+ wotsPrivateKey,
341
+ viewingKey,
342
+ payer,
343
+ signTransaction,
344
+ } = params
345
+
346
+ // Validate
347
+ if (vault.status !== 'active') {
348
+ throw new Error('Vault is not active')
349
+ }
350
+
351
+ if (splitAmount > vault.balance) {
352
+ throw new Error(`Split amount ${splitAmount} exceeds balance ${vault.balance}`)
353
+ }
354
+
355
+ // Check key not already used
356
+ if (!this.keyManager.canUse(vault.wotsMerkleRoot)) {
357
+ throw new Error('WOTS key already used - cannot split vault')
358
+ }
359
+
360
+ // Create split vault
361
+ const splitResult = await this.openVault({
362
+ amount: splitAmount,
363
+ recipientMetaAddress: splitRecipient,
364
+ viewingKey,
365
+ payer,
366
+ signTransaction,
367
+ })
368
+
369
+ // Create refund vault
370
+ const refundAmount = vault.balance - splitAmount
371
+ const refundResult = await this.openVault({
372
+ amount: refundAmount,
373
+ recipientMetaAddress: refundRecipient,
374
+ viewingKey,
375
+ payer,
376
+ signTransaction,
377
+ })
378
+
379
+ // Sign split message with WOTS
380
+ const message = this.buildSplitMessage(
381
+ splitResult.vault.vaultAddress,
382
+ refundResult.vault.vaultAddress,
383
+ splitAmount
384
+ )
385
+
386
+ // Mark key as used BEFORE signing (critical for security)
387
+ await this.keyManager.markUsed(
388
+ vault.wotsMerkleRoot,
389
+ `split:${splitResult.vault.vaultAddress.toBase58()}`
390
+ )
391
+
392
+ const signature = wotsSign(wotsPrivateKey, message)
393
+
394
+ if (this.debug) {
395
+ console.log(`[WinternitzVault] Split vault: ${splitAmount} + ${refundAmount}`)
396
+ }
397
+
398
+ // Mark original vault as spent
399
+ vault.status = 'spent'
400
+
401
+ return {
402
+ splitVault: splitResult.vault,
403
+ refundVault: refundResult.vault,
404
+ signature,
405
+ }
406
+ }
407
+
408
+ /**
409
+ * Close vault and send all funds to recipient
410
+ */
411
+ async closeVault(params: CloseVaultParams): Promise<{
412
+ recipientVault: ShieldedVault
413
+ signature: WotsSignature
414
+ }> {
415
+ const {
416
+ vault,
417
+ recipient,
418
+ wotsPrivateKey,
419
+ viewingKey,
420
+ payer,
421
+ signTransaction,
422
+ } = params
423
+
424
+ // Validate
425
+ if (vault.status !== 'active') {
426
+ throw new Error('Vault is not active')
427
+ }
428
+
429
+ if (!this.keyManager.canUse(vault.wotsMerkleRoot)) {
430
+ throw new Error('WOTS key already used - cannot close vault')
431
+ }
432
+
433
+ // Create recipient vault
434
+ const recipientResult = await this.openVault({
435
+ amount: vault.balance,
436
+ recipientMetaAddress: recipient,
437
+ viewingKey,
438
+ payer,
439
+ signTransaction,
440
+ })
441
+
442
+ // Sign close message
443
+ const message = this.buildCloseMessage(recipientResult.vault.vaultAddress)
444
+
445
+ // Mark key as used
446
+ await this.keyManager.markUsed(
447
+ vault.wotsMerkleRoot,
448
+ `close:${recipientResult.vault.vaultAddress.toBase58()}`
449
+ )
450
+
451
+ const signature = wotsSign(wotsPrivateKey, message)
452
+
453
+ if (this.debug) {
454
+ console.log(`[WinternitzVault] Closed vault: ${vault.balance} lamports`)
455
+ }
456
+
457
+ // Mark original vault as spent
458
+ vault.status = 'spent'
459
+
460
+ return {
461
+ recipientVault: recipientResult.vault,
462
+ signature,
463
+ }
464
+ }
465
+
466
+ /**
467
+ * Scan for vaults belonging to a keypair
468
+ */
469
+ scanVaults(params: ScanVaultsParams): ShieldedVault[] {
470
+ const { spendingPrivateKey, viewingPrivateKey, vaults } = params
471
+
472
+ const matchedVaults: ShieldedVault[] = []
473
+
474
+ for (const vault of vaults) {
475
+ // Check view tag first (97% rejection rate)
476
+ if (!this.checkViewTag(vault.stealthAddress, viewingPrivateKey)) {
477
+ continue
478
+ }
479
+
480
+ // Full stealth check
481
+ if (this.checkStealthOwnership(vault.stealthAddress, spendingPrivateKey, viewingPrivateKey)) {
482
+ matchedVaults.push(vault)
483
+ }
484
+ }
485
+
486
+ return matchedVaults
487
+ }
488
+
489
+ /**
490
+ * Verify signature for a vault operation
491
+ */
492
+ verifySignature(
493
+ publicKey: Uint8Array,
494
+ message: Uint8Array,
495
+ signature: WotsSignature
496
+ ): boolean {
497
+ return wotsVerify(publicKey, message, signature)
498
+ }
499
+
500
+ /**
501
+ * Get key manager for tracking WOTS key usage
502
+ */
503
+ getKeyManager(): WotsKeyManager {
504
+ return this.keyManager
505
+ }
506
+
507
+ /**
508
+ * Estimate transaction cost
509
+ */
510
+ estimateOpenCost(): bigint {
511
+ // Rent for vault account + transaction fee
512
+ const rentExemption = 890880n // ~0.00089 SOL for 256 bytes
513
+ const txFee = 5000n
514
+ return rentExemption + txFee
515
+ }
516
+
517
+ // ─── Private Helpers ──────────────────────────────────────────────────────────
518
+
519
+ private generateMockStealthAddress(_metaAddress: {
520
+ spendingPublicKey: HexString
521
+ viewingPublicKey: HexString
522
+ }): ShieldedVault['stealthAddress'] {
523
+ // In production, use generateEd25519StealthAddress with _metaAddress
524
+ const ephemeral = keccak_256(new TextEncoder().encode(Date.now().toString()))
525
+ return {
526
+ address: `0x${Buffer.from(ephemeral).toString('hex')}`,
527
+ ephemeralPublicKey: `0x${Buffer.from(ephemeral).toString('hex')}`,
528
+ viewTag: ephemeral[0],
529
+ }
530
+ }
531
+
532
+ private generateMockCommitment(amount: bigint): {
533
+ value: HexString
534
+ blindingFactor: HexString
535
+ } {
536
+ // In production, use commit() from crypto module
537
+ const blinding = keccak_256(new TextEncoder().encode(Math.random().toString()))
538
+ const commitment = keccak_256(
539
+ new Uint8Array([...this.bigintToBytes(amount), ...blinding])
540
+ )
541
+ return {
542
+ value: `0x${Buffer.from(commitment).toString('hex')}`,
543
+ blindingFactor: `0x${Buffer.from(blinding).toString('hex')}`,
544
+ }
545
+ }
546
+
547
+ private encryptMetadata(
548
+ metadata: Partial<ShieldedVaultMetadata>,
549
+ viewingKey: HexString
550
+ ): ShieldedVault['encryptedMetadata'] {
551
+ // In production, use XChaCha20-Poly1305
552
+ const data = JSON.stringify(metadata)
553
+ const nonce = keccak_256(new TextEncoder().encode(Date.now().toString())).slice(0, 24)
554
+ const ciphertext = new TextEncoder().encode(data) // Mock - not actually encrypted
555
+
556
+ return {
557
+ ciphertext: `0x${Buffer.from(ciphertext).toString('hex')}`,
558
+ nonce: `0x${Buffer.from(nonce).toString('hex')}`,
559
+ viewingKeyHash: `0x${Buffer.from(keccak_256(this.hexToBytes(viewingKey))).toString('hex')}`,
560
+ }
561
+ }
562
+
563
+ private buildSplitMessage(
564
+ splitVault: PublicKey,
565
+ refundVault: PublicKey,
566
+ amount: bigint
567
+ ): Uint8Array {
568
+ const data = new Uint8Array(96)
569
+ data.set(splitVault.toBytes(), 0)
570
+ data.set(refundVault.toBytes(), 32)
571
+ data.set(this.bigintToBytes(amount), 64)
572
+ return keccak_256(data)
573
+ }
574
+
575
+ private buildCloseMessage(recipientVault: PublicKey): Uint8Array {
576
+ return keccak_256(recipientVault.toBytes())
577
+ }
578
+
579
+ private checkViewTag(
580
+ _stealthAddress: ShieldedVault['stealthAddress'],
581
+ _viewingKey: HexString
582
+ ): boolean {
583
+ // Mock view tag check - in production, verify view tag matches
584
+ return true
585
+ }
586
+
587
+ private checkStealthOwnership(
588
+ _stealthAddress: ShieldedVault['stealthAddress'],
589
+ _spendingKey: HexString,
590
+ _viewingKey: HexString
591
+ ): boolean {
592
+ // Mock ownership check - in production, use checkEd25519StealthAddress
593
+ return true
594
+ }
595
+
596
+ private bigintToBytes(value: bigint): Uint8Array {
597
+ const bytes = new Uint8Array(32)
598
+ let v = value
599
+ for (let i = 31; i >= 0; i--) {
600
+ bytes[i] = Number(v & 0xffn)
601
+ v >>= 8n
602
+ }
603
+ return bytes
604
+ }
605
+
606
+ private hexToBytes(hex: HexString): Uint8Array {
607
+ const cleaned = hex.startsWith('0x') ? hex.slice(2) : hex
608
+ const bytes = new Uint8Array(cleaned.length / 2)
609
+ for (let i = 0; i < bytes.length; i++) {
610
+ bytes[i] = parseInt(cleaned.slice(i * 2, i * 2 + 2), 16)
611
+ }
612
+ return bytes
613
+ }
614
+ }
615
+
616
+ // ─── Factory Function ─────────────────────────────────────────────────────────
617
+
618
+ /**
619
+ * Create a Winternitz vault adapter
620
+ *
621
+ * @example
622
+ * ```typescript
623
+ * const adapter = createWinternitzVaultAdapter({
624
+ * connection: new Connection('https://api.mainnet-beta.solana.com'),
625
+ * })
626
+ *
627
+ * const { vault, wotsKeypair } = await adapter.openVault({
628
+ * amount: 1_000_000_000n,
629
+ * recipientMetaAddress: { spendingPublicKey, viewingPublicKey },
630
+ * payer: wallet.publicKey,
631
+ * signTransaction: wallet.signTransaction,
632
+ * })
633
+ * ```
634
+ */
635
+ export function createWinternitzVaultAdapter(
636
+ config: WinternitzVaultConfig
637
+ ): WinternitzVaultAdapter {
638
+ return new WinternitzVaultAdapter(config)
639
+ }