@agirails/sdk 2.0.1-beta → 2.0.2

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 (405) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +116 -108
  3. package/bin/actp +10 -0
  4. package/dist/ACTPClient.d.ts +456 -33
  5. package/dist/ACTPClient.d.ts.map +1 -1
  6. package/dist/ACTPClient.js +477 -93
  7. package/dist/ACTPClient.js.map +1 -1
  8. package/dist/abi/AgentRegistry.json +782 -0
  9. package/dist/abi/EscrowVault.json +106 -38
  10. package/dist/abi/IdentityRegistry.json +316 -0
  11. package/dist/adapters/BaseAdapter.d.ts +231 -0
  12. package/dist/adapters/BaseAdapter.d.ts.map +1 -0
  13. package/dist/adapters/BaseAdapter.js +393 -0
  14. package/dist/adapters/BaseAdapter.js.map +1 -0
  15. package/dist/adapters/BeginnerAdapter.d.ts +152 -0
  16. package/dist/adapters/BeginnerAdapter.d.ts.map +1 -0
  17. package/dist/adapters/BeginnerAdapter.js +168 -0
  18. package/dist/adapters/BeginnerAdapter.js.map +1 -0
  19. package/dist/adapters/IntermediateAdapter.d.ts +211 -0
  20. package/dist/adapters/IntermediateAdapter.d.ts.map +1 -0
  21. package/dist/adapters/IntermediateAdapter.js +260 -0
  22. package/dist/adapters/IntermediateAdapter.js.map +1 -0
  23. package/dist/adapters/index.d.ts +15 -0
  24. package/dist/adapters/index.d.ts.map +1 -0
  25. package/dist/adapters/index.js +26 -0
  26. package/dist/adapters/index.js.map +1 -0
  27. package/dist/builders/DeliveryProofBuilder.d.ts +60 -1
  28. package/dist/builders/DeliveryProofBuilder.d.ts.map +1 -1
  29. package/dist/builders/DeliveryProofBuilder.js +81 -5
  30. package/dist/builders/DeliveryProofBuilder.js.map +1 -1
  31. package/dist/builders/QuoteBuilder.d.ts +101 -0
  32. package/dist/builders/QuoteBuilder.d.ts.map +1 -1
  33. package/dist/builders/QuoteBuilder.js +120 -3
  34. package/dist/builders/QuoteBuilder.js.map +1 -1
  35. package/dist/builders/index.d.ts +4 -0
  36. package/dist/builders/index.d.ts.map +1 -1
  37. package/dist/builders/index.js +4 -0
  38. package/dist/builders/index.js.map +1 -1
  39. package/dist/cli/commands/balance.d.ts +13 -0
  40. package/dist/cli/commands/balance.d.ts.map +1 -0
  41. package/dist/cli/commands/balance.js +89 -0
  42. package/dist/cli/commands/balance.js.map +1 -0
  43. package/dist/cli/commands/batch.d.ts +24 -0
  44. package/dist/cli/commands/batch.d.ts.map +1 -0
  45. package/dist/cli/commands/batch.js +424 -0
  46. package/dist/cli/commands/batch.js.map +1 -0
  47. package/dist/cli/commands/config.d.ts +13 -0
  48. package/dist/cli/commands/config.d.ts.map +1 -0
  49. package/dist/cli/commands/config.js +192 -0
  50. package/dist/cli/commands/config.js.map +1 -0
  51. package/dist/cli/commands/init.d.ts +19 -0
  52. package/dist/cli/commands/init.d.ts.map +1 -0
  53. package/dist/cli/commands/init.js +143 -0
  54. package/dist/cli/commands/init.js.map +1 -0
  55. package/dist/cli/commands/mint.d.ts +13 -0
  56. package/dist/cli/commands/mint.d.ts.map +1 -0
  57. package/dist/cli/commands/mint.js +91 -0
  58. package/dist/cli/commands/mint.js.map +1 -0
  59. package/dist/cli/commands/pay.d.ts +18 -0
  60. package/dist/cli/commands/pay.d.ts.map +1 -0
  61. package/dist/cli/commands/pay.js +87 -0
  62. package/dist/cli/commands/pay.js.map +1 -0
  63. package/dist/cli/commands/simulate.d.ts +32 -0
  64. package/dist/cli/commands/simulate.d.ts.map +1 -0
  65. package/dist/cli/commands/simulate.js +290 -0
  66. package/dist/cli/commands/simulate.js.map +1 -0
  67. package/dist/cli/commands/time.d.ts +29 -0
  68. package/dist/cli/commands/time.d.ts.map +1 -0
  69. package/dist/cli/commands/time.js +252 -0
  70. package/dist/cli/commands/time.js.map +1 -0
  71. package/dist/cli/commands/tx.d.ts +16 -0
  72. package/dist/cli/commands/tx.d.ts.map +1 -0
  73. package/dist/cli/commands/tx.js +379 -0
  74. package/dist/cli/commands/tx.js.map +1 -0
  75. package/dist/cli/commands/watch.d.ts +20 -0
  76. package/dist/cli/commands/watch.d.ts.map +1 -0
  77. package/dist/cli/commands/watch.js +160 -0
  78. package/dist/cli/commands/watch.js.map +1 -0
  79. package/dist/cli/index.d.ts +17 -0
  80. package/dist/cli/index.d.ts.map +1 -0
  81. package/dist/cli/index.js +104 -0
  82. package/dist/cli/index.js.map +1 -0
  83. package/dist/cli/utils/client.d.ts +70 -0
  84. package/dist/cli/utils/client.d.ts.map +1 -0
  85. package/dist/cli/utils/client.js +240 -0
  86. package/dist/cli/utils/client.js.map +1 -0
  87. package/dist/cli/utils/config.d.ts +91 -0
  88. package/dist/cli/utils/config.d.ts.map +1 -0
  89. package/dist/cli/utils/config.js +240 -0
  90. package/dist/cli/utils/config.js.map +1 -0
  91. package/dist/cli/utils/output.d.ts +174 -0
  92. package/dist/cli/utils/output.d.ts.map +1 -0
  93. package/dist/cli/utils/output.js +380 -0
  94. package/dist/cli/utils/output.js.map +1 -0
  95. package/dist/config/networks.d.ts +28 -0
  96. package/dist/config/networks.d.ts.map +1 -1
  97. package/dist/config/networks.js +60 -12
  98. package/dist/config/networks.js.map +1 -1
  99. package/dist/errors/index.d.ts +165 -2
  100. package/dist/errors/index.d.ts.map +1 -1
  101. package/dist/errors/index.js +260 -2
  102. package/dist/errors/index.js.map +1 -1
  103. package/dist/index.d.ts +61 -13
  104. package/dist/index.d.ts.map +1 -1
  105. package/dist/index.js +141 -36
  106. package/dist/index.js.map +1 -1
  107. package/dist/level0/Provider.d.ts +106 -0
  108. package/dist/level0/Provider.d.ts.map +1 -0
  109. package/dist/level0/Provider.js +10 -0
  110. package/dist/level0/Provider.js.map +1 -0
  111. package/dist/level0/ServiceDirectory.d.ts +74 -0
  112. package/dist/level0/ServiceDirectory.d.ts.map +1 -0
  113. package/dist/level0/ServiceDirectory.js +122 -0
  114. package/dist/level0/ServiceDirectory.js.map +1 -0
  115. package/dist/level0/index.d.ts +10 -0
  116. package/dist/level0/index.d.ts.map +1 -0
  117. package/dist/level0/index.js +15 -0
  118. package/dist/level0/index.js.map +1 -0
  119. package/dist/level0/provide.d.ts +51 -0
  120. package/dist/level0/provide.d.ts.map +1 -0
  121. package/dist/level0/provide.js +113 -0
  122. package/dist/level0/provide.js.map +1 -0
  123. package/dist/level0/request.d.ts +53 -0
  124. package/dist/level0/request.d.ts.map +1 -0
  125. package/dist/level0/request.js +462 -0
  126. package/dist/level0/request.js.map +1 -0
  127. package/dist/level1/Agent.d.ts +472 -0
  128. package/dist/level1/Agent.d.ts.map +1 -0
  129. package/dist/level1/Agent.js +1091 -0
  130. package/dist/level1/Agent.js.map +1 -0
  131. package/dist/level1/index.d.ts +10 -0
  132. package/dist/level1/index.d.ts.map +1 -0
  133. package/dist/level1/index.js +30 -0
  134. package/dist/level1/index.js.map +1 -0
  135. package/dist/level1/pricing/PriceCalculator.d.ts +62 -0
  136. package/dist/level1/pricing/PriceCalculator.d.ts.map +1 -0
  137. package/dist/level1/pricing/PriceCalculator.js +237 -0
  138. package/dist/level1/pricing/PriceCalculator.js.map +1 -0
  139. package/dist/level1/pricing/PricingStrategy.d.ts +179 -0
  140. package/dist/level1/pricing/PricingStrategy.d.ts.map +1 -0
  141. package/dist/level1/pricing/PricingStrategy.js +11 -0
  142. package/dist/level1/pricing/PricingStrategy.js.map +1 -0
  143. package/dist/level1/types/Job.d.ts +166 -0
  144. package/dist/level1/types/Job.d.ts.map +1 -0
  145. package/dist/level1/types/Job.js +11 -0
  146. package/dist/level1/types/Job.js.map +1 -0
  147. package/dist/level1/types/Options.d.ts +258 -0
  148. package/dist/level1/types/Options.d.ts.map +1 -0
  149. package/dist/level1/types/Options.js +8 -0
  150. package/dist/level1/types/Options.js.map +1 -0
  151. package/dist/level1/types/index.d.ts +8 -0
  152. package/dist/level1/types/index.d.ts.map +1 -0
  153. package/dist/level1/types/index.js +8 -0
  154. package/dist/level1/types/index.js.map +1 -0
  155. package/dist/protocol/ACTPKernel.d.ts +229 -2
  156. package/dist/protocol/ACTPKernel.d.ts.map +1 -1
  157. package/dist/protocol/ACTPKernel.js +367 -33
  158. package/dist/protocol/ACTPKernel.js.map +1 -1
  159. package/dist/protocol/AgentRegistry.d.ts +177 -0
  160. package/dist/protocol/AgentRegistry.d.ts.map +1 -0
  161. package/dist/protocol/AgentRegistry.js +449 -0
  162. package/dist/protocol/AgentRegistry.js.map +1 -0
  163. package/dist/protocol/DIDManager.d.ts +289 -0
  164. package/dist/protocol/DIDManager.d.ts.map +1 -0
  165. package/dist/protocol/DIDManager.js +481 -0
  166. package/dist/protocol/DIDManager.js.map +1 -0
  167. package/dist/protocol/DIDResolver.d.ts +236 -0
  168. package/dist/protocol/DIDResolver.d.ts.map +1 -0
  169. package/dist/protocol/DIDResolver.js +495 -0
  170. package/dist/protocol/DIDResolver.js.map +1 -0
  171. package/dist/protocol/EASHelper.d.ts +57 -2
  172. package/dist/protocol/EASHelper.d.ts.map +1 -1
  173. package/dist/protocol/EASHelper.js +230 -37
  174. package/dist/protocol/EASHelper.js.map +1 -1
  175. package/dist/protocol/EscrowVault.d.ts +93 -2
  176. package/dist/protocol/EscrowVault.d.ts.map +1 -1
  177. package/dist/protocol/EscrowVault.js +122 -33
  178. package/dist/protocol/EscrowVault.js.map +1 -1
  179. package/dist/protocol/EventMonitor.d.ts +45 -1
  180. package/dist/protocol/EventMonitor.d.ts.map +1 -1
  181. package/dist/protocol/EventMonitor.js +64 -8
  182. package/dist/protocol/EventMonitor.js.map +1 -1
  183. package/dist/protocol/MessageSigner.d.ts +116 -2
  184. package/dist/protocol/MessageSigner.d.ts.map +1 -1
  185. package/dist/protocol/MessageSigner.js +215 -9
  186. package/dist/protocol/MessageSigner.js.map +1 -1
  187. package/dist/protocol/ProofGenerator.d.ts +93 -0
  188. package/dist/protocol/ProofGenerator.d.ts.map +1 -1
  189. package/dist/protocol/ProofGenerator.js +194 -9
  190. package/dist/protocol/ProofGenerator.js.map +1 -1
  191. package/dist/protocol/QuoteBuilder.d.ts +8 -0
  192. package/dist/protocol/QuoteBuilder.d.ts.map +1 -1
  193. package/dist/protocol/QuoteBuilder.js +8 -0
  194. package/dist/protocol/QuoteBuilder.js.map +1 -1
  195. package/dist/runtime/BlockchainRuntime.d.ts +360 -0
  196. package/dist/runtime/BlockchainRuntime.d.ts.map +1 -0
  197. package/dist/runtime/BlockchainRuntime.js +767 -0
  198. package/dist/runtime/BlockchainRuntime.js.map +1 -0
  199. package/dist/runtime/IACTPRuntime.d.ts +271 -0
  200. package/dist/runtime/IACTPRuntime.d.ts.map +1 -0
  201. package/dist/runtime/IACTPRuntime.js +15 -0
  202. package/dist/runtime/IACTPRuntime.js.map +1 -0
  203. package/dist/runtime/MockRuntime.d.ts +445 -0
  204. package/dist/runtime/MockRuntime.d.ts.map +1 -0
  205. package/dist/runtime/MockRuntime.js +1065 -0
  206. package/dist/runtime/MockRuntime.js.map +1 -0
  207. package/dist/runtime/MockStateManager.d.ts +233 -0
  208. package/dist/runtime/MockStateManager.d.ts.map +1 -0
  209. package/dist/runtime/MockStateManager.js +533 -0
  210. package/dist/runtime/MockStateManager.js.map +1 -0
  211. package/dist/runtime/index.d.ts +14 -0
  212. package/dist/runtime/index.d.ts.map +1 -0
  213. package/dist/runtime/index.js +42 -0
  214. package/dist/runtime/index.js.map +1 -0
  215. package/dist/runtime/types/MockState.d.ts +167 -0
  216. package/dist/runtime/types/MockState.d.ts.map +1 -0
  217. package/dist/runtime/types/MockState.js +43 -0
  218. package/dist/runtime/types/MockState.js.map +1 -0
  219. package/dist/types/agent.d.ts +76 -0
  220. package/dist/types/agent.d.ts.map +1 -0
  221. package/dist/types/agent.js +8 -0
  222. package/dist/types/agent.js.map +1 -0
  223. package/dist/types/did.d.ts +192 -0
  224. package/dist/types/did.d.ts.map +1 -0
  225. package/dist/types/did.js +38 -0
  226. package/dist/types/did.js.map +1 -0
  227. package/dist/types/eip712.d.ts +34 -0
  228. package/dist/types/eip712.d.ts.map +1 -1
  229. package/dist/types/eip712.js +31 -5
  230. package/dist/types/eip712.js.map +1 -1
  231. package/dist/types/escrow.d.ts +17 -10
  232. package/dist/types/escrow.d.ts.map +1 -1
  233. package/dist/types/index.d.ts +5 -0
  234. package/dist/types/index.d.ts.map +1 -1
  235. package/dist/types/index.js +8 -0
  236. package/dist/types/index.js.map +1 -1
  237. package/dist/types/message.d.ts +32 -0
  238. package/dist/types/message.d.ts.map +1 -1
  239. package/dist/types/message.js +4 -0
  240. package/dist/types/message.js.map +1 -1
  241. package/dist/types/state.d.ts +28 -0
  242. package/dist/types/state.d.ts.map +1 -1
  243. package/dist/types/state.js +37 -6
  244. package/dist/types/state.js.map +1 -1
  245. package/dist/types/transaction.d.ts +17 -0
  246. package/dist/types/transaction.d.ts.map +1 -1
  247. package/dist/utils/ErrorRecoveryGuide.d.ts +125 -0
  248. package/dist/utils/ErrorRecoveryGuide.d.ts.map +1 -0
  249. package/dist/utils/ErrorRecoveryGuide.js +579 -0
  250. package/dist/utils/ErrorRecoveryGuide.js.map +1 -0
  251. package/dist/utils/Helpers.d.ts +453 -0
  252. package/dist/utils/Helpers.d.ts.map +1 -0
  253. package/dist/utils/Helpers.js +623 -0
  254. package/dist/utils/Helpers.js.map +1 -0
  255. package/dist/utils/IPFSClient.d.ts +113 -0
  256. package/dist/utils/IPFSClient.d.ts.map +1 -1
  257. package/dist/utils/IPFSClient.js +128 -7
  258. package/dist/utils/IPFSClient.js.map +1 -1
  259. package/dist/utils/Logger.d.ts +195 -0
  260. package/dist/utils/Logger.d.ts.map +1 -0
  261. package/dist/utils/Logger.js +382 -0
  262. package/dist/utils/Logger.js.map +1 -0
  263. package/dist/utils/NonceManager.d.ts +234 -1
  264. package/dist/utils/NonceManager.d.ts.map +1 -1
  265. package/dist/utils/NonceManager.js +372 -7
  266. package/dist/utils/NonceManager.js.map +1 -1
  267. package/dist/utils/RateLimiter.d.ts +253 -0
  268. package/dist/utils/RateLimiter.d.ts.map +1 -0
  269. package/dist/utils/RateLimiter.js +424 -0
  270. package/dist/utils/RateLimiter.js.map +1 -0
  271. package/dist/utils/ReceivedNonceTracker.d.ts +175 -0
  272. package/dist/utils/ReceivedNonceTracker.d.ts.map +1 -1
  273. package/dist/utils/ReceivedNonceTracker.js +261 -5
  274. package/dist/utils/ReceivedNonceTracker.js.map +1 -1
  275. package/dist/utils/SDKLifecycle.d.ts +156 -0
  276. package/dist/utils/SDKLifecycle.d.ts.map +1 -0
  277. package/dist/utils/SDKLifecycle.js +347 -0
  278. package/dist/utils/SDKLifecycle.js.map +1 -0
  279. package/dist/utils/SecureNonce.d.ts +57 -0
  280. package/dist/utils/SecureNonce.d.ts.map +1 -0
  281. package/dist/utils/SecureNonce.js +80 -0
  282. package/dist/utils/SecureNonce.js.map +1 -0
  283. package/dist/utils/Semaphore.d.ts +123 -0
  284. package/dist/utils/Semaphore.d.ts.map +1 -0
  285. package/dist/utils/Semaphore.js +247 -0
  286. package/dist/utils/Semaphore.js.map +1 -0
  287. package/dist/utils/UsedAttestationTracker.d.ts +167 -0
  288. package/dist/utils/UsedAttestationTracker.d.ts.map +1 -0
  289. package/dist/utils/UsedAttestationTracker.js +309 -0
  290. package/dist/utils/UsedAttestationTracker.js.map +1 -0
  291. package/dist/utils/canonicalJson.d.ts +22 -0
  292. package/dist/utils/canonicalJson.d.ts.map +1 -1
  293. package/dist/utils/canonicalJson.js +26 -3
  294. package/dist/utils/canonicalJson.js.map +1 -1
  295. package/dist/utils/computeTypeHash.d.ts +14 -0
  296. package/dist/utils/computeTypeHash.d.ts.map +1 -1
  297. package/dist/utils/computeTypeHash.js +19 -2
  298. package/dist/utils/computeTypeHash.js.map +1 -1
  299. package/dist/utils/fsSafe.d.ts +14 -0
  300. package/dist/utils/fsSafe.d.ts.map +1 -0
  301. package/dist/utils/fsSafe.js +89 -0
  302. package/dist/utils/fsSafe.js.map +1 -0
  303. package/dist/utils/index.d.ts +15 -0
  304. package/dist/utils/index.d.ts.map +1 -0
  305. package/dist/utils/index.js +51 -0
  306. package/dist/utils/index.js.map +1 -0
  307. package/dist/utils/security.d.ts +147 -0
  308. package/dist/utils/security.d.ts.map +1 -0
  309. package/dist/utils/security.js +391 -0
  310. package/dist/utils/security.js.map +1 -0
  311. package/dist/utils/validation.d.ts +40 -0
  312. package/dist/utils/validation.d.ts.map +1 -1
  313. package/dist/utils/validation.js +184 -7
  314. package/dist/utils/validation.js.map +1 -1
  315. package/package.json +54 -37
  316. package/src/ACTPClient.ts +692 -178
  317. package/src/abi/AgentRegistry.json +782 -0
  318. package/src/abi/EscrowVault.json +106 -38
  319. package/src/abi/IdentityRegistry.json +316 -0
  320. package/src/adapters/BaseAdapter.ts +473 -0
  321. package/src/adapters/BeginnerAdapter.ts +232 -0
  322. package/src/adapters/IntermediateAdapter.ts +316 -0
  323. package/src/adapters/index.ts +25 -0
  324. package/src/builders/DeliveryProofBuilder.ts +3 -2
  325. package/src/cli/commands/balance.ts +110 -0
  326. package/src/cli/commands/batch.ts +487 -0
  327. package/src/cli/commands/config.ts +231 -0
  328. package/src/cli/commands/init.ts +161 -0
  329. package/src/cli/commands/mint.ts +116 -0
  330. package/src/cli/commands/pay.ts +113 -0
  331. package/src/cli/commands/simulate.ts +345 -0
  332. package/src/cli/commands/time.ts +303 -0
  333. package/src/cli/commands/tx.ts +448 -0
  334. package/src/cli/commands/watch.ts +211 -0
  335. package/src/cli/index.ts +116 -0
  336. package/src/cli/utils/client.ts +249 -0
  337. package/src/cli/utils/config.ts +282 -0
  338. package/src/cli/utils/output.ts +465 -0
  339. package/src/config/networks.ts +32 -9
  340. package/src/errors/index.ts +298 -1
  341. package/src/index.ts +207 -71
  342. package/src/level0/Provider.ts +117 -0
  343. package/src/level0/ServiceDirectory.ts +131 -0
  344. package/src/level0/index.ts +10 -0
  345. package/src/level0/provide.ts +131 -0
  346. package/src/level0/request.ts +494 -0
  347. package/src/level1/Agent.ts +1432 -0
  348. package/src/level1/index.ts +10 -0
  349. package/src/level1/pricing/PriceCalculator.ts +255 -0
  350. package/src/level1/pricing/PricingStrategy.ts +198 -0
  351. package/src/level1/types/Job.ts +179 -0
  352. package/src/level1/types/Options.ts +291 -0
  353. package/src/level1/types/index.ts +8 -0
  354. package/src/protocol/ACTPKernel.ts +175 -23
  355. package/src/protocol/AgentRegistry.ts +559 -0
  356. package/src/protocol/DIDManager.ts +629 -0
  357. package/src/protocol/DIDResolver.ts +554 -0
  358. package/src/protocol/EASHelper.ts +230 -46
  359. package/src/protocol/EscrowVault.ts +68 -50
  360. package/src/protocol/EventMonitor.ts +44 -15
  361. package/src/protocol/MessageSigner.ts +193 -13
  362. package/src/protocol/ProofGenerator.ts +223 -4
  363. package/src/runtime/BlockchainRuntime.ts +993 -0
  364. package/src/runtime/IACTPRuntime.ts +284 -0
  365. package/src/runtime/MockRuntime.ts +1244 -0
  366. package/src/runtime/MockStateManager.ts +576 -0
  367. package/src/runtime/index.ts +25 -0
  368. package/src/runtime/types/MockState.ts +227 -0
  369. package/src/types/agent.ts +79 -0
  370. package/src/types/did.ts +223 -0
  371. package/src/types/escrow.ts +12 -11
  372. package/src/types/index.ts +5 -1
  373. package/src/types/state.ts +12 -3
  374. package/src/types/transaction.ts +4 -1
  375. package/src/utils/ErrorRecoveryGuide.ts +675 -0
  376. package/src/utils/Helpers.ts +688 -0
  377. package/src/utils/IPFSClient.ts +122 -5
  378. package/src/utils/Logger.ts +484 -0
  379. package/src/utils/NonceManager.ts +305 -8
  380. package/src/utils/RateLimiter.ts +534 -0
  381. package/src/utils/ReceivedNonceTracker.ts +170 -0
  382. package/src/utils/SDKLifecycle.ts +416 -0
  383. package/src/utils/SecureNonce.ts +78 -0
  384. package/src/utils/Semaphore.ts +276 -0
  385. package/src/utils/UsedAttestationTracker.ts +387 -0
  386. package/src/utils/fsSafe.ts +75 -0
  387. package/src/utils/index.ts +80 -0
  388. package/src/utils/security.ts +418 -0
  389. package/src/utils/validation.ts +164 -0
  390. package/src/__tests__/ProofGenerator.test.ts +0 -124
  391. package/src/__tests__/QuoteBuilder.test.ts +0 -516
  392. package/src/__tests__/StateMachine.test.ts +0 -82
  393. package/src/__tests__/builders/DeliveryProofBuilder.test.ts +0 -581
  394. package/src/__tests__/integration/ACTPClient.test.ts +0 -263
  395. package/src/__tests__/integration.test.ts +0 -289
  396. package/src/__tests__/protocol/EASHelper.test.ts +0 -472
  397. package/src/__tests__/protocol/EventMonitor.test.ts +0 -382
  398. package/src/__tests__/security/ACTPKernel.security.test.ts +0 -1167
  399. package/src/__tests__/security/EscrowVault.security.test.ts +0 -570
  400. package/src/__tests__/security/MessageSigner.security.test.ts +0 -286
  401. package/src/__tests__/security/NonceReplay.security.test.ts +0 -501
  402. package/src/__tests__/security/validation.security.test.ts +0 -376
  403. package/src/__tests__/utils/IPFSClient.test.ts +0 -262
  404. package/src/__tests__/utils/NonceManager.test.ts +0 -205
  405. package/src/__tests__/utils/canonicalJson.test.ts +0 -153
