Compare commits

...

10 Commits

Author SHA1 Message Date
chalda d443d063ce
Merge c71b890a10 into 852fcc77be 2024-04-16 08:26:21 +02:00
acheron 852fcc77be
v0.30.0 (#2909) 2024-04-15 17:20:01 +02:00
acheron f74ea64ca6
idl: Rename crate name to `anchor-lang-idl` (#2908) 2024-04-15 13:56:53 +02:00
acheron 257b560109
lang: Return overflow error from `Lamports` trait operations (#2907) 2024-04-14 23:04:51 +02:00
acheron 95c4959287
ts: Add missing errors (#2906) 2024-04-14 00:00:41 +02:00
Bhargava Sai Macha a18d6caa6d
spl: Make `TokenAccount` and `Mint` `Copy` (#2904) 2024-04-13 23:30:02 +02:00
acheron 7356bd5afe
idl: Keep crate and `spec` version the same (#2901) 2024-04-13 01:06:45 +02:00
acheron 1f0bf0ee60
spl: Remove `solana-program` dependency (#2900) 2024-04-11 23:57:41 +02:00
Bhargava Sai Macha e3ced784ad
Add support for token extensions (#2789) 2024-04-11 22:49:13 +02:00
acheron ae26fd84bb
spl: Upgrade `mpl-token-metadata` to 4.1.2 (#2899) 2024-04-10 23:58:13 +02:00
162 changed files with 6389 additions and 318 deletions

View File

@ -388,6 +388,8 @@ jobs:
path: spl/token-wrapper
- cmd: cd tests/spl/transfer-hook && anchor test --skip-lint
path: spl/transfer-hook
- cmd: cd tests/spl/token-extensions && anchor test --skip-lint
path: spl/token-extensions
- cmd: cd tests/multisig && anchor test --skip-lint
path: tests/multisig
# - cmd: cd tests/lockup && anchor test --skip-lint

View File

@ -12,6 +12,14 @@ The minor version will be incremented upon a breaking change and the patch versi
### Features
### Fixes
### Breaking
## [0.30.0] - 2024-04-15
### Features
- cli: Allow force `init` and `new` ([#2698](https://github.com/coral-xyz/anchor/pull/2698)).
- cli: Add verifiable option when `deploy` ([#2705](https://github.com/coral-xyz/anchor/pull/2705)).
- cli: Add support for passing arguments to the underlying `solana program deploy` command with `anchor deploy` ([#2709](https://github.com/coral-xyz/anchor/pull/2709)).
@ -43,6 +51,8 @@ The minor version will be incremented upon a breaking change and the patch versi
- idl: Add `docs` field for constants ([#2887](https://github.com/coral-xyz/anchor/pull/2887)).
- idl: Store deployment addresses for other clusters ([#2892](https://github.com/coral-xyz/anchor/pull/2892)).
- lang: Add `Event` utility type to get events from bytes ([#2897](https://github.com/coral-xyz/anchor/pull/2897)).
- lang, spl: Add support for [token extensions](https://solana.com/solutions/token-extensions) ([#2789](https://github.com/coral-xyz/anchor/pull/2789)).
- lang: Return overflow error from `Lamports` trait operations ([#2907](https://github.com/coral-xyz/anchor/pull/2907)).
### Fixes
@ -69,6 +79,9 @@ The minor version will be incremented upon a breaking change and the patch versi
- client: Fix `parse_logs_response` to prevent panics when more than 1 outer instruction exists in logs ([#2856](https://github.com/coral-xyz/anchor/pull/2856)).
- avm, cli: Fix `stdsimd` feature compilation error from `ahash` when installing the CLI using newer Rust versions ([#2867](https://github.com/coral-xyz/anchor/pull/2867)).
- spl: Fix not being able to deserialize newer token 2022 extensions ([#2876](https://github.com/coral-xyz/anchor/pull/2876)).
- spl: Remove `solana-program` dependency ([#2900](https://github.com/coral-xyz/anchor/pull/2900)).
- spl: Make `TokenAccount` and ` Mint` `Copy` ([#2904](https://github.com/coral-xyz/anchor/pull/2904)).
- ts: Add missing errors ([#2906](https://github.com/coral-xyz/anchor/pull/2906)).
### Breaking

82
Cargo.lock generated
View File

@ -119,7 +119,7 @@ checksum = "6b2d54853319fd101b8dd81de382bcbf3e03410a64d8928bbee85a3e7dcde483"
[[package]]
name = "anchor-attribute-access-control"
version = "0.29.0"
version = "0.30.0"
dependencies = [
"anchor-syn",
"proc-macro2",
@ -129,7 +129,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-account"
version = "0.29.0"
version = "0.30.0"
dependencies = [
"anchor-syn",
"bs58 0.5.0",
@ -140,7 +140,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-constant"
version = "0.29.0"
version = "0.30.0"
dependencies = [
"anchor-syn",
"quote",
@ -149,7 +149,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-error"
version = "0.29.0"
version = "0.30.0"
dependencies = [
"anchor-syn",
"quote",
@ -158,7 +158,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-event"
version = "0.29.0"
version = "0.30.0"
dependencies = [
"anchor-syn",
"proc-macro2",
@ -168,9 +168,9 @@ dependencies = [
[[package]]
name = "anchor-attribute-program"
version = "0.29.0"
version = "0.30.0"
dependencies = [
"anchor-idl",
"anchor-lang-idl",
"anchor-syn",
"anyhow",
"bs58 0.5.0",
@ -183,11 +183,11 @@ dependencies = [
[[package]]
name = "anchor-cli"
version = "0.29.0"
version = "0.30.0"
dependencies = [
"anchor-client",
"anchor-idl",
"anchor-lang",
"anchor-lang-idl",
"anyhow",
"base64 0.21.7",
"bincode",
@ -219,7 +219,7 @@ dependencies = [
[[package]]
name = "anchor-client"
version = "0.29.0"
version = "0.30.0"
dependencies = [
"anchor-lang",
"anyhow",
@ -236,7 +236,7 @@ dependencies = [
[[package]]
name = "anchor-derive-accounts"
version = "0.29.0"
version = "0.30.0"
dependencies = [
"anchor-syn",
"quote",
@ -245,7 +245,7 @@ dependencies = [
[[package]]
name = "anchor-derive-serde"
version = "0.29.0"
version = "0.30.0"
dependencies = [
"anchor-syn",
"borsh-derive-internal 0.10.3",
@ -256,27 +256,16 @@ dependencies = [
[[package]]
name = "anchor-derive-space"
version = "0.29.0"
version = "0.30.0"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "anchor-idl"
version = "0.29.0"
dependencies = [
"anchor-syn",
"anyhow",
"regex",
"serde",
"serde_json",
]
[[package]]
name = "anchor-lang"
version = "0.29.0"
version = "0.30.0"
dependencies = [
"anchor-attribute-access-control",
"anchor-attribute-account",
@ -287,7 +276,7 @@ dependencies = [
"anchor-derive-accounts",
"anchor-derive-serde",
"anchor-derive-space",
"anchor-idl",
"anchor-lang-idl",
"arrayref",
"base64 0.21.7",
"bincode",
@ -298,24 +287,37 @@ dependencies = [
"thiserror",
]
[[package]]
name = "anchor-lang-idl"
version = "0.1.0"
dependencies = [
"anchor-syn",
"anyhow",
"regex",
"serde",
"serde_json",
]
[[package]]
name = "anchor-spl"
version = "0.29.0"
version = "0.30.0"
dependencies = [
"anchor-lang",
"borsh 0.10.3",
"mpl-token-metadata",
"serum_dex",
"solana-program",
"spl-associated-token-account 3.0.2",
"spl-memo",
"spl-pod 0.2.2",
"spl-token 4.0.0",
"spl-token-2022 3.0.2",
"spl-token-group-interface 0.2.3",
"spl-token-metadata-interface 0.3.3",
]
[[package]]
name = "anchor-syn"
version = "0.29.0"
version = "0.30.0"
dependencies = [
"anyhow",
"bs58 0.5.0",
@ -661,7 +663,7 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "avm"
version = "0.29.0"
version = "0.30.0"
dependencies = [
"anyhow",
"cargo_toml",
@ -2530,9 +2532,9 @@ dependencies = [
[[package]]
name = "mpl-token-metadata"
version = "3.1.0"
version = "4.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "177204bbe7486b22ac35af2c91a82630f830a6ddd3392651aefde1ef346aba3d"
checksum = "caf0f61b553e424a6234af1268456972ee66c2222e1da89079242251fa7479e5"
dependencies = [
"borsh 0.10.3",
"num-derive 0.3.3",
@ -4779,9 +4781,9 @@ dependencies = [
[[package]]
name = "spl-pod"
version = "0.1.0"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2881dddfca792737c0706fa0175345ab282b1b0879c7d877bad129645737c079"
checksum = "85a5db7e4efb1107b0b8e52a13f035437cdcb36ef99c58f6d467f089d9b2915a"
dependencies = [
"borsh 0.10.3",
"bytemuck",
@ -4862,7 +4864,7 @@ dependencies = [
"bytemuck",
"solana-program",
"spl-discriminator 0.1.0",
"spl-pod 0.1.0",
"spl-pod 0.1.1",
"spl-program-error 0.3.0",
"spl-type-length-value 0.3.0",
]
@ -4926,7 +4928,7 @@ dependencies = [
"solana-security-txt",
"solana-zk-token-sdk",
"spl-memo",
"spl-pod 0.1.0",
"spl-pod 0.1.1",
"spl-token 4.0.0",
"spl-token-group-interface 0.1.0",
"spl-token-metadata-interface 0.2.0",
@ -4968,7 +4970,7 @@ dependencies = [
"bytemuck",
"solana-program",
"spl-discriminator 0.1.0",
"spl-pod 0.1.0",
"spl-pod 0.1.1",
"spl-program-error 0.3.0",
]
@ -4994,7 +4996,7 @@ dependencies = [
"borsh 0.10.3",
"solana-program",
"spl-discriminator 0.1.0",
"spl-pod 0.1.0",
"spl-pod 0.1.1",
"spl-program-error 0.3.0",
"spl-type-length-value 0.3.0",
]
@ -5023,7 +5025,7 @@ dependencies = [
"bytemuck",
"solana-program",
"spl-discriminator 0.1.0",
"spl-pod 0.1.0",
"spl-pod 0.1.1",
"spl-program-error 0.3.0",
"spl-tlv-account-resolution 0.5.1",
"spl-type-length-value 0.3.0",
@ -5054,7 +5056,7 @@ dependencies = [
"bytemuck",
"solana-program",
"spl-discriminator 0.1.0",
"spl-pod 0.1.0",
"spl-pod 0.1.1",
"spl-program-error 0.3.0",
]

View File

@ -1 +1 @@
0.29.0
0.30.0

View File

@ -1,6 +1,6 @@
[package]
name = "avm"
version = "0.29.0"
version = "0.30.0"
rust-version = "1.60"
edition = "2021"

View File

@ -16,6 +16,18 @@ The programs and their tests are located in [/tests/bench](https://github.com/co
Solana version: 1.18.8
| Program | Binary Size | - |
| ------- | ----------- | --- |
| bench | 791,008 | - |
### Notable changes
---
## [0.30.0]
Solana version: 1.18.8
| Program | Binary Size | - |
| ------- | ----------- | ---------------------- |
| bench | 791,008 | 🔴 **+47,952 (6.45%)** |

View File

@ -16,6 +16,104 @@ The programs and their tests are located in [/tests/bench](https://github.com/co
Solana version: 1.18.8
| Instruction | Compute Units | - |
| --------------------------- | ------------- | --- |
| accountInfo1 | 601 | - |
| accountInfo2 | 923 | - |
| accountInfo4 | 1,583 | - |
| accountInfo8 | 2,975 | - |
| accountEmptyInit1 | 5,034 | - |
| accountEmpty1 | 652 | - |
| accountEmptyInit2 | 9,687 | - |
| accountEmpty2 | 1,016 | - |
| accountEmptyInit4 | 18,501 | - |
| accountEmpty4 | 1,737 | - |
| accountEmptyInit8 | 36,169 | - |
| accountEmpty8 | 3,186 | - |
| accountSizedInit1 | 5,106 | - |
| accountSized1 | 668 | - |
| accountSizedInit2 | 9,828 | - |
| accountSized2 | 1,046 | - |
| accountSizedInit4 | 18,837 | - |
| accountSized4 | 1,807 | - |
| accountSizedInit8 | 36,761 | - |
| accountSized8 | 3,326 | - |
| accountUnsizedInit1 | 5,199 | - |
| accountUnsized1 | 702 | - |
| accountUnsizedInit2 | 10,078 | - |
| accountUnsized2 | 1,116 | - |
| accountUnsizedInit4 | 19,259 | - |
| accountUnsized4 | 1,953 | - |
| accountUnsizedInit8 | 37,331 | - |
| accountUnsized8 | 3,626 | - |
| boxedAccountEmptyInit1 | 5,064 | - |
| boxedAccountEmpty1 | 671 | - |
| boxedAccountEmptyInit2 | 9,721 | - |
| boxedAccountEmpty2 | 1,052 | - |
| boxedAccountEmptyInit4 | 18,582 | - |
| boxedAccountEmpty4 | 1,811 | - |
| boxedAccountEmptyInit8 | 36,329 | - |
| boxedAccountEmpty8 | 3,357 | - |
| boxedAccountSizedInit1 | 5,119 | - |
| boxedAccountSized1 | 686 | - |
| boxedAccountSizedInit2 | 9,845 | - |
| boxedAccountSized2 | 1,085 | - |
| boxedAccountSizedInit4 | 18,825 | - |
| boxedAccountSized4 | 1,874 | - |
| boxedAccountSizedInit8 | 36,824 | - |
| boxedAccountSized8 | 3,490 | - |
| boxedAccountUnsizedInit1 | 5,207 | - |
| boxedAccountUnsized1 | 721 | - |
| boxedAccountUnsizedInit2 | 10,015 | - |
| boxedAccountUnsized2 | 1,157 | - |
| boxedAccountUnsizedInit4 | 19,160 | - |
| boxedAccountUnsized4 | 2,019 | - |
| boxedAccountUnsizedInit8 | 37,496 | - |
| boxedAccountUnsized8 | 3,776 | - |
| boxedInterfaceAccountMint1 | 1,372 | - |
| boxedInterfaceAccountMint2 | 2,293 | - |
| boxedInterfaceAccountMint4 | 4,121 | - |
| boxedInterfaceAccountMint8 | 7,811 | - |
| boxedInterfaceAccountToken1 | 2,056 | - |
| boxedInterfaceAccountToken2 | 3,660 | - |
| boxedInterfaceAccountToken4 | 6,858 | - |
| boxedInterfaceAccountToken8 | 13,284 | - |
| interfaceAccountMint1 | 1,472 | - |
| interfaceAccountMint2 | 2,631 | - |
| interfaceAccountMint4 | 4,951 | - |
| interfaceAccountMint8 | 9,588 | - |
| interfaceAccountToken1 | 2,130 | - |
| interfaceAccountToken2 | 3,928 | - |
| interfaceAccountToken4 | 7,521 | - |
| interface1 | 600 | - |
| interface2 | 745 | - |
| interface4 | 1,033 | - |
| interface8 | 1,616 | - |
| program1 | 596 | - |
| program2 | 737 | - |
| program4 | 1,019 | - |
| program8 | 1,584 | - |
| signer1 | 580 | - |
| signer2 | 872 | - |
| signer4 | 1,454 | - |
| signer8 | 2,618 | - |
| systemAccount1 | 592 | - |
| systemAccount2 | 894 | - |
| systemAccount4 | 1,497 | - |
| systemAccount8 | 2,707 | - |
| uncheckedAccount1 | 563 | - |
| uncheckedAccount2 | 836 | - |
| uncheckedAccount4 | 1,378 | - |
| uncheckedAccount8 | 2,468 | - |
### Notable changes
---
## [0.30.0]
Solana version: 1.18.8
| Instruction | Compute Units | - |
| --------------------------- | ------------- | ---------------------- |
| accountInfo1 | 601 | 🟢 **-94 (13.53%)** |

View File

@ -16,6 +16,104 @@ The programs and their tests are located in [/tests/bench](https://github.com/co
Solana version: 1.18.8
| Instruction | Stack Memory | - |
| ------------------------------ | ------------ | --- |
| account_info1 | 144 | - |
| account_info2 | 144 | - |
| account_info4 | 144 | - |
| account_info8 | 144 | - |
| account_empty_init1 | 144 | - |
| account_empty_init2 | 144 | - |
| account_empty_init4 | 192 | - |
| account_empty_init8 | 224 | - |
| account_empty1 | 144 | - |
| account_empty2 | 144 | - |
| account_empty4 | 144 | - |
| account_empty8 | 144 | - |
| account_sized_init1 | 176 | - |
| account_sized_init2 | 192 | - |
| account_sized_init4 | 224 | - |
| account_sized_init8 | 288 | - |
| account_sized1 | 144 | - |
| account_sized2 | 144 | - |
| account_sized4 | 144 | - |
| account_sized8 | 144 | - |
| account_unsized_init1 | 192 | - |
| account_unsized_init2 | 224 | - |
| account_unsized_init4 | 288 | - |
| account_unsized_init8 | 416 | - |
| account_unsized1 | 144 | - |
| account_unsized2 | 144 | - |
| account_unsized4 | 144 | - |
| account_unsized8 | 144 | - |
| boxed_account_empty_init1 | 144 | - |
| boxed_account_empty_init2 | 144 | - |
| boxed_account_empty_init4 | 192 | - |
| boxed_account_empty_init8 | 224 | - |
| boxed_account_empty1 | 144 | - |
| boxed_account_empty2 | 144 | - |
| boxed_account_empty4 | 144 | - |
| boxed_account_empty8 | 144 | - |
| boxed_account_sized_init1 | 144 | - |
| boxed_account_sized_init2 | 144 | - |
| boxed_account_sized_init4 | 192 | - |
| boxed_account_sized_init8 | 224 | - |
| boxed_account_sized1 | 144 | - |
| boxed_account_sized2 | 144 | - |
| boxed_account_sized4 | 144 | - |
| boxed_account_sized8 | 144 | - |
| boxed_account_unsized_init1 | 144 | - |
| boxed_account_unsized_init2 | 144 | - |
| boxed_account_unsized_init4 | 192 | - |
| boxed_account_unsized_init8 | 224 | - |
| boxed_account_unsized1 | 144 | - |
| boxed_account_unsized2 | 144 | - |
| boxed_account_unsized4 | 144 | - |
| boxed_account_unsized8 | 144 | - |
| boxed_interface_account_mint1 | 144 | - |
| boxed_interface_account_mint2 | 144 | - |
| boxed_interface_account_mint4 | 144 | - |
| boxed_interface_account_mint8 | 144 | - |
| boxed_interface_account_token1 | 144 | - |
| boxed_interface_account_token2 | 144 | - |
| boxed_interface_account_token4 | 144 | - |
| boxed_interface_account_token8 | 144 | - |
| interface_account_mint1 | 144 | - |
| interface_account_mint2 | 144 | - |
| interface_account_mint4 | 144 | - |
| interface_account_mint8 | 144 | - |
| interface_account_token1 | 144 | - |
| interface_account_token2 | 144 | - |
| interface_account_token4 | 144 | - |
| interface1 | 144 | - |
| interface2 | 144 | - |
| interface4 | 144 | - |
| interface8 | 144 | - |
| program1 | 144 | - |
| program2 | 144 | - |
| program4 | 144 | - |
| program8 | 144 | - |
| signer1 | 144 | - |
| signer2 | 144 | - |
| signer4 | 144 | - |
| signer8 | 144 | - |
| system_account1 | 144 | - |
| system_account2 | 144 | - |
| system_account4 | 144 | - |
| system_account8 | 144 | - |
| unchecked_account1 | 144 | - |
| unchecked_account2 | 144 | - |
| unchecked_account4 | 144 | - |
| unchecked_account8 | 144 | - |
### Notable changes
---
## [0.30.0]
Solana version: 1.18.8
| Instruction | Stack Memory | - |
| ------------------------------ | ------------ | ------------------- |
| account_info1 | 144 | 🔴 **+16 (12.50%)** |

View File

@ -1,6 +1,6 @@
[package]
name = "anchor-cli"
version = "0.29.0"
version = "0.30.0"
authors = ["Anchor Maintainers <accounts@200ms.io>"]
rust-version = "1.60"
edition = "2021"
@ -16,9 +16,9 @@ path = "src/bin/main.rs"
dev = []
[dependencies]
anchor-client = { path = "../client", version = "0.29.0" }
anchor-idl = { path = "../idl", features = ["build"], version = "0.29.0" }
anchor-lang = { path = "../lang", version = "0.29.0" }
anchor-client = { path = "../client", version = "0.30.0" }
anchor-lang-idl = { path = "../idl", features = ["build"], version = "0.1.0" }
anchor-lang = { path = "../lang", version = "0.30.0" }
anyhow = "1.0.32"
base64 = "0.21"
bincode = "1.3.3"

View File

@ -1,6 +1,6 @@
{
"name": "@coral-xyz/anchor-cli",
"version": "0.29.0",
"version": "0.30.0",
"description": "Anchor CLI tool",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {

View File

@ -1,6 +1,6 @@
use crate::is_hidden;
use anchor_client::Cluster;
use anchor_idl::types::Idl;
use anchor_lang_idl::types::Idl;
use anyhow::{anyhow, bail, Context, Error, Result};
use clap::{Parser, ValueEnum};
use dirs::home_dir;

View File

@ -6,9 +6,9 @@ use crate::config::{
DEFAULT_LEDGER_PATH, SHUTDOWN_WAIT, STARTUP_WAIT,
};
use anchor_client::Cluster;
use anchor_idl::types::{Idl, IdlArrayLen, IdlDefinedFields, IdlType, IdlTypeDefTy};
use anchor_lang::idl::{IdlAccount, IdlInstruction, ERASED_AUTHORITY};
use anchor_lang::{AccountDeserialize, AnchorDeserialize, AnchorSerialize};
use anchor_lang_idl::types::{Idl, IdlArrayLen, IdlDefinedFields, IdlType, IdlTypeDefTy};
use anyhow::{anyhow, Context, Result};
use checks::{check_anchor_version, check_overflow};
use clap::Parser;
@ -2609,7 +2609,7 @@ fn idl_build(
.path
}
};
let idl = anchor_idl::build::build_idl(
let idl = anchor_lang_idl::build::build_idl(
program_path,
cfg.features.resolution,
cfg.features.skip_lint || skip_lint,
@ -2655,7 +2655,7 @@ in `{path}`."#
));
}
anchor_idl::build::build_idl(
anchor_lang_idl::build::build_idl(
std::env::current_dir()?,
cfg.features.resolution,
cfg.features.skip_lint || skip_lint,

View File

@ -2,7 +2,7 @@ use crate::{
config::ProgramWorkspace, create_files, override_or_create_files, solidity_template, Files,
VERSION,
};
use anchor_idl::types::Idl;
use anchor_lang_idl::types::Idl;
use anyhow::Result;
use clap::{Parser, ValueEnum};
use heck::{ToLowerCamelCase, ToPascalCase, ToSnakeCase};

View File

@ -1,6 +1,6 @@
[package]
name = "anchor-client"
version = "0.29.0"
version = "0.30.0"
authors = ["Anchor Maintainers <accounts@200ms.io>"]
rust-version = "1.60"
edition = "2021"
@ -16,7 +16,7 @@ async = []
debug = []
[dependencies]
anchor-lang = { path = "../lang", version = "0.29.0" }
anchor-lang = { path = "../lang", version = "0.30.0" }
anyhow = "1"
futures = "0.3"
regex = "1"

View File

@ -50,14 +50,14 @@
//!
//! More examples can be found in [here].
//!
//! [here]: https://github.com/coral-xyz/anchor/tree/v0.29.0/client/example/src
//! [here]: https://github.com/coral-xyz/anchor/tree/v0.30.0/client/example/src
//!
//! # Features
//!
//! The client is blocking by default. To enable asynchronous client, add `async` feature:
//!
//! ```toml
//! anchor-client = { version = "0.29.0 ", features = ["async"] }
//! anchor-client = { version = "0.30.0 ", features = ["async"] }
//! ````
use anchor_lang::solana_program::hash::Hash;

View File

@ -2,7 +2,7 @@ WORKDIR=$(PWD)
#
# Anchor version.
#
ANCHOR_CLI=v0.29.0
ANCHOR_CLI=v0.30.0
#
# Solana toolchain.
#

View File

@ -24,7 +24,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-access-control"
version = "0.29.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf7d535e1381be3de2c0716c0a1c1e32ad9df1042cddcf7bc18d743569e53319"
dependencies = [
@ -38,7 +38,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-account"
version = "0.29.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3bcd731f21048a032be27c7791701120e44f3f6371358fc4261a7f716283d29"
dependencies = [
@ -53,7 +53,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-constant"
version = "0.29.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1be64a48e395fe00b8217287f226078be2cf32dae42fdf8a885b997945c3d28"
dependencies = [
@ -64,7 +64,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-error"
version = "0.29.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38ea6713d1938c0da03656ff8a693b17dc0396da66d1ba320557f07e86eca0d4"
dependencies = [
@ -76,7 +76,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-event"
version = "0.29.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d401f11efb3644285685f8339829a9786d43ed7490bb1699f33c478d04d5a582"
dependencies = [
@ -89,7 +89,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-interface"
version = "0.29.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6700a6f5c888a9c33fe8afc0c64fd8575fa28d05446037306d0f96102ae4480"
dependencies = [
@ -103,7 +103,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-program"
version = "0.29.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ad769993b5266714e8939e47fbdede90e5c030333c7522d99a4d4748cf26712"
dependencies = [
@ -116,7 +116,7 @@ dependencies = [
[[package]]
name = "anchor-attribute-state"
version = "0.29.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e677fae4a016a554acdd0e3b7f178d3acafaa7e7ffac6b8690cf4e171f1c116"
dependencies = [
@ -129,7 +129,7 @@ dependencies = [
[[package]]
name = "anchor-derive-accounts"
version = "0.29.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "340beef6809d1c3fcc7ae219153d981e95a8a277ff31985bd7050e32645dc9a8"
dependencies = [
@ -142,7 +142,7 @@ dependencies = [
[[package]]
name = "anchor-lang"
version = "0.29.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "662ceafe667448ee4199a4be2ee83b6bb76da28566eee5cea05f96ab38255af8"
dependencies = [
@ -166,7 +166,7 @@ dependencies = [
[[package]]
name = "anchor-syn"
version = "0.29.0"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0418bcb5daac3b8cb1b60d8fdb1d468ca36f5509f31fb51179326fae1028fdcc"
dependencies = [

View File

@ -16,6 +16,6 @@ cpi = ["no-entrypoint"]
default = []
[dependencies]
anchor-lang = "=0.29.0"
anchor-lang = "=0.30.0"
num-traits = "0.2"
num-derive = "0.3"

View File

@ -28,6 +28,7 @@ const navigation = [
title: 'Release Notes',
links: [
{ title: '0.29.0', href: '/release-notes/0.29.0' },
{ title: '0.30.0', href: '/release-notes/0.30.0' },
{ title: 'CHANGELOG', href: '/release-notes/changelog' },
],
},

View File

@ -63,7 +63,7 @@ Anchor binaries are available via an NPM package [`@coral-xyz/anchor-cli`](https
We can also use Cargo to install the CLI directly. Make sure that the `--tag` argument uses the version you want (the version here is just an example).
```shell
cargo install --git https://github.com/coral-xyz/anchor --tag v0.29.0 anchor-cli --locked
cargo install --git https://github.com/coral-xyz/anchor --tag v0.30.0 anchor-cli --locked
```
On Linux systems you may need to install additional dependencies if cargo install fails. On Ubuntu,

View File

@ -200,6 +200,6 @@ Override toolchain data in the workspace similar to [`rust-toolchain.toml`](http
```toml
[toolchain]
anchor_version = "0.29.0" # `anchor-cli` version to use(requires `avm`)
solana_version = "1.17.0" # Solana version to use(applies to all Solana tools)
anchor_version = "0.30.0" # `anchor-cli` version to use(requires `avm`)
solana_version = "1.18.8" # Solana version to use(applies to all Solana tools)
```

View File

@ -35,8 +35,8 @@ An example `Anchor.toml` config looks as follows,
```toml
[toolchain]
anchor_version = "0.29.0"
solana_version = "1.17.0"
anchor_version = "0.30.0"
solana_version = "1.18.8"
[workspace]
members = ["programs/multisig"]

View File

@ -37,10 +37,10 @@ If the program has an IDL, it will also check the IDL deployed on chain matches.
## Images
A docker image for each version of Anchor is published on [Docker Hub](https://hub.docker.com/r/backpackapp/build). They are tagged in the form `backpackapp/build:<version>`. For example, to get the image for Anchor `v0.29.0` one can run
A docker image for each version of Anchor is published on [Docker Hub](https://hub.docker.com/r/backpackapp/build). They are tagged in the form `backpackapp/build:<version>`. For example, to get the image for Anchor `v0.30.0` one can run
```shell
docker pull backpackapp/build:v0.29.0
docker pull backpackapp/build:v0.30.0
```
## Removing an Image

View File

@ -0,0 +1,327 @@
---
title: Release Notes 0.30.0
description: Anchor - 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](https://github.com/coral-xyz/anchor/blob/v0.30.0/CHANGELOG.md#0300---2024-04-15).
---
## How to upgrade
1. Update `avm`:
```sh
cargo install --git https://github.com/coral-xyz/anchor --tag v0.30.0 avm --locked
```
2. Update `anchor-cli`:
```sh
avm install latest
```
3. Update Anchor crate(s) to `0.30.0`. Optionally, run `cargo update` to update other dependencies to the latest compatible versions.
4. 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](https://github.com/coral-xyz/anchor/pull/2824) 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:
```rs
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](https://en.wikipedia.org/wiki/Dependency_hell). Check out [this](https://github.com/coral-xyz/anchor/blob/0.30.0/tests/declare-program/programs/declare-program/src/lib.rs) example for on-chain CPI usage.
For more information, see the macro's [documentation](https://docs.rs/anchor-lang/0.30.0/anchor_lang/macro.declare_program.html).
### Token extensions
#### Constraints
There are new account constraints for [Token Extensions (Token 2022)](https://solana.com/solutions/token-extensions):
- `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](https://github.com/coral-xyz/anchor/blob/v0.30.0/tests/spl/token-extensions/programs/token-extensions/src/instructions.rs) 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`
```rs
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`](https://github.com/near/borsh-rs/blob/79097e3c71ae469a101b4828457792bcf8be7f5f/borsh/src/ser/mod.rs#L47-L51) implementation, which is used in events, CPI, and return data, heap allocates [1024](https://github.com/near/borsh-rs/blob/79097e3c71ae469a101b4828457792bcf8be7f5f/borsh/src/ser/mod.rs#L19) 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`:
```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`](https://doc.rust-lang.org/cargo/reference/profiles.html#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:
```toml
[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:
```toml
[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:
```diff
- 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:
```diff
- new Program(idl, programId);
+ new Program(idl);
```
### Optional provider options
`opts` parameter of `AnchorProvider` is now optional:
```diff
- 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](https://github.com/coral-xyz/anchor/blob/v0.30.0/ts/packages/anchor/src/idl.ts).
---
See the full list of notable changes in the [CHANGELOG](https://github.com/coral-xyz/anchor/blob/v0.30.0/CHANGELOG.md#0300---2024-04-15).

View File

@ -8,6 +8,96 @@ The minor version will be incremented upon a breaking change and the patch versi
---
## [0.30.0] - 2024-04-15
### Features
- cli: Allow force `init` and `new` ([#2698](https://github.com/coral-xyz/anchor/pull/2698)).
- cli: Add verifiable option when `deploy` ([#2705](https://github.com/coral-xyz/anchor/pull/2705)).
- cli: Add support for passing arguments to the underlying `solana program deploy` command with `anchor deploy` ([#2709](https://github.com/coral-xyz/anchor/pull/2709)).
- lang: Add `InstructionData::write_to` implementation ([#2733](https://github.com/coral-xyz/anchor/pull/2733)).
- lang: Add `#[interface(..)]` attribute for instruction discriminator overrides ([#2728](https://github.com/coral-xyz/anchor/pull/2728)).
- ts: Add `.interface(..)` method for instruction discriminator overrides ([#2728](https://github.com/coral-xyz/anchor/pull/2728)).
- cli: Check `anchor-lang` and CLI version compatibility ([#2753](https://github.com/coral-xyz/anchor/pull/2753)).
- ts: Add missing IDL PDA seed types ([#2752](https://github.com/coral-xyz/anchor/pull/2752)).
- cli: `idl close` accepts optional `--idl-address` parameter ([#2760](https://github.com/coral-xyz/anchor/pull/2760)).
- cli: Add support for simple wildcard patterns in Anchor.toml's `workspace.members` and `workspace.exclude`. ([#2785](https://github.com/coral-xyz/anchor/pull/2785)).
- cli: Add `--test-template` option for `init` command ([#2805](https://github.com/coral-xyz/anchor/pull/2805)).
- cli: `anchor test` is able to run multiple commands ([#2799](https://github.com/coral-xyz/anchor/pull/2799)).
- cli: Check `@coral-xyz/anchor` package and CLI version compatibility ([#2813](https://github.com/coral-xyz/anchor/pull/2813)).
- cli: Accept package name as program name ([#2816](https://github.com/coral-xyz/anchor/pull/2816)).
- cli: Add ability to build and test only a specified program ([#2823](https://github.com/coral-xyz/anchor/pull/2823)).
- idl: Add new IDL spec ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- idl: Add support for `repr`s ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- idl: Add support for expression evaluation ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- idl: Add support for using external types when generating the IDL ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- idl, ts: Add unit and tuple struct support ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- idl, ts: Add generics support ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- ts: Add `accountsPartial` method to keep the old `accounts` method behavior ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- ts: Make `opts` parameter of `AnchorProvider` constructor optional ([#2843](https://github.com/coral-xyz/anchor/pull/2843)).
- cli: Add `--no-idl` flag to the `build` command ([#2847](https://github.com/coral-xyz/anchor/pull/2847)).
- cli: Add priority fees to idl commands ([#2845](https://github.com/coral-xyz/anchor/pull/2845)).
- ts: Add `prepend` option to MethodBuilder `preInstructions` method ([#2863](https://github.com/coral-xyz/anchor/pull/2863)).
- lang: Add `declare_program!` macro ([#2857](https://github.com/coral-xyz/anchor/pull/2857)).
- cli: Add `deactivate_feature` flag to `solana-test-validator` config in Anchor.toml ([#2872](https://github.com/coral-xyz/anchor/pull/2872)).
- idl: Add `docs` field for constants ([#2887](https://github.com/coral-xyz/anchor/pull/2887)).
- idl: Store deployment addresses for other clusters ([#2892](https://github.com/coral-xyz/anchor/pull/2892)).
- lang: Add `Event` utility type to get events from bytes ([#2897](https://github.com/coral-xyz/anchor/pull/2897)).
- lang, spl: Add support for [token extensions](https://solana.com/solutions/token-extensions) ([#2789](https://github.com/coral-xyz/anchor/pull/2789)).
- lang: Return overflow error from `Lamports` trait operations ([#2907](https://github.com/coral-xyz/anchor/pull/2907)).
### Fixes
- syn: Add missing `new_from_array` method to `Hash` ([#2682](https://github.com/coral-xyz/anchor/pull/2682)).
- cli: Switch to Cargo feature resolver(`resolver = "2"`) ([#2676](https://github.com/coral-xyz/anchor/pull/2676)).
- cli: Fix using user specific path for `provider.wallet` in `Anchor.toml` ([#2696](https://github.com/coral-xyz/anchor/pull/2696)).
- syn: Fix IDL constant seeds parsing ([#2699](https://github.com/coral-xyz/anchor/pull/2699)).
- cli: Display errors if toolchain override restoration fails ([#2700](https://github.com/coral-xyz/anchor/pull/2700)).
- cli: Fix commit based `anchor_version` override ([#2704](https://github.com/coral-xyz/anchor/pull/2704)).
- spl: Fix compilation with `shmem` feature enabled ([#2722](https://github.com/coral-xyz/anchor/pull/2722)).
- cli: Localhost default test validator address changes from `localhost` to `127.0.0.1`, NodeJS 17 IP resolution changes for IPv6 ([#2725](https://github.com/coral-xyz/anchor/pull/2725)).
- lang: Eliminate temporary Vec allocations when serializing data with discriminant and set the default capacity to 256 bytes ([#2691](https://github.com/coral-xyz/anchor/pull/2691)).
- lang: Allow custom lifetime in Accounts structure ([#2741](https://github.com/coral-xyz/anchor/pull/2741)).
- lang: Remove `try_to_vec` usage while setting the return data in order to reduce heap memory usage ([#2744](https://github.com/coral-xyz/anchor/pull/2744))
- cli: Show installation progress if Solana tools are not installed when using toolchain overrides ([#2757](https://github.com/coral-xyz/anchor/pull/2757)).
- ts: Fix formatting enums ([#2763](https://github.com/coral-xyz/anchor/pull/2763)).
- cli: Fix `migrate` command not working without global `ts-node` installation ([#2767](https://github.com/coral-xyz/anchor/pull/2767)).
- client, lang, spl, syn: Enable all features for docs.rs build ([#2774](https://github.com/coral-xyz/anchor/pull/2774)).
- ts: Fix construction of field layouts for type aliased instruction arguments ([#2821](https://github.com/coral-xyz/anchor/pull/2821))
- idl: Fix IDL ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- idl, ts: Make casing consistent ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- ts: Fix not being able to use numbers in instruction, account, or event names in some cases due to case conversion ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- cli: Fix excessive test validator requests ([#2828](https://github.com/coral-xyz/anchor/pull/2828)).
- client: Fix `parse_logs_response` to prevent panics when more than 1 outer instruction exists in logs ([#2856](https://github.com/coral-xyz/anchor/pull/2856)).
- avm, cli: Fix `stdsimd` feature compilation error from `ahash` when installing the CLI using newer Rust versions ([#2867](https://github.com/coral-xyz/anchor/pull/2867)).
- spl: Fix not being able to deserialize newer token 2022 extensions ([#2876](https://github.com/coral-xyz/anchor/pull/2876)).
- spl: Remove `solana-program` dependency ([#2900](https://github.com/coral-xyz/anchor/pull/2900)).
- spl: Make `TokenAccount` and ` Mint` `Copy` ([#2904](https://github.com/coral-xyz/anchor/pull/2904)).
- ts: Add missing errors ([#2906](https://github.com/coral-xyz/anchor/pull/2906)).
### Breaking
- cli: Make `cargo build-sbf` the default build command ([#2694](https://github.com/coral-xyz/anchor/pull/2694)).
- cli: Require explicit `overflow-checks` flag ([#2716](https://github.com/coral-xyz/anchor/pull/2716)).
- ts: Remove `anchor-deprecated-state` feature ([#2717](https://github.com/coral-xyz/anchor/pull/2717)).
- lang: Remove `CLOSED_ACCOUNT_DISCRIMINATOR` ([#2726](https://github.com/coral-xyz/anchor/pull/2726)).
- lang: Make bumps of optional accounts `Option<u8>` rather than `u8` ([#2730](https://github.com/coral-xyz/anchor/pull/2730)).
- spl: Remove `shared-memory` program ([#2747](https://github.com/coral-xyz/anchor/pull/2747)).
- ts: Remove `associated`, `account.associated` and `account.associatedAddress` methods ([#2749](https://github.com/coral-xyz/anchor/pull/2749)).
- cli: `idl upgrade` command closes the IDL buffer account ([#2760](https://github.com/coral-xyz/anchor/pull/2760)).
- cli: Remove `--jest` option from the `init` command ([#2805](https://github.com/coral-xyz/anchor/pull/2805)).
- cli: Require `idl-build` feature in program `Cargo.toml` ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- cli: Rename `seeds` feature to `resolution` and make it enabled by default ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- cli: Remove `idl parse` command ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- idl: Change IDL spec ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- syn: Remove `idl-parse` and `seeds` features ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- ts: Change `accounts` method to no longer accept resolvable accounts ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- ts: `Program` instances use camelCase for everything ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- ts: Remove discriminator functions ([#2824](https://github.com/coral-xyz/anchor/pull/2824)).
- ts: Remove `programId` parameter of the `Program` constructor ([#2864](https://github.com/coral-xyz/anchor/pull/2864)).
- idl, syn: Move IDL types from the `anchor-syn` crate to the new IDL crate ([#2882](https://github.com/coral-xyz/anchor/pull/2882)).
- idl: Add `#[non_exhaustive]` to IDL enums ([#2890](https://github.com/coral-xyz/anchor/pull/2890)).
## [0.29.0] - 2023-10-16
### Features

View File

@ -1,6 +1,6 @@
{
"name": "basic-0",
"version": "0.29.0",
"version": "0.30.0",
"license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {

View File

@ -1,6 +1,6 @@
{
"name": "basic-1",
"version": "0.29.0",
"version": "0.30.0",
"license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {

View File

@ -1,6 +1,6 @@
{
"name": "basic-2",
"version": "0.29.0",
"version": "0.30.0",
"license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {

View File

@ -1,6 +1,6 @@
{
"name": "basic-3",
"version": "0.29.0",
"version": "0.30.0",
"license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {

View File

@ -1,6 +1,6 @@
{
"name": "basic-4",
"version": "0.29.0",
"version": "0.30.0",
"license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {

View File

@ -1,6 +1,6 @@
{
"name": "basic-5",
"version": "0.29.0",
"version": "0.30.0",
"license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {

View File

@ -1,6 +1,6 @@
[package]
name = "anchor-idl"
version = "0.29.0"
name = "anchor-lang-idl"
version = "0.1.0"
authors = ["Anchor Maintainers <accounts@200ms.io>"]
repository = "https://github.com/coral-xyz/anchor"
rust-version = "1.60"
@ -21,5 +21,5 @@ serde = { version = "1", features = ["derive"] }
serde_json = "1"
# `build` feature only
anchor-syn = { path = "../lang/syn", version = "0.29.0", optional = true }
anchor-syn = { path = "../lang/syn", version = "0.30.0", optional = true }
regex = { version = "1", optional = true }

View File

@ -4,7 +4,7 @@ use anyhow::anyhow;
use serde::{Deserialize, Serialize};
/// IDL specification Semantic Version
pub const IDL_SPEC: &str = "0.1.0";
pub const IDL_SPEC: &str = env!("CARGO_PKG_VERSION");
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Idl {

View File

@ -1,6 +1,6 @@
[package]
name = "anchor-lang"
version = "0.29.0"
version = "0.30.0"
authors = ["Anchor Maintainers <accounts@200ms.io>"]
repository = "https://github.com/coral-xyz/anchor"
rust-version = "1.60"
@ -33,24 +33,24 @@ idl-build = [
"anchor-attribute-program/idl-build",
"anchor-derive-accounts/idl-build",
"anchor-derive-serde/idl-build",
"anchor-idl/build",
"anchor-lang-idl/build",
]
init-if-needed = ["anchor-derive-accounts/init-if-needed"]
interface-instructions = ["anchor-attribute-program/interface-instructions"]
[dependencies]
anchor-attribute-access-control = { path = "./attribute/access-control", version = "0.29.0" }
anchor-attribute-account = { path = "./attribute/account", version = "0.29.0" }
anchor-attribute-constant = { path = "./attribute/constant", version = "0.29.0" }
anchor-attribute-error = { path = "./attribute/error", version = "0.29.0" }
anchor-attribute-event = { path = "./attribute/event", version = "0.29.0" }
anchor-attribute-program = { path = "./attribute/program", version = "0.29.0" }
anchor-derive-accounts = { path = "./derive/accounts", version = "0.29.0" }
anchor-derive-serde = { path = "./derive/serde", version = "0.29.0" }
anchor-derive-space = { path = "./derive/space", version = "0.29.0" }
anchor-attribute-access-control = { path = "./attribute/access-control", version = "0.30.0" }
anchor-attribute-account = { path = "./attribute/account", version = "0.30.0" }
anchor-attribute-constant = { path = "./attribute/constant", version = "0.30.0" }
anchor-attribute-error = { path = "./attribute/error", version = "0.30.0" }
anchor-attribute-event = { path = "./attribute/event", version = "0.30.0" }
anchor-attribute-program = { path = "./attribute/program", version = "0.30.0" }
anchor-derive-accounts = { path = "./derive/accounts", version = "0.30.0" }
anchor-derive-serde = { path = "./derive/serde", version = "0.30.0" }
anchor-derive-space = { path = "./derive/space", version = "0.30.0" }
# `anchor-idl` should only be included with `idl-build` feature
anchor-idl = { path = "../idl", version = "0.29.0", optional = true }
# `anchor-lang-idl` should only be included with `idl-build` feature
anchor-lang-idl = { path = "../idl", version = "0.1.0", optional = true }
arrayref = "0.3"
base64 = "0.21"
@ -59,6 +59,5 @@ borsh = ">=0.9, <0.11"
bytemuck = "1"
solana-program = "1.16"
thiserror = "1"
# TODO: Remove. This crate has been added to fix a build error with the 1.16.0 release.
getrandom = { version = "0.2", features = ["custom"] }
getrandom = { version = "0.2", features = ["custom"] }

View File

@ -1,6 +1,6 @@
[package]
name = "anchor-attribute-access-control"
version = "0.29.0"
version = "0.30.0"
authors = ["Anchor Maintainers <accounts@200ms.io>"]
repository = "https://github.com/coral-xyz/anchor"
license = "Apache-2.0"
@ -15,7 +15,7 @@ proc-macro = true
anchor-debug = ["anchor-syn/anchor-debug"]
[dependencies]
anchor-syn = { path = "../../syn", version = "0.29.0" }
anchor-syn = { path = "../../syn", version = "0.30.0" }
proc-macro2 = "1"
quote = "1"
syn = { version = "1", features = ["full"] }

View File

@ -1,6 +1,6 @@
[package]
name = "anchor-attribute-account"
version = "0.29.0"
version = "0.30.0"
authors = ["Anchor Maintainers <accounts@200ms.io>"]
repository = "https://github.com/coral-xyz/anchor"
license = "Apache-2.0"
@ -16,7 +16,7 @@ anchor-debug = ["anchor-syn/anchor-debug"]
idl-build = ["anchor-syn/idl-build"]
[dependencies]
anchor-syn = { path = "../../syn", version = "0.29.0", features = ["hash"] }
anchor-syn = { path = "../../syn", version = "0.30.0", features = ["hash"] }
bs58 = "0.5"
proc-macro2 = "1"
quote = "1"

View File

@ -1,6 +1,6 @@
[package]
name = "anchor-attribute-constant"
version = "0.29.0"
version = "0.30.0"
authors = ["Anchor Maintainers <accounts@200ms.io>"]
repository = "https://github.com/coral-xyz/anchor"
license = "Apache-2.0"
@ -16,6 +16,6 @@ anchor-debug = ["anchor-syn/anchor-debug"]
idl-build = ["anchor-syn/idl-build"]
[dependencies]
anchor-syn = { path = "../../syn", version = "0.29.0" }
anchor-syn = { path = "../../syn", version = "0.30.0" }
quote = "1"
syn = { version = "1", features = ["full"] }

View File

@ -1,6 +1,6 @@
[package]
name = "anchor-attribute-error"
version = "0.29.0"
version = "0.30.0"
authors = ["Anchor Maintainers <accounts@200ms.io>"]
repository = "https://github.com/coral-xyz/anchor"
license = "Apache-2.0"
@ -16,6 +16,6 @@ anchor-debug = ["anchor-syn/anchor-debug"]
idl-build = ["anchor-syn/idl-build"]
[dependencies]
anchor-syn = { path = "../../syn", version = "0.29.0" }
anchor-syn = { path = "../../syn", version = "0.30.0" }
quote = "1"
syn = { version = "1", features = ["full"] }

View File

@ -1,6 +1,6 @@
[package]
name = "anchor-attribute-event"
version = "0.29.0"
version = "0.30.0"
authors = ["Anchor Maintainers <accounts@200ms.io>"]
repository = "https://github.com/coral-xyz/anchor"
license = "Apache-2.0"
@ -17,7 +17,7 @@ event-cpi = ["anchor-syn/event-cpi"]
idl-build = ["anchor-syn/idl-build"]
[dependencies]
anchor-syn = { path = "../../syn", version = "0.29.0", features = ["hash"] }
anchor-syn = { path = "../../syn", version = "0.30.0", features = ["hash"] }
proc-macro2 = "1"
quote = "1"
syn = { version = "1", features = ["full"] }

View File

@ -1,6 +1,6 @@
[package]
name = "anchor-attribute-program"
version = "0.29.0"
version = "0.30.0"
authors = ["Anchor Maintainers <accounts@200ms.io>"]
repository = "https://github.com/coral-xyz/anchor"
license = "Apache-2.0"
@ -17,8 +17,8 @@ idl-build = ["anchor-syn/idl-build"]
interface-instructions = ["anchor-syn/interface-instructions"]
[dependencies]
anchor-idl = { path = "../../../idl", version = "0.29.0" }
anchor-syn = { path = "../../syn", version = "0.29.0" }
anchor-lang-idl = { path = "../../../idl", version = "0.1.0" }
anchor-syn = { path = "../../syn", version = "0.30.0" }
anyhow = "1"
bs58 = "0.5"
heck = "0.3"

View File

@ -1,4 +1,4 @@
use anchor_idl::types::{
use anchor_lang_idl::types::{
Idl, IdlArrayLen, IdlDefinedFields, IdlField, IdlGenericArg, IdlRepr, IdlSerialization,
IdlType, IdlTypeDef, IdlTypeDefGeneric, IdlTypeDefTy,
};

View File

@ -1,7 +1,7 @@
mod common;
mod mods;
use anchor_idl::types::Idl;
use anchor_lang_idl::types::Idl;
use anyhow::anyhow;
use quote::{quote, ToTokens};
use syn::parse::{Parse, ParseStream};

View File

@ -1,4 +1,4 @@
use anchor_idl::types::{Idl, IdlSerialization};
use anchor_lang_idl::types::{Idl, IdlSerialization};
use quote::{format_ident, quote};
use super::common::{convert_idl_type_def_to_ts, gen_discriminator, get_canonical_program_id};

View File

@ -1,4 +1,4 @@
use anchor_idl::types::Idl;
use anchor_lang_idl::types::Idl;
use quote::quote;
use super::common::gen_accounts_common;

View File

@ -1,4 +1,4 @@
use anchor_idl::types::{Idl, IdlType};
use anchor_lang_idl::types::{Idl, IdlType};
use quote::{format_ident, quote, ToTokens};
use super::common::convert_idl_type_to_str;

View File

@ -1,4 +1,4 @@
use anchor_idl::types::Idl;
use anchor_lang_idl::types::Idl;
use heck::CamelCase;
use quote::{format_ident, quote};

View File

@ -1,4 +1,4 @@
use anchor_idl::types::Idl;
use anchor_lang_idl::types::Idl;
use quote::{format_ident, quote};
use super::common::{convert_idl_type_def_to_ts, gen_discriminator};

View File

@ -1,4 +1,4 @@
use anchor_idl::types::{Idl, IdlInstructionAccountItem};
use anchor_lang_idl::types::{Idl, IdlInstructionAccountItem};
use anchor_syn::{
codegen::accounts::{__client_accounts, __cpi_client_accounts},
parser::accounts,

View File

@ -1,4 +1,4 @@
use anchor_idl::types::Idl;
use anchor_lang_idl::types::Idl;
use quote::quote;
use super::common::convert_idl_type_def_to_ts;

View File

@ -1,4 +1,4 @@
use anchor_idl::types::Idl;
use anchor_lang_idl::types::Idl;
use quote::{format_ident, quote};
use super::common::gen_discriminator;

View File

@ -1,6 +1,6 @@
[package]
name = "anchor-derive-accounts"
version = "0.29.0"
version = "0.30.0"
authors = ["Anchor Maintainers <accounts@200ms.io>"]
repository = "https://github.com/coral-xyz/anchor"
license = "Apache-2.0"
@ -18,6 +18,6 @@ idl-build = ["anchor-syn/idl-build"]
init-if-needed = ["anchor-syn/init-if-needed"]
[dependencies]
anchor-syn = { path = "../../syn", version = "0.29.0" }
anchor-syn = { path = "../../syn", version = "0.30.0" }
quote = "1"
syn = { version = "1", features = ["full"] }

View File

@ -1,6 +1,6 @@
[package]
name = "anchor-derive-serde"
version = "0.29.0"
version = "0.30.0"
authors = ["Anchor Maintainers <accounts@200ms.io>"]
repository = "https://github.com/coral-xyz/anchor"
license = "Apache-2.0"
@ -15,7 +15,7 @@ proc-macro = true
idl-build = ["anchor-syn/idl-build"]
[dependencies]
anchor-syn = { path = "../../syn", version = "0.29.0" }
anchor-syn = { path = "../../syn", version = "0.30.0" }
borsh-derive-internal = ">=0.9, <0.11"
proc-macro2 = "1"
syn = { version = "1", features = ["full"] }

View File

@ -1,6 +1,6 @@
[package]
name = "anchor-derive-space"
version = "0.29.0"
version = "0.30.0"
authors = ["Anchor Maintainers <accounts@200ms.io>"]
repository = "https://github.com/coral-xyz/anchor"
license = "Apache-2.0"

View File

@ -126,6 +126,56 @@ pub enum ErrorCode {
/// 2023 - A mint token program constraint was violated
#[msg("An associated token account token program constraint was violated")]
ConstraintAssociatedTokenTokenProgram,
/// Extension constraints
///
/// 2024 - A group pointer extension constraint was violated
#[msg("A group pointer extension constraint was violated")]
ConstraintMintGroupPointerExtension,
/// 2025 - A group pointer extension authority constraint was violated
#[msg("A group pointer extension authority constraint was violated")]
ConstraintMintGroupPointerExtensionAuthority,
/// 2026 - A group pointer extension group address constraint was violated
#[msg("A group pointer extension group address constraint was violated")]
ConstraintMintGroupPointerExtensionGroupAddress,
/// 2027 - A group member pointer extension constraint was violated
#[msg("A group member pointer extension constraint was violated")]
ConstraintMintGroupMemberPointerExtension,
/// 2028 - A group member pointer extension authority constraint was violated
#[msg("A group member pointer extension authority constraint was violated")]
ConstraintMintGroupMemberPointerExtensionAuthority,
/// 2029 - A group member pointer extension member address constraint was violated
#[msg("A group member pointer extension group address constraint was violated")]
ConstraintMintGroupMemberPointerExtensionMemberAddress,
/// 2030 - A metadata pointer extension constraint was violated
#[msg("A metadata pointer extension constraint was violated")]
ConstraintMintMetadataPointerExtension,
/// 2031 - A metadata pointer extension authority constraint was violated
#[msg("A metadata pointer extension authority constraint was violated")]
ConstraintMintMetadataPointerExtensionAuthority,
/// 2032 - A metadata pointer extension metadata address constraint was violated
#[msg("A metadata pointer extension metadata address constraint was violated")]
ConstraintMintMetadataPointerExtensionMetadataAddress,
/// 2033 - A close authority extension constraint was violated
#[msg("A close authority constraint was violated")]
ConstraintMintCloseAuthorityExtension,
/// 2034 - A close authority extension authority constraint was violated
#[msg("A close authority extension authority constraint was violated")]
ConstraintMintCloseAuthorityExtensionAuthority,
/// 2035 - A permanent delegate extension constraint was violated
#[msg("A permanent delegate extension constraint was violated")]
ConstraintMintPermanentDelegateExtension,
/// 2036 - A permanent delegate extension authority constraint was violated
#[msg("A permanent delegate extension delegate constraint was violated")]
ConstraintMintPermanentDelegateExtensionDelegate,
/// 2037 - A transfer hook extension constraint was violated
#[msg("A transfer hook extension constraint was violated")]
ConstraintMintTransferHookExtension,
/// 2038 - A transfer hook extension authority constraint was violated
#[msg("A transfer hook extension authority constraint was violated")]
ConstraintMintTransferHookExtensionAuthority,
/// 2039 - A transfer hook extension transfer hook program id constraint was violated
#[msg("A transfer hook extension transfer hook program id constraint was violated")]
ConstraintMintTransferHookExtensionProgramId,
// Require
/// 2500 - A require expression was violated

View File

@ -80,4 +80,4 @@ impl IdlAccount {
}
#[cfg(feature = "idl-build")]
pub use anchor_idl::{build::IdlBuild, *};
pub use anchor_lang_idl::{build::IdlBuild, *};

View File

@ -28,6 +28,7 @@ extern crate self as anchor_lang;
use bytemuck::{Pod, Zeroable};
use solana_program::account_info::AccountInfo;
use solana_program::instruction::AccountMeta;
use solana_program::program_error::ProgramError;
use solana_program::pubkey::Pubkey;
use std::{collections::BTreeSet, fmt::Debug, io::Write};
@ -197,7 +198,10 @@ pub trait Lamports<'info>: AsRef<AccountInfo<'info>> {
///
/// See [`Lamports::sub_lamports`] for subtracting lamports.
fn add_lamports(&self, amount: u64) -> Result<&Self> {
**self.as_ref().try_borrow_mut_lamports()? += amount;
**self.as_ref().try_borrow_mut_lamports()? = self
.get_lamports()
.checked_add(amount)
.ok_or(ProgramError::ArithmeticOverflow)?;
Ok(self)
}
@ -215,7 +219,10 @@ pub trait Lamports<'info>: AsRef<AccountInfo<'info>> {
///
/// See [`Lamports::add_lamports`] for adding lamports.
fn sub_lamports(&self, amount: u64) -> Result<&Self> {
**self.as_ref().try_borrow_mut_lamports()? -= amount;
**self.as_ref().try_borrow_mut_lamports()? = self
.get_lamports()
.checked_sub(amount)
.ok_or(ProgramError::ArithmeticOverflow)?;
Ok(self)
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "anchor-syn"
version = "0.29.0"
version = "0.30.0"
authors = ["Anchor Maintainers <accounts@200ms.io>"]
repository = "https://github.com/coral-xyz/anchor"
license = "Apache-2.0"

View File

@ -661,6 +661,16 @@ fn generate_constraint_init_group(
decimals,
freeze_authority,
token_program,
group_pointer_authority,
group_pointer_group_address,
group_member_pointer_authority,
group_member_pointer_member_address,
metadata_pointer_authority,
metadata_pointer_metadata_address,
close_authority,
permanent_delegate,
transfer_hook_authority,
transfer_hook_program_id,
} => {
let token_program = match token_program {
Some(t) => t.to_token_stream(),
@ -672,6 +682,59 @@ fn generate_constraint_init_group(
None => quote! {},
};
// extension checks
let group_pointer_authority_check = match group_pointer_authority {
Some(gpa) => check_scope.generate_check(gpa),
None => quote! {},
};
let group_pointer_group_address_check = match group_pointer_group_address {
Some(gpga) => check_scope.generate_check(gpga),
None => quote! {},
};
let group_member_pointer_authority_check = match group_member_pointer_authority {
Some(gmpa) => check_scope.generate_check(gmpa),
None => quote! {},
};
let group_member_pointer_member_address_check =
match group_member_pointer_member_address {
Some(gmpm) => check_scope.generate_check(gmpm),
None => quote! {},
};
let metadata_pointer_authority_check = match metadata_pointer_authority {
Some(mpa) => check_scope.generate_check(mpa),
None => quote! {},
};
let metadata_pointer_metadata_address_check = match metadata_pointer_metadata_address {
Some(mpma) => check_scope.generate_check(mpma),
None => quote! {},
};
let close_authority_check = match close_authority {
Some(ca) => check_scope.generate_check(ca),
None => quote! {},
};
let transfer_hook_authority_check = match transfer_hook_authority {
Some(tha) => check_scope.generate_check(tha),
None => quote! {},
};
let transfer_hook_program_id_check = match transfer_hook_program_id {
Some(thpid) => check_scope.generate_check(thpid),
None => quote! {},
};
let permanent_delegate_check = match permanent_delegate {
Some(pd) => check_scope.generate_check(pd),
None => quote! {},
};
let system_program_optional_check = check_scope.generate_check(system_program);
let token_program_optional_check = check_scope.generate_check(&token_program);
let rent_optional_check = check_scope.generate_check(rent);
@ -682,23 +745,126 @@ fn generate_constraint_init_group(
#rent_optional_check
#owner_optional_check
#freeze_authority_optional_check
#group_pointer_authority_check
#group_pointer_group_address_check
#group_member_pointer_authority_check
#group_member_pointer_member_address_check
#metadata_pointer_authority_check
#metadata_pointer_metadata_address_check
#close_authority_check
#transfer_hook_authority_check
#transfer_hook_program_id_check
#permanent_delegate_check
};
let payer_optional_check = check_scope.generate_check(payer);
let create_account = generate_create_account(
field,
quote! {::anchor_spl::token::Mint::LEN},
quote! {&#token_program.key()},
quote! {#payer},
seeds_with_bump,
);
let mut extensions = vec![];
if group_pointer_authority.is_some() || group_pointer_group_address.is_some() {
extensions.push(quote! {::anchor_spl::token_interface::spl_token_2022::extension::ExtensionType::GroupPointer});
}
if group_member_pointer_authority.is_some()
|| group_member_pointer_member_address.is_some()
{
extensions.push(quote! {::anchor_spl::token_interface::spl_token_2022::extension::ExtensionType::GroupMemberPointer});
}
if metadata_pointer_authority.is_some() || metadata_pointer_metadata_address.is_some() {
extensions.push(quote! {::anchor_spl::token_interface::spl_token_2022::extension::ExtensionType::MetadataPointer});
}
if close_authority.is_some() {
extensions.push(quote! {::anchor_spl::token_interface::spl_token_2022::extension::ExtensionType::MintCloseAuthority});
}
if transfer_hook_authority.is_some() || transfer_hook_program_id.is_some() {
extensions.push(quote! {::anchor_spl::token_interface::spl_token_2022::extension::ExtensionType::TransferHook});
}
if permanent_delegate.is_some() {
extensions.push(quote! {::anchor_spl::token_interface::spl_token_2022::extension::ExtensionType::PermanentDelegate});
}
let mint_space = if extensions.is_empty() {
quote! { ::anchor_spl::token::Mint::LEN }
} else {
quote! { ::anchor_spl::token_interface::find_mint_account_size(Some(&vec![#(#extensions),*]))? }
};
let extensions = if extensions.is_empty() {
quote! {Option::<&::anchor_spl::token_interface::ExtensionsVec>::None}
} else {
quote! {Option::<&::anchor_spl::token_interface::ExtensionsVec>::Some(&vec![#(#extensions),*])}
};
let freeze_authority = match freeze_authority {
Some(fa) => quote! { Option::<&anchor_lang::prelude::Pubkey>::Some(&#fa.key()) },
None => quote! { Option::<&anchor_lang::prelude::Pubkey>::None },
};
let group_pointer_authority = match group_pointer_authority {
Some(gpa) => quote! { Option::<anchor_lang::prelude::Pubkey>::Some(#gpa.key()) },
None => quote! { Option::<anchor_lang::prelude::Pubkey>::None },
};
let group_pointer_group_address = match group_pointer_group_address {
Some(gpga) => quote! { Option::<anchor_lang::prelude::Pubkey>::Some(#gpga.key()) },
None => quote! { Option::<anchor_lang::prelude::Pubkey>::None },
};
let group_member_pointer_authority = match group_member_pointer_authority {
Some(gmpa) => quote! { Option::<anchor_lang::prelude::Pubkey>::Some(#gmpa.key()) },
None => quote! { Option::<anchor_lang::prelude::Pubkey>::None },
};
let group_member_pointer_member_address = match group_member_pointer_member_address {
Some(gmpma) => {
quote! { Option::<anchor_lang::prelude::Pubkey>::Some(#gmpma.key()) }
}
None => quote! { Option::<anchor_lang::prelude::Pubkey>::None },
};
let metadata_pointer_authority = match metadata_pointer_authority {
Some(mpa) => quote! { Option::<anchor_lang::prelude::Pubkey>::Some(#mpa.key()) },
None => quote! { Option::<anchor_lang::prelude::Pubkey>::None },
};
let metadata_pointer_metadata_address = match metadata_pointer_metadata_address {
Some(mpma) => quote! { Option::<anchor_lang::prelude::Pubkey>::Some(#mpma.key()) },
None => quote! { Option::<anchor_lang::prelude::Pubkey>::None },
};
let close_authority = match close_authority {
Some(ca) => quote! { Option::<&anchor_lang::prelude::Pubkey>::Some(&#ca.key()) },
None => quote! { Option::<&anchor_lang::prelude::Pubkey>::None },
};
let permanent_delegate = match permanent_delegate {
Some(pd) => quote! { Option::<&anchor_lang::prelude::Pubkey>::Some(&#pd.key()) },
None => quote! { Option::<&anchor_lang::prelude::Pubkey>::None },
};
let transfer_hook_authority = match transfer_hook_authority {
Some(tha) => quote! { Option::<anchor_lang::prelude::Pubkey>::Some(#tha.key()) },
None => quote! { Option::<anchor_lang::prelude::Pubkey>::None },
};
let transfer_hook_program_id = match transfer_hook_program_id {
Some(thpid) => {
quote! { Option::<anchor_lang::prelude::Pubkey>::Some(#thpid.key()) }
}
None => quote! { Option::<anchor_lang::prelude::Pubkey>::None },
};
let create_account = generate_create_account(
field,
mint_space,
quote! {&#token_program.key()},
quote! {#payer},
seeds_with_bump,
);
quote! {
// Define the bump and pda variable.
#find_pda
@ -715,6 +881,78 @@ fn generate_constraint_init_group(
// Create the account with the system program.
#create_account
// Initialize extensions.
if let Some(extensions) = #extensions {
for e in extensions {
match e {
::anchor_spl::token_interface::spl_token_2022::extension::ExtensionType::GroupPointer => {
let cpi_program = #token_program.to_account_info();
let accounts = ::anchor_spl::token_interface::GroupPointerInitialize {
token_program_id: #token_program.to_account_info(),
mint: #field.to_account_info(),
};
let cpi_ctx = anchor_lang::context::CpiContext::new(cpi_program, accounts);
::anchor_spl::token_interface::group_pointer_initialize(cpi_ctx, #group_pointer_authority, #group_pointer_group_address)?;
},
::anchor_spl::token_interface::spl_token_2022::extension::ExtensionType::GroupMemberPointer => {
let cpi_program = #token_program.to_account_info();
let accounts = ::anchor_spl::token_interface::GroupMemberPointerInitialize {
token_program_id: #token_program.to_account_info(),
mint: #field.to_account_info(),
};
let cpi_ctx = anchor_lang::context::CpiContext::new(cpi_program, accounts);
::anchor_spl::token_interface::group_member_pointer_initialize(cpi_ctx, #group_member_pointer_authority, #group_member_pointer_member_address)?;
},
::anchor_spl::token_interface::spl_token_2022::extension::ExtensionType::MetadataPointer => {
let cpi_program = #token_program.to_account_info();
let accounts = ::anchor_spl::token_interface::MetadataPointerInitialize {
token_program_id: #token_program.to_account_info(),
mint: #field.to_account_info(),
};
let cpi_ctx = anchor_lang::context::CpiContext::new(cpi_program, accounts);
::anchor_spl::token_interface::metadata_pointer_initialize(cpi_ctx, #metadata_pointer_authority, #metadata_pointer_metadata_address)?;
},
::anchor_spl::token_interface::spl_token_2022::extension::ExtensionType::MintCloseAuthority => {
let cpi_program = #token_program.to_account_info();
let accounts = ::anchor_spl::token_interface::MintCloseAuthorityInitialize {
token_program_id: #token_program.to_account_info(),
mint: #field.to_account_info(),
};
let cpi_ctx = anchor_lang::context::CpiContext::new(cpi_program, accounts);
::anchor_spl::token_interface::mint_close_authority_initialize(cpi_ctx, #close_authority)?;
},
::anchor_spl::token_interface::spl_token_2022::extension::ExtensionType::TransferHook => {
let cpi_program = #token_program.to_account_info();
let accounts = ::anchor_spl::token_interface::TransferHookInitialize {
token_program_id: #token_program.to_account_info(),
mint: #field.to_account_info(),
};
let cpi_ctx = anchor_lang::context::CpiContext::new(cpi_program, accounts);
::anchor_spl::token_interface::transfer_hook_initialize(cpi_ctx, #transfer_hook_authority, #transfer_hook_program_id)?;
},
::anchor_spl::token_interface::spl_token_2022::extension::ExtensionType::NonTransferable => {
let cpi_program = #token_program.to_account_info();
let accounts = ::anchor_spl::token_interface::NonTransferableMintInitialize {
token_program_id: #token_program.to_account_info(),
mint: #field.to_account_info(),
};
let cpi_ctx = anchor_lang::context::CpiContext::new(cpi_program, accounts);
::anchor_spl::token_interface::non_transferable_mint_initialize(cpi_ctx)?;
},
::anchor_spl::token_interface::spl_token_2022::extension::ExtensionType::PermanentDelegate => {
let cpi_program = #token_program.to_account_info();
let accounts = ::anchor_spl::token_interface::PermanentDelegateInitialize {
token_program_id: #token_program.to_account_info(),
mint: #field.to_account_info(),
};
let cpi_ctx = anchor_lang::context::CpiContext::new(cpi_program, accounts);
::anchor_spl::token_interface::permanent_delegate_initialize(cpi_ctx, #permanent_delegate.unwrap())?;
},
_ => {} // do nothing
}
};
}
// Initialize the mint account.
let cpi_program = #token_program.to_account_info();
let accounts = ::anchor_spl::token_interface::InitializeMint2 {
@ -723,6 +961,7 @@ fn generate_constraint_init_group(
let cpi_ctx = anchor_lang::context::CpiContext::new(cpi_program, accounts);
::anchor_spl::token_interface::initialize_mint2(cpi_ctx, #decimals, &#owner.key(), #freeze_authority)?;
}
let pa: #ty_decl = #from_account_info_unchecked;
if #if_needed {
if pa.mint_authority != anchor_lang::solana_program::program_option::COption::Some(#owner.key()) {
@ -1068,12 +1307,203 @@ fn generate_constraint_mint(
}
None => quote! {},
};
let group_pointer_authority_check = match &c.group_pointer_authority {
Some(group_pointer_authority) => {
let group_pointer_authority_optional_check =
optional_check_scope.generate_check(group_pointer_authority);
quote! {
let group_pointer = ::anchor_spl::token_interface::get_mint_extension_data::<::anchor_spl::token_interface::spl_token_2022::extension::group_pointer::GroupPointer>(#account_ref);
if group_pointer.is_err() {
return Err(anchor_lang::error::ErrorCode::ConstraintMintGroupPointerExtension.into());
}
#group_pointer_authority_optional_check
if group_pointer.unwrap().authority != ::anchor_spl::token_2022_extensions::spl_pod::optional_keys::OptionalNonZeroPubkey::try_from(Some(#group_pointer_authority.key()))? {
return Err(anchor_lang::error::ErrorCode::ConstraintMintGroupPointerExtensionAuthority.into());
}
}
}
None => quote! {},
};
let group_pointer_group_address_check = match &c.group_pointer_group_address {
Some(group_pointer_group_address) => {
let group_pointer_group_address_optional_check =
optional_check_scope.generate_check(group_pointer_group_address);
quote! {
let group_pointer = ::anchor_spl::token_interface::get_mint_extension_data::<::anchor_spl::token_interface::spl_token_2022::extension::group_pointer::GroupPointer>(#account_ref);
if group_pointer.is_err() {
return Err(anchor_lang::error::ErrorCode::ConstraintMintGroupPointerExtension.into());
}
#group_pointer_group_address_optional_check
if group_pointer.unwrap().group_address != ::anchor_spl::token_2022_extensions::spl_pod::optional_keys::OptionalNonZeroPubkey::try_from(Some(#group_pointer_group_address.key()))? {
return Err(anchor_lang::error::ErrorCode::ConstraintMintGroupPointerExtensionGroupAddress.into());
}
}
}
None => quote! {},
};
let group_member_pointer_authority_check = match &c.group_member_pointer_authority {
Some(group_member_pointer_authority) => {
let group_member_pointer_authority_optional_check =
optional_check_scope.generate_check(group_member_pointer_authority);
quote! {
let group_member_pointer = ::anchor_spl::token_interface::get_mint_extension_data::<::anchor_spl::token_interface::spl_token_2022::extension::group_member_pointer::GroupMemberPointer>(#account_ref);
if group_member_pointer.is_err() {
return Err(anchor_lang::error::ErrorCode::ConstraintMintGroupMemberPointerExtension.into());
}
#group_member_pointer_authority_optional_check
if group_member_pointer.unwrap().authority != ::anchor_spl::token_2022_extensions::spl_pod::optional_keys::OptionalNonZeroPubkey::try_from(Some(#group_member_pointer_authority.key()))? {
return Err(anchor_lang::error::ErrorCode::ConstraintMintGroupMemberPointerExtensionAuthority.into());
}
}
}
None => quote! {},
};
let group_member_pointer_member_address_check = match &c.group_member_pointer_member_address {
Some(group_member_pointer_member_address) => {
let group_member_pointer_member_address_optional_check =
optional_check_scope.generate_check(group_member_pointer_member_address);
quote! {
let group_member_pointer = ::anchor_spl::token_interface::get_mint_extension_data::<::anchor_spl::token_interface::spl_token_2022::extension::group_member_pointer::GroupMemberPointer>(#account_ref);
if group_member_pointer.is_err() {
return Err(anchor_lang::error::ErrorCode::ConstraintMintGroupMemberPointerExtension.into());
}
#group_member_pointer_member_address_optional_check
if group_member_pointer.unwrap().member_address != ::anchor_spl::token_2022_extensions::spl_pod::optional_keys::OptionalNonZeroPubkey::try_from(Some(#group_member_pointer_member_address.key()))? {
return Err(anchor_lang::error::ErrorCode::ConstraintMintGroupMemberPointerExtensionMemberAddress.into());
}
}
}
None => quote! {},
};
let metadata_pointer_authority_check = match &c.metadata_pointer_authority {
Some(metadata_pointer_authority) => {
let metadata_pointer_authority_optional_check =
optional_check_scope.generate_check(metadata_pointer_authority);
quote! {
let metadata_pointer = ::anchor_spl::token_interface::get_mint_extension_data::<::anchor_spl::token_interface::spl_token_2022::extension::metadata_pointer::MetadataPointer>(#account_ref);
if metadata_pointer.is_err() {
return Err(anchor_lang::error::ErrorCode::ConstraintMintMetadataPointerExtension.into());
}
#metadata_pointer_authority_optional_check
if metadata_pointer.unwrap().authority != ::anchor_spl::token_2022_extensions::spl_pod::optional_keys::OptionalNonZeroPubkey::try_from(Some(#metadata_pointer_authority.key()))? {
return Err(anchor_lang::error::ErrorCode::ConstraintMintMetadataPointerExtensionAuthority.into());
}
}
}
None => quote! {},
};
let metadata_pointer_metadata_address_check = match &c.metadata_pointer_metadata_address {
Some(metadata_pointer_metadata_address) => {
let metadata_pointer_metadata_address_optional_check =
optional_check_scope.generate_check(metadata_pointer_metadata_address);
quote! {
let metadata_pointer = ::anchor_spl::token_interface::get_mint_extension_data::<::anchor_spl::token_interface::spl_token_2022::extension::metadata_pointer::MetadataPointer>(#account_ref);
if metadata_pointer.is_err() {
return Err(anchor_lang::error::ErrorCode::ConstraintMintMetadataPointerExtension.into());
}
#metadata_pointer_metadata_address_optional_check
if metadata_pointer.unwrap().metadata_address != ::anchor_spl::token_2022_extensions::spl_pod::optional_keys::OptionalNonZeroPubkey::try_from(Some(#metadata_pointer_metadata_address.key()))? {
return Err(anchor_lang::error::ErrorCode::ConstraintMintMetadataPointerExtensionMetadataAddress.into());
}
}
}
None => quote! {},
};
let close_authority_check = match &c.close_authority {
Some(close_authority) => {
let close_authority_optional_check =
optional_check_scope.generate_check(close_authority);
quote! {
let close_authority = ::anchor_spl::token_interface::get_mint_extension_data::<::anchor_spl::token_interface::spl_token_2022::extension::mint_close_authority::MintCloseAuthority>(#account_ref);
if close_authority.is_err() {
return Err(anchor_lang::error::ErrorCode::ConstraintMintCloseAuthorityExtension.into());
}
#close_authority_optional_check
if close_authority.unwrap().close_authority != ::anchor_spl::token_2022_extensions::spl_pod::optional_keys::OptionalNonZeroPubkey::try_from(Some(#close_authority.key()))? {
return Err(anchor_lang::error::ErrorCode::ConstraintMintCloseAuthorityExtensionAuthority.into());
}
}
}
None => quote! {},
};
let permanent_delegate_check = match &c.permanent_delegate {
Some(permanent_delegate) => {
let permanent_delegate_optional_check =
optional_check_scope.generate_check(permanent_delegate);
quote! {
let permanent_delegate = ::anchor_spl::token_interface::get_mint_extension_data::<::anchor_spl::token_interface::spl_token_2022::extension::permanent_delegate::PermanentDelegate>(#account_ref);
if permanent_delegate.is_err() {
return Err(anchor_lang::error::ErrorCode::ConstraintMintPermanentDelegateExtension.into());
}
#permanent_delegate_optional_check
if permanent_delegate.unwrap().delegate != ::anchor_spl::token_2022_extensions::spl_pod::optional_keys::OptionalNonZeroPubkey::try_from(Some(#permanent_delegate.key()))? {
return Err(anchor_lang::error::ErrorCode::ConstraintMintPermanentDelegateExtensionDelegate.into());
}
}
}
None => quote! {},
};
let transfer_hook_authority_check = match &c.transfer_hook_authority {
Some(transfer_hook_authority) => {
let transfer_hook_authority_optional_check =
optional_check_scope.generate_check(transfer_hook_authority);
quote! {
let transfer_hook = ::anchor_spl::token_interface::get_mint_extension_data::<::anchor_spl::token_interface::spl_token_2022::extension::transfer_hook::TransferHook>(#account_ref);
if transfer_hook.is_err() {
return Err(anchor_lang::error::ErrorCode::ConstraintMintTransferHookExtension.into());
}
#transfer_hook_authority_optional_check
if transfer_hook.unwrap().authority != ::anchor_spl::token_2022_extensions::spl_pod::optional_keys::OptionalNonZeroPubkey::try_from(Some(#transfer_hook_authority.key()))? {
return Err(anchor_lang::error::ErrorCode::ConstraintMintTransferHookExtensionAuthority.into());
}
}
}
None => quote! {},
};
let transfer_hook_program_id_check = match &c.transfer_hook_program_id {
Some(transfer_hook_program_id) => {
let transfer_hook_program_id_optional_check =
optional_check_scope.generate_check(transfer_hook_program_id);
quote! {
let transfer_hook = ::anchor_spl::token_interface::get_mint_extension_data::<::anchor_spl::token_interface::spl_token_2022::extension::transfer_hook::TransferHook>(#account_ref);
if transfer_hook.is_err() {
return Err(anchor_lang::error::ErrorCode::ConstraintMintTransferHookExtension.into());
}
#transfer_hook_program_id_optional_check
if transfer_hook.unwrap().program_id != ::anchor_spl::token_2022_extensions::spl_pod::optional_keys::OptionalNonZeroPubkey::try_from(Some(#transfer_hook_program_id.key()))? {
return Err(anchor_lang::error::ErrorCode::ConstraintMintTransferHookExtensionProgramId.into());
}
}
}
None => quote! {},
};
quote! {
{
#decimal_check
#mint_authority_check
#freeze_authority_check
#token_program_check
#group_pointer_authority_check
#group_pointer_group_address_check
#group_member_pointer_authority_check
#group_member_pointer_member_address_check
#metadata_pointer_authority_check
#metadata_pointer_metadata_address_check
#close_authority_check
#permanent_delegate_check
#transfer_hook_authority_check
#transfer_hook_program_id_check
}
}
}

View File

@ -680,6 +680,21 @@ pub enum ConstraintToken {
Realloc(Context<ConstraintRealloc>),
ReallocPayer(Context<ConstraintReallocPayer>),
ReallocZero(Context<ConstraintReallocZero>),
// extensions
ExtensionGroupPointerAuthority(Context<ConstraintExtensionAuthority>),
ExtensionGroupPointerGroupAddress(Context<ConstraintExtensionGroupPointerGroupAddress>),
ExtensionGroupMemberPointerAuthority(Context<ConstraintExtensionAuthority>),
ExtensionGroupMemberPointerMemberAddress(
Context<ConstraintExtensionGroupMemberPointerMemberAddress>,
),
ExtensionMetadataPointerAuthority(Context<ConstraintExtensionAuthority>),
ExtensionMetadataPointerMetadataAddress(
Context<ConstraintExtensionMetadataPointerMetadataAddress>,
),
ExtensionCloseAuthority(Context<ConstraintExtensionAuthority>),
ExtensionTokenHookAuthority(Context<ConstraintExtensionAuthority>),
ExtensionTokenHookProgramId(Context<ConstraintExtensionTokenHookProgramId>),
ExtensionPermanentDelegate(Context<ConstraintExtensionPermanentDelegate>),
}
impl Parse for ConstraintToken {
@ -796,6 +811,37 @@ pub struct ConstraintSpace {
pub space: Expr,
}
// extension constraints
#[derive(Debug, Clone)]
pub struct ConstraintExtensionAuthority {
pub authority: Expr,
}
#[derive(Debug, Clone)]
pub struct ConstraintExtensionGroupPointerGroupAddress {
pub group_address: Expr,
}
#[derive(Debug, Clone)]
pub struct ConstraintExtensionGroupMemberPointerMemberAddress {
pub member_address: Expr,
}
#[derive(Debug, Clone)]
pub struct ConstraintExtensionMetadataPointerMetadataAddress {
pub metadata_address: Expr,
}
#[derive(Debug, Clone)]
pub struct ConstraintExtensionTokenHookProgramId {
pub program_id: Expr,
}
#[derive(Debug, Clone)]
pub struct ConstraintExtensionPermanentDelegate {
pub permanent_delegate: Expr,
}
#[derive(Debug, Clone)]
#[allow(clippy::large_enum_variant)]
pub enum InitKind {
@ -822,6 +868,17 @@ pub enum InitKind {
freeze_authority: Option<Expr>,
decimals: Expr,
token_program: Option<Expr>,
// extensions
group_pointer_authority: Option<Expr>,
group_pointer_group_address: Option<Expr>,
group_member_pointer_authority: Option<Expr>,
group_member_pointer_member_address: Option<Expr>,
metadata_pointer_authority: Option<Expr>,
metadata_pointer_metadata_address: Option<Expr>,
close_authority: Option<Expr>,
permanent_delegate: Option<Expr>,
transfer_hook_authority: Option<Expr>,
transfer_hook_program_id: Option<Expr>,
},
}
@ -835,6 +892,46 @@ pub struct ConstraintTokenMint {
pub mint: Expr,
}
#[derive(Debug, Clone)]
pub struct ConstraintMintConfidentialTransferData {
pub confidential_transfer_data: Expr,
}
#[derive(Debug, Clone)]
pub struct ConstraintMintMetadata {
pub token_metadata: Expr,
}
#[derive(Debug, Clone)]
pub struct ConstraintMintTokenGroupData {
pub token_group_data: Expr,
}
#[derive(Debug, Clone)]
pub struct ConstraintMintTokenGroupMemberData {
pub token_group_member_data: Expr,
}
#[derive(Debug, Clone)]
pub struct ConstraintMintMetadataPointerData {
pub metadata_pointer_data: Expr,
}
#[derive(Debug, Clone)]
pub struct ConstraintMintGroupPointerData {
pub group_pointer_data: Expr,
}
#[derive(Debug, Clone)]
pub struct ConstraintMintGroupMemberPointerData {
pub group_member_pointer_data: Expr,
}
#[derive(Debug, Clone)]
pub struct ConstraintMintCloseAuthority {
pub close_authority: Expr,
}
#[derive(Debug, Clone)]
pub struct ConstraintTokenAuthority {
pub auth: Expr,
@ -890,6 +987,16 @@ pub struct ConstraintTokenMintGroup {
pub mint_authority: Option<Expr>,
pub freeze_authority: Option<Expr>,
pub token_program: Option<Expr>,
pub group_pointer_authority: Option<Expr>,
pub group_pointer_group_address: Option<Expr>,
pub group_member_pointer_authority: Option<Expr>,
pub group_member_pointer_member_address: Option<Expr>,
pub metadata_pointer_authority: Option<Expr>,
pub metadata_pointer_metadata_address: Option<Expr>,
pub close_authority: Option<Expr>,
pub permanent_delegate: Option<Expr>,
pub transfer_hook_authority: Option<Expr>,
pub transfer_hook_program_id: Option<Expr>,
}
// Syntaxt context object for preserving metadata about the inner item.

View File

@ -89,6 +89,177 @@ pub fn parse_token(stream: ParseStream) -> ParseResult<ConstraintToken> {
_ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
}
}
"extensions" => {
stream.parse::<Token![:]>()?;
stream.parse::<Token![:]>()?;
let kw = stream.call(Ident::parse_any)?.to_string();
match kw.as_str() {
"group_pointer" => {
stream.parse::<Token![:]>()?;
stream.parse::<Token![:]>()?;
let kw = stream.call(Ident::parse_any)?.to_string();
stream.parse::<Token![=]>()?;
let span = ident
.span()
.join(stream.span())
.unwrap_or_else(|| ident.span());
match kw.as_str() {
"authority" => {
ConstraintToken::ExtensionGroupPointerAuthority(Context::new(
span,
ConstraintExtensionAuthority {
authority: stream.parse()?,
},
))
}
"group_address" => {
ConstraintToken::ExtensionGroupPointerGroupAddress(Context::new(
span,
ConstraintExtensionGroupPointerGroupAddress {
group_address: stream.parse()?,
},
))
}
_ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
}
}
"group_member_pointer" => {
stream.parse::<Token![:]>()?;
stream.parse::<Token![:]>()?;
let kw = stream.call(Ident::parse_any)?.to_string();
stream.parse::<Token![=]>()?;
let span = ident
.span()
.join(stream.span())
.unwrap_or_else(|| ident.span());
match kw.as_str() {
"authority" => {
ConstraintToken::ExtensionGroupMemberPointerAuthority(Context::new(
span,
ConstraintExtensionAuthority {
authority: stream.parse()?,
},
))
}
"member_address" => {
ConstraintToken::ExtensionGroupMemberPointerMemberAddress(Context::new(
span,
ConstraintExtensionGroupMemberPointerMemberAddress {
member_address: stream.parse()?,
},
))
}
_ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
}
}
"metadata_pointer" => {
stream.parse::<Token![:]>()?;
stream.parse::<Token![:]>()?;
let kw = stream.call(Ident::parse_any)?.to_string();
stream.parse::<Token![=]>()?;
let span = ident
.span()
.join(stream.span())
.unwrap_or_else(|| ident.span());
match kw.as_str() {
"authority" => {
ConstraintToken::ExtensionMetadataPointerAuthority(Context::new(
span,
ConstraintExtensionAuthority {
authority: stream.parse()?,
},
))
}
"metadata_address" => {
ConstraintToken::ExtensionMetadataPointerMetadataAddress(Context::new(
span,
ConstraintExtensionMetadataPointerMetadataAddress {
metadata_address: stream.parse()?,
},
))
}
_ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
}
}
"close_authority" => {
stream.parse::<Token![:]>()?;
stream.parse::<Token![:]>()?;
let kw = stream.call(Ident::parse_any)?.to_string();
stream.parse::<Token![=]>()?;
let span = ident
.span()
.join(stream.span())
.unwrap_or_else(|| ident.span());
match kw.as_str() {
"authority" => ConstraintToken::ExtensionCloseAuthority(Context::new(
span,
ConstraintExtensionAuthority {
authority: stream.parse()?,
},
)),
_ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
}
}
"permanent_delegate" => {
stream.parse::<Token![:]>()?;
stream.parse::<Token![:]>()?;
let kw = stream.call(Ident::parse_any)?.to_string();
stream.parse::<Token![=]>()?;
let span = ident
.span()
.join(stream.span())
.unwrap_or_else(|| ident.span());
match kw.as_str() {
"delegate" => ConstraintToken::ExtensionPermanentDelegate(Context::new(
span,
ConstraintExtensionPermanentDelegate {
permanent_delegate: stream.parse()?,
},
)),
_ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
}
}
"transfer_hook" => {
stream.parse::<Token![:]>()?;
stream.parse::<Token![:]>()?;
let kw = stream.call(Ident::parse_any)?.to_string();
stream.parse::<Token![=]>()?;
let span = ident
.span()
.join(stream.span())
.unwrap_or_else(|| ident.span());
match kw.as_str() {
"authority" => ConstraintToken::ExtensionTokenHookAuthority(Context::new(
span,
ConstraintExtensionAuthority {
authority: stream.parse()?,
},
)),
"program_id" => ConstraintToken::ExtensionTokenHookProgramId(Context::new(
span,
ConstraintExtensionTokenHookProgramId {
program_id: stream.parse()?,
},
)),
_ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
}
}
_ => return Err(ParseError::new(ident.span(), "Invalid attribute")),
}
}
"token" => {
stream.parse::<Token![:]>()?;
stream.parse::<Token![:]>()?;
@ -354,6 +525,19 @@ pub struct ConstraintGroupBuilder<'ty> {
pub mint_freeze_authority: Option<Context<ConstraintMintFreezeAuthority>>,
pub mint_decimals: Option<Context<ConstraintMintDecimals>>,
pub mint_token_program: Option<Context<ConstraintTokenProgram>>,
pub extension_group_pointer_authority: Option<Context<ConstraintExtensionAuthority>>,
pub extension_group_pointer_group_address:
Option<Context<ConstraintExtensionGroupPointerGroupAddress>>,
pub extension_group_member_pointer_authority: Option<Context<ConstraintExtensionAuthority>>,
pub extension_group_member_pointer_member_address:
Option<Context<ConstraintExtensionGroupMemberPointerMemberAddress>>,
pub extension_metadata_pointer_authority: Option<Context<ConstraintExtensionAuthority>>,
pub extension_metadata_pointer_metadata_address:
Option<Context<ConstraintExtensionMetadataPointerMetadataAddress>>,
pub extension_close_authority: Option<Context<ConstraintExtensionAuthority>>,
pub extension_transfer_hook_authority: Option<Context<ConstraintExtensionAuthority>>,
pub extension_transfer_hook_program_id: Option<Context<ConstraintExtensionTokenHookProgramId>>,
pub extension_permanent_delegate: Option<Context<ConstraintExtensionPermanentDelegate>>,
pub bump: Option<Context<ConstraintTokenBump>>,
pub program_seed: Option<Context<ConstraintProgramSeed>>,
pub realloc: Option<Context<ConstraintRealloc>>,
@ -389,6 +573,16 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
mint_freeze_authority: None,
mint_decimals: None,
mint_token_program: None,
extension_group_pointer_authority: None,
extension_group_pointer_group_address: None,
extension_group_member_pointer_authority: None,
extension_group_member_pointer_member_address: None,
extension_metadata_pointer_authority: None,
extension_metadata_pointer_metadata_address: None,
extension_close_authority: None,
extension_transfer_hook_authority: None,
extension_transfer_hook_program_id: None,
extension_permanent_delegate: None,
bump: None,
program_seed: None,
realloc: None,
@ -591,6 +785,16 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
mint_freeze_authority,
mint_decimals,
mint_token_program,
extension_group_pointer_authority,
extension_group_pointer_group_address,
extension_group_member_pointer_authority,
extension_group_member_pointer_member_address,
extension_metadata_pointer_authority,
extension_metadata_pointer_metadata_address,
extension_close_authority,
extension_transfer_hook_authority,
extension_transfer_hook_program_id,
extension_permanent_delegate,
bump,
program_seed,
realloc,
@ -680,8 +884,33 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
&mint_authority,
&mint_freeze_authority,
&mint_token_program,
&extension_group_pointer_authority,
&extension_group_pointer_group_address,
&extension_group_member_pointer_authority,
&extension_group_member_pointer_member_address,
&extension_metadata_pointer_authority,
&extension_metadata_pointer_metadata_address,
&extension_close_authority,
&extension_transfer_hook_authority,
&extension_transfer_hook_program_id,
&extension_permanent_delegate,
) {
(None, None, None, None) => None,
(
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
) => None,
_ => Some(ConstraintTokenMintGroup {
decimals: mint_decimals
.as_ref()
@ -695,6 +924,37 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
token_program: mint_token_program
.as_ref()
.map(|a| a.clone().into_inner().token_program),
// extensions
group_pointer_authority: extension_group_pointer_authority
.as_ref()
.map(|a| a.clone().into_inner().authority),
group_pointer_group_address: extension_group_pointer_group_address
.as_ref()
.map(|a| a.clone().into_inner().group_address),
group_member_pointer_authority: extension_group_member_pointer_authority
.as_ref()
.map(|a| a.clone().into_inner().authority),
group_member_pointer_member_address: extension_group_member_pointer_member_address
.as_ref()
.map(|a| a.clone().into_inner().member_address),
metadata_pointer_authority: extension_metadata_pointer_authority
.as_ref()
.map(|a| a.clone().into_inner().authority),
metadata_pointer_metadata_address: extension_metadata_pointer_metadata_address
.as_ref()
.map(|a| a.clone().into_inner().metadata_address),
close_authority: extension_close_authority
.as_ref()
.map(|a| a.clone().into_inner().authority),
permanent_delegate: extension_permanent_delegate
.as_ref()
.map(|a| a.clone().into_inner().permanent_delegate),
transfer_hook_authority: extension_transfer_hook_authority
.as_ref()
.map(|a| a.clone().into_inner().authority),
transfer_hook_program_id: extension_transfer_hook_program_id
.as_ref()
.map(|a| a.clone().into_inner().program_id),
}),
};
@ -734,6 +994,17 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
},
freeze_authority: mint_freeze_authority.map(|fa| fa.into_inner().mint_freeze_auth),
token_program: mint_token_program.map(|tp| tp.into_inner().token_program),
// extensions
group_pointer_authority: extension_group_pointer_authority.map(|gpa| gpa.into_inner().authority),
group_pointer_group_address: extension_group_pointer_group_address.map(|gpga| gpga.into_inner().group_address),
group_member_pointer_authority: extension_group_member_pointer_authority.map(|gmpa| gmpa.into_inner().authority),
group_member_pointer_member_address: extension_group_member_pointer_member_address.map(|gmpma| gmpma.into_inner().member_address),
metadata_pointer_authority: extension_metadata_pointer_authority.map(|mpa| mpa.into_inner().authority),
metadata_pointer_metadata_address: extension_metadata_pointer_metadata_address.map(|mpma| mpma.into_inner().metadata_address),
close_authority: extension_close_authority.map(|ca| ca.into_inner().authority),
permanent_delegate: extension_permanent_delegate.map(|pd| pd.into_inner().permanent_delegate),
transfer_hook_authority: extension_transfer_hook_authority.map(|tha| tha.into_inner().authority),
transfer_hook_program_id: extension_transfer_hook_program_id.map(|thpid| thpid.into_inner().program_id),
}
} else {
InitKind::Program {
@ -796,6 +1067,32 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
ConstraintToken::Realloc(c) => self.add_realloc(c),
ConstraintToken::ReallocPayer(c) => self.add_realloc_payer(c),
ConstraintToken::ReallocZero(c) => self.add_realloc_zero(c),
ConstraintToken::ExtensionGroupPointerAuthority(c) => {
self.add_extension_group_pointer_authority(c)
}
ConstraintToken::ExtensionGroupPointerGroupAddress(c) => {
self.add_extension_group_pointer_group_address(c)
}
ConstraintToken::ExtensionGroupMemberPointerAuthority(c) => {
self.add_extension_group_member_pointer_authority(c)
}
ConstraintToken::ExtensionGroupMemberPointerMemberAddress(c) => {
self.add_extension_group_member_pointer_member_address(c)
}
ConstraintToken::ExtensionMetadataPointerAuthority(c) => {
self.add_extension_metadata_pointer_authority(c)
}
ConstraintToken::ExtensionMetadataPointerMetadataAddress(c) => {
self.add_extension_metadata_pointer_metadata_address(c)
}
ConstraintToken::ExtensionCloseAuthority(c) => self.add_extension_close_authority(c),
ConstraintToken::ExtensionTokenHookAuthority(c) => self.add_extension_authority(c),
ConstraintToken::ExtensionTokenHookProgramId(c) => {
self.add_extension_transfer_hook_program_id(c)
}
ConstraintToken::ExtensionPermanentDelegate(c) => {
self.add_extension_permanent_delegate(c)
}
}
}
@ -1221,4 +1518,147 @@ impl<'ty> ConstraintGroupBuilder<'ty> {
self.space.replace(c);
Ok(())
}
// extensions
fn add_extension_group_pointer_authority(
&mut self,
c: Context<ConstraintExtensionAuthority>,
) -> ParseResult<()> {
if self.extension_group_pointer_authority.is_some() {
return Err(ParseError::new(
c.span(),
"extension group pointer authority already provided",
));
}
self.extension_group_pointer_authority.replace(c);
Ok(())
}
fn add_extension_group_pointer_group_address(
&mut self,
c: Context<ConstraintExtensionGroupPointerGroupAddress>,
) -> ParseResult<()> {
if self.extension_group_pointer_group_address.is_some() {
return Err(ParseError::new(
c.span(),
"extension group pointer group address already provided",
));
}
self.extension_group_pointer_group_address.replace(c);
Ok(())
}
fn add_extension_group_member_pointer_authority(
&mut self,
c: Context<ConstraintExtensionAuthority>,
) -> ParseResult<()> {
if self.extension_group_member_pointer_authority.is_some() {
return Err(ParseError::new(
c.span(),
"extension group member pointer authority already provided",
));
}
self.extension_group_member_pointer_authority.replace(c);
Ok(())
}
fn add_extension_group_member_pointer_member_address(
&mut self,
c: Context<ConstraintExtensionGroupMemberPointerMemberAddress>,
) -> ParseResult<()> {
if self.extension_group_member_pointer_member_address.is_some() {
return Err(ParseError::new(
c.span(),
"extension group member pointer member address already provided",
));
}
self.extension_group_member_pointer_member_address
.replace(c);
Ok(())
}
fn add_extension_metadata_pointer_authority(
&mut self,
c: Context<ConstraintExtensionAuthority>,
) -> ParseResult<()> {
if self.extension_metadata_pointer_authority.is_some() {
return Err(ParseError::new(
c.span(),
"extension metadata pointer authority already provided",
));
}
self.extension_metadata_pointer_authority.replace(c);
Ok(())
}
fn add_extension_metadata_pointer_metadata_address(
&mut self,
c: Context<ConstraintExtensionMetadataPointerMetadataAddress>,
) -> ParseResult<()> {
if self.extension_metadata_pointer_metadata_address.is_some() {
return Err(ParseError::new(
c.span(),
"extension metadata pointer metadata address already provided",
));
}
self.extension_metadata_pointer_metadata_address.replace(c);
Ok(())
}
fn add_extension_close_authority(
&mut self,
c: Context<ConstraintExtensionAuthority>,
) -> ParseResult<()> {
if self.extension_close_authority.is_some() {
return Err(ParseError::new(
c.span(),
"extension close authority already provided",
));
}
self.extension_close_authority.replace(c);
Ok(())
}
fn add_extension_authority(
&mut self,
c: Context<ConstraintExtensionAuthority>,
) -> ParseResult<()> {
if self.extension_transfer_hook_authority.is_some() {
return Err(ParseError::new(
c.span(),
"extension transfer hook authority already provided",
));
}
self.extension_transfer_hook_authority.replace(c);
Ok(())
}
fn add_extension_transfer_hook_program_id(
&mut self,
c: Context<ConstraintExtensionTokenHookProgramId>,
) -> ParseResult<()> {
if self.extension_transfer_hook_program_id.is_some() {
return Err(ParseError::new(
c.span(),
"extension transfer hook program id already provided",
));
}
self.extension_transfer_hook_program_id.replace(c);
Ok(())
}
fn add_extension_permanent_delegate(
&mut self,
c: Context<ConstraintExtensionPermanentDelegate>,
) -> ParseResult<()> {
if self.extension_permanent_delegate.is_some() {
return Err(ParseError::new(
c.span(),
"extension permanent delegate already provided",
));
}
self.extension_permanent_delegate.replace(c);
Ok(())
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "anchor-spl"
version = "0.29.0"
version = "0.30.0"
authors = ["Anchor Maintainers <accounts@200ms.io>"]
rust-version = "1.60"
edition = "2021"
@ -12,7 +12,7 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[features]
default = ["associated_token", "mint", "token", "token_2022"]
default = ["associated_token", "mint", "token", "token_2022", "token_2022_extensions"]
associated_token = ["spl-associated-token-account"]
dex = ["serum_dex"]
devnet = []
@ -24,14 +24,17 @@ mint = []
stake = ["borsh"]
token = ["spl-token"]
token_2022 = ["spl-token-2022"]
token_2022_extensions = ["spl-token-2022", "spl-token-group-interface", "spl-token-metadata-interface", "spl-pod"]
[dependencies]
anchor-lang = { path = "../lang", version = "0.29.0", features = ["derive"] }
anchor-lang = { path = "../lang", version = "0.30.0", features = ["derive"] }
borsh = { version = ">=0.9, <0.11", optional = true }
mpl-token-metadata = { version = "3.1.0", optional = true }
mpl-token-metadata = { version = "4", optional = true }
serum_dex = { git = "https://github.com/openbook-dex/program/", rev = "1be91f2", version = "0.4.0", features = ["no-entrypoint"], optional = true }
solana-program = "1.16"
spl-associated-token-account = { version = "3", features = ["no-entrypoint"], optional = true }
spl-memo = { version = "4", features = ["no-entrypoint"], optional = true }
spl-token = { version = "4", features = ["no-entrypoint"], optional = true }
spl-token-2022 = { version = "3", features = ["no-entrypoint"], optional = true }
spl-token-group-interface = { version = "0.2.3", optional = true }
spl-token-metadata-interface = { version = "0.3.3", optional = true }
spl-pod = { version = "0.2.2", optional = true }

View File

@ -14,7 +14,7 @@ pub fn create<'info>(ctx: CpiContext<'_, '_, '_, 'info, Create<'info>>) -> Resul
ctx.accounts.mint.key,
ctx.accounts.token_program.key,
);
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.payer,
@ -38,7 +38,7 @@ pub fn create_idempotent<'info>(
ctx.accounts.mint.key,
ctx.accounts.token_program.key,
);
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.payer,

View File

@ -9,10 +9,10 @@ use std::num::NonZeroU64;
pub use serum_dex;
#[cfg(not(feature = "devnet"))]
anchor_lang::solana_program::declare_id!("srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX");
anchor_lang::declare_id!("srmqPvymJeFKQ4zGQed1GFppgkRHL9kaELCbyksJtPX");
#[cfg(feature = "devnet")]
anchor_lang::solana_program::declare_id!("EoTcMgcDRTJVZDMZWBoU6rhYHZfkNTVEAfz3uUJRcYGj");
anchor_lang::declare_id!("EoTcMgcDRTJVZDMZWBoU6rhYHZfkNTVEAfz3uUJRcYGj");
#[allow(clippy::too_many_arguments)]
pub fn new_order_v3<'info>(
@ -52,7 +52,7 @@ pub fn new_order_v3<'info>(
max_native_pc_qty_including_fees,
)
.map_err(|pe| ProgramError::from(pe))?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -77,7 +77,7 @@ pub fn cancel_order_v2<'info>(
order_id,
)
.map_err(|pe| ProgramError::from(pe))?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -101,7 +101,7 @@ pub fn settle_funds<'info>(ctx: CpiContext<'_, '_, '_, 'info, SettleFunds<'info>
ctx.accounts.vault_signer.key,
)
.map_err(|pe| ProgramError::from(pe))?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -120,7 +120,7 @@ pub fn init_open_orders<'info>(
ctx.remaining_accounts.first().map(|acc| acc.key),
)
.map_err(|pe| ProgramError::from(pe))?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -139,7 +139,7 @@ pub fn close_open_orders<'info>(
ctx.accounts.market.key,
)
.map_err(|pe| ProgramError::from(pe))?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -158,7 +158,7 @@ pub fn sweep_fees<'info>(ctx: CpiContext<'_, '_, '_, 'info, SweepFees<'info>>) -
ctx.accounts.token_program.key,
)
.map_err(|pe| ProgramError::from(pe))?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -194,7 +194,7 @@ pub fn initialize_market<'info>(
pc_dust_threshold,
)
.map_err(|pe| ProgramError::from(pe))?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,

View File

@ -12,7 +12,7 @@ macro_rules! vote_weight_record {
let vwr: spl_governance_addin_api::voter_weight::VoterWeightRecord =
anchor_lang::AnchorDeserialize::deserialize(&mut data)
.map_err(|_| anchor_lang::error::ErrorCode::AccountDidNotDeserialize)?;
if !solana_program::program_pack::IsInitialized::is_initialized(&vwr) {
if !anchor_lang::solana_program::program_pack::IsInitialized::is_initialized(&vwr) {
return Err(anchor_lang::error::ErrorCode::AccountDidNotSerialize.into());
}
Ok(VoterWeightRecord(vwr))

View File

@ -14,6 +14,9 @@ pub mod token;
#[cfg(feature = "token_2022")]
pub mod token_2022;
#[cfg(feature = "token_2022_extensions")]
pub mod token_2022_extensions;
#[cfg(feature = "token_2022")]
pub mod token_interface;

View File

@ -13,8 +13,12 @@ pub fn build_memo<'info>(ctx: CpiContext<'_, '_, '_, 'info, BuildMemo>, memo: &[
.map(|account| account.key)
.collect::<Vec<_>>(),
);
solana_program::program::invoke_signed(&ix, &ctx.remaining_accounts, ctx.signer_seeds)
.map_err(Into::into)
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ctx.remaining_accounts,
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]

View File

@ -1,9 +1,9 @@
use anchor_lang::context::CpiContext;
use anchor_lang::error::ErrorCode;
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::solana_program::sysvar;
use anchor_lang::{system_program, Accounts, Result, ToAccountInfos};
use solana_program::account_info::AccountInfo;
use solana_program::pubkey::Pubkey;
use solana_program::sysvar;
use std::ops::Deref;
pub use mpl_token_metadata;
@ -23,7 +23,7 @@ pub fn approve_collection_authority<'info>(
update_authority: *ctx.accounts.update_authority.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -48,7 +48,7 @@ pub fn bubblegum_set_collection_size<'info>(
set_collection_size_args: mpl_token_metadata::types::SetCollectionSizeArgs { size },
},
);
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -72,7 +72,7 @@ pub fn burn_edition_nft<'info>(
spl_token_program: *ctx.accounts.spl_token.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -109,7 +109,7 @@ pub fn burn_nft<'info>(
token_account: *ctx.accounts.token.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -143,7 +143,7 @@ pub fn create_metadata_accounts_v3<'info>(
is_mutable,
},
);
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -170,7 +170,7 @@ pub fn update_metadata_accounts_v2<'info>(
is_mutable,
},
);
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -196,7 +196,7 @@ pub fn create_master_edition_v3<'info>(
.instruction(
mpl_token_metadata::instructions::CreateMasterEditionV3InstructionArgs { max_supply },
);
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -230,7 +230,7 @@ pub fn mint_new_edition_from_master_edition_via_token<'info>(
mpl_token_metadata::types::MintNewEditionFromMasterEditionViaTokenArgs { edition },
},
);
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -249,7 +249,7 @@ pub fn revoke_collection_authority<'info>(
revoke_authority: *ctx.accounts.revoke_authority.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -273,7 +273,7 @@ pub fn set_collection_size<'info>(
set_collection_size_args: mpl_token_metadata::types::SetCollectionSizeArgs { size },
},
);
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -295,7 +295,7 @@ pub fn verify_collection<'info>(
payer: *ctx.accounts.payer.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -317,7 +317,7 @@ pub fn verify_sized_collection_item<'info>(
payer: *ctx.accounts.payer.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -340,7 +340,7 @@ pub fn set_and_verify_collection<'info>(
update_authority: *ctx.accounts.update_authority.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -363,7 +363,7 @@ pub fn set_and_verify_sized_collection_item<'info>(
update_authority: *ctx.accounts.update_authority.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -382,7 +382,7 @@ pub fn freeze_delegated_account<'info>(
token_program: *ctx.accounts.token_program.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -401,7 +401,7 @@ pub fn thaw_delegated_account<'info>(
token_program: *ctx.accounts.token_program.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -418,7 +418,7 @@ pub fn update_primary_sale_happened_via_token<'info>(
token: *ctx.accounts.token.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -437,7 +437,7 @@ pub fn set_token_standard<'info>(
update_authority: *ctx.accounts.update_authority.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -451,7 +451,7 @@ pub fn sign_metadata<'info>(ctx: CpiContext<'_, '_, '_, 'info, SignMetadata<'inf
metadata: *ctx.accounts.metadata.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -467,7 +467,7 @@ pub fn remove_creator_verification<'info>(
metadata: *ctx.accounts.metadata.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -495,7 +495,7 @@ pub fn utilize<'info>(
use_authority_record,
}
.instruction(mpl_token_metadata::instructions::UtilizeInstructionArgs { number_of_uses });
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -516,7 +516,7 @@ pub fn unverify_collection<'info>(
metadata: *ctx.accounts.metadata.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
@ -538,7 +538,7 @@ pub fn unverify_sized_collection_item<'info>(
payer: *ctx.accounts.payer.key,
}
.instruction();
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,

View File

@ -1,4 +1,4 @@
use anchor_lang::solana_program::declare_id;
use anchor_lang::declare_id;
pub use srm::ID as SRM;
mod srm {

View File

@ -36,7 +36,7 @@ pub fn authorize<'info>(
if let Some(c) = custodian {
account_infos.push(c);
}
solana_program::program::invoke_signed(&ix, &account_infos, ctx.signer_seeds)
anchor_lang::solana_program::program::invoke_signed(&ix, &account_infos, ctx.signer_seeds)
.map_err(Into::into)
}
@ -62,7 +62,7 @@ pub fn withdraw<'info>(
if let Some(c) = custodian {
account_infos.push(c);
}
solana_program::program::invoke_signed(&ix, &account_infos, ctx.signer_seeds)
anchor_lang::solana_program::program::invoke_signed(&ix, &account_infos, ctx.signer_seeds)
.map_err(Into::into)
}
@ -70,7 +70,7 @@ pub fn deactivate_stake<'info>(
ctx: CpiContext<'_, '_, '_, 'info, DeactivateStake<'info>>,
) -> Result<()> {
let ix = stake::instruction::deactivate_stake(ctx.accounts.stake.key, ctx.accounts.staker.key);
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.stake, ctx.accounts.clock, ctx.accounts.staker],
ctx.signer_seeds,

View File

@ -20,7 +20,7 @@ pub fn transfer<'info>(
&[],
amount,
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.from, ctx.accounts.to, ctx.accounts.authority],
ctx.signer_seeds,
@ -43,7 +43,7 @@ pub fn transfer_checked<'info>(
amount,
decimals,
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.from,
@ -68,7 +68,7 @@ pub fn mint_to<'info>(
&[],
amount,
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.to, ctx.accounts.mint, ctx.accounts.authority],
ctx.signer_seeds,
@ -85,7 +85,7 @@ pub fn burn<'info>(ctx: CpiContext<'_, '_, '_, 'info, Burn<'info>>, amount: u64)
&[],
amount,
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.from, ctx.accounts.mint, ctx.accounts.authority],
ctx.signer_seeds,
@ -105,7 +105,7 @@ pub fn approve<'info>(
&[],
amount,
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.to,
@ -132,7 +132,7 @@ pub fn approve_checked<'info>(
amount,
decimals,
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.to,
@ -152,7 +152,7 @@ pub fn revoke<'info>(ctx: CpiContext<'_, '_, '_, 'info, Revoke<'info>>) -> Resul
ctx.accounts.authority.key,
&[],
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.source, ctx.accounts.authority],
ctx.signer_seeds,
@ -169,7 +169,7 @@ pub fn initialize_account<'info>(
ctx.accounts.mint.key,
ctx.accounts.authority.key,
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.account,
@ -191,7 +191,7 @@ pub fn initialize_account3<'info>(
ctx.accounts.mint.key,
ctx.accounts.authority.key,
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.account, ctx.accounts.mint],
ctx.signer_seeds,
@ -207,7 +207,7 @@ pub fn close_account<'info>(ctx: CpiContext<'_, '_, '_, 'info, CloseAccount<'inf
ctx.accounts.authority.key,
&[], // TODO: support multisig
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.account,
@ -229,7 +229,7 @@ pub fn freeze_account<'info>(
ctx.accounts.authority.key,
&[], // TODO: Support multisig signers.
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.account,
@ -249,7 +249,7 @@ pub fn thaw_account<'info>(ctx: CpiContext<'_, '_, '_, 'info, ThawAccount<'info>
ctx.accounts.authority.key,
&[], // TODO: Support multisig signers.
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.account,
@ -274,7 +274,7 @@ pub fn initialize_mint<'info>(
freeze_authority,
decimals,
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.mint, ctx.accounts.rent],
ctx.signer_seeds,
@ -295,7 +295,7 @@ pub fn initialize_mint2<'info>(
freeze_authority,
decimals,
)?;
solana_program::program::invoke_signed(&ix, &[ctx.accounts.mint], ctx.signer_seeds)
anchor_lang::solana_program::program::invoke_signed(&ix, &[ctx.accounts.mint], ctx.signer_seeds)
.map_err(Into::into)
}
@ -317,7 +317,7 @@ pub fn set_authority<'info>(
ctx.accounts.current_authority.key,
&[], // TODO: Support multisig signers.
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.account_or_mint, ctx.accounts.current_authority],
ctx.signer_seeds,
@ -327,8 +327,12 @@ pub fn set_authority<'info>(
pub fn sync_native<'info>(ctx: CpiContext<'_, '_, '_, 'info, SyncNative<'info>>) -> Result<()> {
let ix = spl_token::instruction::sync_native(&spl_token::ID, ctx.accounts.account.key)?;
solana_program::program::invoke_signed(&ix, &[ctx.accounts.account], ctx.signer_seeds)
.map_err(Into::into)
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.account],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
@ -439,7 +443,7 @@ pub struct SyncNative<'info> {
pub account: AccountInfo<'info>,
}
#[derive(Clone, Debug, Default, PartialEq)]
#[derive(Clone, Debug, Default, PartialEq, Copy)]
pub struct TokenAccount(spl_token::state::Account);
impl TokenAccount {
@ -470,7 +474,7 @@ impl Deref for TokenAccount {
}
}
#[derive(Clone, Debug, Default, PartialEq)]
#[derive(Clone, Debug, Default, PartialEq, Copy)]
pub struct Mint(spl_token::state::Mint);
impl Mint {

View File

@ -23,7 +23,7 @@ pub fn transfer<'info>(
&[],
amount,
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.from, ctx.accounts.to, ctx.accounts.authority],
ctx.signer_seeds,
@ -46,7 +46,7 @@ pub fn transfer_checked<'info>(
amount,
decimals,
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.from,
@ -71,7 +71,7 @@ pub fn mint_to<'info>(
&[],
amount,
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.to, ctx.accounts.mint, ctx.accounts.authority],
ctx.signer_seeds,
@ -88,7 +88,7 @@ pub fn burn<'info>(ctx: CpiContext<'_, '_, '_, 'info, Burn<'info>>, amount: u64)
&[],
amount,
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.from, ctx.accounts.mint, ctx.accounts.authority],
ctx.signer_seeds,
@ -108,7 +108,7 @@ pub fn approve<'info>(
&[],
amount,
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.to,
@ -127,7 +127,7 @@ pub fn revoke<'info>(ctx: CpiContext<'_, '_, '_, 'info, Revoke<'info>>) -> Resul
ctx.accounts.authority.key,
&[],
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.source, ctx.accounts.authority],
ctx.signer_seeds,
@ -144,7 +144,7 @@ pub fn initialize_account<'info>(
ctx.accounts.mint.key,
ctx.accounts.authority.key,
)?;
solana_program::program::invoke(
anchor_lang::solana_program::program::invoke(
&ix,
&[
ctx.accounts.account,
@ -165,7 +165,7 @@ pub fn initialize_account3<'info>(
ctx.accounts.mint.key,
ctx.accounts.authority.key,
)?;
solana_program::program::invoke(&ix, &[ctx.accounts.account, ctx.accounts.mint])
anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.account, ctx.accounts.mint])
.map_err(Into::into)
}
@ -177,7 +177,7 @@ pub fn close_account<'info>(ctx: CpiContext<'_, '_, '_, 'info, CloseAccount<'inf
ctx.accounts.authority.key,
&[], // TODO: support multisig
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.account,
@ -199,7 +199,7 @@ pub fn freeze_account<'info>(
ctx.accounts.authority.key,
&[], // TODO: Support multisig signers.
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.account,
@ -219,7 +219,7 @@ pub fn thaw_account<'info>(ctx: CpiContext<'_, '_, '_, 'info, ThawAccount<'info>
ctx.accounts.authority.key,
&[], // TODO: Support multisig signers.
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.account,
@ -244,7 +244,7 @@ pub fn initialize_mint<'info>(
freeze_authority,
decimals,
)?;
solana_program::program::invoke(&ix, &[ctx.accounts.mint, ctx.accounts.rent])
anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.mint, ctx.accounts.rent])
.map_err(Into::into)
}
@ -261,7 +261,7 @@ pub fn initialize_mint2<'info>(
freeze_authority,
decimals,
)?;
solana_program::program::invoke(&ix, &[ctx.accounts.mint]).map_err(Into::into)
anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.mint]).map_err(Into::into)
}
pub fn set_authority<'info>(
@ -282,7 +282,7 @@ pub fn set_authority<'info>(
ctx.accounts.current_authority.key,
&[], // TODO: Support multisig signers.
)?;
solana_program::program::invoke_signed(
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.account_or_mint, ctx.accounts.current_authority],
ctx.signer_seeds,
@ -292,7 +292,7 @@ pub fn set_authority<'info>(
pub fn sync_native<'info>(ctx: CpiContext<'_, '_, '_, 'info, SyncNative<'info>>) -> Result<()> {
let ix = spl_token_2022::instruction::sync_native(ctx.program.key, ctx.accounts.account.key)?;
solana_program::program::invoke(&ix, &[ctx.accounts.account]).map_err(Into::into)
anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.account]).map_err(Into::into)
}
pub fn get_account_data_size<'info>(
@ -304,15 +304,15 @@ pub fn get_account_data_size<'info>(
ctx.accounts.mint.key,
extension_types,
)?;
solana_program::program::invoke(&ix, &[ctx.accounts.mint])?;
solana_program::program::get_return_data()
.ok_or(solana_program::program_error::ProgramError::InvalidInstructionData)
anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.mint])?;
anchor_lang::solana_program::program::get_return_data()
.ok_or(anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData)
.and_then(|(key, data)| {
if key != *ctx.program.key {
Err(solana_program::program_error::ProgramError::IncorrectProgramId)
Err(anchor_lang::solana_program::program_error::ProgramError::IncorrectProgramId)
} else {
data.try_into().map(u64::from_le_bytes).map_err(|_| {
solana_program::program_error::ProgramError::InvalidInstructionData
anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData
})
}
})
@ -328,7 +328,7 @@ pub fn initialize_mint_close_authority<'info>(
ctx.accounts.mint.key,
close_authority,
)?;
solana_program::program::invoke(&ix, &[ctx.accounts.mint]).map_err(Into::into)
anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.mint]).map_err(Into::into)
}
pub fn initialize_immutable_owner<'info>(
@ -338,7 +338,7 @@ pub fn initialize_immutable_owner<'info>(
ctx.program.key,
ctx.accounts.account.key,
)?;
solana_program::program::invoke(&ix, &[ctx.accounts.account]).map_err(Into::into)
anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.account]).map_err(Into::into)
}
pub fn amount_to_ui_amount<'info>(
@ -350,15 +350,15 @@ pub fn amount_to_ui_amount<'info>(
ctx.accounts.account.key,
amount,
)?;
solana_program::program::invoke(&ix, &[ctx.accounts.account])?;
solana_program::program::get_return_data()
.ok_or(solana_program::program_error::ProgramError::InvalidInstructionData)
anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.account])?;
anchor_lang::solana_program::program::get_return_data()
.ok_or(anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData)
.and_then(|(key, data)| {
if key != *ctx.program.key {
Err(solana_program::program_error::ProgramError::IncorrectProgramId)
Err(anchor_lang::solana_program::program_error::ProgramError::IncorrectProgramId)
} else {
String::from_utf8(data).map_err(|_| {
solana_program::program_error::ProgramError::InvalidInstructionData
anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData
})
}
})
@ -374,15 +374,15 @@ pub fn ui_amount_to_amount<'info>(
ctx.accounts.account.key,
ui_amount,
)?;
solana_program::program::invoke(&ix, &[ctx.accounts.account])?;
solana_program::program::get_return_data()
.ok_or(solana_program::program_error::ProgramError::InvalidInstructionData)
anchor_lang::solana_program::program::invoke(&ix, &[ctx.accounts.account])?;
anchor_lang::solana_program::program::get_return_data()
.ok_or(anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData)
.and_then(|(key, data)| {
if key != *ctx.program.key {
Err(solana_program::program_error::ProgramError::IncorrectProgramId)
Err(anchor_lang::solana_program::program_error::ProgramError::IncorrectProgramId)
} else {
data.try_into().map(u64::from_le_bytes).map_err(|_| {
solana_program::program_error::ProgramError::InvalidInstructionData
anchor_lang::solana_program::program_error::ProgramError::InvalidInstructionData
})
}
})
@ -522,7 +522,3 @@ impl anchor_lang::Id for Token2022 {
ID
}
}
// Field parsers to save compute. All account validation is assumed to be done
// outside of these methods.
pub use crate::token::accessor;

View File

@ -0,0 +1 @@
// waiting for labs to merge

View File

@ -0,0 +1 @@
// waiting for labs to merge

View File

@ -0,0 +1,50 @@
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts};
pub fn cpi_guard_enable<'info>(ctx: CpiContext<'_, '_, '_, 'info, CpiGuard<'info>>) -> Result<()> {
let ix = spl_token_2022::extension::cpi_guard::instruction::enable_cpi_guard(
ctx.accounts.token_program_id.key,
ctx.accounts.account.key,
ctx.accounts.account.owner,
&[],
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.account,
ctx.accounts.owner,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
pub fn cpi_guard_disable<'info>(ctx: CpiContext<'_, '_, '_, 'info, CpiGuard<'info>>) -> Result<()> {
let ix = spl_token_2022::extension::cpi_guard::instruction::disable_cpi_guard(
ctx.accounts.token_program_id.key,
ctx.accounts.account.key,
ctx.accounts.account.owner,
&[],
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.account,
ctx.accounts.owner,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct CpiGuard<'info> {
pub token_program_id: AccountInfo<'info>,
pub account: AccountInfo<'info>,
pub owner: AccountInfo<'info>,
}

View File

@ -0,0 +1,59 @@
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts};
use spl_token_2022::state::AccountState;
pub fn default_account_state_initialize<'info>(
ctx: CpiContext<'_, '_, '_, 'info, DefaultAccountStateInitialize<'info>>,
state: &AccountState,
) -> Result<()> {
let ix = spl_token_2022::extension::default_account_state::instruction::initialize_default_account_state(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
state
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.token_program_id, ctx.accounts.mint],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct DefaultAccountStateInitialize<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
}
pub fn default_account_state_update<'info>(
ctx: CpiContext<'_, '_, '_, 'info, DefaultAccountStateUpdate<'info>>,
state: &AccountState,
) -> Result<()> {
let ix = spl_token_2022::extension::default_account_state::instruction::update_default_account_state(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
ctx.accounts.freeze_authority.key,
&[],
state
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.mint,
ctx.accounts.freeze_authority,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct DefaultAccountStateUpdate<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
pub freeze_authority: AccountInfo<'info>,
}

View File

@ -0,0 +1,59 @@
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts};
pub fn group_member_pointer_initialize<'info>(
ctx: CpiContext<'_, '_, '_, 'info, GroupMemberPointerInitialize<'info>>,
authority: Option<Pubkey>,
member_address: Option<Pubkey>,
) -> Result<()> {
let ix = spl_token_2022::extension::group_member_pointer::instruction::initialize(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
authority,
member_address,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.token_program_id, ctx.accounts.mint],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct GroupMemberPointerInitialize<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
}
pub fn group_member_pointer_update<'info>(
ctx: CpiContext<'_, '_, '_, 'info, GroupMemberPointerUpdate<'info>>,
member_address: Option<Pubkey>,
) -> Result<()> {
let ix = spl_token_2022::extension::group_member_pointer::instruction::update(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
ctx.accounts.authority.key,
&[],
member_address,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.mint,
ctx.accounts.authority,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct GroupMemberPointerUpdate<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
pub authority: AccountInfo<'info>,
}

View File

@ -0,0 +1,55 @@
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts};
pub fn group_pointer_initialize<'info>(
ctx: CpiContext<'_, '_, '_, 'info, GroupPointerInitialize<'info>>,
authority: Option<Pubkey>,
group_address: Option<Pubkey>,
) -> Result<()> {
let ix = spl_token_2022::extension::group_pointer::instruction::initialize(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
authority,
group_address,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.token_program_id, ctx.accounts.mint],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct GroupPointerInitialize<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
}
pub fn group_pointer_update<'info>(
ctx: CpiContext<'_, '_, '_, 'info, GroupPointerUpdate<'info>>,
group_address: Option<Pubkey>,
) -> Result<()> {
let ix = spl_token_2022::extension::group_pointer::instruction::update(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
ctx.accounts.authority.key,
&[&ctx.accounts.authority.key],
group_address,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.token_program_id, ctx.accounts.mint],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct GroupPointerUpdate<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
pub authority: AccountInfo<'info>,
}

View File

@ -0,0 +1,25 @@
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts};
pub fn immutable_owner_initialize<'info>(
ctx: CpiContext<'_, '_, '_, 'info, ImmutableOwnerInitialize<'info>>,
) -> Result<()> {
let ix = spl_token_2022::instruction::initialize_immutable_owner(
ctx.accounts.token_program_id.key,
ctx.accounts.token_account.key,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.token_program_id, ctx.accounts.token_account],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct ImmutableOwnerInitialize<'info> {
pub token_program_id: AccountInfo<'info>,
pub token_account: AccountInfo<'info>,
}

View File

@ -0,0 +1,59 @@
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts};
pub fn interest_bearing_mint_initialize<'info>(
ctx: CpiContext<'_, '_, '_, 'info, InterestBearingMintInitialize<'info>>,
rate_authority: Option<Pubkey>,
rate: i16,
) -> Result<()> {
let ix = spl_token_2022::extension::interest_bearing_mint::instruction::initialize(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
rate_authority,
rate,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.token_program_id, ctx.accounts.mint],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct InterestBearingMintInitialize<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
}
pub fn interest_bearing_mint_update_rate<'info>(
ctx: CpiContext<'_, '_, '_, 'info, InterestBearingMintUpdateRate<'info>>,
rate: i16,
) -> Result<()> {
let ix = spl_token_2022::extension::interest_bearing_mint::instruction::update_rate(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
ctx.accounts.rate_authority.key,
&[],
rate,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.mint,
ctx.accounts.rate_authority,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct InterestBearingMintUpdateRate<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
pub rate_authority: AccountInfo<'info>,
}

View File

@ -0,0 +1,54 @@
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts};
pub fn memo_transfer_initialize<'info>(
ctx: CpiContext<'_, '_, '_, 'info, MemoTransfer<'info>>,
) -> Result<()> {
let ix = spl_token_2022::extension::memo_transfer::instruction::enable_required_transfer_memos(
ctx.accounts.token_program_id.key,
ctx.accounts.account.key,
ctx.accounts.owner.key,
&[],
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.account,
ctx.accounts.owner,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
pub fn memo_transfer_disable<'info>(
ctx: CpiContext<'_, '_, '_, 'info, MemoTransfer<'info>>,
) -> Result<()> {
let ix =
spl_token_2022::extension::memo_transfer::instruction::disable_required_transfer_memos(
ctx.accounts.token_program_id.key,
ctx.accounts.account.key,
ctx.accounts.owner.key,
&[],
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.account,
ctx.accounts.owner,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct MemoTransfer<'info> {
pub token_program_id: AccountInfo<'info>,
pub account: AccountInfo<'info>,
pub owner: AccountInfo<'info>,
}

View File

@ -0,0 +1,29 @@
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts};
pub fn metadata_pointer_initialize<'info>(
ctx: CpiContext<'_, '_, '_, 'info, MetadataPointerInitialize<'info>>,
authority: Option<Pubkey>,
metadata_address: Option<Pubkey>,
) -> Result<()> {
let ix = spl_token_2022::extension::metadata_pointer::instruction::initialize(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
authority,
metadata_address,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.token_program_id, ctx.accounts.mint],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct MetadataPointerInitialize<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
}

View File

@ -0,0 +1,27 @@
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts};
pub fn mint_close_authority_initialize<'info>(
ctx: CpiContext<'_, '_, '_, 'info, MintCloseAuthorityInitialize<'info>>,
authority: Option<&Pubkey>,
) -> Result<()> {
let ix = spl_token_2022::instruction::initialize_mint_close_authority(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
authority,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.token_program_id, ctx.accounts.mint],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct MintCloseAuthorityInitialize<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
}

View File

@ -0,0 +1,36 @@
pub mod confidential_transfer;
pub mod confidential_transfer_fee;
pub mod cpi_guard;
pub mod default_account_state;
pub mod group_member_pointer;
pub mod group_pointer;
pub mod immutable_owner;
pub mod interest_bearing_mint;
pub mod memo_transfer;
pub mod metadata_pointer;
pub mod mint_close_authority;
pub mod non_transferable;
pub mod permanent_delegate;
pub mod token_group;
pub mod token_metadata;
pub mod transfer_fee;
pub mod transfer_hook;
pub use cpi_guard::*;
pub use default_account_state::*;
pub use group_member_pointer::*;
pub use group_pointer::*;
pub use immutable_owner::*;
pub use interest_bearing_mint::*;
pub use memo_transfer::*;
pub use metadata_pointer::*;
pub use mint_close_authority::*;
pub use non_transferable::*;
pub use permanent_delegate::*;
pub use token_group::*;
pub use token_metadata::*;
pub use transfer_fee::*;
pub use transfer_hook::*;
pub use spl_pod;
pub use spl_token_metadata_interface;

View File

@ -0,0 +1,25 @@
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts};
pub fn non_transferable_mint_initialize<'info>(
ctx: CpiContext<'_, '_, '_, 'info, NonTransferableMintInitialize<'info>>,
) -> Result<()> {
let ix = spl_token_2022::instruction::initialize_non_transferable_mint(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.token_program_id, ctx.accounts.mint],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct NonTransferableMintInitialize<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
}

View File

@ -0,0 +1,27 @@
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts};
pub fn permanent_delegate_initialize<'info>(
ctx: CpiContext<'_, '_, '_, 'info, PermanentDelegateInitialize<'info>>,
permanent_delegate: &Pubkey,
) -> Result<()> {
let ix = spl_token_2022::instruction::initialize_permanent_delegate(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
permanent_delegate,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.token_program_id, ctx.accounts.mint],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct PermanentDelegateInitialize<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
}

View File

@ -0,0 +1,74 @@
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts};
pub fn token_group_initialize<'info>(
ctx: CpiContext<'_, '_, '_, 'info, TokenGroupInitialize<'info>>,
update_authority: Option<Pubkey>,
max_size: u32,
) -> Result<()> {
let ix = spl_token_group_interface::instruction::initialize_group(
ctx.accounts.token_program_id.key,
ctx.accounts.group.key,
ctx.accounts.mint.key,
ctx.accounts.mint_authority.key,
update_authority,
max_size,
);
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.group,
ctx.accounts.mint,
ctx.accounts.mint_authority,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct TokenGroupInitialize<'info> {
pub token_program_id: AccountInfo<'info>,
pub group: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
pub mint_authority: AccountInfo<'info>,
}
pub fn token_member_initialize<'info>(
ctx: CpiContext<'_, '_, '_, 'info, TokenMemberInitialize<'info>>,
) -> Result<()> {
let ix = spl_token_group_interface::instruction::initialize_member(
ctx.accounts.token_program_id.key,
ctx.accounts.member.key,
ctx.accounts.member_mint.key,
ctx.accounts.member_mint_authority.key,
ctx.accounts.group.key,
ctx.accounts.group_update_authority.key,
);
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.member,
ctx.accounts.member_mint,
ctx.accounts.member_mint_authority,
ctx.accounts.group,
ctx.accounts.group_update_authority,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct TokenMemberInitialize<'info> {
pub token_program_id: AccountInfo<'info>,
pub member: AccountInfo<'info>,
pub member_mint: AccountInfo<'info>,
pub member_mint_authority: AccountInfo<'info>,
pub group: AccountInfo<'info>,
pub group_update_authority: AccountInfo<'info>,
}

View File

@ -0,0 +1,107 @@
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts};
use spl_pod::optional_keys::OptionalNonZeroPubkey;
use spl_token_metadata_interface::state::Field;
pub fn token_metadata_initialize<'info>(
ctx: CpiContext<'_, '_, '_, 'info, TokenMetadataInitialize<'info>>,
name: String,
symbol: String,
uri: String,
) -> Result<()> {
let ix = spl_token_metadata_interface::instruction::initialize(
ctx.accounts.token_program_id.key,
ctx.accounts.metadata.key,
ctx.accounts.update_authority.key,
ctx.accounts.mint.key,
ctx.accounts.mint_authority.key,
name,
symbol,
uri,
);
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.metadata,
ctx.accounts.update_authority,
ctx.accounts.mint,
ctx.accounts.mint_authority,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct TokenMetadataInitialize<'info> {
pub token_program_id: AccountInfo<'info>,
pub metadata: AccountInfo<'info>,
pub update_authority: AccountInfo<'info>,
pub mint_authority: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
}
pub fn token_metadata_update_authority<'info>(
ctx: CpiContext<'_, '_, '_, 'info, TokenMetadataUpdateAuthority<'info>>,
new_authority: OptionalNonZeroPubkey,
) -> Result<()> {
let ix = spl_token_metadata_interface::instruction::update_authority(
ctx.accounts.token_program_id.key,
ctx.accounts.metadata.key,
ctx.accounts.current_authority.key,
new_authority,
);
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.metadata,
ctx.accounts.current_authority,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct TokenMetadataUpdateAuthority<'info> {
pub token_program_id: AccountInfo<'info>,
pub metadata: AccountInfo<'info>,
pub current_authority: AccountInfo<'info>,
pub new_authority: AccountInfo<'info>,
}
pub fn token_metadata_update_field<'info>(
ctx: CpiContext<'_, '_, '_, 'info, TokenMetadataUpdateField<'info>>,
field: Field,
value: String,
) -> Result<()> {
let ix = spl_token_metadata_interface::instruction::update_field(
ctx.accounts.token_program_id.key,
ctx.accounts.metadata.key,
ctx.accounts.update_authority.key,
field,
value,
);
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.metadata,
ctx.accounts.update_authority,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct TokenMetadataUpdateField<'info> {
pub token_program_id: AccountInfo<'info>,
pub metadata: AccountInfo<'info>,
pub update_authority: AccountInfo<'info>,
}

View File

@ -0,0 +1,160 @@
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts};
pub fn transfer_fee_initialize<'info>(
ctx: CpiContext<'_, '_, '_, 'info, TransferFeeInitialize<'info>>,
transfer_fee_config_authority: Option<&Pubkey>,
withdraw_withheld_authority: Option<&Pubkey>,
transfer_fee_basis_points: u16,
maximum_fee: u64,
) -> Result<()> {
let ix = spl_token_2022::extension::transfer_fee::instruction::initialize_transfer_fee_config(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
transfer_fee_config_authority,
withdraw_withheld_authority,
transfer_fee_basis_points,
maximum_fee,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.token_program_id, ctx.accounts.mint],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct TransferFeeInitialize<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
}
pub fn transfer_fee_set<'info>(
ctx: CpiContext<'_, '_, '_, 'info, TransferFeeSetTransferFee<'info>>,
transfer_fee_basis_points: u16,
maximum_fee: u64,
) -> Result<()> {
let ix = spl_token_2022::extension::transfer_fee::instruction::set_transfer_fee(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
ctx.accounts.authority.key,
&[],
transfer_fee_basis_points,
maximum_fee,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.mint,
ctx.accounts.authority,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct TransferFeeSetTransferFee<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
pub authority: AccountInfo<'info>,
}
pub fn transfer_checked_with_fee<'info>(
ctx: CpiContext<'_, '_, '_, 'info, TransferCheckedWithFee<'info>>,
amount: u64,
decimals: u8,
fee: u64,
) -> Result<()> {
let ix = spl_token_2022::extension::transfer_fee::instruction::transfer_checked_with_fee(
ctx.accounts.token_program_id.key,
ctx.accounts.source.key,
ctx.accounts.mint.key,
ctx.accounts.destination.key,
ctx.accounts.authority.key,
&[],
amount,
decimals,
fee,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.source,
ctx.accounts.mint,
ctx.accounts.destination,
ctx.accounts.authority,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct TransferCheckedWithFee<'info> {
pub token_program_id: AccountInfo<'info>,
pub source: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
pub destination: AccountInfo<'info>,
pub authority: AccountInfo<'info>,
}
pub fn harvest_withheld_tokens_to_mint<'info>(
ctx: CpiContext<'_, '_, '_, 'info, HarvestWithheldTokensToMint<'info>>,
sources: Vec<AccountInfo<'info>>,
) -> Result<()> {
let ix = spl_token_2022::extension::transfer_fee::instruction::harvest_withheld_tokens_to_mint(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
sources.iter().map(|a| a.key).collect::<Vec<_>>().as_slice(),
)?;
let mut account_infos = vec![ctx.accounts.token_program_id, ctx.accounts.mint];
account_infos.extend_from_slice(&sources);
anchor_lang::solana_program::program::invoke_signed(&ix, &account_infos, ctx.signer_seeds)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct HarvestWithheldTokensToMint<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
}
pub fn withdraw_withheld_tokens_from_mint<'info>(
ctx: CpiContext<'_, '_, '_, 'info, WithdrawWithheldTokensFromMint<'info>>,
) -> Result<()> {
let ix =
spl_token_2022::extension::transfer_fee::instruction::withdraw_withheld_tokens_from_mint(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
ctx.accounts.destination.key,
ctx.accounts.authority.key,
&[],
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.mint,
ctx.accounts.destination,
ctx.accounts.authority,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct WithdrawWithheldTokensFromMint<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
pub destination: AccountInfo<'info>,
pub authority: AccountInfo<'info>,
}

View File

@ -0,0 +1,59 @@
use anchor_lang::solana_program::account_info::AccountInfo;
use anchor_lang::solana_program::pubkey::Pubkey;
use anchor_lang::Result;
use anchor_lang::{context::CpiContext, Accounts};
pub fn transfer_hook_initialize<'info>(
ctx: CpiContext<'_, '_, '_, 'info, TransferHookInitialize<'info>>,
authority: Option<Pubkey>,
transfer_hook_program_id: Option<Pubkey>,
) -> Result<()> {
let ix = spl_token_2022::extension::transfer_hook::instruction::initialize(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
authority,
transfer_hook_program_id,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[ctx.accounts.token_program_id, ctx.accounts.mint],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct TransferHookInitialize<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
}
pub fn transfer_hook_update<'info>(
ctx: CpiContext<'_, '_, '_, 'info, TransferHookUpdate<'info>>,
transfer_hook_program_id: Option<Pubkey>,
) -> Result<()> {
let ix = spl_token_2022::extension::transfer_hook::instruction::update(
ctx.accounts.token_program_id.key,
ctx.accounts.mint.key,
ctx.accounts.authority.key,
&[],
transfer_hook_program_id,
)?;
anchor_lang::solana_program::program::invoke_signed(
&ix,
&[
ctx.accounts.token_program_id,
ctx.accounts.mint,
ctx.accounts.authority,
],
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct TransferHookUpdate<'info> {
pub token_program_id: AccountInfo<'info>,
pub mint: AccountInfo<'info>,
pub authority: AccountInfo<'info>,
}

View File

@ -1,11 +1,19 @@
use anchor_lang::solana_program::program_pack::Pack;
use anchor_lang::solana_program::pubkey::Pubkey;
use spl_token_2022::extension::ExtensionType;
use spl_token_2022::{
extension::{BaseStateWithExtensions, Extension, StateWithExtensions},
solana_zk_token_sdk::instruction::Pod,
};
use std::ops::Deref;
pub use crate::token_2022::*;
#[cfg(feature = "token_2022_extensions")]
pub use crate::token_2022_extensions::*;
static IDS: [Pubkey; 2] = [spl_token::ID, spl_token_2022::ID];
#[derive(Clone, Debug, Default, PartialEq)]
#[derive(Clone, Debug, Default, PartialEq, Copy)]
pub struct TokenAccount(spl_token_2022::state::Account);
impl anchor_lang::AccountDeserialize for TokenAccount {
@ -34,7 +42,7 @@ impl Deref for TokenAccount {
}
}
#[derive(Clone, Debug, Default, PartialEq)]
#[derive(Clone, Debug, Default, PartialEq, Copy)]
pub struct Mint(spl_token_2022::state::Mint);
impl anchor_lang::AccountDeserialize for Mint {
@ -69,3 +77,25 @@ impl anchor_lang::Ids for TokenInterface {
&IDS
}
}
pub type ExtensionsVec = Vec<ExtensionType>;
pub fn find_mint_account_size(extensions: Option<&ExtensionsVec>) -> anchor_lang::Result<usize> {
if let Some(extensions) = extensions {
Ok(ExtensionType::try_calculate_account_len::<
spl_token_2022::state::Mint,
>(extensions)?)
} else {
Ok(spl_token_2022::state::Mint::LEN)
}
}
pub fn get_mint_extension_data<T: Extension + Pod>(
account: &anchor_lang::solana_program::account_info::AccountInfo,
) -> anchor_lang::Result<T> {
let mint_data = account.data.borrow();
let mint_with_extension =
StateWithExtensions::<spl_token_2022::state::Mint>::unpack(&mint_data)?;
let extension_data = *mint_with_extension.get_extension::<T>()?;
Ok(extension_data)
}

View File

@ -1,6 +1,6 @@
{
"name": "anchor-cli-account",
"version": "0.29.0",
"version": "0.30.0",
"license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {

View File

@ -1,6 +1,6 @@
{
"name": "anchor-cli-idl",
"version": "0.29.0",
"version": "0.30.0",
"license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {

View File

@ -1,6 +1,6 @@
{
"name": "auction-house",
"version": "0.29.0",
"version": "0.30.0",
"license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {

View File

@ -557,6 +557,192 @@
}
}
},
"0.30.0": {
"solanaVersion": "1.18.8",
"result": {
"binarySize": {
"bench": 791008
},
"computeUnits": {
"accountInfo1": 601,
"accountInfo2": 923,
"accountInfo4": 1583,
"accountInfo8": 2975,
"accountEmptyInit1": 5034,
"accountEmpty1": 652,
"accountEmptyInit2": 9687,
"accountEmpty2": 1016,
"accountEmptyInit4": 18501,
"accountEmpty4": 1737,
"accountEmptyInit8": 36169,
"accountEmpty8": 3186,
"accountSizedInit1": 5106,
"accountSized1": 668,
"accountSizedInit2": 9828,
"accountSized2": 1046,
"accountSizedInit4": 18837,
"accountSized4": 1807,
"accountSizedInit8": 36761,
"accountSized8": 3326,
"accountUnsizedInit1": 5199,
"accountUnsized1": 702,
"accountUnsizedInit2": 10078,
"accountUnsized2": 1116,
"accountUnsizedInit4": 19259,
"accountUnsized4": 1953,
"accountUnsizedInit8": 37331,
"accountUnsized8": 3626,
"boxedAccountEmptyInit1": 5064,
"boxedAccountEmpty1": 671,
"boxedAccountEmptyInit2": 9721,
"boxedAccountEmpty2": 1052,
"boxedAccountEmptyInit4": 18582,
"boxedAccountEmpty4": 1811,
"boxedAccountEmptyInit8": 36329,
"boxedAccountEmpty8": 3357,
"boxedAccountSizedInit1": 5119,
"boxedAccountSized1": 686,
"boxedAccountSizedInit2": 9845,
"boxedAccountSized2": 1085,
"boxedAccountSizedInit4": 18825,
"boxedAccountSized4": 1874,
"boxedAccountSizedInit8": 36824,
"boxedAccountSized8": 3490,
"boxedAccountUnsizedInit1": 5207,
"boxedAccountUnsized1": 721,
"boxedAccountUnsizedInit2": 10015,
"boxedAccountUnsized2": 1157,
"boxedAccountUnsizedInit4": 19160,
"boxedAccountUnsized4": 2019,
"boxedAccountUnsizedInit8": 37496,
"boxedAccountUnsized8": 3776,
"boxedInterfaceAccountMint1": 1372,
"boxedInterfaceAccountMint2": 2293,
"boxedInterfaceAccountMint4": 4121,
"boxedInterfaceAccountMint8": 7811,
"boxedInterfaceAccountToken1": 2056,
"boxedInterfaceAccountToken2": 3660,
"boxedInterfaceAccountToken4": 6858,
"boxedInterfaceAccountToken8": 13284,
"interfaceAccountMint1": 1472,
"interfaceAccountMint2": 2631,
"interfaceAccountMint4": 4951,
"interfaceAccountMint8": 9588,
"interfaceAccountToken1": 2130,
"interfaceAccountToken2": 3928,
"interfaceAccountToken4": 7521,
"interface1": 600,
"interface2": 745,
"interface4": 1033,
"interface8": 1616,
"program1": 596,
"program2": 737,
"program4": 1019,
"program8": 1584,
"signer1": 580,
"signer2": 872,
"signer4": 1454,
"signer8": 2618,
"systemAccount1": 592,
"systemAccount2": 894,
"systemAccount4": 1497,
"systemAccount8": 2707,
"uncheckedAccount1": 563,
"uncheckedAccount2": 836,
"uncheckedAccount4": 1378,
"uncheckedAccount8": 2468
},
"stackMemory": {
"account_info1": 144,
"account_info2": 144,
"account_info4": 144,
"account_info8": 144,
"account_empty_init1": 144,
"account_empty_init2": 144,
"account_empty_init4": 192,
"account_empty_init8": 224,
"account_empty1": 144,
"account_empty2": 144,
"account_empty4": 144,
"account_empty8": 144,
"account_sized_init1": 176,
"account_sized_init2": 192,
"account_sized_init4": 224,
"account_sized_init8": 288,
"account_sized1": 144,
"account_sized2": 144,
"account_sized4": 144,
"account_sized8": 144,
"account_unsized_init1": 192,
"account_unsized_init2": 224,
"account_unsized_init4": 288,
"account_unsized_init8": 416,
"account_unsized1": 144,
"account_unsized2": 144,
"account_unsized4": 144,
"account_unsized8": 144,
"boxed_account_empty_init1": 144,
"boxed_account_empty_init2": 144,
"boxed_account_empty_init4": 192,
"boxed_account_empty_init8": 224,
"boxed_account_empty1": 144,
"boxed_account_empty2": 144,
"boxed_account_empty4": 144,
"boxed_account_empty8": 144,
"boxed_account_sized_init1": 144,
"boxed_account_sized_init2": 144,
"boxed_account_sized_init4": 192,
"boxed_account_sized_init8": 224,
"boxed_account_sized1": 144,
"boxed_account_sized2": 144,
"boxed_account_sized4": 144,
"boxed_account_sized8": 144,
"boxed_account_unsized_init1": 144,
"boxed_account_unsized_init2": 144,
"boxed_account_unsized_init4": 192,
"boxed_account_unsized_init8": 224,
"boxed_account_unsized1": 144,
"boxed_account_unsized2": 144,
"boxed_account_unsized4": 144,
"boxed_account_unsized8": 144,
"boxed_interface_account_mint1": 144,
"boxed_interface_account_mint2": 144,
"boxed_interface_account_mint4": 144,
"boxed_interface_account_mint8": 144,
"boxed_interface_account_token1": 144,
"boxed_interface_account_token2": 144,
"boxed_interface_account_token4": 144,
"boxed_interface_account_token8": 144,
"interface_account_mint1": 144,
"interface_account_mint2": 144,
"interface_account_mint4": 144,
"interface_account_mint8": 144,
"interface_account_token1": 144,
"interface_account_token2": 144,
"interface_account_token4": 144,
"interface1": 144,
"interface2": 144,
"interface4": 144,
"interface8": 144,
"program1": 144,
"program2": 144,
"program4": 144,
"program8": 144,
"signer1": 144,
"signer2": 144,
"signer4": 144,
"signer8": 144,
"system_account1": 144,
"system_account2": 144,
"system_account4": 144,
"system_account8": 144,
"unchecked_account1": 144,
"unchecked_account2": 144,
"unchecked_account4": 144,
"unchecked_account8": 144
}
}
},
"unreleased": {
"solanaVersion": "1.18.8",
"result": {

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "bench",
"version": "0.29.0",
"version": "0.30.0",
"license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {

View File

@ -1,6 +1,6 @@
{
"name": "cashiers-check",
"version": "0.29.0",
"version": "0.30.0",
"license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {

View File

@ -1,6 +1,6 @@
{
"name": "cfo",
"version": "0.29.0",
"version": "0.30.0",
"license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {

View File

@ -1,6 +1,6 @@
{
"name": "chat",
"version": "0.29.0",
"version": "0.30.0",
"license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {

View File

@ -1,6 +1,6 @@
{
"name": "composite",
"version": "0.29.0",
"version": "0.30.0",
"license": "(MIT OR Apache-2.0)",
"homepage": "https://github.com/coral-xyz/anchor#readme",
"bugs": {

Some files were not shown because too many files have changed in this diff Show More