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