---
title: Permanent Delegate
description:
  Create a Token Extension Program mint with a permanent delegate that can
  transfer or burn tokens from any account for that mint.
url: /docs/tokens/extensions/permanent-delegate
type: tutorial
prerequisites:
  - /docs/tokens/basics/create-mint
  - /docs/tokens/basics/transfer-tokens
  - /docs/tokens/basics/burn-tokens
related:
  - /docs/tokens/basics/approve-delegate
  - /docs/tokens/extensions
---

## What Is a Permanent Delegate?

The Token Extension Program's _rs`PermanentDelegate`_ mint extension assigns a
delegate authority to the mint itself.

A permanent delegate is a mint level authority that can authorize transfers and
burns for any token account for that mint. It acts as a global delegate for all
token accounts for the mint, and token account owners cannot revoke the
permanent delegate from their token accounts.

The mint authority can also rotate the permanent delegate later with
_rs`SetAuthority`_ using _rs`AuthorityType::PermanentDelegate`_.

## How to Create and Use a Permanent Delegate

To create and use a permanent delegate:

1. Calculate the mint account size and rent needed for the mint and the
   _rs`PermanentDelegate`_ extension.
2. Create the mint account with _rs`CreateAccount`_, initialize
   _rs`PermanentDelegate`_, and initialize the mint with _rs`InitializeMint`_.
3. Submit _rs`TransferChecked`_ or _rs`BurnChecked`_ signed by the permanent
   delegate. The token program processes those instructions the same way as if
   the token account owner signed them.

<ScrollyCoding>

## !!steps Calculate account size

Calculate the mint account size for the base mint plus the
_rs`PermanentDelegate`_ 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 owner = await generateKeyPairSigner();
const delegate = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();

// !focus(1:3)
const permanentDelegateExtension = extension("PermanentDelegate", {
  delegate: delegate.address
});

// !focus(1:1)
const mintSpace = BigInt(getMintSize([permanentDelegateExtension]));
```

## !!steps Calculate rent

Calculate rent using the size needed for the mint plus the
_rs`PermanentDelegate`_ 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 owner = await generateKeyPairSigner();
const delegate = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();

const permanentDelegateExtension = extension("PermanentDelegate", {
  delegate: delegate.address
});

const mintSpace = BigInt(getMintSize([permanentDelegateExtension]));

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

## !!steps Create the mint account

Create the mint account with the calculated space and lamports.

<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 owner = await generateKeyPairSigner();
const delegate = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();

const permanentDelegateExtension = extension("PermanentDelegate", {
  delegate: delegate.address
});

const mintSpace = BigInt(getMintSize([permanentDelegateExtension]));

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

// !focus(1:9)
await client.sendTransaction([
  getCreateAccountInstruction({
    payer: client.payer,
    newAccount: mint,
    lamports: mintRent,
    space: mintSpace,
    programAddress: TOKEN_2022_PROGRAM_ADDRESS
  })
]);
```

## !!steps Initialize PermanentDelegate

Initialize the _rs`PermanentDelegate`_ extension on 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 owner = await generateKeyPairSigner();
const delegate = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();

const permanentDelegateExtension = extension("PermanentDelegate", {
  delegate: delegate.address
});

const mintSpace = BigInt(getMintSize([permanentDelegateExtension]));

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
  }),
  // !focus(1:4)
  getInitializePermanentDelegateInstruction({
    mint: mint.address,
    delegate: delegate.address
  })
]);
```

## !!steps Initialize the mint

Initialize the mint with _rs`InitializeMint`_ in the same transaction.

<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 owner = await generateKeyPairSigner();
const delegate = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();

const permanentDelegateExtension = extension("PermanentDelegate", {
  delegate: delegate.address
});

const mintSpace = BigInt(getMintSize([permanentDelegateExtension]));

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
  }),
  getInitializePermanentDelegateInstruction({
    mint: mint.address,
    delegate: delegate.address
  }),
  // !focus(1:6)
  getInitializeMintInstruction({
    mint: mint.address,
    decimals: 0,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
]);
```

