use anyhow::Result;
use testsvm::prelude::*;
use crate::quarry_mine;
use crate::test_rewarder::TestRewarder;
use super::common::init_test_environment;
#[test]
fn test_claim_rewards() -> Result<()> {
let mut env = init_test_environment()?;
let authority = env.new_wallet("authority")?;
let user = env.new_wallet("user")?;
let rewarder = TestRewarder::new_rewarder(&mut env, "main", &authority)?;
let staked_token_mint = env.create_mint("staked_token", 6, &authority.pubkey())?;
let quarry = rewarder.create_quarry(&mut env, "main", &staked_token_mint.key, &authority)?;
let annual_rewards_rate = 1_000_000 * 10u64.pow(6);
rewarder.set_annual_rewards_rate(&mut env, annual_rewards_rate, &authority)?;
let _ = rewarder.new_minter(&mut env, "main", &authority)?;
let user_staked_tokens = create_and_fund_token_account(
&mut env,
"user_staked_tokens",
&user.pubkey(),
&staked_token_mint.key,
1000 * 10u64.pow(6), &authority,
)?;
let (miner, miner_vault) = quarry.create_miner(&mut env, "user", &user)?;
quarry.stake_tokens(
&mut env,
&miner,
&miner_vault,
&user_staked_tokens,
100 * 10u64.pow(6), &user,
)?;
let miner_account: quarry_mine::accounts::Miner = miner.load(&env)?;
assert_eq!(
miner_account.balance,
100 * 10u64.pow(6),
"Miner should have 100 staked tokens"
);
assert_eq!(
miner_account.rewards_earned, 0,
"No rewards should be earned initially"
);
env.advance_time(365 * 24 * 60 * 60);
quarry.update_quarry_rewards(&mut env)?;
let (create_ata_ix, user_rewards_account) = env.create_ata_ix(
"user_rewards",
&user.pubkey(),
&rewarder.mint_wrapper.reward_token_mint.key,
)?;
env.execute_ixs(&[create_ata_ix])?;
quarry.claim_rewards(
&mut env,
&rewarder,
&miner,
&miner_vault,
&user_rewards_account,
&user,
)?;
let reward_account: anchor_spl::token::TokenAccount = user_rewards_account.load(&env)?;
assert!(
reward_account.amount > 0,
"User should have received rewards"
);
let expected_min_rewards = 999_000 * 10u64.pow(6); assert!(
reward_account.amount >= expected_min_rewards,
"User should receive approximately 1M tokens. Got: {}",
reward_account.amount
);
println!(
"✅ Successfully claimed {} reward tokens",
reward_account.amount / 10u64.pow(6)
);
let miner_after_claim: quarry_mine::accounts::Miner = miner.load(&env)?;
assert_eq!(
miner_after_claim.rewards_earned, 0,
"Miner rewards should be reset after claiming"
);
Ok(())
}
#[test]
fn test_claim_rewards_wrong_authority() -> Result<()> {
let mut env = init_test_environment()?;
let authority = env.new_wallet("authority")?;
let user = env.new_wallet("user")?;
let wrong_user = env.new_wallet("wrong_user")?;
let rewarder = TestRewarder::new_rewarder(&mut env, "main", &authority)?;
let staked_token_mint = env.create_mint("staked_token", 6, &authority.pubkey())?;
let quarry = rewarder.create_quarry(&mut env, "main", &staked_token_mint.key, &authority)?;
rewarder.set_annual_rewards_rate(&mut env, 1_000_000 * 10u64.pow(6), &authority)?;
let _ = rewarder.new_minter(&mut env, "main", &authority)?;
let (miner, miner_vault) = quarry.create_miner(&mut env, "user", &user)?;
let user_staked_tokens = create_and_fund_token_account(
&mut env,
"user_staked_tokens",
&user.pubkey(),
&staked_token_mint.key,
1000 * 10u64.pow(6),
&authority,
)?;
quarry.stake_tokens(
&mut env,
&miner,
&miner_vault,
&user_staked_tokens,
100 * 10u64.pow(6),
&user,
)?;
env.advance_time(365 * 24 * 60 * 60);
quarry.update_quarry_rewards(&mut env)?;
let (create_ata_ix, wrong_user_rewards) = env.create_ata_ix(
"wrong_user_rewards",
&wrong_user.pubkey(),
&rewarder.mint_wrapper.reward_token_mint.key,
)?;
env.execute_ixs(&[create_ata_ix])?;
let result = quarry.claim_rewards(
&mut env,
&rewarder,
&miner,
&miner_vault,
&wrong_user_rewards,
&wrong_user, );
assert!(
result.is_err(),
"Should fail when wrong authority tries to claim"
);
Ok(())
}
#[test]
fn test_claim_rewards_no_stake() -> Result<()> {
let mut env = init_test_environment()?;
let authority = env.new_wallet("authority")?;
let user = env.new_wallet("user")?;
let rewarder = TestRewarder::new_rewarder(&mut env, "main", &authority)?;
let staked_token_mint = env.create_mint("staked_token", 6, &authority.pubkey())?;
let quarry = rewarder.create_quarry(&mut env, "main", &staked_token_mint.key, &authority)?;
rewarder.set_annual_rewards_rate(&mut env, 1_000_000 * 10u64.pow(6), &authority)?;
let _ = rewarder.new_minter(&mut env, "main", &authority)?;
let (miner, miner_vault) = quarry.create_miner(&mut env, "user", &user)?;
env.advance_time(365 * 24 * 60 * 60);
quarry.update_quarry_rewards(&mut env)?;
let (create_ata_ix, user_rewards) = env.create_ata_ix(
"user_rewards",
&user.pubkey(),
&rewarder.mint_wrapper.reward_token_mint.key,
)?;
env.execute_ixs(&[create_ata_ix])?;
quarry.claim_rewards(
&mut env,
&rewarder,
&miner,
&miner_vault,
&user_rewards,
&user,
)?;
let reward_account: anchor_spl::token::TokenAccount = user_rewards.load(&env)?;
assert_eq!(
reward_account.amount, 0,
"User should receive 0 rewards when no stake"
);
Ok(())
}
#[test]
fn test_claim_rewards_multiple_users() -> Result<()> {
let mut env = init_test_environment()?;
let authority = env.new_wallet("authority")?;
let user1 = env.new_wallet("user1")?;
let user2 = env.new_wallet("user2")?;
let rewarder = TestRewarder::new_rewarder(&mut env, "main", &authority)?;
let staked_token_mint = env.create_mint("staked_token", 6, &authority.pubkey())?;
let quarry = rewarder.create_quarry(&mut env, "main", &staked_token_mint.key, &authority)?;
let annual_rewards = 1_000_000 * 10u64.pow(6);
rewarder.set_annual_rewards_rate(&mut env, annual_rewards, &authority)?;
let _ = rewarder.new_minter(&mut env, "main", &authority)?;
let (miner1, vault1) = quarry.create_miner(&mut env, "user1", &user1)?;
let (miner2, vault2) = quarry.create_miner(&mut env, "user2", &user2)?;
let user1_tokens = create_and_fund_token_account(
&mut env,
"user1_tokens",
&user1.pubkey(),
&staked_token_mint.key,
1000 * 10u64.pow(6),
&authority,
)?;
let user2_tokens = create_and_fund_token_account(
&mut env,
"user2_tokens",
&user2.pubkey(),
&staked_token_mint.key,
1000 * 10u64.pow(6),
&authority,
)?;
quarry.stake_tokens(
&mut env,
&miner1,
&vault1,
&user1_tokens,
300 * 10u64.pow(6),
&user1,
)?;
quarry.stake_tokens(
&mut env,
&miner2,
&vault2,
&user2_tokens,
200 * 10u64.pow(6),
&user2,
)?;
env.advance_time(365 * 24 * 60 * 60);
quarry.update_quarry_rewards(&mut env)?;
let (ix1, rewards1) = env.create_ata_ix(
"rewards1",
&user1.pubkey(),
&rewarder.mint_wrapper.reward_token_mint.key,
)?;
let (ix2, rewards2) = env.create_ata_ix(
"rewards2",
&user2.pubkey(),
&rewarder.mint_wrapper.reward_token_mint.key,
)?;
env.execute_ixs(&[ix1, ix2])?;
quarry.claim_rewards(&mut env, &rewarder, &miner1, &vault1, &rewards1, &user1)?;
quarry.claim_rewards(&mut env, &rewarder, &miner2, &vault2, &rewards2, &user2)?;
let rewards1_account: anchor_spl::token::TokenAccount = rewards1.load(&env)?;
let rewards2_account: anchor_spl::token::TokenAccount = rewards2.load(&env)?;
let user1_expected = (annual_rewards * 60 / 100) * 999 / 1000; let user2_expected = (annual_rewards * 40 / 100) * 999 / 1000;
assert!(
rewards1_account.amount >= user1_expected,
"User1 should receive ~60% of rewards. Got: {}, Expected min: {}",
rewards1_account.amount,
user1_expected
);
assert!(
rewards2_account.amount >= user2_expected,
"User2 should receive ~40% of rewards. Got: {}, Expected min: {}",
rewards2_account.amount,
user2_expected
);
println!(
"✅ User1 claimed {} tokens (60% stake)",
rewards1_account.amount / 10u64.pow(6)
);
println!(
"✅ User2 claimed {} tokens (40% stake)",
rewards2_account.amount / 10u64.pow(6)
);
Ok(())
}
fn create_and_fund_token_account(
env: &mut TestSVM,
label: &str,
owner: &Pubkey,
mint: &Pubkey,
amount: u64,
mint_authority: &Keypair,
) -> Result<AccountRef<anchor_spl::token::TokenAccount>> {
let (create_ata_ix, token_account) = env.create_ata_ix(label, owner, mint)?;
env.execute_ixs(&[create_ata_ix])?;
let mint_to_ix = anchor_spl::token::spl_token::instruction::mint_to(
&anchor_spl::token::ID,
mint,
&token_account.key,
&mint_authority.pubkey(),
&[],
amount,
)?;
env.execute_ixs_with_signers(&[mint_to_ix], &[mint_authority])?;
Ok(token_account)
}