use crate::states::{Competition, Participant, PARTICIPANT_SEED};
use crate::CompetitionError;
use anchor_lang::prelude::*;
#[derive(Accounts)]
pub struct CreateParticipantIdempotent<'info> {
#[account(mut)]
pub payer: Signer<'info>,
pub competition: Account<'info, Competition>,
#[account(
init_if_needed,
payer = payer,
space = 8 + Participant::INIT_SPACE,
seeds = [
PARTICIPANT_SEED,
competition.key().as_ref(),
trader.key().as_ref(),
],
bump
)]
pub participant: Account<'info, Participant>,
pub trader: UncheckedAccount<'info>,
pub system_program: Program<'info, System>,
}
#[derive(Accounts)]
pub struct CloseParticipant<'info> {
#[account(mut)]
pub trader: Signer<'info>,
pub competition: Account<'info, Competition>,
#[account(
mut,
seeds = [
PARTICIPANT_SEED,
competition.key().as_ref(),
trader.key().as_ref(),
],
bump = participant.bump,
has_one = competition,
has_one = trader,
close = trader,
)]
pub participant: Account<'info, Participant>,
}
impl CloseParticipant<'_> {
pub(crate) fn invoke(ctx: Context<Self>) -> Result<()> {
let now = Clock::get()?.unix_timestamp;
let comp = &ctx.accounts.competition;
require!(
now < comp.start_time || now > comp.end_time,
CompetitionError::CompetitionInProgress
);
Ok(())
}
}
impl CreateParticipantIdempotent<'_> {
pub(crate) fn invoke(ctx: Context<Self>) -> Result<()> {
ctx.accounts
.create_participant_idempotent(ctx.bumps.participant)
}
fn create_participant_idempotent(&mut self, bump: u8) -> Result<()> {
let p = &mut self.participant;
let default_pubkey = Pubkey::default();
if p.trader == default_pubkey {
let now = Clock::get()?.unix_timestamp;
let trader = self.trader.key();
require_keys_neq!(trader, default_pubkey);
p.bump = bump;
p.competition = self.competition.key();
p.trader = trader;
p.volume = 0;
p.last_updated_at = now;
p.merged_volume = 0;
}
Ok(())
}
}