lang, examples: Remove associated keyword

This commit is contained in:
armaniferrante 2021-08-14 03:34:33 -07:00
parent e5b797b31f
commit 53b44e8fae
No known key found for this signature in database
GPG Key ID: 58BEF301E91F7828
6 changed files with 5 additions and 304 deletions

View File

@ -1,11 +1,5 @@
use anchor_lang::prelude::*;
#[associated]
#[derive(Default)]
pub struct TestData {
pub data: u64,
}
#[account]
pub struct Data {
pub udata: u128,

View File

@ -103,35 +103,6 @@ pub struct TestClose<'info> {
sol_dest: AccountInfo<'info>,
}
// `my_account` is the associated token account being created.
// `authority` must be a `mut` and `signer` since it will pay for the creation
// of the associated token account. `state` is used as an association, i.e., one
// can *optionally* identify targets to be used as seeds for the program
// derived address by using `with` (and it doesn't have to be a state account).
// For example, the SPL token program uses a `Mint` account. Lastly,
// `system_program` are *required* by convention, since the account is needed
// when creating the associated program address within the program.
#[derive(Accounts)]
pub struct TestInitAssociatedAccount<'info> {
#[account(init, associated = authority, with = state, with = data, with = b"my-seed")]
pub my_account: ProgramAccount<'info, TestData>,
#[account(mut, signer)]
pub authority: AccountInfo<'info>,
pub state: ProgramState<'info, MyState>,
pub data: ProgramAccount<'info, Data>,
pub system_program: AccountInfo<'info>,
}
#[derive(Accounts)]
pub struct TestAssociatedAccount<'info> {
#[account(mut, associated = authority, with = state, with = data, with = b"my-seed")]
pub my_account: ProgramAccount<'info, TestData>,
#[account(mut, signer)]
pub authority: AccountInfo<'info>,
pub state: ProgramState<'info, MyState>,
pub data: ProgramAccount<'info, Data>,
}
#[derive(Accounts)]
pub struct TestU16<'info> {
#[account(init)]
@ -147,15 +118,6 @@ pub struct TestI16<'info> {
#[derive(Accounts)]
pub struct TestSimulate {}
#[derive(Accounts)]
pub struct TestSimulateAssociatedAccount<'info> {
#[account(init, associated = authority)]
pub my_account: ProgramAccount<'info, TestData>,
#[account(mut, signer)]
pub authority: AccountInfo<'info>,
pub system_program: AccountInfo<'info>,
}
#[derive(Accounts)]
pub struct TestI8<'info> {
#[account(init)]

View File

