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/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
+ });
package/vercel.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "rewrites": [
3
+ { "source": "/api/tokens", "destination": "/api/tokens" },
4
+ { "source": "/(.*)", "destination": "/index.html" }
5
+ ]
6
+ }