@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,872 @@
1
+ /**
2
+ * Compliance Proof Module
3
+ *
4
+ * USER-SIDE tool for generating ZK proofs for regulatory compliance.
5
+ *
6
+ * ## IMPORTANT: Protocol Neutrality
7
+ *
8
+ * **This module is for USERS to prove compliance — NOT protocol-level enforcement.**
9
+ *
10
+ * SIP Protocol follows the Zcash model:
11
+ * - Protocol is neutral infrastructure (like TCP/IP)
12
+ * - Protocol does NOT screen, block, or filter transactions
13
+ * - Users CHOOSE to generate compliance proofs when they need them
14
+ * - Compliance is voluntary, not mandatory
15
+ *
16
+ * This is why Zcash avoided OFAC sanctions while Tornado Cash was sanctioned:
17
+ * Zcash provides compliance TOOLS (viewing keys), not enforcement.
18
+ *
19
+ * ## Use Cases
20
+ *
21
+ * 1. **Viewing Key Disclosure**: User proves to auditor they can decrypt a transaction
22
+ * without revealing the transaction details
23
+ *
24
+ * 2. **Sanctions Self-Check**: User proves they checked sanctions list (their choice)
25
+ * — NOT protocol blocking sanctioned addresses
26
+ *
27
+ * 3. **Balance Attestation**: User proves sufficient funds without revealing balance
28
+ *
29
+ * 4. **Tax Compliance**: User proves transaction history is complete for tax filing
30
+ *
31
+ * ## Architecture
32
+ *
33
+ * ```
34
+ * ┌─────────────────────────────────────────────────────────────┐
35
+ * │ USER-SIDE COMPLIANCE PROOFS │
36
+ * │ (Protocol remains neutral — user generates proofs by choice)
37
+ * │ │
38
+ * │ ┌─────────────────┐ ┌─────────────────┐ │
39
+ * │ │ User │ │ Auditor/ │ │
40
+ * │ │ (generates │───►│ Regulator │ │
41
+ * │ │ proof) │ │ (verifies) │ │
42
+ * │ └─────────────────┘ └─────────────────┘ │
43
+ * │ │
44
+ * │ What user can prove: │
45
+ * │ ✓ Transaction exists and is valid │
46
+ * │ ✓ User has viewing key access │
47
+ * │ ✓ User checked sanctions list (voluntary) │
48
+ * │ │
49
+ * │ What remains hidden: │
50
+ * │ ✗ Actual transaction amount │
51
+ * │ ✗ Sender/recipient identities (unless user discloses) │
52
+ * │ ✗ Transaction path │
53
+ * └─────────────────────────────────────────────────────────────┘
54
+ * ```
55
+ *
56
+ * @module proofs/compliance-proof
57
+ */
58
+
59
+ import type { ZKProof, ViewingKey } from '@sip-protocol/types'
60
+ import type { ProofResult } from './interface'
61
+ import { ProofGenerationError } from './interface'
62
+ import { ProofError, ErrorCode } from '../errors'
63
+
64
+ // ─── Types ───────────────────────────────────────────────────────────────────
65
+
66
+ /**
67
+ * Compliance proof types
68
+ */
69
+ export type ComplianceProofType =
70
+ | 'viewing_key_access' // Prove viewing key holder can access transaction
71
+ | 'sanctions_clear' // Prove no sanctions list matches
72
+ | 'balance_attestation' // Prove balance meets requirement
73
+ | 'history_complete' // Prove complete transaction history
74
+
75
+ /**
76
+ * Parameters for viewing key access proof
77
+ *
78
+ * Proves that the holder of a viewing key can decrypt a specific transaction
79
+ * without revealing the decrypted contents.
80
+ */
81
+ export interface ViewingKeyAccessParams {
82
+ /** The viewing key (private) */
83
+ viewingKey: ViewingKey
84
+ /** Transaction hash to prove access to */
85
+ transactionHash: string
86
+ /** Encrypted transaction data */
87
+ encryptedData: Uint8Array
88
+ /** Auditor's public key for verification */
89
+ auditorPublicKey: string
90
+ /** Timestamp of proof generation */
91
+ timestamp: number
92
+ /** Optional: Chain ID for multi-chain support */
93
+ chainId?: string
94
+ }
95
+
96
+ /**
97
+ * Parameters for sanctions clearance proof
98
+ *
99
+ * Proves that sender and recipient are not on a sanctions list
100
+ * without revealing their actual addresses.
101
+ */
102
+ export interface SanctionsClearParams {
103
+ /** Sender address (private) */
104
+ senderAddress: string
105
+ /** Recipient address (private) */
106
+ recipientAddress: string
107
+ /** Blinding factor for sender (private) */
108
+ senderBlinding: Uint8Array
109
+ /** Blinding factor for recipient (private) */
110
+ recipientBlinding: Uint8Array
111
+ /** Merkle root of known sanctions list (public) */
112
+ sanctionsListRoot: string
113
+ /** Timestamp of check */
114
+ checkTimestamp: number
115
+ /** Jurisdiction (e.g., "US", "EU") */
116
+ jurisdiction: string
117
+ }
118
+
119
+ /**
120
+ * Parameters for balance attestation proof
121
+ *
122
+ * Proves balance meets a threshold without revealing exact balance.
123
+ */
124
+ export interface BalanceAttestationParams {
125
+ /** Actual balance (private) */
126
+ balance: bigint
127
+ /** Blinding factor (private) */
128
+ blindingFactor: Uint8Array
129
+ /** Minimum required balance (public) */
130
+ minimumRequired: bigint
131
+ /** Asset identifier (public) */
132
+ assetId: string
133
+ /** Account identifier (public commitment) */
134
+ accountCommitment: string
135
+ /** Attestation timestamp */
136
+ attestationTime: number
137
+ }
138
+
139
+ /**
140
+ * Parameters for history completeness proof
141
+ *
142
+ * Proves that all transactions in a time range have been disclosed
143
+ * without revealing transaction amounts.
144
+ */
145
+ export interface HistoryCompletenessParams {
146
+ /** Transaction count in range (private) */
147
+ transactionCount: number
148
+ /** Merkle root of transaction hashes (public) */
149
+ historyMerkleRoot: string
150
+ /** Start of time range (public) */
151
+ startTimestamp: number
152
+ /** End of time range (public) */
153
+ endTimestamp: number
154
+ /** Total volume commitment (public) */
155
+ volumeCommitment: string
156
+ /** Viewing key for verification */
157
+ viewingKey: ViewingKey
158
+ }
159
+
160
+ /**
161
+ * Compliance proof result
162
+ */
163
+ export interface ComplianceProofResult extends ProofResult {
164
+ /** Type of compliance proof */
165
+ complianceType: ComplianceProofType
166
+ /** Expiry time for this proof (Unix timestamp) */
167
+ validUntil: number
168
+ /** Jurisdiction this proof is valid for */
169
+ jurisdiction?: string
170
+ /** Auditor verification hash */
171
+ auditorHash?: string
172
+ }
173
+
174
+ /**
175
+ * Compliance proof provider configuration
176
+ */
177
+ export interface ComplianceProofConfig {
178
+ /** Default proof validity period in seconds */
179
+ defaultValidityPeriod?: number
180
+ /** Enable verbose logging */
181
+ verbose?: boolean
182
+ /** Supported jurisdictions */
183
+ jurisdictions?: string[]
184
+ }
185
+
186
+ // ─── Constants ───────────────────────────────────────────────────────────────
187
+
188
+ /**
189
+ * Default proof validity period (24 hours)
190
+ */
191
+ export const DEFAULT_VALIDITY_PERIOD_SECONDS = 86400
192
+
193
+ /**
194
+ * Supported compliance jurisdictions
195
+ */
196
+ export const SUPPORTED_JURISDICTIONS = [
197
+ 'US', // United States
198
+ 'EU', // European Union
199
+ 'UK', // United Kingdom
200
+ 'SG', // Singapore
201
+ 'CH', // Switzerland
202
+ 'GLOBAL', // Global sanctions lists
203
+ ] as const
204
+
205
+ /**
206
+ * Compliance proof circuit IDs
207
+ */
208
+ export const COMPLIANCE_CIRCUIT_IDS = {
209
+ viewing_key_access: 'compliance_viewing_key_v1',
210
+ sanctions_clear: 'compliance_sanctions_v1',
211
+ balance_attestation: 'compliance_balance_v1',
212
+ history_complete: 'compliance_history_v1',
213
+ } as const
214
+
215
+ // ─── Provider ────────────────────────────────────────────────────────────────
216
+
217
+ /**
218
+ * Compliance Proof Provider
219
+ *
220
+ * Generates ZK proofs for regulatory compliance without revealing sensitive data.
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * const provider = new ComplianceProofProvider()
225
+ * await provider.initialize()
226
+ *
227
+ * // Prove viewing key access to auditor
228
+ * const result = await provider.generateViewingKeyAccessProof({
229
+ * viewingKey: myViewingKey,
230
+ * transactionHash: '0x...',
231
+ * encryptedData: encryptedTxData,
232
+ * auditorPublicKey: '0x...',
233
+ * timestamp: Date.now(),
234
+ * })
235
+ *
236
+ * // Share proof with auditor (they can verify without seeing data)
237
+ * await sendToAuditor(result.proof)
238
+ * ```
239
+ */
240
+ export class ComplianceProofProvider {
241
+ private config: Required<ComplianceProofConfig>
242
+ private _isReady = false
243
+
244
+ constructor(config: ComplianceProofConfig = {}) {
245
+ this.config = {
246
+ defaultValidityPeriod: config.defaultValidityPeriod ?? DEFAULT_VALIDITY_PERIOD_SECONDS,
247
+ verbose: config.verbose ?? false,
248
+ jurisdictions: config.jurisdictions ?? [...SUPPORTED_JURISDICTIONS],
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Check if provider is initialized
254
+ */
255
+ get isReady(): boolean {
256
+ return this._isReady
257
+ }
258
+
259
+ /**
260
+ * Initialize the compliance proof provider
261
+ */
262
+ async initialize(): Promise<void> {
263
+ if (this._isReady) {
264
+ return
265
+ }
266
+
267
+ if (this.config.verbose) {
268
+ console.log('[ComplianceProofProvider] Initializing...')
269
+ }
270
+
271
+ // In production, this would load compliance-specific circuits
272
+ // For now, we reuse the existing Noir circuits with compliance parameters
273
+
274
+ this._isReady = true
275
+
276
+ if (this.config.verbose) {
277
+ console.log('[ComplianceProofProvider] Ready')
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Generate a viewing key access proof
283
+ *
284
+ * Proves to an auditor that the holder of a viewing key can decrypt
285
+ * a specific transaction without revealing the decrypted contents.
286
+ *
287
+ * @param params - Viewing key access parameters
288
+ * @returns Compliance proof result
289
+ */
290
+ async generateViewingKeyAccessProof(
291
+ params: ViewingKeyAccessParams
292
+ ): Promise<ComplianceProofResult> {
293
+ this.ensureReady()
294
+
295
+ if (this.config.verbose) {
296
+ console.log('[ComplianceProofProvider] Generating viewing key access proof...')
297
+ }
298
+
299
+ try {
300
+ // Validate parameters
301
+ this.validateViewingKeyAccessParams(params)
302
+
303
+ // Compute proof components
304
+ const viewingKeyHash = await this.hashViewingKey(params.viewingKey)
305
+ const decryptionCommitment = await this.computeDecryptionCommitment(
306
+ params.viewingKey,
307
+ params.encryptedData
308
+ )
309
+ const auditorHash = await this.computeAuditorHash(
310
+ params.auditorPublicKey,
311
+ params.transactionHash
312
+ )
313
+
314
+ // Build public inputs
315
+ const publicInputs: `0x${string}`[] = [
316
+ `0x${params.transactionHash.replace('0x', '').padStart(64, '0')}`,
317
+ `0x${viewingKeyHash}`,
318
+ `0x${decryptionCommitment}`,
319
+ `0x${params.timestamp.toString(16).padStart(16, '0')}`,
320
+ `0x${auditorHash}`,
321
+ ]
322
+
323
+ // Generate proof (in production, this would use the Noir circuit)
324
+ const proofBytes = await this.generateComplianceProofBytes(
325
+ 'viewing_key_access',
326
+ publicInputs
327
+ )
328
+
329
+ const proof: ZKProof = {
330
+ type: 'validity', // Reuses validity proof structure
331
+ proof: `0x${proofBytes}`,
332
+ publicInputs,
333
+ }
334
+
335
+ const validUntil = params.timestamp + this.config.defaultValidityPeriod
336
+
337
+ if (this.config.verbose) {
338
+ console.log('[ComplianceProofProvider] Viewing key access proof generated')
339
+ }
340
+
341
+ return {
342
+ proof,
343
+ publicInputs,
344
+ complianceType: 'viewing_key_access',
345
+ validUntil,
346
+ auditorHash,
347
+ }
348
+ } catch (error) {
349
+ throw new ProofGenerationError(
350
+ 'validity', // Viewing key access uses validity proof structure
351
+ `Failed to generate viewing key access proof: ${error instanceof Error ? error.message : String(error)}`,
352
+ error instanceof Error ? error : undefined
353
+ )
354
+ }
355
+ }
356
+
357
+ /**
358
+ * Generate a sanctions clearance proof
359
+ *
360
+ * Proves that sender and recipient are not on any sanctions lists
361
+ * without revealing their actual addresses.
362
+ *
363
+ * @param params - Sanctions clearance parameters
364
+ * @returns Compliance proof result
365
+ */
366
+ async generateSanctionsClearProof(
367
+ params: SanctionsClearParams
368
+ ): Promise<ComplianceProofResult> {
369
+ this.ensureReady()
370
+
371
+ if (this.config.verbose) {
372
+ console.log('[ComplianceProofProvider] Generating sanctions clearance proof...')
373
+ }
374
+
375
+ try {
376
+ // Validate parameters
377
+ this.validateSanctionsClearParams(params)
378
+
379
+ // Compute address commitments (hide actual addresses)
380
+ const senderCommitment = await this.computeAddressCommitment(
381
+ params.senderAddress,
382
+ params.senderBlinding
383
+ )
384
+ const recipientCommitment = await this.computeAddressCommitment(
385
+ params.recipientAddress,
386
+ params.recipientBlinding
387
+ )
388
+
389
+ // Compute non-membership proof in sanctions list
390
+ const nonMembershipProof = await this.computeNonMembershipProof(
391
+ params.senderAddress,
392
+ params.recipientAddress,
393
+ params.sanctionsListRoot
394
+ )
395
+
396
+ // Build public inputs
397
+ const publicInputs: `0x${string}`[] = [
398
+ `0x${senderCommitment}`,
399
+ `0x${recipientCommitment}`,
400
+ `0x${params.sanctionsListRoot.replace('0x', '').padStart(64, '0')}`,
401
+ `0x${params.checkTimestamp.toString(16).padStart(16, '0')}`,
402
+ `0x${nonMembershipProof}`,
403
+ ]
404
+
405
+ // Generate proof
406
+ const proofBytes = await this.generateComplianceProofBytes(
407
+ 'sanctions_clear',
408
+ publicInputs
409
+ )
410
+
411
+ const proof: ZKProof = {
412
+ type: 'validity',
413
+ proof: `0x${proofBytes}`,
414
+ publicInputs,
415
+ }
416
+
417
+ const validUntil = params.checkTimestamp + this.config.defaultValidityPeriod
418
+
419
+ if (this.config.verbose) {
420
+ console.log('[ComplianceProofProvider] Sanctions clearance proof generated')
421
+ }
422
+
423
+ return {
424
+ proof,
425
+ publicInputs,
426
+ complianceType: 'sanctions_clear',
427
+ validUntil,
428
+ jurisdiction: params.jurisdiction,
429
+ }
430
+ } catch (error) {
431
+ throw new ProofGenerationError(
432
+ 'validity', // Sanctions clearance uses validity proof structure
433
+ `Failed to generate sanctions clearance proof: ${error instanceof Error ? error.message : String(error)}`,
434
+ error instanceof Error ? error : undefined
435
+ )
436
+ }
437
+ }
438
+
439
+ /**
440
+ * Generate a balance attestation proof
441
+ *
442
+ * Proves that an account has at least a certain balance
443
+ * without revealing the exact balance.
444
+ *
445
+ * @param params - Balance attestation parameters
446
+ * @returns Compliance proof result
447
+ */
448
+ async generateBalanceAttestationProof(
449
+ params: BalanceAttestationParams
450
+ ): Promise<ComplianceProofResult> {
451
+ this.ensureReady()
452
+
453
+ if (this.config.verbose) {
454
+ console.log('[ComplianceProofProvider] Generating balance attestation proof...')
455
+ }
456
+
457
+ try {
458
+ // Validate parameters
459
+ this.validateBalanceAttestationParams(params)
460
+
461
+ // Compute balance commitment
462
+ const balanceCommitment = await this.computeBalanceCommitment(
463
+ params.balance,
464
+ params.blindingFactor
465
+ )
466
+
467
+ // Build public inputs
468
+ const publicInputs: `0x${string}`[] = [
469
+ `0x${params.minimumRequired.toString(16).padStart(64, '0')}`,
470
+ `0x${params.assetId.replace('0x', '').padStart(64, '0')}`,
471
+ `0x${params.accountCommitment.replace('0x', '').padStart(64, '0')}`,
472
+ `0x${balanceCommitment}`,
473
+ `0x${params.attestationTime.toString(16).padStart(16, '0')}`,
474
+ ]
475
+
476
+ // Generate proof (reuses funding proof logic)
477
+ const proofBytes = await this.generateComplianceProofBytes(
478
+ 'balance_attestation',
479
+ publicInputs
480
+ )
481
+
482
+ const proof: ZKProof = {
483
+ type: 'funding', // Reuses funding proof structure
484
+ proof: `0x${proofBytes}`,
485
+ publicInputs,
486
+ }
487
+
488
+ const validUntil = params.attestationTime + this.config.defaultValidityPeriod
489
+
490
+ if (this.config.verbose) {
491
+ console.log('[ComplianceProofProvider] Balance attestation proof generated')
492
+ }
493
+
494
+ return {
495
+ proof,
496
+ publicInputs,
497
+ complianceType: 'balance_attestation',
498
+ validUntil,
499
+ }
500
+ } catch (error) {
501
+ throw new ProofGenerationError(
502
+ 'funding', // Balance attestation uses funding proof structure
503
+ `Failed to generate balance attestation proof: ${error instanceof Error ? error.message : String(error)}`,
504
+ error instanceof Error ? error : undefined
505
+ )
506
+ }
507
+ }
508
+
509
+ /**
510
+ * Generate a history completeness proof
511
+ *
512
+ * Proves that all transactions in a time range have been disclosed
513
+ * without revealing individual transaction amounts.
514
+ *
515
+ * @param params - History completeness parameters
516
+ * @returns Compliance proof result
517
+ */
518
+ async generateHistoryCompletenessProof(
519
+ params: HistoryCompletenessParams
520
+ ): Promise<ComplianceProofResult> {
521
+ this.ensureReady()
522
+
523
+ if (this.config.verbose) {
524
+ console.log('[ComplianceProofProvider] Generating history completeness proof...')
525
+ }
526
+
527
+ try {
528
+ // Validate parameters
529
+ this.validateHistoryCompletenessParams(params)
530
+
531
+ // Compute viewing key hash
532
+ const viewingKeyHash = await this.hashViewingKey(params.viewingKey)
533
+
534
+ // Build public inputs
535
+ const publicInputs: `0x${string}`[] = [
536
+ `0x${params.historyMerkleRoot.replace('0x', '').padStart(64, '0')}`,
537
+ `0x${params.startTimestamp.toString(16).padStart(16, '0')}`,
538
+ `0x${params.endTimestamp.toString(16).padStart(16, '0')}`,
539
+ `0x${params.volumeCommitment.replace('0x', '').padStart(64, '0')}`,
540
+ `0x${viewingKeyHash}`,
541
+ ]
542
+
543
+ // Generate proof
544
+ const proofBytes = await this.generateComplianceProofBytes(
545
+ 'history_complete',
546
+ publicInputs
547
+ )
548
+
549
+ const proof: ZKProof = {
550
+ type: 'fulfillment', // Reuses fulfillment proof structure
551
+ proof: `0x${proofBytes}`,
552
+ publicInputs,
553
+ }
554
+
555
+ const validUntil = params.endTimestamp + this.config.defaultValidityPeriod
556
+
557
+ if (this.config.verbose) {
558
+ console.log('[ComplianceProofProvider] History completeness proof generated')
559
+ }
560
+
561
+ return {
562
+ proof,
563
+ publicInputs,
564
+ complianceType: 'history_complete',
565
+ validUntil,
566
+ }
567
+ } catch (error) {
568
+ throw new ProofGenerationError(
569
+ 'fulfillment', // History completeness uses fulfillment proof structure
570
+ `Failed to generate history completeness proof: ${error instanceof Error ? error.message : String(error)}`,
571
+ error instanceof Error ? error : undefined
572
+ )
573
+ }
574
+ }
575
+
576
+ /**
577
+ * Verify a compliance proof
578
+ *
579
+ * @param result - Compliance proof result to verify
580
+ * @returns true if valid, false otherwise
581
+ *
582
+ * @remarks
583
+ * **IMPORTANT: Mock Implementation**
584
+ *
585
+ * This verification performs structural validation only:
586
+ * - Checks proof expiry
587
+ * - Validates proof format and size
588
+ * - Verifies public inputs exist
589
+ * - Checks proof type matches compliance type
590
+ *
591
+ * It does NOT perform cryptographic verification of the ZK proof.
592
+ * For production use, integrate with `SolanaNoirVerifier.verifyOffChain()`
593
+ * or deploy a dedicated compliance circuit verifier.
594
+ *
595
+ * @example
596
+ * ```typescript
597
+ * // For production cryptographic verification:
598
+ * const solanaVerifier = new SolanaNoirVerifier()
599
+ * await solanaVerifier.initialize()
600
+ * const cryptoValid = await solanaVerifier.verifyOffChain(result.proof)
601
+ * const formatValid = await complianceProvider.verifyComplianceProof(result)
602
+ * const isValid = cryptoValid && formatValid
603
+ * ```
604
+ */
605
+ async verifyComplianceProof(result: ComplianceProofResult): Promise<boolean> {
606
+ this.ensureReady()
607
+
608
+ // Check if proof has expired
609
+ if (Date.now() / 1000 > result.validUntil) {
610
+ if (this.config.verbose) {
611
+ console.log('[ComplianceProofProvider] Proof has expired')
612
+ }
613
+ return false
614
+ }
615
+
616
+ // NOTE: This is a mock verification that only checks structure.
617
+ // Production systems should use SolanaNoirVerifier for cryptographic verification.
618
+
619
+ // Verify the underlying ZK proof structure
620
+ const proofHex = result.proof.proof.replace('0x', '')
621
+
622
+ // Check proof has minimum expected size (real proofs are ~2KB)
623
+ if (proofHex.length < 64) {
624
+ if (this.config.verbose) {
625
+ console.log('[ComplianceProofProvider] Proof too small')
626
+ }
627
+ return false
628
+ }
629
+
630
+ // Check public inputs match expected format
631
+ if (result.publicInputs.length === 0) {
632
+ if (this.config.verbose) {
633
+ console.log('[ComplianceProofProvider] No public inputs')
634
+ }
635
+ return false
636
+ }
637
+
638
+ // Check proof type matches compliance type
639
+ const expectedType = this.getExpectedProofType(result.complianceType)
640
+ if (result.proof.type !== expectedType) {
641
+ if (this.config.verbose) {
642
+ console.log(`[ComplianceProofProvider] Type mismatch: expected ${expectedType}, got ${result.proof.type}`)
643
+ }
644
+ return false
645
+ }
646
+
647
+ if (this.config.verbose) {
648
+ console.log('[ComplianceProofProvider] Mock verification: VALID (structural only, not cryptographic)')
649
+ }
650
+
651
+ return true
652
+ }
653
+
654
+ /**
655
+ * Destroy the provider and free resources
656
+ */
657
+ async destroy(): Promise<void> {
658
+ this._isReady = false
659
+ }
660
+
661
+ // ─── Private Methods ───────────────────────────────────────────────────────
662
+
663
+ private ensureReady(): void {
664
+ if (!this._isReady) {
665
+ throw new ProofError(
666
+ 'ComplianceProofProvider not initialized. Call initialize() first.',
667
+ ErrorCode.PROOF_PROVIDER_NOT_READY
668
+ )
669
+ }
670
+ }
671
+
672
+ private validateViewingKeyAccessParams(params: ViewingKeyAccessParams): void {
673
+ if (!params.viewingKey) {
674
+ throw new ProofError('Viewing key is required', ErrorCode.VALIDATION_FAILED)
675
+ }
676
+ if (!params.transactionHash) {
677
+ throw new ProofError('Transaction hash is required', ErrorCode.VALIDATION_FAILED)
678
+ }
679
+ if (!params.encryptedData || params.encryptedData.length === 0) {
680
+ throw new ProofError('Encrypted data is required', ErrorCode.VALIDATION_FAILED)
681
+ }
682
+ if (!params.auditorPublicKey) {
683
+ throw new ProofError('Auditor public key is required', ErrorCode.VALIDATION_FAILED)
684
+ }
685
+ }
686
+
687
+ private validateSanctionsClearParams(params: SanctionsClearParams): void {
688
+ if (!params.senderAddress) {
689
+ throw new ProofError('Sender address is required', ErrorCode.VALIDATION_FAILED)
690
+ }
691
+ if (!params.recipientAddress) {
692
+ throw new ProofError('Recipient address is required', ErrorCode.VALIDATION_FAILED)
693
+ }
694
+ if (!params.sanctionsListRoot) {
695
+ throw new ProofError('Sanctions list root is required', ErrorCode.VALIDATION_FAILED)
696
+ }
697
+ if (!this.config.jurisdictions.includes(params.jurisdiction as never)) {
698
+ throw new ProofError(
699
+ `Unsupported jurisdiction: ${params.jurisdiction}`,
700
+ ErrorCode.VALIDATION_FAILED
701
+ )
702
+ }
703
+ }
704
+
705
+ private validateBalanceAttestationParams(params: BalanceAttestationParams): void {
706
+ if (params.balance < 0n) {
707
+ throw new ProofError('Balance cannot be negative', ErrorCode.VALIDATION_FAILED)
708
+ }
709
+ if (params.balance < params.minimumRequired) {
710
+ throw new ProofError(
711
+ 'Balance must be at least minimum required',
712
+ ErrorCode.VALIDATION_FAILED
713
+ )
714
+ }
715
+ if (!params.assetId) {
716
+ throw new ProofError('Asset ID is required', ErrorCode.VALIDATION_FAILED)
717
+ }
718
+ }
719
+
720
+ private validateHistoryCompletenessParams(params: HistoryCompletenessParams): void {
721
+ if (params.startTimestamp >= params.endTimestamp) {
722
+ throw new ProofError('Start must be before end', ErrorCode.VALIDATION_FAILED)
723
+ }
724
+ if (!params.historyMerkleRoot) {
725
+ throw new ProofError('History merkle root is required', ErrorCode.VALIDATION_FAILED)
726
+ }
727
+ if (!params.viewingKey) {
728
+ throw new ProofError('Viewing key is required', ErrorCode.VALIDATION_FAILED)
729
+ }
730
+ }
731
+
732
+ private async hashViewingKey(viewingKey: ViewingKey): Promise<string> {
733
+ const { sha256 } = await import('@noble/hashes/sha256')
734
+ const { bytesToHex } = await import('@noble/hashes/utils')
735
+
736
+ // Hash the viewing key public component
737
+ const keyString = typeof viewingKey === 'string' ? viewingKey : JSON.stringify(viewingKey)
738
+ const encoder = new TextEncoder()
739
+ const keyBytes = encoder.encode(keyString)
740
+
741
+ return bytesToHex(sha256(keyBytes))
742
+ }
743
+
744
+ private async computeDecryptionCommitment(
745
+ viewingKey: ViewingKey,
746
+ encryptedData: Uint8Array
747
+ ): Promise<string> {
748
+ const { sha256 } = await import('@noble/hashes/sha256')
749
+ const { bytesToHex } = await import('@noble/hashes/utils')
750
+
751
+ // Commitment: hash(viewing_key || encrypted_data)
752
+ const keyHash = await this.hashViewingKey(viewingKey)
753
+ const keyBytes = this.hexToBytes(keyHash)
754
+
755
+ const preimage = new Uint8Array([...keyBytes, ...encryptedData.slice(0, 32)])
756
+ return bytesToHex(sha256(preimage))
757
+ }
758
+
759
+ private async computeAuditorHash(
760
+ auditorPublicKey: string,
761
+ transactionHash: string
762
+ ): Promise<string> {
763
+ const { sha256 } = await import('@noble/hashes/sha256')
764
+ const { bytesToHex } = await import('@noble/hashes/utils')
765
+
766
+ const auditorBytes = this.hexToBytes(auditorPublicKey.replace('0x', '').padStart(64, '0'))
767
+ const txBytes = this.hexToBytes(transactionHash.replace('0x', '').padStart(64, '0'))
768
+
769
+ const preimage = new Uint8Array([...auditorBytes, ...txBytes])
770
+ return bytesToHex(sha256(preimage))
771
+ }
772
+
773
+ private async computeAddressCommitment(
774
+ address: string,
775
+ blinding: Uint8Array
776
+ ): Promise<string> {
777
+ const { sha256 } = await import('@noble/hashes/sha256')
778
+ const { bytesToHex } = await import('@noble/hashes/utils')
779
+
780
+ const addressBytes = this.hexToBytes(address.replace('0x', '').padStart(64, '0'))
781
+ const preimage = new Uint8Array([...addressBytes, ...blinding.slice(0, 32)])
782
+
783
+ return bytesToHex(sha256(preimage))
784
+ }
785
+
786
+ private async computeNonMembershipProof(
787
+ senderAddress: string,
788
+ recipientAddress: string,
789
+ _sanctionsListRoot: string
790
+ ): Promise<string> {
791
+ const { sha256 } = await import('@noble/hashes/sha256')
792
+ const { bytesToHex } = await import('@noble/hashes/utils')
793
+
794
+ // In production, this would be a Merkle non-membership proof
795
+ // For now, we generate a commitment that can be verified
796
+ const senderBytes = this.hexToBytes(senderAddress.replace('0x', '').padStart(64, '0'))
797
+ const recipientBytes = this.hexToBytes(recipientAddress.replace('0x', '').padStart(64, '0'))
798
+
799
+ const preimage = new Uint8Array([...senderBytes, ...recipientBytes])
800
+ return bytesToHex(sha256(preimage))
801
+ }
802
+
803
+ private async computeBalanceCommitment(
804
+ balance: bigint,
805
+ blinding: Uint8Array
806
+ ): Promise<string> {
807
+ const { sha256 } = await import('@noble/hashes/sha256')
808
+ const { bytesToHex } = await import('@noble/hashes/utils')
809
+
810
+ // Convert balance to bytes
811
+ const balanceBytes = new Uint8Array(8)
812
+ let v = balance
813
+ for (let i = 7; i >= 0; i--) {
814
+ balanceBytes[i] = Number(v & 0xffn)
815
+ v = v >> 8n
816
+ }
817
+
818
+ const preimage = new Uint8Array([...balanceBytes, ...blinding.slice(0, 32)])
819
+ return bytesToHex(sha256(preimage))
820
+ }
821
+
822
+ private async generateComplianceProofBytes(
823
+ type: ComplianceProofType,
824
+ publicInputs: string[]
825
+ ): Promise<string> {
826
+ const { sha256 } = await import('@noble/hashes/sha256')
827
+ const { bytesToHex } = await import('@noble/hashes/utils')
828
+
829
+ // In production, this would call the Noir circuit
830
+ // For mock, we generate deterministic proof bytes from inputs
831
+ const circuitId = COMPLIANCE_CIRCUIT_IDS[type]
832
+ const encoder = new TextEncoder()
833
+
834
+ const inputBytes = publicInputs.flatMap((pi) => Array.from(this.hexToBytes(pi.replace('0x', ''))))
835
+ const preimage = new Uint8Array([
836
+ ...encoder.encode(circuitId),
837
+ ...inputBytes,
838
+ ])
839
+
840
+ // Generate 256 bytes of proof data (typical proof size)
841
+ const hash = sha256(preimage)
842
+ let proofBytes = ''
843
+ for (let i = 0; i < 8; i++) {
844
+ proofBytes += bytesToHex(sha256(new Uint8Array([...hash, i])))
845
+ }
846
+
847
+ return proofBytes
848
+ }
849
+
850
+ private getExpectedProofType(complianceType: ComplianceProofType): string {
851
+ switch (complianceType) {
852
+ case 'viewing_key_access':
853
+ case 'sanctions_clear':
854
+ return 'validity'
855
+ case 'balance_attestation':
856
+ return 'funding'
857
+ case 'history_complete':
858
+ return 'fulfillment'
859
+ default:
860
+ return 'validity'
861
+ }
862
+ }
863
+
864
+ private hexToBytes(hex: string): Uint8Array {
865
+ const h = hex.startsWith('0x') ? hex.slice(2) : hex
866
+ const bytes = new Uint8Array(h.length / 2)
867
+ for (let i = 0; i < bytes.length; i++) {
868
+ bytes[i] = parseInt(h.slice(i * 2, i * 2 + 2), 16)
869
+ }
870
+ return bytes
871
+ }
872
+ }