dacty-create 1.0.1 → 1.0.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # dacty-create
2
2
 
3
- Create and deploy autonomous agents in the Dactyclaw ecosystem with a single command.
3
+ Create autonomous agents with secure private key generation in one command.
4
4
 
5
5
  ```bash
6
6
  npx dacty-create
@@ -9,22 +9,25 @@ npx dacty-create
9
9
  ## Features
10
10
 
11
11
  - ✨ **Interactive CLI** - Simple prompts to configure your agent
12
- - 🤖 **Agent Generation** - Auto-generates agent code and configuration
13
- - 💰 **Fee Distribution** - Built-in 80/20 fee split (80% agent, 20% Dactyclaw)
14
- - 🔗 **Blockchain Ready** - Configured for Base network
15
- - 📦 **Complete Setup** - Generates package.json, environment files, and sample code
16
- - 🚀 **Ready to Deploy** - Generated agents are ready to run immediately
12
+ - 🔐 **Secure Key Generation** - Private key stored in .env (never shared)
13
+ - 🤖 **Agent DNA** - Unique identifier for your agent
14
+ - 💰 **Wallet Ready** - Generated wallet for transactions
15
+ - 📦 **Complete Setup** - Project structure with all necessary files
16
+ - 🚀 **Ready to Launch** - Use with `npx dacty-launch` to deploy token
17
17
 
18
18
  ## Installation
19
19
 
20
+ Use directly with npx (recommended):
21
+
20
22
  ```bash
21
- npm install -g dacty-create
23
+ npx dacty-create
22
24
  ```
23
25
 
24
- Or use directly with npx:
26
+ Or install globally:
25
27
 
26
28
  ```bash
27
- npx dacty-create
29
+ npm install -g dacty-create
30
+ dacty-create
28
31
  ```
29
32
 
30
33
  ## Usage
@@ -32,25 +35,23 @@ npx dacty-create
32
35
  Run the interactive CLI:
33
36
 
34
37
  ```bash
35
- dacty-create
38
+ npx dacty-create
36
39
  ```
37
40
 
38
41
  The CLI will prompt you for:
39
42
 
40
43
  1. **Agent Name** - The name of your agent
41
- 2. **Agent Description** - What your agent does
42
- 3. **Agent Type** - Monitor, Trading, Utility, or Custom
43
- 4. **GitHub Username** - For repository setup
44
- 5. **Create GitHub Repository** - Whether to auto-create the repo
44
+ 2. **Agent Type** - Type of agent (monitoring, trading, utility, custom)
45
45
 
46
46
  ## What Gets Created
47
47
 
48
- After running `dacty-create`, you'll get a complete agent project with:
48
+ After running `dacty-create`, you'll get:
49
49
 
50
50
  ```
51
51
  my-agent/
52
- ├── agent.config.json # Agent configuration
53
- ├── .env # Environment variables
52
+ ├── agent.config.json # Agent configuration (wallet address, DNA)
53
+ ├── .env # Private key (NEVER commit this!)
54
+ ├── .env.example # Template for .env
54
55
  ├── package.json # Node.js dependencies
55
56
  ├── README.md # Project documentation
56
57
  ├── .gitignore # Git ignore rules
@@ -64,47 +65,50 @@ my-agent/
64
65
 
65
66
  Each agent gets:
66
67
 
67
- - **Unique DNA** - A unique identifier for your agent
68
- - **Wallet Address** - Generated wallet for transactions
69
- - **Token Symbol** - Unique token symbol for your agent's token
70
- - **Fee Distribution** - 80% to agent, 20% to Dactyclaw
68
+ - **Unique DNA** - Unique identifier (e.g., `abc123def456`)
69
+ - **Wallet Address** - Public wallet address for receiving fees
70
+ - **Private Key** - Stored in .env for signing transactions
71
+ - **Network** - Base network (primary)
71
72
 
72
- ## Quick Start
73
+ ## Security
73
74
 
74
- After creating an agent:
75
+ - **Private keys** are stored locally in `.env` file
76
+ - `.env` is automatically added to `.gitignore`
77
+ - Never commit `.env` to version control
78
+ - Keep `.env` file safe and backed up
75
79
 
76
- ```bash
77
- cd my-agent
78
- npm install
79
- npm run dev
80
- ```
80
+ ## Next Steps
81
81
 
82
- ## Deployment
83
-
84
- To deploy your agent:
82
+ After creating an agent, launch your token:
85
83
 
86
84
  ```bash
87
- npm run deploy
85
+ npx dacty-launch
88
86
  ```
89
87
 
90
- ## Fee Distribution
91
-
92
- All agents created with `dacty-create` follow the standard fee distribution:
93
-
94
- - **80%** goes to your agent (for operations, rewards, etc.)
95
- - **20%** goes to Dactyclaw (platform maintenance and development)
88
+ This will:
89
+ - Use your agent's private key to sign transactions
90
+ - Deploy token to Base network via Clanker
91
+ - Setup 80/20 fee distribution
92
+ - Make token immediately tradeable
96
93
 
97
94
  ## Environment Variables
98
95
 
99
- Generated agents include these environment variables:
96
+ Generated agents include:
100
97
 
101
98
  - `AGENT_NAME` - Your agent's name
102
99
  - `AGENT_DNA` - Unique agent identifier
103
- - `AGENT_WALLET` - Agent's wallet address
104
- - `TOKEN_SYMBOL` - Agent's token symbol
100
+ - `AGENT_WALLET` - Agent's public wallet address
101
+ - `PRIVATE_KEY` - Agent's private key (in .env only)
105
102
  - `NETWORK` - Blockchain network (base)
106
- - `GITHUB_USERNAME` - Your GitHub username
107
- - `GITHUB_REPO` - Repository name
103
+
104
+ ## Fee Distribution
105
+
106
+ All agents follow standard fee distribution:
107
+
108
+ - **80%** → Your Agent Wallet
109
+ - **20%** → Dactyclaw Protocol
110
+
111
+ Fees are automatically distributed from every trade.
108
112
 
109
113
  ## Network Support
110
114
 
@@ -118,10 +122,10 @@ MIT
118
122
 
119
123
  ## Support
120
124
 
121
- For issues and questions, visit:
125
+ For issues and questions:
122
126
  - [Dactyclaw GitHub](https://github.com/dactyclaw/dactyclaw)
123
127
  - [Dactyclaw Documentation](https://dactyclaw.dev)
124
128
 
125
129
  ## Contributing
126
130
 
127
- Contributions are welcome! Please feel free to submit a Pull Request.
131
+ Contributions welcome! Please submit a Pull Request.
@@ -3,23 +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 Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
17
+ return crypto.randomBytes(16).toString('hex');
18
18
  }
19
19
 
20
- // Generate wallet address (simulated)
20
+ // Generate wallet (Ethereum-style)
21
21
  function generateWallet() {
22
- return '0x' + Array.from({ length: 40 }, () => Math.floor(Math.random() * 16).toString(16)).join('');
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
+ };
23
29
  }
24
30
 
25
31
  async function createAgent() {
@@ -59,14 +65,8 @@ async function createAgent() {
59
65
  {
60
66
  type: 'input',
61
67
  name: 'githubUsername',
62
- message: 'GitHub Username (for repo creation):',
63
- validate: (input) => input.length > 0 ? true : 'GitHub username cannot be empty'
64
- },
65
- {
66
- type: 'confirm',
67
- name: 'createRepo',
68
- message: 'Create GitHub repository for this agent?',
69
- default: true
68
+ message: 'GitHub Username (optional):',
69
+ default: ''
70
70
  }
71
71
  ]);
72
72
 
@@ -75,7 +75,7 @@ async function createAgent() {
75
75
  try {
76
76
  // Generate agent data
77
77
  const agentDNA = generateDNA();
78
- const agentWallet = generateWallet();
78
+ const wallet = generateWallet();
79
79
  const timestamp = new Date().toISOString();
80
80
 
81
81
  spinner.start('Generating agent configuration...');
@@ -86,22 +86,18 @@ async function createAgent() {
86
86
  description: answers.description,
87
87
  type: answers.agentType,
88
88
  dna: agentDNA,
89
- wallet: agentWallet,
89
+ wallet: wallet.address,
90
90
  createdAt: timestamp,
91
- github: {
92
- username: answers.githubUsername,
93
- repository: `${answers.agentName.toLowerCase().replace(/\s+/g, '-')}-agent`,
94
- createRepo: answers.createRepo
95
- },
96
91
  network: 'base',
97
- status: 'created'
92
+ status: 'created',
93
+ version: '1.0.0'
98
94
  };
99
95
 
100
96
  spinner.succeed('Agent configuration generated');
101
97
 
102
98
  // Create agent directory
103
99
  spinner.start('Creating agent directory...');
104
- const agentDir = path.join(process.cwd(), agentConfig.github.repository);
100
+ const agentDir = path.join(process.cwd(), answers.agentName.toLowerCase().replace(/\s+/g, '-') + '-agent');
105
101
 
106
102
  if (!fs.existsSync(agentDir)) {
107
103
  fs.mkdirSync(agentDir, { recursive: true });
@@ -109,25 +105,47 @@ async function createAgent() {
109
105
 
110
106
  spinner.succeed(`Agent directory created at ${agentDir}`);
111
107
 
112
- // Create config file
108
+ // Create config file (safe - no private key)
113
109
  spinner.start('Writing configuration files...');
114
110
 
115
111
  const configPath = path.join(agentDir, 'agent.config.json');
116
112
  fs.writeFileSync(configPath, JSON.stringify(agentConfig, null, 2));
117
113
 
118
- // Create .env file
119
- const envContent = `AGENT_NAME=${agentConfig.name}
120
- AGENT_DNA=${agentConfig.dna}
121
- AGENT_WALLET=${agentConfig.wallet}
122
- NETWORK=base
123
- GITHUB_USERNAME=${agentConfig.github.username}
124
- GITHUB_REPO=${agentConfig.github.repository}
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=""
125
127
  `;
126
128
  fs.writeFileSync(path.join(agentDir, '.env'), envContent);
127
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
+
128
146
  // Create package.json for agent
129
147
  const agentPackageJson = {
130
- name: agentConfig.github.repository,
148
+ name: agentConfig.name.toLowerCase().replace(/\s+/g, '-') + '-agent',
131
149
  version: '1.0.0',
132
150
  description: agentConfig.description,
133
151
  type: 'module',
@@ -135,15 +153,16 @@ GITHUB_REPO=${agentConfig.github.repository}
135
153
  scripts: {
136
154
  start: 'node src/index.mjs',
137
155
  dev: 'node --watch src/index.mjs',
138
- deploy: 'node scripts/deploy.mjs'
156
+ launch: 'node scripts/launch.mjs'
139
157
  },
140
- keywords: ['agent', 'dactyclaw', 'blockchain'],
141
- author: agentConfig.github.username,
158
+ keywords: ['agent', 'dactyclaw', 'blockchain', 'base'],
159
+ author: answers.githubUsername || 'Dactyclaw Agent',
142
160
  license: 'MIT',
143
161
  dependencies: {
144
162
  'ethers': '^6.10.0',
145
163
  'dotenv': '^16.3.1',
146
- 'axios': '^1.6.5'
164
+ 'axios': '^1.6.5',
165
+ 'chalk': '^5.3.0'
147
166
  }
148
167
  };
149
168
  fs.writeFileSync(path.join(agentDir, 'package.json'), JSON.stringify(agentPackageJson, null, 2));
@@ -156,19 +175,21 @@ import { ethers } from 'ethers';
156
175
 
157
176
  dotenv.config();
158
177
 
159
- const AGENT_NAME = process.env.AGENT_NAME || '${agentConfig.name}';
160
- const AGENT_DNA = process.env.AGENT_DNA || '${agentConfig.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 || '';
161
181
  const NETWORK = process.env.NETWORK || 'base';
162
182
 
163
183
  console.log(\`
164
184
  ╔════════════════════════════════════════╗
165
185
  ║ DACTYCLAW AGENT - \${AGENT_NAME}
166
- ║ DNA: \${AGENT_DNA}
186
+ ║ DNA: \${AGENT_DNA.substring(0, 16)}...
187
+ ║ Wallet: \${AGENT_WALLET.substring(0, 10)}...
167
188
  ║ Network: \${NETWORK}
168
189
  ╚════════════════════════════════════════╝
169
190
  \`);
170
191
 
171
- // Initialize RPC provider
192
+ // Initialize RPC provider for Base network
172
193
  const rpcUrl = 'https://mainnet.base.org';
173
194
  const provider = new ethers.JsonRpcProvider(rpcUrl);
174
195
 
@@ -184,6 +205,10 @@ async function main() {
184
205
  const network = await provider.getNetwork();
185
206
  console.log(\`[Agent] Network: \${network.name} (chainId: \${network.chainId})\`);
186
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
+
187
212
  // Agent is running
188
213
  console.log('[Agent] Agent is running and monitoring the network...');
189
214
  console.log('[Agent] Press Ctrl+C to stop');
@@ -192,7 +217,7 @@ async function main() {
192
217
  setInterval(async () => {
193
218
  const latestBlock = await provider.getBlockNumber();
194
219
  console.log(\`[Agent] Latest block: \${latestBlock}\`);
195
- }, 10000); // Check every 10 seconds
220
+ }, 30000); // Check every 30 seconds
196
221
 
197
222
  } catch (error) {
198
223
  console.error('[Agent] Error:', error);
@@ -204,33 +229,35 @@ main();
204
229
  `;
205
230
  fs.writeFileSync(path.join(agentDir, 'src', 'index.mjs'), agentCode);
206
231
 
207
- // Create scripts directory with deploy script
232
+ // Create scripts directory with launch script
208
233
  fs.mkdirSync(path.join(agentDir, 'scripts'), { recursive: true });
209
234
 
210
- const deployScript = `import dotenv from 'dotenv';
235
+ const launchScript = `import dotenv from 'dotenv';
211
236
 
212
237
  dotenv.config();
213
238
 
214
239
  const AGENT_NAME = process.env.AGENT_NAME;
215
240
  const AGENT_DNA = process.env.AGENT_DNA;
216
241
  const AGENT_WALLET = process.env.AGENT_WALLET;
242
+ const AGENT_PRIVATE_KEY = process.env.AGENT_PRIVATE_KEY;
217
243
 
218
244
  console.log(\`
219
245
  ╔════════════════════════════════════════╗
220
- ║ DACTYCLAW AGENT DEPLOYMENT
246
+ ║ DACTYCLAW TOKEN LAUNCH
221
247
  ║ Agent: \${AGENT_NAME}
222
248
  ║ DNA: \${AGENT_DNA}
223
249
  ║ Wallet: \${AGENT_WALLET}
224
250
  ╚════════════════════════════════════════╝
225
251
  \`);
226
252
 
227
- console.log('\\n[Deploy] Preparing agent for deployment...');
228
- console.log('[Deploy] Agent configuration validated');
229
- console.log('[Deploy] Ready to deploy to Base network');
230
- console.log('[Deploy] ✓ Deployment ready!');
231
- console.log('[Deploy] Next step: npx dacty-launch');
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');
232
259
  `;
233
- fs.writeFileSync(path.join(agentDir, 'scripts', 'deploy.mjs'), deployScript);
260
+ fs.writeFileSync(path.join(agentDir, 'scripts', 'launch.mjs'), launchScript);
234
261
 
235
262
  // Create README
236
263
  const readmeContent = `# ${agentConfig.name}
@@ -241,8 +268,8 @@ An autonomous agent in the Dactyclaw ecosystem.
241
268
 
242
269
  - **Agent Name:** ${agentConfig.name}
243
270
  - **Agent DNA:** ${agentConfig.dna}
244
- - **Wallet:** ${agentConfig.wallet}
245
- - **Network:** ${agentConfig.network}
271
+ - **Wallet:** ${wallet.address}
272
+ - **Network:** Base
246
273
  - **Type:** ${agentConfig.agentType}
247
274
 
248
275
  ## Getting Started
@@ -252,14 +279,42 @@ npm install
252
279
  npm run dev
253
280
  \`\`\`
254
281
 
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
+
255
290
  ## Launch Token
256
291
 
257
- To launch your token on-chain:
292
+ To launch your token on Clanker:
258
293
 
259
294
  \`\`\`bash
260
295
  npx dacty-launch
261
296
  \`\`\`
262
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
+
263
318
  ## License
264
319
 
265
320
  MIT
@@ -270,13 +325,32 @@ MIT
270
325
  const gitignore = `node_modules/
271
326
  .env
272
327
  .env.local
328
+ .env.*.local
273
329
  dist/
274
330
  build/
275
331
  *.log
332
+ npm-debug.log*
333
+ yarn-debug.log*
334
+ yarn-error.log*
276
335
  .DS_Store
336
+ .vscode/
337
+ .idea/
338
+ *.swp
339
+ *.swo
340
+ *~
341
+ .pnpm-store/
342
+ pnpm-lock.yaml
343
+ package-lock.json
277
344
  `;
278
345
  fs.writeFileSync(path.join(agentDir, '.gitignore'), gitignore);
279
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
+
280
354
  spinner.succeed('Configuration files created');
281
355
 
282
356
  // Display summary
@@ -284,32 +358,33 @@ build/
284
358
  console.log(chalk.green.bold('✓ Agent created successfully!'));
285
359
  console.log('\n');
286
360
  console.log(chalk.cyan('Agent Details:'));
287
- console.log(chalk.gray('─'.repeat(50)));
361
+ console.log(chalk.gray('─'.repeat(60)));
288
362
  console.log(chalk.white(` Name: ${agentConfig.name}`));
289
363
  console.log(chalk.white(` DNA: ${agentConfig.dna}`));
290
- console.log(chalk.white(` Wallet: ${agentConfig.wallet}`));
364
+ console.log(chalk.white(` Wallet Address: ${wallet.address}`));
291
365
  console.log(chalk.white(` Type: ${agentConfig.agentType}`));
292
366
  console.log(chalk.white(` Network: ${agentConfig.network}`));
293
367
  console.log(chalk.white(` Directory: ${agentDir}`));
294
- console.log(chalk.gray('─'.repeat(50)));
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)));
295
377
  console.log('\n');
296
378
 
297
379
  console.log(chalk.cyan('Next Steps:'));
298
- console.log(chalk.gray('─'.repeat(50)));
299
- console.log(chalk.white(` 1. cd ${agentConfig.github.repository}`));
380
+ console.log(chalk.gray('─'.repeat(60)));
381
+ console.log(chalk.white(` 1. cd ${path.basename(agentDir)}`));
300
382
  console.log(chalk.white(` 2. npm install`));
301
383
  console.log(chalk.white(` 3. npm run dev`));
302
384
  console.log(chalk.white(` 4. npx dacty-launch (to launch token)`));
303
- console.log(chalk.gray('─'.repeat(50)));
385
+ console.log(chalk.gray('─'.repeat(60)));
304
386
  console.log('\n');
305
387
 
306
- if (agentConfig.github.createRepo) {
307
- console.log(chalk.yellow('ℹ GitHub repository creation requires manual setup.'));
308
- console.log(chalk.yellow(' Visit https://github.com/new to create the repository.'));
309
- console.log(chalk.yellow(` Repository name: ${agentConfig.github.repository}`));
310
- console.log('\n');
311
- }
312
-
313
388
  } catch (error) {
314
389
  spinner.fail('Error creating agent');
315
390
  console.error(chalk.red(error.message));
package/lib/index.mjs CHANGED
@@ -3,23 +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 Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
17
+ return crypto.randomBytes(16).toString('hex');
18
18
  }
19
19
 
20
- // Generate wallet address (simulated)
20
+ // Generate wallet (Ethereum-style)
21
21
  function generateWallet() {
22
- return '0x' + Array.from({ length: 40 }, () => Math.floor(Math.random() * 16).toString(16)).join('');
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
+ };
23
29
  }
24
30
 
25
31
  async function createAgent() {
@@ -59,14 +65,8 @@ async function createAgent() {
59
65
  {
60
66
  type: 'input',
61
67
  name: 'githubUsername',
62
- message: 'GitHub Username (for repo creation):',
63
- validate: (input) => input.length > 0 ? true : 'GitHub username cannot be empty'
64
- },
65
- {
66
- type: 'confirm',
67
- name: 'createRepo',
68
- message: 'Create GitHub repository for this agent?',
69
- default: true
68
+ message: 'GitHub Username (optional):',
69
+ default: ''
70
70
  }
71
71
  ]);
72
72
 
@@ -75,7 +75,7 @@ async function createAgent() {
75
75
  try {
76
76
  // Generate agent data
77
77
  const agentDNA = generateDNA();
78
- const agentWallet = generateWallet();
78
+ const wallet = generateWallet();
79
79
  const timestamp = new Date().toISOString();
80
80
 
81
81
  spinner.start('Generating agent configuration...');
@@ -86,22 +86,18 @@ async function createAgent() {
86
86
  description: answers.description,
87
87
  type: answers.agentType,
88
88
  dna: agentDNA,
89
- wallet: agentWallet,
89
+ wallet: wallet.address,
90
90
  createdAt: timestamp,
91
- github: {
92
- username: answers.githubUsername,
93
- repository: `${answers.agentName.toLowerCase().replace(/\s+/g, '-')}-agent`,
94
- createRepo: answers.createRepo
95
- },
96
91
  network: 'base',
97
- status: 'created'
92
+ status: 'created',
93
+ version: '1.0.0'
98
94
  };
99
95
 
100
96
  spinner.succeed('Agent configuration generated');
101
97
 
102
98
  // Create agent directory
103
99
  spinner.start('Creating agent directory...');
104
- const agentDir = path.join(process.cwd(), agentConfig.github.repository);
100
+ const agentDir = path.join(process.cwd(), answers.agentName.toLowerCase().replace(/\s+/g, '-') + '-agent');
105
101
 
106
102
  if (!fs.existsSync(agentDir)) {
107
103
  fs.mkdirSync(agentDir, { recursive: true });
@@ -109,25 +105,47 @@ async function createAgent() {
109
105
 
110
106
  spinner.succeed(`Agent directory created at ${agentDir}`);
111
107
 
112
- // Create config file
108
+ // Create config file (safe - no private key)
113
109
  spinner.start('Writing configuration files...');
114
110
 
115
111
  const configPath = path.join(agentDir, 'agent.config.json');
116
112
  fs.writeFileSync(configPath, JSON.stringify(agentConfig, null, 2));
117
113
 
118
- // Create .env file
119
- const envContent = `AGENT_NAME=${agentConfig.name}
120
- AGENT_DNA=${agentConfig.dna}
121
- AGENT_WALLET=${agentConfig.wallet}
122
- NETWORK=base
123
- GITHUB_USERNAME=${agentConfig.github.username}
124
- GITHUB_REPO=${agentConfig.github.repository}
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=""
125
127
  `;
126
128
  fs.writeFileSync(path.join(agentDir, '.env'), envContent);
127
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
+
128
146
  // Create package.json for agent
129
147
  const agentPackageJson = {
130
- name: agentConfig.github.repository,
148
+ name: agentConfig.name.toLowerCase().replace(/\s+/g, '-') + '-agent',
131
149
  version: '1.0.0',
132
150
  description: agentConfig.description,
133
151
  type: 'module',
@@ -135,15 +153,16 @@ GITHUB_REPO=${agentConfig.github.repository}
135
153
  scripts: {
136
154
  start: 'node src/index.mjs',
137
155
  dev: 'node --watch src/index.mjs',
138
- deploy: 'node scripts/deploy.mjs'
156
+ launch: 'node scripts/launch.mjs'
139
157
  },
140
- keywords: ['agent', 'dactyclaw', 'blockchain'],
141
- author: agentConfig.github.username,
158
+ keywords: ['agent', 'dactyclaw', 'blockchain', 'base'],
159
+ author: answers.githubUsername || 'Dactyclaw Agent',
142
160
  license: 'MIT',
143
161
  dependencies: {
144
162
  'ethers': '^6.10.0',
145
163
  'dotenv': '^16.3.1',
146
- 'axios': '^1.6.5'
164
+ 'axios': '^1.6.5',
165
+ 'chalk': '^5.3.0'
147
166
  }
148
167
  };
149
168
  fs.writeFileSync(path.join(agentDir, 'package.json'), JSON.stringify(agentPackageJson, null, 2));
@@ -156,19 +175,21 @@ import { ethers } from 'ethers';
156
175
 
157
176
  dotenv.config();
158
177
 
159
- const AGENT_NAME = process.env.AGENT_NAME || '${agentConfig.name}';
160
- const AGENT_DNA = process.env.AGENT_DNA || '${agentConfig.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 || '';
161
181
  const NETWORK = process.env.NETWORK || 'base';
162
182
 
163
183
  console.log(\`
164
184
  ╔════════════════════════════════════════╗
165
185
  ║ DACTYCLAW AGENT - \${AGENT_NAME}
166
- ║ DNA: \${AGENT_DNA}
186
+ ║ DNA: \${AGENT_DNA.substring(0, 16)}...
187
+ ║ Wallet: \${AGENT_WALLET.substring(0, 10)}...
167
188
  ║ Network: \${NETWORK}
168
189
  ╚════════════════════════════════════════╝
169
190
  \`);
170
191
 
171
- // Initialize RPC provider
192
+ // Initialize RPC provider for Base network
172
193
  const rpcUrl = 'https://mainnet.base.org';
173
194
  const provider = new ethers.JsonRpcProvider(rpcUrl);
174
195
 
@@ -184,6 +205,10 @@ async function main() {
184
205
  const network = await provider.getNetwork();
185
206
  console.log(\`[Agent] Network: \${network.name} (chainId: \${network.chainId})\`);
186
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
+
187
212
  // Agent is running
188
213
  console.log('[Agent] Agent is running and monitoring the network...');
189
214
  console.log('[Agent] Press Ctrl+C to stop');
@@ -192,7 +217,7 @@ async function main() {
192
217
  setInterval(async () => {
193
218
  const latestBlock = await provider.getBlockNumber();
194
219
  console.log(\`[Agent] Latest block: \${latestBlock}\`);
195
- }, 10000); // Check every 10 seconds
220
+ }, 30000); // Check every 30 seconds
196
221
 
197
222
  } catch (error) {
198
223
  console.error('[Agent] Error:', error);
@@ -204,33 +229,35 @@ main();
204
229
  `;
205
230
  fs.writeFileSync(path.join(agentDir, 'src', 'index.mjs'), agentCode);
206
231
 
207
- // Create scripts directory with deploy script
232
+ // Create scripts directory with launch script
208
233
  fs.mkdirSync(path.join(agentDir, 'scripts'), { recursive: true });
209
234
 
210
- const deployScript = `import dotenv from 'dotenv';
235
+ const launchScript = `import dotenv from 'dotenv';
211
236
 
212
237
  dotenv.config();
213
238
 
214
239
  const AGENT_NAME = process.env.AGENT_NAME;
215
240
  const AGENT_DNA = process.env.AGENT_DNA;
216
241
  const AGENT_WALLET = process.env.AGENT_WALLET;
242
+ const AGENT_PRIVATE_KEY = process.env.AGENT_PRIVATE_KEY;
217
243
 
218
244
  console.log(\`
219
245
  ╔════════════════════════════════════════╗
220
- ║ DACTYCLAW AGENT DEPLOYMENT
246
+ ║ DACTYCLAW TOKEN LAUNCH
221
247
  ║ Agent: \${AGENT_NAME}
222
248
  ║ DNA: \${AGENT_DNA}
223
249
  ║ Wallet: \${AGENT_WALLET}
224
250
  ╚════════════════════════════════════════╝
225
251
  \`);
226
252
 
227
- console.log('\\n[Deploy] Preparing agent for deployment...');
228
- console.log('[Deploy] Agent configuration validated');
229
- console.log('[Deploy] Ready to deploy to Base network');
230
- console.log('[Deploy] ✓ Deployment ready!');
231
- console.log('[Deploy] Next step: npx dacty-launch');
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');
232
259
  `;
233
- fs.writeFileSync(path.join(agentDir, 'scripts', 'deploy.mjs'), deployScript);
260
+ fs.writeFileSync(path.join(agentDir, 'scripts', 'launch.mjs'), launchScript);
234
261
 
235
262
  // Create README
236
263
  const readmeContent = `# ${agentConfig.name}
@@ -241,8 +268,8 @@ An autonomous agent in the Dactyclaw ecosystem.
241
268
 
242
269
  - **Agent Name:** ${agentConfig.name}
243
270
  - **Agent DNA:** ${agentConfig.dna}
244
- - **Wallet:** ${agentConfig.wallet}
245
- - **Network:** ${agentConfig.network}
271
+ - **Wallet:** ${wallet.address}
272
+ - **Network:** Base
246
273
  - **Type:** ${agentConfig.agentType}
247
274
 
248
275
  ## Getting Started
@@ -252,14 +279,42 @@ npm install
252
279
  npm run dev
253
280
  \`\`\`
254
281
 
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
+
255
290
  ## Launch Token
256
291
 
257
- To launch your token on-chain:
292
+ To launch your token on Clanker:
258
293
 
259
294
  \`\`\`bash
260
295
  npx dacty-launch
261
296
  \`\`\`
262
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
+
263
318
  ## License
264
319
 
265
320
  MIT
@@ -270,13 +325,32 @@ MIT
270
325
  const gitignore = `node_modules/
271
326
  .env
272
327
  .env.local
328
+ .env.*.local
273
329
  dist/
274
330
  build/
275
331
  *.log
332
+ npm-debug.log*
333
+ yarn-debug.log*
334
+ yarn-error.log*
276
335
  .DS_Store
336
+ .vscode/
337
+ .idea/
338
+ *.swp
339
+ *.swo
340
+ *~
341
+ .pnpm-store/
342
+ pnpm-lock.yaml
343
+ package-lock.json
277
344
  `;
278
345
  fs.writeFileSync(path.join(agentDir, '.gitignore'), gitignore);
279
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
+
280
354
  spinner.succeed('Configuration files created');
281
355
 
282
356
  // Display summary
@@ -284,32 +358,33 @@ build/
284
358
  console.log(chalk.green.bold('✓ Agent created successfully!'));
285
359
  console.log('\n');
286
360
  console.log(chalk.cyan('Agent Details:'));
287
- console.log(chalk.gray('─'.repeat(50)));
361
+ console.log(chalk.gray('─'.repeat(60)));
288
362
  console.log(chalk.white(` Name: ${agentConfig.name}`));
289
363
  console.log(chalk.white(` DNA: ${agentConfig.dna}`));
290
- console.log(chalk.white(` Wallet: ${agentConfig.wallet}`));
364
+ console.log(chalk.white(` Wallet Address: ${wallet.address}`));
291
365
  console.log(chalk.white(` Type: ${agentConfig.agentType}`));
292
366
  console.log(chalk.white(` Network: ${agentConfig.network}`));
293
367
  console.log(chalk.white(` Directory: ${agentDir}`));
294
- console.log(chalk.gray('─'.repeat(50)));
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)));
295
377
  console.log('\n');
296
378
 
297
379
  console.log(chalk.cyan('Next Steps:'));
298
- console.log(chalk.gray('─'.repeat(50)));
299
- console.log(chalk.white(` 1. cd ${agentConfig.github.repository}`));
380
+ console.log(chalk.gray('─'.repeat(60)));
381
+ console.log(chalk.white(` 1. cd ${path.basename(agentDir)}`));
300
382
  console.log(chalk.white(` 2. npm install`));
301
383
  console.log(chalk.white(` 3. npm run dev`));
302
384
  console.log(chalk.white(` 4. npx dacty-launch (to launch token)`));
303
- console.log(chalk.gray('─'.repeat(50)));
385
+ console.log(chalk.gray('─'.repeat(60)));
304
386
  console.log('\n');
305
387
 
306
- if (agentConfig.github.createRepo) {
307
- console.log(chalk.yellow('ℹ GitHub repository creation requires manual setup.'));
308
- console.log(chalk.yellow(' Visit https://github.com/new to create the repository.'));
309
- console.log(chalk.yellow(` Repository name: ${agentConfig.github.repository}`));
310
- console.log('\n');
311
- }
312
-
313
388
  } catch (error) {
314
389
  spinner.fail('Error creating agent');
315
390
  console.error(chalk.red(error.message));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dacty-create",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Create and deploy agents in the Dactyclaw ecosystem",
5
5
  "type": "module",
6
6
  "bin": {