import * as anchor from "@coral-xyz/anchor"; import { Program } from "@coral-xyz/anchor"; import { Bets } from "../target/types/bets"; import { Keypair, PublicKey, LAMPORTS_PER_SOL, Transaction, SystemProgram } from "@solana/web3.js"; import { ProgramTestContext, startAnchor } from "solana-bankrun"; import { BankrunProvider } from "anchor-bankrun"; import { expect } from "chai"; import { BN } from "@coral-xyz/anchor"; const IDL = require('../target/idl/bets.json'); const betsAddress = new PublicKey("Haj94DF925qNRgcoRwQfNsVLKgSmFhG4bjgtvusMkkpD"); describe("bets", () => { let context: ProgramTestContext; let provider: BankrunProvider; let betsProgram: Program; let user1: Keypair; let user2: Keypair; let gameId = "game123"; let userId1 = "user123"; let userId2 = "user456"; let wager = new BN(LAMPORTS_PER_SOL); // 1 SOL before(async () => { context = await startAnchor("", [{ name: "bets", programId: betsAddress }], []); provider = new BankrunProvider(context); betsProgram = new Program(IDL, provider); // Create test users user1 = Keypair.generate(); user2 = Keypair.generate(); // Fund accounts using bankrun const fundAmount = 10 * LAMPORTS_PER_SOL; // Create accounts first by sending a transaction const tx = new Transaction().add( SystemProgram.createAccount({ fromPubkey: context.payer.publicKey, newAccountPubkey: user1.publicKey, lamports: fundAmount, space: 0, programId: SystemProgram.programId, }), SystemProgram.createAccount({ fromPubkey: context.payer.publicKey, newAccountPubkey: user2.publicKey, lamports: fundAmount, space: 0, programId: SystemProgram.programId, }) ); // Get recent blockhash and set it on the transaction const [blockhash] = await context.banksClient.getLatestBlockhash(); tx.recentBlockhash = blockhash; tx.feePayer = context.payer.publicKey; // Sign the transaction with all required signers tx.sign(context.payer, user1, user2); await context.banksClient.processTransaction(tx); }); it("Initializes the bets list", async () => { await betsProgram.methods.initialize().rpc(); const [betsListAddress] = PublicKey.findProgramAddressSync( [Buffer.from("bets_list")], betsAddress ); const betsList = await betsProgram.account.betsList.fetch(betsListAddress); expect(betsList.bets).to.be.an('array').that.is.empty; }); it("Creates a new bet", async () => { const nonce = new BN(Date.now()); await betsProgram.methods .createBet(wager, userId1, gameId, nonce) .accounts({ payer: user1.publicKey, betsList: (await PublicKey.findProgramAddressSync( [Buffer.from("bets_list")], betsAddress ))[0], }) .signers([user1]) .rpc(); const [betVaultAddress] = PublicKey.findProgramAddressSync( [ Buffer.from("bet_vault"), user1.publicKey.toBuffer(), Buffer.from(gameId), nonce.toArrayLike(Buffer, "le", 8), ], betsAddress ); const betVault = await betsProgram.account.betVault.fetch(betVaultAddress); expect(betVault.gameId).to.equal(gameId); expect(betVault.owner).to.eql(user1.publicKey); // expect(betVault.ownerId).to.equal(userId1); // expect(betVault.wager).to.equal(wager); }); it("Joins an existing bet", async () => { const nonce = new BN(Date.now()); // First create a bet await betsProgram.methods .createBet(wager, userId1, gameId, nonce) .accounts({ payer: user1.publicKey, betsList: (await PublicKey.findProgramAddressSync( [Buffer.from("bets_list")], betsAddress ))[0], }) .signers([user1]) .rpc(); // Then join the bet await betsProgram.methods .joinBet(userId2, gameId) .accounts({ betVault: (await PublicKey.findProgramAddressSync( [ Buffer.from("bet_vault"), user1.publicKey.toBuffer(), Buffer.from(gameId), nonce.toArrayLike(Buffer, "le", 8), ], betsAddress ))[0], payer: user2.publicKey }) .signers([user2]) .rpc(); const [betVaultAddress] = PublicKey.findProgramAddressSync( [ Buffer.from("bet_vault"), user1.publicKey.toBuffer(), Buffer.from(gameId), nonce.toArrayLike(Buffer, "le", 8), ], betsAddress ); const betVault = await betsProgram.account.betVault.fetch(betVaultAddress); expect(betVault.joiner).to.eql(user2.publicKey); expect(betVault.joinerId).to.equal(userId2); }); it("Closes a bet with a winner", async () => { const nonce = new BN(Date.now()); // First create a bet await betsProgram.methods .createBet(wager, userId1, gameId, nonce) .accounts({ payer: user1.publicKey, betsList: (await PublicKey.findProgramAddressSync( [Buffer.from("bets_list")], betsAddress ))[0], }) .signers([user1]) .rpc(); // Join the bet await betsProgram.methods .joinBet(userId2, gameId) .accounts({ betVault: (await PublicKey.findProgramAddressSync( [ Buffer.from("bet_vault"), user1.publicKey.toBuffer(), Buffer.from(gameId), nonce.toArrayLike(Buffer, "le", 8), ], betsAddress ))[0], payer: user2.publicKey }) .signers([user2]) .rpc(); // Close the bet with user1 as winner await betsProgram.methods .closeBet(user1.publicKey, userId1) .accounts({ betsList: (await PublicKey.findProgramAddressSync( [Buffer.from("bets_list")], betsAddress ))[0], betVault: (await PublicKey.findProgramAddressSync( [ Buffer.from("bet_vault"), user1.publicKey.toBuffer(), Buffer.from(gameId), nonce.toArrayLike(Buffer, "le", 8), ], betsAddress ))[0], winner: user1.publicKey, payer: user1.publicKey, }) .signers([user1]) .rpc(); // Verify the bet is removed from the bets list const [betsListAddress] = PublicKey.findProgramAddressSync( [Buffer.from("bets_list")], betsAddress ); const betsList = await betsProgram.account.betsList.fetch(betsListAddress); const [betVaultAddress] = PublicKey.findProgramAddressSync( [ Buffer.from("bet_vault"), user1.publicKey.toBuffer(), Buffer.from(gameId), nonce.toArrayLike(Buffer, "le", 8), ], betsAddress ); expect(betsList.bets).to.not.include(betVaultAddress); }); });