I've looked around and I see this is a common error that devs run into based on the fact that an account was already initialized. I'm just wondering how to fix it so that I can run tests without running into this error. I'm testing on localnet and I've already tried deleting the test-ledger folder and running solana-test-validator -r
but neither works. So here is my code. The first two tests pass, it's the third test where I think the gameAccountPDA
is being used again that's causing the failure.
GameTest.ts
const provider = anchor.AnchorProvider.env(); const ownerWallet = provider.wallet as anchor.Wallet; console.log('ownerWallet: ', ownerWallet.publicKey.toString()) anchor.setProvider(provider) const systemProgram = SystemProgram.programId; const program = anchor.workspace.Game as Program<Game>; let [playerAccount,] = web3.PublicKey.findProgramAddressSync( [ownerWallet.publicKey.toBuffer()], program.programId ); console.log( 'player account: ', playerAccount.toString()) let [counterAccount,] = web3.PublicKey.findProgramAddressSync( [ownerWallet.publicKey.toBuffer()], program.programId ); console.log( 'counter account: ', counterAccount.toString()) // PDA's let [gameAcctPDA,] = web3.PublicKey.findProgramAddressSync( [Buffer.from( "game" ), ownerWallet.publicKey.toBuffer()], program.programId ); console.log('gameAcct: ', gameAcctPDA.toString()) let [wordVaultAcctPDA,] = web3.PublicKey.findProgramAddressSync( [Buffer.from("word-vault"), ownerWallet.publicKey.toBuffer()], program.programId ); console.log('wordVaultAcct: ', wordVaultAcctPDA.toString()) let [moneyVaultAcctPDA,] = web3.PublicKey.findProgramAddressSync( [Buffer.from("money-pot")], program.programId ); console.log('moneyVaultAcct: ', moneyVaultAcctPDA.toString()) beforeEach( async () => { // await airdrop(owner.publicKey, provider); } ); it( 'Game Is Created along with Word Vault and Game Pot.', async (): Promise<void> => { const gameName = 'SayWord'; const minDeposit = 1; let transaction = await program.methods.initializeCreateGame(gameName, minDeposit) .accounts( { game: gameAcctPDA, wordVault: wordVaultAcctPDA, moneyPotVault: moneyVaultAcctPDA, owner: ownerWallet.publicKey, systemProgram: systemProgram } ) .signers([ownerWallet.payer]) .rpc(); console.log("Your transaction signature: ", transaction); const gameData = await program.account.gameData.fetch( gameAcctPDA ); const wordVault = await program.account.wordVault.fetch( wordVaultAcctPDA ); const moneyPot = await program.account.gamePot.fetch( moneyVaultAcctPDA ); expect( gameData.name ).to.equal( gameName ); expect( gameData.minDeposit ).to.equal( minDeposit ); expect( gameData.owner.toString() ).to.deep.equal(ownerWallet.publicKey.toString()); expect( gameData.totalGamesWon ).to.equal( 0 ); expect( wordVault.secretWord ).to.be.empty; expect( moneyPot.totalWinnings.toNumber() ).to.equal( 0 ); } ); it( 'Secret word is added to the word vault.', async (): Promise<void> => { const secretWord = 'dog'; let transaction = await program.methods.addSecretWord( secretWord ) .accounts({ wordVault: wordVaultAcctPDA, owner: ownerWallet.publicKey, systemProgram: systemProgram }) .signers([ ownerWallet.payer ]) .rpc() console.log( "Your transaction signature: ", transaction ); const wordVault = await program.account.wordVault.fetch( wordVaultAcctPDA ); expect( wordVault.secretWord ).to.equal( secretWord ); expect( wordVault.secretWord ).to.not.be.empty; }); it( 'Player account created to join the game', async (): Promise<void> => { let transaction = await program.methods.initializeJoinGame() .accounts({ player: playerAccount, tokenCounter: counterAccount, gameAccount: gameAcctPDA, owner: ownerWallet.publicKey, systemProgram: systemProgram }) .signers([ ownerWallet.payer ]) .rpc() console.log( "Your transaction signature: ", transaction ); const onChainPlayer = await program.account.player.fetch( playerAccount ); const counter = await program.account.counter.fetch( counterAccount ); expect( onChainPlayer.owner ).to.equal( ownerWallet.publicKey ); expect( onChainPlayer.gameAccount ).to.equal( gameAcctPDA ); expect( onChainPlayer.tokenCount ).to.equal(0 ); expect( onChainPlayer.gamesWon ).to.equal(0 ); expect( onChainPlayer.depositedAmount ).to.equal(0 ); expect( counter.count ).to.equal( 50 ) });
create_game.rs - Passes
#[derive(Accounts)]pub struct CreateGame<'info> { #[account( init, payer = owner, space = 8 + GameData::MAX_SIZE, seeds = [b"game", owner.key().as_ref()], bump )] pub game: Account<'info, GameData>, #[account( init_if_needed, seeds = [b"word-vault", owner.key().as_ref()], bump, payer = owner, space = 8 + WordVault::MAX_SIZE )] pub word_vault: Account<'info, WordVault>, #[account( init_if_needed, payer = owner, seeds = [b"money-pot"], space = 8 + GamePot::MAX_SIZE, bump, )] pub money_pot_vault: Account<'info, GamePot>, #[account(mut)] pub owner: Signer<'info>, pub system_program: Program<'info, System>,}pub fn handle_create_game(ctx: Context<CreateGame>, name: String, min_deposit: u8) -> Result<()> { let game = &mut ctx.accounts.game; let money_pot = &mut ctx.accounts.money_pot_vault; game.name = name; msg!("Game name: {}", game.name); game.min_deposit = min_deposit; msg!("Minimum deposit: {}", game.min_deposit); game.owner = *ctx.accounts.owner.key; msg!("Game owner: {}", game.owner); game.total_games_won = 0; msg!("Total Games Won: {}", game.total_games_won); money_pot.total_winnings = 0; msg!("Total Winnings: {}", money_pot.total_winnings); Ok(())
join_game.rs - fails
#[derive(Accounts)]pub struct JoinGame<'info> { #[account( init_if_needed, payer = owner, seeds = [owner.key().as_ref()], space = 8 + Player::MAX_SIZE, bump )] pub player: Account<'info, Player>, #[account( init, seeds = [owner.key().as_ref()], payer = owner, space = 8 + Counter::MAX_SIZE, bump )] pub token_counter: Account<'info, Counter>, #[account(mut)] pub game_account: Account<'info, GameData>, #[account(mut)] pub owner: Signer<'info>, pub system_program: Program<'info, System>,}pub fn handle_join_game(ctx: Context<JoinGame>) -> Result<()> { let player = &mut ctx.accounts.player; let game = &mut ctx.accounts.game_account; // Counter to track number of tokens purchased to use the GPT model let counter = &mut ctx.accounts.token_counter; game.total_players = game.total_players.checked_add(1).unwrap(); counter.owner = *ctx.accounts.owner.key; counter.count = counter.count.checked_add(50).unwrap(); // Initially provides 50 free tokens. msg!("Your Initial Token Counter Is Set To: {}", counter.count); // Game account that the player is joining player.game_account = *ctx.accounts.game_account.to_account_info().key; msg!("Joined Game: {}", player.game_account); player.games_won = 0; msg!("Your Player Account: {}", player.games_won); player.deposited_amount = 0; msg!("Initial Deposit Amount: {}", player.deposited_amount); player.token_count = 0; msg!("Initial Chat Token Amount: {}", player.token_count); Ok(())