Introduction

@solana/web3.js Differences and Adapters

Last updated September 21, 2026

Summary

The Umi Web3.js adapters convert common Solana types between Umi and @solana/web3.js.

  • Install or import helpers from @metaplex-foundation/umi-web3js-adapters.
  • Convert public keys, keypairs, instructions, transactions, and messages.
  • Use Umi 1.6.0 and @solana/web3.js 1.99.0 or later for V1 transactions.
  • Keep native Web3.js transaction creation on V0 because Web3.js 1.x cannot create V1 transactions by itself.

The @solana/web3.js library is currently widely used in the Solana ecosystem and defines its own types for Publickeys, Transactions, Instructions, etc.

When creating Umi, we wanted to move away from the class-based types defined in @solana/web3.js. This unfortunately means that, although having the same or similar import names, not all types from @solana/web3.js are compatible with the ones provided by Umi and vice versa.

To help with this issue, Umi provides a set of adapters that allows to parse types to and from their Web3.js counterparts and they can be found in the @metaplex-foundation/umi-web3js-adapters package.

Required Package and Imports

The umi-web3js-adapters package includes all the helper methods needed to convert between Umi and Web3.js types.

While it's already included when you install the @metaplex-foundation/umi package, you can also install it separately using the following command:

npm i @metaplex-foundation/umi-web3js-adapters

Here are the imports you’ll have access to:

import {
// Keypairs
fromWeb3JsKeypair, toWeb3JsKeypair,
// Publickey
fromWeb3JsPublicKey, toWeb3JsPublicKey,
// Instructions
fromWeb3JsInstruction, toWeb3JsInstruction,
// Legacy Transactions
fromWeb3JsLegacyTransaction, toWeb3JsLegacyTransaction,
// Versioned Transactions
fromWeb3JsTransaction, toWeb3JsTransaction,
// Messages
fromWeb3JsMessage, toWeb3JsMessage, toWeb3JsMessageFromInput
} from '@metaplex-foundation/umi-web3js-adapters';

Publickeys

Generating publickeys might seem similar at first sight, but there are some subtle differences between the packages. Web3Js uses a capital P and requires new, while the Umi version uses a lowercase p.

Umi

import { publicKey } from '@metaplex-foundation/umi';
// Generate a new Umi Publickey
const umiPublicKey = publicKey("11111111111111111111111111111111");

Web3Js

import { PublicKey } from '@solana/web3.js';
// Generate a new Web3Js Publickey
const web3jsPublickey = new PublicKey("1111111111111111111111111111111111111111");

Next, let's look into how to use the adapters.

From Web3Js to Umi

