Writing to the Network
In the previous section, you learned how to read data from the Solana network. Now you'll learn how to write data to it. Writing to the Solana network involves sending transactions that contain one or more instruction.
Programs define the business logic for what each instruction does. When you submit a transaction, the Solana runtime executes each instruction in sequence and atomically. The examples in this section show how to build and send transactions to invoke Solana programs, they include:
- Transferring SOL between accounts
- Creating a new token
Transfer SOL
The example below transfers SOL between two accounts. Each account has an owner program, which is the only program that can deduct the account's SOL balance.
All wallet accounts are owned by the System Program. To transfer SOL, you must invoke the System Program's transfer instruction.
import {LAMPORTS_PER_SOL,SystemProgram,Transaction,sendAndConfirmTransaction,Keypair,Connection} from "@solana/web3.js";const connection = new Connection("http://localhost:8899", "confirmed");const sender = new Keypair();const receiver = new Keypair();const signature = await connection.requestAirdrop(sender.publicKey,LAMPORTS_PER_SOL);await connection.confirmTransaction(signature, "confirmed");const transferInstruction = SystemProgram.transfer({fromPubkey: sender.publicKey,toPubkey: receiver.publicKey,lamports: 0.01 * LAMPORTS_PER_SOL});const transaction = new Transaction().add(transferInstruction);const transactionSignature = await sendAndConfirmTransaction(connection,transaction,[sender]);console.log("Transaction Signature:", `${transactionSignature}`);const senderBalance = await connection.getBalance(sender.publicKey);const receiverBalance = await connection.getBalance(receiver.publicKey);console.log("Sender Balance:", `${senderBalance}`);console.log("Receiver Balance:", `${receiverBalance}`);
Create a Connection to handle sending transactions and fetching account data.
In this example, we're connecting to the local test validator which runs on
localhost:8899.
const connection = new Connection("http://localhost:8899", "confirmed");
Generate new keypairs to use as the sender and receiver accounts.
const sender = new Keypair();const receiver = new Keypair();
Add SOL to the sender account.
On networks other than mainnet, you can use the requestAirdrop method to get
SOL for testing.
const signature = await connection.requestAirdrop(sender.publicKey,LAMPORTS_PER_SOL);await connection.confirmTransaction(signature, "confirmed");
The SystemProgram.transfer() method creates an instruction that transfers SOL
from the fromPubkey account to the toPubkey
account for the specified number of lamports.
const transferInstruction = SystemProgram.transfer({fromPubkey: sender.publicKey,toPubkey: receiver.publicKey,lamports: 0.01 * LAMPORTS_PER_SOL});
Create a transaction and add the instruction to the transaction. In this example, we're creating a transaction with a single instruction. However, you can add multiple instructions to a transaction.
const transaction = new Transaction().add(transferInstruction);
Sign and send the transaction to the network. The sender keypair is required in the signers array to authorize the transfer of SOL from their account.
const transactionSignature = await sendAndConfirmTransaction(connection,transaction,[sender]);
The transaction signature is a unique identifier that can be used to look up the transaction on Solana Explorer.
Create a token
The example below creates a new token on Solana using the Token Extensions Program. This requires two instructions:
- Invoke the System Program to create a new account.
- Invoke the Token Extensions Program to initialize that account as a Mint.
import {Connection,Keypair,SystemProgram,Transaction,sendAndConfirmTransaction,LAMPORTS_PER_SOL} from "@solana/web3.js";import {MINT_SIZE,TOKEN_2022_PROGRAM_ID,createInitializeMint2Instruction,getMinimumBalanceForRentExemptMint,getMint} from "@solana/spl-token";const connection = new Connection("http://localhost:8899", "confirmed");const wallet = new Keypair();// Fund the wallet with SOLconst signature = await connection.requestAirdrop(wallet.publicKey,LAMPORTS_PER_SOL);await connection.confirmTransaction(signature, "confirmed");// Generate keypair to use as address of mint accountconst mint = new Keypair();// Calculate lamports required for rent exemptionconst rentExemptionLamports =await getMinimumBalanceForRentExemptMint(connection);// Instruction to create new account with space for new mint accountconst createAccountInstruction = SystemProgram.createAccount({fromPubkey: wallet.publicKey,newAccountPubkey: mint.publicKey,space: MINT_SIZE,lamports: rentExemptionLamports,programId: TOKEN_2022_PROGRAM_ID});// Instruction to initialize mint accountconst initializeMintInstruction = createInitializeMint2Instruction(mint.publicKey,2, // decimalswallet.publicKey, // mint authoritywallet.publicKey, // freeze authorityTOKEN_2022_PROGRAM_ID);// Build transaction with instructions to create new account and initialize mint accountconst transaction = new Transaction().add(createAccountInstruction,initializeMintInstruction);const transactionSignature = await sendAndConfirmTransaction(connection,transaction,[wallet, // payermint // mint address keypair]);console.log("Transaction Signature:", `${transactionSignature}`);const mintData = await getMint(connection,mint.publicKey,"confirmed",TOKEN_2022_PROGRAM_ID););
Creating a token requires using both the @solana/web3.js and
@solana/spl-token libraries.
The code in the example below will:
- Create a connection
- Generate a keypair to pay for the transaction
- Request an airdrop to fund the keypair
const connection = new Connection("http://localhost:8899", "confirmed");const wallet = new Keypair();const signature = await connection.requestAirdrop(wallet.publicKey,LAMPORTS_PER_SOL);await connection.confirmTransaction(signature, "confirmed");
Generate a keypair for the mint account. The public key will be used as the mint account's address.
const mint = new Keypair();
Calculate the minimum lamports required for a mint account.
The getMinimumBalanceForRentExemptMint function calculates how many
lamport must be allocated for the data on a mint account.
const rentExemptionLamports =await getMinimumBalanceForRentExemptMint(connection);
The first instruction invokes the System Program's createAccount instruction
to:
- Allocate the number of bytes needed to store the mint data.
- Transfer lamports from the wallet to fund the new account.
- Assign ownership of the account to the Token Extensions program.
const createAccountInstruction = SystemProgram.createAccount({fromPubkey: wallet.publicKey,newAccountPubkey: mint.publicKey,space: MINT_SIZE,lamports: rentExemptionLamports,programId: TOKEN_2022_PROGRAM_ID});
The second instruction invokes the
Token Extensions Program's
createInitializeMint2Instruction instruction to initialize the mint account
with the following data:
- 2 decimals
- Wallet as both mint authority and freeze authority
const initializeMintInstruction = createInitializeMint2Instruction(mint.publicKey,2,wallet.publicKey,wallet.publicKey,TOKEN_2022_PROGRAM_ID);
Add both instructions to a single transaction. This ensures that account creation and initialization happen atomically. (Either both instructions succeed, or neither does.)
This approach is common when building complex Solana transactions, as it guarantees that all instructions execute together.
const transaction = new Transaction().add(createAccountInstruction,initializeMintInstruction);
Sign and send the transaction. Two signatures are required:
- The wallet account signs as the payer for transaction fees and account creation
- The mint account signs to authorize the use of its address for the new account
const transactionSignature = await sendAndConfirmTransaction(connection,transaction,[wallet,mint]);
The transaction signature returned can be used to inspect the transaction on Solana Explorer.
Is this page helpful?