---
title: Memo Transfer
description:
  Require incoming transfers to include a memo by enabling the MemoTransfer
  account extension on a Token Extension Program token account.
url: /docs/tokens/extensions/memo-transfer
type: tutorial
prerequisites:
  - /docs/tokens/basics/create-token-account
  - /docs/tokens/basics/transfer-tokens
related:
  - /docs/tokens/extensions
---

## What Is Memo Transfer?

The Token Extension Program's _rs`MemoTransfer`_ account extension requires a
memo instruction immediately before any incoming transfer to that token account.
Outgoing transfers from that token account do not require a memo.

The extension is configured on the destination token account, not on the mint.
Once enabled, transfers without a memo fail with _rs`TokenError::NoMemo`_ until
the token account owner disables the requirement.

## How to Create a Token Account with MemoTransfer Enabled

To create a token account with _rs`MemoTransfer`_ enabled:

1. Create and initialize a mint.
2. Calculate the token account size and rent needed for a token account with
   _rs`MemoTransfer`_.
3. Create the token account and enable _rs`MemoTransfer`_ on that account.
4. _rs`Transfer`_ and _rs`TransferChecked`_ instructions to that token account
   must include a memo instruction immediately before the transfer instruction.

<ScrollyCoding>

## !!steps Create and initialize the mint

Create and initialize the mint that the token account will use.

<CodePlaceholder title="Example" />

```ts !! title="Example"
const client = await createClient()
  .use(generatedPayer())
  .use(
    solanaRpc({
      rpcUrl: "http://localhost:8899",
      rpcSubscriptionsUrl: "ws://localhost:8900"
    })
  )
  .use(rpcAirdrop())
  .use(airdropPayer(lamports(1_000_000_000n)));

const mint = await generateKeyPairSigner();
const tokenOwner = await generateKeyPairSigner();
const tokenAccount = await generateKeyPairSigner();

const mintSpace = BigInt(getMintSize());
const mintRent = await client.rpc
  .getMinimumBalanceForRentExemption(mintSpace)
  .send();

// !focus(1:15)
await client.sendTransaction([
  getCreateAccountInstruction({
    payer: client.payer,
    newAccount: mint,
    lamports: mintRent,
    space: mintSpace,
    programAddress: TOKEN_2022_PROGRAM_ADDRESS
  }),
  getInitializeMintInstruction({
    mint: mint.address,
    decimals: 0,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
]);
```

## !!steps Calculate token account size

Calculate the token account size for the base token account plus the
_rs`MemoTransfer`_ extension. This is the size used in _rs`CreateAccount`_.

<CodePlaceholder title="Example" />

```ts !! title="Example"
const client = await createClient()
  .use(generatedPayer())
  .use(
    solanaRpc({
      rpcUrl: "http://localhost:8899",
      rpcSubscriptionsUrl: "ws://localhost:8900"
    })
  )
  .use(rpcAirdrop())
  .use(airdropPayer(lamports(1_000_000_000n)));

const mint = await generateKeyPairSigner();
const tokenOwner = await generateKeyPairSigner();
const tokenAccount = await generateKeyPairSigner();

const mintSpace = BigInt(getMintSize());
const mintRent = await client.rpc
  .getMinimumBalanceForRentExemption(mintSpace)
  .send();

await client.sendTransaction([
  getCreateAccountInstruction({
    payer: client.payer,
    newAccount: mint,
    lamports: mintRent,
    space: mintSpace,
    programAddress: TOKEN_2022_PROGRAM_ADDRESS
  }),
  getInitializeMintInstruction({
    mint: mint.address,
    decimals: 0,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
]);

// !focus(1:4)
const memoTransferAccountExtension = extension("MemoTransfer", {
  requireIncomingTransferMemos: false
});
const tokenSpace = BigInt(getTokenSize([memoTransferAccountExtension]));
```

## !!steps Calculate rent

Calculate rent using the token account size needed for the _rs`MemoTransfer`_
extension.

<CodePlaceholder title="Example" />

