whisky_pallas/utils/
address.rs1use std::str::FromStr;
2
3use pallas::ledger::addresses::{Address, Network, ShelleyAddress, ShelleyDelegationPart};
4use pallas_crypto::hash::Hash;
5use whisky_common::{DeserializedAddress, WError};
6
7pub fn script_to_address(
8 network_id: u8,
9 script_hash: &str,
10 stake_cred: Option<(&str, bool)>,
11) -> String {
12 let stake_cred = match stake_cred {
13 Some((stake, is_script)) => {
14 let stake_cred = if is_script {
15 ShelleyDelegationPart::Script(Hash::from_str(stake).unwrap())
16 } else {
17 ShelleyDelegationPart::Key(Hash::from_str(stake).unwrap())
18 };
19 stake_cred
20 }
21 None => ShelleyDelegationPart::Null,
22 };
23 let payment_cred =
24 pallas::ledger::addresses::ShelleyPaymentPart::Script(Hash::from_str(script_hash).unwrap());
25
26 let address = ShelleyAddress::new(
27 Network::try_from(network_id).unwrap(),
28 payment_cred,
29 stake_cred,
30 );
31 address.to_bech32().unwrap()
32}
33
34pub fn serialize_address_obj(
35 address_obj: DeserializedAddress,
36 network_id: u8,
37) -> Result<String, WError> {
38 let payment_cred = match (
39 address_obj.pub_key_hash.as_str(),
40 address_obj.script_hash.as_str(),
41 ) {
42 (pub_key_hash, "") => {
43 pallas::ledger::addresses::ShelleyPaymentPart::Key(Hash::from_str(pub_key_hash).unwrap())
44 }
45 ("", script_hash) => {
46 pallas::ledger::addresses::ShelleyPaymentPart::Script(Hash::from_str(script_hash).unwrap())
47 }
48 _ => Err(WError::new(
49 "serialze_address_obj",
50 &format!(
51 "Must provide exactly one of pub_key_hash or script_hash, pub_key_hash: {}, script_hash: {}",
52 address_obj.pub_key_hash, address_obj.script_hash
53 ),
54 ))?,
55 };
56
57 let stake_cred_opt = match (
58 address_obj.stake_key_hash.as_str(),
59 address_obj.stake_key_script_hash.as_str(),
60 ) {
61 ("","") => None,
62 (stake_key_hash, "") => Some(ShelleyDelegationPart::Key(Hash::from_str(stake_key_hash).unwrap())),
63 ("", stake_script_hash) => Some(ShelleyDelegationPart::Script(Hash::from_str(stake_script_hash).unwrap())),
64 _ => Err(WError::new(
65 "serialze_address_obj",
66 &format!(
67 "Must provide at most one of stake_key_hash or stake_script_hash, stake_key_hash: {}, stake_script_hash: {}",
68 address_obj.stake_key_hash, address_obj.stake_key_script_hash
69 ),
70 ))?,
71 };
72
73 match stake_cred_opt {
74 Some(stake_cred) => Ok(ShelleyAddress::new(
75 Network::try_from(network_id).unwrap(),
76 payment_cred,
77 stake_cred,
78 )
79 .to_bech32()
80 .unwrap()),
81 None => Ok(ShelleyAddress::new(
82 Network::try_from(network_id).unwrap(),
83 payment_cred,
84 ShelleyDelegationPart::Null,
85 )
86 .to_bech32()
87 .unwrap()),
88 }
89}
90
91pub fn deserialize_address(bech32_address: &str) -> Result<DeserializedAddress, WError> {
92 let address = Address::from_bech32(bech32_address).map_err(|e| {
93 WError::new(
94 "deserialize_address",
95 &format!(
96 "Failed to parse address from bech32: {}, error: {}",
97 bech32_address, e
98 ),
99 )
100 })?;
101
102 match address {
103 Address::Byron(byron_address) => {
104 return Err(WError::new(
105 "deserialize_address",
106 &format!(
107 "Byron addresses are not supported: {}",
108 byron_address.to_base58()
109 ),
110 ))?
111 }
112 Address::Shelley(shelley_address) => {
113 let (payment_pkh, payment_script_hash) = match shelley_address.payment() {
114 pallas::ledger::addresses::ShelleyPaymentPart::Key(key_hash) => {
115 (key_hash.to_string(), String::new())
116 }
117 pallas::ledger::addresses::ShelleyPaymentPart::Script(script_hash) => {
118 (String::new(), script_hash.to_string())
119 }
120 };
121 let (stake_pkh, stake_script_hash) = match shelley_address.delegation() {
122 ShelleyDelegationPart::Null => (String::new(), String::new()),
123 ShelleyDelegationPart::Key(stake_key_hash) => {
124 (stake_key_hash.to_string(), String::new())
125 }
126 ShelleyDelegationPart::Script(stake_script_hash) => {
127 (String::new(), stake_script_hash.to_string())
128 }
129 ShelleyDelegationPart::Pointer(_pointer) => {
130 return Err(WError::new(
131 "deserialize_address",
132 "Pointer stake keys are not supported",
133 ))
134 }
135 };
136
137 Ok(DeserializedAddress::new(
138 &payment_pkh,
139 &payment_script_hash,
140 &stake_pkh,
141 &stake_script_hash,
142 ))
143 }
144 Address::Stake(stake_address) => {
145 let stake_payload = stake_address.payload();
146 let (stake_pkh, stake_script_hash) = match stake_payload {
147 pallas::ledger::addresses::StakePayload::Stake(hash) => {
148 (hash.to_string(), String::new())
149 }
150 pallas::ledger::addresses::StakePayload::Script(hash) => {
151 (String::new(), hash.to_string())
152 }
153 };
154
155 Ok(DeserializedAddress::new(
156 &String::new(),
157 &String::new(),
158 &stake_pkh,
159 &stake_script_hash,
160 ))
161 }
162 }
163}