@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.
- package/README.md +536 -87
- package/dist/ACTPClient.d.ts +200 -0
- package/dist/ACTPClient.d.ts.map +1 -1
- package/dist/ACTPClient.js +266 -2
- package/dist/ACTPClient.js.map +1 -1
- package/dist/abi/ACTPKernel.json +16 -0
- package/dist/adapters/AdapterRegistry.d.ts +140 -0
- package/dist/adapters/AdapterRegistry.d.ts.map +1 -0
- package/dist/adapters/AdapterRegistry.js +166 -0
- package/dist/adapters/AdapterRegistry.js.map +1 -0
- package/dist/adapters/AdapterRouter.d.ts +165 -0
- package/dist/adapters/AdapterRouter.d.ts.map +1 -0
- package/dist/adapters/AdapterRouter.js +350 -0
- package/dist/adapters/AdapterRouter.js.map +1 -0
- package/dist/adapters/BaseAdapter.d.ts +17 -0
- package/dist/adapters/BaseAdapter.d.ts.map +1 -1
- package/dist/adapters/BaseAdapter.js +21 -0
- package/dist/adapters/BaseAdapter.js.map +1 -1
- package/dist/adapters/BasicAdapter.d.ts +72 -3
- package/dist/adapters/BasicAdapter.d.ts.map +1 -1
- package/dist/adapters/BasicAdapter.js +178 -2
- package/dist/adapters/BasicAdapter.js.map +1 -1
- package/dist/adapters/IAdapter.d.ts +230 -0
- package/dist/adapters/IAdapter.d.ts.map +1 -0
- package/dist/adapters/IAdapter.js +44 -0
- package/dist/adapters/IAdapter.js.map +1 -0
- package/dist/adapters/StandardAdapter.d.ts +80 -6
- package/dist/adapters/StandardAdapter.d.ts.map +1 -1
- package/dist/adapters/StandardAdapter.js +203 -6
- package/dist/adapters/StandardAdapter.js.map +1 -1
- package/dist/adapters/X402Adapter.d.ts +208 -0
- package/dist/adapters/X402Adapter.d.ts.map +1 -0
- package/dist/adapters/X402Adapter.js +423 -0
- package/dist/adapters/X402Adapter.js.map +1 -0
- package/dist/adapters/index.d.ts +8 -0
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +19 -1
- package/dist/adapters/index.js.map +1 -1
- package/dist/cli/commands/init.d.ts +4 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +146 -4
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/config/networks.d.ts +9 -0
- package/dist/config/networks.d.ts.map +1 -1
- package/dist/config/networks.js +27 -12
- package/dist/config/networks.js.map +1 -1
- package/dist/erc8004/ERC8004Bridge.d.ts +155 -0
- package/dist/erc8004/ERC8004Bridge.d.ts.map +1 -0
- package/dist/erc8004/ERC8004Bridge.js +325 -0
- package/dist/erc8004/ERC8004Bridge.js.map +1 -0
- package/dist/erc8004/ReputationReporter.d.ts +223 -0
- package/dist/erc8004/ReputationReporter.d.ts.map +1 -0
- package/dist/erc8004/ReputationReporter.js +266 -0
- package/dist/erc8004/ReputationReporter.js.map +1 -0
- package/dist/erc8004/index.d.ts +36 -0
- package/dist/erc8004/index.d.ts.map +1 -0
- package/dist/erc8004/index.js +46 -0
- package/dist/erc8004/index.js.map +1 -0
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -2
- package/dist/index.js.map +1 -1
- package/dist/level0/provide.d.ts.map +1 -1
- package/dist/level0/provide.js +2 -1
- package/dist/level0/provide.js.map +1 -1
- package/dist/level1/Agent.d.ts.map +1 -1
- package/dist/level1/Agent.js +11 -3
- package/dist/level1/Agent.js.map +1 -1
- package/dist/protocol/ACTPKernel.d.ts +1 -1
- package/dist/protocol/ACTPKernel.d.ts.map +1 -1
- package/dist/protocol/ACTPKernel.js +23 -12
- package/dist/protocol/ACTPKernel.js.map +1 -1
- package/dist/protocol/DIDResolver.js +1 -1
- package/dist/protocol/DIDResolver.js.map +1 -1
- package/dist/protocol/EASHelper.d.ts.map +1 -1
- package/dist/protocol/EASHelper.js +2 -3
- package/dist/protocol/EASHelper.js.map +1 -1
- package/dist/protocol/MessageSigner.d.ts.map +1 -1
- package/dist/protocol/MessageSigner.js +8 -8
- package/dist/protocol/MessageSigner.js.map +1 -1
- package/dist/runtime/BlockchainRuntime.d.ts +7 -0
- package/dist/runtime/BlockchainRuntime.d.ts.map +1 -1
- package/dist/runtime/BlockchainRuntime.js +40 -22
- package/dist/runtime/BlockchainRuntime.js.map +1 -1
- package/dist/runtime/IACTPRuntime.d.ts +21 -0
- package/dist/runtime/IACTPRuntime.d.ts.map +1 -1
- package/dist/runtime/MockRuntime.d.ts +19 -0
- package/dist/runtime/MockRuntime.d.ts.map +1 -1
- package/dist/runtime/MockRuntime.js +56 -4
- package/dist/runtime/MockRuntime.js.map +1 -1
- package/dist/runtime/types/MockState.d.ts +11 -2
- package/dist/runtime/types/MockState.d.ts.map +1 -1
- package/dist/runtime/types/MockState.js.map +1 -1
- package/dist/storage/ArchiveBundleBuilder.d.ts +150 -0
- package/dist/storage/ArchiveBundleBuilder.d.ts.map +1 -0
- package/dist/storage/ArchiveBundleBuilder.js +468 -0
- package/dist/storage/ArchiveBundleBuilder.js.map +1 -0
- package/dist/storage/ArweaveClient.d.ts +271 -0
- package/dist/storage/ArweaveClient.d.ts.map +1 -0
- package/dist/storage/ArweaveClient.js +761 -0
- package/dist/storage/ArweaveClient.js.map +1 -0
- package/dist/storage/FilebaseClient.d.ts +193 -0
- package/dist/storage/FilebaseClient.d.ts.map +1 -0
- package/dist/storage/FilebaseClient.js +643 -0
- package/dist/storage/FilebaseClient.js.map +1 -0
- package/dist/storage/index.d.ts +47 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +64 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/types.d.ts +291 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/types.js +18 -0
- package/dist/storage/types.js.map +1 -0
- package/dist/types/adapter.d.ts +359 -0
- package/dist/types/adapter.d.ts.map +1 -0
- package/dist/types/adapter.js +115 -0
- package/dist/types/adapter.js.map +1 -0
- package/dist/types/erc8004.d.ts +184 -0
- package/dist/types/erc8004.d.ts.map +1 -0
- package/dist/types/erc8004.js +132 -0
- package/dist/types/erc8004.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/state.d.ts +5 -4
- package/dist/types/state.d.ts.map +1 -1
- package/dist/types/state.js +10 -9
- package/dist/types/state.js.map +1 -1
- package/dist/types/transaction.d.ts +12 -0
- package/dist/types/transaction.d.ts.map +1 -1
- package/dist/types/x402.d.ts +162 -0
- package/dist/types/x402.d.ts.map +1 -0
- package/dist/types/x402.js +162 -0
- package/dist/types/x402.js.map +1 -0
- package/dist/utils/IPFSClient.d.ts.map +1 -1
- package/dist/utils/IPFSClient.js +5 -2
- package/dist/utils/IPFSClient.js.map +1 -1
- package/dist/utils/NonceManager.d.ts.map +1 -1
- package/dist/utils/NonceManager.js +3 -2
- package/dist/utils/NonceManager.js.map +1 -1
- package/dist/utils/UsedAttestationTracker.d.ts.map +1 -1
- package/dist/utils/UsedAttestationTracker.js +3 -3
- package/dist/utils/UsedAttestationTracker.js.map +1 -1
- package/dist/utils/circuitBreaker.d.ts +136 -0
- package/dist/utils/circuitBreaker.d.ts.map +1 -0
- package/dist/utils/circuitBreaker.js +253 -0
- package/dist/utils/circuitBreaker.js.map +1 -0
- package/dist/utils/retry.d.ts +120 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +260 -0
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/validation.d.ts +100 -0
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +248 -1
- package/dist/utils/validation.js.map +1 -1
- package/package.json +16 -3
- package/src/ACTPClient.ts +318 -2
- package/src/abi/ACTPKernel.json +16 -0
- package/src/adapters/AdapterRegistry.ts +173 -0
- package/src/adapters/AdapterRouter.ts +417 -0
- package/src/adapters/BaseAdapter.ts +25 -0
- package/src/adapters/BasicAdapter.ts +210 -3
- package/src/adapters/IAdapter.ts +292 -0
- package/src/adapters/StandardAdapter.ts +246 -7
- package/src/adapters/X402Adapter.ts +653 -0
- package/src/adapters/index.ts +27 -0
- package/src/cli/commands/init.ts +166 -3
- package/src/config/networks.ts +36 -12
- package/src/erc8004/ERC8004Bridge.ts +461 -0
- package/src/erc8004/ReputationReporter.ts +472 -0
- package/src/erc8004/index.ts +61 -0
- package/src/index.ts +97 -0
- package/src/level0/provide.ts +2 -1
- package/src/level1/Agent.ts +13 -3
- package/src/protocol/ACTPKernel.ts +33 -12
- package/src/protocol/DIDResolver.ts +1 -1
- package/src/protocol/EASHelper.ts +2 -5
- package/src/protocol/MessageSigner.ts +8 -14
- package/src/runtime/BlockchainRuntime.ts +41 -45
- package/src/runtime/IACTPRuntime.ts +22 -0
- package/src/runtime/MockRuntime.ts +58 -4
- package/src/runtime/types/MockState.ts +12 -2
- package/src/storage/ArchiveBundleBuilder.ts +563 -0
- package/src/storage/ArweaveClient.ts +945 -0
- package/src/storage/FilebaseClient.ts +790 -0
- package/src/storage/index.ts +96 -0
- package/src/storage/types.ts +348 -0
- package/src/types/adapter.ts +296 -0
- package/src/types/erc8004.ts +293 -0
- package/src/types/index.ts +3 -0
- package/src/types/state.ts +10 -9
- package/src/types/transaction.ts +12 -0
- package/src/types/x402.ts +219 -0
- package/src/utils/IPFSClient.ts +5 -4
- package/src/utils/NonceManager.ts +3 -2
- package/src/utils/UsedAttestationTracker.ts +3 -5
- package/src/utils/circuitBreaker.ts +324 -0
- package/src/utils/fsSafe.ts +5 -0
- package/src/utils/retry.ts +365 -0
- 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 {
|
|
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:
|
|
685
|
-
//
|
|
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', '
|
|
709
|
+
['uint256', 'uint256', 'address', 'uint256'],
|
|
689
710
|
[
|
|
690
711
|
requesterAmount,
|
|
691
712
|
providerAmount,
|
|
692
|
-
|
|
693
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
467
|
-
|
|
468
|
-
|
|
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
|
-
|
|
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
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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
|
-
|
|
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
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
675
|
-
`BlockchainRuntime.releaseEscrow: Attestation ${attestationUID} verified (optional) for transaction ${txId}.`
|
|
676
|
-
);
|
|
669
|
+
sdkLogger.info('Attestation verified (optional)', { txId, attestationUID });
|
|
677
670
|
} catch (error) {
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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
|
/**
|