PHP WebShell

Текущая директория: /opt/BitGoJS/examples/ts/sol/utils/nonce-account-creation

Просмотр файла: generate-nonce-accounts.ts

import { KeyPair, TransactionBuilderFactory, WalletInitializationBuilder } from "@bitgo/sdk-coin-sol";
import { coins } from '@bitgo/statics';
import { Connection, NONCE_ACCOUNT_LENGTH, PublicKey, clusterApiUrl, LAMPORTS_PER_SOL } from "@solana/web3.js";
import assert = require("assert");
import { readFileSync, writeFileSync } from "fs";

// This script will generate nonce accounts for a given main account
// run this script after running json/keypair.json to generate the main account keypair

// The main account must have enough balance to create all nonce accounts

// If its a mainnet account and it doesn't have enough balance, it will throw an error
// You can find the address to fund it in json/keypair.json
// ** DO NOT USE THIS KEYPAIR FOR ANYTHING ELSE **
// ** DO NOT SEND TOO MANY FUNDS TO THIS ADDRESS **
// You can estimate the required balance by running the script with the required number of nonce accounts
// and checking the error message. 
// The estimated balance is the required balance is 0.00145768 SOL per nonce account


// If its a testnet account and it doesn't have enough balance, it will request an airdrop automatically

// The nonce accounts will be saved in json/nonceAddresses.json where the key is the main account private key
// and the value is an array of nonce accounts public keys

// To run this script you can use the following command:
// npx ts-node generate-nonce-accounts.ts


// UPDATE this variables to match your environment

// Number of nonce accounts to generate
const accountsRequired = 5

// For BitGo Test use solana 'devnet' network
// For BitGo Prod use solana 'mainnet-beta' network
const network: 'mainnet-beta' | 'devnet' | 'testnet' = 'devnet';
// For BitGo Test use 'tsol' coin
// For BitGo Prod use 'sol' coin
const coin = 'tsol';



async function main() {
  console.log(`Creating ${accountsRequired} nonce accounts`);
  const mainAccountKeyPair: { address: string, privateKey: string } = JSON.parse(
    readFileSync('json/keypair.json').toString()
  );
  assert(mainAccountKeyPair.address, 'address is missing');
  assert(mainAccountKeyPair.privateKey, 'privateKey is missing');
  const nonceAddresses: Record<string, string[]> = JSON.parse(readFileSync('json/nonceAddresses.json').toString());
  nonceAddresses[mainAccountKeyPair.privateKey] = nonceAddresses[mainAccountKeyPair.privateKey] || [];

  const connection = new Connection(clusterApiUrl(network), 'confirmed');

  const nonceMinRentBalance = await connection.getMinimumBalanceForRentExemption(NONCE_ACCOUNT_LENGTH);
  const transactionFee = 10000; // fixed 10_000 lamports

  const mainAccountPublicKey = new PublicKey(mainAccountKeyPair.address);

  console.log(`Checking main account balance for address ${mainAccountKeyPair.address} | ${mainAccountPublicKey}`);
  let mainAccountBalance = await connection.getBalance(mainAccountPublicKey);
  const requiredBalance = accountsRequired * (nonceMinRentBalance + transactionFee);
  console.log(`Main Balance : ${mainAccountBalance} | Req Balance : ${requiredBalance}`);
  // check if main account has enough balance to create nonce accounts
  if (mainAccountBalance < requiredBalance) {
    if (network === 'mainnet-beta') {
      throw new Error(
        `Not enough balance to create all nonce accounts - current balance: 
        ${getValueInSol(mainAccountBalance)} SOL - required balance ${getValueInSol(requiredBalance)} SOL`
      );
    } else {
      console.log('Requesting AirDrop...');
      const airdrop = await connection.requestAirdrop(mainAccountPublicKey, 1 * LAMPORTS_PER_SOL);
      await connection.confirmTransaction(airdrop);
      mainAccountBalance = await connection.getBalance(mainAccountPublicKey);
      console.log(`\tMain Balance : ${mainAccountBalance} | Req Balance : ${requiredBalance}`);
    }
  }

  for (let i = 0; i < accountsRequired; i++) {
    console.log(`Creating nonce account ${i + 1} of ${accountsRequired}`);
    const recentBlockhash = await connection.getLatestBlockhash();

    const nonceAccountKeyPair = new KeyPair().getKeys();

    const txBuilder = getBuilder(coin)
      .nonce(recentBlockhash.blockhash)
      .sender(mainAccountKeyPair.address)
      .address(nonceAccountKeyPair.pub)
      .amount(nonceMinRentBalance.toFixed());
    txBuilder.sign({ key: mainAccountKeyPair.privateKey });
    txBuilder.sign({ key: nonceAccountKeyPair.prv });

    const tx = await txBuilder.build();
    const serializedTx = tx.toBroadcastFormat();

    try {
      const txid = await connection.sendRawTransaction(Buffer.from(serializedTx, 'base64'));
      await connection.confirmTransaction(txid);
      nonceAddresses[mainAccountKeyPair.privateKey].push(nonceAccountKeyPair.pub);
      console.log('Nonce account created: ' + nonceAccountKeyPair.pub);
    } catch (e) {
      console.log('Error creating nonce account for address: ' + nonceAccountKeyPair.pub)
      console.error(e);
    }
  }

  writeFileSync(`json/nonceAddresses.json`, JSON.stringify(nonceAddresses));
  console.log(`Nonce accounts created: ${nonceAddresses[mainAccountKeyPair.privateKey].length}`)
  console.log(`Nonce accounts saved in json/nonceAddresses.json`)
}

main().catch((err) => {
  console.error(err);
  process.exit(-1);
});

// utils functions
function getValueInSol(value: number) {
  return value / LAMPORTS_PER_SOL;
}

const getBuilder = (coin: string): WalletInitializationBuilder => {
  return new TransactionBuilderFactory(coins.get(coin)).getWalletInitializationBuilder();
};

Выполнить команду


Для локальной разработки. Не используйте в интернете!