#!/usr/bin/env node "use strict"; const fs = require("fs"); const path = require("path"); const { PublicKey, Keypair, clusterApiUrl } = require("@solana/web3.js"); const { InstructionData, AccountMetaData } = require("@solana/spl-governance"); function parseEnvConfig(configPath) { const raw = fs.readFileSync(configPath, "utf8"); const out = {}; for (const line of raw.split("\n")) { const t = line.trim(); if (!t || t.startsWith("#")) continue; const i = t.indexOf("="); if (i < 0) continue; const k = t.slice(0, i).trim(); let v = t.slice(i + 1).trim(); if ((v.startsWith('"') && v.endsWith('"')) || (v.startsWith("'") && v.endsWith("'"))) v = v.slice(1, -1); out[k] = v; } return out; } function resolveConfigPath(argvPath) { return argvPath ? path.resolve(argvPath) : path.resolve(__dirname, "config.env"); } function loadKeypair(fp) { return Keypair.fromSecretKey(Uint8Array.from(JSON.parse(fs.readFileSync(fp, "utf8")))); } function clusterUrl(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())}`; } function toInstructionData(ix) { return new InstructionData({ programId: ix.programId, accounts: ix.keys.map((k) => new AccountMetaData({ pubkey: k.pubkey, isSigner: !!k.isSigner, isWritable: !!k.isWritable })), data: Uint8Array.from(ix.data), }); } module.exports = { parseEnvConfig, resolveConfigPath, loadKeypair, clusterUrl, nowStamp, toInstructionData, PublicKey };