@ -57,22 +57,6 @@ pub mod misc {
misc2::cpi::state::set_data(ctx, data)
}
pub fn test_init_associated_account(
ctx: Context<TestInitAssociatedAccount>,
data: u64,
) -> ProgramResult {
ctx.accounts.my_account.data = data;
Ok(())
}
pub fn test_associated_account(
ctx: Context<TestAssociatedAccount>,
data: u64,
) -> ProgramResult {
ctx.accounts.my_account.data = data;
Ok(())
}
pub fn test_u16(ctx: Context<TestU16>, data: u16) -> ProgramResult {
ctx.accounts.my_account.data = data;
Ok(())
@ -85,20 +69,6 @@ pub mod misc {
Ok(())
}
pub fn test_simulate_associated_account(
ctx: Context<TestSimulateAssociatedAccount>,
data: u32,
) -> ProgramResult {
let associated_account = *ctx.accounts.my_account.to_account_info().key;
emit!(E1 { data });
emit!(E2 { data: 1234 });
emit!(E3 { data: 9 });
emit!(E4 {
data: associated_account
});
Ok(())
}
pub fn test_i8(ctx: Context<TestI8>, data: i8) -> ProgramResult {
ctx.accounts.data.data = data;
Ok(())

View File

@ -135,89 +135,6 @@ describe("misc", () => {
assert.ok(stateAccount.auth.equals(program.provider.wallet.publicKey));
});
it("Can init an associated program account", async () => {
const state = await program.state.address();
// Manual associated address calculation for test only. Clients should use
// the generated methods.
const [
associatedAccount,
nonce,
] = await anchor.web3.PublicKey.findProgramAddress(
[
anchor.utils.bytes.utf8.encode("anchor"),
program.provider.wallet.publicKey.toBuffer(),
state.toBuffer(),
data.publicKey.toBuffer(),
anchor.utils.bytes.utf8.encode("my-seed"),
],
program.programId
);
await assert.rejects(
async () => {
await program.account.testData.fetch(associatedAccount);
},
(err) => {
assert.ok(
err.toString() ===
`Error: Account does not exist ${associatedAccount.toString()}`
);
return true;
}
);
await program.rpc.testInitAssociatedAccount(new anchor.BN(1234), {
accounts: {
myAccount: associatedAccount,
authority: program.provider.wallet.publicKey,
state,
data: data.publicKey,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
systemProgram: anchor.web3.SystemProgram.programId,
},
});
// Try out the generated associated method.
const account = await program.account.testData.associated(
program.provider.wallet.publicKey,
state,
data.publicKey,
anchor.utils.bytes.utf8.encode("my-seed")
);
assert.ok(account.data.toNumber() === 1234);
});
it("Can use an associated program account", async () => {
const state = await program.state.address();
const [
associatedAccount,
nonce,
] = await anchor.web3.PublicKey.findProgramAddress(
[
anchor.utils.bytes.utf8.encode("anchor"),
program.provider.wallet.publicKey.toBuffer(),
state.toBuffer(),
data.publicKey.toBuffer(),
anchor.utils.bytes.utf8.encode("my-seed"),
],
program.programId
);
await program.rpc.testAssociatedAccount(new anchor.BN(5), {
accounts: {
myAccount: associatedAccount,
authority: program.provider.wallet.publicKey,
state,
data: data.publicKey,
},
});
// Try out the generated associated method.
const account = await program.account.testData.associated(
program.provider.wallet.publicKey,
state,
data.publicKey,
anchor.utils.bytes.utf8.encode("my-seed")
);
assert.ok(account.data.toNumber() === 5);
});
it("Can retrieve events when simulating a transaction", async () => {
const resp = await program.simulate.testSimulate(44);
const expectedRaw = [
@ -238,55 +155,6 @@ describe("misc", () => {
assert.ok(resp.events[2].data.data === 9);
});
it("Can retrieve events when associated account is initialized in simulated transaction", async () => {
const myAccount = await program.account.testData.associatedAddress(
program.provider.wallet.publicKey
);
await assert.rejects(
async () => {
await program.account.testData.fetch(myAccount);
},
(err) => {
assert.ok(
err.toString() ===
`Error: Account does not exist ${myAccount.toString()}`
);
return true;
}
);
const resp = await program.simulate.testSimulateAssociatedAccount(44, {
accounts: {
myAccount,
authority: program.provider.wallet.publicKey,
rent: anchor.web3.SYSVAR_RENT_PUBKEY,
systemProgram: anchor.web3.SystemProgram.programId,
},
});
const expectedRaw = [
"Program Fv6oRfzWETatiMymBvTs1JpRspZz3DbBfjZJEvUTDL1g invoke [1]",
"Program 11111111111111111111111111111111 invoke [2]",
"Program 11111111111111111111111111111111 success",
"Program log: NgyCA9omwbMsAAAA",
"Program log: fPhuIELK/k7SBAAA",
"Program log: jvbowsvlmkcJAAAA",
"Program log: mg+zq/K0sXRV+N/AsG9XLERDZ+J6eQAnnzoQVHlicBQBnGr65KE5Kw==",
"Program Fv6oRfzWETatiMymBvTs1JpRspZz3DbBfjZJEvUTDL1g consumed 20460 of 200000 compute units",
"Program Fv6oRfzWETatiMymBvTs1JpRspZz3DbBfjZJEvUTDL1g success",
];
assert.ok(JSON.stringify(expectedRaw), resp.raw);
assert.ok(resp.events[0].name === "E1");
assert.ok(resp.events[0].data.data === 44);
assert.ok(resp.events[1].name === "E2");
assert.ok(resp.events[1].data.data === 1234);
assert.ok(resp.events[2].name === "E3");
assert.ok(resp.events[2].data.data === 9);
assert.ok(resp.events[3].name === "E4");
assert.ok(resp.events[3].data.data.toBase58() === myAccount.toBase58());
});
it("Can use i8 in the idl", async () => {
const data = anchor.web3.Keypair.generate();
await program.rpc.testI8(-3, {

View File

@ -192,78 +192,6 @@ pub fn account(
})
}
/// Extends the `#[account]` attribute to allow one to create associated
/// accounts. This includes a `Default` implementation, which means all fields
/// in an `#[associated]` struct must implement `Default` and an
/// `anchor_lang::Bump` trait implementation, which allows the account to be
/// used as a program derived address.
///
/// # Zero Copy Deserialization
///
/// Similar to the `#[account]` attribute one can enable zero copy
/// deserialization by using the `zero_copy` argument:
///
/// ```ignore
/// #[associated(zero_copy)]
/// ```
///
/// For more, see the [`account`](./attr.account.html) attribute.
#[proc_macro_attribute]
pub fn associated(
args: proc_macro::TokenStream,
input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
let mut account_strct = parse_macro_input!(input as syn::ItemStruct);
let account_name = &account_strct.ident;
let (impl_gen, ty_gen, where_clause) = account_strct.generics.split_for_impl();
// Add a `__nonce: u8` field to the struct to hold the bump seed for
// the program dervied address.
match &mut account_strct.fields {
syn::Fields::Named(fields) => {
let mut segments = syn::punctuated::Punctuated::new();
segments.push(syn::PathSegment {
ident: syn::Ident::new("u8", proc_macro2::Span::call_site()),
arguments: syn::PathArguments::None,
});
fields.named.push(syn::Field {
attrs: Vec::new(),
vis: syn::Visibility::Restricted(syn::VisRestricted {
pub_token: syn::token::Pub::default(),
paren_token: syn::token::Paren::default(),
in_token: None,
path: Box::new(parse_quote!(crate)),
}),
ident: Some(syn::Ident::new("__nonce", proc_macro2::Span::call_site())),
colon_token: Some(syn::token::Colon {
spans: [proc_macro2::Span::call_site()],
}),
ty: syn::Type::Path(syn::TypePath {
qself: None,
path: syn::Path {
leading_colon: None,
segments,
},
}),
});
}
_ => panic!("Fields must be named"),
}
let args: proc_macro2::TokenStream = args.into();
proc_macro::TokenStream::from(quote! {
#[anchor_lang::account(#args)]
#account_strct
#[automatically_derived]
impl #impl_gen anchor_lang::Bump for #account_name #ty_gen #where_clause {
fn seed(&self) -> u8 {
self.__nonce
}
}
})
}
#[proc_macro_derive(ZeroCopyAccessor, attributes(accessor))]
pub fn derive_zero_copy_accessor(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
let account_strct = parse_macro_input!(item as syn::ItemStruct);

View File

@ -56,7 +56,7 @@ pub use crate::program_account::ProgramAccount;
pub use crate::state::ProgramState;
pub use crate::sysvar::Sysvar;
pub use anchor_attribute_access_control::access_control;
pub use anchor_attribute_account::{account, associated, zero_copy};
pub use anchor_attribute_account::{account, zero_copy};
pub use anchor_attribute_error::error;
pub use anchor_attribute_event::{emit, event};
pub use anchor_attribute_interface::interface;
@ -233,10 +233,10 @@ impl Key for Pubkey {
/// All programs should include it via `anchor_lang::prelude::*;`.
pub mod prelude {
pub use super::{
access_control, account, associated, emit, error, event, interface, program, require,
state, zero_copy, AccountDeserialize, AccountSerialize, Accounts, AccountsExit,
AccountsInit, AnchorDeserialize, AnchorSerialize, Context, CpiAccount, CpiContext,
CpiState, CpiStateContext, Loader, ProgramAccount, ProgramState, Sysvar, ToAccountInfo,
access_control, account, emit, error, event, interface, program, require, state, zero_copy,
AccountDeserialize, AccountSerialize, Accounts, AccountsExit, AccountsInit,
AnchorDeserialize, AnchorSerialize, Context, CpiAccount, CpiContext, CpiState,
CpiStateContext, Loader, ProgramAccount, ProgramState, Sysvar, ToAccountInfo,
ToAccountInfos, ToAccountMetas,
};
@ -307,27 +307,6 @@ pub mod __private {
pub const CLOSED_ACCOUNT_DISCRIMINATOR: [u8; 8] = [255, 255, 255, 255, 255, 255, 255, 255];
}
/// Returns the program-derived-address seeds used for creating the associated
/// account.
#[macro_export]
macro_rules! associated_seeds {
(account = $pda:expr, associated = $associated:expr) => {
&[
b"anchor".as_ref(),
$associated.to_account_info().key.as_ref(),
&[anchor_lang::Bump::seed(&*$pda)],
]
};
(account = $pda:expr, associated = $associated:expr, $(with = $with:expr),+) => {
&[
b"anchor".as_ref(),
$associated.to_account_info().key.as_ref(),
$($with.to_account_info().key.as_ref()),+,
&[anchor_lang::Bump::seed(&*$pda)][..],
]
};
}
/// Ensures a condition is true, otherwise returns the given error.
/// Use this with a custom error type.
///