From 24f532784962dcd005a836cc6fbe0ce48c1c31b0 Mon Sep 17 00:00:00 2001 From: Alexander Cyon Date: Tue, 20 Feb 2024 14:58:05 +0100 Subject: [PATCH] WIP addresses --- src/profile/v100/address/account_address.rs | 76 ++--- src/profile/v100/address/identity_address.rs | 278 +++++++++--------- .../v100/address/non_fungible_global_id.rs | 10 + src/profile/v100/address/package_address.rs | 75 ++++- src/profile/v100/address/resource_address.rs | 116 +++++++- src/profile/v100/address/validator_address.rs | 75 ++++- .../resource_or_non_fungible.rs | 1 + 7 files changed, 403 insertions(+), 228 deletions(-) diff --git a/src/profile/v100/address/account_address.rs b/src/profile/v100/address/account_address.rs index 9d026ebe5..30d5155bb 100644 --- a/src/profile/v100/address/account_address.rs +++ b/src/profile/v100/address/account_address.rs @@ -1,7 +1,6 @@ pub use crate::prelude::*; // use crate::InnerAccountAddress; - /// Human readable address of an account. Always starts with `"account_"``, for example: /// /// `account_rdx16xlfcpp0vf7e3gqnswv8j9k58n6rjccu58vvspmdva22kf3aplease` @@ -63,8 +62,7 @@ pub fn account_address_to_short(address: &AccountAddress) -> String { impl AccountAddress { pub fn new(public_key: PublicKey, network_id: NetworkID) -> Self { - // ::from_public_key(public_key, network_id) - todo!(); + ::from_public_key(public_key, network_id) } /// Formats the AccountAddress to its abbreviated form which is what the user @@ -153,29 +151,23 @@ mod tests { use crate::prelude::*; + #[allow(clippy::upper_case_acronyms)] + type SUT = AccountAddress; + #[test] fn equality() { - assert_eq!( - AccountAddress::placeholder(), - AccountAddress::placeholder() - ); - assert_eq!( - AccountAddress::placeholder_other(), - AccountAddress::placeholder_other() - ); + assert_eq!(SUT::placeholder(), SUT::placeholder()); + assert_eq!(SUT::placeholder_other(), SUT::placeholder_other()); } #[test] fn inequality() { - assert_ne!( - AccountAddress::placeholder(), - AccountAddress::placeholder_other() - ); + assert_ne!(SUT::placeholder(), SUT::placeholder_other()); } #[test] fn try_from_bech32() { - assert!(AccountAddress::try_from_bech32( + assert!(SUT::try_from_bech32( "account_rdx16xlfcpp0vf7e3gqnswv8j9k58n6rjccu58vvspmdva22kf3aplease", ) .is_ok()); @@ -183,17 +175,18 @@ mod tests { #[test] fn from_bech32_invalid_entity_type() { + let s = "identity_tdx_21_12tljxea3s0mse52jmpvsphr0haqs86sung8d3qlhr763nxttj59650"; assert_eq!( - AccountAddress::try_from_bech32( - "identity_tdx_21_12tljxea3s0mse52jmpvsphr0haqs86sung8d3qlhr763nxttj59650", + SUT::try_from_bech32( + s, ), - Err(CommonError::MismatchingEntityTypeWhileDecodingAddress) + Err(CommonError::FailedToDecodeAddressFromBech32 { bad_value: s.to_owned() }) ); } #[test] fn format() { - let a = AccountAddress::try_from_bech32( + let a = SUT::try_from_bech32( "account_rdx16xlfcpp0vf7e3gqnswv8j9k58n6rjccu58vvspmdva22kf3aplease", ) .unwrap(); @@ -211,7 +204,7 @@ mod tests { .unwrap(); assert_eq!( - AccountAddress::from_public_key::(public_key.into(), NetworkID::Mainnet) + SUT::from_public_key::(public_key.into(), NetworkID::Mainnet) .address(), "account_rdx129qdd2yp9vs8jkkn2uwn6sw0ejwmcwr3r4c3usr2hp0nau67m2kzdm" ) @@ -225,14 +218,14 @@ mod tests { .unwrap(); assert_eq!( - AccountAddress::new(public_key.into(), NetworkID::Mainnet).address(), + SUT::new(public_key.into(), NetworkID::Mainnet).address(), "account_rdx129qdd2yp9vs8jkkn2uwn6sw0ejwmcwr3r4c3usr2hp0nau67m2kzdm" ) } #[test] fn nebunet() { - let address = AccountAddress::try_from_bech32( + let address = SUT::try_from_bech32( "account_tdx_b_1286wrrqrfcrfhthfrtdywe8alney8zu0ja5xrhcq2475ej08m9raqq", ) .unwrap(); @@ -241,7 +234,7 @@ mod tests { #[test] fn network_id() { - let sut = AccountAddress::try_from_bech32( + let sut = SUT::try_from_bech32( "account_rdx16xlfcpp0vf7e3gqnswv8j9k58n6rjccu58vvspmdva22kf3aplease", ) .unwrap(); @@ -250,7 +243,7 @@ mod tests { #[test] fn short() { - let sut: AccountAddress = AccountAddress::try_from_bech32( + let sut: SUT = SUT::try_from_bech32( "account_rdx16xlfcpp0vf7e3gqnswv8j9k58n6rjccu58vvspmdva22kf3aplease", ) .unwrap(); @@ -260,7 +253,7 @@ mod tests { #[test] fn invalid() { assert_eq!( - AccountAddress::try_from_bech32("x"), + SUT::try_from_bech32("x"), Err(CommonError::FailedToDecodeAddressFromBech32 { bad_value: "x".to_owned() }) @@ -271,7 +264,7 @@ mod tests { fn invalid_checksum() { let s = "account_rdx16xlfcpp0vf7e3gqnswv8j9k58n6rjccu58vvspmdva22kf3apleasx"; assert_eq!( - AccountAddress::try_from_bech32(s), + SUT::try_from_bech32(s), Err(CommonError::FailedToDecodeAddressFromBech32 { bad_value: s.to_owned() }) @@ -282,7 +275,7 @@ mod tests { fn invalid_entity_type() { let s = "identity_rdx16xlfcpp0vf7e3gqnswv8j9k58n6rjccu58vvspmdva22kf3aplease"; assert_eq!( - AccountAddress::try_from_bech32(s), + SUT::try_from_bech32(s), Err(CommonError::FailedToDecodeAddressFromBech32 { bad_value: s.to_owned() }) @@ -291,7 +284,7 @@ mod tests { #[test] fn json_roundtrip() { - let a: AccountAddress = + let a: SUT = "account_rdx16xlfcpp0vf7e3gqnswv8j9k58n6rjccu58vvspmdva22kf3aplease" .parse() .unwrap(); @@ -309,31 +302,27 @@ mod tests { #[test] fn json_roundtrip_fails_for_invalid() { - assert_json_value_fails::( + assert_json_value_fails::( json!("identity_rdx12gzxlgre0glhh9jxaptm7tdth8j4w4r8ykpg2xjfv45nghzsjzrvmp") ); - assert_json_value_fails::( + assert_json_value_fails::( json!("account_rdx129qdd2yp9vs8jkkn2uwn6sw0ejwmcwr3r4c3usr2hp0nau67m2kzzz") ); - assert_json_value_fails::(json!("super invalid")); + assert_json_value_fails::(json!("super invalid")); } } #[cfg(test)] mod uniffi_tests { - use std::str::FromStr; - use crate::{ - account_address_to_short, new_account_address, - new_account_address_from, Ed25519PublicKey, EntityAddress, NetworkID, - PublicKey, - }; + use super::*; - use super::AccountAddress; + #[allow(clippy::upper_case_acronyms)] + type SUT = AccountAddress; #[test] fn short() { - let sut: AccountAddress = AccountAddress::try_from_bech32( + let sut: SUT = SUT::try_from_bech32( "account_rdx16xlfcpp0vf7e3gqnswv8j9k58n6rjccu58vvspmdva22kf3aplease", ) .unwrap(); @@ -350,14 +339,11 @@ mod uniffi_tests { let bech32 = "account_rdx129qdd2yp9vs8jkkn2uwn6sw0ejwmcwr3r4c3usr2hp0nau67m2kzdm"; assert_eq!( - AccountAddress::new(public_key.clone(), NetworkID::Mainnet), + SUT::new(public_key.clone(), NetworkID::Mainnet), new_account_address_from(public_key, NetworkID::Mainnet) ); let from_bech32 = new_account_address(bech32.to_string()).unwrap(); - assert_eq!( - AccountAddress::try_from_bech32(bech32).unwrap(), - from_bech32.clone() - ); + assert_eq!(SUT::try_from_bech32(bech32).unwrap(), from_bech32.clone()); assert_eq!(from_bech32.address(), bech32) } } diff --git a/src/profile/v100/address/identity_address.rs b/src/profile/v100/address/identity_address.rs index c596c5d2f..b2325efab 100644 --- a/src/profile/v100/address/identity_address.rs +++ b/src/profile/v100/address/identity_address.rs @@ -74,146 +74,140 @@ impl HasPlaceholder for IdentityAddress { } } +#[cfg(test)] +mod tests { + use crate::prelude::*; + use radix_engine_common::crypto::{ + Ed25519PublicKey as ScryptoEd25519PublicKey, + PublicKey as ScryptoPublicKey, + }; + + #[allow(clippy::upper_case_acronyms)] + type SUT = IdentityAddress; + + #[test] + fn from_bech32() { + assert!(SUT::try_from_bech32( + "identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8j", + ) + .is_ok()); + } + + #[test] + fn from_str() { + assert!( + "identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8j" + .parse::() + .is_ok() + ); + } + + #[test] + fn display() { + let a = SUT::try_from_bech32( + "identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8j", + ) + .unwrap(); + assert_eq!( + format!("{}", a), + "identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8j" + ); + } + + #[test] + fn from_public_key_bytes_and_network_id() { + let public_key = ScryptoEd25519PublicKey::from_str( + "6c28952be5cdade99c7dd5d003b6b692714b6b74c5fdb5fdc9a8e4ee1d297838", + ) + .unwrap(); + assert_eq!( + SUT::from_public_key( + ScryptoPublicKey::Ed25519(public_key), + NetworkID::Mainnet + ) + .address(), + "identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8j" + ) + } + + #[test] + fn network_id() { + let sut = SUT::try_from_bech32( + "identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8j", + ) + .unwrap(); + assert_eq!(sut.network_id(), NetworkID::Mainnet); + } -// #[cfg(test)] -// mod tests { -// use crate::prelude::*; -// use radix_engine_common::crypto::{ -// Ed25519PublicKey as ScryptoEd25519PublicKey, -// PublicKey as ScryptoPublicKey, -// }; - -// #[test] -// fn from_bech32() { -// assert!(IdentityAddress::try_from_bech32( -// "identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8j", -// ) -// .is_ok()); -// } - -// #[test] -// fn from_str() { -// assert!( -// "identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8j" -// .parse::() -// .is_ok() -// ); -// } - -// #[test] -// fn display() { -// let a = IdentityAddress::try_from_bech32( -// "identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8j", -// ) -// .unwrap(); -// assert_eq!( -// format!("{}", a), -// "identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8j" -// ); -// } - -// #[test] -// fn from_public_key_bytes_and_network_id() { -// let public_key = ScryptoEd25519PublicKey::from_str( -// "6c28952be5cdade99c7dd5d003b6b692714b6b74c5fdb5fdc9a8e4ee1d297838", -// ) -// .unwrap(); -// assert_eq!( -// IdentityAddress::from_public_key( -// ScryptoPublicKey::Ed25519(public_key), -// NetworkID::Mainnet -// ) -// .address, -// "identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8j" -// ) -// } - -// #[test] -// fn network_id() { -// let sut = IdentityAddress::try_from_bech32( -// "identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8j", -// ) -// .unwrap(); -// assert_eq!(sut.network_id, NetworkID::Mainnet); -// } - -// #[test] -// fn equality() { -// assert_eq!( -// IdentityAddress::placeholder(), -// IdentityAddress::placeholder() -// ); -// assert_eq!( -// IdentityAddress::placeholder_other(), -// IdentityAddress::placeholder_other() -// ); -// } - -// #[test] -// fn inequality() { -// assert_ne!( -// IdentityAddress::placeholder(), -// IdentityAddress::placeholder_other() -// ); -// } - -// #[test] -// fn invalid() { -// assert_eq!( -// IdentityAddress::try_from_bech32("x"), -// Err(CommonError::FailedToDecodeAddressFromBech32 { -// bad_value: "x".to_owned() -// }) -// ) -// } - -// #[test] -// fn invalid_checksum() { -// let s = "identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8x"; -// assert_eq!( -// IdentityAddress::try_from_bech32(s), -// Err(CommonError::FailedToDecodeAddressFromBech32 { -// bad_value: s.to_owned() -// }) -// ) -// } - -// #[test] -// fn invalid_entity_type() { -// assert_eq!( -// IdentityAddress::try_from_bech32( -// "account_rdx16xlfcpp0vf7e3gqnswv8j9k58n6rjccu58vvspmdva22kf3aplease" -// ), -// Err(CommonError::MismatchingEntityTypeWhileDecodingAddress) -// ) -// } - -// #[test] -// fn json_roundtrip_success() { -// let a: IdentityAddress = -// "identity_rdx12gzxlgre0glhh9jxaptm7tdth8j4w4r8ykpg2xjfv45nghzsjzrvmp" -// .parse() -// .unwrap(); - -// assert_json_value_eq_after_roundtrip( -// &a, -// json!("identity_rdx12gzxlgre0glhh9jxaptm7tdth8j4w4r8ykpg2xjfv45nghzsjzrvmp"), -// ); -// assert_json_roundtrip(&a); -// assert_json_value_ne_after_roundtrip( -// &a, -// json!("identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8j"), -// ); -// } - -// #[test] -// fn json_roundtrip_fails_for_invalid() { -// assert_json_value_fails::( -// json!("account_rdx16xlfcpp0vf7e3gqnswv8j9k58n6rjccu58vvspmdva22kf3aplease") -// ); -// assert_json_value_fails::( -// json!("identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzkuxx") -// ); -// assert_json_value_fails::(json!("super invalid")); -// } -// } + #[test] + fn equality() { + assert_eq!(SUT::placeholder(), SUT::placeholder()); + assert_eq!(SUT::placeholder_other(), SUT::placeholder_other()); + } + + #[test] + fn inequality() { + assert_ne!(SUT::placeholder(), SUT::placeholder_other()); + } + + #[test] + fn invalid() { + assert_eq!( + SUT::try_from_bech32("x"), + Err(CommonError::FailedToDecodeAddressFromBech32 { + bad_value: "x".to_owned() + }) + ) + } + + #[test] + fn invalid_checksum() { + let s = "identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8x"; + assert_eq!( + SUT::try_from_bech32(s), + Err(CommonError::FailedToDecodeAddressFromBech32 { + bad_value: s.to_owned() + }) + ) + } + + #[test] + fn invalid_entity_type() { + let s = "account_rdx16xlfcpp0vf7e3gqnswv8j9k58n6rjccu58vvspmdva22kf3aplease"; + assert_eq!( + SUT::try_from_bech32(s), + Err(CommonError::FailedToDecodeAddressFromBech32 { + bad_value: s.to_owned() + }) + ) + } + + #[test] + fn json_roundtrip_success() { + let a: SUT = + "identity_rdx12gzxlgre0glhh9jxaptm7tdth8j4w4r8ykpg2xjfv45nghzsjzrvmp" + .parse() + .unwrap(); + + assert_json_value_eq_after_roundtrip( + &a, + json!("identity_rdx12gzxlgre0glhh9jxaptm7tdth8j4w4r8ykpg2xjfv45nghzsjzrvmp"), + ); + assert_json_roundtrip(&a); + assert_json_value_ne_after_roundtrip( + &a, + json!("identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzku8j"), + ); + } + + #[test] + fn json_roundtrip_fails_for_invalid() { + assert_json_value_fails::( + json!("account_rdx16xlfcpp0vf7e3gqnswv8j9k58n6rjccu58vvspmdva22kf3aplease") + ); + assert_json_value_fails::( + json!("identity_rdx12tgzjrz9u0xz4l28vf04hz87eguclmfaq4d2p8f8lv7zg9ssnzkuxx") + ); + assert_json_value_fails::(json!("super invalid")); + } +} diff --git a/src/profile/v100/address/non_fungible_global_id.rs b/src/profile/v100/address/non_fungible_global_id.rs index 8faa2b465..b81d0ff25 100644 --- a/src/profile/v100/address/non_fungible_global_id.rs +++ b/src/profile/v100/address/non_fungible_global_id.rs @@ -120,6 +120,16 @@ impl NonFungibleGlobalId { } } +impl HasPlaceholder for NonFungibleGlobalId { + fn placeholder() -> Self { + "resource_rdx1nfyg2f68jw7hfdlg5hzvd8ylsa7e0kjl68t5t62v3ttamtejc9wlxa:".parse().expect("Valid GC NFT Global ID") + } + + fn placeholder_other() -> Self { + "resource_rdx1n2ekdd2m0jsxjt9wasmu3p49twy2yfalpaa6wf08md46sk8dfmldnd:#1337#".parse().expect("Valid Scorpion NFT Global ID") + } +} + #[cfg(test)] mod tests { use crate::prelude::*; diff --git a/src/profile/v100/address/package_address.rs b/src/profile/v100/address/package_address.rs index c8d9ff3a7..a0c4cd59a 100644 --- a/src/profile/v100/address/package_address.rs +++ b/src/profile/v100/address/package_address.rs @@ -22,27 +22,74 @@ pub fn new_package_address(bech32: String) -> Result { PackageAddress::try_from_bech32(bech32.as_str()) } +impl HasPlaceholder for PackageAddress { + fn placeholder() -> Self { + Self::placeholder_mainnet_gumball_club() + } + + fn placeholder_other() -> Self { + Self::placeholder_stokenet_gumball_club() + } +} + +impl PackageAddress { + pub fn placeholder_mainnet_gumball_club() -> Self { + "package_rdx1p589ehmmvqa2dnw0jaky3kesjdjvln94hzunsqse8k52083hfcjh63" + .parse() + .expect("Valid Mainnet package placeholder address") + } + pub fn placeholder_stokenet_gumball_club() -> Self { + "package_tdx_2_1pkaw4m82c89hy0gk4dwqtqlln6md8anr2ysnrvegxar53mr6nvn5ay" + .parse() + .expect("Valid Stokenet package placeholder address") + } +} + #[cfg(test)] mod tests { use crate::prelude::*; + #[allow(clippy::upper_case_acronyms)] + type SUT = PackageAddress; + + + #[test] + fn equality() { + assert_eq!( + SUT::placeholder(), + SUT::placeholder() + ); + assert_eq!( + SUT::placeholder_other(), + SUT::placeholder_other() + ); + } + + #[test] + fn inequality() { + assert_ne!( + SUT::placeholder(), + SUT::placeholder_other() + ); + } + #[test] fn display() { - let s = "resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd"; - let a = PackageAddress::try_from_bech32(s).unwrap(); + let s = "package_rdx1p589ehmmvqa2dnw0jaky3kesjdjvln94hzunsqse8k52083hfcjh63"; + let a = SUT::try_from_bech32(s).unwrap(); assert_eq!(format!("{a}"), s); } #[test] fn json_roundtrip() { let a: PackageAddress = - "resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd" + "package_tdx_2_1pkaw4m82c89hy0gk4dwqtqlln6md8anr2ysnrvegxar53mr6nvn5ay" .parse() .unwrap(); assert_json_value_eq_after_roundtrip( &a, - json!("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd"), + json!("package_tdx_2_1pkaw4m82c89hy0gk4dwqtqlln6md8anr2ysnrvegxar53mr6nvn5ay"), ); assert_json_roundtrip(&a); assert_json_value_ne_after_roundtrip( @@ -53,19 +100,19 @@ mod tests { #[test] fn json_roundtrip_fails_for_invalid() { - assert_json_value_fails::( - json!("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxxx") + assert_json_value_fails::( + json!("package_tdx_2_1pkaw4m82c89hy0gk4dwqtqlln6md8anr2ysnrvegxar53mr6nvn5ax") ); - assert_json_value_fails::( - json!("account_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd") + assert_json_value_fails::( + json!("account_tdx_2_1pkaw4m82c89hy0gk4dwqtqlln6md8anr2ysnrvegxar53mr6nvn5ay") ); - assert_json_value_fails::(json!("super invalid")); + assert_json_value_fails::(json!("super invalid")); } #[test] fn network_id_stokenet() { - let a: PackageAddress = - "resource_tdx_2_1tkckx9fynl9f7756z8wxphq7wce6vk874nuq4f2nnxgh3nzrwhjdlp" + let a: SUT = + "package_tdx_2_1pkaw4m82c89hy0gk4dwqtqlln6md8anr2ysnrvegxar53mr6nvn5ay" .parse() .unwrap(); assert_eq!(a.network_id(), NetworkID::Stokenet); @@ -74,7 +121,7 @@ mod tests { #[test] fn network_id_mainnet() { let a: PackageAddress = - "resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd" + "package_rdx1p589ehmmvqa2dnw0jaky3kesjdjvln94hzunsqse8k52083hfcjh63" .parse() .unwrap(); assert_eq!(a.network_id(), NetworkID::Mainnet); @@ -92,8 +139,8 @@ mod uniffi_tests { #[test] fn new() { - let s = "resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd"; - let a = PackageAddress::try_from_bech32(s).unwrap(); + let s = "package_rdx1p589ehmmvqa2dnw0jaky3kesjdjvln94hzunsqse8k52083hfcjh63"; + let a = SUT::try_from_bech32(s).unwrap(); let b = new_package_address(s.to_string()).unwrap(); assert_eq!(b.address(), s); assert_eq!(a, b); diff --git a/src/profile/v100/address/resource_address.rs b/src/profile/v100/address/resource_address.rs index 6239f7511..ad223a484 100644 --- a/src/profile/v100/address/resource_address.rs +++ b/src/profile/v100/address/resource_address.rs @@ -21,6 +21,68 @@ pub struct ResourceAddress { pub(crate) __inner: InnerResourceAddress, } +impl HasPlaceholder for ResourceAddress { + /// The RAD on mainnet + fn placeholder() -> Self { + Self::placeholder_mainnet_xrd() + } + + /// Candy by Gumball club on mainnet + fn placeholder_other() -> Self { + Self::placeholder_mainnet_candy() + } +} + +impl ResourceAddress { + fn placeholder_stokenet() -> Self { + Self::placeholder_stokenet_xrd() + } + + fn placeholder_stokenet_other() -> Self { + Self::placeholder_stokenet_gum() + } +} + +impl ResourceAddress { + /// The RAD on mainnet + fn placeholder_mainnet_xrd() -> Self { + "resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd" + .parse() + .expect("XRD") + } + + /// Candy by Gumball club on mainnet + fn placeholder_mainnet_candy() -> Self { + "resource_rdx1t4dy69k6s0gv040xa64cyadyefwtett62ng6xfdnljyydnml7t6g3j" + .parse() + .expect("Candy") + } + + fn placeholder_stokenet_xrd() -> Self { + "resource_tdx_2_1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxtfd2jc" + .parse() + .expect("XRD") + } + + fn placeholder_stokenet_gum() -> Self { + "resource_tdx_2_1t4kep9ldg9t0cszj78z6fcr2zvfxfq7muetq7pyvhdtctwxum90scq" + .parse() + .expect("Gum") + } + + fn placeholder_stokenet_gc_tokens() -> Self { + "resource_tdx_2_1thqcgjw37fjgycpvqr52nx4jcsdeuq75mf2nywme07kzsuds9a4psp" + .parse() + .expect("GC Tokens") + } + + fn placeholder_stokenet_candy() -> Self { + "resource_tdx_2_1tk30vj4ene95e3vhymtf2p35fzl29rv4us36capu2rz0vretw9gzr3" + .parse() + .expect("Candy") + } +} + #[uniffi::export] pub fn new_resource_address(bech32: String) -> Result { ResourceAddress::try_from_bech32(bech32.as_str()) @@ -30,20 +92,50 @@ pub fn new_resource_address(bech32: String) -> Result { mod tests { use crate::prelude::*; + #[allow(clippy::upper_case_acronyms)] + type SUT = ResourceAddress; + + #[test] + fn equality() { + assert_eq!(SUT::placeholder(), SUT::placeholder()); + assert_eq!(SUT::placeholder_other(), SUT::placeholder_other()); + + assert_eq!(SUT::placeholder_stokenet(), SUT::placeholder_stokenet()); + assert_eq!(SUT::placeholder_stokenet_other(), SUT::placeholder_stokenet_other()); + } + + #[test] + fn inequality() { + assert_ne!(SUT::placeholder(), SUT::placeholder_other()); + assert_ne!(SUT::placeholder_stokenet(), SUT::placeholder()); + } + + #[test] + fn hash() { + assert_eq!( + HashSet::::from_iter([ + SUT::placeholder_mainnet_xrd(), + SUT::placeholder_mainnet_candy(), + SUT::placeholder_stokenet_xrd(), + SUT::placeholder_stokenet_gc_tokens(), + SUT::placeholder_stokenet_gum(), + SUT::placeholder_stokenet_candy(), + ]) + .len(), + 8 + ) + } + #[test] fn display() { let s = "resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd"; - let a = ResourceAddress::try_from_bech32(s).unwrap(); + let a = SUT::try_from_bech32(s).unwrap(); assert_eq!(format!("{a}"), s); } #[test] fn json_roundtrip() { - let a: ResourceAddress = - "resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd" - .parse() - .unwrap(); - + let a = SUT::placeholder(); assert_json_value_eq_after_roundtrip( &a, json!("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd"), @@ -57,18 +149,18 @@ mod tests { #[test] fn json_roundtrip_fails_for_invalid() { - assert_json_value_fails::( + assert_json_value_fails::( json!("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxxx") ); - assert_json_value_fails::( + assert_json_value_fails::( json!("account_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd") ); - assert_json_value_fails::(json!("super invalid")); + assert_json_value_fails::(json!("super invalid")); } #[test] fn network_id_stokenet() { - let a: ResourceAddress = + let a: SUT = "resource_tdx_2_1tkckx9fynl9f7756z8wxphq7wce6vk874nuq4f2nnxgh3nzrwhjdlp" .parse() .unwrap(); @@ -77,7 +169,7 @@ mod tests { #[test] fn network_id_mainnet() { - let a: ResourceAddress = + let a: SUT = "resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd" .parse() .unwrap(); @@ -97,7 +189,7 @@ mod uniffi_tests { #[test] fn new() { let s = "resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd"; - let a = ResourceAddress::try_from_bech32(s).unwrap(); + let a = SUT::try_from_bech32(s).unwrap(); let b = new_resource_address(s.to_string()).unwrap(); assert_eq!(b.address(), s); assert_eq!(a, b); diff --git a/src/profile/v100/address/validator_address.rs b/src/profile/v100/address/validator_address.rs index 17c2a5db5..5b9e4c8a6 100644 --- a/src/profile/v100/address/validator_address.rs +++ b/src/profile/v100/address/validator_address.rs @@ -22,50 +22,95 @@ pub fn new_validator_address(bech32: String) -> Result { ValidatorAddress::try_from_bech32(bech32.as_str()) } +impl HasPlaceholder for ValidatorAddress { + fn placeholder() -> Self { + "validator_rdx1sd5368vqdmjk0y2w7ymdts02cz9c52858gpyny56xdvzuheepdeyy0" + .parse() + .expect("Valid placeholder") + } + + fn placeholder_other() -> Self { + "validator_rdx1sw5rrhkxs65kl9xcxu7t9yu3k8ptscjwamum4phclk297j6r28g8kd" + .parse() + .expect("Valid placeholder other") + } +} + +impl ValidatorAddress { + pub fn placeholder_stokenet() -> Self { + "validator_tdx_2_1sdatqsl6rx05yy2yvpf6ckfl7x8dluvzkcyljkn0x4lxkgucc0xz2w".parse().expect("Valid placeholder") + } + + pub fn placeholder_stokenet_other() -> Self { + "validator_tdx_2_1sdtnujyn3720ymg8lakydkvc5tw4q3zecdj95akdwt9de362mvtd94".parse().expect("Valid placeholder") + } +} + #[cfg(test)] mod tests { use crate::prelude::*; + #[allow(clippy::upper_case_acronyms)] + type SUT = ValidatorAddress; + + #[test] + fn equality() { + assert_eq!(SUT::placeholder(), SUT::placeholder()); + assert_eq!(SUT::placeholder_other(), SUT::placeholder_other()); + + assert_eq!(SUT::placeholder_stokenet(), SUT::placeholder_stokenet()); + assert_eq!( + SUT::placeholder_stokenet_other(), + SUT::placeholder_stokenet_other() + ); + } + + #[test] + fn inequality() { + assert_ne!(SUT::placeholder(), SUT::placeholder_other()); + assert_ne!(SUT::placeholder(), SUT::placeholder_stokenet()); + } + #[test] fn display() { - let s = "resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd"; - let a = ValidatorAddress::try_from_bech32(s).unwrap(); + let s = "validator_rdx1sdcmd3ymwzvswgyva8lpknqrzuzzmmkac9my4auk29j5feumfh77fs"; + let a = SUT::try_from_bech32(s).unwrap(); assert_eq!(format!("{a}"), s); } #[test] fn json_roundtrip() { - let a: ValidatorAddress = - "resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd" + let a: SUT = + "validator_rdx1sd4eq4vvnrmtxy0l4wxaykugwjmyflnnkn4sz3p9jv79ac2sv5sh88" .parse() .unwrap(); assert_json_value_eq_after_roundtrip( &a, - json!("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd"), + json!("validator_rdx1sd4eq4vvnrmtxy0l4wxaykugwjmyflnnkn4sz3p9jv79ac2sv5sh88"), ); assert_json_roundtrip(&a); assert_json_value_ne_after_roundtrip( &a, - json!("resource_rdx1tkk83magp3gjyxrpskfsqwkg4g949rmcjee4tu2xmw93ltw2cz94sq"), + json!("validator_rdx1sdcmd3ymwzvswgyva8lpknqrzuzzmmkac9my4auk29j5feumfh77fs"), ); } #[test] fn json_roundtrip_fails_for_invalid() { - assert_json_value_fails::( - json!("resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxxx") + assert_json_value_fails::( + json!("validator_rdx1sdcmd3ymwzvswgyva8lpknqrzuzzmmkac9my4auk29j5feumfh77ff") ); - assert_json_value_fails::( - json!("account_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd") + assert_json_value_fails::( + json!("account_rdx1sdcmd3ymwzvswgyva8lpknqrzuzzmmkac9my4auk29j5feumfh77ff") ); - assert_json_value_fails::(json!("super invalid")); + assert_json_value_fails::(json!("super invalid")); } #[test] fn network_id_stokenet() { - let a: ValidatorAddress = - "resource_tdx_2_1tkckx9fynl9f7756z8wxphq7wce6vk874nuq4f2nnxgh3nzrwhjdlp" + let a: SUT = + "validator_tdx_2_1sdatqsl6rx05yy2yvpf6ckfl7x8dluvzkcyljkn0x4lxkgucc0xz2w" .parse() .unwrap(); assert_eq!(a.network_id(), NetworkID::Stokenet); @@ -73,7 +118,7 @@ mod tests { #[test] fn network_id_mainnet() { - let a: ValidatorAddress = + let a: SUT = "resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd" .parse() .unwrap(); @@ -93,7 +138,7 @@ mod uniffi_tests { #[test] fn new() { let s = "resource_rdx1tknxxxxxxxxxradxrdxxxxxxxxx009923554798xxxxxxxxxradxrd"; - let a = ValidatorAddress::try_from_bech32(s).unwrap(); + let a = SUT::try_from_bech32(s).unwrap(); let b = new_validator_address(s.to_string()).unwrap(); assert_eq!(b.address(), s); assert_eq!(a, b); diff --git a/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/resource_or_non_fungible.rs b/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/resource_or_non_fungible.rs index 363c5ab0f..c817ca299 100644 --- a/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/resource_or_non_fungible.rs +++ b/src/profile/v100/entity/account/on_ledger_settings/third_party_deposits/resource_or_non_fungible.rs @@ -15,6 +15,7 @@ use crate::prelude::*; pub enum ResourceOrNonFungible { #[serde(rename = "resourceAddress")] Resource { value: ResourceAddress }, + #[serde(rename = "nonFungibleGlobalID")] NonFungible { value: NonFungibleGlobalId }, }