@agirails/sdk 2.0.0 → 2.0.1-beta

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/README.md +108 -116
  2. package/dist/ACTPClient.d.ts +33 -456
  3. package/dist/ACTPClient.d.ts.map +1 -1
  4. package/dist/ACTPClient.js +93 -477
  5. package/dist/ACTPClient.js.map +1 -1
  6. package/dist/abi/EscrowVault.json +38 -106
  7. package/dist/builders/DeliveryProofBuilder.d.ts +1 -60
  8. package/dist/builders/DeliveryProofBuilder.d.ts.map +1 -1
  9. package/dist/builders/DeliveryProofBuilder.js +5 -81
  10. package/dist/builders/DeliveryProofBuilder.js.map +1 -1
  11. package/dist/builders/QuoteBuilder.d.ts +0 -101
  12. package/dist/builders/QuoteBuilder.d.ts.map +1 -1
  13. package/dist/builders/QuoteBuilder.js +3 -120
  14. package/dist/builders/QuoteBuilder.js.map +1 -1
  15. package/dist/builders/index.d.ts +0 -4
  16. package/dist/builders/index.d.ts.map +1 -1
  17. package/dist/builders/index.js +0 -4
  18. package/dist/builders/index.js.map +1 -1
  19. package/dist/config/networks.d.ts +0 -28
  20. package/dist/config/networks.d.ts.map +1 -1
  21. package/dist/config/networks.js +12 -60
  22. package/dist/config/networks.js.map +1 -1
  23. package/dist/errors/index.d.ts +2 -165
  24. package/dist/errors/index.d.ts.map +1 -1
  25. package/dist/errors/index.js +2 -260
  26. package/dist/errors/index.js.map +1 -1
  27. package/dist/index.d.ts +13 -61
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +36 -141
  30. package/dist/index.js.map +1 -1
  31. package/dist/protocol/ACTPKernel.d.ts +2 -229
  32. package/dist/protocol/ACTPKernel.d.ts.map +1 -1
  33. package/dist/protocol/ACTPKernel.js +33 -367
  34. package/dist/protocol/ACTPKernel.js.map +1 -1
  35. package/dist/protocol/EASHelper.d.ts +2 -57
  36. package/dist/protocol/EASHelper.d.ts.map +1 -1
  37. package/dist/protocol/EASHelper.js +37 -230
  38. package/dist/protocol/EASHelper.js.map +1 -1
  39. package/dist/protocol/EscrowVault.d.ts +2 -93
  40. package/dist/protocol/EscrowVault.d.ts.map +1 -1
  41. package/dist/protocol/EscrowVault.js +33 -122
  42. package/dist/protocol/EscrowVault.js.map +1 -1
  43. package/dist/protocol/EventMonitor.d.ts +1 -45
  44. package/dist/protocol/EventMonitor.d.ts.map +1 -1
  45. package/dist/protocol/EventMonitor.js +8 -64
  46. package/dist/protocol/EventMonitor.js.map +1 -1
  47. package/dist/protocol/MessageSigner.d.ts +2 -116
  48. package/dist/protocol/MessageSigner.d.ts.map +1 -1
  49. package/dist/protocol/MessageSigner.js +9 -215
  50. package/dist/protocol/MessageSigner.js.map +1 -1
  51. package/dist/protocol/ProofGenerator.d.ts +0 -93
  52. package/dist/protocol/ProofGenerator.d.ts.map +1 -1
  53. package/dist/protocol/ProofGenerator.js +9 -194
  54. package/dist/protocol/ProofGenerator.js.map +1 -1
  55. package/dist/protocol/QuoteBuilder.d.ts +0 -8
  56. package/dist/protocol/QuoteBuilder.d.ts.map +1 -1
  57. package/dist/protocol/QuoteBuilder.js +0 -8
  58. package/dist/protocol/QuoteBuilder.js.map +1 -1
  59. package/dist/types/eip712.d.ts +0 -34
  60. package/dist/types/eip712.d.ts.map +1 -1
  61. package/dist/types/eip712.js +5 -31
  62. package/dist/types/eip712.js.map +1 -1
  63. package/dist/types/escrow.d.ts +10 -17
  64. package/dist/types/escrow.d.ts.map +1 -1
  65. package/dist/types/index.d.ts +0 -5
  66. package/dist/types/index.d.ts.map +1 -1
  67. package/dist/types/index.js +0 -8
  68. package/dist/types/index.js.map +1 -1
  69. package/dist/types/message.d.ts +0 -32
  70. package/dist/types/message.d.ts.map +1 -1
  71. package/dist/types/message.js +0 -4
  72. package/dist/types/message.js.map +1 -1
  73. package/dist/types/state.d.ts +0 -28
  74. package/dist/types/state.d.ts.map +1 -1
  75. package/dist/types/state.js +6 -37
  76. package/dist/types/state.js.map +1 -1
  77. package/dist/types/transaction.d.ts +0 -17
  78. package/dist/types/transaction.d.ts.map +1 -1
  79. package/dist/utils/IPFSClient.d.ts +0 -113
  80. package/dist/utils/IPFSClient.d.ts.map +1 -1
  81. package/dist/utils/IPFSClient.js +7 -128
  82. package/dist/utils/IPFSClient.js.map +1 -1
  83. package/dist/utils/NonceManager.d.ts +1 -234
  84. package/dist/utils/NonceManager.d.ts.map +1 -1
  85. package/dist/utils/NonceManager.js +7 -372
  86. package/dist/utils/NonceManager.js.map +1 -1
  87. package/dist/utils/ReceivedNonceTracker.d.ts +0 -175
  88. package/dist/utils/ReceivedNonceTracker.d.ts.map +1 -1
  89. package/dist/utils/ReceivedNonceTracker.js +5 -261
  90. package/dist/utils/ReceivedNonceTracker.js.map +1 -1
  91. package/dist/utils/canonicalJson.d.ts +0 -22
  92. package/dist/utils/canonicalJson.d.ts.map +1 -1
  93. package/dist/utils/canonicalJson.js +3 -26
  94. package/dist/utils/canonicalJson.js.map +1 -1
  95. package/dist/utils/computeTypeHash.d.ts +0 -14
  96. package/dist/utils/computeTypeHash.d.ts.map +1 -1
  97. package/dist/utils/computeTypeHash.js +2 -19
  98. package/dist/utils/computeTypeHash.js.map +1 -1
  99. package/dist/utils/validation.d.ts +0 -40
  100. package/dist/utils/validation.d.ts.map +1 -1
  101. package/dist/utils/validation.js +7 -184
  102. package/dist/utils/validation.js.map +1 -1
  103. package/package.json +37 -54
  104. package/src/ACTPClient.ts +178 -692
  105. package/src/__tests__/ProofGenerator.test.ts +124 -0
  106. package/src/__tests__/QuoteBuilder.test.ts +516 -0
  107. package/src/__tests__/StateMachine.test.ts +82 -0
  108. package/src/__tests__/builders/DeliveryProofBuilder.test.ts +581 -0
  109. package/src/__tests__/integration/ACTPClient.test.ts +263 -0
  110. package/src/__tests__/integration.test.ts +289 -0
  111. package/src/__tests__/protocol/EASHelper.test.ts +472 -0
  112. package/src/__tests__/protocol/EventMonitor.test.ts +382 -0
  113. package/src/__tests__/security/ACTPKernel.security.test.ts +1167 -0
  114. package/src/__tests__/security/EscrowVault.security.test.ts +570 -0
  115. package/src/__tests__/security/MessageSigner.security.test.ts +286 -0
  116. package/src/__tests__/security/NonceReplay.security.test.ts +501 -0
  117. package/src/__tests__/security/validation.security.test.ts +376 -0
  118. package/src/__tests__/utils/IPFSClient.test.ts +262 -0
  119. package/src/__tests__/utils/NonceManager.test.ts +205 -0
  120. package/src/__tests__/utils/canonicalJson.test.ts +153 -0
  121. package/src/abi/EscrowVault.json +38 -106
  122. package/src/builders/DeliveryProofBuilder.ts +2 -3
  123. package/src/config/networks.ts +9 -32
  124. package/src/errors/index.ts +1 -298
  125. package/src/index.ts +71 -207
  126. package/src/protocol/ACTPKernel.ts +23 -175
  127. package/src/protocol/EASHelper.ts +46 -230
  128. package/src/protocol/EscrowVault.ts +50 -68
  129. package/src/protocol/EventMonitor.ts +15 -44
  130. package/src/protocol/MessageSigner.ts +13 -193
  131. package/src/protocol/ProofGenerator.ts +4 -223
  132. package/src/types/escrow.ts +11 -12
  133. package/src/types/index.ts +1 -5
  134. package/src/types/state.ts +3 -12
  135. package/src/types/transaction.ts +1 -4
  136. package/src/utils/IPFSClient.ts +5 -122
  137. package/src/utils/NonceManager.ts +8 -305
  138. package/src/utils/ReceivedNonceTracker.ts +0 -170
  139. package/src/utils/validation.ts +0 -164
  140. package/LICENSE +0 -190
  141. package/bin/actp +0 -10
  142. package/dist/abi/AgentRegistry.json +0 -782
  143. package/dist/abi/IdentityRegistry.json +0 -316
  144. package/dist/adapters/BaseAdapter.d.ts +0 -231
  145. package/dist/adapters/BaseAdapter.d.ts.map +0 -1
  146. package/dist/adapters/BaseAdapter.js +0 -393
  147. package/dist/adapters/BaseAdapter.js.map +0 -1
  148. package/dist/adapters/BeginnerAdapter.d.ts +0 -152
  149. package/dist/adapters/BeginnerAdapter.d.ts.map +0 -1
  150. package/dist/adapters/BeginnerAdapter.js +0 -168
  151. package/dist/adapters/BeginnerAdapter.js.map +0 -1
  152. package/dist/adapters/IntermediateAdapter.d.ts +0 -211
  153. package/dist/adapters/IntermediateAdapter.d.ts.map +0 -1
  154. package/dist/adapters/IntermediateAdapter.js +0 -260
  155. package/dist/adapters/IntermediateAdapter.js.map +0 -1
  156. package/dist/adapters/index.d.ts +0 -15
  157. package/dist/adapters/index.d.ts.map +0 -1
  158. package/dist/adapters/index.js +0 -26
  159. package/dist/adapters/index.js.map +0 -1
  160. package/dist/cli/commands/balance.d.ts +0 -13
  161. package/dist/cli/commands/balance.d.ts.map +0 -1
  162. package/dist/cli/commands/balance.js +0 -89
  163. package/dist/cli/commands/balance.js.map +0 -1
  164. package/dist/cli/commands/batch.d.ts +0 -24
  165. package/dist/cli/commands/batch.d.ts.map +0 -1
  166. package/dist/cli/commands/batch.js +0 -424
  167. package/dist/cli/commands/batch.js.map +0 -1
  168. package/dist/cli/commands/config.d.ts +0 -13
  169. package/dist/cli/commands/config.d.ts.map +0 -1
  170. package/dist/cli/commands/config.js +0 -192
  171. package/dist/cli/commands/config.js.map +0 -1
  172. package/dist/cli/commands/init.d.ts +0 -19
  173. package/dist/cli/commands/init.d.ts.map +0 -1
  174. package/dist/cli/commands/init.js +0 -143
  175. package/dist/cli/commands/init.js.map +0 -1
  176. package/dist/cli/commands/mint.d.ts +0 -13
  177. package/dist/cli/commands/mint.d.ts.map +0 -1
  178. package/dist/cli/commands/mint.js +0 -91
  179. package/dist/cli/commands/mint.js.map +0 -1
  180. package/dist/cli/commands/pay.d.ts +0 -18
  181. package/dist/cli/commands/pay.d.ts.map +0 -1
  182. package/dist/cli/commands/pay.js +0 -87
  183. package/dist/cli/commands/pay.js.map +0 -1
  184. package/dist/cli/commands/simulate.d.ts +0 -32
  185. package/dist/cli/commands/simulate.d.ts.map +0 -1
  186. package/dist/cli/commands/simulate.js +0 -290
  187. package/dist/cli/commands/simulate.js.map +0 -1
  188. package/dist/cli/commands/time.d.ts +0 -29
  189. package/dist/cli/commands/time.d.ts.map +0 -1
  190. package/dist/cli/commands/time.js +0 -252
  191. package/dist/cli/commands/time.js.map +0 -1
  192. package/dist/cli/commands/tx.d.ts +0 -16
  193. package/dist/cli/commands/tx.d.ts.map +0 -1
  194. package/dist/cli/commands/tx.js +0 -379
  195. package/dist/cli/commands/tx.js.map +0 -1
  196. package/dist/cli/commands/watch.d.ts +0 -20
  197. package/dist/cli/commands/watch.d.ts.map +0 -1
  198. package/dist/cli/commands/watch.js +0 -160
  199. package/dist/cli/commands/watch.js.map +0 -1
  200. package/dist/cli/index.d.ts +0 -17
  201. package/dist/cli/index.d.ts.map +0 -1
  202. package/dist/cli/index.js +0 -104
  203. package/dist/cli/index.js.map +0 -1
  204. package/dist/cli/utils/client.d.ts +0 -70
  205. package/dist/cli/utils/client.d.ts.map +0 -1
  206. package/dist/cli/utils/client.js +0 -240
  207. package/dist/cli/utils/client.js.map +0 -1
  208. package/dist/cli/utils/config.d.ts +0 -91
  209. package/dist/cli/utils/config.d.ts.map +0 -1
  210. package/dist/cli/utils/config.js +0 -240
  211. package/dist/cli/utils/config.js.map +0 -1
  212. package/dist/cli/utils/output.d.ts +0 -174
  213. package/dist/cli/utils/output.d.ts.map +0 -1
  214. package/dist/cli/utils/output.js +0 -380
  215. package/dist/cli/utils/output.js.map +0 -1
  216. package/dist/level0/Provider.d.ts +0 -106
  217. package/dist/level0/Provider.d.ts.map +0 -1
  218. package/dist/level0/Provider.js +0 -10
  219. package/dist/level0/Provider.js.map +0 -1
  220. package/dist/level0/ServiceDirectory.d.ts +0 -74
  221. package/dist/level0/ServiceDirectory.d.ts.map +0 -1
  222. package/dist/level0/ServiceDirectory.js +0 -122
  223. package/dist/level0/ServiceDirectory.js.map +0 -1
  224. package/dist/level0/index.d.ts +0 -10
  225. package/dist/level0/index.d.ts.map +0 -1
  226. package/dist/level0/index.js +0 -15
  227. package/dist/level0/index.js.map +0 -1
  228. package/dist/level0/provide.d.ts +0 -51
  229. package/dist/level0/provide.d.ts.map +0 -1
  230. package/dist/level0/provide.js +0 -113
  231. package/dist/level0/provide.js.map +0 -1
  232. package/dist/level0/request.d.ts +0 -53
  233. package/dist/level0/request.d.ts.map +0 -1
  234. package/dist/level0/request.js +0 -462
  235. package/dist/level0/request.js.map +0 -1
  236. package/dist/level1/Agent.d.ts +0 -472
  237. package/dist/level1/Agent.d.ts.map +0 -1
  238. package/dist/level1/Agent.js +0 -1091
  239. package/dist/level1/Agent.js.map +0 -1
  240. package/dist/level1/index.d.ts +0 -10
  241. package/dist/level1/index.d.ts.map +0 -1
  242. package/dist/level1/index.js +0 -30
  243. package/dist/level1/index.js.map +0 -1
  244. package/dist/level1/pricing/PriceCalculator.d.ts +0 -62
  245. package/dist/level1/pricing/PriceCalculator.d.ts.map +0 -1
  246. package/dist/level1/pricing/PriceCalculator.js +0 -237
  247. package/dist/level1/pricing/PriceCalculator.js.map +0 -1
  248. package/dist/level1/pricing/PricingStrategy.d.ts +0 -179
  249. package/dist/level1/pricing/PricingStrategy.d.ts.map +0 -1
  250. package/dist/level1/pricing/PricingStrategy.js +0 -11
  251. package/dist/level1/pricing/PricingStrategy.js.map +0 -1
  252. package/dist/level1/types/Job.d.ts +0 -166
  253. package/dist/level1/types/Job.d.ts.map +0 -1
  254. package/dist/level1/types/Job.js +0 -11
  255. package/dist/level1/types/Job.js.map +0 -1
  256. package/dist/level1/types/Options.d.ts +0 -258
  257. package/dist/level1/types/Options.d.ts.map +0 -1
  258. package/dist/level1/types/Options.js +0 -8
  259. package/dist/level1/types/Options.js.map +0 -1
  260. package/dist/level1/types/index.d.ts +0 -8
  261. package/dist/level1/types/index.d.ts.map +0 -1
  262. package/dist/level1/types/index.js +0 -8
  263. package/dist/level1/types/index.js.map +0 -1
  264. package/dist/protocol/AgentRegistry.d.ts +0 -177
  265. package/dist/protocol/AgentRegistry.d.ts.map +0 -1
  266. package/dist/protocol/AgentRegistry.js +0 -449
  267. package/dist/protocol/AgentRegistry.js.map +0 -1
  268. package/dist/protocol/DIDManager.d.ts +0 -289
  269. package/dist/protocol/DIDManager.d.ts.map +0 -1
  270. package/dist/protocol/DIDManager.js +0 -481
  271. package/dist/protocol/DIDManager.js.map +0 -1
  272. package/dist/protocol/DIDResolver.d.ts +0 -236
  273. package/dist/protocol/DIDResolver.d.ts.map +0 -1
  274. package/dist/protocol/DIDResolver.js +0 -495
  275. package/dist/protocol/DIDResolver.js.map +0 -1
  276. package/dist/runtime/BlockchainRuntime.d.ts +0 -360
  277. package/dist/runtime/BlockchainRuntime.d.ts.map +0 -1
  278. package/dist/runtime/BlockchainRuntime.js +0 -767
  279. package/dist/runtime/BlockchainRuntime.js.map +0 -1
  280. package/dist/runtime/IACTPRuntime.d.ts +0 -271
  281. package/dist/runtime/IACTPRuntime.d.ts.map +0 -1
  282. package/dist/runtime/IACTPRuntime.js +0 -15
  283. package/dist/runtime/IACTPRuntime.js.map +0 -1
  284. package/dist/runtime/MockRuntime.d.ts +0 -445
  285. package/dist/runtime/MockRuntime.d.ts.map +0 -1
  286. package/dist/runtime/MockRuntime.js +0 -1065
  287. package/dist/runtime/MockRuntime.js.map +0 -1
  288. package/dist/runtime/MockStateManager.d.ts +0 -233
  289. package/dist/runtime/MockStateManager.d.ts.map +0 -1
  290. package/dist/runtime/MockStateManager.js +0 -533
  291. package/dist/runtime/MockStateManager.js.map +0 -1
  292. package/dist/runtime/index.d.ts +0 -14
  293. package/dist/runtime/index.d.ts.map +0 -1
  294. package/dist/runtime/index.js +0 -42
  295. package/dist/runtime/index.js.map +0 -1
  296. package/dist/runtime/types/MockState.d.ts +0 -167
  297. package/dist/runtime/types/MockState.d.ts.map +0 -1
  298. package/dist/runtime/types/MockState.js +0 -43
  299. package/dist/runtime/types/MockState.js.map +0 -1
  300. package/dist/types/agent.d.ts +0 -76
  301. package/dist/types/agent.d.ts.map +0 -1
  302. package/dist/types/agent.js +0 -8
  303. package/dist/types/agent.js.map +0 -1
  304. package/dist/types/did.d.ts +0 -192
  305. package/dist/types/did.d.ts.map +0 -1
  306. package/dist/types/did.js +0 -38
  307. package/dist/types/did.js.map +0 -1
  308. package/dist/utils/ErrorRecoveryGuide.d.ts +0 -125
  309. package/dist/utils/ErrorRecoveryGuide.d.ts.map +0 -1
  310. package/dist/utils/ErrorRecoveryGuide.js +0 -579
  311. package/dist/utils/ErrorRecoveryGuide.js.map +0 -1
  312. package/dist/utils/Helpers.d.ts +0 -453
  313. package/dist/utils/Helpers.d.ts.map +0 -1
  314. package/dist/utils/Helpers.js +0 -623
  315. package/dist/utils/Helpers.js.map +0 -1
  316. package/dist/utils/Logger.d.ts +0 -195
  317. package/dist/utils/Logger.d.ts.map +0 -1
  318. package/dist/utils/Logger.js +0 -382
  319. package/dist/utils/Logger.js.map +0 -1
  320. package/dist/utils/RateLimiter.d.ts +0 -253
  321. package/dist/utils/RateLimiter.d.ts.map +0 -1
  322. package/dist/utils/RateLimiter.js +0 -424
  323. package/dist/utils/RateLimiter.js.map +0 -1
  324. package/dist/utils/SDKLifecycle.d.ts +0 -156
  325. package/dist/utils/SDKLifecycle.d.ts.map +0 -1
  326. package/dist/utils/SDKLifecycle.js +0 -347
  327. package/dist/utils/SDKLifecycle.js.map +0 -1
  328. package/dist/utils/SecureNonce.d.ts +0 -57
  329. package/dist/utils/SecureNonce.d.ts.map +0 -1
  330. package/dist/utils/SecureNonce.js +0 -80
  331. package/dist/utils/SecureNonce.js.map +0 -1
  332. package/dist/utils/Semaphore.d.ts +0 -123
  333. package/dist/utils/Semaphore.d.ts.map +0 -1
  334. package/dist/utils/Semaphore.js +0 -247
  335. package/dist/utils/Semaphore.js.map +0 -1
  336. package/dist/utils/UsedAttestationTracker.d.ts +0 -167
  337. package/dist/utils/UsedAttestationTracker.d.ts.map +0 -1
  338. package/dist/utils/UsedAttestationTracker.js +0 -309
  339. package/dist/utils/UsedAttestationTracker.js.map +0 -1
  340. package/dist/utils/fsSafe.d.ts +0 -14
  341. package/dist/utils/fsSafe.d.ts.map +0 -1
  342. package/dist/utils/fsSafe.js +0 -89
  343. package/dist/utils/fsSafe.js.map +0 -1
  344. package/dist/utils/index.d.ts +0 -15
  345. package/dist/utils/index.d.ts.map +0 -1
  346. package/dist/utils/index.js +0 -51
  347. package/dist/utils/index.js.map +0 -1
  348. package/dist/utils/security.d.ts +0 -147
  349. package/dist/utils/security.d.ts.map +0 -1
  350. package/dist/utils/security.js +0 -391
  351. package/dist/utils/security.js.map +0 -1
  352. package/src/abi/AgentRegistry.json +0 -782
  353. package/src/abi/IdentityRegistry.json +0 -316
  354. package/src/adapters/BaseAdapter.ts +0 -473
  355. package/src/adapters/BeginnerAdapter.ts +0 -232
  356. package/src/adapters/IntermediateAdapter.ts +0 -316
  357. package/src/adapters/index.ts +0 -25
  358. package/src/cli/commands/balance.ts +0 -110
  359. package/src/cli/commands/batch.ts +0 -487
  360. package/src/cli/commands/config.ts +0 -231
  361. package/src/cli/commands/init.ts +0 -161
  362. package/src/cli/commands/mint.ts +0 -116
  363. package/src/cli/commands/pay.ts +0 -113
  364. package/src/cli/commands/simulate.ts +0 -345
  365. package/src/cli/commands/time.ts +0 -303
  366. package/src/cli/commands/tx.ts +0 -448
  367. package/src/cli/commands/watch.ts +0 -211
  368. package/src/cli/index.ts +0 -116
  369. package/src/cli/utils/client.ts +0 -249
  370. package/src/cli/utils/config.ts +0 -282
  371. package/src/cli/utils/output.ts +0 -465
  372. package/src/level0/Provider.ts +0 -117
  373. package/src/level0/ServiceDirectory.ts +0 -131
  374. package/src/level0/index.ts +0 -10
  375. package/src/level0/provide.ts +0 -131
  376. package/src/level0/request.ts +0 -494
  377. package/src/level1/Agent.ts +0 -1432
  378. package/src/level1/index.ts +0 -10
  379. package/src/level1/pricing/PriceCalculator.ts +0 -255
  380. package/src/level1/pricing/PricingStrategy.ts +0 -198
  381. package/src/level1/types/Job.ts +0 -179
  382. package/src/level1/types/Options.ts +0 -291
  383. package/src/level1/types/index.ts +0 -8
  384. package/src/protocol/AgentRegistry.ts +0 -559
  385. package/src/protocol/DIDManager.ts +0 -629
  386. package/src/protocol/DIDResolver.ts +0 -554
  387. package/src/runtime/BlockchainRuntime.ts +0 -993
  388. package/src/runtime/IACTPRuntime.ts +0 -284
  389. package/src/runtime/MockRuntime.ts +0 -1244
  390. package/src/runtime/MockStateManager.ts +0 -576
  391. package/src/runtime/index.ts +0 -25
  392. package/src/runtime/types/MockState.ts +0 -227
  393. package/src/types/agent.ts +0 -79
  394. package/src/types/did.ts +0 -223
  395. package/src/utils/ErrorRecoveryGuide.ts +0 -675
  396. package/src/utils/Helpers.ts +0 -688
  397. package/src/utils/Logger.ts +0 -484
  398. package/src/utils/RateLimiter.ts +0 -534
  399. package/src/utils/SDKLifecycle.ts +0 -416
  400. package/src/utils/SecureNonce.ts +0 -78
  401. package/src/utils/Semaphore.ts +0 -276
  402. package/src/utils/UsedAttestationTracker.ts +0 -387
  403. package/src/utils/fsSafe.ts +0 -75
  404. package/src/utils/index.ts +0 -80
  405. package/src/utils/security.ts +0 -418
