-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathconfigure.js
More file actions
137 lines (116 loc) · 4.79 KB
/
configure.js
File metadata and controls
137 lines (116 loc) · 4.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// configure.js – interactive .env generator with Solana wallet support
// -------------------------------------------------------------------
// • Reads example.env (template) line‑by‑line
// • Prompts the user for every KEY, offering the template value as default
// • Ensures a Solana key‑pair exists; if not, writes ./id.json in CWD
// • After creating a wallet, prints the public address
// • Adds the public address as a comment in the .env, e.g.
// # WALLET_ADDRESS=6yP4…JWkq
// just above the WALLET_PATH line.
// -------------------------------------------------------------------
import fs from 'fs';
import path from 'path';
import readline from 'readline/promises';
import { stdin as input, stdout as output } from 'node:process';
import { Keypair } from '@solana/web3.js';
const kvRegex = /^\s*([A-Z0-9_]+)\s*=\s*(.*?)\s*(?:#.*)?$/;
/* ---------- helpers -------------------------------------------------- */
/** Parse KEY=value pairs (ignore comments/blank lines). */
function parseTemplate(templatePath) {
const lines = fs.readFileSync(templatePath, 'utf8').split(/\r?\n/);
const pairs = [];
lines.forEach((line, idx) => {
const match = line.match(kvRegex);
if (match) {
pairs.push({ key: match[1], def: match[2] });
} else if (line.trim() && !line.trim().startsWith('#')) {
console.warn(`[warn] line ${idx + 1} ignored (not KEY=VALUE): ${line}`);
}
});
return pairs;
}
/** Ensure wallet exists, return { path, pubkey }. */
function ensureWallet(walletPath) {
let absPath = path.resolve(walletPath);
let kp;
try {
if (fs.existsSync(absPath)) {
// Read existing wallet to get the public key
const secret = JSON.parse(fs.readFileSync(absPath, 'utf8'));
kp = Keypair.fromSecretKey(Uint8Array.from(secret));
console.log(`[info] using existing wallet at ${absPath}`);
return { path: absPath, pubkey: kp.publicKey.toBase58() };
}
console.log('[info] wallet file not found — generating a new key‑pair …');
fs.mkdirSync(path.dirname(absPath), { recursive: true });
kp = Keypair.generate();
fs.writeFileSync(absPath, JSON.stringify(Array.from(kp.secretKey)));
console.log(`[success] new key‑pair saved to ${absPath}`);
return { path: absPath, pubkey: kp.publicKey.toBase58() };
} catch (err) {
console.error(`[warn] cannot write wallet at ${absPath}: ${err.message}`);
// Fallback to ./id.json in CWD
const fallback = path.join(process.cwd(), 'id.json');
try {
kp = Keypair.generate();
fs.writeFileSync(fallback, JSON.stringify(Array.from(kp.secretKey)), {
flag: 'wx',
});
console.log(`[success] new key‑pair saved to ${fallback}`);
return { path: fallback, pubkey: kp.publicKey.toBase58() };
} catch (e) {
console.error(`[error] fallback wallet creation failed: ${e.message}`);
// Return whatever info we have; pubkey may be undefined
return { path: fallback, pubkey: kp?.publicKey?.toBase58() ?? '' };
}
}
}
/* ---------- main ----------------------------------------------------- */
async function main(templateFile = '.env.example', outputFile = '.env') {
if (!fs.existsSync(templateFile)) {
console.error(`[fatal] template not found: ${templateFile}`);
return;
}
const templatePairs = parseTemplate(templateFile);
const rl = readline.createInterface({ input, output });
const answers = {};
// Interactive prompt
for (const { key, def } of templatePairs) {
try {
const reply = await rl.question(`${key} [${def}]: `);
answers[key] = reply.trim() ? reply.trim() : def;
} catch (err) {
console.error(`[error] reading ${key}: ${err.message}`);
answers[key] = def;
}
}
rl.close();
// Wallet handling ----------------------------------------------------
const WALLET_VAR = 'WALLET_PATH';
let walletPath =
answers[WALLET_VAR] || path.join(process.cwd(), 'id.json');
// Make relative paths explicit
if (!path.isAbsolute(walletPath)) {
walletPath = path.join(process.cwd(), walletPath);
}
const { path: finalWalletPath, pubkey } = ensureWallet(walletPath);
answers[WALLET_VAR] = finalWalletPath;
if (pubkey) {
console.log(`[info] wallet public address: ${pubkey}`);
}
// Write .env ---------------------------------------------------------
try {
const lines = [];
for (const [key, val] of Object.entries(answers)) {
if (key === WALLET_VAR && pubkey) {
lines.push(`# WALLET_ADDRESS=${pubkey}`); // comment with address
}
lines.push(`${key}=${val}`);
}
fs.writeFileSync(outputFile, lines.join('\n') + '\n');
console.log(`[success] wrote ${outputFile}`);
} catch (err) {
console.error(`[error] writing ${outputFile}: ${err.message}`);
}
}
main().catch((err) => console.error(`[fatal] unhandled: ${err.message}`));