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(())