Skip to content

Commit 03a4663

Browse files
authored
Merge branch 'ruslan/add-mint-and-metadata' into feature/change-transactionbuilder-creation
2 parents f369b57 + e19c261 commit 03a4663

File tree

3 files changed

+152
-36
lines changed

3 files changed

+152
-36
lines changed

rust/src/lib.rs

Lines changed: 103 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2691,27 +2691,35 @@ impl Mint {
26912691
ScriptHashes(self.0.iter().map(|(k, _v)| k.clone()).collect::<Vec<ScriptHash>>())
26922692
}
26932693

2694-
pub fn to_multiasset(&self) -> Result<MultiAsset, JsError> {
2695-
self.0.iter().fold(Ok(MultiAsset::new()), | res, e | {
2696-
let assets: Result<Assets, JsError> = (e.1).0.iter().fold(Ok(Assets::new()), | res, e| {
2697-
let mut assets = res?;
2698-
if e.1.is_positive() {
2699-
assets.insert(e.0, &e.1.as_positive().unwrap());
2700-
Ok(assets)
2701-
} else {
2702-
Err(JsError::from_str("Asset amount cannot be negative!"))
2694+
fn as_multiasset(&self, is_positive: bool) -> MultiAsset {
2695+
self.0.iter().fold(MultiAsset::new(), | res, e | {
2696+
let assets: Assets = (e.1).0.iter().fold(Assets::new(), | res, e| {
2697+
let mut assets = res;
2698+
if e.1.is_positive() == is_positive {
2699+
let amount = match is_positive {
2700+
true => e.1.as_positive(),
2701+
false => e.1.as_negative(),
2702+
};
2703+
assets.insert(e.0, &amount.unwrap());
27032704
}
2705+
assets
27042706
});
2705-
let mut ma = res?;
2706-
ma.insert(e.0, &assets?);
2707-
Ok(ma)
2707+
let mut ma = res;
2708+
if !assets.0.is_empty() {
2709+
ma.insert(e.0, &assets);
2710+
}
2711+
ma
27082712
})
27092713
}
27102714

2711-
pub fn to_value(&self) -> Result<Value, JsError> {
2712-
let mut val = Value::new(&Coin::zero());
2713-
val.set_multiasset(&self.to_multiasset()?);
2714-
Ok(val)
2715+
/// Returns the multiasset where only positive (minting) entries are present
2716+
pub fn as_positive_multiasset(&self) -> MultiAsset {
2717+
self.as_multiasset(true)
2718+
}
2719+
2720+
/// Returns the multiasset where only negative (burning) entries are present
2721+
pub fn as_negative_multiasset(&self) -> MultiAsset {
2722+
self.as_multiasset(false)
27152723
}
27162724
}
27172725

@@ -2799,7 +2807,7 @@ mod tests {
27992807
}
28002808

28012809
#[test]
2802-
fn mint_to_value() {
2810+
fn mint_to_multiasset() {
28032811
let policy_id1 = PolicyID::from([0u8; 28]);
28042812
let policy_id2 = PolicyID::from([1u8; 28]);
28052813
let name1 = AssetName::new(vec![0u8, 1, 2, 3]).unwrap();
@@ -2819,12 +2827,7 @@ mod tests {
28192827
mint.insert(&policy_id1, &mass1);
28202828
mint.insert(&policy_id2, &mass2);
28212829

2822-
let val = mint.to_value().unwrap();
2823-
2824-
assert_eq!(val.coin(), Coin::zero());
2825-
assert!(val.multiasset().is_some());
2826-
2827-
let multiasset = val.multiasset().unwrap();
2830+
let multiasset = mint.as_positive_multiasset();
28282831
assert_eq!(multiasset.len(), 2);
28292832

28302833
let ass1 = multiasset.get(&policy_id1).unwrap();
@@ -2841,22 +2844,93 @@ mod tests {
28412844
}
28422845

28432846
#[test]
2844-
fn mint_to_value_negative_err() {
2847+
fn mint_to_negative_multiasset() {
28452848
let policy_id1 = PolicyID::from([0u8; 28]);
2849+
let policy_id2 = PolicyID::from([1u8; 28]);
28462850
let name1 = AssetName::new(vec![0u8, 1, 2, 3]).unwrap();
2851+
let name2 = AssetName::new(vec![0u8, 4, 5, 6]).unwrap();
2852+
let amount1 = BigNum::from_str("1234").unwrap();
2853+
let amount2 = BigNum::from_str("5678").unwrap();
28472854

28482855
let mut mass1 = MintAssets::new();
2849-
mass1.insert(&name1, Int::new_i32(-42));
2856+
mass1.insert(&name1, Int::new(&amount1));
2857+
mass1.insert(&name2, Int::new_negative(&amount2));
2858+
2859+
let mut mass2 = MintAssets::new();
2860+
mass2.insert(&name1, Int::new_negative(&amount1));
2861+
mass2.insert(&name2, Int::new(&amount2));
28502862

28512863
let mut mint = Mint::new();
28522864
mint.insert(&policy_id1, &mass1);
2865+
mint.insert(&policy_id2, &mass2);
2866+
2867+
let p_multiasset = mint.as_positive_multiasset();
2868+
let n_multiasset = mint.as_negative_multiasset();
2869+
2870+
assert_eq!(p_multiasset.len(), 2);
2871+
assert_eq!(n_multiasset.len(), 2);
2872+
2873+
let p_ass1 = p_multiasset.get(&policy_id1).unwrap();
2874+
let p_ass2 = p_multiasset.get(&policy_id2).unwrap();
2875+
2876+
let n_ass1 = n_multiasset.get(&policy_id1).unwrap();
2877+
let n_ass2 = n_multiasset.get(&policy_id2).unwrap();
2878+
2879+
assert_eq!(p_ass1.len(), 1);
2880+
assert_eq!(p_ass2.len(), 1);
2881+
assert_eq!(n_ass1.len(), 1);
2882+
assert_eq!(n_ass2.len(), 1);
2883+
2884+
assert_eq!(p_ass1.get(&name1).unwrap(), amount1);
2885+
assert!(p_ass1.get(&name2).is_none());
2886+
2887+
assert!(p_ass2.get(&name1).is_none());
2888+
assert_eq!(p_ass2.get(&name2).unwrap(), amount2);
2889+
2890+
assert!(n_ass1.get(&name1).is_none());
2891+
assert_eq!(n_ass1.get(&name2).unwrap(), amount2);
2892+
2893+
assert_eq!(n_ass2.get(&name1).unwrap(), amount1);
2894+
assert!(n_ass2.get(&name2).is_none());
2895+
}
2896+
2897+
#[test]
2898+
fn mint_to_negative_multiasset_empty() {
2899+
let policy_id1 = PolicyID::from([0u8; 28]);
2900+
let name1 = AssetName::new(vec![0u8, 1, 2, 3]).unwrap();
2901+
let amount1 = BigNum::from_str("1234").unwrap();
2902+
2903+
let mut mass1 = MintAssets::new();
2904+
mass1.insert(&name1, Int::new(&amount1));
2905+
2906+
let mut mass2 = MintAssets::new();
2907+
mass2.insert(&name1, Int::new_negative(&amount1));
2908+
2909+
let mut mint1 = Mint::new();
2910+
mint1.insert(&policy_id1, &mass1);
2911+
2912+
let mut mint2 = Mint::new();
2913+
mint2.insert(&policy_id1, &mass2);
2914+
2915+
let p_multiasset_some = mint1.as_positive_multiasset();
2916+
let p_multiasset_none = mint2.as_positive_multiasset();
2917+
2918+
let n_multiasset_none = mint1.as_negative_multiasset();
2919+
let n_multiasset_some = mint2.as_negative_multiasset();
2920+
2921+
assert_eq!(p_multiasset_some.len(), 1);
2922+
assert_eq!(p_multiasset_none.len(), 0);
28532923

2854-
let res = mint.to_value();
2924+
assert_eq!(n_multiasset_some.len(), 1);
2925+
assert_eq!(n_multiasset_none.len(), 0);
28552926

2856-
assert!(res.is_err());
2927+
let p_ass = p_multiasset_some.get(&policy_id1).unwrap();
2928+
let n_ass = n_multiasset_some.get(&policy_id1).unwrap();
28572929

2858-
let err = res.err().unwrap();
2930+
assert_eq!(p_ass.len(), 1);
2931+
assert_eq!(n_ass.len(), 1);
28592932

2860-
assert!(err.to_string().contains("cannot be negative"))
2933+
assert_eq!(p_ass.get(&name1).unwrap(), amount1);
2934+
assert_eq!(n_ass.get(&name1).unwrap(), amount1);
28612935
}
28622936
}

rust/src/tx_builder.rs

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use super::fees;
33
use super::utils;
44
use std::collections::{BTreeMap, BTreeSet};
55
use derive_builder::Builder;
6+
use itertools::Itertools;
67

78
// comes from witsVKeyNeeded in the Ledger spec
89
fn witness_keys_for_cert(cert_enum: &Certificate, keys: &mut BTreeSet<Ed25519KeyHash>) {
@@ -503,6 +504,10 @@ impl TransactionBuilder {
503504
};
504505
}
505506

507+
pub fn get_auxiliary_data(&self) -> Option<AuxiliaryData> {
508+
self.auxiliary_data.clone()
509+
}
510+
506511
/// Set explicit auxiliary data via an AuxiliaryData object
507512
/// It might contain some metadata plus native or Plutus scripts
508513
pub fn set_auxiliary_data(&mut self, auxiliary_data: &AuxiliaryData) {
@@ -590,11 +595,14 @@ impl TransactionBuilder {
590595
address: &Address,
591596
output_coin: &Coin,
592597
) -> Result<(), JsError> {
598+
if !amount.is_positive() {
599+
return Err(JsError::from_str("Output value must be positive!"));
600+
}
593601
self.add_mint_asset(policy_id, asset_name, amount.clone());
594602
let mut multiasset = Mint::new_from_entry(
595603
policy_id,
596604
&MintAssets::new_from_entry(asset_name, amount.clone())
597-
).to_multiasset()?;
605+
).as_positive_multiasset();
598606
self.add_output_coin_and_asset(address, output_coin, &multiasset)
599607
}
600608

@@ -610,11 +618,14 @@ impl TransactionBuilder {
610618
amount: Int,
611619
address: &Address,
612620
) -> Result<(), JsError> {
621+
if !amount.is_positive() {
622+
return Err(JsError::from_str("Output value must be positive!"));
623+
}
613624
self.add_mint_asset(policy_id, asset_name, amount.clone());
614625
let mut multiasset = Mint::new_from_entry(
615626
policy_id,
616627
&MintAssets::new_from_entry(asset_name, amount.clone())
617-
).to_multiasset()?;
628+
).as_positive_multiasset();
618629
self.add_output_asset_and_min_required_coin(address, &multiasset)
619630
}
620631

@@ -670,15 +681,20 @@ impl TransactionBuilder {
670681
)
671682
}
672683

673-
/// mint as value
674-
pub fn get_mint_value(&self) -> Result<Value, JsError> {
675-
self.mint.as_ref().map(|m| { m.to_value() }).unwrap_or(Ok(Value::zero()))
684+
/// Returns mint as tuple of (mint_value, burn_value) or two zero values
685+
fn get_mint_as_values(&self) -> (Value, Value) {
686+
self.mint.as_ref().map(|m| {
687+
(Value::new_from_assets(&m.as_positive_multiasset()),
688+
Value::new_from_assets(&m.as_negative_multiasset()))
689+
}).unwrap_or((Value::zero(), Value::zero()))
676690
}
677691

678692
fn get_total_input(&self) -> Result<Value, JsError> {
693+
let (mint_value, burn_value) = self.get_mint_as_values();
679694
self.get_explicit_input()?
680695
.checked_add(&self.get_implicit_input()?)?
681-
.checked_add(&self.get_mint_value()?)
696+
.checked_add(&mint_value)?
697+
.checked_sub(&burn_value)
682698
}
683699

684700
/// does not include fee
@@ -906,6 +922,9 @@ impl TransactionBuilder {
906922
return self.outputs.0.iter().map(|o| { o.to_bytes().len() }).collect();
907923
}
908924

925+
/// Returns object the body of the new transaction
926+
/// Auxiliary data itself is not included
927+
/// You can use `get_auxiliary_date` or `build_tx`
909928
pub fn build(&self) -> Result<TransactionBody, JsError> {
910929
let (body, full_tx_size) = self.build_and_size()?;
911930
if full_tx_size > self.max_tx_size as usize {
@@ -919,6 +938,18 @@ impl TransactionBuilder {
919938
}
920939
}
921940

941+
/// Returns full Transaction object with the body and the auxiliary data
942+
/// NOTE: witness_set is set to just empty set
943+
/// NOTE: is_valid set to true
944+
pub fn build_tx(&self) -> Result<Transaction, JsError> {
945+
Ok(Transaction {
946+
body: self.build()?,
947+
witness_set: TransactionWitnessSet::new(),
948+
is_valid: true,
949+
auxiliary_data: self.auxiliary_data.clone(),
950+
})
951+
}
952+
922953
/// warning: sum of all parts of a transaction must equal 0. You cannot just set the fee to the min value and forget about it
923954
/// warning: min_fee may be slightly larger than the actual minimum fee (ex: a few lovelaces)
924955
/// this is done to simplify the library code, but can be fixed later

rust/src/utils.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,15 +265,26 @@ to_from_bytes!(Value);
265265

266266
#[wasm_bindgen]
267267
impl Value {
268+
268269
pub fn new(coin: &Coin) -> Value {
269270
Self {
270271
coin: coin.clone(),
271272
multiasset: None,
272273
}
273274
}
274275

276+
pub fn new_from_assets(multiasset: &MultiAsset) -> Value {
277+
match multiasset.0.is_empty() {
278+
true => Value::zero(),
279+
false => Self {
280+
coin: Coin::zero(),
281+
multiasset: Some(multiasset.clone()),
282+
}
283+
}
284+
}
285+
275286
pub fn zero() -> Value {
276-
Value::new(&to_bignum(0))
287+
Value::new(&Coin::zero())
277288
}
278289

279290
pub fn is_zero(&self) -> bool {

0 commit comments

Comments
 (0)