rustchainpoa 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Elyan Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,56 @@
1
+ # rustchainpoa
2
+
3
+ RustChain Proof-of-Antiquity Miner — Mine RTC tokens by proving real vintage hardware.
4
+
5
+ ## Quick Start
6
+
7
+ ```bash
8
+ npm install -g rustchainpoa
9
+ rustchainpoa install
10
+ ```
11
+
12
+ The installer will:
13
+ 1. Ask for your wallet name
14
+ 2. Download the official miner from [Scottcjn/Rustchain](https://github.com/Scottcjn/Rustchain)
15
+ 3. Create a Python virtual environment with dependencies
16
+ 4. Set up a background service (systemd on Linux, launchd on macOS)
17
+ 5. Start mining automatically
18
+
19
+ ## Requirements
20
+
21
+ - **Node.js** 14+
22
+ - **Python** 3.8+
23
+ - **Linux** or **macOS** (Windows installer coming soon)
24
+
25
+ ## Commands
26
+
27
+ ```bash
28
+ rustchainpoa install # Install and configure the miner
29
+ rustchainpoa start # Start the miner service
30
+ rustchainpoa stop # Stop the miner service
31
+ rustchainpoa status # Check miner and network status
32
+ rustchainpoa logs # View miner logs
33
+ rustchainpoa uninstall # Remove miner and all files
34
+ ```
35
+
36
+ ## What is RustChain?
37
+
38
+ RustChain uses **Proof-of-Antiquity (PoA)** — a consensus mechanism that rewards miners running on real vintage hardware like PowerPC G4/G5, Apple Silicon, and retro x86 systems. The older and more unique your hardware, the higher your mining multiplier.
39
+
40
+ | Hardware | Multiplier |
41
+ |----------|-----------|
42
+ | PowerPC G4 | 2.5x |
43
+ | PowerPC G5 | 2.0x |
44
+ | IBM POWER8 | 2.0x |
45
+ | Apple Silicon | 1.2x |
46
+ | Modern x86_64 | 1.0x |
47
+
48
+ ## Links
49
+
50
+ - [GitHub](https://github.com/Scottcjn/Rustchain)
51
+ - [Block Explorer](https://50.28.86.131/explorer)
52
+ - [Bounties](https://github.com/Scottcjn/rustchain-bounties/issues)
53
+
54
+ ## License
55
+
56
+ MIT — Elyan Labs
@@ -0,0 +1,353 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { execSync, spawn } = require('child_process');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const os = require('os');
7
+ const https = require('https');
8
+ const http = require('http');
9
+ const readline = require('readline');
10
+
11
+ const REPO_BASE = 'https://raw.githubusercontent.com/Scottcjn/Rustchain/main';
12
+ const INSTALL_DIR = path.join(os.homedir(), '.rustchain-miner');
13
+ const VENV_DIR = path.join(INSTALL_DIR, 'venv');
14
+ const NODE_URL = 'https://50.28.86.131';
15
+
16
+ const BLUE = '\x1b[34m';
17
+ const GREEN = '\x1b[32m';
18
+ const RED = '\x1b[31m';
19
+ const YELLOW = '\x1b[33m';
20
+ const NC = '\x1b[0m';
21
+
22
+ function log(msg) { console.log(`${BLUE}[rustchainpoa]${NC} ${msg}`); }
23
+ function success(msg) { console.log(`${GREEN}[OK]${NC} ${msg}`); }
24
+ function warn(msg) { console.log(`${YELLOW}[WARN]${NC} ${msg}`); }
25
+ function error(msg) { console.error(`${RED}[ERROR]${NC} ${msg}`); process.exit(1); }
26
+
27
+ function download(url, dest) {
28
+ return new Promise((resolve, reject) => {
29
+ const file = fs.createWriteStream(dest);
30
+ const get = url.startsWith('https') ? https.get : http.get;
31
+ get(url, (res) => {
32
+ if (res.statusCode === 301 || res.statusCode === 302) {
33
+ download(res.headers.location, dest).then(resolve).catch(reject);
34
+ return;
35
+ }
36
+ if (res.statusCode !== 200) {
37
+ reject(new Error(`HTTP ${res.statusCode} for ${url}`));
38
+ return;
39
+ }
40
+ res.pipe(file);
41
+ file.on('finish', () => { file.close(); resolve(); });
42
+ }).on('error', reject);
43
+ });
44
+ }
45
+
46
+ function ask(question) {
47
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
48
+ return new Promise((resolve) => {
49
+ rl.question(question, (answer) => { rl.close(); resolve(answer.trim()); });
50
+ });
51
+ }
52
+
53
+ function run(cmd, opts = {}) {
54
+ try {
55
+ return execSync(cmd, { encoding: 'utf8', stdio: opts.silent ? 'pipe' : 'inherit', ...opts });
56
+ } catch (e) {
57
+ if (!opts.ignoreError) throw e;
58
+ return '';
59
+ }
60
+ }
61
+
62
+ function checkPython() {
63
+ try {
64
+ const ver = execSync('python3 --version', { encoding: 'utf8' }).trim();
65
+ log(`Found ${ver}`);
66
+ return 'python3';
67
+ } catch {
68
+ try {
69
+ const ver = execSync('python --version', { encoding: 'utf8' }).trim();
70
+ if (ver.startsWith('Python 3')) {
71
+ log(`Found ${ver}`);
72
+ return 'python';
73
+ }
74
+ } catch {}
75
+ }
76
+ error('Python 3.8+ is required. Install it from https://python.org');
77
+ }
78
+
79
+ async function install() {
80
+ console.log(`
81
+ ╔══════════════════════════════════════════════════╗
82
+ ║ RustChain Proof-of-Antiquity Miner ║
83
+ ║ Mine RTC with real hardware ║
84
+ ╚══════════════════════════════════════════════════╝
85
+ `);
86
+
87
+ const platform = os.platform();
88
+ const arch = os.arch();
89
+ log(`Platform: ${platform} | Arch: ${arch}`);
90
+
91
+ if (platform !== 'linux' && platform !== 'darwin') {
92
+ error(`Unsupported platform: ${platform}. Use Linux or macOS. Windows installer coming soon.`);
93
+ }
94
+
95
+ // Check Python
96
+ const python = checkPython();
97
+
98
+ // Wallet setup
99
+ let wallet = process.argv[3] || '';
100
+ if (!wallet) {
101
+ wallet = await ask(`${BLUE}[rustchainpoa]${NC} Enter your wallet name (e.g. my-laptop-miner): `);
102
+ }
103
+ if (!wallet) {
104
+ wallet = `miner-${os.hostname()}-${Date.now().toString(36)}`;
105
+ warn(`No wallet name provided. Auto-generated: ${wallet}`);
106
+ }
107
+
108
+ // Create install dir
109
+ log(`Installing to ${INSTALL_DIR}`);
110
+ fs.mkdirSync(INSTALL_DIR, { recursive: true });
111
+
112
+ // Save wallet config
113
+ fs.writeFileSync(path.join(INSTALL_DIR, '.wallet'), wallet);
114
+
115
+ // Create venv
116
+ if (!fs.existsSync(VENV_DIR)) {
117
+ log('Creating Python virtual environment...');
118
+ run(`${python} -m venv "${VENV_DIR}"`);
119
+ }
120
+
121
+ // Install deps
122
+ log('Installing Python dependencies...');
123
+ const pip = path.join(VENV_DIR, 'bin', 'pip');
124
+ run(`"${pip}" install --upgrade pip -q`, { silent: true });
125
+ run(`"${pip}" install requests -q`, { silent: true });
126
+ success('Dependencies installed');
127
+
128
+ // Download miner files
129
+ log('Downloading miner from upstream...');
130
+
131
+ const downloads = [
132
+ { url: `${REPO_BASE}/miners/linux/fingerprint_checks.py`, dest: 'fingerprint_checks.py' },
133
+ ];
134
+
135
+ if (platform === 'linux') {
136
+ downloads.push({ url: `${REPO_BASE}/miners/linux/rustchain_linux_miner.py`, dest: 'miner.py' });
137
+ } else if (platform === 'darwin') {
138
+ downloads.push({ url: `${REPO_BASE}/miners/macos/rustchain_mac_miner_v2.4.py`, dest: 'miner.py' });
139
+ }
140
+
141
+ for (const dl of downloads) {
142
+ const destPath = path.join(INSTALL_DIR, dl.dest);
143
+ await download(dl.url, destPath);
144
+ const stat = fs.statSync(destPath);
145
+ if (stat.size < 100) error(`Failed to download ${dl.dest}`);
146
+ log(` ${dl.dest} (${(stat.size / 1024).toFixed(1)} KB)`);
147
+ }
148
+
149
+ success('Miner scripts downloaded');
150
+
151
+ // Setup service
152
+ if (platform === 'linux') {
153
+ setupSystemd(wallet);
154
+ } else if (platform === 'darwin') {
155
+ setupLaunchd(wallet);
156
+ }
157
+
158
+ // Verify network
159
+ log('Checking RustChain network...');
160
+ try {
161
+ const out = execSync(`curl -sk ${NODE_URL}/api/miners 2>/dev/null | python3 -c "import sys,json; m=json.load(sys.stdin); print(len(m))"`, { encoding: 'utf8' }).trim();
162
+ log(`Active miners on network: ${out}`);
163
+ } catch {
164
+ warn('Could not reach network (node may be temporarily unavailable)');
165
+ }
166
+
167
+ console.log(`
168
+ ${GREEN}════════════════════════════════════════════════════${NC}
169
+ ${GREEN} RustChain miner installed successfully!${NC}
170
+
171
+ Wallet: ${wallet}
172
+ Location: ${INSTALL_DIR}
173
+
174
+ Commands:
175
+ rustchainpoa start Start mining
176
+ rustchainpoa stop Stop mining
177
+ rustchainpoa status Check miner status
178
+ rustchainpoa logs View miner logs
179
+
180
+ Manual run:
181
+ cd ${INSTALL_DIR} && source venv/bin/activate
182
+ python miner.py --wallet ${wallet}
183
+ ${GREEN}════════════════════════════════════════════════════${NC}
184
+ `);
185
+ }
186
+
187
+ function setupSystemd(wallet) {
188
+ const serviceDir = path.join(os.homedir(), '.config', 'systemd', 'user');
189
+ fs.mkdirSync(serviceDir, { recursive: true });
190
+ const serviceFile = path.join(serviceDir, 'rustchain-miner.service');
191
+ const pythonBin = path.join(VENV_DIR, 'bin', 'python');
192
+
193
+ fs.writeFileSync(serviceFile, `[Unit]
194
+ Description=RustChain Proof-of-Antiquity Miner
195
+ After=network-online.target
196
+ Wants=network-online.target
197
+
198
+ [Service]
199
+ ExecStart=${pythonBin} ${path.join(INSTALL_DIR, 'miner.py')} --wallet ${wallet}
200
+ Restart=always
201
+ RestartSec=30
202
+ WorkingDirectory=${INSTALL_DIR}
203
+ Environment=PYTHONUNBUFFERED=1
204
+
205
+ [Install]
206
+ WantedBy=default.target
207
+ `);
208
+
209
+ try {
210
+ run('systemctl --user daemon-reload', { silent: true });
211
+ run('systemctl --user enable rustchain-miner', { silent: true });
212
+ run('systemctl --user start rustchain-miner', { silent: true });
213
+ success('Systemd service installed and started');
214
+ } catch {
215
+ warn('Systemd user services not available. Run manually with: rustchainpoa start');
216
+ }
217
+ }
218
+
219
+ function setupLaunchd(wallet) {
220
+ const plistDir = path.join(os.homedir(), 'Library', 'LaunchAgents');
221
+ fs.mkdirSync(plistDir, { recursive: true });
222
+ const plistFile = path.join(plistDir, 'com.rustchain.miner.plist');
223
+ const pythonBin = path.join(VENV_DIR, 'bin', 'python');
224
+
225
+ fs.writeFileSync(plistFile, `<?xml version="1.0" encoding="UTF-8"?>
226
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
227
+ <plist version="1.0">
228
+ <dict>
229
+ <key>Label</key>
230
+ <string>com.rustchain.miner</string>
231
+ <key>ProgramArguments</key>
232
+ <array>
233
+ <string>${pythonBin}</string>
234
+ <string>${path.join(INSTALL_DIR, 'miner.py')}</string>
235
+ <string>--wallet</string>
236
+ <string>${wallet}</string>
237
+ </array>
238
+ <key>WorkingDirectory</key>
239
+ <string>${INSTALL_DIR}</string>
240
+ <key>RunAtLoad</key>
241
+ <true/>
242
+ <key>KeepAlive</key>
243
+ <true/>
244
+ <key>StandardOutPath</key>
245
+ <string>${path.join(INSTALL_DIR, 'miner.log')}</string>
246
+ <key>StandardErrorPath</key>
247
+ <string>${path.join(INSTALL_DIR, 'miner.err')}</string>
248
+ </dict>
249
+ </plist>
250
+ `);
251
+
252
+ try {
253
+ run(`launchctl unload "${plistFile}" 2>/dev/null`, { ignoreError: true, silent: true });
254
+ run(`launchctl load "${plistFile}"`, { silent: true });
255
+ success('LaunchAgent installed and loaded');
256
+ } catch {
257
+ warn('Could not load LaunchAgent. Run manually with: rustchainpoa start');
258
+ }
259
+ }
260
+
261
+ // CLI commands
262
+ const command = process.argv[2] || 'install';
263
+
264
+ switch (command) {
265
+ case 'install':
266
+ install().catch(e => error(e.message));
267
+ break;
268
+
269
+ case 'start':
270
+ if (os.platform() === 'linux') {
271
+ run('systemctl --user start rustchain-miner');
272
+ } else if (os.platform() === 'darwin') {
273
+ run(`launchctl load ~/Library/LaunchAgents/com.rustchain.miner.plist`);
274
+ } else {
275
+ const walletFile = path.join(INSTALL_DIR, '.wallet');
276
+ const w = fs.existsSync(walletFile) ? fs.readFileSync(walletFile, 'utf8').trim() : '';
277
+ const wArg = w ? `--wallet ${w}` : '';
278
+ log(`Starting miner... Run: cd ${INSTALL_DIR} && source venv/bin/activate && python miner.py ${wArg}`);
279
+ }
280
+ break;
281
+
282
+ case 'stop':
283
+ if (os.platform() === 'linux') {
284
+ run('systemctl --user stop rustchain-miner');
285
+ } else if (os.platform() === 'darwin') {
286
+ run(`launchctl unload ~/Library/LaunchAgents/com.rustchain.miner.plist`, { ignoreError: true });
287
+ }
288
+ success('Miner stopped');
289
+ break;
290
+
291
+ case 'status':
292
+ if (os.platform() === 'linux') {
293
+ run('systemctl --user status rustchain-miner', { ignoreError: true });
294
+ } else if (os.platform() === 'darwin') {
295
+ run('launchctl list | grep rustchain', { ignoreError: true });
296
+ }
297
+ // Check network
298
+ try {
299
+ const walletFile = path.join(INSTALL_DIR, '.wallet');
300
+ const w = fs.existsSync(walletFile) ? fs.readFileSync(walletFile, 'utf8').trim() : '';
301
+ log(`Wallet: ${w || '(auto-generated)'}`);
302
+ const out = execSync(`curl -sk ${NODE_URL}/health 2>/dev/null`, { encoding: 'utf8' });
303
+ const health = JSON.parse(out);
304
+ log(`Network: ${health.ok ? 'online' : 'offline'} (v${health.version})`);
305
+ } catch {
306
+ warn('Could not reach network');
307
+ }
308
+ break;
309
+
310
+ case 'logs':
311
+ if (os.platform() === 'linux') {
312
+ run('journalctl --user -u rustchain-miner -f --no-pager -n 50', { ignoreError: true });
313
+ } else if (os.platform() === 'darwin') {
314
+ const logFile = path.join(INSTALL_DIR, 'miner.log');
315
+ if (fs.existsSync(logFile)) {
316
+ run(`tail -f "${logFile}"`);
317
+ } else {
318
+ warn('No log file found');
319
+ }
320
+ }
321
+ break;
322
+
323
+ case 'uninstall':
324
+ log('Stopping miner...');
325
+ if (os.platform() === 'linux') {
326
+ run('systemctl --user stop rustchain-miner', { ignoreError: true, silent: true });
327
+ run('systemctl --user disable rustchain-miner', { ignoreError: true, silent: true });
328
+ const sf = path.join(os.homedir(), '.config', 'systemd', 'user', 'rustchain-miner.service');
329
+ if (fs.existsSync(sf)) fs.unlinkSync(sf);
330
+ } else if (os.platform() === 'darwin') {
331
+ const pf = path.join(os.homedir(), 'Library', 'LaunchAgents', 'com.rustchain.miner.plist');
332
+ run(`launchctl unload "${pf}" 2>/dev/null`, { ignoreError: true, silent: true });
333
+ if (fs.existsSync(pf)) fs.unlinkSync(pf);
334
+ }
335
+ if (fs.existsSync(INSTALL_DIR)) {
336
+ fs.rmSync(INSTALL_DIR, { recursive: true });
337
+ }
338
+ success('RustChain miner uninstalled');
339
+ break;
340
+
341
+ default:
342
+ console.log(`
343
+ Usage: rustchainpoa <command>
344
+
345
+ Commands:
346
+ install Install and configure the miner (default)
347
+ start Start the miner service
348
+ stop Stop the miner service
349
+ status Check miner and network status
350
+ logs View miner logs (follow mode)
351
+ uninstall Remove miner and all files
352
+ `);
353
+ }
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "rustchainpoa",
3
+ "version": "1.0.0",
4
+ "description": "RustChain Proof-of-Antiquity Miner — Mine RTC tokens by proving real vintage hardware",
5
+ "bin": {
6
+ "rustchainpoa": "./bin/rustchainpoa.js"
7
+ },
8
+ "keywords": [
9
+ "rustchain",
10
+ "blockchain",
11
+ "miner",
12
+ "proof-of-antiquity",
13
+ "rtc",
14
+ "cryptocurrency",
15
+ "vintage-hardware",
16
+ "powerpc"
17
+ ],
18
+ "author": "Elyan Labs <scott@elyanlabs.ai>",
19
+ "license": "MIT",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/Scottcjn/Rustchain"
23
+ },
24
+ "homepage": "https://rustchain.org",
25
+ "bugs": {
26
+ "url": "https://github.com/Scottcjn/Rustchain/issues"
27
+ },
28
+ "engines": {
29
+ "node": ">=14"
30
+ },
31
+ "os": [
32
+ "linux",
33
+ "darwin"
34
+ ],
35
+ "files": [
36
+ "bin/",
37
+ "README.md",
38
+ "LICENSE"
39
+ ]
40
+ }