Skip to content
This repository has been archived by the owner on Feb 29, 2024. It is now read-only.

Implemented wallet service #1

Merged
merged 14 commits into from
Mar 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ log = "0.3.7"
zmq = "0.8.1"
openssl = "0.9.9"
int_traits = "0.1.1"
rusqlite = "0.10.1"
3 changes: 2 additions & 1 deletion ci/ubuntu.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ RUN apt-get update && \
libzmq3-dev \
libssl-dev \
curl \
build-essential
build-essential \
libsqlite3-dev

ENV RUST_ARCHIVE=rust-1.16.0-x86_64-unknown-linux-gnu.tar.gz
ENV RUST_DOWNLOAD_URL=https://static.rust-lang.org/dist/$RUST_ARCHIVE
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ services:
sovrin-client-rust-test:
build:
context: .
dockerfile: ci/ubuntu.dockerfile
command: cargo test --color=always
volumes:
- "./src:/home/sorvin-client-rust/src"
Expand Down
21 changes: 16 additions & 5 deletions src/api/wallet.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use commands::{Command, CommandExecutor};
use commands::wallet::WalletCommand;
use errors::wallet::WalletError;

use std::sync::Arc;
Expand Down Expand Up @@ -30,8 +31,13 @@ impl WalletAPI {
/// #Errors
/// No method specific errors.
/// See `WallerError` docs for common errors description.
pub fn set(keys: &[&str], value: &str, cb: Box<Fn(Result<(), WalletError>) + Send>) {
unimplemented!();
pub fn set(&self, keys: &[&str], value: &str, cb: Box<Fn(Result<(), WalletError>) + Send>) {
self.command_executor.send(Command::Wallet(
WalletCommand::Set(
keys.iter().map(|key| key.to_string()).collect(),
value.to_string(),
cb))
);
}

/// Get Wallet record identified by keys list.
Expand All @@ -41,13 +47,18 @@ impl WalletAPI {
/// cb: Callback that takes command result as parameter.
///
/// #Returns
/// Value of corresponded Wallet record.
/// None if no value was set for this keys
/// Value of corresponded Wallet record otherwise.
///
/// #Errors
/// WalletError::NotFound - If no corresponded Wallet record found.
/// See `WallerError` docs for common errors description.
pub fn get(keys: &[&str], cb: Box<Fn(Result<String, WalletError>) + Send>) {
unimplemented!();
pub fn get(&self, keys: &[&str], cb: Box<Fn(Result<Option<String>, WalletError>) + Send>) {
self.command_executor.send(Command::Wallet(
WalletCommand::Get(
keys.iter().map(|key| key.to_string()).collect(),
cb))
);
}
}

Expand Down
84 changes: 81 additions & 3 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ pub mod sovrin;
pub mod wallet;

use commands::sovrin::{SovrinCommand, SovrinCommandExecutor};
use commands::wallet::{WalletCommand, WalletCommandExecutor};
use services::sovrin::SovrinService;
use services::wallet::WalletService;

use std::error;
use std::sync::mpsc::{Sender, channel};
Expand All @@ -13,7 +15,8 @@ use std::thread;

pub enum Command {
Exit,
Sovrin(SovrinCommand)
Sovrin(SovrinCommand),
Wallet(WalletCommand)
}

pub struct CommandExecutor {
Expand All @@ -32,13 +35,19 @@ impl CommandExecutor {
info!(target: "command_executor", "Worker thread started");

let sovrin_service = Rc::new(SovrinService::new());
let wallet_service = Rc::new(WalletService::new());
let sovrin_command_executor = SovrinCommandExecutor::new(sovrin_service.clone());
let wallet_command_executor = WalletCommandExecutor::new(wallet_service.clone());

match receiver.recv() {
Ok(Command::Sovrin(cmd)) => {
info!(target: "command_executor", "SovrinCommand command received");
sovrin_command_executor.execute(cmd);
}
},
Ok(Command::Wallet(cmd)) => {
info!(target: "command_executor", "WalletCommand command received");
wallet_command_executor.execute(cmd);
},
Ok(Command::Exit) => {
info!(target: "command_executor", "Exit command received");
break
Expand Down Expand Up @@ -90,7 +99,6 @@ mod tests {

#[test]
fn set_did_command_can_be_sent() {

let (sender, receiver) = channel();

let cb = Box::new(move |result| {
Expand Down Expand Up @@ -120,4 +128,74 @@ mod tests {
}
}
}

#[test]
fn wallet_set_value_command_can_be_sent() {
let (sender, receiver) = channel();

let cb = Box::new(move |result| {
match result {
Ok(val) => sender.send("OK"),
Err(err) => sender.send("ERR")
};
});

let cmd_executor = CommandExecutor::new();
cmd_executor.send(Command::Wallet(WalletCommand::Set(vec!["key".to_string(), "subkey".to_string()], "value".to_string(), cb)));

match receiver.recv() {
Ok(result) => {
assert_eq!("OK", result);
}
Err(err) => {
panic!("Error on result recv: {:?}", err);
}
}
}

#[test]
fn wallet_get_value_command_can_be_sent() {

let cmd_executor = CommandExecutor::new();

let (set_sender, set_receiver) = channel();

let cb_set = Box::new(move |result| {
match result {
Ok(val) => set_sender.send("OK"),
Err(err) => set_sender.send("ERR")
};
});

cmd_executor.send(Command::Wallet(WalletCommand::Set(vec!["key".to_string(), "subkey".to_string()], "value".to_string(), cb_set)));

match set_receiver.recv() {
Ok(result) => {
assert_eq!("OK", result);
}
Err(err) => {
panic!("Error on result recv: {:?}", err);
}
}

let (get_sender, get_receiver) = channel();

let cb = Box::new(move |result| {
match result {
Ok(val) => get_sender.send(val),
Err(err) => get_sender.send(None)
};
});

cmd_executor.send(Command::Wallet(WalletCommand::Get(vec!["key".to_string(), "subkey".to_string()], cb)));

match get_receiver.recv() {
Ok(result) => {
assert_eq!(Some("value".to_string()), result);
}
Err(err) => {
panic!("Error on result recv: {:?}", err);
}
}
}
}
77 changes: 77 additions & 0 deletions src/commands/wallet.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use errors::wallet::WalletError;
use services::wallet::WalletService;
use services::wallet::{Wallet, AnoncredsWallet, IdentityWallet};
use std::rc::Rc;


pub enum WalletCommand {
Set(Vec<String>, String, Box<Fn(Result<(), WalletError>) + Send>),
Get(Vec<String>, Box<Fn(Result<Option<String>, WalletError>) + Send>),
AnoncredsWalletCommand(AnoncredsWalletCommand),
IdentityWalletCommand(IdentityWalletCommand)
}

pub enum AnoncredsWalletCommand {
GetMasterSecret(String, String, String, Box<Fn(Result<Option<String>, WalletError>) + Send>)
}

pub enum IdentityWalletCommand {
GetKeyByDid(String, Box<Fn(Result<Option<String>, WalletError>) + Send>)
}

pub struct WalletCommandExecutor {
wallet_service: Rc<WalletService>
}

impl WalletCommandExecutor {
pub fn new(wallet_service: Rc<WalletService>) -> WalletCommandExecutor {
WalletCommandExecutor {
wallet_service: wallet_service
}
}

pub fn execute(&self, command: WalletCommand) {
match command {
WalletCommand::Set(keys, value, cb) => {
info!(target: "wallet_command_executor", "Set command received");
let result = self.set(&keys, &value);
cb(result);
},
WalletCommand::Get(keys, cb) => {
info!(target: "wallet_command_executor", "Get command received");
let result = self.get(&keys);
cb(result);
},
WalletCommand::AnoncredsWalletCommand(AnoncredsWalletCommand::GetMasterSecret(did, schema, pk, cb)) => {
info!(target: "wallet_command_executor", "Get command received");
let result = self.get_master_secret(&did, &schema, &pk);
cb(result);
},
WalletCommand::IdentityWalletCommand(IdentityWalletCommand::GetKeyByDid(did, cb)) => {
info!(target: "wallet_command_executor", "Get command received");
let result = self.get_key_by_did(&did);
cb(result);
}
};
}

fn set(&self, keys: &Vec<String>, value: &String) -> Result<(), WalletError> {
let vector_links: Vec<&str> = keys.iter().map(|s| &s[..]).collect();

self.wallet_service.set(vector_links.as_slice(), value)
}

fn get(&self, keys: &Vec<String>) -> Result<Option<String>, WalletError> {
let vector_links: Vec<&str> = keys.iter().map(|s| &s[..]).collect();

self.wallet_service.get(vector_links.as_slice())
}

fn get_master_secret(&self, did: &String, schema: &String, pk: &String) -> Result<Option<String>, WalletError> {
self.wallet_service.get_master_secret(did, schema, pk)
}

fn get_key_by_did(&self, did: &String) -> Result<Option<String>, WalletError> {
self.wallet_service.get_key_by_did(did)
}
}
36 changes: 5 additions & 31 deletions src/errors/wallet.rs
Original file line number Diff line number Diff line change
@@ -1,58 +1,32 @@
use std::error;
use std::error::Error;
use std::io;
use std::fmt;
use std::num;

#[derive(Debug)]
pub enum WalletError {
NotFound(String),
Io(io::Error)
BackendError(Box<Error>)
}

impl fmt::Display for WalletError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
WalletError::NotFound(ref description) => write!(f, "Not found: {}", description),
WalletError::Io(ref err) => err.fmt(f)
WalletError::BackendError(ref err) => err.fmt(f)
}
}
}

impl error::Error for WalletError {
fn description(&self) -> &str {
match *self {
WalletError::NotFound(ref description) => &description,
WalletError::Io(ref err) => err.description()
WalletError::BackendError(ref err) => err.description()
}
}

fn cause(&self) -> Option<&error::Error> {
match *self {
WalletError::NotFound(ref description) => None,
WalletError::Io(ref err) => Some(err)
WalletError::BackendError(ref err) => Some(err.as_ref())
}
}
}

impl From<io::Error> for WalletError {
fn from(err: io::Error) -> WalletError {
WalletError::Io(err)
}
}

#[cfg(test)]
mod tests {
use super::*;
use std::sync::mpsc::channel;

#[test]
fn wallet_error_can_be_created() {
let error = WalletError::NotFound("TEST".to_string());
}

#[test]
fn wallet_error_can_be_formatted() {
let error_formatted = format!("{}", WalletError::NotFound("TEST".to_string()));
assert_eq!("Not found: TEST", error_formatted);
}
}
1 change: 1 addition & 0 deletions src/services/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod anoncreds;
pub mod sovrin;
pub mod wallet;
Loading