@agirails/sdk 2.3.0 → 2.3.3
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 +45 -8
- package/dist/ACTPClient.d.ts +35 -1
- package/dist/ACTPClient.d.ts.map +1 -1
- package/dist/ACTPClient.js +156 -26
- package/dist/ACTPClient.js.map +1 -1
- package/dist/adapters/AdapterRouter.d.ts.map +1 -1
- package/dist/adapters/AdapterRouter.js.map +1 -1
- package/dist/adapters/BasicAdapter.d.ts +10 -1
- package/dist/adapters/BasicAdapter.d.ts.map +1 -1
- package/dist/adapters/BasicAdapter.js +36 -1
- package/dist/adapters/BasicAdapter.js.map +1 -1
- package/dist/cli/commands/init.d.ts +2 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +345 -25
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/publish.d.ts.map +1 -1
- package/dist/cli/commands/publish.js.map +1 -1
- package/dist/cli/commands/register.d.ts +16 -0
- package/dist/cli/commands/register.d.ts.map +1 -0
- package/dist/cli/commands/register.js +211 -0
- package/dist/cli/commands/register.js.map +1 -0
- package/dist/cli/index.js +3 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/utils/config.d.ts +20 -0
- package/dist/cli/utils/config.d.ts.map +1 -1
- package/dist/cli/utils/config.js.map +1 -1
- package/dist/config/networks.d.ts +20 -4
- package/dist/config/networks.d.ts.map +1 -1
- package/dist/config/networks.js +59 -27
- package/dist/config/networks.js.map +1 -1
- package/dist/config/publishPipeline.d.ts +14 -0
- package/dist/config/publishPipeline.d.ts.map +1 -1
- package/dist/config/publishPipeline.js +2 -1
- package/dist/config/publishPipeline.js.map +1 -1
- package/dist/erc8004/ERC8004Bridge.d.ts.map +1 -1
- package/dist/erc8004/ERC8004Bridge.js +6 -5
- package/dist/erc8004/ERC8004Bridge.js.map +1 -1
- package/dist/erc8004/ReputationReporter.d.ts.map +1 -1
- package/dist/erc8004/ReputationReporter.js +9 -12
- package/dist/erc8004/ReputationReporter.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/level1/Agent.js +4 -4
- package/dist/level1/Agent.js.map +1 -1
- package/dist/protocol/ACTPKernel.d.ts +7 -1
- package/dist/protocol/ACTPKernel.d.ts.map +1 -1
- package/dist/protocol/ACTPKernel.js +13 -10
- package/dist/protocol/ACTPKernel.js.map +1 -1
- package/dist/protocol/EventMonitor.d.ts +14 -0
- package/dist/protocol/EventMonitor.d.ts.map +1 -1
- package/dist/protocol/EventMonitor.js +14 -0
- package/dist/protocol/EventMonitor.js.map +1 -1
- package/dist/runtime/BlockchainRuntime.d.ts +5 -0
- package/dist/runtime/BlockchainRuntime.d.ts.map +1 -1
- package/dist/runtime/BlockchainRuntime.js +1 -1
- package/dist/runtime/BlockchainRuntime.js.map +1 -1
- package/dist/storage/ArchiveBundleBuilder.d.ts.map +1 -1
- package/dist/storage/ArchiveBundleBuilder.js.map +1 -1
- package/dist/storage/ArweaveClient.d.ts.map +1 -1
- package/dist/storage/ArweaveClient.js +2 -0
- package/dist/storage/ArweaveClient.js.map +1 -1
- package/dist/storage/FilebaseClient.d.ts.map +1 -1
- package/dist/storage/FilebaseClient.js +2 -0
- package/dist/storage/FilebaseClient.js.map +1 -1
- package/dist/utils/ErrorRecoveryGuide.d.ts.map +1 -1
- package/dist/utils/ErrorRecoveryGuide.js +3 -2
- package/dist/utils/ErrorRecoveryGuide.js.map +1 -1
- package/dist/utils/IPFSClient.d.ts +3 -2
- package/dist/utils/IPFSClient.d.ts.map +1 -1
- package/dist/utils/IPFSClient.js +7 -5
- package/dist/utils/IPFSClient.js.map +1 -1
- package/dist/utils/computeTypeHash.js +1 -3
- package/dist/utils/computeTypeHash.js.map +1 -1
- package/dist/utils/retry.d.ts.map +1 -1
- package/dist/utils/retry.js +0 -1
- package/dist/utils/retry.js.map +1 -1
- package/dist/utils/validation.d.ts +2 -2
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +2 -2
- package/dist/utils/validation.js.map +1 -1
- package/dist/wallet/AutoWalletProvider.d.ts +77 -0
- package/dist/wallet/AutoWalletProvider.d.ts.map +1 -0
- package/dist/wallet/AutoWalletProvider.js +197 -0
- package/dist/wallet/AutoWalletProvider.js.map +1 -0
- package/dist/wallet/EOAWalletProvider.d.ts +21 -0
- package/dist/wallet/EOAWalletProvider.d.ts.map +1 -0
- package/dist/wallet/EOAWalletProvider.js +57 -0
- package/dist/wallet/EOAWalletProvider.js.map +1 -0
- package/dist/wallet/IWalletProvider.d.ts +115 -0
- package/dist/wallet/IWalletProvider.d.ts.map +1 -0
- package/dist/wallet/IWalletProvider.js +12 -0
- package/dist/wallet/IWalletProvider.js.map +1 -0
- package/dist/wallet/aa/BundlerClient.d.ts +70 -0
- package/dist/wallet/aa/BundlerClient.d.ts.map +1 -0
- package/dist/wallet/aa/BundlerClient.js +184 -0
- package/dist/wallet/aa/BundlerClient.js.map +1 -0
- package/dist/wallet/aa/DualNonceManager.d.ts +56 -0
- package/dist/wallet/aa/DualNonceManager.d.ts.map +1 -0
- package/dist/wallet/aa/DualNonceManager.js +142 -0
- package/dist/wallet/aa/DualNonceManager.js.map +1 -0
- package/dist/wallet/aa/PaymasterClient.d.ts +52 -0
- package/dist/wallet/aa/PaymasterClient.d.ts.map +1 -0
- package/dist/wallet/aa/PaymasterClient.js +116 -0
- package/dist/wallet/aa/PaymasterClient.js.map +1 -0
- package/dist/wallet/aa/TransactionBatcher.d.ts +87 -0
- package/dist/wallet/aa/TransactionBatcher.d.ts.map +1 -0
- package/dist/wallet/aa/TransactionBatcher.js +148 -0
- package/dist/wallet/aa/TransactionBatcher.js.map +1 -0
- package/dist/wallet/aa/UserOpBuilder.d.ts +71 -0
- package/dist/wallet/aa/UserOpBuilder.d.ts.map +1 -0
- package/dist/wallet/aa/UserOpBuilder.js +196 -0
- package/dist/wallet/aa/UserOpBuilder.js.map +1 -0
- package/dist/wallet/aa/constants.d.ts +54 -0
- package/dist/wallet/aa/constants.d.ts.map +1 -0
- package/dist/wallet/aa/constants.js +18 -0
- package/dist/wallet/aa/constants.js.map +1 -0
- package/package.json +4 -2
- package/src/ACTPClient.ts +217 -31
- package/src/adapters/AdapterRouter.ts +0 -1
- package/src/adapters/BasicAdapter.ts +41 -1
- package/src/cli/commands/init.ts +394 -25
- package/src/cli/commands/publish.ts +1 -2
- package/src/cli/commands/register.ts +233 -0
- package/src/cli/index.ts +4 -0
- package/src/cli/utils/config.ts +30 -0
- package/src/config/networks.ts +82 -27
- package/src/config/publishPipeline.ts +2 -2
- package/src/erc8004/ERC8004Bridge.ts +6 -5
- package/src/erc8004/ReputationReporter.ts +14 -18
- package/src/index.ts +12 -0
- package/src/level1/Agent.ts +5 -5
- package/src/protocol/ACTPKernel.ts +20 -10
- package/src/protocol/EventMonitor.ts +14 -0
- package/src/runtime/BlockchainRuntime.ts +7 -1
- package/src/storage/ArchiveBundleBuilder.ts +0 -2
- package/src/storage/ArweaveClient.ts +2 -1
- package/src/storage/FilebaseClient.ts +3 -3
- package/src/utils/ErrorRecoveryGuide.ts +4 -2
- package/src/utils/IPFSClient.ts +9 -7
- package/src/utils/computeTypeHash.ts +1 -3
- package/src/utils/retry.ts +0 -1
- package/src/utils/validation.ts +2 -2
- package/src/wallet/AutoWalletProvider.ts +294 -0
- package/src/wallet/EOAWalletProvider.ts +69 -0
- package/src/wallet/IWalletProvider.ts +133 -0
- package/src/wallet/aa/BundlerClient.ts +274 -0
- package/src/wallet/aa/DualNonceManager.ts +173 -0
- package/src/wallet/aa/PaymasterClient.ts +174 -0
- package/src/wallet/aa/TransactionBatcher.ts +240 -0
- package/src/wallet/aa/UserOpBuilder.ts +246 -0
- package/src/wallet/aa/constants.ts +60 -0
package/src/ACTPClient.ts
CHANGED
|
@@ -54,6 +54,10 @@ import { ERC8004Bridge } from './erc8004/ERC8004Bridge';
|
|
|
54
54
|
import { ReputationReporter } from './erc8004/ReputationReporter';
|
|
55
55
|
import { ERC8004Network } from './types/erc8004';
|
|
56
56
|
import { getNetwork } from './config/networks';
|
|
57
|
+
import { IWalletProvider } from './wallet/IWalletProvider';
|
|
58
|
+
import { EOAWalletProvider } from './wallet/EOAWalletProvider';
|
|
59
|
+
import { AutoWalletProvider } from './wallet/AutoWalletProvider';
|
|
60
|
+
import { sdkLogger } from './utils/Logger';
|
|
57
61
|
|
|
58
62
|
// ============================================================================
|
|
59
63
|
// Security: Path Validation
|
|
@@ -70,6 +74,33 @@ import { getNetwork } from './config/networks';
|
|
|
70
74
|
* @param stateDirectory - The directory path to validate
|
|
71
75
|
* @throws Error if path is unsafe
|
|
72
76
|
*/
|
|
77
|
+
/**
|
|
78
|
+
* Check if an agent is registered on AgentRegistry.
|
|
79
|
+
* Lightweight read-only check — no signer needed.
|
|
80
|
+
*
|
|
81
|
+
* Uses minimal ABI fragment to avoid importing the full AgentRegistry class.
|
|
82
|
+
* Checks registeredAt field of AgentProfile struct (> 0 means registered).
|
|
83
|
+
*/
|
|
84
|
+
async function checkRegistration(
|
|
85
|
+
provider: ethers.JsonRpcProvider,
|
|
86
|
+
registryAddress: string,
|
|
87
|
+
agentAddress: string
|
|
88
|
+
): Promise<boolean> {
|
|
89
|
+
const contract = new ethers.Contract(
|
|
90
|
+
registryAddress,
|
|
91
|
+
[
|
|
92
|
+
'function getAgent(address agentAddress) view returns ' +
|
|
93
|
+
'(tuple(address agentAddress, string did, string endpoint, bytes32[] serviceTypes, ' +
|
|
94
|
+
'uint256 stakedAmount, uint256 reputationScore, uint256 totalTransactions, ' +
|
|
95
|
+
'uint256 disputedTransactions, uint256 totalVolumeUSDC, uint256 registeredAt, ' +
|
|
96
|
+
'uint256 updatedAt, bool isActive, bytes32 configHash, string configCID, bool listed))',
|
|
97
|
+
],
|
|
98
|
+
provider
|
|
99
|
+
);
|
|
100
|
+
const profile = await contract.getAgent(agentAddress);
|
|
101
|
+
return profile.registeredAt > 0n;
|
|
102
|
+
}
|
|
103
|
+
|
|
73
104
|
function validateStateDirectory(stateDirectory: string): void {
|
|
74
105
|
// Check for path traversal characters
|
|
75
106
|
if (stateDirectory.includes('..')) {
|
|
@@ -174,9 +205,24 @@ export interface ACTPClientConfig {
|
|
|
174
205
|
* This address is used as the "from" address for all transactions
|
|
175
206
|
* created through this client instance.
|
|
176
207
|
*
|
|
208
|
+
* When wallet is 'auto', this is auto-derived from the Smart Wallet
|
|
209
|
+
* and does NOT need to be provided.
|
|
210
|
+
*
|
|
177
211
|
* @example '0x1111111111111111111111111111111111111111'
|
|
178
212
|
*/
|
|
179
|
-
requesterAddress
|
|
213
|
+
requesterAddress?: string;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* AIP-12: Wallet mode.
|
|
217
|
+
*
|
|
218
|
+
* - 'auto': CoinbaseSmartWallet + gas sponsorship (Tier 1, recommended).
|
|
219
|
+
* Requires CDP_API_KEY env var. Agent address = Smart Wallet address.
|
|
220
|
+
* - undefined: EOA wallet from privateKey (Tier 2, backward compatible).
|
|
221
|
+
*
|
|
222
|
+
* When 'auto', requesterAddress is derived from the Smart Wallet
|
|
223
|
+
* and does not need to be provided.
|
|
224
|
+
*/
|
|
225
|
+
wallet?: 'auto';
|
|
180
226
|
|
|
181
227
|
/**
|
|
182
228
|
* Optional: Project root directory for mock state file storage.
|
|
@@ -263,6 +309,7 @@ export interface ACTPClientConfig {
|
|
|
263
309
|
actpKernel?: string;
|
|
264
310
|
escrowVault?: string;
|
|
265
311
|
usdc?: string;
|
|
312
|
+
agentRegistry?: string;
|
|
266
313
|
};
|
|
267
314
|
|
|
268
315
|
/**
|
|
@@ -319,6 +366,8 @@ export interface ACTPClientInfo {
|
|
|
319
366
|
address: string;
|
|
320
367
|
/** State directory (mock mode only) */
|
|
321
368
|
stateDirectory?: string;
|
|
369
|
+
/** Wallet tier ('auto' = Smart Wallet, 'eoa' = EOA, undefined = mock) */
|
|
370
|
+
walletTier?: 'auto' | 'eoa';
|
|
322
371
|
}
|
|
323
372
|
|
|
324
373
|
// ============================================================================
|
|
@@ -463,6 +512,13 @@ export class ACTPClient {
|
|
|
463
512
|
*/
|
|
464
513
|
private readonly reputationReporter?: ReputationReporter;
|
|
465
514
|
|
|
515
|
+
/**
|
|
516
|
+
* AIP-12: Wallet provider (Tier 1 Auto or Tier 2 EOA).
|
|
517
|
+
* Only set in testnet/mainnet modes.
|
|
518
|
+
* @internal
|
|
519
|
+
*/
|
|
520
|
+
private readonly walletProvider?: IWalletProvider;
|
|
521
|
+
|
|
466
522
|
/**
|
|
467
523
|
* Private constructor - use ACTPClient.create() factory method.
|
|
468
524
|
*/
|
|
@@ -472,13 +528,16 @@ export class ACTPClient {
|
|
|
472
528
|
info: ACTPClientInfo,
|
|
473
529
|
easHelper?: EASHelper,
|
|
474
530
|
erc8004Bridge?: ERC8004Bridge,
|
|
475
|
-
reputationReporter?: ReputationReporter
|
|
531
|
+
reputationReporter?: ReputationReporter,
|
|
532
|
+
walletProvider?: IWalletProvider,
|
|
533
|
+
contractAddresses?: { usdc: string; actpKernel: string; escrowVault: string }
|
|
476
534
|
) {
|
|
477
535
|
this.runtime = runtime;
|
|
478
536
|
this.info = info;
|
|
479
537
|
this.easHelper = easHelper;
|
|
480
538
|
this.reputationReporter = reputationReporter;
|
|
481
|
-
this.
|
|
539
|
+
this.walletProvider = walletProvider;
|
|
540
|
+
this.basic = new BasicAdapter(runtime, requesterAddress, easHelper, walletProvider, contractAddresses);
|
|
482
541
|
this.standard = new StandardAdapter(runtime, requesterAddress, easHelper);
|
|
483
542
|
|
|
484
543
|
// Initialize registry and router
|
|
@@ -527,31 +586,45 @@ export class ACTPClient {
|
|
|
527
586
|
* ```
|
|
528
587
|
*/
|
|
529
588
|
static async create(config: ACTPClientConfig): Promise<ACTPClient> {
|
|
530
|
-
// Validate requester address
|
|
531
|
-
if (!config.requesterAddress) {
|
|
532
|
-
throw new Error('requesterAddress is required');
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
if (!/^0x[a-fA-F0-9]{40}$/.test(config.requesterAddress)) {
|
|
536
|
-
throw new Error(
|
|
537
|
-
`Invalid requesterAddress: "${config.requesterAddress}". ` +
|
|
538
|
-
'Must be a valid Ethereum address (0x-prefixed, 40 hex chars)'
|
|
539
|
-
);
|
|
540
|
-
}
|
|
541
|
-
|
|
542
589
|
let runtime: IACTPRuntime;
|
|
543
590
|
let stateDirectory: string | undefined;
|
|
544
591
|
let easHelper: EASHelper | undefined;
|
|
545
592
|
let erc8004Bridge: ERC8004Bridge | undefined;
|
|
546
593
|
let reputationReporter: ReputationReporter | undefined;
|
|
594
|
+
let walletProvider: IWalletProvider | undefined;
|
|
595
|
+
let requesterAddress: string;
|
|
596
|
+
let contractAddresses: { usdc: string; actpKernel: string; escrowVault: string } | undefined;
|
|
547
597
|
|
|
548
598
|
// If custom runtime provided, use it directly
|
|
549
599
|
if (config.runtime) {
|
|
600
|
+
// Custom runtime: requesterAddress is mandatory
|
|
601
|
+
if (!config.requesterAddress) {
|
|
602
|
+
throw new Error('requesterAddress is required when providing a custom runtime');
|
|
603
|
+
}
|
|
604
|
+
if (!/^0x[a-fA-F0-9]{40}$/.test(config.requesterAddress)) {
|
|
605
|
+
throw new Error(
|
|
606
|
+
`Invalid requesterAddress: "${config.requesterAddress}". ` +
|
|
607
|
+
'Must be a valid Ethereum address (0x-prefixed, 40 hex chars)'
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
requesterAddress = config.requesterAddress;
|
|
550
611
|
runtime = config.runtime;
|
|
551
612
|
} else {
|
|
552
613
|
// Initialize runtime based on mode
|
|
553
614
|
switch (config.mode) {
|
|
554
615
|
case 'mock': {
|
|
616
|
+
// Mock mode: requesterAddress is mandatory
|
|
617
|
+
if (!config.requesterAddress) {
|
|
618
|
+
throw new Error('requesterAddress is required for mock mode');
|
|
619
|
+
}
|
|
620
|
+
if (!/^0x[a-fA-F0-9]{40}$/.test(config.requesterAddress)) {
|
|
621
|
+
throw new Error(
|
|
622
|
+
`Invalid requesterAddress: "${config.requesterAddress}". ` +
|
|
623
|
+
'Must be a valid Ethereum address (0x-prefixed, 40 hex chars)'
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
requesterAddress = config.requesterAddress;
|
|
627
|
+
|
|
555
628
|
// SECURITY FIX: Enhanced path validation to prevent path traversal attacks
|
|
556
629
|
if (config.stateDirectory) {
|
|
557
630
|
validateStateDirectory(config.stateDirectory);
|
|
@@ -576,14 +649,12 @@ export class ACTPClient {
|
|
|
576
649
|
|
|
577
650
|
// Map mode to network config
|
|
578
651
|
const network = config.mode === 'testnet' ? 'base-sepolia' : 'base-mainnet';
|
|
652
|
+
const networkConfig = getNetwork(network);
|
|
579
653
|
|
|
580
654
|
// Default RPC URL from network config if not provided
|
|
581
|
-
|
|
582
|
-
const rpcUrl = config.rpcUrl ?? getNetwork(network).rpcUrl;
|
|
655
|
+
const rpcUrl = config.rpcUrl ?? networkConfig.rpcUrl;
|
|
583
656
|
|
|
584
|
-
// Optional persistent state directory
|
|
585
|
-
// - mock mode state (mock-state.json)
|
|
586
|
-
// - blockchain mode safety state (e.g., used-attestation replay protection)
|
|
657
|
+
// Optional persistent state directory
|
|
587
658
|
if (config.stateDirectory) {
|
|
588
659
|
validateStateDirectory(config.stateDirectory);
|
|
589
660
|
}
|
|
@@ -592,6 +663,100 @@ export class ACTPClient {
|
|
|
592
663
|
const provider = new ethers.JsonRpcProvider(rpcUrl);
|
|
593
664
|
const signer = new ethers.Wallet(config.privateKey, provider);
|
|
594
665
|
|
|
666
|
+
// ====================================================================
|
|
667
|
+
// AIP-12: Wallet Provider Selection
|
|
668
|
+
// ====================================================================
|
|
669
|
+
if (config.wallet === 'auto') {
|
|
670
|
+
// Tier 1: CoinbaseSmartWallet + gasless transactions
|
|
671
|
+
if (!networkConfig.aa) {
|
|
672
|
+
throw new Error(
|
|
673
|
+
`AA configuration not available for ${config.mode} mode. ` +
|
|
674
|
+
'Check that networks.ts has aa config for this network.'
|
|
675
|
+
);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// Validate that bundler/paymaster URLs have actual API keys
|
|
679
|
+
const cdpBundlerUrl = networkConfig.aa.bundlerUrls.coinbase;
|
|
680
|
+
const hasPimlico = !!networkConfig.aa.bundlerUrls.pimlico;
|
|
681
|
+
if (cdpBundlerUrl.endsWith('/') && !hasPimlico) {
|
|
682
|
+
throw new Error(
|
|
683
|
+
'CDP_API_KEY is required for gas-sponsored transactions.\n\n' +
|
|
684
|
+
'Set up your API key:\n' +
|
|
685
|
+
' 1. Visit https://portal.cdp.coinbase.com/\n' +
|
|
686
|
+
' 2. Create a new API key\n' +
|
|
687
|
+
' 3. export CDP_API_KEY="your-key-here"\n\n' +
|
|
688
|
+
'Or set PIMLICO_API_KEY as an alternative bundler/paymaster.\n' +
|
|
689
|
+
'Or use wallet: undefined for traditional EOA transactions (requires ETH for gas).'
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
const autoWallet = await AutoWalletProvider.create({
|
|
694
|
+
signer,
|
|
695
|
+
provider,
|
|
696
|
+
chainId: networkConfig.chainId,
|
|
697
|
+
actpKernelAddress: config.contracts?.actpKernel ?? networkConfig.contracts.actpKernel,
|
|
698
|
+
bundler: {
|
|
699
|
+
primaryUrl: networkConfig.aa.bundlerUrls.coinbase,
|
|
700
|
+
backupUrl: networkConfig.aa.bundlerUrls.pimlico,
|
|
701
|
+
},
|
|
702
|
+
paymaster: {
|
|
703
|
+
primaryUrl: networkConfig.aa.paymasterUrls.coinbase,
|
|
704
|
+
backupUrl: networkConfig.aa.paymasterUrls.pimlico,
|
|
705
|
+
},
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
// Check AgentRegistry — gasless only for registered agents
|
|
709
|
+
const smartWalletAddress = autoWallet.getAddress();
|
|
710
|
+
const agentRegistryAddress = config.contracts?.agentRegistry
|
|
711
|
+
?? networkConfig.contracts.agentRegistry;
|
|
712
|
+
|
|
713
|
+
let isRegistered = false;
|
|
714
|
+
if (agentRegistryAddress) {
|
|
715
|
+
try {
|
|
716
|
+
isRegistered = await checkRegistration(
|
|
717
|
+
provider, agentRegistryAddress, smartWalletAddress
|
|
718
|
+
);
|
|
719
|
+
} catch {
|
|
720
|
+
// Registry check failed (e.g. RPC down) — allow AA anyway.
|
|
721
|
+
// Rationale: don't punish legit registered agents for infra issues.
|
|
722
|
+
// Paymaster contract allowlist + rate limits prevent abuse.
|
|
723
|
+
isRegistered = true;
|
|
724
|
+
sdkLogger.warn('AgentRegistry check failed, proceeding with AA wallet');
|
|
725
|
+
}
|
|
726
|
+
} else {
|
|
727
|
+
// No registry deployed — skip check (early testnet)
|
|
728
|
+
isRegistered = true;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
if (isRegistered) {
|
|
732
|
+
walletProvider = autoWallet;
|
|
733
|
+
requesterAddress = smartWalletAddress;
|
|
734
|
+
} else {
|
|
735
|
+
// Not registered — fall back to EOA with warning
|
|
736
|
+
sdkLogger.warn(
|
|
737
|
+
'Agent not registered on AgentRegistry. ' +
|
|
738
|
+
'Falling back to EOA wallet (gas not sponsored). ' +
|
|
739
|
+
'Run "actp register" for gas-free transactions.'
|
|
740
|
+
);
|
|
741
|
+
walletProvider = new EOAWalletProvider(signer, networkConfig.chainId);
|
|
742
|
+
// Force signer.address — config.requesterAddress may be the Smart Wallet
|
|
743
|
+
// address (set by `actp init --wallet auto`), which would be wrong for EOA.
|
|
744
|
+
requesterAddress = signer.address;
|
|
745
|
+
}
|
|
746
|
+
} else {
|
|
747
|
+
// Tier 2: EOA Wallet (backward compatible)
|
|
748
|
+
walletProvider = new EOAWalletProvider(signer, networkConfig.chainId);
|
|
749
|
+
requesterAddress = config.requesterAddress ?? signer.address;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
// Validate derived/provided address
|
|
753
|
+
if (!/^0x[a-fA-F0-9]{40}$/.test(requesterAddress)) {
|
|
754
|
+
throw new Error(
|
|
755
|
+
`Invalid requesterAddress: "${requesterAddress}". ` +
|
|
756
|
+
'Must be a valid Ethereum address (0x-prefixed, 40 hex chars)'
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
|
|
595
760
|
const requireAttestation = config.requireAttestation ?? Boolean(config.easConfig);
|
|
596
761
|
|
|
597
762
|
// Create BlockchainRuntime
|
|
@@ -618,7 +783,6 @@ export class ACTPClient {
|
|
|
618
783
|
}
|
|
619
784
|
|
|
620
785
|
// ERC-8004 INTEGRATION: Create bridge for agent ID resolution
|
|
621
|
-
// Maps network to ERC8004Network ('base-sepolia' or 'base')
|
|
622
786
|
const erc8004Network: ERC8004Network =
|
|
623
787
|
config.mode === 'testnet' ? 'base-sepolia' : 'base';
|
|
624
788
|
erc8004Bridge = new ERC8004Bridge({
|
|
@@ -627,12 +791,18 @@ export class ACTPClient {
|
|
|
627
791
|
});
|
|
628
792
|
|
|
629
793
|
// ERC-8004 REPUTATION: Create reporter for settlement outcome reporting
|
|
630
|
-
// Reports successful settlements and dispute outcomes to Reputation Registry
|
|
631
794
|
reputationReporter = new ReputationReporter({
|
|
632
795
|
network: erc8004Network,
|
|
633
796
|
signer,
|
|
634
797
|
});
|
|
635
798
|
|
|
799
|
+
// AIP-12: Contract addresses for AA batched payments
|
|
800
|
+
contractAddresses = {
|
|
801
|
+
usdc: config.contracts?.usdc ?? networkConfig.contracts.usdc,
|
|
802
|
+
actpKernel: config.contracts?.actpKernel ?? networkConfig.contracts.actpKernel,
|
|
803
|
+
escrowVault: config.contracts?.escrowVault ?? networkConfig.contracts.escrowVault,
|
|
804
|
+
};
|
|
805
|
+
|
|
636
806
|
break;
|
|
637
807
|
}
|
|
638
808
|
|
|
@@ -645,17 +815,20 @@ export class ACTPClient {
|
|
|
645
815
|
}
|
|
646
816
|
|
|
647
817
|
// Normalize address to lowercase for consistency
|
|
648
|
-
const normalizedAddress =
|
|
818
|
+
const normalizedAddress = requesterAddress.toLowerCase();
|
|
649
819
|
|
|
650
820
|
const info: ACTPClientInfo = {
|
|
651
821
|
mode: config.mode,
|
|
652
822
|
address: normalizedAddress,
|
|
653
823
|
stateDirectory,
|
|
824
|
+
walletTier: walletProvider?.getWalletInfo().tier,
|
|
654
825
|
};
|
|
655
826
|
|
|
656
|
-
//
|
|
657
|
-
|
|
658
|
-
|
|
827
|
+
// Pass wallet provider and contract addresses to constructor
|
|
828
|
+
const client = new ACTPClient(
|
|
829
|
+
runtime, normalizedAddress, info, easHelper,
|
|
830
|
+
erc8004Bridge, reputationReporter, walletProvider, contractAddresses
|
|
831
|
+
);
|
|
659
832
|
|
|
660
833
|
// Drift detection: non-blocking check for AGIRAILS.md sync status
|
|
661
834
|
if (config.mode !== 'mock') {
|
|
@@ -1044,7 +1217,7 @@ export class ACTPClient {
|
|
|
1044
1217
|
})
|
|
1045
1218
|
.then((result) => {
|
|
1046
1219
|
if (result) {
|
|
1047
|
-
|
|
1220
|
+
sdkLogger.info(
|
|
1048
1221
|
`[ERC8004] Settlement reported for agent ${agentId}: ${result.txHash}`
|
|
1049
1222
|
);
|
|
1050
1223
|
}
|
|
@@ -1113,6 +1286,19 @@ export class ACTPClient {
|
|
|
1113
1286
|
return this.reputationReporter;
|
|
1114
1287
|
}
|
|
1115
1288
|
|
|
1289
|
+
/**
|
|
1290
|
+
* AIP-12: Get the wallet provider instance.
|
|
1291
|
+
*
|
|
1292
|
+
* Only available in testnet/mainnet modes.
|
|
1293
|
+
* Returns undefined in mock mode.
|
|
1294
|
+
*
|
|
1295
|
+
* Use this for advanced operations like checking wallet info,
|
|
1296
|
+
* or sending custom batched transactions.
|
|
1297
|
+
*/
|
|
1298
|
+
getWalletProvider(): IWalletProvider | undefined {
|
|
1299
|
+
return this.walletProvider;
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1116
1302
|
/**
|
|
1117
1303
|
* Non-blocking drift detection for AGIRAILS.md config.
|
|
1118
1304
|
* Checks if local AGIRAILS.md matches on-chain config hash.
|
|
@@ -1149,17 +1335,17 @@ export class ACTPClient {
|
|
|
1149
1335
|
const { frontmatter } = parseMd(content);
|
|
1150
1336
|
const isTemplate = !frontmatter.config_hash;
|
|
1151
1337
|
|
|
1152
|
-
const onChainState = await registryClient.getConfig(config.requesterAddress);
|
|
1338
|
+
const onChainState = await registryClient.getConfig(config.requesterAddress ?? this.info.address);
|
|
1153
1339
|
const ZERO_HASH = '0x' + '0'.repeat(64);
|
|
1154
1340
|
|
|
1155
1341
|
if (onChainState.configHash === ZERO_HASH) {
|
|
1156
1342
|
if (isTemplate) {
|
|
1157
|
-
|
|
1343
|
+
sdkLogger.info('[AGIRAILS] AGIRAILS.md loaded (template mode). Run "actp publish" to register and sync on-chain.');
|
|
1158
1344
|
} else {
|
|
1159
|
-
|
|
1345
|
+
sdkLogger.warn('[AGIRAILS] Config not published on-chain. Run: actp publish');
|
|
1160
1346
|
}
|
|
1161
1347
|
} else if (onChainState.configHash !== localHash) {
|
|
1162
|
-
|
|
1348
|
+
sdkLogger.warn('[AGIRAILS] Local AGIRAILS.md differs from on-chain. Run: actp diff');
|
|
1163
1349
|
}
|
|
1164
1350
|
} catch {
|
|
1165
1351
|
// Silently ignore — drift detection is best-effort
|
|
@@ -17,7 +17,6 @@ import { AdapterRegistry } from './AdapterRegistry';
|
|
|
17
17
|
import { IAdapter } from './IAdapter';
|
|
18
18
|
import {
|
|
19
19
|
UnifiedPayParams,
|
|
20
|
-
UnifiedPayParamsSchema,
|
|
21
20
|
safeValidatePayParams,
|
|
22
21
|
} from '../types/adapter';
|
|
23
22
|
import { ValidationError } from './BaseAdapter';
|
|
@@ -22,6 +22,8 @@ import {
|
|
|
22
22
|
UnifiedPayParams,
|
|
23
23
|
UnifiedPayResult,
|
|
24
24
|
} from '../types/adapter';
|
|
25
|
+
import { IWalletProvider } from '../wallet/IWalletProvider';
|
|
26
|
+
import { ethers } from 'ethers';
|
|
25
27
|
|
|
26
28
|
/**
|
|
27
29
|
* Parameters for creating a simple payment.
|
|
@@ -116,11 +118,15 @@ export class BasicAdapter extends BaseAdapter implements IAdapter {
|
|
|
116
118
|
* @param runtime - ACTP runtime implementation (MockRuntime or BlockchainRuntime)
|
|
117
119
|
* @param requesterAddress - The requester's Ethereum address
|
|
118
120
|
* @param easHelper - Optional EAS helper for attestation verification (SECURITY FIX C-4)
|
|
121
|
+
* @param walletProvider - Optional wallet provider for AA batched payments
|
|
122
|
+
* @param contractAddresses - Optional contract addresses for batched payment encoding
|
|
119
123
|
*/
|
|
120
124
|
constructor(
|
|
121
125
|
private runtime: IACTPRuntime,
|
|
122
126
|
requesterAddress: string,
|
|
123
|
-
private easHelper?: EASHelper
|
|
127
|
+
private easHelper?: EASHelper,
|
|
128
|
+
private walletProvider?: IWalletProvider,
|
|
129
|
+
private contractAddresses?: { usdc: string; actpKernel: string; escrowVault: string }
|
|
124
130
|
) {
|
|
125
131
|
super(requesterAddress);
|
|
126
132
|
}
|
|
@@ -187,6 +193,40 @@ export class BasicAdapter extends BaseAdapter implements IAdapter {
|
|
|
187
193
|
);
|
|
188
194
|
}
|
|
189
195
|
|
|
196
|
+
// ====================================================================
|
|
197
|
+
// AIP-12: Batched payment via AA wallet (1 UserOp = 3 on-chain calls)
|
|
198
|
+
// ====================================================================
|
|
199
|
+
if (this.walletProvider?.payACTPBatched && this.contractAddresses) {
|
|
200
|
+
const serviceHash = ethers.ZeroHash;
|
|
201
|
+
const result = await this.walletProvider.payACTPBatched({
|
|
202
|
+
provider,
|
|
203
|
+
requester,
|
|
204
|
+
amount: amount.toString(),
|
|
205
|
+
deadline,
|
|
206
|
+
disputeWindow,
|
|
207
|
+
serviceHash,
|
|
208
|
+
agentId: agentId || '0',
|
|
209
|
+
contracts: this.contractAddresses,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
if (!result.success) {
|
|
213
|
+
throw new Error(`Batched payment UserOp failed: ${result.hash}`);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
txId: result.txId,
|
|
218
|
+
provider,
|
|
219
|
+
requester,
|
|
220
|
+
amount: this.formatAmount(amount),
|
|
221
|
+
deadline: new Date(deadline * 1000).toISOString(),
|
|
222
|
+
state: 'COMMITTED',
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// ====================================================================
|
|
227
|
+
// Legacy flow: sequential on-chain calls (EOA / mock)
|
|
228
|
+
// ====================================================================
|
|
229
|
+
|
|
190
230
|
// Create transaction
|
|
191
231
|
const txId = await this.runtime.createTransaction({
|
|
192
232
|
provider,
|