@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
package/src/ACTPClient.ts CHANGED
@@ -1,276 +1,790 @@
1
- import { ethers, Wallet, Signer } from 'ethers';
2
- import type { JsonRpcProvider } from 'ethers';
3
- import { ACTPKernel } from './protocol/ACTPKernel';
4
- import { EscrowVault } from './protocol/EscrowVault';
5
- import { EventMonitor } from './protocol/EventMonitor';
6
- import { ProofGenerator } from './protocol/ProofGenerator';
7
- import { MessageSigner } from './protocol/MessageSigner';
8
- import { QuoteBuilder } from './builders/QuoteBuilder';
9
- import { NetworkConfig, getNetwork } from './config/networks';
10
- import { NetworkError, ValidationError } from './errors';
1
+ /**
2
+ * ACTPClient - Main entry point for AGIRAILS SDK
3
+ *
4
+ * Provides the unified API for interacting with the ACTP protocol
5
+ * through three different abstraction levels:
6
+ * - `beginner`: High-level, opinionated API for simple use cases
7
+ * - `intermediate`: Balanced API with more control
8
+ * - `advanced`: Direct protocol access for full control
9
+ *
10
+ * @module ACTPClient
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * // Create client in mock mode
15
+ * const client = await ACTPClient.create({
16
+ * mode: 'mock',
17
+ * requesterAddress: '0x1234...',
18
+ * });
19
+ *
20
+ * // Beginner API - simplest approach
21
+ * const result = await client.beginner.pay({
22
+ * to: '0xProvider...',
23
+ * amount: '100',
24
+ * });
25
+ *
26
+ * // Intermediate API - more control
27
+ * const txId = await client.intermediate.createTransaction({
28
+ * provider: '0xProvider...',
29
+ * amount: '100',
30
+ * });
31
+ * await client.intermediate.linkEscrow(txId);
32
+ *
33
+ * // Advanced API - direct protocol access
34
+ * const tx = await client.advanced.getTransaction(txId);
35
+ * ```
36
+ */
37
+
38
+ import * as path from 'path';
39
+ import * as os from 'os';
40
+ import * as fs from 'fs';
41
+ import { ethers } from 'ethers';
42
+ import { MockRuntime } from './runtime/MockRuntime';
43
+ import { MockStateManager } from './runtime/MockStateManager';
44
+ import { BlockchainRuntime } from './runtime/BlockchainRuntime';
45
+ import { IACTPRuntime, IMockRuntime } from './runtime/IACTPRuntime';
46
+ import { BeginnerAdapter } from './adapters/BeginnerAdapter';
47
+ import { IntermediateAdapter } from './adapters/IntermediateAdapter';
11
48
  import { EASHelper, EASConfig } from './protocol/EASHelper';
12
- import { NonceManager, InMemoryNonceManager } from './utils/NonceManager';
13
- import { IPFSClient } from './utils/IPFSClient';
49
+ import { getNetwork } from './config/networks';
50
+
51
+ // ============================================================================
52
+ // Security: Path Validation
53
+ // ============================================================================
54
+
55
+ /**
56
+ * Validates that a state directory path is safe to use.
57
+ *
58
+ * SECURITY: Prevents path traversal attacks by ensuring:
59
+ * 1. No '..' components in the path
60
+ * 2. No symbolic links that could escape the intended directory
61
+ * 3. Path resolves to a location within home directory or current working directory
62
+ *
63
+ * @param stateDirectory - The directory path to validate
64
+ * @throws Error if path is unsafe
65
+ */
66
+ function validateStateDirectory(stateDirectory: string): void {
67
+ // Check for path traversal characters
68
+ if (stateDirectory.includes('..')) {
69
+ throw new Error(
70
+ 'stateDirectory cannot contain path traversal characters (..). ' +
71
+ 'Use absolute paths only for security.'
72
+ );
73
+ }
74
+
75
+ // Resolve the path to get the absolute path
76
+ const resolvedPath = path.resolve(stateDirectory);
77
+
78
+ // If path exists, reject symlinks and use realpath for boundary checks.
79
+ // This blocks symlink escapes like "~/project" -> "/etc".
80
+ let effectivePath = resolvedPath;
81
+ if (fs.existsSync(resolvedPath)) {
82
+ const st = fs.lstatSync(resolvedPath);
83
+ if (st.isSymbolicLink()) {
84
+ throw new Error(
85
+ 'stateDirectory cannot be a symbolic link. ' +
86
+ `Path "${stateDirectory}" resolves to a symlink at "${resolvedPath}".`
87
+ );
88
+ }
89
+ if (!st.isDirectory()) {
90
+ throw new Error(
91
+ `stateDirectory must be a directory. Path "${resolvedPath}" is not a directory.`
92
+ );
93
+ }
94
+ effectivePath = fs.realpathSync(resolvedPath);
95
+ }
96
+
97
+ // Get safe base directories
98
+ const homeDir = os.homedir();
99
+ const cwd = process.cwd();
100
+
101
+ // SECURITY FIX (C-5): Use path.relative() instead of startsWith()
102
+ // to handle case-insensitive filesystems (macOS, Windows) correctly.
103
+ // path.relative() returns a path starting with '..' if target is outside base.
104
+ const relativeToHome = path.relative(homeDir, effectivePath);
105
+ const relativeToCwd = path.relative(cwd, effectivePath);
106
+
107
+ // Check if path escapes the boundary (starts with '..' or is absolute)
108
+ const isUnderHome = !relativeToHome.startsWith('..') && !path.isAbsolute(relativeToHome);
109
+ const isUnderCwd = !relativeToCwd.startsWith('..') && !path.isAbsolute(relativeToCwd);
110
+
111
+ if (!isUnderHome && !isUnderCwd) {
112
+ throw new Error(
113
+ 'stateDirectory must be within home directory or current working directory. ' +
114
+ `Resolved path "${resolvedPath}" is outside allowed boundaries.`
115
+ );
116
+ }
117
+
118
+ // Additional check: Ensure path doesn't contain null bytes (can bypass validation)
119
+ if (stateDirectory.includes('\0')) {
120
+ throw new Error('stateDirectory contains invalid null byte character');
121
+ }
122
+ }
123
+
124
+ // ============================================================================
125
+ // Type Guards
126
+ // ============================================================================
14
127
 
