From c4d1dd789e053e4e40bda982c405eb911fd4846f Mon Sep 17 00:00:00 2001 From: Pawel Nowosielski Date: Mon, 22 Mar 2021 13:07:07 +0100 Subject: [PATCH] Payment driver list (#1146) * get DriverDetails & Network from ya_client contracts * fix: fix dummy driver compilation * feat: add cli 'payment drivers' command * feat: get data from payment processor * refactor: flat_map instead of map/flatten * remove 'recv init' column from the table result * chore: update ya-client rev --- Cargo.lock | 7 ++- Cargo.toml | 4 +- core/model/src/payment.rs | 24 ++++----- core/payment-driver/base/src/bus.rs | 3 +- core/payment-driver/base/src/driver.rs | 2 +- core/payment-driver/dummy/Cargo.toml | 1 + core/payment-driver/dummy/src/service.rs | 5 +- core/payment-driver/gnt/src/lib.rs | 2 +- core/payment-driver/gnt/src/networks.rs | 8 +-- core/payment/examples/payment_api.rs | 1 + core/payment/src/cli.rs | 62 +++++++++++++++++++----- core/payment/src/processor.rs | 14 +++++- core/payment/src/service.rs | 15 +++++- 13 files changed, 104 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ca68374aaf..b76b8ff483 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7363,8 +7363,7 @@ dependencies = [ [[package]] name = "ya-client" version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6be6d483d72a51534830a30df9471622d30686144b40677d158d781a0c74f545" +source = "git+https://github.com/golemfactory/ya-client.git?rev=24d7f520267b88ae0722d50e8044bf59b20ef699#24d7f520267b88ae0722d50e8044bf59b20ef699" dependencies = [ "awc 1.0.1", "bytes 0.5.6", @@ -7389,8 +7388,7 @@ dependencies = [ [[package]] name = "ya-client-model" version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f399f4c6753e090751b06f5937ce45bb6188ba0f9ba436383591c51af3347082" +source = "git+https://github.com/golemfactory/ya-client.git?rev=24d7f520267b88ae0722d50e8044bf59b20ef699#24d7f520267b88ae0722d50e8044bf59b20ef699" dependencies = [ "bigdecimal 0.2.0", "chrono", @@ -7461,6 +7459,7 @@ dependencies = [ "maplit", "serde_json", "uuid 0.8.2", + "ya-client-model", "ya-core-model", "ya-payment-driver", "ya-persistence", diff --git a/Cargo.toml b/Cargo.toml index b65ea525d8..4f78d286b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -175,8 +175,8 @@ ya-service-api-web = { path = "core/serv-api/web" } #ya-sb-util = { git = "https://github.com/golemfactory/ya-service-bus.git", rev = "6b494e17d7a662e0b710af8c5a2e99ab4007fdb9"} ## CLIENT -#ya-client = { git = "https://github.com/golemfactory/ya-client.git", rev = "479a7237ccb09f766346a2421d2ae0b30c307a4f" } -#ya-client-model = { git = "https://github.com/golemfactory/ya-client.git", rev = "479a7237ccb09f766346a2421d2ae0b30c307a4f" } +ya-client = { git = "https://github.com/golemfactory/ya-client.git", rev = "24d7f520267b88ae0722d50e8044bf59b20ef699" } +ya-client-model = { git = "https://github.com/golemfactory/ya-client.git", rev = "24d7f520267b88ae0722d50e8044bf59b20ef699" } # ya-client = { path = "../ya-client" } # ya-client-model = { path = "../ya-client/model" } diff --git a/core/model/src/payment.rs b/core/model/src/payment.rs index b14f2bed6e..c413695dc2 100644 --- a/core/model/src/payment.rs +++ b/core/model/src/payment.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use std::collections::HashMap; use ya_client_model::payment::*; use ya_service_bus::RpcMessage; @@ -21,7 +22,6 @@ pub mod local { use crate::driver::{AccountMode, PaymentConfirmation}; use bigdecimal::{BigDecimal, Zero}; use chrono::{DateTime, Utc}; - use std::collections::HashMap; use std::fmt::Display; use structopt::*; use strum::{EnumProperty, VariantNames}; @@ -145,19 +145,6 @@ pub mod local { #[error("")] pub struct NoError {} // This is needed because () doesn't implement Display - #[derive(Clone, Debug, Serialize, Deserialize)] - pub struct Network { - pub default_token: String, - pub tokens: HashMap, // token -> platform - } - - #[derive(Clone, Debug, Serialize, Deserialize)] - pub struct DriverDetails { - pub default_network: String, - pub networks: HashMap, - pub recv_init_required: bool, // Is account initialization required for receiving payments - } - #[derive(Clone, Debug, Serialize, Deserialize)] pub struct RegisterDriver { pub driver_name: String, @@ -405,6 +392,15 @@ pub mod local { Other(String), } + #[derive(Clone, Debug, Serialize, Deserialize)] + pub struct GetDrivers {} + + impl RpcMessage for GetDrivers { + const ID: &'static str = "GetDrivers"; + type Item = HashMap; + type Error = NoError; + } + /// Experimental. In future releases this might change or be removed. #[derive( EnumString, diff --git a/core/payment-driver/base/src/bus.rs b/core/payment-driver/base/src/bus.rs index 037d0a9b2e..ac1cb634c8 100644 --- a/core/payment-driver/base/src/bus.rs +++ b/core/payment-driver/base/src/bus.rs @@ -8,6 +8,7 @@ use std::sync::Arc; // Workspace uses +use ya_client_model::payment::driver_details::DriverDetails; use ya_client_model::NodeId; use ya_core_model::driver::{ driver_bus_id, AccountMode, GenericError, PaymentConfirmation, PaymentDetails, @@ -85,7 +86,7 @@ pub async fn bind_service( log::debug!("Registering driver in payment service..."); let message = payment_srv::RegisterDriver { driver_name: driver.get_name(), - details: payment_srv::DriverDetails { + details: DriverDetails { default_network: driver.get_default_network(), networks: driver.get_networks(), recv_init_required: driver.recv_init_required(), diff --git a/core/payment-driver/base/src/driver.rs b/core/payment-driver/base/src/driver.rs index 1f333d971f..e15e81cd8c 100644 --- a/core/payment-driver/base/src/driver.rs +++ b/core/payment-driver/base/src/driver.rs @@ -18,9 +18,9 @@ use crate::utils; // Public revealed uses, required to implement this trait pub use async_trait::async_trait; pub use bigdecimal::BigDecimal; +pub use ya_client_model::payment::network::Network; pub use ya_client_model::NodeId; pub use ya_core_model::identity::{event::Event as IdentityEvent, Error as IdentityError}; -pub use ya_core_model::payment::local::Network; #[async_trait(?Send)] pub trait PaymentDriver { diff --git a/core/payment-driver/dummy/Cargo.toml b/core/payment-driver/dummy/Cargo.toml index b54ee1aca1..2c47404362 100644 --- a/core/payment-driver/dummy/Cargo.toml +++ b/core/payment-driver/dummy/Cargo.toml @@ -9,6 +9,7 @@ default = [] [dependencies] ya-core-model = { version = "^0.3", features = ["driver", "identity", "payment"] } +ya-client-model = { version = "0.3" } ya-payment-driver = "0.2" ya-persistence = "0.2" ya-service-api-interfaces = "0.1" diff --git a/core/payment-driver/dummy/src/service.rs b/core/payment-driver/dummy/src/service.rs index 59c398359a..e957e7ad30 100644 --- a/core/payment-driver/dummy/src/service.rs +++ b/core/payment-driver/dummy/src/service.rs @@ -5,6 +5,7 @@ use chrono::Utc; use maplit::hashmap; use std::str::FromStr; use uuid::Uuid; +use ya_client_model::payment::{DriverDetails, Network}; use ya_core_model::driver::*; use ya_core_model::payment::local as payment_srv; use ya_service_bus::typed::service; @@ -28,10 +29,10 @@ pub fn bind_service() { pub async fn register_in_payment_service() -> anyhow::Result<()> { log::debug!("Registering driver in payment service..."); - let details = payment_srv::DriverDetails { + let details = DriverDetails { default_network: NETWORK_NAME.to_string(), networks: hashmap! { - NETWORK_NAME.to_string() => payment_srv::Network { + NETWORK_NAME.to_string() => Network { default_token: TOKEN_NAME.to_string(), tokens: hashmap! { TOKEN_NAME.to_string() => PLATFORM_NAME.to_string() diff --git a/core/payment-driver/gnt/src/lib.rs b/core/payment-driver/gnt/src/lib.rs index ec7a0e124f..3151829424 100644 --- a/core/payment-driver/gnt/src/lib.rs +++ b/core/payment-driver/gnt/src/lib.rs @@ -47,11 +47,11 @@ use std::time; use uuid::Uuid; use web3::contract::Contract; use web3::transports::Http; +use ya_client_model::payment::driver_details::DriverDetails; use ya_client_model::payment::Allocation; use ya_client_model::NodeId; use ya_core_model::driver::{AccountMode, PaymentConfirmation, PaymentDetails}; use ya_core_model::identity; -use ya_core_model::payment::local::DriverDetails; use ya_persistence::executor::DbExecutor; use ya_service_api_interfaces::Provider; use ya_service_bus::typed as bus; diff --git a/core/payment-driver/gnt/src/networks.rs b/core/payment-driver/gnt/src/networks.rs index 307d88e7f9..89c2d64727 100644 --- a/core/payment-driver/gnt/src/networks.rs +++ b/core/payment-driver/gnt/src/networks.rs @@ -8,7 +8,7 @@ use maplit::hashmap; use serde::{Deserialize, Serialize}; use std::fmt::{Display, Formatter, Result as FmtResult}; use std::str::FromStr; -use ya_core_model::payment::local as pay_srv; +use ya_client_model::payment::network as pay_model; #[derive(AsExpression, FromSqlRow, PartialEq, Debug, Clone, Copy, FromPrimitive)] #[sql_type = "Integer"] @@ -40,14 +40,14 @@ impl Default for Network { } } -impl Into for Network { - fn into(self) -> pay_srv::Network { +impl Into for Network { + fn into(self) -> pay_model::Network { let default_token = self.default_token(); let default_platform = self.default_platform(); let tokens = hashmap! { default_token.clone() => default_platform }; - pay_srv::Network { + pay_model::Network { default_token, tokens, } diff --git a/core/payment/examples/payment_api.rs b/core/payment/examples/payment_api.rs index 705b1ea26f..25c59d35aa 100644 --- a/core/payment/examples/payment_api.rs +++ b/core/payment/examples/payment_api.rs @@ -223,6 +223,7 @@ async fn main() -> anyhow::Result<()> { erc20::DRIVER_NAME } Driver::Zksync => { + start_dummy_driver().await?; start_zksync_driver(&db, requestor_account).await?; zksync::DRIVER_NAME } diff --git a/core/payment/src/cli.rs b/core/payment/src/cli.rs index 46ee5513f8..1ea48bad6a 100644 --- a/core/payment/src/cli.rs +++ b/core/payment/src/cli.rs @@ -76,6 +76,9 @@ pub enum PaymentCli { #[structopt(subcommand)] command: InvoiceCommand, }, + + /// List registered drivers, networks, tokens and platforms + Drivers, } #[derive(StructOpt, Debug)] @@ -246,17 +249,54 @@ impl PaymentCli { .await?, ) } // TODO: Uncomment when operation is supported by drivers - // PaymentCli::Transfer { - // account, - // driver, - // network, - // to_address, - // amount - // } => { - // let address = resolve_address(account).await?; - // let amount = BigDecimal::from_str(&amount)?; - // CommandOutput::object(wallet::transfer(address, to_address, amount, driver, network, token).await?) - // } + // PaymentCli::Transfer { + // account, + // driver, + // network, + // to_address, + // amount + // } => { + // let address = resolve_address(account).await?; + // let amount = BigDecimal::from_str(&amount)?; + // CommandOutput::object(wallet::transfer(address, to_address, amount, driver, network, token).await?) + // } + PaymentCli::Drivers => { + let drivers = bus::service(pay::BUS_ID).call(pay::GetDrivers {}).await??; + if ctx.json_output { + return CommandOutput::object(drivers); + } + Ok(ResponseTable { columns: vec![ + "driver".to_owned(), + "network".to_owned(), + "default?".to_owned(), + "token".to_owned(), + "default?".to_owned(), + "platform".to_owned(), + ], values: drivers + .iter() + .flat_map(|(driver, dd)| { + dd.networks + .iter() + .flat_map(|(network, n)| { + n.tokens + .iter() + .map(|(token, platform)| + serde_json::json! {[ + driver, + network, + if &dd.default_network == network { "X" } else { "" }, + token, + if &n.default_token == token { "X" } else { "" }, + platform, + ]} + ) + .collect::>() + }) + .collect::>() + }) + .collect() + }.into()) + } } } } diff --git a/core/payment/src/processor.rs b/core/payment/src/processor.rs index e349e52675..de3e9aa848 100644 --- a/core/payment/src/processor.rs +++ b/core/payment/src/processor.rs @@ -10,13 +10,15 @@ use futures::FutureExt; use metrics::counter; use std::collections::hash_map::Entry; use std::collections::HashMap; +use ya_client_model::payment::driver_details::DriverDetails; +use ya_client_model::payment::network::Network; use ya_client_model::payment::{Account, ActivityPayment, AgreementPayment, Payment}; use ya_core_model::driver::{ self, driver_bus_id, AccountMode, PaymentConfirmation, PaymentDetails, ValidateAllocation, }; use ya_core_model::payment::local::{ - DriverDetails, Network, NotifyPayment, RegisterAccount, RegisterAccountError, RegisterDriver, - RegisterDriverError, SchedulePayment, UnregisterAccount, UnregisterDriver, + NotifyPayment, RegisterAccount, RegisterAccountError, RegisterDriver, RegisterDriverError, + SchedulePayment, UnregisterAccount, UnregisterDriver, }; use ya_core_model::payment::public::{SendPayment, BUS_ID}; use ya_net::RemoteEndpoint; @@ -198,6 +200,10 @@ impl DriverRegistry { } } + pub fn get_drivers(&self) -> HashMap { + self.drivers.clone() + } + pub fn get_network( &self, driver: String, @@ -303,6 +309,10 @@ impl PaymentProcessor { self.registry.get_accounts() } + pub async fn get_drivers(&self) -> HashMap { + self.registry.get_drivers() + } + pub async fn get_network( &self, driver: String, diff --git a/core/payment/src/service.rs b/core/payment/src/service.rs index debb38eafc..68f29e23ae 100644 --- a/core/payment/src/service.rs +++ b/core/payment/src/service.rs @@ -2,6 +2,7 @@ use crate::processor::PaymentProcessor; use futures::lock::Mutex; use futures::prelude::*; use metrics::counter; +use std::collections::HashMap; use std::sync::Arc; use ya_core_model as core; use ya_persistence::executor::DbExecutor; @@ -21,7 +22,7 @@ mod local { use super::*; use crate::dao::*; use std::collections::BTreeMap; - use ya_client_model::payment::{Account, DocumentStatus}; + use ya_client_model::payment::{Account, DocumentStatus, DriverDetails}; use ya_core_model::payment::local::*; use ya_persistence::types::Role; @@ -38,7 +39,8 @@ mod local { .bind_with_processor(get_status) .bind_with_processor(get_invoice_stats) .bind_with_processor(get_accounts) - .bind_with_processor(validate_allocation); + .bind_with_processor(validate_allocation) + .bind_with_processor(get_drivers); // Initialize counters to 0 value. Otherwise they won't appear on metrics endpoint // until first change to value will be made. @@ -275,6 +277,15 @@ mod local { .validate_allocation(msg.platform, msg.address, msg.amount) .await?) } + + async fn get_drivers( + db: DbExecutor, + processor: Arc>, + _caller: String, + msg: GetDrivers, + ) -> Result, NoError> { + Ok(processor.lock().await.get_drivers().await) + } } mod public {