```ts !! title="Example"
const client = await createClient()
  .use(generatedPayer())
  .use(
    solanaRpc({
      rpcUrl: "http://localhost:8899",
      rpcSubscriptionsUrl: "ws://localhost:8900"
    })
  )
  .use(rpcAirdrop())
  .use(airdropPayer(lamports(1_000_000_000n)));

const mint = await generateKeyPairSigner();
const tokenOwner = await generateKeyPairSigner();
const tokenAccount = await generateKeyPairSigner();

const mintSpace = BigInt(getMintSize());
const mintRent = await client.rpc
  .getMinimumBalanceForRentExemption(mintSpace)
  .send();

await client.sendTransaction([
  getCreateAccountInstruction({
    payer: client.payer,
    newAccount: mint,
    lamports: mintRent,
    space: mintSpace,
    programAddress: TOKEN_2022_PROGRAM_ADDRESS
  }),
  getInitializeMintInstruction({
    mint: mint.address,
    decimals: 0,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
]);

const memoTransferAccountExtension = extension("MemoTransfer", {
  requireIncomingTransferMemos: false
});
const tokenSpace = BigInt(getTokenSize([memoTransferAccountExtension]));

// !focus(1:3)
const tokenRent = await client.rpc
  .getMinimumBalanceForRentExemption(tokenSpace)
  .send();
```

## !!steps Create and initialize the token account

Create the token account with the calculated space and lamports, then initialize
it for the mint.

<CodePlaceholder title="Example" />

```ts !! title="Example"
const client = await createClient()
  .use(generatedPayer())
  .use(
    solanaRpc({
      rpcUrl: "http://localhost:8899",
      rpcSubscriptionsUrl: "ws://localhost:8900"
    })
  )
  .use(rpcAirdrop())
  .use(airdropPayer(lamports(1_000_000_000n)));

const mint = await generateKeyPairSigner();
const tokenOwner = await generateKeyPairSigner();
const tokenAccount = await generateKeyPairSigner();

const mintSpace = BigInt(getMintSize());
const mintRent = await client.rpc
  .getMinimumBalanceForRentExemption(mintSpace)
  .send();

await client.sendTransaction([
  getCreateAccountInstruction({
    payer: client.payer,
    newAccount: mint,
    lamports: mintRent,
    space: mintSpace,
    programAddress: TOKEN_2022_PROGRAM_ADDRESS
  }),
  getInitializeMintInstruction({
    mint: mint.address,
    decimals: 0,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
]);

const memoTransferExtension = extension("MemoTransfer", {
  requireIncomingTransferMemos: false
});
const tokenSpace = BigInt(getTokenSize([memoTransferExtension]));

const tokenRent = await client.rpc
  .getMinimumBalanceForRentExemption(tokenSpace)
  .send();

// !focus(1:14)
await client.sendTransaction([
  getCreateAccountInstruction({
    payer: client.payer,
    newAccount: tokenAccount,
    lamports: tokenRent,
    space: tokenSpace,
    programAddress: TOKEN_2022_PROGRAM_ADDRESS
  }),
  getInitializeAccountInstruction({
    account: tokenAccount.address,
    mint: mint.address,
    owner: tokenOwner.address
  })
]);
```

## !!steps Enable MemoTransfer

Enable _rs`MemoTransfer`_ on the token account.

<CodePlaceholder title="Example" />

