From 046c694eac295c92c0bc96be09515c4ced36160d Mon Sep 17 00:00:00 2001 From: Alex Coats Date: Mon, 18 Mar 2024 13:05:43 -0400 Subject: [PATCH] Remove option from output unlock conditions --- cli/src/wallet_cli/mod.rs | 41 ++++--- .../wallet/17_check_unlock_conditions.rs | 17 ++- .../transaction_builder/context_inputs.rs | 3 +- .../block_builder/transaction_builder/mod.rs | 5 +- .../transaction_builder/remainder.rs | 9 +- .../transaction_builder/requirement/amount.rs | 13 +-- sdk/src/types/block/output/mod.rs | 19 ++-- sdk/src/types/block/semantic/mod.rs | 38 ++++--- sdk/src/wallet/operations/balance.rs | 39 +++---- sdk/src/wallet/operations/helpers/time.rs | 51 +++++---- sdk/src/wallet/operations/output_claiming.rs | 107 +++++++++--------- .../operations/transaction/prepare_output.rs | 6 +- sdk/tests/wallet/output_preparation.rs | 52 ++++----- sdk/tests/wallet/syncing.rs | 2 +- 14 files changed, 188 insertions(+), 214 deletions(-) diff --git a/cli/src/wallet_cli/mod.rs b/cli/src/wallet_cli/mod.rs index d4c73d0fff..6c6d948c6b 100644 --- a/cli/src/wallet_cli/mod.rs +++ b/cli/src/wallet_cli/mod.rs @@ -594,25 +594,24 @@ pub async fn claimable_outputs_command(wallet: &Wallet) -> Result<(), Error> { println_log_info!(" + {} {}", native_token.amount(), native_token.token_id()); } - if let Some(unlock_conditions) = output.unlock_conditions() { - let deposit_return = unlock_conditions - .storage_deposit_return() - .map(|deposit_return| deposit_return.amount()) - .unwrap_or(0); - let amount = output.amount() - deposit_return; - println_log_info!(" - base coin amount: {}", amount); - - if let Some(expiration) = unlock_conditions.expiration() { - let slot_index = wallet.client().get_slot_index().await?; - - if *expiration.slot_index() > *slot_index { - println_log_info!(" - expires in {} slot indices", *expiration.slot_index() - *slot_index); - } else { - println_log_info!( - " - expired {} slot indices ago", - *slot_index - *expiration.slot_index() - ); - } + let deposit_return = output + .unlock_conditions() + .storage_deposit_return() + .map(|deposit_return| deposit_return.amount()) + .unwrap_or(0); + let amount = output.amount() - deposit_return; + println_log_info!(" - base coin amount: {}", amount); + + if let Some(expiration) = output.unlock_conditions().expiration() { + let slot_index = wallet.client().get_slot_index().await?; + + if *expiration.slot_index() > *slot_index { + println_log_info!(" - expires in {} slot indices", *expiration.slot_index() - *slot_index); + } else { + println_log_info!( + " - expired {} slot indices ago", + *slot_index - *expiration.slot_index() + ); } } } @@ -1313,11 +1312,9 @@ async fn print_wallet_address(wallet: &Wallet) -> Result<(), Error> { Output::Delegation(delegation) => delegations.push(delegation.delegation_id_non_null(&output_id)), Output::Anchor(anchor) => anchors.push(anchor.anchor_id_non_null(&output_id)), } - let unlock_conditions = output_data + let sdr_amount = output_data .output .unlock_conditions() - .expect("output must have unlock conditions"); - let sdr_amount = unlock_conditions .storage_deposit_return() .map(|sdr| sdr.amount()) .unwrap_or(0); diff --git a/sdk/examples/wallet/17_check_unlock_conditions.rs b/sdk/examples/wallet/17_check_unlock_conditions.rs index ed010b9895..04e4be8136 100644 --- a/sdk/examples/wallet/17_check_unlock_conditions.rs +++ b/sdk/examples/wallet/17_check_unlock_conditions.rs @@ -40,16 +40,13 @@ async fn main() -> Result<(), Box> { .add_unlock_condition(AddressUnlockCondition::new(wallet_address.clone())) .finish_output()?; - let controlled_by_account = if let [UnlockCondition::Address(address_unlock_condition)] = output - .unlock_conditions() - .expect("output needs to have unlock conditions") - .as_ref() - { - // Check that the address in the unlock condition belongs to the wallet - wallet_address.inner() == address_unlock_condition.address() - } else { - false - }; + let controlled_by_account = + if let [UnlockCondition::Address(address_unlock_condition)] = output.unlock_conditions().as_ref() { + // Check that the address in the unlock condition belongs to the wallet + wallet_address.inner() == address_unlock_condition.address() + } else { + false + }; println!( "The output has only an address unlock condition and the address is from the account: {controlled_by_account:?}" diff --git a/sdk/src/client/api/block_builder/transaction_builder/context_inputs.rs b/sdk/src/client/api/block_builder/transaction_builder/context_inputs.rs index 4f8b468f92..356b17f6a4 100644 --- a/sdk/src/client/api/block_builder/transaction_builder/context_inputs.rs +++ b/sdk/src/client/api/block_builder/transaction_builder/context_inputs.rs @@ -44,7 +44,8 @@ impl TransactionBuilder { if input .output .unlock_conditions() - .map_or(false, |u| u.iter().any(|u| u.is_timelock() || u.is_expiration())) + .iter() + .any(|u| u.is_timelock() || u.is_expiration()) { log::debug!("Adding commitment context input for timelocked or expiring output"); needs_commitment_context = true; diff --git a/sdk/src/client/api/block_builder/transaction_builder/mod.rs b/sdk/src/client/api/block_builder/transaction_builder/mod.rs index 75bf51aba0..af043267db 100644 --- a/sdk/src/client/api/block_builder/transaction_builder/mod.rs +++ b/sdk/src/client/api/block_builder/transaction_builder/mod.rs @@ -640,10 +640,7 @@ impl TransactionBuilder { return false; } - // PANIC: safe to unwrap as non basic/account/foundry/nft outputs are already filtered out. - let unlock_conditions = input.output.unlock_conditions().unwrap(); - - if unlock_conditions.is_timelocked( + if input.output.unlock_conditions().is_timelocked( self.latest_slot_commitment_id.slot_index(), self.protocol_parameters.min_committable_age(), ) { diff --git a/sdk/src/client/api/block_builder/transaction_builder/remainder.rs b/sdk/src/client/api/block_builder/transaction_builder/remainder.rs index 7111bdfb7b..68f4e9f783 100644 --- a/sdk/src/client/api/block_builder/transaction_builder/remainder.rs +++ b/sdk/src/client/api/block_builder/transaction_builder/remainder.rs @@ -136,8 +136,8 @@ impl TransactionBuilder { // Find the first value that matches the remainder address self.non_remainder_outputs().any(|o| { (o.is_basic() || o.is_account() || o.is_anchor() || o.is_nft()) - && o.unlock_conditions() - .map_or(true, |uc| uc.expiration().is_none() && uc.timelock().is_none()) + && o.unlock_conditions().expiration().is_none() + && o.unlock_conditions().timelock().is_none() && matches!(o.required_address( self.latest_slot_commitment_id.slot_index(), self.protocol_parameters.committable_age_range(), @@ -156,10 +156,7 @@ impl TransactionBuilder { .provided_outputs .iter_mut() .chain(&mut self.added_outputs) - .filter(|o| { - o.unlock_conditions() - .map_or(true, |uc| uc.expiration().is_none() && uc.timelock().is_none()) - }) + .filter(|o| o.unlock_conditions().expiration().is_none() && o.unlock_conditions().timelock().is_none()) .filter_map(|o| sort_order.get(&o.kind()).map(|order| (*order, o))) .collect::>(); diff --git a/sdk/src/client/api/block_builder/transaction_builder/requirement/amount.rs b/sdk/src/client/api/block_builder/transaction_builder/requirement/amount.rs index ad2ae9f372..b667e9bac7 100644 --- a/sdk/src/client/api/block_builder/transaction_builder/requirement/amount.rs +++ b/sdk/src/client/api/block_builder/transaction_builder/requirement/amount.rs @@ -21,16 +21,11 @@ pub(crate) fn sdruc_not_expired( output: &Output, slot_index: SlotIndex, ) -> Option<&StorageDepositReturnUnlockCondition> { - // PANIC: safe to unwrap as outputs without unlock conditions have been filtered out already. - let unlock_conditions = output.unlock_conditions().unwrap(); - - unlock_conditions.storage_deposit_return().and_then(|sdr| { - let expired = unlock_conditions + output.unlock_conditions().storage_deposit_return().filter(|_| { + output + .unlock_conditions() .expiration() - .map_or(false, |expiration| slot_index >= expiration.slot_index()); - - // We only have to send the storage deposit return back if the output is not expired - (!expired).then_some(sdr) + .map_or(true, |expiration| slot_index < expiration.slot_index()) }) } diff --git a/sdk/src/types/block/output/mod.rs b/sdk/src/types/block/output/mod.rs index 129ea04627..37cb08bb56 100644 --- a/sdk/src/types/block/output/mod.rs +++ b/sdk/src/types/block/output/mod.rs @@ -220,14 +220,14 @@ impl Output { } /// Returns the unlock conditions of an [`Output`], if any. - pub fn unlock_conditions(&self) -> Option<&UnlockConditions> { + pub fn unlock_conditions(&self) -> &UnlockConditions { match self { - Self::Basic(output) => Some(output.unlock_conditions()), - Self::Account(output) => Some(output.unlock_conditions()), - Self::Anchor(output) => Some(output.unlock_conditions()), - Self::Foundry(output) => Some(output.unlock_conditions()), - Self::Nft(output) => Some(output.unlock_conditions()), - Self::Delegation(output) => Some(output.unlock_conditions()), + Self::Basic(output) => output.unlock_conditions(), + Self::Account(output) => output.unlock_conditions(), + Self::Anchor(output) => output.unlock_conditions(), + Self::Foundry(output) => output.unlock_conditions(), + Self::Nft(output) => output.unlock_conditions(), + Self::Delegation(output) => output.unlock_conditions(), } } @@ -340,10 +340,7 @@ impl Output { }); } - if let Some(return_condition) = self - .unlock_conditions() - .and_then(UnlockConditions::storage_deposit_return) - { + if let Some(return_condition) = self.unlock_conditions().storage_deposit_return() { // We can't return more tokens than were originally contained in the output. // `Return Amount` ≤ `Amount`. if return_condition.amount() > self.amount() { diff --git a/sdk/src/types/block/semantic/mod.rs b/sdk/src/types/block/semantic/mod.rs index 10f8270cab..e85afed13c 100644 --- a/sdk/src/types/block/semantic/mod.rs +++ b/sdk/src/types/block/semantic/mod.rs @@ -355,25 +355,27 @@ impl<'a> SemanticValidationContext<'a> { } } - if let Some(unlock_conditions) = created_output.unlock_conditions() { - if let (Some(address), Some(timelock)) = (unlock_conditions.address(), unlock_conditions.timelock()) { - if let Address::Account(account_address) = address.address() { - if let Some(entry) = self.block_issuer_mana.get_mut(account_address.account_id()) { - if let Some(commitment_context_input) = self.commitment_context_input { - let past_bounded_slot = - self.protocol_parameters.past_bounded_slot(commitment_context_input); - - if timelock.slot_index() - >= past_bounded_slot + self.protocol_parameters.max_committable_age() - { - entry.1 = entry - .1 - .checked_add(created_output.mana()) - .ok_or(TransactionFailureReason::SemanticValidationFailed)?; - } - } else { - return Err(TransactionFailureReason::BlockIssuerCommitmentInputMissing); + if let Some((address, timelock)) = created_output + .unlock_conditions() + .address() + .zip(created_output.unlock_conditions().timelock()) + { + if let Address::Account(account_address) = address.address() { + if let Some(entry) = self.block_issuer_mana.get_mut(account_address.account_id()) { + if let Some(commitment_context_input) = self.commitment_context_input { + let past_bounded_slot = + self.protocol_parameters.past_bounded_slot(commitment_context_input); + + if timelock.slot_index() + >= past_bounded_slot + self.protocol_parameters.max_committable_age() + { + entry.1 = entry + .1 + .checked_add(created_output.mana()) + .ok_or(TransactionFailureReason::SemanticValidationFailed)?; } + } else { + return Err(TransactionFailureReason::BlockIssuerCommitmentInputMissing); } } } diff --git a/sdk/src/wallet/operations/balance.rs b/sdk/src/wallet/operations/balance.rs index e7747f8380..9efa6b7d59 100644 --- a/sdk/src/wallet/operations/balance.rs +++ b/sdk/src/wallet/operations/balance.rs @@ -124,11 +124,7 @@ impl Wallet { _ => { // If there is only an [AddressUnlockCondition], then we can spend the output at any time // without restrictions - if let [UnlockCondition::Address(_)] = output - .unlock_conditions() - .expect("output needs to have unlock conditions") - .as_ref() - { + if let [UnlockCondition::Address(_)] = output.unlock_conditions().as_ref() { // add nft_id for nft outputs if let Output::Nft(nft) = &output { let nft_id = nft.nft_id_non_null(output_id); @@ -185,21 +181,18 @@ impl Wallet { // If output has a StorageDepositReturnUnlockCondition, the amount of it should // be subtracted, because this part // needs to be sent back - let amount = output - .unlock_conditions() - .and_then(|u| u.storage_deposit_return()) - .map_or_else( - || output.amount(), - |sdr| { - if wallet_address.inner() == sdr.return_address() { - // sending to ourself, we get the full amount - output.amount() - } else { - // Sending to someone else - output.amount() - sdr.amount() - } - }, - ); + let amount = output.unlock_conditions().storage_deposit_return().map_or_else( + || output.amount(), + |sdr| { + if wallet_address.inner() == sdr.return_address() { + // sending to ourself, we get the full amount + output.amount() + } else { + // Sending to someone else + output.amount() - sdr.amount() + } + }, + ); // add nft_id for nft outputs if let Output::Nft(output) = &output { @@ -243,11 +236,7 @@ impl Wallet { } } else { // Don't add expired outputs that can't ever be unlocked by us - if let Some(expiration) = output - .unlock_conditions() - .expect("output needs to have unlock conditions") - .expiration() - { + if let Some(expiration) = output.unlock_conditions().expiration() { // Not expired, could get unlockable when it's expired, so we insert it if slot_index < expiration.slot_index() { balance.potentially_locked_outputs.insert(*output_id, false); diff --git a/sdk/src/wallet/operations/helpers/time.rs b/sdk/src/wallet/operations/helpers/time.rs index 094d356e66..72bda24d23 100644 --- a/sdk/src/wallet/operations/helpers/time.rs +++ b/sdk/src/wallet/operations/helpers/time.rs @@ -15,10 +15,12 @@ pub(crate) fn can_output_be_unlocked_now( commitment_slot_index: impl Into + Copy, committable_age_range: CommittableAgeRange, ) -> Result { - if let Some(unlock_conditions) = output_data.output.unlock_conditions() { - if unlock_conditions.is_timelocked(commitment_slot_index, committable_age_range.min) { - return Ok(false); - } + if output_data + .output + .unlock_conditions() + .is_timelocked(commitment_slot_index, committable_age_range.min) + { + return Ok(false); } let required_address = output_data @@ -40,30 +42,29 @@ pub(crate) fn can_output_be_unlocked_from_now_on( slot_index: impl Into + Copy, committable_age_range: CommittableAgeRange, ) -> bool { - if let Some(unlock_conditions) = output.unlock_conditions() { - if unlock_conditions.is_timelocked(slot_index, committable_age_range.min) { - return false; - } + if output + .unlock_conditions() + .is_timelocked(slot_index, committable_age_range.min) + { + return false; + } - // If there is an expiration unlock condition, we can only unlock it forever from now on, if it's expired and - // the return address belongs to the wallet - if let Some(expiration) = unlock_conditions.expiration() { - if let Some(address) = expiration.return_address_expired( - // Safe to unwrap, if there is an expiration, then there also needs to be an address unlock condition - unlock_conditions.address().unwrap().address(), - slot_index, - committable_age_range, - ) { - if address != expiration.return_address() || !controlled_addresses.contains(address) { - return false; - } - } else { + // If there is an expiration unlock condition, we can only unlock it forever from now on, if it's expired and + // the return address belongs to the wallet + if let Some(expiration) = output.unlock_conditions().expiration() { + if let Some(address) = expiration.return_address_expired( + // Safe to unwrap, if there is an expiration, then there also needs to be an address unlock condition + output.unlock_conditions().address().unwrap().address(), + slot_index, + committable_age_range, + ) { + if address != expiration.return_address() || !controlled_addresses.contains(address) { return false; } + } else { + return false; } - - true - } else { - false } + + true } diff --git a/sdk/src/wallet/operations/output_claiming.rs b/sdk/src/wallet/operations/output_claiming.rs index 621b69c1e0..e975ee5465 100644 --- a/sdk/src/wallet/operations/output_claiming.rs +++ b/sdk/src/wallet/operations/output_claiming.rs @@ -65,66 +65,71 @@ impl WalletLedger { { // Don't use outputs that are locked for other transactions if !self.locked_outputs.contains(output_id) && self.outputs.contains_key(output_id) { - if let Some(unlock_conditions) = output_data.output.unlock_conditions() { - // If there is a single [UnlockCondition], then it's an - // [AddressUnlockCondition] and we own it already without - // further restrictions - if unlock_conditions.len() != 1 - && can_output_be_unlocked_now( - // We use the addresses with unspent outputs, because other addresses of the - // account without unspent outputs can't be related to this output - &controlled_addresses, - output_data, - slot_index, - protocol_parameters.committable_age_range(), - )? - { - match outputs_to_claim { - OutputsToClaim::MicroTransactions => { - if let Some(sdr) = unlock_conditions.storage_deposit_return() { - // If expired, it's not a micro transaction anymore - match unlock_conditions - .is_expired(slot_index, protocol_parameters.committable_age_range()) - { - Some(false) => { - // Only micro transaction if not the same amount needs to be returned - // (resulting in 0 amount to claim) - if sdr.amount() != output_data.output.amount() { - output_ids_to_claim.insert(output_data.output_id); - } + // If there is a single [UnlockCondition], then it's an + // [AddressUnlockCondition] and we own it already without + // further restrictions + if output_data.output.unlock_conditions().len() != 1 + && can_output_be_unlocked_now( + // We use the addresses with unspent outputs, because other addresses of the + // account without unspent outputs can't be related to this output + &controlled_addresses, + output_data, + slot_index, + protocol_parameters.committable_age_range(), + )? + { + match outputs_to_claim { + OutputsToClaim::MicroTransactions => { + if let Some(sdr) = output_data.output.unlock_conditions().storage_deposit_return() { + // If expired, it's not a micro transaction anymore + match output_data + .output + .unlock_conditions() + .is_expired(slot_index, protocol_parameters.committable_age_range()) + { + Some(false) => { + // Only micro transaction if not the same amount needs to be returned + // (resulting in 0 amount to claim) + if sdr.amount() != output_data.output.amount() { + output_ids_to_claim.insert(output_data.output_id); } - _ => continue, } + _ => continue, } } - OutputsToClaim::NativeTokens => { - if output_data.output.native_token().is_some() { - output_ids_to_claim.insert(output_data.output_id); - } - } - OutputsToClaim::Nfts => { - if output_data.output.is_nft() { - output_ids_to_claim.insert(output_data.output_id); - } + } + OutputsToClaim::NativeTokens => { + if output_data.output.native_token().is_some() { + output_ids_to_claim.insert(output_data.output_id); } - OutputsToClaim::Amount => { - let mut claimable_amount = output_data.output.amount(); - if unlock_conditions.is_expired(slot_index, protocol_parameters.committable_age_range()) - == Some(false) - { - claimable_amount -= unlock_conditions - .storage_deposit_return() - .map(|s| s.amount()) - .unwrap_or_default() - }; - if claimable_amount > 0 { - output_ids_to_claim.insert(output_data.output_id); - } + } + OutputsToClaim::Nfts => { + if output_data.output.is_nft() { + output_ids_to_claim.insert(output_data.output_id); } - OutputsToClaim::All => { + } + OutputsToClaim::Amount => { + let mut claimable_amount = output_data.output.amount(); + if output_data + .output + .unlock_conditions() + .is_expired(slot_index, protocol_parameters.committable_age_range()) + == Some(false) + { + claimable_amount -= output_data + .output + .unlock_conditions() + .storage_deposit_return() + .map(|s| s.amount()) + .unwrap_or_default() + }; + if claimable_amount > 0 { output_ids_to_claim.insert(output_data.output_id); } } + OutputsToClaim::All => { + output_ids_to_claim.insert(output_data.output_id); + } } } } diff --git a/sdk/src/wallet/operations/transaction/prepare_output.rs b/sdk/src/wallet/operations/transaction/prepare_output.rs index 21b7694461..5ac8958ce6 100644 --- a/sdk/src/wallet/operations/transaction/prepare_output.rs +++ b/sdk/src/wallet/operations/transaction/prepare_output.rs @@ -192,11 +192,7 @@ impl Wallet { final_amount += remaining_balance; second_output_builder = second_output_builder.with_amount(final_amount); - if let Some(sdr) = third_output - .unlock_conditions() - .expect("basic and nft outputs have unlock conditions") - .storage_deposit_return() - { + if let Some(sdr) = third_output.unlock_conditions().storage_deposit_return() { // create a new sdr unlock_condition with the updated amount and replace it let new_sdr_amount = sdr.amount() + remaining_balance; second_output_builder = diff --git a/sdk/tests/wallet/output_preparation.rs b/sdk/tests/wallet/output_preparation.rs index 9d4cfc4829..378e0c00c0 100644 --- a/sdk/tests/wallet/output_preparation.rs +++ b/sdk/tests/wallet/output_preparation.rs @@ -45,8 +45,8 @@ async fn output_preparation() -> Result<(), Box> { .await?; assert_eq!(output.amount(), 46800); // address and sdr unlock condition - assert_eq!(output.unlock_conditions().unwrap().len(), 2); - let sdr = output.unlock_conditions().unwrap().storage_deposit_return().unwrap(); + assert_eq!(output.unlock_conditions().len(), 2); + let sdr = output.unlock_conditions().storage_deposit_return().unwrap(); assert_eq!(sdr.amount(), 46300); let output = wallet @@ -64,7 +64,7 @@ async fn output_preparation() -> Result<(), Box> { .await?; assert_eq!(output.amount(), 500000); // only address condition - assert_eq!(output.unlock_conditions().unwrap().len(), 1); + assert_eq!(output.unlock_conditions().len(), 1); let native_token = NativeToken::new( TokenId::from_str("0x08847bd287c912fadedb6bf38900bda9f2d377b75b2a0bece8738699f56ebca4130100000000")?, @@ -91,7 +91,7 @@ async fn output_preparation() -> Result<(), Box> { .await?; assert_eq!(output.amount(), 500000); // only address condition - assert_eq!(output.unlock_conditions().unwrap().len(), 1); + assert_eq!(output.unlock_conditions().len(), 1); assert_eq!(output.native_token(), Some(&native_token)); let output = wallet @@ -115,7 +115,7 @@ async fn output_preparation() -> Result<(), Box> { .await?; assert_eq!(output.amount(), 300000); // only address condition - assert_eq!(output.unlock_conditions().unwrap().len(), 1); + assert_eq!(output.unlock_conditions().len(), 1); // metadata and tag features assert_eq!(output.features().unwrap().len(), 2); @@ -140,7 +140,7 @@ async fn output_preparation() -> Result<(), Box> { ) .await?; assert_eq!(output.amount(), 49000); - let unlock_conditions = output.unlock_conditions().unwrap(); + let unlock_conditions = output.unlock_conditions(); // address + sdr assert_eq!(unlock_conditions.len(), 2); let storage_deposit_return = unlock_conditions.storage_deposit_return().unwrap(); @@ -171,7 +171,7 @@ async fn output_preparation() -> Result<(), Box> { assert_eq!(output.amount(), 54600); // address and storage deposit unlock condition, because of the metadata feature block, 12000 is not enough for the // required storage deposit - assert_eq!(output.unlock_conditions().unwrap().len(), 2); + assert_eq!(output.unlock_conditions().len(), 2); // metadata and tag features assert_eq!(output.features().unwrap().len(), 2); @@ -195,12 +195,12 @@ async fn output_preparation() -> Result<(), Box> { ) .await?; assert_eq!(output.amount(), 49000); - let sdr = output.unlock_conditions().unwrap().storage_deposit_return().unwrap(); + let sdr = output.unlock_conditions().storage_deposit_return().unwrap(); assert_eq!(sdr.amount(), 48999); // address and storage deposit unlock condition, because of the metadata feature block, 213000 is not enough for the // required storage deposit - assert_eq!(output.unlock_conditions().unwrap().len(), 2); + assert_eq!(output.unlock_conditions().len(), 2); // metadata and tag features assert_eq!(output.features().unwrap().len(), 2); @@ -249,7 +249,7 @@ async fn output_preparation() -> Result<(), Box> { assert_eq!(output.kind(), iota_sdk::types::block::output::NftOutput::KIND); assert_eq!(output.amount(), 500000); // only address condition - assert_eq!(output.unlock_conditions().unwrap().len(), 1); + assert_eq!(output.unlock_conditions().len(), 1); } let issuer_and_sender_address_bech32 = @@ -281,7 +281,7 @@ async fn output_preparation() -> Result<(), Box> { assert_eq!(output.kind(), iota_sdk::types::block::output::BasicOutput::KIND); assert_eq!(output.amount(), 500000); - assert_eq!(output.unlock_conditions().unwrap().len(), 1); + assert_eq!(output.unlock_conditions().len(), 1); let features = output.features().unwrap(); assert_eq!(features.len(), 1); assert_eq!(features.sender().unwrap().address(), expected_address); @@ -352,7 +352,7 @@ async fn output_preparation() -> Result<(), Box> { let sender_feature = features.sender().unwrap(); assert_eq!(sender_feature.address(), issuer_and_sender_address.inner()); // Unlocks - let conditions = output.unlock_conditions().unwrap(); + let conditions = output.unlock_conditions(); assert!(conditions.is_timelocked(0, 0)); assert_eq!( conditions.is_expired(2, CommittableAgeRange { min: 0, max: 0 }), @@ -389,7 +389,7 @@ async fn output_preparation() -> Result<(), Box> { assert_eq!(output.kind(), iota_sdk::types::block::output::NftOutput::KIND); assert_eq!(output.amount(), 53900); // address, sdr, expiration - assert_eq!(output.unlock_conditions().unwrap().len(), 3); + assert_eq!(output.unlock_conditions().len(), 3); let output = wallet .prepare_output( @@ -419,11 +419,11 @@ async fn output_preparation() -> Result<(), Box> { let minimum_amount = output.minimum_amount(storage_score_params); assert_eq!(output.amount(), minimum_amount); assert_eq!(output.amount(), 187900); - let sdr = output.unlock_conditions().unwrap().storage_deposit_return().unwrap(); + let sdr = output.unlock_conditions().storage_deposit_return().unwrap(); assert_eq!(sdr.amount(), 145300); // address and storage deposit unlock condition, because of the metadata feature block, 42600 is not enough for the // required storage deposit - assert_eq!(output.unlock_conditions().unwrap().len(), 2); + assert_eq!(output.unlock_conditions().len(), 2); // metadata and tag features assert_eq!(output.features().unwrap().len(), 2); @@ -463,8 +463,8 @@ async fn output_preparation_sdr() -> Result<(), Box> { output.verify_storage_deposit(storage_score_params)?; assert_eq!(output.amount(), 50601); // address and sdr unlock condition - assert_eq!(output.unlock_conditions().unwrap().len(), 2); - let sdr = output.unlock_conditions().unwrap().storage_deposit_return().unwrap(); + assert_eq!(output.unlock_conditions().len(), 2); + let sdr = output.unlock_conditions().storage_deposit_return().unwrap(); assert_eq!(sdr.amount(), 42600); let output = wallet @@ -484,8 +484,8 @@ async fn output_preparation_sdr() -> Result<(), Box> { output.verify_storage_deposit(storage_score_params)?; assert_eq!(output.amount(), 85199); // address and sdr unlock condition - assert_eq!(output.unlock_conditions().unwrap().len(), 2); - let sdr = output.unlock_conditions().unwrap().storage_deposit_return().unwrap(); + assert_eq!(output.unlock_conditions().len(), 2); + let sdr = output.unlock_conditions().storage_deposit_return().unwrap(); assert_eq!(sdr.amount(), 42600); // ReturnStrategy::Return provided @@ -509,8 +509,8 @@ async fn output_preparation_sdr() -> Result<(), Box> { output.verify_storage_deposit(storage_score_params)?; assert_eq!(output.amount(), 85199); // address and sdr unlock condition - assert_eq!(output.unlock_conditions().unwrap().len(), 2); - let sdr = output.unlock_conditions().unwrap().storage_deposit_return().unwrap(); + assert_eq!(output.unlock_conditions().len(), 2); + let sdr = output.unlock_conditions().storage_deposit_return().unwrap(); assert_eq!(sdr.amount(), 42600); // ReturnStrategy::Gift provided @@ -535,7 +535,7 @@ async fn output_preparation_sdr() -> Result<(), Box> { // The additional 1 amount will be added, because the storage deposit should be gifted and not returned assert_eq!(output.amount(), 42600); // storage deposit gifted, only address unlock condition - assert_eq!(output.unlock_conditions().unwrap().len(), 1); + assert_eq!(output.unlock_conditions().len(), 1); tear_down(storage_path) } @@ -674,7 +674,7 @@ async fn prepare_output_remainder_dust() -> Result<(), Box Result<(), Box Result<(), Box