123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- import { describe, test } from 'mocha';
- import { assert, expect } from 'chai';
- import { Blockhash, Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction } from '@solana/web3.js';
- import { BanksClient, ProgramTestContext, Rent, start , } from 'solana-bankrun';
- import { BN } from 'bn.js';
- import * as borsh from "borsh"
- // 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;
- }
- }
- }
- enum MyInstruction {
- CreateFav = 0,
- GetFav = 1,
- }
- 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, client:BanksClient, payer: Keypair, 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);
- })
- })
|