```ts !! title="Example"
const client = await createClient()
  .use(generatedPayer())
  .use(
    solanaRpc({
      rpcUrl: "http://localhost:8899",
      rpcSubscriptionsUrl: "ws://localhost:8900"
    })
  )
  .use(rpcAirdrop())
  .use(airdropPayer(lamports(1_000_000_000n)));

const mint = await generateKeyPairSigner();
const tokenOwner = await generateKeyPairSigner();
const tokenAccount = await generateKeyPairSigner();

const mintSpace = BigInt(getMintSize());
const mintRent = await client.rpc
  .getMinimumBalanceForRentExemption(mintSpace)
  .send();

await client.sendTransaction([
  getCreateAccountInstruction({
    payer: client.payer,
    newAccount: mint,
    lamports: mintRent,
    space: mintSpace,
    programAddress: TOKEN_2022_PROGRAM_ADDRESS
  }),
  getInitializeMintInstruction({
    mint: mint.address,
    decimals: 0,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
]);

const memoTransferExtension = extension("MemoTransfer", {
  requireIncomingTransferMemos: false
});
const tokenSpace = BigInt(getTokenSize([memoTransferExtension]));

const tokenRent = await client.rpc
  .getMinimumBalanceForRentExemption(tokenSpace)
  .send();

await client.sendTransaction([
  getCreateAccountInstruction({
    payer: client.payer,
    newAccount: tokenAccount,
    lamports: tokenRent,
    space: tokenSpace,
    programAddress: TOKEN_2022_PROGRAM_ADDRESS
  }),
  getInitializeAccountInstruction({
    account: tokenAccount.address,
    mint: mint.address,
    owner: tokenOwner.address
  })
]);

// !focus(1:6)
await client.sendTransaction([
  getEnableMemoTransfersInstruction({
    token: tokenAccount.address,
    owner: tokenOwner
  })
]);
```

</ScrollyCoding>

### Source Reference

| Item                                            | Description                                                                                              | Source                                                                                                                                     |
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| _rs`MemoTransfer`_                              | Account extension that stores whether incoming transfers require a memo.                                 | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/extension/memo_transfer/mod.rs#L17-L22)         |
| _rs`RequiredMemoTransfersInstruction::Enable`_  | Instruction that enables memo-required transfers on a token account.                                     | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/extension/memo_transfer/instruction.rs#L50-L71) |
| _rs`RequiredMemoTransfersInstruction::Disable`_ | Instruction that disables memo-required transfers on a token account.                                    | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/extension/memo_transfer/instruction.rs#L74-L95) |
| _rs`process_toggle_required_memo_transfers`_    | Processor logic that initializes or rewrites the _rs`MemoTransfer`_ extension after verifying ownership. | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/program/src/extension/memo_transfer/processor.rs#L20-L48)     |

### Typescript

The `Kit` example below uses the generated instructions directly. Legacy
examples using `@solana/web3.js`, `@solana/spl-token`, and `@solana/spl-memo`
are included for reference.

#### Kit

<CodeTabs storage="token-ts-kit" flags="r">

