Skip to content

Commit

Permalink
--send-url now accepts multiple urls to improve odds of transaction i…
Browse files Browse the repository at this point in the history
…nclusion. don't hate the player
  • Loading branch information
mvines committed Jun 6, 2024
1 parent f8da630 commit 0eed4c0
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 51 deletions.
17 changes: 9 additions & 8 deletions src/bin/sys-lend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use {
},
std::collections::{BTreeMap, HashMap, HashSet},
sys::{
app_version, metrics,
metrics,
notifier::*,
priority_fee::{apply_priority_fee, PriorityFee},
send_transaction_until_expired,
Expand All @@ -35,7 +35,7 @@ use {
kamino, marginfi_v2,
solend::{self, math::TryMul},
},
RpcClients,
*,
},
};

Expand Down Expand Up @@ -197,13 +197,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.help("JSON RPC URL for the cluster"),
)
.arg(
Arg::with_name("send_json_rpc_url")
Arg::with_name("send_json_rpc_urls")
.long("send-url")
.value_name("URL")
.takes_value(true)
.validator(is_url_or_moniker)
.help("Optional addition JSON RPC URL for the cluster to be used only \
for submitting transactions [default: same as --url]"),
.validator(is_comma_separated_url_or_moniker_list)
.help("Optional additional JSON RPC URLs, separated by commas, to \
submit transactions with in addition to --url"),

)
.arg(
Arg::with_name("priority_fee_exact")
Expand Down Expand Up @@ -452,9 +453,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

let rpc_clients = RpcClients::new(
value_t_or_exit!(app_matches, "json_rpc_url", String),
value_t!(app_matches, "send_json_rpc_url", String).ok(),
value_t!(app_matches, "send_json_rpc_urls", String).ok(),
);
let rpc_client = &rpc_clients.default;
let rpc_client = rpc_clients.default();

let priority_fee = if let Ok(ui_priority_fee) = value_t!(app_matches, "priority_fee_exact", f64)
{
Expand Down
72 changes: 48 additions & 24 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,29 +34,47 @@ pub fn app_version() -> String {
})
}

