Skip to content

Commit

Permalink
some fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
0xEdgar committed Feb 27, 2023
1 parent ccf1e6e commit 4279b25
Show file tree
Hide file tree
Showing 22 changed files with 324 additions and 358 deletions.
199 changes: 91 additions & 108 deletions client/src/arb.rs
Original file line number Diff line number Diff line change
@@ -1,143 +1,131 @@
use anchor_client::solana_client::rpc_client::RpcClient;
use anchor_client::solana_client::rpc_config::RpcSendTransactionConfig;
use anchor_client::solana_sdk::commitment_config::CommitmentConfig;

use anchor_client::solana_sdk::pubkey::Pubkey;

use anchor_client::solana_sdk::signature::{Keypair, Signer};
use anchor_client::solana_sdk::signature::read_keypair_file;
use anchor_client::{Cluster, Program};
use std::collections::{HashSet, HashMap};

use anchor_client::{Client, Cluster, Program};

use anchor_lang::Key;
use solana_sdk::instruction::Instruction;
use solana_sdk::transaction::Transaction;

use std::borrow::Borrow;
use std::rc::Rc;
use std::str::FromStr;
use std::collections::{HashMap, HashSet};
use std::fmt::Debug;
use std::sync::Arc;

use std::vec;
use std::borrow::Borrow;

use clap::Parser;

use log::{info, warn};

use log::{info};

use tmp::accounts as tmp_accounts;
use tmp::instruction as tmp_ix;

use client::serialize::{
token::unpack_token_account,
};
use client::utils::{str2pubkey, derive_token_address, read_json_dir};
use client::pool::{PoolType, PoolOperations, pool_factory, PoolDir};
use client::constants::*;

use crate::pool::{PoolOperations};

use crate::utils::{derive_token_address};

pub struct Arbitrager<'a> {
pub token_mints: Vec<Pubkey>,
pub graph_edges: Vec<HashSet<usize>>, // used for quick searching over the graph
pub token_mints: Vec<Pubkey>,
pub graph_edges: Vec<HashSet<usize>>, // used for quick searching over the graph
pub graph: HashMap<usize, HashMap<usize, Vec<Rc<&'a mut Box<dyn PoolOperations>>>>>,
pub cluster: Cluster,
// vv -- need to clone these explicitly -- vv
// vv -- need to clone these explicitly -- vv
pub owner: Rc<Keypair>,
pub program: Program,
pub program: Program,
pub connection: RpcClient,
}

impl Arbitrager<'_> {

pub fn brute_force_search(
&self,
start_mint_idx: usize,
start_mint_idx: usize,
init_balance: u128,
curr_balance: u128,
path: Vec<usize>,
path: Vec<usize>,
pool_path: Vec<Rc<&mut Box<dyn PoolOperations>>>,
sent_arbs: &mut HashSet<String>,
) {
let src_curr = path[path.len()-1]; // last mint
let src_curr = path[path.len() - 1]; // last mint
let src_mint = self.token_mints[src_curr];

let out_edges = &self.graph_edges[src_curr];

// path = 4 = A -> B -> C -> D
// path >= 5 == not valid bc max tx size is swaps
if path.len() == 4 { return };

if path.len() == 4 {
return;
};

for dst_mint_idx in out_edges {

let pools =
self.graph
.get(&src_curr).unwrap()
.get(dst_mint_idx).unwrap();

if path.contains(dst_mint_idx) && *dst_mint_idx != start_mint_idx {
continue;
let pools = self
.graph
.get(&src_curr)
.unwrap()
.get(dst_mint_idx)
.unwrap();

if path.contains(dst_mint_idx) && *dst_mint_idx != start_mint_idx {
continue;
}

let dst_mint_idx = *dst_mint_idx;
let dst_mint = self.token_mints[dst_mint_idx];

for pool in pools {

let new_balance = pool.get_quote_with_amounts_scaled(
curr_balance,
&src_mint,
&dst_mint,
);

let new_balance =
pool.get_quote_with_amounts_scaled(curr_balance, &src_mint, &dst_mint);

let mut new_path = path.clone();
new_path.push(dst_mint_idx);

let mut new_pool_path = pool_path.clone();
let mut new_pool_path = pool_path.clone();
new_pool_path.push(pool.clone()); // clone the pointer

if dst_mint_idx == start_mint_idx {
// info!("{:?} -> {:?} (-{:?})", init_balance, new_balance, init_balance - new_balance);

// if new_balance > init_balance - 1086310399 {
if new_balance > init_balance {
// ... profitable arb!
// ... profitable arb!
info!("found arbitrage: {:?} -> {:?}", init_balance, new_balance);
// check if arb was sent with a larger size

// check if arb was sent with a larger size
// key = {mint_path}{pool_names}
let mint_keys: Vec<String> = new_path.clone()
.iter_mut()
.map(|i| i.to_string())
.collect();
let pool_keys: Vec<String> = new_pool_path
.iter()
.map(|p| p.get_name())
.collect();
let mint_keys: Vec<String> =
new_path.clone().iter_mut().map(|i| i.to_string()).collect();
let pool_keys: Vec<String> =
new_pool_path.iter().map(|p| p.get_name()).collect();
let arb_key = format!("{}{}", mint_keys.join(""), pool_keys.join(""));
if sent_arbs.contains(&arb_key) {
info!("arb already sent...");
continue; // dont re-send an already sent arb -- bad for network
} else {
continue; // dont re-send an already sent arb -- bad for network
} else {
sent_arbs.insert(arb_key);
}

let ixs = self.get_arbitrage_instructions(
init_balance,
&new_path,
&new_pool_path,
init_balance,
&new_path,
&new_pool_path,
);
self.send_ixs(ixs);
}

} else if !path.contains(&dst_mint_idx) {
// ... search deeper
// ... search deeper
self.brute_force_search(
start_mint_idx,
init_balance,
new_balance, // !
new_path, // !
new_balance, // !
new_path, // !
new_pool_path, // !
sent_arbs,
);
}
}
}
}
}

