tests: Move IDL related tests in `misc` to `idl` (#2606)
This commit is contained in:
parent
6eacad4b11
commit
6f9f7d9369
|
@ -2,6 +2,8 @@
|
|||
seeds = true
|
||||
|
||||
[programs.localnet]
|
||||
client_interactions = "C1ient1nteractions1111111111111111111111111"
|
||||
docs = "Docs111111111111111111111111111111111111111"
|
||||
external = "Externa1111111111111111111111111111111111111"
|
||||
generics = "Generics111111111111111111111111111111111111"
|
||||
idl = "id11111111111111111111111111111111111111111"
|
||||
|
|
|
@ -10,6 +10,11 @@
|
|||
"type": "u8",
|
||||
"value": "6"
|
||||
},
|
||||
{
|
||||
"name": "BYTE_STR",
|
||||
"type": "u8",
|
||||
"value": "116"
|
||||
},
|
||||
{
|
||||
"name": "FOO_CONST",
|
||||
"type": "u128",
|
||||
|
|
|
@ -14,6 +14,16 @@
|
|||
"name": "BAR_CONST",
|
||||
"type": "u8",
|
||||
"value": "6"
|
||||
},
|
||||
{
|
||||
"name": "BYTES_STR",
|
||||
"type": "bytes",
|
||||
"value": "[116, 101, 115, 116]"
|
||||
},
|
||||
{
|
||||
"name": "BYTE_STR",
|
||||
"type": "u8",
|
||||
"value": "116"
|
||||
}
|
||||
],
|
||||
"instructions": [
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "idl_doc"
|
||||
name = "client-interactions"
|
||||
version = "0.1.0"
|
||||
description = "Created with Anchor"
|
||||
rust-version = "1.60"
|
||||
|
@ -7,7 +7,7 @@ edition = "2021"
|
|||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "lib"]
|
||||
name = "idl_doc"
|
||||
name = "client_interactions"
|
||||
|
||||
[features]
|
||||
no-entrypoint = []
|
||||
|
@ -16,4 +16,4 @@ cpi = ["no-entrypoint"]
|
|||
default = []
|
||||
|
||||
[dependencies]
|
||||
anchor-lang = { path = "../../../../lang", features = ["init-if-needed"] }
|
||||
anchor-lang = { path = "../../../../lang" }
|
|
@ -0,0 +1,95 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
declare_id!("C1ient1nteractions1111111111111111111111111");
|
||||
|
||||
#[program]
|
||||
pub mod client_interactions {
|
||||
use super::*;
|
||||
|
||||
pub fn int(ctx: Context<Int>, i8: i8, i16: i16, i32: i32, i64: i64, i128: i128) -> Result<()> {
|
||||
ctx.accounts.account.i8 = i8;
|
||||
ctx.accounts.account.i16 = i16;
|
||||
ctx.accounts.account.i32 = i32;
|
||||
ctx.accounts.account.i64 = i64;
|
||||
ctx.accounts.account.i128 = i128;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn uint(
|
||||
ctx: Context<UnsignedInt>,
|
||||
u8: u8,
|
||||
u16: u16,
|
||||
u32: u32,
|
||||
u64: u64,
|
||||
u128: u128,
|
||||
) -> Result<()> {
|
||||
ctx.accounts.account.u8 = u8;
|
||||
ctx.accounts.account.u16 = u16;
|
||||
ctx.accounts.account.u32 = u32;
|
||||
ctx.accounts.account.u64 = u64;
|
||||
ctx.accounts.account.u128 = u128;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn enm(ctx: Context<Enum>, enum_arg: MyEnum) -> Result<()> {
|
||||
ctx.accounts.account.enum_field = enum_arg;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct Int<'info> {
|
||||
#[account(zero)]
|
||||
pub account: Account<'info, IntAccount>,
|
||||
}
|
||||
|
||||
#[account]
|
||||
pub struct IntAccount {
|
||||
pub i8: i8,
|
||||
pub i16: i16,
|
||||
pub i32: i32,
|
||||
pub i64: i64,
|
||||
pub i128: i128,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct UnsignedInt<'info> {
|
||||
#[account(zero)]
|
||||
pub account: Account<'info, UnsignedIntAccount>,
|
||||
}
|
||||
|
||||
#[account]
|
||||
pub struct UnsignedIntAccount {
|
||||
pub u8: u8,
|
||||
pub u16: u16,
|
||||
pub u32: u32,
|
||||
pub u64: u64,
|
||||
pub u128: u128,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct Enum<'info> {
|
||||
#[account(zero)]
|
||||
pub account: Account<'info, EnumAccount>,
|
||||
}
|
||||
|
||||
#[account]
|
||||
pub struct EnumAccount {
|
||||
pub enum_field: MyEnum,
|
||||
}
|
||||
|
||||
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum MyEnum {
|
||||
Unit,
|
||||
Named { x: u64, y: u64 },
|
||||
Unnamed(u8, u8, u16, u16),
|
||||
UnnamedStruct(MyStruct),
|
||||
}
|
||||
|
||||
#[derive(AnchorSerialize, AnchorDeserialize, Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct MyStruct {
|
||||
pub u8: u8,
|
||||
pub u16: u16,
|
||||
pub u32: u32,
|
||||
pub u64: u64,
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
[package]
|
||||
name = "docs"
|
||||
version = "0.1.0"
|
||||
description = "Created with Anchor"
|
||||
rust-version = "1.60"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "lib"]
|
||||
name = "docs"
|
||||
|
||||
[features]
|
||||
no-entrypoint = []
|
||||
no-idl = []
|
||||
cpi = ["no-entrypoint"]
|
||||
default = []
|
||||
|
||||
[dependencies]
|
||||
anchor-lang = { path = "../../../../lang" }
|
|
@ -0,0 +1,2 @@
|
|||
[target.bpfel-unknown-unknown.dependencies.std]
|
||||
features = []
|
|
@ -2,18 +2,15 @@
|
|||
|
||||
use anchor_lang::prelude::*;
|
||||
|
||||
|
||||
declare_id!("BqmKjZGVa8fqyWuojJzG16zaKSV1GjAisZToNuvEaz6m");
|
||||
declare_id!("Docs111111111111111111111111111111111111111");
|
||||
|
||||
/// This is a doc comment for the program
|
||||
#[program]
|
||||
pub mod idl_doc {
|
||||
pub mod docs {
|
||||
use super::*;
|
||||
|
||||
/// This instruction doc should appear in the IDL
|
||||
pub fn test_idl_doc_parse(
|
||||
_ctx: Context<TestIdlDocParse>,
|
||||
) -> Result<()> {
|
||||
pub fn test_idl_doc_parse(_ctx: Context<TestIdlDocParse>) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +22,6 @@ pub struct DataWithDoc {
|
|||
pub data: u16,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestIdlDocParse<'info> {
|
||||
/// This account doc comment should appear in the IDL
|
|
@ -5,9 +5,18 @@ declare_id!("id11111111111111111111111111111111111111111");
|
|||
|
||||
#[constant]
|
||||
pub const FOO_CONST: u128 = 1_000_000;
|
||||
|
||||
#[constant]
|
||||
pub const BAR_CONST: u8 = 6;
|
||||
|
||||
#[constant]
|
||||
pub const BYTES_STR: &[u8] = b"test";
|
||||
|
||||
#[constant]
|
||||
pub const BYTE_STR: u8 = b't';
|
||||
|
||||
pub const NO_IDL: u16 = 55;
|
||||
|
||||
/// IDL test program documentation.
|
||||
#[program]
|
||||
pub mod idl {
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
import * as anchor from "@coral-xyz/anchor";
|
||||
import { assert } from "chai";
|
||||
|
||||
import { ClientInteractions } from "../target/types/client_interactions";
|
||||
|
||||
describe("Client interactions", () => {
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
const program = anchor.workspace
|
||||
.clientInteractions as anchor.Program<ClientInteractions>;
|
||||
|
||||
it("Can use integers", async () => {
|
||||
const kp = anchor.web3.Keypair.generate();
|
||||
|
||||
const i8 = -3;
|
||||
const i16 = 1;
|
||||
const i32 = -5555551;
|
||||
const i64 = new anchor.BN("384535471");
|
||||
const i128 = new anchor.BN(-8342491);
|
||||
|
||||
await program.methods
|
||||
.int(i8, i16, i32, i64, i128)
|
||||
.accounts({ account: kp.publicKey })
|
||||
.signers([kp])
|
||||
.preInstructions([await program.account.intAccount.createInstruction(kp)])
|
||||
.rpc();
|
||||
|
||||
const account = await program.account.intAccount.fetch(kp.publicKey);
|
||||
assert.strictEqual(account.i8, i8);
|
||||
assert.strictEqual(account.i16, i16);
|
||||
assert.strictEqual(account.i32, i32);
|
||||
assert(account.i64.eq(i64));
|
||||
assert(account.i128.eq(i128));
|
||||
});
|
||||
|
||||
it("Can use unsigned integers", async () => {
|
||||
const kp = anchor.web3.Keypair.generate();
|
||||
|
||||
const u8 = 123;
|
||||
const u16 = 7888;
|
||||
const u32 = 5555551;
|
||||
const u64 = new anchor.BN("384535471");
|
||||
const u128 = new anchor.BN(8888888);
|
||||
|
||||
await program.methods
|
||||
.uint(u8, u16, u32, u64, u128)
|
||||
.accounts({ account: kp.publicKey })
|
||||
.signers([kp])
|
||||
.preInstructions([
|
||||
await program.account.unsignedIntAccount.createInstruction(kp),
|
||||
])
|
||||
.rpc();
|
||||
|
||||
const account = await program.account.unsignedIntAccount.fetch(
|
||||
kp.publicKey
|
||||
);
|
||||
assert.strictEqual(account.u8, u8);
|
||||
assert.strictEqual(account.u16, u16);
|
||||
assert.strictEqual(account.u32, u32);
|
||||
assert(account.u64.eq(u64));
|
||||
assert(account.u128.eq(u128));
|
||||
});
|
||||
|
||||
it("Can use enum", async () => {
|
||||
const testAccountEnum = async (
|
||||
...args: Parameters<typeof program["methods"]["enm"]>
|
||||
) => {
|
||||
const kp = anchor.web3.Keypair.generate();
|
||||
await program.methods
|
||||
.enm(...(args as any))
|
||||
.accounts({ account: kp.publicKey })
|
||||
.signers([kp])
|
||||
.preInstructions([
|
||||
await program.account.enumAccount.createInstruction(kp),
|
||||
])
|
||||
.rpc();
|
||||
return await program.account.enumAccount.fetch(kp.publicKey);
|
||||
};
|
||||
|
||||
// Unit
|
||||
const unit = await testAccountEnum({ unit: {} });
|
||||
assert.deepEqual(unit.enumField.unit, {});
|
||||
|
||||
// Named
|
||||
const x = new anchor.BN(1);
|
||||
const y = new anchor.BN(2);
|
||||
const named = await testAccountEnum({ named: { x, y } });
|
||||
assert(named.enumField.named.x.eq(x));
|
||||
assert(named.enumField.named.y.eq(y));
|
||||
|
||||
// Unnamed
|
||||
const tupleArg = [1, 2, 3, 4] as const;
|
||||
const unnamed = await testAccountEnum({ unnamed: tupleArg });
|
||||
assert.strictEqual(unnamed.enumField.unnamed[0], tupleArg[0]);
|
||||
assert.strictEqual(unnamed.enumField.unnamed[1], tupleArg[1]);
|
||||
assert.strictEqual(unnamed.enumField.unnamed[2], tupleArg[2]);
|
||||
assert.strictEqual(unnamed.enumField.unnamed[3], tupleArg[3]);
|
||||
|
||||
// Unnamed struct
|
||||
const tupleStructArg = [
|
||||
{ u8: 1, u16: 11, u32: 111, u64: new anchor.BN(1111) },
|
||||
] as const;
|
||||
const unnamedStruct = await testAccountEnum({
|
||||
unnamedStruct: tupleStructArg,
|
||||
});
|
||||
assert.strictEqual(
|
||||
unnamedStruct.enumField.unnamedStruct[0].u8,
|
||||
tupleStructArg[0].u8
|
||||
);
|
||||
assert.strictEqual(
|
||||
unnamedStruct.enumField.unnamedStruct[0].u16,
|
||||
tupleStructArg[0].u16
|
||||
);
|
||||
assert.strictEqual(
|
||||
unnamedStruct.enumField.unnamedStruct[0].u32,
|
||||
tupleStructArg[0].u32
|
||||
);
|
||||
assert(
|
||||
unnamedStruct.enumField.unnamedStruct[0].u64.eq(tupleStructArg[0].u64)
|
||||
);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,46 @@
|
|||
import * as anchor from "@coral-xyz/anchor";
|
||||
import { Program } from "@coral-xyz/anchor";
|
||||
import { assert } from "chai";
|
||||
|
||||
import { Docs } from "../target/types/docs";
|
||||
|
||||
describe("Docs", () => {
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
const program = anchor.workspace.docs as Program<Docs>;
|
||||
|
||||
const instruction = program.idl.instructions.find(
|
||||
(i) => i.name === "testIdlDocParse"
|
||||
);
|
||||
|
||||
it("includes instruction doc comment", () => {
|
||||
assert.deepEqual(instruction.docs, [
|
||||
"This instruction doc should appear in the IDL",
|
||||
]);
|
||||
});
|
||||
|
||||
it("includes account doc comment", () => {
|
||||
const act = instruction.accounts.find((i) => i.name === "act");
|
||||
assert.deepEqual(act.docs, [
|
||||
"This account doc comment should appear in the IDL",
|
||||
"This is a multi-line comment",
|
||||
]);
|
||||
});
|
||||
|
||||
const dataWithDoc = program.idl.accounts.find(
|
||||
// @ts-expect-error
|
||||
(acc) => acc.name === "DataWithDoc"
|
||||
);
|
||||
|
||||
it("includes accounts doc comment", () => {
|
||||
assert.deepEqual(dataWithDoc.docs, [
|
||||
"Custom account doc comment should appear in the IDL",
|
||||
]);
|
||||
});
|
||||
|
||||
it("includes account attribute doc comment", () => {
|
||||
const dataField = dataWithDoc.type.fields.find((i) => i.name === "data");
|
||||
assert.deepEqual(dataField.docs, [
|
||||
"Account attribute doc comment should appear in the IDL",
|
||||
]);
|
||||
});
|
||||
});
|
|
@ -1,43 +1,32 @@
|
|||
import * as anchor from "@coral-xyz/anchor";
|
||||
import { Program } from "@coral-xyz/anchor";
|
||||
import { assert } from "chai";
|
||||
|
||||
import { Idl } from "../target/types/idl";
|
||||
|
||||
describe("IDL", () => {
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
const program = anchor.workspace.idl as Program<Idl>;
|
||||
|
||||
it("Can lazy load workspace programs", () => {
|
||||
assert.doesNotThrow(() => {
|
||||
// Program exists, should not throw
|
||||
anchor.workspace.relationsDerivation;
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
// IDL path in Anchor.toml doesn't exist but other tests still run
|
||||
// successfully because workspace programs are getting loaded on-demand
|
||||
anchor.workspace.nonExistent;
|
||||
}, /non-existent\.json/);
|
||||
it("Should include `FOO_CONST`", () => {
|
||||
assert.isDefined(
|
||||
program.idl.constants.find(
|
||||
(c) =>
|
||||
c.name === "FOO_CONST" && c.type === "u128" && c.value === "1000000"
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it("Can get workspace programs by their name independent of casing", () => {
|
||||
const camel = anchor.workspace.relationsDerivation;
|
||||
const pascal = anchor.workspace.RelationsDerivation;
|
||||
const kebab = anchor.workspace["relations-derivation"];
|
||||
const snake = anchor.workspace["relations_derivation"];
|
||||
|
||||
const compareProgramNames = (...programs: anchor.Program[]) => {
|
||||
return programs.every(
|
||||
(program) => program.idl.name === "relations_derivation"
|
||||
);
|
||||
};
|
||||
|
||||
assert(compareProgramNames(camel, pascal, kebab, snake));
|
||||
it("Should include `BAR_CONST`", () => {
|
||||
assert.isDefined(
|
||||
program.idl.constants.find(
|
||||
(c) => c.name === "BAR_CONST" && c.type === "u8" && c.value === "6"
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it("Can use numbers in program names", () => {
|
||||
assert.doesNotThrow(() => {
|
||||
anchor.workspace.numbers123;
|
||||
anchor.workspace.Numbers123;
|
||||
anchor.workspace["numbers-123"];
|
||||
anchor.workspace["numbers_123"];
|
||||
});
|
||||
it("Should not include `NO_IDL` const", () => {
|
||||
// @ts-expect-error
|
||||
assert.isUndefined(program.idl.constants.find((c) => c.name === "NO_IDL"));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
import * as anchor from "@coral-xyz/anchor";
|
||||
import { assert } from "chai";
|
||||
|
||||
describe("Workspace", () => {
|
||||
anchor.setProvider(anchor.AnchorProvider.env());
|
||||
|
||||
it("Can lazy load workspace programs", () => {
|
||||
assert.doesNotThrow(() => {
|
||||
// Program exists, should not throw
|
||||
anchor.workspace.relationsDerivation;
|
||||
});
|
||||
|
||||
assert.throws(() => {
|
||||
// IDL path in Anchor.toml doesn't exist but other tests still run
|
||||
// successfully because workspace programs are getting loaded on-demand
|
||||
anchor.workspace.nonExistent;
|
||||
}, /non-existent\.json/);
|
||||
});
|
||||
|
||||
it("Can get workspace programs by their name independent of casing", () => {
|
||||
const camel = anchor.workspace.relationsDerivation;
|
||||
const pascal = anchor.workspace.RelationsDerivation;
|
||||
const kebab = anchor.workspace["relations-derivation"];
|
||||
const snake = anchor.workspace["relations_derivation"];
|
||||
|
||||
const compareProgramNames = (...programs: anchor.Program[]) => {
|
||||
return programs.every(
|
||||
(program) => program.idl.name === "relations_derivation"
|
||||
);
|
||||
};
|
||||
|
||||
assert(compareProgramNames(camel, pascal, kebab, snake));
|
||||
});
|
||||
|
||||
it("Can use numbers in program names", () => {
|
||||
assert.doesNotThrow(() => {
|
||||
anchor.workspace.numbers123;
|
||||
anchor.workspace.Numbers123;
|
||||
anchor.workspace["numbers-123"];
|
||||
anchor.workspace["numbers_123"];
|
||||
});
|
||||
});
|
||||
});
|
|
@ -3,7 +3,6 @@ cluster = "localnet"
|
|||
wallet = "~/.config/solana/id.json"
|
||||
|
||||
[programs.localnet]
|
||||
idl_doc = "BqmKjZGVa8fqyWuojJzG16zaKSV1GjAisZToNuvEaz6m"
|
||||
init_if_needed = "BZoppwWi6jMnydnUBEJzotgEXHwLr3b3NramJgZtWeF2"
|
||||
lamports = "Lamports11111111111111111111111111111111111"
|
||||
misc = "3TEqcc8xhrhdspwbvoamUJe2borm4Nr72JxL66k6rgrh"
|
||||
|
|
|
@ -30,18 +30,6 @@ pub struct DataI8 {
|
|||
}
|
||||
size!(DataI8, 1);
|
||||
|
||||
#[account]
|
||||
pub struct DataI16 {
|
||||
pub data: i16, // 2
|
||||
}
|
||||
size!(DataI16, 2);
|
||||
|
||||
#[account]
|
||||
pub struct DataEnum {
|
||||
pub data: TestEnum, // 1 + 16
|
||||
}
|
||||
size!(DataEnum, 17);
|
||||
|
||||
#[account(zero_copy)]
|
||||
pub struct DataZeroCopy {
|
||||
pub data: u16, // 2
|
||||
|
@ -79,19 +67,3 @@ pub struct DataConstCastArraySize {
|
|||
pub struct DataMultidimensionalArrayConstSizes {
|
||||
pub data: [[u8; MAX_SIZE_U8 as usize]; MAX_SIZE],
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, AnchorSerialize, AnchorDeserialize, PartialEq, Eq)]
|
||||
pub enum TestEnum {
|
||||
First,
|
||||
Second { x: u64, y: u64 },
|
||||
TupleTest(u8, u8, u16, u16),
|
||||
TupleStructTest(TestStruct),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, AnchorSerialize, AnchorDeserialize, PartialEq, Eq)]
|
||||
pub struct TestStruct {
|
||||
pub data1: u8,
|
||||
pub data2: u16,
|
||||
pub data3: u32,
|
||||
pub data4: u64,
|
||||
}
|
||||
|
|
|
@ -193,35 +193,9 @@ pub struct TestCloseMut<'info> {
|
|||
pub sol_dest: Option<AccountInfo<'info>>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestU16<'info> {
|
||||
#[account(zero)]
|
||||
pub my_account: Option<Account<'info, DataU16>>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestI16<'info> {
|
||||
#[account(zero)]
|
||||
pub data: Option<Account<'info, DataI16>>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestSimulate {}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestAccountEnum<'info> {
|
||||
#[account(init, payer = payer.as_ref().unwrap(), space = 8+ DataEnum::LEN )]
|
||||
pub data: Option<Account<'info, DataEnum>>,
|
||||
pub payer: Option<Signer<'info>>,
|
||||
pub system_program: Option<Program<'info, System>>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestI8<'info> {
|
||||
#[account(zero)]
|
||||
pub data: Option<Account<'info, DataI8>>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestCompositePayer<'info> {
|
||||
pub composite: TestInit<'info>,
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
use crate::account::*;
|
||||
|
||||
pub const MAX_EVENT_SIZE: usize = 10;
|
||||
pub const MAX_EVENT_SIZE_U8: u8 = 11;
|
||||
|
||||
|
@ -34,8 +32,3 @@ pub struct E5 {
|
|||
pub struct E6 {
|
||||
pub data: [u8; MAX_EVENT_SIZE_U8 as usize],
|
||||
}
|
||||
|
||||
#[event]
|
||||
pub struct E7 {
|
||||
pub data: TestEnum,
|
||||
}
|
||||
|
|
|
@ -44,11 +44,6 @@ pub mod misc_optional {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_u16(ctx: Context<TestU16>, data: u16) -> Result<()> {
|
||||
ctx.accounts.my_account.as_mut().unwrap().data = data;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_simulate(_ctx: Context<TestSimulate>, data: u32) -> Result<()> {
|
||||
emit!(E1 { data });
|
||||
emit!(E2 { data: 1234 });
|
||||
|
@ -62,26 +57,6 @@ pub mod misc_optional {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_input_enum(_ctx: Context<TestSimulate>, data: TestEnum) -> Result<()> {
|
||||
emit!(E7 { data: data });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_account_enum(ctx: Context<TestAccountEnum>, data: TestEnum) -> Result<()> {
|
||||
ctx.accounts.data.as_mut().unwrap().data = data;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_i8(ctx: Context<TestI8>, data: i8) -> Result<()> {
|
||||
ctx.accounts.data.as_mut().unwrap().data = data;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_i16(ctx: Context<TestI16>, data: i16) -> Result<()> {
|
||||
ctx.accounts.data.as_mut().unwrap().data = data;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_const_array_size(ctx: Context<TestConstArraySize>, data: u8) -> Result<()> {
|
||||
ctx.accounts.data.as_mut().unwrap().data[0] = data;
|
||||
Ok(())
|
||||
|
|
|
@ -30,18 +30,6 @@ pub struct DataI8 {
|
|||
}
|
||||
size!(DataI8, 1);
|
||||
|
||||
#[account]
|
||||
pub struct DataI16 {
|
||||
pub data: i16, // 2
|
||||
}
|
||||
size!(DataI16, 2);
|
||||
|
||||
#[account]
|
||||
pub struct DataEnum {
|
||||
pub data: TestEnum, // 1 + 16
|
||||
}
|
||||
size!(DataEnum, 17);
|
||||
|
||||
#[account(zero_copy)]
|
||||
pub struct DataZeroCopy {
|
||||
pub data: u16, // 2
|
||||
|
@ -101,14 +89,6 @@ pub enum CoolEnum {
|
|||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, AnchorSerialize, AnchorDeserialize, PartialEq, Eq)]
|
||||
pub enum TestEnum {
|
||||
First,
|
||||
Second { x: u64, y: u64 },
|
||||
TupleTest(u8, u8, u16, u16),
|
||||
TupleStructTest(TestStruct),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, AnchorSerialize, AnchorDeserialize, PartialEq, Eq)]
|
||||
pub struct TestStruct {
|
||||
pub data1: u8,
|
||||
|
|
|
@ -200,36 +200,9 @@ pub struct TestCloseMut<'info> {
|
|||
pub sol_dest: AccountInfo<'info>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestU16<'info> {
|
||||
#[account(zero)]
|
||||
pub my_account: Account<'info, DataU16>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestI16<'info> {
|
||||
#[account(zero)]
|
||||
pub data: Account<'info, DataI16>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestSimulate {}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestAccountEnum<'info> {
|
||||
#[account(init, payer = payer, space = 8 + DataEnum::LEN)]
|
||||
pub data: Account<'info, DataEnum>,
|
||||
#[account(mut)]
|
||||
pub payer: Signer<'info>,
|
||||
pub system_program: Program<'info, System>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestI8<'info> {
|
||||
#[account(zero)]
|
||||
pub data: Account<'info, DataI8>,
|
||||
}
|
||||
|
||||
#[derive(Accounts)]
|
||||
pub struct TestInit<'info> {
|
||||
#[account(init, payer = payer, space = DataI8::LEN + 8)]
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
use anchor_lang::prelude::*;
|
||||
|
||||
use crate::account::*;
|
||||
|
||||
pub const MAX_EVENT_SIZE: usize = 10;
|
||||
pub const MAX_EVENT_SIZE_U8: u8 = 11;
|
||||
|
||||
|
@ -34,8 +32,3 @@ pub struct E5 {
|
|||
pub struct E6 {
|
||||
pub data: [u8; MAX_EVENT_SIZE_U8 as usize],
|
||||
}
|
||||
|
||||
#[event]
|
||||
pub struct E7 {
|
||||
pub data: TestEnum,
|
||||
}
|
||||
|
|
|
@ -12,16 +12,6 @@ mod event;
|
|||
|
||||
declare_id!("3TEqcc8xhrhdspwbvoamUJe2borm4Nr72JxL66k6rgrh");
|
||||
|
||||
#[constant]
|
||||
pub const BASE: u128 = 1_000_000;
|
||||
#[constant]
|
||||
pub const DECIMALS: u8 = 6;
|
||||
#[constant]
|
||||
pub const BYTES_STR: &[u8] = b"test";
|
||||
#[constant]
|
||||
pub const BYTE_STR: u8 = b't';
|
||||
pub const NO_IDL: u16 = 55;
|
||||
|
||||
#[program]
|
||||
pub mod misc {
|
||||
use super::*;
|
||||
|
@ -48,11 +38,6 @@ pub mod misc {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_u16(ctx: Context<TestU16>, data: u16) -> Result<()> {
|
||||
ctx.accounts.my_account.data = data;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_simulate(_ctx: Context<TestSimulate>, data: u32) -> Result<()> {
|
||||
emit!(E1 { data });
|
||||
emit!(E2 { data: 1234 });
|
||||
|
@ -66,26 +51,6 @@ pub mod misc {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_input_enum(_ctx: Context<TestSimulate>, data: TestEnum) -> Result<()> {
|
||||
emit!(E7 { data: data });
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_account_enum(ctx: Context<TestAccountEnum>, data: TestEnum) -> Result<()> {
|
||||
ctx.accounts.data.data = data;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_i8(ctx: Context<TestI8>, data: i8) -> Result<()> {
|
||||
ctx.accounts.data.data = data;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_i16(ctx: Context<TestI16>, data: i16) -> Result<()> {
|
||||
ctx.accounts.data.data = data;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn test_const_array_size(ctx: Context<TestConstArraySize>, data: u8) -> Result<()> {
|
||||
ctx.accounts.data.data[0] = data;
|
||||
Ok(())
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
[scripts]
|
||||
test = "yarn run ts-mocha -t 1000000 ./tests/idl_doc/*.ts"
|
|
@ -1,50 +0,0 @@
|
|||
import * as anchor from "@coral-xyz/anchor";
|
||||
import { Program, Wallet } from "@coral-xyz/anchor";
|
||||
import { IdlDoc } from "../../target/types/idl_doc";
|
||||
const { expect } = require("chai");
|
||||
const idl_doc_idl = require("../../target/idl/idl_doc.json");
|
||||
|
||||
describe("idl_doc", () => {
|
||||
// Configure the client to use the local cluster.
|
||||
const provider = anchor.AnchorProvider.env();
|
||||
const wallet = provider.wallet as Wallet;
|
||||
anchor.setProvider(provider);
|
||||
const program = anchor.workspace.IdlDoc as Program<IdlDoc>;
|
||||
|
||||
describe("IDL doc strings", () => {
|
||||
const instruction = program.idl.instructions.find(
|
||||
(i) => i.name === "testIdlDocParse"
|
||||
);
|
||||
it("includes instruction doc comment", async () => {
|
||||
expect(instruction.docs).to.have.same.members([
|
||||
"This instruction doc should appear in the IDL",
|
||||
]);
|
||||
});
|
||||
|
||||
it("includes account doc comment", async () => {
|
||||
const act = instruction.accounts.find((i) => i.name === "act");
|
||||
expect(act.docs).to.have.same.members([
|
||||
"This account doc comment should appear in the IDL",
|
||||
"This is a multi-line comment",
|
||||
]);
|
||||
});
|
||||
|
||||
const dataWithDoc = program.idl.accounts.find(
|
||||
// @ts-expect-error
|
||||
(i) => i.name === "DataWithDoc"
|
||||
);
|
||||
|
||||
it("includes accounts doc comment", async () => {
|
||||
expect(dataWithDoc.docs).to.have.same.members([
|
||||
"Custom account doc comment should appear in the IDL",
|
||||
]);
|
||||
});
|
||||
|
||||
it("includes account attribute doc comment", async () => {
|
||||
const dataField = dataWithDoc.type.fields.find((i) => i.name === "data");
|
||||
expect(dataField.docs).to.have.same.members([
|
||||
"Account attribute doc comment should appear in the IDL",
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,5 +1,5 @@
|
|||
import * as anchor from "@coral-xyz/anchor";
|
||||
import { Program, BN, AnchorError, Wallet, IdlEvents } from "@coral-xyz/anchor";
|
||||
import { Program, AnchorError, Wallet } from "@coral-xyz/anchor";
|
||||
import {
|
||||
PublicKey,
|
||||
Keypair,
|
||||
|
@ -14,11 +14,12 @@ import {
|
|||
Token,
|
||||
ASSOCIATED_TOKEN_PROGRAM_ID,
|
||||
} from "@solana/spl-token";
|
||||
import { assert, expect } from "chai";
|
||||
|
||||
import { Misc } from "../../target/types/misc";
|
||||
import { MiscOptional } from "../../target/types/misc_optional";
|
||||
|
||||
const utf8 = anchor.utils.bytes.utf8;
|
||||
const { assert, expect } = require("chai");
|
||||
const nativeAssert = require("assert");
|
||||
const miscIdl = require("../../target/idl/misc.json");
|
||||
|
||||
|
@ -31,36 +32,217 @@ const miscTest = (
|
|||
const wallet = provider.wallet as Wallet;
|
||||
anchor.setProvider(provider);
|
||||
|
||||
const data = anchor.web3.Keypair.generate();
|
||||
|
||||
it("Can use u128 and i128", async () => {
|
||||
const tx = await program.rpc.initialize(
|
||||
new anchor.BN(1234),
|
||||
new anchor.BN(22),
|
||||
{
|
||||
accounts: {
|
||||
data: data.publicKey,
|
||||
},
|
||||
signers: [data],
|
||||
instructions: [await program.account.data.createInstruction(data)],
|
||||
}
|
||||
);
|
||||
const dataAccount = await program.account.data.fetch(data.publicKey);
|
||||
assert.isTrue(dataAccount.udata.eq(new anchor.BN(1234)));
|
||||
assert.isTrue(dataAccount.idata.eq(new anchor.BN(22)));
|
||||
});
|
||||
|
||||
it("Can use u16", async () => {
|
||||
describe("Data Account", () => {
|
||||
const data = anchor.web3.Keypair.generate();
|
||||
const tx = await program.rpc.testU16(99, {
|
||||
accounts: {
|
||||
myAccount: data.publicKey,
|
||||
},
|
||||
signers: [data],
|
||||
instructions: [await program.account.dataU16.createInstruction(data)],
|
||||
const udata = new anchor.BN(1);
|
||||
const idata = new anchor.BN(2);
|
||||
|
||||
it("Can initialize data account", async () => {
|
||||
await program.methods
|
||||
.initialize(udata, idata)
|
||||
.accounts({ data: data.publicKey })
|
||||
.signers([data])
|
||||
.preInstructions([await program.account.data.createInstruction(data)])
|
||||
.rpc();
|
||||
const dataAccount = await program.account.data.fetch(data.publicKey);
|
||||
assert(dataAccount.udata.eq(udata));
|
||||
assert(dataAccount.idata.eq(idata));
|
||||
});
|
||||
|
||||
it("Can use base58 strings to fetch an account", async () => {
|
||||
const dataAccount = await program.account.data.fetch(
|
||||
data.publicKey.toString()
|
||||
);
|
||||
assert(dataAccount.udata.eq(udata));
|
||||
assert(dataAccount.idata.eq(idata));
|
||||
});
|
||||
|
||||
it("Can use the owner constraint", async () => {
|
||||
await program.methods
|
||||
.testOwner()
|
||||
.accounts({
|
||||
data: data.publicKey,
|
||||
misc: program.programId,
|
||||
})
|
||||
.rpc();
|
||||
|
||||
await nativeAssert.rejects(
|
||||
async () => {
|
||||
await program.methods
|
||||
.testOwner()
|
||||
.accounts({
|
||||
data: provider.wallet.publicKey,
|
||||
misc: program.programId,
|
||||
})
|
||||
.rpc();
|
||||
},
|
||||
(err) => {
|
||||
return true;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it("Should fail to close an account when sending lamports to itself", async () => {
|
||||
try {
|
||||
await program.methods
|
||||
.testClose()
|
||||
.accounts({
|
||||
data: data.publicKey,
|
||||
solDest: data.publicKey,
|
||||
})
|
||||
.rpc();
|
||||
expect(false).to.be.true;
|
||||
} catch (err) {
|
||||
assert.strictEqual(
|
||||
err.error.errorMessage,
|
||||
"A close constraint was violated"
|
||||
);
|
||||
assert.strictEqual(err.error.errorCode.number, 2011);
|
||||
}
|
||||
});
|
||||
|
||||
it("Can close an account", async () => {
|
||||
const connection = program.provider.connection;
|
||||
const openAccount = await connection.getAccountInfo(data.publicKey);
|
||||
|
||||
assert.isNotNull(openAccount);
|
||||
const openAccountBalance = openAccount.lamports;
|
||||
// double balance to calculate closed balance correctly
|
||||
const transferIx = anchor.web3.SystemProgram.transfer({
|
||||
fromPubkey: provider.wallet.publicKey,
|
||||
toPubkey: data.publicKey,
|
||||
lamports: openAccountBalance,
|
||||
});
|
||||
const transferTransaction = new anchor.web3.Transaction().add(
|
||||
transferIx
|
||||
);
|
||||
await provider.sendAndConfirm(transferTransaction);
|
||||
|
||||
let beforeBalance = (
|
||||
await connection.getAccountInfo(provider.wallet.publicKey)
|
||||
).lamports;
|
||||
|
||||
await program.methods
|
||||
.testClose()
|
||||
.accounts({
|
||||
data: data.publicKey,
|
||||
solDest: provider.wallet.publicKey,
|
||||
})
|
||||
.postInstructions([transferIx])
|
||||
.rpc();
|
||||
|
||||
let afterBalance = (
|
||||
await connection.getAccountInfo(provider.wallet.publicKey)
|
||||
).lamports;
|
||||
|
||||
// Retrieved rent exemption sol.
|
||||
expect(afterBalance > beforeBalance).to.be.true;
|
||||
|
||||
const closedAccount = await connection.getAccountInfo(data.publicKey);
|
||||
|
||||
assert.isTrue(closedAccount.data.length === 0);
|
||||
assert.isTrue(closedAccount.owner.equals(SystemProgram.programId));
|
||||
});
|
||||
|
||||
it("Can close an account twice", async () => {
|
||||
const data = anchor.web3.Keypair.generate();
|
||||
await program.methods
|
||||
.initialize(new anchor.BN(10), new anchor.BN(10))
|
||||
.accounts({ data: data.publicKey })
|
||||
.preInstructions([await program.account.data.createInstruction(data)])
|
||||
.signers([data])
|
||||
.rpc();
|
||||
|
||||
const connection = program.provider.connection;
|
||||
const openAccount = await connection.getAccountInfo(data.publicKey);
|
||||
assert.isNotNull(openAccount);
|
||||
|
||||
const openAccountBalance = openAccount.lamports;
|
||||
// double balance to calculate closed balance correctly
|
||||
const transferIx = anchor.web3.SystemProgram.transfer({
|
||||
fromPubkey: provider.wallet.publicKey,
|
||||
toPubkey: data.publicKey,
|
||||
lamports: openAccountBalance,
|
||||
});
|
||||
const transferTransaction = new anchor.web3.Transaction().add(
|
||||
transferIx
|
||||
);
|
||||
await provider.sendAndConfirm(transferTransaction);
|
||||
|
||||
let beforeBalance = (
|
||||
await connection.getAccountInfo(provider.wallet.publicKey)
|
||||
).lamports;
|
||||
|
||||
await program.methods
|
||||
.testCloseTwice()
|
||||
.accounts({
|
||||
data: data.publicKey,
|
||||
solDest: provider.wallet.publicKey,
|
||||
})
|
||||
.postInstructions([transferIx])
|
||||
.rpc();
|
||||
|
||||
let afterBalance = (
|
||||
await connection.getAccountInfo(provider.wallet.publicKey)
|
||||
).lamports;
|
||||
|
||||
// Retrieved rent exemption sol.
|
||||
expect(afterBalance > beforeBalance).to.be.true;
|
||||
|
||||
const closedAccount = await connection.getAccountInfo(data.publicKey);
|
||||
assert.isTrue(closedAccount.data.length === 0);
|
||||
assert.isTrue(closedAccount.owner.equals(SystemProgram.programId));
|
||||
});
|
||||
|
||||
it("Can close a mut account manually", async () => {
|
||||
const data = anchor.web3.Keypair.generate();
|
||||
await program.methods
|
||||
.initialize(new anchor.BN(10), new anchor.BN(10))
|
||||
.accounts({ data: data.publicKey })
|
||||
.preInstructions([await program.account.data.createInstruction(data)])
|
||||
.signers([data])
|
||||
.rpc();
|
||||
|
||||
const connection = program.provider.connection;
|
||||
const openAccount = await connection.getAccountInfo(data.publicKey);
|
||||
|
||||
assert.isNotNull(openAccount);
|
||||
const openAccountBalance = openAccount.lamports;
|
||||
// double balance to calculate closed balance correctly
|
||||
const transferIx = anchor.web3.SystemProgram.transfer({
|
||||
fromPubkey: provider.wallet.publicKey,
|
||||
toPubkey: data.publicKey,
|
||||
lamports: openAccountBalance,
|
||||
});
|
||||
const transferTransaction = new anchor.web3.Transaction().add(
|
||||
transferIx
|
||||
);
|
||||
await provider.sendAndConfirm(transferTransaction);
|
||||
|
||||
let beforeBalance = (
|
||||
await connection.getAccountInfo(provider.wallet.publicKey)
|
||||
).lamports;
|
||||
|
||||
await program.methods
|
||||
.testCloseMut()
|
||||
.accounts({
|
||||
data: data.publicKey,
|
||||
solDest: provider.wallet.publicKey,
|
||||
})
|
||||
.postInstructions([transferIx])
|
||||
.rpc();
|
||||
|
||||
let afterBalance = (
|
||||
await connection.getAccountInfo(provider.wallet.publicKey)
|
||||
).lamports;
|
||||
|
||||
// Retrieved rent exemption sol.
|
||||
expect(afterBalance > beforeBalance).to.be.true;
|
||||
|
||||
const closedAccount = await connection.getAccountInfo(data.publicKey);
|
||||
assert.isTrue(closedAccount.data.length === 0);
|
||||
assert.isTrue(closedAccount.owner.equals(SystemProgram.programId));
|
||||
});
|
||||
const dataAccount = await program.account.dataU16.fetch(data.publicKey);
|
||||
assert.strictEqual(dataAccount.data, 99);
|
||||
});
|
||||
|
||||
it("Can send VersionedTransaction", async () => {
|
||||
|
@ -216,29 +398,6 @@ const miscTest = (
|
|||
assert.isTrue(accInfo.executable);
|
||||
});
|
||||
|
||||
it("Can use the owner constraint", async () => {
|
||||
await program.rpc.testOwner({
|
||||
accounts: {
|
||||
data: data.publicKey,
|
||||
misc: program.programId,
|
||||
},
|
||||
});
|
||||
|
||||
await nativeAssert.rejects(
|
||||
async () => {
|
||||
await program.rpc.testOwner({
|
||||
accounts: {
|
||||
data: provider.wallet.publicKey,
|
||||
misc: program.programId,
|
||||
},
|
||||
});
|
||||
},
|
||||
(err) => {
|
||||
return true;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it("Can use the executable attribute", async () => {
|
||||
await program.rpc.testExecutable({
|
||||
accounts: {
|
||||
|
@ -291,292 +450,6 @@ const miscTest = (
|
|||
);
|
||||
});
|
||||
|
||||
it("Can use enum in idl", async () => {
|
||||
const resp1 = await program.methods
|
||||
.testInputEnum({ first: {} })
|
||||
.simulate();
|
||||
const event1 = resp1.events[0].data as IdlEvents<
|
||||
typeof program.idl
|
||||
>["E7"];
|
||||
assert.deepEqual(event1.data.first, {});
|
||||
|
||||
const resp2 = await program.methods
|
||||
.testInputEnum({ second: { x: new BN(1), y: new BN(2) } })
|
||||
.simulate();
|
||||
const event2 = resp2.events[0].data as IdlEvents<
|
||||
typeof program.idl
|
||||
>["E7"];
|
||||
assert.isTrue(new BN(1).eq(event2.data.second.x));
|
||||
assert.isTrue(new BN(2).eq(event2.data.second.y));
|
||||
|
||||
const resp3 = await program.methods
|
||||
.testInputEnum({
|
||||
tupleStructTest: [
|
||||
{ data1: 1, data2: 11, data3: 111, data4: new BN(1111) },
|
||||
],
|
||||
})
|
||||
.simulate();
|
||||
const event3 = resp3.events[0].data as IdlEvents<
|
||||
typeof program.idl
|
||||
>["E7"];
|
||||
assert.strictEqual(event3.data.tupleStructTest[0].data1, 1);
|
||||
assert.strictEqual(event3.data.tupleStructTest[0].data2, 11);
|
||||
assert.strictEqual(event3.data.tupleStructTest[0].data3, 111);
|
||||
assert.isTrue(event3.data.tupleStructTest[0].data4.eq(new BN(1111)));
|
||||
|
||||
const resp4 = await program.methods
|
||||
.testInputEnum({ tupleTest: [1, 2, 3, 4] })
|
||||
.simulate();
|
||||
const event4 = resp4.events[0].data as IdlEvents<
|
||||
typeof program.idl
|
||||
>["E7"];
|
||||
assert.strictEqual(event4.data.tupleTest[0], 1);
|
||||
assert.strictEqual(event4.data.tupleTest[1], 2);
|
||||
assert.strictEqual(event4.data.tupleTest[2], 3);
|
||||
assert.strictEqual(event4.data.tupleTest[3], 4);
|
||||
});
|
||||
|
||||
it("Can use enum in accounts", async () => {
|
||||
const testAccountEnum = async (
|
||||
...args: Parameters<typeof program["methods"]["testAccountEnum"]>
|
||||
) => {
|
||||
const dataKp = anchor.web3.Keypair.generate();
|
||||
const txHash = await program.methods
|
||||
.testAccountEnum(...(args as any))
|
||||
.accounts({
|
||||
data: dataKp.publicKey,
|
||||
payer: program.provider.publicKey,
|
||||
})
|
||||
.signers([dataKp])
|
||||
.rpc();
|
||||
await program.provider.connection.confirmTransaction(txHash);
|
||||
return await program.account.dataEnum.fetch(dataKp.publicKey);
|
||||
};
|
||||
|
||||
// Unit
|
||||
const unit = await testAccountEnum({ first: {} });
|
||||
assert.deepEqual(unit.data.first, {});
|
||||
|
||||
// Named
|
||||
const named = await testAccountEnum({
|
||||
second: { x: new BN(1), y: new BN(2) },
|
||||
});
|
||||
assert.isTrue(new BN(1).eq(named.data.second.x));
|
||||
assert.isTrue(new BN(2).eq(named.data.second.y));
|
||||
|
||||
// Unnamed
|
||||
const unnamed = await testAccountEnum({ tupleTest: [1, 2, 3, 4] });
|
||||
assert.strictEqual(unnamed.data.tupleTest[0], 1);
|
||||
assert.strictEqual(unnamed.data.tupleTest[1], 2);
|
||||
assert.strictEqual(unnamed.data.tupleTest[2], 3);
|
||||
assert.strictEqual(unnamed.data.tupleTest[3], 4);
|
||||
|
||||
// Unnamed struct
|
||||
const unnamedStruct = await testAccountEnum({
|
||||
tupleStructTest: [
|
||||
{ data1: 1, data2: 11, data3: 111, data4: new BN(1111) },
|
||||
],
|
||||
});
|
||||
assert.strictEqual(unnamedStruct.data.tupleStructTest[0].data1, 1);
|
||||
assert.strictEqual(unnamedStruct.data.tupleStructTest[0].data2, 11);
|
||||
assert.strictEqual(unnamedStruct.data.tupleStructTest[0].data3, 111);
|
||||
assert.isTrue(
|
||||
unnamedStruct.data.tupleStructTest[0].data4.eq(new BN(1111))
|
||||
);
|
||||
});
|
||||
|
||||
let dataI8;
|
||||
|
||||
it("Can use i8 in the idl", async () => {
|
||||
dataI8 = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testI8(-3, {
|
||||
accounts: {
|
||||
data: dataI8.publicKey,
|
||||
},
|
||||
instructions: [await program.account.dataI8.createInstruction(dataI8)],
|
||||
signers: [dataI8],
|
||||
});
|
||||
const dataAccount = await program.account.dataI8.fetch(dataI8.publicKey);
|
||||
assert.strictEqual(dataAccount.data, -3);
|
||||
});
|
||||
|
||||
let dataPubkey;
|
||||
|
||||
it("Can use i16 in the idl", async () => {
|
||||
const data = anchor.web3.Keypair.generate();
|
||||
await program.rpc.testI16(-2048, {
|
||||
accounts: {
|
||||
data: data.publicKey,
|
||||
},
|
||||
instructions: [await program.account.dataI16.createInstruction(data)],
|
||||
signers: [data],
|
||||
});
|
||||
const dataAccount = await program.account.dataI16.fetch(data.publicKey);
|
||||
assert.strictEqual(dataAccount.data, -2048);
|
||||
|
||||
dataPubkey = data.publicKey;
|
||||
});
|
||||
|
||||
it("Can use base58 strings to fetch an account", async () => {
|
||||
const dataAccount = await program.account.dataI16.fetch(
|
||||
dataPubkey.toString()
|
||||
);
|
||||
assert.strictEqual(dataAccount.data, -2048);
|
||||
});
|
||||
|
||||
it("Should fail to close an account when sending lamports to itself", async () => {
|
||||
try {
|
||||
await program.rpc.testClose({
|
||||
accounts: {
|
||||
data: data.publicKey,
|
||||
solDest: data.publicKey,
|
||||
},
|
||||
});
|
||||
expect(false).to.be.true;
|
||||
} catch (err) {
|
||||
const errMsg = "A close constraint was violated";
|
||||
assert.strictEqual(err.error.errorMessage, errMsg);
|
||||
assert.strictEqual(err.error.errorCode.number, 2011);
|
||||
}
|
||||
});
|
||||
|
||||
it("Can close an account", async () => {
|
||||
const connection = program.provider.connection;
|
||||
const openAccount = await connection.getAccountInfo(data.publicKey);
|
||||
|
||||
assert.isNotNull(openAccount);
|
||||
const openAccountBalance = openAccount.lamports;
|
||||
// double balance to calculate closed balance correctly
|
||||
const transferIx = anchor.web3.SystemProgram.transfer({
|
||||
fromPubkey: provider.wallet.publicKey,
|
||||
toPubkey: data.publicKey,
|
||||
lamports: openAccountBalance,
|
||||
});
|
||||
const transferTransaction = new anchor.web3.Transaction().add(transferIx);
|
||||
await provider.sendAndConfirm(transferTransaction);
|
||||
|
||||
let beforeBalance = (
|
||||
await connection.getAccountInfo(provider.wallet.publicKey)
|
||||
).lamports;
|
||||
|
||||
await program.methods
|
||||
.testClose()
|
||||
.accounts({
|
||||
data: data.publicKey,
|
||||
solDest: provider.wallet.publicKey,
|
||||
})
|
||||
.postInstructions([transferIx])
|
||||
.rpc();
|
||||
|
||||
let afterBalance = (
|
||||
await connection.getAccountInfo(provider.wallet.publicKey)
|
||||
).lamports;
|
||||
|
||||
// Retrieved rent exemption sol.
|
||||
expect(afterBalance > beforeBalance).to.be.true;
|
||||
|
||||
const closedAccount = await connection.getAccountInfo(data.publicKey);
|
||||
|
||||
assert.isTrue(closedAccount.data.length === 0);
|
||||
assert.isTrue(closedAccount.owner.equals(SystemProgram.programId));
|
||||
});
|
||||
|
||||
it("Can close an account twice", async () => {
|
||||
const data = anchor.web3.Keypair.generate();
|
||||
await program.methods
|
||||
.initialize(new anchor.BN(10), new anchor.BN(10))
|
||||
.accounts({ data: data.publicKey })
|
||||
.preInstructions([await program.account.data.createInstruction(data)])
|
||||
.signers([data])
|
||||
.rpc();
|
||||
|
||||
const connection = program.provider.connection;
|
||||
const openAccount = await connection.getAccountInfo(data.publicKey);
|
||||
assert.isNotNull(openAccount);
|
||||
|
||||
const openAccountBalance = openAccount.lamports;
|
||||
// double balance to calculate closed balance correctly
|
||||
const transferIx = anchor.web3.SystemProgram.transfer({
|
||||
fromPubkey: provider.wallet.publicKey,
|
||||
toPubkey: data.publicKey,
|
||||
lamports: openAccountBalance,
|
||||
});
|
||||
const transferTransaction = new anchor.web3.Transaction().add(transferIx);
|
||||
await provider.sendAndConfirm(transferTransaction);
|
||||
|
||||
let beforeBalance = (
|
||||
await connection.getAccountInfo(provider.wallet.publicKey)
|
||||
).lamports;
|
||||
|
||||
await program.methods
|
||||
.testCloseTwice()
|
||||
.accounts({
|
||||
data: data.publicKey,
|
||||
solDest: provider.wallet.publicKey,
|
||||
})
|
||||
.postInstructions([transferIx])
|
||||
.rpc();
|
||||
|
||||
let afterBalance = (
|
||||
await connection.getAccountInfo(provider.wallet.publicKey)
|
||||
).lamports;
|
||||
|
||||
// Retrieved rent exemption sol.
|
||||
expect(afterBalance > beforeBalance).to.be.true;
|
||||
|
||||
const closedAccount = await connection.getAccountInfo(data.publicKey);
|
||||
assert.isTrue(closedAccount.data.length === 0);
|
||||
assert.isTrue(closedAccount.owner.equals(SystemProgram.programId));
|
||||
});
|
||||
|
||||
it("Can close a mut account manually", async () => {
|
||||
const data = anchor.web3.Keypair.generate();
|
||||
await program.methods
|
||||
.initialize(new anchor.BN(10), new anchor.BN(10))
|
||||
.accounts({ data: data.publicKey })
|
||||
.preInstructions([await program.account.data.createInstruction(data)])
|
||||
.signers([data])
|
||||
.rpc();
|
||||
|
||||
const connection = program.provider.connection;
|
||||
const openAccount = await connection.getAccountInfo(data.publicKey);
|
||||
|
||||
assert.isNotNull(openAccount);
|
||||
const openAccountBalance = openAccount.lamports;
|
||||
// double balance to calculate closed balance correctly
|
||||
const transferIx = anchor.web3.SystemProgram.transfer({
|
||||
fromPubkey: provider.wallet.publicKey,
|
||||
toPubkey: data.publicKey,
|
||||
lamports: openAccountBalance,
|
||||
});
|
||||
const transferTransaction = new anchor.web3.Transaction().add(transferIx);
|
||||
await provider.sendAndConfirm(transferTransaction);
|
||||
|
||||
let beforeBalance = (
|
||||
await connection.getAccountInfo(provider.wallet.publicKey)
|
||||
).lamports;
|
||||
|
||||
await program.methods
|
||||
.testCloseMut()
|
||||
.accounts({
|
||||
data: data.publicKey,
|
||||
solDest: provider.wallet.publicKey,
|
||||
})
|
||||
.postInstructions([transferIx])
|
||||
.rpc();
|
||||
|
||||
let afterBalance = (
|
||||
await connection.getAccountInfo(provider.wallet.publicKey)
|
||||
).lamports;
|
||||
|
||||
// Retrieved rent exemption sol.
|
||||
expect(afterBalance > beforeBalance).to.be.true;
|
||||
|
||||
const closedAccount = await connection.getAccountInfo(data.publicKey);
|
||||
assert.isTrue(closedAccount.data.length === 0);
|
||||
assert.isTrue(closedAccount.owner.equals(SystemProgram.programId));
|
||||
});
|
||||
|
||||
it("Can use instruction data in accounts constraints", async () => {
|
||||
// b"my-seed"
|
||||
const seed = Buffer.from([109, 121, 45, 115, 101, 101, 100]);
|
||||
|
@ -1501,27 +1374,6 @@ const miscTest = (
|
|||
assert.deepStrictEqual(dataAccount.data, dataArray);
|
||||
});
|
||||
|
||||
it("Should include BASE const in IDL", async () => {
|
||||
assert.isDefined(
|
||||
miscIdl.constants.find(
|
||||
(c) =>
|
||||
c.name === "BASE" && c.type === "u128" && c.value === "1_000_000"
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it("Should include DECIMALS const in IDL", async () => {
|
||||
assert.isDefined(
|
||||
miscIdl.constants.find(
|
||||
(c) => c.name === "DECIMALS" && c.type === "u8" && c.value === "6"
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it("Should not include NO_IDL const in IDL", async () => {
|
||||
assert.isUndefined(miscIdl.constants.find((c) => c.name === "NO_IDL"));
|
||||
});
|
||||
|
||||
it("init_if_needed creates mint account if not exists", async () => {
|
||||
const newMint = anchor.web3.Keypair.generate();
|
||||
|
||||
|
@ -2678,6 +2530,7 @@ const miscTest = (
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("Token Constraint Test", () => {
|
||||
it("Token Constraint Test(no init) - Can make token::mint and token::authority", async () => {
|
||||
const mint = anchor.web3.Keypair.generate();
|
||||
|
@ -3349,22 +3202,6 @@ const miscTest = (
|
|||
);
|
||||
assert.isDefined(thisTx);
|
||||
});
|
||||
it("Can access enum variant fields using camel case without throwing a type error", async () => {
|
||||
const anotherProgram = new anchor.Program<Misc>(
|
||||
miscIdl,
|
||||
program.programId,
|
||||
provider
|
||||
);
|
||||
const enumWrappers =
|
||||
await anotherProgram.account.coolEnumWrapperAccount.all();
|
||||
for (let enumWrapper of enumWrappers) {
|
||||
// this code never gets run so just putting whatever
|
||||
console.log(enumWrapper.account.myEnum.variant2?.someSlot);
|
||||
console.log(enumWrapper.account.myEnum.variant2?.user1);
|
||||
console.log(enumWrapper.account.myEnum.variant3?.someSlot);
|
||||
console.log(enumWrapper.account.myEnum.variant3?.user2);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue