dacty-launch 1.1.3 → 1.1.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/bin/dacty-launch.mjs +156 -197
- package/lib/index.mjs +156 -197
- package/package.json +2 -1
package/bin/dacty-launch.mjs
CHANGED
|
@@ -1,259 +1,218 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import inquirer from 'inquirer';
|
|
5
|
-
import ora from 'ora';
|
|
6
3
|
import fs from 'fs';
|
|
7
4
|
import path from 'path';
|
|
8
5
|
import { fileURLToPath } from 'url';
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
6
|
+
import readline from 'readline';
|
|
7
|
+
import { Clanker } from 'clanker-sdk/v4';
|
|
8
|
+
import { createWalletClient, createPublicClient, privateKeyToAccount, http } from 'viem';
|
|
9
|
+
import { base } from 'viem/chains';
|
|
12
10
|
|
|
13
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
-
const __dirname = dirname(__filename);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const CLANKER_RPC = process.env.CLANKER_RPC || 'https://mainnet.base.org';
|
|
21
|
-
const CLANKER_API = process.env.CLANKER_API || 'https://api.clanker.world';
|
|
14
|
+
const rl = readline.createInterface({
|
|
15
|
+
input: process.stdin,
|
|
16
|
+
output: process.stdout,
|
|
17
|
+
});
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
function question(prompt) {
|
|
20
|
+
return new Promise((resolve) => {
|
|
21
|
+
rl.question(prompt, (answer) => {
|
|
22
|
+
resolve(answer);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
async function main() {
|
|
28
|
+
console.log('\n╔═══════════════════════════════════════╗');
|
|
29
|
+
console.log('║ DACTYCLAW - Token Launch ║');
|
|
30
|
+
console.log('║ Powered by Clanker v4.0.0 ║');
|
|
31
|
+
console.log('╚═══════════════════════════════════════╝\n');
|
|
32
|
+
|
|
33
|
+
// Check if agent.config.json exists
|
|
34
|
+
const agentConfigPath = path.join(process.cwd(), 'agent.config.json');
|
|
35
|
+
if (!fs.existsSync(agentConfigPath)) {
|
|
36
|
+
console.error('❌ Error: agent.config.json not found!');
|
|
37
|
+
console.error(' Please run `npx dacty-create` first to create an agent.');
|
|
32
38
|
process.exit(1);
|
|
33
39
|
}
|
|
34
40
|
|
|
35
|
-
// Load agent
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
// Load agent configuration
|
|
42
|
+
const agentConfig = JSON.parse(fs.readFileSync(agentConfigPath, 'utf-8'));
|
|
43
|
+
console.log(`✓ Agent loaded: ${agentConfig.name} (DNA: ${agentConfig.dna})`);
|
|
44
|
+
console.log(`✓ Wallet: ${agentConfig.wallet}\n`);
|
|
45
|
+
|
|
46
|
+
// Check if .env exists with private key
|
|
47
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
48
|
+
if (!fs.existsSync(envPath)) {
|
|
49
|
+
console.error('❌ Error: .env file not found!');
|
|
50
|
+
console.error(' Private key should be in .env file.');
|
|
42
51
|
process.exit(1);
|
|
43
52
|
}
|
|
44
53
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
console.
|
|
54
|
+
const envContent = fs.readFileSync(envPath, 'utf-8');
|
|
55
|
+
const privateKeyMatch = envContent.match(/PRIVATE_KEY=(.+)/);
|
|
56
|
+
if (!privateKeyMatch) {
|
|
57
|
+
console.error('❌ Error: PRIVATE_KEY not found in .env file!');
|
|
49
58
|
process.exit(1);
|
|
50
59
|
}
|
|
51
60
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
{
|
|
55
|
-
type: 'input',
|
|
56
|
-
name: 'tokenName',
|
|
57
|
-
message: 'Token name:',
|
|
58
|
-
default: `${agentConfig.name} Token`,
|
|
59
|
-
validate: (input) => input.length > 0 && input.length <= 50 ? true : 'Token name must be 1-50 characters',
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
type: 'input',
|
|
63
|
-
name: 'tokenSymbol',
|
|
64
|
-
message: 'Token symbol (uppercase):',
|
|
65
|
-
default: agentConfig.name.substring(0, 4).toUpperCase(),
|
|
66
|
-
validate: (input) => /^[A-Z0-9]{1,10}$/.test(input) ? true : 'Symbol must be 1-10 uppercase letters/numbers',
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
type: 'input',
|
|
70
|
-
name: 'supply',
|
|
71
|
-
message: 'Total supply (in billions):',
|
|
72
|
-
default: '1',
|
|
73
|
-
validate: (input) => !isNaN(input) && parseFloat(input) > 0 ? true : 'Supply must be a positive number',
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
type: 'input',
|
|
77
|
-
name: 'description',
|
|
78
|
-
message: 'Token description (optional):',
|
|
79
|
-
default: `Autonomous agent token for ${agentConfig.name}`,
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
type: 'confirm',
|
|
83
|
-
name: 'confirmLaunch',
|
|
84
|
-
message: 'Ready to deploy token on Base network via Clanker?',
|
|
85
|
-
default: false,
|
|
86
|
-
},
|
|
87
|
-
]);
|
|
88
|
-
|
|
89
|
-
if (!answers.confirmLaunch) {
|
|
90
|
-
console.log(chalk.yellow('\n✗ Token launch cancelled.\n'));
|
|
91
|
-
process.exit(0);
|
|
92
|
-
}
|
|
61
|
+
const privateKey = privateKeyMatch[1].trim();
|
|
62
|
+
console.log('✓ Private key loaded from .env\n');
|
|
93
63
|
|
|
94
|
-
|
|
64
|
+
// Get token details from user
|
|
65
|
+
const tokenName = await question('Token Name: ');
|
|
66
|
+
const tokenSymbol = await question('Token Symbol: ');
|
|
67
|
+
const initialSupply = await question('Initial Supply (default: 1000000000): ') || '1000000000';
|
|
95
68
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
69
|
+
console.log('\n📋 Configuration:');
|
|
70
|
+
console.log(` Name: ${tokenName}`);
|
|
71
|
+
console.log(` Symbol: ${tokenSymbol}`);
|
|
72
|
+
console.log(` Supply: ${initialSupply}`);
|
|
73
|
+
console.log(` Agent Wallet: ${agentConfig.wallet}`);
|
|
74
|
+
console.log(` Fee Distribution: 80% Agent, 20% Dactyclaw\n`);
|
|
99
75
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const totalSupply = BigInt(supplyInBillions) * BigInt(10) ** BigInt(9) * BigInt(10) ** BigInt(18);
|
|
76
|
+
// Dactyclaw wallet address (should be configured)
|
|
77
|
+
const DACTYCLAW_WALLET = process.env.DACTYCLAW_WALLET || '0x0000000000000000000000000000000000000000';
|
|
103
78
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
79
|
+
try {
|
|
80
|
+
console.log('🔄 Initializing Clanker SDK...');
|
|
81
|
+
|
|
82
|
+
// Setup viem clients
|
|
83
|
+
const account = privateKeyToAccount(`0x${privateKey.replace(/^0x/, '')}`);
|
|
84
|
+
const publicClient = createPublicClient({ chain: base, transport: http() });
|
|
85
|
+
const walletClient = createWalletClient({ account, chain: base, transport: http() });
|
|
86
|
+
|
|
87
|
+
// Initialize Clanker SDK
|
|
88
|
+
const clanker = new Clanker({
|
|
89
|
+
publicClient,
|
|
90
|
+
wallet: walletClient,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
console.log('✓ Clanker SDK initialized');
|
|
94
|
+
console.log('✓ Connected to Base network');
|
|
95
|
+
console.log('✓ Account:', account.address);
|
|
96
|
+
|
|
97
|
+
console.log('\n🚀 Deploying token...');
|
|
98
|
+
|
|
99
|
+
// Deploy token with 80/20 reward split
|
|
100
|
+
const { txHash, waitForTransaction, error } = await clanker.deploy({
|
|
101
|
+
name: tokenName,
|
|
102
|
+
symbol: tokenSymbol,
|
|
103
|
+
tokenAdmin: account.address,
|
|
104
|
+
vanity: true, // Generate vanity address with "b07" suffix
|
|
105
|
+
rewards: {
|
|
106
|
+
recipients: [
|
|
118
107
|
{
|
|
119
108
|
recipient: agentConfig.wallet,
|
|
120
109
|
admin: agentConfig.wallet,
|
|
121
|
-
bps:
|
|
122
|
-
token: '
|
|
110
|
+
bps: 8_000, // 80% of rewards
|
|
111
|
+
token: 'Paired', // Take fees in WETH
|
|
123
112
|
},
|
|
124
113
|
{
|
|
125
114
|
recipient: DACTYCLAW_WALLET,
|
|
126
115
|
admin: DACTYCLAW_WALLET,
|
|
127
|
-
bps:
|
|
128
|
-
token: 'Both', //
|
|
116
|
+
bps: 2_000, // 20% of rewards
|
|
117
|
+
token: 'Both', // Take fees in both tokens
|
|
129
118
|
},
|
|
130
119
|
],
|
|
131
|
-
pool: {
|
|
132
|
-
positions: 'Standard', // Meme token configuration
|
|
133
|
-
},
|
|
134
|
-
fees: {
|
|
135
|
-
type: 'static',
|
|
136
|
-
clankerFee: 100, // 1% in bps
|
|
137
|
-
pairedFee: 100, // 1% in bps
|
|
138
|
-
},
|
|
139
120
|
},
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
121
|
+
fees: {
|
|
122
|
+
type: 'static',
|
|
123
|
+
clankerFee: 100, // 1%
|
|
124
|
+
pairedFee: 100, // 1%
|
|
125
|
+
},
|
|
126
|
+
metadata: {
|
|
127
|
+
description: `${tokenName} - Created with DACTYCLAW`,
|
|
128
|
+
},
|
|
129
|
+
context: {
|
|
130
|
+
interface: 'DACTYCLAW',
|
|
131
|
+
},
|
|
132
|
+
});
|
|
144
133
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
if (!tokenConfig.symbol || tokenConfig.symbol.length === 0) {
|
|
150
|
-
throw new Error('Token symbol is required');
|
|
134
|
+
if (error) {
|
|
135
|
+
console.error('❌ Deployment error:', error);
|
|
136
|
+
process.exit(1);
|
|
151
137
|
}
|
|
152
138
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
// Verify network connectivity
|
|
157
|
-
try {
|
|
158
|
-
const response = await axios.get(`${CLANKER_API}/health`, { timeout: 5000 });
|
|
159
|
-
if (response.status !== 200) {
|
|
160
|
-
throw new Error('Clanker API unavailable');
|
|
161
|
-
}
|
|
162
|
-
} catch (error) {
|
|
163
|
-
console.log(chalk.yellow('\n⚠ Warning: Clanker API temporarily unavailable'));
|
|
164
|
-
console.log(chalk.gray(' Proceeding with local configuration...\n'));
|
|
165
|
-
}
|
|
139
|
+
console.log(`✓ Transaction submitted: ${txHash}`);
|
|
140
|
+
console.log('⏳ Waiting for confirmation...\n');
|
|
166
141
|
|
|
167
|
-
|
|
168
|
-
await new Promise(resolve => setTimeout(resolve, 600));
|
|
142
|
+
const result = await waitForTransaction();
|
|
169
143
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
throw new Error('Invalid private key format. Must be 0x followed by 64 hex characters');
|
|
144
|
+
if (result.error) {
|
|
145
|
+
console.error('❌ Transaction failed:', result.error);
|
|
146
|
+
process.exit(1);
|
|
174
147
|
}
|
|
175
148
|
|
|
176
|
-
|
|
177
|
-
await new Promise(resolve => setTimeout(resolve, 800));
|
|
178
|
-
|
|
179
|
-
// In production, this would call the actual Clanker SDK
|
|
180
|
-
// For now, we're simulating the deployment with proper configuration
|
|
181
|
-
spinner.text = 'Signing transaction with private key...';
|
|
182
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
149
|
+
const tokenAddress = result.address;
|
|
183
150
|
|
|
184
|
-
|
|
185
|
-
|
|
151
|
+
console.log('✅ Token deployed successfully!');
|
|
152
|
+
console.log(`\n📊 Token Details:`);
|
|
153
|
+
console.log(` Address: ${tokenAddress}`);
|
|
154
|
+
console.log(` Name: ${tokenName}`);
|
|
155
|
+
console.log(` Symbol: ${tokenSymbol}`);
|
|
156
|
+
console.log(` Supply: ${initialSupply}`);
|
|
157
|
+
console.log(` Network: Base`);
|
|
158
|
+
console.log(` Explorer: https://basescan.org/token/${tokenAddress}`);
|
|
186
159
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
spinner.succeed('Token deployed successfully');
|
|
160
|
+
console.log(`\n💰 Fee Distribution:`);
|
|
161
|
+
console.log(` Agent (${agentConfig.wallet}): 80%`);
|
|
162
|
+
console.log(` Dactyclaw: 20%`);
|
|
192
163
|
|
|
193
164
|
// Save token configuration
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
165
|
+
const tokenConfig = {
|
|
166
|
+
name: tokenName,
|
|
167
|
+
symbol: tokenSymbol,
|
|
168
|
+
address: tokenAddress,
|
|
169
|
+
supply: initialSupply,
|
|
198
170
|
txHash,
|
|
199
171
|
deployedAt: new Date().toISOString(),
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
172
|
+
network: 'base',
|
|
173
|
+
agentDNA: agentConfig.dna,
|
|
174
|
+
agentWallet: agentConfig.wallet,
|
|
175
|
+
fees: {
|
|
176
|
+
agent: 80,
|
|
177
|
+
dactyclaw: 20,
|
|
178
|
+
},
|
|
203
179
|
};
|
|
204
180
|
|
|
205
|
-
fs.writeFileSync(
|
|
181
|
+
fs.writeFileSync(
|
|
182
|
+
path.join(process.cwd(), 'token.config.json'),
|
|
183
|
+
JSON.stringify(tokenConfig, null, 2)
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
console.log('\n✓ Token configuration saved to token.config.json');
|
|
206
187
|
|
|
207
188
|
// Update agent config with token info
|
|
208
189
|
agentConfig.token = {
|
|
209
|
-
name:
|
|
210
|
-
symbol:
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
deploymentDate: tokenConfig.deploymentDate,
|
|
214
|
-
txHash,
|
|
190
|
+
name: tokenName,
|
|
191
|
+
symbol: tokenSymbol,
|
|
192
|
+
address: tokenAddress,
|
|
193
|
+
deployedAt: new Date().toISOString(),
|
|
215
194
|
};
|
|
216
195
|
|
|
217
|
-
fs.writeFileSync(
|
|
218
|
-
|
|
219
|
-
spinner.succeed('Configuration saved');
|
|
220
|
-
|
|
221
|
-
// Display summary
|
|
222
|
-
console.log(chalk.green.bold('\n✓ Token launched successfully!\n'));
|
|
223
|
-
|
|
224
|
-
console.log(chalk.cyan('[ TOKEN DETAILS ]'));
|
|
225
|
-
console.log(chalk.white(`Name: ${tokenConfig.name}`));
|
|
226
|
-
console.log(chalk.white(`Symbol: ${tokenConfig.symbol}`));
|
|
227
|
-
console.log(chalk.white(`Total Supply: ${supplyInBillions}B`));
|
|
228
|
-
console.log(chalk.white(`Decimals: 18`));
|
|
229
|
-
console.log(chalk.white(`Network: Base Mainnet`));
|
|
230
|
-
console.log(chalk.white(`Contract Address: ${contractAddress}`));
|
|
231
|
-
console.log(chalk.white(`Transaction: ${txHash}`));
|
|
232
|
-
|
|
233
|
-
console.log(chalk.cyan('\n[ FEE DISTRIBUTION ]'));
|
|
234
|
-
console.log(chalk.white(`Agent Wallet: 80% of trading fees`));
|
|
235
|
-
console.log(chalk.white(`Dactyclaw: 20% of trading fees`));
|
|
236
|
-
console.log(chalk.white(`Your Address: ${agentConfig.wallet}`));
|
|
237
|
-
|
|
238
|
-
console.log(chalk.cyan('\n[ BLOCKCHAIN LINKS ]'));
|
|
239
|
-
console.log(chalk.white(`BaseScan: https://basescan.org/token/${contractAddress}`));
|
|
240
|
-
console.log(chalk.white(`Clanker: https://clanker.world/token/${contractAddress}`));
|
|
196
|
+
fs.writeFileSync(agentConfigPath, JSON.stringify(agentConfig, null, 2));
|
|
197
|
+
console.log('✓ Agent configuration updated');
|
|
241
198
|
|
|
242
|
-
console.log(
|
|
243
|
-
console.log(
|
|
244
|
-
console.log(
|
|
245
|
-
console.log(
|
|
246
|
-
console.log(
|
|
247
|
-
console.log(
|
|
199
|
+
console.log('\n🎉 Ready to trade!');
|
|
200
|
+
console.log(`\n📱 View on Clanker: https://clanker.world/token/${tokenAddress}`);
|
|
201
|
+
console.log(`🔗 View on Basescan: https://basescan.org/token/${tokenAddress}`);
|
|
202
|
+
console.log(`\n💡 Next steps:`);
|
|
203
|
+
console.log(` 1. Fund your wallet with ETH for gas fees`);
|
|
204
|
+
console.log(` 2. Monitor your token on Clanker.world`);
|
|
205
|
+
console.log(` 3. Check your earnings: npx dacty-status`);
|
|
248
206
|
|
|
207
|
+
rl.close();
|
|
249
208
|
} catch (error) {
|
|
250
|
-
|
|
251
|
-
|
|
209
|
+
console.error('❌ Error:', error.message);
|
|
210
|
+
rl.close();
|
|
252
211
|
process.exit(1);
|
|
253
212
|
}
|
|
254
213
|
}
|
|
255
214
|
|
|
256
|
-
|
|
257
|
-
console.error(
|
|
215
|
+
main().catch((error) => {
|
|
216
|
+
console.error('❌ Fatal error:', error);
|
|
258
217
|
process.exit(1);
|
|
259
218
|
});
|
package/lib/index.mjs
CHANGED
|
@@ -1,259 +1,218 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import inquirer from 'inquirer';
|
|
5
|
-
import ora from 'ora';
|
|
6
3
|
import fs from 'fs';
|
|
7
4
|
import path from 'path';
|
|
8
5
|
import { fileURLToPath } from 'url';
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
6
|
+
import readline from 'readline';
|
|
7
|
+
import { Clanker } from 'clanker-sdk/v4';
|
|
8
|
+
import { createWalletClient, createPublicClient, privateKeyToAccount, http } from 'viem';
|
|
9
|
+
import { base } from 'viem/chains';
|
|
12
10
|
|
|
13
11
|
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
-
const __dirname = dirname(__filename);
|
|
12
|
+
const __dirname = path.dirname(__filename);
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const CLANKER_RPC = process.env.CLANKER_RPC || 'https://mainnet.base.org';
|
|
21
|
-
const CLANKER_API = process.env.CLANKER_API || 'https://api.clanker.world';
|
|
14
|
+
const rl = readline.createInterface({
|
|
15
|
+
input: process.stdin,
|
|
16
|
+
output: process.stdout,
|
|
17
|
+
});
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
19
|
+
function question(prompt) {
|
|
20
|
+
return new Promise((resolve) => {
|
|
21
|
+
rl.question(prompt, (answer) => {
|
|
22
|
+
resolve(answer);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
}
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
async function main() {
|
|
28
|
+
console.log('\n╔═══════════════════════════════════════╗');
|
|
29
|
+
console.log('║ DACTYCLAW - Token Launch ║');
|
|
30
|
+
console.log('║ Powered by Clanker v4.0.0 ║');
|
|
31
|
+
console.log('╚═══════════════════════════════════════╝\n');
|
|
32
|
+
|
|
33
|
+
// Check if agent.config.json exists
|
|
34
|
+
const agentConfigPath = path.join(process.cwd(), 'agent.config.json');
|
|
35
|
+
if (!fs.existsSync(agentConfigPath)) {
|
|
36
|
+
console.error('❌ Error: agent.config.json not found!');
|
|
37
|
+
console.error(' Please run `npx dacty-create` first to create an agent.');
|
|
32
38
|
process.exit(1);
|
|
33
39
|
}
|
|
34
40
|
|
|
35
|
-
// Load agent
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
// Load agent configuration
|
|
42
|
+
const agentConfig = JSON.parse(fs.readFileSync(agentConfigPath, 'utf-8'));
|
|
43
|
+
console.log(`✓ Agent loaded: ${agentConfig.name} (DNA: ${agentConfig.dna})`);
|
|
44
|
+
console.log(`✓ Wallet: ${agentConfig.wallet}\n`);
|
|
45
|
+
|
|
46
|
+
// Check if .env exists with private key
|
|
47
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
48
|
+
if (!fs.existsSync(envPath)) {
|
|
49
|
+
console.error('❌ Error: .env file not found!');
|
|
50
|
+
console.error(' Private key should be in .env file.');
|
|
42
51
|
process.exit(1);
|
|
43
52
|
}
|
|
44
53
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
console.
|
|
54
|
+
const envContent = fs.readFileSync(envPath, 'utf-8');
|
|
55
|
+
const privateKeyMatch = envContent.match(/PRIVATE_KEY=(.+)/);
|
|
56
|
+
if (!privateKeyMatch) {
|
|
57
|
+
console.error('❌ Error: PRIVATE_KEY not found in .env file!');
|
|
49
58
|
process.exit(1);
|
|
50
59
|
}
|
|
51
60
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
{
|
|
55
|
-
type: 'input',
|
|
56
|
-
name: 'tokenName',
|
|
57
|
-
message: 'Token name:',
|
|
58
|
-
default: `${agentConfig.name} Token`,
|
|
59
|
-
validate: (input) => input.length > 0 && input.length <= 50 ? true : 'Token name must be 1-50 characters',
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
type: 'input',
|
|
63
|
-
name: 'tokenSymbol',
|
|
64
|
-
message: 'Token symbol (uppercase):',
|
|
65
|
-
default: agentConfig.name.substring(0, 4).toUpperCase(),
|
|
66
|
-
validate: (input) => /^[A-Z0-9]{1,10}$/.test(input) ? true : 'Symbol must be 1-10 uppercase letters/numbers',
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
type: 'input',
|
|
70
|
-
name: 'supply',
|
|
71
|
-
message: 'Total supply (in billions):',
|
|
72
|
-
default: '1',
|
|
73
|
-
validate: (input) => !isNaN(input) && parseFloat(input) > 0 ? true : 'Supply must be a positive number',
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
type: 'input',
|
|
77
|
-
name: 'description',
|
|
78
|
-
message: 'Token description (optional):',
|
|
79
|
-
default: `Autonomous agent token for ${agentConfig.name}`,
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
type: 'confirm',
|
|
83
|
-
name: 'confirmLaunch',
|
|
84
|
-
message: 'Ready to deploy token on Base network via Clanker?',
|
|
85
|
-
default: false,
|
|
86
|
-
},
|
|
87
|
-
]);
|
|
88
|
-
|
|
89
|
-
if (!answers.confirmLaunch) {
|
|
90
|
-
console.log(chalk.yellow('\n✗ Token launch cancelled.\n'));
|
|
91
|
-
process.exit(0);
|
|
92
|
-
}
|
|
61
|
+
const privateKey = privateKeyMatch[1].trim();
|
|
62
|
+
console.log('✓ Private key loaded from .env\n');
|
|
93
63
|
|
|
94
|
-
|
|
64
|
+
// Get token details from user
|
|
65
|
+
const tokenName = await question('Token Name: ');
|
|
66
|
+
const tokenSymbol = await question('Token Symbol: ');
|
|
67
|
+
const initialSupply = await question('Initial Supply (default: 1000000000): ') || '1000000000';
|
|
95
68
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
69
|
+
console.log('\n📋 Configuration:');
|
|
70
|
+
console.log(` Name: ${tokenName}`);
|
|
71
|
+
console.log(` Symbol: ${tokenSymbol}`);
|
|
72
|
+
console.log(` Supply: ${initialSupply}`);
|
|
73
|
+
console.log(` Agent Wallet: ${agentConfig.wallet}`);
|
|
74
|
+
console.log(` Fee Distribution: 80% Agent, 20% Dactyclaw\n`);
|
|
99
75
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const totalSupply = BigInt(supplyInBillions) * BigInt(10) ** BigInt(9) * BigInt(10) ** BigInt(18);
|
|
76
|
+
// Dactyclaw wallet address (should be configured)
|
|
77
|
+
const DACTYCLAW_WALLET = process.env.DACTYCLAW_WALLET || '0x0000000000000000000000000000000000000000';
|
|
103
78
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
79
|
+
try {
|
|
80
|
+
console.log('🔄 Initializing Clanker SDK...');
|
|
81
|
+
|
|
82
|
+
// Setup viem clients
|
|
83
|
+
const account = privateKeyToAccount(`0x${privateKey.replace(/^0x/, '')}`);
|
|
84
|
+
const publicClient = createPublicClient({ chain: base, transport: http() });
|
|
85
|
+
const walletClient = createWalletClient({ account, chain: base, transport: http() });
|
|
86
|
+
|
|
87
|
+
// Initialize Clanker SDK
|
|
88
|
+
const clanker = new Clanker({
|
|
89
|
+
publicClient,
|
|
90
|
+
wallet: walletClient,
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
console.log('✓ Clanker SDK initialized');
|
|
94
|
+
console.log('✓ Connected to Base network');
|
|
95
|
+
console.log('✓ Account:', account.address);
|
|
96
|
+
|
|
97
|
+
console.log('\n🚀 Deploying token...');
|
|
98
|
+
|
|
99
|
+
// Deploy token with 80/20 reward split
|
|
100
|
+
const { txHash, waitForTransaction, error } = await clanker.deploy({
|
|
101
|
+
name: tokenName,
|
|
102
|
+
symbol: tokenSymbol,
|
|
103
|
+
tokenAdmin: account.address,
|
|
104
|
+
vanity: true, // Generate vanity address with "b07" suffix
|
|
105
|
+
rewards: {
|
|
106
|
+
recipients: [
|
|
118
107
|
{
|
|
119
108
|
recipient: agentConfig.wallet,
|
|
120
109
|
admin: agentConfig.wallet,
|
|
121
|
-
bps:
|
|
122
|
-
token: '
|
|
110
|
+
bps: 8_000, // 80% of rewards
|
|
111
|
+
token: 'Paired', // Take fees in WETH
|
|
123
112
|
},
|
|
124
113
|
{
|
|
125
114
|
recipient: DACTYCLAW_WALLET,
|
|
126
115
|
admin: DACTYCLAW_WALLET,
|
|
127
|
-
bps:
|
|
128
|
-
token: 'Both', //
|
|
116
|
+
bps: 2_000, // 20% of rewards
|
|
117
|
+
token: 'Both', // Take fees in both tokens
|
|
129
118
|
},
|
|
130
119
|
],
|
|
131
|
-
pool: {
|
|
132
|
-
positions: 'Standard', // Meme token configuration
|
|
133
|
-
},
|
|
134
|
-
fees: {
|
|
135
|
-
type: 'static',
|
|
136
|
-
clankerFee: 100, // 1% in bps
|
|
137
|
-
pairedFee: 100, // 1% in bps
|
|
138
|
-
},
|
|
139
120
|
},
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
121
|
+
fees: {
|
|
122
|
+
type: 'static',
|
|
123
|
+
clankerFee: 100, // 1%
|
|
124
|
+
pairedFee: 100, // 1%
|
|
125
|
+
},
|
|
126
|
+
metadata: {
|
|
127
|
+
description: `${tokenName} - Created with DACTYCLAW`,
|
|
128
|
+
},
|
|
129
|
+
context: {
|
|
130
|
+
interface: 'DACTYCLAW',
|
|
131
|
+
},
|
|
132
|
+
});
|
|
144
133
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
if (!tokenConfig.symbol || tokenConfig.symbol.length === 0) {
|
|
150
|
-
throw new Error('Token symbol is required');
|
|
134
|
+
if (error) {
|
|
135
|
+
console.error('❌ Deployment error:', error);
|
|
136
|
+
process.exit(1);
|
|
151
137
|
}
|
|
152
138
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
// Verify network connectivity
|
|
157
|
-
try {
|
|
158
|
-
const response = await axios.get(`${CLANKER_API}/health`, { timeout: 5000 });
|
|
159
|
-
if (response.status !== 200) {
|
|
160
|
-
throw new Error('Clanker API unavailable');
|
|
161
|
-
}
|
|
162
|
-
} catch (error) {
|
|
163
|
-
console.log(chalk.yellow('\n⚠ Warning: Clanker API temporarily unavailable'));
|
|
164
|
-
console.log(chalk.gray(' Proceeding with local configuration...\n'));
|
|
165
|
-
}
|
|
139
|
+
console.log(`✓ Transaction submitted: ${txHash}`);
|
|
140
|
+
console.log('⏳ Waiting for confirmation...\n');
|
|
166
141
|
|
|
167
|
-
|
|
168
|
-
await new Promise(resolve => setTimeout(resolve, 600));
|
|
142
|
+
const result = await waitForTransaction();
|
|
169
143
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
throw new Error('Invalid private key format. Must be 0x followed by 64 hex characters');
|
|
144
|
+
if (result.error) {
|
|
145
|
+
console.error('❌ Transaction failed:', result.error);
|
|
146
|
+
process.exit(1);
|
|
174
147
|
}
|
|
175
148
|
|
|
176
|
-
|
|
177
|
-
await new Promise(resolve => setTimeout(resolve, 800));
|
|
178
|
-
|
|
179
|
-
// In production, this would call the actual Clanker SDK
|
|
180
|
-
// For now, we're simulating the deployment with proper configuration
|
|
181
|
-
spinner.text = 'Signing transaction with private key...';
|
|
182
|
-
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
149
|
+
const tokenAddress = result.address;
|
|
183
150
|
|
|
184
|
-
|
|
185
|
-
|
|
151
|
+
console.log('✅ Token deployed successfully!');
|
|
152
|
+
console.log(`\n📊 Token Details:`);
|
|
153
|
+
console.log(` Address: ${tokenAddress}`);
|
|
154
|
+
console.log(` Name: ${tokenName}`);
|
|
155
|
+
console.log(` Symbol: ${tokenSymbol}`);
|
|
156
|
+
console.log(` Supply: ${initialSupply}`);
|
|
157
|
+
console.log(` Network: Base`);
|
|
158
|
+
console.log(` Explorer: https://basescan.org/token/${tokenAddress}`);
|
|
186
159
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
spinner.succeed('Token deployed successfully');
|
|
160
|
+
console.log(`\n💰 Fee Distribution:`);
|
|
161
|
+
console.log(` Agent (${agentConfig.wallet}): 80%`);
|
|
162
|
+
console.log(` Dactyclaw: 20%`);
|
|
192
163
|
|
|
193
164
|
// Save token configuration
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
165
|
+
const tokenConfig = {
|
|
166
|
+
name: tokenName,
|
|
167
|
+
symbol: tokenSymbol,
|
|
168
|
+
address: tokenAddress,
|
|
169
|
+
supply: initialSupply,
|
|
198
170
|
txHash,
|
|
199
171
|
deployedAt: new Date().toISOString(),
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
172
|
+
network: 'base',
|
|
173
|
+
agentDNA: agentConfig.dna,
|
|
174
|
+
agentWallet: agentConfig.wallet,
|
|
175
|
+
fees: {
|
|
176
|
+
agent: 80,
|
|
177
|
+
dactyclaw: 20,
|
|
178
|
+
},
|
|
203
179
|
};
|
|
204
180
|
|
|
205
|
-
fs.writeFileSync(
|
|
181
|
+
fs.writeFileSync(
|
|
182
|
+
path.join(process.cwd(), 'token.config.json'),
|
|
183
|
+
JSON.stringify(tokenConfig, null, 2)
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
console.log('\n✓ Token configuration saved to token.config.json');
|
|
206
187
|
|
|
207
188
|
// Update agent config with token info
|
|
208
189
|
agentConfig.token = {
|
|
209
|
-
name:
|
|
210
|
-
symbol:
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
deploymentDate: tokenConfig.deploymentDate,
|
|
214
|
-
txHash,
|
|
190
|
+
name: tokenName,
|
|
191
|
+
symbol: tokenSymbol,
|
|
192
|
+
address: tokenAddress,
|
|
193
|
+
deployedAt: new Date().toISOString(),
|
|
215
194
|
};
|
|
216
195
|
|
|
217
|
-
fs.writeFileSync(
|
|
218
|
-
|
|
219
|
-
spinner.succeed('Configuration saved');
|
|
220
|
-
|
|
221
|
-
// Display summary
|
|
222
|
-
console.log(chalk.green.bold('\n✓ Token launched successfully!\n'));
|
|
223
|
-
|
|
224
|
-
console.log(chalk.cyan('[ TOKEN DETAILS ]'));
|
|
225
|
-
console.log(chalk.white(`Name: ${tokenConfig.name}`));
|
|
226
|
-
console.log(chalk.white(`Symbol: ${tokenConfig.symbol}`));
|
|
227
|
-
console.log(chalk.white(`Total Supply: ${supplyInBillions}B`));
|
|
228
|
-
console.log(chalk.white(`Decimals: 18`));
|
|
229
|
-
console.log(chalk.white(`Network: Base Mainnet`));
|
|
230
|
-
console.log(chalk.white(`Contract Address: ${contractAddress}`));
|
|
231
|
-
console.log(chalk.white(`Transaction: ${txHash}`));
|
|
232
|
-
|
|
233
|
-
console.log(chalk.cyan('\n[ FEE DISTRIBUTION ]'));
|
|
234
|
-
console.log(chalk.white(`Agent Wallet: 80% of trading fees`));
|
|
235
|
-
console.log(chalk.white(`Dactyclaw: 20% of trading fees`));
|
|
236
|
-
console.log(chalk.white(`Your Address: ${agentConfig.wallet}`));
|
|
237
|
-
|
|
238
|
-
console.log(chalk.cyan('\n[ BLOCKCHAIN LINKS ]'));
|
|
239
|
-
console.log(chalk.white(`BaseScan: https://basescan.org/token/${contractAddress}`));
|
|
240
|
-
console.log(chalk.white(`Clanker: https://clanker.world/token/${contractAddress}`));
|
|
196
|
+
fs.writeFileSync(agentConfigPath, JSON.stringify(agentConfig, null, 2));
|
|
197
|
+
console.log('✓ Agent configuration updated');
|
|
241
198
|
|
|
242
|
-
console.log(
|
|
243
|
-
console.log(
|
|
244
|
-
console.log(
|
|
245
|
-
console.log(
|
|
246
|
-
console.log(
|
|
247
|
-
console.log(
|
|
199
|
+
console.log('\n🎉 Ready to trade!');
|
|
200
|
+
console.log(`\n📱 View on Clanker: https://clanker.world/token/${tokenAddress}`);
|
|
201
|
+
console.log(`🔗 View on Basescan: https://basescan.org/token/${tokenAddress}`);
|
|
202
|
+
console.log(`\n💡 Next steps:`);
|
|
203
|
+
console.log(` 1. Fund your wallet with ETH for gas fees`);
|
|
204
|
+
console.log(` 2. Monitor your token on Clanker.world`);
|
|
205
|
+
console.log(` 3. Check your earnings: npx dacty-status`);
|
|
248
206
|
|
|
207
|
+
rl.close();
|
|
249
208
|
} catch (error) {
|
|
250
|
-
|
|
251
|
-
|
|
209
|
+
console.error('❌ Error:', error.message);
|
|
210
|
+
rl.close();
|
|
252
211
|
process.exit(1);
|
|
253
212
|
}
|
|
254
213
|
}
|
|
255
214
|
|
|
256
|
-
|
|
257
|
-
console.error(
|
|
215
|
+
main().catch((error) => {
|
|
216
|
+
console.error('❌ Fatal error:', error);
|
|
258
217
|
process.exit(1);
|
|
259
218
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dacty-launch",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"description": "Launch tokens for agents in the Dactyclaw ecosystem",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"author": "Dactyclaw",
|
|
22
22
|
"license": "MIT",
|
|
23
23
|
"dependencies": {
|
|
24
|
+
"clanker-sdk": "^4.0.0",
|
|
24
25
|
"chalk": "^5.3.0",
|
|
25
26
|
"inquirer": "^9.2.12",
|
|
26
27
|
"ora": "^8.0.1",
|