import { PublicKey } from '@solana/web3.js';
import { fromWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters';
// Generate a new Publickey
const web3jsPublickey = new PublicKey("1111111111111111111111111111111111111111");
// Convert it using the UmiWeb3jsAdapters Package
const umiPublicKey = fromWeb3JsPublicKey(web3jsPublickey);

From Umi to Web3Js

import { publicKey } from '@metaplex-foundation/umi';
import { toWeb3JsPublicKey } from '@metaplex-foundation/umi-web3js-adapters';
// Generate a new Publickey
const umiPublicKey = publicKey("11111111111111111111111111111111");
// Convert it using the UmiWeb3jsAdapters Package
const web3jsPublickey = toWeb3JsPublicKey(umiPublicKey);

Keypairs

Generating keypairs is where the difference from Web3Js and Umi increase. With Web3Js, you can simply use Keypair.generate(), however, in Umi, you first need to create an Umi instance, which you'll use for most Umi and Metaplex-related operations.

Umi

import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { generateSigner, createSignerFromKeypair } from '@metaplex-foundation/umi'
// Generate a new Umi instance
const umi = createUmi('https://api.devnet.solana.com')
// Generate a new Umi keypair
const umiKeypair = generateSigner(umi)
// Or use an existing one
const umiKeypair = umi.eddsa.createKeypairFromSecretKey(new Uint8Array(walletFile));

Web3Js

import { Keypair } from '@solana/web3.js';
// Generate a new Web3Js keypair
const web3jsKeypair = Keypair.generate();
// Or use an existing one
const web3jsKeypair = Keypair.fromSecretKey(new Uint8Array(walletFile));

Next, let's look into how to use the adapters.

From Umi to Web3Js

import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { generateSigner } from '@metaplex-foundation/umi'
import { toWeb3JsKeypair } from '@metaplex-foundation/umi-web3js-adapters';
// Generate a new Umi instance
const umi = createUmi('https://api.devnet.solana.com')
// Generate a new keypair
const umiKeypair = generateSigner(umi)
// Convert it using the UmiWeb3jsAdapters Package
const web3jsKeypair = toWeb3JsKeypair(umiKeypair);

From Web3Js to Umi

import { Keypair } from '@solana/web3.js';
import { fromWeb3JsKeypair } from '@metaplex-foundation/umi-web3js-adapters';
// Generate a new keypair
const web3jsKeypair = Keypair.generate();
// Convert it using the UmiWeb3jsAdapters Package
const umiKeypair = fromWeb3JsKeypair(web3jsKeypair);

Instructions

When creating instructions, the key difference with Umi is that you must first create an Umi instance (as with Keypairs). Additionally, getInstructions() returns an array of instructions instead of a single one.

For most use cases, handling individual instructions isn't necessary anyway, as this can be simplified using other helpers and transaction builders.

Umi

import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { transferSol } from '@metaplex-foundation/mpl-toolbox';
// Generate a new Umi instance
const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
// Create a new instruction (like a core nft transfer)
// get instructions will give you an Array of instructions
const umiInstructions = transferSol(umi, {...TransferParams}).getInstructions();

Web3Js

import { SystemProgram } from '@solana/web3.js';
// Create a new instruction (like a lamport transfer)
const web3jsInstruction = SystemProgram.transfer({...TransferParams})

Next, let's look into how to use the adapters.

From Umi to Web3Js

import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { transferSol } from '@metaplex-foundation/mpl-toolbox';
import { toWeb3JsInstruction } from '@metaplex-foundation/umi-web3js-adapters';
// Generate a new Umi instance
const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
// Create a new instruction (like a core nft transfer)
const umiInstruction = transferSol(umi, {...TransferParams}).getInstructions();
// Convert it using the UmiWeb3jsAdapters Package
const web3jsInstruction = umiInstruction.map(toWeb3JsInstruction);

From Web3Js to Umi

import { SystemProgram } from '@solana/web3.js';
import { fromWeb3JsInstruction } from '@metaplex-foundation/umi-web3js-adapters';
// Generate a new Umi instance
const umi = createUmi('https://api.devnet.solana.com')
// Create a new instruction (like a lamport transfer)
const web3jsInstruction = SystemProgram.transfer({...TransferParams})
// Convert it using the UmiWeb3jsAdapters Package
const umiInstruction = fromWeb3JsInstruction(web3jsInstruction);

Transactions

The Solana runtime supports three transaction formats:

  • Legacy transaction: The original transaction format
  • V0 transaction: Adds support for Address Lookup Tables
  • V1 transaction: Raises the transaction size limit to 4,096 bytes and stores compute configuration in the message

Note: If you're not familiar with versioned transactions, read Migrating from V0 to V1 Transactions.

Umi 1.6.0 and umi-web3js-adapters support legacy, V0, and V1 transactions. V1 requires @solana/web3.js 1.99.0 or later.

Umi

import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { transferSol } from '@metaplex-foundation/mpl-toolbox';
// Generate a new Umi instance
const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
// Create a new Umi Legacy Transaction
const umiTransaction = transferSol(umi, {...TransferParams}).useLegacyVersion();
// Create a new Umi V1 transaction
const umiVersionedTransaction = transferSol(umi, {...TransferParams}).useV1().build(umi)

Web3Js

import { Transaction, VersionedTransaction, TransactionMessage, Connection, clusterApiUrl, SystemProgram } from '@solana/web3.js';
// Create a new Web3Js Legacy Transaction
const web3jsTransaction = new Transaction().add(SystemProgram.transfer({...TransferParams}));
// Create a new Web3Js Versioned Transaction
const instructions = [SystemProgram.transfer({...TransferParams})];
const connection = new Connection(clusterApiUrl("devnet"));
const blockhash = await connection.getLatestBlockhash().then(res => res.blockhash);
const messageV0 = new TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: blockhash,
instructions,
}).compileToV0Message();
const web3jsVersionedTransaction = new VersionedTransaction(messageV0);

