dactyclaw 1.3.4 → 1.4.0
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/dactyclaw.js +170 -0
- package/package.json +4 -5
package/bin/dactyclaw.js
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { program } = require('commander');
|
|
3
|
+
const { ethers } = require('ethers');
|
|
4
|
+
const { createPublicClient, createWalletClient, http, formatEther } = require('viem');
|
|
5
|
+
const { privateKeyToAccount } = require('viem/accounts');
|
|
6
|
+
const { base } = require('viem/chains');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const crypto = require('crypto');
|
|
10
|
+
const axios = require('axios');
|
|
11
|
+
const { Clanker, POOL_POSITIONS } = require('clanker-sdk/v4');
|
|
12
|
+
const { POOL_POSITIONS: ROOT_POS_V4 } = require('clanker-sdk');
|
|
13
|
+
const readline = require('readline');
|
|
14
|
+
|
|
15
|
+
function ask(question) {
|
|
16
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
17
|
+
return new Promise((resolve) => {
|
|
18
|
+
rl.question(question, (answer) => {
|
|
19
|
+
rl.close();
|
|
20
|
+
resolve(answer.trim());
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function sleep(ms) {
|
|
26
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function generateSubStringHash(str, length) {
|
|
30
|
+
return crypto.createHash('md5').update(str).digest('hex').substring(0, length);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
program
|
|
34
|
+
.name('dactyclaw')
|
|
35
|
+
.description('Spawn and Deploy an Autonomous Agent Token on Base (Clanker)')
|
|
36
|
+
.option('-n, --name <name>', 'Agent name')
|
|
37
|
+
.option('-t, --ticker <ticker>', 'Token ticker symbol')
|
|
38
|
+
.action(async (options) => {
|
|
39
|
+
console.log(`\n╔════════════════════════════════════════╗`);
|
|
40
|
+
console.log(`║ DACTYCLAW AGENT SPAWNER V2 ║`);
|
|
41
|
+
console.log(`║ Create and Deploy Automatically ║`);
|
|
42
|
+
console.log(`╚════════════════════════════════════════╝\n`);
|
|
43
|
+
|
|
44
|
+
const name = options.name || await ask('? Agent Name: ');
|
|
45
|
+
if (!name) { console.log('Name is required.'); process.exit(1); }
|
|
46
|
+
|
|
47
|
+
const defaultTicker = name.toUpperCase().replace(/[^A-Z0-9]/g, "").slice(0, 6);
|
|
48
|
+
const tickerInput = options.ticker || await ask(`? Token Symbol [${defaultTicker}]: `);
|
|
49
|
+
const ticker = tickerInput || defaultTicker;
|
|
50
|
+
|
|
51
|
+
const description = await ask('? Agent Description (optional): ');
|
|
52
|
+
|
|
53
|
+
// Wallet setup
|
|
54
|
+
const localWallet = ethers.Wallet.createRandom();
|
|
55
|
+
const dnaId = generateSubStringHash(localWallet.address + Date.now(), 12);
|
|
56
|
+
|
|
57
|
+
// Env & Agent files processing
|
|
58
|
+
const cwd = process.cwd();
|
|
59
|
+
const agentDirName = `${name.toLowerCase().replace(/[^a-z0-9]/g, '-')}-agent`;
|
|
60
|
+
const agentDir = path.join(cwd, agentDirName);
|
|
61
|
+
|
|
62
|
+
if (!fs.existsSync(agentDir)) {
|
|
63
|
+
fs.mkdirSync(agentDir, { recursive: true });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const agentJsonPath = path.join(agentDir, 'agent.json');
|
|
67
|
+
const agentData = {
|
|
68
|
+
name,
|
|
69
|
+
ticker,
|
|
70
|
+
dnaId,
|
|
71
|
+
description: description || "An autonomous agent in the Dactyclaw ecosystem",
|
|
72
|
+
network: "base",
|
|
73
|
+
createdAt: new Date().toISOString(),
|
|
74
|
+
wallet: { address: localWallet.address }
|
|
75
|
+
};
|
|
76
|
+
fs.writeFileSync(agentJsonPath, JSON.stringify(agentData, null, 2));
|
|
77
|
+
|
|
78
|
+
const envPath = path.join(agentDir, '.env');
|
|
79
|
+
let envContent = `AGENT_DNA=${dnaId}\nPRIVATE_KEY=${localWallet.privateKey}\nAGENT_DIR=${agentDir}\n`;
|
|
80
|
+
fs.writeFileSync(envPath, envContent);
|
|
81
|
+
|
|
82
|
+
console.log(`\n✔ Configuration generated at ` + agentDir);
|
|
83
|
+
|
|
84
|
+
console.log(`\nAgent Details:`);
|
|
85
|
+
console.log(`────────────────────────────────────────────────────────────`);
|
|
86
|
+
console.log(` Name: ${name}`);
|
|
87
|
+
console.log(` Ticker: $${ticker}`);
|
|
88
|
+
console.log(` DNA: ${dnaId}`);
|
|
89
|
+
console.log(` Wallet Address: ${localWallet.address}`);
|
|
90
|
+
console.log(`────────────────────────────────────────────────────────────`);
|
|
91
|
+
|
|
92
|
+
console.log(`\n💳 FUNDING REQUIRED FOR TOKEN LAUNCH:`);
|
|
93
|
+
console.log(` Please send at least 0.001 ETH (Base) to the Agent Wallet:`);
|
|
94
|
+
console.log(` ${localWallet.address}`);
|
|
95
|
+
console.log(`\nWaiting for funds... (Polling Base network)`);
|
|
96
|
+
|
|
97
|
+
const rpc = "https://mainnet.base.org";
|
|
98
|
+
const rpcProvider = new ethers.JsonRpcProvider(rpc);
|
|
99
|
+
const MIN_BALANCE = ethers.parseEther("0.001");
|
|
100
|
+
|
|
101
|
+
let funded = false;
|
|
102
|
+
for (let i = 0; i < 120; i++) { // wait for max 10 minutes
|
|
103
|
+
const balance = await rpcProvider.getBalance(localWallet.address);
|
|
104
|
+
if (balance >= MIN_BALANCE) {
|
|
105
|
+
console.log(`\n✅ ${ethers.formatEther(balance)} ETH — funded!`);
|
|
106
|
+
funded = true;
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
if (i > 0 && i % 6 === 0) {
|
|
110
|
+
console.log(`... Waiting: ${ethers.formatEther(balance)} ETH (Needs 0.001 ETH)`);
|
|
111
|
+
}
|
|
112
|
+
await sleep(5000);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (!funded) {
|
|
116
|
+
console.log(`\n❌ Funding timed out. You can manually launch later by CD-ing into ${agentDirName} and running 'npx dacty-launch'.`);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
console.log(`\n🚀 Initiating Dactyclaw Clanker Auto-Deploy...`);
|
|
121
|
+
const account = privateKeyToAccount(localWallet.privateKey);
|
|
122
|
+
const publicClient = createPublicClient({ chain: base, transport: http(rpc) });
|
|
123
|
+
const walletClient = createWalletClient({ account, chain: base, transport: http(rpc) });
|
|
124
|
+
const clanker = new Clanker({ publicClient: publicClient, wallet: walletClient });
|
|
125
|
+
|
|
126
|
+
const tokenConfig = {
|
|
127
|
+
name,
|
|
128
|
+
symbol: ticker,
|
|
129
|
+
tokenAdmin: account.address,
|
|
130
|
+
image: "ipfs://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi",
|
|
131
|
+
metadata: { description: description || "Deployed via Dactyclaw Seamless CLI", socialMediaUrls: [], auditUrls: [] },
|
|
132
|
+
context: { interface: "Dactyl", platform: "Dactyl", messageId: dnaId, id: ticker },
|
|
133
|
+
pool: { quoteToken: "0x4200000000000000000000000000000000000006", initialMarketCap: "0.2", positions: ROOT_POS_V4.Standard },
|
|
134
|
+
vault: { percentage: 0, lockupDuration: 604800 }
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
console.log(`[1/3] Compiling Factory Payload...`);
|
|
138
|
+
console.log(`[2/3] Executing deployment contract... (This will spend Layer-2 Gas)`);
|
|
139
|
+
|
|
140
|
+
const deployResult = await clanker.deploy(tokenConfig);
|
|
141
|
+
|
|
142
|
+
if (deployResult.error) {
|
|
143
|
+
console.error(`\n❌ Deployment Failed: ${deployResult.error.shortMessage || deployResult.error.message || 'Smart Contract Error'}`);
|
|
144
|
+
fs.writeFileSync(path.join(agentDir, 'error_launch.log'), JSON.stringify(deployResult, null, 2));
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
console.log(`[3/3] Broadcasting Tx: ${deployResult.txHash}`);
|
|
149
|
+
console.log(`Waiting for Block validation...`);
|
|
150
|
+
|
|
151
|
+
const resultContract = await deployResult.waitForTransaction();
|
|
152
|
+
console.log(`\n🎉 SUCCESS! Token deployed autonomously on-chain.`);
|
|
153
|
+
if (resultContract && resultContract.address) {
|
|
154
|
+
console.log(`\n🪙 Token Address: ${resultContract.address}`);
|
|
155
|
+
console.log(`🔗 Token Explorer: https://clanker.world/clanker/${resultContract.address}`);
|
|
156
|
+
|
|
157
|
+
// Update config with token payload
|
|
158
|
+
agentData.token = {
|
|
159
|
+
address: resultContract.address,
|
|
160
|
+
txHash: deployResult.txHash
|
|
161
|
+
};
|
|
162
|
+
fs.writeFileSync(agentJsonPath, JSON.stringify(agentData, null, 2));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
console.log(`\nYour Agent ${name} is fully materialized.`);
|
|
166
|
+
console.log(`Directory: cd ${agentDirName}`);
|
|
167
|
+
console.log(`Keep your private keys safe!`);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dactyclaw",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "**Agent Monitor & Deployer for Clawn Ecosystem on Base**",
|
|
5
5
|
"main": "proxy.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"dacty-create": "bin/
|
|
8
|
-
"
|
|
9
|
-
"dactyclaw": "bin/dacty-create.js"
|
|
7
|
+
"dacty-create": "bin/dactyclaw.js",
|
|
8
|
+
"dactyclaw": "bin/dactyclaw.js"
|
|
10
9
|
},
|
|
11
10
|
"scripts": {
|
|
12
11
|
"test": "echo \"Error: no test specified\" && exit 1"
|
|
@@ -32,4 +31,4 @@
|
|
|
32
31
|
"viem": "^2.46.3"
|
|
33
32
|
},
|
|
34
33
|
"devDependencies": {}
|
|
35
|
-
}
|
|
34
|
+
}
|