# SPL Token decoder (Carbon 2.0)

> Decode SPL Token instructions and accounts in Rust with carbon-token-program-decoder 2.0.0. Program ID TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA.

`carbon-token-program-decoder` decodes the instructions and accounts of the SPL Token program (`TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`): 28 instructions, 3 account types. It is generated with Codama from the program's IDL; see [decoders](https://carbon.sevenlabs.org/concepts/decoders.md) for how decoders plug into a pipeline.

|                  |                                                                                                                     |
| ---------------- | ------------------------------------------------------------------------------------------------------------------- |
| Crate            | [`carbon-token-program-decoder`](https://crates.io/crates/carbon-token-program-decoder/2.0.0) 2.0.0                 |
| Install          | `cargo add carbon-token-program-decoder@2.0.0`                                                                      |
| Program ID       | `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` (`carbon_token_program_decoder::PROGRAM_ID`)                          |
| Category         | [Core & SPL](https://carbon.sevenlabs.org/decoders/core-and-spl.md)                                                 |
| Decoder          | `carbon_token_program_decoder::TokenProgramDecoder`                                                                 |
| Instruction enum | `instructions::TokenProgramInstruction`                                                                             |
| Account enum     | `accounts::TokenProgramAccount`                                                                                     |
| Features         | `serde`, `postgres`, `graphql` (none enabled by default)                                                            |
| API docs         | [docs.rs/carbon-token-program-decoder/2.0.0](https://docs.rs/carbon-token-program-decoder/2.0.0)                    |
| Source           | [decoders/token-program-decoder](https://github.com/sevenlabs-hq/carbon/tree/v2.0.0/decoders/token-program-decoder) |

Other core and SPL decoders: [Address Lookup Table](https://carbon.sevenlabs.org/decoders/address-lookup-table.md), [Associated Token Account](https://carbon.sevenlabs.org/decoders/associated-token-account.md), [SPL Memo](https://carbon.sevenlabs.org/decoders/memo-program.md), [SPL Name Service](https://carbon.sevenlabs.org/decoders/name-service.md), [Stake Program](https://carbon.sevenlabs.org/decoders/stake-program.md), [System Program](https://carbon.sevenlabs.org/decoders/system-program.md), [Token-2022](https://carbon.sevenlabs.org/decoders/token-2022.md). To decode several in one pipeline, see [core and SPL program decoders](https://carbon.sevenlabs.org/decoders/core-and-spl.md).

Guide: [Index token transfers](https://carbon.sevenlabs.org/guides/index-token-transfers.md).

The `serde` feature derives `Serialize`/`Deserialize` on every type, `postgres` adds tables and processors for [Postgres](https://carbon.sevenlabs.org/guides/postgres.md), and `graphql` adds a schema for the [GraphQL server](https://carbon.sevenlabs.org/guides/graphql.md).

## Usage

This program crawls recent SPL Token transactions from the public RPC and prints every decoded `TransferChecked` instruction. Add the dependencies:

```sh
cargo add carbon-core@2.0.0 carbon-token-program-decoder@2.0.0 carbon-rpc-transaction-crawler-datasource@2.0.0 carbon-log-metrics@2.0.0 env_logger tokio --features tokio/full
```

`src/main.rs`:

```rust
use {
    carbon_core::{
        error::CarbonResult, instruction::InstructionProcessorInputType, pipeline::Pipeline,
        processor::Processor,
    },
    carbon_log_metrics::LogMetrics,
    carbon_token_program_decoder::{
        instructions::TokenProgramInstruction, TokenProgramDecoder, PROGRAM_ID,
    },
    carbon_rpc_transaction_crawler_datasource::{ConnectionConfig, Filters, RpcTransactionCrawler},
    std::sync::Arc,
};

#[tokio::main]
async fn main() -> CarbonResult<()> {
    env_logger::init();

    // Fetches the program's recent transactions over JSON-RPC, newest first.
    let datasource = RpcTransactionCrawler::new(
        "https://api.mainnet-beta.solana.com".to_string(),
        PROGRAM_ID,
        ConnectionConfig::default(),
        Filters::new(None, None, None),
        None,
    );

    Pipeline::builder()
        .datasource(datasource)
        .metrics(Arc::new(LogMetrics::new()))
        .instruction(TokenProgramDecoder, InstructionLogger)
        .build()?
        .run()
        .await
}

struct InstructionLogger;

impl Processor<InstructionProcessorInputType<'_, TokenProgramInstruction>> for InstructionLogger {
    async fn process(
        &mut self,
        input: &InstructionProcessorInputType<'_, TokenProgramInstruction>,
    ) -> CarbonResult<()> {
        let signature = input.metadata.transaction_metadata.signature;
        if let TokenProgramInstruction::TransferChecked { data, accounts, .. } = input.decoded_instruction {
            println!("transfer_checked {signature}: {data:?} source={}", accounts.source);
        }
        Ok(())
    }
}
```

```sh
RUST_LOG=info cargo run
```

Each `TransferChecked` instruction prints one line with the transaction signature and the decoded `TransferChecked` data. The public endpoint rate-limits requests, so the first lines can take a while; use your own RPC URL for anything beyond a test. See [stream with RPC](https://carbon.sevenlabs.org/guides/stream-with-rpc.md) for the crawler options.

### Decode accounts

The transaction crawler emits transactions only. To decode accounts, use a datasource that emits account updates. This program subscribes to the program's accounts with `programSubscribe` on the public WebSocket endpoint and prints every decoded `Mint` account as it changes. Add the datasource and the Solana RPC types it takes:

```sh
cargo add carbon-rpc-program-subscribe-datasource@2.0.0 solana-client@4.2.2
```

`src/main.rs`:

```rust
use {
    carbon_core::{
        account::AccountProcessorInputType, error::CarbonResult, pipeline::Pipeline,
        processor::Processor,
    },
    carbon_log_metrics::LogMetrics,
    carbon_token_program_decoder::{accounts::TokenProgramAccount, TokenProgramDecoder, PROGRAM_ID},
    carbon_rpc_program_subscribe_datasource::{Filters, RpcProgramSubscribe},
    solana_client::{
        rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig, UiAccountEncoding},
        rpc_filter::RpcFilterType,
    },
    std::sync::Arc,
};

#[tokio::main]
async fn main() -> CarbonResult<()> {
    env_logger::init();

    // Streams every change to an account owned by the program (programSubscribe).
    let config = RpcProgramAccountsConfig {
        // Mint accounts are 82 bytes; without a filter this streams every token account.
        filters: Some(vec![RpcFilterType::DataSize(82)]),
        account_config: RpcAccountInfoConfig {
            encoding: Some(UiAccountEncoding::Base64),
            ..Default::default()
        },
        ..Default::default()
    };
    let datasource = RpcProgramSubscribe::new(
        "wss://api.mainnet-beta.solana.com".to_string(),
        Filters::new(PROGRAM_ID, Some(config)),
    );

    Pipeline::builder()
        .datasource(datasource)
        .metrics(Arc::new(LogMetrics::new()))
        .account(TokenProgramDecoder, AccountLogger)
        .build()?
        .run()
        .await
}

struct AccountLogger;

impl Processor<AccountProcessorInputType<'_, TokenProgramAccount>> for AccountLogger {
    async fn process(
        &mut self,
        input: &AccountProcessorInputType<'_, TokenProgramAccount>,
    ) -> CarbonResult<()> {
        if let TokenProgramAccount::Mint(mint) = &input.decoded_account.data {
            println!("mint {}: {mint:?}", input.metadata.pubkey);
        }
        Ok(())
    }
}
```

```sh
RUST_LOG=info cargo run
```

Each update to a `Mint` account prints its address and decoded fields; the program runs until you stop it. Cargo resolves `solana-client` to 4.2.2, the exact version the datasource pins, so both use the same `RpcProgramAccountsConfig` type. To load every existing account once instead of streaming changes, see [load account state](https://carbon.sevenlabs.org/guides/load-account-state.md).

## Instructions

Variants of `TokenProgramInstruction`. Each is `TokenProgramInstruction::<Variant> { program_id, data, accounts }`, where `data` and `accounts` are the types listed under the variant, exported from `carbon_token_program_decoder::instructions`. Discriminators are the leading bytes of the instruction data, in hex.

**How an instruction decodes.** The decoder returns a variant only when all of these hold; otherwise the instruction is skipped and no processor is called:

1. The instruction's program ID is `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA`.
2. The data starts with the variant's discriminator, and the rest deserializes into its data type.
3. The instruction has at least as many accounts as the variant requires (the "Required accounts" count under each variant).

**Accounts.** They are matched by position, in the order listed. An account marked _optional_ is `None` only when the instruction ends before it; Anchor programs pass the program ID as a placeholder for an omitted optional account, so check for `Some(PROGRAM_ID)` too. Accounts after the listed ones are in `accounts.remaining` as `AccountMeta`s. The decoder doesn't record whether an account signed or was writable: read that from `input.raw_instruction.accounts[i].is_signer` and `.is_writable`, which follow the same order. It doesn't check signer, writable, owner or PDA constraints either; the program enforced those when the transaction executed, so a decoded instruction from a successful transaction already satisfied them.

### `AmountToUiAmount`

> _From the program's IDL:_
>
> Convert an Amount of tokens to a UiAmount `string`, using the given mint. In this version of the program, the mint can only specify the number of decimals.\
> Fails on an invalid mint.\
> Return data can be fetched using `sol_get_return_data` and deserialized with `String::from_utf8`.

Discriminator `17` · data `AmountToUiAmount` · accounts `AmountToUiAmountInstructionAccounts`.

| Field    | Type  | Description                       |
| -------- | ----- | --------------------------------- |
| `amount` | `u64` | The amount of tokens to reformat. |

Required accounts: 1; extras go to `remaining`.

Fields of `AmountToUiAmountInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `mint`      | `Pubkey`           |
| 1… | `remaining` | `Vec<AccountMeta>` |

### `Approve`

> _From the program's IDL:_
>
> Approves a delegate. A delegate is given the authority over tokens on behalf of the source account's owner.

Discriminator `04` · data `Approve` · accounts `ApproveInstructionAccounts`.

| Field    | Type  | Description                                        |
| -------- | ----- | -------------------------------------------------- |
| `amount` | `u64` | The amount of tokens the delegate is approved for. |

Required accounts: 3; extras go to `remaining`.

Fields of `ApproveInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `source`    | `Pubkey`           |
| 1  | `delegate`  | `Pubkey`           |
| 2  | `owner`     | `Pubkey`           |
| 3… | `remaining` | `Vec<AccountMeta>` |

### `ApproveChecked`

> _From the program's IDL:_
>
> Approves a delegate. A delegate is given the authority over tokens on behalf of the source account's owner.\
> This instruction differs from Approve in that the token mint and decimals value is checked by the caller. This may be useful when creating transactions offline or within a hardware wallet.

Discriminator `0d` · data `ApproveChecked` · accounts `ApproveCheckedInstructionAccounts`.

| Field      | Type  | Description                                                          |
| ---------- | ----- | -------------------------------------------------------------------- |
| `amount`   | `u64` | The amount of tokens the delegate is approved for.                   |
| `decimals` | `u8`  | Expected number of base 10 digits to the right of the decimal place. |

Required accounts: 4; extras go to `remaining`.

Fields of `ApproveCheckedInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `source`    | `Pubkey`           |
| 1  | `mint`      | `Pubkey`           |
| 2  | `delegate`  | `Pubkey`           |
| 3  | `owner`     | `Pubkey`           |
| 4… | `remaining` | `Vec<AccountMeta>` |

### `Batch`

> _From the program's IDL:_
>
> Executes a batch of instructions. The instructions to be executed are specified in sequence on the instruction data.

Discriminator `ff` · data `Batch` · accounts `BatchInstructionAccounts`.

| Field  | Type                           | Description                              |
| ------ | ------------------------------ | ---------------------------------------- |
| `data` | [`Vec<BatchItem>`](#batchitem) | Instruction data for batch instructions. |

No named accounts.

### `Burn`

> _From the program's IDL:_
>
> Burns tokens by removing them from an account. `Burn` does not support accounts associated with the native mint, use `CloseAccount` instead.

Discriminator `08` · data `Burn` · accounts `BurnInstructionAccounts`.

| Field    | Type  |
| -------- | ----- |
| `amount` | `u64` |

Required accounts: 3; extras go to `remaining`.

Fields of `BurnInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `account`   | `Pubkey`           |
| 1  | `mint`      | `Pubkey`           |
| 2  | `authority` | `Pubkey`           |
| 3… | `remaining` | `Vec<AccountMeta>` |

### `BurnChecked`

> _From the program's IDL:_
>
> Burns tokens by removing them from an account. `BurnChecked` does not support accounts associated with the native mint, use `CloseAccount` instead. This instruction differs from Burn in that the decimals value is checked by the caller. This may be useful when creating transactions offline or within a hardware wallet.

Discriminator `0f` · data `BurnChecked` · accounts `BurnCheckedInstructionAccounts`.

| Field      | Type  | Description                                                          |
| ---------- | ----- | -------------------------------------------------------------------- |
| `amount`   | `u64` | The amount of tokens to burn.                                        |
| `decimals` | `u8`  | Expected number of base 10 digits to the right of the decimal place. |

Required accounts: 3; extras go to `remaining`.

Fields of `BurnCheckedInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `account`   | `Pubkey`           |
| 1  | `mint`      | `Pubkey`           |
| 2  | `authority` | `Pubkey`           |
| 3… | `remaining` | `Vec<AccountMeta>` |

### `CloseAccount`

> _From the program's IDL:_
>
> Close an account by transferring all its SOL to the destination account.\
> Non-native accounts may only be closed if its token amount is zero.

Discriminator `09` · data `CloseAccount` · accounts `CloseAccountInstructionAccounts`.

No data fields.

Required accounts: 3; extras go to `remaining`.

Fields of `CloseAccountInstructionAccounts`, in account order:

| #  | Field         | Type               |
| -- | ------------- | ------------------ |
| 0  | `account`     | `Pubkey`           |
| 1  | `destination` | `Pubkey`           |
| 2  | `owner`       | `Pubkey`           |
| 3… | `remaining`   | `Vec<AccountMeta>` |

### `FreezeAccount`

> _From the program's IDL:_
>
> Freeze an Initialized account using the Mint's freeze_authority (if set).

Discriminator `0a` · data `FreezeAccount` · accounts `FreezeAccountInstructionAccounts`.

No data fields.

Required accounts: 3; extras go to `remaining`.

Fields of `FreezeAccountInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `account`   | `Pubkey`           |
| 1  | `mint`      | `Pubkey`           |
| 2  | `owner`     | `Pubkey`           |
| 3… | `remaining` | `Vec<AccountMeta>` |

### `GetAccountDataSize`

> _From the program's IDL:_
>
> Gets the required size of an account for the given mint as a little-endian `u64`.\
> Return data can be fetched using `sol_get_return_data` and deserializing the return data as a little-endian `u64`.

Discriminator `15` · data `GetAccountDataSize` · accounts `GetAccountDataSizeInstructionAccounts`.

No data fields.

Required accounts: 1; extras go to `remaining`.

Fields of `GetAccountDataSizeInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `mint`      | `Pubkey`           |
| 1… | `remaining` | `Vec<AccountMeta>` |

### `InitializeAccount`

> _From the program's IDL:_
>
> Initializes a new account to hold tokens. If this account is associated with the native mint then the token balance of the initialized account will be equal to the amount of SOL in the account. If this account is associated with another mint, that mint must be initialized before this command can succeed.\
> The `InitializeAccount` instruction requires no signers and MUST be included within the same Transaction as the system program's `CreateAccount` instruction that creates the account being initialized.\
> Otherwise another party can acquire ownership of the uninitialized account.

Discriminator `01` · data `InitializeAccount` · accounts `InitializeAccountInstructionAccounts`.

No data fields.

Required accounts: 4; extras go to `remaining`.

Fields of `InitializeAccountInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `account`   | `Pubkey`           |
| 1  | `mint`      | `Pubkey`           |
| 2  | `owner`     | `Pubkey`           |
| 3  | `rent`      | `Pubkey`           |
| 4… | `remaining` | `Vec<AccountMeta>` |

### `InitializeAccount2`

> _From the program's IDL:_
>
> Like InitializeAccount, but the owner pubkey is passed via instruction data rather than the accounts list. This variant may be preferable when using Cross Program Invocation from an instruction that does not need the owner's `AccountInfo` otherwise.

Discriminator `10` · data `InitializeAccount2` · accounts `InitializeAccount2InstructionAccounts`.

| Field   | Type     | Description                             |
| ------- | -------- | --------------------------------------- |
| `owner` | `Pubkey` | The new account's owner/multisignature. |

Required accounts: 3; extras go to `remaining`.

Fields of `InitializeAccount2InstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `account`   | `Pubkey`           |
| 1  | `mint`      | `Pubkey`           |
| 2  | `rent`      | `Pubkey`           |
| 3… | `remaining` | `Vec<AccountMeta>` |

### `InitializeAccount3`

> _From the program's IDL:_
>
> Like InitializeAccount2, but does not require the Rent sysvar to be provided.

Discriminator `12` · data `InitializeAccount3` · accounts `InitializeAccount3InstructionAccounts`.

| Field   | Type     | Description                             |
| ------- | -------- | --------------------------------------- |
| `owner` | `Pubkey` | The new account's owner/multisignature. |

Required accounts: 2; extras go to `remaining`.

Fields of `InitializeAccount3InstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `account`   | `Pubkey`           |
| 1  | `mint`      | `Pubkey`           |
| 2… | `remaining` | `Vec<AccountMeta>` |

### `InitializeImmutableOwner`

> _From the program's IDL:_
>
> Initialize the Immutable Owner extension for the given token account\
> Fails if the account has already been initialized, so must be called before `InitializeAccount`.\
> No-ops in this version of the program, but is included for compatibility with the Associated Token Account program.

Discriminator `16` · data `InitializeImmutableOwner` · accounts `InitializeImmutableOwnerInstructionAccounts`.

No data fields.

Required accounts: 1; extras go to `remaining`.

Fields of `InitializeImmutableOwnerInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `account`   | `Pubkey`           |
| 1… | `remaining` | `Vec<AccountMeta>` |

### `InitializeMint`

> _From the program's IDL:_
>
> Initializes a new mint and optionally deposits all the newly minted tokens in an account.\
> The `InitializeMint` instruction requires no signers and MUST be included within the same Transaction as the system program's `CreateAccount` instruction that creates the account being initialized.\
> Otherwise another party can acquire ownership of the uninitialized account.

Discriminator `00` · data `InitializeMint` · accounts `InitializeMintInstructionAccounts`.

| Field              | Type             | Description                                        |
| ------------------ | ---------------- | -------------------------------------------------- |
| `decimals`         | `u8`             | Number of decimals in token account amounts.       |
| `mint_authority`   | `Pubkey`         | Minting authority.                                 |
| `freeze_authority` | `Option<Pubkey>` | Optional authority that can freeze token accounts. |

Required accounts: 2; extras go to `remaining`.

Fields of `InitializeMintInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `mint`      | `Pubkey`           |
| 1  | `rent`      | `Pubkey`           |
| 2… | `remaining` | `Vec<AccountMeta>` |

### `InitializeMint2`

> _From the program's IDL:_
>
> Like \[`InitializeMint`], but does not require the Rent sysvar to be provided.

Discriminator `14` · data `InitializeMint2` · accounts `InitializeMint2InstructionAccounts`.

| Field              | Type             | Description                                                 |
| ------------------ | ---------------- | ----------------------------------------------------------- |
| `decimals`         | `u8`             | Number of base 10 digits to the right of the decimal place. |
| `mint_authority`   | `Pubkey`         | The authority/multisignature to mint tokens.                |
| `freeze_authority` | `Option<Pubkey>` | The optional freeze authority/multisignature of the mint.   |

Required accounts: 1; extras go to `remaining`.

Fields of `InitializeMint2InstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `mint`      | `Pubkey`           |
| 1… | `remaining` | `Vec<AccountMeta>` |

### `InitializeMultisig`

> _From the program's IDL:_
>
> Initializes a multisignature account with N provided signers.\
> Multisignature accounts can used in place of any single owner/delegate accounts in any token instruction that require an owner/delegate to be present. The variant field represents the number of signers (M) required to validate this multisignature account.\
> The `InitializeMultisig` instruction requires no signers and MUST be included within the same Transaction as the system program's `CreateAccount` instruction that creates the account being initialized.\
> Otherwise another party can acquire ownership of the uninitialized account.

Discriminator `02` · data `InitializeMultisig` · accounts `InitializeMultisigInstructionAccounts`.

| Field | Type | Description                                                                 |
| ----- | ---- | --------------------------------------------------------------------------- |
| `m`   | `u8` | The number of signers (M) required to validate this multisignature account. |

Required accounts: 2; extras go to `remaining`.

Fields of `InitializeMultisigInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `multisig`  | `Pubkey`           |
| 1  | `rent`      | `Pubkey`           |
| 2… | `remaining` | `Vec<AccountMeta>` |

### `InitializeMultisig2`

> _From the program's IDL:_
>
> Like InitializeMultisig, but does not require the Rent sysvar to be provided.

Discriminator `13` · data `InitializeMultisig2` · accounts `InitializeMultisig2InstructionAccounts`.

| Field | Type | Description                                                                 |
| ----- | ---- | --------------------------------------------------------------------------- |
| `m`   | `u8` | The number of signers (M) required to validate this multisignature account. |

Required accounts: 1; extras go to `remaining`.

Fields of `InitializeMultisig2InstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `multisig`  | `Pubkey`           |
| 1… | `remaining` | `Vec<AccountMeta>` |

### `MintTo`

> _From the program's IDL:_
>
> Mints new tokens to an account. The native mint does not support minting.

Discriminator `07` · data `MintTo` · accounts `MintToInstructionAccounts`.

| Field    | Type  | Description                       |
| -------- | ----- | --------------------------------- |
| `amount` | `u64` | The amount of new tokens to mint. |

Required accounts: 3; extras go to `remaining`.

Fields of `MintToInstructionAccounts`, in account order:

| #  | Field            | Type               |
| -- | ---------------- | ------------------ |
| 0  | `mint`           | `Pubkey`           |
| 1  | `token`          | `Pubkey`           |
| 2  | `mint_authority` | `Pubkey`           |
| 3… | `remaining`      | `Vec<AccountMeta>` |

### `MintToChecked`

> _From the program's IDL:_
>
> Mints new tokens to an account. The native mint does not support minting.\
> This instruction differs from MintTo in that the decimals value is checked by the caller. This may be useful when creating transactions offline or within a hardware wallet.

Discriminator `0e` · data `MintToChecked` · accounts `MintToCheckedInstructionAccounts`.

| Field      | Type  | Description                                                          |
| ---------- | ----- | -------------------------------------------------------------------- |
| `amount`   | `u64` | The amount of new tokens to mint.                                    |
| `decimals` | `u8`  | Expected number of base 10 digits to the right of the decimal place. |

Required accounts: 3; extras go to `remaining`.

Fields of `MintToCheckedInstructionAccounts`, in account order:

| #  | Field            | Type               |
| -- | ---------------- | ------------------ |
| 0  | `mint`           | `Pubkey`           |
| 1  | `token`          | `Pubkey`           |
| 2  | `mint_authority` | `Pubkey`           |
| 3… | `remaining`      | `Vec<AccountMeta>` |

### `Revoke`

> _From the program's IDL:_
>
> Revokes the delegate's authority.

Discriminator `05` · data `Revoke` · accounts `RevokeInstructionAccounts`.

No data fields.

Required accounts: 2; extras go to `remaining`.

Fields of `RevokeInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `source`    | `Pubkey`           |
| 1  | `owner`     | `Pubkey`           |
| 2… | `remaining` | `Vec<AccountMeta>` |

### `SetAuthority`

> _From the program's IDL:_
>
> Sets a new authority of a mint or account.

Discriminator `06` · data `SetAuthority` · accounts `SetAuthorityInstructionAccounts`.

| Field            | Type                              | Description                      |
| ---------------- | --------------------------------- | -------------------------------- |
| `authority_type` | [`AuthorityType`](#authoritytype) | The type of authority to update. |
| `new_authority`  | `Option<Pubkey>`                  | The new authority                |

Required accounts: 2; extras go to `remaining`.

Fields of `SetAuthorityInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `owned`     | `Pubkey`           |
| 1  | `owner`     | `Pubkey`           |
| 2… | `remaining` | `Vec<AccountMeta>` |

### `SyncNative`

> _From the program's IDL:_
>
> Given a wrapped / native token account (a token account containing SOL) updates its amount field based on the account's underlying `lamports`.\
> This is useful if a non-wrapped SOL account uses `system_instruction::transfer` to move lamports to a wrapped token account, and needs to have its token `amount` field updated.

Discriminator `11` · data `SyncNative` · accounts `SyncNativeInstructionAccounts`.

No data fields.

Required accounts: 1 (2 listed); extras go to `remaining`.

Fields of `SyncNativeInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `account`   | `Pubkey`           |
| 1  | `rent`      | `Option<Pubkey>`   |
| 2… | `remaining` | `Vec<AccountMeta>` |

### `ThawAccount`

> _From the program's IDL:_
>
> Thaw a Frozen account using the Mint's freeze_authority (if set).

Discriminator `0b` · data `ThawAccount` · accounts `ThawAccountInstructionAccounts`.

No data fields.

Required accounts: 3; extras go to `remaining`.

Fields of `ThawAccountInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `account`   | `Pubkey`           |
| 1  | `mint`      | `Pubkey`           |
| 2  | `owner`     | `Pubkey`           |
| 3… | `remaining` | `Vec<AccountMeta>` |

### `Transfer`

> _From the program's IDL:_
>
> Transfers tokens from one account to another either directly or via a delegate. If this account is associated with the native mint then equal amounts of SOL and Tokens will be transferred to the destination account.

Discriminator `03` · data `Transfer` · accounts `TransferInstructionAccounts`.

| Field    | Type  | Description                       |
| -------- | ----- | --------------------------------- |
| `amount` | `u64` | The amount of tokens to transfer. |

Required accounts: 3; extras go to `remaining`.

Fields of `TransferInstructionAccounts`, in account order:

| #  | Field         | Type               |
| -- | ------------- | ------------------ |
| 0  | `source`      | `Pubkey`           |
| 1  | `destination` | `Pubkey`           |
| 2  | `authority`   | `Pubkey`           |
| 3… | `remaining`   | `Vec<AccountMeta>` |

### `TransferChecked`

> _From the program's IDL:_
>
> Transfers tokens from one account to another either directly or via a delegate. If this account is associated with the native mint then equal amounts of SOL and Tokens will be transferred to the destination account.\
> This instruction differs from Transfer in that the token mint and decimals value is checked by the caller. This may be useful when creating transactions offline or within a hardware wallet.

Discriminator `0c` · data `TransferChecked` · accounts `TransferCheckedInstructionAccounts`.

| Field      | Type  | Description                                                          |
| ---------- | ----- | -------------------------------------------------------------------- |
| `amount`   | `u64` | The amount of tokens to transfer.                                    |
| `decimals` | `u8`  | Expected number of base 10 digits to the right of the decimal place. |

Required accounts: 4; extras go to `remaining`.

Fields of `TransferCheckedInstructionAccounts`, in account order:

| #  | Field         | Type               |
| -- | ------------- | ------------------ |
| 0  | `source`      | `Pubkey`           |
| 1  | `mint`        | `Pubkey`           |
| 2  | `destination` | `Pubkey`           |
| 3  | `authority`   | `Pubkey`           |
| 4… | `remaining`   | `Vec<AccountMeta>` |

### `UiAmountToAmount`

> _From the program's IDL:_
>
> Convert a UiAmount of tokens to a little-endian `u64` raw Amount, using the given mint. In this version of the program, the mint can only specify the number of decimals.\
> Return data can be fetched using `sol_get_return_data` and deserializing the return data as a little-endian `u64`.

Discriminator `18` · data `UiAmountToAmount` · accounts `UiAmountToAmountInstructionAccounts`.

| Field       | Type     | Description                          |
| ----------- | -------- | ------------------------------------ |
| `ui_amount` | `String` | The ui_amount of tokens to reformat. |

Required accounts: 1; extras go to `remaining`.

Fields of `UiAmountToAmountInstructionAccounts`, in account order:

| #  | Field       | Type               |
| -- | ----------- | ------------------ |
| 0  | `mint`      | `Pubkey`           |
| 1… | `remaining` | `Vec<AccountMeta>` |

### `UnwrapLamports`

> _From the program's IDL:_
>
> Transfer lamports from a native SOL account to a destination account.

Discriminator `2d` · data `UnwrapLamports` · accounts `UnwrapLamportsInstructionAccounts`.

| Field    | Type          | Description                                                                                                                     |
| -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `amount` | `Option<u64>` | Optional amount of lamports to transfer. If not provided, the instruction will unwrap all lamports in excess of rent exemption. |

Required accounts: 3; extras go to `remaining`.

Fields of `UnwrapLamportsInstructionAccounts`, in account order:

| #  | Field         | Type               |
| -- | ------------- | ------------------ |
| 0  | `source`      | `Pubkey`           |
| 1  | `destination` | `Pubkey`           |
| 2  | `authority`   | `Pubkey`           |
| 3… | `remaining`   | `Vec<AccountMeta>` |

### `WithdrawExcessLamports`

> _From the program's IDL:_
>
> Rescue SOL sent to any TokenProgram-owned account by sending them to any other account, leaving behind only lamports for rent exemption.

Discriminator `26` · data `WithdrawExcessLamports` · accounts `WithdrawExcessLamportsInstructionAccounts`.

No data fields.

Required accounts: 3; extras go to `remaining`.

Fields of `WithdrawExcessLamportsInstructionAccounts`, in account order:

| #  | Field         | Type               |
| -- | ------------- | ------------------ |
| 0  | `source`      | `Pubkey`           |
| 1  | `destination` | `Pubkey`           |
| 2  | `authority`   | `Pubkey`           |
| 3… | `remaining`   | `Vec<AccountMeta>` |

## Accounts

Variants of `TokenProgramAccount`. Each wraps a boxed struct from `carbon_token_program_decoder::accounts::<module>`. `decode_account` only considers accounts owned by `PROGRAM_ID` and returns the first variant that matches.

### `Mint`

Unpacked with `spl_token_interface::state::Mint::unpack` · `accounts::mint::Mint`.

| Field              | Type             | Description                                                                                                                                                                                                     |
| ------------------ | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `mint_authority`   | `Option<Pubkey>` | Optional authority used to mint new tokens. The mint authority may only be provided during mint creation. If no mint authority is present then the mint has a fixed supply and no further tokens may be minted. |
| `supply`           | `u64`            | Total supply of tokens.                                                                                                                                                                                         |
| `decimals`         | `u8`             | Number of base 10 digits to the right of the decimal place.                                                                                                                                                     |
| `is_initialized`   | `bool`           | Is `true` if this structure has been initialized.                                                                                                                                                               |
| `freeze_authority` | `Option<Pubkey>` | Optional authority to freeze token accounts.                                                                                                                                                                    |

### `Multisig`

Unpacked with `spl_token_interface::state::Multisig::unpack` · `accounts::multisig::Multisig`.

| Field            | Type           | Description                                       |
| ---------------- | -------------- | ------------------------------------------------- |
| `m`              | `u8`           | Number of signers required.                       |
| `n`              | `u8`           | Number of valid signers.                          |
| `is_initialized` | `bool`         | Is `true` if this structure has been initialized. |
| `signers`        | `[Pubkey; 11]` | Signer public keys.                               |

### `Token`

Unpacked with `spl_token_interface::state::Account::unpack` · `accounts::token::Token`.

| Field              | Type                            | Description                                                                                                                                                                                                                                     |
| ------------------ | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `mint`             | `Pubkey`                        | The mint associated with this account.                                                                                                                                                                                                          |
| `owner`            | `Pubkey`                        | The owner of this account.                                                                                                                                                                                                                      |
| `amount`           | `u64`                           | The amount of tokens this account holds.                                                                                                                                                                                                        |
| `delegate`         | `Option<Pubkey>`                | If `delegate` is `Some` then `delegated_amount` represents the amount authorized by the delegate.                                                                                                                                               |
| `state`            | [`AccountState`](#accountstate) | The account's state.                                                                                                                                                                                                                            |
| `is_native`        | `Option<u64>`                   | If is_native.is_some, this is a native token, and the value logs the rent-exempt reserve. An Account is required to be rent-exempt, so the value is used by the Processor to ensure that wrapped SOL accounts do not drop below this threshold. |
| `delegated_amount` | `u64`                           | The amount delegated.                                                                                                                                                                                                                           |
| `close_authority`  | `Option<Pubkey>`                | Optional authority to close the account.                                                                                                                                                                                                        |

## Types

Types used by the instructions, accounts and events above, exported from `carbon_token_program_decoder::types`.

### `AccountState`

Enum `types::AccountState`.

| Variant         |
| --------------- |
| `Uninitialized` |
| `Initialized`   |
| `Frozen`        |

### `AuthorityType`

Enum `types::AuthorityType`.

| Variant         |
| --------------- |
| `MintTokens`    |
| `FreezeAccount` |
| `AccountOwner`  |
| `CloseAccount`  |

### `BatchItem`

Struct `types::BatchItem`.

| Field                | Type      |
| -------------------- | --------- |
| `number_of_accounts` | `u8`      |
| `instruction_data`   | `Vec<u8>` |

---

Carbon 2.0.0 documentation · Web: https://carbon.sevenlabs.org/decoders/token-program · Last updated 2026-11-09 · Index of all pages: https://carbon.sevenlabs.org/llms.txt