```ts !! title="Instructions"
import {
  lamports,
  createClient,
  generateKeyPairSigner,
  unwrapOption
} from "@solana/kit";
import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";
import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";
import { getAddMemoInstruction } from "@solana-program/memo";
import { getCreateAccountInstruction } from "@solana-program/system";
import {
  extension,
  fetchToken,
  findAssociatedTokenPda,
  getCreateAssociatedTokenInstructionAsync,
  getDisableMemoTransfersInstruction,
  getEnableMemoTransfersInstruction,
  getInitializeAccountInstruction,
  getInitializeMintInstruction,
  getMintSize,
  getMintToCheckedInstruction,
  getTokenSize,
  getTransferCheckedInstruction,
  isExtension,
  TOKEN_2022_PROGRAM_ADDRESS
} from "@solana-program/token-2022";

const client = await createClient()
  .use(generatedPayer())
  .use(
    solanaRpc({
      rpcUrl: "http://localhost:8899",
      rpcSubscriptionsUrl: "ws://localhost:8900"
    })
  )
  .use(rpcAirdrop())
  .use(airdropPayer(lamports(1_000_000_000n)));

const mint = await generateKeyPairSigner();
const tokenOwner = await generateKeyPairSigner();
const tokenAccount = await generateKeyPairSigner();
const tokenAmount = 1n;

const mintSpace = BigInt(getMintSize());
const mintRent = await client.rpc
  .getMinimumBalanceForRentExemption(mintSpace)
  .send();

await client.sendTransaction([
  getCreateAccountInstruction({
    payer: client.payer, // Account funding the new mint account.
    newAccount: mint, // New mint account to create.
    lamports: mintRent, // Lamports funding the mint account rent.
    space: mintSpace, // Account size in bytes for the mint.
    programAddress: TOKEN_2022_PROGRAM_ADDRESS // Program that owns the mint account.
  }),
  getInitializeMintInstruction({
    mint: mint.address, // Mint account to initialize.
    decimals: 0, // Number of decimals for the token.
    mintAuthority: client.payer.address, // Authority allowed to mint new tokens.
    freezeAuthority: client.payer.address // Authority allowed to freeze token accounts.
  })
]);

const [sourceToken] = await findAssociatedTokenPda({
  mint: mint.address, // Mint for the source token account.
  owner: client.payer.address, // Owner of the source token account.
  tokenProgram: TOKEN_2022_PROGRAM_ADDRESS // Token program that owns the token account.
});

const memoTransferAccountExtension = extension("MemoTransfer", {
  requireIncomingTransferMemos: false
});
const tokenSpace = BigInt(getTokenSize([memoTransferAccountExtension]));
const tokenRent = await client.rpc
  .getMinimumBalanceForRentExemption(tokenSpace)
  .send();

await client.sendTransaction([
  await getCreateAssociatedTokenInstructionAsync({
    payer: client.payer, // Account funding the associated token account creation.
    mint: mint.address, // Mint for the associated token account.
    owner: client.payer.address // Owner of the associated token account.
  }),
  getMintToCheckedInstruction({
    mint: mint.address, // Mint account that issues the tokens.
    token: sourceToken, // Token account receiving the newly minted tokens.
    mintAuthority: client.payer, // Signer authorized to mint new tokens.
    amount: tokenAmount, // Token amount in base units.
    decimals: 0 // Decimals defined on the mint.
  }),
  getCreateAccountInstruction({
    payer: client.payer, // Account funding the new token account.
    newAccount: tokenAccount, // New token account to create.
    lamports: tokenRent, // Lamports funding the token account rent.
    space: tokenSpace, // Account size in bytes for the token account plus MemoTransfer.
    programAddress: TOKEN_2022_PROGRAM_ADDRESS // Program that owns the token account.
  }),
  getInitializeAccountInstruction({
    account: tokenAccount.address, // Token account to initialize.
    mint: mint.address, // Mint for the token account.
    owner: tokenOwner.address // Owner of the token account.
  })
]);

await client.sendTransaction([
  // !mark(1:4)
  getEnableMemoTransfersInstruction({
    token: tokenAccount.address, // Token account that stores the MemoTransfer extension.
    owner: tokenOwner // Token account owner authorized to toggle memo requirements.
  })
]);

await client.sendTransaction([
  getAddMemoInstruction({
    memo: "memo required" // Memo string required by the destination token account.
  }),
  getTransferCheckedInstruction({
    source: sourceToken, // Token account sending the transfer.
    mint: mint.address, // Mint for the transfer.
    destination: tokenAccount.address, // Token account receiving the transfer.
    authority: client.payer, // Owner of the source token account.
    amount: tokenAmount, // Token amount in base units.
    decimals: 0 // Decimals defined on the mint.
  })
]);

await client.sendTransaction([
  // !mark(1:4)
  getDisableMemoTransfersInstruction({
    token: tokenAccount.address, // Token account that stores the MemoTransfer extension.
    owner: tokenOwner // Token account owner authorized to toggle memo requirements.
  })
]);

const tokenAccountData = await fetchToken(client.rpc, tokenAccount.address);
const memoTransferExtension = (
  unwrapOption(tokenAccountData.data.extensions) ?? []
).find((item) => isExtension("MemoTransfer", item));

console.log("Mint Address:", mint.address);
console.log("Token Account:", tokenAccount.address);
console.log("Destination Amount:", tokenAccountData.data.amount);
console.log("MemoTransfer Extension:", memoTransferExtension);
```

</CodeTabs>

#### Web3.js

<CodeTabs storage="token-ts-legacy" flags="r">