@@ -0,0 +1,1065 @@
1
+ "use strict";
2
+ /**
3
+ * MockRuntime - Core mock blockchain engine for ACTP protocol testing
4
+ *
5
+ * Provides a complete mock blockchain environment for testing ACTP transactions
6
+ * without real blockchain interactions. Implements the 8-state ACTP transaction
7
+ * lifecycle with strict state machine validation.
8
+ *
9
+ * Features:
10
+ * - 8-state transaction lifecycle (INITIATED -> QUOTED -> COMMITTED -> IN_PROGRESS -> DELIVERED -> SETTLED)
11
+ * - Time manipulation (advanceTime, setTime, advanceBlocks)
12
+ * - Balance management (mint, transfer)
13
+ * - Event recording and querying
14
+ * - Escrow operations (link, release, balance tracking)
15
+ *
16
+ * @module runtime/MockRuntime
17
+ * @see ADR-004 (Mock Blockchain Emulation Scope)
18
+ * @see MOCK_MODE_SPECIFICATION.md
19
+ */
20
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
21
+ if (k2 === undefined) k2 = k;
22
+ var desc = Object.getOwnPropertyDescriptor(m, k);
23
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
24
+ desc = { enumerable: true, get: function() { return m[k]; } };
25
+ }
26
+ Object.defineProperty(o, k2, desc);
27
+ }) : (function(o, m, k, k2) {
28
+ if (k2 === undefined) k2 = k;
29
+ o[k2] = m[k];
30
+ }));
31
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
32
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
33
+ }) : function(o, v) {
34
+ o["default"] = v;
35
+ });
36
+ var __importStar = (this && this.__importStar) || function (mod) {
37
+ if (mod && mod.__esModule) return mod;
38
+ var result = {};
39
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
40
+ __setModuleDefault(result, mod);
41
+ return result;
42
+ };
43
+ Object.defineProperty(exports, "__esModule", { value: true });
44
+ exports.MockRuntime = exports.DisputeWindowActiveError = exports.InvalidAmountError = exports.ContractPausedError = exports.DeadlinePassedError = exports.EscrowNotFoundError = exports.InsufficientBalanceError = exports.InvalidStateTransitionError = exports.TransactionNotFoundError = void 0;
45
+ const crypto = __importStar(require("crypto"));
46
+ const MockStateManager_1 = require("./MockStateManager");
47
+ // ============================================================================
48
+ // Custom Error Classes
49
+ // ============================================================================
50
+ /**
51
+ * Error thrown when a transaction is not found.
52
+ */
53
+ class TransactionNotFoundError extends Error {
54
+ constructor(txId) {
55
+ super(`Transaction not found: ${txId}`);
56
+ this.name = 'TransactionNotFoundError';
57
+ this.txId = txId;
58
+ }
59
+ }
60
+ exports.TransactionNotFoundError = TransactionNotFoundError;
61
+ /**
62
+ * Error thrown when an invalid state transition is attempted.
63
+ */
64
+ class InvalidStateTransitionError extends Error {
65
+ constructor(txId, currentState, targetState) {
66
+ super(`Invalid state transition for transaction ${txId}: ${currentState} -> ${targetState}`);
67
+ this.name = 'InvalidStateTransitionError';
68
+ this.txId = txId;
69
+ this.currentState = currentState;
70
+ this.targetState = targetState;
71
+ }
72
+ }
73
+ exports.InvalidStateTransitionError = InvalidStateTransitionError;
74
+ /**
75
+ * Error thrown when there are insufficient funds for an operation.
76
+ */
77
+ class InsufficientBalanceError extends Error {
78
+ constructor(address, required, available) {
79
+ super(`Insufficient balance for ${address}: required ${required}, available ${available}`);
80
+ this.name = 'InsufficientBalanceError';
81
+ this.address = address;
82
+ this.required = required;
83
+ this.available = available;
84
+ }
85
+ }
86
+ exports.InsufficientBalanceError = InsufficientBalanceError;
87
+ /**
88
+ * Error thrown when an escrow is not found.
89
+ */
90
+ class EscrowNotFoundError extends Error {
91
+ constructor(escrowId) {
92
+ super(`Escrow not found: ${escrowId}`);
93
+ this.name = 'EscrowNotFoundError';
94
+ this.escrowId = escrowId;
95
+ }
96
+ }
97
+ exports.EscrowNotFoundError = EscrowNotFoundError;
98
+ /**
99
+ * Error thrown when the deadline has passed.
100
+ */
101
+ class DeadlinePassedError extends Error {
102
+ constructor(txId, deadline, currentTime) {
103
+ super(`Deadline passed for transaction ${txId}: deadline ${deadline}, current time ${currentTime}`);
104
+ this.name = 'DeadlinePassedError';
105
+ this.txId = txId;
106
+ this.deadline = deadline;
107
+ this.currentTime = currentTime;
108
+ }
109
+ }
110
+ exports.DeadlinePassedError = DeadlinePassedError;
111
+ /**
112
+ * Error thrown when the contract is paused.
113
+ */
114
+ class ContractPausedError extends Error {
115
+ constructor() {
116
+ super('Contract is paused');
117
+ this.name = 'ContractPausedError';
118
+ }
119
+ }
120
+ exports.ContractPausedError = ContractPausedError;
121
+ /**
122
+ * Error thrown when an invalid amount is provided.
123
+ *
124
+ * Thrown when zero or negative amounts are passed to transaction
125
+ * or escrow operations.
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * // This will throw InvalidAmountError
130
+ * await runtime.createTransaction({
131
+ * provider: '0x...',
132
+ * requester: '0x...',
133
+ * amount: '0', // Invalid - must be positive
134
+ * deadline: Date.now() + 86400
135
+ * });
136
+ * ```
137
+ */
138
+ class InvalidAmountError extends Error {
139
+ constructor(amount, reason) {
140
+ super(`Invalid amount "${amount}": ${reason}`);
141
+ this.name = 'InvalidAmountError';
142
+ this.amount = amount;
143
+ this.reason = reason;
144
+ }
145
+ }
146
+ exports.InvalidAmountError = InvalidAmountError;
147
+ /**
148
+ * Error thrown when dispute window is still active.
149
+ *
150
+ * Thrown when attempting to release escrow funds before the dispute
151
+ * window has expired. Use `runtime.time.advanceTime()` in tests to
152
+ * simulate waiting for the window to close.
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * // Transaction delivered, but dispute window still active
157
+ * await runtime.releaseEscrow(escrowId);
158
+ * // Throws: DisputeWindowActiveError
159
+ *
160
+ * // Solution: advance time past the dispute window
161
+ * runtime.time.advanceTime(tx.disputeWindow + 1);
162
+ * await runtime.releaseEscrow(escrowId); // Now works
163
+ * ```
164
+ */
165
+ class DisputeWindowActiveError extends Error {
166
+ constructor(txId, windowEnd, currentTime) {
167
+ super(`Dispute window still active for transaction ${txId}. ` +
168
+ `Window ends at ${windowEnd}, current time is ${currentTime}. ` +
169
+ `Use time.advanceTime() to simulate waiting.`);
170
+ this.name = 'DisputeWindowActiveError';
171
+ this.txId = txId;
172
+ this.windowEnd = windowEnd;
173
+ this.currentTime = currentTime;
174
+ }
175
+ }
176
+ exports.DisputeWindowActiveError = DisputeWindowActiveError;
177
+ // ============================================================================
178
+ // Types
179
+ // ============================================================================
180
+ // CreateTransactionParams now imported from IACTPRuntime interface
181
+ /**
182
+ * Valid state transitions for the ACTP 8-state machine.
183
+ *
184
+ * State machine:
185
+ * - INITIATED -> QUOTED (optional), COMMITTED, CANCELLED
186
+ * - QUOTED -> COMMITTED, CANCELLED
187
+ * - COMMITTED -> IN_PROGRESS (optional), DELIVERED, CANCELLED
188
+ * - IN_PROGRESS -> DELIVERED, CANCELLED
189
+ * - DELIVERED -> SETTLED, DISPUTED
190
+ * - DISPUTED -> SETTLED
191
+ * - SETTLED (terminal)
192
+ * - CANCELLED (terminal)
193
+ */
194
+ const VALID_TRANSITIONS = {
195
+ INITIATED: ['QUOTED', 'COMMITTED', 'CANCELLED'],
196
+ QUOTED: ['COMMITTED', 'CANCELLED'],
197
+ COMMITTED: ['IN_PROGRESS', 'DELIVERED', 'CANCELLED'],
198
+ IN_PROGRESS: ['DELIVERED', 'CANCELLED'],
199
+ DELIVERED: ['SETTLED', 'DISPUTED'],
200
+ DISPUTED: ['SETTLED'],
201
+ SETTLED: [], // Terminal state
202
+ CANCELLED: [], // Terminal state
203
+ };
204
+ /**
205
+ * States from which cancellation is allowed.
206
+ */
207
+ const CANCELLABLE_STATES = [
208
+ 'INITIATED',
209
+ 'QUOTED',
210
+ 'COMMITTED',
211
+ 'IN_PROGRESS',
212
+ ];
213
+ // ============================================================================
214
+ // MockRuntime Class
215
+ // ============================================================================
216
+ /**
217
+ * MockRuntime - Core mock blockchain engine for ACTP protocol testing.
218
+ *
219
+ * Implements the IACTPRuntime interface for mock/testing mode.
220
+ * Provides a complete mock blockchain environment with:
221
+ * - Transaction state machine (8 states)
222
+ * - Time manipulation
223
+ * - Balance management
224
+ * - Event recording
225
+ *
226
+ * @example
227
+ * ```typescript
228
+ * const runtime = new MockRuntime();
229
+ *
230
+ * // Mint initial funds
231
+ * await runtime.mintTokens('0xRequester', '10000000000'); // 10,000 USDC
232
+ *
233
+ * // Create transaction
234
+ * const txId = await runtime.createTransaction({
235
+ * provider: '0xProvider',
236
+ * requester: '0xRequester',
237
+ * amount: '1000000', // 1 USDC
238
+ * deadline: runtime.time.now() + 86400,
239
+ * });
240
+ *
241
+ * // Advance time and process
242
+ * runtime.time.advanceTime(3600);
243
+ * ```
244
+ */
245
+ class MockRuntime {
246
+ /**
247
+ * Creates a new MockRuntime instance.
248
+ *
249
+ * @param stateManager - Optional custom state manager (default: creates new one)
250
+ */
251
+ constructor(stateManager) {
252
+ /**
253
+ * In-memory event log, also persisted to state file.
254
+ *
255
+ * SECURITY FIX (L-4): Events are now persisted to the state file
256
+ * so they survive across CLI invocations.
257
+ */
258
+ this.eventLog = [];
259
+ this.stateManager = stateManager ?? new MockStateManager_1.MockStateManager();
260
+ // SECURITY FIX (L-4): Load persisted events from state file
261
+ this.loadPersistedEvents();
262
+ // Initialize time interface
263
+ // SECURITY FIX: Time operations now use withLock to prevent race conditions
264
+ this.time = {
265
+ now: () => this.getCurrentTime(),
266
+ advanceTime: (seconds) => this.advanceTimeWithLock(seconds),
267
+ advanceBlocks: (blocks) => this.advanceBlocksWithLock(blocks),
268
+ setTime: (timestamp) => this.setTimeWithLock(timestamp),
269
+ };
270
+ // Initialize events interface
271
+ this.events = {
272
+ getAll: () => [...this.eventLog],
273
+ getByType: (type) => this.eventLog.filter((e) => e.type === type),
274
+ getByTransaction: (txId) => this.getEventsByTransaction(txId),
275
+ clear: () => {
276
+ this.eventLog = [];
277
+ // Also clear persisted events
278
+ this.clearPersistedEvents();
279
+ },
280
+ };
281
+ }
282
+ /**
283
+ * Load events from persisted state file.
284
+ *
285
+ * SECURITY FIX (L-4): Events survive across CLI invocations.
286
+ */
287
+ loadPersistedEvents() {
288
+ try {
289
+ const state = this.stateManager.loadState();
290
+ this.eventLog = state.events ?? [];
291
+ }
292
+ catch {
293
+ // If state doesn't exist yet, start with empty events
294
+ this.eventLog = [];
295
+ }
296
+ }
297
+ /**
298
+ * Clear persisted events from state file.
299
+ */
300
+ clearPersistedEvents() {
301
+ try {
302
+ const state = this.stateManager.loadState();
303
+ state.events = [];
304
+ this.stateManager.saveState(state);
305
+ }
306
+ catch {
307
+ // Ignore errors during clear
308
+ }
309
+ }
310
+ /**
311
+ * Persist an event to both in-memory log and state file.
312
+ *
313
+ * SECURITY FIX (L-4): Events are persisted for audit trail.
314
+ *
315
+ * @param event - Event to persist
316
+ * @param state - Current state (to avoid re-loading)
317
+ */
318
+ persistEvent(event, state) {
319
+ this.eventLog.push(event);
320
+ // Ensure events array exists
321
+ if (!state.events) {
322
+ state.events = [];
323
+ }
324
+ state.events.push(event);
325
+ }
326
+ // ============================================================================
327
+ // Transaction Operations
328
+ // ============================================================================
329
+ /**
330
+ * Creates a new transaction.
331
+ *
332
+ * @param params - Transaction creation parameters
333
+ * @returns Promise resolving to the transaction ID (bytes32 hex string)
334
+ *
335
+ * @throws {DeadlinePassedError} If deadline is in the past
336
+ *
337
+ * @example
338
+ * ```typescript
339
+ * const txId = await runtime.createTransaction({
340
+ * provider: '0xProvider',
341
+ * requester: '0xRequester',
342
+ * amount: '1000000', // 1 USDC
343
+ * deadline: runtime.time.now() + 86400,
344
+ * });
345
+ * ```
346
+ */
347
+ async createTransaction(params) {
348
+ return this.stateManager.withLock(async (state) => {
349
+ const currentTime = state.blockchain.currentTime;
350
+ const blockNumber = state.blockchain.blockNumber;
351
+ // Validate amount (Issue #2 fix)
352
+ const amountBigInt = BigInt(params.amount);
353
+ if (amountBigInt <= 0n) {
354
+ throw new InvalidAmountError(params.amount, 'Amount must be positive');
355
+ }
356
+ // Validate deadline
357
+ if (params.deadline <= currentTime) {
358
+ throw new DeadlinePassedError('new', params.deadline, currentTime);
359
+ }
360
+ // SECURITY FIX (M-4): Generate transaction ID with collision check
361
+ const txId = this.generateTransactionIdWithCollisionCheck(state);
362
+ // Create transaction
363
+ const transaction = {
364
+ id: txId,
365
+ requester: params.requester,
366
+ provider: params.provider,
367
+ amount: params.amount,
368
+ state: 'INITIATED',
369
+ createdAt: currentTime,
370
+ updatedAt: currentTime,
371
+ deadline: params.deadline,
372
+ disputeWindow: params.disputeWindow ?? 172800, // Default 2 days
373
+ completedAt: null,
374
+ escrowId: null,
375
+ serviceDescription: params.serviceDescription ?? '',
376
+ deliveryProof: null,
377
+ events: [],
378
+ };
379
+ // Record event
380
+ const event = {
381
+ type: 'TransactionCreated',
382
+ timestamp: currentTime,
383
+ blockNumber,
384
+ data: {
385
+ txId,
386
+ requester: params.requester,
387
+ provider: params.provider,
388
+ amount: params.amount,
389
+ deadline: params.deadline,
390
+ },
391
+ };
392
+ transaction.events.push(event);
393
+ state.transactions[txId] = transaction;
394
+ // SECURITY FIX (L-4): Persist event to state file
395
+ this.persistEvent(event, state);
396
+ return txId;
397
+ });
398
+ }
399
+ /**
400
+ * Gets a transaction by ID.
401
+ *
402
+ * @param txId - Transaction ID
403
+ * @returns Promise resolving to the transaction or null if not found
404
+ */
405
+ async getTransaction(txId) {
406
+ const state = this.stateManager.loadState();
407
+ return state.transactions[txId] ?? null;
408
+ }
409
+ /**
410
+ * Gets all transactions.
411
+ *
412
+ * @returns Promise resolving to array of all transactions
413
+ */
414
+ async getAllTransactions() {
415
+ const state = this.stateManager.loadState();
416
+ return Object.values(state.transactions);
417
+ }
418
+ /**
419
+ * Gets transactions filtered by provider address and optionally state.
420
+ *
421
+ * SECURITY FIX (H-1): Filtered query to prevent DoS via memory exhaustion.
422
+ * Instead of loading all transactions and filtering client-side, we filter
423
+ * server-side and limit the result set.
424
+ *
425
+ * @param provider - Provider address to filter by
426
+ * @param state - Optional state filter (e.g., 'INITIATED', 'DELIVERED')
427
+ * @param limit - Maximum number of transactions to return (default 100)
428
+ * @returns Promise resolving to filtered transactions
429
+ *
430
+ * @example
431
+ * ```typescript
432
+ * // Get up to 100 INITIATED transactions for this provider
433
+ * const pending = await runtime.getTransactionsByProvider(
434
+ * providerAddress,
435
+ * 'INITIATED',
436
+ * 100
437
+ * );
438
+ * ```
439
+ */
440
+ async getTransactionsByProvider(provider, state, limit = 100) {
441
+ return this.stateManager.withLock(async (s) => {
442
+ let txs = Object.values(s.transactions).filter((tx) => tx.provider === provider);
443
+ if (state) {
444
+ txs = txs.filter((tx) => tx.state === state);
445
+ }
446
+ if (limit > 0) {
447
+ txs = txs.slice(0, limit);
448
+ }
449
+ return txs;
450
+ });
451
+ }
452
+ /**
453
+ * Transitions a transaction to a new state.
454
+ *
455
+ * Validates the transition against the ACTP 8-state machine:
456
+ * - INITIATED -> QUOTED, COMMITTED, CANCELLED
457
+ * - QUOTED -> COMMITTED, CANCELLED
458
+ * - COMMITTED -> IN_PROGRESS, DELIVERED, CANCELLED
459
+ * - IN_PROGRESS -> DELIVERED, CANCELLED
460
+ * - DELIVERED -> SETTLED, DISPUTED
461
+ * - DISPUTED -> SETTLED
462
+ *
463
+ * @param txId - Transaction ID
464
+ * @param newState - Target state
465
+ *
466
+ * @throws {TransactionNotFoundError} If transaction doesn't exist
467
+ * @throws {InvalidStateTransitionError} If transition is not valid
468
+ * @throws {DeadlinePassedError} If deadline passed (for CANCELLED transition)
469
+ *
470
+ * @example
471
+ * ```typescript
472
+ * // Transition to DELIVERED state
473
+ * await runtime.transitionState(txId, 'DELIVERED');
474
+ *
475
+ * // With delivery proof
476
+ * await runtime.transitionState(txId, 'DELIVERED', deliveryProofBytes);
477
+ * ```
478
+ */
479
+ async transitionState(txId, newState, proof) {
480
+ // SECURITY FIX (PROOF-PARAM): Accept optional proof parameter for interface compliance
481
+ // In MockRuntime, proof is stored but not validated (no on-chain verification)
482
+ // This allows testing delivery proof flows without actual blockchain interaction
483
+ return this.stateManager.withLock(async (state) => {
484
+ const tx = state.transactions[txId];
485
+ if (!tx) {
486
+ throw new TransactionNotFoundError(txId);
487
+ }
488
+ const currentState = tx.state;
489
+ const currentTime = state.blockchain.currentTime;
490
+ const blockNumber = state.blockchain.blockNumber;
491
+ // Validate transition
492
+ const validTargets = VALID_TRANSITIONS[currentState];
493
+ if (!validTargets.includes(newState)) {
494
+ throw new InvalidStateTransitionError(txId, currentState, newState);
495
+ }
496
+ // For cancellation before deadline, check deadline hasn't passed
497
+ if (newState === 'CANCELLED' && CANCELLABLE_STATES.includes(currentState)) {
498
+ // Allow cancellation if deadline passed OR if before deadline
499
+ // (This matches real contract behavior - can cancel anytime before DELIVERED)
500
+ }
501
+ // Update state
502
+ const oldState = tx.state;
503
+ tx.state = newState;
504
+ tx.updatedAt = currentTime;
505
+ // Record completion time for DELIVERED state
506
+ if (newState === 'DELIVERED') {
507
+ tx.completedAt = currentTime;
508
+ // SECURITY FIX (PROOF-PARAM): Store delivery proof if provided
509
+ if (proof) {
510
+ tx.deliveryProof = proof;
511
+ }
512
+ }
513
+ // Handle escrow refund on CANCELLED state (Issue #1 fix)
514
+ if (newState === 'CANCELLED' && tx.escrowId !== null) {
515
+ const escrow = state.escrows[tx.escrowId];
516
+ if (escrow && BigInt(escrow.balance) > 0n) {
517
+ const refundAmount = BigInt(escrow.balance);
518
+ // Create requester account if doesn't exist
519
+ if (!state.accounts[tx.requester]) {
520
+ state.accounts[tx.requester] = {
521
+ address: tx.requester,
522
+ usdcBalance: '0',
523
+ };
524
+ }
525
+ // Return funds to requester
526
+ const requesterBalance = BigInt(state.accounts[tx.requester].usdcBalance);
527
+ state.accounts[tx.requester].usdcBalance = (requesterBalance + refundAmount).toString();
528
+ // Clear escrow balance
529
+ escrow.balance = '0';
530
+ escrow.locked = false;
531
+ // Record EscrowRefunded event
532
+ const refundEvent = {
533
+ type: 'EscrowRefunded',
534
+ timestamp: currentTime,
535
+ blockNumber,
536
+ data: {
537
+ txId,
538
+ escrowId: tx.escrowId,
539
+ requester: tx.requester,
540
+ amount: refundAmount.toString(),
541
+ },
542
+ };
543
+ tx.events.push(refundEvent);
544
+ // SECURITY FIX (L-4): Persist event
545
+ this.persistEvent(refundEvent, state);
546
+ }
547
+ }
548
+ // Record event
549
+ const event = {
550
+ type: 'StateTransitioned',
551
+ timestamp: currentTime,
552
+ blockNumber,
553
+ data: {
554
+ txId,
555
+ oldState,
556
+ newState,
557
+ },
558
+ };
559
+ tx.events.push(event);
560
+ // SECURITY FIX (L-4): Persist event
561
+ this.persistEvent(event, state);
562
+ });
563
+ }
564
+ // ============================================================================
565
+ // Escrow Operations
566
+ // ============================================================================
567
+ /**
568
+ * Links an escrow to a transaction and locks funds.
569
+ *
570
+ * Automatically transitions INITIATED or QUOTED -> COMMITTED (per ACTP spec).
571
+ * Deducts funds from requester and adds to escrow balance.
572
+ *
573
+ * @param txId - Transaction ID
574
+ * @param amount - Amount to lock (must match transaction amount)
575
+ * @returns Promise resolving to the escrow ID
576
+ *
577
+ * @throws {TransactionNotFoundError} If transaction doesn't exist
578
+ * @throws {InvalidStateTransitionError} If not in INITIATED or QUOTED state
579
+ * @throws {InsufficientBalanceError} If requester has insufficient funds
580
+ *
581
+ * @example
582
+ * ```typescript
583
+ * // Ensure requester has funds
584
+ * await runtime.mintTokens(requester, '10000000');
585
+ *
586
+ * // Link escrow
587
+ * const escrowId = await runtime.linkEscrow(txId, '1000000');
588
+ * ```
589
+ */
590
+ async linkEscrow(txId, amount) {
591
+ return this.stateManager.withLock(async (state) => {
592
+ // Validate amount (Issue #2 fix)
593
+ const amountBigInt = BigInt(amount);
594
+ if (amountBigInt <= 0n) {
595
+ throw new InvalidAmountError(amount, 'Amount must be positive');
596
+ }
597
+ const tx = state.transactions[txId];
598
+ if (!tx) {
599
+ throw new TransactionNotFoundError(txId);
600
+ }
601
+ // Validate state - can only link from INITIATED or QUOTED
602
+ if (tx.state !== 'INITIATED' && tx.state !== 'QUOTED') {
603
+ throw new InvalidStateTransitionError(txId, tx.state, 'COMMITTED');
604
+ }
605
+ // Check deadline
606
+ const currentTime = state.blockchain.currentTime;
607
+ if (currentTime > tx.deadline) {
608
+ throw new DeadlinePassedError(txId, tx.deadline, currentTime);
609
+ }
610
+ // Check requester balance
611
+ const requesterAccount = state.accounts[tx.requester];
612
+ const requesterBalance = BigInt(requesterAccount?.usdcBalance ?? '0');
613
+ if (requesterBalance < amountBigInt) {
614
+ throw new InsufficientBalanceError(tx.requester, amount, requesterBalance.toString());
615
+ }
616
+ // Generate escrow ID
617
+ const escrowId = this.generateEscrowId();
618
+ // Create or update requester account
619
+ if (!state.accounts[tx.requester]) {
620
+ state.accounts[tx.requester] = {
621
+ address: tx.requester,
622
+ usdcBalance: '0',
623
+ };
624
+ }
625
+ // Deduct from requester
626
+ state.accounts[tx.requester].usdcBalance = (requesterBalance - amountBigInt).toString();
627
+ // Create escrow
628
+ const escrow = {
629
+ id: escrowId,
630
+ balance: amount,
631
+ locked: true,
632
+ transactions: [txId],
633
+ createdAt: currentTime,
634
+ };
635
+ state.escrows[escrowId] = escrow;
636
+ // Link to transaction and auto-transition to COMMITTED
637
+ const oldState = tx.state;
638
+ tx.escrowId = escrowId;
639
+ tx.state = 'COMMITTED';
640
+ tx.updatedAt = currentTime;
641
+ // Record events
642
+ const blockNumber = state.blockchain.blockNumber;
643
+ const linkEvent = {
644
+ type: 'EscrowLinked',
645
+ timestamp: currentTime,
646
+ blockNumber,
647
+ data: {
648
+ txId,
649
+ escrowId,
650
+ amount,
651
+ },
652
+ };
653
+ const transitionEvent = {
654
+ type: 'StateTransitioned',
655
+ timestamp: currentTime,
656
+ blockNumber,
657
+ data: {
658
+ txId,
659
+ oldState,
660
+ newState: 'COMMITTED',
661
+ },
662
+ };
663
+ tx.events.push(linkEvent, transitionEvent);
664
+ // SECURITY FIX (L-4): Persist events
665
+ this.persistEvent(linkEvent, state);
666
+ this.persistEvent(transitionEvent, state);
667
+ return escrowId;
668
+ });
669
+ }
670
+ /**
671
+ * Releases escrow funds to the provider and settles the transaction.
672
+ *
673
+ * Can only be called when transaction is in DELIVERED state.
674
+ *
675
+ * @param escrowId - Escrow ID
676
+ *
677
+ * @throws {EscrowNotFoundError} If escrow doesn't exist
678
+ * @throws {TransactionNotFoundError} If linked transaction doesn't exist
679
+ * @throws {InvalidStateTransitionError} If transaction not in DELIVERED state
680
+ *
681
+ * @example
682
+ * ```typescript
683
+ * // After delivery is confirmed
684
+ * await runtime.releaseEscrow(escrowId);
685
+ *
686
+ * // Provider now has funds
687
+ * const balance = await runtime.getBalance(provider);
688
+ * ```
689
+ */
690
+ async releaseEscrow(escrowId, _attestationUID) {
691
+ return this.stateManager.withLock(async (state) => {
692
+ const escrow = state.escrows[escrowId];
693
+ if (!escrow) {
694
+ throw new EscrowNotFoundError(escrowId);
695
+ }
696
+ // Get linked transaction (assume single transaction per escrow for now)
697
+ const txId = escrow.transactions[0];
698
+ const tx = state.transactions[txId];
699
+ if (!tx) {
700
+ throw new TransactionNotFoundError(txId);
701
+ }
702
+ // Validate state
703
+ if (tx.state !== 'DELIVERED') {
704
+ throw new InvalidStateTransitionError(txId, tx.state, 'SETTLED');
705
+ }
706
+ const currentTime = state.blockchain.currentTime;
707
+ const blockNumber = state.blockchain.blockNumber;
708
+ // Enforce dispute window (Issue #3 fix)
709
+ if (tx.completedAt !== null) {
710
+ const disputeWindowEnd = tx.completedAt + tx.disputeWindow;
711
+ if (currentTime < disputeWindowEnd) {
712
+ throw new DisputeWindowActiveError(txId, disputeWindowEnd, currentTime);
713
+ }
714
+ }
715
+ const amount = BigInt(escrow.balance);
716
+ // Create or update provider account
717
+ if (!state.accounts[tx.provider]) {
718
+ state.accounts[tx.provider] = {
719
+ address: tx.provider,
720
+ usdcBalance: '0',
721
+ };
722
+ }
723
+ // Transfer to provider
724
+ const providerBalance = BigInt(state.accounts[tx.provider].usdcBalance);
725
+ state.accounts[tx.provider].usdcBalance = (providerBalance + amount).toString();
726
+ // Clear escrow balance
727
+ escrow.balance = '0';
728
+ escrow.locked = false;
729
+ // Transition to SETTLED
730
+ const oldState = tx.state;
731
+ tx.state = 'SETTLED';
732
+ tx.updatedAt = currentTime;
733
+ // Record events
734
+ const releaseEvent = {
735
+ type: 'EscrowReleased',
736
+ timestamp: currentTime,
737
+ blockNumber,
738
+ data: {
739
+ txId,
740
+ escrowId,
741
+ provider: tx.provider,
742
+ amount: amount.toString(),
743
+ },
744
+ };
745
+ const transitionEvent = {
746
+ type: 'StateTransitioned',
747
+ timestamp: currentTime,
748
+ blockNumber,
749
+ data: {
750
+ txId,
751
+ oldState,
752
+ newState: 'SETTLED',
753
+ },
754
+ };
755
+ tx.events.push(releaseEvent, transitionEvent);
756
+ // SECURITY FIX (L-4): Persist events
757
+ this.persistEvent(releaseEvent, state);
758
+ this.persistEvent(transitionEvent, state);
759
+ });
760
+ }
761
+ /**
762
+ * Gets the balance of an escrow.
763
+ *
764
+ * @param escrowId - Escrow ID
765
+ * @returns Promise resolving to the balance as string
766
+ *
767
+ * @throws {EscrowNotFoundError} If escrow doesn't exist
768
+ */
769
+ async getEscrowBalance(escrowId) {
770
+ const state = this.stateManager.loadState();
771
+ const escrow = state.escrows[escrowId];
772
+ if (!escrow) {
773
+ throw new EscrowNotFoundError(escrowId);
774
+ }
775
+ return escrow.balance;
776
+ }
777
+ // ============================================================================
778
+ // Account Operations
779
+ // ============================================================================
780
+ /**
781
+ * Gets the USDC balance of an address.
782
+ *
783
+ * @param address - Ethereum address
784
+ * @returns Promise resolving to the balance as string (0 if account doesn't exist)
785
+ */
786
+ async getBalance(address) {
787
+ const state = this.stateManager.loadState();
788
+ return state.accounts[address]?.usdcBalance ?? '0';
789
+ }
790
+ /**
791
+ * Mints USDC tokens to an address (testing only).
792
+ *
793
+ * @param address - Ethereum address to receive tokens
794
+ * @param amount - Amount to mint in USDC wei
795
+ *
796
+ * @example
797
+ * ```typescript
798
+ * // Mint 10,000 USDC (6 decimals)
799
+ * await runtime.mintTokens('0xRequester', '10000000000');
800
+ * ```
801
+ */
802
+ async mintTokens(address, amount) {
803
+ return this.stateManager.withLock(async (state) => {
804
+ // Create account if doesn't exist
805
+ if (!state.accounts[address]) {
806
+ state.accounts[address] = {
807
+ address,
808
+ usdcBalance: '0',
809
+ };
810
+ }
811
+ const currentBalance = BigInt(state.accounts[address].usdcBalance);
812
+ const mintAmount = BigInt(amount);
813
+ state.accounts[address].usdcBalance = (currentBalance + mintAmount).toString();
814
+ // Record event
815
+ const event = {
816
+ type: 'TokensMinted',
817
+ timestamp: state.blockchain.currentTime,
818
+ blockNumber: state.blockchain.blockNumber,
819
+ data: {
820
+ address,
821
+ amount,
822
+ newBalance: state.accounts[address].usdcBalance,
823
+ },
824
+ };
825
+ // SECURITY FIX (L-4): Persist event
826
+ this.persistEvent(event, state);
827
+ });
828
+ }
829
+ /**
830
+ * Transfers USDC tokens between addresses.
831
+ *
832
+ * @param from - Sender address
833
+ * @param to - Recipient address
834
+ * @param amount - Amount to transfer in USDC wei
835
+ *
836
+ * @throws {InsufficientBalanceError} If sender has insufficient funds
837
+ *
838
+ * @example
839
+ * ```typescript
840
+ * await runtime.transfer('0xFrom', '0xTo', '1000000');
841
+ * ```
842
+ */
843
+ async transfer(from, to, amount) {
844
+ return this.stateManager.withLock(async (state) => {
845
+ // Check sender balance
846
+ const fromAccount = state.accounts[from];
847
+ const fromBalance = BigInt(fromAccount?.usdcBalance ?? '0');
848
+ const transferAmount = BigInt(amount);
849
+ if (fromBalance < transferAmount) {
850
+ throw new InsufficientBalanceError(from, amount, fromBalance.toString());
851
+ }
852
+ // Create receiver account if doesn't exist
853
+ if (!state.accounts[to]) {
854
+ state.accounts[to] = {
855
+ address: to,
856
+ usdcBalance: '0',
857
+ };
858
+ }
859
+ // Create sender account if doesn't exist (shouldn't happen but be safe)
860
+ if (!state.accounts[from]) {
861
+ state.accounts[from] = {
862
+ address: from,
863
+ usdcBalance: '0',
864
+ };
865
+ }
866
+ // Transfer
867
+ state.accounts[from].usdcBalance = (fromBalance - transferAmount).toString();
868
+ const toBalance = BigInt(state.accounts[to].usdcBalance);
869
+ state.accounts[to].usdcBalance = (toBalance + transferAmount).toString();
870
+ // Record event
871
+ const event = {
872
+ type: 'Transfer',
873
+ timestamp: state.blockchain.currentTime,
874
+ blockNumber: state.blockchain.blockNumber,
875
+ data: {
876
+ from,
877
+ to,
878
+ amount,
879
+ },
880
+ };
881
+ // SECURITY FIX (L-4): Persist event
882
+ this.persistEvent(event, state);
883
+ });
884
+ }
885
+ // ============================================================================
886
+ // State Management
887
+ // ============================================================================
888
+ /**
889
+ * Resets the runtime to initial state.
890
+ *
891
+ * Clears all transactions, escrows, accounts, and events.
892
+ */
893
+ async reset() {
894
+ this.stateManager.reset();
895
+ this.eventLog = [];
896
+ // Note: reset() on stateManager will also clear persisted events via getDefaultState()
897
+ }
898
+ /**
899
+ * Gets the complete mock state.
900
+ *
901
+ * @returns Current mock state snapshot
902
+ */
903
+ getState() {
904
+ return this.stateManager.loadState();
905
+ }
906
+ // ============================================================================
907
+ // Private Methods - Time Management
908
+ // ============================================================================
909
+ /**
910
+ * Gets the current mock timestamp.
911
+ */
912
+ getCurrentTime() {
913
+ const state = this.stateManager.loadState();
914
+ return state.blockchain.currentTime;
915
+ }
916
+ /**
917
+ * Advances time by specified seconds (with file locking).
918
+ *
919
+ * SECURITY FIX: Uses withLock to prevent race conditions when
920
+ * multiple processes access the state file concurrently.
921
+ */
922
+ async advanceTimeWithLock(seconds) {
923
+ if (seconds < 0) {
924
+ throw new Error('Cannot advance time by negative amount');
925
+ }
926
+ return this.stateManager.withLock(async (state) => {
927
+ const blockTimeSeconds = state.blockchain.blockTime;
928
+ state.blockchain.currentTime += seconds;
929
+ state.blockchain.blockNumber += Math.floor(seconds / blockTimeSeconds);
930
+ // Record event
931
+ const event = {
932
+ type: 'TimeAdvanced',
933
+ timestamp: state.blockchain.currentTime,
934
+ blockNumber: state.blockchain.blockNumber,
935
+ data: {
936
+ seconds,
937
+ newTime: state.blockchain.currentTime,
938
+ newBlock: state.blockchain.blockNumber,
939
+ },
940
+ };
941
+ // SECURITY FIX (L-4): Persist event
942
+ this.persistEvent(event, state);
943
+ });
944
+ }
945
+ /**
946
+ * Advances time by specified blocks (with file locking).
947
+ *
948
+ * SECURITY FIX: Uses withLock to prevent race conditions.
949
+ */
950
+ async advanceBlocksWithLock(blocks) {
951
+ if (blocks < 0) {
952
+ throw new Error('Cannot advance blocks by negative amount');
953
+ }
954
+ return this.stateManager.withLock(async (state) => {
955
+ const blockTimeSeconds = state.blockchain.blockTime;
956
+ const secondsToAdvance = blocks * blockTimeSeconds;
957
+ state.blockchain.blockNumber += blocks;
958
+ state.blockchain.currentTime += secondsToAdvance;
959
+ // Record event
960
+ const event = {
961
+ type: 'BlocksAdvanced',
962
+ timestamp: state.blockchain.currentTime,
963
+ blockNumber: state.blockchain.blockNumber,
964
+ data: {
965
+ blocks,
966
+ newTime: state.blockchain.currentTime,
967
+ newBlock: state.blockchain.blockNumber,
968
+ },
969
+ };
970
+ // SECURITY FIX (L-4): Persist event
971
+ this.persistEvent(event, state);
972
+ });
973
+ }
974
+ /**
975
+ * Sets exact timestamp (must be >= current time) (with file locking).
976
+ *
977
+ * SECURITY FIX: Uses withLock to prevent race conditions.
978
+ */
979
+ async setTimeWithLock(timestamp) {
980
+ return this.stateManager.withLock(async (state) => {
981
+ if (timestamp < state.blockchain.currentTime) {
982
+ throw new Error(`Cannot move time backwards: ${timestamp} < ${state.blockchain.currentTime}`);
983
+ }
984
+ const timeDiff = timestamp - state.blockchain.currentTime;
985
+ const blockTimeSeconds = state.blockchain.blockTime;
986
+ state.blockchain.currentTime = timestamp;
987
+ state.blockchain.blockNumber += Math.floor(timeDiff / blockTimeSeconds);
988
+ // Record event
989
+ const event = {
990
+ type: 'TimeSet',
991
+ timestamp: state.blockchain.currentTime,
992
+ blockNumber: state.blockchain.blockNumber,
993
+ data: {
994
+ newTime: timestamp,
995
+ newBlock: state.blockchain.blockNumber,
996
+ },
997
+ };
998
+ // SECURITY FIX (L-4): Persist event
999
+ this.persistEvent(event, state);
1000
+ });
1001
+ }
1002
+ // ============================================================================
1003
+ // Private Methods - Event Management
1004
+ // ============================================================================
1005
+ /**
1006
+ * Gets events for a specific transaction from both global log and transaction events.
1007
+ */
1008
+ getEventsByTransaction(txId) {
1009
+ const state = this.stateManager.loadState();
1010
+ const tx = state.transactions[txId];
1011
+ if (!tx) {
1012
+ return [];
1013
+ }
1014
+ // Return transaction-specific events
1015
+ return [...tx.events];
1016
+ }
1017
+ // ============================================================================
1018
+ // Private Methods - ID Generation
1019
+ // ============================================================================
1020
+ /**
1021
+ * Generates a unique transaction ID (bytes32 hex string).
1022
+ *
1023
+ * SECURITY FIX (M-4): Now checks for collisions against existing transactions.
1024
+ * Uses cryptographically secure random bytes (32 bytes = 256 bits of entropy).
1025
+ *
1026
+ * @param state - Current mock state to check for collisions
1027
+ * @returns Unique transaction ID
1028
+ */
1029
+ generateTransactionIdWithCollisionCheck(state) {
1030
+ const maxAttempts = 10;
1031
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
1032
+ const txId = `0x${crypto.randomBytes(32).toString('hex')}`;
1033
+ // Check for collision (extremely unlikely with 256 bits of randomness)
1034
+ if (!state.transactions[txId]) {
1035
+ return txId;
1036
+ }
1037
+ }
1038
+ // This should never happen with 256-bit IDs, but fail safely
1039
+ throw new Error('Failed to generate unique transaction ID after multiple attempts. ' +
1040
+ 'This indicates a critical system issue.');
1041
+ }
1042
+ /**
1043
+ * Generates a unique transaction ID (bytes32 hex string).
1044
+ *
1045
+ * Note: This version is used when state is not available.
1046
+ * Prefer generateTransactionIdWithCollisionCheck when possible.
1047
+ */
1048
+ generateTransactionId() {
1049
+ return `0x${crypto.randomBytes(32).toString('hex')}`;
1050
+ }
1051
+ /**
1052
+ * Generates a unique escrow ID with improved randomness.
1053
+ *
1054
+ * SECURITY FIX (L-5): Uses 16 bytes (128 bits) of cryptographic randomness
1055
+ * instead of just 4 bytes. Removes timestamp to prevent predictability.
1056
+ *
1057
+ * @returns Unique escrow ID
1058
+ */
1059
+ generateEscrowId() {
1060
+ // Use 16 bytes of cryptographic randomness (128 bits of entropy)
1061
+ return `escrow-${crypto.randomBytes(16).toString('hex')}`;
1062
+ }
1063
+ }
1064
+ exports.MockRuntime = MockRuntime;
1065
+ //# sourceMappingURL=MockRuntime.js.map