From 8dedb47f8e82bdac203912b04d4fbb4def38ac34 Mon Sep 17 00:00:00 2001 From: Sewmina Dilshan Date: Wed, 18 Jun 2025 20:09:02 +0530 Subject: [PATCH] token sup --- .../bets/src/instructions/close_bet_token.rs | 23 +++++++--- programs/bets/src/instructions/create_bet.rs | 2 +- .../bets/src/instructions/create_bet_token.rs | 1 + .../src/instructions/deduct_fees_token.rs | 46 +++++++++++++------ programs/bets/src/instructions/shared.rs | 36 ++++++++++++++- programs/bets/src/state/bet_vault.rs | 2 + 6 files changed, 87 insertions(+), 23 deletions(-) diff --git a/programs/bets/src/instructions/close_bet_token.rs b/programs/bets/src/instructions/close_bet_token.rs index fb8dcde..73bf16c 100644 --- a/programs/bets/src/instructions/close_bet_token.rs +++ b/programs/bets/src/instructions/close_bet_token.rs @@ -11,15 +11,22 @@ pub fn close_token_bet(ctx: Context, winner: Pubkey, userid: Stri bet_vault.owner == winner || bet_vault.joiner == winner || bet_vault.owner_id == userid || bet_vault.joiner_id == userid, BettingError::InvalidWinner ); - + let seeds = &[ + b"bet_vault", + bet_vault.owner.as_ref(), + bet_vault.game_id.as_bytes(), + &bet_vault.nonce.to_le_bytes(), + ]; // Transfer tokens from vault to winner - transfer_tokens( + transfer_tokens_pda( &ctx.accounts.token_vault, &ctx.accounts.winner_token_account, - &bet_vault.wager, + bet_vault.wager, &ctx.accounts.token_mint, - &bet_vault.to_account_info(), - &ctx.accounts.token_program + &bet_vault, + &ctx.accounts.token_program, + seeds, + ctx.bumps.bet_vault, )?; // Remove bet from global list @@ -37,7 +44,11 @@ pub struct CloseBetToken<'info> { #[account(mut)] pub bets_list: Account<'info, BetsList>, - #[account(mut)] + #[account( + mut, + seeds = [b"bet_vault", bet_vault.owner.as_ref(), bet_vault.game_id.as_bytes(), &bet_vault.nonce.to_le_bytes()], + bump + )] pub bet_vault: Account<'info, BetVault>, #[account(mut)] diff --git a/programs/bets/src/instructions/create_bet.rs b/programs/bets/src/instructions/create_bet.rs index 86e4462..c111b5e 100644 --- a/programs/bets/src/instructions/create_bet.rs +++ b/programs/bets/src/instructions/create_bet.rs @@ -12,7 +12,7 @@ pub fn create(ctx: Context, wager: u64, user_id:String, game_id:Strin bet_vault.owner = payer.key(); bet_vault.owner_id= user_id; bet_vault.wager = wager; - + bet_vault.nonce = _nonce; // Transfer SOL from the payer to the bet vault let cpi_accounts = anchor_lang::system_program::Transfer { from: payer.to_account_info(), diff --git a/programs/bets/src/instructions/create_bet_token.rs b/programs/bets/src/instructions/create_bet_token.rs index 6f453c6..076904a 100644 --- a/programs/bets/src/instructions/create_bet_token.rs +++ b/programs/bets/src/instructions/create_bet_token.rs @@ -17,6 +17,7 @@ pub fn create_token_bet(ctx: Context, wager: u64, user_id:String bet_vault.owner_id= user_id; bet_vault.wager = wager; bet_vault.token_mint = ctx.accounts.token_mint.key(); + bet_vault.nonce = _nonce; transfer_tokens( &ctx.accounts.payer_token_account, diff --git a/programs/bets/src/instructions/deduct_fees_token.rs b/programs/bets/src/instructions/deduct_fees_token.rs index 6f07902..13b953d 100644 --- a/programs/bets/src/instructions/deduct_fees_token.rs +++ b/programs/bets/src/instructions/deduct_fees_token.rs @@ -5,7 +5,7 @@ use anchor_spl::{ associated_token::AssociatedToken, token_interface::{TokenAccount, TokenInterface}, }; -use crate::{error::BettingError, shared::transfer_tokens, *}; +use crate::{error::BettingError, shared::transfer_tokens_pda, *}; pub fn handle_deduct_fees_token(ctx: Context, winner: Pubkey, userid: String) -> Result<()> { let bet_vault = &mut ctx.accounts.bet_vault; @@ -40,35 +40,49 @@ pub fn handle_deduct_fees_token(ctx: Context, winner: Pubkey, u BettingError::InsufficientFunds ); + // Get PDA seeds and bump + let seeds = &[ + b"bet_vault", + bet_vault.owner.as_ref(), + bet_vault.game_id.as_bytes(), + &bet_vault.nonce.to_le_bytes(), + ]; + // Transfer referrer fees - transfer_tokens( + transfer_tokens_pda( &ctx.accounts.token_vault, &ctx.accounts.owner_referrer_token_account, - &referrer_fee, + referrer_fee, &ctx.accounts.token_mint, - &ctx.accounts.bet_vault.to_account_info(), - &ctx.accounts.token_program + &bet_vault, + &ctx.accounts.token_program, + seeds, + ctx.bumps.bet_vault, )?; msg!("Transferred {} tokens to owner referrer", referrer_fee); - transfer_tokens( + transfer_tokens_pda( &ctx.accounts.token_vault, &ctx.accounts.joiner_referrer_token_account, - &referrer_fee, + referrer_fee, &ctx.accounts.token_mint, - &ctx.accounts.bet_vault.to_account_info(), - &ctx.accounts.token_program + &bet_vault, + &ctx.accounts.token_program, + seeds, + ctx.bumps.bet_vault, )?; msg!("Transferred {} tokens to joiner referrer", referrer_fee); // Transfer platform fee - transfer_tokens( + transfer_tokens_pda( &ctx.accounts.token_vault, &ctx.accounts.fee_wallet_token_account, - &fee, + fee, &ctx.accounts.token_mint, - &ctx.accounts.bet_vault.to_account_info(), - &ctx.accounts.token_program + &bet_vault, + &ctx.accounts.token_program, + seeds, + ctx.bumps.bet_vault, )?; msg!("Transferred {} tokens to fee wallet", fee); @@ -80,7 +94,11 @@ pub struct DeductFeesToken<'info> { #[account(mut)] pub bets_list: Account<'info, BetsList>, - #[account(mut)] + #[account( + mut, + seeds = [b"bet_vault", bet_vault.owner.as_ref(), bet_vault.game_id.as_bytes(), &bet_vault.nonce.to_le_bytes()], + bump + )] pub bet_vault: Account<'info, BetVault>, /// CHECK: This is validated against the FEE_COLLECTOR constant. diff --git a/programs/bets/src/instructions/shared.rs b/programs/bets/src/instructions/shared.rs index 3ab2027..0db517d 100644 --- a/programs/bets/src/instructions/shared.rs +++ b/programs/bets/src/instructions/shared.rs @@ -2,13 +2,14 @@ use anchor_lang::prelude::*; use anchor_spl::token_interface::{ transfer_checked, Mint, TokenAccount, TokenInterface, TransferChecked, }; +use crate::*; pub fn transfer_tokens<'info>( from: &InterfaceAccount<'info, TokenAccount>, to: &InterfaceAccount<'info, TokenAccount>, amount: &u64, mint: &InterfaceAccount<'info, Mint>, - authority: &AccountInfo<'info>, + authority: &Signer<'info>, token_program: &Interface<'info, TokenInterface>, ) -> Result<()> { let transfer_accounts_options = TransferChecked { @@ -21,4 +22,35 @@ pub fn transfer_tokens<'info>( let cpi_context = CpiContext::new(token_program.to_account_info(), transfer_accounts_options); transfer_checked(cpi_context, *amount, mint.decimals) -} \ No newline at end of file +} + +pub fn transfer_tokens_pda<'info>( + from: &InterfaceAccount<'info, TokenAccount>, + to: &InterfaceAccount<'info, TokenAccount>, + amount: u64, + mint: &InterfaceAccount<'info, Mint>, + pda_account: &Account<'info, BetVault>, + token_program: &Interface<'info, TokenInterface>, + seeds: &[&[u8]], + bump: u8, +) -> Result<()> { + let transfer_accounts_options = TransferChecked { + from: from.to_account_info(), + mint: mint.to_account_info(), + to: to.to_account_info(), + authority: pda_account.to_account_info(), + }; + + let bump_seed = [bump]; + let mut all_seeds = seeds.to_vec(); + all_seeds.push(&bump_seed); + let signer_seeds: &[&[&[u8]]] = &[&all_seeds]; + + let cpi_context = CpiContext::new_with_signer( + token_program.to_account_info(), + transfer_accounts_options, + signer_seeds, + ); + + transfer_checked(cpi_context, amount, mint.decimals) +} diff --git a/programs/bets/src/state/bet_vault.rs b/programs/bets/src/state/bet_vault.rs index e071557..6683ea7 100644 --- a/programs/bets/src/state/bet_vault.rs +++ b/programs/bets/src/state/bet_vault.rs @@ -4,6 +4,8 @@ use crate::*; #[account] #[derive(InitSpace)] pub struct BetVault { + #[max_len(10)] + pub nonce: u64, #[max_len(10)] pub game_id: String, pub owner: Pubkey,