apow-cli 0.1.4 → 0.3.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/dist/fund.js ADDED
@@ -0,0 +1,313 @@
1
+ "use strict";
2
+ // Fund command — bridge SOL → ETH on Base so Solana users can start mining.
3
+ // Three paths:
4
+ // Option A: Direct Solana signing via deBridge DLN (~20s)
5
+ // Option B: Deposit address + QR via Squid Router (~1-3 min)
6
+ // Option C: Manual send (just show Base address)
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.runFundFlow = runFundFlow;
42
+ const viem_1 = require("viem");
43
+ const wallet_1 = require("./wallet");
44
+ const ui = __importStar(require("./ui"));
45
+ async function fetchPrices() {
46
+ const res = await fetch("https://api.coingecko.com/api/v3/simple/price?ids=solana,ethereum&vs_currencies=usd");
47
+ if (!res.ok)
48
+ throw new Error("Failed to fetch prices from CoinGecko");
49
+ const data = (await res.json());
50
+ const ethUsd = data.ethereum.usd;
51
+ const solUsd = data.solana.usd;
52
+ return { solPerEth: ethUsd / solUsd, ethPriceUsd: ethUsd, solPriceUsd: solUsd };
53
+ }
54
+ /** SOL needed for target ETH, with 10% buffer for bridge fees + slippage. */
55
+ function solNeededForEth(targetEth, solPerEth) {
56
+ return targetEth * solPerEth * 1.1;
57
+ }
58
+ // ---------------------------------------------------------------------------
59
+ // QR code helper
60
+ // ---------------------------------------------------------------------------
61
+ async function showQrCode(text) {
62
+ try {
63
+ const mod = await Promise.resolve().then(() => __importStar(require("qrcode-terminal")));
64
+ const qrcode = mod.default || mod;
65
+ await new Promise((resolve) => {
66
+ qrcode.generate(text, { small: true }, (qr) => {
67
+ for (const line of qr.split("\n")) {
68
+ if (line)
69
+ console.log(` ${line}`);
70
+ }
71
+ resolve();
72
+ });
73
+ });
74
+ }
75
+ catch {
76
+ // QR is nice-to-have, not critical
77
+ }
78
+ }
79
+ // ---------------------------------------------------------------------------
80
+ // Option A — Direct signing via deBridge
81
+ // ---------------------------------------------------------------------------
82
+ async function runDirectBridge(solanaKeyInput, baseAddress, targetEth) {
83
+ const solanaSpinner = ui.spinner("Checking Solana balance...");
84
+ const solana = await Promise.resolve().then(() => __importStar(require("./bridge/solana")));
85
+ const debridge = await Promise.resolve().then(() => __importStar(require("./bridge/debridge")));
86
+ let kp;
87
+ try {
88
+ kp = await solana.parseSolanaKey(solanaKeyInput);
89
+ }
90
+ catch (err) {
91
+ solanaSpinner.fail("Invalid Solana key");
92
+ throw err;
93
+ }
94
+ const balance = await solana.getSolanaBalance(kp.publicKey);
95
+ solanaSpinner.stop(`Solana balance: ${balance.toFixed(4)} SOL`);
96
+ // Prices
97
+ const priceSpinner = ui.spinner("Fetching prices...");
98
+ const prices = await fetchPrices();
99
+ const solAmount = solNeededForEth(targetEth, prices.solPerEth);
100
+ priceSpinner.stop(`SOL/ETH rate: ${prices.solPerEth.toFixed(1)} SOL = 1 ETH`);
101
+ if (balance < solAmount) {
102
+ ui.error(`Insufficient SOL. Need ~${solAmount.toFixed(4)} SOL, have ${balance.toFixed(4)} SOL.`);
103
+ return;
104
+ }
105
+ console.log("");
106
+ ui.table([
107
+ ["Bridging", `${solAmount.toFixed(4)} SOL → ~${targetEth.toFixed(4)} ETH on Base`],
108
+ ["Via", "deBridge DLN (~20 seconds)"],
109
+ [
110
+ "From",
111
+ `${kp.publicKey.slice(0, 4)}...${kp.publicKey.slice(-4)}`,
112
+ ],
113
+ ["To", `${baseAddress.slice(0, 6)}...${baseAddress.slice(-4)}`],
114
+ ]);
115
+ console.log("");
116
+ const proceed = await ui.confirm("Confirm bridge?");
117
+ if (!proceed) {
118
+ console.log(" Cancelled.");
119
+ return;
120
+ }
121
+ const bridgeSpinner = ui.spinner("Signing bridge transaction...");
122
+ const result = await debridge.bridgeViaDeBridge(kp.keypair, baseAddress, solAmount);
123
+ bridgeSpinner.stop(`Submitted! Order: ${result.orderId.slice(0, 12)}...`);
124
+ const pollSpinner = ui.spinner("Waiting for bridge fulfillment... (~20s)");
125
+ const fulfillment = await debridge.pollOrderStatus(result.orderId, (status) => pollSpinner.update(`Bridge status: ${status}`));
126
+ const received = fulfillment.ethReceived || `~${targetEth.toFixed(4)}`;
127
+ pollSpinner.stop(`Bridge complete! ${received} ETH arrived on Base`);
128
+ console.log("");
129
+ console.log(` ${ui.green("Your wallet is funded!")} Next: ${ui.cyan("apow mint")}`);
130
+ console.log("");
131
+ }
132
+ // ---------------------------------------------------------------------------
133
+ // Options B+C — Deposit address via Squid
134
+ // ---------------------------------------------------------------------------
135
+ async function runDepositBridge(baseAddress, targetEth) {
136
+ const priceSpinner = ui.spinner("Fetching prices...");
137
+ const prices = await fetchPrices();
138
+ const solAmount = solNeededForEth(targetEth, prices.solPerEth);
139
+ priceSpinner.stop(`SOL/ETH rate: ${prices.solPerEth.toFixed(1)} SOL = 1 ETH`);
140
+ const addrSpinner = ui.spinner("Generating deposit address...");
141
+ const squid = await Promise.resolve().then(() => __importStar(require("./bridge/squid")));
142
+ const solana = await Promise.resolve().then(() => __importStar(require("./bridge/solana")));
143
+ let deposit;
144
+ try {
145
+ deposit = await squid.getDepositAddress(baseAddress, solAmount);
146
+ }
147
+ catch (err) {
148
+ addrSpinner.fail("Failed to get deposit address");
149
+ throw err;
150
+ }
151
+ addrSpinner.stop("Deposit address ready");
152
+ // Display deposit info
153
+ console.log("");
154
+ console.log(` ${ui.bold("Send SOL to this address:")}`);
155
+ console.log("");
156
+ console.log(` ${ui.cyan(deposit.depositAddress)}`);
157
+ console.log("");
158
+ await showQrCode(deposit.depositAddress);
159
+ console.log("");
160
+ ui.table([
161
+ [
162
+ "Amount",
163
+ `~${solAmount.toFixed(4)} SOL (~$${(solAmount * prices.solPriceUsd).toFixed(2)})`,
164
+ ],
165
+ ["You'll receive", `~${deposit.expectedReceive} ETH on Base`],
166
+ ["Bridge", "Squid Router (Chainflip)"],
167
+ ["Time", "~1-3 minutes"],
168
+ ]);
169
+ console.log("");
170
+ if (deposit.expiresAt) {
171
+ ui.warn(`Deposit address expires: ${deposit.expiresAt}`);
172
+ console.log("");
173
+ }
174
+ // Poll for SOL deposit
175
+ const depositSpinner = ui.spinner("Waiting for SOL deposit... (Ctrl+C to cancel)");
176
+ const initialBalance = await solana.getAddressBalance(deposit.depositAddress);
177
+ let depositDetected = false;
178
+ const depositDeadline = Date.now() + 600_000; // 10 min
179
+ while (!depositDetected && Date.now() < depositDeadline) {
180
+ await new Promise((r) => setTimeout(r, 3000));
181
+ try {
182
+ const currentBalance = await solana.getAddressBalance(deposit.depositAddress);
183
+ if (currentBalance > initialBalance + 0.001) {
184
+ depositDetected = true;
185
+ depositSpinner.stop(`Deposit received! ${(currentBalance - initialBalance).toFixed(4)} SOL`);
186
+ }
187
+ }
188
+ catch {
189
+ // Transient RPC error — keep polling
190
+ }
191
+ }
192
+ if (!depositDetected) {
193
+ depositSpinner.fail("No deposit detected after 10 minutes");
194
+ ui.hint("If you sent SOL, check: https://explorer.squidrouter.com");
195
+ return;
196
+ }
197
+ // Poll for bridge completion
198
+ const bridgeSpinner = ui.spinner("Bridging SOL → ETH on Base... (~1-3 min)");
199
+ const result = await squid.pollBridgeStatus(deposit.requestId, (status) => bridgeSpinner.update(`Bridge status: ${status}`));
200
+ const received = result.ethReceived || deposit.expectedReceive;
201
+ bridgeSpinner.stop(`Bridge complete! ${received} ETH arrived`);
202
+ console.log("");
203
+ console.log(` ${ui.green("Your wallet is funded!")} Next: ${ui.cyan("apow mint")}`);
204
+ console.log("");
205
+ }
206
+ // ---------------------------------------------------------------------------
207
+ // Option C — Manual Base address
208
+ // ---------------------------------------------------------------------------
209
+ async function runManualFund(baseAddress) {
210
+ console.log("");
211
+ console.log(` ${ui.bold("Send ETH on Base to this address:")}`);
212
+ console.log("");
213
+ console.log(` ${ui.cyan(baseAddress)}`);
214
+ console.log("");
215
+ await showQrCode(baseAddress);
216
+ console.log("");
217
+ console.log(` ${ui.dim("Send from any wallet — Coinbase, MetaMask, Phantom, etc.")}`);
218
+ console.log(` ${ui.dim("Need ~0.005 ETH to start mining.")}`);
219
+ console.log(` ${ui.dim("After sending, run:")} ${ui.cyan("apow mint")}`);
220
+ console.log("");
221
+ }
222
+ // ---------------------------------------------------------------------------
223
+ // Main entry point
224
+ // ---------------------------------------------------------------------------
225
+ async function runFundFlow(options) {
226
+ if (!wallet_1.account) {
227
+ ui.error("No wallet configured. Run `apow setup` first.");
228
+ process.exit(1);
229
+ }
230
+ const baseAddress = wallet_1.account.address;
231
+ const balance = await (0, wallet_1.getEthBalance)();
232
+ const ethBalance = Number((0, viem_1.formatEther)(balance));
233
+ console.log("");
234
+ ui.banner(["Fund Your Mining Wallet"]);
235
+ console.log("");
236
+ ui.table([
237
+ [
238
+ "Your Base wallet",
239
+ `${baseAddress.slice(0, 6)}...${baseAddress.slice(-4)}`,
240
+ ],
241
+ [
242
+ "Balance",
243
+ `${ethBalance.toFixed(6)} ETH${ethBalance < 0.005 ? " (need ~0.005 ETH to start)" : ""}`,
244
+ ],
245
+ ]);
246
+ console.log("");
247
+ // Parse target ETH
248
+ const targetEth = options.amount ? parseFloat(options.amount) : 0.005;
249
+ if (isNaN(targetEth) || targetEth <= 0) {
250
+ ui.error("Invalid amount. Specify ETH target (e.g., --amount 0.005).");
251
+ return;
252
+ }
253
+ // --key flag: direct bridge immediately
254
+ if (options.key) {
255
+ await runDirectBridge(options.key, baseAddress, targetEth);
256
+ return;
257
+ }
258
+ // --solana flag: ask about key, then bridge
259
+ if (options.solana) {
260
+ const hasKey = await ui.confirm("Do you have your Solana private key?");
261
+ if (hasKey) {
262
+ const key = await ui.promptSecret("Solana private key (base58)");
263
+ if (!key) {
264
+ ui.error("No key provided.");
265
+ return;
266
+ }
267
+ await runDirectBridge(key, baseAddress, targetEth);
268
+ }
269
+ else {
270
+ await runDepositBridge(baseAddress, targetEth);
271
+ }
272
+ return;
273
+ }
274
+ // Interactive menu
275
+ console.log(" How do you want to fund?");
276
+ console.log(` ${ui.cyan("1.")} Bridge from Solana (SOL → ETH on Base)`);
277
+ console.log(` ${ui.cyan("2.")} Send ETH on Base directly (from another wallet)`);
278
+ console.log(` ${ui.cyan("3.")} Copy address and fund manually`);
279
+ console.log("");
280
+ const choice = await ui.prompt("Choice", "1");
281
+ switch (choice) {
282
+ case "1": {
283
+ const hasKey = await ui.confirm("Do you have your Solana private key?");
284
+ if (hasKey) {
285
+ const key = await ui.promptSecret("Solana private key (base58)");
286
+ if (!key) {
287
+ ui.error("No key provided.");
288
+ return;
289
+ }
290
+ await runDirectBridge(key, baseAddress, targetEth);
291
+ }
292
+ else {
293
+ await runDepositBridge(baseAddress, targetEth);
294
+ }
295
+ break;
296
+ }
297
+ case "2": {
298
+ console.log("");
299
+ console.log(` ${ui.bold("Send ETH on Base to:")}`);
300
+ console.log(` ${ui.cyan(baseAddress)}`);
301
+ console.log("");
302
+ console.log(` ${ui.dim("Need ~0.005 ETH to start mining.")}`);
303
+ console.log(` ${ui.dim("After sending, run:")} ${ui.cyan("apow mint")}`);
304
+ console.log("");
305
+ break;
306
+ }
307
+ case "3":
308
+ default: {
309
+ await runManualFund(baseAddress);
310
+ break;
311
+ }
312
+ }
313
+ }
package/dist/index.js CHANGED
@@ -39,12 +39,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
39
39
  Object.defineProperty(exports, "__esModule", { value: true });
