@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,866 @@
1
+ /**
2
+ * Combined Privacy Service
3
+ *
4
+ * Integrates SIP Native (stealth addresses, Pedersen commitments, viewing keys)
5
+ * with Arcium C-SPL (encrypted amounts) for comprehensive transaction privacy.
6
+ *
7
+ * ## Privacy Layers Combined
8
+ *
9
+ * | Feature | SIP Native | Arcium C-SPL | Combined |
10
+ * |---------|------------|--------------|----------|
11
+ * | Hidden Sender | ✓ | ✗ | ✓ |
12
+ * | Hidden Recipient | ✓ | ✗ | ✓ |
13
+ * | Hidden Amount | ✓ (Pedersen) | ✓ (Encrypted) | ✓ |
14
+ * | Hidden Compute | ✗ | ✓ (MPC) | ✓ |
15
+ * | Compliance | ✓ (Viewing Keys) | ✗ | ✓ |
16
+ *
17
+ * ## Usage
18
+ *
19
+ * ```typescript
20
+ * import { CombinedPrivacyService } from '@sip-protocol/sdk'
21
+ *
22
+ * const service = new CombinedPrivacyService({
23
+ * rpcUrl: 'https://api.devnet.solana.com',
24
+ * })
25
+ *
26
+ * await service.initialize()
27
+ *
28
+ * // Execute private transfer with full privacy
29
+ * const result = await service.executePrivateTransfer({
30
+ * sender: wallet.publicKey,
31
+ * recipientMetaAddress: 'sip:solana:0x...',
32
+ * amount: 1_000_000_000n,
33
+ * token: 'So11111111111111111111111111111111111111112',
34
+ * privacyLevel: 'shielded',
35
+ * })
36
+ *
37
+ * // IMPORTANT: Always check success before accessing result fields
38
+ * if (!result.success) {
39
+ * console.error('Transfer failed:', result.error)
40
+ * return
41
+ * }
42
+ *
43
+ * console.log('Stealth address:', result.stealthAddress)
44
+ * console.log('Signature:', result.signature)
45
+ * ```
46
+ *
47
+ * @see CSPLTokenService for C-SPL operations
48
+ * @see SIPNativeBackend for stealth address operations
49
+ */
50
+
51
+ import { PrivacyLevel, type ViewingKey } from '@sip-protocol/types'
52
+ import {
53
+ CSPLTokenService,
54
+ type CSPLTokenServiceConfig,
55
+ } from './cspl-token'
56
+ import type { CSPLToken } from './cspl-types'
57
+ import { SIPNativeBackend, type SIPNativeBackendConfig } from './sip-native'
58
+
59
+ // ─── Types ─────────────────────────────────────────────────────────────────────
60
+
61
+ /**
62
+ * Parameters for a combined private transfer
63
+ */
64
+ export interface CombinedTransferParams {
65
+ /** Sender wallet address */
66
+ sender: string
67
+ /** Recipient's meta-address (sip:chain:spending:viewing format) */
68
+ recipientMetaAddress: string
69
+ /** Amount to transfer (in smallest units) */
70
+ amount: bigint
71
+ /** Token mint address (SPL token, will be wrapped to C-SPL) */
72
+ token: string
73
+ /** Privacy level */
74
+ privacyLevel: PrivacyLevel
75
+ /** Optional viewing key for compliance (required for 'compliant' level) */
76
+ viewingKey?: ViewingKey
77
+ /** Optional memo (public if not encrypted) */
78
+ memo?: string
79
+ }
80
+
81
+ /**
82
+ * Result of a combined private transfer
83
+ *
84
+ * IMPORTANT: Always check `success` before accessing other fields.
85
+ * Fields like stealthAddress, csplMint, etc. are only populated when success is true.
86
+ */
87
+ export interface CombinedTransferResult {
88
+ /** Whether the transfer succeeded */
89
+ success: boolean
90
+ /** Error message (only if !success) */
91
+ error?: string
92
+ /** The one-time stealth address for this transfer (only if success) */
93
+ stealthAddress?: string
94
+ /** The C-SPL token mint used (only if success) */
95
+ csplMint?: string
96
+ /** Encrypted balance after transfer (only if success) */
97
+ encryptedBalance?: Uint8Array
98
+ /** Transaction signature for wrap operation (only if success) */
99
+ wrapSignature?: string
100
+ /** Transaction signature for transfer operation (only if success) */
101
+ transferSignature?: string
102
+ /** Combined operation signatures (only if success) */
103
+ signatures?: string[]
104
+ /** Transfer metadata */
105
+ metadata?: {
106
+ privacyLevel: PrivacyLevel
107
+ hasViewingKey: boolean
108
+ wrapDuration?: number
109
+ transferDuration?: number
110
+ totalDuration?: number
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Result of stealth address derivation
116
+ */
117
+ export interface StealthAddressResult {
118
+ /** Whether derivation succeeded */
119
+ success: boolean
120
+ /** Error message (only if !success) */
121
+ error?: string
122
+ /** The derived stealth address (only if success) */
123
+ stealthAddress?: string
124
+ /** The ephemeral public key (only if success) */
125
+ ephemeralPubkey?: string
126
+ /** The view tag for efficient scanning (only if success) */
127
+ viewTag?: number
128
+ }
129
+
130
+ /**
131
+ * Parameters for claiming from stealth address
132
+ */
133
+ export interface ClaimParams {
134
+ /** The stealth address to claim from */
135
+ stealthAddress: string
136
+ /** The ephemeral public key from sender */
137
+ ephemeralPubkey: string
138
+ /** Recipient's spending private key */
139
+ spendingPrivateKey: string
140
+ /** Recipient's viewing private key */
141
+ viewingPrivateKey: string
142
+ /** C-SPL token to claim */
143
+ csplMint: string
144
+ }
145
+
146
+ /**
147
+ * Result of claiming from stealth address
148
+ */
149
+ export interface ClaimResult {
150
+ /** Whether claim succeeded */
151
+ success: boolean
152
+ /** Error message (only if !success) */
153
+ error?: string
154
+ /** Amount claimed (decrypted) */
155
+ amount?: bigint
156
+ /** Transaction signature */
157
+ signature?: string
158
+ }
159
+
160
+ /**
161
+ * Cost breakdown for combined operations
162
+ */
163
+ export interface CostBreakdown {
164
+ /** Cost for wrapping to C-SPL */
165
+ wrapCost: bigint
166
+ /** Cost for stealth address derivation */
167
+ stealthCost: bigint
168
+ /** Cost for confidential transfer */
169
+ transferCost: bigint
170
+ /** Total estimated cost */
171
+ totalCost: bigint
172
+ /** Currency (e.g., 'lamports', 'gwei') */
173
+ currency: string
174
+ }
175
+
176
+ /**
177
+ * Privacy comparison between backends
178
+ */
179
+ export interface PrivacyComparison {
180
+ sipNative: {
181
+ hiddenSender: boolean
182
+ hiddenRecipient: boolean
183
+ hiddenAmount: boolean
184
+ hiddenCompute: boolean
185
+ compliance: boolean
186
+ }
187
+ arciumCSPL: {
188
+ hiddenSender: boolean
189
+ hiddenRecipient: boolean
190
+ hiddenAmount: boolean
191
+ hiddenCompute: boolean
192
+ compliance: boolean
193
+ }
194
+ combined: {
195
+ hiddenSender: boolean
196
+ hiddenRecipient: boolean
197
+ hiddenAmount: boolean
198
+ hiddenCompute: boolean
199
+ compliance: boolean
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Service status
205
+ */
206
+ export interface ServiceStatus {
207
+ /** Whether service is initialized */
208
+ initialized: boolean
209
+ /** C-SPL service status */
210
+ csplStatus: {
211
+ connected: boolean
212
+ tokenCount: number
213
+ }
214
+ /** SIP Native backend status */
215
+ sipNativeStatus: {
216
+ available: boolean
217
+ chainCount: number
218
+ }
219
+ }
220
+
221
+ // ─── Service Implementation ────────────────────────────────────────────────────
222
+
223
+ /**
224
+ * Configuration for CombinedPrivacyService
225
+ */
226
+ export interface CombinedPrivacyServiceConfig {
227
+ /** Solana RPC endpoint URL */
228
+ rpcUrl?: string
229
+ /** C-SPL service configuration */
230
+ csplConfig?: CSPLTokenServiceConfig
231
+ /** SIP Native backend configuration */
232
+ sipNativeConfig?: SIPNativeBackendConfig
233
+ /** Default privacy level */
234
+ defaultPrivacyLevel?: PrivacyLevel
235
+ }
236
+
237
+ /**
238
+ * Combined Privacy Service
239
+ *
240
+ * Provides comprehensive privacy by combining:
241
+ * - SIP Native: Stealth addresses (unlinkable recipients)
242
+ * - SIP Native: Pedersen commitments (hidden amounts)
243
+ * - SIP Native: Viewing keys (compliance support)
244
+ * - Arcium C-SPL: Encrypted token balances
245
+ *
246
+ * ## Critical: Always Check Success Before Accessing Fields
247
+ *
248
+ * All result types in this service use the Result pattern.
249
+ * You MUST check `result.success` before accessing other fields.
250
+ *
251
+ * @example
252
+ * ```typescript
253
+ * // CORRECT: Check success first
254
+ * if (!result.success) {
255
+ * console.error(result.error)
256
+ * return
257
+ * }
258
+ * console.log(result.stealthAddress) // Now safe to access
259
+ *
260
+ * // INCORRECT: Never use non-null assertions without checking success
261
+ * // console.log(result.stealthAddress!) // UNSAFE - could be undefined
262
+ * ```
263
+ */
264
+ export class CombinedPrivacyService {
265
+ private csplService: CSPLTokenService
266
+ private sipNativeBackend: SIPNativeBackend
267
+ private config: Required<CombinedPrivacyServiceConfig>
268
+ private initialized: boolean = false
269
+
270
+ /**
271
+ * Create a new Combined Privacy Service
272
+ *
273
+ * @param config - Service configuration
274
+ */
275
+ constructor(config: CombinedPrivacyServiceConfig = {}) {
276
+ this.config = {
277
+ rpcUrl: config.rpcUrl ?? 'https://api.devnet.solana.com',
278
+ csplConfig: config.csplConfig ?? {},
279
+ sipNativeConfig: config.sipNativeConfig ?? {},
280
+ defaultPrivacyLevel: config.defaultPrivacyLevel ?? PrivacyLevel.SHIELDED,
281
+ }
282
+
283
+ // Initialize sub-services
284
+ this.csplService = new CSPLTokenService({
285
+ ...this.config.csplConfig,
286
+ rpcUrl: this.config.rpcUrl,
287
+ })
288
+
289
+ this.sipNativeBackend = new SIPNativeBackend(this.config.sipNativeConfig)
290
+ }
291
+
292
+ /**
293
+ * Initialize the service
294
+ *
295
+ * Initializes both C-SPL and SIP Native components.
296
+ */
297
+ async initialize(): Promise<void> {
298
+ if (this.initialized) {
299
+ return
300
+ }
301
+
302
+ await this.csplService.initialize()
303
+ this.initialized = true
304
+ }
305
+
306
+ /**
307
+ * Execute a privacy-preserving transfer
308
+ *
309
+ * This combines:
310
+ * 1. Wrap SPL to C-SPL (encrypted balance)
311
+ * 2. Derive stealth address (unlinkable recipient)
312
+ * 3. Transfer to stealth address with encrypted amount
313
+ *
314
+ * IMPORTANT: Always check result.success before accessing result fields!
315
+ *
316
+ * @param params - Transfer parameters
317
+ * @returns Transfer result with success status
318
+ *
319
+ * @example
320
+ * ```typescript
321
+ * const result = await service.executePrivateTransfer({
322
+ * sender: wallet.publicKey,
323
+ * recipientMetaAddress: 'sip:solana:0x...',
324
+ * amount: 1_000_000_000n,
325
+ * token: 'So11...',
326
+ * privacyLevel: 'shielded',
327
+ * })
328
+ *
329
+ * // ALWAYS check success first
330
+ * if (!result.success) {
331
+ * console.error('Failed:', result.error)
332
+ * return
333
+ * }
334
+ *
335
+ * // Now safe to access fields
336
+ * console.log('Stealth:', result.stealthAddress)
337
+ * console.log('C-SPL:', result.csplMint)
338
+ * ```
339
+ */
340
+ async executePrivateTransfer(
341
+ params: CombinedTransferParams
342
+ ): Promise<CombinedTransferResult> {
343
+ const startTime = Date.now()
344
+
345
+ if (!this.initialized) {
346
+ return {
347
+ success: false,
348
+ error: 'Service not initialized. Call initialize() first.',
349
+ }
350
+ }
351
+
352
+ // Validate inputs
353
+ const validation = this.validateTransferParams(params)
354
+ if (!validation.valid) {
355
+ return {
356
+ success: false,
357
+ error: validation.error,
358
+ }
359
+ }
360
+
361
+ try {
362
+ // Step 1: Wrap SPL to C-SPL
363
+ const wrapStartTime = Date.now()
364
+ const wrapResult = await this.csplService.wrap({
365
+ mint: params.token,
366
+ amount: params.amount,
367
+ owner: params.sender,
368
+ })
369
+
370
+ // CRITICAL: Check wrapResult.success BEFORE accessing fields!
371
+ // This is the fix for issue #527 - never use non-null assertion
372
+ // on result fields without first checking success.
373
+ if (!wrapResult.success) {
374
+ return {
375
+ success: false,
376
+ error: `Failed to wrap tokens: ${wrapResult.error}`,
377
+ }
378
+ }
379
+
380
+ const wrapDuration = Date.now() - wrapStartTime
381
+
382
+ // Now safe to access wrapResult fields since success is true
383
+ const csplMint = wrapResult.csplMint
384
+ const encryptedBalance = wrapResult.encryptedBalance
385
+
386
+ // Step 2: Derive stealth address for recipient
387
+ const stealthResult = await this.deriveStealthAddress(params.recipientMetaAddress)
388
+
389
+ // Check stealthResult.success before accessing fields
390
+ if (!stealthResult.success) {
391
+ return {
392
+ success: false,
393
+ error: `Failed to derive stealth address: ${stealthResult.error}`,
394
+ }
395
+ }
396
+
397
+ const stealthAddress = stealthResult.stealthAddress
398
+
399
+ // Step 3: Execute transfer via SIP Native backend
400
+ const transferStartTime = Date.now()
401
+
402
+ // Note: Using SIP Native for the actual transfer with stealth address
403
+ // The C-SPL wrapping provides encrypted amounts, SIP Native provides
404
+ // stealth addresses for unlinkable recipients
405
+ const transferResult = await this.sipNativeBackend.execute({
406
+ chain: 'solana',
407
+ sender: params.sender,
408
+ recipient: stealthAddress!,
409
+ mint: csplMint!,
410
+ amount: params.amount,
411
+ decimals: 9, // TODO(#645): Get from token metadata
412
+ viewingKey: params.viewingKey,
413
+ })
414
+
415
+ // Check transferResult.success
416
+ if (!transferResult.success) {
417
+ return {
418
+ success: false,
419
+ error: `Failed to execute transfer: ${transferResult.error}`,
420
+ }
421
+ }
422
+
423
+ const transferDuration = Date.now() - transferStartTime
424
+ const totalDuration = Date.now() - startTime
425
+
426
+ // All steps succeeded - return complete result
427
+ return {
428
+ success: true,
429
+ stealthAddress: stealthAddress,
430
+ csplMint: csplMint,
431
+ encryptedBalance: encryptedBalance,
432
+ wrapSignature: wrapResult.signature,
433
+ transferSignature: transferResult.signature,
434
+ signatures: [wrapResult.signature!, transferResult.signature!].filter(Boolean),
435
+ metadata: {
436
+ privacyLevel: params.privacyLevel,
437
+ hasViewingKey: !!params.viewingKey,
438
+ wrapDuration,
439
+ transferDuration,
440
+ totalDuration,
441
+ },
442
+ }
443
+ } catch (error) {
444
+ return {
445
+ success: false,
446
+ error: error instanceof Error ? error.message : 'Unknown error during transfer',
447
+ }
448
+ }
449
+ }
450
+
451
+ /**
452
+ * Derive a one-time stealth address from a recipient's meta-address
453
+ *
454
+ * Stealth addresses provide unlinkable recipients — each payment creates a unique
455
+ * address that only the recipient can identify and claim. This prevents linking
456
+ * multiple payments to the same recipient.
457
+ *
458
+ * ## Meta-Address Format
459
+ *
460
+ * The meta-address must follow the SIP format: `sip:<chain>:<spendingKey>:<viewingKey>`
461
+ *
462
+ * - `chain` — The blockchain (e.g., "solana", "ethereum")
463
+ * - `spendingKey` — Recipient's public spending key (controls funds)
464
+ * - `viewingKey` — Recipient's public viewing key (for scanning)
465
+ *
466
+ * ## Return Value
467
+ *
468
+ * On success, returns:
469
+ * - `stealthAddress` — The derived one-time address to send funds to
470
+ * - `ephemeralPubkey` — Must be published so recipient can compute private key
471
+ * - `viewTag` — Optimization for efficient payment scanning (0-255)
472
+ *
473
+ * IMPORTANT: Always check `result.success` before accessing other fields.
474
+ *
475
+ * @param metaAddress - SIP meta-address in format `sip:<chain>:<spendingKey>:<viewingKey>`
476
+ * @returns Stealth address result with success status
477
+ *
478
+ * @example
479
+ * ```typescript
480
+ * const result = await service.deriveStealthAddress(
481
+ * 'sip:solana:0x02abc...123:0x03def...456'
482
+ * )
483
+ *
484
+ * if (!result.success) {
485
+ * console.error('Failed:', result.error)
486
+ * return
487
+ * }
488
+ *
489
+ * // Now safe to access fields
490
+ * console.log('Send to:', result.stealthAddress)
491
+ * console.log('Publish:', result.ephemeralPubkey)
492
+ * console.log('View tag:', result.viewTag)
493
+ * ```
494
+ */
495
+ async deriveStealthAddress(metaAddress: string): Promise<StealthAddressResult> {
496
+ // Parse meta-address
497
+ const parts = metaAddress.split(':')
498
+ if (parts.length !== 4 || parts[0] !== 'sip') {
499
+ return {
500
+ success: false,
501
+ error: `Invalid meta-address format. Expected: sip:<chain>:<spendingKey>:<viewingKey>, got: ${metaAddress}`,
502
+ }
503
+ }
504
+
505
+ const [, chain, spendingKey, viewingKey] = parts
506
+
507
+ if (!chain || !spendingKey || !viewingKey) {
508
+ return {
509
+ success: false,
510
+ error: 'Meta-address must contain chain, spending key, and viewing key',
511
+ }
512
+ }
513
+
514
+ try {
515
+ // In production, this would:
516
+ // 1. Generate ephemeral keypair
517
+ // 2. Compute shared secret with recipient's viewing key
518
+ // 3. Derive stealth address from spending key + shared secret
519
+
520
+ // Simulated stealth address derivation
521
+ const simulatedEphemeralPubkey = `eph_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`
522
+ const simulatedStealthAddress = `stealth_${chain}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`
523
+ const viewTag = Math.floor(Math.random() * 256)
524
+
525
+ return {
526
+ success: true,
527
+ stealthAddress: simulatedStealthAddress,
528
+ ephemeralPubkey: simulatedEphemeralPubkey,
529
+ viewTag,
530
+ }
531
+ } catch (error) {
532
+ return {
533
+ success: false,
534
+ error: error instanceof Error ? error.message : 'Failed to derive stealth address',
535
+ }
536
+ }
537
+ }
538
+
539
+ /**
540
+ * Claim tokens from a stealth address
541
+ *
542
+ * Recipients use this method to claim funds sent to their stealth addresses.
543
+ * The ephemeral public key (published by sender) is combined with the
544
+ * recipient's private viewing key to derive the stealth private key.
545
+ *
546
+ * ## Required Parameters
547
+ *
548
+ * - `stealthAddress` — The stealth address containing funds
549
+ * - `ephemeralPubkey` — The sender's ephemeral public key (from announcement)
550
+ * - `spendingPrivateKey` — Recipient's private spending key
551
+ * - `viewingPrivateKey` — Recipient's private viewing key
552
+ *
553
+ * ## Process
554
+ *
555
+ * 1. Computes shared secret from ephemeralPubkey + viewingPrivateKey
556
+ * 2. Derives stealth private key from spendingPrivateKey + shared secret
557
+ * 3. Creates claim transaction signed with stealth private key
558
+ * 4. Unwraps C-SPL back to regular SPL token
559
+ *
560
+ * IMPORTANT: Always check `result.success` before accessing other fields.
561
+ *
562
+ * @param params - Claim parameters including keys and addresses
563
+ * @returns Claim result with amount and transaction signature
564
+ *
565
+ * @example
566
+ * ```typescript
567
+ * const result = await service.claimFromStealth({
568
+ * stealthAddress: 'stealth_solana_...',
569
+ * ephemeralPubkey: 'eph_...',
570
+ * spendingPrivateKey: 'spending_priv_...',
571
+ * viewingPrivateKey: 'viewing_priv_...',
572
+ * })
573
+ *
574
+ * if (!result.success) {
575
+ * console.error('Claim failed:', result.error)
576
+ * return
577
+ * }
578
+ *
579
+ * console.log('Claimed:', result.amount, 'tokens')
580
+ * console.log('Transaction:', result.signature)
581
+ * ```
582
+ */
583
+ async claimFromStealth(params: ClaimParams): Promise<ClaimResult> {
584
+ if (!this.initialized) {
585
+ return {
586
+ success: false,
587
+ error: 'Service not initialized. Call initialize() first.',
588
+ }
589
+ }
590
+
591
+ // Validate inputs
592
+ if (!params.stealthAddress || !params.ephemeralPubkey) {
593
+ return {
594
+ success: false,
595
+ error: 'stealthAddress and ephemeralPubkey are required',
596
+ }
597
+ }
598
+
599
+ if (!params.spendingPrivateKey || !params.viewingPrivateKey) {
600
+ return {
601
+ success: false,
602
+ error: 'Both spending and viewing private keys are required',
603
+ }
604
+ }
605
+
606
+ try {
607
+ // In production, this would:
608
+ // 1. Compute shared secret from ephemeralPubkey + viewingPrivateKey
609
+ // 2. Derive stealth private key from spendingPrivateKey + shared secret
610
+ // 3. Create claim transaction signed with stealth private key
611
+ // 4. Unwrap C-SPL back to SPL
612
+
613
+ // Simulated claim
614
+ const simulatedSignature = `claim_${Date.now()}_${Math.random().toString(36).slice(2)}`
615
+ const simulatedAmount = BigInt(1_000_000_000) // 1 token (simulated)
616
+
617
+ return {
618
+ success: true,
619
+ amount: simulatedAmount,
620
+ signature: simulatedSignature,
621
+ }
622
+ } catch (error) {
623
+ return {
624
+ success: false,
625
+ error: error instanceof Error ? error.message : 'Failed to claim from stealth',
626
+ }
627
+ }
628
+ }
629
+
630
+ /**
631
+ * Estimate the total cost for a combined privacy transfer
632
+ *
633
+ * Returns a breakdown of costs across all privacy layers:
634
+ * - `wrapCost` — Cost to wrap SPL into C-SPL (encrypted balance)
635
+ * - `stealthCost` — Cost for stealth address derivation (client-side, 0)
636
+ * - `transferCost` — Cost for the SIP Native transfer
637
+ * - `totalCost` — Sum of all costs
638
+ *
639
+ * All costs are in lamports (1 SOL = 1,000,000,000 lamports).
640
+ *
641
+ * @param params - Transfer parameters (sender, recipient, amount, token)
642
+ * @returns Cost breakdown with individual and total costs
643
+ *
644
+ * @example
645
+ * ```typescript
646
+ * const costs = await service.estimateCost({
647
+ * sender: wallet.publicKey,
648
+ * recipientMetaAddress: 'sip:solana:0x...',
649
+ * amount: 1_000_000_000n,
650
+ * token: 'So11...',
651
+ * })
652
+ *
653
+ * console.log('Wrap cost:', costs.wrapCost, 'lamports')
654
+ * console.log('Transfer cost:', costs.transferCost, 'lamports')
655
+ * console.log('Total:', costs.totalCost, 'lamports')
656
+ * ```
657
+ */
658
+ async estimateCost(params: CombinedTransferParams): Promise<CostBreakdown> {
659
+ // Wrap cost
660
+ const wrapCost = await this.csplService.estimateCost('wrap')
661
+
662
+ // Stealth address derivation is client-side, minimal cost
663
+ const stealthCost = BigInt(0)
664
+
665
+ // Transfer cost from SIP Native
666
+ const transferCost = await this.sipNativeBackend.estimateCost({
667
+ chain: 'solana',
668
+ sender: params.sender,
669
+ recipient: params.recipientMetaAddress,
670
+ mint: params.token,
671
+ amount: params.amount,
672
+ decimals: 9,
673
+ })
674
+
675
+ return {
676
+ wrapCost,
677
+ stealthCost,
678
+ transferCost,
679
+ totalCost: wrapCost + stealthCost + transferCost,
680
+ currency: 'lamports',
681
+ }
682
+ }
683
+
684
+ /**
685
+ * Get a comparison of privacy features across backends
686
+ *
687
+ * Compares privacy capabilities between:
688
+ * - **SIP Native** — Stealth addresses + Pedersen commitments + viewing keys
689
+ * - **Arcium C-SPL** — Encrypted balances + MPC compute
690
+ * - **Combined** — Full privacy using both layers
691
+ *
692
+ * Privacy dimensions:
693
+ * - `hiddenSender` — Sender identity is not revealed on-chain
694
+ * - `hiddenRecipient` — Recipient identity is unlinkable
695
+ * - `hiddenAmount` — Transfer amount is encrypted/committed
696
+ * - `hiddenCompute` — Contract execution is private
697
+ * - `compliance` — Selective disclosure available for auditors
698
+ *
699
+ * @returns Privacy comparison for each backend and combined approach
700
+ *
701
+ * @example
702
+ * ```typescript
703
+ * const comparison = service.getPrivacyComparison()
704
+ *
705
+ * console.log('SIP Native hides sender:', comparison.sipNative.hiddenSender)
706
+ * console.log('Combined full privacy:', comparison.combined)
707
+ * ```
708
+ */
709
+ getPrivacyComparison(): PrivacyComparison {
710
+ return {
711
+ sipNative: {
712
+ hiddenSender: true,
713
+ hiddenRecipient: true,
714
+ hiddenAmount: true, // Pedersen commitments
715
+ hiddenCompute: false,
716
+ compliance: true, // Viewing keys
717
+ },
718
+ arciumCSPL: {
719
+ hiddenSender: false,
720
+ hiddenRecipient: false,
721
+ hiddenAmount: true, // Encrypted balances
722
+ hiddenCompute: true, // MPC
723
+ compliance: false,
724
+ },
725
+ combined: {
726
+ hiddenSender: true, // From SIP Native
727
+ hiddenRecipient: true, // From SIP Native stealth addresses
728
+ hiddenAmount: true, // Both Pedersen and encrypted
729
+ hiddenCompute: true, // From Arcium when used
730
+ compliance: true, // From SIP Native viewing keys
731
+ },
732
+ }
733
+ }
734
+
735
+ /**
736
+ * Get the current status of the combined privacy service
737
+ *
738
+ * Returns status information for both underlying services:
739
+ * - `initialized` — Whether the service has been initialized
740
+ * - `csplStatus` — C-SPL service connection and token count
741
+ * - `sipNativeStatus` — SIP Native availability and chain support
742
+ *
743
+ * @returns Service status for monitoring and debugging
744
+ *
745
+ * @example
746
+ * ```typescript
747
+ * const status = service.getStatus()
748
+ *
749
+ * if (!status.initialized) {
750
+ * console.log('Service needs initialization')
751
+ * await service.initialize()
752
+ * }
753
+ *
754
+ * console.log('C-SPL connected:', status.csplStatus.connected)
755
+ * console.log('Registered tokens:', status.csplStatus.tokenCount)
756
+ * console.log('SIP Native available:', status.sipNativeStatus.available)
757
+ * ```
758
+ */
759
+ getStatus(): ServiceStatus {
760
+ const csplStatus = this.csplService.getStatus()
761
+ const sipNativeCaps = this.sipNativeBackend.getCapabilities()
762
+
763
+ return {
764
+ initialized: this.initialized,
765
+ csplStatus: {
766
+ connected: csplStatus.connected,
767
+ tokenCount: csplStatus.registeredTokenCount,
768
+ },
769
+ sipNativeStatus: {
770
+ available: sipNativeCaps.setupRequired === false,
771
+ chainCount: this.sipNativeBackend.chains.length,
772
+ },
773
+ }
774
+ }
775
+
776
+ /**
777
+ * Register a token for use with the service
778
+ *
779
+ * @param token - C-SPL token to register
780
+ */
781
+ registerToken(token: CSPLToken): void {
782
+ this.csplService.registerToken(token)
783
+ }
784
+
785
+ /**
786
+ * Disconnect and cleanup
787
+ */
788
+ async disconnect(): Promise<void> {
789
+ await this.csplService.disconnect()
790
+ this.initialized = false
791
+ }
792
+
793
+ // ─── Private Methods ─────────────────────────────────────────────────────────
794
+
795
+ /**
796
+ * Validate transfer parameters
797
+ */
798
+ private validateTransferParams(params: CombinedTransferParams): {
799
+ valid: boolean
800
+ error?: string
801
+ } {
802
+ if (!params.sender || params.sender.trim() === '') {
803
+ return { valid: false, error: 'Sender address is required' }
804
+ }
805
+
806
+ if (!params.recipientMetaAddress || params.recipientMetaAddress.trim() === '') {
807
+ return { valid: false, error: 'Recipient meta-address is required' }
808
+ }
809
+
810
+ if (!params.recipientMetaAddress.startsWith('sip:')) {
811
+ return {
812
+ valid: false,
813
+ error: 'Recipient must be a SIP meta-address (sip:chain:spending:viewing)',
814
+ }
815
+ }
816
+
817
+ if (params.amount <= BigInt(0)) {
818
+ return { valid: false, error: 'Amount must be greater than 0' }
819
+ }
820
+
821
+ if (!params.token || params.token.trim() === '') {
822
+ return { valid: false, error: 'Token mint address is required' }
823
+ }
824
+
825
+ if (params.privacyLevel === PrivacyLevel.COMPLIANT && !params.viewingKey) {
826
+ return {
827
+ valid: false,
828
+ error: 'Viewing key is required for compliant privacy level',
829
+ }
830
+ }
831
+
832
+ return { valid: true }
833
+ }
834
+ }
835
+
836
+ // ─── Factory Functions ─────────────────────────────────────────────────────────
837
+
838
+ /**
839
+ * Create a CombinedPrivacyService for devnet
840
+ *
841
+ * @param config - Optional additional configuration
842
+ * @returns Configured service for devnet
843
+ */
844
+ export function createCombinedPrivacyServiceDevnet(
845
+ config?: Partial<CombinedPrivacyServiceConfig>
846
+ ): CombinedPrivacyService {
847
+ return new CombinedPrivacyService({
848
+ ...config,
849
+ rpcUrl: config?.rpcUrl ?? 'https://api.devnet.solana.com',
850
+ })
851
+ }
852
+
853
+ /**
854
+ * Create a CombinedPrivacyService for mainnet
855
+ *
856
+ * @param config - Optional additional configuration
857
+ * @returns Configured service for mainnet
858
+ */
859
+ export function createCombinedPrivacyServiceMainnet(
860
+ config?: Partial<CombinedPrivacyServiceConfig>
861
+ ): CombinedPrivacyService {
862
+ return new CombinedPrivacyService({
863
+ ...config,
864
+ rpcUrl: config?.rpcUrl ?? 'https://api.mainnet-beta.solana.com',
865
+ })
866
+ }