| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
- import {
- Blockhash,
- Keypair,
- PublicKey,
- SystemProgram,
- Transaction,
- TransactionInstruction,
- } from "@solana/web3.js";
- import { BN } from "bn.js";
- import * as borsh from "borsh";
- import { assert, expect } from "chai";
- import { describe, test } from "mocha";
- import { BanksClient, ProgramTestContext, start } from "solana-bankrun";
- // This is a helper class to assign properties to the class
- class Assignable {
- constructor(properties) {
- for (const [key, value] of Object.entries(properties)) {
- this[key] = value;
- }
- }
- }
- const MyInstruction = {
- CreateFav: 0,
- GetFav: 1,
- } as const;
- class CreateFav extends Assignable {
- number: number;
- instruction: MyInstruction;
- color: string;
- hobbies: string[];
- toBuffer() {
- return Buffer.from(borsh.serialize(CreateNewAccountSchema, this));
- }
- static fromBuffer(buffer: Buffer): CreateFav {
- return borsh.deserialize(
- {
- struct: {
- number: "u64",
- color: "string",
- hobbies: {
- array: {
- type: "string",
- },
- },
- },
- },
- buffer,
- ) as CreateFav;
- }
- }
- const CreateNewAccountSchema = {
- struct: {
- instruction: "u8",
- number: "u64",
- color: "string",
- hobbies: {
- array: {
- type: "string",
- },
- },
- },
- };
- class GetFav extends Assignable {
- toBuffer() {
- return Buffer.from(borsh.serialize(GetFavSchema, this));
- }
- }
- const GetFavSchema = {
- struct: {
- instruction: "u8",
- },
- };
- describe("Favorites Solana Native", () => {
- // Randomly generate the program keypair and load the program to solana-bankrun
- const programId = PublicKey.unique();
- let context: ProgramTestContext;
- let client: BanksClient;
- let payer: Keypair;
- let blockhash: Blockhash;
- beforeEach(async () => {
- context = await start([{ name: "favorites_native", programId }], []);
- client = context.banksClient;
- // Get the payer keypair from the context, this will be used to sign transactions with enough lamports
- payer = context.payer;
- blockhash = context.lastBlockhash;
- });
- test("Set the favorite pda and cross-check the updated data", async () => {
- const favoritesPda = PublicKey.findProgramAddressSync(
- [Buffer.from("favorite"), payer.publicKey.toBuffer()],
- programId,
- )[0];
- const favData = {
- instruction: MyInstruction.CreateFav,
- number: 42,
- color: "blue",
- hobbies: ["coding", "reading", "traveling"],
- };
- const favorites = new CreateFav(favData);
- const ix = new TransactionInstruction({
- keys: [
- { pubkey: payer.publicKey, isSigner: true, isWritable: true },
- { pubkey: favoritesPda, isSigner: false, isWritable: true },
- { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
- ],
- programId,
- data: favorites.toBuffer(),
- });
- const tx = new Transaction().add(ix);
- tx.feePayer = payer.publicKey;
- tx.recentBlockhash = blockhash;
- tx.sign(payer);
- tx.recentBlockhash = blockhash;
- await client.processTransaction(tx);
- const account = await client.getAccount(favoritesPda);
- const data = Buffer.from(account.data);
- const favoritesData = CreateFav.fromBuffer(data);
- console.log("Deserialized data:", favoritesData);
- expect(new BN(favoritesData.number as any, "le").toNumber()).to.equal(
- favData.number,
- );
- expect(favoritesData.color).to.equal(favData.color);
- expect(favoritesData.hobbies).to.deep.equal(favData.hobbies);
- });
- test("Check if the test fails if the pda seeds aren't same", async () => {
- // We put the wrong seeds knowingly to see if the test fails because of checks
- const favoritesPda = PublicKey.findProgramAddressSync(
- [Buffer.from("favorite"), payer.publicKey.toBuffer()],
- programId,
- )[0];
- const favData = {
- instruction: MyInstruction.CreateFav,
- number: 42,
- color: "blue",
- hobbies: ["coding", "reading", "traveling"],
- };
- const favorites = new CreateFav(favData);
- const ix = new TransactionInstruction({
- keys: [
- { pubkey: payer.publicKey, isSigner: true, isWritable: true },
- { pubkey: favoritesPda, isSigner: false, isWritable: true },
- { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
- ],
- programId,
- data: favorites.toBuffer(),
- });
- const tx = new Transaction().add(ix);
- tx.feePayer = payer.publicKey;
- tx.recentBlockhash = blockhash;
- tx.sign(payer);
- tx.recentBlockhash = blockhash;
- try {
- await client.processTransaction(tx);
- console.error("Expected the test to fail");
- } catch (_err) {
- assert(true);
- }
- });
- test("Get the favorite pda and cross-check the data", async () => {
- // Creating a new account with payer's pubkey
- const favoritesPda = PublicKey.findProgramAddressSync(
- [Buffer.from("favorite"), payer.publicKey.toBuffer()],
- programId,
- )[0];
- const favData = {
- instruction: MyInstruction.CreateFav,
- number: 42,
- color: "hazel",
- hobbies: ["singing", "dancing", "skydiving"],
- };
- const favorites = new CreateFav(favData);
- const ix = new TransactionInstruction({
- keys: [
- { pubkey: payer.publicKey, isSigner: true, isWritable: true },
- { pubkey: favoritesPda, isSigner: false, isWritable: true },
- { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
- ],
- programId,
- data: favorites.toBuffer(),
- });
- const tx1 = new Transaction().add(ix);
- tx1.feePayer = payer.publicKey;
- tx1.recentBlockhash = blockhash;
- tx1.sign(payer);
- tx1.recentBlockhash = blockhash;
- await client.processTransaction(tx1);
- // Getting the user's data through the get_pda instruction
- const getfavData = { instruction: MyInstruction.GetFav };
- const getfavorites = new GetFav(getfavData);
- const ix2 = new TransactionInstruction({
- keys: [
- { pubkey: payer.publicKey, isSigner: true, isWritable: true },
- { pubkey: favoritesPda, isSigner: false, isWritable: false },
- ],
- programId,
- data: getfavorites.toBuffer(),
- });
- const tx = new Transaction().add(ix2);
- tx.feePayer = payer.publicKey;
- tx.recentBlockhash = blockhash;
- tx.sign(payer);
- tx.recentBlockhash = blockhash;
- await client.processTransaction(tx);
- });
- });
|