favorites-bankrun.test.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import { describe, it } from 'node:test';
  2. import * as anchor from '@coral-xyz/anchor';
  3. import { getCustomErrorMessage } from '@solana-developers/helpers';
  4. import { PublicKey } from '@solana/web3.js';
  5. import { BankrunProvider } from 'anchor-bankrun';
  6. import { assert } from 'chai';
  7. import { startAnchor } from 'solana-bankrun';
  8. import type { Favorites } from '../target/types/favorites';
  9. import { systemProgramErrors } from './system-errors';
  10. const web3 = anchor.web3;
  11. const IDL = require('../target/idl/favorites.json');
  12. const PROGRAM_ID = new PublicKey(IDL.address);
  13. describe('Favorites Bankrun', async () => {
  14. // Use the cluster and the keypair from Anchor.toml
  15. // Load programs into anchor-bankrun
  16. const context = await startAnchor('', [{ name: 'favorites', programId: PROGRAM_ID }], []);
  17. const provider = new BankrunProvider(context);
  18. anchor.setProvider(provider);
  19. const user = (provider.wallet as anchor.Wallet).payer;
  20. const someRandomGuy = anchor.web3.Keypair.generate();
  21. const program = new anchor.Program<Favorites>(IDL, provider);
  22. // Here's what we want to write to the blockchain
  23. const favoriteNumber = new anchor.BN(23);
  24. const favoriteColor = 'purple';
  25. const favoriteHobbies = ['skiing', 'skydiving', 'biking'];
  26. // We don't need to airdrop if we're using the local cluster
  27. // because the local cluster gives us 1,000,000 SOL
  28. const balance = await context.banksClient.getBalance(user.publicKey);
  29. const balanceInSOL = balance / BigInt(web3.LAMPORTS_PER_SOL);
  30. const formattedBalance = new Intl.NumberFormat().format(balanceInSOL);
  31. console.log(`Balance: ${formattedBalance} SOL`);
  32. it('Writes our favorites to the blockchain', async () => {
  33. await program.methods
  34. // set_favourites in Rust becomes setFavorites in TypeScript
  35. .setFavorites(favoriteNumber, favoriteColor, favoriteHobbies)
  36. // Sign the transaction
  37. .signers([user])
  38. // Send the transaction to the cluster or RPC
  39. .rpc();
  40. // Find the PDA for the user's favorites
  41. const favoritesPdaAndBump = web3.PublicKey.findProgramAddressSync([Buffer.from('favorites'), user.publicKey.toBuffer()], program.programId);
  42. const favoritesPda = favoritesPdaAndBump[0];
  43. const dataFromPda = await program.account.favorites.fetch(favoritesPda);
  44. // And make sure it matches!
  45. assert.equal(dataFromPda.color, favoriteColor);
  46. // A little extra work to make sure the BNs are equal
  47. assert.equal(dataFromPda.number.toString(), favoriteNumber.toString());
  48. // And check the hobbies too
  49. assert.deepEqual(dataFromPda.hobbies, favoriteHobbies);
  50. });
  51. it('Updates the favorites', async () => {
  52. const newFavoriteHobbies = ['skiing', 'skydiving', 'biking', 'swimming'];
  53. try {
  54. await program.methods.setFavorites(favoriteNumber, favoriteColor, newFavoriteHobbies).signers([user]).rpc();
  55. } catch (error) {
  56. console.error((error as Error).message);
  57. const customErrorMessage = getCustomErrorMessage(systemProgramErrors, error);
  58. throw new Error(customErrorMessage);
  59. }
  60. });
  61. it('Rejects transactions from unauthorized signers', async () => {
  62. try {
  63. await program.methods
  64. // set_favourites in Rust becomes setFavorites in TypeScript
  65. .setFavorites(favoriteNumber, favoriteColor, favoriteHobbies)
  66. // Sign the transaction
  67. .signers([someRandomGuy])
  68. // Send the transaction to the cluster or RPC
  69. .rpc();
  70. } catch (error) {
  71. const errorMessage = (error as Error).message;
  72. assert.isTrue(errorMessage.includes('unknown signer'));
  73. }
  74. });
  75. });