mirror of
https://github.com/payden/libwsclient
synced 2026-03-02 04:09:18 +00:00
feat : add strategy
This commit is contained in:
11
dex/dex_integration.rs
Normal file
11
dex/dex_integration.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
use async_trait::async_trait;
|
||||
use solana_sdk::pubkey::Pubkey;
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[async_trait]
|
||||
pub trait DexIntegration {
|
||||
async fn get_prices(&self) -> HashMap<String, f64>;
|
||||
async fn get_account_balances(&self, account: &Pubkey) -> HashMap<String, f64>;
|
||||
async fn place_order(&self, market: &str, side: &str, size: f64, price: f64) -> Option<String>;
|
||||
async fn cancel_order(&self, order_id: &str) -> bool;
|
||||
}
|
||||
4
dex/mod.rs
Normal file
4
dex/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
pub mod dex_integration;
|
||||
pub mod raydium;
|
||||
pub mod serum;
|
||||
pub mod orca;
|
||||
147
dex/orca.rs
Normal file
147
dex/orca.rs
Normal file
@@ -0,0 +1,147 @@
|
||||
use crate::dex::dex_trait::DexTrait;
|
||||
use crate::error::Result;
|
||||
use crate::models::market::Market;
|
||||
use crate::models::order::{Order, OrderSide, OrderStatus, OrderType};
|
||||
use sdk::pubkey::Pubkey;
|
||||
use sdk::signature::Keypair;
|
||||
use sdk::signer::Signer;
|
||||
use sdk::transaction::Transaction;
|
||||
use solana_client::rpc_client::RpcClient;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct Orca {
|
||||
pub rpc_client: RpcClient,
|
||||
pub program_id: Pubkey,
|
||||
pub authority: Keypair,
|
||||
}
|
||||
|
||||
impl Orca {
|
||||
pub fn new(rpc_client: RpcClient, program_id: Pubkey, authority: Keypair) -> Self {
|
||||
Orca {
|
||||
rpc_client,
|
||||
program_id,
|
||||
authority,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl DexTrait for Orca {
|
||||
async fn get_markets(&self) -> Result<Vec<Market>> {
|
||||
let mut markets = Vec::new();
|
||||
|
||||
let pools = self.rpc_client.get_program_accounts(&self.program_id)?;
|
||||
|
||||
for pool in pools {
|
||||
let pool_data: PoolData = bincode::deserialize(&pool.account.data)?;
|
||||
|
||||
let market = Market {
|
||||
address: pool.pubkey,
|
||||
name: format!("{}/{}", pool_data.token_a.to_string(), pool_data.token_b.to_string()),
|
||||
base_asset: pool_data.token_a,
|
||||
quote_asset: pool_data.token_b,
|
||||
base_decimals: pool_data.token_a_decimals,
|
||||
quote_decimals: pool_data.token_b_decimals,
|
||||
};
|
||||
markets.push(market);
|
||||
}
|
||||
|
||||
Ok(markets)
|
||||
}
|
||||
|
||||
async fn get_orderbook(&self, market: &Market) -> Result<(Vec<Order>, Vec<Order>)> {
|
||||
Ok((Vec::new(), Vec::new()))
|
||||
}
|
||||
|
||||
async fn place_order(
|
||||
&self,
|
||||
market: &Market,
|
||||
order_type: OrderType,
|
||||
side: OrderSide,
|
||||
price: f64,
|
||||
quantity: f64,
|
||||
) -> Result<Order> {
|
||||
let pool_data = self.get_pool_data(&market.address).await?;
|
||||
|
||||
let (token_a_amount, token_b_amount) = match side {
|
||||
OrderSide::Bid => (quantity, quantity * price),
|
||||
OrderSide::Ask => (quantity / price, quantity),
|
||||
};
|
||||
|
||||
let minimum_amount_out = match side {
|
||||
OrderSide::Bid => token_b_amount * 0.99,
|
||||
OrderSide::Ask => token_a_amount * 0.99,
|
||||
};
|
||||
|
||||
let instruction = orca_swap::instruction::swap(
|
||||
&self.program_id,
|
||||
&market.address,
|
||||
&self.authority.pubkey(),
|
||||
&pool_data.token_a_account,
|
||||
&pool_data.token_b_account,
|
||||
&self.get_token_account(&market.base_asset).await?,
|
||||
&self.get_token_account(&market.quote_asset).await?,
|
||||
token_a_amount,
|
||||
minimum_amount_out,
|
||||
)?;
|
||||
|
||||
let recent_blockhash = self.rpc_client.get_latest_blockhash()?;
|
||||
let transaction = Transaction::new_signed_with_payer(
|
||||
&[instruction],
|
||||
Some(&self.authority.pubkey()),
|
||||
&[&self.authority],
|
||||
recent_blockhash,
|
||||
);
|
||||
|
||||
self.rpc_client.send_and_confirm_transaction(&transaction)?;
|
||||
|
||||
Ok(Order {
|
||||
id: self.create_order_id(),
|
||||
market: market.clone(),
|
||||
order_type,
|
||||
side,
|
||||
price,
|
||||
quantity,
|
||||
status: OrderStatus::Filled,
|
||||
})
|
||||
}
|
||||
|
||||
async fn cancel_order(&self, _order: &Order) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_balances(&self, market: &Market) -> Result<HashMap<Pubkey, f64>> {
|
||||
let pool_data = self.get_pool_data(&market.address).await?;
|
||||
|
||||
let token_a_balance = self.rpc_client.get_token_account_balance(&pool_data.token_a_account)?;
|
||||
let token_b_balance = self.rpc_client.get_token_account_balance(&pool_data.token_b_account)?;
|
||||
|
||||
let mut balances = HashMap::new();
|
||||
balances.insert(market.base_asset, token_a_balance.amount as f64);
|
||||
balances.insert(market.quote_asset, token_b_balance.amount as f64);
|
||||
|
||||
Ok(balances)
|
||||
}
|
||||
}
|
||||
|
||||
impl Orca {
|
||||
fn create_order_id(&self) -> u64 {
|
||||
rand::random()
|
||||
}
|
||||
|
||||
async fn get_pool_data(&self, pool_address: &Pubkey) -> Result<PoolData> {
|
||||
let pool_account_info = self.rpc_client.get_account(pool_address)?;
|
||||
let pool_data: PoolData = bincode::deserialize(&pool_account_info.data)?;
|
||||
|
||||
Ok(pool_data)
|
||||
}
|
||||
|
||||
async fn get_token_account(&self, token_mint: &Pubkey) -> Result<Pubkey> {
|
||||
let token_account = spl_associated_token_account::get_associated_token_address(
|
||||
&self.authority.pubkey(),
|
||||
token_mint,
|
||||
);
|
||||
|
||||
Ok(token_account)
|
||||
}
|
||||
}
|
||||
259
dex/raydium.rs
Normal file
259
dex/raydium.rs
Normal file
@@ -0,0 +1,259 @@
|
||||
use crate::dex::dex_trait::DexTrait;
|
||||
use crate::error::Result;
|
||||
use crate::models::market::Market;
|
||||
use crate::models::order::{Order, OrderSide, OrderStatus, OrderType};
|
||||
use sdk::pubkey::Pubkey;
|
||||
use sdk::signature::Keypair;
|
||||
use sdk::signer::Signer;
|
||||
use sdk::transaction::Transaction;
|
||||
use solana_client::rpc_client::RpcClient;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct Raydium {
|
||||
pub rpc_client: RpcClient,
|
||||
pub program_id: Pubkey,
|
||||
pub amm_id: Pubkey,
|
||||
pub serum_program_id: Pubkey,
|
||||
pub authority: Keypair,
|
||||
}
|
||||
|
||||
impl Raydium {
|
||||
pub fn new(
|
||||
rpc_client: RpcClient,
|
||||
program_id: Pubkey,
|
||||
amm_id: Pubkey,
|
||||
serum_program_id: Pubkey,
|
||||
authority: Keypair,
|
||||
) -> Self {
|
||||
Raydium {
|
||||
rpc_client,
|
||||
program_id,
|
||||
amm_id,
|
||||
serum_program_id,
|
||||
authority,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl DexTrait for Raydium {
|
||||
async fn get_markets(&self) -> Result<Vec<Market>> {
|
||||
let mut markets = Vec::new();
|
||||
|
||||
let market_infos = self.rpc_client.get_account_info(&self.amm_id)?;
|
||||
let market_data: AmmInfo = bincode::deserialize(&market_infos.data)?;
|
||||
|
||||
for (mint_a, mint_b) in market_data.mints.iter() {
|
||||
let market = Market {
|
||||
address: Pubkey::default(),
|
||||
name: format!("{}/{}", mint_a, mint_b),
|
||||
base_asset: *mint_a,
|
||||
quote_asset: *mint_b,
|
||||
base_decimals: 0,
|
||||
quote_decimals: 0,
|
||||
};
|
||||
markets.push(market);
|
||||
}
|
||||
|
||||
Ok(markets)
|
||||
}
|
||||
|
||||
async fn get_orderbook(&self, market: &Market) -> Result<(Vec<Order>, Vec<Order>)> {
|
||||
let market_account_info = self.rpc_client.get_account_info(&market.address)?;
|
||||
let market_data: MarketState = bincode::deserialize(&market_account_info.data)?;
|
||||
|
||||
let bids = market_data.bids.iter().map(|order| Order {
|
||||
price: order.price,
|
||||
quantity: order.quantity,
|
||||
side: OrderSide::Bid,
|
||||
}).collect();
|
||||
|
||||
let asks = market_data.asks.iter().map(|order| Order {
|
||||
price: order.price,
|
||||
quantity: order.quantity,
|
||||
side: OrderSide::Ask,
|
||||
}).collect();
|
||||
|
||||
Ok((bids, asks))
|
||||
}
|
||||
|
||||
async fn place_order(
|
||||
&self,
|
||||
market: &Market,
|
||||
order_type: OrderType,
|
||||
side: OrderSide,
|
||||
price: f64,
|
||||
quantity: f64,
|
||||
) -> Result<Order> {
|
||||
let order_id = self.create_order_id();
|
||||
let order_account = Keypair::new();
|
||||
|
||||
let (vault_a, vault_b) = self.get_vaults(market).await?;
|
||||
|
||||
let (token_a_account, token_b_account) = self.get_token_accounts(market).await?;
|
||||
|
||||
let order_data = match side {
|
||||
OrderSide::Bid => MarketInstruction::NewOrder {
|
||||
order_type: order_type.into(),
|
||||
side: Side::Bid,
|
||||
limit_price: price,
|
||||
max_quantity: quantity,
|
||||
order_id,
|
||||
},
|
||||
OrderSide::Ask => MarketInstruction::NewOrder {
|
||||
order_type: order_type.into(),
|
||||
side: Side::Ask,
|
||||
limit_price: price,
|
||||
max_quantity: quantity,
|
||||
order_id,
|
||||
},
|
||||
};
|
||||
|
||||
let accounts = match side {
|
||||
OrderSide::Bid => vec![
|
||||
AccountMeta::new(market.address, false),
|
||||
AccountMeta::new(order_account.pubkey(), true),
|
||||
AccountMeta::new(self.authority.pubkey(), true),
|
||||
AccountMeta::new_readonly(spl_token::ID, false),
|
||||
AccountMeta::new(token_b_account, false),
|
||||
AccountMeta::new(vault_b, false),
|
||||
AccountMeta::new(vault_a, false),
|
||||
AccountMeta::new(token_a_account, false),
|
||||
AccountMeta::new_readonly(solana_sdk::sysvar::rent::ID, false),
|
||||
],
|
||||
OrderSide::Ask => vec![
|
||||
AccountMeta::new(market.address, false),
|
||||
AccountMeta::new(order_account.pubkey(), true),
|
||||
AccountMeta::new(self.authority.pubkey(), true),
|
||||
AccountMeta::new_readonly(spl_token::ID, false),
|
||||
AccountMeta::new(token_a_account, false),
|
||||
AccountMeta::new(vault_a, false),
|
||||
AccountMeta::new(vault_b, false),
|
||||
AccountMeta::new(token_b_account, false),
|
||||
AccountMeta::new_readonly(solana_sdk::sysvar::rent::ID, false),
|
||||
],
|
||||
};
|
||||
|
||||
let instruction = Instruction {
|
||||
program_id: self.program_id,
|
||||
accounts,
|
||||
data: order_data.pack(),
|
||||
};
|
||||
|
||||
let recent_blockhash = self.rpc_client.get_latest_blockhash()?;
|
||||
let transaction = Transaction::new_signed_with_payer(
|
||||
&[instruction],
|
||||
Some(&self.authority.pubkey()),
|
||||
&[&self.authority, &order_account],
|
||||
recent_blockhash,
|
||||
);
|
||||
|
||||
self.rpc_client.send_and_confirm_transaction(&transaction)?;
|
||||
|
||||
Ok(Order {
|
||||
id: order_id,
|
||||
market: market.clone(),
|
||||
order_type,
|
||||
side,
|
||||
price,
|
||||
quantity,
|
||||
status: OrderStatus::Open,
|
||||
})
|
||||
}
|
||||
|
||||
async fn cancel_order(&self, order: &Order) -> Result<()> {
|
||||
let cancel_data = MarketInstruction::CancelOrder { order_id: order.id };
|
||||
|
||||
let accounts = vec![
|
||||
AccountMeta::new(order.market.address, false),
|
||||
AccountMeta::new_readonly(self.authority.pubkey(), true),
|
||||
AccountMeta::new(self.get_bids_address(&order.market)?, false),
|
||||
AccountMeta::new(self.get_asks_address(&order.market)?, false),
|
||||
];
|
||||
|
||||
let instruction = Instruction {
|
||||
program_id: self.program_id,
|
||||
accounts,
|
||||
data: cancel_data.pack(),
|
||||
};
|
||||
|
||||
let recent_blockhash = self.rpc_client.get_latest_blockhash()?;
|
||||
let transaction = Transaction::new_signed_with_payer(
|
||||
&[instruction],
|
||||
Some(&self.authority.pubkey()),
|
||||
&[&self.authority],
|
||||
recent_blockhash,
|
||||
);
|
||||
|
||||
self.rpc_client.send_and_confirm_transaction(&transaction)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_balances(&self, market: &Market) -> Result<HashMap<Pubkey, f64>> {
|
||||
let (vault_a, vault_b) = self.get_vaults(market).await?;
|
||||
|
||||
let vault_a_balance = self.rpc_client.get_token_account_balance(&vault_a)?;
|
||||
let vault_b_balance = self.rpc_client.get_token_account_balance(&vault_b)?;
|
||||
|
||||
let mut balances = HashMap::new();
|
||||
balances.insert(market.base_asset, vault_a_balance.amount as f64);
|
||||
balances.insert(market.quote_asset, vault_b_balance.amount as f64);
|
||||
|
||||
Ok(balances)
|
||||
}
|
||||
}
|
||||
|
||||
impl Raydium {
|
||||
fn create_order_id(&self) -> u64 {
|
||||
rand::random()
|
||||
}
|
||||
|
||||
async fn get_vaults(&self, market: &Market) -> Result<(Pubkey, Pubkey)> {
|
||||
let market_account_info = self.rpc_client.get_account_info(&market.address)?;
|
||||
let market_data: MarketState = bincode::deserialize(&market_account_info.data)?;
|
||||
|
||||
Ok((market_data.base_vault, market_data.quote_vault))
|
||||
}
|
||||
|
||||
async fn get_token_accounts(&self, market: &Market) -> Result<(Pubkey, Pubkey)> {
|
||||
let token_a_account = spl_associated_token_account::get_associated_token_address(
|
||||
&self.authority.pubkey(),
|
||||
&market.base_asset,
|
||||
);
|
||||
let token_b_account = spl_associated_token_account::get_associated_token_address(
|
||||
&self.authority.pubkey(),
|
||||
&market.quote_asset,
|
||||
);
|
||||
|
||||
Ok((token_a_account, token_b_account))
|
||||
}
|
||||
|
||||
fn get_bids_address(&self, market: &Market) -> Result<Pubkey> {
|
||||
let (bids_address, _) = Pubkey::find_program_address(
|
||||
&[
|
||||
&market.address.to_bytes(),
|
||||
&spl_token::ID.to_bytes(),
|
||||
&self.program_id.to_bytes(),
|
||||
b"bids",
|
||||
],
|
||||
&self.program_id,
|
||||
);
|
||||
|
||||
Ok(bids_address)
|
||||
}
|
||||
|
||||
fn get_asks_address(&self, market: &Market) -> Result<Pubkey> {
|
||||
let (asks_address, _) = Pubkey::find_program_address(
|
||||
&[
|
||||
&market.address.to_bytes(),
|
||||
&spl_token::ID.to_bytes(),
|
||||
&self.program_id.to_bytes(),
|
||||
b"asks",
|
||||
],
|
||||
&self.program_id,
|
||||
);
|
||||
|
||||
Ok(asks_address)
|
||||
}
|
||||
}
|
||||
273
dex/serum.rs
Normal file
273
dex/serum.rs
Normal file
@@ -0,0 +1,273 @@
|
||||
use crate::dex::dex_trait::DexTrait;
|
||||
use crate::error::Result;
|
||||
use crate::models::market::Market;
|
||||
use crate::models::order::{Order, OrderSide, OrderStatus, OrderType};
|
||||
use sdk::pubkey::Pubkey;
|
||||
use sdk::signature::Keypair;
|
||||
use sdk::signer::Signer;
|
||||
use sdk::transaction::Transaction;
|
||||
use solana_client::rpc_client::RpcClient;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct Serum {
|
||||
pub rpc_client: RpcClient,
|
||||
pub program_id: Pubkey,
|
||||
pub authority: Keypair,
|
||||
}
|
||||
|
||||
impl Serum {
|
||||
pub fn new(rpc_client: RpcClient, program_id: Pubkey, authority: Keypair) -> Self {
|
||||
Serum {
|
||||
rpc_client,
|
||||
program_id,
|
||||
authority,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl DexTrait for Serum {
|
||||
async fn get_markets(&self) -> Result<Vec<Market>> {
|
||||
let mut markets = Vec::new();
|
||||
|
||||
let market_infos = self.rpc_client.get_program_accounts(&self.program_id)?;
|
||||
|
||||
for market_info in market_infos {
|
||||
let market_data: MarketState = bincode::deserialize(&market_info.account.data)?;
|
||||
|
||||
let market = Market {
|
||||
address: market_info.pubkey,
|
||||
name: String::from_utf8_lossy(&market_data.name).to_string(),
|
||||
base_asset: market_data.coin_lot_size,
|
||||
quote_asset: market_data.pc_lot_size,
|
||||
base_decimals: market_data.coin_decimals,
|
||||
quote_decimals: market_data.pc_decimals,
|
||||
};
|
||||
markets.push(market);
|
||||
}
|
||||
|
||||
Ok(markets)
|
||||
}
|
||||
|
||||
async fn get_orderbook(&self, market: &Market) -> Result<(Vec<Order>, Vec<Order>)> {
|
||||
let market_account_info = self.rpc_client.get_account_info(&market.address)?;
|
||||
let market_data: MarketState = bincode::deserialize(&market_account_info.data)?;
|
||||
|
||||
let bids = market_data.load_bids_mut(&self.program_id)?;
|
||||
let asks = market_data.load_asks_mut(&self.program_id)?;
|
||||
|
||||
let bid_orders = bids.orders(&market_data, &self.program_id)?;
|
||||
let ask_orders = asks.orders(&market_data, &self.program_id)?;
|
||||
|
||||
Ok((bid_orders, ask_orders))
|
||||
}
|
||||
|
||||
async fn place_order(
|
||||
&self,
|
||||
market: &Market,
|
||||
order_type: OrderType,
|
||||
side: OrderSide,
|
||||
price: f64,
|
||||
quantity: f64,
|
||||
) -> Result<Order> {
|
||||
let order_id = self.create_order_id();
|
||||
let order_account = Keypair::new();
|
||||
|
||||
let (token_a_account, token_b_account) = self.get_token_accounts(market).await?;
|
||||
|
||||
let order_data = NewOrderInstructionV3 {
|
||||
side: side.into(),
|
||||
limit_price: price,
|
||||
max_qty: quantity,
|
||||
order_type: order_type.into(),
|
||||
client_order_id: 0,
|
||||
self_trade_behavior: SelfTradeBehavior::DecrementTake,
|
||||
limit: 65535,
|
||||
max_coin_qty: quantity,
|
||||
max_native_pc_qty_including_fees: price * quantity,
|
||||
self_trade_behavior_v2: SelfTradeBehaviorV2::CancelProvide,
|
||||
padding: [0; 5],
|
||||
};
|
||||
|
||||
let accounts = match side {
|
||||
OrderSide::Bid => vec![
|
||||
AccountMeta::new(market.address, false),
|
||||
AccountMeta::new(order_account.pubkey(), true),
|
||||
AccountMeta::new(self.authority.pubkey(), true),
|
||||
AccountMeta::new_readonly(spl_token::ID, false),
|
||||
AccountMeta::new(token_b_account, false),
|
||||
AccountMeta::new(self.get_bids_address(&market)?, false),
|
||||
AccountMeta::new(self.get_asks_address(&market)?, false),
|
||||
AccountMeta::new(self.get_event_queue_address(&market)?, false),
|
||||
AccountMeta::new(token_a_account, false),
|
||||
AccountMeta::new_readonly(solana_sdk::sysvar::rent::ID, false),
|
||||
],
|
||||
OrderSide::Ask => vec![
|
||||
AccountMeta::new(market.address, false),
|
||||
AccountMeta::new(order_account.pubkey(), true),
|
||||
AccountMeta::new(self.authority.pubkey(), true),
|
||||
AccountMeta::new_readonly(spl_token::ID, false),
|
||||
AccountMeta::new(token_a_account, false),
|
||||
AccountMeta::new(self.get_asks_address(&market)?, false),
|
||||
AccountMeta::new(self.get_bids_address(&market)?, false),
|
||||
AccountMeta::new(self.get_event_queue_address(&market)?, false),
|
||||
AccountMeta::new(token_b_account, false),
|
||||
AccountMeta::new_readonly(solana_sdk::sysvar::rent::ID, false),
|
||||
],
|
||||
};
|
||||
|
||||
let instruction = Instruction {
|
||||
program_id: self.program_id,
|
||||
accounts,
|
||||
data: order_data.pack(),
|
||||
};
|
||||
|
||||
let recent_blockhash = self.rpc_client.get_latest_blockhash()?;
|
||||
let transaction = Transaction::new_signed_with_payer(
|
||||
&[instruction],
|
||||
Some(&self.authority.pubkey()),
|
||||
&[&self.authority, &order_account],
|
||||
recent_blockhash,
|
||||
);
|
||||
|
||||
self.rpc_client.send_and_confirm_transaction(&transaction)?;
|
||||
|
||||
Ok(Order {
|
||||
id: order_id,
|
||||
market: market.clone(),
|
||||
order_type,
|
||||
side,
|
||||
price,
|
||||
quantity,
|
||||
status: OrderStatus::Open,
|
||||
})
|
||||
}
|
||||
|
||||
async fn cancel_order(&self, order: &Order) -> Result<()> {
|
||||
let cancel_data = MarketInstruction::CancelOrderV2 {
|
||||
side: order.side.into(),
|
||||
order_id: order.id,
|
||||
};
|
||||
|
||||
let accounts = vec![
|
||||
AccountMeta::new(order.market.address, false),
|
||||
AccountMeta::new_readonly(self.authority.pubkey(), true),
|
||||
AccountMeta::new(self.get_bids_address(&order.market)?, false),
|
||||
AccountMeta::new(self.get_asks_address(&order.market)?, false),
|
||||
AccountMeta::new(self.get_event_queue_address(&order.market)?, false),
|
||||
];
|
||||
|
||||
let instruction = Instruction {
|
||||
program_id: self.program_id,
|
||||
accounts,
|
||||
data: cancel_data.pack(),
|
||||
};
|
||||
|
||||
let recent_blockhash = self.rpc_client.get_latest_blockhash()?;
|
||||
let transaction = Transaction::new_signed_with_payer(
|
||||
&[instruction],
|
||||
Some(&self.authority.pubkey()),
|
||||
&[&self.authority],
|
||||
recent_blockhash,
|
||||
);
|
||||
|
||||
self.rpc_client.send_and_confirm_transaction(&transaction)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_balances(&self, market: &Market) -> Result<HashMap<Pubkey, f64>> {
|
||||
let vault_signer = self.get_vault_signer_address(&market)?;
|
||||
let base_vault = self.get_vault_address(&market, &market.base_asset)?;
|
||||
let quote_vault = self.get_vault_address(&market, &market.quote_asset)?;
|
||||
|
||||
let base_vault_balance = self.rpc_client.get_token_account_balance(&base_vault)?;
|
||||
let quote_vault_balance = self.rpc_client.get_token_account_balance("e_vault)?;
|
||||
|
||||
let mut balances = HashMap::new();
|
||||
balances.insert(market.base_asset, base_vault_balance.amount as f64);
|
||||
balances.insert(market.quote_asset, quote_vault_balance.amount as f64);
|
||||
|
||||
Ok(balances)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serum {
|
||||
fn create_order_id(&self) -> u64 {
|
||||
rand::random()
|
||||
}
|
||||
|
||||
async fn get_token_accounts(&self, market: &Market) -> Result<(Pubkey, Pubkey)> {
|
||||
let token_a_account = spl_associated_token_account::get_associated_token_address(
|
||||
&self.authority.pubkey(),
|
||||
&market.base_asset,
|
||||
);
|
||||
let token_b_account = spl_associated_token_account::get_associated_token_address(
|
||||
&self.authority.pubkey(),
|
||||
&market.quote_asset,
|
||||
);
|
||||
|
||||
Ok((token_a_account, token_b_account))
|
||||
}
|
||||
|
||||
fn get_bids_address(&self, market: &Market) -> Result<Pubkey> {
|
||||
let (bids_address, _) = Pubkey::find_program_address(
|
||||
&[
|
||||
&market.address.to_bytes(),
|
||||
b"bids",
|
||||
],
|
||||
&self.program_id,
|
||||
);
|
||||
|
||||
Ok(bids_address)
|
||||
}
|
||||
|
||||
fn get_asks_address(&self, market: &Market) -> Result<Pubkey> {
|
||||
let (asks_address, _) = Pubkey::find_program_address(
|
||||
&[
|
||||
&market.address.to_bytes(),
|
||||
b"asks",
|
||||
],
|
||||
&self.program_id,
|
||||
);
|
||||
|
||||
Ok(asks_address)
|
||||
}
|
||||
|
||||
fn get_event_queue_address(&self, market: &Market) -> Result<Pubkey> {
|
||||
let (event_queue_address, _) = Pubkey::find_program_address(
|
||||
&[
|
||||
&market.address.to_bytes(),
|
||||
b"event_queue",
|
||||
],
|
||||
&self.program_id,
|
||||
);
|
||||
|
||||
Ok(event_queue_address)
|
||||
}
|
||||
|
||||
fn get_vault_signer_address(&self, market: &Market) -> Result<Pubkey> {
|
||||
let (vault_signer_address, _) = Pubkey::find_program_address(
|
||||
&[
|
||||
&market.address.to_bytes(),
|
||||
b"vault_signer",
|
||||
],
|
||||
&self.program_id,
|
||||
);
|
||||
|
||||
Ok(vault_signer_address)
|
||||
}
|
||||
|
||||
fn get_vault_address(&self, market: &Market, token_mint: &Pubkey) -> Result<Pubkey> {
|
||||
let (vault_address, _) = Pubkey::find_program_address(
|
||||
&[
|
||||
&market.address.to_bytes(),
|
||||
&token_mint.to_bytes(),
|
||||
b"vault",
|
||||
],
|
||||
&spl_token::ID,
|
||||
);
|
||||
|
||||
Ok(vault_address)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user