```ts !! title="Instructions"
import {
  Connection,
  Keypair,
  sendAndConfirmTransaction,
  SystemProgram,
  Transaction,
  LAMPORTS_PER_SOL
} from "@solana/web3.js";
import {
  ASSOCIATED_TOKEN_PROGRAM_ID,
  getAssociatedTokenAddressSync,
  createAssociatedTokenAccountInstruction,
  createDisableRequiredMemoTransfersInstruction,
  createEnableRequiredMemoTransfersInstruction,
  createInitializeAccountInstruction,
  createInitializeMintInstruction,
  getAccount,
  getAccountLen,
  getMemoTransfer,
  createMintToCheckedInstruction,
  createTransferCheckedInstruction,
  ExtensionType,
  getMintLen,
  TOKEN_2022_PROGRAM_ID
} from "@solana/spl-token";
import { createMemoInstruction } from "@solana/spl-memo";

const connection = new Connection("http://localhost:8899", "confirmed");

const feePayer = Keypair.generate();
const tokenOwner = Keypair.generate();
const tokenAmount = 1;

const airdropSignature = await connection.requestAirdrop(
  feePayer.publicKey,
  5 * LAMPORTS_PER_SOL
);
await connection.confirmTransaction(airdropSignature, "confirmed");

const mint = Keypair.generate();

const mintLength = getMintLen([]);

const mintRent = await connection.getMinimumBalanceForRentExemption(mintLength);
const extensions = [ExtensionType.MemoTransfer];
const tokenAccount = Keypair.generate();
const tokenAccountLen = getAccountLen(extensions);
const tokenAccountRent =
  await connection.getMinimumBalanceForRentExemption(tokenAccountLen);

const createMintAccountInstruction = SystemProgram.createAccount({
  fromPubkey: feePayer.publicKey, // Account funding the new mint account.
  newAccountPubkey: mint.publicKey, // New mint account to create.
  space: mintLength, // Account size in bytes for the mint.
  lamports: mintRent, // Lamports funding the mint account rent.
  programId: TOKEN_2022_PROGRAM_ID // Program that owns the mint account.
});

const initializeMintInstruction = createInitializeMintInstruction(
  mint.publicKey, // Mint account to initialize.
  0, // Number of decimals for the token.
  feePayer.publicKey, // Authority allowed to mint new tokens.
  feePayer.publicKey, // Authority allowed to freeze token accounts.
  TOKEN_2022_PROGRAM_ID // Token program that owns the mint account.
);

const sourceToken = getAssociatedTokenAddressSync(
  mint.publicKey, // Mint for the source token account.
  feePayer.publicKey, // Owner of the source token account.
  false, // Whether the owner is a PDA.
  TOKEN_2022_PROGRAM_ID, // Token program that owns the token account.
  ASSOCIATED_TOKEN_PROGRAM_ID // Associated Token Program that derives the ATA.
);

const createSourceTokenInstruction = createAssociatedTokenAccountInstruction(
  feePayer.publicKey, // Account funding the associated token account creation.
  sourceToken, // Associated token account address to create.
  feePayer.publicKey, // Owner of the associated token account.
  mint.publicKey, // Mint for the associated token account.
  TOKEN_2022_PROGRAM_ID, // Token program that owns the token account.
  ASSOCIATED_TOKEN_PROGRAM_ID // Associated Token Program that creates the account.
);

const mintToInstruction = createMintToCheckedInstruction(
  mint.publicKey, // Mint account that issues the tokens.
  sourceToken, // Token account receiving the newly minted tokens.
  feePayer.publicKey, // Signer authorized to mint new tokens.
  tokenAmount, // Token amount in base units.
  0, // Decimals defined on the mint.
  [], // Additional multisig signers.
  TOKEN_2022_PROGRAM_ID // Token program that owns the mint and token account.
);

const createTokenAccountInstruction = SystemProgram.createAccount({
  fromPubkey: feePayer.publicKey, // Account funding the new token account.
  newAccountPubkey: tokenAccount.publicKey, // New token account to create.
  space: tokenAccountLen, // Account size in bytes for the token account plus MemoTransfer.
  lamports: tokenAccountRent, // Lamports funding the token account rent.
  programId: TOKEN_2022_PROGRAM_ID // Program that owns the token account.
});

const initializeTokenAccountInstruction = createInitializeAccountInstruction(
  tokenAccount.publicKey, // Token account to initialize.
  mint.publicKey, // Mint for the token account.
  tokenOwner.publicKey, // Owner of the token account.
  TOKEN_2022_PROGRAM_ID // Token program that owns the token account.
);

await sendAndConfirmTransaction(
  connection,
  new Transaction().add(
    createMintAccountInstruction,
    initializeMintInstruction
  ),
  [feePayer, mint]
);

await sendAndConfirmTransaction(
  connection,
  new Transaction().add(
    createSourceTokenInstruction,
    mintToInstruction,
    createTokenAccountInstruction,
    initializeTokenAccountInstruction
  ),
  [feePayer, tokenAccount]
);

// !mark(1:7)
const enableMemoTransferExtensionInstruction =
  createEnableRequiredMemoTransfersInstruction(
    tokenAccount.publicKey, // Token account that stores the MemoTransfer extension.
    tokenOwner.publicKey, // Token account owner authorized to toggle memo requirements.
    [], // Additional multisig signers.
    TOKEN_2022_PROGRAM_ID // Token program that owns the token account.
  );

await sendAndConfirmTransaction(
  connection,
  new Transaction().add(enableMemoTransferExtensionInstruction),
  [feePayer, tokenOwner]
);

const memoIx = createMemoInstruction(
  "memo required", // Memo string required by the destination token account.
  [feePayer.publicKey] // Accounts to include in the memo instruction.
);

const transferInstruction = createTransferCheckedInstruction(
  sourceToken, // Token account sending the transfer.
  mint.publicKey, // Mint for the transfer.
  tokenAccount.publicKey, // Token account receiving the transfer.
  feePayer.publicKey, // Owner of the source token account.
  tokenAmount, // Token amount in base units.
  0, // Decimals defined on the mint.
  [], // Additional multisig signers.
  TOKEN_2022_PROGRAM_ID // Token program that processes the transfer.
);

await sendAndConfirmTransaction(
  connection,
  new Transaction().add(memoIx, transferInstruction),
  [feePayer]
);

// !mark(1:7)
const disableMemoTransferExtensionInstruction =
  createDisableRequiredMemoTransfersInstruction(
    tokenAccount.publicKey, // Token account that stores the MemoTransfer extension.
    tokenOwner.publicKey, // Token account owner authorized to toggle memo requirements.
    [], // Additional multisig signers.
    TOKEN_2022_PROGRAM_ID // Token program that owns the token account.
  );

await sendAndConfirmTransaction(
  connection,
  new Transaction().add(disableMemoTransferExtensionInstruction),
  [feePayer, tokenOwner]
);

const tokenAccountData = await getAccount(
  connection,
  tokenAccount.publicKey,
  "confirmed",
  TOKEN_2022_PROGRAM_ID
);
const memoTransferExtension = getMemoTransfer(tokenAccountData);

console.log("Mint Address:", mint.publicKey.toBase58());
console.log("Token Account:", tokenAccount.publicKey.toBase58());
console.log("Destination Amount:", tokenAccountData.amount.toString());
console.log("MemoTransfer Extension:", memoTransferExtension);
```

