7
Cargo.lock
generated
7
Cargo.lock
generated
@ -2338,6 +2338,8 @@ dependencies = [
|
|||||||
"bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"solana-runtime 0.14.0",
|
"solana-runtime 0.14.0",
|
||||||
@ -2650,6 +2652,8 @@ dependencies = [
|
|||||||
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"hex 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rayon 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -2713,6 +2717,8 @@ version = "0.14.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bincode 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"solana-logger 0.14.0",
|
"solana-logger 0.14.0",
|
||||||
@ -2787,6 +2793,7 @@ dependencies = [
|
|||||||
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"solana 0.14.0",
|
"solana 0.14.0",
|
||||||
"solana-budget-api 0.14.0",
|
"solana-budget-api 0.14.0",
|
||||||
|
50
client/src/client_error.rs
Normal file
50
client/src/client_error.rs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
use crate::rpc_request;
|
||||||
|
use solana_sdk::transaction::TransactionError;
|
||||||
|
use std::{fmt, io};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ClientError {
|
||||||
|
Io(io::Error),
|
||||||
|
Reqwest(reqwest::Error),
|
||||||
|
RpcError(rpc_request::RpcError),
|
||||||
|
SerdeJson(serde_json::error::Error),
|
||||||
|
TransactionError(TransactionError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ClientError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "solana client error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for ClientError {}
|
||||||
|
|
||||||
|
impl From<io::Error> for ClientError {
|
||||||
|
fn from(err: io::Error) -> ClientError {
|
||||||
|
ClientError::Io(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<reqwest::Error> for ClientError {
|
||||||
|
fn from(err: reqwest::Error) -> ClientError {
|
||||||
|
ClientError::Reqwest(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<rpc_request::RpcError> for ClientError {
|
||||||
|
fn from(err: rpc_request::RpcError) -> ClientError {
|
||||||
|
ClientError::RpcError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<serde_json::error::Error> for ClientError {
|
||||||
|
fn from(err: serde_json::error::Error) -> ClientError {
|
||||||
|
ClientError::SerdeJson(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<TransactionError> for ClientError {
|
||||||
|
fn from(err: TransactionError) -> ClientError {
|
||||||
|
ClientError::TransactionError(err)
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::client_error::ClientError;
|
||||||
use crate::rpc_request::RpcRequest;
|
use crate::rpc_request::RpcRequest;
|
||||||
|
|
||||||
pub(crate) trait GenericRpcClientRequest {
|
pub(crate) trait GenericRpcClientRequest {
|
||||||
@ -6,5 +7,5 @@ pub(crate) trait GenericRpcClientRequest {
|
|||||||
request: &RpcRequest,
|
request: &RpcRequest,
|
||||||
params: Option<serde_json::Value>,
|
params: Option<serde_json::Value>,
|
||||||
retries: usize,
|
retries: usize,
|
||||||
) -> Result<serde_json::Value, Box<dyn std::error::Error>>;
|
) -> Result<serde_json::Value, ClientError>;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
pub mod client_error;
|
||||||
mod generic_rpc_client_request;
|
mod generic_rpc_client_request;
|
||||||
pub mod mock_rpc_client_request;
|
pub mod mock_rpc_client_request;
|
||||||
pub mod rpc_client;
|
pub mod rpc_client;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::client_error::ClientError;
|
||||||
use crate::generic_rpc_client_request::GenericRpcClientRequest;
|
use crate::generic_rpc_client_request::GenericRpcClientRequest;
|
||||||
use crate::rpc_request::RpcRequest;
|
use crate::rpc_request::RpcRequest;
|
||||||
use serde_json::{Number, Value};
|
use serde_json::{Number, Value};
|
||||||
@ -23,7 +24,7 @@ impl GenericRpcClientRequest for MockRpcClientRequest {
|
|||||||
request: &RpcRequest,
|
request: &RpcRequest,
|
||||||
params: Option<serde_json::Value>,
|
params: Option<serde_json::Value>,
|
||||||
_retries: usize,
|
_retries: usize,
|
||||||
) -> Result<serde_json::Value, Box<dyn std::error::Error>> {
|
) -> Result<serde_json::Value, ClientError> {
|
||||||
if self.url == "fails" {
|
if self.url == "fails" {
|
||||||
return Ok(Value::Null);
|
return Ok(Value::Null);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::client_error::ClientError;
|
||||||
use crate::generic_rpc_client_request::GenericRpcClientRequest;
|
use crate::generic_rpc_client_request::GenericRpcClientRequest;
|
||||||
use crate::mock_rpc_client_request::MockRpcClientRequest;
|
use crate::mock_rpc_client_request::MockRpcClientRequest;
|
||||||
use crate::rpc_client_request::RpcClientRequest;
|
use crate::rpc_client_request::RpcClientRequest;
|
||||||
@ -46,10 +47,7 @@ impl RpcClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_transaction(
|
pub fn send_transaction(&self, transaction: &Transaction) -> Result<String, ClientError> {
|
||||||
&self,
|
|
||||||
transaction: &Transaction,
|
|
||||||
) -> Result<String, Box<dyn error::Error>> {
|
|
||||||
let serialized = serialize(transaction).unwrap();
|
let serialized = serialize(transaction).unwrap();
|
||||||
let params = json!([serialized]);
|
let params = json!([serialized]);
|
||||||
let signature = self
|
let signature = self
|
||||||
@ -67,7 +65,7 @@ impl RpcClient {
|
|||||||
pub fn get_signature_status(
|
pub fn get_signature_status(
|
||||||
&self,
|
&self,
|
||||||
signature: &str,
|
signature: &str,
|
||||||
) -> Result<Option<transaction::Result<()>>, Box<dyn error::Error>> {
|
) -> Result<Option<transaction::Result<()>>, ClientError> {
|
||||||
let params = json!([signature.to_string()]);
|
let params = json!([signature.to_string()]);
|
||||||
let signature_status =
|
let signature_status =
|
||||||
self.client
|
self.client
|
||||||
@ -81,7 +79,7 @@ impl RpcClient {
|
|||||||
&self,
|
&self,
|
||||||
transaction: &mut Transaction,
|
transaction: &mut Transaction,
|
||||||
signer: &T,
|
signer: &T,
|
||||||
) -> Result<String, Box<dyn error::Error>> {
|
) -> Result<String, ClientError> {
|
||||||
let mut send_retries = 5;
|
let mut send_retries = 5;
|
||||||
loop {
|
loop {
|
||||||
let mut status_retries = 4;
|
let mut status_retries = 4;
|
||||||
@ -117,6 +115,9 @@ impl RpcClient {
|
|||||||
send_retries - 1
|
send_retries - 1
|
||||||
};
|
};
|
||||||
if send_retries == 0 {
|
if send_retries == 0 {
|
||||||
|
if status.is_some() {
|
||||||
|
status.unwrap()?
|
||||||
|
} else {
|
||||||
Err(io::Error::new(
|
Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("Transaction {:?} failed: {:?}", signature_str, status),
|
format!("Transaction {:?} failed: {:?}", signature_str, status),
|
||||||
@ -124,6 +125,7 @@ impl RpcClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn send_and_confirm_transactions(
|
pub fn send_and_confirm_transactions(
|
||||||
&self,
|
&self,
|
||||||
@ -201,7 +203,7 @@ impl RpcClient {
|
|||||||
&self,
|
&self,
|
||||||
tx: &mut Transaction,
|
tx: &mut Transaction,
|
||||||
signer_key: &T,
|
signer_key: &T,
|
||||||
) -> Result<(), Box<dyn error::Error>> {
|
) -> Result<(), ClientError> {
|
||||||
let blockhash = self.get_new_blockhash(&tx.message().recent_blockhash)?;
|
let blockhash = self.get_new_blockhash(&tx.message().recent_blockhash)?;
|
||||||
tx.sign(&[signer_key], blockhash);
|
tx.sign(&[signer_key], blockhash);
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -482,7 +484,7 @@ impl RpcClient {
|
|||||||
)
|
)
|
||||||
.map_err(|error| {
|
.map_err(|error| {
|
||||||
debug!(
|
debug!(
|
||||||
"Response get_num_blocks_since_signature_confirmation: {}",
|
"Response get_num_blocks_since_signature_confirmation: {:?}",
|
||||||
error
|
error
|
||||||
);
|
);
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
@ -526,7 +528,7 @@ impl RpcClient {
|
|||||||
request: &RpcRequest,
|
request: &RpcRequest,
|
||||||
params: Option<Value>,
|
params: Option<Value>,
|
||||||
retries: usize,
|
retries: usize,
|
||||||
) -> Result<Value, Box<dyn error::Error>> {
|
) -> Result<Value, ClientError> {
|
||||||
self.client.send(request, params, retries)
|
self.client.send(request, params, retries)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use crate::client_error::ClientError;
|
||||||
use crate::generic_rpc_client_request::GenericRpcClientRequest;
|
use crate::generic_rpc_client_request::GenericRpcClientRequest;
|
||||||
use crate::rpc_request::{RpcError, RpcRequest};
|
use crate::rpc_request::{RpcError, RpcRequest};
|
||||||
use log::*;
|
use log::*;
|
||||||
@ -36,7 +37,7 @@ impl GenericRpcClientRequest for RpcClientRequest {
|
|||||||
request: &RpcRequest,
|
request: &RpcRequest,
|
||||||
params: Option<serde_json::Value>,
|
params: Option<serde_json::Value>,
|
||||||
mut retries: usize,
|
mut retries: usize,
|
||||||
) -> Result<serde_json::Value, Box<dyn std::error::Error>> {
|
) -> Result<serde_json::Value, ClientError> {
|
||||||
// Concurrent requests are not supported so reuse the same request id for all requests
|
// Concurrent requests are not supported so reuse the same request id for all requests
|
||||||
let request_id = 1;
|
let request_id = 1;
|
||||||
|
|
||||||
|
@ -221,7 +221,7 @@ impl SyncClient for ThinClient {
|
|||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
io::Error::new(
|
io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("send_transaction failed with error {}", err),
|
format!("send_transaction failed with error {:?}", err),
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
Ok(status)
|
Ok(status)
|
||||||
|
@ -12,6 +12,8 @@ edition = "2018"
|
|||||||
bincode = "1.1.3"
|
bincode = "1.1.3"
|
||||||
chrono = { version = "0.4.0", features = ["serde"] }
|
chrono = { version = "0.4.0", features = ["serde"] }
|
||||||
log = "0.4.2"
|
log = "0.4.2"
|
||||||
|
num-derive = "0.2"
|
||||||
|
num-traits = "0.2"
|
||||||
serde = "1.0.90"
|
serde = "1.0.90"
|
||||||
serde_derive = "1.0.90"
|
serde_derive = "1.0.90"
|
||||||
solana-sdk = { path = "../../sdk", version = "0.14.0" }
|
solana-sdk = { path = "../../sdk", version = "0.14.0" }
|
||||||
|
@ -1,14 +1,29 @@
|
|||||||
//! budget state
|
//! budget state
|
||||||
use crate::budget_expr::BudgetExpr;
|
use crate::budget_expr::BudgetExpr;
|
||||||
use bincode::{self, deserialize, serialize_into};
|
use bincode::{self, deserialize, serialize_into};
|
||||||
|
use num_derive::FromPrimitive;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use solana_sdk::instruction::InstructionError;
|
use solana_sdk::instruction::InstructionError;
|
||||||
|
use solana_sdk::instruction_processor_utils::DecodeError;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, FromPrimitive)]
|
||||||
pub enum BudgetError {
|
pub enum BudgetError {
|
||||||
DestinationMissing,
|
DestinationMissing,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> DecodeError<T> for BudgetError {
|
||||||
|
fn type_of(&self) -> &'static str {
|
||||||
|
"BudgetError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for BudgetError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
write!(f, "error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for BudgetError {}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
|
||||||
pub struct BudgetState {
|
pub struct BudgetState {
|
||||||
pub initialized: bool,
|
pub initialized: bool,
|
||||||
|
@ -11,6 +11,8 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
bincode = "1.1.3"
|
bincode = "1.1.3"
|
||||||
log = "0.4.2"
|
log = "0.4.2"
|
||||||
|
num-derive = "0.2"
|
||||||
|
num-traits = "0.2"
|
||||||
serde = "1.0.90"
|
serde = "1.0.90"
|
||||||
serde_derive = "1.0.90"
|
serde_derive = "1.0.90"
|
||||||
solana-logger = { path = "../../logger", version = "0.14.0" }
|
solana-logger = { path = "../../logger", version = "0.14.0" }
|
||||||
|
@ -1,15 +1,23 @@
|
|||||||
use log::*;
|
use log::*;
|
||||||
|
use num_derive::FromPrimitive;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use solana_sdk::account::KeyedAccount;
|
use solana_sdk::account::KeyedAccount;
|
||||||
|
use solana_sdk::instruction_processor_utils::DecodeError;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
|
||||||
#[derive(Serialize, Debug, PartialEq)]
|
#[derive(Serialize, Debug, PartialEq, FromPrimitive)]
|
||||||
pub enum TokenError {
|
pub enum TokenError {
|
||||||
InvalidArgument,
|
InvalidArgument,
|
||||||
InsufficentFunds,
|
InsufficentFunds,
|
||||||
NotOwner,
|
NotOwner,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> DecodeError<T> for TokenError {
|
||||||
|
fn type_of(&self) -> &'static str {
|
||||||
|
"TokenError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for TokenError {
|
impl std::fmt::Display for TokenError {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
write!(f, "error")
|
write!(f, "error")
|
||||||
|
@ -18,6 +18,8 @@ chrono = { version = "0.4.0", features = ["serde"] }
|
|||||||
generic-array = { version = "0.13.0", default-features = false, features = ["serde"] }
|
generic-array = { version = "0.13.0", default-features = false, features = ["serde"] }
|
||||||
itertools = "0.8.0"
|
itertools = "0.8.0"
|
||||||
log = "0.4.2"
|
log = "0.4.2"
|
||||||
|
num-derive = "0.2"
|
||||||
|
num-traits = "0.2"
|
||||||
rand = "0.6.5"
|
rand = "0.6.5"
|
||||||
rayon = "1.0.0"
|
rayon = "1.0.0"
|
||||||
sha2 = "0.8.0"
|
sha2 = "0.8.0"
|
||||||
|
@ -2,6 +2,7 @@ use crate::account::{Account, KeyedAccount};
|
|||||||
use crate::instruction::InstructionError;
|
use crate::instruction::InstructionError;
|
||||||
use crate::pubkey::Pubkey;
|
use crate::pubkey::Pubkey;
|
||||||
use bincode::ErrorKind;
|
use bincode::ErrorKind;
|
||||||
|
use num_traits::FromPrimitive;
|
||||||
|
|
||||||
// All native programs export a symbol named process()
|
// All native programs export a symbol named process()
|
||||||
pub const ENTRYPOINT: &str = "process";
|
pub const ENTRYPOINT: &str = "process";
|
||||||
@ -64,3 +65,39 @@ where
|
|||||||
self.account.set_state(state)
|
self.account.set_state(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait DecodeError<E> {
|
||||||
|
fn decode_custom_error_to_enum(int: u32) -> Option<E>
|
||||||
|
where
|
||||||
|
E: FromPrimitive,
|
||||||
|
{
|
||||||
|
E::from_u32(int)
|
||||||
|
}
|
||||||
|
fn type_of(&self) -> &'static str;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use num_derive::FromPrimitive;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decode_custom_error_to_enum() {
|
||||||
|
#[derive(Debug, FromPrimitive, PartialEq)]
|
||||||
|
enum TestEnum {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
C,
|
||||||
|
}
|
||||||
|
impl<T> DecodeError<T> for TestEnum {
|
||||||
|
fn type_of(&self) -> &'static str {
|
||||||
|
"TestEnum"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_eq!(TestEnum::decode_custom_error_to_enum(0), Some(TestEnum::A));
|
||||||
|
assert_eq!(TestEnum::decode_custom_error_to_enum(1), Some(TestEnum::B));
|
||||||
|
assert_eq!(TestEnum::decode_custom_error_to_enum(2), Some(TestEnum::C));
|
||||||
|
let option: Option<TestEnum> = TestEnum::decode_custom_error_to_enum(3);
|
||||||
|
assert_eq!(option, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,14 +1,29 @@
|
|||||||
use crate::instruction::{AccountMeta, Instruction};
|
use crate::instruction::{AccountMeta, Instruction};
|
||||||
|
use crate::instruction_processor_utils::DecodeError;
|
||||||
use crate::pubkey::Pubkey;
|
use crate::pubkey::Pubkey;
|
||||||
use crate::system_program;
|
use crate::system_program;
|
||||||
|
use num_derive::FromPrimitive;
|
||||||
|
|
||||||
#[derive(Serialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Debug, Clone, PartialEq, FromPrimitive)]
|
||||||
pub enum SystemError {
|
pub enum SystemError {
|
||||||
AccountAlreadyInUse,
|
AccountAlreadyInUse,
|
||||||
ResultWithNegativeLamports,
|
ResultWithNegativeLamports,
|
||||||
SourceNotSystemAccount,
|
SourceNotSystemAccount,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> DecodeError<T> for SystemError {
|
||||||
|
fn type_of(&self) -> &'static str {
|
||||||
|
"SystemError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for SystemError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
write!(f, "error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for SystemError {}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
|
||||||
pub enum SystemInstruction {
|
pub enum SystemInstruction {
|
||||||
/// Create a new account
|
/// Create a new account
|
||||||
|
@ -15,6 +15,7 @@ clap = "2.33.0"
|
|||||||
chrono = { version = "0.4.0", features = ["serde"] }
|
chrono = { version = "0.4.0", features = ["serde"] }
|
||||||
dirs = "1.0.5"
|
dirs = "1.0.5"
|
||||||
log = "0.4.2"
|
log = "0.4.2"
|
||||||
|
num-traits = "0.2"
|
||||||
serde_json = "1.0.39"
|
serde_json = "1.0.39"
|
||||||
solana-budget-api = { path = "../programs/budget_api", version = "0.14.0" }
|
solana-budget-api = { path = "../programs/budget_api", version = "0.14.0" }
|
||||||
solana-client = { path = "../client", version = "0.14.0" }
|
solana-client = { path = "../client", version = "0.14.0" }
|
||||||
|
@ -2,10 +2,13 @@ use bs58;
|
|||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use clap::ArgMatches;
|
use clap::ArgMatches;
|
||||||
use log::*;
|
use log::*;
|
||||||
|
use num_traits::FromPrimitive;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use solana_budget_api;
|
use solana_budget_api;
|
||||||
use solana_budget_api::budget_instruction;
|
use solana_budget_api::budget_instruction;
|
||||||
|
use solana_budget_api::budget_state::BudgetError;
|
||||||
|
use solana_client::client_error::ClientError;
|
||||||
use solana_client::rpc_client::{get_rpc_request_str, RpcClient};
|
use solana_client::rpc_client::{get_rpc_request_str, RpcClient};
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
use solana_drone::drone::request_airdrop_transaction;
|
use solana_drone::drone::request_airdrop_transaction;
|
||||||
@ -14,12 +17,15 @@ use solana_drone::drone::DRONE_PORT;
|
|||||||
use solana_drone::drone_mock::request_airdrop_transaction;
|
use solana_drone::drone_mock::request_airdrop_transaction;
|
||||||
use solana_sdk::bpf_loader;
|
use solana_sdk::bpf_loader;
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
|
use solana_sdk::instruction::InstructionError;
|
||||||
|
use solana_sdk::instruction_processor_utils::DecodeError;
|
||||||
use solana_sdk::loader_instruction;
|
use solana_sdk::loader_instruction;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::rpc_port::DEFAULT_RPC_PORT;
|
use solana_sdk::rpc_port::DEFAULT_RPC_PORT;
|
||||||
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
use solana_sdk::signature::{Keypair, KeypairUtil, Signature};
|
||||||
|
use solana_sdk::system_instruction::SystemError;
|
||||||
use solana_sdk::system_transaction;
|
use solana_sdk::system_transaction;
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::{Transaction, TransactionError};
|
||||||
use solana_vote_api::vote_instruction;
|
use solana_vote_api::vote_instruction;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
@ -448,9 +454,8 @@ fn process_deploy(
|
|||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
trace!("Creating program account");
|
trace!("Creating program account");
|
||||||
rpc_client
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &config.keypair);
|
||||||
.send_and_confirm_transaction(&mut tx, &config.keypair)
|
log_instruction_custom_error::<SystemError>(result).map_err(|_| {
|
||||||
.map_err(|_| {
|
|
||||||
WalletError::DynamicProgramError("Program allocate space failed".to_string())
|
WalletError::DynamicProgramError("Program allocate space failed".to_string())
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@ -499,7 +504,8 @@ fn process_pay(
|
|||||||
|
|
||||||
if timestamp == None && *witnesses == None {
|
if timestamp == None && *witnesses == None {
|
||||||
let mut tx = system_transaction::transfer(&config.keypair, to, lamports, blockhash, 0);
|
let mut tx = system_transaction::transfer(&config.keypair, to, lamports, blockhash, 0);
|
||||||
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.keypair)?;
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &config.keypair);
|
||||||
|
let signature_str = log_instruction_custom_error::<SystemError>(result)?;
|
||||||
Ok(signature_str.to_string())
|
Ok(signature_str.to_string())
|
||||||
} else if *witnesses == None {
|
} else if *witnesses == None {
|
||||||
let dt = timestamp.unwrap();
|
let dt = timestamp.unwrap();
|
||||||
@ -521,7 +527,8 @@ fn process_pay(
|
|||||||
lamports,
|
lamports,
|
||||||
);
|
);
|
||||||
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], ixs, blockhash);
|
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], ixs, blockhash);
|
||||||
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.keypair)?;
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &config.keypair);
|
||||||
|
let signature_str = log_instruction_custom_error::<BudgetError>(result)?;
|
||||||
|
|
||||||
Ok(json!({
|
Ok(json!({
|
||||||
"signature": signature_str,
|
"signature": signature_str,
|
||||||
@ -551,7 +558,8 @@ fn process_pay(
|
|||||||
lamports,
|
lamports,
|
||||||
);
|
);
|
||||||
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], ixs, blockhash);
|
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], ixs, blockhash);
|
||||||
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.keypair)?;
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &config.keypair);
|
||||||
|
let signature_str = log_instruction_custom_error::<BudgetError>(result)?;
|
||||||
|
|
||||||
Ok(json!({
|
Ok(json!({
|
||||||
"signature": signature_str,
|
"signature": signature_str,
|
||||||
@ -571,7 +579,8 @@ fn process_cancel(rpc_client: &RpcClient, config: &WalletConfig, pubkey: &Pubkey
|
|||||||
&config.keypair.pubkey(),
|
&config.keypair.pubkey(),
|
||||||
);
|
);
|
||||||
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], vec![ix], blockhash);
|
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], vec![ix], blockhash);
|
||||||
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.keypair)?;
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &config.keypair);
|
||||||
|
let signature_str = log_instruction_custom_error::<BudgetError>(result)?;
|
||||||
Ok(signature_str.to_string())
|
Ok(signature_str.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -598,7 +607,8 @@ fn process_time_elapsed(
|
|||||||
|
|
||||||
let ix = budget_instruction::apply_timestamp(&config.keypair.pubkey(), pubkey, to, dt);
|
let ix = budget_instruction::apply_timestamp(&config.keypair.pubkey(), pubkey, to, dt);
|
||||||
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], vec![ix], blockhash);
|
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], vec![ix], blockhash);
|
||||||
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.keypair)?;
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &config.keypair);
|
||||||
|
let signature_str = log_instruction_custom_error::<BudgetError>(result)?;
|
||||||
|
|
||||||
Ok(signature_str.to_string())
|
Ok(signature_str.to_string())
|
||||||
}
|
}
|
||||||
@ -619,7 +629,8 @@ fn process_witness(
|
|||||||
let blockhash = rpc_client.get_recent_blockhash()?;
|
let blockhash = rpc_client.get_recent_blockhash()?;
|
||||||
let ix = budget_instruction::apply_signature(&config.keypair.pubkey(), pubkey, to);
|
let ix = budget_instruction::apply_signature(&config.keypair.pubkey(), pubkey, to);
|
||||||
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], vec![ix], blockhash);
|
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], vec![ix], blockhash);
|
||||||
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &config.keypair)?;
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &config.keypair);
|
||||||
|
let signature_str = log_instruction_custom_error::<BudgetError>(result)?;
|
||||||
|
|
||||||
Ok(signature_str.to_string())
|
Ok(signature_str.to_string())
|
||||||
}
|
}
|
||||||
@ -766,10 +777,39 @@ pub fn request_and_confirm_airdrop(
|
|||||||
let blockhash = rpc_client.get_recent_blockhash()?;
|
let blockhash = rpc_client.get_recent_blockhash()?;
|
||||||
let keypair = DroneKeypair::new_keypair(drone_addr, to_pubkey, lamports, blockhash)?;
|
let keypair = DroneKeypair::new_keypair(drone_addr, to_pubkey, lamports, blockhash)?;
|
||||||
let mut tx = keypair.airdrop_transaction();
|
let mut tx = keypair.airdrop_transaction();
|
||||||
rpc_client.send_and_confirm_transaction(&mut tx, &keypair)?;
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &keypair);
|
||||||
|
log_instruction_custom_error::<SystemError>(result)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn log_instruction_custom_error<E>(result: Result<String, ClientError>) -> ProcessResult
|
||||||
|
where
|
||||||
|
E: 'static + std::error::Error + DecodeError<E> + FromPrimitive,
|
||||||
|
{
|
||||||
|
if result.is_err() {
|
||||||
|
let err = result.unwrap_err();
|
||||||
|
if let ClientError::TransactionError(TransactionError::InstructionError(
|
||||||
|
_,
|
||||||
|
InstructionError::CustomError(code),
|
||||||
|
)) = err
|
||||||
|
{
|
||||||
|
if let Some(specific_error) = E::decode_custom_error_to_enum(code) {
|
||||||
|
error!(
|
||||||
|
"{:?}: {}::{:?}",
|
||||||
|
err,
|
||||||
|
specific_error.type_of(),
|
||||||
|
specific_error
|
||||||
|
);
|
||||||
|
Err(specific_error)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error!("{:?}", err);
|
||||||
|
Err(err)?
|
||||||
|
} else {
|
||||||
|
Ok(result.unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
Reference in New Issue
Block a user