Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/wallet lib #73

Merged
merged 30 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
7ee5d57
Release 2.1.0 (#65)
camfairchild Nov 12, 2024
197627c
Update CHANGELOG.MD
roman-opentensor Nov 18, 2024
06e873c
Update Cargo.toml (change pyo3 version)
roman-opentensor Nov 18, 2024
50f08dd
feat: separate python bindings , make code more idiomatic
distributedstatemachine Nov 22, 2024
e902864
wip: python bindings
distributedstatemachine Nov 22, 2024
a1abdf7
stash
distributedstatemachine Nov 22, 2024
cbd5bcb
Implement Display for Config
keithtensor Nov 26, 2024
09253e4
Some refactorings
keithtensor Nov 27, 2024
9b64075
Fix some renamed paths
keithtensor Nov 27, 2024
dad88df
Partially fix python bindings
keithtensor Dec 2, 2024
79f4c8b
Fix remaining python bindings
keithtensor Dec 3, 2024
5dd68f8
Add python-bindings feature
keithtensor Dec 4, 2024
79f7eb3
Make PyKeypair subclassable
keithtensor Dec 4, 2024
dee3e53
Remove unnecessary get_type
keithtensor Dec 4, 2024
5c2a8b4
Fix some test cases
keithtensor Dec 4, 2024
82d0b32
Fix remaining python test failures
keithtensor Dec 5, 2024
2502eec
Merge branch 'staging' into feat/wallet_lib
keithtensor Dec 5, 2024
031ca7b
Update Cargo.lock
keithtensor Dec 9, 2024
2813a1f
Comment out weird test
keithtensor Dec 9, 2024
53b83f0
Update src/utils.rs
keithtensor Dec 9, 2024
f18b80b
Add set_coldkey, set_choldkeypub and set_hotkey
keithtensor Dec 9, 2024
e4a8ba0
Add coldkey_file, coldkeypub_file and hotkey_file getters
keithtensor Dec 9, 2024
4662f69
cargo fmt
keithtensor Dec 9, 2024
d16d8e6
Updates err return types for python bindings
ibraheem-opentensor Dec 10, 2024
efd17ec
Add add_args
keithtensor Dec 10, 2024
38bd425
cargo fmt
keithtensor Dec 10, 2024
00bb649
Clean up wallet config setup
keithtensor Dec 10, 2024
911e15f
sets should_save_to_env default to false in PyKeyfile
ibraheem-opentensor Dec 11, 2024
9ecd8f3
Do not parse config as Config struct
keithtensor Dec 11, 2024
40d2823
Adds supp for config.wallet in config parsing
ibraheem-opentensor Dec 12, 2024
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
219 changes: 186 additions & 33 deletions Cargo.lock

Large diffs are not rendered by default.

7 changes: 6 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ edition = "2021"

[lib]
name = "bittensor_wallet"
crate-type = ["cdylib"]
path = "src/lib.rs"
crate-type = ["cdylib", "rlib"]

[dependencies]
sp-core = "34.0.0"
Expand All @@ -28,7 +29,11 @@ scrypt = "0.11.0"
pkcs8 = "0.10.2"
schnorrkel = "0.11.4"
shellexpand = "3.1.0"
rpassword = "7.3.1"
clap = "4.5.21"
thiserror = "2.0.3"

[features]
extension-module = ["pyo3/extension-module"]
default = ["extension-module"]
python-bindings = []
53 changes: 20 additions & 33 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::fmt::Display;

use crate::constants::{BT_WALLET_HOTKEY, BT_WALLET_NAME, BT_WALLET_PATH};
use pyo3::prelude::*;

#[derive(Clone)]
pub struct WalletConfig {
Expand All @@ -19,50 +20,36 @@ impl WalletConfig {
}

#[derive(Clone)]
#[pyclass(subclass)]
pub struct Config {
pub wallet: WalletConfig,
}

#[pymethods]
impl Config {
#[new]
#[pyo3(signature = (name = None, hotkey = None, path = None))]
pub fn new(
name: Option<String>,
hotkey: Option<String>,
path: Option<String>,
) -> PyResult<Config> {
Ok(Config {
wallet: WalletConfig::new(name, hotkey, path),
})
}
fn __str__(&self) -> PyResult<String> {
Ok(format!(
"Config(name: '{}', path: '{}', hotkey: '{}')",
impl Display for Config {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"Config(name: '{}', path: '{}', hotkey: '{}'",
self.wallet.name, self.wallet.path, self.wallet.hotkey
))
)
}
}

fn __repr__(&self) -> PyResult<String> {
self.__str__()
impl Config {
pub fn new(name: Option<String>, hotkey: Option<String>, path: Option<String>) -> Config {
Config {
wallet: WalletConfig::new(name, hotkey, path),
}
}

/// Returns wallet name
#[getter]
pub fn name(&self) -> PyResult<String> {
Ok(self.wallet.name.clone())
pub fn name(&self) -> String {
self.wallet.name.clone()
}

/// Returns wallet name
#[getter]
pub fn path(&self) -> PyResult<String> {
Ok(self.wallet.path.clone())
pub fn path(&self) -> String {
self.wallet.path.clone()
}

/// Returns wallet name
#[getter]
pub fn hotkey(&self) -> PyResult<String> {
Ok(self.wallet.hotkey.clone())
pub fn hotkey(&self) -> String {
self.wallet.hotkey.clone()
}
}
151 changes: 59 additions & 92 deletions src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,93 +1,60 @@
use pyo3::exceptions::PyException;
use pyo3::prelude::*;
use std::{error, fmt};

// KeyFileError
#[pyclass(extends=PyException)]
#[derive(Debug)]
pub struct KeyFileError {
pub message: String,
}

/// Error thrown when the keyfile is corrupt, non-writable, non-readable.
#[pymethods]
impl KeyFileError {
#[new]
#[pyo3(signature = (message=None))]
pub fn new(message: Option<String>) -> Self {
let msg = message.unwrap_or_default();
KeyFileError { message: msg }
}

pub fn __str__(&self) -> String {
self.message.clone()
}
}

impl fmt::Display for KeyFileError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "KeyFileError: {}", self.message)
}
}

impl error::Error for KeyFileError {}

// ConfigurationError
#[pyclass(extends=PyException)]
#[derive(Debug)]
pub struct ConfigurationError {
pub message: String,
}

/// ConfigurationError
#[pymethods]
impl ConfigurationError {
#[new]
#[pyo3(signature = (message=None))]
pub fn new(message: Option<String>) -> Self {
let msg = message.unwrap_or_default();
ConfigurationError { message: msg }
}

pub fn __str__(&self) -> String {
self.message.clone()
}
use thiserror::Error;

#[derive(Error, Debug)]
pub enum KeyFileError {
#[error("Failed to create directory: {0}")]
DirectoryCreation(String),
#[error("Failed to get metadata: {0}")]
MetadataError(String),
#[error("File does not exist: {0}")]
FileNotFound(String),
#[error("File is not readable: {0}")]
NotReadable(String),
#[error("File is not writable: {0}")]
NotWritable(String),
#[error("Failed to open file: {0}")]
FileOpen(String),
#[error("Failed to read file: {0}")]
FileRead(String),
#[error("Failed to write file: {0}")]
FileWrite(String),
#[error("Failed to set permissions: {0}")]
PermissionError(String),
#[error("Serialization error: {0}")]
SerializationError(String),
#[error("Deserialization error: {0}")]
DeserializationError(String),
#[error("Encryption error: {0}")]
EncryptionError(String),
#[error("Decryption error: {0}")]
DecryptionError(String),
#[error("Invalid encryption method: {0}")]
InvalidEncryption(String),
#[error("Environment variable error: {0}")]
EnvVarError(String),
#[error("Password error: {0}")]
PasswordError(String),
#[error("Generic error: {0}")]
Generic(String),
}

#[derive(Error, Debug)]
pub enum ConfigurationError {
#[error("ConfigurationError: {0}")]
Message(String),
}

#[derive(Error, Debug)]
pub enum PasswordError {
#[error("PasswordError: {0}")]
Message(String),
}
#[derive(Error, Debug)]
pub enum WalletError {
#[error("WalletError: {0}")]
KeyGeneration(String),
#[error("WalletError: {0}")]
InvalidInput(String),
#[error("WalletError: {0}")]
KeyFileError(#[from] KeyFileError),
}

impl fmt::Display for ConfigurationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ConfigurationError: {}", self.message)
}
}

impl error::Error for ConfigurationError {}

// PasswordError
#[pyclass(extends=PyException)]
#[derive(Debug)]
pub struct PasswordError {
pub message: String,
}

/// PasswordError occurs if the password used for decryption is invalid.
#[pymethods]
impl PasswordError {
#[new]
#[pyo3(signature = (message=None))]
pub fn new(message: Option<String>) -> Self {
let msg = message.unwrap_or_default();
PasswordError { message: msg }
}

pub fn __str__(&self) -> String {
self.message.clone()
}
}

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

impl error::Error for PasswordError {}
Loading
Loading