## !!steps Create token accounts and mint tokens

Create token accounts for the owner and recipient, then mint tokens to the owner
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 owner = await generateKeyPairSigner();
const delegate = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();

const permanentDelegateExtension = extension("PermanentDelegate", {
  delegate: delegate.address
});

const mintSpace = BigInt(getMintSize([permanentDelegateExtension]));

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
  }),
  getInitializePermanentDelegateInstruction({
    mint: mint.address,
    delegate: delegate.address
  }),
  getInitializeMintInstruction({
    mint: mint.address,
    decimals: 0,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
]);

const [sourceToken] = await findAssociatedTokenPda({
  mint: mint.address,
  owner: owner.address,
  tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
});
const [destinationToken] = await findAssociatedTokenPda({
  mint: mint.address,
  owner: recipient.address,
  tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
});

// !focus(1:19)
await client.sendTransaction([
  await getCreateAssociatedTokenInstructionAsync({
    payer: client.payer,
    mint: mint.address,
    owner: owner.address
  }),
  await getCreateAssociatedTokenInstructionAsync({
    payer: client.payer,
    mint: mint.address,
    owner: recipient.address
  }),
  getMintToCheckedInstruction({
    mint: mint.address,
    token: sourceToken,
    mintAuthority: client.payer,
    amount: 1n,
    decimals: 0
  })
]);
```

## !!steps Transfer with the permanent delegate

Transfer tokens with _rs`TransferChecked`_ signed by the permanent delegate.

<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 owner = await generateKeyPairSigner();
const delegate = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();

const permanentDelegateExtension = extension("PermanentDelegate", {
  delegate: delegate.address
});

const mintSpace = BigInt(getMintSize([permanentDelegateExtension]));

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
  }),
  getInitializePermanentDelegateInstruction({
    mint: mint.address,
    delegate: delegate.address
  }),
  getInitializeMintInstruction({
    mint: mint.address,
    decimals: 0,
    mintAuthority: client.payer.address,
    freezeAuthority: client.payer.address
  })
]);

const [sourceToken] = await findAssociatedTokenPda({
  mint: mint.address,
  owner: owner.address,
  tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
});
const [destinationToken] = await findAssociatedTokenPda({
  mint: mint.address,
  owner: recipient.address,
  tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
});

await client.sendTransaction([
  await getCreateAssociatedTokenInstructionAsync({
    payer: client.payer,
    mint: mint.address,
    owner: owner.address
  }),
  await getCreateAssociatedTokenInstructionAsync({
    payer: client.payer,
    mint: mint.address,
    owner: recipient.address
  }),
  getMintToCheckedInstruction({
    mint: mint.address,
    token: sourceToken,
    mintAuthority: client.payer,
    amount: 1n,
    decimals: 0
  })
]);

// !focus(1:10)
await client.sendTransaction([
  getTransferCheckedInstruction({
    source: sourceToken,
    mint: mint.address,
    destination: destinationToken,
    // !mark(1:1)
    authority: delegate,
    amount: 1n,
    decimals: 0
  })
]);
```

</ScrollyCoding>

<Callout type="info" title="Instruction Order">
  _rs`InitializePermanentDelegate`_ must come before _rs`InitializeMint`_.
  _rs`CreateAccount`_, _rs`InitializePermanentDelegate`_, and
  _rs`InitializeMint`_ must be included in the same transaction.
</Callout>

### Source Reference

