mirror of
https://github.com/d0zingcat/ore.git
synced 2026-05-13 23:16:52 +00:00
cli
This commit is contained in:
3392
Cargo.lock
generated
3392
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["ore/*", "ore-delegate/*"]
|
||||
members = ["ore/*", "ore-delegate/*", "cli"]
|
||||
|
||||
[workspace.package]
|
||||
version = "3.7.0"
|
||||
|
||||
@@ -18,9 +18,7 @@ anyhow.workspace = true
|
||||
base64 = "0.22.1"
|
||||
bincode = "1.3.3"
|
||||
bytemuck.workspace = true
|
||||
meteora-pools-sdk.workspace = true
|
||||
ore-api = { path = "../api" }
|
||||
ore-boost-api.workspace = true
|
||||
ore-api = { path = "../ore/api" }
|
||||
serde_json = "1.0.140"
|
||||
solana-account-decoder.workspace = true
|
||||
solana-client.workspace = true
|
||||
|
||||
315
cli/src/main.rs
315
cli/src/main.rs
@@ -1,5 +1,4 @@
|
||||
use meteora_pools_sdk::instructions::Swap;
|
||||
use ore_api::{prelude::*, sdk::*};
|
||||
use ore_api::prelude::*;
|
||||
use solana_account_decoder::UiAccountEncoding;
|
||||
use solana_client::{
|
||||
client_error::{reqwest::StatusCode, ClientErrorKind},
|
||||
@@ -7,16 +6,13 @@ use solana_client::{
|
||||
rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig},
|
||||
rpc_filter::{Memcmp, RpcFilterType},
|
||||
};
|
||||
use solana_program::pubkey;
|
||||
use solana_sdk::{
|
||||
compute_budget::ComputeBudgetInstruction,
|
||||
keccak::hashv,
|
||||
native_token::{lamports_to_sol, sol_to_lamports},
|
||||
pubkey::Pubkey,
|
||||
signature::{read_keypair_file, Signer},
|
||||
transaction::Transaction,
|
||||
};
|
||||
use steel::{AccountDeserialize, Clock, Discriminator, Instruction};
|
||||
use steel::{AccountDeserialize, Clock, Discriminator};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
@@ -30,246 +26,60 @@ async fn main() {
|
||||
.expect("Missing COMMAND env var")
|
||||
.as_str()
|
||||
{
|
||||
"initialize" => {
|
||||
let ix = initialize(payer.pubkey());
|
||||
submit_transaction(&rpc, &payer, &[ix]).await.unwrap();
|
||||
}
|
||||
"payout" => {
|
||||
let ix = payout(payer.pubkey(), Pubkey::new_unique(), Pubkey::new_unique());
|
||||
submit_transaction(&rpc, &payer, &[ix]).await.unwrap();
|
||||
}
|
||||
"reset" => {
|
||||
let ix = reset(payer.pubkey(), ore_boost_api::state::config_pda().0);
|
||||
submit_transaction(&rpc, &payer, &[ix]).await.unwrap();
|
||||
}
|
||||
"block" => {
|
||||
let block = get_block(&rpc).await.unwrap();
|
||||
println!("Block: {:?}", block);
|
||||
}
|
||||
"crank" => {
|
||||
crank(&rpc, &payer).await.unwrap();
|
||||
}
|
||||
"deploy" => {
|
||||
deploy(&rpc, &payer, sol_to_lamports(1.0)).await.unwrap();
|
||||
"open" => {
|
||||
open(&rpc, &payer).await.unwrap();
|
||||
}
|
||||
"close" => {
|
||||
close_all_commits(&rpc, &payer).await.unwrap();
|
||||
close(&rpc, &payer).await.unwrap();
|
||||
}
|
||||
"commits" => {
|
||||
let commits = get_block_commits(&rpc).await.unwrap();
|
||||
println!("Commits: {:?}", commits);
|
||||
"clock" => {
|
||||
log_clock(&rpc).await.unwrap();
|
||||
}
|
||||
"bury" => {
|
||||
bury_ore_sol(&rpc, &payer).await.unwrap();
|
||||
"block" => {
|
||||
log_block(&rpc).await.unwrap();
|
||||
}
|
||||
_ => panic!("Invalid command"),
|
||||
};
|
||||
}
|
||||
|
||||
async fn crank(
|
||||
async fn open(
|
||||
rpc: &RpcClient,
|
||||
payer: &solana_sdk::signer::keypair::Keypair,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let boost_config = ore_boost_api::state::config_pda().0;
|
||||
loop {
|
||||
if let Ok(block) = get_block(rpc).await {
|
||||
if let Ok(clock) = get_clock(rpc).await {
|
||||
if clock.slot >= block.ends_at {
|
||||
// Time to payout and reset
|
||||
if let Ok(payout_ix) = build_payout_ix(rpc, payer).await {
|
||||
let reset_ix = reset(payer.pubkey(), boost_config);
|
||||
submit_transaction(rpc, &payer, &[payout_ix, reset_ix])
|
||||
.await
|
||||
.ok();
|
||||
println!("Submitted payout and reset transaction");
|
||||
}
|
||||
} else {
|
||||
// Calculate and print time remaining
|
||||
let slots_remaining = block.ends_at.saturating_sub(clock.slot);
|
||||
let seconds_remaining = (slots_remaining as f64) * 0.4;
|
||||
println!(
|
||||
"Time until payout: {:.1} seconds ({} slots) – {} commits – {} SOL",
|
||||
seconds_remaining,
|
||||
slots_remaining,
|
||||
block.total_commits,
|
||||
lamports_to_sol(block.cumulative_sum)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
println!("Error getting clock");
|
||||
}
|
||||
} else {
|
||||
println!("Error getting block");
|
||||
}
|
||||
|
||||
// Wait 3 seconds before next check
|
||||
tokio::time::sleep(std::time::Duration::from_secs(3)).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn deploy(
|
||||
rpc: &RpcClient,
|
||||
payer: &solana_sdk::signer::keypair::Keypair,
|
||||
amount: u64,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
// Get current block to get round number
|
||||
let block = get_block(rpc).await?;
|
||||
|
||||
// Create WSOL ATA if it doesn't exist
|
||||
let wsol_ata = spl_associated_token_account::get_associated_token_address(
|
||||
&payer.pubkey(),
|
||||
&spl_token::native_mint::ID,
|
||||
);
|
||||
let create_ata_ix = spl_associated_token_account::instruction::create_associated_token_account(
|
||||
&payer.pubkey(),
|
||||
&payer.pubkey(),
|
||||
&spl_token::native_mint::ID,
|
||||
&spl_token::ID,
|
||||
);
|
||||
let mut ixs = match rpc.get_account(&wsol_ata).await {
|
||||
Ok(_) => vec![],
|
||||
Err(_) => vec![create_ata_ix],
|
||||
};
|
||||
|
||||
// Wrap SOL
|
||||
let wrap_ix = solana_sdk::system_instruction::transfer(
|
||||
&payer.pubkey(),
|
||||
&spl_associated_token_account::get_associated_token_address(
|
||||
&payer.pubkey(),
|
||||
&spl_token::native_mint::ID,
|
||||
),
|
||||
amount,
|
||||
);
|
||||
let sync_native_ix = spl_token::instruction::sync_native(
|
||||
&spl_token::ID,
|
||||
&spl_associated_token_account::get_associated_token_address(
|
||||
&payer.pubkey(),
|
||||
&spl_token::native_mint::ID,
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Build deploy instruction
|
||||
let seed = generate_seed(&payer, &block);
|
||||
println!("Seed: {:?}", seed);
|
||||
let ix = ore_api::sdk::deploy(
|
||||
payer.pubkey(),
|
||||
spl_token::native_mint::ID,
|
||||
amount,
|
||||
block.current_round,
|
||||
seed,
|
||||
);
|
||||
ixs.push(wrap_ix);
|
||||
ixs.push(sync_native_ix);
|
||||
ixs.push(ix);
|
||||
|
||||
// Submit transaction
|
||||
submit_transaction(rpc, payer, &ixs).await?;
|
||||
println!("Deployed {} SOL", lamports_to_sol(amount));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn bury_ore_sol(
|
||||
rpc: &RpcClient,
|
||||
payer: &solana_sdk::signer::keypair::Keypair,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let swap = Swap {
|
||||
pool: pubkey!("GgaDTFbqdgjoZz3FP7zrtofGwnRS4E6MCzmmD5Ni1Mxj"),
|
||||
user_source_token: spl_token::native_mint::ID,
|
||||
user_destination_token: ore_api::consts::MINT_ADDRESS,
|
||||
a_vault: pubkey!("3s6ki6dQSM8FuqWiPsnGkgVsAEo8BTAfUR1Vvt1TPiJN"),
|
||||
b_vault: pubkey!("FERjPVNEa7Udq8CEv68h6tPL46Tq7ieE49HrE2wea3XT"),
|
||||
a_token_vault: pubkey!("BtJuiRG44vew5nYBVeUhuBawPTZLyYYxdzTYzerkfnto"),
|
||||
b_token_vault: pubkey!("HZeLxbZ9uHtSpwZC3LBr4Nubd14iHwz7bRSghRZf5VCG"),
|
||||
a_vault_lp_mint: pubkey!("6Av9sdKvnjwoDHVnhEiz6JEq8e6SGzmhCsCncT2WJ7nN"),
|
||||
b_vault_lp_mint: pubkey!("FZN7QZ8ZUUAxMPfxYEYkH3cXUASzH8EqA6B4tyCL8f1j"),
|
||||
a_vault_lp: pubkey!("2k7V1NtM1krwh1sdt5wWqBRcvNQ5jzxj3J2rV78zdTsL"),
|
||||
b_vault_lp: pubkey!("CFATQFgkKXJyU3MdCNvQqN79qorNSMJFF8jrF66a7r6i"),
|
||||
protocol_token_fee: pubkey!("6kzYo2LMo2q2bkLAD8ienoG5NC1MkNXNTfm8sdyHuX3h"),
|
||||
user: payer.pubkey(),
|
||||
vault_program: pubkey!("24Uqj9JCLxUeoC3hGfh5W3s9FM9uCHDS2SG3LYwBpyTi"),
|
||||
token_program: spl_token::ID,
|
||||
};
|
||||
let ix = bury(payer.pubkey(), swap, u64::MAX);
|
||||
let id_str = std::env::var("ID").expect("Missing ID env var");
|
||||
let id = id_str.parse::<u64>()?;
|
||||
let ix = ore_api::sdk::open(payer.pubkey(), id);
|
||||
submit_transaction(rpc, payer, &[ix]).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn build_payout_ix(
|
||||
rpc: &RpcClient,
|
||||
payer: &solana_sdk::signer::keypair::Keypair,
|
||||
) -> Result<Instruction, anyhow::Error> {
|
||||
let block = get_block(rpc).await?;
|
||||
let commits = get_block_commits(rpc).await?;
|
||||
|
||||
// Return early if no commits
|
||||
if block.cumulative_sum == 0 || block.reward == 0 {
|
||||
return Ok(payout(
|
||||
payer.pubkey(),
|
||||
Pubkey::new_unique(),
|
||||
Pubkey::new_unique(),
|
||||
));
|
||||
}
|
||||
|
||||
// Get blockhash
|
||||
let solana_block = rpc.get_block(block.ends_at).await?;
|
||||
let blockhash = solana_block.blockhash;
|
||||
let noise = hashv(&[&block.noise, blockhash.as_ref()]).to_bytes();
|
||||
|
||||
// Calculate the random number.
|
||||
let x = u64::from_le_bytes(noise[0..8].try_into().unwrap());
|
||||
let y = u64::from_le_bytes(noise[8..16].try_into().unwrap());
|
||||
let z = u64::from_le_bytes(noise[16..24].try_into().unwrap());
|
||||
let w = u64::from_le_bytes(noise[24..32].try_into().unwrap());
|
||||
let roll = (x ^ y ^ z ^ w) % block.cumulative_sum;
|
||||
|
||||
// Find the winning commit
|
||||
let mut winner = None;
|
||||
for (pubkey, commit) in commits {
|
||||
if roll >= commit.cumulative_sum && roll < commit.cumulative_sum + commit.amount {
|
||||
println!("Roll: {}, Winner: {:?}", roll, pubkey);
|
||||
winner = Some((pubkey, commit));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Build payout instruction
|
||||
let ix = if let Some((pubkey, commit)) = winner {
|
||||
payout(
|
||||
payer.pubkey(),
|
||||
pubkey,
|
||||
spl_associated_token_account::get_associated_token_address(
|
||||
&commit.authority,
|
||||
&spl_token::native_mint::ID,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
payout(payer.pubkey(), Pubkey::new_unique(), Pubkey::new_unique())
|
||||
};
|
||||
|
||||
Ok(ix)
|
||||
}
|
||||
|
||||
async fn close_all_commits(
|
||||
async fn close(
|
||||
rpc: &RpcClient,
|
||||
payer: &solana_sdk::signer::keypair::Keypair,
|
||||
) -> Result<(), anyhow::Error> {
|
||||
let block = get_block(rpc).await?;
|
||||
let commits = get_my_commits(rpc, payer).await?;
|
||||
let mut ixs = vec![];
|
||||
for (pubkey, commit) in commits {
|
||||
if commit.round != block.current_round {
|
||||
let ix = ore_api::sdk::close(payer.pubkey(), pubkey);
|
||||
ixs.push(ix);
|
||||
}
|
||||
}
|
||||
submit_transaction(rpc, payer, &ixs).await?;
|
||||
let id_str = std::env::var("ID").expect("Missing ID env var");
|
||||
let id = id_str.parse::<u64>()?;
|
||||
let ix = ore_api::sdk::close(payer.pubkey(), payer.pubkey(), id);
|
||||
submit_transaction(rpc, payer, &[ix]).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_block(rpc: &RpcClient) -> Result<Block, anyhow::Error> {
|
||||
let block_pda = ore_api::state::block_pda();
|
||||
async fn log_clock(rpc: &RpcClient) -> Result<(), anyhow::Error> {
|
||||
let clock = get_clock(&rpc).await?;
|
||||
println!("Clock: {:?}", clock);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn log_block(rpc: &RpcClient) -> Result<(), anyhow::Error> {
|
||||
let id_str = std::env::var("ID").expect("Missing ID env var");
|
||||
let id = id_str.parse::<u64>()?;
|
||||
let block = get_block(&rpc, id).await?;
|
||||
println!("Block: {:?}", block);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_block(rpc: &RpcClient, id: u64) -> Result<Block, anyhow::Error> {
|
||||
let block_pda = ore_api::state::block_pda(id);
|
||||
let account = rpc.get_account(&block_pda.0).await?;
|
||||
let block = Block::try_from_bytes(&account.data)?;
|
||||
Ok(*block)
|
||||
@@ -281,44 +91,27 @@ async fn get_clock(rpc: &RpcClient) -> Result<Clock, anyhow::Error> {
|
||||
Ok(clock)
|
||||
}
|
||||
|
||||
async fn get_block_commits(rpc: &RpcClient) -> Result<Vec<(Pubkey, Commit)>, anyhow::Error> {
|
||||
let block = get_block(rpc).await?;
|
||||
let filter = RpcFilterType::Memcmp(Memcmp::new_base58_encoded(
|
||||
56,
|
||||
&block.current_round.to_le_bytes(),
|
||||
));
|
||||
let commits = get_program_accounts::<Commit>(rpc, ore_api::ID, vec![filter]).await?;
|
||||
Ok(commits)
|
||||
}
|
||||
// async fn get_block_commits(rpc: &RpcClient) -> Result<Vec<(Pubkey, Commit)>, anyhow::Error> {
|
||||
// let block = get_block(rpc).await?;
|
||||
// let filter = RpcFilterType::Memcmp(Memcmp::new_base58_encoded(
|
||||
// 56,
|
||||
// &block.current_round.to_le_bytes(),
|
||||
// ));
|
||||
// let commits = get_program_accounts::<Commit>(rpc, ore_api::ID, vec![filter]).await?;
|
||||
// Ok(commits)
|
||||
// }
|
||||
|
||||
async fn get_my_commits(
|
||||
rpc: &RpcClient,
|
||||
payer: &solana_sdk::signer::keypair::Keypair,
|
||||
) -> Result<Vec<(Pubkey, Commit)>, anyhow::Error> {
|
||||
let filter = RpcFilterType::Memcmp(Memcmp::new_base58_encoded(
|
||||
16,
|
||||
&payer.pubkey().to_bytes().as_ref(),
|
||||
));
|
||||
let commits = get_program_accounts::<Commit>(rpc, ore_api::ID, vec![filter]).await?;
|
||||
Ok(commits)
|
||||
}
|
||||
|
||||
fn generate_seed(payer: &solana_sdk::signer::keypair::Keypair, block: &Block) -> [u8; 32] {
|
||||
solana_sdk::hash::hash(
|
||||
&[
|
||||
payer.pubkey().to_bytes().as_ref(),
|
||||
block.current_round.to_le_bytes().as_ref(),
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos()
|
||||
.to_le_bytes()
|
||||
.as_ref(),
|
||||
]
|
||||
.concat(),
|
||||
)
|
||||
.to_bytes()
|
||||
}
|
||||
// async fn get_my_commits(
|
||||
// rpc: &RpcClient,
|
||||
// payer: &solana_sdk::signer::keypair::Keypair,
|
||||
// ) -> Result<Vec<(Pubkey, Commit)>, anyhow::Error> {
|
||||
// let filter = RpcFilterType::Memcmp(Memcmp::new_base58_encoded(
|
||||
// 16,
|
||||
// &payer.pubkey().to_bytes().as_ref(),
|
||||
// ));
|
||||
// let commits = get_program_accounts::<Commit>(rpc, ore_api::ID, vec![filter]).await?;
|
||||
// Ok(commits)
|
||||
// }
|
||||
|
||||
async fn submit_transaction(
|
||||
rpc: &RpcClient,
|
||||
|
||||
@@ -11,6 +11,8 @@ pub fn open(signer: Pubkey, id: u64) -> Instruction {
|
||||
let block_adddress = block_pda(id).0;
|
||||
let market_address = market_pda(id).0;
|
||||
let base_mint_address = mint_pda(id).0;
|
||||
let vault_base_address = get_associated_token_address(&market_address, &base_mint_address);
|
||||
let vault_quote_address = get_associated_token_address(&market_address, &MINT_ADDRESS);
|
||||
Instruction {
|
||||
program_id: crate::ID,
|
||||
accounts: vec![
|
||||
@@ -19,6 +21,8 @@ pub fn open(signer: Pubkey, id: u64) -> Instruction {
|
||||
AccountMeta::new(market_address, false),
|
||||
AccountMeta::new(base_mint_address, false),
|
||||
AccountMeta::new(MINT_ADDRESS, false),
|
||||
AccountMeta::new(vault_base_address, false),
|
||||
AccountMeta::new(vault_quote_address, false),
|
||||
AccountMeta::new_readonly(system_program::ID, false),
|
||||
AccountMeta::new_readonly(spl_token::ID, false),
|
||||
AccountMeta::new_readonly(spl_associated_token_account::ID, false),
|
||||
@@ -35,8 +39,8 @@ pub fn close(signer: Pubkey, recipient: Pubkey, id: u64) -> Instruction {
|
||||
let block_adddress = block_pda(id).0;
|
||||
let market_address = market_pda(id).0;
|
||||
let base_mint_address = mint_pda(id).0;
|
||||
let vault_base = get_associated_token_address(&signer, &base_mint_address);
|
||||
let vault_quote = get_associated_token_address(&signer, &MINT_ADDRESS);
|
||||
let vault_base = get_associated_token_address(&market_address, &base_mint_address);
|
||||
let vault_quote = get_associated_token_address(&market_address, &MINT_ADDRESS);
|
||||
Instruction {
|
||||
program_id: crate::ID,
|
||||
accounts: vec![
|
||||
@@ -110,6 +114,7 @@ pub fn swap(
|
||||
AccountMeta::new(vault_quote_address, false),
|
||||
AccountMeta::new_readonly(system_program::ID, false),
|
||||
AccountMeta::new_readonly(spl_token::ID, false),
|
||||
AccountMeta::new_readonly(spl_associated_token_account::ID, false),
|
||||
],
|
||||
data: Swap {
|
||||
amount: amount.to_le_bytes(),
|
||||
@@ -119,11 +124,3 @@ pub fn swap(
|
||||
.to_bytes(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_open() {
|
||||
// let ix = open(Pubkey::default(), 0);
|
||||
let treasury_pda = treasury_pda();
|
||||
println!("{:?}", treasury_pda);
|
||||
assert!(false);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@ pub fn process_open(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
|
||||
let id = u64::from_le_bytes(args.id);
|
||||
|
||||
// Load accounts.
|
||||
let [signer_info, block_info, market_info, mint_base_info, mint_quote_info, system_program, vault_base_info, vault_quote_info, token_program, associated_token_program, rent_sysvar] =
|
||||
let clock = Clock::get()?;
|
||||
let [signer_info, block_info, market_info, mint_base_info, mint_quote_info, vault_base_info, vault_quote_info, system_program, token_program, associated_token_program, rent_sysvar] =
|
||||
accounts
|
||||
else {
|
||||
return Err(ProgramError::NotEnoughAccountKeys);
|
||||
@@ -34,6 +35,14 @@ pub fn process_open(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
|
||||
associated_token_program.is_program(&spl_associated_token_account::ID)?;
|
||||
rent_sysvar.is_sysvar(&sysvar::rent::ID)?;
|
||||
|
||||
// Error out if start slot is within the current period.
|
||||
let start_slot = id * 1500;
|
||||
let current_period_start = (clock.slot / 1500) * 1500;
|
||||
let current_period_end = current_period_start + 1500;
|
||||
if start_slot < current_period_end {
|
||||
return Err(ProgramError::InvalidArgument);
|
||||
}
|
||||
|
||||
// Initialize config.
|
||||
create_program_account::<Block>(
|
||||
block_info,
|
||||
@@ -48,7 +57,7 @@ pub fn process_open(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
|
||||
block.id = id;
|
||||
block.reward = ONE_ORE * 10;
|
||||
block.slot_hash = [0; 32];
|
||||
block.start_slot = 1500 * id;
|
||||
block.start_slot = start_slot;
|
||||
|
||||
// Initialize market.
|
||||
create_program_account::<Market>(
|
||||
@@ -83,15 +92,17 @@ pub fn process_open(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
|
||||
market.id = id;
|
||||
|
||||
// Initialize hash token mint.
|
||||
allocate_account(
|
||||
let mint_bump = mint_pda(block.id).1;
|
||||
allocate_account_with_bump(
|
||||
mint_base_info,
|
||||
system_program,
|
||||
signer_info,
|
||||
spl_token::state::Mint::LEN,
|
||||
&spl_token::ID,
|
||||
&[MINT, &id.to_le_bytes()],
|
||||
mint_bump,
|
||||
)?;
|
||||
initialize_mint_signed(
|
||||
initialize_mint_signed_with_bump(
|
||||
mint_base_info,
|
||||
block_info,
|
||||
None,
|
||||
@@ -99,6 +110,7 @@ pub fn process_open(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
|
||||
rent_sysvar,
|
||||
0,
|
||||
&[MINT, &id.to_le_bytes()],
|
||||
mint_bump,
|
||||
)?;
|
||||
|
||||
// TODO Initialize hash token metadata.
|
||||
|
||||
@@ -11,34 +11,22 @@ pub fn process_swap(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
|
||||
|
||||
// Load accounts.
|
||||
let clock = Clock::get()?;
|
||||
let [signer_info, block_info, market_info, mint_base_info, mint_quote_info, tokens_base_info, tokens_quote_info, vault_base_info, vault_quote_info, system_program, token_program] =
|
||||
let [signer_info, block_info, market_info, mint_base_info, mint_quote_info, tokens_base_info, tokens_quote_info, vault_base_info, vault_quote_info, system_program, token_program, associated_token_program] =
|
||||
accounts
|
||||
else {
|
||||
return Err(ProgramError::NotEnoughAccountKeys);
|
||||
};
|
||||
signer_info.is_signer()?;
|
||||
let block = block_info
|
||||
let block: &mut Block = block_info
|
||||
.as_account_mut::<Block>(&ore_api::ID)?
|
||||
.assert_mut(|b| clock.slot >= b.start_slot + 1500)?;
|
||||
.assert_mut(|b| clock.slot < b.start_slot)?;
|
||||
let market = market_info
|
||||
.as_account_mut::<Market>(&ore_api::ID)?
|
||||
.assert_mut(|m| m.id == block.id)?
|
||||
.assert_mut_err(
|
||||
|m| m.base.liquidity() > 0,
|
||||
OreError::InsufficientLiquidity.into(),
|
||||
)?
|
||||
.assert_mut_err(
|
||||
|m| m.quote.liquidity() > 0,
|
||||
OreError::InsufficientLiquidity.into(),
|
||||
)?;
|
||||
.assert_mut(|m| m.base.liquidity() > 0)?
|
||||
.assert_mut(|m| m.quote.liquidity() > 0)?;
|
||||
mint_base_info.has_address(&market.base.mint)?.as_mint()?;
|
||||
mint_quote_info.has_address(&market.quote.mint)?.as_mint()?;
|
||||
tokens_base_info
|
||||
.is_writable()?
|
||||
.as_associated_token_account(signer_info.key, mint_base_info.key)?;
|
||||
tokens_quote_info
|
||||
.is_writable()?
|
||||
.as_associated_token_account(signer_info.key, mint_quote_info.key)?;
|
||||
vault_base_info
|
||||
.is_writable()?
|
||||
.as_associated_token_account(market_info.key, mint_base_info.key)?;
|
||||
@@ -47,6 +35,39 @@ pub fn process_swap(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult
|
||||
.as_associated_token_account(market_info.key, mint_quote_info.key)?;
|
||||
system_program.is_program(&system_program::ID)?;
|
||||
token_program.is_program(&spl_token::ID)?;
|
||||
associated_token_program.is_program(&spl_associated_token_account::ID)?;
|
||||
|
||||
// Load token acccounts.
|
||||
if tokens_base_info.data_is_empty() {
|
||||
create_associated_token_account(
|
||||
signer_info,
|
||||
signer_info,
|
||||
tokens_base_info,
|
||||
mint_base_info,
|
||||
system_program,
|
||||
token_program,
|
||||
associated_token_program,
|
||||
)?;
|
||||
} else {
|
||||
tokens_base_info
|
||||
.is_writable()?
|
||||
.as_associated_token_account(signer_info.key, mint_base_info.key)?;
|
||||
}
|
||||
if tokens_quote_info.data_is_empty() {
|
||||
create_associated_token_account(
|
||||
signer_info,
|
||||
signer_info,
|
||||
tokens_quote_info,
|
||||
mint_quote_info,
|
||||
system_program,
|
||||
token_program,
|
||||
associated_token_program,
|
||||
)?;
|
||||
} else {
|
||||
tokens_quote_info
|
||||
.is_writable()?
|
||||
.as_associated_token_account(signer_info.key, mint_quote_info.key)?;
|
||||
}
|
||||
|
||||
// Update market state.
|
||||
let mut swap_result = market.swap(amount, direction, precision, clock)?;
|
||||
|
||||
Reference in New Issue
Block a user