SHiNE-server/shine-solana/shine/scripts/CreateGovernmentTokenAndDAO/js/_common.js

119 lines
4.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
"use strict";
const fs = require("fs");
const path = require("path");
const readline = require("readline");
const { Keypair, PublicKey, clusterApiUrl } = require("@solana/web3.js");
function parseEnvConfig(configPath) {
const raw = fs.readFileSync(configPath, "utf8");
const out = {};
for (const line of raw.split("\n")) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith("#")) continue;
const eq = trimmed.indexOf("=");
if (eq === -1) continue;
const key = trimmed.slice(0, eq).trim();
let val = trimmed.slice(eq + 1).trim();
if ((val.startsWith('"') && val.endsWith('"')) || (val.startsWith("'") && val.endsWith("'"))) val = val.slice(1, -1);
val = val.replace(/\$HOME/g, process.env.HOME || "");
out[key] = val;
}
return out;
}
function assertRequired(cfg, key) {
if (!cfg[key]) throw new Error(`В конфиге отсутствует обязательный параметр / Missing config key: ${key}`);
}
function resolveConfigPath(argvPath) {
return argvPath ? path.resolve(argvPath) : path.resolve(__dirname, "..", "governance_token.config.env");
}
function loadKeypair(filePath) {
const arr = JSON.parse(fs.readFileSync(filePath, "utf8"));
return Keypair.fromSecretKey(Uint8Array.from(arr));
}
function findSingleJsonFile(dirPath) {
const abs = path.resolve(dirPath);
if (!fs.existsSync(abs)) throw new Error(`Папка не найдена / Directory not found: ${abs}`);
const files = fs.readdirSync(abs).filter((f) => {
const p = path.join(abs, f);
return fs.statSync(p).isFile() && f.endsWith(".json");
});
if (files.length !== 1) {
throw new Error(`В папке должен быть ровно 1 json-файл / Directory must contain exactly 1 json file: ${abs}. Сейчас: ${files.length}`);
}
return path.join(abs, files[0]);
}
function saveKeypair(filePath, keypair) {
fs.mkdirSync(path.dirname(filePath), { recursive: true });
fs.writeFileSync(filePath, JSON.stringify(Array.from(keypair.secretKey)));
}
function parseCluster(cluster) {
if (cluster === "devnet" || cluster === "mainnet-beta" || cluster === "testnet") return clusterApiUrl(cluster);
return cluster;
}
function nowStamp() {
const d = new Date();
const p = (n) => String(n).padStart(2, "0");
return `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}_${p(d.getHours())}-${p(d.getMinutes())}-${p(d.getSeconds())}`;
}
async function askYes(prompt) {
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const answer = await new Promise((resolve) => rl.question(prompt, resolve));
rl.close();
return answer.trim() === "yes";
}
function colors(s, code) { return `\x1b[${code}m${s}\x1b[0m`; }
const ui = {
info: (s) => console.log(colors(s, "36")),
ok: (s) => console.log(colors(s, "32")),
warn: (s) => console.log(colors(s, "33")),
err: (s) => console.log(colors(s, "31")),
title: (s) => console.log(colors(s, "1;35")),
};
function getMintPublicKeyFromConfig(cfg) {
if (cfg.GT_MINT_ADDRESS && cfg.GT_MINT_ADDRESS.trim()) return new PublicKey(cfg.GT_MINT_ADDRESS.trim());
if (cfg.GT_GOVERNMENT_TOKEN_KEYPAIR_DIR && cfg.GT_GOVERNMENT_TOKEN_KEYPAIR_DIR.trim()) {
const kpPath = findSingleJsonFile(path.resolve(cfg.GT_GOVERNMENT_TOKEN_KEYPAIR_DIR));
return loadKeypair(kpPath).publicKey;
}
if (cfg.GT_MINT_KEYPAIR_PATH && cfg.GT_MINT_KEYPAIR_PATH.trim()) return loadKeypair(path.resolve(cfg.GT_MINT_KEYPAIR_PATH)).publicKey;
throw new Error("Не задан mint: укажите GT_MINT_ADDRESS или положите 1 keypair в GT_GOVERNMENT_TOKEN_KEYPAIR_DIR");
}
function getOperatorKeypairFromConfig(cfg) {
if (cfg.GT_DAO_CREATOR_KEYPAIR_DIR && cfg.GT_DAO_CREATOR_KEYPAIR_DIR.trim()) {
const kpPath = findSingleJsonFile(path.resolve(cfg.GT_DAO_CREATOR_KEYPAIR_DIR));
return loadKeypair(kpPath);
}
if (cfg.GT_OPERATOR_KEYPAIR_PATH && cfg.GT_OPERATOR_KEYPAIR_PATH.trim()) {
return loadKeypair(path.resolve(cfg.GT_OPERATOR_KEYPAIR_PATH));
}
throw new Error("Не задан ключ оператора: укажите GT_DAO_CREATOR_KEYPAIR_DIR или GT_OPERATOR_KEYPAIR_PATH");
}
module.exports = {
parseEnvConfig,
assertRequired,
resolveConfigPath,
loadKeypair,
findSingleJsonFile,
saveKeypair,
parseCluster,
nowStamp,
askYes,
ui,
getMintPublicKeyFromConfig,
getOperatorKeypairFromConfig,
};