|
@@ -110,8 +110,8 @@ fn generate_constraint(f: &Field, c: &Constraint) -> proc_macro2::TokenStream {
|
|
|
Constraint::Mut(c) => generate_constraint_mut(f, c),
|
|
|
Constraint::HasOne(c) => generate_constraint_has_one(f, c),
|
|
|
Constraint::Signer(c) => generate_constraint_signer(f, c),
|
|
|
- Constraint::Literal(c) => generate_constraint_literal(c),
|
|
|
- Constraint::Raw(c) => generate_constraint_raw(c),
|
|
|
+ Constraint::Literal(c) => generate_constraint_literal(&f.ident, c),
|
|
|
+ Constraint::Raw(c) => generate_constraint_raw(&f.ident, c),
|
|
|
Constraint::Owner(c) => generate_constraint_owner(f, c),
|
|
|
Constraint::RentExempt(c) => generate_constraint_rent_exempt(f, c),
|
|
|
Constraint::Seeds(c) => generate_constraint_seeds(f, c),
|
|
@@ -123,10 +123,10 @@ fn generate_constraint(f: &Field, c: &Constraint) -> proc_macro2::TokenStream {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-fn generate_constraint_composite(_f: &CompositeField, c: &Constraint) -> proc_macro2::TokenStream {
|
|
|
+fn generate_constraint_composite(f: &CompositeField, c: &Constraint) -> proc_macro2::TokenStream {
|
|
|
match c {
|
|
|
- Constraint::Raw(c) => generate_constraint_raw(c),
|
|
|
- Constraint::Literal(c) => generate_constraint_literal(c),
|
|
|
+ Constraint::Raw(c) => generate_constraint_raw(&f.ident, c),
|
|
|
+ Constraint::Literal(c) => generate_constraint_literal(&f.ident, c),
|
|
|
_ => panic!("Invariant violation"),
|
|
|
}
|
|
|
}
|
|
@@ -134,10 +134,10 @@ fn generate_constraint_composite(_f: &CompositeField, c: &Constraint) -> proc_ma
|
|
|
fn generate_constraint_address(f: &Field, c: &ConstraintAddress) -> proc_macro2::TokenStream {
|
|
|
let field = &f.ident;
|
|
|
let addr = &c.address;
|
|
|
- let error = generate_custom_error(&c.error, quote! { ConstraintAddress });
|
|
|
+ let error = generate_custom_error(field, &c.error, quote! { ConstraintAddress });
|
|
|
quote! {
|
|
|
if #field.key() != #addr {
|
|
|
- return Err(#error);
|
|
|
+ return #error;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -148,6 +148,7 @@ pub fn generate_constraint_init(f: &Field, c: &ConstraintInitGroup) -> proc_macr
|
|
|
|
|
|
pub fn generate_constraint_zeroed(f: &Field, _c: &ConstraintZeroed) -> proc_macro2::TokenStream {
|
|
|
let field = &f.ident;
|
|
|
+ let name_str = field.to_string();
|
|
|
let ty_decl = f.ty_decl();
|
|
|
let from_account_info = f.from_account_info_unchecked(None);
|
|
|
quote! {
|
|
@@ -157,7 +158,7 @@ pub fn generate_constraint_zeroed(f: &Field, _c: &ConstraintZeroed) -> proc_macr
|
|
|
__disc_bytes.copy_from_slice(&__data[..8]);
|
|
|
let __discriminator = u64::from_le_bytes(__disc_bytes);
|
|
|
if __discriminator != 0 {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintZero.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintZero, #name_str));
|
|
|
}
|
|
|
#from_account_info
|
|
|
};
|
|
@@ -166,20 +167,21 @@ pub fn generate_constraint_zeroed(f: &Field, _c: &ConstraintZeroed) -> proc_macr
|
|
|
|
|
|
pub fn generate_constraint_close(f: &Field, c: &ConstraintClose) -> proc_macro2::TokenStream {
|
|
|
let field = &f.ident;
|
|
|
+ let name_str = field.to_string();
|
|
|
let target = &c.sol_dest;
|
|
|
quote! {
|
|
|
if #field.key() == #target.key() {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintClose.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintClose, #name_str));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
pub fn generate_constraint_mut(f: &Field, c: &ConstraintMut) -> proc_macro2::TokenStream {
|
|
|
let ident = &f.ident;
|
|
|
- let error = generate_custom_error(&c.error, quote! { ConstraintMut });
|
|
|
+ let error = generate_custom_error(ident, &c.error, quote! { ConstraintMut });
|
|
|
quote! {
|
|
|
if !#ident.to_account_info().is_writable {
|
|
|
- return Err(#error);
|
|
|
+ return #error;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -192,10 +194,10 @@ pub fn generate_constraint_has_one(f: &Field, c: &ConstraintHasOne) -> proc_macr
|
|
|
Ty::AccountLoader(_) => quote! {#ident.load()?},
|
|
|
_ => quote! {#ident},
|
|
|
};
|
|
|
- let error = generate_custom_error(&c.error, quote! { ConstraintHasOne });
|
|
|
+ let error = generate_custom_error(ident, &c.error, quote! { ConstraintHasOne });
|
|
|
quote! {
|
|
|
if #field.#target != #target.key() {
|
|
|
- return Err(#error);
|
|
|
+ return #error;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -211,15 +213,19 @@ pub fn generate_constraint_signer(f: &Field, c: &ConstraintSigner) -> proc_macro
|
|
|
Ty::CpiAccount(_) => quote! { #ident.to_account_info() },
|
|
|
_ => panic!("Invalid syntax: signer cannot be specified."),
|
|
|
};
|
|
|
- let error = generate_custom_error(&c.error, quote! { ConstraintSigner });
|
|
|
+ let error = generate_custom_error(ident, &c.error, quote! { ConstraintSigner });
|
|
|
quote! {
|
|
|
if !#info.is_signer {
|
|
|
- return Err(#error);
|
|
|
+ return #error;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-pub fn generate_constraint_literal(c: &ConstraintLiteral) -> proc_macro2::TokenStream {
|
|
|
+pub fn generate_constraint_literal(
|
|
|
+ ident: &Ident,
|
|
|
+ c: &ConstraintLiteral,
|
|
|
+) -> proc_macro2::TokenStream {
|
|
|
+ let name_str = ident.to_string();
|
|
|
let lit: proc_macro2::TokenStream = {
|
|
|
let lit = &c.lit;
|
|
|
let constraint = lit.value().replace('\"', "");
|
|
@@ -232,17 +238,17 @@ pub fn generate_constraint_literal(c: &ConstraintLiteral) -> proc_macro2::TokenS
|
|
|
};
|
|
|
quote! {
|
|
|
if !(#lit) {
|
|
|
- return Err(anchor_lang::error::ErrorCode::Deprecated.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::Deprecated, #name_str));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-pub fn generate_constraint_raw(c: &ConstraintRaw) -> proc_macro2::TokenStream {
|
|
|
+pub fn generate_constraint_raw(ident: &Ident, c: &ConstraintRaw) -> proc_macro2::TokenStream {
|
|
|
let raw = &c.raw;
|
|
|
- let error = generate_custom_error(&c.error, quote! { ConstraintRaw });
|
|
|
+ let error = generate_custom_error(ident, &c.error, quote! { ConstraintRaw });
|
|
|
quote! {
|
|
|
if !(#raw) {
|
|
|
- return Err(#error);
|
|
|
+ return #error;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -250,10 +256,10 @@ pub fn generate_constraint_raw(c: &ConstraintRaw) -> proc_macro2::TokenStream {
|
|
|
pub fn generate_constraint_owner(f: &Field, c: &ConstraintOwner) -> proc_macro2::TokenStream {
|
|
|
let ident = &f.ident;
|
|
|
let owner_address = &c.owner_address;
|
|
|
- let error = generate_custom_error(&c.error, quote! { ConstraintOwner });
|
|
|
+ let error = generate_custom_error(ident, &c.error, quote! { ConstraintOwner });
|
|
|
quote! {
|
|
|
if #ident.as_ref().owner != &#owner_address {
|
|
|
- return Err(#error);
|
|
|
+ return #error;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -263,6 +269,7 @@ pub fn generate_constraint_rent_exempt(
|
|
|
c: &ConstraintRentExempt,
|
|
|
) -> proc_macro2::TokenStream {
|
|
|
let ident = &f.ident;
|
|
|
+ let name_str = ident.to_string();
|
|
|
let info = quote! {
|
|
|
#ident.to_account_info()
|
|
|
};
|
|
@@ -270,7 +277,7 @@ pub fn generate_constraint_rent_exempt(
|
|
|
ConstraintRentExempt::Skip => quote! {},
|
|
|
ConstraintRentExempt::Enforce => quote! {
|
|
|
if !__anchor_rent.is_exempt(#info.lamports(), #info.try_data_len()?) {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintRentExempt.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintRentExempt, #name_str));
|
|
|
}
|
|
|
},
|
|
|
}
|
|
@@ -278,6 +285,7 @@ pub fn generate_constraint_rent_exempt(
|
|
|
|
|
|
fn generate_constraint_init_group(f: &Field, c: &ConstraintInitGroup) -> proc_macro2::TokenStream {
|
|
|
let field = &f.ident;
|
|
|
+ let name_str = f.ident.to_string();
|
|
|
let ty_decl = f.ty_decl();
|
|
|
let if_needed = if c.if_needed {
|
|
|
quote! {true}
|
|
@@ -301,7 +309,6 @@ fn generate_constraint_init_group(f: &Field, c: &ConstraintInitGroup) -> proc_ma
|
|
|
let (find_pda, seeds_with_bump) = match &c.seeds {
|
|
|
None => (quote! {}, quote! {}),
|
|
|
Some(c) => {
|
|
|
- let name_str = f.ident.to_string();
|
|
|
let seeds = &mut c.seeds.clone();
|
|
|
|
|
|
// If the seeds came with a trailing comma, we need to chop it off
|
|
@@ -367,10 +374,10 @@ fn generate_constraint_init_group(f: &Field, c: &ConstraintInitGroup) -> proc_ma
|
|
|
let pa: #ty_decl = #from_account_info;
|
|
|
if #if_needed {
|
|
|
if pa.mint != #mint.key() {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintTokenMint.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintTokenMint, #name_str));
|
|
|
}
|
|
|
if pa.owner != #owner.key() {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintTokenOwner.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintTokenOwner, #name_str));
|
|
|
}
|
|
|
}
|
|
|
pa
|
|
@@ -402,14 +409,14 @@ fn generate_constraint_init_group(f: &Field, c: &ConstraintInitGroup) -> proc_ma
|
|
|
let pa: #ty_decl = #from_account_info;
|
|
|
if #if_needed {
|
|
|
if pa.mint != #mint.key() {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintTokenMint.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintTokenMint, #name_str));
|
|
|
}
|
|
|
if pa.owner != #owner.key() {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintTokenOwner.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintTokenOwner, #name_str));
|
|
|
}
|
|
|
|
|
|
if pa.key() != anchor_spl::associated_token::get_associated_token_address(&#owner.key(), &#mint.key()) {
|
|
|
- return Err(anchor_lang::error::ErrorCode::AccountNotAssociatedTokenAccount.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::AccountNotAssociatedTokenAccount, #name_str));
|
|
|
}
|
|
|
}
|
|
|
pa
|
|
@@ -455,16 +462,16 @@ fn generate_constraint_init_group(f: &Field, c: &ConstraintInitGroup) -> proc_ma
|
|
|
let pa: #ty_decl = #from_account_info;
|
|
|
if #if_needed {
|
|
|
if pa.mint_authority != anchor_lang::solana_program::program_option::COption::Some(#owner.key()) {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintMintMintAuthority.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintMintMintAuthority, #name_str));
|
|
|
}
|
|
|
if pa.freeze_authority
|
|
|
.as_ref()
|
|
|
.map(|fa| #freeze_authority.as_ref().map(|expected_fa| fa != *expected_fa).unwrap_or(true))
|
|
|
.unwrap_or(#freeze_authority.is_some()) {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintMintFreezeAuthority.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintMintFreezeAuthority, #name_str));
|
|
|
}
|
|
|
if pa.decimals != #decimals {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintMintDecimals.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintMintDecimals, #name_str));
|
|
|
}
|
|
|
}
|
|
|
pa
|
|
@@ -540,17 +547,17 @@ fn generate_constraint_init_group(f: &Field, c: &ConstraintInitGroup) -> proc_ma
|
|
|
// Assert the account was created correctly.
|
|
|
if #if_needed {
|
|
|
if space != actual_field.data_len() {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintSpace.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintSpace, #name_str));
|
|
|
}
|
|
|
|
|
|
if actual_owner != #owner {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintOwner.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintOwner, #name_str));
|
|
|
}
|
|
|
|
|
|
{
|
|
|
let required_lamports = __anchor_rent.minimum_balance(space);
|
|
|
if pa.to_account_info().lamports() < required_lamports {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintRentExempt.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintRentExempt, #name_str));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -592,10 +599,10 @@ fn generate_constraint_seeds(f: &Field, c: &ConstraintSeedsGroup) -> proc_macro2
|
|
|
let b = c.bump.as_ref().unwrap();
|
|
|
quote! {
|
|
|
if #name.key() != __pda_address {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintSeeds.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintSeeds, #name_str));
|
|
|
}
|
|
|
if __bump != #b {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintSeeds.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintSeeds, #name_str));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -607,7 +614,7 @@ fn generate_constraint_seeds(f: &Field, c: &ConstraintSeedsGroup) -> proc_macro2
|
|
|
else if c.is_init {
|
|
|
quote! {
|
|
|
if #name.key() != __pda_address {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintSeeds.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintSeeds, #name_str));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -616,6 +623,7 @@ fn generate_constraint_seeds(f: &Field, c: &ConstraintSeedsGroup) -> proc_macro2
|
|
|
let maybe_seeds_plus_comma = (!s.is_empty()).then(|| {
|
|
|
quote! { #s, }
|
|
|
});
|
|
|
+
|
|
|
let define_pda = match c.bump.as_ref() {
|
|
|
// Bump target not given. Find it.
|
|
|
None => quote! {
|
|
@@ -630,7 +638,7 @@ fn generate_constraint_seeds(f: &Field, c: &ConstraintSeedsGroup) -> proc_macro2
|
|
|
let __pda_address = Pubkey::create_program_address(
|
|
|
&[#maybe_seeds_plus_comma &[#b][..]],
|
|
|
&#deriving_program_id,
|
|
|
- ).map_err(|_| anchor_lang::error::ErrorCode::ConstraintSeeds)?;
|
|
|
+ ).map_err(|_| anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintSeeds, #name_str))?;
|
|
|
},
|
|
|
};
|
|
|
quote! {
|
|
@@ -639,7 +647,7 @@ fn generate_constraint_seeds(f: &Field, c: &ConstraintSeedsGroup) -> proc_macro2
|
|
|
|
|
|
// Check it.
|
|
|
if #name.key() != __pda_address {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintSeeds.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintSeeds, #name_str));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -650,15 +658,16 @@ fn generate_constraint_associated_token(
|
|
|
c: &ConstraintAssociatedToken,
|
|
|
) -> proc_macro2::TokenStream {
|
|
|
let name = &f.ident;
|
|
|
+ let name_str = name.to_string();
|
|
|
let wallet_address = &c.wallet;
|
|
|
let spl_token_mint_address = &c.mint;
|
|
|
quote! {
|
|
|
if #name.owner != #wallet_address.key() {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintTokenOwner.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintTokenOwner, #name_str));
|
|
|
}
|
|
|
let __associated_token_address = anchor_spl::associated_token::get_associated_token_address(&#wallet_address.key(), &#spl_token_mint_address.key());
|
|
|
if #name.key() != __associated_token_address {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintAssociated.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintAssociated, #name_str));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -751,9 +760,10 @@ pub fn generate_constraint_executable(
|
|
|
_c: &ConstraintExecutable,
|
|
|
) -> proc_macro2::TokenStream {
|
|
|
let name = &f.ident;
|
|
|
+ let name_str = name.to_string();
|
|
|
quote! {
|
|
|
if !#name.to_account_info().executable {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintExecutable.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintExecutable, #name_str));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -761,6 +771,7 @@ pub fn generate_constraint_executable(
|
|
|
pub fn generate_constraint_state(f: &Field, c: &ConstraintState) -> proc_macro2::TokenStream {
|
|
|
let program_target = c.program_target.clone();
|
|
|
let ident = &f.ident;
|
|
|
+ let name_str = ident.to_string();
|
|
|
let account_ty = match &f.ty {
|
|
|
Ty::CpiState(ty) => &ty.account_type_path,
|
|
|
_ => panic!("Invalid state constraint"),
|
|
@@ -769,20 +780,26 @@ pub fn generate_constraint_state(f: &Field, c: &ConstraintState) -> proc_macro2:
|
|
|
// Checks the given state account is the canonical state account for
|
|
|
// the target program.
|
|
|
if #ident.key() != anchor_lang::accounts::cpi_state::CpiState::<#account_ty>::address(&#program_target.key()) {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintState.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintState, #name_str));
|
|
|
}
|
|
|
if #ident.as_ref().owner != &#program_target.key() {
|
|
|
- return Err(anchor_lang::error::ErrorCode::ConstraintState.into());
|
|
|
+ return Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::ConstraintState, #name_str));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
fn generate_custom_error(
|
|
|
+ account_name: &Ident,
|
|
|
custom_error: &Option<Expr>,
|
|
|
error: proc_macro2::TokenStream,
|
|
|
) -> proc_macro2::TokenStream {
|
|
|
+ let account_name = account_name.to_string();
|
|
|
match custom_error {
|
|
|
- Some(error) => quote! { #error.into() },
|
|
|
- None => quote! { anchor_lang::error::ErrorCode::#error.into() },
|
|
|
+ Some(error) => {
|
|
|
+ quote! { Err(anchor_lang::anchor_attribute_error::error_with_account_name!(#error, #account_name)) }
|
|
|
+ }
|
|
|
+ None => {
|
|
|
+ quote! { Err(anchor_lang::anchor_attribute_error::error_with_account_name!(anchor_lang::error::ErrorCode::#error, #account_name)) }
|
|
|
+ }
|
|
|
}
|
|
|
}
|