anchor/tests/custom-coder/tests/system-coder.ts

426 lines
12 KiB
TypeScript

import * as anchor from "@coral-xyz/anchor";
import { Native } from "@coral-xyz/anchor";
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
import {
Keypair,
LAMPORTS_PER_SOL,
NONCE_ACCOUNT_LENGTH,
PublicKey,
SystemProgram,
SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
} from "@solana/web3.js";
import * as assert from "assert";
import BN from "bn.js";
describe("system-coder", () => {
// Configure the client to use the local cluster.
const provider = anchor.AnchorProvider.env();
anchor.setProvider(provider);
// Client.
const program = Native.system();
// Constants.
const aliceKeypair = Keypair.generate();
it("Creates an account", async () => {
// arrange
const space = 100;
const lamports =
await program.provider.connection.getMinimumBalanceForRentExemption(
space
);
const owner = SystemProgram.programId;
// act
await program.methods
.createAccount(new BN(lamports), new BN(space), owner)
.accounts({
from: provider.wallet.publicKey,
to: aliceKeypair.publicKey,
})
.signers([aliceKeypair])
.rpc();
// assert
const aliceAccount = await program.provider.connection.getAccountInfo(
aliceKeypair.publicKey
);
assert.notEqual(aliceAccount, null);
assert.ok(owner.equals(aliceAccount.owner));
assert.equal(lamports, aliceAccount.lamports);
});
it("Assigns an account to a program", async () => {
// arrange
const owner = TOKEN_PROGRAM_ID;
// act
await program.methods
.assign(owner)
.accounts({
pubkey: aliceKeypair.publicKey,
})
.signers([aliceKeypair])
.rpc();
// assert
const aliceAccount = await program.provider.connection.getAccountInfo(
aliceKeypair.publicKey
);
assert.notEqual(aliceAccount, null);
assert.ok(owner.equals(aliceAccount.owner));
});
it("Allocates space to an account", async () => {
// arrange
const newKeypair = Keypair.generate();
const space = 100;
const lamports =
await program.provider.connection.getMinimumBalanceForRentExemption(
space
);
// act
await program.methods
.allocate(new BN(space))
.accounts({
pubkey: newKeypair.publicKey,
})
.postInstructions([
await program.methods
.transfer(new BN(lamports))
.accounts({
from: provider.wallet.publicKey,
to: newKeypair.publicKey,
})
.instruction(),
])
.signers([newKeypair])
.rpc();
// assert
const newAccountAfter = await program.provider.connection.getAccountInfo(
newKeypair.publicKey
);
assert.equal(space, newAccountAfter.data.byteLength);
});
it("Creates an account with seed", async () => {
const space = 100;
const lamports =
await program.provider.connection.getMinimumBalanceForRentExemption(
space
);
const owner = SystemProgram.programId;
const seed = "seeds";
const bobPublicKey = await PublicKey.createWithSeed(
aliceKeypair.publicKey,
seed,
owner
);
// act
await program.methods
.createAccountWithSeed(
aliceKeypair.publicKey,
seed,
new BN(lamports),
new BN(space),
owner
)
.accounts({
base: aliceKeypair.publicKey,
from: provider.wallet.publicKey,
to: bobPublicKey,
})
.signers([aliceKeypair])
.rpc();
// assert
const bobAccount = await program.provider.connection.getAccountInfo(
bobPublicKey
);
assert.notEqual(bobAccount, null);
});
it("Allocates and assigns an account with seed", async () => {
const owner = TOKEN_PROGRAM_ID;
const seed = "seeds2";
const space = 100;
const lamports =
await program.provider.connection.getMinimumBalanceForRentExemption(
space
);
const bobPublicKey = await PublicKey.createWithSeed(
aliceKeypair.publicKey,
seed,
owner
);
// act
await program.methods
.allocateWithSeed(aliceKeypair.publicKey, seed, new BN(space), owner)
.accounts({
base: aliceKeypair.publicKey,
account: bobPublicKey,
})
.postInstructions([
await program.methods
.transfer(new BN(lamports))
.accounts({
from: provider.wallet.publicKey,
to: bobPublicKey,
})
.instruction(),
await program.methods
.assignWithSeed(aliceKeypair.publicKey, seed, owner)
.accounts({
base: aliceKeypair.publicKey,
account: bobPublicKey,
})
.instruction(),
])
.signers([aliceKeypair])
.rpc();
// assert
const bobAccount = await program.provider.connection.getAccountInfo(
bobPublicKey
);
assert.notEqual(bobAccount, null);
assert.ok(owner.equals(bobAccount.owner));
});
it("Transfers from account with seed", async () => {
const lamports = 1 * LAMPORTS_PER_SOL;
const owner = SystemProgram.programId;
const seed = "seeds3";
const bobPublicKey = await PublicKey.createWithSeed(
aliceKeypair.publicKey,
seed,
owner
);
const aliceAccountBefore = await program.provider.connection.getAccountInfo(
aliceKeypair.publicKey
);
// act
await program.methods
.transfer(new BN(lamports))
.accounts({
from: provider.wallet.publicKey,
to: bobPublicKey,
})
.rpc();
await program.methods
.transferWithSeed(new BN(lamports), seed, owner)
.accounts({
from: bobPublicKey,
base: aliceKeypair.publicKey,
to: aliceKeypair.publicKey,
})
.signers([aliceKeypair])
.rpc();
// assert
const aliceAccountAfter = await program.provider.connection.getAccountInfo(
aliceKeypair.publicKey
);
assert.equal(
aliceAccountBefore.lamports + lamports,
aliceAccountAfter.lamports
);
});
it("Transfers lamports", async () => {
// arrange
const receiverKeypair = Keypair.generate();
const lamports = 0.1 * LAMPORTS_PER_SOL;
// act
await program.methods
.transfer(new BN(lamports))
.accounts({
from: provider.wallet.publicKey,
to: receiverKeypair.publicKey,
})
.rpc();
// assert
const receiverAccount = await program.provider.connection.getAccountInfo(
receiverKeypair.publicKey
);
assert.notEqual(receiverAccount, null);
assert.equal(lamports, receiverAccount.lamports);
});
it("Initializes nonce account", async () => {
// arrange
const nonceKeypair = Keypair.generate();
const owner = SystemProgram.programId;
const space = NONCE_ACCOUNT_LENGTH;
const lamports =
await provider.connection.getMinimumBalanceForRentExemption(space);
// act
await program.methods
.initializeNonceAccount(provider.wallet.publicKey)
.accounts({
nonce: nonceKeypair.publicKey,
recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
})
.preInstructions([
await program.methods
.createAccount(new BN(lamports), new BN(space), owner)
.accounts({
from: provider.wallet.publicKey,
to: nonceKeypair.publicKey,
})
.instruction(),
])
.signers([nonceKeypair])
.rpc();
// assert
const nonceAccount = await program.account.nonce.fetch(
nonceKeypair.publicKey
);
assert.notEqual(nonceAccount, null);
assert.ok(nonceAccount.authorizedPubkey.equals(provider.wallet.publicKey));
});
it("Advances a nonce account", async () => {
// arrange
const nonceKeypair = Keypair.generate();
const owner = SystemProgram.programId;
const space = NONCE_ACCOUNT_LENGTH;
const lamports =
await provider.connection.getMinimumBalanceForRentExemption(space);
// act
await program.methods
.initializeNonceAccount(provider.wallet.publicKey)
.accounts({
nonce: nonceKeypair.publicKey,
recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
})
.preInstructions([
await program.methods
.createAccount(new BN(lamports), new BN(space), owner)
.accounts({
from: provider.wallet.publicKey,
to: nonceKeypair.publicKey,
})
.instruction(),
])
.signers([nonceKeypair])
.rpc();
// These have to be separate to make sure advance is in another slot.
await program.methods
.advanceNonceAccount(provider.wallet.publicKey)
.accounts({
nonce: nonceKeypair.publicKey,
recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
})
.rpc();
// assert
const nonceAccount = await program.account.nonce.fetch(
nonceKeypair.publicKey
);
assert.notEqual(nonceAccount, null);
});
it("Authorizes a nonce account", async () => {
// arrange
const nonceKeypair = Keypair.generate();
const owner = SystemProgram.programId;
const space = NONCE_ACCOUNT_LENGTH;
const lamports =
await provider.connection.getMinimumBalanceForRentExemption(space);
// act
await program.methods
.initializeNonceAccount(provider.wallet.publicKey)
.accounts({
nonce: nonceKeypair.publicKey,
recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
})
.preInstructions([
await program.methods
.createAccount(new BN(lamports), new BN(space), owner)
.accounts({
from: provider.wallet.publicKey,
to: nonceKeypair.publicKey,
})
.instruction(),
])
.signers([nonceKeypair])
.rpc();
await program.methods
.authorizeNonceAccount(aliceKeypair.publicKey)
.accounts({
nonce: nonceKeypair.publicKey,
authorized: provider.wallet.publicKey,
})
.rpc();
// assert
const nonceAccount = await program.account.nonce.fetch(
nonceKeypair.publicKey
);
assert.notEqual(nonceAccount, null);
assert.ok(nonceAccount.authorizedPubkey.equals(aliceKeypair.publicKey));
});
it("Withdraws from nonce account", async () => {
// arrange
const nonceKeypair = Keypair.generate();
const owner = SystemProgram.programId;
const space = NONCE_ACCOUNT_LENGTH;
const lamports =
await provider.connection.getMinimumBalanceForRentExemption(space);
const amount = 0.1 * LAMPORTS_PER_SOL;
const aliceBalanceBefore = (
await program.provider.connection.getAccountInfo(aliceKeypair.publicKey)
).lamports;
// act
await program.methods
.initializeNonceAccount(provider.wallet.publicKey)
.accounts({
nonce: nonceKeypair.publicKey,
recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
})
.preInstructions([
await program.methods
.createAccount(new BN(lamports), new BN(space), owner)
.accounts({
from: provider.wallet.publicKey,
to: nonceKeypair.publicKey,
})
.instruction(),
])
.signers([nonceKeypair])
.rpc();
await program.methods
.advanceNonceAccount(provider.wallet.publicKey)
.accounts({
nonce: nonceKeypair.publicKey,
recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
})
.postInstructions([
await program.methods
.transfer(new BN(amount))
.accounts({
from: provider.wallet.publicKey,
to: nonceKeypair.publicKey,
})
.instruction(),
])
.rpc();
await program.methods
.authorizeNonceAccount(aliceKeypair.publicKey)
.accounts({
nonce: nonceKeypair.publicKey,
authorized: provider.wallet.publicKey,
})
.rpc();
await program.methods
.withdrawNonceAccount(new BN(amount))
.accounts({
authorized: aliceKeypair.publicKey,
nonce: nonceKeypair.publicKey,
recentBlockhashes: SYSVAR_RECENT_BLOCKHASHES_PUBKEY,
to: aliceKeypair.publicKey,
})
.signers([aliceKeypair])
.rpc();
// assert
const aliceBalanceAfter = (
await program.provider.connection.getAccountInfo(aliceKeypair.publicKey)
).lamports;
assert.equal(aliceBalanceAfter - aliceBalanceBefore, amount);
});
});