use solana_program::pubkey::Pubkey;
use spl_associated_token_account::{
get_associated_token_address,
get_associated_token_address_with_program_id,
};
use steel::*;
use crate::{
consts::{
EXECUTOR_ADDRESS, EXECUTOR_PAY_DAILY_JACKPOT, EXECUTOR_PAY_WEEKLY_JACKPOT, FEE_COLLECTOR,
USDC_MAINNET_MINT,
},
instruction::*,
state::{Ledger, Market, Position, Treasury},
};
#[inline(always)]
pub fn program_id() -> Pubkey {
crate::ID
}
#[inline(always)]
fn executor_treasury_ix_bytes(kind: u8, pool: u8, amount: u64) -> Vec<u8> {
ExecutorTreasury {
kind,
pool,
_pad: [0; 6],
amount: amount.to_le_bytes(),
}
.to_bytes()
}
#[inline(always)]
pub fn treasury_usdc_ata() -> Pubkey {
get_associated_token_address(&Treasury::pda().0, &USDC_MAINNET_MINT)
}
#[inline(always)]
pub fn treasury_usdc_ata_with_token_program(token_program: &Pubkey) -> Pubkey {
get_associated_token_address_with_program_id(&Treasury::pda().0, &USDC_MAINNET_MINT, token_program)
}
#[inline(always)]
pub fn associated_usdc_ata(owner: Pubkey, token_program: &Pubkey) -> Pubkey {
get_associated_token_address_with_program_id(&owner, &USDC_MAINNET_MINT, token_program)
}
#[inline(always)]
pub fn usdc_ata(owner: Pubkey) -> Pubkey {
get_associated_token_address(&owner, &USDC_MAINNET_MINT)
}
#[inline(always)]
pub fn fee_collector_usdc_ata() -> Pubkey {
get_associated_token_address(&FEE_COLLECTOR, &USDC_MAINNET_MINT)
}
#[inline(always)]
pub fn fee_collector_usdc_ata_with_token_program(token_program: &Pubkey) -> Pubkey {
get_associated_token_address_with_program_id(&FEE_COLLECTOR, &USDC_MAINNET_MINT, token_program)
}
#[inline(always)]
pub fn buy_tickets_or_place_bet_previous_accounts(user: Pubkey, period: u64) -> (Pubkey, Pubkey) {
match period.checked_sub(1) {
Some(p) => (Market::pda(p).0, Position::pda(p, user).0),
None => (system_program::ID, system_program::ID),
}
}
pub fn initialize(payer: Pubkey, token_program: Pubkey) -> Instruction {
let treasury_address = Treasury::pda().0;
let mint_address = USDC_MAINNET_MINT;
let treasury_ata = treasury_usdc_ata_with_token_program(&token_program);
Instruction {
program_id: crate::ID,
accounts: vec![
AccountMeta::new(payer, true),
AccountMeta::new(treasury_address, false),
AccountMeta::new_readonly(mint_address, false),
AccountMeta::new(treasury_ata, false),
AccountMeta::new_readonly(system_program::ID, false),
AccountMeta::new_readonly(token_program, false),
AccountMeta::new_readonly(spl_associated_token_account::ID, false),
],
data: Initialize {}.to_bytes(),
}
}
pub fn buy_tickets(user: Pubkey, period: u64, amount: u64, token_program: Pubkey) -> Instruction {
let treasury_address = Treasury::pda().0;
let ledger_address = Ledger::pda(user).0;
let mint_address = USDC_MAINNET_MINT;
let user_ata = associated_usdc_ata(user, &token_program);
let treasury_ata_addr = treasury_usdc_ata_with_token_program(&token_program);
let team_ata_addr = fee_collector_usdc_ata_with_token_program(&token_program);
let (prev_mkt, prev_pos) = buy_tickets_or_place_bet_previous_accounts(user, period);
Instruction {
program_id: crate::ID,
accounts: vec![
AccountMeta::new(user, true),
AccountMeta::new(treasury_address, false),
AccountMeta::new(ledger_address, false),
AccountMeta::new_readonly(mint_address, false),
AccountMeta::new(user_ata, false),
AccountMeta::new(treasury_ata_addr, false),
AccountMeta::new(team_ata_addr, false),
AccountMeta::new_readonly(system_program::ID, false),
AccountMeta::new_readonly(token_program, false),
AccountMeta::new_readonly(spl_associated_token_account::ID, false),
AccountMeta::new_readonly(prev_mkt, false),
AccountMeta::new_readonly(prev_pos, false),
],
data: BuyTickets {
period: period.to_le_bytes(),
amount: amount.to_le_bytes(),
}
.to_bytes(),
}
}
pub fn place_bet(user: Pubkey, period: u64, ticket_units: u64, side: u8) -> Instruction {
let ledger_address = Ledger::pda(user).0;
let treasury_address = Treasury::pda().0;
let market_address = Market::pda(period).0;
let position_address = Position::pda(period, user).0;
let (prev_mkt, prev_pos) = buy_tickets_or_place_bet_previous_accounts(user, period);
Instruction {
program_id: crate::ID,
accounts: vec![
AccountMeta::new(user, true),
AccountMeta::new(ledger_address, false),
AccountMeta::new_readonly(treasury_address, false),
AccountMeta::new(market_address, false),
AccountMeta::new(position_address, false),
AccountMeta::new_readonly(prev_mkt, false),
AccountMeta::new_readonly(prev_pos, false),
AccountMeta::new_readonly(system_program::ID, false),
],
data: PlaceBet {
period: period.to_le_bytes(),
ticket_units: ticket_units.to_le_bytes(),
side,
_pad: [0; 7],
}
.to_bytes(),
}
}
pub fn settle_market(authority: Pubkey, period: u64, pyth_price_feed: Pubkey) -> Instruction {
let treasury_address = Treasury::pda().0;
let market_address = Market::pda(period).0;
Instruction {
program_id: crate::ID,
accounts: vec![
AccountMeta::new(authority, true),
AccountMeta::new(treasury_address, false),
AccountMeta::new(market_address, false),
AccountMeta::new_readonly(pyth_price_feed, false),
],
data: AdminInstantSettlement {
period: period.to_le_bytes(),
}
.to_bytes(),
}
}
pub fn init_market(
authority: Pubkey,
period: u64,
open_ts: i64,
close_ts: i64,
pyth_price_feed: Pubkey,
rules_hash: [u8; 32],
) -> Instruction {
let market_address = Market::pda(period).0;
let treasury_address = Treasury::pda().0;
Instruction {
program_id: crate::ID,
accounts: vec![
AccountMeta::new(authority, true),
AccountMeta::new(market_address, false),
AccountMeta::new_readonly(treasury_address, false),
AccountMeta::new_readonly(system_program::ID, false),
AccountMeta::new_readonly(pyth_price_feed, false),
],
data: InitMarket {
period: period.to_le_bytes(),
open_ts: open_ts.to_le_bytes(),
close_ts: close_ts.to_le_bytes(),
pyth_price_feed: pyth_price_feed.to_bytes(),
rules_hash,
}
.to_bytes(),
}
}
pub fn distribute_market_reward(
executor: Pubkey,
winning_authority: Pubkey,
market_period: u64,
token_program: Pubkey,
) -> Instruction {
let treasury_address = Treasury::pda().0;
let treasury_ata_addr = treasury_usdc_ata_with_token_program(&token_program);
let recipient_ata = associated_usdc_ata(winning_authority, &token_program);
let mint_address = USDC_MAINNET_MINT;
let market_address = Market::pda(market_period).0;
let position_address = Position::pda(market_period, winning_authority).0;
let ledger_address = Ledger::pda(winning_authority).0;
Instruction {
program_id: crate::ID,
accounts: vec![
AccountMeta::new(executor, true),
AccountMeta::new(treasury_address, false),
AccountMeta::new(treasury_ata_addr, false),
AccountMeta::new(recipient_ata, false),
AccountMeta::new_readonly(mint_address, false),
AccountMeta::new_readonly(token_program, false),
AccountMeta::new_readonly(market_address, false),
AccountMeta::new(position_address, false),
AccountMeta::new(ledger_address, false),
],
data: executor_treasury_ix_bytes(EXECUTOR_KIND_DISTRIBUTE_MARKET_REWARD, 0, 0),
}
}
pub fn distribute_market_reward_default_executor(
winning_authority: Pubkey,
market_period: u64,
token_program: Pubkey,
) -> Instruction {
distribute_market_reward(EXECUTOR_ADDRESS, winning_authority, market_period, token_program)
}
pub fn release_market_line(executor: Pubkey, period: u64) -> Instruction {
let treasury_address = Treasury::pda().0;
let market_address = Market::pda(period).0;
Instruction {
program_id: crate::ID,
accounts: vec![
AccountMeta::new(executor, true),
AccountMeta::new(treasury_address, false),
AccountMeta::new_readonly(market_address, false),
],
data: executor_treasury_ix_bytes(EXECUTOR_KIND_MARKET_LINE_RELEASE, 0, period),
}
}
#[inline(always)]
pub fn release_market_line_default_executor(period: u64) -> Instruction {
release_market_line(EXECUTOR_ADDRESS, period)
}
pub fn executor_treasury_pay_recipient_account(
executor: Pubkey,
recipient_ata: Pubkey,
amount: u64,
pool: u8,
token_program: Pubkey,
) -> Instruction {
let treasury_address = Treasury::pda().0;
let treasury_ata_addr = treasury_usdc_ata_with_token_program(&token_program);
let mint_address = USDC_MAINNET_MINT;
Instruction {
program_id: crate::ID,
accounts: vec![
AccountMeta::new(executor, true),
AccountMeta::new(treasury_address, false),
AccountMeta::new(treasury_ata_addr, false),
AccountMeta::new_readonly(mint_address, false),
AccountMeta::new_readonly(token_program, false),
AccountMeta::new(recipient_ata, false),
],
data: executor_treasury_ix_bytes(EXECUTOR_KIND_LANE_PAY, pool, amount),
}
}
#[inline(always)]
pub fn executor_treasury_pay(
executor: Pubkey,
recipient_owner: Pubkey,
amount: u64,
pool: u8,
token_program: Pubkey,
) -> Instruction {
executor_treasury_pay_recipient_account(
executor,
associated_usdc_ata(recipient_owner, &token_program),
amount,
pool,
token_program,
)
}
#[inline(always)]
pub fn executor_treasury_pay_daily(
executor: Pubkey,
recipient_owner: Pubkey,
amount: u64,
token_program: Pubkey,
) -> Instruction {
executor_treasury_pay_recipient_account(
executor,
associated_usdc_ata(recipient_owner, &token_program),
amount,
EXECUTOR_PAY_DAILY_JACKPOT,
token_program,
)
}
#[inline(always)]
pub fn executor_treasury_pay_weekly(
executor: Pubkey,
recipient_owner: Pubkey,
amount: u64,
token_program: Pubkey,
) -> Instruction {
executor_treasury_pay_recipient_account(
executor,
associated_usdc_ata(recipient_owner, &token_program),
amount,
EXECUTOR_PAY_WEEKLY_JACKPOT,
token_program,
)
}
pub fn claim_position_fee_accounts_prefix(
owner: Pubkey,
owner_usdc_ata: Pubkey,
token_program: Pubkey,
) -> [AccountMeta; 9] {
let executor = EXECUTOR_ADDRESS;
let treasury_address = Treasury::pda().0;
let treasury_ata_addr = treasury_usdc_ata_with_token_program(&token_program);
let team_ata_addr = fee_collector_usdc_ata_with_token_program(&token_program);
[
AccountMeta::new(executor, true),
AccountMeta::new(owner, true),
AccountMeta::new(treasury_address, false),
AccountMeta::new(treasury_ata_addr, false),
AccountMeta::new(team_ata_addr, false),
AccountMeta::new_readonly(USDC_MAINNET_MINT, false),
AccountMeta::new_readonly(system_program::ID, false),
AccountMeta::new_readonly(token_program, false),
AccountMeta::new(owner_usdc_ata, false),
]
}
pub fn claim_position_fee(
owner: Pubkey,
owner_usdc_ata: Pubkey,
cp_amm_accounts: &[AccountMeta],
token_program: Pubkey,
) -> Instruction {
let prefix = claim_position_fee_accounts_prefix(owner, owner_usdc_ata, token_program);
let mut accounts = Vec::with_capacity(9 + cp_amm_accounts.len());
accounts.extend_from_slice(&prefix);
accounts.extend_from_slice(cp_amm_accounts);
Instruction {
program_id: crate::ID,
accounts,
data: ClaimPositionFee {}.to_bytes(),
}
}