-
Notifications
You must be signed in to change notification settings - Fork 199
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
DX-272: Rust tx-sender crate #820
Conversation
Cargo.toml
Outdated
@@ -1,7 +1,8 @@ | |||
[workspace] | |||
resolver = "2" | |||
members = [ | |||
"programs/*" | |||
"programs/*", | |||
"rust-sdk/tx-sender", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We only added programs/*
to the workspace to avoid version conflicts. Each SDK has their own cargo.lock file and can thus have an independent version of shared dependencies (e.g. solana-program). Can you remove?
rust-sdk/Cargo.toml
Outdated
@@ -0,0 +1,5 @@ | |||
[workspace] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same goes for this one ^
rust-sdk/tx-sender/Cargo.toml
Outdated
edition = "2021" | ||
description = "Solana Transaction Sender for building and sending transactions with priority fees" | ||
repository = "https://github.com/orca-so/whirlpools" | ||
license = "Orca" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think this should match what is in the other cargo.toml files. I think we use license-path
instead
rust-sdk/tx-sender/Cargo.toml
Outdated
description = "Solana Transaction Sender for building and sending transactions with priority fees" | ||
repository = "https://github.com/orca-so/whirlpools" | ||
license = "Orca" | ||
rust-version = "1.70" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless this is a limitation I wouldn't add this one
rust-sdk/tx-sender/Cargo.toml
Outdated
rust-version = "1.70" | ||
|
||
[dependencies] | ||
# Use consistent versions to avoid conflicts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cargo is kinda annoying when it comes to dependencies. Specifying "1.17.22" here will most likely pull in v1.18.x.
On the other hand we want this lib to work with as many versions of solana-program as possible. Specifying "1.17.22" in cargo means >= 1.17.22 and <2.0.0
. We might want this lib to also work with >2.0 like the other libs in the repo.
rust-sdk/tx-sender/src/rpc_config.rs
Outdated
|
||
/// Chain identifier based on genesis hash | ||
#[derive(Debug, Clone, PartialEq, Eq)] | ||
pub struct ChainId(Hash); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to have a enum
instead and implement From<Hash>
for it?
rust-sdk/tx-sender/src/rpc_config.rs
Outdated
} | ||
|
||
/// RPC configuration for connecting to Solana nodes | ||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need Serialize and Deserialize?
rust-sdk/tx-sender/src/rpc_config.rs
Outdated
} | ||
|
||
/// Async constructor with chain ID detection | ||
pub async fn with_chain_detection(url: impl Into<String>) -> Result<Self> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would just only do the async constructor. Is there a scenario where we would want this without a chain_id?
rust-sdk/tx-sender/src/tests.rs
Outdated
@@ -0,0 +1,70 @@ | |||
#[cfg(test)] | |||
mod tests { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this a separate file and not in-file?
rust-sdk/tx-sender/src/tx_config.rs
Outdated
use std::time::Duration; | ||
|
||
/// Transaction configuration for sending transactions | ||
#[derive(Debug, Clone, Serialize, Deserialize)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need Serialize and Deserialize?
rust-sdk/tx-sender/README.md
Outdated
}; | ||
|
||
// Create sender instance | ||
let sender = TransactionSender::new(rpc_config, fee_config); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this still accurate?
|
||
let transaction = Transaction::new_unsigned(message); | ||
// Simulate transaction | ||
let simulation_result = rpc_client.simulate_transaction(&transaction) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this work with an unsigned tx? I thought you had to add a param to disable sig_verify and replace_blockhash. Also can we use VersionedTransaction here?
|
||
|
||
/// Calculate and return compute budget instructions for a transaction | ||
pub async fn add_compute_budget_instructions( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: maybe get_compute_budget_instruction
is more appropriate here
/// - `Option<RpcConfig>` - Must be explicitly set with `set_rpc()` before sending transactions | ||
/// - `Option<Arc<RpcClient>>` - Created when RPC is set, for reuse across transactions | ||
/// - `FeeConfig` - Configured with defaults but can be customized | ||
static GLOBAL_CONFIG: OnceLock<RwLock<GlobalConfig>> = OnceLock::new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need a OnceLock here?
rust-sdk/tx-sender/src/lib.rs
Outdated
); | ||
|
||
// Return unsigned transaction (signing happens at the higher level) | ||
Ok(Transaction::new_unsigned(message)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we do a versioned TX?
rust-sdk/tx-sender/src/lib.rs
Outdated
let expiry_time = Instant::now() + Duration::from_millis(options.timeout_ms); | ||
let mut retries = 0; | ||
|
||
while Instant::now() < expiry_time && retries <= options.max_retries { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am still kinda concerned about the max_retries.
- I think a default of 3 is too low
- After the last retry there is still a fairly decent chance that the transaction lands (but we won't pick picked up potentially because of the
timeout_ms
).
I think it would be safest to add the same logic here as in the TS sdk.
loop until expiry_time:
send TX
see if TX is confirmed
Wait 1s
rust-sdk/tx-sender/src/lib.rs
Outdated
|
||
while Instant::now() < expiry_time && retries <= options.max_retries { | ||
let send_config = RpcSendTransactionConfig { | ||
skip_preflight: options.skip_preflight, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With client retries skip_preflight needs to be always true. Don't think it makes sense to make this configurable by the user.
rust-sdk/tx-sender/src/rpc_config.rs
Outdated
impl From<Hash> for ChainId { | ||
fn from(hash: Hash) -> Self { | ||
// Mainnet genesis hash | ||
let mainnet_hash = Hash::from_str(MAINNET_HASH).unwrap_or_default(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we need to do the from_str
here every time? Can we instead do hash.to_string()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One comment about timeout and retries but other than that lgtm 🚀
rust-sdk/tx-sender/src/config.rs
Outdated
pub const DEFAULT_TRANSACTION_TIMEOUT_MS: u64 = 30_000; | ||
|
||
/// Default number of retries | ||
pub const DEFAULT_RETRIES: usize = 3; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these still being used?
rust-sdk/tx-sender/src/lib.rs
Outdated
return Err(format!("Transaction simulation failed: {}", err)); | ||
} | ||
|
||
let expiry_time = Instant::now() + Duration::from_millis(options.timeout_ms); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think the default for this should be 90 seconds instead of 30 (or just make it not configurable like on TS). The issue with lowering the timeout is that the transaction is valid for the full 90 seconds. This means that if it ends up landing on the final send this function never picks up on it. If you set the timeout to 30 seconds and it 'times-out' you can't definitively say that the transaction did not land
https://linear.app/orca-so/issue/DX-272/build-and-test-crate-with-same-specs-as-ts-package
this still needs some thoughtful review but at least it works with and without fees
jito
exact + dynamic
not as clean as typescript but thats a rust limitation
tests are doing small transfers between orca wallets (can use whatever on devnet)
but you need a locally stored
mainnet-test-keypair.json
(ping me on slack if you need the lightly funded orca pk)