Expand All @@ -149,61 +137,55 @@ impl Arbitrager<'_> {
) -> Vec<Instruction> {
// gather swap ixs
let mut ixs = vec![];
let (swap_state_pda, _) = Pubkey::find_program_address(
&[b"swap_state"], &self.program.id());
let (swap_state_pda, _) =
Pubkey::find_program_address(&[b"swap_state"], &self.program.id());

let src_mint = self.token_mints[mint_idxs[0]];
let src_ata = derive_token_address(
&self.owner.pubkey(),
&src_mint
);
let src_ata = derive_token_address(&self.owner.pubkey(), &src_mint);

// initialize swap ix
let ix = self.program
// initialize swap ix
let ix = self
.program
.request()
.accounts(tmp_accounts::TokenAndSwapState {
src: src_ata,
swap_state: swap_state_pda,
})
.args(tmp_ix::StartSwap {
swap_input: swap_start_amount as u64
}).instructions().unwrap();
swap_input: swap_start_amount as u64,
})
.instructions()
.unwrap();
ixs.push(ix);

for i in 0..mint_idxs.len()-1 {
let [mint_idx0, mint_idx1] = [mint_idxs[i], mint_idxs[i+1]];
for i in 0..mint_idxs.len() - 1 {
let [mint_idx0, mint_idx1] = [mint_idxs[i], mint_idxs[i + 1]];
let [mint0, mint1] = [self.token_mints[mint_idx0], self.token_mints[mint_idx1]];
let pool = &pools[i];

let swap_ix = pool.swap_ix(
&self.program,
&self.owner.pubkey(),
&mint0,
&mint1,
);

let swap_ix = pool.swap_ix(&self.program, &self.owner.pubkey(), &mint0, &mint1);
ixs.push(swap_ix);
}

// PROFIT OR REVERT instruction
let ix = self.program
// PROFIT OR REVERT instruction
let ix = self
.program
.request()
.accounts(tmp_accounts::TokenAndSwapState {
src: src_ata,
swap_state: swap_state_pda
src: src_ata,
swap_state: swap_state_pda,
})
.args(tmp_ix::ProfitOrRevert {})
.instructions().unwrap();
.instructions()
.unwrap();
ixs.push(ix);

let ixs = ixs.concat(); // flatten to Vec<Instructions>
return ixs
// flatten to Vec<Instructions>
ixs.concat()
}

fn send_ixs(
&self,
ixs: Vec<Instruction>,
) {
let owner: &Keypair = self.owner.borrow();
fn send_ixs(&self, ixs: Vec<Instruction>) {
let owner: &Keypair = self.owner.borrow();
let tx = Transaction::new_signed_with_payer(
&ixs,
Some(&owner.pubkey()),
Expand All @@ -214,17 +196,18 @@ impl Arbitrager<'_> {
if self.cluster == Cluster::Localnet {
let res = self.connection.simulate_transaction(&tx).unwrap();
println!("{:#?}", res);

} else if self.cluster == Cluster::Mainnet {
let signature = self.connection.send_transaction_with_config(
&tx,
RpcSendTransactionConfig {
skip_preflight: true,
..RpcSendTransactionConfig::default()
},
).unwrap();
let signature = self
.connection
.send_transaction_with_config(
&tx,
RpcSendTransactionConfig {
skip_preflight: true,
..RpcSendTransactionConfig::default()
},
)
.unwrap();
println!("signature: {:?}", signature);
}
}

}
}
Loading

0 comments on commit 4279b25

Please sign in to comment.