From cb6c380c44a2229147349c7325fa3368a18b6bc3 Mon Sep 17 00:00:00 2001 From: Stan Bondi Date: Thu, 22 Sep 2022 12:19:02 +0400 Subject: [PATCH] feat(clients): add base node and wallet client crates --- Cargo.lock | 29 +++++- Cargo.toml | 2 + .../src/authentication/basic_auth.rs | 24 +++-- .../src/authentication/client_interceptor.rs | 8 +- .../tari_merge_mining_proxy/Cargo.toml | 4 +- .../src/block_template_data.rs | 2 +- .../src/block_template_protocol.rs | 17 ++-- .../src/common/merge_mining.rs | 2 +- .../tari_merge_mining_proxy/src/config.rs | 2 +- .../tari_merge_mining_proxy/src/error.rs | 3 +- .../tari_merge_mining_proxy/src/main.rs | 37 ++------ .../tari_merge_mining_proxy/src/proxy.rs | 17 ++-- base_layer/p2p/Cargo.toml | 4 +- .../base_node_grpc_client/README.md | 0 .../base_node_grpc_client/package.json | 0 .../base_node_grpc_client/src/index.js | 0 .../base_node_grpc_client/src/index.test.js | 0 .../wallet_grpc_client/.prettierrc | 0 .../{ => nodejs}/wallet_grpc_client/README.md | 0 .../{ => nodejs}/wallet_grpc_client/index.js | 0 .../wallet_grpc_client/package.json | 0 clients/rust/base_node_grpc_client/Cargo.toml | 25 +++++ clients/rust/base_node_grpc_client/src/lib.rs | 24 +++++ .../base_node_grpc_client/tests/client.rs | 38 ++++++++ clients/rust/wallet_grpc_client/Cargo.toml | 20 ++++ clients/rust/wallet_grpc_client/src/lib.rs | 91 +++++++++++++++++++ .../rust/wallet_grpc_client/tests/client.rs | 39 ++++++++ integration_tests/package.json | 2 +- 28 files changed, 316 insertions(+), 74 deletions(-) rename clients/{ => nodejs}/base_node_grpc_client/README.md (100%) rename clients/{ => nodejs}/base_node_grpc_client/package.json (100%) rename clients/{ => nodejs}/base_node_grpc_client/src/index.js (100%) rename clients/{ => nodejs}/base_node_grpc_client/src/index.test.js (100%) rename clients/{ => nodejs}/wallet_grpc_client/.prettierrc (100%) rename clients/{ => nodejs}/wallet_grpc_client/README.md (100%) rename clients/{ => nodejs}/wallet_grpc_client/index.js (100%) rename clients/{ => nodejs}/wallet_grpc_client/package.json (100%) create mode 100644 clients/rust/base_node_grpc_client/Cargo.toml create mode 100644 clients/rust/base_node_grpc_client/src/lib.rs create mode 100644 clients/rust/base_node_grpc_client/tests/client.rs create mode 100644 clients/rust/wallet_grpc_client/Cargo.toml create mode 100644 clients/rust/wallet_grpc_client/src/lib.rs create mode 100644 clients/rust/wallet_grpc_client/tests/client.rs diff --git a/Cargo.lock b/Cargo.lock index 4a724589f8..577db90300 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3841,9 +3841,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.11" +version = "0.11.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" +checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" dependencies = [ "base64 0.13.0", "bytes 1.2.1", @@ -3857,10 +3857,10 @@ dependencies = [ "hyper-tls", "ipnet", "js-sys", - "lazy_static", "log", "mime", "native-tls", + "once_cell", "percent-encoding 2.2.0", "pin-project-lite", "serde", @@ -4648,6 +4648,14 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "tari_base_node_grpc_client" +version = "0.1.0" +dependencies = [ + "tari_app_grpc", + "tokio", +] + [[package]] name = "tari_bulletproofs" version = "4.2.1" @@ -5060,14 +5068,14 @@ dependencies = [ "serde", "serde_json", "structopt", - "tari_app_grpc", "tari_app_utilities", + "tari_base_node_grpc_client", "tari_common", - "tari_common_types", "tari_comms", "tari_core", "tari_crypto", "tari_utilities", + "tari_wallet_grpc_client", "thiserror", "tokio", "tonic", @@ -5371,6 +5379,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tari_wallet_grpc_client" +version = "0.1.0" +dependencies = [ + "tari_app_grpc", + "tari_common_types", + "thiserror", + "tokio", + "tonic", +] + [[package]] name = "tempfile" version = "3.3.0" diff --git a/Cargo.toml b/Cargo.toml index 50bf4fc94a..b1dfbc715e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,8 @@ members = [ "base_layer/wallet", "base_layer/wallet_ffi", "base_layer/tari_mining_helper_ffi", + "clients/rust/base_node_grpc_client", + "clients/rust/wallet_grpc_client", "comms/core", "comms/dht", "comms/rpc_macros", diff --git a/applications/tari_app_grpc/src/authentication/basic_auth.rs b/applications/tari_app_grpc/src/authentication/basic_auth.rs index 36e6acfe30..4bd5efe30d 100644 --- a/applications/tari_app_grpc/src/authentication/basic_auth.rs +++ b/applications/tari_app_grpc/src/authentication/basic_auth.rs @@ -24,6 +24,7 @@ use std::{borrow::Cow, string::FromUtf8Error}; use argon2::{password_hash::Encoding, Argon2, PasswordHash, PasswordVerifier}; use tari_utilities::SafePassword; +use tonic::metadata::{errors::InvalidMetadataValue, Ascii, MetadataValue}; use zeroize::{Zeroize, Zeroizing}; /// Implements [RFC 2617](https://www.ietf.org/rfc/rfc2617.txt#:~:text=The%20%22basic%22%20authentication%20scheme%20is,other%20realms%20on%20that%20server.) @@ -89,7 +90,7 @@ impl BasicAuthCredentials { Ok(()) } - pub fn generate_header(username: &str, password: &[u8]) -> Result { + pub fn generate_header(username: &str, password: &[u8]) -> Result, BasicAuthError> { let password_str = String::from_utf8_lossy(password); let token_str = Zeroizing::new(format!("{}:{}", username, password_str)); let mut token = base64::encode(token_str); @@ -99,12 +100,13 @@ impl BasicAuthCredentials { Cow::Borrowed(_) => {}, Cow::Owned(mut owned) => owned.zeroize(), } + let header = header.parse()?; Ok(header) } } /// Authorization Header Error -#[derive(Debug, thiserror::Error, PartialEq, Eq)] +#[derive(Debug, thiserror::Error)] pub enum BasicAuthError { #[error("Invalid username")] InvalidUsername, @@ -118,6 +120,8 @@ pub enum BasicAuthError { InvalidUtf8Value(#[from] FromUtf8Error), #[error("Invalid password: {0}")] InvalidPassword(#[from] argon2::password_hash::Error), + #[error("Invalid header value: {0}")] + InvalidMetadataValue(#[from] InvalidMetadataValue), } #[cfg(test)] @@ -137,9 +141,17 @@ mod tests { #[test] fn it_rejects_header_without_basic_scheme() { let err = BasicAuthCredentials::from_header(" YWRtaW46c2VjcmV0").unwrap_err(); - assert_eq!(err, BasicAuthError::InvalidScheme("".to_string())); + if let BasicAuthError::InvalidScheme(s) = err { + assert_eq!(s, ""); + } else { + panic!("Unexpected error: {:?}", err); + }; let err = BasicAuthCredentials::from_header("Cookie YWRtaW46c2VjcmV0").unwrap_err(); - assert_eq!(err, BasicAuthError::InvalidScheme("Cookie".to_string())); + if let BasicAuthError::InvalidScheme(s) = err { + assert_eq!(s, "Cookie"); + } else { + panic!("Unexpected error: {:?}", err); + }; } } @@ -162,7 +174,7 @@ mod tests { let credentials = BasicAuthCredentials::new("bruteforce".to_string(), "secret".to_string().into()); let err = credentials.validate("admin", b"secret").unwrap_err(); - assert_eq!(err, BasicAuthError::InvalidUsername); + assert!(matches!(err, BasicAuthError::InvalidUsername)); } } @@ -172,7 +184,7 @@ mod tests { #[test] fn it_generates_a_valid_header() { let header = BasicAuthCredentials::generate_header("admin", b"secret").unwrap(); - let cred = BasicAuthCredentials::from_header(&header).unwrap(); + let cred = BasicAuthCredentials::from_header(header.to_str().unwrap()).unwrap(); assert_eq!(cred.user_name, "admin"); assert_eq!(cred.password.reveal(), &b"secret"[..]); } diff --git a/applications/tari_app_grpc/src/authentication/client_interceptor.rs b/applications/tari_app_grpc/src/authentication/client_interceptor.rs index 47c75a9156..9c0e45dbb1 100644 --- a/applications/tari_app_grpc/src/authentication/client_interceptor.rs +++ b/applications/tari_app_grpc/src/authentication/client_interceptor.rs @@ -40,11 +40,9 @@ impl ClientAuthenticationInterceptor { pub fn create(auth: &GrpcAuthentication) -> Result { let authorization_header = match auth { GrpcAuthentication::None => None, - GrpcAuthentication::Basic { username, password } => Some( - BasicAuthCredentials::generate_header(username, password.reveal())? - .parse() - .unwrap(), - ), + GrpcAuthentication::Basic { username, password } => { + Some(BasicAuthCredentials::generate_header(username, password.reveal())?) + }, }; Ok(Self { authorization_header }) } diff --git a/applications/tari_merge_mining_proxy/Cargo.toml b/applications/tari_merge_mining_proxy/Cargo.toml index 24aeb93bd6..e3c3e307eb 100644 --- a/applications/tari_merge_mining_proxy/Cargo.toml +++ b/applications/tari_merge_mining_proxy/Cargo.toml @@ -11,14 +11,14 @@ edition = "2018" default = [] [dependencies] -tari_app_grpc = { path = "../tari_app_grpc" } tari_common = { path = "../../common" } -tari_common_types = { path = "../../base_layer/common_types" } tari_comms = { path = "../../comms/core" } tari_core = { path = "../../base_layer/core", default-features = false, features = ["transactions"] } tari_app_utilities = { path = "../tari_app_utilities" } tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.15.5" } tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag = "v0.4.5" } +tari_base_node_grpc_client = {path="../../clients/rust/base_node_grpc_client" } +tari_wallet_grpc_client = {path="../../clients/rust/wallet_grpc_client" } anyhow = "1.0.53" crossterm = { version = "0.17" } diff --git a/applications/tari_merge_mining_proxy/src/block_template_data.rs b/applications/tari_merge_mining_proxy/src/block_template_data.rs index 696db876ee..0407691968 100644 --- a/applications/tari_merge_mining_proxy/src/block_template_data.rs +++ b/applications/tari_merge_mining_proxy/src/block_template_data.rs @@ -27,7 +27,7 @@ use std::{collections::HashMap, sync::Arc}; #[cfg(not(test))] use chrono::Duration; use chrono::{self, DateTime, Utc}; -use tari_app_grpc::tari_rpc as grpc; +use tari_base_node_grpc_client::grpc; use tari_core::proof_of_work::monero_rx::FixedByteArray; use tokio::sync::RwLock; use tracing::trace; diff --git a/applications/tari_merge_mining_proxy/src/block_template_protocol.rs b/applications/tari_merge_mining_proxy/src/block_template_protocol.rs index d7ccc67a6e..c547e4db49 100644 --- a/applications/tari_merge_mining_proxy/src/block_template_protocol.rs +++ b/applications/tari_merge_mining_proxy/src/block_template_protocol.rs @@ -25,8 +25,9 @@ use std::cmp; use log::*; -use tari_app_grpc::{authentication::ClientAuthenticationInterceptor, tari_rpc as grpc}; +use tari_base_node_grpc_client::{grpc, BaseNodeGrpcClient}; use tari_core::proof_of_work::{monero_rx, monero_rx::FixedByteArray, Difficulty}; +use tari_wallet_grpc_client::WalletGrpcClient; use crate::{ block_template_data::{BlockTemplateData, BlockTemplateDataBuilder}, @@ -38,18 +39,14 @@ const LOG_TARGET: &str = "tari_mm_proxy::proxy::block_template_protocol"; /// Structure holding grpc connections. pub struct BlockTemplateProtocol<'a> { - base_node_client: &'a mut grpc::base_node_client::BaseNodeClient, - wallet_client: &'a mut grpc::wallet_client::WalletClient< - tonic::codegen::InterceptedService, - >, + base_node_client: &'a mut BaseNodeGrpcClient, + wallet_client: &'a mut WalletGrpcClient, } impl<'a> BlockTemplateProtocol<'a> { pub fn new( - base_node_client: &'a mut grpc::base_node_client::BaseNodeClient, - wallet_client: &'a mut grpc::wallet_client::WalletClient< - tonic::codegen::InterceptedService, - >, + base_node_client: &'a mut BaseNodeGrpcClient, + wallet_client: &'a mut WalletGrpcClient, ) -> Self { Self { base_node_client, @@ -160,7 +157,7 @@ impl BlockTemplateProtocol<'_> { let tip = self .base_node_client .clone() - .get_tip_info(tari_app_grpc::tari_rpc::Empty {}) + .get_tip_info(grpc::Empty {}) .await? .into_inner(); let tip_height = tip.metadata.as_ref().map(|m| m.height_of_longest_chain).unwrap_or(0); diff --git a/applications/tari_merge_mining_proxy/src/common/merge_mining.rs b/applications/tari_merge_mining_proxy/src/common/merge_mining.rs index 6f56c861ff..42ec9d2331 100644 --- a/applications/tari_merge_mining_proxy/src/common/merge_mining.rs +++ b/applications/tari_merge_mining_proxy/src/common/merge_mining.rs @@ -24,7 +24,7 @@ use std::convert::{TryFrom, TryInto}; -use tari_app_grpc::tari_rpc as grpc; +use tari_base_node_grpc_client::grpc; use tari_core::{ blocks::NewBlockTemplate, transactions::transaction_components::{TransactionKernel, TransactionOutput}, diff --git a/applications/tari_merge_mining_proxy/src/config.rs b/applications/tari_merge_mining_proxy/src/config.rs index 0bffda2fa9..b8824556cd 100644 --- a/applications/tari_merge_mining_proxy/src/config.rs +++ b/applications/tari_merge_mining_proxy/src/config.rs @@ -22,8 +22,8 @@ use serde::{Deserialize, Serialize}; use tari_common::{configuration::StringList, SubConfigPath}; -use tari_common_types::grpc_authentication::GrpcAuthentication; use tari_comms::multiaddr::Multiaddr; +use tari_wallet_grpc_client::GrpcAuthentication; #[derive(Clone, Debug, Deserialize, Serialize)] #[serde(deny_unknown_fields)] diff --git a/applications/tari_merge_mining_proxy/src/error.rs b/applications/tari_merge_mining_proxy/src/error.rs index 0d308d3bf4..0ea0579fb6 100644 --- a/applications/tari_merge_mining_proxy/src/error.rs +++ b/applications/tari_merge_mining_proxy/src/error.rs @@ -26,9 +26,10 @@ use std::io; use hex::FromHexError; use hyper::header::InvalidHeaderValue; -use tari_app_grpc::authentication::BasicAuthError; +// use tari_app_grpc::authentication::BasicAuthError; use tari_common::{ConfigError, ConfigurationError}; use tari_core::{proof_of_work::monero_rx::MergeMineError, transactions::CoinbaseBuildError}; +use tari_wallet_grpc_client::BasicAuthError; use thiserror::Error; use tonic::{codegen::http::uri::InvalidUri, transport}; diff --git a/applications/tari_merge_mining_proxy/src/main.rs b/applications/tari_merge_mining_proxy/src/main.rs index a58230850d..274bb60321 100644 --- a/applications/tari_merge_mining_proxy/src/main.rs +++ b/applications/tari_merge_mining_proxy/src/main.rs @@ -34,7 +34,6 @@ mod test; use std::{ convert::Infallible, io::{stdout, Write}, - str::FromStr, }; use clap::Parser; @@ -43,16 +42,13 @@ use futures::future; use hyper::{service::make_service_fn, Server}; use log::*; use proxy::MergeMiningProxyService; -use tari_app_grpc::{authentication::ClientAuthenticationInterceptor, tari_rpc as grpc}; use tari_app_utilities::consts; +use tari_base_node_grpc_client::BaseNodeGrpcClient; use tari_common::{initialize_logging, load_configuration, DefaultConfigLoader}; use tari_comms::utils::multiaddr::multiaddr_to_socketaddr; use tari_core::proof_of_work::randomx_factory::RandomXFactory; +use tari_wallet_grpc_client::WalletGrpcClient; use tokio::time::Duration; -use tonic::{ - codegen::InterceptedService, - transport::{Channel, Endpoint}, -}; use crate::{ block_template_data::BlockTemplateRepository, @@ -62,24 +58,6 @@ use crate::{ }; const LOG_TARGET: &str = "tari_mm_proxy::proxy"; -pub(crate) type WalletGrpcClient = - grpc::wallet_client::WalletClient>; - -async fn connect_wallet_with_authenticator(config: &MergeMiningProxyConfig) -> Result { - let wallet_addr = format!( - "http://{}", - multiaddr_to_socketaddr(&config.console_wallet_grpc_address)? - ); - info!(target: LOG_TARGET, "👛 Connecting to wallet at {}", wallet_addr); - let channel = Endpoint::from_str(&wallet_addr)?.connect().await?; - let wallet_conn = grpc::wallet_client::WalletClient::with_interceptor( - channel, - ClientAuthenticationInterceptor::create(&config.console_wallet_grpc_authentication)?, - ); - - Ok(wallet_conn) -} - #[tokio::main] async fn main() -> Result<(), anyhow::Error> { let terminal_title = format!("Tari Merge Mining Proxy - Version {}", consts::APP_VERSION); @@ -109,11 +87,12 @@ async fn main() -> Result<(), anyhow::Error> { let base_node = multiaddr_to_socketaddr(&config.base_node_grpc_address)?; info!(target: LOG_TARGET, "Connecting to base node at {}", base_node); println!("Connecting to base node at {}", base_node); - let base_node_client = grpc::base_node_client::BaseNodeClient::connect(format!("http://{}", base_node)).await?; - let wallet = multiaddr_to_socketaddr(&config.console_wallet_grpc_address)?; - info!(target: LOG_TARGET, "Connecting to wallet at {}", wallet); - println!("Connecting to wallet at {}", wallet); - let wallet_client = connect_wallet_with_authenticator(&config).await?; + let base_node_client = BaseNodeGrpcClient::connect(format!("http://{}", base_node)).await?; + let wallet_addr = multiaddr_to_socketaddr(&config.console_wallet_grpc_address)?; + info!(target: LOG_TARGET, "Connecting to wallet at {}", wallet_addr); + let wallet_addr = format!("http://{}", wallet_addr); + let wallet_client = + WalletGrpcClient::connect_with_auth(&wallet_addr, &config.console_wallet_grpc_authentication).await?; let listen_addr = multiaddr_to_socketaddr(&config.listener_address)?; let randomx_factory = RandomXFactory::new(config.max_randomx_vms); let xmrig_service = MergeMiningProxyService::new( diff --git a/applications/tari_merge_mining_proxy/src/proxy.rs b/applications/tari_merge_mining_proxy/src/proxy.rs index 667cb21320..c4cbf17b9b 100644 --- a/applications/tari_merge_mining_proxy/src/proxy.rs +++ b/applications/tari_merge_mining_proxy/src/proxy.rs @@ -40,12 +40,13 @@ use json::json; use jsonrpc::error::StandardError; use reqwest::{ResponseBuilderExt, Url}; use serde_json as json; -use tari_app_grpc::tari_rpc as grpc; +use tari_base_node_grpc_client::{grpc, BaseNodeGrpcClient}; use tari_core::{ consensus::ConsensusEncoding, proof_of_work::{monero_difficulty, monero_rx, monero_rx::FixedByteArray, randomx_factory::RandomXFactory}, }; use tari_utilities::hex::Hex; +use tari_wallet_grpc_client::WalletGrpcClient; use tracing::{debug, error, info, instrument, trace, warn}; use crate::{ @@ -54,7 +55,6 @@ use crate::{ common::{json_rpc, monero_rpc::CoreRpcErrorCode, proxy, proxy::convert_json_to_hyper_json_response}, config::MergeMiningProxyConfig, error::MmProxyError, - WalletGrpcClient, }; const LOG_TARGET: &str = "tari_mm_proxy::proxy"; @@ -72,8 +72,8 @@ impl MergeMiningProxyService { pub fn new( config: MergeMiningProxyConfig, http_client: reqwest::Client, - base_node_client: grpc::base_node_client::BaseNodeClient, - wallet_client: WalletGrpcClient, + base_node_client: BaseNodeGrpcClient, + wallet_client: WalletGrpcClient, block_templates: BlockTemplateRepository, randomx_factory: RandomXFactory, ) -> Self { @@ -154,8 +154,8 @@ struct InnerService { config: MergeMiningProxyConfig, block_templates: BlockTemplateRepository, http_client: reqwest::Client, - base_node_client: grpc::base_node_client::BaseNodeClient, - wallet_client: WalletGrpcClient, + base_node_client: BaseNodeGrpcClient, + wallet_client: WalletGrpcClient, initial_sync_achieved: Arc, current_monerod_server: Arc>>, last_assigned_monerod_server: Arc>>, @@ -394,10 +394,7 @@ impl InnerService { initial_sync_achieved, metadata, .. - } = grpc_client - .get_tip_info(tari_app_grpc::tari_rpc::Empty {}) - .await? - .into_inner(); + } = grpc_client.get_tip_info(grpc::Empty {}).await?.into_inner(); if initial_sync_achieved { self.initial_sync_achieved.store(true, Ordering::Relaxed); diff --git a/base_layer/p2p/Cargo.toml b/base_layer/p2p/Cargo.toml index 6e70fdcbfe..1b1ed8425e 100644 --- a/base_layer/p2p/Cargo.toml +++ b/base_layer/p2p/Cargo.toml @@ -31,7 +31,7 @@ prost = "=0.9.0" rand = "0.8" reqwest = { version = "0.11", optional = true, default-features = false } rustls = "0.20.2" -semver = "1.0.1" +semver = { version = "1.0.1", optional = true } serde = "1.0.90" serde_derive = "1.0.90" thiserror = "1.0.26" @@ -55,6 +55,6 @@ tari_common = { version = "^0.38", path = "../../common", features = ["build"] } [features] test-mocks = [] -auto-update = ["reqwest/default", "pgp"] +auto-update = ["reqwest/default", "pgp" ,"semver"] avx2 = ["tari_crypto/simd_backend"] diff --git a/clients/base_node_grpc_client/README.md b/clients/nodejs/base_node_grpc_client/README.md similarity index 100% rename from clients/base_node_grpc_client/README.md rename to clients/nodejs/base_node_grpc_client/README.md diff --git a/clients/base_node_grpc_client/package.json b/clients/nodejs/base_node_grpc_client/package.json similarity index 100% rename from clients/base_node_grpc_client/package.json rename to clients/nodejs/base_node_grpc_client/package.json diff --git a/clients/base_node_grpc_client/src/index.js b/clients/nodejs/base_node_grpc_client/src/index.js similarity index 100% rename from clients/base_node_grpc_client/src/index.js rename to clients/nodejs/base_node_grpc_client/src/index.js diff --git a/clients/base_node_grpc_client/src/index.test.js b/clients/nodejs/base_node_grpc_client/src/index.test.js similarity index 100% rename from clients/base_node_grpc_client/src/index.test.js rename to clients/nodejs/base_node_grpc_client/src/index.test.js diff --git a/clients/wallet_grpc_client/.prettierrc b/clients/nodejs/wallet_grpc_client/.prettierrc similarity index 100% rename from clients/wallet_grpc_client/.prettierrc rename to clients/nodejs/wallet_grpc_client/.prettierrc diff --git a/clients/wallet_grpc_client/README.md b/clients/nodejs/wallet_grpc_client/README.md similarity index 100% rename from clients/wallet_grpc_client/README.md rename to clients/nodejs/wallet_grpc_client/README.md diff --git a/clients/wallet_grpc_client/index.js b/clients/nodejs/wallet_grpc_client/index.js similarity index 100% rename from clients/wallet_grpc_client/index.js rename to clients/nodejs/wallet_grpc_client/index.js diff --git a/clients/wallet_grpc_client/package.json b/clients/nodejs/wallet_grpc_client/package.json similarity index 100% rename from clients/wallet_grpc_client/package.json rename to clients/nodejs/wallet_grpc_client/package.json diff --git a/clients/rust/base_node_grpc_client/Cargo.toml b/clients/rust/base_node_grpc_client/Cargo.toml new file mode 100644 index 0000000000..37c2059b7f --- /dev/null +++ b/clients/rust/base_node_grpc_client/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "tari_base_node_grpc_client" +version = "0.1.0" +edition = "2021" +description = "Base node GRPC client" +authors = ["The Tari Development Community"] +repository = "https://github.com/tari-project/tari" +homepage = "https://tari.com" +readme = "README.md" +license = "BSD-3-Clause" + +[dependencies] +tari_app_grpc = { path = "../../../applications/tari_app_grpc" } + +#tonic = { version = "0.8", default-features = false, features = ["codegen", "transport", "prost"] } +#prost = "0.11.0" +#prost-types = "0.11.1" +#thiserror = "1.0.35" +#url = "2.3" + +[dev-dependencies] +tokio = { version = "1", features = ["macros"] } + +#[build-dependencies] +#tonic-build = "0.8.0" diff --git a/clients/rust/base_node_grpc_client/src/lib.rs b/clients/rust/base_node_grpc_client/src/lib.rs new file mode 100644 index 0000000000..f02143d130 --- /dev/null +++ b/clients/rust/base_node_grpc_client/src/lib.rs @@ -0,0 +1,24 @@ +// Copyright 2022, The Tari Project +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +// disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +pub use tari_app_grpc::tari_rpc as grpc; +pub type BaseNodeGrpcClient = grpc::base_node_client::BaseNodeClient; diff --git a/clients/rust/base_node_grpc_client/tests/client.rs b/clients/rust/base_node_grpc_client/tests/client.rs new file mode 100644 index 0000000000..0a8b488ae2 --- /dev/null +++ b/clients/rust/base_node_grpc_client/tests/client.rs @@ -0,0 +1,38 @@ +// Copyright 2022. The Tari Project +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +// disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use tari_base_node_grpc_client::{grpc, BaseNodeGrpcClient}; + +#[tokio::test] +async fn it_works() { + match BaseNodeGrpcClient::connect("http://127.0.0.1:18142").await { + Ok(mut client) => { + let _tip_info = client.get_tip_info(grpc::Empty {}).await; + #[cfg(debug_assertions)] + eprintln!("Tip info: {:?}", _tip_info); + }, + Err(_err) => { + #[cfg(debug_assertions)] + eprintln!("Could not connect: {:?}", _err); + }, + } +} diff --git a/clients/rust/wallet_grpc_client/Cargo.toml b/clients/rust/wallet_grpc_client/Cargo.toml new file mode 100644 index 0000000000..32f82c69ac --- /dev/null +++ b/clients/rust/wallet_grpc_client/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "tari_wallet_grpc_client" +version = "0.1.0" +edition = "2021" +description = "Base node GRPC client" +authors = ["The Tari Development Community"] +repository = "https://github.com/tari-project/tari" +homepage = "https://tari.com" +readme = "README.md" +license = "BSD-3-Clause" + +[dependencies] +tari_app_grpc = { path = "../../../applications/tari_app_grpc" } +tari_common_types = { path = "../../../base_layer/common_types" } + +thiserror = "1.0.35" +tonic = { version = "0.6", default-features = false, features = ["codegen", "transport"] } + +[dev-dependencies] +tokio = { version = "1", features = ["macros"] } diff --git a/clients/rust/wallet_grpc_client/src/lib.rs b/clients/rust/wallet_grpc_client/src/lib.rs new file mode 100644 index 0000000000..d610a6f5ec --- /dev/null +++ b/clients/rust/wallet_grpc_client/src/lib.rs @@ -0,0 +1,91 @@ +// Copyright 2022, The Tari Project +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +// disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use std::{ + ops::{Deref, DerefMut}, + str::FromStr, +}; + +use tonic::{ + codegen::{http::uri::InvalidUri, InterceptedService}, + transport::Endpoint, +}; + +pub type Client = grpc::wallet_client::WalletClient; + +// Re-export so that users don't have to depend on tari_app_grpc +pub use tari_app_grpc::{ + authentication::{BasicAuthError, ClientAuthenticationInterceptor}, + tari_rpc as grpc, +}; +pub use tari_common_types::grpc_authentication::GrpcAuthentication; + +#[derive(Debug, Clone)] +pub struct WalletGrpcClient { + client: Client>, +} + +impl WalletGrpcClient { + pub async fn connect(addr: &str) -> Result { + let channel = Endpoint::from_str(addr)?.connect().await?; + Ok(Self { + client: Client::::with_interceptor( + channel, + ClientAuthenticationInterceptor::create(&GrpcAuthentication::None)?, + ), + }) + } + + pub async fn connect_with_auth(addr: &str, auth_config: &GrpcAuthentication) -> Result { + let channel = Endpoint::from_str(addr)?.connect().await?; + Ok(Self { + client: Client::::with_interceptor( + channel, + ClientAuthenticationInterceptor::create(auth_config)?, + ), + }) + } +} + +impl Deref for WalletGrpcClient { + type Target = Client>; + + fn deref(&self) -> &Self::Target { + &self.client + } +} + +impl DerefMut for WalletGrpcClient { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.client + } +} + +#[derive(Debug, thiserror::Error)] +pub enum WalletClientError { + #[error(transparent)] + InvalidUri(#[from] InvalidUri), + #[error(transparent)] + TransportError(#[from] tonic::transport::Error), + #[error(transparent)] + AuthenticationError(#[from] BasicAuthError), +} diff --git a/clients/rust/wallet_grpc_client/tests/client.rs b/clients/rust/wallet_grpc_client/tests/client.rs new file mode 100644 index 0000000000..d28c2b74cd --- /dev/null +++ b/clients/rust/wallet_grpc_client/tests/client.rs @@ -0,0 +1,39 @@ +// Copyright 2022. The Tari Project +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +// disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use tari_wallet_grpc_client::{grpc, WalletGrpcClient}; + +#[tokio::test] +async fn it_works() { + // Basic test that only works if a wallet is running on localhost:18143 + match WalletGrpcClient::connect("http://127.0.0.1:18143").await { + Ok(mut client) => { + let _res = client.identify(grpc::GetIdentityRequest {}).await; + #[cfg(debug_assertions)] + eprintln!("Wallet identify: {:?}", _res); + }, + Err(_err) => { + #[cfg(debug_assertions)] + eprintln!("Could not connect: {:?}", _err); + }, + } +} diff --git a/integration_tests/package.json b/integration_tests/package.json index f38f423d1f..843a99241a 100644 --- a/integration_tests/package.json +++ b/integration_tests/package.json @@ -44,7 +44,7 @@ "sha3": "^2.1.3", "tari_crypto": "v0.14.0", "utf8": "^3.0.0", - "wallet-grpc-client": "file:../clients/wallet_grpc_client", + "wallet-grpc-client": "file:../clients/nodejs/wallet_grpc_client", "varint": "^6.0.0" } }