Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

token 2022 support for router #44

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
2 changes: 2 additions & 0 deletions bin/autobahn-router/src/debug_tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ pub fn name(mint: &Pubkey) -> String {
"BOME".to_string()
} else if m == "3S8qX1MsMqRbiwKg2cQyx7nis1oHMgaCuc9c4VfvVdPN" {
"MOTHER".to_string()
} else if m == "AKEWE7Bgh87GPp171b4cJPSSZfmZwQ3KaqYqXoKLNAEE" {
"USDC (hyperlane)".to_string()
} else {
m
}
Expand Down
42 changes: 34 additions & 8 deletions bin/autobahn-router/src/ix_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
use crate::swap::Swap;
use anchor_lang::Id;
use anchor_spl::associated_token::get_associated_token_address;
use anchor_spl::token::Token;
use anchor_spl::token::{spl_token, Token};
use anchor_spl::token_2022::spl_token_2022;
use autobahn_executor::swap_ix::generate_swap_ix_data;
use router_lib::dex::{AccountProviderView, SwapInstruction, SwapMode};
use router_lib::dex::{AccountProvider, AccountProviderView, SwapInstruction, SwapMode};
use solana_program::instruction::Instruction;
use solana_program::pubkey::Pubkey;
use solana_sdk::account::ReadableAccount;
use std::str::FromStr;
use std::sync::Arc;

