Skip to main content

Release Notes 0.30.1

There are a good number of quality of life improvements in this patch release. You can upgrade to this version from 0.30.0 with ease since there are no major breaking changes.


How to upgrade

  1. Update anchor-cli:

    avm install 0.30.1
  2. Update Anchor crate(s) to 0.30.1.

  3. Update TS package(s) to 0.30.1.

While this release supports anything above 1.17.3, the recommended Solana version is 1.18.17. You can upgrade Solana tools by running:

solana-install init 1.18.17

IDL

Convert legacy IDLs

A new feature has been added to the IDL crate in order to convert legacy IDLs (pre Anchor v0.30) to new IDLs.

To programmatically convert legacy IDLs, add:

anchor-lang-idl = { version = "0.1.1", features = ["convert"] }

and use the convert_idl function.

NOTE: This functionality has also been implemented as a CLI command for convenience, see idl convert command.

Unsupported seed expressions

Some seed expressions such as &(my_account.data + 1).to_le_bytes():

#[derive(Accounts)]
pub struct SeedMathExpr<'info> {
#[account(seeds = [&(my_account.data + 1).to_le_bytes()], bump)]
pub math_expr_account: UncheckedAccount<'info>,
pub my_account: Account<'info, MyAccount>,
}

#[account]
pub struct MyAccount {
data: u64,
}

cannot currently get stored in the IDL, but there was a regression in the IDL generation that resulted in compile errors when using these or similar unsupported expressions.

They no longer cause compile errors, but this also means that they also cannot get automatically resolved by clients.

Fields with address constraint

Using field expressions as an address constraint e.g.

#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(address = my_account.authority)]
pub authority: UncheckedAccount<'info>,
pub my_account: Account<'info, MyAccount>,
}

#[account]
pub struct MyAccount {
authority: u64,
}

no longer result in a compile error when generating the IDL.

However, accounts that use the address constraint with non-constant values do not currently resolve automatically. For this reason, you might want to consider using the has_one constraint instead:

#[derive(Accounts)]
pub struct Initialize<'info> {
pub authority: UncheckedAccount<'info>,
#[account(has_one = authority)]
pub my_account: Account<'info, MyAccount>,
}

Override nightly version on builds

IDL generation currently uses the nightly compiler to build the IDL, and this can potentially result in compile errors on certain nightly versions.

In this release, you can now override the nightly version with RUSTUP_TOOLCHAIN env variable.

Recursive generation

There was a compile error during generation with recursive external type resolution, which is now fixed. See this if you'd like to see the problem in more detail.

New spec crate

Making changes to the IDL crate, e.g. adding features such as the convert feature, would require bumping the version to get the changes even if the spec itself doesn't change.

To fix this problem, a new crate that only includes the IDL spec has been introduced. The new crate's version will be used in the idl.metadata.spec field to differentiate between various IDLs.

NOTE: This crate is accesible via the main IDL crate from anchor_lang_idl::types.

CLI

idl convert command

This command allows you to convert legacy IDLs with the new anchor idl convert command:

anchor idl convert <PATH_TO_IDL_JSON>

idl type command

This command creates TypeScript IDL type (with camelCase fields) from an existing IDL file:

anchor idl type <PATH_TO_IDL_JSON>

idl build toolchain override

See the explanation in the IDL section. Example usage with the CLI:

RUSTUP_TOOLCHAIN="nightly-2024-05-09" anchor idl build

Automatic program id updates

When building a program for the first time ever, the program id declarations will get automatically updated if there is not a [programs.localnet] entry in Anchor.toml.

Note that this is essentially the same as running anchor keys sync, only difference being that this will only run once automatically.

Upgradeable program clones

Cloning upgradeable programs with

[test.validator]
url = "https://api.mainnet-beta.solana.com"

[[test.validator.clone]]
address = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"

would result in unusable programs due to a breaking change in Solana 1.17.12.

This problem has been fixed from both Anchor and Solana's side. However, it requires using solana-cli >=1.18.10.

File system error improvements

Default Rust error when a file is not found in the file system does not log the file path, which makes it difficult to debug.

In this release, file system related errors also include the path of the file.

Lang

Using legacy IDLs with declare_program!

declare_program! macro can now be used with legacy IDLs (pre Anchor v0.30).

This works great as long as the program can be described correctly with the legacy IDL spec. However, if a program uses non-default features such as zero copy, or repr modifications, the declaration of the program either won't compile, or will be invalid. There are two main solutions in this scenerio:

  • Use the idl convert command, and manually fix the invalid parts
  • Generate the program's IDL by upgrading the program to Anchor v0.30

The latter option is preferred as it's less error-prone. If you have dependency issues while upgrading, simply remove them when generating the IDL since the IDL generation only cares about the signatures, and all program logic, including all dependencies (except Anchor), can be removed when generating the IDL. Here is an example program that you can generate an IDL from.

In short, IDLs should be preferably generated with v0.30 rather than the conversion method, as a new IDL spec wouldn't be necessary if the old one was sufficient to reliably describe programs.

declare_program! fixes

There were a number of cases where the new declare_program! would cause a compile error.

Using the following would result in a compile error:

  • Defined types (e.g. structs) in instruction parameters
  • Types with const generics
  • Vec<u8> type
  • Instruction with a non-unit return type
  • Optional accounts (in clients)
  • bytemuckunsafe account serialization

Another issue was tuple struct fields were private (Rust default), they are now public.

pubkey! macro

solana-program has pubkey! to easily declare public keys:

let key = pubkey!("11111111111111111111111111111111");

which is more convenient than Pubkey::from_str:

use std::str::FromStr;
let key = Pubkey::from_str("11111111111111111111111111111111").unwrap();

However, because of how the macro is implemented, it wasn't possible to use it from Anchor without also including solana-program to your dependency list as the macro was specifically using ::solana_program.

You can now directly use pubkey! as it's exported from anchor_lang::prelude.

Note that because solana_program is exported from anchor_lang, you can also remove solana-program dependency from your Cargo.toml if pubkey! was the reason for adding it.

ID_CONST constant

Program ids declared from declare_id! and declare_program! have ID declared as static which doesn't allow compile time checks.

Both of these macros now have a new constant (ID_CONST), which is essentially the same as ID, but is declared as const instead of static.

Stack usage of token extensions

Stack usage of the new token extensions constraints has been improved.

Error propagation from integer conversion errors

You can now propagate integer conversion errors with ?:

let n: i32 = u32::MAX.try_into()?;

SPL

Export ATA crate

[spl-associated-token-account](https://crates.io/crates/spl-associated-token-account) crate is now re-exported from anchor_spl::associated_token`.

Similar to how you can remove the mpl-token-metadata crate from your dependency list, you can also remove spl-associated-token-accounts crate.

[dependencies]
anchor-spl = "0.30.1"
- spl-associated-token-account = "3.0.2"

TypeScript

ATA resolution

The account resolution support has been extended to support associated token accounts in this release.

If you use ATAs in your instruction, you'll get a type error if you call the accounts method with those account specified. To solve, simply remove all ATAs from your accounts call.

Defined types in generics

Using defined types (structs, enums, or type aliases) as a generic argument e.g.

param: GenericStruct<MyStruct>,

no longer results in an error.

Versioned transactions

A problem where maxSupportedTransactionVersion was needed, but not being set from AnchorProvider has been fixed.

New errors package

Anchor errors have been separated into a new package @coral-xyz/anchor-errors.


See the full list of notable changes in the CHANGELOG.