| Item                                        | Description                                                                                                            | Source                                                                                                                              |
| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| _rs`PermanentDelegate`_                     | Mint extension that stores the delegate authorized across every token account for the mint.                            | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/extension/permanent_delegate.rs#L15-L21) |
| _rs`InitializePermanentDelegate`_           | Instruction that initializes the permanent delegate before _rs`InitializeMint`_.                                       | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/instruction.rs#L1952-L1967)              |
| _rs`SetAuthority`_                          | Base token instruction used with _rs`AuthorityType::PermanentDelegate`_ to rotate the delegate.                        | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/instruction.rs#L1488-L1520)              |
| _rs`AuthorityType::PermanentDelegate`_      | Authority discriminator used with _rs`SetAuthority`_ to rotate the permanent delegate on a mint.                       | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/instruction.rs#L1138-L1139)              |
| _rs`process_initialize_permanent_delegate`_ | Processor logic that writes the permanent delegate extension onto the mint.                                            | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/program/src/processor.rs#L1542-L1557)                  |
| _rs`process_set_authority`_                 | Processor logic that validates and rotates the permanent delegate when _rs`AuthorityType::PermanentDelegate`_ is used. | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/program/src/processor.rs#L849-L860)                    |

### Typescript

The `Kit` example below uses the generated instructions directly. Legacy
examples using `@solana/web3.js` and `@solana/spl-token` 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 { getCreateAccountInstruction } from "@solana-program/system";
import {
  extension,
  fetchMint,
  fetchToken,
  findAssociatedTokenPda,
  getCreateAssociatedTokenInstructionAsync,
  getInitializeMintInstruction,
  getInitializePermanentDelegateInstruction,
  getMintSize,
  getMintToCheckedInstruction,
  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 owner = await generateKeyPairSigner();
const delegate = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();

const permanentDelegateExtension = extension("PermanentDelegate", {
  delegate: delegate.address
});
const mintSpace = BigInt(getMintSize([permanentDelegateExtension]));
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 plus PermanentDelegate.
    programAddress: TOKEN_2022_PROGRAM_ADDRESS // Program that owns the mint account.
  }),
  // !mark(1:4)
  getInitializePermanentDelegateInstruction({
    mint: mint.address, // Mint account that stores the PermanentDelegate extension.
    delegate: delegate.address // Permanent delegate authorized for all token accounts for the mint.
  }),
  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,
  owner: owner.address,
  tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
});
const [destinationToken] = await findAssociatedTokenPda({
  mint: mint.address,
  owner: recipient.address,
  tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
});

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: owner.address // Owner of the source token account.
  }),
  await getCreateAssociatedTokenInstructionAsync({
    payer: client.payer, // Account funding the associated token account creation.
    mint: mint.address, // Mint for the associated token account.
    owner: recipient.address // Owner of the destination 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: 1n, // Token amount in base units.
    decimals: 0 // Decimals defined on the mint.
  })
]);

await client.sendTransaction([
  // !mark(1:8)
  getTransferCheckedInstruction({
    source: sourceToken, // Token account sending the transfer.
    mint: mint.address, // Mint with the permanent delegate configuration.
    destination: destinationToken, // Token account receiving the transfer.
    authority: delegate, // Permanent delegate signing the transfer.
    amount: 1n, // Token amount in base units.
    decimals: 0 // Decimals defined on the mint.
  })
]);

const destinationAccount = await fetchToken(client.rpc, destinationToken);
const mintAccount = await fetchMint(client.rpc, mint.address);
const permanentDelegate = (
  unwrapOption(mintAccount.data.extensions) ?? []
).find((item) => isExtension("PermanentDelegate", item));

