|
15 | 15 |
|
16 | 16 | use crate::{
|
17 | 17 | address::{
|
18 |
| - hexified::HexifiedAddress, pubkeyhash::PublicKeyHash, traits::Addressable, AddressError, |
| 18 | + hexified::HexifiedAddress, pubkeyhash::PublicKeyHash, traits::Addressable, Address, |
| 19 | + AddressError, |
19 | 20 | },
|
20 | 21 | chain::{
|
21 | 22 | output_value::OutputValue,
|
22 |
| - tokens::{NftIssuance, TokenId, TokenIssuance}, |
| 23 | + tokens::{IsTokenFreezable, NftIssuance, TokenId, TokenIssuance, TokenTotalSupply}, |
23 | 24 | ChainConfig, DelegationId, PoolId,
|
24 | 25 | },
|
25 | 26 | primitives::{Amount, Id},
|
| 27 | + text_summary::TextSummary, |
26 | 28 | };
|
| 29 | +use crypto::vrf::VRFPublicKey; |
27 | 30 | use script::Script;
|
28 | 31 | use serialization::{Decode, DecodeAll, Encode};
|
29 | 32 | use variant_count::VariantCount;
|
@@ -128,3 +131,161 @@ impl TxOutput {
|
128 | 131 | }
|
129 | 132 | }
|
130 | 133 | }
|
| 134 | + |
| 135 | +impl TextSummary for TxOutput { |
| 136 | + fn text_summary(&self, chain_config: &ChainConfig) -> String { |
| 137 | + let fmt_ml = |v: &Amount| v.into_fixedpoint_str(chain_config.coin_decimals()); |
| 138 | + let fmt_val = |val: &OutputValue| { |
| 139 | + match val { |
| 140 | + OutputValue::Coin(amount) => fmt_ml(amount), |
| 141 | + OutputValue::TokenV0(token_data) => format!("{token_data:?}"), // Not important since it's deprecated |
| 142 | + OutputValue::TokenV1(id, amount) => { |
| 143 | + format!( |
| 144 | + "TokenV1({}, {amount:?})", |
| 145 | + Address::new(chain_config, id) |
| 146 | + .expect("Cannot fail due to TokenId being fixed size") |
| 147 | + ) |
| 148 | + } |
| 149 | + } |
| 150 | + }; |
| 151 | + let fmt_timelock = |tl: &OutputTimeLock| match tl { |
| 152 | + OutputTimeLock::UntilHeight(h) => format!("OutputTimeLock::UntilHeight({h})"), |
| 153 | + OutputTimeLock::UntilTime(t) => format!("OutputTimeLock::UntilTime({})", t.into_time()), |
| 154 | + OutputTimeLock::ForBlockCount(n) => { |
| 155 | + format!("OutputTimeLock::ForBlockCount({n} blocks)") |
| 156 | + } |
| 157 | + OutputTimeLock::ForSeconds(secs) => { |
| 158 | + format!("OutputTimeLock::ForSeconds({secs} seconds)") |
| 159 | + } |
| 160 | + }; |
| 161 | + let fmt_dest = |
| 162 | + |d: &Destination| format!("{}", Address::new(chain_config, d).expect("addressable")); |
| 163 | + let fmt_vrf = |
| 164 | + |k: &VRFPublicKey| format!("{}", Address::new(chain_config, k).expect("addressable")); |
| 165 | + let fmt_poolid = |id: &PoolId| { |
| 166 | + Address::new(chain_config, id).expect("Cannot fail because fixed size addressable") |
| 167 | + }; |
| 168 | + let fmt_tknid = |id: &TokenId| { |
| 169 | + Address::new(chain_config, id).expect("Cannot fail because fixed size addressable") |
| 170 | + }; |
| 171 | + let fmt_delid = |id: &DelegationId| { |
| 172 | + Address::new(chain_config, id).expect("Cannot fail because fixed size addressable") |
| 173 | + }; |
| 174 | + let fmt_stakepooldata = |p: &StakePoolData| { |
| 175 | + let pledge = fmt_ml(&p.pledge()); |
| 176 | + format!( |
| 177 | + "Pledge({pledge}), Staker({}), VRFPubKey({}), DecommissionKey({}), MarginRatio({}), CostPerBlock({})", |
| 178 | + fmt_dest(p.staker()), |
| 179 | + fmt_vrf(p.vrf_public_key()), |
| 180 | + fmt_dest(p.decommission_key()), |
| 181 | + p.margin_ratio_per_thousand().into_percentage_str(), |
| 182 | + fmt_ml(&p.cost_per_block()) |
| 183 | + ) |
| 184 | + }; |
| 185 | + let fmt_tkn_supply = |s: &TokenTotalSupply, d: u8| match s { |
| 186 | + TokenTotalSupply::Fixed(v) => format!("Fixed({})", v.into_fixedpoint_str(d)), |
| 187 | + TokenTotalSupply::Lockable => "Lockable".to_string(), |
| 188 | + TokenTotalSupply::Unlimited => "Unlimited".to_string(), |
| 189 | + }; |
| 190 | + let fmt_tkn_frzble = |f: &IsTokenFreezable| match f { |
| 191 | + IsTokenFreezable::No => "Yes".to_string(), |
| 192 | + IsTokenFreezable::Yes => "No".to_string(), |
| 193 | + }; |
| 194 | + let fmt_tkn_iss = |iss: &TokenIssuance| { |
| 195 | + match iss { |
| 196 | + TokenIssuance::V1(iss1) => format!( |
| 197 | + "TokenIssuance(Ticker({}), Decimals({}), MetadataUri({}), TotalSupply({}), Authority({}), IsFreezable({}))", |
| 198 | + String::from_utf8_lossy(&iss1.token_ticker), |
| 199 | + iss1.number_of_decimals, |
| 200 | + String::from_utf8_lossy(&iss1.metadata_uri), |
| 201 | + fmt_tkn_supply(&iss1.total_supply, iss1.number_of_decimals), |
| 202 | + fmt_dest(&iss1.authority), |
| 203 | + fmt_tkn_frzble(&iss1.is_freezable) |
| 204 | + ), |
| 205 | + } |
| 206 | + }; |
| 207 | + let fmt_nft_iss = |iss: &NftIssuance| match iss { |
| 208 | + NftIssuance::V0(iss1) => { |
| 209 | + let md = &iss1.metadata; |
| 210 | + let creator = match &md.creator { |
| 211 | + Some(c) => hex::encode(c.public_key.encode()).to_string(), |
| 212 | + None => "Unspecified".to_string(), |
| 213 | + }; |
| 214 | + format!( |
| 215 | + "Create({}), Name({}), Description({}), Ticker({}), IconUri({}), AdditionalMetaData({}), MediaUri({}), MediaHash(0x{})", |
| 216 | + creator, |
| 217 | + String::from_utf8_lossy(&md.name), |
| 218 | + String::from_utf8_lossy(&md.description), |
| 219 | + String::from_utf8_lossy(&md.ticker), |
| 220 | + String::from_utf8_lossy(md.icon_uri.as_ref().as_ref().unwrap_or(&vec![])), |
| 221 | + String::from_utf8_lossy( |
| 222 | + md.additional_metadata_uri.as_ref().as_ref().unwrap_or(&vec![]) |
| 223 | + ), |
| 224 | + String::from_utf8_lossy( |
| 225 | + md.media_uri.as_ref().as_ref().unwrap_or(&vec![]) |
| 226 | + ), |
| 227 | + hex::encode(&md.media_hash), |
| 228 | + |
| 229 | + ) |
| 230 | + } |
| 231 | + }; |
| 232 | + |
| 233 | + match self { |
| 234 | + TxOutput::Transfer(val, dest) => { |
| 235 | + let val_str = fmt_val(val); |
| 236 | + format!("Transfer({}, {val_str})", fmt_dest(dest)) |
| 237 | + } |
| 238 | + TxOutput::LockThenTransfer(val, dest, timelock) => { |
| 239 | + let val_str = fmt_val(val); |
| 240 | + format!( |
| 241 | + "LockThenTransfer({}, {val_str}, {})", |
| 242 | + fmt_dest(dest), |
| 243 | + fmt_timelock(timelock) |
| 244 | + ) |
| 245 | + } |
| 246 | + TxOutput::Burn(val) => format!("Burn({})", fmt_val(val)), |
| 247 | + TxOutput::CreateStakePool(id, data) => { |
| 248 | + format!( |
| 249 | + "CreateStakePool(Id({}), {})", |
| 250 | + fmt_poolid(id), |
| 251 | + fmt_stakepooldata(data) |
| 252 | + ) |
| 253 | + } |
| 254 | + TxOutput::ProduceBlockFromStake(dest, pool_id) => { |
| 255 | + format!( |
| 256 | + "ProduceBlockFromStake({}, {})", |
| 257 | + fmt_dest(dest), |
| 258 | + fmt_poolid(pool_id) |
| 259 | + ) |
| 260 | + } |
| 261 | + TxOutput::CreateDelegationId(owner, pool_id) => { |
| 262 | + format!( |
| 263 | + "CreateDelegationId(Owner({}), StakingPool({}))", |
| 264 | + fmt_dest(owner), |
| 265 | + fmt_poolid(pool_id) |
| 266 | + ) |
| 267 | + } |
| 268 | + TxOutput::DelegateStaking(amount, del_ig) => { |
| 269 | + format!( |
| 270 | + "DelegateStaking(Owner({}), StakingPool({}))", |
| 271 | + fmt_ml(amount), |
| 272 | + fmt_delid(del_ig) |
| 273 | + ) |
| 274 | + } |
| 275 | + TxOutput::IssueFungibleToken(issuance) => { |
| 276 | + format!("IssueFungibleToken({})", fmt_tkn_iss(issuance)) |
| 277 | + } |
| 278 | + TxOutput::IssueNft(token_id, iss, receiver) => { |
| 279 | + format!( |
| 280 | + "IssueNft(Id({}), NftIssuance({}), Receiver({}))", |
| 281 | + fmt_tknid(token_id), |
| 282 | + fmt_nft_iss(iss), |
| 283 | + fmt_dest(receiver) |
| 284 | + ) |
| 285 | + } |
| 286 | + TxOutput::DataDeposit(data) => { |
| 287 | + format!("DataDeposit(0x{})", hex::encode(data)) |
| 288 | + } |
| 289 | + } |
| 290 | + } |
| 291 | +} |
0 commit comments