Surface transaction logs in rpc client
This commit is contained in:
parent
04c5e6cc48
commit
6d9ca0ae15
|
@ -1618,9 +1618,9 @@ pub(crate) fn fetch_epoch_rewards(
|
||||||
kind:
|
kind:
|
||||||
ClientErrorKind::RpcError(rpc_request::RpcError::RpcResponseError {
|
ClientErrorKind::RpcError(rpc_request::RpcError::RpcResponseError {
|
||||||
code: rpc_custom_error::JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE,
|
code: rpc_custom_error::JSON_RPC_SERVER_ERROR_BLOCK_NOT_AVAILABLE,
|
||||||
message: _,
|
..
|
||||||
}),
|
}),
|
||||||
request: _,
|
..
|
||||||
}) => {
|
}) => {
|
||||||
// RPC node doesn't have this block
|
// RPC node doesn't have this block
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
client_error::Result,
|
client_error::Result,
|
||||||
rpc_request::{RpcError, RpcRequest},
|
rpc_custom_error,
|
||||||
|
rpc_request::{RpcError, RpcRequest, RpcResponseErrorData},
|
||||||
|
rpc_response::RpcSimulateTransactionResult,
|
||||||
rpc_sender::RpcSender,
|
rpc_sender::RpcSender,
|
||||||
};
|
};
|
||||||
use log::*;
|
use log::*;
|
||||||
|
@ -31,7 +33,7 @@ impl HttpSender {
|
||||||
struct RpcErrorObject {
|
struct RpcErrorObject {
|
||||||
code: i64,
|
code: i64,
|
||||||
message: String,
|
message: String,
|
||||||
/*data field omitted*/
|
data: serde_json::Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RpcSender for HttpSender {
|
impl RpcSender for HttpSender {
|
||||||
|
@ -72,11 +74,27 @@ impl RpcSender for HttpSender {
|
||||||
if json["error"].is_object() {
|
if json["error"].is_object() {
|
||||||
return match serde_json::from_value::<RpcErrorObject>(json["error"].clone())
|
return match serde_json::from_value::<RpcErrorObject>(json["error"].clone())
|
||||||
{
|
{
|
||||||
Ok(rpc_error_object) => Err(RpcError::RpcResponseError {
|
Ok(rpc_error_object) => {
|
||||||
|
let data = match rpc_error_object.code {
|
||||||
|
rpc_custom_error::JSON_RPC_SERVER_ERROR_SEND_TRANSACTION_PREFLIGHT_FAILURE => {
|
||||||
|
match serde_json::from_value::<RpcSimulateTransactionResult>(json["error"]["data"].clone()) {
|
||||||
|
Ok(data) => RpcResponseErrorData::SendTransactionPreflightFailure(data),
|
||||||
|
Err(err) => {
|
||||||
|
debug!("Failed to deserialize RpcSimulateTransactionResult: {:?}", err);
|
||||||
|
RpcResponseErrorData::Empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => RpcResponseErrorData::Empty
|
||||||
|
};
|
||||||
|
|
||||||
|
Err(RpcError::RpcResponseError {
|
||||||
code: rpc_error_object.code,
|
code: rpc_error_object.code,
|
||||||
message: rpc_error_object.message,
|
message: rpc_error_object.message,
|
||||||
|
data,
|
||||||
|
}
|
||||||
|
.into())
|
||||||
}
|
}
|
||||||
.into()),
|
|
||||||
Err(err) => Err(RpcError::RpcRequestError(format!(
|
Err(err) => Err(RpcError::RpcRequestError(format!(
|
||||||
"Failed to deserialize RPC error response: {} [{}]",
|
"Failed to deserialize RPC error response: {} [{}]",
|
||||||
serde_json::to_string(&json["error"]).unwrap(),
|
serde_json::to_string(&json["error"]).unwrap(),
|
||||||
|
|
|
@ -8,7 +8,7 @@ use crate::{
|
||||||
RpcProgramAccountsConfig, RpcSendTransactionConfig, RpcSimulateTransactionConfig,
|
RpcProgramAccountsConfig, RpcSendTransactionConfig, RpcSimulateTransactionConfig,
|
||||||
RpcTokenAccountsFilter,
|
RpcTokenAccountsFilter,
|
||||||
},
|
},
|
||||||
rpc_request::{RpcError, RpcRequest, TokenAccountsFilter},
|
rpc_request::{RpcError, RpcRequest, RpcResponseErrorData, TokenAccountsFilter},
|
||||||
rpc_response::*,
|
rpc_response::*,
|
||||||
rpc_sender::RpcSender,
|
rpc_sender::RpcSender,
|
||||||
};
|
};
|
||||||
|
@ -171,10 +171,33 @@ impl RpcClient {
|
||||||
..config
|
..config
|
||||||
};
|
};
|
||||||
let serialized_encoded = serialize_encode_transaction(transaction, encoding)?;
|
let serialized_encoded = serialize_encode_transaction(transaction, encoding)?;
|
||||||
let signature_base58_str: String = self.send(
|
let signature_base58_str: String = match self.send(
|
||||||
RpcRequest::SendTransaction,
|
RpcRequest::SendTransaction,
|
||||||
json!([serialized_encoded, config]),
|
json!([serialized_encoded, config]),
|
||||||
)?;
|
) {
|
||||||
|
Ok(signature_base58_str) => signature_base58_str,
|
||||||
|
Err(err) => {
|
||||||
|
if let ClientErrorKind::RpcError(RpcError::RpcResponseError {
|
||||||
|
code,
|
||||||
|
message,
|
||||||
|
data,
|
||||||
|
}) = &err.kind
|
||||||
|
{
|
||||||
|
debug!("{} {}", code, message);
|
||||||
|
if let RpcResponseErrorData::SendTransactionPreflightFailure(
|
||||||
|
RpcSimulateTransactionResult {
|
||||||
|
logs: Some(logs), ..
|
||||||
|
},
|
||||||
|
) = data
|
||||||
|
{
|
||||||
|
for (i, log) in logs.iter().enumerate() {
|
||||||
|
debug!("{:>3}: {}", i + 1, log);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let signature = signature_base58_str
|
let signature = signature_base58_str
|
||||||
.parse::<Signature>()
|
.parse::<Signature>()
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use crate::rpc_response::RpcSimulateTransactionResult;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -138,12 +139,38 @@ impl RpcRequest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum RpcResponseErrorData {
|
||||||
|
Empty,
|
||||||
|
SendTransactionPreflightFailure(RpcSimulateTransactionResult),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for RpcResponseErrorData {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
RpcResponseErrorData::SendTransactionPreflightFailure(
|
||||||
|
RpcSimulateTransactionResult {
|
||||||
|
logs: Some(logs), ..
|
||||||
|
},
|
||||||
|
) => {
|
||||||
|
// Give the user a hint that there is more useful logging information available...
|
||||||
|
write!(f, "{} log messages", logs.len())
|
||||||
|
}
|
||||||
|
_ => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum RpcError {
|
pub enum RpcError {
|
||||||
#[error("RPC request error: {0}")]
|
#[error("RPC request error: {0}")]
|
||||||
RpcRequestError(String),
|
RpcRequestError(String),
|
||||||
#[error("RPC response error {code}: {message}")]
|
#[error("RPC response error {code}: {message} [{data}]")]
|
||||||
RpcResponseError { code: i64, message: String },
|
RpcResponseError {
|
||||||
|
code: i64,
|
||||||
|
message: String,
|
||||||
|
data: RpcResponseErrorData,
|
||||||
|
},
|
||||||
#[error("parse error: expected {0}")]
|
#[error("parse error: expected {0}")]
|
||||||
ParseError(String), /* "expected" */
|
ParseError(String), /* "expected" */
|
||||||
// Anything in a `ForUser` needs to die. The caller should be
|
// Anything in a `ForUser` needs to die. The caller should be
|
||||||
|
|
Loading…
Reference in New Issue