console.log("Mint Address:", mint.address);
console.log("Destination Amount:", destinationAccount.data.amount);
console.log("Permanent Delegate Extension:", permanentDelegate);
```

</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,
  createAssociatedTokenAccountInstruction,
  createInitializeMintInstruction,
  createInitializePermanentDelegateInstruction,
  createMintToCheckedInstruction,
  createTransferCheckedInstruction,
  ExtensionType,
  getAccount,
  getAssociatedTokenAddressSync,
  getMint,
  getMintLen,
  getPermanentDelegate,
  TOKEN_2022_PROGRAM_ID
} from "@solana/spl-token";

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

const feePayer = Keypair.generate();
const owner = Keypair.generate();
const delegate = Keypair.generate();
const recipient = Keypair.generate();

const airdropSignature = await connection.requestAirdrop(
  feePayer.publicKey,
  5 * LAMPORTS_PER_SOL
);
await connection.confirmTransaction({
  blockhash: latestBlockhash.blockhash,
  lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
  signature: airdropSignature
});

const extensions = [ExtensionType.PermanentDelegate];

const mint = Keypair.generate();
const mintLength = getMintLen(extensions);
const mintRent = await connection.getMinimumBalanceForRentExemption(mintLength);

const sourceToken = getAssociatedTokenAddressSync(
  mint.publicKey,
  owner.publicKey,
  false,
  TOKEN_2022_PROGRAM_ID,
  ASSOCIATED_TOKEN_PROGRAM_ID
);
const destinationToken = getAssociatedTokenAddressSync(
  mint.publicKey,
  recipient.publicKey,
  false,
  TOKEN_2022_PROGRAM_ID,
  ASSOCIATED_TOKEN_PROGRAM_ID
);

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 plus PermanentDelegate.
  lamports: mintRent, // Lamports funding the mint account rent.
  programId: TOKEN_2022_PROGRAM_ID // Program that owns the mint account.
});

// !mark(1:6)
const initializePermanentDelegateInstruction =
  createInitializePermanentDelegateInstruction(
    mint.publicKey, // Mint account that stores the PermanentDelegate extension.
    delegate.publicKey, // Permanent delegate authorized for all token accounts for the mint.
    TOKEN_2022_PROGRAM_ID // Token program that owns the mint.
  );

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 // Program that owns the mint account.
);

await sendAndConfirmTransaction(
  connection,
  new Transaction().add(
    createMintAccountInstruction,
    initializePermanentDelegateInstruction,
    initializeMintInstruction
  ),
  [feePayer, mint],
  {
    commitment: "confirmed"
  }
);

await sendAndConfirmTransaction(
  connection,
  new Transaction().add(
    createAssociatedTokenAccountInstruction(
      feePayer.publicKey, // Account funding the associated token account creation.
      sourceToken, // Associated token account address to create.
      owner.publicKey, // Owner of the source 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.
    ),
    createAssociatedTokenAccountInstruction(
      feePayer.publicKey, // Account funding the associated token account creation.
      destinationToken, // Associated token account address to create.
      recipient.publicKey, // Owner of the destination 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.
    ),
    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.
      1, // 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.
    )
  ),
  [feePayer],
  {
    commitment: "confirmed"
  }
);

await sendAndConfirmTransaction(
  connection,
  new Transaction().add(
    // !mark(1:10)
    createTransferCheckedInstruction(
      sourceToken, // Token account sending the transfer.
      mint.publicKey, // Mint with the permanent delegate configuration.
      destinationToken, // Token account receiving the transfer.
      delegate.publicKey, // Permanent delegate signing the transfer.
      1, // Token amount in base units.
      0, // Decimals defined on the mint.
      [], // Additional multisig signers.
      TOKEN_2022_PROGRAM_ID // Token program that processes the transfer.
    )
  ),
  [feePayer, delegate],
  {
    commitment: "confirmed"
  }
);

const destinationAccount = await getAccount(
  connection,
  destinationToken,
  "confirmed",
  TOKEN_2022_PROGRAM_ID
);
const mintAccount = await getMint(
  connection,
  mint.publicKey,
  "confirmed",
  TOKEN_2022_PROGRAM_ID
);
const permanentDelegate = getPermanentDelegate(mintAccount);

console.log("Mint Address:", mint.publicKey.toBase58());
console.log("Destination Amount:", destinationAccount.amount.toString());
console.log("Permanent Delegate Extension:", permanentDelegate);
```

