use serde::{Deserialize, Serialize};
use steel::*;
use crate::state::{miner_pda, OreAccountV4, Treasury};
use super::OreAccount;
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
pub struct Miner {
pub authority: Pubkey,
pub deployed: [u64; 25],
pub cumulative: [u64; 25],
pub checkpoint_fee: u64,
pub checkpoint_id: u64,
pub last_claim_ore_at: i64,
pub last_claim_sol_at: i64,
pub rewards_factor: Numeric,
pub rewards_sol: u64,
pub rewards_ore: u64,
pub refined_ore: u64,
pub round_id: u64,
pub lifetime_rewards_sol: u64,
pub lifetime_rewards_ore: u64,
pub lifetime_deployed: u64,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
pub struct MinerV4 {
pub authority: Pubkey,
pub auto_return: u64,
pub checkpoint_id: u64,
pub checkpoint_fee: u64,
pub sol: [u64; 25],
pub mass: [u64; 25],
pub mass_cumulative: [u64; 25],
pub round_id: u64,
pub rewards_factor: Numeric,
pub sol_returned: u64,
pub ore_refined: u64,
pub ore_unrefined: u64,
pub last_claim_ore_at: i64,
pub last_claim_sol_at: i64,
pub lifetime_rewards: u64,
pub lifetime_deployed: u64,
pub lifetime_returned_sol: u64,
}
impl Miner {
pub fn pda(&self) -> (Pubkey, u8) {
miner_pda(self.authority)
}
pub fn claim_ore(&mut self, clock: &Clock, treasury: &mut Treasury) -> u64 {
self.update_rewards(treasury);
let refined_ore = self.refined_ore;
let rewards_ore = self.rewards_ore;
let mut amount = refined_ore + rewards_ore;
self.refined_ore = 0;
self.rewards_ore = 0;
treasury.total_unclaimed -= rewards_ore;
treasury.total_refined -= refined_ore;
self.last_claim_ore_at = clock.unix_timestamp;
if treasury.total_unclaimed > 0 {
let fee = rewards_ore / 10;
amount -= fee;
treasury.miner_rewards_factor += Numeric::from_fraction(fee, treasury.total_unclaimed);
treasury.total_refined += fee;
self.lifetime_rewards_ore -= fee;
}
amount
}
pub fn claim_sol(&mut self, clock: &Clock) -> u64 {
let amount = self.rewards_sol;
self.rewards_sol = 0;
self.last_claim_sol_at = clock.unix_timestamp;
amount
}
pub fn update_rewards(&mut self, treasury: &Treasury) {
if treasury.miner_rewards_factor > self.rewards_factor {
let accumulated_rewards = treasury.miner_rewards_factor - self.rewards_factor;
if accumulated_rewards < Numeric::ZERO {
panic!("Accumulated rewards is negative");
}
let personal_rewards = accumulated_rewards * Numeric::from_u64(self.rewards_ore);
self.refined_ore += personal_rewards.to_u64();
self.lifetime_rewards_ore += personal_rewards.to_u64();
}
self.rewards_factor = treasury.miner_rewards_factor;
}
}
impl MinerV4 {
pub fn pda(&self) -> (Pubkey, u8) {
miner_pda(self.authority)
}
pub fn claim_ore(&mut self, clock: &Clock, treasury: &mut Treasury) -> u64 {
self.update_rewards(treasury);
let refined_ore = self.ore_refined;
let rewards_ore = self.ore_unrefined;
let mut amount = refined_ore + rewards_ore;
self.ore_refined = 0;
self.ore_unrefined = 0;
treasury.total_unclaimed -= rewards_ore;
treasury.total_refined -= refined_ore;
self.last_claim_ore_at = clock.unix_timestamp;
if treasury.total_unclaimed > 0 {
let fee = rewards_ore / 10;
amount -= fee;
treasury.miner_rewards_factor += Numeric::from_fraction(fee, treasury.total_unclaimed);
treasury.total_refined += fee;
self.lifetime_rewards -= fee;
}
amount
}
pub fn claim_sol(&mut self, clock: &Clock) -> u64 {
let amount = self.sol_returned;
self.sol_returned = 0;
self.last_claim_sol_at = clock.unix_timestamp;
amount
}
pub fn update_rewards(&mut self, treasury: &Treasury) {
if treasury.miner_rewards_factor > self.rewards_factor {
let accumulated_rewards = treasury.miner_rewards_factor - self.rewards_factor;
if accumulated_rewards < Numeric::ZERO {
panic!("Accumulated rewards is negative");
}
let personal_rewards = accumulated_rewards * Numeric::from_u64(self.ore_unrefined);
self.ore_refined += personal_rewards.to_u64();
self.lifetime_rewards += personal_rewards.to_u64();
}
self.rewards_factor = treasury.miner_rewards_factor;
}
}
account!(OreAccount, Miner);
account!(OreAccountV4, MinerV4);
pub enum MinerAccount {
Miner(Miner),
MinerV4(MinerV4),
}
impl MinerAccount {
pub fn authority(&self) -> Pubkey {
match self {
MinerAccount::Miner(miner) => miner.authority,
MinerAccount::MinerV4(miner) => miner.authority,
}
}
pub fn deployed(&self) -> [u64; 25] {
match self {
MinerAccount::Miner(miner) => miner.deployed,
MinerAccount::MinerV4(miner) => miner.sol,
}
}
pub fn cumulative(&self) -> [u64; 25] {
match self {
MinerAccount::Miner(miner) => miner.cumulative,
MinerAccount::MinerV4(miner) => miner.mass_cumulative,
}
}
pub fn checkpoint_fee(&self) -> u64 {
match self {
MinerAccount::Miner(miner) => miner.checkpoint_fee,
MinerAccount::MinerV4(miner) => miner.checkpoint_fee,
}
}
pub fn checkpoint_id(&self) -> u64 {
match self {
MinerAccount::Miner(miner) => miner.checkpoint_id,
MinerAccount::MinerV4(miner) => miner.checkpoint_id,
}
}
pub fn last_claim_ore_at(&self) -> i64 {
match self {
MinerAccount::Miner(miner) => miner.last_claim_ore_at,
MinerAccount::MinerV4(miner) => miner.last_claim_ore_at,
}
}
pub fn last_claim_sol_at(&self) -> i64 {
match self {
MinerAccount::Miner(miner) => miner.last_claim_sol_at,
MinerAccount::MinerV4(miner) => miner.last_claim_sol_at,
}
}
pub fn rewards_factor(&self) -> Numeric {
match self {
MinerAccount::Miner(miner) => miner.rewards_factor,
MinerAccount::MinerV4(miner) => miner.rewards_factor,
}
}
pub fn rewards_sol(&self) -> u64 {
match self {
MinerAccount::Miner(miner) => miner.rewards_sol,
MinerAccount::MinerV4(miner) => miner.sol_returned,
}
}
pub fn rewards_ore(&self) -> u64 {
match self {
MinerAccount::Miner(miner) => miner.rewards_ore,
MinerAccount::MinerV4(miner) => miner.ore_unrefined,
}
}
pub fn refined_ore(&self) -> u64 {
match self {
MinerAccount::Miner(miner) => miner.refined_ore,
MinerAccount::MinerV4(miner) => miner.ore_refined,
}
}
pub fn round_id(&self) -> u64 {
match self {
MinerAccount::Miner(miner) => miner.round_id,
MinerAccount::MinerV4(miner) => miner.round_id,
}
}
pub fn lifetime_rewards_sol(&self) -> u64 {
match self {
MinerAccount::Miner(miner) => miner.lifetime_rewards_sol,
MinerAccount::MinerV4(miner) => miner.lifetime_returned_sol,
}
}
pub fn lifetime_rewards_ore(&self) -> u64 {
match self {
MinerAccount::Miner(miner) => miner.lifetime_rewards_ore,
MinerAccount::MinerV4(miner) => miner.lifetime_rewards,
}
}
pub fn lifetime_deployed(&self) -> u64 {
match self {
MinerAccount::Miner(miner) => miner.lifetime_deployed,
MinerAccount::MinerV4(miner) => miner.lifetime_deployed,
}
}
pub fn pda(&self) -> (Pubkey, u8) {
match self {
MinerAccount::Miner(miner) => miner.pda(),
MinerAccount::MinerV4(miner) => miner.pda(),
}
}
pub fn claim_ore(&mut self, clock: &Clock, treasury: &mut Treasury) -> u64 {
match self {
MinerAccount::Miner(miner) => miner.claim_ore(clock, treasury),
MinerAccount::MinerV4(miner) => miner.claim_ore(clock, treasury),
}
}
pub fn claim_sol(&mut self, clock: &Clock) -> u64 {
match self {
MinerAccount::Miner(miner) => miner.claim_sol(clock),
MinerAccount::MinerV4(miner) => miner.claim_sol(clock),
}
}
pub fn update_rewards(&mut self, treasury: &Treasury) {
match self {
MinerAccount::Miner(miner) => miner.update_rewards(treasury),
MinerAccount::MinerV4(miner) => miner.update_rewards(treasury),
}
}
}