snapshot before rebranding
This commit is contained in:
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
# Changelog
|
||||
|
||||
## v0.1 Changes from inside substrate tree
|
||||
|
||||
- try_from(u16), try_from(u8) => from(u16) and from(u8) as the conversions are infallable.
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
# Lists some code owners.
|
||||
#
|
||||
# A codeowner just oversees some part of the codebase. If an owned file is changed then the
|
||||
# corresponding codeowner receives a review request. An approval of the codeowner might be
|
||||
# required for merging a PR (depends on repository settings).
|
||||
#
|
||||
# For details about syntax, see:
|
||||
# https://help.github.com/en/articles/about-code-owners
|
||||
# But here are some important notes:
|
||||
#
|
||||
# - Glob syntax is git-like, e.g. `/core` means the core directory in the root, unlike `core`
|
||||
# which can be everywhere.
|
||||
# - Multiple owners are supported.
|
||||
# - Either handle (e.g, @github_user or @github_org/team) or email can be used. Keep in mind,
|
||||
# that handles might work better because they are more recognizable on GitHub,
|
||||
# you can use them for mentioning unlike an email.
|
||||
# - The latest matching rule, if multiple, takes precedence.
|
||||
|
||||
# CI
|
||||
/.github/ @paritytech/ci
|
||||
/scripts/ci/ @paritytech/ci
|
||||
/.gitlab-ci.yml @paritytech/ci
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
[package]
|
||||
name = "pezkuwi-ss58-registry"
|
||||
version = "1.51.0"
|
||||
description = "Registry of known SS58 address types - PezkuwiChain fork"
|
||||
documentation = "https://docs.rs/pez-ss58-registry"
|
||||
license = "Apache-2.0"
|
||||
authors.workspace = true
|
||||
edition.workspace = true
|
||||
homepage.workspace = true
|
||||
repository.workspace = true
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = ["num-format"]
|
||||
|
||||
[dependencies]
|
||||
num-format = { version = "0.4.3", optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
quote = { version = "1.0.15", default-features = false }
|
||||
serde = { version = "1.0.136", default-features = false, features = ["std", "derive"] }
|
||||
serde_json = { version = "1.0.79", default-features = false, features = ["std"] }
|
||||
proc-macro2 = "1.0.36"
|
||||
Inflector = { version = "0.11.4", default-features = false }
|
||||
unicode-xid = "0.2.2"
|
||||
Vendored
+201
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
Vendored
+39
@@ -0,0 +1,39 @@
|
||||
# SS58 Registry
|
||||
|
||||
[](#LICENSE) [](https://gitlab.parity.io/parity/ss58-registry/pipelines)
|
||||
|
||||
A list of known [SS58](https://docs.substrate.io/reference/address-formats/) account types as an enum, typically used by the Polkadot, Kusama or Substrate ecosystems.
|
||||
|
||||
These are derived from the [json data file](ss58-registry.json) in this repository which contains entries like this:
|
||||
|
||||
```js
|
||||
{
|
||||
"prefix": 5, // unique u16
|
||||
"network": "astar", // unique no spaces
|
||||
"displayName": "Astar Network", //
|
||||
"symbols": ["ASTR"], // symbol for each instance of the Balances pallet (usually one)
|
||||
"decimals": [18], // decimals for each symbol listed
|
||||
"standardAccount": "*25519", // Sr25519, Ed25519 or secp256k1
|
||||
"website": "https://astar.network" // website or code repository of network
|
||||
},
|
||||
```
|
||||
|
||||
## Process
|
||||
|
||||
1. Fork and clone this repo.
|
||||
|
||||
2. Add an additional account type to `ss58-registry.json` (contiguous prefixes are better).
|
||||
|
||||
3. Bump the minor (middle) version number of the `Cargo.toml` by running:
|
||||
```
|
||||
cargo install cargo-bump && cargo bump minor
|
||||
```
|
||||
4. Run git stage, commit, push and then raise a pull request.
|
||||
|
||||
5. Once the PR has landed, one of the admins can
|
||||
[create a new release](https://github.com/paritytech/ss58-registry/releases/new).
|
||||
This will release the new version to [crates.io](https://crates.io/crates/ss58-registry)
|
||||
|
||||
## Licensing
|
||||
|
||||
Apache-2.0
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
// 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.
|
||||
#![feature(bench_black_box)]
|
||||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
use std::hint::black_box;
|
||||
|
||||
use test::Bencher;
|
||||
static BENCH_SIZE: u16 = 100;
|
||||
use ss58_registry::{from_address_format, Ss58AddressFormat, Ss58AddressFormatRegistry};
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[bench]
|
||||
fn new(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
for i in 0..BENCH_SIZE {
|
||||
let _ = ss58_registry::Ss58AddressFormat::custom(black_box(i));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn is_custom(b: &mut Bencher) {
|
||||
let v: Vec<Ss58AddressFormat> =
|
||||
(0..BENCH_SIZE).map(ss58_registry::Ss58AddressFormat::custom).collect();
|
||||
b.iter(|| {
|
||||
for i in &v {
|
||||
let _ = i.is_custom();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn is_reserved(b: &mut Bencher) {
|
||||
let v: Vec<Ss58AddressFormat> =
|
||||
(0..BENCH_SIZE).map(ss58_registry::Ss58AddressFormat::custom).collect();
|
||||
b.iter(|| {
|
||||
for i in &v {
|
||||
let _ = i.is_reserved();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn to_string(b: &mut Bencher) {
|
||||
let v: Vec<Ss58AddressFormat> =
|
||||
(0..BENCH_SIZE).map(ss58_registry::Ss58AddressFormat::custom).collect();
|
||||
b.iter(|| {
|
||||
for i in &v {
|
||||
let _ = i.to_string();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn known_to_prefix(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
for i in ss58_registry::Ss58AddressFormat::all() {
|
||||
let i: Ss58AddressFormat = (*i).into();
|
||||
let _ii: u16 = from_address_format(i);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn name_to_enum(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
for name in ss58_registry::Ss58AddressFormat::all_names() {
|
||||
let _: Ss58AddressFormatRegistry =
|
||||
(*name).try_into().unwrap_or_else(|_| panic!("{}", name));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn prefix_to_known(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
for i in 0_u16..100 {
|
||||
let i: Ss58AddressFormat = i.into();
|
||||
let _: Result<Ss58AddressFormatRegistry, _> = i.try_into();
|
||||
}
|
||||
})
|
||||
}
|
||||
Vendored
+319
@@ -0,0 +1,319 @@
|
||||
// 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.
|
||||
|
||||
//! Enumerations of well-known SS58 account types and tokens used in the Polkadot ecosystem.
|
||||
use proc_macro2::Ident;
|
||||
use quote::{format_ident, quote};
|
||||
use serde::Deserialize;
|
||||
use std::{
|
||||
collections::{btree_map::Entry, BTreeMap, HashMap},
|
||||
env, fs,
|
||||
path::Path,
|
||||
};
|
||||
use unicode_xid::UnicodeXID;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Registry {
|
||||
#[serde(rename = "registry")]
|
||||
accounts: Vec<AccountType>,
|
||||
}
|
||||
|
||||
fn is_valid_rust_identifier(id: &str) -> Result<(), String> {
|
||||
if let Some(ch) = id.chars().next() {
|
||||
if ch.is_xid_start() {
|
||||
for ch in id.chars().skip(1) {
|
||||
if !ch.is_xid_continue() {
|
||||
return Err(format!("Invalid char `{}` in `{}`", ch, id))
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
} else {
|
||||
Err(format!("`{}` starts with `{}` which is not valid at the start", id, ch))
|
||||
}
|
||||
} else {
|
||||
Err("empty identifier".into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Registry {
|
||||
pub fn validate(self) -> Result<(Vec<AccountType>, Vec<TokenType>), String> {
|
||||
let mut tokens = BTreeMap::<String, TokenType>::new();
|
||||
let mut used_prefixes = HashMap::<u16, AccountType>::new();
|
||||
let mut used_networks = HashMap::<String, AccountType>::new();
|
||||
for account_type in &self.accounts {
|
||||
if let Some(clash) = used_prefixes.insert(account_type.prefix, (*account_type).clone())
|
||||
{
|
||||
return Err(format!(
|
||||
"prefixes must be unique but this account's prefix:\n{:#?}\nclashed with\n{:#?}",
|
||||
account_type,
|
||||
clash
|
||||
));
|
||||
}
|
||||
if let Some(clash) = used_networks.insert(account_type.name(), account_type.clone()) {
|
||||
return Err(format!(
|
||||
"networks must be unique but this account's network:\n{:#?}\nclashed with\n:{:#?}",
|
||||
account_type,
|
||||
clash
|
||||
));
|
||||
}
|
||||
if account_type.network.is_empty() {
|
||||
return Err("network is mandatory.".into())
|
||||
}
|
||||
|
||||
if let Err(err) = is_valid_rust_identifier(&account_type.name()) {
|
||||
return Err(format!("network not valid: {} for {:#?}", err, account_type))
|
||||
}
|
||||
if account_type.decimals.len() != account_type.symbols.len() {
|
||||
return Err(format!(
|
||||
"decimals must be specified for each symbol: {:?}",
|
||||
account_type
|
||||
))
|
||||
}
|
||||
for (name, decimals) in account_type.symbols.iter().zip(&account_type.decimals) {
|
||||
use Entry::*;
|
||||
let network = account_type.display_name.clone();
|
||||
match tokens.entry(name.to_owned()) {
|
||||
Occupied(mut e) => {
|
||||
if e.get().decimals != *decimals {
|
||||
return Err(format!(
|
||||
"Inconsistent decimals specified for token {}.\nPrevious networks: {}\nCurrent network: {}",
|
||||
name,
|
||||
e.get().networks.join(", "),
|
||||
network,
|
||||
))
|
||||
}
|
||||
e.get_mut().networks.push(network);
|
||||
},
|
||||
Vacant(e) => {
|
||||
e.insert(TokenType {
|
||||
symbol: name.to_owned(),
|
||||
decimals: *decimals,
|
||||
networks: vec![network],
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
let tokens = tokens.into_values().collect();
|
||||
Ok((self.accounts, tokens))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone, Copy)]
|
||||
enum SignatureType {
|
||||
#[serde(rename = "Sr25519")]
|
||||
Sr25519,
|
||||
#[serde(rename = "Ed25519")]
|
||||
Ed25519,
|
||||
#[serde(rename = "secp256k1")]
|
||||
Secp256k1,
|
||||
#[serde(rename = "*25519")]
|
||||
Any25519,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct AccountType {
|
||||
prefix: u16,
|
||||
network: String,
|
||||
display_name: String,
|
||||
/// If standard account is None then the network is reserved.
|
||||
standard_account: Option<SignatureType>,
|
||||
symbols: Vec<String>,
|
||||
decimals: Vec<u8>,
|
||||
website: Option<String>,
|
||||
}
|
||||
|
||||
impl AccountType {
|
||||
fn name(&self) -> String {
|
||||
format!("{}Account", inflector::cases::pascalcase::to_pascal_case(&self.network))
|
||||
}
|
||||
|
||||
fn tokens(&self) -> impl Iterator<Item = Ident> + '_ {
|
||||
self.symbols.iter().map(|s| token_symbol_to_variant(s))
|
||||
}
|
||||
|
||||
fn is_reserved(&self) -> bool {
|
||||
self.standard_account.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
fn token_symbol_to_variant(symbol: &str) -> Ident {
|
||||
format_ident!("{}", inflector::cases::pascalcase::to_pascal_case(symbol))
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct TokenType {
|
||||
symbol: String,
|
||||
decimals: u8,
|
||||
networks: Vec<String>,
|
||||
}
|
||||
|
||||
impl TokenType {
|
||||
fn doc_string(&self) -> String {
|
||||
format!("{} token used on {}", self.symbol, self.networks.join(", "))
|
||||
}
|
||||
}
|
||||
|
||||
fn consecutive_runs(data: &[u16]) -> (Vec<u16>, Vec<u16>) {
|
||||
let mut slice_start = 0_u16;
|
||||
let (mut starts, mut ends) = (Vec::new(), Vec::new());
|
||||
for i in 1..data.len() {
|
||||
if data[i - 1] + 1 != data[i] {
|
||||
starts.push(slice_start);
|
||||
ends.push(data[i - 1]);
|
||||
slice_start = data[i];
|
||||
}
|
||||
}
|
||||
if !data.is_empty() {
|
||||
starts.push(slice_start);
|
||||
ends.push(data[data.len() - 1]);
|
||||
}
|
||||
(starts, ends)
|
||||
}
|
||||
|
||||
fn create_ss58_registry(json: &str) -> Result<proc_macro2::TokenStream, String> {
|
||||
let registry: Registry =
|
||||
serde_json::from_str(json).map_err(|e| format!("json parsing error: {}", e))?;
|
||||
|
||||
let (mut accounts, tokens) = registry.validate()?;
|
||||
|
||||
// Sort by name so that we can later binary search by network
|
||||
accounts.sort_by_key(|a| a.network.clone());
|
||||
|
||||
// Variables to insert into quote template:
|
||||
let identifier: Vec<_> = accounts.iter().map(|r| format_ident!("{}", r.name())).collect();
|
||||
|
||||
let count = accounts.len();
|
||||
let prefix: Vec<_> = accounts.iter().map(|r| r.prefix).collect();
|
||||
|
||||
let name = accounts.iter().map(|r| r.network.clone());
|
||||
let desc = accounts.iter().map(|r| {
|
||||
if let Some(website) = &r.website {
|
||||
format!("{} - <{}>", r.display_name, website)
|
||||
} else {
|
||||
r.display_name.clone()
|
||||
}
|
||||
});
|
||||
|
||||
let mut prefix_to_idx: Vec<_> = prefix.iter().enumerate().map(|(a, b)| (b, a)).collect();
|
||||
prefix_to_idx.sort_by_key(|(prefix, _)| *prefix);
|
||||
let prefix_to_idx = prefix_to_idx.iter().map(|(prefix, idx)| quote! { (#prefix, #idx) });
|
||||
|
||||
let ident_to_tokens: Vec<_> = accounts
|
||||
.iter()
|
||||
.map(|r| {
|
||||
let t = r.tokens();
|
||||
quote! { #( TokenRegistry::#t ,)* }
|
||||
})
|
||||
.collect();
|
||||
|
||||
let reserved_prefixes = accounts.iter().filter(|r| r.is_reserved()).map(|r| r.prefix);
|
||||
|
||||
let mut ordered_prefixes = accounts.iter().map(|i| i.prefix).collect::<Vec<_>>();
|
||||
ordered_prefixes.sort_unstable();
|
||||
let (prefix_starts, prefix_ends) = consecutive_runs(ordered_prefixes.as_slice());
|
||||
|
||||
let token_defs: Vec<_> = tokens.iter().map(|t| token_symbol_to_variant(&t.symbol)).collect();
|
||||
let token_names = tokens.iter().map(|t| t.symbol.to_owned());
|
||||
let token_docs = tokens.iter().map(|t| t.doc_string());
|
||||
let token_decimals = tokens.iter().map(|t| t.decimals);
|
||||
|
||||
Ok(quote! {
|
||||
/// A known address (sub)format/network ID for SS58.
|
||||
#[non_exhaustive]
|
||||
#[repr(u16)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum Ss58AddressFormatRegistry {
|
||||
#(#[doc = #desc] #identifier = #prefix),*,
|
||||
}
|
||||
|
||||
/// All non-custom address formats (Sorted by network)
|
||||
pub(crate) static ALL_SS58_ADDRESS_FORMATS: [Ss58AddressFormatRegistry; #count] = [
|
||||
#(Ss58AddressFormatRegistry::#identifier),*,
|
||||
];
|
||||
|
||||
/// Names of all address formats (Sorted by network)
|
||||
pub(crate) static ALL_SS58_ADDRESS_FORMAT_NAMES: [&str; #count] = [
|
||||
#(#name),*,
|
||||
];
|
||||
|
||||
/// (Sorted) prefixes to index of ALL_SS58_ADDRESS_FORMATS
|
||||
pub(crate) static PREFIX_TO_INDEX: [(u16, usize); #count] = [
|
||||
#(#prefix_to_idx),*,
|
||||
];
|
||||
|
||||
impl Ss58AddressFormatRegistry {
|
||||
/// Tokens used on the given network.
|
||||
pub fn tokens(&self) -> &'static[TokenRegistry] {
|
||||
match self {
|
||||
#(Ss58AddressFormatRegistry::#identifier => &[#ident_to_tokens],)*
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Ss58AddressFormat {
|
||||
/// Network/AddressType is reserved for future use.
|
||||
pub fn is_reserved(&self) -> bool {
|
||||
self.prefix() > 16384 || matches!(self.prefix(), #(#reserved_prefixes)|*)
|
||||
}
|
||||
|
||||
/// A custom format is one that is not already known.
|
||||
pub fn is_custom(&self) -> bool {
|
||||
// A match is faster than bin search
|
||||
// as most hits will be in the first group.
|
||||
!matches!(self.prefix(), #(#prefix_starts..=#prefix_ends)|*)
|
||||
}
|
||||
}
|
||||
|
||||
/// List of well-known tokens used on some network in the ecosystem.
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum TokenRegistry {
|
||||
#(#[doc = #token_docs]
|
||||
#token_defs,)*
|
||||
}
|
||||
|
||||
impl From<TokenRegistry> for Token {
|
||||
fn from(x: TokenRegistry) -> Self {
|
||||
match x {
|
||||
#(TokenRegistry::#token_defs => Token { name: #token_names, decimals: #token_decimals },)*
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-changed=ss58-registry.json");
|
||||
|
||||
let out_dir = env::var_os("OUT_DIR").expect("OUT_DIR should exist");
|
||||
|
||||
let code = match create_ss58_registry(include_str!("ss58-registry.json")) {
|
||||
Ok(result) => result.to_string(),
|
||||
Err(msg) => {
|
||||
eprintln!("failed to generate code from json: {}", &msg);
|
||||
std::process::exit(-1);
|
||||
},
|
||||
};
|
||||
|
||||
let dest_path = Path::new(&out_dir).join("registry_gen.rs");
|
||||
if let Err(err) = fs::write(&dest_path, code) {
|
||||
eprintln!("failed to write generated code to {}: {}", &dest_path.display(), err);
|
||||
std::process::exit(-1);
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"name": "@substrate/ss58-registry",
|
||||
"version": "1.17.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@substrate/ss58-registry",
|
||||
"version": "1.17.0",
|
||||
"license": "Apache-2.0",
|
||||
"devDependencies": {
|
||||
"toml": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/toml": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
|
||||
"integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==",
|
||||
"dev": true
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"toml": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
|
||||
"integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "@substrate/ss58-registry",
|
||||
"version": "1.17.0",
|
||||
"license": "Apache-2.0",
|
||||
"description": "Registry for SS58 account types",
|
||||
"author": "Parity Technologies <admin@parity.io>",
|
||||
"main": "ss58-registry.json",
|
||||
"repository": "https://github.com/paritytech/ss58-registry",
|
||||
"scripts": {
|
||||
"alignVersion": "./scripts/js/align_version.mjs && npm install",
|
||||
"build": "npm run alignVersion && rm -rf npm_dist && mkdir -p npm_dist && ./scripts/js/build_js.mjs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"toml": "^3.0.0"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
Vendored
+23
@@ -0,0 +1,23 @@
|
||||
# Basic
|
||||
hard_tabs = true
|
||||
max_width = 100
|
||||
use_small_heuristics = "Max"
|
||||
# Imports
|
||||
imports_granularity = "Crate"
|
||||
reorder_imports = true
|
||||
# Consistency
|
||||
newline_style = "Unix"
|
||||
# Format comments
|
||||
comment_width = 100
|
||||
wrap_comments = true
|
||||
# Misc
|
||||
chain_width = 80
|
||||
spaces_around_ranges = false
|
||||
binop_separator = "Back"
|
||||
reorder_impl_items = false
|
||||
match_arm_leading_pipes = "Preserve"
|
||||
match_arm_blocks = false
|
||||
match_block_trailing_comma = true
|
||||
trailing_comma = "Vertical"
|
||||
trailing_semicolon = false
|
||||
use_field_init_shorthand = true
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
# This template contains all of the possible sections and their default values
|
||||
|
||||
# Note that all fields that take a lint level have these possible values:
|
||||
# * deny - An error will be produced and the check will fail
|
||||
# * warn - A warning will be produced, but the check will not fail
|
||||
# * allow - No warning or error will be produced, though in some cases a note
|
||||
# will be
|
||||
|
||||
# The values provided in this template are the default values that will be used
|
||||
# when any section or field is not specified in your own configuration
|
||||
|
||||
# If 1 or more target triples (and optionally, target_features) are specified,
|
||||
# only the specified targets will be checked when running `cargo deny check`.
|
||||
# This means, if a particular package is only ever used as a target specific
|
||||
# dependency, such as, for example, the `nix` crate only being used via the
|
||||
# `target_family = "unix"` configuration, that only having windows targets in
|
||||
# this list would mean the nix crate, as well as any of its exclusive
|
||||
# dependencies not shared by any other crates, would be ignored, as the target
|
||||
# list here is effectively saying which targets you are building for.
|
||||
targets = [
|
||||
# The triple can be any string, but only the target triples built in to
|
||||
# rustc (as of 1.40) can be checked against actual config expressions
|
||||
#{ triple = "x86_64-unknown-linux-musl" },
|
||||
# You can also specify which target_features you promise are enabled for a
|
||||
# particular target. target_features are currently not validated against
|
||||
# the actual valid features supported by the target architecture.
|
||||
#{ triple = "wasm32-unknown-unknown", features = ["atomics"] },
|
||||
]
|
||||
|
||||
# This section is considered when running `cargo deny check advisories`
|
||||
# More documentation for the advisories section can be found here:
|
||||
# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
|
||||
[advisories]
|
||||
# The path where the advisory database is cloned/fetched into
|
||||
db-path = "~/.cargo/advisory-db"
|
||||
# The url of the advisory database to use
|
||||
db-url = "https://github.com/rustsec/advisory-db"
|
||||
# The lint level for security vulnerabilities
|
||||
vulnerability = "deny"
|
||||
# The lint level for unmaintained crates
|
||||
unmaintained = "warn"
|
||||
# The lint level for crates that have been yanked from their source registry
|
||||
yanked = "warn"
|
||||
# The lint level for crates with security notices. Note that as of
|
||||
# 2019-12-17 there are no security notice advisories in
|
||||
# https://github.com/rustsec/advisory-db
|
||||
notice = "warn"
|
||||
# A list of advisory IDs to ignore. Note that ignored advisories will still
|
||||
# output a note when they are encountered.
|
||||
ignore = [
|
||||
#"RUSTSEC-0000-0000",
|
||||
]
|
||||
# Threshold for security vulnerabilities, any vulnerability with a CVSS score
|
||||
# lower than the range specified will be ignored. Note that ignored advisories
|
||||
# will still output a note when they are encountered.
|
||||
# * None - CVSS Score 0.0
|
||||
# * Low - CVSS Score 0.1 - 3.9
|
||||
# * Medium - CVSS Score 4.0 - 6.9
|
||||
# * High - CVSS Score 7.0 - 8.9
|
||||
# * Critical - CVSS Score 9.0 - 10.0
|
||||
#severity-threshold =
|
||||
|
||||
# This section is considered when running `cargo deny check licenses`
|
||||
# More documentation for the licenses section can be found here:
|
||||
# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
|
||||
[licenses]
|
||||
# The lint level for crates which do not have a detectable license
|
||||
unlicensed = "deny"
|
||||
# List of explictly allowed licenses
|
||||
# See https://spdx.org/licenses/ for list of possible licenses
|
||||
# [possible values: any SPDX 3.7 short identifier (+ optional exception)].
|
||||
allow = [
|
||||
#"MIT",
|
||||
#"Apache-2.0",
|
||||
#"Apache-2.0 WITH LLVM-exception",
|
||||
]
|
||||
# List of explictly disallowed licenses
|
||||
# See https://spdx.org/licenses/ for list of possible licenses
|
||||
# [possible values: any SPDX 3.7 short identifier (+ optional exception)].
|
||||
deny = [
|
||||
#"Nokia",
|
||||
]
|
||||
# Lint level for licenses considered copyleft
|
||||
copyleft = "allow"
|
||||
# Blanket approval or denial for OSI-approved or FSF Free/Libre licenses
|
||||
# * both - The license will be approved if it is both OSI-approved *AND* FSF
|
||||
# * either - The license will be approved if it is either OSI-approved *OR* FSF
|
||||
# * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF
|
||||
# * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved
|
||||
# * neither - This predicate is ignored and the default lint level is used
|
||||
allow-osi-fsf-free = "either"
|
||||
# Lint level used when no other predicates are matched
|
||||
# 1. License isn't in the allow or deny lists
|
||||
# 2. License isn't copyleft
|
||||
# 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither"
|
||||
default = "deny"
|
||||
# The confidence threshold for detecting a license from license text.
|
||||
# The higher the value, the more closely the license text must be to the
|
||||
# canonical license text of a valid SPDX license file.
|
||||
# [possible values: any between 0.0 and 1.0].
|
||||
confidence-threshold = 0.9
|
||||
# Allow 1 or more licenses on a per-crate basis, so that particular licenses
|
||||
# aren't accepted for every possible crate as with the normal allow list
|
||||
exceptions = [
|
||||
# Each entry is the crate and version constraint, and its specific allow
|
||||
# list
|
||||
#{ allow = ["Zlib"], name = "adler32", version = "*" },
|
||||
]
|
||||
|
||||
# Some crates don't have (easily) machine readable licensing information,
|
||||
# adding a clarification entry for it allows you to manually specify the
|
||||
# licensing information
|
||||
[[licenses.clarify]]
|
||||
# The name of the crate the clarification applies to
|
||||
name = "ring"
|
||||
# THe optional version constraint for the crate
|
||||
#version = "*"
|
||||
# The SPDX expression for the license requirements of the crate
|
||||
expression = "OpenSSL"
|
||||
# One or more files in the crate's source used as the "source of truth" for
|
||||
# the license expression. If the contents match, the clarification will be used
|
||||
# when running the license check, otherwise the clarification will be ignored
|
||||
# and the crate will be checked normally, which may produce warnings or errors
|
||||
# depending on the rest of your configuration
|
||||
license-files = [
|
||||
# Each entry is a crate relative path, and the (opaque) hash of its contents
|
||||
{ path = "LICENSE", hash = 0xbd0eed23 }
|
||||
]
|
||||
[[licenses.clarify]]
|
||||
name = "webpki"
|
||||
expression = "ISC"
|
||||
license-files = [{ path = "LICENSE", hash = 0x001c7e6c }]
|
||||
|
||||
[licenses.private]
|
||||
# If true, ignores workspace crates that aren't published, or are only
|
||||
# published to private registries
|
||||
ignore = false
|
||||
# One or more private registries that you might publish crates to, if a crate
|
||||
# is only published to private registries, and ignore is true, the crate will
|
||||
# not have its license(s) checked
|
||||
registries = [
|
||||
#"https://sekretz.com/registry
|
||||
]
|
||||
|
||||
# This section is considered when running `cargo deny check bans`.
|
||||
# More documentation about the 'bans' section can be found here:
|
||||
# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html
|
||||
[bans]
|
||||
# Lint level for when multiple versions of the same crate are detected
|
||||
multiple-versions = "warn"
|
||||
# The graph highlighting used when creating dotgraphs for crates
|
||||
# with multiple versions
|
||||
# * lowest-version - The path to the lowest versioned duplicate is highlighted
|
||||
# * simplest-path - The path to the version with the fewest edges is highlighted
|
||||
# * all - Both lowest-version and simplest-path are used
|
||||
highlight = "lowest-version"
|
||||
# List of crates that are allowed. Use with care!
|
||||
allow = [
|
||||
#{ name = "ansi_term", version = "=0.11.0" },
|
||||
]
|
||||
# List of crates to deny
|
||||
deny = [
|
||||
{ name = "parity-util-mem", version = "<0.6" }
|
||||
# Each entry the name of a crate and a version range. If version is
|
||||
# not specified, all versions will be matched.
|
||||
]
|
||||
# Certain crates/versions that will be skipped when doing duplicate detection.
|
||||
skip = [
|
||||
#{ name = "ansi_term", version = "=0.11.0" },
|
||||
]
|
||||
# Similarly to `skip` allows you to skip certain crates during duplicate
|
||||
# detection. Unlike skip, it also includes the entire tree of transitive
|
||||
# dependencies starting at the specified crate, up to a certain depth, which is
|
||||
# by default infinite
|
||||
skip-tree = [
|
||||
#{ name = "ansi_term", version = "=0.11.0", depth = 20 },
|
||||
]
|
||||
|
||||
# This section is considered when running `cargo deny check sources`.
|
||||
# More documentation about the 'sources' section can be found here:
|
||||
# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html
|
||||
[sources]
|
||||
# Lint level for what to happen when a crate from a crate registry that is not
|
||||
# in the allow list is encountered
|
||||
unknown-registry = "deny"
|
||||
# Lint level for what to happen when a crate from a git repository that is not
|
||||
# in the allow list is encountered
|
||||
unknown-git = "warn"
|
||||
# List of URLs for allowed crate registries. Defaults to the crates.io index
|
||||
# if not specified. If it is specified but empty, no registries are allowed.
|
||||
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
|
||||
# List of URLs for allowed Git repositories
|
||||
allow-git = []
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import fs from 'fs';
|
||||
import toml from 'toml';
|
||||
|
||||
function main () {
|
||||
const pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf-8'));
|
||||
const tomlData = toml.parse(fs.readFileSync('Cargo.toml', 'utf-8'));
|
||||
|
||||
pkgJson.version = tomlData.package.version;
|
||||
|
||||
fs.writeFileSync('package.json', JSON.stringify(pkgJson, null, 2));
|
||||
}
|
||||
|
||||
main();
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
const OUTPUT = 'npm_dist/';
|
||||
const HEADER = `// Copyright (C) 2021-${new Date().getFullYear()} 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.
|
||||
`;
|
||||
|
||||
function copyFiles (...files) {
|
||||
files.forEach((f) =>
|
||||
writeFile(f, fs.readFileSync(f, 'utf-8'))
|
||||
);
|
||||
}
|
||||
|
||||
function writeFile (file, contents) {
|
||||
fs.writeFileSync(path.join(OUTPUT, file), contents);
|
||||
}
|
||||
|
||||
function writeWithHeader (file, contents) {
|
||||
writeFile(file, `${HEADER}\n${contents}`);
|
||||
}
|
||||
|
||||
function mkdirs (...dirs) {
|
||||
dirs.forEach((d) => {
|
||||
const dir = path.join(OUTPUT, d);
|
||||
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function adjustPkg (pkgJson, obj) {
|
||||
Object.entries(obj).forEach(([k, v]) => {
|
||||
delete pkgJson[k];
|
||||
|
||||
if (v !== undefined) {
|
||||
pkgJson[k] = v;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function main () {
|
||||
const typesD = fs.readFileSync('types.d.ts', 'utf-8');
|
||||
const pkgJson = JSON.parse(fs.readFileSync('package.json', 'utf-8'));
|
||||
const all = JSON.parse(fs.readFileSync('ss58-registry.json', 'utf-8'));
|
||||
const code = JSON.stringify(all.registry, null, '\t');
|
||||
|
||||
adjustPkg(pkgJson, {
|
||||
exports: {
|
||||
'.': {
|
||||
types: './index.d.ts',
|
||||
require: './cjs/index.js',
|
||||
default: './esm/index.js'
|
||||
},
|
||||
'./package.json': './package.json',
|
||||
'./cjs/package.json': './cjs/package.json',
|
||||
'./esm/package.json': './esm/package.json'
|
||||
},
|
||||
main: './cjs/index.js',
|
||||
module: './esm/index.js',
|
||||
types: 'index.d.ts',
|
||||
type: 'module',
|
||||
scripts: undefined,
|
||||
devDependencies: undefined
|
||||
});
|
||||
|
||||
mkdirs('cjs', 'esm');
|
||||
|
||||
writeWithHeader('cjs/index.js', `module.exports = ${code};\n`);
|
||||
writeWithHeader('esm/index.js', `export default ${code};\n`);
|
||||
|
||||
writeFile('cjs/package.json', JSON.stringify({ type: 'commonjs' }, null, '\t'));
|
||||
writeFile('esm/package.json', JSON.stringify({ type: 'module' }, null, '\t'));
|
||||
|
||||
writeFile('package.json', JSON.stringify(pkgJson, null, '\t'));
|
||||
writeFile('index.d.ts', `${typesD}\ndeclare const _default: Registry;\n\nexport default _default;\n`);
|
||||
|
||||
copyFiles('CHANGELOG.md', 'README.md', 'LICENSE');
|
||||
}
|
||||
|
||||
main();
|
||||
+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),
|
||||
)
|
||||
}
|
||||
}
|
||||
+1930
File diff suppressed because it is too large
Load Diff
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
// 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.
|
||||
|
||||
export interface RegistryEntry {
|
||||
decimals: number[],
|
||||
displayName: string;
|
||||
network: string;
|
||||
prefix: number;
|
||||
standardAccount: '*25519' | 'Ed25519' | 'Sr25519' | 'secp256k1' | null;
|
||||
symbols: string[];
|
||||
website: string | null;
|
||||
}
|
||||
|
||||
export type Registry = RegistryEntry[];
|
||||
Reference in New Issue
Block a user