40
40
  const node_fs_1 = require("node:fs");
41
41
  const node_path_1 = require("node:path");
42
+ const node_child_process_1 = require("node:child_process");
42
43
  const commander_1 = require("commander");
43
44
  const viem_1 = require("viem");
44
45
  const MiningAgent_json_1 = __importDefault(require("./abi/MiningAgent.json"));
45
46
  const config_1 = require("./config");
46
47
  const detect_1 = require("./detect");
47
48
  const explorer_1 = require("./explorer");
49
+ const fund_1 = require("./fund");
48
50
  const mint_1 = require("./mint");
49
51
  const miner_1 = require("./miner");
50
52
  const preflight_1 = require("./preflight");
@@ -271,6 +273,18 @@ async function main() {
271
273
  .action(async () => {
272
274
  await setupWizard();
273
275
  });
276
+ program
277
+ .command("fund")
278
+ .description("Fund your wallet — bridge SOL → ETH on Base, or show deposit address")
279
+ .option("--solana", "Bridge from Solana")
280
+ .option("--key <base58>", "Solana private key for direct signing")
281
+ .option("--amount <eth>", "Target ETH amount (default: 0.005)")
282
+ .hook("preAction", async () => {
283
+ await (0, preflight_1.runPreflight)("readonly");
284
+ })
285
+ .action(async (opts) => {
286
+ await (0, fund_1.runFundFlow)(opts);
287
+ });
274
288
  program
275
289
  .command("mint")
276
290
  .description("Mint a new miner NFT")
@@ -457,8 +471,198 @@ async function main() {
457
471
  console.log(` Tx: ${ui.dim((0, explorer_1.txUrl)(receipt.transactionHash))}`);
458
472
  console.log("");
459
473
  });
