How to Create an Account

Creating an account requires using the System Program createAccount instruction. The Solana runtime will grant the owner program of an account, access to write to its data or transfer lamports. When creating an account, we have to preallocate a fixed storage space in bytes (space) and enough lamports to cover the rent.

create-account.ts
import {
  pipe,
  createSolanaRpc,
  appendTransactionMessageInstructions,
  createSolanaRpcSubscriptions,
  createTransactionMessage,
  generateKeyPairSigner,
  getSignatureFromTransaction,
  sendAndConfirmTransactionFactory,
  setTransactionMessageFeePayerSigner,
  setTransactionMessageLifetimeUsingBlockhash,
  signTransactionMessageWithSigners,
} from "@solana/web3.js";
import { getSetComputeUnitPriceInstruction } from "@solana-program/compute-budget";
import {
  getCreateAccountInstruction,
  SYSTEM_PROGRAM_ADDRESS,
} from "@solana-program/system";
 
const rpc = createSolanaRpc("https://api.devnet.solana.com");
const rpcSubscriptions = createSolanaRpcSubscriptions(
  "wss://api.devnet.solana.com",
);
 
const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
  rpc,
  rpcSubscriptions,
});
 
const space = 0n; // any extra space in the account
const rentLamports = await rpc.getMinimumBalanceForRentExemption(space).send();
console.log("Minimum balance for rent exception:", rentLamports);
 
// todo: load your own signer with SOL
const signer = await generateKeyPairSigner();
 
// generate a new keypair and address to create
const newAccountKeypair = await generateKeyPairSigner();
console.log("New account address:", newAccountKeypair.address);
 
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
 
const transactionMessage = pipe(
  createTransactionMessage({ version: "legacy" }),
  tx => setTransactionMessageFeePayerSigner(signer, tx),
  tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
  tx =>
    appendTransactionMessageInstructions(
      [
        // add a priority fee
        getSetComputeUnitPriceInstruction({
          microLamports: 200_000,
        }),
        // create the new account
        getCreateAccountInstruction({
          lamports: rentLamports,
          newAccount: newAccountKeypair,
          payer: signer,
          space: space,
          // "wallet" accounts are owned by the system program
          programAddress: SYSTEM_PROGRAM_ADDRESS,
        }),
      ],
      tx,
    ),
);
 
const signedTransaction =
  await signTransactionMessageWithSigners(transactionMessage);
const signature = getSignatureFromTransaction(signedTransaction);
 
await sendAndConfirmTransaction(signedTransaction, {
  commitment: "confirmed",
});
console.log("Signature:", signature);