1use crate::crypto::address::{Address, AddressFormat};
2use crate::crypto::{Algorithm, PublicKey, SecretKey};
3use crate::types::{
4 Block, BlockIdentifier, CallRequest, Coin, Currency, CurveType, NetworkIdentifier,
5 PartialBlockIdentifier, SignatureType, Transaction, TransactionIdentifier,
6};
7use anyhow::Result;
8use async_trait::async_trait;
9use serde::de::DeserializeOwned;
10use serde::Serialize;
11use serde_json::Value;
12use std::sync::Arc;
13
14pub use rosetta_crypto as crypto;
15pub use rosetta_types as types;
16
17type NodeCommand = Arc<dyn Fn(&str, u16) -> Vec<String> + Send + Sync + 'static>;
18
19#[derive(Clone)]
20pub struct BlockchainConfig {
21 pub blockchain: &'static str,
22 pub network: &'static str,
23 pub algorithm: Algorithm,
24 pub address_format: AddressFormat,
25 pub coin: u32,
26 pub bip44: bool,
27 pub utxo: bool,
28 pub currency_unit: &'static str,
29 pub currency_symbol: &'static str,
30 pub currency_decimals: u32,
31 pub node_port: u16,
32 pub node_image: &'static str,
33 pub node_command: NodeCommand,
34 pub node_additional_ports: &'static [u16],
35 pub connector_port: u16,
36 pub testnet: bool,
37}
38
39impl BlockchainConfig {
40 pub fn network(&self) -> NetworkIdentifier {
41 NetworkIdentifier {
42 blockchain: self.blockchain.into(),
43 network: self.network.into(),
44 sub_network_identifier: None,
45 }
46 }
47
48 pub fn currency(&self) -> Currency {
49 Currency {
50 symbol: self.currency_symbol.into(),
51 decimals: self.currency_decimals,
52 metadata: None,
53 }
54 }
55
56 pub fn node_url(&self) -> String {
57 format!("http://rosetta.analog.one:{}", self.node_port)
58 }
59
60 pub fn connector_url(&self) -> String {
61 format!("http://rosetta.analog.one:{}", self.connector_port)
62 }
63}
64
65#[async_trait]
66pub trait BlockchainClient: Sized + Send + Sync + 'static {
67 type MetadataParams: DeserializeOwned + Send + Sync + 'static;
68 type Metadata: Serialize;
69 fn create_config(network: &str) -> Result<BlockchainConfig>;
70 async fn new(config: BlockchainConfig, addr: &str) -> Result<Self>;
71 fn config(&self) -> &BlockchainConfig;
72 fn genesis_block(&self) -> &BlockIdentifier;
73 async fn node_version(&self) -> Result<String>;
74 async fn current_block(&self) -> Result<BlockIdentifier>;
75 async fn balance(&self, address: &Address, block: &BlockIdentifier) -> Result<u128>;
76 async fn coins(&self, address: &Address, block: &BlockIdentifier) -> Result<Vec<Coin>>;
77 async fn faucet(&self, address: &Address, param: u128) -> Result<Vec<u8>>;
78 async fn metadata(
79 &self,
80 public_key: &PublicKey,
81 params: &Self::MetadataParams,
82 ) -> Result<Self::Metadata>;
83 async fn submit(&self, transaction: &[u8]) -> Result<Vec<u8>>;
84 async fn block(&self, block: &PartialBlockIdentifier) -> Result<Block>;
85 async fn block_transaction(
86 &self,
87 block: &BlockIdentifier,
88 tx: &TransactionIdentifier,
89 ) -> Result<Transaction>;
90 async fn call(&self, req: &CallRequest) -> Result<Value>;
91}
92
93pub trait RosettaAlgorithm {
94 fn to_signature_type(self) -> SignatureType;
95 fn to_curve_type(self) -> CurveType;
96}
97
98impl RosettaAlgorithm for Algorithm {
99 fn to_signature_type(self) -> SignatureType {
100 match self {
101 Algorithm::EcdsaSecp256k1 => SignatureType::Ecdsa,
102 Algorithm::EcdsaRecoverableSecp256k1 => SignatureType::EcdsaRecovery,
103 Algorithm::EcdsaSecp256r1 => SignatureType::Ecdsa,
104 Algorithm::Ed25519 => SignatureType::Ed25519,
105 Algorithm::Sr25519 => SignatureType::Sr25519,
106 }
107 }
108
109 fn to_curve_type(self) -> CurveType {
110 match self {
111 Algorithm::EcdsaSecp256k1 => CurveType::Secp256k1,
112 Algorithm::EcdsaRecoverableSecp256k1 => CurveType::Secp256k1,
113 Algorithm::EcdsaSecp256r1 => CurveType::Secp256r1,
114 Algorithm::Ed25519 => CurveType::Edwards25519,
115 Algorithm::Sr25519 => CurveType::Schnorrkel,
116 }
117 }
118}
119
120pub trait TransactionBuilder: Default + Sized {
121 type MetadataParams: Serialize + Clone;
122 type Metadata: DeserializeOwned + Sized + Send + Sync + 'static;
123
124 fn transfer(&self, address: &Address, amount: u128) -> Result<Self::MetadataParams>;
125
126 fn method_call(
127 &self,
128 contract: &str,
129 method: &str,
130 values: &[String],
131 amount: u128,
132 ) -> Result<Self::MetadataParams>;
133
134 fn deploy_contract(&self, contract_binary: Vec<u8>) -> Result<Self::MetadataParams>;
135
136 fn create_and_sign(
137 &self,
138 config: &BlockchainConfig,
139 metadata_params: &Self::MetadataParams,
140 metdata: &Self::Metadata,
141 secret_key: &SecretKey,
142 ) -> Vec<u8>;
143}