Release Notes 0.30.0
The long-awaited v0.30.0 release is finally here!
We'll go over the main changes, but if you'd like to see all notable changes, check out the CHANGELOG.
How to upgrade
-
Update
avm
:cargo install --git https://github.com/coral-xyz/anchor --tag v0.30.0 avm --locked
-
Update
anchor-cli
:avm install latest
-
Update Anchor crate(s) to
0.30.0
. Optionally, runcargo update
to update other dependencies to the latest compatible versions. -
Update TS package(s) to
0.30.0
.
Recommended Solana Version
While this release supports anything above 1.16
, the recommended Solana version is 1.18.8
. You can upgrade Solana tools by running:
solana-install init 1.18.8
IDL
The IDL type specification and generation has been rewritten. To keep the release notes short, we won't go over the changes here, but see this if you'd like to learn more.
idl-build
feature
idl-build
feature is now required in your program's Cargo.toml
definition in order for the IDL generation to work.
Without this feature, anchor build
outputs:
Error: `idl-build` feature is missing. To solve, add
[features]
idl-build = ["anchor-lang/idl-build"]
in `<PATH_TO_CARGO_TOML>`.
Note that all crates that you use to generate type definitions for the IDL need to be specified in the list of idl-build
, e.g. anchor-spl/idl-build
, some-program/idl-build
...
Lang
Dependency free program declaration
Depending on other crates who used different versions of Anchor is not the best experience, to say the least. To solve this problem, program clients can now be generated from their IDL using the new declare_program!
macro:
declare_program!(program_name);
program_name
is based on the file name of the IDL in idls
directory, e.g. idls/program_name.json
is required to exist in order for the above example to work.
This works for both on-chain (CPI) and off-chain (RPC) usage, allowing program interactions without creating a dependency hell. Check out this example for on-chain CPI usage.
For more information, see the macro's documentation.
Token extensions
Constraints
There are new account constraints for Token Extensions (Token 2022):
group_pointer
:authority
group_address
group_member_pointer
:authority
member_address
metadata_pointer
:authority
metadata_address
close_authority
authority
permanent_delegate
:delegate
transfer_hook
:authority
program_id
Note: Above values are concatinated with ::
(similar to other Anchor constraints) and have extensions
prefix e.g. extensions::group_pointer::authority = <EXPR>
.
These constraints can be used both with or without the init
constraint.
Here is an example program that uses these constraints.
CPI wrappers
anchor-spl
now includes CPI wrappers for Token Extensions which can be accessed from anchor_spl::token_2022_extensions
.
#[interface]
attribute
Transfer hooks can now be used with the new #[interface]
macro. This argument overrides the Anchor's default instruction discriminator to use the interface instruction's discriminator.
Current supported values are:
spl_transfer_hook_interface::initialize_extra_account_meta_list
spl_transfer_hook_interface::execute
mod my_hook_program {
#[interface(spl_transfer_hook_interface::initialize_extra_account_meta_list)]
pub fn initialize(ctx: Context<Initialize>, metas: Vec<AnchorExtraAccountMeta>) -> Result<()> {
/* ... */
}
#[interface(spl_transfer_hook_interface::execute)]
pub fn execute(ctx: Context<Execute>, amount: u64) -> Result<()> {
/* ... */
}
}
Optional bumps
When an optional account is not specified, instead of defaulting it to u8::MAX
, this release changes the optional bump type to be Option<u8>
and sets the bump field to None
.
Less heap allocations
BorshSerialize::try_to_vec
implementation, which is used in events, CPI, and return data, heap allocates 1024 bytes each time it's used, even if your data is much smaller. In this release, the default allocation is set to 256 bytes.
There is also a new method InstructionData::write_to()
to write to an existing allocation rather than creating a new allocation with InstructionData::data()
.
CLI
Priority fees in CLI
IDL commands take in --priority-fee
argument
As it's getting harder and harder to land transactions in mainnet-beta without using priority fees, this release supports setting --priority-fee
argument for the IDL commands. For example:
anchor idl erase-authority --program-id <PROGRAM_ID> --priority-fee 9000
When the --priortiy-fee
argument is not specified, the median fee of the last 150 confirmed slots is used.
--no-idl
flag on builds
IDL generation requires building of the program, but this is unnecessary if your program API doesn't change. In that case, you can use --no-idl
flag to build your program but skip the IDL generation:
anchor build --no-idl
IDL buffer is closed after idl upgrade
After an IDL upgrade, the buffer account is now closed and the lamports are returned back to the IDL authority.
Pass deploy arguments to solana-cli
You can now pass arguments to solana program deploy
from anchor deploy
:
anchor deploy -- --final
Verifiable deployments
Similar to verifiable builds, you can now deploy the verified build instead of the default build:
anchor deploy --verifiable
Accept package name as program name
--program-name
(-p
) argument of various commands also works with package name of the program rather than lib name which is snake_case. For example:
anchor build -p my-program
Deactivate test-validator features
You can now deactivate test-validator features from Anchor.toml
:
[test.validator]
deactivate_feature = ["GDH5TVdbTPUpRnXaRyQqiKUa7uZAbZ28Q2N9bhbKoMLm", "zkiTNuzBKxrCLMKehzuQeKZyLtX2yvFcEKMML8nExU8"]
Crate and package compatibility
Using non-matching versions of anchor-cli
, anchor-lang
, and @coral-xyz/anchor
can result in unexpected behavior. In this release, you'll get a warning if any of them don't match.
Explicit overflow-checks
flag
overflow-checks
flag is implicitly disabled by default. Anchor workspaces that are crated with anchor init
have this flag enabled, however, Anchor doesn't do any checks for it after the initial workspace creation.
With this release, overflow-checks
in the workspace Cargo.toml
need to be specified. Note that "specified" does not mean enabled, as you can also disable it, but you need to be explicit in doing so.
Wildcard pattern in Anchor.toml
workspace.members
and workspace.exclude
now supports simple wildcard pattern:
[workspace]
members = ["programs/*"]
Note that the support is limited to this simple wildcard pattern, and more complex globs are not currently supported.
cargo build-sbf
is now the default
Before this release, anchor build
used cargo build-bpf
to build programs, however, because it is deprecated, anchor build
now defaults to cargo build-sbf
.
To preserve the old behavior, you can use:
anchor build --arch bpf
Run multiple commands in scripts
Scripts in Anchor.toml
now supports running multiple commands:
[scripts]
test-all = "cargo test && yarn run ts-mocha tests/**/*.ts"
This script would run both cargo
and yarn
commands:
anchor run test-all
Test only a specified program
A single program can be tested in a multi program workspace with the --program-name
(-p
) argument:
anchor test --program-name example
This builds and tests only the specified program.
Rust test template
A wild TypeScript test won't appear if you initialize your workspace with the new Rust test template:
anchor init --test-template rust
TypeScript
Account resolution
Account resolution refers to the ability of clients to resolve accounts without having to manually specify them when sending transactions.
There are too many changes to the account resolution logic in the TS library, however, we can skip a good chunk of them since they're mostly internal.
One change that affects everyone is the change in the accounts
method. Even though the TS library had some support for account resolution, it had no type-level support for it — all accounts were essentially typed as partial, and there was no way to know which accounts were resolvable and which were not.
There are now 3 methods to specify accounts with the transaction builder:
accounts
: This method is now fully type-safe based on the resolution fields in the IDL, making it much easier to only specify the accounts that are actually needed.accountsPartial
: This method keeps the old behavior and let's you specify all accounts including the resolvable ones.accountsStrict
: If you don't want to use account resolution and specify all accounts manually (unchanged).
This change is likely to result in errors in your existing .accounts()
calls. To fix, either change accounts
to accountsPartial
, or remove all accounts that can be resolved from the IDL. For example:
- await program.methods
- .init()
- .accounts({
- pda: ...,
- signer: ...,
- systemProgram: ...,
- })
- .rpc();
+ await program.methods.init().rpc();
Magic account names
Another change that affects most projects is the removal of "magic" account names. The TS library used to autofill common program and sysvar accounts based on their name, e.g. systemProgram
, however, this is no longer necessary with the introduction of the address
field (in the IDL) which is used to resolve all program and sysvars by default.
Case conversion
The internals of the TS library are filled with case conversion logic before making string comparison and this also forces other libraries who build on top of Anchor to do the same.
Along with making the IDL have consistent casing, TS library also has consistent casing (camelCase) in this release.
No more Program ID
programId
parameter of Program
is removed since the new IDL requires to store the program id in its address
field:
- new Program(idl, programId);
+ new Program(idl);
Optional provider options
opts
parameter of AnchorProvider
is now optional:
- new AnchorProvider(connection, wallet, {});
+ new AnchorProvider(connection, wallet);
Type changes
There are too many type changes to list here, especially the types that are related to the IDL. The new IDL types can be found here.
See the full list of notable changes in the CHANGELOG.