</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::{
    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_token_2022_interface::{
    extension::{
        permanent_delegate::PermanentDelegate, BaseStateWithExtensions, ExtensionType,
        StateWithExtensions,
    },
    instruction::{
        initialize_mint, initialize_permanent_delegate, 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 owner = Keypair::new();
    let delegate = Keypair::new();
    let recipient = Keypair::new();

    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 =
        ExtensionType::try_calculate_account_len::<Mint>(&[ExtensionType::PermanentDelegate])?;

    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 plus PermanentDelegate.
        &TOKEN_2022_PROGRAM_ID, // Program that owns the mint account.
    );

    // !mark(1:5)
    let initialize_permanent_delegate_ix = initialize_permanent_delegate(
        &TOKEN_2022_PROGRAM_ID, // Token program that owns the mint.
        &mint.pubkey(), // Mint account that stores the PermanentDelegate extension.
        &delegate.pubkey(), // Permanent delegate authorized for all token accounts for the mint.
    )?;

    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_permanent_delegate_ix,
            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(
        &owner.pubkey(),
        &mint.pubkey(),
        &TOKEN_2022_PROGRAM_ID,
    );
    let destination_token = get_associated_token_address_with_program_id(
        &recipient.pubkey(),
        &mint.pubkey(),
        &TOKEN_2022_PROGRAM_ID,
    );

    let create_token_accounts_transaction = Transaction::new_signed_with_payer(
        &[
            create_associated_token_account(
                &fee_payer.pubkey(), // Account funding the associated token account creation.
                &owner.pubkey(), // Owner of the source token account.
                &mint.pubkey(), // Mint for the associated token account.
                &TOKEN_2022_PROGRAM_ID, // Token program that owns the token account.
            ),
            create_associated_token_account(
                &fee_payer.pubkey(), // Account funding the associated token account creation.
                &recipient.pubkey(), // Owner of the destination token account.
                &mint.pubkey(), // Mint for the associated token account.
                &TOKEN_2022_PROGRAM_ID, // Token program that owns the token account.
            ),
            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.
                &[&fee_payer.pubkey()], // Additional multisig signers.
                1, // Token amount in base units.
                0, // Decimals defined on the mint.
            )?,
        ],
        Some(&fee_payer.pubkey()),
        &[&fee_payer],
        client.get_latest_blockhash().await?,
    );

    client
        .send_and_confirm_transaction(&create_token_accounts_transaction)
        .await?;

    let transfer_transaction = Transaction::new_signed_with_payer(
        &[
            // !mark(1:10)
            transfer_checked(
                &TOKEN_2022_PROGRAM_ID, // Token program that processes the transfer.
                &source_token, // Token account sending the transfer.
                &mint.pubkey(), // Mint with the permanent delegate configuration.
                &destination_token, // Token account receiving the transfer.
                &delegate.pubkey(), // Permanent delegate signing the transfer.
                &[&delegate.pubkey()], // Additional multisig signers.
                1, // Token amount in base units.
                0, // Decimals defined on the mint.
            )?,
        ],
        Some(&fee_payer.pubkey()),
        &[&fee_payer, &delegate],
        client.get_latest_blockhash().await?,
    );

    client
        .send_and_confirm_transaction(&transfer_transaction)
        .await?;

    let destination_account = client.get_account(&destination_token).await?;
    let destination_state =
        StateWithExtensions::<Account>::unpack(&destination_account.data)?;
    let mint_account = client.get_account(&mint.pubkey()).await?;
    let mint_state = StateWithExtensions::<Mint>::unpack(&mint_account.data)?;
    let permanent_delegate = mint_state.get_extension::<PermanentDelegate>()?;

    println!("Mint Address: {}", mint.pubkey());
    println!(
        "Destination Amount: {}",
        u64::from(destination_state.base.amount)
    );
    println!("Permanent Delegate Extension: {:?}", permanent_delegate);

    Ok(())
}
```

</CodeTabs>
