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
-
Update
anchor-cli
:avm install 0.30.1
-
Update Anchor crate(s) to
0.30.1
. -
Update TS package(s) to
0.30.1
.
Recommended Solana Version
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.
struct
s) 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.