> For the complete documentation index, see [llms.txt](/llms.txt).

# Send a versioned transaction

Solana [versioned transactions](https://solana.com/developers/guides/advanced/versions) (`v0`) support [Address Lookup Tables](https://solana.com/developers/guides/advanced/lookup-tables), which let you reference up to 256 addresses in a single transaction. This is useful for complex operations that would exceed the limits of legacy transactions.

This guide shows you how to create, sign, and send versioned transactions through MetaMask.

## Prerequisites[​](#prerequisites "Direct link to Prerequisites")

- Follow Step 1 of the [quickstart](/metamask-connect/solana/quickstart/javascript/) to install the Solana client.
- Initialize a Solana client using [createSolanaClient](/metamask-connect/solana/reference/methods/#createsolanaclient) and connect to the user's wallet using [getWallet](/metamask-connect/solana/reference/methods/#getwallet) and [standard:connect](/metamask-connect/solana/reference/methods/#supported-wallet-standard-features):  
```  
import { createSolanaClient } from '@metamask/connect-solana'  
import {  
  Connection,  
  PublicKey,  
  SystemProgram,  
  TransactionMessage,  
  VersionedTransaction,  
  AddressLookupTableProgram,  
} from '@solana/web3.js'  
const solanaClient = await createSolanaClient({  
  dapp: {  
    name: 'My Solana Dapp',  
    url: window.location.origin,  
  },  
})  
const wallet = solanaClient.getWallet()  
const { accounts } = await wallet.features['standard:connect'].connect()  
const account = accounts[0]  
const publicKey = new PublicKey(account.address)  
const connection = new Connection('https://solana-devnet.infura.io/v3/YOUR_INFURA_API_KEY')  
```

## Create a versioned transaction[​](#create-a-versioned-transaction "Direct link to Create a versioned transaction")

Solana versioned transactions are created in a similar way to [legacy transactions](https://solana.com/docs/core/transactions). The only difference is to use the `VersionedTransaction` class instead of the `Transaction` class.

The following example shows how to create a simple transfer instruction, format the instruction into a `v0`-compatible transaction message, and create a versioned transaction that parses the message:

```
const { blockhash } = await connection.getLatestBlockhash()

const instructions = [
  SystemProgram.transfer({
    fromPubkey: publicKey,
    toPubkey: publicKey,
    lamports: 10,
  }),
]

const messageV0 = new TransactionMessage({
  payerKey: publicKey,
  recentBlockhash: blockhash,
  instructions,
}).compileToV0Message()

const transactionV0 = new VersionedTransaction(messageV0)

```

## Sign and send a versioned transaction[​](#sign-and-send-a-versioned-transaction "Direct link to Sign and send a versioned transaction")

After creating an unsigned versioned transaction, use the wallet's [solana:signAndSendTransaction](/metamask-connect/solana/reference/methods/#supported-wallet-standard-features) feature to ask the user's MetaMask wallet to sign and send it.

The method returns a promise for an object containing the `signature`.

```
const [{ signature }] = await wallet.features[
  'solana:signAndSendTransaction'
].signAndSendTransaction({
  account,
  transaction: transactionV0.serialize(),
  chain: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
})

await connection.getSignatureStatus(signature)

```

## Sign a transaction without sending[​](#sign-a-transaction-without-sending "Direct link to Sign a transaction without sending")

Use the [solana:signTransaction](/metamask-connect/solana/reference/methods/#supported-wallet-standard-features) feature when you need a signed versioned transaction but want to submit it yourself. For example, for offline signing or multisig workflows.

```
const [{ signedTransaction }] = await wallet.features['solana:signTransaction'].signTransaction({
  account,
  transaction: transactionV0.serialize(),
  chain: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
})

const txSignature = await connection.sendRawTransaction(signedTransaction)

```

## Create an Address Lookup Table[​](#create-an-address-lookup-table "Direct link to Create an Address Lookup Table")

Create an [Address Lookup Table (ALT)](https://solana.com/developers/guides/advanced/lookup-tables) to efficiently load addresses into tables, significantly increasing the number of addresses that can be used in a single transaction.

Use the [createLookupTable](https://solana-foundation.github.io/solana-web3.js/classes/AddressLookupTableProgram.html#createlookuptable) method to create the instruction needed to create a new ALT and determine its address. With this instruction, create a transaction, sign it, and send it to create an ALT onchain. For example:

```
const slot = await connection.getSlot()
const { blockhash } = await connection.getLatestBlockhash()

const [lookupTableInst, lookupTableAddress] = AddressLookupTableProgram.createLookupTable({
  authority: publicKey,
  payer: publicKey,
  recentSlot: slot,
})

const lookupMessage = new TransactionMessage({
  payerKey: publicKey,
  recentBlockhash: blockhash,
  instructions: [lookupTableInst],
}).compileToV0Message()

const lookupTransaction = new VersionedTransaction(lookupMessage)

const [{ signature: lookupSignature }] = await wallet.features[
  'solana:signAndSendTransaction'
].signAndSendTransaction({
  account,
  transaction: lookupTransaction.serialize(),
  chain: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
})

```

## Extend an Address Lookup Table[​](#extend-an-address-lookup-table "Direct link to Extend an Address Lookup Table")

After creating an ALT, extend it by appending addresses to the table. Use the [extendLookupTable](https://solana-foundation.github.io/solana-web3.js/classes/AddressLookupTableProgram.html#extendlookuptable) method to create a new extend instruction, and send it in a transaction. For example:

```
const extendInstruction = AddressLookupTableProgram.extendLookupTable({
  payer: publicKey,
  authority: publicKey,
  lookupTable: lookupTableAddress,
  addresses: [publicKey, SystemProgram.programId],
})

const { blockhash: extensionBlockhash } = await connection.getLatestBlockhash()

const extensionMessageV0 = new TransactionMessage({
  payerKey: publicKey,
  recentBlockhash: extensionBlockhash,
  instructions: [extendInstruction],
}).compileToV0Message()

const extensionTransactionV0 = new VersionedTransaction(extensionMessageV0)

const [{ signature: extensionSignature }] = await wallet.features[
  'solana:signAndSendTransaction'
].signAndSendTransaction({
  account,
  transaction: extensionTransactionV0.serialize(),
  chain: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
})

```

## Create, sign, and send a versioned transaction with an ALT[​](#create-sign-and-send-a-versioned-transaction-with-an-alt "Direct link to Create, sign, and send a versioned transaction with an ALT")

After creating an ALT, create a versioned transaction with the ALT and ask the user's MetaMask wallet to sign and send it.

First, use the [getAddressLookupTable](https://solana-foundation.github.io/solana-web3.js/classes/Connection.html#getaddresslookuptable) method to fetch the account of the created ALT:

```
const lookupTableAccount = await connection
  .getAddressLookupTable(lookupTableAddress)
  .then(res => res.value)
console.log('Table address from cluster:', lookupTableAccount.key.toBase58())

```

Then, parse and read all the addresses currently stored in the fetched ALT:

```
for (let i = 0; i < lookupTableAccount.state.addresses.length; i++) {
  const address = lookupTableAccount.state.addresses[i]
  console.log(i, address.toBase58())
}

```

The following example creates a simple transfer instruction, formats the instruction into a `v0`-compatible transaction message using the ALT's account, and creates a versioned transaction that parses the message. Sign and send the transaction using the wallet's [solana:signAndSendTransaction](/metamask-connect/solana/reference/methods/#supported-wallet-standard-features) feature.

```
const { blockhash: altBlockhash } = await connection.getLatestBlockhash()

const instructions = [
  SystemProgram.transfer({
    fromPubkey: publicKey,
    toPubkey: publicKey,
    lamports: minRent,
  }),
]

const messageV0 = new TransactionMessage({
  payerKey: publicKey,
  recentBlockhash: altBlockhash,
  instructions,
}).compileToV0Message([lookupTableAccount])

const transactionV0 = new VersionedTransaction(messageV0)

const [{ signature }] = await wallet.features[
  'solana:signAndSendTransaction'
].signAndSendTransaction({
  account,
  transaction: transactionV0.serialize(),
  chain: 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1',
})

```

## Next steps[​](#next-steps "Direct link to Next steps")

- [Send a legacy transaction](/metamask-connect/solana/guides/send-transactions/legacy/) for simpler transactions that don't require Address Lookup Tables.
- [Sign messages](/metamask-connect/solana/guides/sign-data/sign-message/) to verify wallet ownership or authorize offchain actions.
- [MetaMask Connect Solana methods](/metamask-connect/solana/reference/methods/) for the full API reference.
- [Use the Multichain SDK](/metamask-connect/multichain/quickstart/javascript/) to send transactions on both EVM and Solana from a single session.