15
128
  /**
16
- * ACTPClient configuration
129
+ * Type guard to check if runtime is MockRuntime.
130
+ *
131
+ * @param runtime - Runtime to check
132
+ * @returns True if runtime is IMockRuntime
133
+ */
134
+ function isMockRuntime(runtime: IACTPRuntime): runtime is IMockRuntime {
135
+ return 'reset' in runtime && typeof (runtime as IMockRuntime).reset === 'function';
136
+ }
137
+
138
+ // ============================================================================
139
+ // Types
140
+ // ============================================================================
141
+
142
+ /**
143
+ * Supported modes for ACTPClient.
144
+ *
145
+ * - `mock`: Local development mode with file-based state
146
+ * - `testnet`: Base Sepolia testnet (future)
147
+ * - `mainnet`: Base mainnet (future)
148
+ */
149
+ export type ACTPClientMode = 'mock' | 'testnet' | 'mainnet';
150
+
151
+ /**
152
+ * Configuration for creating an ACTPClient instance.
17
153
  */
18
154
  export interface ACTPClientConfig {
19
- network: 'base-sepolia' | 'base-mainnet';
155
+ /**
156
+ * Operating mode.
157
+ *
158
+ * - 'mock': Local development with file-based state
159
+ * - 'testnet': Base Sepolia testnet
160
+ * - 'mainnet': Base mainnet
161
+ */
162
+ mode: ACTPClientMode;
163
+
164
+ /**
165
+ * The requester's Ethereum address.
166
+ *
167
+ * This address is used as the "from" address for all transactions
168
+ * created through this client instance.
169
+ *
170
+ * @example '0x1111111111111111111111111111111111111111'
171
+ */
172
+ requesterAddress: string;
173
+
174
+ /**
175
+ * Optional: Project root directory for mock state file storage.
176
+ *
177
+ * The state file will be stored at `{stateDirectory}/.actp/mock-state.json`.
178
+ * Defaults to current working directory.
179
+ * Only used when mode is 'mock'.
180
+ */
181
+ stateDirectory?: string;
182
+
183
+ /**
184
+ * Optional: Private key for signing transactions.
185
+ *
186
+ * Required when mode is 'testnet' or 'mainnet'.
187
+ * Not used in 'mock' mode.
188
+ *
189
+ * ⚠️ CRITICAL SECURITY WARNING (C-1):
190
+ *
191
+ * **NEVER use raw private keys in production environments**
192
+ *
193
+ * **Recommended Approaches:**
194
+ * 1. **Encrypted JSON Keystore** (ethers.Wallet.fromEncryptedJson) - Best for server-side
195
+ * - Stores key encrypted with password
196
+ * - Requires decryption at runtime (password from secure vault)
197
+ * - Standard Web3 format (compatible with MetaMask, Geth, etc.)
198
+ *
199
+ * 2. **Hardware Wallets** (Ledger/Trezor) - Best for high-value operations
200
+ * - Private key never leaves device
201
+ * - User confirmation for each transaction
202
+ * - Future SDK integration planned
203
+ *
204
+ * 3. **KMS/HSM Integration** - Best for enterprise deployment
205
+ * - AWS KMS, Google Cloud KMS, Azure Key Vault
206
+ * - Private key never accessible to application
207
+ * - Audit trail for all signing operations
208
+ *
209
+ * **Security Requirements:**
210
+ * - NEVER log this value or include in error messages
211
+ * - NEVER store in plaintext files or git repositories
212
+ * - NEVER expose in API responses or client-side code
213
+ * - NEVER hardcode in source code (use environment variables minimum)
214
+ * - ALWAYS use encrypted storage (keystore, KMS, hardware wallet)
215
+ * - ALWAYS rotate keys if compromise suspected
216
+ * - The ACTPClient toJSON() method excludes this field from serialization
217
+ *
218
+ * **Example (Encrypted Keystore):**
219
+ * ```typescript
220
+ * import { Wallet } from 'ethers';
221
+ * import fs from 'fs';
222
+ *
223
+ * // Load encrypted keystore
224
+ * const keystore = fs.readFileSync('path/to/keystore.json', 'utf8');
225
+ * const password = process.env.KEYSTORE_PASSWORD; // From secure vault, not .env file
226
+ * const wallet = await Wallet.fromEncryptedJson(keystore, password);
227
+ *
228
+ * // Use with ACTPClient
229
+ * const client = await ACTPClient.create({
230
+ * mode: 'testnet',
231
+ * requesterAddress: wallet.address,
232
+ * privateKey: wallet.privateKey, // Decrypted at runtime only
233
+ * rpcUrl: process.env.RPC_URL
234
+ * });
235
+ * ```
236
+ */
20
237
  privateKey?: string;
21
- signer?: Signer;
22
- provider?: JsonRpcProvider;
238
+
239
+ /**
240
+ * Optional: RPC URL for blockchain connection.
241
+ *
242
+ * Required when mode is 'testnet' or 'mainnet'.
243
+ * Not used in 'mock' mode.
244
+ *
245
+ * @example 'https://base-sepolia.g.alchemy.com/v2/YOUR_KEY'
246
+ */
23
247
  rpcUrl?: string;
248
+
249
+ /**
250
+ * Optional: Contract address overrides.
251
+ *
252
+ * Override default deployed contract addresses.
253
+ * Used in 'testnet' and 'mainnet' modes.
254
+ */
24
255
  contracts?: {
25
256
  actpKernel?: string;
26
257
  escrowVault?: string;
27
258
  usdc?: string;
28
259
  };
260
+
261
+ /**
262
+ * Optional: Gas settings for blockchain transactions.
263
+ *
264
+ * Used in 'testnet' and 'mainnet' modes.
265
+ */
29
266
  gasSettings?: {
30
267
  maxFeePerGas?: bigint;
31
268
  maxPriorityFeePerGas?: bigint;
32
269
  };
33
- eas?: EASConfig;
270
+
271
+ /**
272
+ * Optional: EAS (Ethereum Attestation Service) configuration.
273
+ *
274
+ * SECURITY FIX (C-4): Required for attestation verification in testnet/mainnet modes.
275
+ * If not provided, attestation verification in releaseEscrow() will be skipped.
276
+ *
277
+ * Used in 'testnet' and 'mainnet' modes.
278
+ */
279
+ easConfig?: EASConfig;
280
+
281
+ /**
282
+ * Optional: Require valid EAS attestation before escrow release (blockchain modes).
283
+ *
284
+ * If true, `releaseEscrow()` will require an `attestationUID` and verify it on-chain via EAS.
285
+ *
286
+ * Default:
287
+ * - true when `easConfig` is provided
288
+ * - false otherwise
289
+ */
290
+ requireAttestation?: boolean;
291
+
292
+ /**
293
+ * Optional: Custom runtime instance.
294
+ *
295
+ * For advanced use cases where you want to provide your own
296
+ * runtime implementation (e.g., for testing with custom mocks).
297
+ *
298
+ * If provided, mode and stateDirectory are ignored.
299
+ */
300
+ runtime?: IACTPRuntime;
301
+ }
302
+
303
+ /**
304
+ * Result of creating an ACTPClient.
305
+ *
306
+ * Contains metadata about the client initialization.
307
+ */
308
+ export interface ACTPClientInfo {
309
+ /** Operating mode */
310
+ mode: ACTPClientMode;
311
+ /** Requester address */
312
+ address: string;
313
+ /** State directory (mock mode only) */
314
+ stateDirectory?: string;
34
315
  }
