snapshot before rebranding
This commit is contained in:
+130
@@ -0,0 +1,130 @@
|
||||
// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::*;
|
||||
|
||||
/// A custom address format. See also [`Ss58AddressFormatRegistry`]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Ss58AddressFormat {
|
||||
prefix: u16,
|
||||
}
|
||||
|
||||
/// An enumeration of unique networks.
|
||||
/// Some are reserved.
|
||||
impl Ss58AddressFormat {
|
||||
/// Custom constructor
|
||||
#[inline]
|
||||
pub fn custom(prefix: u16) -> Self {
|
||||
Ss58AddressFormat { prefix }
|
||||
}
|
||||
|
||||
/// Address prefix used on the network
|
||||
pub const fn prefix(&self) -> u16 {
|
||||
self.prefix
|
||||
}
|
||||
|
||||
/// names of all address formats
|
||||
pub fn all_names() -> &'static [&'static str] {
|
||||
&ALL_SS58_ADDRESS_FORMAT_NAMES
|
||||
}
|
||||
|
||||
/// All known address formats.
|
||||
pub fn all() -> &'static [Ss58AddressFormatRegistry] {
|
||||
&ALL_SS58_ADDRESS_FORMATS
|
||||
}
|
||||
}
|
||||
|
||||
/// Display the name of the address format (not the description).
|
||||
#[cfg(feature = "std")]
|
||||
impl std::fmt::Display for Ss58AddressFormat {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
if let Ok(lookup) =
|
||||
PREFIX_TO_INDEX.binary_search_by_key(&self.prefix, |(prefix, _)| *prefix)
|
||||
{
|
||||
let (_, idx) = PREFIX_TO_INDEX[lookup];
|
||||
write!(f, "{}", ALL_SS58_ADDRESS_FORMAT_NAMES[idx])
|
||||
} else {
|
||||
write!(f, "{}", self.prefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// const function to convert [`Ss58AddressFormat`] to u16
|
||||
pub const fn from_address_format(x: Ss58AddressFormat) -> u16 {
|
||||
x.prefix
|
||||
}
|
||||
|
||||
impl From<Ss58AddressFormatRegistry> for Ss58AddressFormat {
|
||||
fn from(x: Ss58AddressFormatRegistry) -> Ss58AddressFormat {
|
||||
Ss58AddressFormat { prefix: x as u16 }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for Ss58AddressFormat {
|
||||
#[inline]
|
||||
fn from(x: u8) -> Ss58AddressFormat {
|
||||
Ss58AddressFormat::from(u16::from(x))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Ss58AddressFormat> for u16 {
|
||||
#[inline]
|
||||
fn from(x: Ss58AddressFormat) -> u16 {
|
||||
from_address_format(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u16> for Ss58AddressFormat {
|
||||
#[inline]
|
||||
fn from(prefix: u16) -> Ss58AddressFormat {
|
||||
Ss58AddressFormat { prefix }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'a str> for Ss58AddressFormat {
|
||||
type Error = ParseError;
|
||||
|
||||
fn try_from(x: &'a str) -> Result<Ss58AddressFormat, Self::Error> {
|
||||
Ss58AddressFormatRegistry::try_from(x).map(|a| a.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'a str> for Ss58AddressFormatRegistry {
|
||||
type Error = ParseError;
|
||||
|
||||
fn try_from(x: &'a str) -> Result<Ss58AddressFormatRegistry, Self::Error> {
|
||||
ALL_SS58_ADDRESS_FORMAT_NAMES
|
||||
.into_iter()
|
||||
.position(|n| n.eq_ignore_ascii_case(x))
|
||||
.map(|lookup| ALL_SS58_ADDRESS_FORMATS[lookup])
|
||||
.ok_or(ParseError)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl From<Ss58AddressFormat> for String {
|
||||
fn from(x: Ss58AddressFormat) -> String {
|
||||
x.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::str::FromStr for Ss58AddressFormatRegistry {
|
||||
type Err = ParseError;
|
||||
|
||||
fn from_str(data: &str) -> Result<Self, Self::Err> {
|
||||
TryFrom::try_from(data)
|
||||
}
|
||||
}
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Error encountered while parsing `Ss58AddressFormat` from &'_ str
|
||||
/// unit struct for now.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct ParseError;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::fmt::Display for ParseError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "failed to parse network value as u16")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for ParseError {}
|
||||
Vendored
+35
@@ -0,0 +1,35 @@
|
||||
// Copyright (C) 2021 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![warn(missing_docs)]
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
//! Enumerations of well-known SS58 account types and tokens used in the Polkadot ecosystem.
|
||||
use core::convert::TryFrom;
|
||||
mod address_format;
|
||||
mod error;
|
||||
mod registry;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
mod token;
|
||||
|
||||
pub use address_format::{from_address_format, Ss58AddressFormat};
|
||||
pub use error::ParseError;
|
||||
pub use registry::{from_known_address_format, Ss58AddressFormatRegistry, TokenRegistry};
|
||||
pub use token::{Token, TokenAmount};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use registry::PREFIX_TO_INDEX;
|
||||
use registry::{ALL_SS58_ADDRESS_FORMATS, ALL_SS58_ADDRESS_FORMAT_NAMES};
|
||||
Vendored
+58
@@ -0,0 +1,58 @@
|
||||
// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::*;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/registry_gen.rs"));
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::fmt::Display for Ss58AddressFormatRegistry {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let lookup = PREFIX_TO_INDEX
|
||||
.binary_search_by_key(&from_known_address_format(*self), |(prefix, _)| *prefix)
|
||||
.expect("always be found");
|
||||
let (_, idx) = PREFIX_TO_INDEX[lookup];
|
||||
write!(f, "{}", ALL_SS58_ADDRESS_FORMAT_NAMES[idx])
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Ss58AddressFormat> for Ss58AddressFormatRegistry {
|
||||
type Error = ParseError;
|
||||
|
||||
fn try_from(x: Ss58AddressFormat) -> Result<Ss58AddressFormatRegistry, ParseError> {
|
||||
PREFIX_TO_INDEX
|
||||
.binary_search_by_key(&x.prefix(), |(prefix, _)| *prefix)
|
||||
.map(|lookup| {
|
||||
let (_, idx) = PREFIX_TO_INDEX[lookup];
|
||||
ALL_SS58_ADDRESS_FORMATS[idx]
|
||||
})
|
||||
.map_err(|_| ParseError)
|
||||
}
|
||||
}
|
||||
|
||||
/// const function to convert [`Ss58AddressFormat`] to u16
|
||||
pub const fn from_known_address_format(x: Ss58AddressFormatRegistry) -> u16 {
|
||||
x as u16
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for TokenRegistry {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
let token: Token = (*self).into();
|
||||
f.debug_struct("TokenRegistry")
|
||||
.field("name", &token.name)
|
||||
.field("decimals", &token.decimals)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
Vendored
+73
@@ -0,0 +1,73 @@
|
||||
// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use super::{Ss58AddressFormat, Ss58AddressFormatRegistry, TokenRegistry};
|
||||
|
||||
#[test]
|
||||
fn is_reserved() {
|
||||
let reserved: Ss58AddressFormat = Ss58AddressFormatRegistry::Reserved46Account.into();
|
||||
assert!(reserved.is_reserved());
|
||||
|
||||
let not_reserved: Ss58AddressFormat = Ss58AddressFormatRegistry::PolkadexAccount.into();
|
||||
assert!(!not_reserved.is_reserved());
|
||||
|
||||
assert!(!Ss58AddressFormat::custom(100).is_reserved());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_custom() {
|
||||
assert!(Ss58AddressFormat::custom(432).is_custom());
|
||||
|
||||
let reserved: Ss58AddressFormat = Ss58AddressFormatRegistry::Reserved46Account.into();
|
||||
assert!(!reserved.is_custom());
|
||||
|
||||
let not_reserved: Ss58AddressFormat = Ss58AddressFormatRegistry::PolkadexAccount.into();
|
||||
assert!(!not_reserved.is_custom());
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn enum_to_name_and_back() {
|
||||
use std::convert::TryInto;
|
||||
for name in Ss58AddressFormat::all_names() {
|
||||
let val: Ss58AddressFormatRegistry = (*name).try_into().expect(name);
|
||||
assert_eq!(name, &val.to_string());
|
||||
|
||||
let val: Ss58AddressFormatRegistry = name.to_lowercase().as_str().try_into().expect(name);
|
||||
assert_eq!(name, &val.to_string());
|
||||
|
||||
let val: Ss58AddressFormatRegistry =
|
||||
name.to_ascii_uppercase().as_str().try_into().expect(name);
|
||||
assert_eq!(name, &val.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prefix() {
|
||||
let dot: Ss58AddressFormat = Ss58AddressFormatRegistry::PolkadotAccount.into();
|
||||
assert_eq!(dot.prefix(), 0);
|
||||
let ksm: Ss58AddressFormat = Ss58AddressFormatRegistry::KusamaAccount.into();
|
||||
assert_eq!(ksm.prefix(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tokens() {
|
||||
let polka = Ss58AddressFormatRegistry::PolkadotAccount;
|
||||
assert_eq!(polka.tokens(), &[TokenRegistry::Dot]);
|
||||
let kusama = Ss58AddressFormatRegistry::KusamaAccount;
|
||||
assert_eq!(kusama.tokens(), &[TokenRegistry::Ksm]);
|
||||
let n46 = Ss58AddressFormatRegistry::Reserved46Account;
|
||||
assert_eq!(n46.tokens(), &[]);
|
||||
}
|
||||
Vendored
+110
@@ -0,0 +1,110 @@
|
||||
// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use num_format::{Locale, ToFormattedString};
|
||||
|
||||
/// Name and decimals of a given token.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Token {
|
||||
/// The short name (ticker) of the token
|
||||
pub name: &'static str,
|
||||
/// The number of decimals the token has (smallest granularity of the token)
|
||||
pub decimals: u8,
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for Token {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("Token")
|
||||
.field("name", &self.name)
|
||||
.field("decimals", &self.decimals)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Token {
|
||||
/// Creates the specified amount of [`Token`] with its name and decimals filled from the
|
||||
/// [`TokenRegistry`] variant.
|
||||
///
|
||||
/// ```
|
||||
/// # use ss58_registry::{Token, TokenRegistry};
|
||||
/// # #[cfg(feature = "std")]
|
||||
/// # fn x() {
|
||||
/// let token: Token = TokenRegistry::Dot.into();
|
||||
/// let my_amount = token.amount(100_000_000);
|
||||
/// assert_eq!(format!("{}", my_amount), "0.010 DOT");
|
||||
/// assert_eq!(format!("{:?}", my_amount), "0.010 DOT (100,000,000)");
|
||||
/// # }
|
||||
/// # #[cfg(not(feature = "std"))]
|
||||
/// # fn x() {}
|
||||
/// # x();
|
||||
/// ```
|
||||
pub fn amount(&self, amount: u128) -> TokenAmount {
|
||||
TokenAmount { token: self.clone(), amount }
|
||||
}
|
||||
}
|
||||
|
||||
/// A given amount of token. Can be used for nicely formatted output and token-aware comparison of
|
||||
/// different amounts.
|
||||
///
|
||||
/// ```
|
||||
/// # use ss58_registry::{Token, TokenAmount};
|
||||
/// # #[cfg(feature = "std")]
|
||||
/// # fn x() {
|
||||
/// let token = Token { name: "I❤U", decimals: 8 };
|
||||
/// let my_amount = token.amount(100_000_000_000);
|
||||
/// assert_eq!(format!("{}", my_amount), "1,000.000 I❤U");
|
||||
/// assert_eq!(format!("{:?}", my_amount), "1000.000 I❤U (100,000,000,000)");
|
||||
/// # }
|
||||
/// # #[cfg(not(feature = "std"))]
|
||||
/// # fn x() {}
|
||||
/// # x();
|
||||
/// ```
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct TokenAmount {
|
||||
/// The token this amount is from.
|
||||
pub token: Token,
|
||||
/// The amount in the smallest granularity of the token.
|
||||
pub amount: u128,
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::fmt::Display for TokenAmount {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let multiplier = u128::pow(10, self.token.decimals as u32);
|
||||
write!(
|
||||
f,
|
||||
"{}.{:0>3} {}",
|
||||
(self.amount / multiplier).to_formatted_string(&Locale::en),
|
||||
self.amount % multiplier / (multiplier / 1000),
|
||||
self.token.name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::fmt::Debug for TokenAmount {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let multiplier = u128::pow(10, self.token.decimals as u32);
|
||||
write!(
|
||||
f,
|
||||
"{}.{:0>3} {} ({})",
|
||||
self.amount / multiplier,
|
||||
self.amount % multiplier / (multiplier / 1000),
|
||||
self.token.name,
|
||||
self.amount.to_formatted_string(&Locale::en),
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user