diff --git a/programs/bets/src/error.rs b/programs/bets/src/error.rs index 0f01f47..4cab67c 100644 --- a/programs/bets/src/error.rs +++ b/programs/bets/src/error.rs @@ -25,4 +25,12 @@ pub enum BettingError { FeeCalculationError, #[msg("Invalid ticket sale vault address")] InvalidTicketSaleVault, +} + +#[error_code] +pub enum LeaderboardError { + #[msg("Invalid id")] + InvalidId, + #[msg("Not active")] + NotActive, } \ No newline at end of file diff --git a/programs/bets/src/instructions/buy_tickets.rs b/programs/bets/src/instructions/buy_tickets.rs index 7da682b..917869e 100644 --- a/programs/bets/src/instructions/buy_tickets.rs +++ b/programs/bets/src/instructions/buy_tickets.rs @@ -4,7 +4,7 @@ use crate::{error::BettingError, *}; use crate::constants::TICKET_SALE_VAULT_ADDRESS; use std::str::FromStr; -pub fn buy_tickets(ctx: Context, _id:u64, amount: u64) -> Result<()> { +pub fn buy(ctx: Context, amount: u64) -> Result<()> { let transfer_amount = 100000000; // 0.1 SOL in lamports diff --git a/programs/bets/src/instructions/create_leaderboard.rs b/programs/bets/src/instructions/create_leaderboard.rs index 33d7927..8c41ebd 100644 --- a/programs/bets/src/instructions/create_leaderboard.rs +++ b/programs/bets/src/instructions/create_leaderboard.rs @@ -2,11 +2,14 @@ use anchor_lang::prelude::*; use anchor_spl::{associated_token::AssociatedToken, token_interface::{TokenAccount, TokenInterface}}; use crate::*; -pub fn create_leaderboard(ctx: Context, _id:u64) -> Result<()> { +pub fn create(ctx: Context, id:u64, game_id:String) -> Result<()> { let ticket_leaderboard_list = &mut ctx.accounts.ticket_leaderboard_list; let ticket_leaderboard = &mut ctx.accounts.ticket_leaderboard; + ticket_leaderboard.id = id; ticket_leaderboard.players = vec![]; + ticket_leaderboard.game_id = game_id; + ticket_leaderboard.is_over = false; ticket_leaderboard_list.leaderboards.push(ticket_leaderboard.key()); msg!("Leaderboard created!"); diff --git a/programs/bets/src/instructions/enter_leaderboard.rs b/programs/bets/src/instructions/enter_leaderboard.rs new file mode 100644 index 0000000..fc56285 --- /dev/null +++ b/programs/bets/src/instructions/enter_leaderboard.rs @@ -0,0 +1,73 @@ +use anchor_lang::prelude::*; +use anchor_spl::{associated_token::AssociatedToken, token_interface::{TokenAccount, TokenInterface}}; +use crate::*; + +pub fn enter(ctx: Context, id:u64) -> Result<()> { + let payer = &ctx.accounts.payer; + let receipt = &mut ctx.accounts.receipt_account; + + // Transfer 1 token from user's vault to leaderboard vault + let transfer_amount = 1u64; + + let cpi_program = ctx.accounts.token_program.to_account_info(); + let cpi_accounts = anchor_spl::token_interface::TransferChecked { + from: ctx.accounts.user_token_vault.to_account_info(), + to: ctx.accounts.token_vault.to_account_info(), + authority: payer.to_account_info(), + mint: ctx.accounts.token_mint.to_account_info(), + }; + let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts); + anchor_spl::token_interface::transfer_checked(cpi_ctx, transfer_amount, ctx.accounts.token_mint.decimals)?; + + receipt.active = true; + receipt.id= id; + + msg!("Successfully entered leaderboard"); + Ok(()) +} + + +#[derive(Accounts)] +#[instruction(id:u64)] +pub struct EnterLeaderboard<'info>{ + #[account(mut)] + pub payer: Signer<'info>, + + #[account( + mut, + seeds = [b"ticket_leaderboard", id.to_le_bytes().as_ref()], + bump + )] + pub ticket_leaderboard: Account<'info, TicketLeaderboard>, + + #[account( + init_if_needed, + payer= payer, + space = 8 + TicketReceiptVault::INIT_SPACE, + seeds = [b"receipt", payer.key().as_ref()], + bump + )] + pub receipt_account: Account<'info, TicketReceiptVault>, + + #[account( + mut, + associated_token::mint = token_mint, + associated_token::authority = ticket_leaderboard, + associated_token::token_program = token_program + )] + pub token_vault: InterfaceAccount<'info, TokenAccount>, + + #[account( + mut, + associated_token::mint = token_mint, + associated_token::authority = payer, + associated_token::token_program = token_program + )] + pub user_token_vault: InterfaceAccount<'info, TokenAccount>, + + pub token_mint: InterfaceAccount<'info, anchor_spl::token_interface::Mint>, + + pub system_program: Program<'info, System>, + pub token_program: Interface<'info, TokenInterface>, + pub associated_token_program: Program<'info, AssociatedToken>, +} \ No newline at end of file diff --git a/programs/bets/src/instructions/init_leaderboard_list.rs b/programs/bets/src/instructions/init_leaderboard_list.rs index e1be407..5bc111c 100644 --- a/programs/bets/src/instructions/init_leaderboard_list.rs +++ b/programs/bets/src/instructions/init_leaderboard_list.rs @@ -1,7 +1,7 @@ use anchor_lang::prelude::*; use crate::*; -pub fn init_leaderboard_list(ctx: Context) -> Result<()> { +pub fn init(ctx: Context) -> Result<()> { ctx.accounts.ticket_leaderboard_list.leaderboards = vec![]; msg!("Initialized Leaderboard List!"); Ok(()) diff --git a/programs/bets/src/instructions/mod.rs b/programs/bets/src/instructions/mod.rs index 077ac6f..232afea 100644 --- a/programs/bets/src/instructions/mod.rs +++ b/programs/bets/src/instructions/mod.rs @@ -44,4 +44,7 @@ pub mod update_leaderboard; pub use update_leaderboard::*; pub mod buy_tickets; -pub use buy_tickets::*; \ No newline at end of file +pub use buy_tickets::*; + +pub mod enter_leaderboard; +pub use enter_leaderboard::*; \ No newline at end of file diff --git a/programs/bets/src/instructions/update_leaderboard.rs b/programs/bets/src/instructions/update_leaderboard.rs index d2bb5f4..3b5c1b3 100644 --- a/programs/bets/src/instructions/update_leaderboard.rs +++ b/programs/bets/src/instructions/update_leaderboard.rs @@ -1,34 +1,29 @@ use anchor_lang::prelude::*; -use anchor_spl::{associated_token::AssociatedToken, token_interface::{TokenAccount, TokenInterface}}; -use crate::*; +use crate::{error::LeaderboardError, *}; -pub fn update_leaderboard(ctx: Context, _id:u64, new_score:u64) -> Result<()> { - let payer = &ctx.accounts.payer; +pub fn update(ctx: Context, id:u64, player:Pubkey, new_score:u64) -> Result<()> { let leaderboard_entry: &mut Account = &mut ctx.accounts.leaderboard_entry; let leaderboard: &mut Account = &mut ctx.accounts.ticket_leaderboard; - - // Transfer 1 token from user's vault to leaderboard vault - let transfer_amount = 1u64; - - let cpi_program = ctx.accounts.token_program.to_account_info(); - let cpi_accounts = anchor_spl::token_interface::TransferChecked { - from: ctx.accounts.user_token_vault.to_account_info(), - to: ctx.accounts.token_vault.to_account_info(), - authority: payer.to_account_info(), - mint: ctx.accounts.token_mint.to_account_info(), - }; - let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts); - anchor_spl::token_interface::transfer_checked(cpi_ctx, transfer_amount, ctx.accounts.token_mint.decimals)?; - + + let receipt = &mut ctx.accounts.receipt_account; + + if receipt.id != id { + return Err(LeaderboardError::InvalidId.into()); + } + + if !receipt.active { + return Err(LeaderboardError::NotActive.into()); + } + // Find existing entry for this payer if leaderboard_entry.highscore < new_score { leaderboard_entry.highscore = new_score; } - leaderboard_entry.total_tickets += transfer_amount; + leaderboard_entry.total_tickets += 1; - if !leaderboard.players.contains(&payer.key()) { - leaderboard.players.push(payer.key()); + if !leaderboard.players.contains(&player) { + leaderboard.players.push(player); } msg!("Successfully updated leaderboard with score: {}", new_score); @@ -37,7 +32,7 @@ pub fn update_leaderboard(ctx: Context, _id:u64, new_score:u6 #[derive(Accounts)] -#[instruction(id:u64)] +#[instruction(id:u64, player:Pubkey, new_score:u64)] pub struct UpdateLeaderboard<'info>{ #[account(mut)] pub payer: Signer<'info>, @@ -60,23 +55,11 @@ pub struct UpdateLeaderboard<'info>{ #[account( mut, - associated_token::mint = token_mint, - associated_token::authority = ticket_leaderboard, - associated_token::token_program = token_program + seeds = [b"receipt", player.as_ref()], + bump )] - pub token_vault: InterfaceAccount<'info, TokenAccount>, + pub receipt_account: Account<'info, TicketReceiptVault>, - #[account( - mut, - associated_token::mint = token_mint, - associated_token::authority = payer, - associated_token::token_program = token_program - )] - pub user_token_vault: InterfaceAccount<'info, TokenAccount>, - - pub token_mint: InterfaceAccount<'info, anchor_spl::token_interface::Mint>, pub system_program: Program<'info, System>, - pub token_program: Interface<'info, TokenInterface>, - pub associated_token_program: Program<'info, AssociatedToken>, } \ No newline at end of file diff --git a/programs/bets/src/lib.rs b/programs/bets/src/lib.rs index 7ea9f3d..4c6b146 100644 --- a/programs/bets/src/lib.rs +++ b/programs/bets/src/lib.rs @@ -58,4 +58,26 @@ pub mod bets { pub fn clear_bets_list(ctx: Context) -> Result<()> { clear_bets_list::clear(ctx) } + + pub fn init_leaderboard_list(ctx:Context) -> Result<()>{ + init_leaderboard_list::init(ctx) + } + + pub fn create_leaderboard(ctx:Context, id:u64, game_id:String)->Result<()>{ + create_leaderboard::create(ctx, id, game_id) + } + + pub fn update_leaderboard(ctx:Context, id:u64, player:Pubkey, new_score:u64)->Result<()>{ + update_leaderboard::update(ctx, id, player, new_score) + } + + pub fn buy_tickets(ctx:Context, amount:u64)->Result<()>{ + buy_tickets::buy(ctx,amount) + } + + pub fn enter_leaderboard(ctx:Context, id:u64)->Result<()>{ + enter_leaderboard::enter(ctx, id) + } + + } diff --git a/programs/bets/src/state/mod.rs b/programs/bets/src/state/mod.rs index 5fc2769..ac29d72 100644 --- a/programs/bets/src/state/mod.rs +++ b/programs/bets/src/state/mod.rs @@ -11,4 +11,7 @@ pub mod ticket_leaderboard_account; pub use ticket_leaderboard_account::*; pub mod ticket_leaderboard_list; -pub use ticket_leaderboard_list::*; \ No newline at end of file +pub use ticket_leaderboard_list::*; + +pub mod ticket_receipt_vault; +pub use ticket_receipt_vault::*; \ No newline at end of file diff --git a/programs/bets/src/state/ticket_leaderboard.rs b/programs/bets/src/state/ticket_leaderboard.rs index 091bbd5..752d826 100644 --- a/programs/bets/src/state/ticket_leaderboard.rs +++ b/programs/bets/src/state/ticket_leaderboard.rs @@ -4,8 +4,10 @@ use crate::*; #[account] #[derive(InitSpace)] pub struct TicketLeaderboard{ + pub id: u64, + #[max_len(16)] + pub game_id: String, #[max_len(500)] - pub players: Vec - - + pub players: Vec, + pub is_over: bool, } \ No newline at end of file diff --git a/programs/bets/src/state/ticket_receipt_vault.rs b/programs/bets/src/state/ticket_receipt_vault.rs new file mode 100644 index 0000000..fb93ef1 --- /dev/null +++ b/programs/bets/src/state/ticket_receipt_vault.rs @@ -0,0 +1,9 @@ +use anchor_lang::*; +use crate::*; + +#[account] +#[derive(InitSpace)] +pub struct TicketReceiptVault{ + pub id: u64, + pub active: bool +} \ No newline at end of file