-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #168 from 0xcregis/15-feat-anychain-polkadot
feat: anychain polkadot
- Loading branch information
Showing
11 changed files
with
799 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
use std::{fmt::Display, marker::PhantomData, str::FromStr}; | ||
|
||
use anychain_core::{hex, Address, AddressError, PublicKey, TransactionError}; | ||
|
||
use crate::{PolkadotFormat, PolkadotNetwork, PolkadotPublicKey, PolkadotSecretKey}; | ||
use base58::{FromBase58, ToBase58}; | ||
use sp_core::hashing::blake2_512; | ||
|
||
#[derive(Debug, PartialEq, Eq, Hash, Clone)] | ||
pub struct PolkadotAddress<N: PolkadotNetwork> { | ||
addr: String, | ||
_network: PhantomData<N>, | ||
} | ||
|
||
impl<N: PolkadotNetwork> Address for PolkadotAddress<N> { | ||
type SecretKey = PolkadotSecretKey; | ||
type PublicKey = PolkadotPublicKey<N>; | ||
type Format = PolkadotFormat; | ||
|
||
fn from_secret_key( | ||
secret_key: &Self::SecretKey, | ||
format: &Self::Format, | ||
) -> Result<Self, anychain_core::AddressError> { | ||
Self::PublicKey::from_secret_key(secret_key).to_address(format) | ||
} | ||
|
||
fn from_public_key( | ||
public_key: &Self::PublicKey, | ||
_format: &Self::Format, | ||
) -> Result<Self, anychain_core::AddressError> { | ||
Self::from_payload(&hex::encode(public_key.address_payload())) | ||
} | ||
} | ||
|
||
impl<N: PolkadotNetwork> PolkadotAddress<N> { | ||
pub fn from_payload(payload: &str) -> Result<Self, AddressError> { | ||
let payload = hex::decode(payload).unwrap(); | ||
let payload = [vec![N::VERSION], payload].concat(); | ||
|
||
let ss_prefix = vec![0x53u8, 0x53, 0x35, 0x38, 0x50, 0x52, 0x45]; | ||
|
||
let checksum = blake2_512(&[ss_prefix, payload.clone()].concat()).to_vec(); | ||
let addr = [payload, checksum[..2].to_vec()].concat().to_base58(); | ||
|
||
Ok(PolkadotAddress { | ||
addr, | ||
_network: PhantomData::<N>, | ||
}) | ||
} | ||
|
||
pub fn to_payload(&self) -> Result<Vec<u8>, AddressError> { | ||
let bin = self.addr.as_str().from_base58()?; | ||
Ok(bin[1..33].to_vec()) | ||
} | ||
} | ||
|
||
impl<N: PolkadotNetwork> FromStr for PolkadotAddress<N> { | ||
type Err = TransactionError; | ||
fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
let bytes = s.from_base58()?; | ||
if N::VERSION != bytes[0] { | ||
return Err(TransactionError::Message(format!( | ||
"Invalid version byte {} for polkadot network {}", | ||
bytes[0], | ||
N::NAME, | ||
))); | ||
} | ||
let checksum_provided = bytes[33..].to_vec(); | ||
let ss_prefix = vec![0x53u8, 0x53, 0x35, 0x38, 0x50, 0x52, 0x45]; | ||
let checksum_expected = | ||
blake2_512(&[ss_prefix, bytes[..33].to_vec()].concat())[..2].to_vec(); | ||
if checksum_expected != checksum_provided { | ||
return Err(TransactionError::Message(format!( | ||
"Invalid {} address", | ||
N::NAME | ||
))); | ||
} | ||
Ok(PolkadotAddress { | ||
addr: s.to_string(), | ||
_network: PhantomData, | ||
}) | ||
} | ||
} | ||
|
||
impl<N: PolkadotNetwork> Display for PolkadotAddress<N> { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "{}", self.addr) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use std::str::FromStr; | ||
|
||
use crate::{PolkadotAddress, PolkadotFormat, PolkadotSecretKey, Westend}; | ||
use anychain_core::{hex, Address}; | ||
use ed25519_dalek_fiat::SecretKey; | ||
|
||
#[test] | ||
fn test_address() { | ||
let sk = [ | ||
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, | ||
25, 26, 27, 28, 29, 30, 31, 32, | ||
]; | ||
let h = hex::encode(sk); | ||
println!("{}", h); | ||
|
||
let sk = SecretKey::from_bytes(&sk).unwrap(); | ||
let sk = PolkadotSecretKey::Ed25519(sk); | ||
|
||
let address = | ||
PolkadotAddress::<Westend>::from_secret_key(&sk, &PolkadotFormat::Standard).unwrap(); | ||
|
||
println!("address = {}", address); | ||
} | ||
|
||
#[test] | ||
fn test_address_2() { | ||
let hash = "8ee504148e75c34e8f051899b3c6e4241ff18dc1c9211260b6a6a434bedb485f"; | ||
let address = PolkadotAddress::<Westend>::from_payload(hash).unwrap(); | ||
println!("address = {}", address); | ||
} | ||
|
||
#[test] | ||
fn test_address_3() { | ||
let addr = "5DoW9HHuqSfpf55Ux5pLdJbHFWvbngeg8Ynhub9DrdtxmZeV"; | ||
let addr = PolkadotAddress::<Westend>::from_str(addr).unwrap(); | ||
let payload = addr.to_payload().unwrap(); | ||
let payload = hex::encode(payload); | ||
println!("{}", payload); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
use anychain_core::Format; | ||
use std::fmt::Display; | ||
|
||
#[derive(Hash, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)] | ||
pub enum PolkadotFormat { | ||
Standard, | ||
} | ||
|
||
impl Format for PolkadotFormat {} | ||
|
||
impl Display for PolkadotFormat { | ||
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
todo!() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,14 @@ | ||
mod public_key; | ||
pub use public_key::*; | ||
|
||
mod address; | ||
pub use address::*; | ||
|
||
mod format; | ||
pub use format::*; | ||
|
||
mod transaction; | ||
pub use transaction::*; | ||
|
||
mod network; | ||
pub use network::*; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
use std::{fmt::Display, str::FromStr}; | ||
|
||
use crate::PolkadotNetwork; | ||
use anychain_core::{Network, NetworkError}; | ||
|
||
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)] | ||
pub struct Kusama; | ||
|
||
impl Network for Kusama { | ||
const NAME: &'static str = "kusama"; | ||
} | ||
|
||
impl PolkadotNetwork for Kusama { | ||
const VERSION: u8 = 0x02; | ||
const PALLET_ASSET: u8 = 4; | ||
const TRANSFER_ALLOW_DEATH: u8 = 0; | ||
const TRANSFER_KEEP_ALIVE: u8 = 3; | ||
} | ||
|
||
impl FromStr for Kusama { | ||
type Err = NetworkError; | ||
fn from_str(_s: &str) -> Result<Self, Self::Err> { | ||
todo!() | ||
} | ||
} | ||
|
||
impl Display for Kusama { | ||
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
todo!() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
mod polkadot; | ||
pub use polkadot::*; | ||
|
||
mod kusama; | ||
pub use kusama::*; | ||
|
||
mod westend; | ||
pub use westend::*; | ||
|
||
mod rococo; | ||
pub use rococo::*; | ||
|
||
use anychain_core::Network; | ||
|
||
pub trait PolkadotNetwork: Network { | ||
const VERSION: u8; | ||
const PALLET_ASSET: u8; | ||
const TRANSFER_ALLOW_DEATH: u8; | ||
const TRANSFER_KEEP_ALIVE: u8; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
use std::{fmt::Display, str::FromStr}; | ||
|
||
use crate::PolkadotNetwork; | ||
use anychain_core::{Network, NetworkError}; | ||
|
||
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)] | ||
pub struct Polkadot; | ||
|
||
impl Network for Polkadot { | ||
const NAME: &'static str = "polkadot"; | ||
} | ||
|
||
impl PolkadotNetwork for Polkadot { | ||
const VERSION: u8 = 0x00; | ||
const PALLET_ASSET: u8 = 5; | ||
const TRANSFER_ALLOW_DEATH: u8 = 0; | ||
const TRANSFER_KEEP_ALIVE: u8 = 3; | ||
} | ||
|
||
impl FromStr for Polkadot { | ||
type Err = NetworkError; | ||
fn from_str(_s: &str) -> Result<Self, Self::Err> { | ||
todo!() | ||
} | ||
} | ||
|
||
impl Display for Polkadot { | ||
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
todo!() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
use std::{fmt::Display, str::FromStr}; | ||
|
||
use crate::PolkadotNetwork; | ||
use anychain_core::{Network, NetworkError}; | ||
|
||
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)] | ||
pub struct Rococo; | ||
|
||
impl Network for Rococo { | ||
const NAME: &'static str = "rococo"; | ||
} | ||
|
||
impl PolkadotNetwork for Rococo { | ||
const VERSION: u8 = 0x2a; | ||
const PALLET_ASSET: u8 = 4; | ||
const TRANSFER_ALLOW_DEATH: u8 = 0; | ||
const TRANSFER_KEEP_ALIVE: u8 = 3; | ||
} | ||
|
||
impl FromStr for Rococo { | ||
type Err = NetworkError; | ||
fn from_str(_s: &str) -> Result<Self, Self::Err> { | ||
todo!() | ||
} | ||
} | ||
|
||
impl Display for Rococo { | ||
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
todo!() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
use std::{fmt::Display, str::FromStr}; | ||
|
||
use crate::PolkadotNetwork; | ||
use anychain_core::{Network, NetworkError}; | ||
|
||
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)] | ||
pub struct Westend; | ||
|
||
impl Network for Westend { | ||
const NAME: &'static str = "westend"; | ||
} | ||
|
||
impl PolkadotNetwork for Westend { | ||
const VERSION: u8 = 0x2a; | ||
const PALLET_ASSET: u8 = 4; | ||
const TRANSFER_ALLOW_DEATH: u8 = 0; | ||
const TRANSFER_KEEP_ALIVE: u8 = 3; | ||
} | ||
|
||
impl FromStr for Westend { | ||
type Err = NetworkError; | ||
fn from_str(_s: &str) -> Result<Self, Self::Err> { | ||
todo!() | ||
} | ||
} | ||
|
||
impl Display for Westend { | ||
fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
todo!() | ||
} | ||
} |
Oops, something went wrong.