474
+ // --- Dashboard commands ---
475
+ const dashboardCmd = program
476
+ .command("dashboard")
477
+ .description("Multi-wallet mining dashboard");
478
+ dashboardCmd
479
+ .command("start", { isDefault: true })
480
+ .description("Launch the dashboard web UI")
481
+ .action(async () => {
482
+ const walletsPath = getWalletsPath();
483
+ // Seed wallets.json if it doesn't exist
484
+ if (!(0, node_fs_1.existsSync)(walletsPath)) {
485
+ const walletsDir = (0, node_path_1.join)(process.env.HOME ?? "", ".apow");
486
+ if (!(0, node_fs_1.existsSync)(walletsDir))
487
+ (0, node_fs_1.mkdirSync)(walletsDir, { recursive: true });
488
+ const initial = wallet_1.account ? [wallet_1.account.address] : [];
489
+ (0, node_fs_1.writeFileSync)(walletsPath, JSON.stringify(initial, null, 2), "utf8");
490
+ if (wallet_1.account) {
491
+ ui.ok(`Seeded ${walletsPath} with ${wallet_1.account.address.slice(0, 6)}...${wallet_1.account.address.slice(-4)}`);
492
+ }
493
+ else {
494
+ ui.ok(`Created ${walletsPath} (empty — add wallets with: apow dashboard add <address>)`);
495
+ }
496
+ }
497
+ // Auto-detect wallets from CWD
498
+ const { addresses, newCount } = detectWallets(process.cwd());
499
+ if (newCount > 0) {
500
+ ui.ok(`Detected ${addresses.length} wallets (${newCount} new)`);
501
+ }
502
+ else if (addresses.length > 0) {
503
+ console.log(` ${ui.dim(`${addresses.length} wallets loaded`)}`);
504
+ }
505
+ const { startDashboardServer } = await Promise.resolve().then(() => __importStar(require("./dashboard")));
506
+ console.log("");
507
+ console.log(` ${ui.bold("APoW Dashboard")} starting on http://localhost:3847`);
508
+ console.log(` ${ui.dim("Press Ctrl+C to stop")}`);
509
+ console.log("");
510
+ const server = startDashboardServer({
511
+ port: 3847,
512
+ walletsPath,
513
+ rpcUrl: config_1.config.rpcUrl,
514
+ miningAgentAddress: config_1.config.miningAgentAddress,
515
+ agentCoinAddress: config_1.config.agentCoinAddress,
516
+ });
517
+ // Open browser after short delay (server starts instantly)
518
+ setTimeout(() => {
519
+ const openCmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
520
+ (0, node_child_process_1.spawn)(openCmd, ["http://localhost:3847"], { stdio: "ignore" });
521
+ }, 500);
522
+ // Wait for SIGINT
523
+ await new Promise((resolve) => {
524
+ process.on("SIGINT", () => {
525
+ server.close();
526
+ resolve();
527
+ });
528
+ });
529
+ });
530
+ dashboardCmd
531
+ .command("add <address>")
532
+ .description("Add a wallet address to monitor")
533
+ .action((address) => {
534
+ if (!/^0x[0-9a-fA-F]{40}$/.test(address)) {
535
+ ui.error("Invalid address. Must be 0x + 40 hex characters.");
536
+ return;
537
+ }
538
+ const walletsPath = getWalletsPath();
539
+ const wallets = loadWallets(walletsPath);
540
+ const lower = address.toLowerCase();
541
+ if (wallets.some((w) => w.toLowerCase() === lower)) {
542
+ ui.warn("Address already monitored.");
543
+ return;
544
+ }
545
+ wallets.push(address);
546
+ saveWallets(walletsPath, wallets);
547
+ ui.ok(`Added ${address.slice(0, 6)}...${address.slice(-4)} (${wallets.length} wallets total)`);
548
+ });
549
+ dashboardCmd
550
+ .command("remove <address>")
551
+ .description("Remove a wallet address from monitoring")
552
+ .action((address) => {
553
+ const walletsPath = getWalletsPath();
554
+ const wallets = loadWallets(walletsPath);
555
+ const lower = address.toLowerCase();
556
+ const filtered = wallets.filter((w) => w.toLowerCase() !== lower);
557
+ if (filtered.length === wallets.length) {
558
+ ui.warn("Address not found in wallet list.");
559
+ return;
560
+ }
561
+ saveWallets(walletsPath, filtered);
562
+ ui.ok(`Removed ${address.slice(0, 6)}...${address.slice(-4)} (${filtered.length} wallets remaining)`);
563
+ });
564
+ dashboardCmd
565
+ .command("scan [dir]")
566
+ .description("Auto-detect wallets from wallet-0x*.txt files in a directory")
567
+ .action((dir) => {
568
+ const scanDir = dir ?? process.cwd();
569
+ const { addresses, newCount } = detectWallets(scanDir);
570
+ console.log("");
571
+ if (addresses.length === 0) {
572
+ console.log(` No wallets found in ${scanDir}`);
573
+ console.log(` ${ui.dim("Expected files named wallet-0x<address>.txt")}`);
574
+ }
575
+ else {
576
+ console.log(` ${ui.bold("Detected Wallets")} (${newCount} new, ${addresses.length} total)`);
577
+ console.log("");
578
+ for (const addr of addresses) {
579
+ console.log(` ${addr}`);
580
+ }
581
+ }
582
+ console.log("");
583
+ });
584
+ dashboardCmd
585
+ .command("wallets")
586
+ .description("List monitored wallet addresses")
587
+ .action(() => {
588
+ const walletsPath = getWalletsPath();
589
+ const wallets = loadWallets(walletsPath);
590
+ if (wallets.length === 0) {
591
+ console.log(" No wallets configured. Run: apow dashboard add <address>");
592
+ return;
593
+ }
594
+ console.log("");
595
+ console.log(` ${ui.bold("Monitored Wallets")} (${wallets.length})`);
596
+ console.log("");
597
+ for (const w of wallets) {
598
+ console.log(` ${w}`);
599
+ }
600
+ console.log("");
601
+ });
460
602
  await program.parseAsync(process.argv);
