1use ergo_lib::ergo_chain_types::EcPoint;
4use ergo_lib::ergotree_ir::serialization::SigmaSerializable;
5use ergo_lib::ergotree_ir::sigma_protocol::sigma_boolean::ProveDlog;
6use wasm_bindgen::prelude::*;
7
8use crate::{ergo_tree::ErgoTree, error_conversion::to_js};
9
10extern crate derive_more;
11use derive_more::{From, Into};
12
13#[wasm_bindgen]
15#[repr(u8)]
16#[derive(PartialEq, Eq, Debug, Clone, Copy)]
17pub enum NetworkPrefix {
18    Mainnet = 0,
20    Testnet = 16,
22}
23
24impl From<NetworkPrefix> for ergo_lib::ergotree_ir::chain::address::NetworkPrefix {
25    fn from(v: NetworkPrefix) -> Self {
26        use ergo_lib::ergotree_ir::chain::address::NetworkPrefix::*;
27        match v {
28            NetworkPrefix::Mainnet => Mainnet,
29            NetworkPrefix::Testnet => Testnet,
30        }
31    }
32}
33
34impl From<ergo_lib::ergotree_ir::chain::address::NetworkPrefix> for NetworkPrefix {
35    fn from(v: ergo_lib::ergotree_ir::chain::address::NetworkPrefix) -> Self {
36        use NetworkPrefix::*;
37        match v {
38            ergo_lib::ergotree_ir::chain::address::NetworkPrefix::Mainnet => Mainnet,
39            ergo_lib::ergotree_ir::chain::address::NetworkPrefix::Testnet => Testnet,
40        }
41    }
42}
43
44#[wasm_bindgen]
46#[repr(u8)]
47pub enum AddressTypePrefix {
48    P2Pk = 1,
50    Pay2Sh = 2,
52    Pay2S = 3,
54}
55
56impl From<AddressTypePrefix> for ergo_lib::ergotree_ir::chain::address::AddressTypePrefix {
57    fn from(v: AddressTypePrefix) -> Self {
58        use ergo_lib::ergotree_ir::chain::address::AddressTypePrefix::*;
59        match v {
60            AddressTypePrefix::P2Pk => P2Pk,
61            AddressTypePrefix::Pay2Sh => Pay2Sh,
62            AddressTypePrefix::Pay2S => Pay2S,
63        }
64    }
65}
66
67impl From<ergo_lib::ergotree_ir::chain::address::AddressTypePrefix> for AddressTypePrefix {
68    fn from(v: ergo_lib::ergotree_ir::chain::address::AddressTypePrefix) -> Self {
69        use AddressTypePrefix::*;
70        match v {
71            ergo_lib::ergotree_ir::chain::address::AddressTypePrefix::P2Pk => P2Pk,
72            ergo_lib::ergotree_ir::chain::address::AddressTypePrefix::Pay2Sh => Pay2Sh,
73            ergo_lib::ergotree_ir::chain::address::AddressTypePrefix::Pay2S => Pay2S,
74        }
75    }
76}
77
78#[wasm_bindgen]
122#[derive(PartialEq, Eq, Debug, Clone, From, Into)]
123pub struct Address(pub(crate) ergo_lib::ergotree_ir::chain::address::Address);
124
125#[wasm_bindgen]
126impl Address {
127    pub fn recreate_from_ergo_tree(ergo_tree: &ErgoTree) -> Result<Address, JsValue> {
133        ergo_lib::ergotree_ir::chain::address::Address::recreate_from_ergo_tree(
134            &ergo_tree.clone().into(),
135        )
136        .map(Address)
137        .map_err(to_js)
138    }
139
140    pub fn p2pk_from_pk_bytes(bytes: &[u8]) -> Result<Address, JsValue> {
142        ergo_lib::ergotree_ir::chain::address::Address::p2pk_from_pk_bytes(bytes)
143            .map(Address)
144            .map_err(to_js)
145    }
146
147    pub fn from_testnet_str(s: &str) -> Result<Address, JsValue> {
149        ergo_lib::ergotree_ir::chain::address::AddressEncoder::new(
150            ergo_lib::ergotree_ir::chain::address::NetworkPrefix::Testnet,
151        )
152        .parse_address_from_str(s)
153        .map(Address)
154        .map_err(to_js)
155    }
156
157    pub fn from_mainnet_str(s: &str) -> Result<Address, JsValue> {
159        ergo_lib::ergotree_ir::chain::address::AddressEncoder::new(
160            ergo_lib::ergotree_ir::chain::address::NetworkPrefix::Mainnet,
161        )
162        .parse_address_from_str(s)
163        .map(Address)
164        .map_err(to_js)
165    }
166
167    #[allow(clippy::should_implement_trait)]
169    pub fn from_base58(s: &str) -> Result<Address, JsValue> {
170        ergo_lib::ergotree_ir::chain::address::AddressEncoder::unchecked_parse_address_from_str(s)
171            .map(Address)
172            .map_err(to_js)
173    }
174
175    pub fn to_base58(&self, network_prefix: NetworkPrefix) -> String {
177        ergo_lib::ergotree_ir::chain::address::AddressEncoder::encode_address_as_string(
178            network_prefix.into(),
179            &self.0,
180        )
181    }
182
183    pub fn from_bytes(data: Vec<u8>) -> Result<Address, JsValue> {
185        ergo_lib::ergotree_ir::chain::address::AddressEncoder::unchecked_parse_address_from_bytes(
186            &data,
187        )
188        .map(Address)
189        .map_err(to_js)
190    }
191
192    pub fn to_bytes(&self, network_prefix: NetworkPrefix) -> Vec<u8> {
194        ergo_lib::ergotree_ir::chain::address::AddressEncoder::encode_address_as_bytes(
195            network_prefix.into(),
196            &self.0,
197        )
198    }
199
200    pub fn content_bytes(&self) -> Vec<u8> {
203        self.0.content_bytes()
204    }
205
206    pub fn address_type_prefix(&self) -> AddressTypePrefix {
208        self.0.address_type_prefix().into()
209    }
210
211    pub fn from_public_key(bytes: &[u8]) -> Result<Address, JsValue> {
213        EcPoint::sigma_parse_bytes(bytes)
214            .map(|point| {
215                ergo_lib::ergotree_ir::chain::address::Address::P2Pk(ProveDlog::new(point))
216            })
217            .map(Address)
218            .map_err(to_js)
219    }
220
221    pub fn to_ergo_tree(&self) -> Result<ErgoTree, JsValue> {
223        self.0.script().map(|script| script.into()).map_err(to_js)
224    }
225}
226
227#[wasm_bindgen]
230#[derive(PartialEq, Eq, Debug, Clone)]
231pub struct NetworkAddress(ergo_lib::ergotree_ir::chain::address::NetworkAddress);
232
233#[wasm_bindgen]
234impl NetworkAddress {
235    pub fn new(network: NetworkPrefix, address: &Address) -> NetworkAddress {
237        NetworkAddress(ergo_lib::ergotree_ir::chain::address::NetworkAddress::new(
238            network.into(),
239            &address.clone().into(),
240        ))
241    }
242
243    pub fn from_base58(s: &str) -> Result<NetworkAddress, JsValue> {
245        ergo_lib::ergotree_ir::chain::address::AddressEncoder::unchecked_parse_network_address_from_str(s)
246            .map(NetworkAddress)
247            .map_err(to_js)
248    }
249
250    pub fn to_base58(&self) -> String {
252        self.0.to_base58()
253    }
254
255    pub fn from_bytes(data: Vec<u8>) -> Result<NetworkAddress, JsValue> {
257        ergo_lib::ergotree_ir::chain::address::AddressEncoder::unchecked_parse_network_address_from_bytes(
258            &data,
259        )
260        .map(NetworkAddress)
261        .map_err(to_js)
262    }
263
264    pub fn to_bytes(&self) -> Vec<u8> {
266        ergo_lib::ergotree_ir::chain::address::AddressEncoder::encode_address_as_bytes(
267            self.network().into(),
268            &self.address().into(),
269        )
270    }
271
272    pub fn network(&self) -> NetworkPrefix {
274        self.0.network().into()
275    }
276
277    pub fn address(&self) -> Address {
279        self.0.address().into()
280    }
281}