tests: Add remaining accounts test (#2683)
This commit is contained in:
parent
85a5a9bdfc
commit
9331908aee
|
@ -7,6 +7,7 @@ init_if_needed = "BZoppwWi6jMnydnUBEJzotgEXHwLr3b3NramJgZtWeF2"
|
|||
lamports = "Lamports11111111111111111111111111111111111"
|
||||
misc = "3TEqcc8xhrhdspwbvoamUJe2borm4Nr72JxL66k6rgrh"
|
||||
misc_optional = "FNqz6pqLAwvMSds2FYjR4nKV3moVpPNtvkfGFrqLKrgG"
|
||||
remaining_accounts = "RemainingAccounts11111111111111111111111111"
|
||||
|
||||
[workspace]
|
||||
exclude = ["programs/shared"]
|
||||
|
|
|
@ -18,5 +18,5 @@ default = []
|
|||
[dependencies]
|
||||
anchor-lang = { path = "../../../../lang", features = ["init-if-needed"] }
|
||||
anchor-spl = { path = "../../../../spl" }
|
||||
spl-associated-token-account = "1.1.1"
|
||||
bytemuck = {version = "1.4.0", features = ["derive", "min_const_generics"]}
|
||||
spl-associated-token-account = { version = "1.1.1", features = ["no-entrypoint"] }
|
||||
bytemuck = { version = "1.4.0", features = ["derive", "min_const_generics"] }
|
||||
|
|
|
@ -18,5 +18,5 @@ default = []
|
|||
[dependencies]
|
||||
anchor-lang = { path = "../../../../lang", features = ["init-if-needed"] }
|
||||
anchor-spl = { path = "../../../../spl" }
|
||||
spl-associated-token-account = "1.1.1"
|
||||
bytemuck = {version = "1.4.0", features = ["derive", "min_const_generics"]}
|
||||
spl-associated-token-account = { version = "1.1.1", features = ["no-entrypoint"] }
|
||||
bytemuck = { version = "1.4.0", features = ["derive", "min_const_generics"] }
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
[package]
|
||||
name = "remaining-accounts"
|
||||
version = "0.1.0"
|
||||
description = "Created with Anchor"
|
||||
rust-version = "1.60"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "lib"]
|
||||
name = "remaining_accounts"
|
||||
|
||||
[features]
|
||||
no-entrypoint = []
|
||||
no-idl = []
|
||||
cpi = ["no-entrypoint"]
|
||||
default = []
|
||||
|
||||
[dependencies]
|
||||
anchor-lang = { path = "../../../../lang", features = ["init-if-needed"] }
|
||||
anchor-spl = { path = "../../../../spl" }
|
|
@ -0,0 +1,2 @@
|
|||
[target.bpfel-unknown-unknown.dependencies.std]
|
||||
features = []
|
|
@ -0,0 +1,11 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
#[account]
|
||||
#[derive(InitSpace)]
|
||||
pub struct Data {
|
||||
pub someone: Pubkey,
|
||||
}
|
||||
|
||||
#[account]
|
||||
#[derive(InitSpace)]
|
||||
pub struct Another {}
|
|
@ -0,0 +1,26 @@
|
|||
use crate::account::*;
|
||||
use anchor_lang::prelude::*;
|
||||
use anchor_spl::token::Token;
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestInit<'info> {
|
||||
#[account(init, payer = payer, space = Data::INIT_SPACE + 8)]
|
||||
pub data: Account<'info, Data>,
|
||||
#[account(mut)]
|
||||
pub payer: Signer<'info>,
|
||||
pub system_program: Program<'info, System>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestInitAnother<'info> {
|
||||
#[account(init, payer = payer, space = Data::INIT_SPACE + 8)]
|
||||
pub another: Account<'info, Another>,
|
||||
#[account(mut)]
|
||||
pub payer: Signer<'info>,
|
||||
pub system_program: Program<'info, System>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestRemainingAccounts<'info> {
|
||||
pub token_program: Program<'info, Token>,
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
//! Testing of handling of remaining accounts with anchor Account structs
|
||||
|
||||
use account::*;
|
||||
use anchor_lang::prelude::*;
|
||||
use anchor_spl::token::TokenAccount;
|
||||
use context::*;
|
||||
|
||||
mod account;
|
||||
mod context;
|
||||
|
||||
declare_id!("RemainingAccounts11111111111111111111111111");
|
||||
|
||||
#[program]
|
||||
pub mod remaining_accounts {
|
||||
use super::*;
|
||||
|
||||
pub fn test_init(_ctx: Context<TestInit>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_init_another(_ctx: Context<TestInitAnother>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_remaining_accounts<'c: 'info, 'info>(
|
||||
ctx: Context<'_, '_, 'c, 'info, TestRemainingAccounts>,
|
||||
) -> Result<()> {
|
||||
let remaining_accounts_iter = &mut ctx.remaining_accounts.iter();
|
||||
|
||||
let token_account =
|
||||
Account::<TokenAccount>::try_from(next_account_info(remaining_accounts_iter)?)?;
|
||||
|
||||
let data_account_info = next_account_info(remaining_accounts_iter)?;
|
||||
require_eq!(data_account_info.is_writable, true);
|
||||
let mut data = Account::<Data>::try_from(data_account_info)?;
|
||||
|
||||
data.someone = token_account.owner;
|
||||
data.exit(ctx.program_id)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
[scripts]
|
||||
test = "yarn run ts-mocha -t 1000000 ./tests/remaining-accounts/*.ts"
|
|
@ -0,0 +1,111 @@
|
|||
import * as anchor from "@coral-xyz/anchor";
|
||||
|
||||
import { TOKEN_PROGRAM_ID, Token } from "@solana/spl-token";
|
||||
import { assert } from "chai";
|
||||
import { RemainingAccounts, IDL } from "../../target/types/remaining_accounts";
|
||||
import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";
|
||||
|
||||
describe(IDL.name, () => {
|
||||
// Configure the client to use the local cluster
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
const payer = NodeWallet.local().payer;
|
||||
|
||||
const program = anchor.workspace
|
||||
.RemainingAccounts as anchor.Program<RemainingAccounts>;
|
||||
|
||||
it("Account can be used with remaining accounts - read token account and write someone to Data", async () => {
|
||||
const data = anchor.web3.Keypair.generate();
|
||||
await program.methods
|
||||
.testInit()
|
||||
.accounts({ data: data.publicKey })
|
||||
.signers([data])
|
||||
.rpc();
|
||||
const ata = await Token.createWrappedNativeAccount(
|
||||
program.provider.connection,
|
||||
TOKEN_PROGRAM_ID,
|
||||
payer.publicKey,
|
||||
payer,
|
||||
0
|
||||
);
|
||||
|
||||
// Data is not initialized
|
||||
try {
|
||||
await program.methods
|
||||
.testRemainingAccounts()
|
||||
.accounts({
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
})
|
||||
.remainingAccounts([
|
||||
{ pubkey: ata, isSigner: false, isWritable: false },
|
||||
{
|
||||
pubkey: anchor.web3.Keypair.generate().publicKey,
|
||||
isSigner: false,
|
||||
isWritable: true,
|
||||
},
|
||||
])
|
||||
.rpc();
|
||||
assert.isTrue(false);
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof anchor.AnchorError);
|
||||
const err: anchor.AnchorError = _err;
|
||||
assert.strictEqual(err.error.errorCode.number, 3012);
|
||||
assert.strictEqual(err.error.errorCode.code, "AccountNotInitialized");
|
||||
}
|
||||
|
||||
// Can read and write from account infos from remaining_accounts
|
||||
await program.methods
|
||||
.testRemainingAccounts()
|
||||
.accounts({
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
})
|
||||
.remainingAccounts([
|
||||
{ pubkey: ata, isSigner: false, isWritable: false },
|
||||
{
|
||||
pubkey: data.publicKey,
|
||||
isSigner: false,
|
||||
isWritable: true,
|
||||
},
|
||||
])
|
||||
.rpc();
|
||||
|
||||
const dataAccount = await program.account.data.fetch(data.publicKey);
|
||||
assert.strictEqual(
|
||||
dataAccount.someone.toString(),
|
||||
payer.publicKey.toString()
|
||||
);
|
||||
|
||||
// Another account
|
||||
const another = anchor.web3.Keypair.generate();
|
||||
await program.methods
|
||||
.testInitAnother()
|
||||
.accounts({ another: another.publicKey })
|
||||
.signers([another])
|
||||
.rpc();
|
||||
|
||||
try {
|
||||
await program.methods
|
||||
.testRemainingAccounts()
|
||||
.accounts({
|
||||
tokenProgram: TOKEN_PROGRAM_ID,
|
||||
})
|
||||
.remainingAccounts([
|
||||
{ pubkey: ata, isSigner: false, isWritable: false },
|
||||
{
|
||||
pubkey: another.publicKey,
|
||||
isSigner: false,
|
||||
isWritable: true,
|
||||
},
|
||||
])
|
||||
.rpc();
|
||||
assert.isTrue(false);
|
||||
} catch (_err) {
|
||||
assert.isTrue(_err instanceof anchor.AnchorError);
|
||||
const err: anchor.AnchorError = _err;
|
||||
assert.strictEqual(err.error.errorCode.number, 3002);
|
||||
assert.strictEqual(
|
||||
err.error.errorCode.code,
|
||||
"AccountDiscriminatorMismatch"
|
||||
);
|
||||
}
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue