dacty-create 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/dacty-create.mjs +143 -98
- package/lib/index.mjs +143 -98
- package/package.json +1 -1
package/bin/dacty-create.mjs
CHANGED
|
@@ -3,28 +3,29 @@
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import inquirer from 'inquirer';
|
|
5
5
|
import ora from 'ora';
|
|
6
|
-
import axios from 'axios';
|
|
7
6
|
import fs from 'fs';
|
|
8
7
|
import path from 'path';
|
|
9
8
|
import { fileURLToPath } from 'url';
|
|
10
9
|
import { dirname } from 'path';
|
|
10
|
+
import crypto from 'crypto';
|
|
11
11
|
|
|
12
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
13
|
const __dirname = dirname(__filename);
|
|
14
14
|
|
|
15
15
|
// Generate unique DNA (identifier)
|
|
16
16
|
function generateDNA() {
|
|
17
|
-
return
|
|
17
|
+
return crypto.randomBytes(16).toString('hex');
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
// Generate wallet
|
|
20
|
+
// Generate wallet (Ethereum-style)
|
|
21
21
|
function generateWallet() {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
const privateKey = crypto.randomBytes(32).toString('hex');
|
|
23
|
+
return {
|
|
24
|
+
privateKey: '0x' + privateKey,
|
|
25
|
+
// Note: In production, derive address from private key using ethers.js
|
|
26
|
+
// For now, generate a mock address
|
|
27
|
+
address: '0x' + crypto.randomBytes(20).toString('hex')
|
|
28
|
+
};
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
async function createAgent() {
|
|
@@ -64,14 +65,8 @@ async function createAgent() {
|
|
|
64
65
|
{
|
|
65
66
|
type: 'input',
|
|
66
67
|
name: 'githubUsername',
|
|
67
|
-
message: 'GitHub Username (
|
|
68
|
-
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
type: 'confirm',
|
|
72
|
-
name: 'createRepo',
|
|
73
|
-
message: 'Create GitHub repository for this agent?',
|
|
74
|
-
default: true
|
|
68
|
+
message: 'GitHub Username (optional):',
|
|
69
|
+
default: ''
|
|
75
70
|
}
|
|
76
71
|
]);
|
|
77
72
|
|
|
@@ -80,8 +75,7 @@ async function createAgent() {
|
|
|
80
75
|
try {
|
|
81
76
|
// Generate agent data
|
|
82
77
|
const agentDNA = generateDNA();
|
|
83
|
-
const
|
|
84
|
-
const tokenSymbol = generateTokenSymbol(answers.agentName);
|
|
78
|
+
const wallet = generateWallet();
|
|
85
79
|
const timestamp = new Date().toISOString();
|
|
86
80
|
|
|
87
81
|
spinner.start('Generating agent configuration...');
|
|
@@ -92,32 +86,18 @@ async function createAgent() {
|
|
|
92
86
|
description: answers.description,
|
|
93
87
|
type: answers.agentType,
|
|
94
88
|
dna: agentDNA,
|
|
95
|
-
wallet:
|
|
96
|
-
token: {
|
|
97
|
-
symbol: tokenSymbol,
|
|
98
|
-
name: `${answers.agentName} Token`,
|
|
99
|
-
totalSupply: '1000000000000000000000000', // 1M tokens
|
|
100
|
-
decimals: 18
|
|
101
|
-
},
|
|
102
|
-
feeDistribution: {
|
|
103
|
-
agent: 80,
|
|
104
|
-
dactyclaw: 20
|
|
105
|
-
},
|
|
89
|
+
wallet: wallet.address,
|
|
106
90
|
createdAt: timestamp,
|
|
107
|
-
github: {
|
|
108
|
-
username: answers.githubUsername,
|
|
109
|
-
repository: `${answers.agentName.toLowerCase().replace(/\s+/g, '-')}-agent`,
|
|
110
|
-
createRepo: answers.createRepo
|
|
111
|
-
},
|
|
112
91
|
network: 'base',
|
|
113
|
-
status: 'created'
|
|
92
|
+
status: 'created',
|
|
93
|
+
version: '1.0.0'
|
|
114
94
|
};
|
|
115
95
|
|
|
116
96
|
spinner.succeed('Agent configuration generated');
|
|
117
97
|
|
|
118
98
|
// Create agent directory
|
|
119
99
|
spinner.start('Creating agent directory...');
|
|
120
|
-
const agentDir = path.join(process.cwd(),
|
|
100
|
+
const agentDir = path.join(process.cwd(), answers.agentName.toLowerCase().replace(/\s+/g, '-') + '-agent');
|
|
121
101
|
|
|
122
102
|
if (!fs.existsSync(agentDir)) {
|
|
123
103
|
fs.mkdirSync(agentDir, { recursive: true });
|
|
@@ -125,26 +105,47 @@ async function createAgent() {
|
|
|
125
105
|
|
|
126
106
|
spinner.succeed(`Agent directory created at ${agentDir}`);
|
|
127
107
|
|
|
128
|
-
// Create config file
|
|
108
|
+
// Create config file (safe - no private key)
|
|
129
109
|
spinner.start('Writing configuration files...');
|
|
130
110
|
|
|
131
111
|
const configPath = path.join(agentDir, 'agent.config.json');
|
|
132
112
|
fs.writeFileSync(configPath, JSON.stringify(agentConfig, null, 2));
|
|
133
113
|
|
|
134
|
-
// Create .env file
|
|
135
|
-
const envContent =
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
114
|
+
// Create .env file with private key (gitignored)
|
|
115
|
+
const envContent = `# DACTYCLAW Agent Environment Variables
|
|
116
|
+
# IMPORTANT: Keep this file secret! Never commit to version control!
|
|
117
|
+
|
|
118
|
+
AGENT_NAME="${agentConfig.name}"
|
|
119
|
+
AGENT_DNA="${agentConfig.dna}"
|
|
120
|
+
AGENT_WALLET="${wallet.address}"
|
|
121
|
+
AGENT_PRIVATE_KEY="${wallet.privateKey}"
|
|
122
|
+
NETWORK="base"
|
|
123
|
+
GITHUB_USERNAME="${answers.githubUsername || ''}"
|
|
124
|
+
|
|
125
|
+
# Clanker API (optional - user can add their own)
|
|
126
|
+
# CLANKER_API_KEY=""
|
|
142
127
|
`;
|
|
143
128
|
fs.writeFileSync(path.join(agentDir, '.env'), envContent);
|
|
144
129
|
|
|
130
|
+
// Create .env.example (safe - no private key)
|
|
131
|
+
const envExampleContent = `# DACTYCLAW Agent Environment Variables
|
|
132
|
+
# Copy this file to .env and fill in your values
|
|
133
|
+
|
|
134
|
+
AGENT_NAME="MyAgent"
|
|
135
|
+
AGENT_DNA="your-agent-dna"
|
|
136
|
+
AGENT_WALLET="0x..."
|
|
137
|
+
AGENT_PRIVATE_KEY="0x..."
|
|
138
|
+
NETWORK="base"
|
|
139
|
+
GITHUB_USERNAME=""
|
|
140
|
+
|
|
141
|
+
# Clanker API (optional)
|
|
142
|
+
# CLANKER_API_KEY=""
|
|
143
|
+
`;
|
|
144
|
+
fs.writeFileSync(path.join(agentDir, '.env.example'), envExampleContent);
|
|
145
|
+
|
|
145
146
|
// Create package.json for agent
|
|
146
147
|
const agentPackageJson = {
|
|
147
|
-
name: agentConfig.
|
|
148
|
+
name: agentConfig.name.toLowerCase().replace(/\s+/g, '-') + '-agent',
|
|
148
149
|
version: '1.0.0',
|
|
149
150
|
description: agentConfig.description,
|
|
150
151
|
type: 'module',
|
|
@@ -152,15 +153,16 @@ GITHUB_REPO=${agentConfig.github.repository}
|
|
|
152
153
|
scripts: {
|
|
153
154
|
start: 'node src/index.mjs',
|
|
154
155
|
dev: 'node --watch src/index.mjs',
|
|
155
|
-
|
|
156
|
+
launch: 'node scripts/launch.mjs'
|
|
156
157
|
},
|
|
157
|
-
keywords: ['agent', 'dactyclaw', 'blockchain'],
|
|
158
|
-
author:
|
|
158
|
+
keywords: ['agent', 'dactyclaw', 'blockchain', 'base'],
|
|
159
|
+
author: answers.githubUsername || 'Dactyclaw Agent',
|
|
159
160
|
license: 'MIT',
|
|
160
161
|
dependencies: {
|
|
161
162
|
'ethers': '^6.10.0',
|
|
162
163
|
'dotenv': '^16.3.1',
|
|
163
|
-
'axios': '^1.6.5'
|
|
164
|
+
'axios': '^1.6.5',
|
|
165
|
+
'chalk': '^5.3.0'
|
|
164
166
|
}
|
|
165
167
|
};
|
|
166
168
|
fs.writeFileSync(path.join(agentDir, 'package.json'), JSON.stringify(agentPackageJson, null, 2));
|
|
@@ -173,19 +175,21 @@ import { ethers } from 'ethers';
|
|
|
173
175
|
|
|
174
176
|
dotenv.config();
|
|
175
177
|
|
|
176
|
-
const AGENT_NAME = process.env.AGENT_NAME || '
|
|
177
|
-
const AGENT_DNA = process.env.AGENT_DNA || '
|
|
178
|
+
const AGENT_NAME = process.env.AGENT_NAME || 'Agent';
|
|
179
|
+
const AGENT_DNA = process.env.AGENT_DNA || '';
|
|
180
|
+
const AGENT_WALLET = process.env.AGENT_WALLET || '';
|
|
178
181
|
const NETWORK = process.env.NETWORK || 'base';
|
|
179
182
|
|
|
180
183
|
console.log(\`
|
|
181
184
|
╔════════════════════════════════════════╗
|
|
182
185
|
║ DACTYCLAW AGENT - \${AGENT_NAME}
|
|
183
|
-
║ DNA: \${AGENT_DNA}
|
|
186
|
+
║ DNA: \${AGENT_DNA.substring(0, 16)}...
|
|
187
|
+
║ Wallet: \${AGENT_WALLET.substring(0, 10)}...
|
|
184
188
|
║ Network: \${NETWORK}
|
|
185
189
|
╚════════════════════════════════════════╝
|
|
186
190
|
\`);
|
|
187
191
|
|
|
188
|
-
// Initialize RPC provider
|
|
192
|
+
// Initialize RPC provider for Base network
|
|
189
193
|
const rpcUrl = 'https://mainnet.base.org';
|
|
190
194
|
const provider = new ethers.JsonRpcProvider(rpcUrl);
|
|
191
195
|
|
|
@@ -201,6 +205,10 @@ async function main() {
|
|
|
201
205
|
const network = await provider.getNetwork();
|
|
202
206
|
console.log(\`[Agent] Network: \${network.name} (chainId: \${network.chainId})\`);
|
|
203
207
|
|
|
208
|
+
// Get wallet balance
|
|
209
|
+
const balance = await provider.getBalance(process.env.AGENT_WALLET);
|
|
210
|
+
console.log(\`[Agent] Wallet balance: \${ethers.formatEther(balance)} ETH\`);
|
|
211
|
+
|
|
204
212
|
// Agent is running
|
|
205
213
|
console.log('[Agent] Agent is running and monitoring the network...');
|
|
206
214
|
console.log('[Agent] Press Ctrl+C to stop');
|
|
@@ -209,7 +217,7 @@ async function main() {
|
|
|
209
217
|
setInterval(async () => {
|
|
210
218
|
const latestBlock = await provider.getBlockNumber();
|
|
211
219
|
console.log(\`[Agent] Latest block: \${latestBlock}\`);
|
|
212
|
-
},
|
|
220
|
+
}, 30000); // Check every 30 seconds
|
|
213
221
|
|
|
214
222
|
} catch (error) {
|
|
215
223
|
console.error('[Agent] Error:', error);
|
|
@@ -221,35 +229,35 @@ main();
|
|
|
221
229
|
`;
|
|
222
230
|
fs.writeFileSync(path.join(agentDir, 'src', 'index.mjs'), agentCode);
|
|
223
231
|
|
|
224
|
-
// Create scripts directory with
|
|
232
|
+
// Create scripts directory with launch script
|
|
225
233
|
fs.mkdirSync(path.join(agentDir, 'scripts'), { recursive: true });
|
|
226
234
|
|
|
227
|
-
const
|
|
235
|
+
const launchScript = `import dotenv from 'dotenv';
|
|
228
236
|
|
|
229
237
|
dotenv.config();
|
|
230
238
|
|
|
231
239
|
const AGENT_NAME = process.env.AGENT_NAME;
|
|
232
240
|
const AGENT_DNA = process.env.AGENT_DNA;
|
|
233
241
|
const AGENT_WALLET = process.env.AGENT_WALLET;
|
|
234
|
-
const
|
|
242
|
+
const AGENT_PRIVATE_KEY = process.env.AGENT_PRIVATE_KEY;
|
|
235
243
|
|
|
236
244
|
console.log(\`
|
|
237
245
|
╔════════════════════════════════════════╗
|
|
238
|
-
║ DACTYCLAW
|
|
246
|
+
║ DACTYCLAW TOKEN LAUNCH
|
|
239
247
|
║ Agent: \${AGENT_NAME}
|
|
240
248
|
║ DNA: \${AGENT_DNA}
|
|
241
249
|
║ Wallet: \${AGENT_WALLET}
|
|
242
|
-
║ Token: \${TOKEN_SYMBOL}
|
|
243
250
|
╚════════════════════════════════════════╝
|
|
244
251
|
\`);
|
|
245
252
|
|
|
246
|
-
console.log('\\n[
|
|
247
|
-
console.log('[
|
|
248
|
-
console.log('[
|
|
249
|
-
console.log('[
|
|
250
|
-
console.log('[
|
|
253
|
+
console.log('\\n[Launch] Preparing to launch token...');
|
|
254
|
+
console.log('[Launch] ✓ Agent configuration loaded');
|
|
255
|
+
console.log('[Launch] ✓ Wallet ready');
|
|
256
|
+
console.log('[Launch] ✓ Private key loaded');
|
|
257
|
+
console.log('[Launch] ✓ Ready to deploy!');
|
|
258
|
+
console.log('\\n[Launch] Next step: npx dacty-launch');
|
|
251
259
|
`;
|
|
252
|
-
fs.writeFileSync(path.join(agentDir, 'scripts', '
|
|
260
|
+
fs.writeFileSync(path.join(agentDir, 'scripts', 'launch.mjs'), launchScript);
|
|
253
261
|
|
|
254
262
|
// Create README
|
|
255
263
|
const readmeContent = `# ${agentConfig.name}
|
|
@@ -260,16 +268,10 @@ An autonomous agent in the Dactyclaw ecosystem.
|
|
|
260
268
|
|
|
261
269
|
- **Agent Name:** ${agentConfig.name}
|
|
262
270
|
- **Agent DNA:** ${agentConfig.dna}
|
|
263
|
-
- **Wallet:** ${
|
|
264
|
-
- **
|
|
265
|
-
- **Network:** ${agentConfig.network}
|
|
271
|
+
- **Wallet:** ${wallet.address}
|
|
272
|
+
- **Network:** Base
|
|
266
273
|
- **Type:** ${agentConfig.agentType}
|
|
267
274
|
|
|
268
|
-
## Fee Distribution
|
|
269
|
-
|
|
270
|
-
- Agent: 80%
|
|
271
|
-
- Dactyclaw: 20%
|
|
272
|
-
|
|
273
275
|
## Getting Started
|
|
274
276
|
|
|
275
277
|
\`\`\`bash
|
|
@@ -277,12 +279,42 @@ npm install
|
|
|
277
279
|
npm run dev
|
|
278
280
|
\`\`\`
|
|
279
281
|
|
|
280
|
-
##
|
|
282
|
+
## Environment Variables
|
|
283
|
+
|
|
284
|
+
This project uses a \`.env\` file to store sensitive information including your private key.
|
|
285
|
+
|
|
286
|
+
**⚠️ IMPORTANT: Never commit \`.env\` to version control!**
|
|
287
|
+
|
|
288
|
+
The \`.env\` file is already in \`.gitignore\` for your safety.
|
|
289
|
+
|
|
290
|
+
## Launch Token
|
|
291
|
+
|
|
292
|
+
To launch your token on Clanker:
|
|
281
293
|
|
|
282
294
|
\`\`\`bash
|
|
283
|
-
|
|
295
|
+
npx dacty-launch
|
|
284
296
|
\`\`\`
|
|
285
297
|
|
|
298
|
+
This will:
|
|
299
|
+
1. Use your private key to sign transactions
|
|
300
|
+
2. Deploy token to Base network via Clanker
|
|
301
|
+
3. Setup fee distribution (80% to your wallet, 20% to Dactyclaw)
|
|
302
|
+
|
|
303
|
+
## Fee Distribution
|
|
304
|
+
|
|
305
|
+
Once your token is launched:
|
|
306
|
+
- **80%** of trading fees go to your agent wallet
|
|
307
|
+
- **20%** of trading fees go to Dactyclaw
|
|
308
|
+
|
|
309
|
+
Monitor your fees on [Clanker.world](https://clanker.world)
|
|
310
|
+
|
|
311
|
+
## Security
|
|
312
|
+
|
|
313
|
+
- Keep your \`.env\` file private
|
|
314
|
+
- Never share your private key
|
|
315
|
+
- Never commit \`.env\` to version control
|
|
316
|
+
- Use a hardware wallet for production
|
|
317
|
+
|
|
286
318
|
## License
|
|
287
319
|
|
|
288
320
|
MIT
|
|
@@ -293,13 +325,32 @@ MIT
|
|
|
293
325
|
const gitignore = `node_modules/
|
|
294
326
|
.env
|
|
295
327
|
.env.local
|
|
328
|
+
.env.*.local
|
|
296
329
|
dist/
|
|
297
330
|
build/
|
|
298
331
|
*.log
|
|
332
|
+
npm-debug.log*
|
|
333
|
+
yarn-debug.log*
|
|
334
|
+
yarn-error.log*
|
|
299
335
|
.DS_Store
|
|
336
|
+
.vscode/
|
|
337
|
+
.idea/
|
|
338
|
+
*.swp
|
|
339
|
+
*.swo
|
|
340
|
+
*~
|
|
341
|
+
.pnpm-store/
|
|
342
|
+
pnpm-lock.yaml
|
|
343
|
+
package-lock.json
|
|
300
344
|
`;
|
|
301
345
|
fs.writeFileSync(path.join(agentDir, '.gitignore'), gitignore);
|
|
302
346
|
|
|
347
|
+
// Create .gitattributes to ensure .env is never committed
|
|
348
|
+
const gitattributes = `# Ensure .env files are never committed
|
|
349
|
+
.env export-ignore
|
|
350
|
+
.env.* export-ignore
|
|
351
|
+
`;
|
|
352
|
+
fs.writeFileSync(path.join(agentDir, '.gitattributes'), gitattributes);
|
|
353
|
+
|
|
303
354
|
spinner.succeed('Configuration files created');
|
|
304
355
|
|
|
305
356
|
// Display summary
|
|
@@ -307,38 +358,32 @@ build/
|
|
|
307
358
|
console.log(chalk.green.bold('✓ Agent created successfully!'));
|
|
308
359
|
console.log('\n');
|
|
309
360
|
console.log(chalk.cyan('Agent Details:'));
|
|
310
|
-
console.log(chalk.gray('─'.repeat(
|
|
361
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
311
362
|
console.log(chalk.white(` Name: ${agentConfig.name}`));
|
|
312
363
|
console.log(chalk.white(` DNA: ${agentConfig.dna}`));
|
|
313
|
-
console.log(chalk.white(` Wallet:
|
|
314
|
-
console.log(chalk.white(` Token Symbol: ${agentConfig.token.symbol}`));
|
|
364
|
+
console.log(chalk.white(` Wallet Address: ${wallet.address}`));
|
|
315
365
|
console.log(chalk.white(` Type: ${agentConfig.agentType}`));
|
|
316
366
|
console.log(chalk.white(` Network: ${agentConfig.network}`));
|
|
317
367
|
console.log(chalk.white(` Directory: ${agentDir}`));
|
|
318
|
-
console.log(chalk.gray('─'.repeat(
|
|
368
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
369
|
+
console.log('\n');
|
|
370
|
+
|
|
371
|
+
console.log(chalk.cyan('Security Notice:'));
|
|
372
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
373
|
+
console.log(chalk.yellow(` ⚠️ Your private key is stored in .env file`));
|
|
374
|
+
console.log(chalk.yellow(` ⚠️ NEVER commit .env to version control`));
|
|
375
|
+
console.log(chalk.yellow(` ⚠️ Keep your private key safe and secure`));
|
|
376
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
319
377
|
console.log('\n');
|
|
320
378
|
|
|
321
379
|
console.log(chalk.cyan('Next Steps:'));
|
|
322
|
-
console.log(chalk.gray('─'.repeat(
|
|
323
|
-
console.log(chalk.white(` 1. cd ${
|
|
380
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
381
|
+
console.log(chalk.white(` 1. cd ${path.basename(agentDir)}`));
|
|
324
382
|
console.log(chalk.white(` 2. npm install`));
|
|
325
383
|
console.log(chalk.white(` 3. npm run dev`));
|
|
326
|
-
console.log(chalk.
|
|
384
|
+
console.log(chalk.white(` 4. npx dacty-launch (to launch token)`));
|
|
385
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
327
386
|
console.log('\n');
|
|
328
|
-
|
|
329
|
-
console.log(chalk.cyan('Fee Distribution:'));
|
|
330
|
-
console.log(chalk.gray('─'.repeat(50)));
|
|
331
|
-
console.log(chalk.white(` Agent: 80%`));
|
|
332
|
-
console.log(chalk.white(` Dactyclaw: 20%`));
|
|
333
|
-
console.log(chalk.gray('─'.repeat(50)));
|
|
334
|
-
console.log('\n');
|
|
335
|
-
|
|
336
|
-
if (agentConfig.github.createRepo) {
|
|
337
|
-
console.log(chalk.yellow('ℹ GitHub repository creation requires manual setup.'));
|
|
338
|
-
console.log(chalk.yellow(' Visit https://github.com/new to create the repository.'));
|
|
339
|
-
console.log(chalk.yellow(` Repository name: ${agentConfig.github.repository}`));
|
|
340
|
-
console.log('\n');
|
|
341
|
-
}
|
|
342
387
|
|
|
343
388
|
} catch (error) {
|
|
344
389
|
spinner.fail('Error creating agent');
|
package/lib/index.mjs
CHANGED
|
@@ -3,28 +3,29 @@
|
|
|
3
3
|
import chalk from 'chalk';
|
|
4
4
|
import inquirer from 'inquirer';
|
|
5
5
|
import ora from 'ora';
|
|
6
|
-
import axios from 'axios';
|
|
7
6
|
import fs from 'fs';
|
|
8
7
|
import path from 'path';
|
|
9
8
|
import { fileURLToPath } from 'url';
|
|
10
9
|
import { dirname } from 'path';
|
|
10
|
+
import crypto from 'crypto';
|
|
11
11
|
|
|
12
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
13
|
const __dirname = dirname(__filename);
|
|
14
14
|
|
|
15
15
|
// Generate unique DNA (identifier)
|
|
16
16
|
function generateDNA() {
|
|
17
|
-
return
|
|
17
|
+
return crypto.randomBytes(16).toString('hex');
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
// Generate wallet
|
|
20
|
+
// Generate wallet (Ethereum-style)
|
|
21
21
|
function generateWallet() {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
const privateKey = crypto.randomBytes(32).toString('hex');
|
|
23
|
+
return {
|
|
24
|
+
privateKey: '0x' + privateKey,
|
|
25
|
+
// Note: In production, derive address from private key using ethers.js
|
|
26
|
+
// For now, generate a mock address
|
|
27
|
+
address: '0x' + crypto.randomBytes(20).toString('hex')
|
|
28
|
+
};
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
async function createAgent() {
|
|
@@ -64,14 +65,8 @@ async function createAgent() {
|
|
|
64
65
|
{
|
|
65
66
|
type: 'input',
|
|
66
67
|
name: 'githubUsername',
|
|
67
|
-
message: 'GitHub Username (
|
|
68
|
-
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
type: 'confirm',
|
|
72
|
-
name: 'createRepo',
|
|
73
|
-
message: 'Create GitHub repository for this agent?',
|
|
74
|
-
default: true
|
|
68
|
+
message: 'GitHub Username (optional):',
|
|
69
|
+
default: ''
|
|
75
70
|
}
|
|
76
71
|
]);
|
|
77
72
|
|
|
@@ -80,8 +75,7 @@ async function createAgent() {
|
|
|
80
75
|
try {
|
|
81
76
|
// Generate agent data
|
|
82
77
|
const agentDNA = generateDNA();
|
|
83
|
-
const
|
|
84
|
-
const tokenSymbol = generateTokenSymbol(answers.agentName);
|
|
78
|
+
const wallet = generateWallet();
|
|
85
79
|
const timestamp = new Date().toISOString();
|
|
86
80
|
|
|
87
81
|
spinner.start('Generating agent configuration...');
|
|
@@ -92,32 +86,18 @@ async function createAgent() {
|
|
|
92
86
|
description: answers.description,
|
|
93
87
|
type: answers.agentType,
|
|
94
88
|
dna: agentDNA,
|
|
95
|
-
wallet:
|
|
96
|
-
token: {
|
|
97
|
-
symbol: tokenSymbol,
|
|
98
|
-
name: `${answers.agentName} Token`,
|
|
99
|
-
totalSupply: '1000000000000000000000000', // 1M tokens
|
|
100
|
-
decimals: 18
|
|
101
|
-
},
|
|
102
|
-
feeDistribution: {
|
|
103
|
-
agent: 80,
|
|
104
|
-
dactyclaw: 20
|
|
105
|
-
},
|
|
89
|
+
wallet: wallet.address,
|
|
106
90
|
createdAt: timestamp,
|
|
107
|
-
github: {
|
|
108
|
-
username: answers.githubUsername,
|
|
109
|
-
repository: `${answers.agentName.toLowerCase().replace(/\s+/g, '-')}-agent`,
|
|
110
|
-
createRepo: answers.createRepo
|
|
111
|
-
},
|
|
112
91
|
network: 'base',
|
|
113
|
-
status: 'created'
|
|
92
|
+
status: 'created',
|
|
93
|
+
version: '1.0.0'
|
|
114
94
|
};
|
|
115
95
|
|
|
116
96
|
spinner.succeed('Agent configuration generated');
|
|
117
97
|
|
|
118
98
|
// Create agent directory
|
|
119
99
|
spinner.start('Creating agent directory...');
|
|
120
|
-
const agentDir = path.join(process.cwd(),
|
|
100
|
+
const agentDir = path.join(process.cwd(), answers.agentName.toLowerCase().replace(/\s+/g, '-') + '-agent');
|
|
121
101
|
|
|
122
102
|
if (!fs.existsSync(agentDir)) {
|
|
123
103
|
fs.mkdirSync(agentDir, { recursive: true });
|
|
@@ -125,26 +105,47 @@ async function createAgent() {
|
|
|
125
105
|
|
|
126
106
|
spinner.succeed(`Agent directory created at ${agentDir}`);
|
|
127
107
|
|
|
128
|
-
// Create config file
|
|
108
|
+
// Create config file (safe - no private key)
|
|
129
109
|
spinner.start('Writing configuration files...');
|
|
130
110
|
|
|
131
111
|
const configPath = path.join(agentDir, 'agent.config.json');
|
|
132
112
|
fs.writeFileSync(configPath, JSON.stringify(agentConfig, null, 2));
|
|
133
113
|
|
|
134
|
-
// Create .env file
|
|
135
|
-
const envContent =
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
114
|
+
// Create .env file with private key (gitignored)
|
|
115
|
+
const envContent = `# DACTYCLAW Agent Environment Variables
|
|
116
|
+
# IMPORTANT: Keep this file secret! Never commit to version control!
|
|
117
|
+
|
|
118
|
+
AGENT_NAME="${agentConfig.name}"
|
|
119
|
+
AGENT_DNA="${agentConfig.dna}"
|
|
120
|
+
AGENT_WALLET="${wallet.address}"
|
|
121
|
+
AGENT_PRIVATE_KEY="${wallet.privateKey}"
|
|
122
|
+
NETWORK="base"
|
|
123
|
+
GITHUB_USERNAME="${answers.githubUsername || ''}"
|
|
124
|
+
|
|
125
|
+
# Clanker API (optional - user can add their own)
|
|
126
|
+
# CLANKER_API_KEY=""
|
|
142
127
|
`;
|
|
143
128
|
fs.writeFileSync(path.join(agentDir, '.env'), envContent);
|
|
144
129
|
|
|
130
|
+
// Create .env.example (safe - no private key)
|
|
131
|
+
const envExampleContent = `# DACTYCLAW Agent Environment Variables
|
|
132
|
+
# Copy this file to .env and fill in your values
|
|
133
|
+
|
|
134
|
+
AGENT_NAME="MyAgent"
|
|
135
|
+
AGENT_DNA="your-agent-dna"
|
|
136
|
+
AGENT_WALLET="0x..."
|
|
137
|
+
AGENT_PRIVATE_KEY="0x..."
|
|
138
|
+
NETWORK="base"
|
|
139
|
+
GITHUB_USERNAME=""
|
|
140
|
+
|
|
141
|
+
# Clanker API (optional)
|
|
142
|
+
# CLANKER_API_KEY=""
|
|
143
|
+
`;
|
|
144
|
+
fs.writeFileSync(path.join(agentDir, '.env.example'), envExampleContent);
|
|
145
|
+
|
|
145
146
|
// Create package.json for agent
|
|
146
147
|
const agentPackageJson = {
|
|
147
|
-
name: agentConfig.
|
|
148
|
+
name: agentConfig.name.toLowerCase().replace(/\s+/g, '-') + '-agent',
|
|
148
149
|
version: '1.0.0',
|
|
149
150
|
description: agentConfig.description,
|
|
150
151
|
type: 'module',
|
|
@@ -152,15 +153,16 @@ GITHUB_REPO=${agentConfig.github.repository}
|
|
|
152
153
|
scripts: {
|
|
153
154
|
start: 'node src/index.mjs',
|
|
154
155
|
dev: 'node --watch src/index.mjs',
|
|
155
|
-
|
|
156
|
+
launch: 'node scripts/launch.mjs'
|
|
156
157
|
},
|
|
157
|
-
keywords: ['agent', 'dactyclaw', 'blockchain'],
|
|
158
|
-
author:
|
|
158
|
+
keywords: ['agent', 'dactyclaw', 'blockchain', 'base'],
|
|
159
|
+
author: answers.githubUsername || 'Dactyclaw Agent',
|
|
159
160
|
license: 'MIT',
|
|
160
161
|
dependencies: {
|
|
161
162
|
'ethers': '^6.10.0',
|
|
162
163
|
'dotenv': '^16.3.1',
|
|
163
|
-
'axios': '^1.6.5'
|
|
164
|
+
'axios': '^1.6.5',
|
|
165
|
+
'chalk': '^5.3.0'
|
|
164
166
|
}
|
|
165
167
|
};
|
|
166
168
|
fs.writeFileSync(path.join(agentDir, 'package.json'), JSON.stringify(agentPackageJson, null, 2));
|
|
@@ -173,19 +175,21 @@ import { ethers } from 'ethers';
|
|
|
173
175
|
|
|
174
176
|
dotenv.config();
|
|
175
177
|
|
|
176
|
-
const AGENT_NAME = process.env.AGENT_NAME || '
|
|
177
|
-
const AGENT_DNA = process.env.AGENT_DNA || '
|
|
178
|
+
const AGENT_NAME = process.env.AGENT_NAME || 'Agent';
|
|
179
|
+
const AGENT_DNA = process.env.AGENT_DNA || '';
|
|
180
|
+
const AGENT_WALLET = process.env.AGENT_WALLET || '';
|
|
178
181
|
const NETWORK = process.env.NETWORK || 'base';
|
|
179
182
|
|
|
180
183
|
console.log(\`
|
|
181
184
|
╔════════════════════════════════════════╗
|
|
182
185
|
║ DACTYCLAW AGENT - \${AGENT_NAME}
|
|
183
|
-
║ DNA: \${AGENT_DNA}
|
|
186
|
+
║ DNA: \${AGENT_DNA.substring(0, 16)}...
|
|
187
|
+
║ Wallet: \${AGENT_WALLET.substring(0, 10)}...
|
|
184
188
|
║ Network: \${NETWORK}
|
|
185
189
|
╚════════════════════════════════════════╝
|
|
186
190
|
\`);
|
|
187
191
|
|
|
188
|
-
// Initialize RPC provider
|
|
192
|
+
// Initialize RPC provider for Base network
|
|
189
193
|
const rpcUrl = 'https://mainnet.base.org';
|
|
190
194
|
const provider = new ethers.JsonRpcProvider(rpcUrl);
|
|
191
195
|
|
|
@@ -201,6 +205,10 @@ async function main() {
|
|
|
201
205
|
const network = await provider.getNetwork();
|
|
202
206
|
console.log(\`[Agent] Network: \${network.name} (chainId: \${network.chainId})\`);
|
|
203
207
|
|
|
208
|
+
// Get wallet balance
|
|
209
|
+
const balance = await provider.getBalance(process.env.AGENT_WALLET);
|
|
210
|
+
console.log(\`[Agent] Wallet balance: \${ethers.formatEther(balance)} ETH\`);
|
|
211
|
+
|
|
204
212
|
// Agent is running
|
|
205
213
|
console.log('[Agent] Agent is running and monitoring the network...');
|
|
206
214
|
console.log('[Agent] Press Ctrl+C to stop');
|
|
@@ -209,7 +217,7 @@ async function main() {
|
|
|
209
217
|
setInterval(async () => {
|
|
210
218
|
const latestBlock = await provider.getBlockNumber();
|
|
211
219
|
console.log(\`[Agent] Latest block: \${latestBlock}\`);
|
|
212
|
-
},
|
|
220
|
+
}, 30000); // Check every 30 seconds
|
|
213
221
|
|
|
214
222
|
} catch (error) {
|
|
215
223
|
console.error('[Agent] Error:', error);
|
|
@@ -221,35 +229,35 @@ main();
|
|
|
221
229
|
`;
|
|
222
230
|
fs.writeFileSync(path.join(agentDir, 'src', 'index.mjs'), agentCode);
|
|
223
231
|
|
|
224
|
-
// Create scripts directory with
|
|
232
|
+
// Create scripts directory with launch script
|
|
225
233
|
fs.mkdirSync(path.join(agentDir, 'scripts'), { recursive: true });
|
|
226
234
|
|
|
227
|
-
const
|
|
235
|
+
const launchScript = `import dotenv from 'dotenv';
|
|
228
236
|
|
|
229
237
|
dotenv.config();
|
|
230
238
|
|
|
231
239
|
const AGENT_NAME = process.env.AGENT_NAME;
|
|
232
240
|
const AGENT_DNA = process.env.AGENT_DNA;
|
|
233
241
|
const AGENT_WALLET = process.env.AGENT_WALLET;
|
|
234
|
-
const
|
|
242
|
+
const AGENT_PRIVATE_KEY = process.env.AGENT_PRIVATE_KEY;
|
|
235
243
|
|
|
236
244
|
console.log(\`
|
|
237
245
|
╔════════════════════════════════════════╗
|
|
238
|
-
║ DACTYCLAW
|
|
246
|
+
║ DACTYCLAW TOKEN LAUNCH
|
|
239
247
|
║ Agent: \${AGENT_NAME}
|
|
240
248
|
║ DNA: \${AGENT_DNA}
|
|
241
249
|
║ Wallet: \${AGENT_WALLET}
|
|
242
|
-
║ Token: \${TOKEN_SYMBOL}
|
|
243
250
|
╚════════════════════════════════════════╝
|
|
244
251
|
\`);
|
|
245
252
|
|
|
246
|
-
console.log('\\n[
|
|
247
|
-
console.log('[
|
|
248
|
-
console.log('[
|
|
249
|
-
console.log('[
|
|
250
|
-
console.log('[
|
|
253
|
+
console.log('\\n[Launch] Preparing to launch token...');
|
|
254
|
+
console.log('[Launch] ✓ Agent configuration loaded');
|
|
255
|
+
console.log('[Launch] ✓ Wallet ready');
|
|
256
|
+
console.log('[Launch] ✓ Private key loaded');
|
|
257
|
+
console.log('[Launch] ✓ Ready to deploy!');
|
|
258
|
+
console.log('\\n[Launch] Next step: npx dacty-launch');
|
|
251
259
|
`;
|
|
252
|
-
fs.writeFileSync(path.join(agentDir, 'scripts', '
|
|
260
|
+
fs.writeFileSync(path.join(agentDir, 'scripts', 'launch.mjs'), launchScript);
|
|
253
261
|
|
|
254
262
|
// Create README
|
|
255
263
|
const readmeContent = `# ${agentConfig.name}
|
|
@@ -260,16 +268,10 @@ An autonomous agent in the Dactyclaw ecosystem.
|
|
|
260
268
|
|
|
261
269
|
- **Agent Name:** ${agentConfig.name}
|
|
262
270
|
- **Agent DNA:** ${agentConfig.dna}
|
|
263
|
-
- **Wallet:** ${
|
|
264
|
-
- **
|
|
265
|
-
- **Network:** ${agentConfig.network}
|
|
271
|
+
- **Wallet:** ${wallet.address}
|
|
272
|
+
- **Network:** Base
|
|
266
273
|
- **Type:** ${agentConfig.agentType}
|
|
267
274
|
|
|
268
|
-
## Fee Distribution
|
|
269
|
-
|
|
270
|
-
- Agent: 80%
|
|
271
|
-
- Dactyclaw: 20%
|
|
272
|
-
|
|
273
275
|
## Getting Started
|
|
274
276
|
|
|
275
277
|
\`\`\`bash
|
|
@@ -277,12 +279,42 @@ npm install
|
|
|
277
279
|
npm run dev
|
|
278
280
|
\`\`\`
|
|
279
281
|
|
|
280
|
-
##
|
|
282
|
+
## Environment Variables
|
|
283
|
+
|
|
284
|
+
This project uses a \`.env\` file to store sensitive information including your private key.
|
|
285
|
+
|
|
286
|
+
**⚠️ IMPORTANT: Never commit \`.env\` to version control!**
|
|
287
|
+
|
|
288
|
+
The \`.env\` file is already in \`.gitignore\` for your safety.
|
|
289
|
+
|
|
290
|
+
## Launch Token
|
|
291
|
+
|
|
292
|
+
To launch your token on Clanker:
|
|
281
293
|
|
|
282
294
|
\`\`\`bash
|
|
283
|
-
|
|
295
|
+
npx dacty-launch
|
|
284
296
|
\`\`\`
|
|
285
297
|
|
|
298
|
+
This will:
|
|
299
|
+
1. Use your private key to sign transactions
|
|
300
|
+
2. Deploy token to Base network via Clanker
|
|
301
|
+
3. Setup fee distribution (80% to your wallet, 20% to Dactyclaw)
|
|
302
|
+
|
|
303
|
+
## Fee Distribution
|
|
304
|
+
|
|
305
|
+
Once your token is launched:
|
|
306
|
+
- **80%** of trading fees go to your agent wallet
|
|
307
|
+
- **20%** of trading fees go to Dactyclaw
|
|
308
|
+
|
|
309
|
+
Monitor your fees on [Clanker.world](https://clanker.world)
|
|
310
|
+
|
|
311
|
+
## Security
|
|
312
|
+
|
|
313
|
+
- Keep your \`.env\` file private
|
|
314
|
+
- Never share your private key
|
|
315
|
+
- Never commit \`.env\` to version control
|
|
316
|
+
- Use a hardware wallet for production
|
|
317
|
+
|
|
286
318
|
## License
|
|
287
319
|
|
|
288
320
|
MIT
|
|
@@ -293,13 +325,32 @@ MIT
|
|
|
293
325
|
const gitignore = `node_modules/
|
|
294
326
|
.env
|
|
295
327
|
.env.local
|
|
328
|
+
.env.*.local
|
|
296
329
|
dist/
|
|
297
330
|
build/
|
|
298
331
|
*.log
|
|
332
|
+
npm-debug.log*
|
|
333
|
+
yarn-debug.log*
|
|
334
|
+
yarn-error.log*
|
|
299
335
|
.DS_Store
|
|
336
|
+
.vscode/
|
|
337
|
+
.idea/
|
|
338
|
+
*.swp
|
|
339
|
+
*.swo
|
|
340
|
+
*~
|
|
341
|
+
.pnpm-store/
|
|
342
|
+
pnpm-lock.yaml
|
|
343
|
+
package-lock.json
|
|
300
344
|
`;
|
|
301
345
|
fs.writeFileSync(path.join(agentDir, '.gitignore'), gitignore);
|
|
302
346
|
|
|
347
|
+
// Create .gitattributes to ensure .env is never committed
|
|
348
|
+
const gitattributes = `# Ensure .env files are never committed
|
|
349
|
+
.env export-ignore
|
|
350
|
+
.env.* export-ignore
|
|
351
|
+
`;
|
|
352
|
+
fs.writeFileSync(path.join(agentDir, '.gitattributes'), gitattributes);
|
|
353
|
+
|
|
303
354
|
spinner.succeed('Configuration files created');
|
|
304
355
|
|
|
305
356
|
// Display summary
|
|
@@ -307,38 +358,32 @@ build/
|
|
|
307
358
|
console.log(chalk.green.bold('✓ Agent created successfully!'));
|
|
308
359
|
console.log('\n');
|
|
309
360
|
console.log(chalk.cyan('Agent Details:'));
|
|
310
|
-
console.log(chalk.gray('─'.repeat(
|
|
361
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
311
362
|
console.log(chalk.white(` Name: ${agentConfig.name}`));
|
|
312
363
|
console.log(chalk.white(` DNA: ${agentConfig.dna}`));
|
|
313
|
-
console.log(chalk.white(` Wallet:
|
|
314
|
-
console.log(chalk.white(` Token Symbol: ${agentConfig.token.symbol}`));
|
|
364
|
+
console.log(chalk.white(` Wallet Address: ${wallet.address}`));
|
|
315
365
|
console.log(chalk.white(` Type: ${agentConfig.agentType}`));
|
|
316
366
|
console.log(chalk.white(` Network: ${agentConfig.network}`));
|
|
317
367
|
console.log(chalk.white(` Directory: ${agentDir}`));
|
|
318
|
-
console.log(chalk.gray('─'.repeat(
|
|
368
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
369
|
+
console.log('\n');
|
|
370
|
+
|
|
371
|
+
console.log(chalk.cyan('Security Notice:'));
|
|
372
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
373
|
+
console.log(chalk.yellow(` ⚠️ Your private key is stored in .env file`));
|
|
374
|
+
console.log(chalk.yellow(` ⚠️ NEVER commit .env to version control`));
|
|
375
|
+
console.log(chalk.yellow(` ⚠️ Keep your private key safe and secure`));
|
|
376
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
319
377
|
console.log('\n');
|
|
320
378
|
|
|
321
379
|
console.log(chalk.cyan('Next Steps:'));
|
|
322
|
-
console.log(chalk.gray('─'.repeat(
|
|
323
|
-
console.log(chalk.white(` 1. cd ${
|
|
380
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
381
|
+
console.log(chalk.white(` 1. cd ${path.basename(agentDir)}`));
|
|
324
382
|
console.log(chalk.white(` 2. npm install`));
|
|
325
383
|
console.log(chalk.white(` 3. npm run dev`));
|
|
326
|
-
console.log(chalk.
|
|
384
|
+
console.log(chalk.white(` 4. npx dacty-launch (to launch token)`));
|
|
385
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
327
386
|
console.log('\n');
|
|
328
|
-
|
|
329
|
-
console.log(chalk.cyan('Fee Distribution:'));
|
|
330
|
-
console.log(chalk.gray('─'.repeat(50)));
|
|
331
|
-
console.log(chalk.white(` Agent: 80%`));
|
|
332
|
-
console.log(chalk.white(` Dactyclaw: 20%`));
|
|
333
|
-
console.log(chalk.gray('─'.repeat(50)));
|
|
334
|
-
console.log('\n');
|
|
335
|
-
|
|
336
|
-
if (agentConfig.github.createRepo) {
|
|
337
|
-
console.log(chalk.yellow('ℹ GitHub repository creation requires manual setup.'));
|
|
338
|
-
console.log(chalk.yellow(' Visit https://github.com/new to create the repository.'));
|
|
339
|
-
console.log(chalk.yellow(` Repository name: ${agentConfig.github.repository}`));
|
|
340
|
-
console.log('\n');
|
|
341
|
-
}
|
|
342
387
|
|
|
343
388
|
} catch (error) {
|
|
344
389
|
spinner.fail('Error creating agent');
|