pub struct RpcClients {
pub default: RpcClient,
pub fn is_comma_separated_url_or_moniker_list<T>(string: T) -> Result<(), String>
where
T: AsRef<str> + std::fmt::Display,
{
for url_or_moniker in string.to_string().split(',') {
solana_clap_utils::input_validators::is_url_or_moniker(url_or_moniker)?;
}

// Optional `RpcClient` for use only for sending transactions.
// If `None` then the `default` client is used for sending transactions
pub send: Option<RpcClient>,
Ok(())
}

pub struct RpcClients {
clients: Vec<(String, RpcClient)>,
}

impl RpcClients {
pub fn new(json_rpc_url: String, send_json_rpc_url: Option<String>) -> Self {
pub fn new(json_rpc_url: String, send_json_rpc_urls: Option<String>) -> Self {
let mut json_rpc_urls = vec![json_rpc_url];
if let Some(send_json_rpc_urls) = send_json_rpc_urls {
for send_json_rpc_url in send_json_rpc_urls.split(',') {
json_rpc_urls.push(send_json_rpc_url.into());
}
}

Self {
default: RpcClient::new_with_commitment(
normalize_to_url_if_moniker(json_rpc_url),
CommitmentConfig::confirmed(),
),
send: send_json_rpc_url.map(|send_json_rpc_url| {
RpcClient::new_with_commitment(
normalize_to_url_if_moniker(send_json_rpc_url),
CommitmentConfig::confirmed(),
)
}),
clients: json_rpc_urls
.into_iter()
.map(|json_rpc_url| {
let json_rpc_url = normalize_to_url_if_moniker(json_rpc_url);
(
json_rpc_url.clone(),
RpcClient::new_with_commitment(json_rpc_url, CommitmentConfig::confirmed()),
)
})
.collect(),
}
}

pub fn default(&self) -> &RpcClient {
&self.clients[0].1
}
}

// Assumes `transaction` has already been signed and simulated...
Expand All @@ -65,9 +83,6 @@ pub fn send_transaction_until_expired(
transaction: &impl SerializableTransaction,
last_valid_block_height: u64,
) -> bool {
let send_rpc_client = rpc_clients.send.as_ref().unwrap_or(&rpc_clients.default);
let rpc_client = &rpc_clients.default;

let mut last_send_attempt = None;

let config = RpcSendTransactionConfig {
Expand All @@ -82,16 +97,25 @@ pub fn send_transaction_until_expired(
.as_secs()
> 2
{
println!("Sending transaction {}", transaction.get_signature());
if let Err(err) = send_rpc_client.send_transaction_with_config(transaction, config) {
println!("Unable to send transaction: {err:?}");
for (json_rpc_url, rpc_client) in rpc_clients.clients.iter().rev() {
println!(
"Sending transaction {} [{json_rpc_url}]",
transaction.get_signature()
);

if let Err(err) = rpc_client.send_transaction_with_config(transaction, config) {
println!("Unable to send transaction: {err:?}");
}
}
last_send_attempt = Some(Instant::now());
}

sleep(Duration::from_millis(500));

match rpc_client.get_signature_statuses(&[*transaction.get_signature()]) {
match rpc_clients
.default()
.get_signature_statuses(&[*transaction.get_signature()])
{
Ok(rpc_response::Response { context, value }) => {
let confirmation_context_slot = context.slot;
if let Some(ref transaction_status) = value[0] {
Expand All @@ -103,7 +127,7 @@ pub fn send_transaction_until_expired(
}
}
} else {
match rpc_client.get_epoch_info() {
match rpc_clients.default().get_epoch_info() {
Ok(epoch_info) => {
if epoch_info.block_height > last_valid_block_height
&& epoch_info.absolute_slot >= confirmation_context_slot
Expand Down
35 changes: 17 additions & 18 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,14 @@ use {
time::Duration,
},
sys::{
app_version,
exchange::{self, *},
metrics::{self, dp, MetricsConfig},
notifier::*,
priority_fee::{apply_priority_fee, PriorityFee},
send_transaction_until_expired,
token::*,
//tulip,
RpcClients,
*,
},
};

Expand Down Expand Up @@ -442,7 +441,7 @@ async fn process_exchange_deposit<T: Signers>(
lot_numbers: Option<HashSet<usize>>,
priority_fee: PriorityFee,
) -> Result<(), Box<dyn std::error::Error>> {
let rpc_client = &rpc_clients.default;
let rpc_client = rpc_clients.default();

if let Some(if_exchange_balance_less_than) = if_exchange_balance_less_than {
let exchange_balance = exchange_client
Expand Down Expand Up @@ -1036,7 +1035,7 @@ async fn process_jup_swap<T: Signers>(
priority_fee: PriorityFee,
notifier: &Notifier,
) -> Result<(), Box<dyn std::error::Error>> {
let rpc_client = &rpc_clients.default;
let rpc_client = rpc_clients.default();

let from_account = db
.get_account(address, from_token)
Expand Down Expand Up @@ -2959,7 +2958,7 @@ async fn process_account_merge<T: Signers>(
priority_fee: PriorityFee,
existing_signature: Option<Signature>,
) -> Result<(), Box<dyn std::error::Error>> {
let rpc_client = &rpc_clients.default;
let rpc_client = rpc_clients.default();
let token = MaybeToken::SOL(); // TODO: Support merging tokens one day

if let Some(existing_signature) = existing_signature {
Expand Down Expand Up @@ -3086,7 +3085,7 @@ async fn process_account_sweep<T: Signers>(
priority_fee: PriorityFee,
existing_signature: Option<Signature>,
) -> Result<(), Box<dyn std::error::Error>> {
let rpc_client = &rpc_clients.default;
let rpc_client = rpc_clients.default();

let (recent_blockhash, last_valid_block_height) =
rpc_client.get_latest_blockhash_with_commitment(rpc_client.commitment())?;
Expand Down Expand Up @@ -3437,7 +3436,7 @@ async fn process_account_split<T: Signers>(
if_balance_exceeds: Option<f64>,
priority_fee: PriorityFee,
) -> Result<(), Box<dyn std::error::Error>> {
let rpc_client = &rpc_clients.default;
let rpc_client = rpc_clients.default();

// TODO: Support splitting two system accounts? Tokens? Otherwise at least error cleanly when it's attempted
let token = MaybeToken::SOL(); // TODO: Support splitting tokens one day
Expand Down Expand Up @@ -3574,7 +3573,7 @@ async fn process_account_redelegate<T: Signers>(
signers: &T,
into_keypair: Option<Keypair>,
) -> Result<(), Box<dyn std::error::Error>> {
let rpc_client = &rpc_clients.default;
let rpc_client = rpc_clients.default();
let (recent_blockhash, last_valid_block_height) =
rpc_client.get_latest_blockhash_with_commitment(rpc_client.commitment())?;

Expand Down Expand Up @@ -3680,7 +3679,7 @@ async fn process_account_sync(
force_rescan_balances: bool,
notifier: &Notifier,
) -> Result<(), Box<dyn std::error::Error>> {
let rpc_client = &rpc_clients.default;
let rpc_client = rpc_clients.default();
process_account_sync_pending_transfers(db, rpc_client).await?;
process_account_sync_sweep(db, rpc_clients, notifier).await?;

Expand Down Expand Up @@ -3914,7 +3913,7 @@ async fn process_account_wrap<T: Signers>(
signers: T,
priority_fee: PriorityFee,
) -> Result<(), Box<dyn std::error::Error>> {
let rpc_client = &rpc_clients.default;
let rpc_client = rpc_clients.default();
let sol = MaybeToken::SOL();
let wsol = Token::wSOL;
let wsol_address = wsol.ata(&address);
Expand Down Expand Up @@ -4021,7 +4020,7 @@ async fn process_account_unwrap<T: Signers>(
signers: T,
priority_fee: PriorityFee,
) -> Result<(), Box<dyn std::error::Error>> {
let rpc_client = &rpc_clients.default;
let rpc_client = rpc_clients.default();
let sol = MaybeToken::SOL();
let wsol = Token::wSOL;

Expand Down Expand Up @@ -4157,7 +4156,7 @@ async fn process_account_sync_sweep(
rpc_clients: &RpcClients,
_notifier: &Notifier,
) -> Result<(), Box<dyn std::error::Error>> {
let rpc_client = &rpc_clients.default;
let rpc_client = rpc_clients.default();
let token = MaybeToken::SOL();

let transitory_sweep_stake_addresses = db.get_transitory_sweep_stake_addresses();
Expand Down Expand Up @@ -4383,13 +4382,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.help("JSON RPC URL for the cluster"),
)
.arg(
Arg::with_name("send_json_rpc_url")
Arg::with_name("send_json_rpc_urls")
.long("send-url")
.value_name("URL")
.takes_value(true)
.validator(is_url_or_moniker)
.help("Optional addition JSON RPC URL for the cluster to be used only \
for submitting transactions [default: same as --url]"),
.validator(is_comma_separated_url_or_moniker_list)
.help("Optional additional JSON RPC URLs, separated by commas, to \
submit transactions with in addition to --url"),
)
.arg(
Arg::with_name("verbose")
Expand Down Expand Up @@ -5956,10 +5955,10 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

let rpc_clients = RpcClients::new(
value_t_or_exit!(app_matches, "json_rpc_url", String),
value_t!(app_matches, "send_json_rpc_url", String).ok(),
value_t!(app_matches, "send_json_rpc_urls", String).ok(),
);

let rpc_client = &rpc_clients.default;
let rpc_client = rpc_clients.default();

let mut wallet_manager = None;
let notifier = Notifier::default();
Expand Down
2 changes: 1 addition & 1 deletion src/stake_spreader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ pub async fn run<T: Signers>(
signers: T,
notifier: &Notifier,
) -> Result<(), Box<dyn std::error::Error>> {
let rpc_client = &rpc_clients.default;
let rpc_client = rpc_clients.default();
let epoch_info = rpc_client.get_epoch_info()?;
let current_epoch = epoch_info.epoch;

Expand Down

0 comments on commit 0eed4c0

Please sign in to comment.