123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- 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, Rent, 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;
- }
- }
- }
- 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;
- 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);
- });
- });
|