diff --git a/.github/workflows/build-rust.yml b/.github/workflows/build-rust.yml index 64aae9702..1a7bc578c 100644 --- a/.github/workflows/build-rust.yml +++ b/.github/workflows/build-rust.yml @@ -25,5 +25,9 @@ jobs: working-directory: ./cli steps: - uses: actions/checkout@v1 - - run: cargo build - - run: cargo test + - run: | + rustup install nightly + rustup default nightly + rustup component add rustfmt + cargo build + cargo test diff --git a/cli/Cargo.toml b/cli/Cargo.toml index 27d5d57c5..5357f2c9b 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -2,12 +2,12 @@ name = "trinsic" version = "0.1.0" authors = ["Trinsic "] -edition = "2018" +edition = "2021" [dependencies] -tonic = "0.4" -prost = "0.7" -prost-types = "0.7" +tonic = { version = "0.6", features = ["tls", "tls-roots"] } +prost = "0.9" +prost-types = "0.9" tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } okapi = { git ="https://github.com/trinsic-id/okapi", branch = "main" } clap = { version = "~2", features = ["yaml"] } @@ -21,8 +21,7 @@ yaml-rust = "0.3" colored = "2" [build-dependencies] -tonic-build = "0.4" -prost-build = "0.7" +tonic-build = { version = "0.6", features = ["prost", "rustfmt"] } [[bin]] name = "trinsic" diff --git a/cli/MAINTAINERS.md b/cli/MAINTAINERS.md index a62a3ad88..54805baca 100644 --- a/cli/MAINTAINERS.md +++ b/cli/MAINTAINERS.md @@ -1,3 +1,9 @@ -# Okapi CLI Maintainers +# Trinsic CLI Maintainers -Before checking in your code, please always run `cargo fmt` and `cargo clippy`. \ No newline at end of file +Before checking in your code, please always run `cargo fmt` and `cargo clippy`. + +## Tooling + +- [clap](https://github.com/clap-rs/clap) - command line argument parser for Rust +- [tonic](https://github.com/hyperium/tonic) - gRPC framework +- [prost](https://github.com/danburkert/prost) - protocol buffer implementation \ No newline at end of file diff --git a/cli/README.md b/cli/README.md index e6c0137c7..02980fe02 100644 --- a/cli/README.md +++ b/cli/README.md @@ -2,19 +2,13 @@ ## Installation -Requires [Rustup](https://www.rust-lang.org/tools/install) toolchain +Requires [Rustup](https://www.rust-lang.org/tools/install) nightly toolchain ```bash -cargo install --path . +cargo +nightly install --git https://github.com/trinsic-id/sdk trinsic ``` -## Tooling - -- [clap](https://github.com/clap-rs/clap) - command line argument parser for Rust -- [tonic](https://github.com/hyperium/tonic) - gRPC framework -- [prost](https://github.com/danburkert/prost) - protocol buffer implementation - -## Running the CLI +## Usage ``` trinsic --help diff --git a/cli/build.rs b/cli/build.rs index 1c2b3a800..76a9af116 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -6,11 +6,8 @@ fn main() { .out_dir("./src/proto") .format(true); - let mut prost_config = prost_build::Config::new(); - prost_config.compile_well_known_types(); - //.type_attribute(".", "#[derive(::serde::Serialize, ::serde::Deserialize)]"); - config + .compile_well_known_types(true) .type_attribute( "JsonPayload", "#[derive(::serde::Serialize, ::serde::Deserialize)]", @@ -19,8 +16,7 @@ fn main() { "JsonPayload.json", "#[derive(::serde::Serialize, ::serde::Deserialize)]", ) - .compile_with_config( - prost_config, + .compile( &[ "../proto/pbmse/v1/pbmse.proto", "../proto/services/debug/v1/debug.proto", @@ -34,39 +30,39 @@ fn main() { ) .unwrap(); - cleanup!( + move_file!( "./src/proto/google.protobuf.rs", "./src/proto/google/protobuf/mod.rs" ); - cleanup!("./src/proto/pbmse.v1.rs", "./src/proto/pbmse/v1/mod.rs"); - cleanup!( + move_file!("./src/proto/pbmse.v1.rs", "./src/proto/pbmse/v1/mod.rs"); + move_file!( "./src/proto/services.common.v1.rs", "./src/proto/services/common/v1/mod.rs" ); - cleanup!( + move_file!( "./src/proto/services.debug.v1.rs", "./src/proto/services/debug/v1/mod.rs" ); - cleanup!( + move_file!( "./src/proto/services.provider.v1.rs", "./src/proto/services/provider/v1/mod.rs" ); - cleanup!( + move_file!( "./src/proto/services.trustregistry.v1.rs", "./src/proto/services/trustregistry/v1/mod.rs" ); - cleanup!( + move_file!( "./src/proto/services.universalwallet.v1.rs", "./src/proto/services/universalwallet/v1/mod.rs" ); - cleanup!( + move_file!( "./src/proto/services.verifiablecredentials.v1.rs", "./src/proto/services/verifiablecredentials/v1/mod.rs" ); } #[macro_export] -macro_rules! cleanup { +macro_rules! move_file { ($from:expr,$to:expr) => { copy($from, $to).unwrap(); remove_file($from).unwrap(); diff --git a/cli/src/proto/services/common/v1/mod.rs b/cli/src/proto/services/common/v1/mod.rs index eac6a64e9..a6f956fa4 100644 --- a/cli/src/proto/services/common/v1/mod.rs +++ b/cli/src/proto/services/common/v1/mod.rs @@ -39,8 +39,9 @@ pub enum JsonFormat { } #[doc = r" Generated client implementations."] pub mod common_client { - #![allow(unused_variables, dead_code, missing_docs)] + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] use tonic::codegen::*; + #[derive(Debug, Clone)] pub struct CommonClient { inner: tonic::client::Grpc, } @@ -58,17 +59,43 @@ pub mod common_client { impl CommonClient where T: tonic::client::GrpcService, - T::ResponseBody: Body + HttpBody + Send + 'static, + T::ResponseBody: Body + Send + 'static, T::Error: Into, - ::Error: Into + Send, + ::Error: Into + Send, { pub fn new(inner: T) -> Self { let inner = tonic::client::Grpc::new(inner); Self { inner } } - pub fn with_interceptor(inner: T, interceptor: impl Into) -> Self { - let inner = tonic::client::Grpc::with_interceptor(inner, interceptor); - Self { inner } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> CommonClient> + where + F: tonic::service::Interceptor, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + >>::Error: + Into + Send + Sync, + { + CommonClient::new(InterceptedService::new(inner, interceptor)) + } + #[doc = r" Compress requests with `gzip`."] + #[doc = r""] + #[doc = r" This requires the server to support it otherwise it might respond with an"] + #[doc = r" error."] + pub fn send_gzip(mut self) -> Self { + self.inner = self.inner.send_gzip(); + self + } + #[doc = r" Enable decompressing responses with `gzip`."] + pub fn accept_gzip(mut self) -> Self { + self.inner = self.inner.accept_gzip(); + self } pub async fn request( &mut self, @@ -88,16 +115,4 @@ pub mod common_client { self.inner.unary(request.into_request(), path, codec).await } } - impl Clone for CommonClient { - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - } - } - } - impl std::fmt::Debug for CommonClient { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "CommonClient {{ ... }}") - } - } } diff --git a/cli/src/proto/services/debug/v1/mod.rs b/cli/src/proto/services/debug/v1/mod.rs index c7bd52b48..a793c7c70 100644 --- a/cli/src/proto/services/debug/v1/mod.rs +++ b/cli/src/proto/services/debug/v1/mod.rs @@ -1,7 +1,8 @@ #[doc = r" Generated client implementations."] pub mod debugging_client { - #![allow(unused_variables, dead_code, missing_docs)] + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] use tonic::codegen::*; + #[derive(Debug, Clone)] pub struct DebuggingClient { inner: tonic::client::Grpc, } @@ -19,23 +20,51 @@ pub mod debugging_client { impl DebuggingClient where T: tonic::client::GrpcService, - T::ResponseBody: Body + HttpBody + Send + 'static, + T::ResponseBody: Body + Send + 'static, T::Error: Into, - ::Error: Into + Send, + ::Error: Into + Send, { pub fn new(inner: T) -> Self { let inner = tonic::client::Grpc::new(inner); Self { inner } } - pub fn with_interceptor(inner: T, interceptor: impl Into) -> Self { - let inner = tonic::client::Grpc::with_interceptor(inner, interceptor); - Self { inner } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> DebuggingClient> + where + F: tonic::service::Interceptor, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + >>::Error: + Into + Send + Sync, + { + DebuggingClient::new(InterceptedService::new(inner, interceptor)) + } + #[doc = r" Compress requests with `gzip`."] + #[doc = r""] + #[doc = r" This requires the server to support it otherwise it might respond with an"] + #[doc = r" error."] + pub fn send_gzip(mut self) -> Self { + self.inner = self.inner.send_gzip(); + self + } + #[doc = r" Enable decompressing responses with `gzip`."] + pub fn accept_gzip(mut self) -> Self { + self.inner = self.inner.accept_gzip(); + self } pub async fn call_empty( &mut self, - request: impl tonic::IntoRequest, - ) -> Result, tonic::Status> - { + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { self.inner.ready().await.map_err(|e| { tonic::Status::new( tonic::Code::Unknown, @@ -49,9 +78,11 @@ pub mod debugging_client { } pub async fn call_empty_auth( &mut self, - request: impl tonic::IntoRequest, - ) -> Result, tonic::Status> - { + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { self.inner.ready().await.map_err(|e| { tonic::Status::new( tonic::Code::Unknown, @@ -64,16 +95,4 @@ pub mod debugging_client { self.inner.unary(request.into_request(), path, codec).await } } - impl Clone for DebuggingClient { - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - } - } - } - impl std::fmt::Debug for DebuggingClient { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "DebuggingClient {{ ... }}") - } - } } diff --git a/cli/src/proto/services/provider/v1/mod.rs b/cli/src/proto/services/provider/v1/mod.rs index c0808a5e0..2cef55bed 100644 --- a/cli/src/proto/services/provider/v1/mod.rs +++ b/cli/src/proto/services/provider/v1/mod.rs @@ -65,8 +65,9 @@ pub enum ParticipantType { } #[doc = r" Generated client implementations."] pub mod provider_client { - #![allow(unused_variables, dead_code, missing_docs)] + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] use tonic::codegen::*; + #[derive(Debug, Clone)] pub struct ProviderClient { inner: tonic::client::Grpc, } @@ -84,17 +85,43 @@ pub mod provider_client { impl ProviderClient where T: tonic::client::GrpcService, - T::ResponseBody: Body + HttpBody + Send + 'static, + T::ResponseBody: Body + Send + 'static, T::Error: Into, - ::Error: Into + Send, + ::Error: Into + Send, { pub fn new(inner: T) -> Self { let inner = tonic::client::Grpc::new(inner); Self { inner } } - pub fn with_interceptor(inner: T, interceptor: impl Into) -> Self { - let inner = tonic::client::Grpc::with_interceptor(inner, interceptor); - Self { inner } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> ProviderClient> + where + F: tonic::service::Interceptor, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + >>::Error: + Into + Send + Sync, + { + ProviderClient::new(InterceptedService::new(inner, interceptor)) + } + #[doc = r" Compress requests with `gzip`."] + #[doc = r""] + #[doc = r" This requires the server to support it otherwise it might respond with an"] + #[doc = r" error."] + pub fn send_gzip(mut self) -> Self { + self.inner = self.inner.send_gzip(); + self + } + #[doc = r" Enable decompressing responses with `gzip`."] + pub fn accept_gzip(mut self) -> Self { + self.inner = self.inner.accept_gzip(); + self } #[doc = " rpc CreateOrganization(CreateOrganizationRequest) returns (CreateOrganizationResponse);"] pub async fn invite( @@ -145,16 +172,4 @@ pub mod provider_client { self.inner.unary(request.into_request(), path, codec).await } } - impl Clone for ProviderClient { - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - } - } - } - impl std::fmt::Debug for ProviderClient { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "ProviderClient {{ ... }}") - } - } } diff --git a/cli/src/proto/services/trustregistry/v1/mod.rs b/cli/src/proto/services/trustregistry/v1/mod.rs index 135faf7a5..fc24aae19 100644 --- a/cli/src/proto/services/trustregistry/v1/mod.rs +++ b/cli/src/proto/services/trustregistry/v1/mod.rs @@ -239,8 +239,9 @@ pub enum RegistrationStatus { } #[doc = r" Generated client implementations."] pub mod trust_registry_client { - #![allow(unused_variables, dead_code, missing_docs)] + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] use tonic::codegen::*; + #[derive(Debug, Clone)] pub struct TrustRegistryClient { inner: tonic::client::Grpc, } @@ -258,17 +259,43 @@ pub mod trust_registry_client { impl TrustRegistryClient where T: tonic::client::GrpcService, - T::ResponseBody: Body + HttpBody + Send + 'static, + T::ResponseBody: Body + Send + 'static, T::Error: Into, - ::Error: Into + Send, + ::Error: Into + Send, { pub fn new(inner: T) -> Self { let inner = tonic::client::Grpc::new(inner); Self { inner } } - pub fn with_interceptor(inner: T, interceptor: impl Into) -> Self { - let inner = tonic::client::Grpc::with_interceptor(inner, interceptor); - Self { inner } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> TrustRegistryClient> + where + F: tonic::service::Interceptor, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + >>::Error: + Into + Send + Sync, + { + TrustRegistryClient::new(InterceptedService::new(inner, interceptor)) + } + #[doc = r" Compress requests with `gzip`."] + #[doc = r""] + #[doc = r" This requires the server to support it otherwise it might respond with an"] + #[doc = r" error."] + pub fn send_gzip(mut self) -> Self { + self.inner = self.inner.send_gzip(); + self + } + #[doc = r" Enable decompressing responses with `gzip`."] + pub fn accept_gzip(mut self) -> Self { + self.inner = self.inner.accept_gzip(); + self } #[doc = " Adds a trust registry defintion to the ecosystem"] pub async fn add_framework( @@ -439,16 +466,4 @@ pub mod trust_registry_client { .await } } - impl Clone for TrustRegistryClient { - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - } - } - } - impl std::fmt::Debug for TrustRegistryClient { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "TrustRegistryClient {{ ... }}") - } - } } diff --git a/cli/src/proto/services/universalwallet/v1/mod.rs b/cli/src/proto/services/universalwallet/v1/mod.rs index 1c55d9a90..155267bbd 100644 --- a/cli/src/proto/services/universalwallet/v1/mod.rs +++ b/cli/src/proto/services/universalwallet/v1/mod.rs @@ -154,8 +154,9 @@ pub struct InsertItemResponse { } #[doc = r" Generated client implementations."] pub mod wallet_client { - #![allow(unused_variables, dead_code, missing_docs)] + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] use tonic::codegen::*; + #[derive(Debug, Clone)] pub struct WalletClient { inner: tonic::client::Grpc, } @@ -173,17 +174,43 @@ pub mod wallet_client { impl WalletClient where T: tonic::client::GrpcService, - T::ResponseBody: Body + HttpBody + Send + 'static, + T::ResponseBody: Body + Send + 'static, T::Error: Into, - ::Error: Into + Send, + ::Error: Into + Send, { pub fn new(inner: T) -> Self { let inner = tonic::client::Grpc::new(inner); Self { inner } } - pub fn with_interceptor(inner: T, interceptor: impl Into) -> Self { - let inner = tonic::client::Grpc::with_interceptor(inner, interceptor); - Self { inner } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> WalletClient> + where + F: tonic::service::Interceptor, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + >>::Error: + Into + Send + Sync, + { + WalletClient::new(InterceptedService::new(inner, interceptor)) + } + #[doc = r" Compress requests with `gzip`."] + #[doc = r""] + #[doc = r" This requires the server to support it otherwise it might respond with an"] + #[doc = r" error."] + pub fn send_gzip(mut self) -> Self { + self.inner = self.inner.send_gzip(); + self + } + #[doc = r" Enable decompressing responses with `gzip`."] + pub fn accept_gzip(mut self) -> Self { + self.inner = self.inner.accept_gzip(); + self } pub async fn get_provider_configuration( &mut self, @@ -333,16 +360,4 @@ pub mod wallet_client { self.inner.unary(request.into_request(), path, codec).await } } - impl Clone for WalletClient { - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - } - } - } - impl std::fmt::Debug for WalletClient { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "WalletClient {{ ... }}") - } - } } diff --git a/cli/src/proto/services/verifiablecredentials/v1/mod.rs b/cli/src/proto/services/verifiablecredentials/v1/mod.rs index 43dc1e415..119ea9dd7 100644 --- a/cli/src/proto/services/verifiablecredentials/v1/mod.rs +++ b/cli/src/proto/services/verifiablecredentials/v1/mod.rs @@ -65,8 +65,9 @@ pub struct SendResponse { } #[doc = r" Generated client implementations."] pub mod credential_client { - #![allow(unused_variables, dead_code, missing_docs)] + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] use tonic::codegen::*; + #[derive(Debug, Clone)] pub struct CredentialClient { inner: tonic::client::Grpc, } @@ -84,17 +85,43 @@ pub mod credential_client { impl CredentialClient where T: tonic::client::GrpcService, - T::ResponseBody: Body + HttpBody + Send + 'static, + T::ResponseBody: Body + Send + 'static, T::Error: Into, - ::Error: Into + Send, + ::Error: Into + Send, { pub fn new(inner: T) -> Self { let inner = tonic::client::Grpc::new(inner); Self { inner } } - pub fn with_interceptor(inner: T, interceptor: impl Into) -> Self { - let inner = tonic::client::Grpc::with_interceptor(inner, interceptor); - Self { inner } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> CredentialClient> + where + F: tonic::service::Interceptor, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + >>::Error: + Into + Send + Sync, + { + CredentialClient::new(InterceptedService::new(inner, interceptor)) + } + #[doc = r" Compress requests with `gzip`."] + #[doc = r""] + #[doc = r" This requires the server to support it otherwise it might respond with an"] + #[doc = r" error."] + pub fn send_gzip(mut self) -> Self { + self.inner = self.inner.send_gzip(); + self + } + #[doc = r" Enable decompressing responses with `gzip`."] + pub fn accept_gzip(mut self) -> Self { + self.inner = self.inner.accept_gzip(); + self } pub async fn issue( &mut self, @@ -177,16 +204,4 @@ pub mod credential_client { self.inner.unary(request.into_request(), path, codec).await } } - impl Clone for CredentialClient { - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - } - } - } - impl std::fmt::Debug for CredentialClient { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "CredentialClient {{ ... }}") - } - } } diff --git a/cli/src/services/config.rs b/cli/src/services/config.rs index 5a3a400c7..d6cab96a4 100644 --- a/cli/src/services/config.rs +++ b/cli/src/services/config.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use std::{env::var, path::Path}; use std::{fs, io::prelude::*}; use std::{fs::OpenOptions, path::PathBuf}; -use tonic::{Interceptor, Request}; +use tonic::service::Interceptor; use trinsic::proto::services::universalwallet::v1::WalletProfile; use trinsic::MessageFormatter; @@ -221,19 +221,35 @@ impl Config { } } -#[allow(clippy::from_over_into)] -impl Into for Config { - fn into(self) -> Interceptor { - Interceptor::new(move |mut req: Request<()>| { - req.metadata_mut().insert( - "capability-invocation", - self.read_capability() - .expect("couldn't read capability document") - .parse() - .expect("error parsing capability"), - ); - Ok(req) - }) +// #[allow(clippy::from_over_into)] +// impl Into for Config { +// fn into(self) -> Interceptor { +// Interceptor::new(move |mut req: Request<()>| { +// req.metadata_mut().insert( +// "capability-invocation", +// self.read_capability() +// .expect("couldn't read capability document") +// .parse() +// .expect("error parsing capability"), +// ); +// Ok(req) +// }) +// } +// } + +impl Interceptor for Config { + fn call( + &mut self, + mut request: tonic::Request<()>, + ) -> Result, tonic::Status> { + request.metadata_mut().insert( + "capability-invocation", + self.read_capability() + .expect("couldn't read capability document") + .parse() + .expect("error parsing capability"), + ); + Ok(request) } } diff --git a/cli/src/services/wallet.rs b/cli/src/services/wallet.rs index dc3b5899e..27cccbf47 100644 --- a/cli/src/services/wallet.rs +++ b/cli/src/services/wallet.rs @@ -52,7 +52,7 @@ async fn create(args: &CreateArgs, config: Config) -> Result<(), Error> { } None => DIDKey::generate(&GenerateKeyRequest { seed: vec![], - key_type: 0, + key_type: KeyType::Ed25519 as i32, }) .unwrap(), }; @@ -64,9 +64,13 @@ async fn create(args: &CreateArgs, config: Config) -> Result<(), Error> { None => "My Cloud Wallet".to_string(), }; - let mut client = WalletClient::connect(config.server.address) + let channel = Channel::from_shared(config.server.address) + .unwrap() + .connect() .await - .expect("Unable to connect to server"); + .unwrap(); + + let mut client = WalletClient::new(channel); let request = tonic::Request::new(CreateWalletRequest { controller: key.key[0].kid.clone(),