</CodeTabs>

### Rust

<CodeTabs storage="token-rs" flags="r">

```rust !! title="Rust"
use anyhow::Result;
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_commitment_config::CommitmentConfig;
use solana_sdk::{
    program_pack::Pack,
    signature::{Keypair, Signer},
    transaction::Transaction,
};
use solana_system_interface::instruction::create_account;
use spl_associated_token_account_interface::{
    address::get_associated_token_address_with_program_id,
    instruction::create_associated_token_account,
};
use spl_memo_interface::{instruction::build_memo, v3::ID as MEMO_PROGRAM_ID};
use spl_token_2022_interface::{
    extension::{
        memo_transfer::{
            instruction::{disable_required_transfer_memos, enable_required_transfer_memos},
            MemoTransfer,
        },
        BaseStateWithExtensions, ExtensionType, StateWithExtensions,
    },
    instruction::{initialize_account, initialize_mint, mint_to_checked, transfer_checked},
    state::{Account, Mint},
    ID as TOKEN_2022_PROGRAM_ID,
};

#[tokio::main]
async fn main() -> Result<()> {
    let client = RpcClient::new_with_commitment(
        String::from("http://localhost:8899"),
        CommitmentConfig::confirmed(),
    );
    let fee_payer = Keypair::new();
    let token_owner = Keypair::new();
    let token_amount = 1u64;

    let airdrop_signature = client
        .request_airdrop(&fee_payer.pubkey(), 5_000_000_000)
        .await?;

    loop {
        let confirmed = client.confirm_transaction(&airdrop_signature).await?;
        if confirmed {
            break;
        }
    }

    let mint = Keypair::new();

    let mint_space = Mint::LEN;
    let mint_rent = client
        .get_minimum_balance_for_rent_exemption(mint_space)
        .await?;

    let create_mint_account_instruction = create_account(
        &fee_payer.pubkey(),    // Account funding the new mint account.
        &mint.pubkey(),         // New mint account to create.
        mint_rent,              // Lamports funding the mint account rent.
        mint_space as u64,      // Account size in bytes for the mint.
        &TOKEN_2022_PROGRAM_ID, // Program that owns the mint account.
    );

    let initialize_mint_instruction = initialize_mint(
        &TOKEN_2022_PROGRAM_ID,    // Program that owns the mint account.
        &mint.pubkey(),            // Mint account to initialize.
        &fee_payer.pubkey(),       // Authority allowed to mint new tokens.
        Some(&fee_payer.pubkey()), // Authority allowed to freeze token accounts.
        0,                         // Number of decimals for the token.
    )?;

    let create_mint_transaction = Transaction::new_signed_with_payer(
        &[create_mint_account_instruction, initialize_mint_instruction],
        Some(&fee_payer.pubkey()),
        &[&fee_payer, &mint],
        client.get_latest_blockhash().await?,
    );

    client
        .send_and_confirm_transaction(&create_mint_transaction)
        .await?;

    let source_token = get_associated_token_address_with_program_id(
        &fee_payer.pubkey(),    // Owner of the associated token account.
        &mint.pubkey(),         // Mint for the associated token account.
        &TOKEN_2022_PROGRAM_ID, // Token program that owns the token account.
    );

    let create_source_token_instruction = create_associated_token_account(
        &fee_payer.pubkey(),    // Account funding the associated token account creation.
        &fee_payer.pubkey(),    // Owner of the associated token account.
        &mint.pubkey(),         // Mint for the associated token account.
        &TOKEN_2022_PROGRAM_ID, // Token program that owns the token account.
    );

    let mint_to_instruction = mint_to_checked(
        &TOKEN_2022_PROGRAM_ID, // Token program that owns the mint and token account.
        &mint.pubkey(),         // Mint account that issues the tokens.
        &source_token,          // Token account receiving the newly minted tokens.
        &fee_payer.pubkey(),    // Signer authorized to mint new tokens.
        &[],                    // Additional multisig signers.
        token_amount,           // Token amount in base units.
        0,                      // Decimals defined on the mint.
    )?;

    let token_account = Keypair::new();

    let token_account_space =
        ExtensionType::try_calculate_account_len::<Account>(&[ExtensionType::MemoTransfer])?;

    let token_account_rent = client
        .get_minimum_balance_for_rent_exemption(token_account_space)
        .await?;

    let create_token_account_instruction = create_account(
        &fee_payer.pubkey(),        // Account funding the new token account.
        &token_account.pubkey(),    // New token account to create.
        token_account_rent,         // Lamports funding the token account rent.
        token_account_space as u64, // Account size in bytes for the token account plus MemoTransfer.
        &TOKEN_2022_PROGRAM_ID,     // Program that owns the token account.
    );

    let initialize_token_account = initialize_account(
        &TOKEN_2022_PROGRAM_ID,  // Token program that owns the token account.
        &token_account.pubkey(), // Token account to initialize.
        &mint.pubkey(),          // Mint for the token account.
        &token_owner.pubkey(),   // Owner of the token account.
    )?;

    let setup_transaction = Transaction::new_signed_with_payer(
        &[
            create_source_token_instruction,
            mint_to_instruction,
            create_token_account_instruction,
            initialize_token_account,
        ],
        Some(&fee_payer.pubkey()),
        &[&fee_payer, &token_account],
        client.get_latest_blockhash().await?,
    );

    client.send_and_confirm_transaction(&setup_transaction).await?;

    // !mark(1:6)
    let enable_memo_transfer_instruction = enable_required_transfer_memos(
        &TOKEN_2022_PROGRAM_ID,  // Token program that owns the token account.
        &token_account.pubkey(), // Token account that stores the MemoTransfer extension.
        &token_owner.pubkey(),   // Token account owner authorized to toggle memo requirements.
        &[],                     // Additional multisig signers.
    )?;

    let enable_blockhash = client.get_latest_blockhash().await?;
    let enable_transaction = Transaction::new_signed_with_payer(
        &[enable_memo_transfer_instruction],
        Some(&fee_payer.pubkey()),
        &[&fee_payer, &token_owner],
        enable_blockhash,
    );

    client
        .send_and_confirm_transaction(&enable_transaction)
        .await?;

    let memo_instruction = build_memo(
        &MEMO_PROGRAM_ID,       // Memo program that records the memo string.
        b"memo required",       // Memo string required by the destination token account.
        &[&fee_payer.pubkey()], // Accounts to include in the memo instruction.
    );

    let transfer_instruction = transfer_checked(
        &TOKEN_2022_PROGRAM_ID,  // Token program that processes the transfer.
        &source_token,           // Token account sending the transfer.
        &mint.pubkey(),          // Mint for the transfer.
        &token_account.pubkey(), // Token account receiving the transfer.
        &fee_payer.pubkey(),     // Owner of the source token account.
        &[],                     // Additional multisig signers.
        token_amount,            // Token amount in base units.
        0,                       // Decimals defined on the mint.
    )?;

    let transfer_blockhash = client.get_latest_blockhash().await?;
    let transfer_transaction = Transaction::new_signed_with_payer(
        &[memo_instruction, transfer_instruction],
        Some(&fee_payer.pubkey()),
        &[&fee_payer],
        transfer_blockhash,
    );

    client
        .send_and_confirm_transaction(&transfer_transaction)
        .await?;

    // !mark(1:6)
    let disable_memo_transfer_instruction = disable_required_transfer_memos(
        &TOKEN_2022_PROGRAM_ID,  // Token program that owns the token account.
        &token_account.pubkey(), // Token account that stores the MemoTransfer extension.
        &token_owner.pubkey(),   // Token account owner authorized to toggle memo requirements.
        &[],                     // Additional multisig signers.
    )?;

    let disable_blockhash = client.get_latest_blockhash().await?;
    let disable_transaction = Transaction::new_signed_with_payer(
        &[disable_memo_transfer_instruction],
        Some(&fee_payer.pubkey()),
        &[&fee_payer, &token_owner],
        disable_blockhash,
    );

    client
        .send_and_confirm_transaction(&disable_transaction)
        .await?;

    let token_account_data = client.get_account(&token_account.pubkey()).await?;
    let token_account_state = StateWithExtensions::<Account>::unpack(&token_account_data.data)?;
    let memo_transfer_extension = token_account_state.get_extension::<MemoTransfer>()?;

    println!("Mint Address: {}", mint.pubkey());
    println!("Token Account: {}", token_account.pubkey());
    println!("Destination Amount: {}", token_account_state.base.amount);
    println!("MemoTransfer Extension: {:#?}", memo_transfer_extension);

    Ok(())
}
```

</CodeTabs>
