* refactor(rpc_client): simplfy send and confirm transaction flow
* chore: configurable num of retries for send and confirm
(cherry picked from commit 70234dfdf4
)
Co-authored-by: hrls <viktor.kharitonovich@gmail.com>
This commit is contained in:
@ -1012,41 +1012,48 @@ impl RpcClient {
|
|||||||
&self,
|
&self,
|
||||||
transaction: &Transaction,
|
transaction: &Transaction,
|
||||||
) -> ClientResult<Signature> {
|
) -> ClientResult<Signature> {
|
||||||
|
const SEND_RETRIES: usize = 1;
|
||||||
|
const GET_STATUS_RETRIES: usize = usize::MAX;
|
||||||
|
|
||||||
|
'sending: for _ in 0..SEND_RETRIES {
|
||||||
let signature = self.send_transaction(transaction)?;
|
let signature = self.send_transaction(transaction)?;
|
||||||
|
|
||||||
let recent_blockhash = if uses_durable_nonce(transaction).is_some() {
|
let recent_blockhash = if uses_durable_nonce(transaction).is_some() {
|
||||||
self.get_recent_blockhash_with_commitment(CommitmentConfig::processed())?
|
let (recent_blockhash, ..) = self
|
||||||
.value
|
.get_recent_blockhash_with_commitment(CommitmentConfig::processed())?
|
||||||
.0
|
.value;
|
||||||
|
recent_blockhash
|
||||||
} else {
|
} else {
|
||||||
transaction.message.recent_blockhash
|
transaction.message.recent_blockhash
|
||||||
};
|
};
|
||||||
let status = loop {
|
|
||||||
let status = self.get_signature_status(&signature)?;
|
for status_retry in 0..GET_STATUS_RETRIES {
|
||||||
if status.is_none() {
|
match self.get_signature_status(&signature)? {
|
||||||
if self
|
Some(Ok(_)) => return Ok(signature),
|
||||||
|
Some(Err(e)) => return Err(e.into()),
|
||||||
|
None => {
|
||||||
|
let fee_calculator = self
|
||||||
.get_fee_calculator_for_blockhash_with_commitment(
|
.get_fee_calculator_for_blockhash_with_commitment(
|
||||||
&recent_blockhash,
|
&recent_blockhash,
|
||||||
CommitmentConfig::processed(),
|
CommitmentConfig::processed(),
|
||||||
)?
|
)?
|
||||||
.value
|
.value;
|
||||||
.is_none()
|
if fee_calculator.is_none() {
|
||||||
|
// Block hash is not found by some reason
|
||||||
|
break 'sending;
|
||||||
|
} else if cfg!(not(test))
|
||||||
|
// Ignore sleep at last step.
|
||||||
|
&& status_retry < GET_STATUS_RETRIES
|
||||||
{
|
{
|
||||||
break status;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break status;
|
|
||||||
}
|
|
||||||
if cfg!(not(test)) {
|
|
||||||
// Retry twice a second
|
// Retry twice a second
|
||||||
sleep(Duration::from_millis(500));
|
sleep(Duration::from_millis(500));
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
if let Some(result) = status {
|
|
||||||
match result {
|
|
||||||
Ok(_) => Ok(signature),
|
|
||||||
Err(err) => Err(err.into()),
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Err(RpcError::ForUser(
|
Err(RpcError::ForUser(
|
||||||
"unable to confirm transaction. \
|
"unable to confirm transaction. \
|
||||||
This can happen in situations such as transaction expiration \
|
This can happen in situations such as transaction expiration \
|
||||||
@ -1055,7 +1062,6 @@ impl RpcClient {
|
|||||||
)
|
)
|
||||||
.into())
|
.into())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// Note that `get_account` returns `Err(..)` if the account does not exist whereas
|
/// Note that `get_account` returns `Err(..)` if the account does not exist whereas
|
||||||
/// `get_account_with_commitment` returns `Ok(None)` if the account does not exist.
|
/// `get_account_with_commitment` returns `Ok(None)` if the account does not exist.
|
||||||
|
Reference in New Issue
Block a user