@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,719 @@
1
+ /**
2
+ * Arcium Privacy Backend
3
+ *
4
+ * Implements the PrivacyBackend interface using Arcium MPC (Multi-Party Computation).
5
+ * Arcium provides compute privacy - hiding what happens inside smart contracts.
6
+ *
7
+ * ## Key Characteristics
8
+ *
9
+ * - **MPC Computation**: Encrypted data processed by multiple nodes
10
+ * - **Compute Privacy**: Hides contract execution logic, not transaction details
11
+ * - **Circuit-Based**: Computations defined by pre-uploaded circuits
12
+ * - **Cluster Coordination**: MPC nodes coordinate to produce results
13
+ *
14
+ * ## Trade-offs vs Transaction Backends
15
+ *
16
+ * | Feature | Arcium (Compute) | SIP Native (Transaction) |
17
+ * |---------|------------------|--------------------------|
18
+ * | Hides sender | ❌ | ✅ Stealth addresses |
19
+ * | Hides amount | ❌ (in tx) | ✅ Pedersen |
20
+ * | Hides computation | ✅ MPC | ❌ |
21
+ * | Setup required | ✅ Circuit upload | ❌ |
22
+ * | Latency | Slow (MPC coord) | Fast |
23
+ *
24
+ * ## Use Cases
25
+ *
26
+ * - Private DEX swap logic (hide slippage, routing)
27
+ * - Private auctions (hide bid amounts during bidding)
28
+ * - Private lending (hide collateral ratios)
29
+ * - Private governance (hide vote weights)
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * import { ArciumBackend, PrivacyBackendRegistry } from '@sip-protocol/sdk'
34
+ *
35
+ * const backend = new ArciumBackend({
36
+ * rpcUrl: 'https://api.devnet.solana.com',
37
+ * network: 'devnet',
38
+ * })
39
+ *
40
+ * const registry = new PrivacyBackendRegistry()
41
+ * registry.register(backend, { priority: 70 })
42
+ *
43
+ * // Execute private computation
44
+ * const result = await backend.executeComputation({
45
+ * chain: 'solana',
46
+ * circuitId: 'private-swap',
47
+ * encryptedInputs: [encryptedAmount, encryptedPrice],
48
+ * cluster: 'devnet-cluster-1',
49
+ * })
50
+ *
51
+ * if (result.success) {
52
+ * console.log(`Computation ${result.computationId} completed`)
53
+ * }
54
+ * ```
55
+ *
56
+ * @see https://docs.arcium.com/developers
57
+ */
58
+
59
+ import type {
60
+ PrivacyBackend,
61
+ BackendType,
62
+ BackendCapabilities,
63
+ TransferParams,
64
+ TransactionResult,
65
+ ComputationParams,
66
+ ComputationResult,
67
+ AvailabilityResult,
68
+ BackendParams,
69
+ ComputationStatus,
70
+ CipherType,
71
+ } from './interface'
72
+
73
+ import {
74
+ isComputationParams,
75
+ withTimeout,
76
+ ComputationTimeoutError,
77
+ } from './interface'
78
+
79
+ import {
80
+ ARCIUM_CLUSTERS,
81
+ DEFAULT_COMPUTATION_TIMEOUT_MS,
82
+ ESTIMATED_COMPUTATION_TIME_MS,
83
+ BASE_COMPUTATION_COST_LAMPORTS,
84
+ COST_PER_ENCRYPTED_INPUT_LAMPORTS,
85
+ COST_PER_INPUT_KB_LAMPORTS,
86
+ BYTES_PER_KB,
87
+ DEFAULT_MAX_ENCRYPTED_INPUTS,
88
+ DEFAULT_MAX_INPUT_SIZE_BYTES,
89
+ DEFAULT_MAX_TOTAL_INPUT_SIZE_BYTES,
90
+ DEFAULT_MAX_COMPUTATION_COST_LAMPORTS,
91
+ ArciumError,
92
+ // Environment variable configuration
93
+ resolveRpcUrl,
94
+ resolveNetwork,
95
+ resolveTimeout,
96
+ resolveCluster,
97
+ type ArciumNetwork,
98
+ type IArciumClient,
99
+ type ComputationInfo,
100
+ type ArciumLimitsConfig,
101
+ type ArciumLimitsResolved,
102
+ } from './arcium-types'
103
+
104
+ import { createPrivacyLogger } from '../privacy-logger'
105
+
106
+ const arciumLogger = createPrivacyLogger('Arcium')
107
+
108
+ /**
109
+ * Configuration options for Arcium backend
110
+ */
111
+ export interface ArciumBackendConfig {
112
+ /** Solana RPC endpoint URL */
113
+ rpcUrl?: string
114
+ /** Network type */
115
+ network?: ArciumNetwork
116
+ /** Default MPC cluster to use */
117
+ cluster?: string
118
+ /** Default cipher for encryption */
119
+ defaultCipher?: CipherType
120
+ /** Computation timeout in milliseconds */
121
+ timeout?: number
122
+ /** Custom SDK client (for testing) */
123
+ client?: IArciumClient
124
+ /** Enable debug mode (includes stack traces in error responses) */
125
+ debug?: boolean
126
+ /** Configurable validation limits */
127
+ limits?: ArciumLimitsConfig
128
+ }
129
+
130
+ /**
131
+ * Arcium capabilities (static)
132
+ */
133
+ const ARCIUM_CAPABILITIES: BackendCapabilities = {
134
+ hiddenAmount: false, // Arcium hides compute, not amounts
135
+ hiddenSender: false, // Arcium doesn't hide transaction sender
136
+ hiddenRecipient: false, // Arcium doesn't hide transaction recipient
137
+ hiddenCompute: true, // PRIMARY PURPOSE: Hide computation logic
138
+ complianceSupport: false, // No viewing keys for MPC
139
+ anonymitySet: undefined, // Not applicable for MPC
140
+ setupRequired: true, // Need circuit upload before use
141
+ latencyEstimate: 'slow', // MPC coordination takes time
142
+ supportedTokens: 'all', // Can work with any token in compute
143
+ }
144
+
145
+ /**
146
+ * Arcium MPC Compute Privacy Backend
147
+ *
148
+ * Provides compute privacy through Multi-Party Computation.
149
+ * Use this backend to hide smart contract execution logic.
150
+ */
151
+ export class ArciumBackend implements PrivacyBackend {
152
+ readonly name = 'arcium'
153
+ readonly type: BackendType = 'compute'
154
+ readonly chains: string[] = ['solana']
155
+
156
+ private config: Required<Omit<ArciumBackendConfig, 'client' | 'limits'>> & {
157
+ client?: IArciumClient
158
+ }
159
+ private computationCache: Map<string, ComputationInfo> = new Map()
160
+ private limits: ArciumLimitsResolved
161
+
162
+ /**
163
+ * Create a new Arcium backend
164
+ *
165
+ * Configuration is resolved with the following priority:
166
+ * 1. Environment variables (highest priority)
167
+ * 2. Config parameters
168
+ * 3. Default values
169
+ *
170
+ * @param config - Backend configuration
171
+ * @throws {ArciumError} If network is invalid
172
+ * @throws {Error} If limits are invalid (non-positive values)
173
+ *
174
+ * @example
175
+ * ```bash
176
+ * # Configure via environment variables
177
+ * export ARCIUM_RPC_URL_DEVNET=https://my-rpc.example.com
178
+ * export ARCIUM_NETWORK=devnet
179
+ * export ARCIUM_TIMEOUT_MS=600000
180
+ * ```
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * // Or configure via constructor
185
+ * const backend = new ArciumBackend({
186
+ * rpcUrl: 'https://my-rpc.example.com',
187
+ * network: 'devnet',
188
+ * timeout: 600_000,
189
+ * })
190
+ * ```
191
+ */
192
+ constructor(config: ArciumBackendConfig = {}) {
193
+ // Resolve network first (needed for other resolvers)
194
+ const network = resolveNetwork(config.network)
195
+
196
+ // Validate network parameter if explicitly provided
197
+ if (config.network !== undefined) {
198
+ const validNetworks: ArciumNetwork[] = ['devnet', 'testnet', 'mainnet-beta']
199
+ if (!validNetworks.includes(config.network)) {
200
+ throw new ArciumError(
201
+ `Invalid Arcium network '${config.network}'. Valid networks: ${validNetworks.join(', ')}`,
202
+ 'ARCIUM_INVALID_NETWORK',
203
+ {
204
+ context: {
205
+ receivedNetwork: config.network,
206
+ validNetworks,
207
+ },
208
+ }
209
+ )
210
+ }
211
+ }
212
+
213
+ this.config = {
214
+ rpcUrl: resolveRpcUrl(network, config.rpcUrl),
215
+ network,
216
+ cluster: resolveCluster(network, config.cluster),
217
+ defaultCipher: config.defaultCipher ?? 'aes256',
218
+ timeout: resolveTimeout(config.timeout),
219
+ client: config.client,
220
+ debug: config.debug ?? false,
221
+ }
222
+
223
+ // Resolve limits with defaults
224
+ this.limits = {
225
+ maxEncryptedInputs:
226
+ config.limits?.maxEncryptedInputs ?? DEFAULT_MAX_ENCRYPTED_INPUTS,
227
+ maxInputSizeBytes:
228
+ config.limits?.maxInputSizeBytes ?? DEFAULT_MAX_INPUT_SIZE_BYTES,
229
+ maxTotalInputSizeBytes:
230
+ config.limits?.maxTotalInputSizeBytes ?? DEFAULT_MAX_TOTAL_INPUT_SIZE_BYTES,
231
+ maxComputationCostLamports:
232
+ config.limits?.maxComputationCostLamports ?? DEFAULT_MAX_COMPUTATION_COST_LAMPORTS,
233
+ }
234
+
235
+ // Validate configured limits are positive
236
+ if (this.limits.maxEncryptedInputs <= 0) {
237
+ throw new Error('maxEncryptedInputs must be positive')
238
+ }
239
+ if (this.limits.maxInputSizeBytes <= 0) {
240
+ throw new Error('maxInputSizeBytes must be positive')
241
+ }
242
+ if (this.limits.maxTotalInputSizeBytes <= 0) {
243
+ throw new Error('maxTotalInputSizeBytes must be positive')
244
+ }
245
+ if (this.limits.maxComputationCostLamports <= BigInt(0)) {
246
+ throw new Error('maxComputationCostLamports must be positive')
247
+ }
248
+ }
249
+
250
+ /**
251
+ * Get the current resolved limits configuration
252
+ * @returns A copy of the resolved limits
253
+ */
254
+ getLimits(): ArciumLimitsResolved {
255
+ return { ...this.limits }
256
+ }
257
+
258
+ /**
259
+ * Check if backend is available for given parameters
260
+ */
261
+ async checkAvailability(params: BackendParams): Promise<AvailabilityResult> {
262
+ // Must be computation params for Arcium
263
+ if (!isComputationParams(params)) {
264
+ return {
265
+ available: false,
266
+ reason:
267
+ 'Arcium is a compute backend. Use ComputationParams with circuitId and encryptedInputs.',
268
+ }
269
+ }
270
+
271
+ return this.checkComputeAvailability(params)
272
+ }
273
+
274
+ /**
275
+ * Check availability for computation params
276
+ */
277
+ /**
278
+ * Format bytes into human-readable string
279
+ */
280
+ private formatBytes(bytes: number): string {
281
+ if (bytes >= 1_048_576) {
282
+ return `${Math.round(bytes / 1_048_576)} MB`
283
+ }
284
+ if (bytes >= 1024) {
285
+ return `${Math.round(bytes / 1024)} KB`
286
+ }
287
+ return `${bytes} bytes`
288
+ }
289
+
290
+ private async checkComputeAvailability(
291
+ params: ComputationParams
292
+ ): Promise<AvailabilityResult> {
293
+ // Validate chain
294
+ if (params.chain !== 'solana') {
295
+ return {
296
+ available: false,
297
+ reason: `Arcium only supports Solana, not '${params.chain}'`,
298
+ }
299
+ }
300
+
301
+ // Validate circuitId
302
+ if (!params.circuitId || params.circuitId.trim() === '') {
303
+ return {
304
+ available: false,
305
+ reason: 'circuitId is required for Arcium computations',
306
+ }
307
+ }
308
+
309
+ // Validate encrypted inputs
310
+ if (!params.encryptedInputs || params.encryptedInputs.length === 0) {
311
+ return {
312
+ available: false,
313
+ reason: 'encryptedInputs array is required and must not be empty',
314
+ }
315
+ }
316
+
317
+ // Validate number of inputs doesn't exceed maximum
318
+ if (params.encryptedInputs.length > this.limits.maxEncryptedInputs) {
319
+ arciumLogger.warn('Validation failed: too many inputs', {
320
+ amount: params.encryptedInputs.length,
321
+ })
322
+ return {
323
+ available: false,
324
+ reason: `Too many encrypted inputs: ${params.encryptedInputs.length} exceeds maximum of ${this.limits.maxEncryptedInputs}`,
325
+ }
326
+ }
327
+
328
+ // Validate each input is a valid Uint8Array with size bounds
329
+ let totalInputSize = 0
330
+ for (let i = 0; i < params.encryptedInputs.length; i++) {
331
+ const input = params.encryptedInputs[i]
332
+ if (!(input instanceof Uint8Array) || input.length === 0) {
333
+ return {
334
+ available: false,
335
+ reason: `encryptedInputs[${i}] must be a non-empty Uint8Array`,
336
+ }
337
+ }
338
+ if (input.length > this.limits.maxInputSizeBytes) {
339
+ arciumLogger.warn('Validation failed: input too large', {
340
+ amount: input.length,
341
+ })
342
+ return {
343
+ available: false,
344
+ reason: `encryptedInputs[${i}] size ${input.length} bytes exceeds maximum of ${this.formatBytes(this.limits.maxInputSizeBytes)}`,
345
+ }
346
+ }
347
+ totalInputSize += input.length
348
+ }
349
+
350
+ // Validate total input size
351
+ if (totalInputSize > this.limits.maxTotalInputSizeBytes) {
352
+ arciumLogger.warn('Validation failed: total input size exceeded', {
353
+ amount: totalInputSize,
354
+ })
355
+ return {
356
+ available: false,
357
+ reason: `Total input size ${this.formatBytes(totalInputSize)} exceeds maximum of ${this.formatBytes(this.limits.maxTotalInputSizeBytes)}`,
358
+ }
359
+ }
360
+
361
+ // Validate cipher type if provided
362
+ if (params.cipher) {
363
+ const validCiphers: CipherType[] = ['aes128', 'aes192', 'aes256', 'rescue']
364
+ if (!validCiphers.includes(params.cipher)) {
365
+ return {
366
+ available: false,
367
+ reason: `Invalid cipher '${params.cipher}'. Supported: ${validCiphers.join(', ')}`,
368
+ }
369
+ }
370
+ }
371
+
372
+ // In production, would check:
373
+ // - Circuit exists and is valid
374
+ // - Cluster is available
375
+ // - User has permissions
376
+
377
+ return {
378
+ available: true,
379
+ estimatedCost: this.estimateComputeCost(params),
380
+ estimatedTime: ESTIMATED_COMPUTATION_TIME_MS,
381
+ }
382
+ }
383
+
384
+ /**
385
+ * Get backend capabilities
386
+ */
387
+ getCapabilities(): BackendCapabilities {
388
+ return { ...ARCIUM_CAPABILITIES }
389
+ }
390
+
391
+ /**
392
+ * Execute a privacy-preserving transfer
393
+ *
394
+ * Arcium is a compute backend - this method returns an error
395
+ * directing users to use executeComputation() instead.
396
+ */
397
+ async execute(_params: TransferParams): Promise<TransactionResult> {
398
+ return {
399
+ success: false,
400
+ error:
401
+ 'Arcium is a compute privacy backend. ' +
402
+ 'Use executeComputation() for MPC operations. ' +
403
+ 'For transaction privacy, use SIPNativeBackend or PrivacyCashBackend.',
404
+ backend: this.name,
405
+ metadata: {
406
+ hint: 'executeComputation',
407
+ paramsType: 'ComputationParams',
408
+ },
409
+ }
410
+ }
411
+
412
+ /**
413
+ * Execute a privacy-preserving computation via MPC
414
+ *
415
+ * This submits encrypted data to the Arcium MPC network for processing.
416
+ * The computation is defined by a pre-uploaded circuit.
417
+ *
418
+ * @param params - Computation parameters
419
+ * @returns Computation result with ID for tracking
420
+ */
421
+ async executeComputation(
422
+ params: ComputationParams
423
+ ): Promise<ComputationResult> {
424
+ // Validate availability first
425
+ const availability = await this.checkComputeAvailability(params)
426
+ if (!availability.available) {
427
+ return {
428
+ success: false,
429
+ error: availability.reason,
430
+ backend: this.name,
431
+ }
432
+ }
433
+
434
+ try {
435
+ const cluster = params.cluster ?? this.config.cluster
436
+ const cipher = params.cipher ?? this.config.defaultCipher
437
+
438
+ // In a real implementation with the SDK:
439
+ // 1. const client = await this.getClient()
440
+ // 2. const computationId = await client.submitComputation({
441
+ // circuitId: params.circuitId,
442
+ // encryptedInputs: params.encryptedInputs,
443
+ // cluster,
444
+ // callback: params.callbackAddress,
445
+ // })
446
+ // 3. Optionally await finalization
447
+
448
+ // Simulated result (SDK integration pending)
449
+ const simulatedComputationId = this.generateComputationId()
450
+
451
+ // Cache the computation info
452
+ const info: ComputationInfo = {
453
+ id: simulatedComputationId,
454
+ status: 'submitted',
455
+ circuitId: params.circuitId,
456
+ cluster,
457
+ submittedAt: Date.now(),
458
+ }
459
+ this.computationCache.set(simulatedComputationId, info)
460
+
461
+ return {
462
+ success: true,
463
+ computationId: simulatedComputationId,
464
+ backend: this.name,
465
+ status: 'submitted',
466
+ metadata: {
467
+ circuitId: params.circuitId,
468
+ cluster,
469
+ cipher,
470
+ inputCount: params.encryptedInputs.length,
471
+ network: this.config.network,
472
+ submittedAt: Date.now(),
473
+ warning: 'Simulated result - SDK integration pending',
474
+ },
475
+ }
476
+ } catch (error) {
477
+ return {
478
+ success: false,
479
+ error: this.formatErrorMessage(error),
480
+ backend: this.name,
481
+ status: 'failed',
482
+ metadata: this.config.debug ? this.getErrorMetadata(error) : undefined,
483
+ }
484
+ }
485
+ }
486
+
487
+ /**
488
+ * Estimate cost for an operation
489
+ */
490
+ async estimateCost(params: BackendParams): Promise<bigint> {
491
+ if (isComputationParams(params)) {
492
+ return this.estimateComputeCost(params)
493
+ }
494
+
495
+ // Transfer params - return 0 as we don't support transfers
496
+ return BigInt(0)
497
+ }
498
+
499
+ /**
500
+ * Get computation status
501
+ *
502
+ * @param computationId - Computation to check
503
+ * @returns Current status or undefined if not found
504
+ */
505
+ async getComputationStatus(
506
+ computationId: string
507
+ ): Promise<ComputationStatus | undefined> {
508
+ // Check cache first
509
+ const cached = this.computationCache.get(computationId)
510
+ if (cached) {
511
+ return cached.status
512
+ }
513
+
514
+ // In production, would query the Arcium network:
515
+ // const client = await this.getClient()
516
+ // return client.getComputationStatus(computationId)
517
+
518
+ return undefined
519
+ }
520
+
521
+ /**
522
+ * Get computation info
523
+ *
524
+ * @param computationId - Computation to query
525
+ * @returns Computation info or undefined if not found
526
+ */
527
+ async getComputationInfo(
528
+ computationId: string
529
+ ): Promise<ComputationInfo | undefined> {
530
+ // Check cache
531
+ const cached = this.computationCache.get(computationId)
532
+ if (cached) {
533
+ return cached
534
+ }
535
+
536
+ // In production, would query the Arcium network
537
+ return undefined
538
+ }
539
+
540
+ /**
541
+ * Wait for computation to complete
542
+ *
543
+ * @param computationId - Computation to wait for
544
+ * @param timeout - Optional timeout override (defaults to config.timeout)
545
+ * @returns Computation result
546
+ * @throws {ComputationTimeoutError} If computation exceeds timeout
547
+ */
548
+ async awaitComputation(
549
+ computationId: string,
550
+ timeout?: number
551
+ ): Promise<ComputationResult> {
552
+ const timeoutMs = timeout ?? this.config.timeout
553
+
554
+ // Check if computation exists before waiting
555
+ const info = this.computationCache.get(computationId)
556
+ if (!info) {
557
+ return {
558
+ success: false,
559
+ error: `Computation ${computationId} not found`,
560
+ backend: this.name,
561
+ status: 'failed',
562
+ }
563
+ }
564
+
565
+ // Wrap the polling/waiting logic with timeout
566
+ return withTimeout(
567
+ this.pollComputationResult(computationId, info),
568
+ timeoutMs,
569
+ () => {
570
+ throw new ComputationTimeoutError(computationId, timeoutMs, this.name)
571
+ }
572
+ )
573
+ }
574
+
575
+ /**
576
+ * Poll for computation result (simulation)
577
+ *
578
+ * In production, this would poll the Arcium network for completion.
579
+ * Currently simulates immediate completion for testing.
580
+ */
581
+ private async pollComputationResult(
582
+ computationId: string,
583
+ info: ComputationInfo
584
+ ): Promise<ComputationResult> {
585
+ // In production, would poll the Arcium network:
586
+ // const client = await this.getClient()
587
+ // const output = await client.awaitFinalization(computationId)
588
+
589
+ // Simulated: Mark as completed immediately
590
+ info.status = 'completed'
591
+ info.completedAt = Date.now()
592
+ this.computationCache.set(computationId, info)
593
+
594
+ return {
595
+ success: true,
596
+ computationId,
597
+ output: new Uint8Array([0, 1, 2, 3]), // Simulated output
598
+ backend: this.name,
599
+ status: 'completed',
600
+ completedAt: info.completedAt,
601
+ metadata: {
602
+ circuitId: info.circuitId,
603
+ cluster: info.cluster,
604
+ duration: info.completedAt - info.submittedAt,
605
+ warning: 'Simulated result - SDK integration pending',
606
+ },
607
+ }
608
+ }
609
+
610
+ // ─── Private Methods ─────────────────────────────────────────────────────────
611
+
612
+ /**
613
+ * Estimate cost for a computation
614
+ */
615
+ private estimateComputeCost(params: ComputationParams): bigint {
616
+ let cost = BASE_COMPUTATION_COST_LAMPORTS
617
+
618
+ // More inputs = higher cost
619
+ const inputCost =
620
+ BigInt(params.encryptedInputs.length) * COST_PER_ENCRYPTED_INPUT_LAMPORTS
621
+ cost += inputCost
622
+
623
+ // Larger inputs = higher cost
624
+ const totalInputSize = params.encryptedInputs.reduce(
625
+ (sum, input) => sum + input.length,
626
+ 0
627
+ )
628
+ const sizeCost =
629
+ BigInt(Math.ceil(totalInputSize / BYTES_PER_KB)) * COST_PER_INPUT_KB_LAMPORTS
630
+ cost += sizeCost
631
+
632
+ // Cap at maximum reasonable cost to prevent unexpected charges
633
+ if (cost > this.limits.maxComputationCostLamports) {
634
+ return this.limits.maxComputationCostLamports
635
+ }
636
+
637
+ return cost
638
+ }
639
+
640
+ /**
641
+ * Generate a unique computation ID
642
+ */
643
+ private generateComputationId(): string {
644
+ const timestamp = Date.now().toString(36)
645
+ const random = Math.random().toString(36).slice(2, 10)
646
+ return `arcium_${timestamp}_${random}`
647
+ }
648
+
649
+ /**
650
+ * Clear computation cache
651
+ */
652
+ clearComputationCache(): void {
653
+ this.computationCache.clear()
654
+ }
655
+
656
+ /**
657
+ * Get cached computation count
658
+ */
659
+ getCachedComputationCount(): number {
660
+ return this.computationCache.size
661
+ }
662
+
663
+ // ─── Error Handling Helpers ─────────────────────────────────────────────────
664
+
665
+ /**
666
+ * Format an error message for user-facing output
667
+ *
668
+ * Include error type for better debugging while keeping the message clear.
669
+ */
670
+ private formatErrorMessage(error: unknown): string {
671
+ if (error instanceof Error) {
672
+ const errorType = error.name !== 'Error' ? `[${error.name}] ` : ''
673
+ return `${errorType}${error.message}`
674
+ }
675
+ return 'Unknown error occurred'
676
+ }
677
+
678
+ /**
679
+ * Get detailed error metadata for debugging
680
+ *
681
+ * Only called when debug mode is enabled. Includes stack trace and
682
+ * error chain information for troubleshooting.
683
+ */
684
+ private getErrorMetadata(error: unknown): Record<string, unknown> {
685
+ const metadata: Record<string, unknown> = {
686
+ timestamp: new Date().toISOString(),
687
+ }
688
+
689
+ if (error instanceof Error) {
690
+ metadata.errorName = error.name
691
+ metadata.errorMessage = error.message
692
+ metadata.stack = error.stack
693
+
694
+ // Preserve error cause chain
695
+ if (error.cause) {
696
+ metadata.cause =
697
+ error.cause instanceof Error
698
+ ? {
699
+ name: error.cause.name,
700
+ message: error.cause.message,
701
+ stack: error.cause.stack,
702
+ }
703
+ : String(error.cause)
704
+ }
705
+
706
+ // Handle SIPError-specific fields
707
+ if ('code' in error && typeof (error as Record<string, unknown>).code === 'string') {
708
+ metadata.errorCode = (error as Record<string, unknown>).code
709
+ }
710
+ if ('context' in error) {
711
+ metadata.errorContext = (error as Record<string, unknown>).context
712
+ }
713
+ } else {
714
+ metadata.rawError = String(error)
715
+ }
716
+
717
+ return metadata
718
+ }
719
+ }