35
316
 
317
+ // ============================================================================
318
+ // ACTPClient Class
319
+ // ============================================================================
320
+
36
321
  /**
37
- * ACTPClient - Main entry point for ACTP SDK
322
+ * ACTPClient - Main entry point for AGIRAILS SDK.
323
+ *
324
+ * This class provides a unified interface to the ACTP protocol through
325
+ * three abstraction levels, catering to developers with different needs:
326
+ *
327
+ * **Beginner API** (`client.beginner`):
328
+ * - Simplest possible interface
329
+ * - Smart defaults (24h deadline, 2-day dispute window)
330
+ * - User-friendly inputs (strings, no BigInt)
331
+ * - Perfect for: Quick prototypes, simple integrations
38
332
  *
39
- * Example:
333
+ * **Intermediate API** (`client.intermediate`):
334
+ * - Explicit lifecycle methods
335
+ * - More control over transaction flow
336
+ * - Still with user-friendly input parsing
337
+ * - Perfect for: Production apps needing control
338
+ *
339
+ * **Advanced API** (`client.advanced`):
340
+ * - Direct access to protocol runtime
341
+ * - Full control over all parameters
342
+ * - Protocol-level types (BigInt, timestamps)
343
+ * - Perfect for: Power users, custom integrations
344
+ *
345
+ * @example
40
346
  * ```typescript
347
+ * // Create client
41
348
  * const client = await ACTPClient.create({
42
- * network: 'base-sepolia',
43
- * privateKey: process.env.PRIVATE_KEY
349
+ * mode: 'mock',
350
+ * requesterAddress: '0xRequester...',
351
+ * });
352
+ *
353
+ * // Three ways to create a transaction:
354
+ *
355
+ * // 1. Beginner: One call does everything
356
+ * await client.beginner.pay({ to: '0xProvider', amount: '100' });
357
+ *
358
+ * // 2. Intermediate: Explicit steps
359
+ * const txId = await client.intermediate.createTransaction({
360
+ * provider: '0xProvider',
361
+ * amount: '100',
44
362
  * });
363
+ * await client.intermediate.linkEscrow(txId);
45
364
  *
46
- * const txId = await client.kernel.createTransaction({...});
365
+ * // 3. Advanced: Full control
366
+ * const txId = await client.advanced.createTransaction({
367
+ * provider: '0xProvider',
368
+ * requester: '0xRequester',
369
+ * amount: '100000000', // wei
370
+ * deadline: Math.floor(Date.now() / 1000) + 86400,
371
+ * disputeWindow: 172800,
372
+ * });
47
373
  * ```
48
374
  */
