How to transfer token to multiple addresses at a single Solana transaction

Generate three key pairs with solana cli solana-keygen

solana-keygen new --outfile wallet1.json
solana-keygen new --outfile wallet2.json
solana-keygen new --outfile wallet3.json

Create a config.json with the above key pairs for the application

  "RPC": "",
  "WALLET_1": [1,2,3,...,123],
  "WALLET_2": [4,5,6,...,456],
  "WALLET_3": [7,8,9,...,789]

Install @solana/web3.js

npm install -s @solana/web3.js

Create a typescript file sol-transfer.ts

import * as fs from 'fs';
import * as W3 from '@solana/web3.js';
let CONF_FILE = process.argv[2] || "./config.json";

let CONF = JSON.parse(fs.readFileSync(CONF_FILE, {encoding:"utf8"}));

async function main(){
  let conn = new W3.Connection(CONF['RPC']);
  let wallet1 = W3.Keypair.fromSecretKey(Buffer.from(CONF['WALLET_1']));
  let wallet2 = W3.Keypair.fromSecretKey(Buffer.from(CONF['WALLET_2']));
  let wallet3 = W3.Keypair.fromSecretKey(Buffer.from(CONF['WALLET_3']));
  console.log('RPC:', conn.rpcEndpoint);
  console.log('Wallet 1:', wallet1.publicKey.toBase58(), await conn.getBalance(wallet1.publicKey)/W3.LAMPORTS_PER_SOL);
  console.log('Wallet 2:', wallet2.publicKey.toBase58(), await conn.getBalance(wallet2.publicKey)/W3.LAMPORTS_PER_SOL);
  console.log('Wallet 3:', wallet3.publicKey.toBase58(), await conn.getBalance(wallet3.publicKey)/W3.LAMPORTS_PER_SOL);

  await sendSol(conn, wallet1, wallet2, wallet3);


async function sendSol(
  conn: W3.Connection, 
  fromWallet: W3.Keypair, 
  toWallet1: W3.Keypair, 
  toWallet2: W3.Keypair

  // instruction for sending SOL to wallet1
  let instruction1 = W3.SystemProgram.transfer({
    fromPubkey: fromWallet.publicKey,
    toPubkey: toWallet1.publicKey,
    lamports: 0.002 * W3.LAMPORTS_PER_SOL,

  // instruction for sending SOL to wallet2
  let instruction2 = W3.SystemProgram.transfer({
    fromPubkey: fromWallet.publicKey,
    toPubkey: toWallet2.publicKey,
    lamports: 0.003 * W3.LAMPORTS_PER_SOL,

  // create a transaction and add the instructions into it 
  let txn = new W3.Transaction();

  txn.feePayer = fromWallet.publicKey;

  // the txn needs the recent blockhash
  let { blockhash } = await conn.getLatestBlockhash();
  txn.recentBlockhash = blockhash ;

  // sign the txn with sender's private key

  // run!
  let signature = await conn.sendTransaction(txn, [fromWallet], {preflightCommitment:'finalized'});
  console.log('Txn instructions:', JSON.stringify(txn.instructions,null,2));
  console.log('Txn signatures:', JSON.stringify(txn.signatures,null,2) );
  console.log('Txn hash:', signature );