Solana SDK migration Guide (v1 → @solana/web3.js 2.x)

Solana SDK migration Guide (v1 → @solana/web3.js 2.x)

The 2.x SDK leverages modern TypeScript features for enhanced type-safety, this means you get:

  • More compile-time errors and fewer run time errors
  • Improved IDE completions and IntelliSense
  • Harder for bugs and mistakes to make it to production

Following incidents will result in type errors:

  • Transaction missing a blockhash
  • Transaction missing a signature
  • Instruction missing an account
  • Lookup tables passed in legacy transactions

Installation

npm install --save @solana/web3.js@next
# This repository has been archived by the owner on Jan 10, 2025. Could be skipped
npm install --save @solana/spl-token@latest # seems next point to an old version

Types

Finality -> Commitment
connection: Connection ->   rpc: ReturnType<typeof createSolanaRpc>
                       ->   rpcSubscriptions: ReturnType<typeof rpcSubscriptions>

V1

connection: Connection;
 
export const connection = new Connection(process.env.RPC_URL!, {wsEndpoint: process.env.RPC_WSS_URL!, commitment: 'confirmed'});

V2

rpc: ReturnType<typeof createSolanaRpc>;
 
export const rpc = createSolanaRpc(process.env.RPC_URL!);
export const rpcSubscriptions = createSolanaRpcSubscriptions(process.env.RPC_WSS_URL!);

V1

export const owner: Keypair = Keypair.fromSecretKey(
  bs58.decode(process.env.WALLET_PRIVATE_KEY!)
);
 
owner.publicKey -> owner.address

V2

import bs58 from 'bs58';
import {createKeyPairSignerFromBytes, KeyPairSigner} from '@solana/web3.js';
 
const owner: KeyPairSigner = await createKeyPairSignerFromBytes(bs58.decode(process.env.WALLET_PRIVATE_KEY!));

V1

await connection.getAccountInfo(owner.publicKey)
 
await connection.getTokenAccountsByOwner(
    owner.address,
    { programId: TOKEN_PROGRAM_ID }
  );

V2

await rpc.getAccountInfo(owner.address).send();
 
await rpc
    .getTokenAccountsByOwner(
      owner.address,
      { programId: address(TOKEN_PROGRAM_ID.toBase58()) },
      { commitment: 'confirmed' }
    )
    .send();

Send transactions

V2

// 1 Crete function `sendAndConfirmTransaction`
// 2 Setup lifetime for a transaction (Every transaction needs to specify a valid lifetime for it to be accepted for execution on the * network.)
// 3 Crete transaction
 
// 1
const sendAndConfirmTransaction = sendAndConfirmTransactionFactory({
    /**
     * The RPC implements a `sendTransaction` method which relays transactions to the network.
     */
    rpc,
    /**
     * RPC subscriptions allow the transaction sender to subscribe to the status of our transaction.
     * The sender will resolve when the transaction is reported to have been confirmed, or will
     * reject in the event of an error, or a timeout if the transaction lifetime is thought to have
     * expired.
     */
    rpcSubscriptions,
});
 
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
 
const transactionMessage = pipe(
    createTransactionMessage({ version: 0 }),
    tx => setTransactionMessageFeePayer(FEE_PAYER_ADDRESS, tx),
    tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
    tx =>
        appendTransactionMessageInstructions(
            [
                getTransferSolInstruction({
                    amount: lamports(12345678n),
                    destination: DESTINATION_ADDRESS,
                    source: SOURCE_ACCOUNT_SIGNER,
                }),
                getAddMemoInstruction({
                    memo: 'hello from @solana/web3.js',
                }),
            ],
            tx,
        ),
);

Errors

SolanaError: JSON-RPC error: The JSON sent is not a valid Request object (Encoded binary (base 58) data should be less than 128 bytes, please use Base64 encoding.)

Fix by adding encoding:

{
    encoding: 'base64',
}
const tokenAccountsResponse = await connection
  .getTokenAccountsByOwner(ownerPublicKey, {programId: address('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA')}, {encoding: 'base64'})
  .send();
 
// or
 
const tokenAccountsResponse = await connection
  .getTokenAccountsByOwner(ownerPublicKey, {programId: address('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA')}, {encoding: 'jsonParsed'})
  .send();
Published Jan 13, 2025 | Updated Feb 24, 2025