@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,602 @@
1
+ /**
2
+ * Dependency Graph Analyzer for Parallel Proof Generation
3
+ *
4
+ * @module proofs/parallel/dependency-graph
5
+ * @description Analyzes proof dependencies and determines optimal execution order
6
+ *
7
+ * M20-12: Optimize proof generation parallelization (#307)
8
+ */
9
+
10
+ import type {
11
+ DependencyNode,
12
+ DependencyEdge,
13
+ DependencyGraph,
14
+ GraphAnalysis,
15
+ IDependencyAnalyzer,
16
+ } from './interface'
17
+
18
+ // ─── Dependency Analyzer Implementation ──────────────────────────────────────
19
+
20
+ /**
21
+ * Analyzes proof dependencies and builds execution graphs
22
+ */
23
+ export class DependencyAnalyzer implements IDependencyAnalyzer {
24
+ /**
25
+ * Analyze a set of proof requests and build dependency graph
26
+ */
27
+ analyze(nodes: DependencyNode[]): GraphAnalysis {
28
+ // Build the graph
29
+ const nodeMap = new Map<string, DependencyNode>()
30
+ const edges: DependencyEdge[] = []
31
+ const inDegree = new Map<string, number>()
32
+ const outDegree = new Map<string, number>()
33
+
34
+ // Index all nodes
35
+ for (const node of nodes) {
36
+ nodeMap.set(node.id, node)
37
+ inDegree.set(node.id, 0)
38
+ outDegree.set(node.id, 0)
39
+ }
40
+
41
+ // Build edges and calculate degrees
42
+ for (const node of nodes) {
43
+ for (const depId of node.dependencies) {
44
+ if (nodeMap.has(depId)) {
45
+ edges.push({
46
+ from: depId,
47
+ to: node.id,
48
+ connectionType: 'proof', // Default connection type
49
+ })
50
+ inDegree.set(node.id, (inDegree.get(node.id) ?? 0) + 1)
51
+ outDegree.set(depId, (outDegree.get(depId) ?? 0) + 1)
52
+ }
53
+ }
54
+ }
55
+
56
+ // Find roots (no incoming edges)
57
+ const roots: string[] = []
58
+ for (const [id, degree] of inDegree) {
59
+ if (degree === 0) {
60
+ roots.push(id)
61
+ }
62
+ }
63
+
64
+ // Find leaves (no outgoing edges)
65
+ const leaves: string[] = []
66
+ for (const [id, degree] of outDegree) {
67
+ if (degree === 0) {
68
+ leaves.push(id)
69
+ }
70
+ }
71
+
72
+ // Detect cycles using DFS
73
+ const cycleResult = this.detectCycles(nodeMap, edges)
74
+
75
+ // Calculate depths and find critical path
76
+ const depths = this.calculateDepths(nodeMap, edges)
77
+ const maxDepth = Math.max(0, ...Array.from(depths.values()))
78
+
79
+ // Find critical path (longest weighted path)
80
+ const criticalPath = this.findCriticalPath(nodeMap, edges, depths)
81
+
82
+ // Calculate total cost
83
+ let totalCost = 0
84
+ for (const node of nodes) {
85
+ totalCost += node.estimatedCost
86
+ }
87
+
88
+ const graph: DependencyGraph = {
89
+ nodes: nodeMap,
90
+ edges,
91
+ roots,
92
+ leaves,
93
+ maxDepth,
94
+ totalCost,
95
+ criticalPath,
96
+ }
97
+
98
+ // Calculate execution levels
99
+ const executionLevels = this.calculateExecutionLevels(graph)
100
+
101
+ // Find bottlenecks (high cost nodes on critical path)
102
+ const bottlenecks = this.findBottlenecks(graph, criticalPath)
103
+
104
+ // Suggest parallelism based on graph structure
105
+ const suggestedParallelism = this.suggestParallelism(graph, executionLevels)
106
+
107
+ return {
108
+ graph,
109
+ suggestedParallelism,
110
+ executionLevels,
111
+ hasCycles: cycleResult.hasCycles,
112
+ cyclePath: cycleResult.cyclePath,
113
+ bottlenecks,
114
+ }
115
+ }
116
+
117
+ /**
118
+ * Add a node to an existing graph
119
+ */
120
+ addNode(graph: DependencyGraph, node: DependencyNode): DependencyGraph {
121
+ const newNodes = new Map(graph.nodes)
122
+ newNodes.set(node.id, node)
123
+
124
+ // Add edges for dependencies
125
+ const newEdges = [...graph.edges]
126
+ for (const depId of node.dependencies) {
127
+ if (newNodes.has(depId)) {
128
+ newEdges.push({
129
+ from: depId,
130
+ to: node.id,
131
+ connectionType: 'proof',
132
+ })
133
+ }
134
+ }
135
+
136
+ // Recalculate graph properties
137
+ const roots = this.calculateRoots(newNodes, newEdges)
138
+ const leaves = this.calculateLeaves(newNodes, newEdges)
139
+ const depths = this.calculateDepths(newNodes, newEdges)
140
+ const maxDepth = Math.max(0, ...Array.from(depths.values()))
141
+ const criticalPath = this.findCriticalPath(newNodes, newEdges, depths)
142
+
143
+ let totalCost = 0
144
+ for (const n of newNodes.values()) {
145
+ totalCost += n.estimatedCost
146
+ }
147
+
148
+ return {
149
+ nodes: newNodes,
150
+ edges: newEdges,
151
+ roots,
152
+ leaves,
153
+ maxDepth,
154
+ totalCost,
155
+ criticalPath,
156
+ }
157
+ }
158
+
159
+ /**
160
+ * Remove a node from the graph
161
+ */
162
+ removeNode(graph: DependencyGraph, nodeId: string): DependencyGraph {
163
+ const newNodes = new Map(graph.nodes)
164
+ newNodes.delete(nodeId)
165
+
166
+ // Remove edges involving this node
167
+ const newEdges = graph.edges.filter((e) => e.from !== nodeId && e.to !== nodeId)
168
+
169
+ // Recalculate graph properties
170
+ const roots = this.calculateRoots(newNodes, newEdges)
171
+ const leaves = this.calculateLeaves(newNodes, newEdges)
172
+ const depths = this.calculateDepths(newNodes, newEdges)
173
+ const maxDepth = Math.max(0, ...Array.from(depths.values()))
174
+ const criticalPath = this.findCriticalPath(newNodes, newEdges, depths)
175
+
176
+ let totalCost = 0
177
+ for (const n of newNodes.values()) {
178
+ totalCost += n.estimatedCost
179
+ }
180
+
181
+ return {
182
+ nodes: newNodes,
183
+ edges: newEdges,
184
+ roots,
185
+ leaves,
186
+ maxDepth,
187
+ totalCost,
188
+ criticalPath,
189
+ }
190
+ }
191
+
192
+ /**
193
+ * Get execution order respecting dependencies (topological sort)
194
+ */
195
+ getExecutionOrder(graph: DependencyGraph): readonly string[] {
196
+ const result: string[] = []
197
+ const visited = new Set<string>()
198
+ const inProgress = new Set<string>()
199
+
200
+ const visit = (nodeId: string): boolean => {
201
+ if (inProgress.has(nodeId)) {
202
+ // Cycle detected
203
+ return false
204
+ }
205
+ if (visited.has(nodeId)) {
206
+ return true
207
+ }
208
+
209
+ inProgress.add(nodeId)
210
+ const node = graph.nodes.get(nodeId)
211
+ if (node) {
212
+ for (const depId of node.dependencies) {
213
+ if (graph.nodes.has(depId)) {
214
+ if (!visit(depId)) {
215
+ return false
216
+ }
217
+ }
218
+ }
219
+ }
220
+ inProgress.delete(nodeId)
221
+ visited.add(nodeId)
222
+ result.push(nodeId)
223
+ return true
224
+ }
225
+
226
+ for (const nodeId of graph.nodes.keys()) {
227
+ if (!visited.has(nodeId)) {
228
+ visit(nodeId)
229
+ }
230
+ }
231
+
232
+ return result
233
+ }
234
+
235
+ /**
236
+ * Find nodes ready to execute (all dependencies satisfied)
237
+ */
238
+ getReadyNodes(graph: DependencyGraph, completed: Set<string>): readonly string[] {
239
+ const ready: string[] = []
240
+
241
+ for (const [nodeId, node] of graph.nodes) {
242
+ if (completed.has(nodeId)) {
243
+ continue
244
+ }
245
+
246
+ // Check if all dependencies are satisfied
247
+ let allDependenciesSatisfied = true
248
+ for (const depId of node.dependencies) {
249
+ if (graph.nodes.has(depId) && !completed.has(depId)) {
250
+ allDependenciesSatisfied = false
251
+ break
252
+ }
253
+ }
254
+
255
+ if (allDependenciesSatisfied) {
256
+ ready.push(nodeId)
257
+ }
258
+ }
259
+
260
+ // Sort by priority (higher first), then by cost (lower first for better parallelism)
261
+ ready.sort((a, b) => {
262
+ const nodeA = graph.nodes.get(a)!
263
+ const nodeB = graph.nodes.get(b)!
264
+ const priorityDiff = (nodeB.priority ?? 0) - (nodeA.priority ?? 0)
265
+ if (priorityDiff !== 0) return priorityDiff
266
+ return nodeA.estimatedCost - nodeB.estimatedCost
267
+ })
268
+
269
+ return ready
270
+ }
271
+
272
+ /**
273
+ * Validate graph is acyclic
274
+ */
275
+ validateAcyclic(graph: DependencyGraph): boolean {
276
+ const result = this.detectCycles(graph.nodes, graph.edges)
277
+ return !result.hasCycles
278
+ }
279
+
280
+ // ─── Private Helper Methods ──────────────────────────────────────────────────
281
+
282
+ private detectCycles(
283
+ nodes: Map<string, DependencyNode>,
284
+ edges: DependencyEdge[]
285
+ ): { hasCycles: boolean; cyclePath?: string[] } {
286
+ const visited = new Set<string>()
287
+ const recursionStack = new Set<string>()
288
+ const path: string[] = []
289
+
290
+ // Build adjacency list
291
+ const adjacency = new Map<string, string[]>()
292
+ for (const node of nodes.keys()) {
293
+ adjacency.set(node, [])
294
+ }
295
+ for (const edge of edges) {
296
+ adjacency.get(edge.from)?.push(edge.to)
297
+ }
298
+
299
+ const dfs = (nodeId: string): boolean => {
300
+ visited.add(nodeId)
301
+ recursionStack.add(nodeId)
302
+ path.push(nodeId)
303
+
304
+ for (const neighbor of adjacency.get(nodeId) ?? []) {
305
+ if (!visited.has(neighbor)) {
306
+ if (dfs(neighbor)) {
307
+ return true
308
+ }
309
+ } else if (recursionStack.has(neighbor)) {
310
+ // Found cycle
311
+ path.push(neighbor)
312
+ return true
313
+ }
314
+ }
315
+
316
+ recursionStack.delete(nodeId)
317
+ path.pop()
318
+ return false
319
+ }
320
+
321
+ for (const nodeId of nodes.keys()) {
322
+ if (!visited.has(nodeId)) {
323
+ if (dfs(nodeId)) {
324
+ // Extract cycle from path
325
+ const cycleStart = path.indexOf(path[path.length - 1])
326
+ const cyclePath = path.slice(cycleStart)
327
+ return { hasCycles: true, cyclePath }
328
+ }
329
+ }
330
+ }
331
+
332
+ return { hasCycles: false }
333
+ }
334
+
335
+ private calculateDepths(
336
+ nodes: Map<string, DependencyNode>,
337
+ edges: DependencyEdge[]
338
+ ): Map<string, number> {
339
+ const depths = new Map<string, number>()
340
+ const inDegree = new Map<string, number>()
341
+
342
+ // Initialize
343
+ for (const nodeId of nodes.keys()) {
344
+ depths.set(nodeId, 0)
345
+ inDegree.set(nodeId, 0)
346
+ }
347
+
348
+ // Count in-degrees
349
+ for (const edge of edges) {
350
+ inDegree.set(edge.to, (inDegree.get(edge.to) ?? 0) + 1)
351
+ }
352
+
353
+ // BFS from roots
354
+ const queue: string[] = []
355
+ for (const [nodeId, degree] of inDegree) {
356
+ if (degree === 0) {
357
+ queue.push(nodeId)
358
+ depths.set(nodeId, 0)
359
+ }
360
+ }
361
+
362
+ while (queue.length > 0) {
363
+ const current = queue.shift()!
364
+ const currentDepth = depths.get(current) ?? 0
365
+
366
+ for (const edge of edges) {
367
+ if (edge.from === current) {
368
+ const newDepth = Math.max(depths.get(edge.to) ?? 0, currentDepth + 1)
369
+ depths.set(edge.to, newDepth)
370
+
371
+ const newInDegree = (inDegree.get(edge.to) ?? 1) - 1
372
+ inDegree.set(edge.to, newInDegree)
373
+
374
+ if (newInDegree === 0) {
375
+ queue.push(edge.to)
376
+ }
377
+ }
378
+ }
379
+ }
380
+
381
+ return depths
382
+ }
383
+
384
+ private findCriticalPath(
385
+ nodes: Map<string, DependencyNode>,
386
+ edges: DependencyEdge[],
387
+ depths: Map<string, number>
388
+ ): readonly string[] {
389
+ if (nodes.size === 0) {
390
+ return []
391
+ }
392
+
393
+ // Build reverse adjacency (to traverse backwards from leaves)
394
+ const reverseAdj = new Map<string, string[]>()
395
+ for (const nodeId of nodes.keys()) {
396
+ reverseAdj.set(nodeId, [])
397
+ }
398
+ for (const edge of edges) {
399
+ reverseAdj.get(edge.to)?.push(edge.from)
400
+ }
401
+
402
+ // Calculate cumulative cost from each node to any leaf
403
+ const costToLeaf = new Map<string, number>()
404
+ const pathToLeaf = new Map<string, string[]>()
405
+
406
+ // Find leaves
407
+ const outDegree = new Map<string, number>()
408
+ for (const nodeId of nodes.keys()) {
409
+ outDegree.set(nodeId, 0)
410
+ }
411
+ for (const edge of edges) {
412
+ outDegree.set(edge.from, (outDegree.get(edge.from) ?? 0) + 1)
413
+ }
414
+
415
+ const leaves: string[] = []
416
+ for (const [nodeId, degree] of outDegree) {
417
+ if (degree === 0) {
418
+ leaves.push(nodeId)
419
+ const node = nodes.get(nodeId)!
420
+ costToLeaf.set(nodeId, node.estimatedCost)
421
+ pathToLeaf.set(nodeId, [nodeId])
422
+ }
423
+ }
424
+
425
+ // Process nodes in reverse topological order
426
+ const sortedNodes = Array.from(nodes.keys()).sort(
427
+ (a, b) => (depths.get(b) ?? 0) - (depths.get(a) ?? 0)
428
+ )
429
+
430
+ for (const nodeId of sortedNodes) {
431
+ if (costToLeaf.has(nodeId)) continue
432
+
433
+ const node = nodes.get(nodeId)!
434
+ let maxCost = 0
435
+ let bestPath: string[] = [nodeId]
436
+
437
+ // Find successor with maximum cost to leaf
438
+ for (const edge of edges) {
439
+ if (edge.from === nodeId) {
440
+ const successorCost = costToLeaf.get(edge.to) ?? 0
441
+ if (successorCost > maxCost) {
442
+ maxCost = successorCost
443
+ bestPath = [nodeId, ...(pathToLeaf.get(edge.to) ?? [])]
444
+ }
445
+ }
446
+ }
447
+
448
+ costToLeaf.set(nodeId, node.estimatedCost + maxCost)
449
+ pathToLeaf.set(nodeId, bestPath)
450
+ }
451
+
452
+ // Find root with maximum cost to leaf
453
+ let maxTotalCost = 0
454
+ let criticalPath: string[] = []
455
+
456
+ for (const nodeId of nodes.keys()) {
457
+ const inDeg = edges.filter((e) => e.to === nodeId).length
458
+ if (inDeg === 0) {
459
+ const totalCost = costToLeaf.get(nodeId) ?? 0
460
+ if (totalCost > maxTotalCost) {
461
+ maxTotalCost = totalCost
462
+ criticalPath = pathToLeaf.get(nodeId) ?? []
463
+ }
464
+ }
465
+ }
466
+
467
+ return criticalPath
468
+ }
469
+
470
+ private calculateExecutionLevels(graph: DependencyGraph): readonly string[][] {
471
+ const levels: string[][] = []
472
+ const completed = new Set<string>()
473
+
474
+ while (completed.size < graph.nodes.size) {
475
+ const ready = this.getReadyNodes(graph, completed)
476
+ if (ready.length === 0) {
477
+ // No more nodes ready (cycle or all done)
478
+ break
479
+ }
480
+
481
+ levels.push([...ready])
482
+ for (const nodeId of ready) {
483
+ completed.add(nodeId)
484
+ }
485
+ }
486
+
487
+ return levels
488
+ }
489
+
490
+ private findBottlenecks(graph: DependencyGraph, criticalPath: readonly string[]): readonly string[] {
491
+ if (criticalPath.length === 0) {
492
+ return []
493
+ }
494
+
495
+ // Calculate average cost
496
+ let totalCost = 0
497
+ for (const node of graph.nodes.values()) {
498
+ totalCost += node.estimatedCost
499
+ }
500
+ const avgCost = totalCost / graph.nodes.size
501
+
502
+ // Bottlenecks are critical path nodes with above-average cost
503
+ const bottlenecks: string[] = []
504
+ for (const nodeId of criticalPath) {
505
+ const node = graph.nodes.get(nodeId)
506
+ if (node && node.estimatedCost > avgCost * 1.5) {
507
+ bottlenecks.push(nodeId)
508
+ }
509
+ }
510
+
511
+ return bottlenecks
512
+ }
513
+
514
+ private suggestParallelism(_graph: DependencyGraph, levels: readonly string[][]): number {
515
+ if (levels.length === 0) {
516
+ return 1
517
+ }
518
+
519
+ // Suggested parallelism is the maximum level width
520
+ let maxWidth = 1
521
+ for (const level of levels) {
522
+ maxWidth = Math.max(maxWidth, level.length)
523
+ }
524
+
525
+ // Cap at reasonable maximum
526
+ return Math.min(maxWidth, 8)
527
+ }
528
+
529
+ private calculateRoots(
530
+ nodes: Map<string, DependencyNode>,
531
+ edges: DependencyEdge[]
532
+ ): readonly string[] {
533
+ const hasIncoming = new Set<string>()
534
+ for (const edge of edges) {
535
+ hasIncoming.add(edge.to)
536
+ }
537
+
538
+ const roots: string[] = []
539
+ for (const nodeId of nodes.keys()) {
540
+ if (!hasIncoming.has(nodeId)) {
541
+ roots.push(nodeId)
542
+ }
543
+ }
544
+
545
+ return roots
546
+ }
547
+
548
+ private calculateLeaves(
549
+ nodes: Map<string, DependencyNode>,
550
+ edges: DependencyEdge[]
551
+ ): readonly string[] {
552
+ const hasOutgoing = new Set<string>()
553
+ for (const edge of edges) {
554
+ hasOutgoing.add(edge.from)
555
+ }
556
+
557
+ const leaves: string[] = []
558
+ for (const nodeId of nodes.keys()) {
559
+ if (!hasOutgoing.has(nodeId)) {
560
+ leaves.push(nodeId)
561
+ }
562
+ }
563
+
564
+ return leaves
565
+ }
566
+ }
567
+
568
+ /**
569
+ * Create a dependency analyzer instance
570
+ */
571
+ export function createDependencyAnalyzer(): IDependencyAnalyzer {
572
+ return new DependencyAnalyzer()
573
+ }
574
+
575
+ /**
576
+ * Create a dependency node
577
+ */
578
+ export function createDependencyNode(
579
+ id: string,
580
+ circuitId: string,
581
+ system: DependencyNode['system'],
582
+ options: {
583
+ dependencies?: string[]
584
+ estimatedCost?: number
585
+ estimatedMemory?: number
586
+ privateInputs?: Record<string, unknown>
587
+ publicInputs?: Record<string, unknown>
588
+ priority?: number
589
+ } = {}
590
+ ): DependencyNode {
591
+ return {
592
+ id,
593
+ circuitId,
594
+ system,
595
+ dependencies: options.dependencies ?? [],
596
+ estimatedCost: options.estimatedCost ?? 100,
597
+ estimatedMemory: options.estimatedMemory ?? 64 * 1024 * 1024, // 64MB default
598
+ privateInputs: options.privateInputs ?? {},
599
+ publicInputs: options.publicInputs ?? {},
600
+ priority: options.priority,
601
+ }
602
+ }