Skip to content

Instantly share code, notes, and snippets.

@NotoriousPyro
Last active May 16, 2024 22:54
Show Gist options
  • Save NotoriousPyro/f316329f4a2d55ae1506d447716c82ce to your computer and use it in GitHub Desktop.
Save NotoriousPyro/f316329f4a2d55ae1506d447716c82ce to your computer and use it in GitHub Desktop.
Create nonce accounts on solana example
import {
Connection,
CreateNonceAccountParams,
Keypair,
NONCE_ACCOUNT_LENGTH,
PublicKey,
SystemProgram,
Transaction,
TransactionMessage,
VersionedTransaction,
WithdrawNonceParams
} from "@solana/web3.js";
import config from "../src/lib/Config";
import bs58 from "bs58";
import fs from 'fs';
import yaml from 'yaml';
import { createComputeBudgetInstruction } from "../src/lib/TransactionBuilder";
const connection = new Connection(
config.rpc[0].httpEndpoint,
{
disableRetryOnRateLimit: config.rpc[0].disableRetryOnRateLimit,
commitment: config.rpc[0].commitment,
wsEndpoint: config.rpc[0].wsEndpoint,
},
);
/**
* Create 4 nonce accounts and initialise them.
*/
const createNonceAccount = async () => {
const instruction = new Transaction();
const keypairs: Keypair[] = []
for (let i = 0; i < 4; i++) {
keypairs.push(Keypair.generate());
}
console.log("Secret keys for nonce accounts: ")
for (const keypair of keypairs) {
console.log(bs58.encode(keypair.secretKey))
const rent = await connection.getMinimumBalanceForRentExemption(NONCE_ACCOUNT_LENGTH)
const nonceparams: CreateNonceAccountParams = {
fromPubkey: config.keypair.publicKey,
noncePubkey: keypair.publicKey,
authorizedPubkey: config.keypair.publicKey,
lamports: rent,
};
instruction.add(
SystemProgram.createNonceAccount(nonceparams),
)
}
const bhInfo = await connection.getLatestBlockhashAndContext({ commitment: "finalized" });
const messageV0 = new TransactionMessage({
payerKey: config.keypair.publicKey,
recentBlockhash: bhInfo.value.blockhash,
instructions: [
...createComputeBudgetInstruction(
100_000, 100
),
...instruction.instructions
],
}).compileToV0Message();
const tx = new VersionedTransaction(messageV0);
tx.sign([config.keypair, ...keypairs]);
const simulation = await connection.simulateTransaction(tx, { commitment: "confirmed" });
if (simulation.value.err) {
throw new Error(`Simulation failed: ${simulation.value.err.toString()}`);
}
try {
const signature = await connection.sendTransaction(tx, {
maxRetries: 20,
skipPreflight: false,
preflightCommitment: "confirmed",
});
const confirmation = await connection.confirmTransaction({
signature,
blockhash: bhInfo.value.blockhash,
lastValidBlockHeight: bhInfo.value.lastValidBlockHeight,
}, "confirmed");
if (confirmation.value.err) {
throw new Error(`Transaction not confirmed: ${confirmation.value.err.toString()}`);
}
console.log("Confirmed: ", signature);
fs.appendFileSync("noncekeys.yaml", yaml.stringify(keypairs.map(keypair => bs58.encode(keypair.secretKey))));
fs.appendFileSync("noncepubkeys.yaml", yaml.stringify(keypairs.map(keypair => keypair.publicKey.toString())));
} catch (error) {
console.error("Failed: ", error);
throw error;
}
}
/**
* Withdraw the lamports from the nonce accounts and close them.
*/
const withdrawNonceAccount = async () => {
const publicKeys: PublicKey[] = [
].map(secret => new PublicKey(secret));
console.log("Secret keys for nonce accounts: ")
const chunkSize = 5;
for (let i = 0; i < publicKeys.length; i += chunkSize) {
const instruction = new Transaction();
const chunk = publicKeys.slice(i, i + chunkSize);
for (const publicKey of chunk) {
const rent = await connection.getMinimumBalanceForRentExemption(NONCE_ACCOUNT_LENGTH)
const nonceparams: WithdrawNonceParams = {
noncePubkey: publicKey,
authorizedPubkey: config.keypair.publicKey,
toPubkey: config.keypair.publicKey,
lamports: rent,
};
instruction.add(
SystemProgram.nonceWithdraw(nonceparams),
)
}
// eslint-disable-next-line no-constant-condition
while (true) {
const bhInfo = await connection.getLatestBlockhashAndContext();
const messageV0 = new TransactionMessage({
payerKey: config.keypair.publicKey,
recentBlockhash: bhInfo.value.blockhash,
instructions: [
...createComputeBudgetInstruction(
100_000, 100
),
...instruction.instructions
],
}).compileToV0Message();
const tx = new VersionedTransaction(messageV0);
tx.sign([config.keypair]);
const simulation = await connection.simulateTransaction(tx, { commitment: "confirmed" });
console.log("Simulation: ", simulation.value);
if (simulation.value.err === "BlockhashNotFound") {
continue;
}
try {
const signature = await connection.sendTransaction(tx, {
maxRetries: 20,
skipPreflight: false,
});
const confirmation = await connection.confirmTransaction({
signature,
blockhash: bhInfo.value.blockhash,
lastValidBlockHeight: bhInfo.value.lastValidBlockHeight,
}, "confirmed");
if (confirmation.value.err) {
throw new Error(`Transaction not confirmed: ${confirmation.value.err.toString()}`);
}
console.log("Confirmed: ", signature);
} catch (error) {
console.error("Failed: ", error);
throw error;
}
break;
}
}
}
// uncomment what you want to do
createNonceAccount();
//withdrawNonceAccount();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment