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

Commit

Permalink
Added 'update_account' API to Wallet, and asserted that mutable recor…
Browse files Browse the repository at this point in the history
…ds work.
  • Loading branch information
Sajjon committed Jan 23, 2024
1 parent 1e76d64 commit 413f743
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::prelude::*;

// Generate the FfiConverter needed by UniFFI for newtype `BIP39Passphrase`.
uniffi::custom_newtype!(BIP39Passphrase, String);

/// A BIP39 passphrase, which required but when not used by user, the Default value will be use (empty string),
/// as per BIP39 standard.
#[derive(
Expand Down Expand Up @@ -66,8 +69,6 @@ impl Default for BIP39Passphrase {
}
}

uniffi::custom_newtype!(BIP39Passphrase, String);

#[cfg(test)]
mod tests {
use crate::prelude::*;
Expand Down
125 changes: 125 additions & 0 deletions profile/src/v100/entity/account/appearance_id.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use radix_engine_toolkit_json::models::value;

use crate::prelude::*;

#[derive(
Expand All @@ -21,6 +23,21 @@ pub struct AppearanceID {
pub value: u8,
}

#[uniffi::export]
pub fn new_appearance_id(validating: u8) -> Result<AppearanceID> {
AppearanceID::new(validating)
}

#[uniffi::export]
pub fn new_appearance_id_placeholder() -> AppearanceID {
AppearanceID::placeholder()
}

#[uniffi::export]
pub fn new_appearance_id_placeholder_other() -> AppearanceID {
AppearanceID::placeholder_other()
}

impl AppearanceID {
/// The number of different appearances
pub const MAX: u8 = 11;
Expand All @@ -36,6 +53,56 @@ impl AppearanceID {
value: (n % (Self::MAX as usize)) as u8,
}
}

// Probably want this as a macro... but it is just not worth it, why I boilerplate it.
fn declare(value: u8) -> Self {
Self::new(value).expect("Should have declared valid value.")
}
pub fn gradient0() -> Self {
Self::declare(0)
}
pub fn gradient1() -> Self {
Self::declare(1)
}
pub fn gradient2() -> Self {
Self::declare(2)
}
pub fn gradient3() -> Self {
Self::declare(3)
}
pub fn gradient4() -> Self {
Self::declare(4)
}
pub fn gradient5() -> Self {
Self::declare(5)
}
pub fn gradient6() -> Self {
Self::declare(6)
}
pub fn gradient7() -> Self {
Self::declare(7)
}
pub fn gradient8() -> Self {
Self::declare(8)
}
pub fn gradient9() -> Self {
Self::declare(9)
}
pub fn gradient10() -> Self {
Self::declare(10)
}
pub fn gradient11() -> Self {
Self::declare(11)
}
}

impl HasPlaceholder for AppearanceID {
fn placeholder() -> Self {
Self::gradient0()
}
fn placeholder_other() -> Self {
Self::gradient11()
}
}