const CU_PER_HOP_DEFAULT: u32 = 80_000;
const CU_BASE: u32 = 150_000;
Expand All @@ -26,6 +29,7 @@
pub trait SwapInstructionsBuilder {
fn build_ixs(
&self,
live_account_provider: Arc<dyn AccountProvider>,
wallet_pk: &Pubkey,
route: &Route,
wrap_and_unwrap_sol: bool,
Expand Down Expand Up @@ -81,6 +85,7 @@
impl<T: SwapStepInstructionBuilder> SwapInstructionsBuilder for SwapInstructionsBuilderImpl<T> {
fn build_ixs(
&self,
live_account_provider: Arc<dyn AccountProvider>,
wallet_pk: &Pubkey,
route: &Route,
auto_wrap_sol: bool,
Expand All @@ -101,7 +106,7 @@
Pubkey::from_str("So11111111111111111111111111111111111111112").unwrap();

if auto_wrap_sol && route.input_mint == sol_mint {
Self::create_ata(&wallet_pk, &mut setup_instructions, &sol_mint);
Self::create_ata(&wallet_pk, &mut setup_instructions, &sol_mint, false);
let wsol_account = get_associated_token_address(wallet_pk, &sol_mint);

let in_amount = match swap_mode {
Expand Down Expand Up @@ -145,13 +150,25 @@

for step in &swap_instructions {
if auto_create_out || (step.out_mint == sol_mint && auto_wrap_sol) {
Self::create_ata(&wallet_pk, &mut setup_instructions, &step.out_mint);
// wrapped SOL is always legacy token not 2022
let out_is_token_2022 = (step.out_mint != sol_mint)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could have a list of well-known hardcoded spl_token instead of "step.out_mint != sol_mint"

&& spl_token_2022::ID.eq(live_account_provider
.account(&step.out_mint)?
.account
.owner());
Self::create_ata(
wallet_pk,
&mut setup_instructions,
&step.out_mint,
out_is_token_2022,
);

cu_estimate += 12_000;
}

if step.out_mint == sol_mint && auto_wrap_sol {
let wsol_account = get_associated_token_address(wallet_pk, &sol_mint);
Self::close_wsol_ata(&wallet_pk, &mut cleanup_instructions, &wsol_account)?;
Self::close_wsol_ata(wallet_pk, &mut cleanup_instructions, &wsol_account)?;
cu_estimate += 12_000;
}

Expand Down Expand Up @@ -190,7 +207,7 @@

impl<T: SwapStepInstructionBuilder> SwapInstructionsBuilderImpl<T> {
fn close_wsol_ata(
wallet_pk: &&Pubkey,
wallet_pk: &Pubkey,
cleanup_instructions: &mut Vec<Instruction>,
wsol_account: &Pubkey,
) -> anyhow::Result<()> {
Expand All @@ -204,13 +221,22 @@
Ok(())
}

fn create_ata(wallet_pk: &&Pubkey, setup_instructions: &mut Vec<Instruction>, mint: &Pubkey) {
fn create_ata(
wallet_pk: &Pubkey,
setup_instructions: &mut Vec<Instruction>,
mint: &Pubkey,
token_program_is_2022: bool,
) {
setup_instructions.push(
spl_associated_token_account::instruction::create_associated_token_account_idempotent(
&wallet_pk,
&wallet_pk,
&mint,
&Token::id(),
if token_program_is_2022 {
&spl_token_2022::ID
} else {
&spl_token::ID
},
),
);
}
Expand Down Expand Up @@ -361,7 +387,7 @@
let builder = SwapInstructionsBuilderImpl::new(MockSwapStepInstructionBuilder {}, 0);
let wallet = 0.to_pubkey();

let ixs = builder.build_ixs(

Check failure on line 390 in bin/autobahn-router/src/ix_builder.rs

View workflow job for this annotation

GitHub Actions / Router full build

this method takes 8 arguments but 7 arguments were supplied

Check failure on line 390 in bin/autobahn-router/src/ix_builder.rs

View workflow job for this annotation

GitHub Actions / Router full build

this method takes 8 arguments but 7 arguments were supplied
&wallet,
&Route {
input_mint: 1.to_pubkey(),
Expand All @@ -388,7 +414,7 @@
let builder = SwapInstructionsBuilderImpl::new(MockSwapStepInstructionBuilder {}, 0);
let wallet = 0.to_pubkey();

let ixs = builder.build_ixs(

Check failure on line 417 in bin/autobahn-router/src/ix_builder.rs

View workflow job for this annotation

GitHub Actions / Router full build

this method takes 8 arguments but 7 arguments were supplied

Check failure on line 417 in bin/autobahn-router/src/ix_builder.rs

View workflow job for this annotation

GitHub Actions / Router full build

this method takes 8 arguments but 7 arguments were supplied
&wallet,
&Route {
input_mint: 1.to_pubkey(),
Expand Down Expand Up @@ -437,7 +463,7 @@
};

let ixs = builder
.build_ixs(

Check failure on line 466 in bin/autobahn-router/src/ix_builder.rs

View workflow job for this annotation

GitHub Actions / Router full build

this method takes 8 arguments but 7 arguments were supplied

Check failure on line 466 in bin/autobahn-router/src/ix_builder.rs

View workflow job for this annotation

GitHub Actions / Router full build

this method takes 8 arguments but 7 arguments were supplied
&wallet,
&Route {
input_mint: in_mint,
Expand Down Expand Up @@ -480,7 +506,7 @@
let wallet = 0.to_pubkey();

let ixs = builder
.build_ixs(

Check failure on line 509 in bin/autobahn-router/src/ix_builder.rs

View workflow job for this annotation

GitHub Actions / Router full build

this method takes 8 arguments but 7 arguments were supplied

Check failure on line 509 in bin/autobahn-router/src/ix_builder.rs

View workflow job for this annotation

GitHub Actions / Router full build

this method takes 8 arguments but 7 arguments were supplied
&wallet,
&Route {
input_mint: 1.to_pubkey(),
Expand Down Expand Up @@ -523,7 +549,7 @@
let wallet = 0.to_pubkey();

let ixs = builder
.build_ixs(

Check failure on line 552 in bin/autobahn-router/src/ix_builder.rs

View workflow job for this annotation

GitHub Actions / Router full build

this method takes 8 arguments but 7 arguments were supplied

Check failure on line 552 in bin/autobahn-router/src/ix_builder.rs

View workflow job for this annotation

GitHub Actions / Router full build

this method takes 8 arguments but 7 arguments were supplied
&wallet,
&Route {
input_mint: 1.to_pubkey(),
Expand Down
12 changes: 11 additions & 1 deletion bin/autobahn-router/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,8 +302,8 @@ async fn main() -> anyhow::Result<()> {
dex_invariant::InvariantDex::initialize(&mut router_rpc, HashMap::new()).await?,
&mango_data,
config.invariant.enabled,
config.invariant.take_all_mints,
config.invariant.add_mango_tokens,
config.invariant.take_all_mints,
&config.invariant.mints
),
]
Expand Down Expand Up @@ -440,6 +440,15 @@ async fn main() -> anyhow::Result<()> {
)
.collect::<HashSet<_>>();

// collect all mints traded so their token program owner can be checked
let mut mints = HashSet::new();
for d in dexs.iter() {
for e in d.edges_per_pk.values().flatten() {
mints.insert(e.input_mint);
mints.insert(e.output_mint);
}
}

debug_tools::set_global_filters(&filters);

info!(
Expand All @@ -455,6 +464,7 @@ async fn main() -> anyhow::Result<()> {
DexSubscriptionMode::Mixed(m) => m.accounts.clone().into_iter(),
DexSubscriptionMode::Disabled => HashSet::new().into_iter(),
})
.chain(mints.into_iter())
.collect();

let subscribed_programs = dexs
Expand Down
2 changes: 2 additions & 0 deletions bin/autobahn-router/src/path_warmer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ where
};

let sol_mint = Pubkey::from_str("So11111111111111111111111111111111111111112").unwrap();
let usdc_mint = Pubkey::from_str("AKEWE7Bgh87GPp171b4cJPSSZfmZwQ3KaqYqXoKLNAEE").unwrap();
let config = config.clone();
let start = Instant::now();
let job = tokio::spawn(async move {
Expand All @@ -83,6 +84,7 @@ where

let mut all_mints = token_cache.tokens();
all_mints.insert(sol_mint);
all_mints.insert(usdc_mint);

let hot_mints = hot_mints_cache.read().unwrap().get();
let mints = match generate_mints(
Expand Down
9 changes: 5 additions & 4 deletions bin/autobahn-router/src/routing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -778,10 +778,11 @@ impl Routing {
price_impact,
);

if price_impact > 0.25 {
skipped_bad_price_impact += 1;
continue;
}
// TODO: make this a config variable for reach network
// if price_impact > 0.25 {
// skipped_bad_price_impact += 1;
// continue;
// }

match swap_mode {
SwapMode::ExactIn => {
Expand Down
15 changes: 12 additions & 3 deletions bin/autobahn-router/src/server/http_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ impl HttpServer {
address_lookup_table_addresses.clone(),
hash_provider.clone(),
alt_provider.clone(),
live_account_provider.clone(),
ix_builder.clone(),
&route_candidate,
Pubkey::new_unique().to_string(),
Expand Down Expand Up @@ -199,7 +200,7 @@ impl HttpServer {

let route: Route = route?;

Self::log_repriced_amount(live_account_provider, reprice_probability, &route);
Self::log_repriced_amount(live_account_provider.clone(), reprice_probability, &route);

let other_amount_threshold = if swap_mode == SwapMode::ExactOut {
(route.in_amount as f64 * (10_000f64 + input.slippage_bps as f64) / 10_000f64).floor()
Expand Down Expand Up @@ -279,7 +280,7 @@ impl HttpServer {
) -> Result<Json<Value>, AppError> {
let route = route_provider.try_from(&input.quote_response)?;

Self::log_repriced_amount(live_account_provider, reprice_probability, &route);
Self::log_repriced_amount(live_account_provider.clone(), reprice_probability, &route);

let swap_mode: SwapMode = SwapMode::from_str(&input.quote_response.swap_mode)
.map_err(|_| anyhow::Error::msg("Invalid SwapMode"))?;
Expand All @@ -293,6 +294,7 @@ impl HttpServer {
address_lookup_table_addresses,
hash_provider,
alt_provider,
live_account_provider,
ix_builder,
&route,
input.user_public_key,
Expand Down Expand Up @@ -352,10 +354,12 @@ impl HttpServer {
THashProvider: HashProvider + Send + Sync + 'static,
TAltProvider: AltProvider + Send + Sync + 'static,
TIxBuilder: SwapInstructionsBuilder + Send + Sync + 'static,
TAccountProvider: AccountProvider + Send + Sync + 'static,
>(
address_lookup_table_addresses: Vec<String>,
hash_provider: Arc<THashProvider>,
alt_provider: Arc<TAltProvider>,
live_account_provider: Arc<TAccountProvider>,
ix_builder: Arc<TIxBuilder>,
route_plan: &Route,
wallet_pk: String,
Expand All @@ -369,6 +373,7 @@ impl HttpServer {
let wallet_pk = Pubkey::from_str(&wallet_pk)?;

let ixs = ix_builder.build_ixs(
live_account_provider,
&wallet_pk,
route_plan,
wrap_unwrap_sol,
Expand Down Expand Up @@ -413,11 +418,13 @@ impl HttpServer {
async fn swap_ix_handler<
TRouteProvider: RouteProvider + Send + Sync + 'static,
TAltProvider: AltProvider + Send + Sync + 'static,
TAccountProvider: AccountProvider + Send + Sync + 'static,
TIxBuilder: SwapInstructionsBuilder + Send + Sync + 'static,
>(
address_lookup_table_addresses: Vec<String>,
route_provider: Arc<TRouteProvider>,
alt_provider: Arc<TAltProvider>,
live_account_provider: Arc<TAccountProvider>,
ix_builder: Arc<TIxBuilder>,
Query(_query): Query<SwapForm>,
Json(input): Json<SwapRequest>,
Expand All @@ -434,6 +441,7 @@ impl HttpServer {
};

let ixs = ix_builder.build_ixs(
live_account_provider,
&wallet_pk,
&route_plan,
input.wrap_and_unwrap_sol,
Expand Down Expand Up @@ -628,6 +636,7 @@ impl HttpServer {
let alt = address_lookup_tables.clone();
let rp = route_provider.clone();
let altp = alt_provider.clone();
let lap = live_account_provider.clone();
let ixb = ix_builder.clone();
router = router.route(
"/swap-instructions",
Expand All @@ -637,7 +646,7 @@ impl HttpServer {
.with_label_values(&["swap-ix", client_key])
.start_timer();

let response = Self::swap_ix_handler(alt, rp, altp, ixb, query, form).await;
let response = Self::swap_ix_handler(alt, rp, altp, lap, ixb, query, form).await;

match response {
Ok(_) => {
Expand Down
8 changes: 5 additions & 3 deletions bin/autobahn-router/src/source/grpc_plugin_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,9 +762,11 @@ async fn process_account_updated_from_sources(
metrics::GRPC_SNAPSHOT_ACCOUNT_WRITES.inc();
metrics::GRPC_ACCOUNT_WRITE_QUEUE.set(account_write_queue_sender.len() as i64);

if !filters.contains(&account.pubkey) {
continue;
}
// TODO: disabled for eclipse launch, was causing issues with the program id
// subscription for invariant

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

guess we cannot merge that without breaking autobahn on solana

// if !filters.contains(&account.pubkey) {
// continue;
// }

updated_accounts.push(account);
}
Expand Down
30 changes: 19 additions & 11 deletions bin/autobahn-router/src/source/mint_accounts_source.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use anchor_lang::AccountDeserialize;
use anchor_spl::token::Mint;
use anchor_spl::token::{spl_token, Mint};
use anchor_spl::token_2022::spl_token_2022;
use anchor_spl::token_2022::spl_token_2022::extension::StateWithExtensions;
use futures_util::future::join_all;
use itertools::Itertools;
use jsonrpc_core_client::transports::http;
use router_feed_lib::solana_rpc_minimal::rpc_accounts_scan::RpcAccountsScanClient;
use solana_account_decoder::UiAccountEncoding;
use solana_client::rpc_config::RpcAccountInfoConfig;
use solana_program::pubkey::Pubkey;
use solana_sdk::account::Account;
use solana_sdk::account::{Account, ReadableAccount};
use solana_sdk::commitment_config::CommitmentConfig;
use solana_sdk::program_pack::Pack;
use std::collections::{HashMap, HashSet};
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
Expand Down Expand Up @@ -43,7 +46,7 @@ pub async fn request_mint_metadata(
.unwrap();
let rpc_client = Arc::new(rpc_client);
let account_info_config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Binary),
encoding: Some(UiAccountEncoding::Base64),
commitment: Some(CommitmentConfig::finalized()),
data_slice: None,
min_context_slot: None,
Expand Down Expand Up @@ -71,18 +74,23 @@ pub async fn request_mint_metadata(
for (account_pk, ui_account) in accounts {
if let Some(ui_account) = ui_account {
let mut account: Account = ui_account.decode().unwrap();
let data = account.data.as_mut_slice();
let mint_account = Mint::try_deserialize(&mut &*data).unwrap();
trace!(
"Mint Account {}: decimals={}",
account_pk.to_string(),
mint_account.decimals
);

let decimals = match account.owner {
spl_token::ID => {
let mint = spl_token::state::Mint::unpack(account.data()).unwrap();
mint.decimals
},
spl_token_2022::ID => {
let mint = StateWithExtensions::<spl_token_2022::state::Mint>::unpack(&account.data()).unwrap();
mint.base.decimals
}
_ => panic!("could not parse mint {:?}", account_pk)
};
mint_accounts.insert(
account_pk,
Token {
mint: account_pk,
decimals: mint_account.decimals,
decimals,
},
);
count.fetch_add(1, Ordering::Relaxed);
Expand Down
11 changes: 6 additions & 5 deletions bin/autobahn-router/template-config-eclipse.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,11 @@ add_mango_tokens = false

[routing]
path_cache_validity_ms = 30000
path_warming_mode = "ConfiguredMints"
#path_warming_mode = "HotMints"
path_warming_amounts = [100, 1000, 10_000]
path_warming_mode = "All"
path_warming_amounts = [1, 3, 10]
path_warming_for_mints = [
"So11111111111111111111111111111111111111112", # SOL
"So11111111111111111111111111111111111111112", # ETH
"AKEWE7Bgh87GPp171b4cJPSSZfmZwQ3KaqYqXoKLNAEE", # USDC
]
path_warming_interval_secs = 5
path_warming_max_accounts = [20, 30, 40, 64]
Expand Down Expand Up @@ -95,7 +95,8 @@ min_quote_out_to_in_amount_ratio = 0.65

[hot_mints]
always_hot_mints = [
"So11111111111111111111111111111111111111112", # SOL
"So11111111111111111111111111111111111111112", # ETH
"AKEWE7Bgh87GPp171b4cJPSSZfmZwQ3KaqYqXoKLNAEE", # USDC
]
keep_latest_count = 50

Expand Down
2 changes: 1 addition & 1 deletion lib/dex-invariant/src/internal/swap.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use invariant_types::{
decimals::{CheckedOps, Decimal, Price, TokenAmount},

Check warning on line 2 in lib/dex-invariant/src/internal/swap.rs

View workflow job for this annotation

GitHub Actions / Router full build

unused imports: `Decimal`, `TICKS_BACK_COUNT`, `TokenAmount`, `compute_swap_step`, `cross_tick`, `get_closer_limit`, `get_max_sqrt_price`, `get_max_tick`, `get_min_sqrt_price`, `get_min_tick`, `is_enough_amount_to_push_price`, `log::get_tick_at_sqrt_price`
log::get_tick_at_sqrt_price,
math::{
compute_swap_step, cross_tick, get_closer_limit, get_max_sqrt_price, get_max_tick,
Expand All @@ -16,7 +16,7 @@
pub sqrt_price_limit: Price,
}

#[derive(Clone, Default)]
#[derive(Clone, Default, Debug)]
pub struct InvariantSwapResult {
pub in_amount: u64,
pub out_amount: u64,
Expand Down
4 changes: 4 additions & 0 deletions lib/router-lib/src/price_feeds/birdeye.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,15 @@

impl BirdeyePriceFeed {
pub async fn refresh(
api_token: String,

Check warning on line 85 in lib/router-lib/src/price_feeds/birdeye.rs

View workflow job for this annotation

GitHub Actions / Router full build

unused variable: `api_token`

Check warning on line 85 in lib/router-lib/src/price_feeds/birdeye.rs

View workflow job for this annotation

GitHub Actions / Router full build

unused variable: `api_token`
mints: &HashSet<Pubkey>,

Check warning on line 86 in lib/router-lib/src/price_feeds/birdeye.rs

View workflow job for this annotation

GitHub Actions / Router full build

unused variable: `mints`

Check warning on line 86 in lib/router-lib/src/price_feeds/birdeye.rs

View workflow job for this annotation

GitHub Actions / Router full build

unused variable: `mints`
sender: broadcast::Sender<PriceUpdate>,

Check warning on line 87 in lib/router-lib/src/price_feeds/birdeye.rs

View workflow job for this annotation

GitHub Actions / Router full build

unused variable: `sender`

Check warning on line 87 in lib/router-lib/src/price_feeds/birdeye.rs

View workflow job for this annotation

GitHub Actions / Router full build

unused variable: `sender`
) -> anyhow::Result<()> {

// TODO: disabled for eclipse launch until traffic is live

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be a config param

return Ok(());

let http_client = reqwest::Client::new();

Check warning on line 93 in lib/router-lib/src/price_feeds/birdeye.rs

View workflow job for this annotation

GitHub Actions / Router full build

unreachable statement

Check warning on line 93 in lib/router-lib/src/price_feeds/birdeye.rs

View workflow job for this annotation

GitHub Actions / Router full build

unreachable statement

let mut chunks: Vec<Vec<Pubkey>> = vec![];
for chunk in &mints.iter().chunks(50) {
Expand Down
Loading
Loading