Skip to content

Commit

Permalink
add auth methods to config and safe password capabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
willyrgf committed Dec 17, 2023
1 parent b9d94e7 commit 1cecbcc
Show file tree
Hide file tree
Showing 11 changed files with 273 additions and 77 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions mfm_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ edition = "2021"

[dependencies]
serde = "1.0.193"
zeroize = "1.7.0"
15 changes: 15 additions & 0 deletions mfm_core/src/config/authentication/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
pub mod wallet;

use serde::{Deserialize, Serialize};

use self::wallet::Wallet;

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case", tag = "type")]
pub enum Method {
Wallet(Wallet),
MetaMask, // TODO: the next auth method
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct Methods(Vec<Method>);
11 changes: 11 additions & 0 deletions mfm_core/src/config/authentication/wallet.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use serde::{Deserialize, Serialize};

use crate::password::{deserialize_safe_password, SafePassword};

#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct Wallet {
#[serde(deserialize_with = "deserialize_safe_password")]
pub private_key: SafePassword,
pub not_encrypted: bool,
pub env_password: Option<String>,
}
27 changes: 27 additions & 0 deletions mfm_core/src/config/dexes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum Kind {
UniswapV2,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct Dex {
pub name: String,
pub kind: Kind,
pub router_address: String,
pub factory_address: String,
pub network_id: String,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct Dexes(HashMap<String, Dex>);
impl Dexes {
pub fn hashmap(&self) -> &HashMap<String, Dex> {
&self.0
}
pub fn get(&self, key: &str) -> Option<&Dex> {
self.0.get(key)
}
}
86 changes: 9 additions & 77 deletions mfm_core/src/config/mod.rs
Original file line number Diff line number Diff line change
@@ -1,88 +1,20 @@
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum Kind {
EVM,
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct Network {
pub name: String,
pub kind: Kind,
pub symbol: String,
pub decimals: Option<u8>,
pub chain_id: u32,
pub node_url: String,
pub node_url_failover: Option<String>,
pub blockexplorer_url: Option<String>,
pub min_balance_coin: f64,
pub wrapped_asset: Option<Token>,
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct Networks(HashMap<String, Network>);
impl Networks {
pub fn get(&self, key: &str) -> Option<&Network> {
self.0.get(key)
}
pub fn hashmap(&self) -> &HashMap<String, Network> {
&self.0
}
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct Dex {
pub name: String,
pub kind: Kind,
pub router_address: String,
pub factory_address: String,
pub network_id: String,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct Dexes(HashMap<String, Dex>);
impl Dexes {
pub fn hashmap(&self) -> &HashMap<String, Dex> {
&self.0
}
pub fn get(&self, key: &str) -> Option<&Dex> {
self.0.get(key)
}
}
pub mod authentication;
pub mod dexes;
pub mod network;
pub mod token;

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct TokenNetwork {
pub(crate) name: String,
pub(crate) network_id: String,
pub(crate) address: String,
pub(crate) slippage: f64,
pub(crate) path_asset: String,
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct TokenNetworks(HashMap<String, TokenNetwork>);
use dexes::Dexes;
use network::Networks;
use token::Tokens;

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct Token {
pub(crate) kind: String,
pub(crate) networks: TokenNetworks,
}
use self::authentication::Methods;

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct Tokens(HashMap<String, Token>);
impl Tokens {
pub fn hashmap(&self) -> &HashMap<String, Token> {
&self.0
}

pub fn get(&self, key: &str) -> Option<&Token> {
self.0.get(key)
}
}

pub struct Config {
pub networks: Networks,
pub dexes: Dexes,
pub tokens: Tokens,
pub auth_methods: Methods,
}
33 changes: 33 additions & 0 deletions mfm_core/src/config/network.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use super::token::Token;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum Kind {
EVM,
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct Network {
pub name: String,
pub kind: Kind,
pub symbol: String,
pub decimals: Option<u8>,
pub chain_id: u32,
pub node_url: String,
pub node_url_failover: Option<String>,
pub blockexplorer_url: Option<String>,
pub min_balance_coin: f64,
pub wrapped_asset: Option<Token>,
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct Networks(HashMap<String, Network>);
impl Networks {
pub fn get(&self, key: &str) -> Option<&Network> {
self.0.get(key)
}
pub fn hashmap(&self) -> &HashMap<String, Network> {
&self.0
}
}
37 changes: 37 additions & 0 deletions mfm_core/src/config/token.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use serde::{Deserialize, Serialize};
use std::collections::HashMap;

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub enum Kind {
ERC20,
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct TokenNetwork {
pub name: String,
pub network_id: String,
pub address: String,
pub slippage: f64,
pub path_asset: String,
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct TokenNetworks(HashMap<String, TokenNetwork>);

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct Token {
pub kind: Kind,
pub networks: TokenNetworks,
}

#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)]
pub struct Tokens(HashMap<String, Token>);
impl Tokens {
pub fn hashmap(&self) -> &HashMap<String, Token> {
&self.0
}

pub fn get(&self, key: &str) -> Option<&Token> {
self.0.get(key)
}
}
72 changes: 72 additions & 0 deletions mfm_core/src/hidden/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/// ! A wrapper to conceal secrets when output into logs or displayed.
//
use serde::{Deserialize, Serialize};
use std::{fmt, ops::DerefMut};

/// A simple struct with a single inner value to wrap content of any type.
#[derive(Copy, Clone, Serialize, Deserialize)]
#[serde(transparent)]
pub struct Hidden<T> {
inner: T,
}

impl<T> Hidden<T> {
/// Returns ownership of the inner value discarding the wrapper.
pub fn into_inner(self) -> T {
self.inner
}
}

impl<T> From<T> for Hidden<T> {
fn from(inner: T) -> Self {
Hidden { inner }
}
}

/// Defines a masked value for the type to output as debug information. Concealing the secrets within.
impl<T> fmt::Debug for Hidden<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Hidden<{}>", std::any::type_name::<T>())
}
}

/// Defines a masked value for the type to display. Concealing the secrets within.
impl<T> fmt::Display for Hidden<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Hidden<{}>", std::any::type_name::<T>())
}
}

/// Attempts to make the wrapper more transparent by having deref return a reference to the inner value.
impl<T> std::ops::Deref for Hidden<T> {
type Target = T;

fn deref(&self) -> &Self::Target {
&self.inner
}
}

impl<T> DerefMut for Hidden<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}

impl<T: PartialEq> PartialEq for Hidden<T> {
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
}
}

impl<T: Eq> Eq for Hidden<T> {}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn into_applies_wrapper_deref_removes_it() {
let wrapped: Hidden<u8> = 42.into();
assert_eq!(42, *wrapped)
}
}
2 changes: 2 additions & 0 deletions mfm_core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
pub mod config;
pub mod hidden;
pub mod password;
pub mod states;
pub mod tasks;

59 changes: 59 additions & 0 deletions mfm_core/src/password/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use crate::hidden::Hidden;
use serde::{Deserialize, Serialize};
use std::{error::Error, fmt, str::FromStr};
use zeroize::Zeroize;

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(transparent)]
pub struct SafePassword {
password: Hidden<Box<[u8]>>,
}

impl From<String> for SafePassword {
fn from(s: String) -> Self {
Self {
password: Hidden::from(s.into_bytes().into_boxed_slice()),
}
}
}

impl Drop for SafePassword {
fn drop(&mut self) {
self.password.zeroize();
}
}

impl SafePassword {
/// Gets a reference to bytes of a passphrase.
pub fn reveal(&self) -> &[u8] {
self.password.as_ref()
}
}

/// An error for parsing a password from string.
#[derive(Debug)]
pub struct PasswordError;

impl Error for PasswordError {}

impl fmt::Display for PasswordError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "PasswordError")
}
}

impl FromStr for SafePassword {
type Err = PasswordError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self::from(s.to_owned()))
}
}

pub fn deserialize_safe_password<'de, D>(deserializer: D) -> Result<SafePassword, D::Error>
where
D: serde::Deserializer<'de>,
{
let password: String = Deserialize::deserialize(deserializer)?;
Ok(SafePassword::from(password))
}

0 comments on commit 1cecbcc

Please sign in to comment.