@@ -0,0 +1,570 @@
1
+ /**
2
+ * EscrowVault Security Test Suite
3
+ *
4
+ * CRITICAL: This module prepares token approvals for escrow creation.
5
+ * Actual escrow creation happens in ACTPKernel.linkEscrow() (tested in ACTPKernel integration tests).
6
+ *
7
+ * Per AIP-3 specification, escrow creation is atomic inside Kernel.linkEscrow(),
8
+ * not a separate EscrowVault SDK call. This test suite validates:
9
+ * 1. Token approval safety (USDC race condition mitigation)
10
+ * 2. Escrow release security (multi-recipient disbursement)
11
+ *
12
+ * Coverage Target: 90%+ (statements, functions, lines), 85%+ (branches)
13
+ *
14
+ * Security Test Categories:
15
+ * 1. Token Approval Safety (10+ tests) - Pre-escrow USDC approval
16
+ * 2. Escrow Release Security (10 tests) - Post-settlement disbursement
17
+ * 3. USDC Race Condition Mitigation (5+ tests) - Reset-to-zero pattern
18
+ * 4. Gas Estimation Buffers (2+ tests) - Dynamic gas buffers
19
+ *
20
+ * References:
21
+ * - Security Analysis: /Testnet/tests/SDK_SECURITY_ANALYSIS-Ultra-Think.md
22
+ * - AIP-3 §3.2: Escrow Linking Workflow
23
+ */
24
+
25
+ import { EscrowVault } from '../../protocol/EscrowVault';
26
+
27
+ // Mock ethers Contract
28
+ const mockContract = {
29
+ estimateGas: {
30
+ disburse: jest.fn().mockResolvedValue(BigInt(80000)),
31
+ approve: jest.fn().mockResolvedValue(BigInt(50000))
32
+ },
33
+ disburse: jest.fn().mockResolvedValue({
34
+ wait: jest.fn().mockResolvedValue({})
35
+ }),
36
+ escrows: jest.fn().mockResolvedValue({
37
+ kernel: '0x' + '1'.repeat(40),
38
+ txId: '0x' + '2'.repeat(64),
39
+ token: '0x' + '3'.repeat(40),
40
+ amount: BigInt('100000000'), // 100 USDC (6 decimals)
41
+ beneficiary: '0x' + '4'.repeat(40),
42
+ released: false
43
+ }),
44
+ allowance: jest.fn().mockResolvedValue(BigInt(0)),
45
+ balanceOf: jest.fn().mockResolvedValue(BigInt('1000000000')), // 1000 USDC
46
+ approve: jest.fn().mockResolvedValue({
47
+ wait: jest.fn().mockResolvedValue({})
48
+ }),
49
+ // ethers v6 requires getFunction
50
+ getFunction: jest.fn((name: string) => {
51
+ const functions: any = {
52
+ disburse: mockContract.disburse,
53
+ approve: mockContract.approve,
54
+ estimateGas: jest.fn().mockResolvedValue(BigInt(100000))
55
+ };
56
+ const func = functions[name] || jest.fn();
57
+ const estimateGasMap: any = mockContract.estimateGas;
58
+ func.estimateGas = estimateGasMap[name] || jest.fn().mockResolvedValue(BigInt(100000));
59
+ return func;
60
+ }),
61
+ // ethers v6: interface.parseLog for event parsing
62
+ interface: {
63
+ parseLog: jest.fn((_log: any) => ({
64
+ name: 'EscrowCreated',
65
+ args: { escrowId: '0x' + '1'.repeat(64) }
66
+ }))
67
+ }
68
+ };
69
+
70
+ // Mock signer
71
+ const mockSigner = {
72
+ provider: {},
73
+ getAddress: jest.fn().mockResolvedValue('0x' + 'e'.repeat(40))
74
+ };
75
+
76
+ // Mock Contract constructor
77
+ jest.mock('ethers', () => {
78
+ const actual = jest.requireActual('ethers');
79
+ return {
80
+ ...actual,
81
+ Contract: jest.fn().mockImplementation(() => mockContract)
82
+ };
83
+ });
84
+
85
+ describe('EscrowVault - Fund Flow Integrity', () => {
86
+ let escrowVault: EscrowVault;
87
+
88
+ const ESCROW_ADDRESS = '0x' + 'a'.repeat(40);
89
+ const TOKEN_ADDRESS = '0x' + 'c'.repeat(40);
90
+ const BENEFICIARY_ADDRESS = '0x' + 'd'.repeat(40);
91
+
92
+ beforeEach(() => {
93
+ jest.clearAllMocks();
94
+ escrowVault = new EscrowVault(ESCROW_ADDRESS, mockSigner as any);
95
+ });
96
+
97
+ describe('approveToken - Token Approval Safety', () => {
98
+ // NOTE: These tests cover PRE-escrow workflow (USDC approval).
99
+ // Escrow linking atomicity (approve → Kernel.linkEscrow → state transition)
100
+ // is tested in ACTPKernel integration tests.
101
+
102
+ it('should successfully approve token with valid parameters', async () => {
103
+ await escrowVault.approveToken(TOKEN_ADDRESS, BigInt('100000000'));
104
+
105
+ expect(mockContract.approve).toHaveBeenCalledWith(
106
+ ESCROW_ADDRESS,
107
+ BigInt('100000000'),
108
+ expect.objectContaining({
109
+ gasLimit: expect.any(BigInt)
110
+ })
111
+ );
112
+ });
113
+
114
+ it('should reject approval with zero address as token', async () => {
115
+ await expect(
116
+ escrowVault.approveToken('0x0000000000000000000000000000000000000000', BigInt('100000000'))
117
+ ).rejects.toThrow('zero address');
118
+ });
119
+
120
+ it('should reject approval with invalid token address format', async () => {
121
+ await expect(
122
+ escrowVault.approveToken('invalid-address', BigInt('100000000'))
123
+ ).rejects.toThrow('Invalid Ethereum address');
124
+ });
125
+
126
+ it('should reject approval with zero amount', async () => {
127
+ await expect(
128
+ escrowVault.approveToken(TOKEN_ADDRESS, BigInt(0))
129
+ ).rejects.toThrow('Invalid amount');
130
+ });
131
+
132
+ it('should reject approval with negative amount', async () => {
133
+ await expect(
134
+ escrowVault.approveToken(TOKEN_ADDRESS, BigInt(-1))
135
+ ).rejects.toThrow('Invalid amount');
136
+ });
137
+
138
+ it('should handle minimum USDC amount (0.05 USDC = 50000 wei)', async () => {
139
+ await escrowVault.approveToken(TOKEN_ADDRESS, BigInt(50000));
140
+
141
+ expect(mockContract.approve).toHaveBeenCalledWith(
142
+ ESCROW_ADDRESS,
143
+ BigInt(50000), // 0.05 USDC minimum
144
+ expect.objectContaining({
145
+ gasLimit: expect.any(BigInt)
146
+ })
147
+ );
148
+ });
149
+
150
+ it('should handle large amounts without overflow', async () => {
151
+ // Should not throw overflow error
152
+ await escrowVault.approveToken(TOKEN_ADDRESS, BigInt('1000000000000'));
153
+
154
+ expect(mockContract.approve).toHaveBeenCalledWith(
155
+ ESCROW_ADDRESS,
156
+ BigInt('1000000000000'), // 1M USDC
157
+ expect.objectContaining({
158
+ gasLimit: expect.any(BigInt)
159
+ })
160
+ );
161
+ });
162
+
163
+ it('should check current allowance before approving', async () => {
164
+ await escrowVault.approveToken(TOKEN_ADDRESS, BigInt('100000000'));
165
+
166
+ // Should have checked allowance
167
+ expect(mockContract.allowance).toHaveBeenCalled();
168
+ });
169
+
170
+ it('should skip approval if current allowance is sufficient', async () => {
171
+ // Mock sufficient allowance
172
+ mockContract.allowance.mockResolvedValueOnce(BigInt('200000000'));
173
+
174
+ await escrowVault.approveToken(TOKEN_ADDRESS, BigInt('100000000'));
175
+
176
+ // Should NOT call approve if allowance is sufficient
177
+ expect(mockContract.approve).not.toHaveBeenCalled();
178
+ });
179
+
180
+ it('should wrap transaction revert errors with proper context', async () => {
181
+ mockContract.approve.mockRejectedValueOnce({
182
+ transactionHash: '0x' + 'f'.repeat(64),
183
+ reason: 'Approval failed',
184
+ message: 'execution reverted: Approval failed'
185
+ });
186
+
187
+ await expect(
188
+ escrowVault.approveToken(TOKEN_ADDRESS, BigInt('100000000'))
189
+ ).rejects.toThrow('Token approval failed');
190
+ });
191
+
192
+ it('should skip approval if current allowance exceeds required amount', async () => {
193
+ // Mock allowance greater than required
194
+ mockContract.allowance.mockResolvedValueOnce(BigInt('200000000')); // 200 USDC
195
+
196
+ await escrowVault.approveToken(TOKEN_ADDRESS, BigInt('100000000')); // Need 100 USDC
197
+
198
+ // Should skip approval entirely
199
+ expect(mockContract.approve).not.toHaveBeenCalled();
200
+ });
201
+
202
+ it('should use explicit 20% gas buffer for approveToken operation', async () => {
203
+ // This test verifies explicit buffer for approveToken (not default)
204
+ mockContract.allowance.mockResolvedValueOnce(BigInt(0));
205
+
206
+ // estimateGas returns 50000
207
+ mockContract.getFunction('approve').estimateGas.mockResolvedValueOnce(BigInt(50000));
208
+
209
+ await escrowVault.approveToken(TOKEN_ADDRESS, BigInt('100000000'));
210
+
211
+ const approveCall = mockContract.approve.mock.calls[0];
212
+ const gasLimit = approveCall[2].gasLimit;
213
+
214
+ // 50000 * 1.20 = 60000 (approveToken uses explicit 20% buffer)
215
+ expect(gasLimit).toBe(BigInt(60000));
216
+ });
217
+
218
+ it('should wrap approval transaction errors with context', async () => {
219
+ mockContract.allowance.mockResolvedValueOnce(BigInt(0));
220
+
221
+ // Mock approve() rejecting with transaction error
222
+ mockContract.approve.mockRejectedValueOnce({
223
+ transactionHash: '0x' + 'f'.repeat(64),
224
+ reason: 'Insufficient funds'
225
+ });
226
+
227
+ await expect(
228
+ escrowVault.approveToken(TOKEN_ADDRESS, BigInt('100000000'))
229
+ ).rejects.toThrow('Token approval failed: Insufficient funds');
230
+ });
231
+
232
+ it('should handle USDC approval returning false instead of reverting', async () => {
233
+ mockContract.allowance.mockResolvedValueOnce(BigInt(0));
234
+
235
+ // Mock approve() returning transaction that fails on wait()
236
+ // This simulates USDC returning false instead of reverting
237
+ mockContract.approve.mockResolvedValueOnce({
238
+ wait: jest.fn().mockRejectedValue(new Error('Transaction failed: status 0'))
239
+ });
240
+
241
+ // SDK should detect failed transaction and throw
242
+ await expect(
243
+ escrowVault.approveToken(TOKEN_ADDRESS, BigInt('100000000'))
244
+ ).rejects.toThrow('Token approval failed');
245
+ });
246
+ });
247
+
248
+ describe('releaseEscrow - Distribution Safety', () => {
249
+ const ESCROW_ID = '0x' + '1'.repeat(64);
250
+
251
+ it('should successfully release escrow to single recipient', async () => {
252
+ const recipients = [BENEFICIARY_ADDRESS];
253
+ const amounts = [BigInt('100000000')];
254
+
255
+ await escrowVault.releaseEscrow(ESCROW_ID, recipients, amounts);
256
+
257
+ expect(mockContract.disburse).toHaveBeenCalledWith(
258
+ ESCROW_ID,
259
+ recipients,
260
+ amounts,
261
+ expect.any(Object)
262
+ );
263
+ });
264
+
265
+ it('should successfully release escrow to multiple recipients', async () => {
266
+ const recipients = [
267
+ BENEFICIARY_ADDRESS,
268
+ '0x' + '5'.repeat(40),
269
+ '0x' + '6'.repeat(40)
270
+ ];
271
+ const amounts = [
272
+ BigInt('50000000'), // 50 USDC
273
+ BigInt('30000000'), // 30 USDC
274
+ BigInt('20000000') // 20 USDC
275
+ ];
276
+
277
+ await escrowVault.releaseEscrow(ESCROW_ID, recipients, amounts);
278
+
279
+ expect(mockContract.disburse).toHaveBeenCalled();
280
+ });
281
+
282
+ it('should reject release with mismatched recipients/amounts length', async () => {
283
+ const recipients = [BENEFICIARY_ADDRESS, '0x' + '5'.repeat(40)];
284
+ const amounts = [BigInt('100000000')]; // Only 1 amount for 2 recipients
285
+
286
+ await expect(escrowVault.releaseEscrow(ESCROW_ID, recipients, amounts))
287
+ .rejects.toThrow('length mismatch');
288
+ });
289
+
290
+ it('should reject release with empty recipients array', async () => {
291
+ const recipients: string[] = [];
292
+ const amounts: bigint[] = [];
293
+
294
+ await expect(escrowVault.releaseEscrow(ESCROW_ID, recipients, amounts))
295
+ .rejects.toThrow('at least one recipient');
296
+ });
297
+
298
+ it('should reject release with zero address recipient', async () => {
299
+ const recipients = ['0x0000000000000000000000000000000000000000'];
300
+ const amounts = [BigInt('100000000')];
301
+
302
+ await expect(escrowVault.releaseEscrow(ESCROW_ID, recipients, amounts))
303
+ .rejects.toThrow('zero address');
304
+ });
305
+
306
+ it('should reject release with zero amount', async () => {
307
+ const recipients = [BENEFICIARY_ADDRESS];
308
+ const amounts = [BigInt(0)];
309
+
310
+ await expect(escrowVault.releaseEscrow(ESCROW_ID, recipients, amounts))
311
+ .rejects.toThrow('Invalid amount');
312
+ });
313
+
314
+ it('should reject release with negative amount', async () => {
315
+ const recipients = [BENEFICIARY_ADDRESS];
316
+ const amounts = [BigInt(-1)];
317
+
318
+ await expect(escrowVault.releaseEscrow(ESCROW_ID, recipients, amounts))
319
+ .rejects.toThrow('Invalid amount');
320
+ });
321
+
322
+ it('should reject release with invalid escrow ID format', async () => {
323
+ const recipients = [BENEFICIARY_ADDRESS];
324
+ const amounts = [BigInt('100000000')];
325
+
326
+ await expect(escrowVault.releaseEscrow('invalid-id', recipients, amounts))
327
+ .rejects.toThrow('Invalid transaction ID format');
328
+ });
329
+
330
+ it('should handle disbursement transaction revert', async () => {
331
+ mockContract.disburse.mockRejectedValueOnce({
332
+ transactionHash: '0x' + 'f'.repeat(64),
333
+ reason: 'Escrow already released',
334
+ message: 'execution reverted: Escrow already released'
335
+ });
336
+
337
+ const recipients = [BENEFICIARY_ADDRESS];
338
+ const amounts = [BigInt('100000000')];
339
+
340
+ await expect(escrowVault.releaseEscrow(ESCROW_ID, recipients, amounts))
341
+ .rejects.toThrow('Transaction reverted');
342
+ });
343
+
344
+ it('should validate all recipients in array', async () => {
345
+ const recipients = [
346
+ BENEFICIARY_ADDRESS,
347
+ 'invalid-address', // Invalid address
348
+ '0x' + '6'.repeat(40)
349
+ ];
350
+ const amounts = [
351
+ BigInt('50000000'),
352
+ BigInt('30000000'),
353
+ BigInt('20000000')
354
+ ];
355
+
356
+ await expect(escrowVault.releaseEscrow(ESCROW_ID, recipients, amounts))
357
+ .rejects.toThrow('Invalid Ethereum address');
358
+ });
359
+ });
360
+
361
+ describe('approveToken - USDC Race Condition Mitigation', () => {
362
+ it('should reset approval to zero before setting new value (USDC pattern)', async () => {
363
+ // Mock existing allowance
364
+ mockContract.allowance.mockResolvedValueOnce(BigInt('50000000'));
365
+
366
+ await escrowVault.approveToken(TOKEN_ADDRESS, BigInt('100000000'));
367
+
368
+ // Should approve twice (reset to 0, then set amount)
369
+ expect(mockContract.approve).toHaveBeenCalledTimes(2);
370
+ });
371
+
372
+ it('should only approve if current allowance is less than required amount', async () => {
373
+ // Mock allowance exactly equal to amount
374
+ mockContract.allowance.mockResolvedValueOnce(BigInt('100000000'));
375
+
376
+ await escrowVault.approveToken(TOKEN_ADDRESS, BigInt('100000000'));
377
+
378
+ // Should NOT approve if allowance equals amount
379
+ expect(mockContract.approve).not.toHaveBeenCalled();
380
+ });
381
+
382
+ it('should estimate gas for both reset and set approval', async () => {
383
+ mockContract.allowance.mockResolvedValueOnce(BigInt('50000000'));
384
+
385
+ await escrowVault.approveToken(TOKEN_ADDRESS, BigInt('100000000'));
386
+
387
+ // Should estimate gas twice (reset + set)
388
+ expect(mockContract.estimateGas.approve).toHaveBeenCalledTimes(2);
389
+ });
390
+
391
+ it('should wait for reset approval before setting new approval', async () => {
392
+ mockContract.allowance.mockResolvedValueOnce(BigInt('50000000'));
393
+
394
+ const waitMock = jest.fn().mockResolvedValue({});
395
+ mockContract.approve.mockResolvedValue({ wait: waitMock });
396
+
397
+ await escrowVault.approveToken(TOKEN_ADDRESS, BigInt('100000000'));
398
+
399
+ // Should wait twice (reset + set)
400
+ expect(waitMock).toHaveBeenCalledTimes(2);
401
+ });
402
+
403
+ it('should include gas settings in approval transactions', async () => {
404
+ const gasSettings = {
405
+ maxFeePerGas: BigInt('2000000000'), // 2 gwei
406
+ maxPriorityFeePerGas: BigInt('1000000000') // 1 gwei
407
+ };
408
+
409
+ const vaultWithGas = new EscrowVault(ESCROW_ADDRESS, mockSigner as any, gasSettings);
410
+
411
+ await vaultWithGas.approveToken(TOKEN_ADDRESS, BigInt('100000000'));
412
+
413
+ // Should pass gas settings to approval transactions
414
+ expect(mockContract.approve).toHaveBeenCalledWith(
415
+ ESCROW_ADDRESS,
416
+ BigInt('100000000'),
417
+ expect.objectContaining({
418
+ gasLimit: expect.any(BigInt),
419
+ maxFeePerGas: gasSettings.maxFeePerGas,
420
+ maxPriorityFeePerGas: gasSettings.maxPriorityFeePerGas
421
+ })
422
+ );
423
+ });
424
+ });
425
+
426
+ describe('getEscrow - Data Retrieval', () => {
427
+ it('should retrieve escrow details correctly', async () => {
428
+ const ESCROW_ID = '0x' + '1'.repeat(64);
429
+
430
+ const escrow = await escrowVault.getEscrow(ESCROW_ID);
431
+
432
+ expect(escrow.escrowId).toBe(ESCROW_ID);
433
+ expect(escrow.kernel).toBe('0x' + '1'.repeat(40));
434
+ expect(escrow.txId).toBe('0x' + '2'.repeat(64));
435
+ expect(escrow.token).toBe('0x' + '3'.repeat(40));
436
+ expect(escrow.amount).toEqual(BigInt('100000000'));
437
+ expect(escrow.beneficiary).toBe('0x' + '4'.repeat(40));
438
+ expect(escrow.released).toBe(false);
439
+ });
440
+
441
+ it('should get escrow balance', async () => {
442
+ const ESCROW_ID = '0x' + '1'.repeat(64);
443
+
444
+ const balance = await escrowVault.getEscrowBalance(ESCROW_ID);
445
+
446
+ expect(balance).toEqual(BigInt('100000000'));
447
+ });
448
+ });
449
+
450
+ describe('Token Helper Methods', () => {
451
+ it('should get token balance for account', async () => {
452
+ const USER_ADDRESS = '0x' + 'e'.repeat(40);
453
+ const balance = await escrowVault.getTokenBalance(TOKEN_ADDRESS, USER_ADDRESS);
454
+
455
+ expect(balance).toEqual(BigInt('1000000000'));
456
+ expect(mockContract.balanceOf).toHaveBeenCalledWith(USER_ADDRESS);
457
+ });
458
+
459
+ it('should get token allowance', async () => {
460
+ const USER_ADDRESS = '0x' + 'e'.repeat(40);
461
+ await escrowVault.getTokenAllowance(
462
+ TOKEN_ADDRESS,
463
+ USER_ADDRESS,
464
+ ESCROW_ADDRESS
465
+ );
466
+
467
+ expect(mockContract.allowance).toHaveBeenCalledWith(USER_ADDRESS, ESCROW_ADDRESS);
468
+ });
469
+ });
470
+
471
+ describe('Gas Estimation - V6 Dynamic Buffers', () => {
472
+ it('should apply 20% gas buffer to approveToken', async () => {
473
+ mockContract.estimateGas.approve.mockResolvedValueOnce(BigInt(50000));
474
+
475
+ await escrowVault.approveToken(TOKEN_ADDRESS, BigInt('100000000'));
476
+
477
+ // Should call with gasLimit = estimatedGas * 1.2 (20% buffer for ERC20 approval)
478
+ expect(mockContract.approve).toHaveBeenCalledWith(
479
+ ESCROW_ADDRESS,
480
+ BigInt('100000000'),
481
+ expect.objectContaining({
482
+ gasLimit: BigInt(60000) // 50000 * 1.20
483
+ })
484
+ );
485
+ });
486
+
487
+ it('should apply 30% gas buffer to releaseEscrow', async () => {
488
+ mockContract.estimateGas.disburse.mockResolvedValueOnce(BigInt(80000));
489
+
490
+ const ESCROW_ID = '0x' + '1'.repeat(64);
491
+ const recipients = [BENEFICIARY_ADDRESS];
492
+ const amounts = [BigInt('100000000')];
493
+
494
+ await escrowVault.releaseEscrow(ESCROW_ID, recipients, amounts);
495
+
496
+ expect(mockContract.disburse).toHaveBeenCalledWith(
497
+ ESCROW_ID,
498
+ recipients,
499
+ amounts,
500
+ expect.objectContaining({
501
+ gasLimit: BigInt(104000) // 80000 * 1.30 (30% buffer for multi-recipient disbursement)
502
+ })
503
+ );
504
+ });
505
+
506
+ it('should build transaction options without gas settings', async () => {
507
+ // Create vault without gas settings
508
+ const vaultNoGas = new EscrowVault(ESCROW_ADDRESS, mockSigner as any);
509
+
510
+ mockContract.estimateGas.approve.mockResolvedValueOnce(BigInt(50000));
511
+
512
+ await vaultNoGas.approveToken(TOKEN_ADDRESS, BigInt('100000000'));
513
+
514
+ // Should only include gasLimit, no maxFeePerGas or maxPriorityFeePerGas
515
+ expect(mockContract.approve).toHaveBeenCalledWith(
516
+ ESCROW_ADDRESS,
517
+ BigInt('100000000'),
518
+ expect.objectContaining({
519
+ gasLimit: BigInt(60000) // 50000 * 1.20
520
+ })
521
+ );
522
+
523
+ // Verify gas settings are NOT included
524
+ const approveCall = mockContract.approve.mock.calls[0];
525
+ expect(approveCall[2]).not.toHaveProperty('maxFeePerGas');
526
+ expect(approveCall[2]).not.toHaveProperty('maxPriorityFeePerGas');
527
+ });
528
+
529
+ it('should handle releaseEscrow error without reason field', async () => {
530
+ mockContract.disburse.mockRejectedValueOnce({
531
+ transactionHash: '0x' + 'f'.repeat(64),
532
+ message: 'Transaction failed'
533
+ // No 'reason' field
534
+ });
535
+
536
+ const ESCROW_ID = '0x' + '1'.repeat(64);
537
+ const recipients = [BENEFICIARY_ADDRESS];
538
+ const amounts = [BigInt('100000000')];
539
+
540
+ await expect(escrowVault.releaseEscrow(ESCROW_ID, recipients, amounts))
541
+ .rejects.toThrow('Transaction failed');
542
+ });
543
+
544
+ it('should use correct buffer for releaseEscrow operation (30%)', async () => {
545
+ const ESCROW_ID = '0x' + '1'.repeat(64);
546
+ const recipients = [BENEFICIARY_ADDRESS, '0x' + '5'.repeat(40)];
547
+ const amounts = [BigInt('60000000'), BigInt('40000000')];
548
+
549
+ mockContract.estimateGas.disburse.mockResolvedValueOnce(BigInt(100000));
550
+
551
+ await escrowVault.releaseEscrow(ESCROW_ID, recipients, amounts);
552
+
553
+ // Should use 30% buffer for releaseEscrow (multi-recipient complexity)
554
+ expect(mockContract.disburse).toHaveBeenCalledWith(
555
+ ESCROW_ID,
556
+ recipients,
557
+ amounts,
558
+ expect.objectContaining({
559
+ gasLimit: BigInt(130000) // 100000 * 1.30
560
+ })
561
+ );
562
+ });
563
+ });
564
+
565
+ describe('getAddress', () => {
566
+ it('should return escrow vault address', () => {
567
+ expect(escrowVault.getAddress()).toBe(ESCROW_ADDRESS);
568
+ });
569
+ });
570
+ });