@agirails/sdk 2.5.2 → 2.5.4
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/dist/ACTPClient.d.ts +18 -0
- package/dist/ACTPClient.d.ts.map +1 -1
- package/dist/ACTPClient.js +67 -22
- package/dist/ACTPClient.js.map +1 -1
- package/dist/adapters/BasicAdapter.d.ts +12 -0
- package/dist/adapters/BasicAdapter.d.ts.map +1 -1
- package/dist/adapters/BasicAdapter.js +30 -4
- package/dist/adapters/BasicAdapter.js.map +1 -1
- package/dist/adapters/StandardAdapter.d.ts +20 -3
- package/dist/adapters/StandardAdapter.d.ts.map +1 -1
- package/dist/adapters/StandardAdapter.js +45 -11
- package/dist/adapters/StandardAdapter.js.map +1 -1
- package/dist/cli/commands/publish.js +16 -4
- package/dist/cli/commands/publish.js.map +1 -1
- package/dist/cli/commands/register.js +16 -4
- package/dist/cli/commands/register.js.map +1 -1
- package/dist/cli/commands/tx.js +31 -3
- package/dist/cli/commands/tx.js.map +1 -1
- package/dist/cli/utils/client.d.ts.map +1 -1
- package/dist/cli/utils/client.js +1 -0
- package/dist/cli/utils/client.js.map +1 -1
- package/dist/config/networks.d.ts +2 -2
- package/dist/config/networks.d.ts.map +1 -1
- package/dist/config/networks.js +27 -22
- package/dist/config/networks.js.map +1 -1
- package/dist/level0/request.d.ts.map +1 -1
- package/dist/level0/request.js +2 -1
- package/dist/level0/request.js.map +1 -1
- package/dist/runtime/BlockchainRuntime.d.ts.map +1 -1
- package/dist/runtime/BlockchainRuntime.js +11 -5
- package/dist/runtime/BlockchainRuntime.js.map +1 -1
- package/dist/runtime/MockStateManager.d.ts.map +1 -1
- package/dist/runtime/MockStateManager.js +2 -1
- package/dist/runtime/MockStateManager.js.map +1 -1
- package/dist/utils/IPFSClient.d.ts +3 -1
- package/dist/utils/IPFSClient.d.ts.map +1 -1
- package/dist/utils/IPFSClient.js +27 -7
- package/dist/utils/IPFSClient.js.map +1 -1
- package/dist/wallet/AutoWalletProvider.d.ts.map +1 -1
- package/dist/wallet/AutoWalletProvider.js +52 -18
- package/dist/wallet/AutoWalletProvider.js.map +1 -1
- package/dist/wallet/SmartWalletRouter.d.ts +116 -0
- package/dist/wallet/SmartWalletRouter.d.ts.map +1 -0
- package/dist/wallet/SmartWalletRouter.js +212 -0
- package/dist/wallet/SmartWalletRouter.js.map +1 -0
- package/dist/wallet/aa/DualNonceManager.d.ts +19 -0
- package/dist/wallet/aa/DualNonceManager.d.ts.map +1 -1
- package/dist/wallet/aa/DualNonceManager.js +100 -5
- package/dist/wallet/aa/DualNonceManager.js.map +1 -1
- package/package.json +3 -6
- package/src/ACTPClient.ts +0 -1579
- package/src/abi/ACTPKernel.json +0 -1356
- package/src/abi/AgentRegistry.json +0 -915
- package/src/abi/ERC20.json +0 -40
- package/src/abi/EscrowVault.json +0 -134
- package/src/abi/IdentityRegistry.json +0 -316
- package/src/adapters/AdapterRegistry.ts +0 -173
- package/src/adapters/AdapterRouter.ts +0 -416
- package/src/adapters/BaseAdapter.ts +0 -498
- package/src/adapters/BasicAdapter.ts +0 -514
- package/src/adapters/IAdapter.ts +0 -292
- package/src/adapters/StandardAdapter.ts +0 -555
- package/src/adapters/X402Adapter.ts +0 -731
- package/src/adapters/index.ts +0 -60
- package/src/builders/DeliveryProofBuilder.ts +0 -327
- package/src/builders/QuoteBuilder.ts +0 -483
- package/src/builders/index.ts +0 -17
- package/src/cli/commands/balance.ts +0 -110
- package/src/cli/commands/batch.ts +0 -487
- package/src/cli/commands/config.ts +0 -231
- package/src/cli/commands/deploy-check.ts +0 -364
- package/src/cli/commands/deploy-env.ts +0 -120
- package/src/cli/commands/diff.ts +0 -141
- package/src/cli/commands/init.ts +0 -469
- package/src/cli/commands/mint.ts +0 -116
- package/src/cli/commands/pay.ts +0 -113
- package/src/cli/commands/publish.ts +0 -475
- package/src/cli/commands/pull.ts +0 -124
- package/src/cli/commands/register.ts +0 -247
- package/src/cli/commands/simulate.ts +0 -345
- package/src/cli/commands/time.ts +0 -302
- package/src/cli/commands/tx.ts +0 -448
- package/src/cli/commands/watch.ts +0 -211
- package/src/cli/index.ts +0 -134
- package/src/cli/utils/client.ts +0 -251
- package/src/cli/utils/config.ts +0 -389
- package/src/cli/utils/output.ts +0 -465
- package/src/cli/utils/wallet.ts +0 -109
- package/src/config/agirailsmd.ts +0 -262
- package/src/config/networks.ts +0 -275
- package/src/config/pendingPublish.ts +0 -237
- package/src/config/publishPipeline.ts +0 -359
- package/src/config/syncOperations.ts +0 -279
- package/src/erc8004/ERC8004Bridge.ts +0 -462
- package/src/erc8004/ReputationReporter.ts +0 -468
- package/src/erc8004/index.ts +0 -61
- package/src/errors/index.ts +0 -427
- package/src/index.ts +0 -364
- package/src/level0/Provider.ts +0 -117
- package/src/level0/ServiceDirectory.ts +0 -131
- package/src/level0/index.ts +0 -10
- package/src/level0/provide.ts +0 -132
- package/src/level0/request.ts +0 -432
- package/src/level1/Agent.ts +0 -1426
- package/src/level1/index.ts +0 -10
- package/src/level1/pricing/PriceCalculator.ts +0 -255
- package/src/level1/pricing/PricingStrategy.ts +0 -198
- package/src/level1/types/Job.ts +0 -179
- package/src/level1/types/Options.ts +0 -291
- package/src/level1/types/index.ts +0 -8
- package/src/protocol/ACTPKernel.ts +0 -808
- package/src/protocol/AgentRegistry.ts +0 -559
- package/src/protocol/DIDManager.ts +0 -629
- package/src/protocol/DIDResolver.ts +0 -554
- package/src/protocol/EASHelper.ts +0 -378
- package/src/protocol/EscrowVault.ts +0 -255
- package/src/protocol/EventMonitor.ts +0 -204
- package/src/protocol/MessageSigner.ts +0 -510
- package/src/protocol/ProofGenerator.ts +0 -339
- package/src/protocol/QuoteBuilder.ts +0 -15
- package/src/registry/AgentRegistryClient.ts +0 -202
- package/src/runtime/BlockchainRuntime.ts +0 -1015
- package/src/runtime/IACTPRuntime.ts +0 -306
- package/src/runtime/MockRuntime.ts +0 -1298
- package/src/runtime/MockStateManager.ts +0 -576
- package/src/runtime/index.ts +0 -25
- package/src/runtime/types/MockState.ts +0 -237
- package/src/storage/ArchiveBundleBuilder.ts +0 -561
- package/src/storage/ArweaveClient.ts +0 -946
- package/src/storage/FilebaseClient.ts +0 -790
- package/src/storage/index.ts +0 -96
- package/src/storage/types.ts +0 -348
- package/src/types/adapter.ts +0 -310
- package/src/types/agent.ts +0 -79
- package/src/types/did.ts +0 -223
- package/src/types/eip712.ts +0 -175
- package/src/types/erc8004.ts +0 -293
- package/src/types/escrow.ts +0 -27
- package/src/types/index.ts +0 -17
- package/src/types/message.ts +0 -145
- package/src/types/state.ts +0 -87
- package/src/types/transaction.ts +0 -69
- package/src/types/x402.ts +0 -251
- package/src/utils/ErrorRecoveryGuide.ts +0 -676
- package/src/utils/Helpers.ts +0 -688
- package/src/utils/IPFSClient.ts +0 -368
- package/src/utils/Logger.ts +0 -484
- package/src/utils/NonceManager.ts +0 -591
- package/src/utils/RateLimiter.ts +0 -534
- package/src/utils/ReceivedNonceTracker.ts +0 -567
- package/src/utils/SDKLifecycle.ts +0 -416
- package/src/utils/SecureNonce.ts +0 -78
- package/src/utils/Semaphore.ts +0 -276
- package/src/utils/UsedAttestationTracker.ts +0 -385
- package/src/utils/canonicalJson.ts +0 -38
- package/src/utils/circuitBreaker.ts +0 -324
- package/src/utils/computeTypeHash.ts +0 -48
- package/src/utils/fsSafe.ts +0 -80
- package/src/utils/index.ts +0 -80
- package/src/utils/retry.ts +0 -364
- package/src/utils/security.ts +0 -418
- package/src/utils/validation.ts +0 -540
- package/src/wallet/AutoWalletProvider.ts +0 -299
- package/src/wallet/EOAWalletProvider.ts +0 -69
- package/src/wallet/IWalletProvider.ts +0 -135
- package/src/wallet/aa/BundlerClient.ts +0 -274
- package/src/wallet/aa/DualNonceManager.ts +0 -173
- package/src/wallet/aa/PaymasterClient.ts +0 -174
- package/src/wallet/aa/TransactionBatcher.ts +0 -353
- package/src/wallet/aa/UserOpBuilder.ts +0 -246
- package/src/wallet/aa/constants.ts +0 -60
- package/src/wallet/keystore.ts +0 -240
package/src/cli/commands/init.ts
DELETED
|
@@ -1,469 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Init Command - Initialize ACTP in the current directory
|
|
3
|
-
*
|
|
4
|
-
* Creates .actp/ directory with configuration and initial state.
|
|
5
|
-
* Supports interactive and non-interactive modes.
|
|
6
|
-
*
|
|
7
|
-
* @module cli/commands/init
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import * as crypto from 'crypto';
|
|
11
|
-
import * as fs from 'fs';
|
|
12
|
-
import * as path from 'path';
|
|
13
|
-
import { Command } from 'commander';
|
|
14
|
-
import {
|
|
15
|
-
saveConfig,
|
|
16
|
-
addToGitignore,
|
|
17
|
-
addToDockerignore,
|
|
18
|
-
addToRailwayignore,
|
|
19
|
-
isInitialized,
|
|
20
|
-
getActpDir,
|
|
21
|
-
CLIConfig,
|
|
22
|
-
CLIMode,
|
|
23
|
-
} from '../utils/config';
|
|
24
|
-
import { Output, ExitCode } from '../utils/output';
|
|
25
|
-
import { generateWallet, computeSmartWalletInit } from '../utils/wallet';
|
|
26
|
-
import { MockStateManager } from '../../runtime/MockStateManager';
|
|
27
|
-
|
|
28
|
-
// ============================================================================
|
|
29
|
-
// Command Definition
|
|
30
|
-
// ============================================================================
|
|
31
|
-
|
|
32
|
-
export function createInitCommand(): Command {
|
|
33
|
-
const cmd = new Command('init')
|
|
34
|
-
.description('Initialize ACTP in the current directory')
|
|
35
|
-
.option('-m, --mode <mode>', 'Operating mode: mock, testnet, mainnet', 'mock')
|
|
36
|
-
.option('-a, --address <address>', 'Your Ethereum address')
|
|
37
|
-
.option('-w, --wallet <type>', 'Wallet type: auto (gas-free Smart Wallet) or eoa (traditional)', 'auto')
|
|
38
|
-
.option('-f, --force', 'Overwrite existing configuration')
|
|
39
|
-
.option('--scaffold', 'Generate a starter agent.ts file')
|
|
40
|
-
.option('--intent <intent>', 'Agent intent: earn, pay, or both (default: earn)')
|
|
41
|
-
.option('--service <name>', 'Service name (default: my-service)')
|
|
42
|
-
.option('--price <usdc>', 'Base price in USDC (default: 1)')
|
|
43
|
-
.option('--json', 'Output as JSON')
|
|
44
|
-
.option('-q, --quiet', 'Minimal output')
|
|
45
|
-
.action(async (options, command) => {
|
|
46
|
-
const output = new Output(
|
|
47
|
-
options.json ? 'json' : options.quiet ? 'quiet' : 'human'
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
try {
|
|
51
|
-
await runInit(options, output, command);
|
|
52
|
-
} catch (error) {
|
|
53
|
-
output.errorResult({
|
|
54
|
-
code: 'INIT_FAILED',
|
|
55
|
-
message: (error as Error).message,
|
|
56
|
-
});
|
|
57
|
-
process.exit(ExitCode.ERROR);
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
return cmd;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// ============================================================================
|
|
65
|
-
// Implementation
|
|
66
|
-
// ============================================================================
|
|
67
|
-
|
|
68
|
-
type ScaffoldIntent = 'earn' | 'pay' | 'both';
|
|
69
|
-
|
|
70
|
-
interface InitOptions {
|
|
71
|
-
mode: string;
|
|
72
|
-
address?: string;
|
|
73
|
-
wallet?: string;
|
|
74
|
-
force?: boolean;
|
|
75
|
-
scaffold?: boolean;
|
|
76
|
-
intent?: string;
|
|
77
|
-
service?: string;
|
|
78
|
-
price?: string;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async function runInit(options: InitOptions, output: Output, cmd?: Command): Promise<void> {
|
|
82
|
-
const projectRoot = process.cwd();
|
|
83
|
-
|
|
84
|
-
// Check if already initialized
|
|
85
|
-
if (isInitialized(projectRoot) && !options.force) {
|
|
86
|
-
throw new Error(
|
|
87
|
-
'ACTP already initialized in this directory.\n' +
|
|
88
|
-
'Use --force to reinitialize.'
|
|
89
|
-
);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// ── AGIRAILS.md pre-fill ──────────────────────────────────────────────
|
|
93
|
-
const agirailsMdPath = path.join(projectRoot, 'AGIRAILS.md');
|
|
94
|
-
let mdConfig: Record<string, unknown> | null = null;
|
|
95
|
-
|
|
96
|
-
if (fs.existsSync(agirailsMdPath)) {
|
|
97
|
-
try {
|
|
98
|
-
const { parseAgirailsMd } = await import('../../config/agirailsmd');
|
|
99
|
-
const parsed = parseAgirailsMd(fs.readFileSync(agirailsMdPath, 'utf-8'));
|
|
100
|
-
mdConfig = parsed.frontmatter;
|
|
101
|
-
} catch {
|
|
102
|
-
output.warning('Found AGIRAILS.md but could not parse it — ignoring');
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// Helper: true when the user explicitly passed a flag on the CLI
|
|
107
|
-
const isExplicit = (flag: string): boolean =>
|
|
108
|
-
cmd?.getOptionValueSource(flag) === 'cli';
|
|
109
|
-
|
|
110
|
-
// Apply AGIRAILS.md values where the user didn't set an explicit flag
|
|
111
|
-
if (mdConfig) {
|
|
112
|
-
// network → mode mapping
|
|
113
|
-
if (!isExplicit('mode') && mdConfig.network) {
|
|
114
|
-
const net = String(mdConfig.network);
|
|
115
|
-
if (net === 'base-sepolia' || net === 'testnet') options.mode = 'testnet';
|
|
116
|
-
else if (net === 'base-mainnet' || net === 'mainnet') options.mode = 'mainnet';
|
|
117
|
-
else if (net === 'mock') options.mode = 'mock';
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// intent
|
|
121
|
-
if (!isExplicit('intent') && mdConfig.intent) {
|
|
122
|
-
options.intent = String(mdConfig.intent);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// capabilities → service (first capability)
|
|
126
|
-
if (!isExplicit('service') && Array.isArray(mdConfig.capabilities) && mdConfig.capabilities.length > 0) {
|
|
127
|
-
options.service = String(mdConfig.capabilities[0]);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// price
|
|
131
|
-
if (!isExplicit('price') && mdConfig.price != null) {
|
|
132
|
-
options.price = String(mdConfig.price);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Log what we pre-filled
|
|
136
|
-
const lines: string[] = [];
|
|
137
|
-
if (mdConfig.network) lines.push(` Mode: ${options.mode}`);
|
|
138
|
-
if (mdConfig.name) lines.push(` Agent: ${String(mdConfig.name)}`);
|
|
139
|
-
if (mdConfig.intent) lines.push(` Intent: ${options.intent || mdConfig.intent}`);
|
|
140
|
-
if (Array.isArray(mdConfig.capabilities)) lines.push(` Capabilities: ${mdConfig.capabilities.join(', ')}`);
|
|
141
|
-
if (mdConfig.price != null) lines.push(` Price: $${mdConfig.price} USDC`);
|
|
142
|
-
|
|
143
|
-
output.info('Found AGIRAILS.md \u2014 using config from file');
|
|
144
|
-
for (const line of lines) {
|
|
145
|
-
output.print(line);
|
|
146
|
-
}
|
|
147
|
-
output.blank();
|
|
148
|
-
}
|
|
149
|
-
// ── End AGIRAILS.md pre-fill ──────────────────────────────────────────
|
|
150
|
-
|
|
151
|
-
// Validate mode
|
|
152
|
-
const validModes: CLIMode[] = ['mock', 'testnet', 'mainnet'];
|
|
153
|
-
if (!validModes.includes(options.mode as CLIMode)) {
|
|
154
|
-
throw new Error(
|
|
155
|
-
`Invalid mode: "${options.mode}". Valid modes: ${validModes.join(', ')}`
|
|
156
|
-
);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
const mode = options.mode as CLIMode;
|
|
160
|
-
|
|
161
|
-
// Determine wallet type
|
|
162
|
-
const walletType = (mode === 'mock') ? 'mock' : (options.wallet || 'auto');
|
|
163
|
-
if (walletType !== 'mock' && walletType !== 'auto' && walletType !== 'eoa') {
|
|
164
|
-
throw new Error(
|
|
165
|
-
`Invalid wallet type: "${walletType}". Valid types: auto, eoa`
|
|
166
|
-
);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Get or generate address
|
|
170
|
-
let address = options.address;
|
|
171
|
-
let smartWalletAddress: string | undefined;
|
|
172
|
-
if (!address) {
|
|
173
|
-
if (mode === 'mock') {
|
|
174
|
-
// Generate a random address for mock mode
|
|
175
|
-
address = '0x' + crypto.randomBytes(20).toString('hex');
|
|
176
|
-
output.info(`Generated mock address: ${address}`);
|
|
177
|
-
} else {
|
|
178
|
-
// Generate a real wallet with encrypted keystore
|
|
179
|
-
const actpDir = getActpDir(projectRoot);
|
|
180
|
-
fs.mkdirSync(actpDir, { recursive: true });
|
|
181
|
-
const eoaAddress = await generateWallet(actpDir, output);
|
|
182
|
-
|
|
183
|
-
if (walletType === 'auto') {
|
|
184
|
-
// Compute Smart Wallet address from signer
|
|
185
|
-
smartWalletAddress = await computeSmartWalletInit(eoaAddress, mode, output);
|
|
186
|
-
address = smartWalletAddress;
|
|
187
|
-
|
|
188
|
-
output.info('');
|
|
189
|
-
output.info('Gas-free transactions enabled (activates on first payment)');
|
|
190
|
-
output.info('Next: run "actp publish" to publish your agent config');
|
|
191
|
-
} else {
|
|
192
|
-
address = eoaAddress;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// Validate address format
|
|
198
|
-
if (!/^0x[a-fA-F0-9]{40}$/.test(address)) {
|
|
199
|
-
throw new Error(
|
|
200
|
-
`Invalid address format: "${address}"\n` +
|
|
201
|
-
'Expected 0x-prefixed 40-character hex string.'
|
|
202
|
-
);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Create configuration
|
|
206
|
-
const config: CLIConfig = {
|
|
207
|
-
mode,
|
|
208
|
-
address: address.toLowerCase(),
|
|
209
|
-
version: '1.0',
|
|
210
|
-
...(walletType !== 'mock' && { wallet: walletType as 'auto' | 'eoa' }),
|
|
211
|
-
...(smartWalletAddress && { smartWallet: smartWalletAddress.toLowerCase() }),
|
|
212
|
-
// AGIRAILS.md-derived values (stored for downstream use)
|
|
213
|
-
...(mdConfig && mdConfig.name ? { agentName: String(mdConfig.name) } : {}),
|
|
214
|
-
...(mdConfig && mdConfig.intent ? { intent: String(mdConfig.intent) as 'earn' | 'pay' | 'both' } : {}),
|
|
215
|
-
...(mdConfig && Array.isArray(mdConfig.capabilities) ? { capabilities: mdConfig.capabilities.map(String) } : {}),
|
|
216
|
-
...(mdConfig && mdConfig.price != null ? { price: Number(mdConfig.price) } : {}),
|
|
217
|
-
...(mdConfig && mdConfig.concurrency != null ? { concurrency: Number(mdConfig.concurrency) } : {}),
|
|
218
|
-
...(mdConfig && mdConfig.payment_mode ? { paymentMode: String(mdConfig.payment_mode) as 'actp' | 'x402' | 'both' } : {}),
|
|
219
|
-
...(mdConfig && mdConfig.budget != null ? { budget: Number(mdConfig.budget) } : {}),
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
// Save configuration
|
|
223
|
-
saveConfig(config, projectRoot);
|
|
224
|
-
output.success('Configuration saved');
|
|
225
|
-
|
|
226
|
-
// Initialize mock state if in mock mode
|
|
227
|
-
if (mode === 'mock') {
|
|
228
|
-
const stateManager = new MockStateManager(projectRoot);
|
|
229
|
-
if (!stateManager.exists() || options.force) {
|
|
230
|
-
stateManager.reset();
|
|
231
|
-
output.success('Mock state initialized');
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Mint initial tokens for the address
|
|
235
|
-
const { MockRuntime } = await import('../../runtime/MockRuntime');
|
|
236
|
-
const runtime = new MockRuntime(stateManager);
|
|
237
|
-
await runtime.mintTokens(address.toLowerCase(), '10000000000'); // 10,000 USDC
|
|
238
|
-
output.info('Minted 10,000 USDC to your address');
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Add to ignore files (AIP-13: gitignore + dockerignore + railwayignore)
|
|
242
|
-
try {
|
|
243
|
-
addToGitignore(projectRoot);
|
|
244
|
-
output.success('Added .actp/ to .gitignore');
|
|
245
|
-
} catch {
|
|
246
|
-
output.warning('Could not update .gitignore (may not exist)');
|
|
247
|
-
}
|
|
248
|
-
try {
|
|
249
|
-
addToDockerignore(projectRoot);
|
|
250
|
-
output.success('Added .actp/ to .dockerignore');
|
|
251
|
-
} catch {
|
|
252
|
-
output.warning('Could not update .dockerignore');
|
|
253
|
-
}
|
|
254
|
-
try {
|
|
255
|
-
addToRailwayignore(projectRoot);
|
|
256
|
-
output.success('Added .actp/ to .railwayignore');
|
|
257
|
-
} catch {
|
|
258
|
-
output.warning('Could not update .railwayignore');
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// Output result
|
|
262
|
-
output.blank();
|
|
263
|
-
output.result(
|
|
264
|
-
{
|
|
265
|
-
initialized: true,
|
|
266
|
-
directory: getActpDir(projectRoot),
|
|
267
|
-
mode,
|
|
268
|
-
address,
|
|
269
|
-
...(walletType !== 'mock' && { wallet: walletType }),
|
|
270
|
-
},
|
|
271
|
-
{ quietKey: 'address' }
|
|
272
|
-
);
|
|
273
|
-
|
|
274
|
-
// Generate scaffold if requested
|
|
275
|
-
if (options.scaffold) {
|
|
276
|
-
await runScaffold(options, mode, output, mdConfig);
|
|
277
|
-
} else {
|
|
278
|
-
output.blank();
|
|
279
|
-
output.print('Next steps:');
|
|
280
|
-
if (walletType === 'auto') {
|
|
281
|
-
output.print(' 1. Publish config: actp publish');
|
|
282
|
-
output.print(' 2. Create a payment: actp pay <provider> <amount>');
|
|
283
|
-
output.print(' 3. Check your balance: actp balance');
|
|
284
|
-
} else {
|
|
285
|
-
output.print(' 1. Create a payment: actp pay <provider> <amount>');
|
|
286
|
-
output.print(' 2. Check your balance: actp balance');
|
|
287
|
-
output.print(' 3. List transactions: actp tx list');
|
|
288
|
-
}
|
|
289
|
-
output.print('');
|
|
290
|
-
output.print('Tip: Use --scaffold to generate a starter agent.ts');
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// ============================================================================
|
|
295
|
-
// Scaffold
|
|
296
|
-
// ============================================================================
|
|
297
|
-
|
|
298
|
-
async function runScaffold(
|
|
299
|
-
options: InitOptions,
|
|
300
|
-
mode: CLIMode,
|
|
301
|
-
output: Output,
|
|
302
|
-
mdConfig?: Record<string, unknown> | null,
|
|
303
|
-
): Promise<void> {
|
|
304
|
-
const validIntents: ScaffoldIntent[] = ['earn', 'pay', 'both'];
|
|
305
|
-
const intent: ScaffoldIntent = (options.intent as ScaffoldIntent) || 'earn';
|
|
306
|
-
|
|
307
|
-
if (!validIntents.includes(intent)) {
|
|
308
|
-
throw new Error(
|
|
309
|
-
`Invalid intent: "${options.intent}". Valid intents: ${validIntents.join(', ')}`
|
|
310
|
-
);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
const service = options.service || 'my-service';
|
|
314
|
-
const price = options.price || '1';
|
|
315
|
-
const agentFile = path.join(process.cwd(), 'agent.ts');
|
|
316
|
-
|
|
317
|
-
// Check if file already exists
|
|
318
|
-
if (fs.existsSync(agentFile) && !options.force) {
|
|
319
|
-
output.warning('agent.ts already exists. Use --force to overwrite.');
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Derive agent name: prefer AGIRAILS.md name, fallback to directory name
|
|
324
|
-
const agentName = (mdConfig?.name ? String(mdConfig.name) : null) || path.basename(process.cwd());
|
|
325
|
-
|
|
326
|
-
// Get template and substitute variables
|
|
327
|
-
const template = getTemplate(intent);
|
|
328
|
-
const content = template
|
|
329
|
-
.replace(/\{\{service\}\}/g, service)
|
|
330
|
-
.replace(/\{\{mode\}\}/g, mode)
|
|
331
|
-
.replace(/\{\{price\}\}/g, price)
|
|
332
|
-
.replace(/\{\{name\}\}/g, agentName);
|
|
333
|
-
|
|
334
|
-
// Atomic write
|
|
335
|
-
const tempFile = `${agentFile}.tmp`;
|
|
336
|
-
try {
|
|
337
|
-
fs.writeFileSync(tempFile, content, 'utf-8');
|
|
338
|
-
fs.renameSync(tempFile, agentFile);
|
|
339
|
-
} catch (error) {
|
|
340
|
-
if (fs.existsSync(tempFile)) {
|
|
341
|
-
try { fs.unlinkSync(tempFile); } catch { /* ignore */ }
|
|
342
|
-
}
|
|
343
|
-
throw error;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
output.success(`Generated agent.ts (intent: ${intent})`);
|
|
347
|
-
|
|
348
|
-
// Generate tsconfig.json if it doesn't exist
|
|
349
|
-
const tsconfigFile = path.join(process.cwd(), 'tsconfig.json');
|
|
350
|
-
if (!fs.existsSync(tsconfigFile)) {
|
|
351
|
-
const tsconfigContent = JSON.stringify({
|
|
352
|
-
compilerOptions: {
|
|
353
|
-
target: 'ES2022',
|
|
354
|
-
module: 'commonjs',
|
|
355
|
-
moduleResolution: 'node',
|
|
356
|
-
esModuleInterop: true,
|
|
357
|
-
strict: true,
|
|
358
|
-
outDir: 'dist',
|
|
359
|
-
skipLibCheck: true,
|
|
360
|
-
},
|
|
361
|
-
include: ['*.ts'],
|
|
362
|
-
}, null, 2);
|
|
363
|
-
|
|
364
|
-
const tsconfigTemp = `${tsconfigFile}.tmp`;
|
|
365
|
-
try {
|
|
366
|
-
fs.writeFileSync(tsconfigTemp, tsconfigContent, 'utf-8');
|
|
367
|
-
fs.renameSync(tsconfigTemp, tsconfigFile);
|
|
368
|
-
output.success('Generated tsconfig.json');
|
|
369
|
-
} catch {
|
|
370
|
-
output.warning('Could not generate tsconfig.json');
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
// Note: @agirails/sdk is CJS — no type:module check needed
|
|
375
|
-
|
|
376
|
-
output.blank();
|
|
377
|
-
output.print('Next steps:');
|
|
378
|
-
output.print(' 1. Edit agent.ts with your logic');
|
|
379
|
-
output.print(' 2. Run: npx ts-node --esm agent.ts');
|
|
380
|
-
output.print(' 3. Check balance: actp balance');
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
function getTemplate(intent: ScaffoldIntent): string {
|
|
384
|
-
switch (intent) {
|
|
385
|
-
case 'earn':
|
|
386
|
-
return TEMPLATE_EARN;
|
|
387
|
-
case 'pay':
|
|
388
|
-
return TEMPLATE_PAY;
|
|
389
|
-
case 'both':
|
|
390
|
-
return TEMPLATE_BOTH;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
// ============================================================================
|
|
395
|
-
// Templates
|
|
396
|
-
// ============================================================================
|
|
397
|
-
|
|
398
|
-
const TEMPLATE_EARN = `import { provide } from '@agirails/sdk';
|
|
399
|
-
|
|
400
|
-
const provider = provide('{{service}}', async (job) => {
|
|
401
|
-
console.log(\`Job received: \${job.id} (\${job.budget} USDC)\`);
|
|
402
|
-
|
|
403
|
-
// TODO: Replace with your actual work
|
|
404
|
-
const result = await processJob(job.input);
|
|
405
|
-
|
|
406
|
-
return result;
|
|
407
|
-
}, {
|
|
408
|
-
network: '{{mode}}',
|
|
409
|
-
filter: { minBudget: {{price}} },
|
|
410
|
-
});
|
|
411
|
-
|
|
412
|
-
async function processJob(input: any): Promise<any> {
|
|
413
|
-
// Your logic here
|
|
414
|
-
return { status: 'completed', output: input };
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
console.log(\`Provider listening for '{{service}}' jobs...\`);
|
|
418
|
-
`;
|
|
419
|
-
|
|
420
|
-
const TEMPLATE_PAY = `import { request } from '@agirails/sdk';
|
|
421
|
-
|
|
422
|
-
async function main() {
|
|
423
|
-
const { result, transaction } = await request('{{service}}', {
|
|
424
|
-
provider: '0xPROVIDER_ADDRESS', // replace with the provider's address
|
|
425
|
-
input: { /* your data here */ },
|
|
426
|
-
budget: {{price}},
|
|
427
|
-
network: '{{mode}}',
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
console.log('Result:', result);
|
|
431
|
-
console.log('Transaction:', transaction.id);
|
|
432
|
-
console.log('Fee:', transaction.fee, 'USDC');
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
main().catch(console.error);
|
|
436
|
-
`;
|
|
437
|
-
|
|
438
|
-
const TEMPLATE_BOTH = `import { Agent } from '@agirails/sdk';
|
|
439
|
-
|
|
440
|
-
async function main() {
|
|
441
|
-
const agent = new Agent({
|
|
442
|
-
name: '{{name}}',
|
|
443
|
-
network: '{{mode}}',
|
|
444
|
-
behavior: {
|
|
445
|
-
autoAccept: true,
|
|
446
|
-
concurrency: 10,
|
|
447
|
-
},
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
// Provide a service
|
|
451
|
-
agent.provide('{{service}}', async (job, ctx) => {
|
|
452
|
-
ctx.progress(50, 'Working...');
|
|
453
|
-
|
|
454
|
-
// TODO: Replace with your actual work
|
|
455
|
-
return { status: 'completed', output: job.input };
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
agent.on('payment:received', (data) => {
|
|
459
|
-
console.log(\`Earned \${data.amount} USDC\`);
|
|
460
|
-
});
|
|
461
|
-
|
|
462
|
-
await agent.start();
|
|
463
|
-
console.log(\`Agent '{{name}}' running on {{mode}}\`);
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
main().catch(console.error);
|
|
467
|
-
`;
|
|
468
|
-
|
|
469
|
-
export { runInit };
|
package/src/cli/commands/mint.ts
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mint Command - Mint test USDC tokens (mock mode only)
|
|
3
|
-
*
|
|
4
|
-
* Useful for testing scenarios where you need to fund accounts.
|
|
5
|
-
*
|
|
6
|
-
* @module cli/commands/mint
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { Command } from 'commander';
|
|
10
|
-
import { Output, ExitCode } from '../utils/output';
|
|
11
|
-
import { createClient, mapError } from '../utils/client';
|
|
12
|
-
import { loadConfig } from '../utils/config';
|
|
13
|
-
|
|
14
|
-
// ============================================================================
|
|
15
|
-
// Command Definition
|
|
16
|
-
// ============================================================================
|
|
17
|
-
|
|
18
|
-
export function createMintCommand(): Command {
|
|
19
|
-
const cmd = new Command('mint')
|
|
20
|
-
.description('Mint test USDC tokens (mock mode only)')
|
|
21
|
-
.argument('<address>', 'Address to mint tokens to')
|
|
22
|
-
.argument('<amount>', 'Amount to mint (in USDC, e.g., "1000")')
|
|
23
|
-
.option('--json', 'Output as JSON')
|
|
24
|
-
.option('-q, --quiet', 'Minimal output')
|
|
25
|
-
.action(async (address, amount, options) => {
|
|
26
|
-
const output = new Output(
|
|
27
|
-
options.json ? 'json' : options.quiet ? 'quiet' : 'human'
|
|
28
|
-
);
|
|
29
|
-
|
|
30
|
-
try {
|
|
31
|
-
await runMint(address, amount, output);
|
|
32
|
-
} catch (error) {
|
|
33
|
-
const structuredError = mapError(error);
|
|
34
|
-
output.errorResult({
|
|
35
|
-
code: structuredError.code,
|
|
36
|
-
message: structuredError.message,
|
|
37
|
-
details: structuredError.details,
|
|
38
|
-
});
|
|
39
|
-
process.exit(ExitCode.ERROR);
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
return cmd;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// ============================================================================
|
|
47
|
-
// Implementation
|
|
48
|
-
// ============================================================================
|
|
49
|
-
|
|
50
|
-
async function runMint(
|
|
51
|
-
address: string,
|
|
52
|
-
amount: string,
|
|
53
|
-
output: Output
|
|
54
|
-
): Promise<void> {
|
|
55
|
-
// Check we're in mock mode
|
|
56
|
-
const config = loadConfig();
|
|
57
|
-
if (config.mode !== 'mock') {
|
|
58
|
-
throw new Error(
|
|
59
|
-
'Mint command only available in mock mode.\n' +
|
|
60
|
-
'You cannot mint real USDC on testnet/mainnet.'
|
|
61
|
-
);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Validate address format
|
|
65
|
-
if (!/^0x[a-fA-F0-9]{40}$/.test(address)) {
|
|
66
|
-
throw new Error(
|
|
67
|
-
`Invalid address format: "${address}"\n` +
|
|
68
|
-
'Expected 0x-prefixed 40-character hex string.'
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Parse amount (user enters USDC, we convert to wei)
|
|
73
|
-
const amountNum = parseFloat(amount);
|
|
74
|
-
if (isNaN(amountNum) || amountNum <= 0) {
|
|
75
|
-
throw new Error(
|
|
76
|
-
`Invalid amount: "${amount}"\n` +
|
|
77
|
-
'Expected positive number (e.g., "1000" for 1000 USDC).'
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Convert to wei (USDC has 6 decimals)
|
|
82
|
-
const amountWei = Math.floor(amountNum * 1_000_000).toString();
|
|
83
|
-
|
|
84
|
-
// Create client and mint
|
|
85
|
-
const client = await createClient();
|
|
86
|
-
await client.mintTokens(address.toLowerCase(), amountWei);
|
|
87
|
-
|
|
88
|
-
// Get new balance
|
|
89
|
-
const newBalance = await client.getBalance(address.toLowerCase());
|
|
90
|
-
|
|
91
|
-
output.result(
|
|
92
|
-
{
|
|
93
|
-
address,
|
|
94
|
-
minted: `${amountNum} USDC`,
|
|
95
|
-
mintedWei: amountWei,
|
|
96
|
-
newBalance: `${formatUsdc(newBalance)} USDC`,
|
|
97
|
-
},
|
|
98
|
-
{ quietKey: 'newBalance' }
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
output.success(`Minted ${amountNum} USDC to ${address}`);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Format USDC amount from wei to decimal
|
|
106
|
-
*/
|
|
107
|
-
function formatUsdc(weiAmount: string): string {
|
|
108
|
-
const amount = BigInt(weiAmount);
|
|
109
|
-
const whole = amount / 1_000_000n;
|
|
110
|
-
const decimal = amount % 1_000_000n;
|
|
111
|
-
const decimalStr = decimal.toString().padStart(6, '0').slice(0, 2);
|
|
112
|
-
const wholeFormatted = whole.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
113
|
-
return `${wholeFormatted}.${decimalStr}`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export { runMint };
|
package/src/cli/commands/pay.ts
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pay Command - One-liner payment command (basic API)
|
|
3
|
-
*
|
|
4
|
-
* The simplest way to create a payment transaction.
|
|
5
|
-
* Creates transaction, links escrow, and returns immediately.
|
|
6
|
-
*
|
|
7
|
-
* @module cli/commands/pay
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { Command } from 'commander';
|
|
11
|
-
import { Output, ExitCode } from '../utils/output';
|
|
12
|
-
import { createClient, mapError } from '../utils/client';
|
|
13
|
-
|
|
14
|
-
// ============================================================================
|
|
15
|
-
// Command Definition
|
|
16
|
-
// ============================================================================
|
|
17
|
-
|
|
18
|
-
export function createPayCommand(): Command {
|
|
19
|
-
const cmd = new Command('pay')
|
|
20
|
-
.description('Create a payment transaction (simplest API)')
|
|
21
|
-
.argument('<to>', 'Provider address (recipient)')
|
|
22
|
-
.argument('<amount>', 'Amount to pay (e.g., "100", "100.50", "100 USDC")')
|
|
23
|
-
.option('-d, --deadline <deadline>', 'Deadline (+24h, +7d, or Unix timestamp)', '+24h')
|
|
24
|
-
.option('-w, --dispute-window <seconds>', 'Dispute window in seconds', '172800')
|
|
25
|
-
.option('--json', 'Output as JSON')
|
|
26
|
-
.option('-q, --quiet', 'Output only the transaction ID')
|
|
27
|
-
.action(async (to, amount, options) => {
|
|
28
|
-
const output = new Output(
|
|
29
|
-
options.json ? 'json' : options.quiet ? 'quiet' : 'human'
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
await runPay(to, amount, options, output);
|
|
34
|
-
} catch (error) {
|
|
35
|
-
const structuredError = mapError(error);
|
|
36
|
-
output.errorResult({
|
|
37
|
-
code: structuredError.code,
|
|
38
|
-
message: structuredError.message,
|
|
39
|
-
details: structuredError.details,
|
|
40
|
-
});
|
|
41
|
-
process.exit(ExitCode.ERROR);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
return cmd;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// ============================================================================
|
|
49
|
-
// Implementation
|
|
50
|
-
// ============================================================================
|
|
51
|
-
|
|
52
|
-
interface PayOptions {
|
|
53
|
-
deadline: string;
|
|
54
|
-
disputeWindow: string;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async function runPay(
|
|
58
|
-
to: string,
|
|
59
|
-
amount: string,
|
|
60
|
-
options: PayOptions,
|
|
61
|
-
output: Output
|
|
62
|
-
): Promise<void> {
|
|
63
|
-
// Create spinner for human mode
|
|
64
|
-
const spinner = output.spinner('Creating payment...');
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
// Create client
|
|
68
|
-
const client = await createClient();
|
|
69
|
-
|
|
70
|
-
// Parse options
|
|
71
|
-
let deadline: string | number = options.deadline;
|
|
72
|
-
if (/^\d+$/.test(options.deadline)) {
|
|
73
|
-
deadline = parseInt(options.deadline, 10);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const disputeWindow = parseInt(options.disputeWindow, 10);
|
|
77
|
-
|
|
78
|
-
// Create payment
|
|
79
|
-
const result = await client.basic.pay({
|
|
80
|
-
to,
|
|
81
|
-
amount,
|
|
82
|
-
deadline,
|
|
83
|
-
disputeWindow,
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
spinner.stop(true);
|
|
87
|
-
|
|
88
|
-
// Output result
|
|
89
|
-
output.result(
|
|
90
|
-
{
|
|
91
|
-
txId: result.txId,
|
|
92
|
-
state: result.state,
|
|
93
|
-
provider: result.provider,
|
|
94
|
-
requester: result.requester,
|
|
95
|
-
amount: result.amount,
|
|
96
|
-
deadline: result.deadline,
|
|
97
|
-
},
|
|
98
|
-
{ quietKey: 'txId' }
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
output.blank();
|
|
102
|
-
output.success('Payment created and funded!');
|
|
103
|
-
output.print('');
|
|
104
|
-
output.print('Next steps:');
|
|
105
|
-
output.print(' - Provider delivers: actp tx deliver ' + result.txId.slice(0, 10) + '...');
|
|
106
|
-
output.print(' - Check status: actp tx status ' + result.txId.slice(0, 10) + '...');
|
|
107
|
-
} catch (error) {
|
|
108
|
-
spinner.stop(false);
|
|
109
|
-
throw error;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export { runPay };
|