Next, let's look into how to use the adapters.

From Umi to Web3Js

import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { transferSol } from '@metaplex-foundation/mpl-toolbox';
import { toWeb3JsLegacyTransaction, toWeb3JsTransaction } from '@metaplex-foundation/umi-web3js-adapters';
// Generate a new Umi instance
const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
// Create a new Legacy Transaction
const umiTransaction = transferSol(umi, {...TransferParams}).useLegacyVersion();
// Convert it using the UmiWeb3jsAdapters Package
const web3jsTransaction = toWeb3JsTransaction(umiTransaction);
/// V1 transactions ///
// Create a new V1 transaction
const umiVersionedTransaction = transferSol(umi, {...TransferParams}).useV1().build(umi)
// Convert it using the UmiWeb3jsAdapters Package
const web3jsVersionedTransaction = toWeb3JsTransaction(umiVersionedTransaction);

From Web3Js to Umi

import { Transaction, VersionedTransaction, TransactionMessage, Connection, clusterApiUrl, SystemProgram } from '@solana/web3.js';
import { fromWeb3JsLegacyTransaction, fromWeb3JsTransaction } from '@metaplex-foundation/umi-web3js-adapters';
// Create a new Legacy Transaction
const web3jsTransaction = new Transaction().add(SystemProgram.transfer({...TransferParams}));
// Convert it using the UmiWeb3jsAdapters Package
const umiTransaction = fromWeb3JsLegacyTransaction(web3jsTransaction);
/// Versioned Transactions ///
// Create a new Versioned Transaction
const web3jsVersionedTransaction = new VersionedTransaction(...messageV0Params);
// Convert it using the UmiWeb3jsAdapters Package
const umiVersionedTransaction = fromWeb3JsTransaction(web3jsVersionedTransaction);

Messages

We've already covered creating messages during versioned transaction creation. Let's review it again.

Umi

import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { transfer, mplCore } from '@metaplex-foundation/mpl-core'
// Generate a new Umi instance
const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
// Create a new Umi Message
const blockhash = await umi.rpc.getLatestBlockhash()
const instructions = transfer(umi, {...TransferParams}).getInstructions()
const umiVersionedTransaction = umi.transactions.create({
version: 1,
payer: frontEndSigner.publicKey,
instructions,
blockhash: blockhash.blockhash,
transactionConfig: {
computeUnitLimit: 200_000,
loadedAccountsDataSizeLimit: 64 * 1024 * 1024,
},
});
const umiMessage = umiVersionedTransaction.message

Web3Js

import { TransactionMessage, Connection, clusterApiUrl, SystemProgram } from '@solana/web3.js';
// Create a new Web3Js Message
const connection = new Connection(clusterApiUrl("devnet"));
const minRent = await connection.getMinimumBalanceForRentExemption(0);
const blockhash = await connection.getLatestBlockhash().then(res => res.blockhash);
const instructions = [SystemProgram.transfer({...TransferParams})];
const Web3JsMessage = new TransactionMessage({
payerKey: payer.publicKey,
recentBlockhash: blockhash,
instructions,
}).compileToV0Message();

Next, let's look into how to use the adapters.

From Umi to Web3Js

import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { toWeb3JMessage } from '@metaplex-foundation/umi-web3js-adapters';
// Generate a new Umi instance
const umi = createUmi('https://api.devnet.solana.com').use(mplCore())
// Create a new Versioned Transaction
const umiMessage = umi.transactions.create({...createParams}).message;
// Convert it using the UmiWeb3jsAdapters Package
const web3jsMessage = toWeb3JMessage(umiMessage);

From Web3Js to Umi

import { TransactionMessage } from '@solana/web3.js';
import { fromWeb3JMessage } from '@metaplex-foundation/umi-web3js-adapters';
// Create a new Versioned Transaction
const Web3JsMessage = new TransactionMessage({...createMessageParams}).compileToV0Message();
// Convert it using the UmiWeb3jsAdapters Package
const umiMessage = fromWeb3JMessage(Web3JsMessage);

Notes

Web3.js 1.x has limited support for V1 transactions.

  • Web3.js 1.x can deserialize V1 transactions but cannot create or serialize them on its own.
  • Umi provides the V1 serializer used by the adapters.
  • The native Web3.js transaction creation examples remain on V0.