Add `IdlBuild` trait (#2629)
This commit is contained in:
parent
fdda604d41
commit
b5f4796156
|
@ -43,8 +43,10 @@ anchor-attribute-program = { path = "./attribute/program", version = "0.28.0" }
|
|||
anchor-derive-accounts = { path = "./derive/accounts", version = "0.28.0" }
|
||||
anchor-derive-serde = { path = "./derive/serde", version = "0.28.0" }
|
||||
anchor-derive-space = { path = "./derive/space", version = "0.28.0" }
|
||||
|
||||
# `anchor-syn` should only be included with `idl-build` feature
|
||||
anchor-syn = { path = "./syn", version = "0.28.0", optional = true }
|
||||
|
||||
arrayref = "0.3"
|
||||
base64 = "0.13"
|
||||
bincode = "1"
|
||||
|
|
|
@ -405,10 +405,10 @@ pub fn zero_copy(
|
|||
#[cfg(feature = "idl-build")]
|
||||
{
|
||||
let no_docs = get_no_docs();
|
||||
let idl_gen_impl = gen_idl_gen_impl_for_struct(&account_strct, no_docs);
|
||||
let idl_build_impl = gen_idl_build_impl_for_struct(&account_strct, no_docs);
|
||||
return proc_macro::TokenStream::from(quote! {
|
||||
#ret
|
||||
#idl_gen_impl
|
||||
#idl_build_impl
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -48,10 +48,10 @@ pub fn event(
|
|||
|
||||
#[cfg(feature = "idl-build")]
|
||||
{
|
||||
let idl_gen = anchor_syn::idl::build::gen_idl_print_function_for_event(&event_strct);
|
||||
let idl_build = anchor_syn::idl::build::gen_idl_print_function_for_event(&event_strct);
|
||||
return proc_macro::TokenStream::from(quote! {
|
||||
#ret
|
||||
#idl_gen
|
||||
#idl_build
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -37,12 +37,12 @@ pub fn anchor_serialize(input: TokenStream) -> TokenStream {
|
|||
{
|
||||
let no_docs = get_no_docs();
|
||||
|
||||
let idl_gen_impl = match syn::parse(input).unwrap() {
|
||||
Item::Struct(item) => gen_idl_gen_impl_for_struct(&item, no_docs),
|
||||
Item::Enum(item) => gen_idl_gen_impl_for_enum(item, no_docs),
|
||||
let idl_build_impl = match syn::parse(input).unwrap() {
|
||||
Item::Struct(item) => gen_idl_build_impl_for_struct(&item, no_docs),
|
||||
Item::Enum(item) => gen_idl_build_impl_for_enum(item, no_docs),
|
||||
Item::Union(item) => {
|
||||
// unions are not included in the IDL - TODO print a warning
|
||||
idl_gen_impl_skeleton(quote! {None}, quote! {}, &item.ident, &item.generics)
|
||||
idl_build_impl_skeleton(quote! {None}, quote! {}, &item.ident, &item.generics)
|
||||
}
|
||||
// Derive macros can only be defined on structs, enums, and unions.
|
||||
_ => unreachable!(),
|
||||
|
@ -50,7 +50,7 @@ pub fn anchor_serialize(input: TokenStream) -> TokenStream {
|
|||
|
||||
return TokenStream::from(quote! {
|
||||
#ret
|
||||
#idl_gen_impl
|
||||
#idl_build_impl
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -50,19 +50,21 @@ pub use anchor_attribute_account::{account, declare_id, zero_copy};
|
|||
pub use anchor_attribute_constant::constant;
|
||||
pub use anchor_attribute_error::*;
|
||||
pub use anchor_attribute_event::{emit, event};
|
||||
#[cfg(feature = "event-cpi")]
|
||||
pub use anchor_attribute_event::{emit_cpi, event_cpi};
|
||||
pub use anchor_attribute_program::program;
|
||||
pub use anchor_derive_accounts::Accounts;
|
||||
pub use anchor_derive_serde::{AnchorDeserialize, AnchorSerialize};
|
||||
pub use anchor_derive_space::InitSpace;
|
||||
|
||||
/// Borsh is the default serialization format for instructions and accounts.
|
||||
pub use borsh::de::BorshDeserialize as AnchorDeserialize;
|
||||
pub use borsh::ser::BorshSerialize as AnchorSerialize;
|
||||
pub use solana_program;
|
||||
|
||||
#[cfg(feature = "event-cpi")]
|
||||
pub use anchor_attribute_event::{emit_cpi, event_cpi};
|
||||
|
||||
#[cfg(feature = "idl-build")]
|
||||
pub use anchor_syn;
|
||||
pub use anchor_syn::{self, idl::build::IdlBuild};
|
||||
|
||||
pub type Result<T> = std::result::Result<T, error::Error>;
|
||||
|
||||
|
@ -353,8 +355,6 @@ pub mod prelude {
|
|||
AccountsClose, AccountsExit, AnchorDeserialize, AnchorSerialize, Id, InitSpace, Key,
|
||||
Lamports, Owner, ProgramData, Result, Space, ToAccountInfo, ToAccountInfos, ToAccountMetas,
|
||||
};
|
||||
#[cfg(feature = "event-cpi")]
|
||||
pub use super::{emit_cpi, event_cpi};
|
||||
pub use anchor_attribute_error::*;
|
||||
pub use borsh;
|
||||
pub use error::*;
|
||||
|
@ -373,6 +373,12 @@ pub mod prelude {
|
|||
pub use solana_program::sysvar::stake_history::StakeHistory;
|
||||
pub use solana_program::sysvar::Sysvar as SolanaSysvar;
|
||||
pub use thiserror;
|
||||
|
||||
#[cfg(feature = "event-cpi")]
|
||||
pub use super::{emit_cpi, event_cpi};
|
||||
|
||||
#[cfg(feature = "idl-build")]
|
||||
pub use super::IdlBuild;
|
||||
}
|
||||
|
||||
/// Internal module used by macros and unstable apis.
|
||||
|
|
|
@ -36,10 +36,11 @@ pub fn generate(accs: &AccountsStruct) -> proc_macro2::TokenStream {
|
|||
{
|
||||
#![allow(warnings)]
|
||||
let no_docs = crate::idl::build::get_no_docs();
|
||||
let idl_gen_impl = crate::idl::build::gen_idl_gen_impl_for_accounts_strct(&accs, no_docs);
|
||||
let idl_build_impl =
|
||||
crate::idl::build::gen_idl_build_impl_for_accounts_struct(&accs, no_docs);
|
||||
return quote! {
|
||||
#ret
|
||||
#idl_gen_impl
|
||||
#idl_build_impl
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -103,10 +103,10 @@ pub fn generate(error: Error) -> proc_macro2::TokenStream {
|
|||
|
||||
#[cfg(feature = "idl-build")]
|
||||
{
|
||||
let idl_gen = gen_idl_print_function_for_error(&error);
|
||||
let idl_build = gen_idl_print_function_for_error(&error);
|
||||
return quote! {
|
||||
#ret
|
||||
#idl_gen
|
||||
#idl_build
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -40,11 +40,11 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
|
|||
#[cfg(feature = "idl-build")]
|
||||
{
|
||||
let no_docs = crate::idl::build::get_no_docs();
|
||||
let idl_gen = crate::idl::build::gen_idl_print_function_for_program(program, no_docs);
|
||||
let idl_build = crate::idl::build::gen_idl_print_function_for_program(program, no_docs);
|
||||
|
||||
return quote! {
|
||||
#ret
|
||||
#idl_gen
|
||||
#idl_build
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,39 @@
|
|||
pub use serde_json;
|
||||
|
||||
use crate::{parser::docs, AccountField, AccountsStruct, Error, Program};
|
||||
use heck::MixedCase;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
pub use serde_json;
|
||||
use syn::{Ident, ItemEnum, ItemStruct};
|
||||
|
||||
/// A trait that types must implement in order to generate the IDL via compilation.
|
||||
///
|
||||
/// This trait is automatically implemented for Anchor all types that use the `AnchorSerialize`
|
||||
/// proc macro. Note that manually implementing the `AnchorSerialize` trait will **NOT** have the
|
||||
/// same effect.
|
||||
///
|
||||
/// Types that don't implement this trait will cause a compile error during the IDL generation.
|
||||
///
|
||||
/// The methods have default implementation that allows the program to compile but the type will
|
||||
/// **NOT** be included in the IDL.
|
||||
pub trait IdlBuild {
|
||||
/// Returns the full module path of the type.
|
||||
fn __anchor_private_full_path() -> String {
|
||||
String::default()
|
||||
}
|
||||
|
||||
/// Returns the IDL type definition of the type or `None` if it doesn't exist.
|
||||
fn __anchor_private_gen_idl_type() -> Option<super::types::IdlTypeDefinition> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Insert the type definition to the defined types hashmap.
|
||||
fn __anchor_private_insert_idl_defined(
|
||||
_defined_types: &mut std::collections::HashMap<String, super::types::IdlTypeDefinition>,
|
||||
) {
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn get_module_paths() -> (TokenStream, TokenStream) {
|
||||
(
|
||||
|
@ -439,7 +468,7 @@ pub fn idl_type_definition_ts_from_syn_enum(
|
|||
))
|
||||
}
|
||||
|
||||
pub fn idl_gen_impl_skeleton(
|
||||
pub fn idl_build_impl_skeleton(
|
||||
idl_type_definition_ts: TokenStream,
|
||||
insert_defined_ts: TokenStream,
|
||||
ident: &Ident,
|
||||
|
@ -448,18 +477,19 @@ pub fn idl_gen_impl_skeleton(
|
|||
let (idl, _) = get_module_paths();
|
||||
let name = ident.to_string();
|
||||
let (impl_generics, ty_generics, where_clause) = input_generics.split_for_impl();
|
||||
let idl_build_trait = quote! {anchor_lang::anchor_syn::idl::build::IdlBuild};
|
||||
|
||||
quote! {
|
||||
impl #impl_generics #ident #ty_generics #where_clause {
|
||||
pub fn __anchor_private_full_path() -> String {
|
||||
impl #impl_generics #idl_build_trait for #ident #ty_generics #where_clause {
|
||||
fn __anchor_private_full_path() -> String {
|
||||
format!("{}::{}", std::module_path!(), #name)
|
||||
}
|
||||
|
||||
pub fn __anchor_private_gen_idl_type() -> Option<#idl::IdlTypeDefinition> {
|
||||
fn __anchor_private_gen_idl_type() -> Option<#idl::IdlTypeDefinition> {
|
||||
#idl_type_definition_ts
|
||||
}
|
||||
|
||||
pub fn __anchor_private_insert_idl_defined(
|
||||
fn __anchor_private_insert_idl_defined(
|
||||
defined_types: &mut std::collections::HashMap<String, #idl::IdlTypeDefinition>
|
||||
) {
|
||||
#insert_defined_ts
|
||||
|
@ -469,7 +499,7 @@ pub fn idl_gen_impl_skeleton(
|
|||
}
|
||||
|
||||
// generates the IDL generation impl for for a struct
|
||||
pub fn gen_idl_gen_impl_for_struct(strct: &ItemStruct, no_docs: bool) -> TokenStream {
|
||||
pub fn gen_idl_build_impl_for_struct(strct: &ItemStruct, no_docs: bool) -> TokenStream {
|
||||
let idl_type_definition_ts: TokenStream;
|
||||
let insert_defined_ts: TokenStream;
|
||||
|
||||
|
@ -492,7 +522,7 @@ pub fn gen_idl_gen_impl_for_struct(strct: &ItemStruct, no_docs: bool) -> TokenSt
|
|||
let ident = &strct.ident;
|
||||
let input_generics = &strct.generics;
|
||||
|
||||
idl_gen_impl_skeleton(
|
||||
idl_build_impl_skeleton(
|
||||
idl_type_definition_ts,
|
||||
insert_defined_ts,
|
||||
ident,
|
||||
|
@ -501,7 +531,7 @@ pub fn gen_idl_gen_impl_for_struct(strct: &ItemStruct, no_docs: bool) -> TokenSt
|
|||
}
|
||||
|
||||
// generates the IDL generation impl for for an enum
|
||||
pub fn gen_idl_gen_impl_for_enum(enm: ItemEnum, no_docs: bool) -> TokenStream {
|
||||
pub fn gen_idl_build_impl_for_enum(enm: ItemEnum, no_docs: bool) -> TokenStream {
|
||||
let idl_type_definition_ts: TokenStream;
|
||||
let insert_defined_ts: TokenStream;
|
||||
|
||||
|
@ -524,7 +554,7 @@ pub fn gen_idl_gen_impl_for_enum(enm: ItemEnum, no_docs: bool) -> TokenStream {
|
|||
let ident = &enm.ident;
|
||||
let input_generics = &enm.generics;
|
||||
|
||||
idl_gen_impl_skeleton(
|
||||
idl_build_impl_skeleton(
|
||||
idl_type_definition_ts,
|
||||
insert_defined_ts,
|
||||
ident,
|
||||
|
@ -533,7 +563,7 @@ pub fn gen_idl_gen_impl_for_enum(enm: ItemEnum, no_docs: bool) -> TokenStream {
|
|||
}
|
||||
|
||||
// generates the IDL generation impl for for an event
|
||||
pub fn gen_idl_gen_impl_for_event(event_strct: &ItemStruct) -> TokenStream {
|
||||
pub fn gen_idl_build_impl_for_event(event_strct: &ItemStruct) -> TokenStream {
|
||||
fn parse_fields(
|
||||
fields: &syn::FieldsNamed,
|
||||
) -> Result<(Vec<TokenStream>, Vec<syn::TypePath>), ()> {
|
||||
|
@ -601,7 +631,7 @@ pub fn gen_idl_gen_impl_for_event(event_strct: &ItemStruct) -> TokenStream {
|
|||
}
|
||||
|
||||
// generates the IDL generation impl for the Accounts struct
|
||||
pub fn gen_idl_gen_impl_for_accounts_strct(
|
||||
pub fn gen_idl_build_impl_for_accounts_struct(
|
||||
accs_strct: &AccountsStruct,
|
||||
no_docs: bool,
|
||||
) -> TokenStream {
|
||||
|
@ -817,7 +847,7 @@ pub fn gen_idl_print_function_for_event(event: &ItemStruct) -> TokenStream {
|
|||
|
||||
let ident = &event.ident;
|
||||
let fn_name = format_ident!("__anchor_private_print_idl_event_{}", ident.to_string());
|
||||
let impl_gen = gen_idl_gen_impl_for_event(event);
|
||||
let impl_gen = gen_idl_build_impl_for_event(event);
|
||||
|
||||
quote! {
|
||||
#impl_gen
|
||||
|
|
|
@ -13,6 +13,7 @@ associated_token = ["spl-associated-token-account"]
|
|||
dex = ["serum_dex"]
|
||||
devnet = []
|
||||
governance = []
|
||||
idl-build = ["anchor-lang/idl-build"]
|
||||
metadata = ["mpl-token-metadata"]
|
||||
mint = []
|
||||
shmem = []
|
||||
|
|
|
@ -54,5 +54,8 @@ macro_rules! vote_weight_record {
|
|||
&mut self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "idl-build")]
|
||||
impl anchor_lang::IdlBuild for VoterWeightRecord {}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -782,6 +782,9 @@ impl Deref for MetadataAccount {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "idl-build")]
|
||||
impl anchor_lang::IdlBuild for MetadataAccount {}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct MasterEditionAccount(mpl_token_metadata::state::MasterEditionV2);
|
||||
|
||||
|
@ -819,6 +822,9 @@ impl anchor_lang::Owner for MasterEditionAccount {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "idl-build")]
|
||||
impl anchor_lang::IdlBuild for MasterEditionAccount {}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct TokenRecordAccount(mpl_token_metadata::state::TokenRecord);
|
||||
|
||||
|
@ -855,6 +861,9 @@ impl Deref for TokenRecordAccount {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "idl-build")]
|
||||
impl anchor_lang::IdlBuild for TokenRecordAccount {}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Metadata;
|
||||
|
||||
|
|
|
@ -156,6 +156,9 @@ impl Deref for StakeAccount {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "idl-build")]
|
||||
impl anchor_lang::IdlBuild for StakeAccount {}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Stake;
|
||||
|
||||
|
|
|
@ -486,6 +486,9 @@ impl Deref for TokenAccount {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "idl-build")]
|
||||
impl anchor_lang::IdlBuild for TokenAccount {}
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
pub struct Mint(spl_token::state::Mint);
|
||||
|
||||
|
@ -517,6 +520,9 @@ impl Deref for Mint {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "idl-build")]
|
||||
impl anchor_lang::IdlBuild for Mint {}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Token;
|
||||
|
||||
|
|
|
@ -32,6 +32,9 @@ impl Deref for TokenAccount {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "idl-build")]
|
||||
impl anchor_lang::IdlBuild for TokenAccount {}
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq)]
|
||||
pub struct Mint(spl_token_2022::state::Mint);
|
||||
|
||||
|
@ -59,6 +62,9 @@ impl Deref for Mint {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "idl-build")]
|
||||
impl anchor_lang::IdlBuild for Mint {}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct TokenInterface;
|
||||
|
||||
|
|
|
@ -61,6 +61,26 @@
|
|||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "tokenAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "mintAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "tokenInterfaceAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "mintInterfaceAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "payer",
|
||||
"isMut": true,
|
||||
|
@ -111,6 +131,26 @@
|
|||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "tokenAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "mintAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "tokenInterfaceAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "mintInterfaceAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "payer",
|
||||
"isMut": true,
|
||||
|
|
|
@ -61,6 +61,26 @@
|
|||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "tokenAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "mintAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "tokenInterfaceAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "mintInterfaceAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "payer",
|
||||
"isMut": true,
|
||||
|
@ -111,6 +131,26 @@
|
|||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "tokenAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "mintAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "tokenInterfaceAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "mintInterfaceAccount",
|
||||
"isMut": false,
|
||||
"isSigner": false
|
||||
},
|
||||
{
|
||||
"name": "payer",
|
||||
"isMut": true,
|
||||
|
|
|
@ -13,11 +13,11 @@ no-entrypoint = []
|
|||
no-idl = []
|
||||
no-log-ix-name = []
|
||||
cpi = ["no-entrypoint"]
|
||||
idl-build = ["anchor-lang/idl-build", "external/idl-build"]
|
||||
idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build", "external/idl-build"]
|
||||
default = []
|
||||
|
||||
[dependencies]
|
||||
anchor-lang = { path = "../../../../lang" }
|
||||
anchor-spl = { path = "../../../../spl" }
|
||||
bytemuck = {version = "1.4.0", features = ["derive", "min_const_generics"]}
|
||||
bytemuck = {version = "1.4.0", features = ["derive", "min_const_generics"] }
|
||||
external = { path = "../external", features = ["no-entrypoint"] }
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use anchor_lang::prelude::*;
|
||||
use anchor_spl::{token, token_interface};
|
||||
use std::str::FromStr;
|
||||
|
||||
declare_id!("id11111111111111111111111111111111111111111");
|
||||
|
@ -274,6 +275,11 @@ pub struct Initialize<'info> {
|
|||
nested: NestedAccounts<'info>,
|
||||
zc_account: AccountLoader<'info, SomeZcAccount>,
|
||||
|
||||
token_account: Account<'info, token::TokenAccount>,
|
||||
mint_account: Account<'info, token::Mint>,
|
||||
token_interface_account: InterfaceAccount<'info, token_interface::TokenAccount>,
|
||||
mint_interface_account: InterfaceAccount<'info, token_interface::Mint>,
|
||||
|
||||
#[account(mut)]
|
||||
payer: Signer<'info>,
|
||||
system_program: Program<'info, System>,
|
||||
|
|
Loading…
Reference in New Issue