dactyclaw 1.0.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/README.md +36 -0
- package/agent.json +7 -0
- package/api/tokens.js +20 -0
- package/api/top-tokens.js +25 -0
- package/bin/dacty-create.js +44 -0
- package/bin/dacty-launch.js +40 -0
- package/index.html +1395 -0
- package/package.json +32 -0
- package/proxy.js +112 -0
- package/vercel.json +6 -0
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dactyclaw",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "**Agent Monitor & Deployer for Clawn Ecosystem on Base**",
|
|
5
|
+
"main": "proxy.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"dacty-create": "bin/dacty-create.js",
|
|
8
|
+
"dacty-launch": "bin/dacty-launch.js",
|
|
9
|
+
"dactyclaw": "bin/dacty-create.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/dactyclaw/dactyclaw.git"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [],
|
|
19
|
+
"author": "",
|
|
20
|
+
"license": "ISC",
|
|
21
|
+
"type": "commonjs",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/dactyclaw/dactyclaw/issues"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://github.com/dactyclaw/dactyclaw#readme",
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"axios": "^1.13.5",
|
|
28
|
+
"commander": "^14.0.3",
|
|
29
|
+
"dotenv": "^17.3.1",
|
|
30
|
+
"ethers": "^6.16.0"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/proxy.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local CORS Proxy for DACTYCLAW dev
|
|
3
|
+
* Usage: node proxy.js
|
|
4
|
+
* Serves /api/tokens -> https://clawn.ch/api/tokens (with CORS headers)
|
|
5
|
+
* Also serves static files on the same port (5500)
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const http = require('http');
|
|
9
|
+
const https = require('https');
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
|
|
13
|
+
const PORT = 5500;
|
|
14
|
+
|
|
15
|
+
const MIME = {
|
|
16
|
+
'.html': 'text/html',
|
|
17
|
+
'.css': 'text/css',
|
|
18
|
+
'.js': 'application/javascript',
|
|
19
|
+
'.json': 'application/json',
|
|
20
|
+
'.png': 'image/png',
|
|
21
|
+
'.svg': 'image/svg+xml',
|
|
22
|
+
'.ico': 'image/x-icon',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const server = http.createServer((req, res) => {
|
|
26
|
+
const corsHeaders = {
|
|
27
|
+
'Access-Control-Allow-Origin': '*',
|
|
28
|
+
'Access-Control-Allow-Methods': 'GET, OPTIONS',
|
|
29
|
+
'Access-Control-Allow-Headers': 'Content-Type',
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
if (req.method === 'OPTIONS') {
|
|
33
|
+
res.writeHead(204, corsHeaders);
|
|
34
|
+
res.end();
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Proxy /api/top-tokens -> clawn.ch with prices enabled
|
|
39
|
+
if (req.url === '/api/top-tokens' || req.url.startsWith('/api/top-tokens?')) {
|
|
40
|
+
const qs = req.url.includes('?') ? req.url.split('?')[1] : '';
|
|
41
|
+
const basePath = '/api/tokens?prices=1&sort=hot&limit=10' + (qs ? '&' + qs : '');
|
|
42
|
+
const options = {
|
|
43
|
+
hostname: 'clawn.ch',
|
|
44
|
+
path: basePath,
|
|
45
|
+
method: 'GET',
|
|
46
|
+
headers: { 'User-Agent': 'dactyclaw/2.2' },
|
|
47
|
+
};
|
|
48
|
+
const proxyReq = https.request(options, (proxyRes) => {
|
|
49
|
+
res.writeHead(proxyRes.statusCode, {
|
|
50
|
+
...corsHeaders,
|
|
51
|
+
'Content-Type': 'application/json',
|
|
52
|
+
'Cache-Control': 's-maxage=30',
|
|
53
|
+
});
|
|
54
|
+
proxyRes.pipe(res);
|
|
55
|
+
});
|
|
56
|
+
proxyReq.on('error', (err) => {
|
|
57
|
+
res.writeHead(500, corsHeaders);
|
|
58
|
+
res.end(JSON.stringify({ success: false, error: err.message }));
|
|
59
|
+
});
|
|
60
|
+
proxyReq.end();
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Proxy /api/tokens to clawn.ch
|
|
65
|
+
if (req.url === '/api/tokens' || req.url.startsWith('/api/tokens?')) {
|
|
66
|
+
const qs = req.url.includes('?') ? req.url.split('?')[1] : '';
|
|
67
|
+
const upstream = `https://clawn.ch/api/tokens${qs ? '?' + qs : ''}`;
|
|
68
|
+
const options = {
|
|
69
|
+
hostname: 'clawn.ch',
|
|
70
|
+
path: '/api/tokens' + (qs ? '?' + qs : ''),
|
|
71
|
+
method: 'GET',
|
|
72
|
+
headers: { 'User-Agent': 'dactyclaw/2.2' },
|
|
73
|
+
};
|
|
74
|
+
const proxyReq = https.request(options, (proxyRes) => {
|
|
75
|
+
res.writeHead(proxyRes.statusCode, {
|
|
76
|
+
...corsHeaders,
|
|
77
|
+
'Content-Type': 'application/json',
|
|
78
|
+
'Cache-Control': 's-maxage=10',
|
|
79
|
+
});
|
|
80
|
+
proxyRes.pipe(res);
|
|
81
|
+
});
|
|
82
|
+
proxyReq.on('error', (err) => {
|
|
83
|
+
res.writeHead(500, corsHeaders);
|
|
84
|
+
res.end(JSON.stringify({ success: false, error: err.message }));
|
|
85
|
+
});
|
|
86
|
+
proxyReq.end();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Serve static files
|
|
91
|
+
let filePath = path.join(__dirname, req.url === '/' ? 'index.html' : req.url.split('?')[0]);
|
|
92
|
+
if (!fs.existsSync(filePath)) {
|
|
93
|
+
filePath = path.join(__dirname, 'index.html'); // SPA fallback
|
|
94
|
+
}
|
|
95
|
+
const ext = path.extname(filePath);
|
|
96
|
+
const contentType = MIME[ext] || 'text/plain';
|
|
97
|
+
fs.readFile(filePath, (err, data) => {
|
|
98
|
+
if (err) {
|
|
99
|
+
res.writeHead(404, corsHeaders);
|
|
100
|
+
res.end('Not found');
|
|
101
|
+
} else {
|
|
102
|
+
res.writeHead(200, { ...corsHeaders, 'Content-Type': contentType });
|
|
103
|
+
res.end(data);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
server.listen(PORT, () => {
|
|
109
|
+
console.log(`DACTYCLAW dev server running at http://localhost:${PORT}`);
|
|
110
|
+
console.log(` - Static files: http://localhost:${PORT}/`);
|
|
111
|
+
console.log(` - API proxy: http://localhost:${PORT}/api/tokens`);
|
|
112
|
+
});
|