49
375
  export class ACTPClient {
50
- public readonly kernel: ACTPKernel;
51
- public readonly escrow: EscrowVault;
52
- public readonly events: EventMonitor;
53
- public readonly proofGenerator: ProofGenerator;
54
- public readonly messageSigner: MessageSigner;
55
- public readonly quote: QuoteBuilder;
56
- public readonly eas?: EASHelper;
57
-
58
- private readonly provider: JsonRpcProvider;
59
- private readonly signer: Signer;
60
- private readonly networkConfig: NetworkConfig;
61
- private readonly nonceManager: NonceManager;
62
- private readonly ipfs?: IPFSClient;
376
+ /**
377
+ * Beginner-level API.
378
+ *
379
+ * Provides the simplest interface for creating and checking transactions.
380
+ * Ideal for developers who want to "just make it work" without deep
381
+ * protocol knowledge.
382
+ *
383
+ * @example
384
+ * ```typescript
385
+ * const result = await client.beginner.pay({
386
+ * to: '0xProvider...',
387
+ * amount: '100',
388
+ * });
389
+ * console.log('Transaction ID:', result.txId);
390
+ * console.log('State:', result.state); // 'COMMITTED'
391
+ * ```
392
+ */
393
+ public readonly beginner: BeginnerAdapter;
63
394
 
64
395
  /**
65
- * Private constructor - use ACTPClient.create() instead
396
+ * Intermediate-level API.
397
+ *
398
+ * Provides explicit lifecycle methods for more control over
399
+ * the transaction flow while still offering user-friendly inputs.
400
+ *
401
+ * @example
402
+ * ```typescript
403
+ * // Create transaction (INITIATED state)
404
+ * const txId = await client.intermediate.createTransaction({
405
+ * provider: '0xProvider...',
406
+ * amount: '100',
407
+ * deadline: '+7d',
408
+ * });
409
+ *
410
+ * // Link escrow (auto-transitions to COMMITTED)
411
+ * await client.intermediate.linkEscrow(txId);
412
+ *
413
+ * // Transition to DELIVERED
414
+ * await client.intermediate.transitionState(txId, 'DELIVERED');
415
+ * ```
66
416
  */
67
- private constructor(config: ACTPClientConfig) {
68
- // Validate config
69
- this.validateConfig(config);
70
-
71
- // Get network configuration (already cloned in getNetwork)
72
- this.networkConfig = getNetwork(config.network);
73
-
74
- // Apply overrides immutably (create new objects, don't mutate)
75
- if (config.contracts) {
76
- this.networkConfig = {
77
- ...this.networkConfig,
78
- contracts: {
79
- ...this.networkConfig.contracts,
80
- ...config.contracts
81
- }
82
- };
417
+ public readonly intermediate: IntermediateAdapter;
418
+
419
+ /**
420
+ * The underlying runtime implementation.
421
+ *
422
+ * Direct access to the protocol runtime for advanced use cases.
423
+ * This is the same as `client.advanced`.
424
+ */
425
+ public readonly runtime: IACTPRuntime;
426
+
427
+ /**
428
+ * Client information (mode, address, etc.)
429
+ */
430
+ public readonly info: ACTPClientInfo;
431
+
432
+ /**
433
+ * SECURITY FIX (C-4): EAS helper for attestation verification.
434
+ * Only available in testnet/mainnet modes when easConfig is provided.
435
+ */
436
+ public readonly easHelper?: EASHelper;
437
+
438
+ /**
439
+ * Private constructor - use ACTPClient.create() factory method.
440
+ */
441
+ private constructor(
442
+ runtime: IACTPRuntime,
443
+ requesterAddress: string,
444
+ info: ACTPClientInfo,
445
+ easHelper?: EASHelper
446
+ ) {
447
+ this.runtime = runtime;
448
+ this.info = info;
449
+ this.easHelper = easHelper;
450
+ this.beginner = new BeginnerAdapter(runtime, requesterAddress, easHelper);
451
+ this.intermediate = new IntermediateAdapter(runtime, requesterAddress, easHelper);
452
+ }
453
+
454
+ // ==========================================================================
455
+ // Factory Method
456
+ // ==========================================================================
457
+
458
+ /**
459
+ * Creates a new ACTPClient instance.
460
+ *
461
+ * This is the primary way to instantiate an ACTPClient.
462
+ * It handles runtime initialization based on the specified mode.
463
+ *
464
+ * @param config - Client configuration
465
+ * @returns Promise resolving to initialized ACTPClient
466
+ * @throws {Error} If mode is not supported (only 'mock' currently)
467
+ *
468
+ * @example
469
+ * ```typescript
470
+ * // Mock mode (local development)
471
+ * const client = await ACTPClient.create({
472
+ * mode: 'mock',
473
+ * requesterAddress: '0x1234...',
474
+ * });
475
+ *
476
+ * // Mock mode with custom state directory
477
+ * const client = await ACTPClient.create({
478
+ * mode: 'mock',
479
+ * requesterAddress: '0x1234...',
480
+ * stateDirectory: '/custom/path/.actp',
481
+ * });
482
+ *
483
+ * // Custom runtime (for testing)
484
+ * const customRuntime = new MockRuntime();
485
+ * const client = await ACTPClient.create({
486
+ * mode: 'mock',
487
+ * requesterAddress: '0x1234...',
488
+ * runtime: customRuntime,
489
+ * });
490
+ * ```
491
+ */
492
+ static async create(config: ACTPClientConfig): Promise<ACTPClient> {
493
+ // Validate requester address
494
+ if (!config.requesterAddress) {
495
+ throw new Error('requesterAddress is required');
83
496
  }
84
497
 
85
- // Apply gas settings overrides
86
- if (config.gasSettings) {
87
- this.networkConfig = {
88
- ...this.networkConfig,
89
- gasSettings: {
90
- ...this.networkConfig.gasSettings,
91
- ...config.gasSettings
92
- }
93
- };
498
+ if (!/^0x[a-fA-F0-9]{40}$/.test(config.requesterAddress)) {
499
+ throw new Error(
500
+ `Invalid requesterAddress: "${config.requesterAddress}". ` +
501
+ 'Must be a valid Ethereum address (0x-prefixed, 40 hex chars)'
502
+ );
94
503
  }
95
504
 
96
- // Freeze config to prevent accidental mutation
97
- Object.freeze(this.networkConfig.contracts);
98
- Object.freeze(this.networkConfig.gasSettings);
99
- Object.freeze(this.networkConfig);
505
+ let runtime: IACTPRuntime;
506
+ let stateDirectory: string | undefined;
507
+ let easHelper: EASHelper | undefined;
100
508
 
101
- // Setup provider
102
- if (config.provider) {
103
- this.provider = config.provider;
509
+ // If custom runtime provided, use it directly
510
+ if (config.runtime) {
511
+ runtime = config.runtime;
104
512
  } else {
105
- const rpcUrl = config.rpcUrl || this.networkConfig.rpcUrl;
106
- this.provider = new ethers.JsonRpcProvider(rpcUrl, this.networkConfig.chainId);
107
- }
513
+ // Initialize runtime based on mode
514
+ switch (config.mode) {
515
+ case 'mock': {
516
+ // SECURITY FIX: Enhanced path validation to prevent path traversal attacks
517
+ if (config.stateDirectory) {
518
+ validateStateDirectory(config.stateDirectory);
519
+ }
108
520
 
109
- // Setup signer
110
- if (config.signer) {
111
- this.signer = config.signer;
112
- } else if (config.privateKey) {
113
- this.signer = new Wallet(config.privateKey, this.provider);
114
- } else {
115
- // Attempt to derive signer from provider if possible
116
- // In ethers v6, getSigner() is async and returns a JsonRpcSigner
117
- throw new ValidationError('signer', 'Either privateKey or signer must be provided');
118
- }
521
+ // MockStateManager takes projectRoot as string parameter
522
+ const stateManager = new MockStateManager(config.stateDirectory);
523
+ runtime = new MockRuntime(stateManager);
524
+ stateDirectory = config.stateDirectory;
525
+ // EASHelper not needed in mock mode
526
+ break;
527
+ }
119
528
 
120
- // Initialize shared utilities
121
- this.nonceManager = new InMemoryNonceManager();
529
+ case 'testnet':
530
+ case 'mainnet': {
531
+ // Validate required parameters for blockchain modes
532
+ if (!config.privateKey) {
533
+ throw new Error(
534
+ `privateKey is required for ${config.mode} mode`
535
+ );
536
+ }
122
537
 
123
- // Initialize IPFS client if configured
124
- if (config.rpcUrl) {
125
- // IPFS configuration could be added to ACTPClientConfig in the future
126
- // For now, QuoteBuilder can work without IPFS (quotes stored only on-chain)
127
- }
538
+ // Map mode to network config
539
+ const network = config.mode === 'testnet' ? 'base-sepolia' : 'base-mainnet';
128
540
 
129
- // Initialize protocol modules
130
- this.kernel = new ACTPKernel(
131
- this.networkConfig.contracts.actpKernel,
132
- this.signer,
133
- this.networkConfig.gasSettings
134
- );
541
+ // Default RPC URL from network config if not provided
542
+ // This makes Level0/Agent usable on testnet without forcing users to pass rpcUrl explicitly.
543
+ const rpcUrl = config.rpcUrl ?? getNetwork(network).rpcUrl;
135
544
 
136
- this.escrow = new EscrowVault(
137
- this.networkConfig.contracts.escrowVault,
138
- this.signer,
139
- this.networkConfig.gasSettings
140
- );
545
+ // Optional persistent state directory can be used for:
546
+ // - mock mode state (mock-state.json)
547
+ // - blockchain mode safety state (e.g., used-attestation replay protection)
548
+ if (config.stateDirectory) {
549
+ validateStateDirectory(config.stateDirectory);
550
+ }
141
551
 
142
- this.events = new EventMonitor(
143
- this.kernel['contract'], // Access private contract field
144
- this.escrow['contract']
145
- );
552
+ // Create ethers provider and signer
553
+ const provider = new ethers.JsonRpcProvider(rpcUrl);
554
+ const signer = new ethers.Wallet(config.privateKey, provider);
555
+
556
+ const requireAttestation = config.requireAttestation ?? Boolean(config.easConfig);
146
557
 
147
- this.proofGenerator = new ProofGenerator();
558
+ // Create BlockchainRuntime
559
+ const blockchainRuntime = new BlockchainRuntime({
560
+ network,
561
+ signer,
562
+ provider,
563
+ contracts: config.contracts,
564
+ gasSettings: config.gasSettings,
565
+ easConfig: config.easConfig,
566
+ requireAttestation,
567
+ stateDirectory: config.stateDirectory,
568
+ });
148
569
 
149
- this.messageSigner = new MessageSigner(this.signer);
570
+ // Initialize async components
571
+ await blockchainRuntime.initialize();
150
572
 
151
- // Initialize QuoteBuilder (AIP-2)
152
- this.quote = new QuoteBuilder(this.signer, this.nonceManager, this.ipfs);
573
+ runtime = blockchainRuntime;
153
574
 
154
- if (config.eas) {
155
- this.eas = new EASHelper(this.signer, config.eas);
575
+ // SECURITY FIX (C-4): Use the runtime's initialized EASHelper so
576
+ // adapters and runtime share the same tracker + verification logic.
577
+ if (config.easConfig) {
578
+ easHelper = blockchainRuntime.getEASHelper();
579
+ }
580
+ break;
581
+ }
582
+
583
+ default:
584
+ throw new Error(
585
+ `Unknown mode: "${config.mode}". ` +
586
+ 'Supported modes: "mock", "testnet", "mainnet"'
587
+ );
588
+ }
156
589
  }
590
+
591
+ // Normalize address to lowercase for consistency
592
+ const normalizedAddress = config.requesterAddress.toLowerCase();
593
+
594
+ const info: ACTPClientInfo = {
595
+ mode: config.mode,
596
+ address: normalizedAddress,
597
+ stateDirectory,
598
+ };
599
+
600
+ // SECURITY FIX (C-4): Pass EASHelper to adapters for attestation verification
601
+ return new ACTPClient(runtime, normalizedAddress, info, easHelper);
157
602
  }
158
603
 
604
+ // ==========================================================================
605
+ // Public Methods
606
+ // ==========================================================================
607
+
159
608
  /**
160
- * Create and initialize ACTPClient (async factory pattern)
161
- * Ensures all async components (EIP-712 domain) are ready before returning
609
+ * Advanced-level API.
610
+ *
611
+ * Provides direct access to the underlying protocol runtime.
612
+ * Use this when you need full control over all parameters.
613
+ *
614
+ * This is the same as accessing `client.runtime` directly.
615
+ *
616
+ * @example
617
+ * ```typescript
618
+ * // Direct runtime access
619
+ * const txId = await client.advanced.createTransaction({
620
+ * provider: '0xProvider',
621
+ * requester: '0xRequester',
622
+ * amount: '100000000', // wei
623
+ * deadline: Math.floor(Date.now() / 1000) + 86400,
624
+ * });
625
+ *
626
+ * // Get transaction details
627
+ * const tx = await client.advanced.getTransaction(txId);
628
+ *
629
+ * // Time manipulation (mock mode only - requires IMockRuntime cast)
630
+ * import { IMockRuntime } from './runtime/IACTPRuntime';
631
+ * if (client.getMode() === 'mock') {
632
+ * (client.advanced as IMockRuntime).time.advanceTime(3600); // Advance 1 hour
633
+ * }
634
+ * ```
162
635
  */
163
- static async create(config: ACTPClientConfig): Promise<ACTPClient> {
164
- const client = new ACTPClient(config);
165
-
166
- // Initialize EIP-712 domain for message signing
167
- await client.messageSigner.initDomain(client.networkConfig.contracts.actpKernel);
168
-
169
- return client;
636
+ get advanced(): IACTPRuntime {
637
+ return this.runtime;
170
638
  }
171
639
 
172
640
  /**
173
- * @deprecated Use ACTPClient.create() instead
174
- * Initialize async components (must be called after construction)
641
+ * Gets the requester's Ethereum address.
642
+ *
643
+ * This is the address used as the "from" address for all transactions
644
+ * created through this client.
645
+ *
646
+ * @returns The requester's Ethereum address (normalized to lowercase)
647
+ *
648
+ * @example
649
+ * ```typescript
650
+ * const address = client.getAddress();
651
+ * console.log('My address:', address);
652
+ * // '0x1111111111111111111111111111111111111111'
653
+ * ```
175
654
  */
176
- async initialize(): Promise<void> {
177
- await this.messageSigner.initDomain(this.networkConfig.contracts.actpKernel);
655
+ getAddress(): string {
656
+ return this.info.address;
178
657
  }
179
658
 
180
659
  /**
181
- * Get signer address
660
+ * Gets the current operating mode.
661
+ *
662
+ * @returns The client's operating mode ('mock', 'testnet', or 'mainnet')
663
+ *
664
+ * @example
665
+ * ```typescript
666
+ * if (client.getMode() === 'mock') {
667
+ * console.log('Running in local development mode');
668
+ * }
669
+ * ```
182
670
  */
183
- async getAddress(): Promise<string> {
184
- return await this.signer.getAddress();
671
+ getMode(): ACTPClientMode {
672
+ return this.info.mode;
185
673
  }
186
674
 
187
675
  /**
188
- * Get network configuration
676
+ * Resets the mock state to default.
677
+ *
678
+ * Only available in mock mode. Clears all transactions, escrows,
679
+ * and accounts, resetting to a fresh state.
680
+ *
681
+ * @throws {Error} If not in mock mode or runtime doesn't support reset
682
+ *
683
+ * @example
684
+ * ```typescript
685
+ * // Reset state between test runs
686
+ * await client.reset();
687
+ * ```
189
688
  */
190
- getNetworkConfig(): NetworkConfig {
191
- return this.networkConfig;
689
+ async reset(): Promise<void> {
690
+ if (this.info.mode !== 'mock') {
691
+ throw new Error(
692
+ `reset() is only available in mock mode. Current mode: "${this.info.mode}"`
693
+ );
694
+ }
695
+
696
+ if (!isMockRuntime(this.runtime)) {
697
+ throw new Error('Runtime does not support reset operation');
698
+ }
699
+
700
+ await this.runtime.reset();
192
701
  }
193
702
 
194
703
  /**
195
- * Get provider
704
+ * Custom JSON serialization to prevent private key exposure.
705
+ *
706
+ * SECURITY FIX (HIGH-4): Prevents accidental private key logging
707
+ * when ACTPClient instance is serialized (e.g., JSON.stringify, console.log).
708
+ *
709
+ * @returns Safe serializable object with sensitive data removed
196
710
  */
197
- getProvider(): JsonRpcProvider {
198
- return this.provider;
711
+ toJSON(): object {
712
+ return {
713
+ mode: this.info.mode,
714
+ address: this.info.address,
715
+ stateDirectory: this.info.stateDirectory,
716
+ isInitialized: true,
717
+ // Explicitly exclude: privateKey, signer, provider internals
718
+ _warning: 'Sensitive data (privateKey, signer) excluded for security',
719
+ };
199
720
  }
200
721
 
201
722
  /**
202
- * Get current block number
723
+ * Custom string representation for debugging.
724
+ *
725
+ * SECURITY FIX (HIGH-4): Prevents private key exposure in logs.
203
726
  */
204
- async getBlockNumber(): Promise<number> {
205
- try {
206
- return await this.provider.getBlockNumber();
207
- } catch (error: any) {
208
- throw new NetworkError(this.networkConfig.name, error.message);
209
- }
727
+ toString(): string {
728
+ return `ACTPClient(mode=${this.info.mode}, address=${this.info.address})`;
210
729
  }
211
730
 
212
731
  /**
213
- * Get gas price (ethers v6: use getFeeData instead)
732
+ * Custom inspect for Node.js util.inspect (console.log).
733
+ *
734
+ * SECURITY FIX (HIGH-4): Prevents private key exposure in console output.
214
735
  */
215
- async getGasPrice() {
216
- try {
217
- const feeData = await this.provider.getFeeData();
218
- return feeData.gasPrice || 0n;
219
- } catch (error: any) {
220
- throw new NetworkError(this.networkConfig.name, error.message);
221
- }
736
+ [Symbol.for('nodejs.util.inspect.custom')](): string {
737
+ return this.toString();
222
738
  }
223
739
 
224
740
  /**
225
- * Release escrow with automatic attestation verification (recommended for security).
226
- *
227
- * SECURITY: This method verifies the attestation belongs to the transaction BEFORE
228
- * releasing escrow. This protects against malicious providers submitting attestations
229
- * from different transactions.
741
+ * Mints USDC tokens to an address.
230
742
  *
231
- * ACTPKernel V1 contract accepts any attestationUID without on-chain validation.
232
- * This SDK-side verification is the recommended protection until V2 adds on-chain checks.
743
+ * Only available in mock mode. Useful for testing scenarios
744
+ * where you need to fund accounts.
233
745
  *
234
- * @param txId - Transaction ID to settle
235
- * @param attestationUID - EAS attestation UID to verify
236
- * @throws {Error} If EAS is not configured (client.eas is undefined)
237
- * @throws {Error} If attestation verification fails (revoked, expired, or txId mismatch)
238
- * @throws {TransactionRevertedError} If escrow release fails
746
+ * @param address - Address to mint tokens to
747
+ * @param amount - Amount to mint (in USDC wei, e.g., '1000000' for 1 USDC)
748
+ * @throws {Error} If not in mock mode or runtime doesn't support mintTokens
239
749
  *
240
750
  * @example
241
751
  * ```typescript
242
- * // Get transaction to find attestation UID
243
- * const tx = await client.kernel.getTransaction(txId);
244
- *
245
- * // Verify and release escrow in one call
246
- * await client.releaseEscrowWithVerification(txId, tx.attestationUID);
752
+ * // Mint 1000 USDC to the requester
753
+ * await client.mintTokens(client.getAddress(), '1000000000'); // 1000 * 10^6
247
754
  * ```
248
755
  */
249
- async releaseEscrowWithVerification(txId: string, attestationUID: string): Promise<void> {
250
- // Ensure EAS is configured
251
- if (!this.eas) {
756
+ async mintTokens(address: string, amount: string): Promise<void> {
757
+ if (this.info.mode !== 'mock') {
252
758
  throw new Error(
253
- 'EAS is not configured. Initialize ACTPClient with eas config or use kernel.releaseEscrow() directly (unsafe)'
759
+ `mintTokens() is only available in mock mode. Current mode: "${this.info.mode}"`
254
760
  );
255
761
  }
256
762
 
257
- // Step 1: Verify attestation belongs to this transaction
258
- await this.eas.verifyDeliveryAttestation(txId, attestationUID);
763
+ if (!isMockRuntime(this.runtime)) {
764
+ throw new Error('Runtime does not support mintTokens operation');
765
+ }
259
766
 
260
- // Step 2: Release escrow (verification passed)
261
- await this.kernel.releaseEscrow(txId);
767
+ await this.runtime.mintTokens(address, amount);
262
768
  }
263
769
 
264
770
  /**
265
- * Validate configuration
771
+ * Gets the USDC balance of an address.
772
+ *
773
+ * @param address - Address to check balance for
774
+ * @returns Promise resolving to balance in USDC wei
775
+ * @throws {Error} If runtime doesn't support getBalance
776
+ *
777
+ * @example
778
+ * ```typescript
779
+ * const balance = await client.getBalance(client.getAddress());
780
+ * console.log('Balance:', balance); // '1000000000' (1000 USDC)
781
+ * ```
266
782
  */
267
- private validateConfig(config: ACTPClientConfig): void {
268
- if (!config.network) {
269
- throw new ValidationError('network', 'Network is required');
783
+ async getBalance(address: string): Promise<string> {
784
+ if (!isMockRuntime(this.runtime)) {
785
+ throw new Error('Runtime does not support getBalance operation');
270
786
  }
271
787
 
272
- if (!config.privateKey && !config.signer && !config.provider) {
273
- throw new ValidationError('auth', 'Provide either privateKey, signer, or provider with signer access');
274
- }
788
+ return this.runtime.getBalance(address);
275
789
  }
276
790
  }