@agirails/sdk 2.0.4 → 2.2.1

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 (201) hide show
  1. package/README.md +536 -87
  2. package/dist/ACTPClient.d.ts +200 -0
  3. package/dist/ACTPClient.d.ts.map +1 -1
  4. package/dist/ACTPClient.js +266 -2
  5. package/dist/ACTPClient.js.map +1 -1
  6. package/dist/abi/ACTPKernel.json +16 -0
  7. package/dist/adapters/AdapterRegistry.d.ts +140 -0
  8. package/dist/adapters/AdapterRegistry.d.ts.map +1 -0
  9. package/dist/adapters/AdapterRegistry.js +166 -0
  10. package/dist/adapters/AdapterRegistry.js.map +1 -0
  11. package/dist/adapters/AdapterRouter.d.ts +165 -0
  12. package/dist/adapters/AdapterRouter.d.ts.map +1 -0
  13. package/dist/adapters/AdapterRouter.js +350 -0
  14. package/dist/adapters/AdapterRouter.js.map +1 -0
  15. package/dist/adapters/BaseAdapter.d.ts +17 -0
  16. package/dist/adapters/BaseAdapter.d.ts.map +1 -1
  17. package/dist/adapters/BaseAdapter.js +21 -0
  18. package/dist/adapters/BaseAdapter.js.map +1 -1
  19. package/dist/adapters/BasicAdapter.d.ts +72 -3
  20. package/dist/adapters/BasicAdapter.d.ts.map +1 -1
  21. package/dist/adapters/BasicAdapter.js +178 -2
  22. package/dist/adapters/BasicAdapter.js.map +1 -1
  23. package/dist/adapters/IAdapter.d.ts +230 -0
  24. package/dist/adapters/IAdapter.d.ts.map +1 -0
  25. package/dist/adapters/IAdapter.js +44 -0
  26. package/dist/adapters/IAdapter.js.map +1 -0
  27. package/dist/adapters/StandardAdapter.d.ts +80 -6
  28. package/dist/adapters/StandardAdapter.d.ts.map +1 -1
  29. package/dist/adapters/StandardAdapter.js +203 -6
  30. package/dist/adapters/StandardAdapter.js.map +1 -1
  31. package/dist/adapters/X402Adapter.d.ts +208 -0
  32. package/dist/adapters/X402Adapter.d.ts.map +1 -0
  33. package/dist/adapters/X402Adapter.js +423 -0
  34. package/dist/adapters/X402Adapter.js.map +1 -0
  35. package/dist/adapters/index.d.ts +8 -0
  36. package/dist/adapters/index.d.ts.map +1 -1
  37. package/dist/adapters/index.js +19 -1
  38. package/dist/adapters/index.js.map +1 -1
  39. package/dist/cli/commands/init.d.ts +4 -0
  40. package/dist/cli/commands/init.d.ts.map +1 -1
  41. package/dist/cli/commands/init.js +146 -4
  42. package/dist/cli/commands/init.js.map +1 -1
  43. package/dist/config/networks.d.ts +9 -0
  44. package/dist/config/networks.d.ts.map +1 -1
  45. package/dist/config/networks.js +27 -12
  46. package/dist/config/networks.js.map +1 -1
  47. package/dist/erc8004/ERC8004Bridge.d.ts +155 -0
  48. package/dist/erc8004/ERC8004Bridge.d.ts.map +1 -0
  49. package/dist/erc8004/ERC8004Bridge.js +325 -0
  50. package/dist/erc8004/ERC8004Bridge.js.map +1 -0
  51. package/dist/erc8004/ReputationReporter.d.ts +223 -0
  52. package/dist/erc8004/ReputationReporter.d.ts.map +1 -0
  53. package/dist/erc8004/ReputationReporter.js +266 -0
  54. package/dist/erc8004/ReputationReporter.js.map +1 -0
  55. package/dist/erc8004/index.d.ts +36 -0
  56. package/dist/erc8004/index.d.ts.map +1 -0
  57. package/dist/erc8004/index.js +46 -0
  58. package/dist/erc8004/index.js.map +1 -0
  59. package/dist/index.d.ts +11 -1
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +51 -2
  62. package/dist/index.js.map +1 -1
  63. package/dist/level0/provide.d.ts.map +1 -1
  64. package/dist/level0/provide.js +2 -1
  65. package/dist/level0/provide.js.map +1 -1
  66. package/dist/level1/Agent.d.ts.map +1 -1
  67. package/dist/level1/Agent.js +11 -3
  68. package/dist/level1/Agent.js.map +1 -1
  69. package/dist/protocol/ACTPKernel.d.ts +1 -1
  70. package/dist/protocol/ACTPKernel.d.ts.map +1 -1
  71. package/dist/protocol/ACTPKernel.js +23 -12
  72. package/dist/protocol/ACTPKernel.js.map +1 -1
  73. package/dist/protocol/DIDResolver.js +1 -1
  74. package/dist/protocol/DIDResolver.js.map +1 -1
  75. package/dist/protocol/EASHelper.d.ts.map +1 -1
  76. package/dist/protocol/EASHelper.js +2 -3
  77. package/dist/protocol/EASHelper.js.map +1 -1
  78. package/dist/protocol/MessageSigner.d.ts.map +1 -1
  79. package/dist/protocol/MessageSigner.js +8 -8
  80. package/dist/protocol/MessageSigner.js.map +1 -1
  81. package/dist/runtime/BlockchainRuntime.d.ts +7 -0
  82. package/dist/runtime/BlockchainRuntime.d.ts.map +1 -1
  83. package/dist/runtime/BlockchainRuntime.js +40 -22
  84. package/dist/runtime/BlockchainRuntime.js.map +1 -1
  85. package/dist/runtime/IACTPRuntime.d.ts +21 -0
  86. package/dist/runtime/IACTPRuntime.d.ts.map +1 -1
  87. package/dist/runtime/MockRuntime.d.ts +19 -0
  88. package/dist/runtime/MockRuntime.d.ts.map +1 -1
  89. package/dist/runtime/MockRuntime.js +56 -4
  90. package/dist/runtime/MockRuntime.js.map +1 -1
  91. package/dist/runtime/types/MockState.d.ts +11 -2
  92. package/dist/runtime/types/MockState.d.ts.map +1 -1
  93. package/dist/runtime/types/MockState.js.map +1 -1
  94. package/dist/storage/ArchiveBundleBuilder.d.ts +150 -0
  95. package/dist/storage/ArchiveBundleBuilder.d.ts.map +1 -0
  96. package/dist/storage/ArchiveBundleBuilder.js +468 -0
  97. package/dist/storage/ArchiveBundleBuilder.js.map +1 -0
  98. package/dist/storage/ArweaveClient.d.ts +271 -0
  99. package/dist/storage/ArweaveClient.d.ts.map +1 -0
  100. package/dist/storage/ArweaveClient.js +761 -0
  101. package/dist/storage/ArweaveClient.js.map +1 -0
  102. package/dist/storage/FilebaseClient.d.ts +193 -0
  103. package/dist/storage/FilebaseClient.d.ts.map +1 -0
  104. package/dist/storage/FilebaseClient.js +643 -0
  105. package/dist/storage/FilebaseClient.js.map +1 -0
  106. package/dist/storage/index.d.ts +47 -0
  107. package/dist/storage/index.d.ts.map +1 -0
  108. package/dist/storage/index.js +64 -0
  109. package/dist/storage/index.js.map +1 -0
  110. package/dist/storage/types.d.ts +291 -0
  111. package/dist/storage/types.d.ts.map +1 -0
  112. package/dist/storage/types.js +18 -0
  113. package/dist/storage/types.js.map +1 -0
  114. package/dist/types/adapter.d.ts +359 -0
  115. package/dist/types/adapter.d.ts.map +1 -0
  116. package/dist/types/adapter.js +115 -0
  117. package/dist/types/adapter.js.map +1 -0
  118. package/dist/types/erc8004.d.ts +184 -0
  119. package/dist/types/erc8004.d.ts.map +1 -0
  120. package/dist/types/erc8004.js +132 -0
  121. package/dist/types/erc8004.js.map +1 -0
  122. package/dist/types/index.d.ts +3 -0
  123. package/dist/types/index.d.ts.map +1 -1
  124. package/dist/types/index.js +3 -0
  125. package/dist/types/index.js.map +1 -1
  126. package/dist/types/state.d.ts +5 -4
  127. package/dist/types/state.d.ts.map +1 -1
  128. package/dist/types/state.js +10 -9
  129. package/dist/types/state.js.map +1 -1
  130. package/dist/types/transaction.d.ts +12 -0
  131. package/dist/types/transaction.d.ts.map +1 -1
  132. package/dist/types/x402.d.ts +162 -0
  133. package/dist/types/x402.d.ts.map +1 -0
  134. package/dist/types/x402.js +162 -0
  135. package/dist/types/x402.js.map +1 -0
  136. package/dist/utils/IPFSClient.d.ts.map +1 -1
  137. package/dist/utils/IPFSClient.js +5 -2
  138. package/dist/utils/IPFSClient.js.map +1 -1
  139. package/dist/utils/NonceManager.d.ts.map +1 -1
  140. package/dist/utils/NonceManager.js +3 -2
  141. package/dist/utils/NonceManager.js.map +1 -1
  142. package/dist/utils/UsedAttestationTracker.d.ts.map +1 -1
  143. package/dist/utils/UsedAttestationTracker.js +3 -3
  144. package/dist/utils/UsedAttestationTracker.js.map +1 -1
  145. package/dist/utils/circuitBreaker.d.ts +136 -0
  146. package/dist/utils/circuitBreaker.d.ts.map +1 -0
  147. package/dist/utils/circuitBreaker.js +253 -0
  148. package/dist/utils/circuitBreaker.js.map +1 -0
  149. package/dist/utils/retry.d.ts +120 -0
  150. package/dist/utils/retry.d.ts.map +1 -0
  151. package/dist/utils/retry.js +260 -0
  152. package/dist/utils/retry.js.map +1 -0
  153. package/dist/utils/validation.d.ts +100 -0
  154. package/dist/utils/validation.d.ts.map +1 -1
  155. package/dist/utils/validation.js +248 -1
  156. package/dist/utils/validation.js.map +1 -1
  157. package/package.json +16 -3
  158. package/src/ACTPClient.ts +318 -2
  159. package/src/abi/ACTPKernel.json +16 -0
  160. package/src/adapters/AdapterRegistry.ts +173 -0
  161. package/src/adapters/AdapterRouter.ts +417 -0
  162. package/src/adapters/BaseAdapter.ts +25 -0
  163. package/src/adapters/BasicAdapter.ts +210 -3
  164. package/src/adapters/IAdapter.ts +292 -0
  165. package/src/adapters/StandardAdapter.ts +246 -7
  166. package/src/adapters/X402Adapter.ts +653 -0
  167. package/src/adapters/index.ts +27 -0
  168. package/src/cli/commands/init.ts +166 -3
  169. package/src/config/networks.ts +36 -12
  170. package/src/erc8004/ERC8004Bridge.ts +461 -0
  171. package/src/erc8004/ReputationReporter.ts +472 -0
  172. package/src/erc8004/index.ts +61 -0
  173. package/src/index.ts +97 -0
  174. package/src/level0/provide.ts +2 -1
  175. package/src/level1/Agent.ts +13 -3
  176. package/src/protocol/ACTPKernel.ts +33 -12
  177. package/src/protocol/DIDResolver.ts +1 -1
  178. package/src/protocol/EASHelper.ts +2 -5
  179. package/src/protocol/MessageSigner.ts +8 -14
  180. package/src/runtime/BlockchainRuntime.ts +41 -45
  181. package/src/runtime/IACTPRuntime.ts +22 -0
  182. package/src/runtime/MockRuntime.ts +58 -4
  183. package/src/runtime/types/MockState.ts +12 -2
  184. package/src/storage/ArchiveBundleBuilder.ts +563 -0
  185. package/src/storage/ArweaveClient.ts +945 -0
  186. package/src/storage/FilebaseClient.ts +790 -0
  187. package/src/storage/index.ts +96 -0
  188. package/src/storage/types.ts +348 -0
  189. package/src/types/adapter.ts +296 -0
  190. package/src/types/erc8004.ts +293 -0
  191. package/src/types/index.ts +3 -0
  192. package/src/types/state.ts +10 -9
  193. package/src/types/transaction.ts +12 -0
  194. package/src/types/x402.ts +219 -0
  195. package/src/utils/IPFSClient.ts +5 -4
  196. package/src/utils/NonceManager.ts +3 -2
  197. package/src/utils/UsedAttestationTracker.ts +3 -5
  198. package/src/utils/circuitBreaker.ts +324 -0
  199. package/src/utils/fsSafe.ts +5 -0
  200. package/src/utils/retry.ts +365 -0
  201. package/src/utils/validation.ts +295 -1
