@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,921 @@
1
+ /**
2
+ * Fireblocks Viewing Key API Integration
3
+ *
4
+ * Integrates viewing key API with Fireblocks, the leading institutional custody platform.
5
+ * Enables compliance officers using Fireblocks to access SIP Protocol transaction history
6
+ * with cryptographic privacy guarantees.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * import { FireblocksViewingKeyClient, createFireblocksClient } from '@sip-protocol/sdk'
11
+ *
12
+ * const client = createFireblocksClient({
13
+ * apiKey: process.env.FIREBLOCKS_API_KEY!,
14
+ * secretKey: process.env.FIREBLOCKS_SECRET_KEY!,
15
+ * vaultAccountId: 'vault-123',
16
+ * })
17
+ *
18
+ * // Register viewing key for compliance
19
+ * const registration = await client.registerViewingKey({
20
+ * viewingKey: orgViewingKey,
21
+ * auditorName: 'Compliance Team',
22
+ * scope: { transactionTypes: ['transfer', 'swap'] },
23
+ * })
24
+ *
25
+ * // Export transaction history for audit
26
+ * const history = await client.exportTransactionHistory({
27
+ * viewingKey: orgViewingKey,
28
+ * startDate: new Date('2025-01-01'),
29
+ * endDate: new Date('2025-12-31'),
30
+ * format: 'csv',
31
+ * })
32
+ * ```
33
+ *
34
+ * @see https://docs.fireblocks.com/api/
35
+ * @see https://docs.fireblocks.com/api/#signing-a-request
36
+ */
37
+
38
+ import { sha256 } from '@noble/hashes/sha256'
39
+ import { bytesToHex, hexToBytes } from '@noble/hashes/utils'
40
+ import type { ViewingKey, EncryptedTransaction, Hash } from '@sip-protocol/types'
41
+ import { decryptWithViewing, type TransactionData } from '../privacy'
42
+
43
+ /**
44
+ * Fireblocks API configuration
45
+ */
46
+ export interface FireblocksConfig {
47
+ /** Fireblocks API key */
48
+ apiKey: string
49
+ /** Fireblocks secret key (RSA private key for signing) */
50
+ secretKey: string
51
+ /** Vault account ID for operations */
52
+ vaultAccountId: string
53
+ /** Base URL (defaults to production) */
54
+ baseUrl?: string
55
+ /** Request timeout in ms (default: 30000) */
56
+ timeout?: number
57
+ /** Enable sandbox mode for testing */
58
+ sandbox?: boolean
59
+ }
60
+
61
+ /**
62
+ * Viewing key registration parameters
63
+ */
64
+ export interface RegisterViewingKeyParams {
65
+ /** The viewing key to register */
66
+ viewingKey: ViewingKey
67
+ /** Name of the auditor/compliance team */
68
+ auditorName: string
69
+ /** Scope of access */
70
+ scope: ViewingKeyScope
71
+ /** Expiration date (optional) */
72
+ expiresAt?: Date
73
+ /** Metadata for compliance records */
74
+ metadata?: Record<string, string>
75
+ }
76
+
77
+ /**
78
+ * Scope of viewing key access
79
+ */
80
+ export interface ViewingKeyScope {
81
+ /** Transaction types to include */
82
+ transactionTypes?: TransactionType[]
83
+ /** Chain IDs to include */
84
+ chains?: string[]
85
+ /** Token/asset addresses to include */
86
+ assets?: string[]
87
+ /** Minimum amount threshold */
88
+ minAmount?: bigint
89
+ /** Maximum amount threshold */
90
+ maxAmount?: bigint
91
+ /** Start date for transaction range */
92
+ startDate?: Date
93
+ /** End date for transaction range */
94
+ endDate?: Date
95
+ }
96
+
97
+ /**
98
+ * Transaction types for scoping
99
+ */
100
+ export type TransactionType =
101
+ | 'transfer'
102
+ | 'swap'
103
+ | 'deposit'
104
+ | 'withdrawal'
105
+ | 'stake'
106
+ | 'unstake'
107
+ | 'bridge'
108
+ | 'mint'
109
+ | 'burn'
110
+
111
+ /**
112
+ * Viewing key registration result
113
+ */
114
+ export interface ViewingKeyRegistration {
115
+ /** Registration ID */
116
+ id: string
117
+ /** Viewing key hash (for identification) */
118
+ viewingKeyHash: Hash
119
+ /** Auditor name */
120
+ auditorName: string
121
+ /** Access scope */
122
+ scope: ViewingKeyScope
123
+ /** When registered */
124
+ registeredAt: Date
125
+ /** When expires */
126
+ expiresAt?: Date
127
+ /** Registration status */
128
+ status: RegistrationStatus
129
+ /** Fireblocks vault account */
130
+ vaultAccountId: string
131
+ }
132
+
133
+ /**
134
+ * Registration status
135
+ */
136
+ export type RegistrationStatus = 'active' | 'expired' | 'revoked' | 'pending'
137
+
138
+ /**
139
+ * Transaction history export parameters
140
+ */
141
+ export interface ExportTransactionHistoryParams {
142
+ /** Viewing key for decryption */
143
+ viewingKey: ViewingKey
144
+ /** Start date */
145
+ startDate: Date
146
+ /** End date */
147
+ endDate: Date
148
+ /** Export format */
149
+ format: ExportFormat
150
+ /** Include raw encrypted data */
151
+ includeRaw?: boolean
152
+ /** Filter by transaction types */
153
+ transactionTypes?: TransactionType[]
154
+ /** Filter by chains */
155
+ chains?: string[]
156
+ /** Filter by assets */
157
+ assets?: string[]
158
+ }
159
+
160
+ /**
161
+ * Export format options
162
+ */
163
+ export type ExportFormat = 'json' | 'csv' | 'pdf'
164
+
165
+ /**
166
+ * Transaction history export result
167
+ */
168
+ export interface TransactionHistoryExport {
169
+ /** Export ID */
170
+ id: string
171
+ /** When generated */
172
+ generatedAt: Date
173
+ /** Export format */
174
+ format: ExportFormat
175
+ /** Number of transactions */
176
+ transactionCount: number
177
+ /** Date range */
178
+ dateRange: { start: Date; end: Date }
179
+ /** Export data (base64 for PDF, string for CSV, object for JSON) */
180
+ data: string | DecryptedTransaction[]
181
+ /** Checksum for verification */
182
+ checksum: Hash
183
+ }
184
+
185
+ /**
186
+ * Decrypted transaction for export
187
+ */
188
+ export interface DecryptedTransaction {
189
+ /** Transaction ID */
190
+ id: string
191
+ /** Transaction type */
192
+ type: TransactionType
193
+ /** Chain ID */
194
+ chain: string
195
+ /** Sender address (decrypted) */
196
+ sender: string
197
+ /** Recipient address (decrypted) */
198
+ recipient: string
199
+ /** Amount (decrypted) */
200
+ amount: string
201
+ /** Asset/token */
202
+ asset: string
203
+ /** Timestamp */
204
+ timestamp: Date
205
+ /** Fireblocks transaction ID (if available) */
206
+ fireblocksId?: string
207
+ /** Risk score (0-100) */
208
+ riskScore?: number
209
+ /** Tags/labels */
210
+ tags?: string[]
211
+ }
212
+
213
+ /**
214
+ * Compliance report parameters
215
+ */
216
+ export interface GenerateComplianceReportParams {
217
+ /** Viewing key for decryption */
218
+ viewingKey: ViewingKey
219
+ /** Report type */
220
+ reportType: ComplianceReportType
221
+ /** Reporting period start */
222
+ periodStart: Date
223
+ /** Reporting period end */
224
+ periodEnd: Date
225
+ /** Include transaction details */
226
+ includeDetails?: boolean
227
+ /** Include risk analysis */
228
+ includeRiskAnalysis?: boolean
229
+ /** Output format */
230
+ format: ExportFormat
231
+ }
232
+
233
+ /**
234
+ * Compliance report types
235
+ */
236
+ export type ComplianceReportType =
237
+ | 'transaction_summary'
238
+ | 'audit_trail'
239
+ | 'risk_assessment'
240
+ | 'regulatory_filing'
241
+ | 'tax_report'
242
+
243
+ /**
244
+ * Compliance report result
245
+ */
246
+ export interface ComplianceReport {
247
+ /** Report ID */
248
+ id: string
249
+ /** Report type */
250
+ type: ComplianceReportType
251
+ /** When generated */
252
+ generatedAt: Date
253
+ /** Reporting period */
254
+ period: { start: Date; end: Date }
255
+ /** Summary statistics */
256
+ summary: {
257
+ totalTransactions: number
258
+ totalVolume: string
259
+ uniqueCounterparties: number
260
+ averageRiskScore: number
261
+ flaggedTransactions: number
262
+ }
263
+ /** Report data */
264
+ data: string | Record<string, unknown>
265
+ /** Format */
266
+ format: ExportFormat
267
+ /** Checksum */
268
+ checksum: Hash
269
+ }
270
+
271
+ /**
272
+ * Fireblocks API error
273
+ */
274
+ export class FireblocksError extends Error {
275
+ code: FireblocksErrorCode
276
+ statusCode?: number
277
+ details?: unknown
278
+
279
+ constructor(message: string, code: FireblocksErrorCode, statusCode?: number, details?: unknown) {
280
+ super(message)
281
+ this.name = 'FireblocksError'
282
+ this.code = code
283
+ this.statusCode = statusCode
284
+ this.details = details
285
+ }
286
+ }
287
+
288
+ /**
289
+ * Error codes for Fireblocks integration
290
+ */
291
+ export enum FireblocksErrorCode {
292
+ AUTHENTICATION_FAILED = 'AUTHENTICATION_FAILED',
293
+ INVALID_VIEWING_KEY = 'INVALID_VIEWING_KEY',
294
+ REGISTRATION_FAILED = 'REGISTRATION_FAILED',
295
+ EXPORT_FAILED = 'EXPORT_FAILED',
296
+ DECRYPTION_FAILED = 'DECRYPTION_FAILED',
297
+ API_ERROR = 'API_ERROR',
298
+ RATE_LIMITED = 'RATE_LIMITED',
299
+ TIMEOUT = 'TIMEOUT',
300
+ INVALID_SCOPE = 'INVALID_SCOPE',
301
+ }
302
+
303
+ /**
304
+ * Fireblocks Viewing Key Client
305
+ *
306
+ * Integrates SIP Protocol viewing keys with Fireblocks institutional custody.
307
+ */
308
+ export class FireblocksViewingKeyClient {
309
+ private readonly apiKey: string
310
+ private readonly secretKey: string
311
+ private readonly vaultAccountId: string
312
+
313
+ /** In-memory registration storage (production would use secure backend) */
314
+ private registrations: Map<string, ViewingKeyRegistration> = new Map()
315
+ private exports: Map<string, TransactionHistoryExport> = new Map()
316
+ private reports: Map<string, ComplianceReport> = new Map()
317
+
318
+ constructor(config: FireblocksConfig) {
319
+ this.apiKey = config.apiKey
320
+ this.secretKey = config.secretKey
321
+ this.vaultAccountId = config.vaultAccountId
322
+ }
323
+
324
+ /**
325
+ * Register a viewing key for compliance access
326
+ *
327
+ * @param params - Registration parameters
328
+ * @returns Registration result
329
+ */
330
+ async registerViewingKey(params: RegisterViewingKeyParams): Promise<ViewingKeyRegistration> {
331
+ // Validate viewing key
332
+ if (!this.isValidViewingKey(params.viewingKey)) {
333
+ throw new FireblocksError(
334
+ 'Invalid viewing key format',
335
+ FireblocksErrorCode.INVALID_VIEWING_KEY
336
+ )
337
+ }
338
+
339
+ // Validate scope
340
+ if (!this.isValidScope(params.scope)) {
341
+ throw new FireblocksError(
342
+ 'Invalid scope configuration',
343
+ FireblocksErrorCode.INVALID_SCOPE
344
+ )
345
+ }
346
+
347
+ // Compute viewing key hash for identification
348
+ const viewingKeyHash = this.computeViewingKeyHash(params.viewingKey)
349
+
350
+ // Check for existing registration
351
+ const existing = Array.from(this.registrations.values())
352
+ .find(r => r.viewingKeyHash === viewingKeyHash && r.status === 'active')
353
+
354
+ if (existing) {
355
+ throw new FireblocksError(
356
+ 'Viewing key already registered',
357
+ FireblocksErrorCode.REGISTRATION_FAILED
358
+ )
359
+ }
360
+
361
+ // Create registration
362
+ const registration: ViewingKeyRegistration = {
363
+ id: this.generateId('reg'),
364
+ viewingKeyHash,
365
+ auditorName: params.auditorName,
366
+ scope: params.scope,
367
+ registeredAt: new Date(),
368
+ expiresAt: params.expiresAt,
369
+ status: 'active',
370
+ vaultAccountId: this.vaultAccountId,
371
+ }
372
+
373
+ // Store registration
374
+ this.registrations.set(registration.id, registration)
375
+
376
+ // In production, this would sync to Fireblocks via API
377
+ // await this.syncRegistrationToFireblocks(registration)
378
+
379
+ return registration
380
+ }
381
+
382
+ /**
383
+ * Get a viewing key registration
384
+ *
385
+ * @param registrationId - Registration ID
386
+ * @returns Registration or null
387
+ */
388
+ getRegistration(registrationId: string): ViewingKeyRegistration | null {
389
+ return this.registrations.get(registrationId) ?? null
390
+ }
391
+
392
+ /**
393
+ * List all registrations for the vault
394
+ *
395
+ * @returns All registrations
396
+ */
397
+ listRegistrations(): ViewingKeyRegistration[] {
398
+ return Array.from(this.registrations.values())
399
+ .filter(r => r.vaultAccountId === this.vaultAccountId)
400
+ }
401
+
402
+ /**
403
+ * Revoke a viewing key registration
404
+ *
405
+ * @param registrationId - Registration to revoke
406
+ * @param reason - Reason for revocation
407
+ */
408
+ async revokeRegistration(registrationId: string, reason: string): Promise<void> {
409
+ const registration = this.registrations.get(registrationId)
410
+
411
+ if (!registration) {
412
+ throw new FireblocksError(
413
+ 'Registration not found',
414
+ FireblocksErrorCode.REGISTRATION_FAILED
415
+ )
416
+ }
417
+
418
+ registration.status = 'revoked'
419
+ this.registrations.set(registrationId, registration)
420
+
421
+ // In production, sync revocation to Fireblocks
422
+ // await this.syncRevocationToFireblocks(registrationId, reason)
423
+ }
424
+
425
+ /**
426
+ * Export transaction history using viewing key
427
+ *
428
+ * @param params - Export parameters
429
+ * @param encryptedTransactions - Encrypted transactions to export
430
+ * @returns Export result
431
+ */
432
+ async exportTransactionHistory(
433
+ params: ExportTransactionHistoryParams,
434
+ encryptedTransactions: EncryptedTransaction[]
435
+ ): Promise<TransactionHistoryExport> {
436
+ // Validate viewing key
437
+ if (!this.isValidViewingKey(params.viewingKey)) {
438
+ throw new FireblocksError(
439
+ 'Invalid viewing key',
440
+ FireblocksErrorCode.INVALID_VIEWING_KEY
441
+ )
442
+ }
443
+
444
+ // Verify viewing key is registered
445
+ const viewingKeyHash = this.computeViewingKeyHash(params.viewingKey)
446
+ const registration = Array.from(this.registrations.values())
447
+ .find(r => r.viewingKeyHash === viewingKeyHash && r.status === 'active')
448
+
449
+ if (!registration) {
450
+ throw new FireblocksError(
451
+ 'Viewing key not registered or inactive',
452
+ FireblocksErrorCode.INVALID_VIEWING_KEY
453
+ )
454
+ }
455
+
456
+ // Decrypt transactions
457
+ const decryptedTransactions: DecryptedTransaction[] = []
458
+
459
+ for (const encrypted of encryptedTransactions) {
460
+ try {
461
+ // Verify viewing key hash matches
462
+ if (encrypted.viewingKeyHash !== viewingKeyHash) {
463
+ continue // Skip transactions encrypted with different key
464
+ }
465
+
466
+ const decrypted = decryptWithViewing(encrypted, params.viewingKey)
467
+
468
+ // Apply filters
469
+ if (params.startDate && new Date(decrypted.timestamp) < params.startDate) continue
470
+ if (params.endDate && new Date(decrypted.timestamp) > params.endDate) continue
471
+
472
+ decryptedTransactions.push(this.mapToDecryptedTransaction(decrypted, encrypted))
473
+ } catch {
474
+ // Skip transactions that can't be decrypted
475
+ continue
476
+ }
477
+ }
478
+
479
+ // Format export
480
+ let data: string | DecryptedTransaction[]
481
+
482
+ switch (params.format) {
483
+ case 'json':
484
+ data = decryptedTransactions
485
+ break
486
+ case 'csv':
487
+ data = this.formatAsCsv(decryptedTransactions)
488
+ break
489
+ case 'pdf':
490
+ data = this.formatAsPdfBase64(decryptedTransactions)
491
+ break
492
+ }
493
+
494
+ // Create export record
495
+ const exportResult: TransactionHistoryExport = {
496
+ id: this.generateId('exp'),
497
+ generatedAt: new Date(),
498
+ format: params.format,
499
+ transactionCount: decryptedTransactions.length,
500
+ dateRange: { start: params.startDate, end: params.endDate },
501
+ data,
502
+ checksum: this.computeChecksum(data),
503
+ }
504
+
505
+ this.exports.set(exportResult.id, exportResult)
506
+
507
+ return exportResult
508
+ }
509
+
510
+ /**
511
+ * Generate a compliance report
512
+ *
513
+ * @param params - Report parameters
514
+ * @param encryptedTransactions - Encrypted transactions
515
+ * @returns Compliance report
516
+ */
517
+ async generateComplianceReport(
518
+ params: GenerateComplianceReportParams,
519
+ encryptedTransactions: EncryptedTransaction[]
520
+ ): Promise<ComplianceReport> {
521
+ // First, export transaction history
522
+ const historyExport = await this.exportTransactionHistory(
523
+ {
524
+ viewingKey: params.viewingKey,
525
+ startDate: params.periodStart,
526
+ endDate: params.periodEnd,
527
+ format: 'json',
528
+ },
529
+ encryptedTransactions
530
+ )
531
+
532
+ const transactions = historyExport.data as DecryptedTransaction[]
533
+
534
+ // Compute summary statistics
535
+ const summary = this.computeSummaryStats(transactions)
536
+
537
+ // Generate report based on type
538
+ let reportData: Record<string, unknown>
539
+
540
+ switch (params.reportType) {
541
+ case 'transaction_summary':
542
+ reportData = this.generateTransactionSummary(transactions, params.includeDetails)
543
+ break
544
+ case 'audit_trail':
545
+ reportData = this.generateAuditTrail(transactions)
546
+ break
547
+ case 'risk_assessment':
548
+ reportData = this.generateRiskAssessment(transactions)
549
+ break
550
+ case 'regulatory_filing':
551
+ reportData = this.generateRegulatoryFiling(transactions)
552
+ break
553
+ case 'tax_report':
554
+ reportData = this.generateTaxReport(transactions)
555
+ break
556
+ }
557
+
558
+ // Format output
559
+ let data: string | Record<string, unknown>
560
+
561
+ switch (params.format) {
562
+ case 'json':
563
+ data = reportData
564
+ break
565
+ case 'csv':
566
+ data = this.formatReportAsCsv(reportData)
567
+ break
568
+ case 'pdf':
569
+ data = this.formatReportAsPdfBase64(reportData)
570
+ break
571
+ }
572
+
573
+ const report: ComplianceReport = {
574
+ id: this.generateId('rpt'),
575
+ type: params.reportType,
576
+ generatedAt: new Date(),
577
+ period: { start: params.periodStart, end: params.periodEnd },
578
+ summary,
579
+ data,
580
+ format: params.format,
581
+ checksum: this.computeChecksum(data),
582
+ }
583
+
584
+ this.reports.set(report.id, report)
585
+
586
+ return report
587
+ }
588
+
589
+ /**
590
+ * Get a previously generated report
591
+ *
592
+ * @param reportId - Report ID
593
+ * @returns Report or null
594
+ */
595
+ getReport(reportId: string): ComplianceReport | null {
596
+ return this.reports.get(reportId) ?? null
597
+ }
598
+
599
+ /**
600
+ * Verify API connectivity to Fireblocks
601
+ *
602
+ * @returns Whether connection is successful
603
+ */
604
+ async verifyConnection(): Promise<boolean> {
605
+ try {
606
+ // In production, this would make an authenticated API call
607
+ // For now, validate configuration
608
+ return !!(this.apiKey && this.secretKey && this.vaultAccountId)
609
+ } catch {
610
+ return false
611
+ }
612
+ }
613
+
614
+ /**
615
+ * Validate viewing key format
616
+ */
617
+ private isValidViewingKey(viewingKey: ViewingKey): boolean {
618
+ if (!viewingKey.key || !viewingKey.path || !viewingKey.hash) {
619
+ return false
620
+ }
621
+
622
+ // Must be hex string starting with 0x
623
+ if (!viewingKey.key.startsWith('0x') || viewingKey.key.length < 66) {
624
+ return false
625
+ }
626
+
627
+ return true
628
+ }
629
+
630
+ /**
631
+ * Validate scope configuration
632
+ */
633
+ private isValidScope(scope: ViewingKeyScope): boolean {
634
+ if (scope.startDate && scope.endDate && scope.startDate > scope.endDate) {
635
+ return false
636
+ }
637
+
638
+ if (scope.minAmount !== undefined && scope.maxAmount !== undefined) {
639
+ if (scope.minAmount > scope.maxAmount) {
640
+ return false
641
+ }
642
+ }
643
+
644
+ return true
645
+ }
646
+
647
+ /**
648
+ * Compute viewing key hash
649
+ */
650
+ private computeViewingKeyHash(viewingKey: ViewingKey): Hash {
651
+ const keyBytes = hexToBytes(viewingKey.key.slice(2))
652
+ const hash = sha256(keyBytes)
653
+ return `0x${bytesToHex(hash)}` as Hash
654
+ }
655
+
656
+ /**
657
+ * Generate unique ID
658
+ */
659
+ private generateId(prefix: string): string {
660
+ const timestamp = Date.now().toString(36)
661
+ const random = Math.random().toString(36).slice(2, 10)
662
+ return `${prefix}_${timestamp}_${random}`
663
+ }
664
+
665
+ /**
666
+ * Map decrypted data to transaction format
667
+ */
668
+ private mapToDecryptedTransaction(
669
+ decrypted: TransactionData,
670
+ _encrypted: EncryptedTransaction
671
+ ): DecryptedTransaction {
672
+ return {
673
+ id: this.generateId('tx'),
674
+ type: 'transfer', // Default type
675
+ chain: 'solana', // Would be extracted from metadata
676
+ sender: decrypted.sender,
677
+ recipient: decrypted.recipient,
678
+ amount: decrypted.amount.toString(),
679
+ asset: 'USDC', // Would be extracted from metadata
680
+ timestamp: new Date(decrypted.timestamp),
681
+ }
682
+ }
683
+
684
+ /**
685
+ * Format transactions as CSV
686
+ */
687
+ private formatAsCsv(transactions: DecryptedTransaction[]): string {
688
+ const headers = [
689
+ 'id',
690
+ 'type',
691
+ 'chain',
692
+ 'sender',
693
+ 'recipient',
694
+ 'amount',
695
+ 'asset',
696
+ 'timestamp',
697
+ 'riskScore',
698
+ ]
699
+
700
+ const rows = transactions.map(tx =>
701
+ [
702
+ tx.id,
703
+ tx.type,
704
+ tx.chain,
705
+ tx.sender,
706
+ tx.recipient,
707
+ tx.amount,
708
+ tx.asset,
709
+ tx.timestamp.toISOString(),
710
+ tx.riskScore ?? '',
711
+ ].join(',')
712
+ )
713
+
714
+ return [headers.join(','), ...rows].join('\n')
715
+ }
716
+
717
+ /**
718
+ * Format transactions as PDF (base64)
719
+ */
720
+ private formatAsPdfBase64(transactions: DecryptedTransaction[]): string {
721
+ // In production, would use a PDF library
722
+ // For now, return a placeholder
723
+ const content = JSON.stringify({
724
+ title: 'SIP Protocol Transaction History',
725
+ generatedAt: new Date().toISOString(),
726
+ transactionCount: transactions.length,
727
+ transactions: transactions.map(tx => ({
728
+ id: tx.id,
729
+ type: tx.type,
730
+ amount: tx.amount,
731
+ timestamp: tx.timestamp,
732
+ })),
733
+ })
734
+
735
+ return Buffer.from(content).toString('base64')
736
+ }
737
+
738
+ /**
739
+ * Compute summary statistics
740
+ */
741
+ private computeSummaryStats(transactions: DecryptedTransaction[]): ComplianceReport['summary'] {
742
+ const uniqueCounterparties = new Set([
743
+ ...transactions.map(tx => tx.sender),
744
+ ...transactions.map(tx => tx.recipient),
745
+ ])
746
+
747
+ const riskScores = transactions
748
+ .filter(tx => tx.riskScore !== undefined)
749
+ .map(tx => tx.riskScore!)
750
+
751
+ const totalVolume = transactions.reduce(
752
+ (sum, tx) => sum + BigInt(tx.amount),
753
+ 0n
754
+ )
755
+
756
+ return {
757
+ totalTransactions: transactions.length,
758
+ totalVolume: totalVolume.toString(),
759
+ uniqueCounterparties: uniqueCounterparties.size,
760
+ averageRiskScore: riskScores.length > 0
761
+ ? riskScores.reduce((a, b) => a + b, 0) / riskScores.length
762
+ : 0,
763
+ flaggedTransactions: transactions.filter(tx => (tx.riskScore ?? 0) >= 70).length,
764
+ }
765
+ }
766
+
767
+ /**
768
+ * Generate transaction summary report
769
+ */
770
+ private generateTransactionSummary(
771
+ transactions: DecryptedTransaction[],
772
+ includeDetails?: boolean
773
+ ): Record<string, unknown> {
774
+ const byType = new Map<TransactionType, number>()
775
+ const byChain = new Map<string, number>()
776
+ const byAsset = new Map<string, bigint>()
777
+
778
+ for (const tx of transactions) {
779
+ byType.set(tx.type, (byType.get(tx.type) ?? 0) + 1)
780
+ byChain.set(tx.chain, (byChain.get(tx.chain) ?? 0) + 1)
781
+ byAsset.set(tx.asset, (byAsset.get(tx.asset) ?? 0n) + BigInt(tx.amount))
782
+ }
783
+
784
+ return {
785
+ reportType: 'transaction_summary',
786
+ period: {
787
+ start: transactions[0]?.timestamp,
788
+ end: transactions[transactions.length - 1]?.timestamp,
789
+ },
790
+ breakdown: {
791
+ byType: Object.fromEntries(byType),
792
+ byChain: Object.fromEntries(byChain),
793
+ byAsset: Object.fromEntries(
794
+ Array.from(byAsset.entries()).map(([k, v]) => [k, v.toString()])
795
+ ),
796
+ },
797
+ transactions: includeDetails ? transactions : undefined,
798
+ }
799
+ }
800
+
801
+ /**
802
+ * Generate audit trail report
803
+ */
804
+ private generateAuditTrail(transactions: DecryptedTransaction[]): Record<string, unknown> {
805
+ return {
806
+ reportType: 'audit_trail',
807
+ entries: transactions.map(tx => ({
808
+ timestamp: tx.timestamp,
809
+ action: tx.type,
810
+ from: tx.sender,
811
+ to: tx.recipient,
812
+ amount: tx.amount,
813
+ asset: tx.asset,
814
+ chain: tx.chain,
815
+ id: tx.id,
816
+ })),
817
+ }
818
+ }
819
+
820
+ /**
821
+ * Generate risk assessment report
822
+ */
823
+ private generateRiskAssessment(transactions: DecryptedTransaction[]): Record<string, unknown> {
824
+ const highRisk = transactions.filter(tx => (tx.riskScore ?? 0) >= 70)
825
+ const mediumRisk = transactions.filter(tx =>
826
+ (tx.riskScore ?? 0) >= 30 && (tx.riskScore ?? 0) < 70
827
+ )
828
+ const lowRisk = transactions.filter(tx => (tx.riskScore ?? 0) < 30)
829
+
830
+ return {
831
+ reportType: 'risk_assessment',
832
+ distribution: {
833
+ high: highRisk.length,
834
+ medium: mediumRisk.length,
835
+ low: lowRisk.length,
836
+ },
837
+ flaggedTransactions: highRisk.map(tx => ({
838
+ id: tx.id,
839
+ riskScore: tx.riskScore,
840
+ reason: 'High value transaction', // Would be more detailed in production
841
+ })),
842
+ recommendations: [
843
+ 'Review high-risk transactions for suspicious activity',
844
+ 'Verify counterparty identities for flagged addresses',
845
+ ],
846
+ }
847
+ }
848
+
849
+ /**
850
+ * Generate regulatory filing report
851
+ */
852
+ private generateRegulatoryFiling(transactions: DecryptedTransaction[]): Record<string, unknown> {
853
+ return {
854
+ reportType: 'regulatory_filing',
855
+ filingType: 'SAR_PREP', // Suspicious Activity Report preparation
856
+ totalTransactions: transactions.length,
857
+ flaggedForReview: transactions.filter(tx => (tx.riskScore ?? 0) >= 70).length,
858
+ volumeAnalysis: this.computeSummaryStats(transactions),
859
+ attachments: ['transaction_detail', 'risk_assessment'],
860
+ }
861
+ }
862
+
863
+ /**
864
+ * Generate tax report
865
+ */
866
+ private generateTaxReport(transactions: DecryptedTransaction[]): Record<string, unknown> {
867
+ // Group by asset for cost basis tracking
868
+ const byAsset = new Map<string, DecryptedTransaction[]>()
869
+
870
+ for (const tx of transactions) {
871
+ const existing = byAsset.get(tx.asset) ?? []
872
+ existing.push(tx)
873
+ byAsset.set(tx.asset, existing)
874
+ }
875
+
876
+ return {
877
+ reportType: 'tax_report',
878
+ taxYear: transactions[0]?.timestamp.getFullYear(),
879
+ assets: Array.from(byAsset.entries()).map(([asset, txs]) => ({
880
+ asset,
881
+ transactionCount: txs.length,
882
+ totalVolume: txs.reduce((sum, tx) => sum + BigInt(tx.amount), 0n).toString(),
883
+ // Would include cost basis calculations in production
884
+ })),
885
+ disclaimer: 'This report is for informational purposes only. Consult a tax professional.',
886
+ }
887
+ }
888
+
889
+ /**
890
+ * Format report as CSV
891
+ */
892
+ private formatReportAsCsv(report: Record<string, unknown>): string {
893
+ return JSON.stringify(report) // Simplified for demo
894
+ }
895
+
896
+ /**
897
+ * Format report as PDF (base64)
898
+ */
899
+ private formatReportAsPdfBase64(report: Record<string, unknown>): string {
900
+ return Buffer.from(JSON.stringify(report)).toString('base64')
901
+ }
902
+
903
+ /**
904
+ * Compute checksum for data integrity
905
+ */
906
+ private computeChecksum(data: string | unknown): Hash {
907
+ const str = typeof data === 'string' ? data : JSON.stringify(data)
908
+ const hash = sha256(new TextEncoder().encode(str))
909
+ return `0x${bytesToHex(hash)}` as Hash
910
+ }
911
+ }
912
+
913
+ /**
914
+ * Create a Fireblocks viewing key client
915
+ *
916
+ * @param config - Fireblocks configuration
917
+ * @returns Configured client
918
+ */
919
+ export function createFireblocksClient(config: FireblocksConfig): FireblocksViewingKeyClient {
920
+ return new FireblocksViewingKeyClient(config)
921
+ }