impl Default for AppearanceID {
Expand All @@ -61,6 +128,24 @@ impl From<AppearanceID> for u8 {
mod tests {

use crate::prelude::*;

#[test]
fn equality() {
assert_eq!(AppearanceID::placeholder(), AppearanceID::placeholder());
assert_eq!(
AppearanceID::placeholder_other(),
AppearanceID::placeholder_other()
);
}

#[test]
fn inequality() {
assert_ne!(
AppearanceID::placeholder(),
AppearanceID::placeholder_other()
);
}

#[test]
fn lowest() {
assert!(AppearanceID::new(0).is_ok());
Expand Down Expand Up @@ -102,4 +187,44 @@ mod tests {
assert_json_value_fails::<AppearanceID>(json!("3"));
assert_json_value_fails::<AppearanceID>(json!(99));
}

#[test]
fn presets() {
let set = [
AppearanceID::gradient0(),
AppearanceID::gradient1(),
AppearanceID::gradient2(),
AppearanceID::gradient3(),
AppearanceID::gradient4(),
AppearanceID::gradient5(),
AppearanceID::gradient6(),
AppearanceID::gradient7(),
AppearanceID::gradient8(),
AppearanceID::gradient9(),
AppearanceID::gradient10(),
AppearanceID::gradient11(),
]
.into_iter()
.map(|a| a.value)
.collect::<HashSet<_>>();
assert_eq!(set.len(), (AppearanceID::MAX as usize) + 1);
}
}

#[cfg(test)]
mod uniffi_tests {
use crate::prelude::*;

#[test]
fn new() {
assert_eq!(new_appearance_id(5).unwrap(), AppearanceID::gradient5());
}

#[test]
fn placeholders() {
assert_ne!(
new_appearance_id_placeholder(),
new_appearance_id_placeholder_other()
);
}
}
31 changes: 31 additions & 0 deletions profile/src/wallet/wallet_accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,14 @@ impl Wallet {
Ok(account)
}

/// Updates `account` as a whole, if it exists, else an error is thrown.
pub fn update_account(&self, to: Account) -> Result<Account> {
self.write(|mut p| {
p.update_account(&to.address, |a| *a = to.to_owned())
})
.ok_or(CommonError::UnknownAccount)
}

/// Updates the display name of account with the provided address, throws an error if the account is unknown to the wallet.
pub fn change_name_of_account(
&self,
Expand Down Expand Up @@ -251,6 +259,29 @@ mod tests {
);
}

#[test]
fn update_account() {
let profile = Profile::placeholder();
let (wallet, _) = Wallet::ephemeral(profile.clone());
let mut account = wallet.read(|p| p.networks[0].accounts[0].clone());
assert_eq!(account.display_name.value, "Alice");
account.display_name = DisplayName::new("Stella").unwrap();
account.appearance_id = AppearanceID::new(7).unwrap();

// Assert that `Account` returned by method `update_account` is the updated one.
assert_eq!(
wallet.update_account(account).unwrap().display_name.value,
"Stella"
);

// Assert account has been updated in `wallet.profile`
wallet.read(|p| {
let account = &p.networks[0].accounts[0];
assert_eq!(account.display_name.value, "Stella");
assert_eq!(account.appearance_id.value, 7);
});
}

#[test]
fn load_private_device_factor_source() {
let private =
Expand Down
33 changes: 30 additions & 3 deletions profile/tests/uniffi/bindings/test_wallet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,30 @@ func test() throws {
assert(keychain.contains(value: initialNameOfFirstAccount))
print("✨ Successfully created first account ✅")
// MARK: ==================================
print("🔮 Renaming account")
let updatedNameOfFirstAccount = "Satoshi"
print("🔮 Update account using `update_account`")
var updatedNameOfFirstAccount = "Stella"
main0.displayName = try DisplayName(validating: updatedNameOfFirstAccount)
main0.appearanceId = .placeholderOther
let main0Updated = try wallet.updateAccount(to: main0)
assert(main0Updated == main0)
assert(
wallet.profile().networks[0].accounts[0].displayName.value
== updatedNameOfFirstAccount
)
assert(
wallet.profile().networks[0].accounts[0].appearanceId
== .placeholderOther
)

assert(
keychain.contains(
value: updatedNameOfFirstAccount
))
print("✨ Successfully updated first account using `update_account` ✅")

// MARK: ==================================
print("🔮 Renaming account using changeNameOfAccount")
updatedNameOfFirstAccount = "Satoshi"
main0 = try wallet.changeNameOfAccount(
address: main0.address,
to: DisplayName(
Expand All @@ -58,7 +80,7 @@ func test() throws {
keychain.contains(
value: updatedNameOfFirstAccount
))
print("✨ Successfully renamed first account ✅")
print("✨ Successfully renamed first account using changeNameOfAccount ")
// MARK: ==================================
print("🔮 Creating second mainnet account")
let main1 = try wallet.createAndSaveNewAccount(
Expand Down Expand Up @@ -112,6 +134,11 @@ extension DisplayName {
self = try newDisplayName(name: value)
}
}
typealias AppearanceID = AppearanceId
extension AppearanceID {
static let placeholder: Self = newAppearanceIdPlaceholder()
static let placeholderOther: Self = newAppearanceIdPlaceholderOther()
}
extension Data {
public static func random(byteCount: Int) throws -> Self {
var bytes = [UInt8](repeating: 0, count: byteCount)
Expand Down

0 comments on commit 413f743

Please sign in to comment.