461
603
  }
604
+ function getWalletsPath() {
605
+ return (0, node_path_1.join)(process.env.HOME ?? "", ".apow", "wallets.json");
606
+ }
607
+ function loadWallets(path) {
608
+ try {
609
+ const raw = (0, node_fs_1.readFileSync)(path, "utf8");
610
+ const data = JSON.parse(raw);
611
+ return Array.isArray(data) ? data.filter((a) => typeof a === "string") : [];
612
+ }
613
+ catch {
614
+ return [];
615
+ }
616
+ }
617
+ function saveWallets(path, wallets) {
618
+ const dir = (0, node_path_1.join)(process.env.HOME ?? "", ".apow");
619
+ if (!(0, node_fs_1.existsSync)(dir))
620
+ (0, node_fs_1.mkdirSync)(dir, { recursive: true });
621
+ (0, node_fs_1.writeFileSync)(path, JSON.stringify(wallets, null, 2), "utf8");
622
+ }
623
+ function detectWallets(scanDir) {
624
+ const walletsPath = getWalletsPath();
625
+ const existing = loadWallets(walletsPath);
626
+ const seen = new Set(existing.map((a) => a.toLowerCase()));
627
+ const detected = [];
628
+ // Scan scanDir for wallet-0x*.txt files
629
+ try {
630
+ const entries = (0, node_fs_1.readdirSync)(scanDir, { withFileTypes: true });
631
+ for (const entry of entries) {
632
+ if (entry.isFile()) {
633
+ const match = entry.name.match(/^wallet-(0x[0-9a-fA-F]{40})\.txt$/);
634
+ if (match && !seen.has(match[1].toLowerCase())) {
635
+ detected.push(match[1]);
636
+ seen.add(match[1].toLowerCase());
637
+ }
638
+ }
639
+ // Scan rig*/wallet-0x*.txt subdirectories
640
+ if (entry.isDirectory() && entry.name.startsWith("rig")) {
641
+ try {
642
+ const rigFiles = (0, node_fs_1.readdirSync)((0, node_path_1.join)(scanDir, entry.name));
643
+ for (const file of rigFiles) {
644
+ const m = file.match(/^wallet-(0x[0-9a-fA-F]{40})\.txt$/);
645
+ if (m && !seen.has(m[1].toLowerCase())) {
646
+ detected.push(m[1]);
647
+ seen.add(m[1].toLowerCase());
648
+ }
649
+ }
650
+ }
651
+ catch {
652
+ // rig dir not readable — skip
653
+ }
654
+ }
655
+ }
656
+ }
657
+ catch {
658
+ // scanDir not readable
659
+ }
660
+ const merged = [...existing, ...detected];
661
+ if (detected.length > 0) {
662
+ saveWallets(walletsPath, merged);
663
+ }
664
+ return { addresses: merged, newCount: detected.length };
665
+ }
462
666
  main().catch((error) => {
463
667
  const message = error instanceof Error ? error.message : String(error);
464
668
  ui.error(message);
package/dist/smhl.js CHANGED
@@ -234,7 +234,7 @@ async function requestGeminiSolution(prompt) {
234
234
  parts: [{ text: "You generate short lowercase word sequences that match exact constraints. Return only the words separated by spaces. Nothing else." }],
235
235
  },
236
236
  contents: [{ parts: [{ text: prompt }] }],
237
- generationConfig: { temperature: 0.7 },
237
+ generationConfig: { temperature: 0.7, thinkingConfig: { thinkingBudget: 0 } },
238
238
  }),
239
239
  });
240
240
  if (response.status === 429) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "apow-cli",
3
- "version": "0.1.4",
3
+ "version": "0.3.0",
4
4
  "description": "Mine AGENT tokens on Base L2 with AI-powered proof of work",
5
5
  "keywords": [
6
6
  "apow",
@@ -39,9 +39,11 @@
39
39
  "prepublishOnly": "npm run build"
40
40
  },
41
41
  "dependencies": {
42
+ "@solana/web3.js": "^1.98.0",
42
43
  "commander": "^14.0.0",
43
44
  "dotenv": "^17.2.3",
44
45
  "openai": "^6.6.0",
46
+ "qrcode-terminal": "^0.12.0",
45
47
  "viem": "^2.38.2"
46
48
  },
47
49
  "devDependencies": {