@@ -161,7 +161,7 @@ export class ACTPKernel {
161
161
  * Create a new transaction
162
162
  * Reference: Yellow Paper §3.4.1
163
163
  *
164
- * Contract signature: createTransaction(provider, requester, amount, deadline, disputeWindow, serviceHash)
164
+ * Contract signature: createTransaction(provider, requester, amount, deadline, disputeWindow, serviceHash, agentId)
165
165
  * Returns: bytes32 transactionId (generated by contract)
166
166
  */
167
167
  async createTransaction(params: CreateTransactionParams): Promise<string> {
@@ -171,7 +171,8 @@ export class ACTPKernel {
171
171
  amount,
172
172
  deadline,
173
173
  disputeWindow,
174
- metadata = '0x0000000000000000000000000000000000000000000000000000000000000000'
174
+ metadata = '0x0000000000000000000000000000000000000000000000000000000000000000',
175
+ agentId = '0' // Default to 0 (not an ERC-8004 agent)
175
176
  } = params;
176
177
 
177
178
  // Input validation
@@ -185,14 +186,15 @@ export class ACTPKernel {
185
186
  // ethers v6: use getFunction() for typed access
186
187
  const createTxFunc = this.contract.getFunction('createTransaction');
187
188
 
188
- // Contract signature: createTransaction(provider, requester, amount, deadline, disputeWindow, serviceHash)
189
+ // Contract signature: createTransaction(provider, requester, amount, deadline, disputeWindow, serviceHash, agentId)
189
190
  const estimatedGas = await createTxFunc.estimateGas(
190
191
  provider,
191
192
  requester,
192
193
  amount,
193
194
  deadline,
194
195
  disputeWindow,
195
- metadata // serviceHash
196
+ metadata, // serviceHash
197
+ BigInt(agentId) // ERC-8004 agent ID (0 = not an agent)
196
198
  );
197
199
 
198
200
  // Build tx options with gas settings (15% buffer for simple state initialization)
@@ -207,6 +209,7 @@ export class ACTPKernel {
207
209
  deadline,
208
210
  disputeWindow,
209
211
  metadata, // serviceHash
212
+ BigInt(agentId), // ERC-8004 agent ID
210
213
  txOptions
211
214
  );
212
215
 
@@ -549,6 +552,11 @@ export class ACTPKernel {
549
552
  throw new TransactionNotFoundError(txId);
550
553
  }
551
554
 
555
+ // Parse agentId - convert BigInt to string, 0n means "not an ERC-8004 agent"
556
+ const agentIdValue = typeof txData.agentId === 'bigint'
557
+ ? txData.agentId.toString()
558
+ : txData.agentId?.toString();
559
+
552
560
  return {
553
561
  txId: txData.transactionId,
554
562
  requester: txData.requester,
@@ -568,7 +576,9 @@ export class ACTPKernel {
568
576
  platformFeeBpsLocked:
569
577
  typeof txData.platformFeeBpsLocked === 'bigint'
570
578
  ? Number(txData.platformFeeBpsLocked)
571
- : txData.platformFeeBpsLocked
579
+ : txData.platformFeeBpsLocked,
580
+ // ERC-8004 agent ID (undefined or '0' means not an ERC-8004 agent)
581
+ agentId: agentIdValue && agentIdValue !== '0' ? agentIdValue : undefined
572
582
  };
573
583
  }
574
584
 
@@ -602,7 +612,15 @@ export class ACTPKernel {
602
612
  * Estimate gas for transaction creation
603
613
  */
604
614
  async estimateCreateTransaction(params: CreateTransactionParams): Promise<bigint> {
605
- const { provider, requester, amount, deadline, disputeWindow, metadata = '0x0000000000000000000000000000000000000000000000000000000000000000' } = params;
615
+ const {
616
+ provider,
617
+ requester,
618
+ amount,
619
+ deadline,
620
+ disputeWindow,
621
+ metadata = '0x0000000000000000000000000000000000000000000000000000000000000000',
622
+ agentId = '0'
623
+ } = params;
606
624
 
607
625
  // ethers v6: use getFunction()
608
626
  const createTxFunc = this.contract.getFunction('createTransaction');
@@ -612,7 +630,8 @@ export class ACTPKernel {
612
630
  amount,
613
631
  deadline,
614
632
  disputeWindow,
615
- metadata
633
+ metadata,
634
+ BigInt(agentId)
616
635
  );
617
636
  }
618
637
 
@@ -681,16 +700,18 @@ export class ACTPKernel {
681
700
  validateAddress(mediator, 'mediator');
682
701
  }
683
702
 
684
- // Encode resolution proof (128 bytes: 3x uint256 + address)
685
- // Kernel contract will decode this in _decodeResolutionProof and disburse funds
703
+ // Encode resolution proof (128 bytes: 2x uint256 + address + uint256)
704
+ // AUDIT FIX (2026-02): Contract expects: (uint256, uint256, address, uint256)
705
+ // = [requesterAmount, providerAmount, mediator, mediatorAmount]
706
+ // See ACTPKernel.sol _decodeResolutionProof() line 654-655
686
707
  const abiCoder = AbiCoder.defaultAbiCoder();
687
708
  const proofData = abiCoder.encode(
688
- ['uint256', 'uint256', 'uint256', 'address'],
709
+ ['uint256', 'uint256', 'address', 'uint256'],
689
710
  [
690
711
  requesterAmount,
691
712
  providerAmount,
692
- mediatorAmount,
693
- mediator || ethers.getAddress('0x0000000000000000000000000000000000000000')
713
+ mediator || ethers.getAddress('0x0000000000000000000000000000000000000000'),
714
+ mediatorAmount
694
715
  ]
695
716
  );
696
717
 
@@ -115,7 +115,7 @@ export class DIDResolver {
115
115
  network: config.network,
116
116
  chainId: config.chainId || networkConfig.chainId,
117
117
  rpcUrl: config.rpcUrl || networkConfig.rpcUrl,
118
- registryAddress: config.registryAddress || networkConfig.contracts.agentRegistry || ''
118
+ registryAddress: config.registryAddress || networkConfig.contracts.identityRegistry || ''
119
119
  };
120
120
  }
121
121
 
@@ -6,6 +6,7 @@ import {
6
6
  IUsedAttestationTracker,
7
7
  InMemoryUsedAttestationTracker
8
8
  } from '../utils/UsedAttestationTracker';
9
+ import { sdkLogger } from '../utils/Logger';
9
10
 
10
11
  export interface EASConfig {
11
12
  contractAddress: string;
@@ -65,11 +66,7 @@ export class EASHelper {
65
66
  //
66
67
  // Without persistence, attestation replay protection is lost on process restart,
67
68
  // allowing potential double-spend attacks.
68
- console.warn(
69
- '[SECURITY WARNING] EASHelper: Using in-memory attestation tracker. ' +
70
- 'Replay protection will be lost on process restart. ' +
71
- 'For production, provide FileBasedUsedAttestationTracker for persistence.'
72
- );
69
+ sdkLogger.warn('Using in-memory attestation tracker - replay protection lost on restart (use FileBasedUsedAttestationTracker for production)');
73
70
  }
74
71
  this.attestationTracker = attestationTracker || new InMemoryUsedAttestationTracker();
75
72
  }
@@ -10,6 +10,7 @@ import {
10
10
  deliveryProofDataFromProof
11
11
  } from '../types/eip712';
12
12
  import { IReceivedNonceTracker } from '../utils/ReceivedNonceTracker';
13
+ import { sdkLogger } from '../utils/Logger';
13
14
 
14
15
  // Legacy generic ACTP message types moved to types/eip712.ts
15
16
 
@@ -175,22 +176,14 @@ export class MessageSigner {
175
176
  const nonceValue = BigInt(nonce);
176
177
  if (nonceValue < 0xFFFFFFFFn) {
177
178
  // Nonce is suspiciously small (< 4 billion = likely sequential)
178
- console.warn(
179
- `[SECURITY WARNING] Nonce ${nonce} appears to be sequential (value < 2^32). ` +
180
- `This makes replay attacks easier. ` +
181
- `Use SecureNonce.generateSecureNonce() for cryptographically secure random nonces.`
182
- );
179
+ sdkLogger.warn('Nonce appears sequential - use SecureNonce.generateSecureNonce()', { nonce });
183
180
  }
184
181
 
185
182
  // Check if nonce has all same digits (e.g., 0x111...111 or 0x000...000)
186
183
  const hexDigits = nonce.slice(2); // Remove '0x'
187
184
  const firstDigit = hexDigits[0];
188
185
  if (hexDigits.split('').every(d => d === firstDigit)) {
189
- console.warn(
190
- `[SECURITY WARNING] Nonce ${nonce} has low entropy (all digits are '${firstDigit}'). ` +
191
- `This is NOT cryptographically secure. ` +
192
- `Use SecureNonce.generateSecureNonce() instead.`
193
- );
186
+ sdkLogger.warn('Nonce has low entropy - use SecureNonce.generateSecureNonce()', { nonce, repeatedDigit: firstDigit });
194
187
  }
195
188
 
196
189
  // Generic ACTPMessage with payload encoding (backward compatible)
@@ -463,10 +456,11 @@ export class MessageSigner {
463
456
  // This prevents cross-chain replay attacks where a message signed for one chain
464
457
  // is replayed on another. For now, we just extract the address but log a warning.
465
458
  if (this.domain && this.domain.chainId !== chainId) {
466
- console.warn(
467
- `[SECURITY WARNING] DID chainId (${chainId}) does not match domain chainId (${this.domain.chainId}). ` +
468
- `This could indicate a cross-chain replay attempt. DID: ${did}`
469
- );
459
+ sdkLogger.warn('DID chainId mismatch - potential cross-chain replay attempt', {
460
+ didChainId: chainId,
461
+ domainChainId: this.domain.chainId,
462
+ did,
463
+ });
470
464
  }
471
465
 
472
466
  return address;
@@ -28,6 +28,7 @@ import { ValidationError } from '../errors';
28
28
  import { ServiceHash, DisputeWindow } from '../utils/Helpers';
29
29
  import { IUsedAttestationTracker, createUsedAttestationTracker } from '../utils/UsedAttestationTracker';
30
30
  import { IReceivedNonceTracker, createReceivedNonceTracker } from '../utils/ReceivedNonceTracker';
31
+ import { sdkLogger } from '../utils/Logger';
31
32
 
32
33
  /**
33
34
  * Configuration for BlockchainRuntime
@@ -217,20 +218,17 @@ export class BlockchainRuntime implements IACTPRuntime {
217
218
  );
218
219
  }
219
220
 
220
- console.info(
221
- `BlockchainRuntime: Connected to ${this.networkConfig.name} (chainId: ${connectedChainId})`
222
- );
221
+ sdkLogger.info(`Connected to ${this.networkConfig.name}`, { chainId: connectedChainId });
223
222
  } catch (error) {
224
223
  if (error instanceof Error && error.message.includes('Network mismatch')) {
225
224
  throw error; // Re-throw our validation error
226
225
  }
227
226
  // For other errors (e.g., network issues), log warning but continue
228
227
  // This allows initialization to proceed even if network check fails temporarily
229
- console.warn(
230
- `BlockchainRuntime: Could not verify network chainId. ` +
231
- `Error: ${error instanceof Error ? error.message : String(error)}. ` +
232
- `Proceeding with expected chainId ${this.networkConfig.chainId}.`
233
- );
228
+ sdkLogger.warn('Could not verify network chainId, proceeding with expected value', {
229
+ error: error instanceof Error ? error.message : String(error),
230
+ expectedChainId: this.networkConfig.chainId,
231
+ });
234
232
  }
235
233
 
236
234
  // SECURITY FIX (H-4): Use factory pattern to guarantee domain initialization
@@ -254,10 +252,7 @@ export class BlockchainRuntime implements IACTPRuntime {
254
252
  this.attestationTracker
255
253
  );
256
254
  } else if (this.requireAttestation) {
257
- console.warn(
258
- '[SECURITY WARNING] BlockchainRuntime: requireAttestation is true but no EAS config provided. ' +
259
- 'Attestation verification will fail. Please provide easConfig in BlockchainRuntimeConfig.'
260
- );
255
+ sdkLogger.warn('requireAttestation is true but no EAS config provided - attestation verification will fail');
261
256
  }
262
257
  }
263
258
 
@@ -319,11 +314,12 @@ export class BlockchainRuntime implements IACTPRuntime {
319
314
  this.reconnectAttempts = attempt + 1;
320
315
  const delay = this.baseReconnectDelay * Math.pow(2, attempt);
321
316
 
322
- console.warn(
323
- `Provider connection lost. Attempting reconnection ${attempt + 1}/${this.maxReconnectAttempts} ` +
324
- `after ${delay}ms delay... ` +
325
- `(Error: ${error instanceof Error ? error.message : String(error)})`
326
- );
317
+ sdkLogger.warn('Provider connection lost, attempting reconnection', {
318
+ attempt: attempt + 1,
319
+ maxAttempts: this.maxReconnectAttempts,
320
+ delayMs: delay,
321
+ error: error instanceof Error ? error.message : String(error),
322
+ });
327
323
 
328
324
  // Wait before next attempt
329
325
  await new Promise(resolve => setTimeout(resolve, delay));
@@ -399,6 +395,8 @@ export class BlockchainRuntime implements IACTPRuntime {
399
395
  // SECURITY FIX (CRITICAL): serviceDescription should be a bytes32 hash
400
396
  // If caller passes raw string, it will fail on-chain. Basic/Standard API now hash before calling.
401
397
  metadata: this.validateServiceHash(params.serviceDescription),
398
+ // ERC-8004 agent ID - pass through if provided (see ADR-001)
399
+ agentId: params.agentId,
402
400
  });
403
401
 
404
402
  return txId;
@@ -543,7 +541,11 @@ export class BlockchainRuntime implements IACTPRuntime {
543
541
  escrowId: tx.escrowId,
544
542
  createdAt: Number(tx.createdAt),
545
543
  updatedAt: Number(tx.updatedAt),
546
- completedAt: 0, // V2: Track via DELIVERED event timestamp
544
+ // LIMITATION (V2): completedAt requires event indexing to fetch DELIVERED event timestamp.
545
+ // Currently 0, which means SDK-side dispute window check in releaseEscrow() is bypassed.
546
+ // On-chain contract still enforces dispute window correctly via _validateSettlementConditions().
547
+ // V2 will implement EventMonitor to track this properly.
548
+ completedAt: 0,
547
549
  serviceDescription: '', // V2: Decode from on-chain serviceHash
548
550
  deliveryProof: '', // V2: Fetch from EAS attestation
549
551
  events: [], // V2: Populate via EventMonitor.getTransactionEvents()
@@ -562,9 +564,7 @@ export class BlockchainRuntime implements IACTPRuntime {
562
564
  async getAllTransactions(): Promise<MockTransaction[]> {
563
565
  // V2: Implement event-based transaction indexing via EventMonitor
564
566
  // For now, return empty array as this requires off-chain indexer
565
- console.warn(
566
- 'getAllTransactions() not fully implemented for BlockchainRuntime. Use EventMonitor for event-based queries.'
567
- );
567
+ sdkLogger.warn('getAllTransactions() not implemented - use EventMonitor for event-based queries');
568
568
  return [];
569
569
  }
570
570
 
@@ -604,10 +604,7 @@ export class BlockchainRuntime implements IACTPRuntime {
604
604
  if (legacyMatch) {
605
605
  // Legacy SDK format - extract txId
606
606
  txId = legacyMatch[1];
607
- console.warn(
608
- `BlockchainRuntime.releaseEscrow: Using legacy escrowId format. ` +
609
- `Please update to use txId directly as escrowId.`
610
- );
607
+ sdkLogger.warn('Using legacy escrowId format - please update to use txId directly as escrowId');
611
608
  } else {
612
609
  // Standard: escrowId = txId
613
610
  txId = escrowId;
@@ -658,9 +655,7 @@ export class BlockchainRuntime implements IACTPRuntime {
658
655
  // Verify attestation is valid for this transaction
659
656
  try {
660
657
  await this.easHelper.verifyAndRecordForRelease(txId, attestationUID);
661
- console.info(
662
- `BlockchainRuntime.releaseEscrow: Attestation ${attestationUID} verified for transaction ${txId}.`
663
- );
658
+ sdkLogger.info('Attestation verified for release', { txId, attestationUID });
664
659
  } catch (error) {
665
660
  throw new Error(
666
661
  `Cannot release escrow: attestation verification failed for transaction ${txId}. ` +
@@ -671,21 +666,16 @@ export class BlockchainRuntime implements IACTPRuntime {
671
666
  // Even if not required, verify attestation if provided (best effort)
672
667
  try {
673
668
  await this.easHelper.verifyAndRecordForRelease(txId, attestationUID);
674
- console.info(
675
- `BlockchainRuntime.releaseEscrow: Attestation ${attestationUID} verified (optional) for transaction ${txId}.`
676
- );
669
+ sdkLogger.info('Attestation verified (optional)', { txId, attestationUID });
677
670
  } catch (error) {
678
- console.warn(
679
- `BlockchainRuntime.releaseEscrow: Attestation verification failed but not required. ` +
680
- `Proceeding with release. Error: ${error instanceof Error ? error.message : String(error)}`
681
- );
671
+ sdkLogger.warn('Attestation verification failed but not required, proceeding', {
672
+ txId,
673
+ error: error instanceof Error ? error.message : String(error),
674
+ });
682
675
  }
683
676
  } else {
684
677
  // No attestation verification
685
- console.info(
686
- `BlockchainRuntime.releaseEscrow: Settling transaction ${txId}. ` +
687
- `Note: Set requireAttestation=true and provide easConfig for additional security.`
688
- );
678
+ sdkLogger.info('Settling transaction without attestation verification', { txId });
689
679
  }
690
680
 
691
681
  // SECURITY FIX (SETTLEMENT-FLOW): Use transitionState(SETTLED) instead of releaseEscrow()
@@ -731,7 +721,7 @@ export class BlockchainRuntime implements IACTPRuntime {
731
721
  return '0';
732
722
  } catch (error) {
733
723
  // If query fails, return 0
734
- console.warn('BlockchainRuntime.getEscrowBalance: Query failed', error);
724
+ sdkLogger.warn('getEscrowBalance query failed', { error: error instanceof Error ? error.message : String(error) });
735
725
  return '0';
736
726
  }
737
727
  }
@@ -773,6 +763,16 @@ export class BlockchainRuntime implements IACTPRuntime {
773
763
  return this.networkConfig;
774
764
  }
775
765
 
766
+ /**
767
+ * Maximum transaction amount in USDC (human-readable).
768
+ *
769
+ * SECURITY: Limits exposure on unaudited mainnet contracts.
770
+ * Returns undefined if no limit (testnet).
771
+ */
772
+ get maxTransactionAmount(): number | undefined {
773
+ return this.networkConfig.maxTransactionAmount;
774
+ }
775
+
776
776
  /**
777
777
  * Get ACTPKernel instance (for advanced usage)
778
778
  */
@@ -869,11 +869,7 @@ export class BlockchainRuntime implements IACTPRuntime {
869
869
 
870
870
  // SECURITY FIX (CRITICAL): If it's a raw string (legacy format), hash it
871
871
  // This ensures on-chain compatibility with the contract's bytes32 expectation
872
- console.warn(
873
- 'BlockchainRuntime: serviceDescription is not a valid bytes32 hash. ' +
874
- 'Hashing it now. For best practice, use ServiceHash.hash() before calling createTransaction.'
875
- );
876
-
872
+ sdkLogger.warn('serviceDescription is not a valid bytes32 hash - hashing now (use ServiceHash.hash() for best practice)');
877
873
  return keccak256(toUtf8Bytes(serviceDescription));
878
874
  }
879
875
 
@@ -29,6 +29,12 @@ export interface CreateTransactionParams {
29
29
  disputeWindow?: number;
30
30
  /** Service description or metadata hash */
31
31
  serviceDescription?: string;
32
+ /**
33
+ * ERC-8004 agent ID (optional).
34
+ * If set, enables reputation reporting after settlement.
35
+ * Stored in transaction for later use by ReputationReporter.
36
+ */
37
+ agentId?: string;
32
38
  }
33
39
 
34
40
  /**
@@ -199,6 +205,22 @@ export interface IACTPRuntime {
199
205
  /** Get current timestamp in seconds */
200
206
  now(): number;
201
207
  };
208
+
209
+ /**
210
+ * Maximum transaction amount in USDC (human-readable, e.g., 100 = $100).
211
+ *
212
+ * SECURITY: Limits exposure on unaudited contracts.
213
+ * Returns undefined if no limit is enforced (testnet/mock mode).
214
+ *
215
+ * @example
216
+ * ```typescript
217
+ * const limit = runtime.maxTransactionAmount;
218
+ * if (limit && amount > limit) {
219
+ * throw new Error(`Amount exceeds limit of $${limit}`);
220
+ * }
221
+ * ```
222
+ */
223
+ maxTransactionAmount?: number;
202
224
  }
203
225
 
204
226
  /**
@@ -199,23 +199,27 @@ export class DisputeWindowActiveError extends Error {
199
199
  /**
200
200
  * Valid state transitions for the ACTP 8-state machine.
201
201
  *
202
+ * AUDIT FIX (2026-02): Synced with on-chain ACTPKernel contract.
203
+ *
202
204
  * State machine:
203
205
  * - INITIATED -> QUOTED (optional), COMMITTED, CANCELLED
204
206
  * - QUOTED -> COMMITTED, CANCELLED
205
- * - COMMITTED -> IN_PROGRESS (optional), DELIVERED, CANCELLED
207
+ * - COMMITTED -> IN_PROGRESS, CANCELLED (cannot skip to DELIVERED)
206
208
  * - IN_PROGRESS -> DELIVERED, CANCELLED
207
209
  * - DELIVERED -> SETTLED, DISPUTED
208
- * - DISPUTED -> SETTLED
210
+ * - DISPUTED -> SETTLED, CANCELLED (admin/pauser emergency)
209
211
  * - SETTLED (terminal)
210
212
  * - CANCELLED (terminal)
211
213
  */
212
214
  const VALID_TRANSITIONS: Record<TransactionState, TransactionState[]> = {
213
215
  INITIATED: ['QUOTED', 'COMMITTED', 'CANCELLED'],
214
216
  QUOTED: ['COMMITTED', 'CANCELLED'],
215
- COMMITTED: ['IN_PROGRESS', 'DELIVERED', 'CANCELLED'],
217
+ // AUDIT FIX: Cannot skip IN_PROGRESS - must transition through it
218
+ COMMITTED: ['IN_PROGRESS', 'CANCELLED'],
216
219
  IN_PROGRESS: ['DELIVERED', 'CANCELLED'],
217
220
  DELIVERED: ['SETTLED', 'DISPUTED'],
218
- DISPUTED: ['SETTLED'],
221
+ // AUDIT FIX: DISPUTED can also be CANCELLED by admin/pauser
222
+ DISPUTED: ['SETTLED', 'CANCELLED'],
219
223
  SETTLED: [], // Terminal state
220
224
  CANCELLED: [], // Terminal state
221
225
  };
@@ -337,6 +341,14 @@ export class MockRuntime implements IACTPRuntime {
337
341
  };
338
342
  }
339
343
 
344
+ /**
345
+ * Maximum transaction amount - no limit in mock mode.
346
+ *
347
+ * Mock mode is for testing, so we don't enforce limits.
348
+ * Real blockchain runtimes may have limits for security.
349
+ */
350
+ readonly maxTransactionAmount: number | undefined = undefined;
351
+
340
352
  /**
341
353
  * Load events from persisted state file.
342
354
  *
@@ -439,6 +451,7 @@ export class MockRuntime implements IACTPRuntime {
439
451
  serviceDescription: params.serviceDescription ?? '',
440
452
  deliveryProof: null,
441
453
  events: [],
454
+ agentId: params.agentId,
442
455
  };
443
456
 
444
457
  // Record event
@@ -452,6 +465,7 @@ export class MockRuntime implements IACTPRuntime {
452
465
  provider: params.provider,
453
466
  amount: params.amount,
454
467
  deadline: params.deadline,
468
+ agentId: params.agentId,
455
469
  },
456
470
  };
457
471
 
@@ -468,14 +482,54 @@ export class MockRuntime implements IACTPRuntime {
468
482
  /**
469
483
  * Gets a transaction by ID.
470
484
  *
485
+ * AUTO-RELEASE: If transaction is DELIVERED and dispute window has passed,
486
+ * automatically settles the transaction (lazy auto-release).
487
+ *
471
488
  * @param txId - Transaction ID
472
489
  * @returns Promise resolving to the transaction or null if not found
473
490
  */
474
491
  async getTransaction(txId: string): Promise<MockTransaction | null> {
492
+ // First, check if auto-settle is needed
493
+ await this.autoSettleIfReady(txId);
494
+
495
+ // Then return the (possibly updated) transaction
475
496
  const state = this.stateManager.loadState();
476
497
  return state.transactions[txId] ?? null;
477
498
  }
478
499
 
500
+ /**
501
+ * Auto-settle a transaction if dispute window has passed.
502
+ *
503
+ * This implements "lazy auto-release" - when anyone checks a transaction
504
+ * that is DELIVERED with expired dispute window, it automatically settles.
505
+ *
506
+ * @param txId - Transaction ID to check
507
+ */
508
+ private async autoSettleIfReady(txId: string): Promise<void> {
509
+ const state = this.stateManager.loadState();
510
+ const tx = state.transactions[txId];
511
+
512
+ if (!tx) return;
513
+ if (tx.state !== 'DELIVERED') return;
514
+ if (tx.completedAt === null) return;
515
+
516
+ const currentTime = state.blockchain.currentTime;
517
+ const disputeWindowEnd = tx.completedAt + tx.disputeWindow;
518
+
519
+ // Dispute window still active - don't auto-settle
520
+ if (currentTime < disputeWindowEnd) return;
521
+
522
+ // Dispute window passed - auto-settle!
523
+ // Find the escrow and release it
524
+ if (tx.escrowId) {
525
+ try {
526
+ await this.releaseEscrow(tx.escrowId);
527
+ } catch {
528
+ // Already settled or other issue - ignore
529
+ }
530
+ }
531
+ }
532
+
479
533
  /**
480
534
  * Gets all transactions.
481
535
  *
@@ -14,10 +14,13 @@
14
14
  * ACTP Transaction State enum matching the smart contract states.
15
15
  *
16
16
  * State machine:
17
- * - INITIATED (0) -> QUOTED (1, optional) -> COMMITTED (2) -> IN_PROGRESS (3, optional)
17
+ * - INITIATED (0) -> QUOTED (1, optional) -> COMMITTED (2) -> IN_PROGRESS (3, mandatory)
18
18
  * -> DELIVERED (4) -> SETTLED (5)
19
- * - Dispute path: DELIVERED -> DISPUTED (6) -> SETTLED
19
+ * - Dispute path: DELIVERED -> DISPUTED (6) -> SETTLED or CANCELLED (admin)
20
20
  * - Cancel path: Any pre-DELIVERED state -> CANCELLED (7)
21
+ *
22
+ * AUDIT FIX (2026-02): IN_PROGRESS is now mandatory per contract. Direct
23
+ * COMMITTED -> DELIVERED transitions are rejected on-chain.
21
24
  */
22
25
  export type TransactionState =
23
26
  | 'INITIATED'
@@ -111,6 +114,13 @@ export interface MockTransaction {
111
114
 
112
115
  /** List of events emitted during transaction lifecycle */
113
116
  events: MockEvent[];
117
+
118
+ /**
119
+ * ERC-8004 agent ID (optional).
120
+ * If set, can be used for reputation reporting after settlement.
121
+ * Stored as string representation of uint256.
122
+ */
123
+ agentId?: string;
114
124
  }
115
125
 
116
126
  /**