shine-solana/shine/scripts/governance_token/01_create_governance_token_exec.js

115 lines
3.3 KiB
JavaScript

#!/usr/bin/env node
"use strict";
const fs = require("fs");
const path = require("path");
const {
Connection,
Keypair,
SystemProgram,
Transaction,
sendAndConfirmTransaction,
} = require("@solana/web3.js");
const {
TOKEN_2022_PROGRAM_ID,
ExtensionType,
getMintLen,
createInitializeMintInstruction,
createInitializeNonTransferableMintInstruction,
createInitializePermanentDelegateInstruction,
} = require("@solana/spl-token");
const {
parseEnvConfig,
assertRequired,
resolveConfigPath,
loadKeypair,
saveKeypair,
parseCluster,
nowStamp,
} = require("./_common");
async function main() {
const configPath = resolveConfigPath(process.argv[2]);
const cfg = parseEnvConfig(configPath);
assertRequired(cfg, "GT_CLUSTER");
assertRequired(cfg, "GT_OPERATOR_KEYPAIR_PATH");
assertRequired(cfg, "GT_RUNS_DIR");
const operator = loadKeypair(path.resolve(cfg.GT_OPERATOR_KEYPAIR_PATH));
const connection = new Connection(parseCluster(cfg.GT_CLUSTER), "confirmed");
let mint;
if (cfg.GT_MINT_KEYPAIR_PATH) {
mint = loadKeypair(path.resolve(cfg.GT_MINT_KEYPAIR_PATH));
} else {
mint = Keypair.generate();
}
const extensions = [ExtensionType.NonTransferable, ExtensionType.PermanentDelegate];
const mintLen = getMintLen(extensions);
const rent = await connection.getMinimumBalanceForRentExemption(mintLen, "confirmed");
const tx = new Transaction().add(
SystemProgram.createAccount({
fromPubkey: operator.publicKey,
newAccountPubkey: mint.publicKey,
space: mintLen,
lamports: rent,
programId: TOKEN_2022_PROGRAM_ID,
}),
createInitializeNonTransferableMintInstruction(mint.publicKey, TOKEN_2022_PROGRAM_ID),
createInitializePermanentDelegateInstruction(
mint.publicKey,
operator.publicKey,
TOKEN_2022_PROGRAM_ID
),
createInitializeMintInstruction(
mint.publicKey,
0,
operator.publicKey,
operator.publicKey,
TOKEN_2022_PROGRAM_ID
)
);
const sig = await sendAndConfirmTransaction(connection, tx, [operator, mint], {
commitment: "confirmed",
});
const runsDir = path.resolve(cfg.GT_RUNS_DIR);
fs.mkdirSync(runsDir, { recursive: true });
const outMintPath =
cfg.GT_MINT_KEYPAIR_PATH && cfg.GT_MINT_KEYPAIR_PATH.trim()
? path.resolve(cfg.GT_MINT_KEYPAIR_PATH)
: path.join(runsDir, `${nowStamp()}_mint-keypair.json`);
saveKeypair(outMintPath, mint);
const report = {
createdAt: new Date().toISOString(),
cluster: cfg.GT_CLUSTER,
operator: operator.publicKey.toBase58(),
mint: mint.publicKey.toBase58(),
tokenProgram: TOKEN_2022_PROGRAM_ID.toBase58(),
nonTransferable: true,
permanentDelegate: operator.publicKey.toBase58(),
mintAuthority: operator.publicKey.toBase58(),
freezeAuthority: operator.publicKey.toBase58(),
mintKeypairPath: outMintPath,
txCreateMint: sig,
};
const reportPath = path.join(runsDir, `${nowStamp()}_create_token.json`);
fs.writeFileSync(reportPath, JSON.stringify(report, null, 2));
console.log("Governance token создан.");
console.log("Mint:", mint.publicKey.toBase58());
console.log("Mint keypair:", outMintPath);
console.log("Tx:", sig);
console.log("Report:", reportPath);
}
main().catch((e) => {
console.error("Ошибка создания governance token:", e?.message || e);
process.exit(1);
});