From 429967256232891d981066999acaa1e1bfebd667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Mon, 18 Mar 2024 11:23:52 +0100 Subject: [PATCH 01/15] Update private tangle tests so they work with 2.0 --- .github/workflows/private-tangle-tests.yml | 5 +- bindings/core/tests/combined.rs | 18 +- sdk/src/types/block/output/basic.rs | 9 +- sdk/tests/client/common/constants.rs | 2 +- sdk/tests/client/node_api/core.rs | 21 +- sdk/tests/client/node_api/mod.rs | 61 ++- .../secret_manager/address_generation.rs | 13 +- sdk/tests/client/secret_manager/mnemonic.rs | 1 - sdk/tests/client/secret_manager/stronghold.rs | 1 - sdk/tests/wallet/balance.rs | 29 +- sdk/tests/wallet/burn_outputs.rs | 35 +- sdk/tests/wallet/claim_outputs.rs | 51 ++- sdk/tests/wallet/common/constants.rs | 2 +- sdk/tests/wallet/common/mod.rs | 89 ++++- sdk/tests/wallet/consolidation.rs | 11 +- sdk/tests/wallet/output_preparation.rs | 368 +++++++++--------- sdk/tests/wallet/transactions.rs | 60 +-- 17 files changed, 449 insertions(+), 327 deletions(-) diff --git a/.github/workflows/private-tangle-tests.yml b/.github/workflows/private-tangle-tests.yml index 92a9b8494e..92e7a00a92 100644 --- a/.github/workflows/private-tangle-tests.yml +++ b/.github/workflows/private-tangle-tests.yml @@ -65,10 +65,7 @@ jobs: uses: "./.github/actions/ledger-nano" - name: Run tests - run: | - cargo nextest run test_get_info --all-features --run-ignored ignored-only --profile ci --cargo-profile ci -p iota-sdk -p iota-sdk-bindings-core --no-capture - # TODO: change in the future to run all tests and not only test_get_info - # cargo ci-tangle-test + run: cargo ci-tangle-test - name: Tear down private tangle if: always() diff --git a/bindings/core/tests/combined.rs b/bindings/core/tests/combined.rs index 06e4822fcd..bd71902e31 100644 --- a/bindings/core/tests/combined.rs +++ b/bindings/core/tests/combined.rs @@ -95,17 +95,13 @@ async fn client_from_wallet() -> Result<(), Error> { .build() .await?; - // TODO reenable - // // Send ClientMethod via the client from the wallet - // let response = wallet - // .client() - // .call_method(ClientMethod::GetHealth) - // .await; - - // match response { - // Response::Bool(_) => {} - // _ => panic!("unexpected response {response:?}"), - // } + // Send ClientMethod via the client from the wallet + let response = wallet.client().call_method(ClientMethod::GetNodeInfo).await; + + match response { + Response::NodeInfo(_) => {} + _ => panic!("unexpected response {response:?}"), + } std::fs::remove_dir_all(storage_path).ok(); Ok(()) diff --git a/sdk/src/types/block/output/basic.rs b/sdk/src/types/block/output/basic.rs index e6761ea619..01e10b7934 100644 --- a/sdk/src/types/block/output/basic.rs +++ b/sdk/src/types/block/output/basic.rs @@ -517,14 +517,9 @@ mod tests { use super::*; use crate::types::block::{ - output::{basic::dto::BasicOutputDto, FoundryId, SimpleTokenScheme, TokenId}, + output::basic::dto::BasicOutputDto, protocol::iota_mainnet_protocol_parameters, - rand::{ - address::rand_account_address, - output::{ - feature::rand_allowed_features, rand_basic_output, unlock_condition::rand_address_unlock_condition, - }, - }, + rand::output::{rand_basic_output, unlock_condition::rand_address_unlock_condition}, }; #[test] diff --git a/sdk/tests/client/common/constants.rs b/sdk/tests/client/common/constants.rs index c06eb0d4e6..9fe5aa7574 100644 --- a/sdk/tests/client/common/constants.rs +++ b/sdk/tests/client/common/constants.rs @@ -3,6 +3,6 @@ pub static NODE_LOCAL: &str = "http://localhost:8050"; -pub static FAUCET_URL: &str = "http://localhost:8091/api/enqueue"; +pub static FAUCET_URL: &str = "http://localhost:8088/api/enqueue"; pub static DEFAULT_MNEMONIC: &str = "inhale gorilla deny three celery song category owner lottery rent author wealth penalty crawl hobby obtain glad warm early rain clutch slab august bleak"; diff --git a/sdk/tests/client/node_api/core.rs b/sdk/tests/client/node_api/core.rs index e276993666..7aade154cb 100644 --- a/sdk/tests/client/node_api/core.rs +++ b/sdk/tests/client/node_api/core.rs @@ -55,8 +55,7 @@ async fn test_get_issuance() { #[ignore] #[tokio::test] async fn test_post_block_with_tagged_data() { - let secret_manager = setup_secret_manager(); - let block_id = setup_tagged_data_block(&secret_manager).await; + let block_id = setup_tagged_data_block().await.unwrap(); println!("{block_id}"); } @@ -72,9 +71,8 @@ async fn test_post_block_with_transaction() { #[tokio::test] async fn test_get_block_data() { let client = setup_client_with_node_health_ignored().await; - let secret_manager = setup_secret_manager(); - let block_id = setup_tagged_data_block(&secret_manager).await; + let block_id = setup_tagged_data_block().await.unwrap(); let r = client.get_block(&block_id).await.unwrap(); println!("{r:#?}"); @@ -83,8 +81,7 @@ async fn test_get_block_data() { #[ignore] #[tokio::test] async fn test_get_block_metadata() { - let secret_manager = setup_secret_manager(); - let block_id = setup_tagged_data_block(&secret_manager).await; + let block_id = setup_tagged_data_block().await.unwrap(); let r = setup_client_with_node_health_ignored() .await @@ -98,8 +95,7 @@ async fn test_get_block_metadata() { #[ignore] #[tokio::test] async fn test_get_block_raw() { - let secret_manager = setup_secret_manager(); - let block_id = setup_tagged_data_block(&secret_manager).await; + let block_id = setup_tagged_data_block().await.unwrap(); let r = setup_client_with_node_health_ignored() .await @@ -201,7 +197,7 @@ async fn test_call_plugin_route() { // we call the "custom" plugin "node info" let plugin_res: NodeInfoResponse = c - .call_plugin_route("api/core/v2/", "GET", "info", vec![], None) + .call_plugin_route("api/core/v3/", "GET", "info", vec![], None) .await .unwrap(); @@ -218,7 +214,7 @@ async fn test_get_routes() { let routes_response = client.get_routes().await.unwrap(); // At at least one route, which is not created by plugin, is available - assert!(routes_response.routes.contains(&"core/v2".to_string())); + assert!(routes_response.routes.contains(&"core/v3".to_string())); println!("{routes_response:#?}"); } @@ -231,7 +227,10 @@ async fn test_get_included_block_metadata() { let metadata_response = client.get_included_block_metadata(&transaction_id).await.unwrap(); assert_eq!(metadata_response.block_id, block_id); - assert_eq!(metadata_response.block_state, BlockState::Finalized); + match metadata_response.block_state { + BlockState::Accepted | BlockState::Confirmed | BlockState::Finalized => {} + _ => panic!("block state is not accepted/confirmed/finalized"), + } println!("{metadata_response:#?}"); } diff --git a/sdk/tests/client/node_api/mod.rs b/sdk/tests/client/node_api/mod.rs index 1d5a9edb0c..70883b2713 100644 --- a/sdk/tests/client/node_api/mod.rs +++ b/sdk/tests/client/node_api/mod.rs @@ -11,12 +11,14 @@ use iota_sdk::{ client::{ api::GetAddressesOptions, constants::IOTA_COIN_TYPE, + generate_mnemonic, node_api::indexer::query_parameters::BasicOutputQueryParameters, request_funds_from_faucet, - secret::{SecretManager, SignBlock}, + secret::{mnemonic::MnemonicSecretManager, SecretManager, SignBlock}, Client, }, types::block::{ + address::{Address, Bech32Address, ImplicitAccountCreationAddress}, output::AccountId, payload::{signed_transaction::TransactionId, tagged_data::TaggedDataPayload, Payload}, BlockId, @@ -28,25 +30,64 @@ use crate::client::common::{setup_client_with_node_health_ignored, FAUCET_URL}; // THIS SEED SERVES FOR TESTING PURPOSES! DON'T USE THIS SEED IN PRODUCTION! const DEFAULT_DEVELOPMENT_SEED: &str = "0x256a818b2aac458941f7274985a410e57fb750f3a3a67969ece5bd9ae7eef5b2"; -// Sends a tagged data block to the node to test against it. -async fn setup_tagged_data_block(secret_manager: &SecretManager) -> BlockId { +// Sends a tagged data block to the node to test against it.* +async fn setup_tagged_data_block() -> Result> { let client = setup_client_with_node_health_ignored().await; - let protocol_params = client.get_protocol_parameters().await.unwrap(); + let secret_manager = SecretManager::Mnemonic(MnemonicSecretManager::try_from_mnemonic(generate_mnemonic()?)?); + + let bech32_hrp = client.get_bech32_hrp().await?; + + let address = secret_manager + .generate_ed25519_address(IOTA_COIN_TYPE, 0, 0, bech32_hrp, None) + .await?; + let address = + Address::ImplicitAccountCreation(ImplicitAccountCreationAddress::new(**address.into_inner().as_ed25519())); + let bech32_address = Bech32Address::new(bech32_hrp, address); + + request_funds_from_faucet(FAUCET_URL, &bech32_address).await?; - client + let mut account_id = AccountId::null(); + // Continue only after funds are received + for i in 0..30 { + let output_ids = client + .basic_output_ids(BasicOutputQueryParameters::only_address_unlock_condition( + bech32_address.clone(), + )) + .await? + .items; + if !output_ids.is_empty() { + account_id = AccountId::from(&output_ids[0]); + break; + } + if i == 29 { + panic!("Faucet no longer wants to hand over coins"); + } + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + } + // Wait until account is read to issue blocks + for _ in 0..60 { + if let Ok(_r) = client.get_account_congestion(&account_id, None).await { + break; + } + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + } + + let block = client .build_basic_block( - AccountId::null(), + account_id, Some(Payload::TaggedData(Box::new( TaggedDataPayload::new(b"Hello".to_vec(), b"Tangle".to_vec()).unwrap(), ))), ) .await .unwrap() - .sign_ed25519(secret_manager, Bip44::new(IOTA_COIN_TYPE)) - .await - .unwrap() - .id(&protocol_params) + .sign_ed25519(&secret_manager, Bip44::new(IOTA_COIN_TYPE)) + .await?; + client.post_block(&block).await?; + + let protocol_params = client.get_protocol_parameters().await.unwrap(); + Ok(block.id(&protocol_params)) } pub fn setup_secret_manager() -> SecretManager { diff --git a/sdk/tests/client/secret_manager/address_generation.rs b/sdk/tests/client/secret_manager/address_generation.rs index 7ff9584cce..85ef64d7c6 100644 --- a/sdk/tests/client/secret_manager/address_generation.rs +++ b/sdk/tests/client/secret_manager/address_generation.rs @@ -3,26 +3,21 @@ #[cfg(feature = "stronghold")] use crypto::keys::bip39::Mnemonic; -use crypto::keys::bip44::Bip44; +#[cfg(feature = "ledger_nano")] +use iota_sdk::client::secret::ledger_nano::LedgerSecretManager; #[cfg(feature = "stronghold")] use iota_sdk::client::secret::stronghold::StrongholdSecretManager; -#[cfg(feature = "ledger_nano")] -use iota_sdk::client::secret::{ledger_nano::LedgerSecretManager, GenerateAddressOptions}; -#[cfg(feature = "events")] -use iota_sdk::wallet::events::{WalletEvent, WalletEventType}; use iota_sdk::{ client::{ - api::GetAddressesOptions, constants::{IOTA_COIN_TYPE, SHIMMER_COIN_TYPE}, secret::{mnemonic::MnemonicSecretManager, SecretManager}, ClientError, }, - types::block::address::{Hrp, ToBech32Ext}, - wallet::{ClientOptions, Wallet}, + types::block::address::ToBech32Ext, }; use pretty_assertions::assert_eq; -use crate::client::common::{setup, tear_down, DEFAULT_MNEMONIC, NODE_LOCAL}; +use crate::client::common::{setup, tear_down, DEFAULT_MNEMONIC}; #[tokio::test] async fn address_generation_mnemonic() -> Result<(), Box> { diff --git a/sdk/tests/client/secret_manager/mnemonic.rs b/sdk/tests/client/secret_manager/mnemonic.rs index 84cf4e6cbe..aad323aa43 100644 --- a/sdk/tests/client/secret_manager/mnemonic.rs +++ b/sdk/tests/client/secret_manager/mnemonic.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 use iota_sdk::client::{ - api::GetAddressesOptions, constants::{SHIMMER_COIN_TYPE, SHIMMER_TESTNET_BECH32_HRP}, secret::SecretManager, ClientError, diff --git a/sdk/tests/client/secret_manager/stronghold.rs b/sdk/tests/client/secret_manager/stronghold.rs index bb087859ee..7f304d4b15 100644 --- a/sdk/tests/client/secret_manager/stronghold.rs +++ b/sdk/tests/client/secret_manager/stronghold.rs @@ -2,7 +2,6 @@ // SPDX-License-Identifier: Apache-2.0 use iota_sdk::client::{ - api::GetAddressesOptions, constants::{SHIMMER_COIN_TYPE, SHIMMER_TESTNET_BECH32_HRP}, secret::SecretManager, ClientError, diff --git a/sdk/tests/wallet/balance.rs b/sdk/tests/wallet/balance.rs index 0fd52dc90b..fde0e9ffe4 100644 --- a/sdk/tests/wallet/balance.rs +++ b/sdk/tests/wallet/balance.rs @@ -141,7 +141,7 @@ async fn balance_expiration() -> Result<(), Box> { request_funds(&wallet_0).await?; - let slots_until_expired = 20; + let slots_until_expired = 5; let outputs = [BasicOutputBuilder::new_with_amount(1_000_000) // Send to account 1 with expiration to account 2, both have no amount yet .with_unlock_conditions([ @@ -162,7 +162,7 @@ async fn balance_expiration() -> Result<(), Box> { balance_before_tx.base_coin().total(), balance_after_tx.base_coin().total() ); - assert_eq!(balance_after_tx.base_coin().available(), 0); + assert_eq!(balance_after_tx.base_coin().available(), 999968300); wallet_0 .wait_for_transaction_acceptance(&tx.transaction_id, None, None) @@ -203,13 +203,6 @@ async fn balance_expiration() -> Result<(), Box> { assert_eq!(balance.base_coin().total(), 1_000_000); assert_eq!(balance.base_coin().available(), 1_000_000); - // It's possible to send the expired output - let outputs = [BasicOutputBuilder::new_with_amount(1_000_000) - // Send to wallet 1 with expiration to wallet 2, both have no amount yet - .with_unlock_conditions([AddressUnlockCondition::new(wallet_1.address().await)]) - .finish_output()?]; - let _tx = wallet_2.send_outputs(outputs, None).await?; - tear_down(storage_path_0)?; tear_down(storage_path_1)?; tear_down(storage_path_2)?; @@ -218,7 +211,7 @@ async fn balance_expiration() -> Result<(), Box> { #[ignore] #[tokio::test] -async fn balance_transfer() -> Result<(), Box> { +async fn available_balance_transfer() -> Result<(), Box> { let storage_path_0 = "test-storage/addresses_balance_0"; let storage_path_1 = "test-storage/addresses_balance_1"; setup(storage_path_0)?; @@ -229,13 +222,11 @@ async fn balance_transfer() -> Result<(), Box> { request_funds(&wallet_0).await?; - let balance_0 = wallet_0.balance().await?; - let balance_0_sync = wallet_0.sync(None).await?; + let balance_0 = wallet_0.sync(None).await?; let to_send = balance_0.base_coin().available(); // Check if 0 has balance and sync() and address_balance() match assert!(to_send > 0); - assert_eq!(balance_0, balance_0_sync); // Make sure 1 is empty let balance_1 = wallet_1.sync(None).await?; @@ -244,20 +235,22 @@ async fn balance_transfer() -> Result<(), Box> { // Send to 1 let tx = wallet_0.send(to_send, wallet_1.address().await, None).await?; - // Balance should update without sync + // Available balance should update without sync let balance_0 = wallet_0.balance().await?; let balance_0_sync = wallet_0.sync(None).await?; assert_eq!(balance_0.base_coin().available(), 0); - assert_eq!(balance_0, balance_0_sync); + assert_eq!( + balance_0.base_coin().available(), + balance_0_sync.base_coin().available() + ); wallet_0 .wait_for_transaction_acceptance(&tx.transaction_id, None, None) .await?; - // Balance should have transferred entirely - let balance_1_sync = wallet_1.sync(None).await?; + // Available balance should have transferred entirely + let balance_1 = wallet_1.sync(None).await?; assert!(balance_1.base_coin().available() > 0); - assert_eq!(balance_1, balance_1_sync); tear_down(storage_path_0)?; tear_down(storage_path_1)?; diff --git a/sdk/tests/wallet/burn_outputs.rs b/sdk/tests/wallet/burn_outputs.rs index 7d7dd7209b..5514340a75 100644 --- a/sdk/tests/wallet/burn_outputs.rs +++ b/sdk/tests/wallet/burn_outputs.rs @@ -6,7 +6,7 @@ use iota_sdk::{ types::block::output::{ feature::MetadataFeature, unlock_condition::{AddressUnlockCondition, ExpirationUnlockCondition}, - NativeToken, NftId, NftOutputBuilder, OutputId, UnlockCondition, + AccountId, NativeToken, NftId, NftOutputBuilder, OutputId, UnlockCondition, }, wallet::{CreateNativeTokenParams, MintNftParams, Wallet}, U256, @@ -60,12 +60,15 @@ async fn mint_and_burn_nft() -> Result<(), Box> { #[ignore] #[tokio::test] async fn mint_and_burn_expired_nft() -> Result<(), Box> { - let storage_path = "test-storage/mint_and_burn_expired_nft"; - setup(storage_path)?; + let storage_path_0 = "test-storage/mint_and_burn_expired_nft_0"; + let storage_path_1 = "test-storage/mint_and_burn_expired_nft_1"; + setup(storage_path_0)?; + setup(storage_path_1)?; - let wallet_0 = make_wallet(storage_path, None, None).await?; - let wallet_1 = make_wallet(storage_path, None, None).await?; + let wallet_0 = make_wallet(storage_path_0, None, None).await?; + let wallet_1 = make_wallet(storage_path_1, None, None).await?; request_funds(&wallet_0).await?; + request_funds(&wallet_1).await?; let amount = 1_000_000; let outputs = [NftOutputBuilder::new_with_amount(amount, NftId::null()) @@ -90,10 +93,10 @@ async fn mint_and_burn_expired_nft() -> Result<(), Box> { .wait_for_transaction_acceptance(&transaction.transaction_id, None, None) .await?; let balance = wallet_1.sync(None).await?; - // After burning the amount is available on account_1 - assert_eq!(balance.base_coin().available(), amount); + assert_eq!(balance.nfts().len(), 0); - tear_down(storage_path) + tear_down(storage_path_0)?; + tear_down(storage_path_1) } #[ignore] @@ -234,12 +237,6 @@ async fn create_and_burn_native_tokens() -> Result<(), Box Result<(), Box Result<(), Box Result<(), Box> setup(storage_path_1)?; let wallet_0 = make_wallet(storage_path_0, None, None).await?; - let wallet_1 = make_wallet(storage_path_0, None, None).await?; + let wallet_1 = make_wallet(storage_path_1, None, None).await?; request_funds(&wallet_0).await?; request_funds(&wallet_1).await?; @@ -447,9 +450,9 @@ async fn claim_2_nft_outputs() -> Result<(), Box> { #[ignore] #[tokio::test] -async fn claim_2_nft_outputs_no_outputs_in_claim_account() -> Result<(), Box> { - let storage_path_0 = "test-storage/claim_2_nft_outputs_no_outputs_in_claim_wallet_0"; - let storage_path_1 = "test-storage/claim_2_nft_outputs_no_outputs_in_claim_wallet_1"; +async fn claim_2_nft_outputs_no_available_in_claim_account() -> Result<(), Box> { + let storage_path_0 = "test-storage/claim_2_nft_outputs_no_available_in_claim_account_0"; + let storage_path_1 = "test-storage/claim_2_nft_outputs_no_available_in_claim_account_1"; setup(storage_path_0)?; setup(storage_path_1)?; @@ -457,6 +460,22 @@ async fn claim_2_nft_outputs_no_outputs_in_claim_account() -> Result<(), Box Result<(), Box Result<(), Box Result<(), Box> { + request_funds_from_faucet(FAUCET_URL, &wallet.implicit_account_creation_address().await?).await?; request_funds_from_faucet(FAUCET_URL, &wallet.address().await).await?; // Continue only after funds are received - for _ in 0..30 { + for i in 0..30 { + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + wallet + .sync(Some(SyncOptions { + sync_implicit_accounts: true, + ..Default::default() + })) + .await?; + if wallet.ledger().await.implicit_accounts().next().is_some() { + break; + } + if i == 29 { + panic!("Faucet no longer wants to hand over coins"); + } + } + + let wallet_ledger = wallet.ledger().await; + let implicit_account = wallet_ledger + .implicit_accounts() + .next() + .expect("No implicit account found") + .clone(); + drop(wallet_ledger); + + let mut tries = 0; + while let Err(ClientError::Node(iota_sdk::client::node_api::error::Error::NotFound(_))) = wallet + .client() + .get_account_congestion(&AccountId::from(&implicit_account.output_id), None) + .await + { + tries += 1; tokio::time::sleep(std::time::Duration::from_secs(2)).await; - let balance = wallet.sync(None).await?; - if balance.base_coin().available() > 0 { - return Ok(()); + if tries > 100 { + panic!("Can't get_account_congestion for implicit account"); } } - panic!("Faucet no longer wants to hand over coins"); + + let transaction = wallet + .implicit_account_transition( + &implicit_account.output_id, + BlockIssuerKeySource::ImplicitAccountAddress, + ) + .await?; + + wallet + .wait_for_transaction_acceptance(&transaction.transaction_id, None, None) + .await?; + + wallet.sync(None).await?; + + // Is this better than using the congestion endpoint? + // prepare a big tx and wait the time it takes until enough mana is generated + #[allow(unused_variables)] + if let Err(WalletError::Client(ClientError::TransactionBuilder(TransactionBuilderError::InsufficientMana { + found, + required, + slots_remaining, + }))) = wallet + .prepare_send(vec![SendParams::new(1_000_000, wallet.address().await)?; 10], None) + .await + { + tokio::time::sleep(std::time::Duration::from_secs( + slots_remaining as u64 + * wallet + .client() + .get_protocol_parameters() + .await? + .slot_duration_in_seconds() as u64, + )) + .await; + } + + Ok(()) } #[allow(dead_code)] diff --git a/sdk/tests/wallet/consolidation.rs b/sdk/tests/wallet/consolidation.rs index 87cb3d3d67..900894b958 100644 --- a/sdk/tests/wallet/consolidation.rs +++ b/sdk/tests/wallet/consolidation.rs @@ -18,6 +18,7 @@ async fn consolidation() -> Result<(), Box> { let wallet_1 = make_wallet(storage_path_1, None, None).await?; request_funds(&wallet_0).await?; + request_funds(&wallet_1).await?; // Send 10 outputs to wallet_1 let amount = 1_000_000; @@ -30,8 +31,8 @@ async fn consolidation() -> Result<(), Box> { .await?; let balance = wallet_1.sync(None).await.unwrap(); - assert_eq!(balance.base_coin().available(), 10 * amount); - assert_eq!(wallet_1.ledger().await.unspent_outputs().len(), 10); + assert_eq!(balance.base_coin().available(), 2009968300); + assert_eq!(wallet_1.ledger().await.unspent_outputs().len(), 12); let tx = wallet_1 .consolidate_outputs(ConsolidationParams::new().with_force(true)) @@ -42,9 +43,9 @@ async fn consolidation() -> Result<(), Box> { let balance = wallet_1.sync(None).await.unwrap(); // Balance still the same - assert_eq!(balance.base_coin().available(), 10 * amount); - // Only one unspent output - assert_eq!(wallet_1.ledger().await.unspent_outputs().len(), 1); + assert_eq!(balance.base_coin().available(), 2009968300); + // Account and basic unspent output + assert_eq!(wallet_1.ledger().await.unspent_outputs().len(), 2); tear_down(storage_path_0)?; tear_down(storage_path_1)?; diff --git a/sdk/tests/wallet/output_preparation.rs b/sdk/tests/wallet/output_preparation.rs index 9d4cfc4829..22f322fd6b 100644 --- a/sdk/tests/wallet/output_preparation.rs +++ b/sdk/tests/wallet/output_preparation.rs @@ -43,11 +43,11 @@ async fn output_preparation() -> Result<(), Box> { None, ) .await?; - assert_eq!(output.amount(), 46800); + assert_eq!(output.amount(), 18300); // 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!(sdr.amount(), 46300); + assert_eq!(sdr.amount(), 17800); let output = wallet .prepare_output( @@ -139,13 +139,13 @@ async fn output_preparation() -> Result<(), Box> { None, ) .await?; - assert_eq!(output.amount(), 49000); + let min_amount_with_metadata_and_tag = 21100; + assert_eq!(output.amount(), min_amount_with_metadata_and_tag); let unlock_conditions = output.unlock_conditions().unwrap(); // address + sdr assert_eq!(unlock_conditions.len(), 2); let storage_deposit_return = unlock_conditions.storage_deposit_return().unwrap(); - // output amount -1 - assert_eq!(storage_deposit_return.amount(), 48999); + assert_eq!(storage_deposit_return.amount(), min_amount_with_metadata_and_tag - 1); // metadata and tag features assert_eq!(output.features().unwrap().len(), 2); @@ -168,7 +168,7 @@ async fn output_preparation() -> Result<(), Box> { None, ) .await?; - assert_eq!(output.amount(), 54600); + assert_eq!(output.amount(), 26100); // 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); @@ -194,9 +194,9 @@ async fn output_preparation() -> Result<(), Box> { None, ) .await?; - assert_eq!(output.amount(), 49000); + assert_eq!(output.amount(), min_amount_with_metadata_and_tag); let sdr = output.unlock_conditions().unwrap().storage_deposit_return().unwrap(); - assert_eq!(sdr.amount(), 48999); + assert_eq!(sdr.amount(), min_amount_with_metadata_and_tag - 1); // address and storage deposit unlock condition, because of the metadata feature block, 213000 is not enough for the // required storage deposit @@ -279,11 +279,11 @@ async fn output_preparation() -> Result<(), Box> { ) .await?; - assert_eq!(output.kind(), iota_sdk::types::block::output::BasicOutput::KIND); + assert_eq!(output.kind(), BasicOutput::KIND); assert_eq!(output.amount(), 500000); assert_eq!(output.unlock_conditions().unwrap().len(), 1); let features = output.features().unwrap(); - assert_eq!(features.len(), 1); + assert_eq!(features.len(), 2); assert_eq!(features.sender().unwrap().address(), expected_address); // error when adding issuer when building basic output @@ -356,7 +356,7 @@ async fn output_preparation() -> Result<(), Box> { assert!(conditions.is_timelocked(0, 0)); assert_eq!( conditions.is_expired(2, CommittableAgeRange { min: 0, max: 0 }), - Some(false) + Some(true) ); // nft with expiration @@ -387,7 +387,7 @@ async fn output_preparation() -> Result<(), Box> { ) .await?; assert_eq!(output.kind(), iota_sdk::types::block::output::NftOutput::KIND); - assert_eq!(output.amount(), 53900); + assert_eq!(output.amount(), 25400); // address, sdr, expiration assert_eq!(output.unlock_conditions().unwrap().len(), 3); @@ -418,9 +418,9 @@ async fn output_preparation() -> Result<(), Box> { let storage_score_params = wallet.client().get_storage_score_parameters().await?; let minimum_amount = output.minimum_amount(storage_score_params); assert_eq!(output.amount(), minimum_amount); - assert_eq!(output.amount(), 187900); + assert_eq!(output.amount(), 160000); let sdr = output.unlock_conditions().unwrap().storage_deposit_return().unwrap(); - assert_eq!(sdr.amount(), 145300); + assert_eq!(sdr.amount(), 117400); // 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); @@ -450,7 +450,7 @@ async fn output_preparation_sdr() -> Result<(), Box> { .prepare_output( OutputParams { recipient_address: recipient_address.clone(), - amount: 8001, + amount: 4001, assets: None, features: None, unlocks: None, @@ -461,17 +461,19 @@ async fn output_preparation_sdr() -> Result<(), Box> { .await?; // Check if the output has enough amount to cover the storage deposit output.verify_storage_deposit(storage_score_params)?; - assert_eq!(output.amount(), 50601); + assert_eq!(output.amount(), 18300); // 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!(sdr.amount(), 42600); + assert_eq!(sdr.amount(), 14299); + + let min_amount = 14100; let output = wallet .prepare_output( OutputParams { recipient_address: recipient_address.clone(), - amount: 42599, + amount: min_amount - 1, assets: None, features: None, unlocks: None, @@ -482,18 +484,18 @@ async fn output_preparation_sdr() -> Result<(), Box> { .await?; // Check if the output has enough amount to cover the storage deposit output.verify_storage_deposit(storage_score_params)?; - assert_eq!(output.amount(), 85199); + assert_eq!(output.amount(), (min_amount * 2) - 1); // 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!(sdr.amount(), 42600); + assert_eq!(sdr.amount(), min_amount); // ReturnStrategy::Return provided let output = wallet .prepare_output( OutputParams { recipient_address: recipient_address.clone(), - amount: 42599, + amount: min_amount - 1, assets: None, features: None, unlocks: None, @@ -507,18 +509,18 @@ async fn output_preparation_sdr() -> Result<(), Box> { .await?; // Check if the output has enough amount to cover the storage deposit output.verify_storage_deposit(storage_score_params)?; - assert_eq!(output.amount(), 85199); + assert_eq!(output.amount(), (min_amount * 2) - 1); // 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!(sdr.amount(), 42600); + assert_eq!(sdr.amount(), min_amount); // ReturnStrategy::Gift provided let output = wallet .prepare_output( OutputParams { recipient_address: recipient_address.clone(), - amount: 42599, + amount: min_amount - 1, assets: None, features: None, unlocks: None, @@ -533,7 +535,7 @@ async fn output_preparation_sdr() -> Result<(), Box> { // Check if the output has enough amount to cover the storage deposit output.verify_storage_deposit(storage_score_params)?; // The additional 1 amount will be added, because the storage deposit should be gifted and not returned - assert_eq!(output.amount(), 42600); + assert_eq!(output.amount(), min_amount); // storage deposit gifted, only address unlock condition assert_eq!(output.unlock_conditions().unwrap().len(), 1); @@ -553,12 +555,22 @@ async fn prepare_nft_output_features_update() -> Result<(), Box Result<(), Box Result<(), Box Result<(), Box> { - let storage_path_0 = "test-storage/prepare_output_remainder_dust_0"; - let storage_path_1 = "test-storage/prepare_output_remainder_dust_1"; - setup(storage_path_0)?; - setup(storage_path_1)?; - - let wallet_0 = make_wallet(storage_path_0, None, None).await?; - let wallet_1 = make_wallet(storage_path_1, None, None).await?; - request_funds(&wallet_0).await?; - request_funds(&wallet_1).await?; - - let storage_score_params = wallet_0.client().get_storage_score_parameters().await?; - - let balance = wallet_0.sync(None).await?; - let minimum_amount = BasicOutput::minimum_amount(&*wallet_1.address().await, storage_score_params); - - // Send away most balance so we can test with leaving dust - let output = wallet_0 - .prepare_output( - OutputParams { - recipient_address: wallet_1.address().await, - amount: balance.base_coin().available() - 63900, - assets: None, - features: None, - unlocks: None, - storage_deposit: None, - }, - None, - ) - .await?; - let transaction = wallet_0.send_outputs(vec![output], None).await?; - wallet_0 - .wait_for_transaction_acceptance(&transaction.transaction_id, None, None) - .await?; - let balance = wallet_0.sync(None).await?; - - // 63900 left - let output = wallet_0 - .prepare_output( - OutputParams { - recipient_address: wallet_1.address().await, - amount: minimum_amount - 1, // Leave less than min. deposit - assets: None, - features: None, - unlocks: None, - storage_deposit: Some(StorageDeposit { - return_strategy: Some(ReturnStrategy::Gift), - use_excess_if_low: Some(true), - }), - }, - None, - ) - .await?; - - // Check if the output has enough amount to cover the storage deposit - output.verify_storage_deposit(storage_score_params)?; - // The left over 21299 is too small to keep, so we donate it - assert_eq!(output.amount(), balance.base_coin().available()); - // storage deposit gifted, only address unlock condition - assert_eq!(output.unlock_conditions().unwrap().len(), 1); - - let result = wallet_0 - .prepare_output( - OutputParams { - recipient_address: wallet_1.address().await, - amount: minimum_amount - 1, // Leave less than min. deposit - assets: None, - features: None, - unlocks: None, - storage_deposit: Some(StorageDeposit { - return_strategy: Some(ReturnStrategy::Return), - use_excess_if_low: Some(true), - }), - }, - None, - ) - .await; - assert!( - matches!(result, Err(iota_sdk::wallet::WalletError::InsufficientFunds{available, required}) if available == balance.base_coin().available() && required == 85199) - ); - - let output = wallet_0 - .prepare_output( - OutputParams { - recipient_address: wallet_1.address().await, - amount: 100, // leave more behind than min. deposit - assets: None, - features: None, - unlocks: None, - storage_deposit: Some(StorageDeposit { - return_strategy: Some(ReturnStrategy::Gift), - use_excess_if_low: Some(true), - }), - }, - None, - ) - .await?; - - // Check if the output has enough amount to cover the storage deposit - output.verify_storage_deposit(storage_score_params)?; - // We use excess if leftover is too small, so amount == all available balance - assert_eq!(output.amount(), 63900); - // storage deposit gifted, only address unlock condition - assert_eq!(output.unlock_conditions().unwrap().len(), 1); - - let output = wallet_0 - .prepare_output( - OutputParams { - recipient_address: wallet_1.address().await, - amount: 100, // leave more behind than min. deposit - assets: None, - features: None, - unlocks: None, - storage_deposit: Some(StorageDeposit { - return_strategy: Some(ReturnStrategy::Return), - use_excess_if_low: Some(true), - }), - }, - None, - ) - .await?; - - // Check if the output has enough amount to cover the storage deposit - output.verify_storage_deposit(storage_score_params)?; - // We use excess if leftover is too small, so amount == all available balance - assert_eq!(output.amount(), 63900); - // storage deposit returned, address and SDR unlock condition - assert_eq!(output.unlock_conditions().unwrap().len(), 2); - // We have ReturnStrategy::Return, so leftover amount gets returned - let sdr = output.unlock_conditions().unwrap().storage_deposit_return().unwrap(); - assert_eq!(sdr.amount(), 63900 - 100); - - tear_down(storage_path_0)?; - tear_down(storage_path_1)?; - - Ok(()) -} +// TODO: adjust amounts +// #[ignore] +// #[tokio::test] +// async fn prepare_output_remainder_dust() -> Result<(), Box> { +// let storage_path_0 = "test-storage/prepare_output_remainder_dust_0"; +// let storage_path_1 = "test-storage/prepare_output_remainder_dust_1"; +// setup(storage_path_0)?; +// setup(storage_path_1)?; + +// let wallet_0 = make_wallet(storage_path_0, None, None).await?; +// let wallet_1 = make_wallet(storage_path_1, None, None).await?; +// request_funds(&wallet_0).await?; +// request_funds(&wallet_1).await?; + +// let storage_score_params = wallet_0.client().get_storage_score_parameters().await?; + +// let balance = wallet_0.sync(None).await?; +// let minimum_amount = BasicOutput::minimum_amount(&*wallet_1.address().await, storage_score_params); + +// // Send away most balance so we can test with leaving dust +// let output = wallet_0 +// .prepare_output( +// OutputParams { +// recipient_address: wallet_1.address().await, +// amount: balance.base_coin().available() - 63900, +// assets: None, +// features: None, +// unlocks: None, +// storage_deposit: None, +// }, +// None, +// ) +// .await?; +// let transaction = wallet_0.send_outputs(vec![output], None).await?; +// wallet_0 +// .wait_for_transaction_acceptance(&transaction.transaction_id, None, None) +// .await?; +// let balance = wallet_0.sync(None).await?; + +// // 63900 left +// let output = wallet_0 +// .prepare_output( +// OutputParams { +// recipient_address: wallet_1.address().await, +// amount: minimum_amount - 1, // Leave less than min. deposit +// assets: None, +// features: None, +// unlocks: None, +// storage_deposit: Some(StorageDeposit { +// return_strategy: Some(ReturnStrategy::Gift), +// use_excess_if_low: Some(true), +// }), +// }, +// None, +// ) +// .await?; + +// // Check if the output has enough amount to cover the storage deposit +// output.verify_storage_deposit(storage_score_params)?; +// // The left over 21299 is too small to keep, so we donate it +// assert_eq!(output.amount(), balance.base_coin().available()); +// // storage deposit gifted, only address unlock condition +// assert_eq!(output.unlock_conditions().unwrap().len(), 1); + +// let result = wallet_0 +// .prepare_output( +// OutputParams { +// recipient_address: wallet_1.address().await, +// amount: minimum_amount - 1, // Leave less than min. deposit +// assets: None, +// features: None, +// unlocks: None, +// storage_deposit: Some(StorageDeposit { +// return_strategy: Some(ReturnStrategy::Return), +// use_excess_if_low: Some(true), +// }), +// }, +// None, +// ) +// .await; +// assert!( +// matches!(result, Err(iota_sdk::wallet::WalletError::InsufficientFunds{available, required}) if available == +// balance.base_coin().available() && required == 42599) ); + +// let output = wallet_0 +// .prepare_output( +// OutputParams { +// recipient_address: wallet_1.address().await, +// amount: 100, // leave more behind than min. deposit +// assets: None, +// features: None, +// unlocks: None, +// storage_deposit: Some(StorageDeposit { +// return_strategy: Some(ReturnStrategy::Gift), +// use_excess_if_low: Some(true), +// }), +// }, +// None, +// ) +// .await?; + +// // Check if the output has enough amount to cover the storage deposit +// output.verify_storage_deposit(storage_score_params)?; +// // We use excess if leftover is too small, so amount == all available balance +// assert_eq!(output.amount(), 63900); +// // storage deposit gifted, only address unlock condition +// assert_eq!(output.unlock_conditions().unwrap().len(), 1); + +// let output = wallet_0 +// .prepare_output( +// OutputParams { +// recipient_address: wallet_1.address().await, +// amount: 100, // leave more behind than min. deposit +// assets: None, +// features: None, +// unlocks: None, +// storage_deposit: Some(StorageDeposit { +// return_strategy: Some(ReturnStrategy::Return), +// use_excess_if_low: Some(true), +// }), +// }, +// None, +// ) +// .await?; + +// // Check if the output has enough amount to cover the storage deposit +// output.verify_storage_deposit(storage_score_params)?; +// // We use excess if leftover is too small, so amount == all available balance +// assert_eq!(output.amount(), 63900); +// // storage deposit returned, address and SDR unlock condition +// assert_eq!(output.unlock_conditions().unwrap().len(), 2); +// // We have ReturnStrategy::Return, so leftover amount gets returned +// let sdr = output.unlock_conditions().unwrap().storage_deposit_return().unwrap(); +// assert_eq!(sdr.amount(), 63900 - 100); + +// tear_down(storage_path_0)?; +// tear_down(storage_path_1)?; + +// Ok(()) +// } #[ignore] #[tokio::test] @@ -764,8 +764,9 @@ async fn prepare_output_only_single_nft() -> Result<(), Box Result<(), Box Result<(), Box Result<(), WalletError> { -// let storage_path_0 = "test-storage/send_amount_0"; -// setup(storage_path_0)?; -// let storage_path_1 = "test-storage/send_amount_1"; -// setup(storage_path_1)?; +#[tokio::test] +async fn send_amount() -> Result<(), Box> { + let storage_path_0 = "test-storage/send_amount_0"; + setup(storage_path_0)?; + let storage_path_1 = "test-storage/send_amount_1"; + setup(storage_path_1)?; -// let wallet_0 = make_wallet(storage_path_0, None, None).await?; -// request_funds(&wallet_0, 1).await?; + let wallet_0 = make_wallet(storage_path_0, Some(generate_mnemonic()?), None).await?; + request_funds(&wallet_0).await?; -// let wallet_1 = make_wallet(storage_path_1, None, None).await?; + let wallet_1 = make_wallet(storage_path_1, None, None).await?; -// let amount = 1_000_000; -// let tx = wallet_0 -// .send_with_params([SendParams::new(amount, wallet_1.address().clone())?], None) -// .await?; + let amount = 1_000_000; + let tx = wallet_0 + .send_with_params([SendParams::new(amount, wallet_1.address().await)?], None) + .await?; -// wallet_0 -// .wait_for_transaction_acceptance(&tx.transaction_id, None, None) -// .await?; + wallet_0 + .wait_for_transaction_acceptance(&tx.transaction_id, None, None) + .await?; -// let balance = wallet_1.sync(None).await.unwrap(); -// assert_eq!(balance.base_coin().available(), amount); + let balance = wallet_1.sync(None).await.unwrap(); + assert_eq!(balance.base_coin().available(), amount); -// tear_down(storage_path) -// } + tear_down(storage_path_0)?; + tear_down(storage_path_1) +} // #[ignore] // #[tokio::test] -// async fn send_amount_127_outputs() -> Result<(), WalletError> { +// async fn send_amount_127_outputs() -> Result<(), Box> { // let storage_path_0 = "test-storage/send_amount_127_outputs_0"; // setup(storage_path_0)?; // let storage_path_1 = "test-storage/send_amount_127_outputs_1"; @@ -74,7 +74,7 @@ // #[ignore] // #[tokio::test] -// async fn send_amount_custom_input() -> Result<(), WalletError> { +// async fn send_amount_custom_input() -> Result<(), Box> { // let storage_path_0 = "test-storage/send_amount_custom_input_0"; // setup(storage_path_0)?; // let storage_path_1 = "test-storage/send_amount_custom_input_1"; @@ -121,7 +121,7 @@ // #[ignore] // #[tokio::test] -// async fn send_nft() -> Result<(), WalletError> { +// async fn send_nft() -> Result<(), Box> { // let storage_path_0 = "test-storage/send_nft_0"; // setup(storage_path_0)?; // let storage_path_1 = "test-storage/send_nft_1"; @@ -164,7 +164,7 @@ // #[ignore] // #[tokio::test] -// async fn send_with_note() -> Result<(), WalletError> { +// async fn send_with_note() -> Result<(), Box> { // let storage_path_0 = "test-storage/send_with_note_0"; // setup(storage_path_0)?; // let storage_path_1 = "test-storage/send_with_note_1"; @@ -193,7 +193,7 @@ // #[ignore] // #[tokio::test] -// async fn conflicting_transaction() -> Result<(), WalletError> { +// async fn conflicting_transaction() -> Result<(), Box> { // let storage_path_0 = "test-storage/conflicting_transaction_0"; // let storage_path_1 = "test-storage/conflicting_transaction_1"; // setup(storage_path_0)?; @@ -265,7 +265,7 @@ // #[tokio::test] // #[cfg(all(feature = "ledger_nano", feature = "events"))] // #[ignore = "requires ledger nano instance"] -// async fn prepare_transaction_ledger() -> Result<(), WalletError> { +// async fn prepare_transaction_ledger() -> Result<(), Box> { // use iota_sdk::wallet::events::{types::TransactionProgressEvent, WalletEvent, WalletEventType}; // let storage_path_0 = "test-storage/wallet_address_generation_ledger_0"; From 784c8414bf1f0cd142a8cf90865cf5cfc763d0c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Tue, 19 Mar 2024 12:02:54 +0100 Subject: [PATCH 02/15] Fix more tests, don't select inputs for mana when they don't add anything --- sdk/examples/wallet/logger.rs | 1 - sdk/examples/wallet/spammer.rs | 8 +-- .../transaction_builder/requirement/mana.rs | 9 ++++ sdk/tests/wallet/burn_outputs.rs | 19 +++++-- sdk/tests/wallet/claim_outputs.rs | 53 ++++++++++++++++--- sdk/tests/wallet/transactions.rs | 4 +- 6 files changed, 72 insertions(+), 22 deletions(-) diff --git a/sdk/examples/wallet/logger.rs b/sdk/examples/wallet/logger.rs index 907a75120d..37390bd4f6 100644 --- a/sdk/examples/wallet/logger.rs +++ b/sdk/examples/wallet/logger.rs @@ -10,7 +10,6 @@ use iota_sdk::{ client::{ - api::GetAddressesOptions, constants::SHIMMER_COIN_TYPE, secret::{mnemonic::MnemonicSecretManager, SecretManager}, }, diff --git a/sdk/examples/wallet/spammer.rs b/sdk/examples/wallet/spammer.rs index 52786a6f73..70fc0aaf88 100644 --- a/sdk/examples/wallet/spammer.rs +++ b/sdk/examples/wallet/spammer.rs @@ -12,14 +12,10 @@ use iota_sdk::{ client::{ constants::SHIMMER_COIN_TYPE, request_funds_from_faucet, - secret::{mnemonic::MnemonicSecretManager, SecretManage, SecretManager}, + secret::{mnemonic::MnemonicSecretManager, SecretManager}, }, crypto::keys::bip44::Bip44, - types::block::{ - address::{Address, Bech32Address, Hrp}, - output::BasicOutput, - payload::signed_transaction::TransactionId, - }, + types::block::{address::Bech32Address, output::BasicOutput, payload::signed_transaction::TransactionId}, wallet::{ClientOptions, FilterOptions, SendParams, Wallet}, }; diff --git a/sdk/src/client/api/block_builder/transaction_builder/requirement/mana.rs b/sdk/src/client/api/block_builder/transaction_builder/requirement/mana.rs index 58a0b8989f..e7cfc405dd 100644 --- a/sdk/src/client/api/block_builder/transaction_builder/requirement/mana.rs +++ b/sdk/src/client/api/block_builder/transaction_builder/requirement/mana.rs @@ -256,6 +256,15 @@ impl TransactionBuilder { let Some(input) = priority_map.next(required_mana - selected_mana) else { break; }; + // Don't select input with 0 available mana + if input.output.available_mana( + &self.protocol_parameters, + input.output_id().transaction_id().slot_index(), + self.creation_slot, + )? == 0 + { + continue; + } selected_mana += self.total_mana(&input, include_generated)?; if let Some(output) = self.select_input(input)? { required_mana += output.mana(); diff --git a/sdk/tests/wallet/burn_outputs.rs b/sdk/tests/wallet/burn_outputs.rs index 5514340a75..796bf4e38a 100644 --- a/sdk/tests/wallet/burn_outputs.rs +++ b/sdk/tests/wallet/burn_outputs.rs @@ -111,6 +111,7 @@ async fn create_and_melt_native_token() -> Result<(), Box // First create an account output, this needs to be done only once, because an account can have many foundry outputs let transaction = wallet.create_account_output(None, None).await?; + let account_id = AccountId::from(&OutputId::new(transaction.transaction_id, 0)); wallet .wait_for_transaction_acceptance(&transaction.transaction_id, None, None) .await?; @@ -118,7 +119,7 @@ async fn create_and_melt_native_token() -> Result<(), Box let circulating_supply = U256::from(60i32); let params = CreateNativeTokenParams { - account_id: None, + account_id: Some(account_id), circulating_supply, maximum_supply: U256::from(100i32), foundry_metadata: None, @@ -175,7 +176,7 @@ async fn create_and_melt_native_token() -> Result<(), Box // Call to run tests in sequence destroy_foundry(&wallet).await?; - destroy_account(&wallet).await?; + destroy_account(&wallet, account_id).await?; tear_down(storage_path) } @@ -203,12 +204,10 @@ async fn destroy_foundry(wallet: &Wallet) -> Result<(), Box Result<(), Box> { +async fn destroy_account(wallet: &Wallet, account_id: AccountId) -> Result<(), Box> { let balance = wallet.sync(None).await.unwrap(); println!("account balance -> {}", serde_json::to_string(&balance).unwrap()); - // Let's destroy the first account we can find - let account_id = *balance.accounts().first().unwrap(); println!("account_id -> {account_id}"); let transaction = wallet.burn(account_id, None).await.unwrap(); wallet @@ -228,6 +227,16 @@ async fn destroy_account(wallet: &Wallet) -> Result<(), Box Result<(), Box> { + let logger_output_config = fern_logger::LoggerOutputConfigBuilder::new() + .name("client.log") + .target_exclusions(&["h2", "hyper", "rustls"]) + .level_filter(log::LevelFilter::Debug); + + let config = fern_logger::LoggerConfig::build() + .with_output(logger_output_config) + .finish(); + + fern_logger::logger_init(config).unwrap(); let storage_path = "test-storage/create_and_burn_native_tokens"; setup(storage_path)?; diff --git a/sdk/tests/wallet/claim_outputs.rs b/sdk/tests/wallet/claim_outputs.rs index 9ab3c25e73..d6d0bda2fa 100644 --- a/sdk/tests/wallet/claim_outputs.rs +++ b/sdk/tests/wallet/claim_outputs.rs @@ -133,9 +133,9 @@ async fn claim_1_of_2_basic_outputs() -> Result<(), Box> #[ignore] #[tokio::test] -async fn claim_2_basic_outputs_no_outputs_in_claim_account() -> Result<(), Box> { - let storage_path_0 = "test-storage/claim_2_basic_outputs_no_outputs_in_claim_account_0"; - let storage_path_1 = "test-storage/claim_2_basic_outputs_no_outputs_in_claim_account_1"; +async fn claim_2_basic_outputs_no_available_in_claim_account() -> Result<(), Box> { + let storage_path_0 = "test-storage/claim_2_basic_outputs_no_available_in_claim_account_0"; + let storage_path_1 = "test-storage/claim_2_basic_outputs_no_available_in_claim_account_1"; setup(storage_path_0)?; setup(storage_path_1)?; @@ -143,10 +143,31 @@ async fn claim_2_basic_outputs_no_outputs_in_claim_account() -> Result<(), Box Result<(), Box> { #[ignore] #[tokio::test] -async fn claim_2_native_tokens_no_outputs_in_claim_account() -> Result<(), Box> { - let storage_path_0 = "test-storage/claim_2_native_tokens_no_outputs_in_claim_account_0"; - let storage_path_1 = "test-storage/claim_2_native_tokens_no_outputs_in_claim_account_1"; +async fn claim_2_native_tokens_no_available_balance_in_claim_account() -> Result<(), Box> { + let storage_path_0 = "test-storage/claim_2_native_tokens_no_available_balance_in_claim_account_0"; + let storage_path_1 = "test-storage/claim_2_native_tokens_no_available_balance_in_claim_account_1"; setup(storage_path_0)?; setup(storage_path_1)?; @@ -291,6 +312,22 @@ async fn claim_2_native_tokens_no_outputs_in_claim_account() -> Result<(), Box Result<(), Box> { let storage_path_1 = "test-storage/send_amount_1"; setup(storage_path_1)?; - let wallet_0 = make_wallet(storage_path_0, Some(generate_mnemonic()?), None).await?; + let wallet_0 = make_wallet(storage_path_0, None, None).await?; request_funds(&wallet_0).await?; let wallet_1 = make_wallet(storage_path_1, None, None).await?; From 09f6bc533de40a328d301902ed5c2d0bd104f337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Tue, 19 Mar 2024 16:16:10 +0100 Subject: [PATCH 03/15] Use nova branch for ledger nano simulator --- .github/actions/ledger-nano/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/ledger-nano/action.yml b/.github/actions/ledger-nano/action.yml index 36d162f742..c9d7775803 100644 --- a/.github/actions/ledger-nano/action.yml +++ b/.github/actions/ledger-nano/action.yml @@ -7,7 +7,7 @@ runs: uses: actions/checkout@v3 with: repository: iotaledger/ledger-iota-app - ref: develop + ref: feat/nova path: ledger-iota-app - name: Update submodules From 168ee5e3727a9f8330fd99c942aa0339cde1fd7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Tue, 19 Mar 2024 17:08:10 +0100 Subject: [PATCH 04/15] Uncomment and update test --- sdk/tests/wallet/output_preparation.rs | 280 ++++++++++++------------- 1 file changed, 140 insertions(+), 140 deletions(-) diff --git a/sdk/tests/wallet/output_preparation.rs b/sdk/tests/wallet/output_preparation.rs index 22f322fd6b..2037a7abce 100644 --- a/sdk/tests/wallet/output_preparation.rs +++ b/sdk/tests/wallet/output_preparation.rs @@ -612,146 +612,146 @@ async fn prepare_nft_output_features_update() -> Result<(), Box Result<(), Box> { -// let storage_path_0 = "test-storage/prepare_output_remainder_dust_0"; -// let storage_path_1 = "test-storage/prepare_output_remainder_dust_1"; -// setup(storage_path_0)?; -// setup(storage_path_1)?; - -// let wallet_0 = make_wallet(storage_path_0, None, None).await?; -// let wallet_1 = make_wallet(storage_path_1, None, None).await?; -// request_funds(&wallet_0).await?; -// request_funds(&wallet_1).await?; - -// let storage_score_params = wallet_0.client().get_storage_score_parameters().await?; - -// let balance = wallet_0.sync(None).await?; -// let minimum_amount = BasicOutput::minimum_amount(&*wallet_1.address().await, storage_score_params); - -// // Send away most balance so we can test with leaving dust -// let output = wallet_0 -// .prepare_output( -// OutputParams { -// recipient_address: wallet_1.address().await, -// amount: balance.base_coin().available() - 63900, -// assets: None, -// features: None, -// unlocks: None, -// storage_deposit: None, -// }, -// None, -// ) -// .await?; -// let transaction = wallet_0.send_outputs(vec![output], None).await?; -// wallet_0 -// .wait_for_transaction_acceptance(&transaction.transaction_id, None, None) -// .await?; -// let balance = wallet_0.sync(None).await?; - -// // 63900 left -// let output = wallet_0 -// .prepare_output( -// OutputParams { -// recipient_address: wallet_1.address().await, -// amount: minimum_amount - 1, // Leave less than min. deposit -// assets: None, -// features: None, -// unlocks: None, -// storage_deposit: Some(StorageDeposit { -// return_strategy: Some(ReturnStrategy::Gift), -// use_excess_if_low: Some(true), -// }), -// }, -// None, -// ) -// .await?; - -// // Check if the output has enough amount to cover the storage deposit -// output.verify_storage_deposit(storage_score_params)?; -// // The left over 21299 is too small to keep, so we donate it -// assert_eq!(output.amount(), balance.base_coin().available()); -// // storage deposit gifted, only address unlock condition -// assert_eq!(output.unlock_conditions().unwrap().len(), 1); - -// let result = wallet_0 -// .prepare_output( -// OutputParams { -// recipient_address: wallet_1.address().await, -// amount: minimum_amount - 1, // Leave less than min. deposit -// assets: None, -// features: None, -// unlocks: None, -// storage_deposit: Some(StorageDeposit { -// return_strategy: Some(ReturnStrategy::Return), -// use_excess_if_low: Some(true), -// }), -// }, -// None, -// ) -// .await; -// assert!( -// matches!(result, Err(iota_sdk::wallet::WalletError::InsufficientFunds{available, required}) if available == -// balance.base_coin().available() && required == 42599) ); - -// let output = wallet_0 -// .prepare_output( -// OutputParams { -// recipient_address: wallet_1.address().await, -// amount: 100, // leave more behind than min. deposit -// assets: None, -// features: None, -// unlocks: None, -// storage_deposit: Some(StorageDeposit { -// return_strategy: Some(ReturnStrategy::Gift), -// use_excess_if_low: Some(true), -// }), -// }, -// None, -// ) -// .await?; - -// // Check if the output has enough amount to cover the storage deposit -// output.verify_storage_deposit(storage_score_params)?; -// // We use excess if leftover is too small, so amount == all available balance -// assert_eq!(output.amount(), 63900); -// // storage deposit gifted, only address unlock condition -// assert_eq!(output.unlock_conditions().unwrap().len(), 1); - -// let output = wallet_0 -// .prepare_output( -// OutputParams { -// recipient_address: wallet_1.address().await, -// amount: 100, // leave more behind than min. deposit -// assets: None, -// features: None, -// unlocks: None, -// storage_deposit: Some(StorageDeposit { -// return_strategy: Some(ReturnStrategy::Return), -// use_excess_if_low: Some(true), -// }), -// }, -// None, -// ) -// .await?; - -// // Check if the output has enough amount to cover the storage deposit -// output.verify_storage_deposit(storage_score_params)?; -// // We use excess if leftover is too small, so amount == all available balance -// assert_eq!(output.amount(), 63900); -// // storage deposit returned, address and SDR unlock condition -// assert_eq!(output.unlock_conditions().unwrap().len(), 2); -// // We have ReturnStrategy::Return, so leftover amount gets returned -// let sdr = output.unlock_conditions().unwrap().storage_deposit_return().unwrap(); -// assert_eq!(sdr.amount(), 63900 - 100); - -// tear_down(storage_path_0)?; -// tear_down(storage_path_1)?; - -// Ok(()) -// } +#[ignore] +#[tokio::test] +async fn prepare_output_remainder_dust() -> Result<(), Box> { + let storage_path_0 = "test-storage/prepare_output_remainder_dust_0"; + let storage_path_1 = "test-storage/prepare_output_remainder_dust_1"; + setup(storage_path_0)?; + setup(storage_path_1)?; + + let wallet_0 = make_wallet(storage_path_0, None, None).await?; + let wallet_1 = make_wallet(storage_path_1, None, None).await?; + request_funds(&wallet_0).await?; + request_funds(&wallet_1).await?; + + let storage_score_params = wallet_0.client().get_storage_score_parameters().await?; + + let balance = wallet_0.sync(None).await?; + let minimum_amount = BasicOutput::minimum_amount(&*wallet_1.address().await, storage_score_params); + + // Send away most balance so we can test with leaving dust + let output = wallet_0 + .prepare_output( + OutputParams { + recipient_address: wallet_1.address().await, + amount: balance.base_coin().available() - 18300, + assets: None, + features: None, + unlocks: None, + storage_deposit: None, + }, + None, + ) + .await?; + let transaction = wallet_0.send_outputs(vec![output], None).await?; + wallet_0 + .wait_for_transaction_acceptance(&transaction.transaction_id, None, None) + .await?; + let balance = wallet_0.sync(None).await?; + + // 18300 left + let output = wallet_0 + .prepare_output( + OutputParams { + recipient_address: wallet_1.address().await, + amount: minimum_amount - 1, // Leave less than min. deposit + assets: None, + features: None, + unlocks: None, + storage_deposit: Some(StorageDeposit { + return_strategy: Some(ReturnStrategy::Gift), + use_excess_if_low: Some(true), + }), + }, + None, + ) + .await?; + + // Check if the output has enough amount to cover the storage deposit + output.verify_storage_deposit(storage_score_params)?; + // The left over 21299 is too small to keep, so we donate it + assert_eq!(output.amount(), balance.base_coin().available()); + // storage deposit gifted, only address unlock condition + assert_eq!(output.unlock_conditions().unwrap().len(), 1); + + let result = wallet_0 + .prepare_output( + OutputParams { + recipient_address: wallet_1.address().await, + amount: minimum_amount - 1, // Leave less than min. deposit + assets: None, + features: None, + unlocks: None, + storage_deposit: Some(StorageDeposit { + return_strategy: Some(ReturnStrategy::Return), + use_excess_if_low: Some(true), + }), + }, + None, + ) + .await; + assert!( + matches!(result, Err(iota_sdk::wallet::WalletError::InsufficientFunds{available, required}) if available == + balance.base_coin().available() && required == 28199) + ); + + let output = wallet_0 + .prepare_output( + OutputParams { + recipient_address: wallet_1.address().await, + amount: 100, // leave more behind than min. deposit + assets: None, + features: None, + unlocks: None, + storage_deposit: Some(StorageDeposit { + return_strategy: Some(ReturnStrategy::Gift), + use_excess_if_low: Some(true), + }), + }, + None, + ) + .await?; + + // Check if the output has enough amount to cover the storage deposit + output.verify_storage_deposit(storage_score_params)?; + // We use excess if leftover is too small, so amount == all available balance + assert_eq!(output.amount(), 18300); + // storage deposit gifted, only address unlock condition + assert_eq!(output.unlock_conditions().unwrap().len(), 1); + + let output = wallet_0 + .prepare_output( + OutputParams { + recipient_address: wallet_1.address().await, + amount: 100, // leave more behind than min. deposit + assets: None, + features: None, + unlocks: None, + storage_deposit: Some(StorageDeposit { + return_strategy: Some(ReturnStrategy::Return), + use_excess_if_low: Some(true), + }), + }, + None, + ) + .await?; + + // Check if the output has enough amount to cover the storage deposit + output.verify_storage_deposit(storage_score_params)?; + // We use excess if leftover is too small, so amount == all available balance + assert_eq!(output.amount(), 18300); + // storage deposit returned, address and SDR unlock condition + assert_eq!(output.unlock_conditions().unwrap().len(), 2); + // We have ReturnStrategy::Return, so leftover amount gets returned + let sdr = output.unlock_conditions().unwrap().storage_deposit_return().unwrap(); + assert_eq!(sdr.amount(), 18300 - 100); + + tear_down(storage_path_0)?; + tear_down(storage_path_1)?; + + Ok(()) +} #[ignore] #[tokio::test] From 4a97d120b3592c0ff7f40938132e710104741019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Tue, 19 Mar 2024 17:25:13 +0100 Subject: [PATCH 05/15] Update failing tests --- bindings/core/tests/combined.rs | 4 ++-- sdk/tests/wallet/transactions.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/bindings/core/tests/combined.rs b/bindings/core/tests/combined.rs index bd71902e31..423f68bff4 100644 --- a/bindings/core/tests/combined.rs +++ b/bindings/core/tests/combined.rs @@ -96,10 +96,10 @@ async fn client_from_wallet() -> Result<(), Error> { .await?; // Send ClientMethod via the client from the wallet - let response = wallet.client().call_method(ClientMethod::GetNodeInfo).await; + let response = wallet.client().call_method(ClientMethod::GetProtocolParameters).await; match response { - Response::NodeInfo(_) => {} + Response::ProtocolParameters(_) => {} _ => panic!("unexpected response {response:?}"), } diff --git a/sdk/tests/wallet/transactions.rs b/sdk/tests/wallet/transactions.rs index e5ea426195..81bd494678 100644 --- a/sdk/tests/wallet/transactions.rs +++ b/sdk/tests/wallet/transactions.rs @@ -6,6 +6,7 @@ use pretty_assertions::assert_eq; use crate::wallet::common::{make_wallet, request_funds, setup, tear_down}; +#[ignore] #[tokio::test] async fn send_amount() -> Result<(), Box> { let storage_path_0 = "test-storage/send_amount_0"; From 121fd07f952c05b9ce2a121e82d6baa519721353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Wed, 20 Mar 2024 09:16:35 +0100 Subject: [PATCH 06/15] Build ledger simulator with default IOTA coin type --- .github/actions/ledger-nano/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/ledger-nano/action.yml b/.github/actions/ledger-nano/action.yml index c9d7775803..f6e0a102d5 100644 --- a/.github/actions/ledger-nano/action.yml +++ b/.github/actions/ledger-nano/action.yml @@ -17,5 +17,5 @@ runs: - name: Run the simulator shell: bash - run: ./build.sh -s -v shimmer -b + run: ./build.sh -s -b working-directory: ledger-iota-app From fcf7a7e01cb1157f8c9a477121e6c75fcc68d1e4 Mon Sep 17 00:00:00 2001 From: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> Date: Wed, 20 Mar 2024 15:37:08 +0100 Subject: [PATCH 07/15] Update sdk/tests/wallet/common/mod.rs Co-authored-by: DaughterOfMars --- sdk/tests/wallet/common/mod.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/sdk/tests/wallet/common/mod.rs b/sdk/tests/wallet/common/mod.rs index 814beaaee8..4e70dfd050 100644 --- a/sdk/tests/wallet/common/mod.rs +++ b/sdk/tests/wallet/common/mod.rs @@ -91,7 +91,8 @@ pub(crate) async fn request_funds(wallet: &Wallet) -> Result<(), Box Result<(), Box Date: Wed, 20 Mar 2024 15:36:58 +0100 Subject: [PATCH 08/15] Review suggestions --- sdk/tests/client/node_api/mod.rs | 4 ++-- sdk/tests/wallet/common/mod.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/tests/client/node_api/mod.rs b/sdk/tests/client/node_api/mod.rs index 70883b2713..31b0304ce2 100644 --- a/sdk/tests/client/node_api/mod.rs +++ b/sdk/tests/client/node_api/mod.rs @@ -30,7 +30,7 @@ use crate::client::common::{setup_client_with_node_health_ignored, FAUCET_URL}; // THIS SEED SERVES FOR TESTING PURPOSES! DON'T USE THIS SEED IN PRODUCTION! const DEFAULT_DEVELOPMENT_SEED: &str = "0x256a818b2aac458941f7274985a410e57fb750f3a3a67969ece5bd9ae7eef5b2"; -// Sends a tagged data block to the node to test against it.* +// Sends a tagged data block to the node to test against it. async fn setup_tagged_data_block() -> Result> { let client = setup_client_with_node_health_ignored().await; @@ -67,7 +67,7 @@ async fn setup_tagged_data_block() -> Result } // Wait until account is read to issue blocks for _ in 0..60 { - if let Ok(_r) = client.get_account_congestion(&account_id, None).await { + if client.get_account_congestion(&account_id, None).await.is_ok() { break; } tokio::time::sleep(std::time::Duration::from_secs(2)).await; diff --git a/sdk/tests/wallet/common/mod.rs b/sdk/tests/wallet/common/mod.rs index 4e70dfd050..7c6cf679e7 100644 --- a/sdk/tests/wallet/common/mod.rs +++ b/sdk/tests/wallet/common/mod.rs @@ -118,7 +118,7 @@ pub(crate) async fn request_funds(wallet: &Wallet) -> Result<(), Box 100 { - panic!("Can't get_account_congestion for implicit account"); + panic!("Can't get account for implicit account"); } } From ce9ca65914a52ce4242f078cc9c37e2112498af5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Wed, 20 Mar 2024 15:41:50 +0100 Subject: [PATCH 09/15] Fix implicit_account break --- sdk/tests/wallet/common/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/tests/wallet/common/mod.rs b/sdk/tests/wallet/common/mod.rs index 7c6cf679e7..dce0bfa0a6 100644 --- a/sdk/tests/wallet/common/mod.rs +++ b/sdk/tests/wallet/common/mod.rs @@ -101,13 +101,13 @@ pub(crate) async fn request_funds(wallet: &Wallet) -> Result<(), Box Date: Wed, 20 Mar 2024 16:39:58 +0100 Subject: [PATCH 10/15] Add and use slots_in_duration() --- sdk/src/types/block/protocol/mod.rs | 6 ++++++ sdk/tests/wallet/claim_outputs.rs | 7 ++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/sdk/src/types/block/protocol/mod.rs b/sdk/src/types/block/protocol/mod.rs index 92757829bf..e4ec1dbf0b 100644 --- a/sdk/src/types/block/protocol/mod.rs +++ b/sdk/src/types/block/protocol/mod.rs @@ -10,6 +10,7 @@ use core::borrow::Borrow; use crypto::hashes::{blake2b::Blake2b256, Digest}; use getset::{CopyGetters, Getters}; +use instant::Duration; use packable::{prefix::StringPrefix, Packable, PackableExt}; #[cfg(feature = "protocol_parameters_samples")] pub use samples::{iota_mainnet_protocol_parameters, shimmer_mainnet_protocol_parameters}; @@ -173,6 +174,11 @@ impl ProtocolParameters { } } + /// Calculates the number of slots in a duration. + pub fn slots_in_duration(&self, duration: Duration) -> u32 { + (duration.as_secs() / self.slot_duration_in_seconds() as u64) as u32 + } + /// Gets the [`EpochIndex`] of a given [`SlotIndex`]. pub fn epoch_index_of(&self, slot_index: impl Into) -> EpochIndex { EpochIndex::from_slot_index(slot_index, self.genesis_slot, self.slots_per_epoch_exponent()) diff --git a/sdk/tests/wallet/claim_outputs.rs b/sdk/tests/wallet/claim_outputs.rs index d6d0bda2fa..8c19b1f836 100644 --- a/sdk/tests/wallet/claim_outputs.rs +++ b/sdk/tests/wallet/claim_outputs.rs @@ -1,6 +1,7 @@ // Copyright 2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 +use instant::Duration; use iota_sdk::{ client::{ api::{options::TransactionOptions, transaction_builder::TransactionBuilderError}, @@ -161,13 +162,13 @@ async fn claim_2_basic_outputs_no_available_in_claim_account() -> Result<(), Box .await?; let storage_score_params = wallet_0.client().get_storage_score_parameters().await?; - let slot_duration_in_seconds = wallet_0 + let slots_in_one_day = wallet_0 .client() .get_protocol_parameters() .await? - .slot_duration_in_seconds(); + .slots_in_duration(Duration::from_secs(86400)); - let expiration_slot = wallet_0.client().get_slot_index().await? + (86400 / slot_duration_in_seconds as u32); + let expiration_slot = wallet_0.client().get_slot_index().await? + slots_in_one_day; let output = BasicOutputBuilder::new_with_minimum_amount(storage_score_params) .add_unlock_condition(AddressUnlockCondition::new(wallet_1.address().await)) From 236de1cf30ed68fee5451f23b8a0c2d222688a43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Wed, 20 Mar 2024 16:46:09 +0100 Subject: [PATCH 11/15] Make instant dep required --- sdk/Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index e66e4a34d1..f1ef155f12 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -37,6 +37,7 @@ hashbrown = { version = "0.14.3", default-features = false, features = [ "inline-more", ] } hex = { version = "0.4.3", default-features = false } +instant = { version = "0.1.12", default-features = false } iota-crypto = { version = "0.23.1", default-features = false, features = [ "blake2b", "ed25519", @@ -66,7 +67,6 @@ fern-logger = { version = "0.5.0", default-features = false, optional = true } futures = { version = "0.3.30", default-features = false, features = [ "thread-pool", ], optional = true } -instant = { version = "0.1.12", default-features = false, optional = true } iota-ledger-nano = { version = "1.0.4-alpha.3", default-features = false, features = [ "nova", ], optional = true } @@ -199,7 +199,6 @@ client = [ "iota-crypto/slip10", "dep:async-trait", "dep:futures", - "dep:instant", "dep:log", "dep:reqwest", "dep:thiserror", From df9da41a712bd9b2df9ee5749d6a9f4ed39ee280 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Thu, 21 Mar 2024 10:09:58 +0100 Subject: [PATCH 12/15] Add and use ProtocolParameters::duration_of_slots() --- sdk/src/types/block/protocol/mod.rs | 5 +++++ sdk/tests/wallet/common/mod.rs | 18 ++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/sdk/src/types/block/protocol/mod.rs b/sdk/src/types/block/protocol/mod.rs index e4ec1dbf0b..8b53b8959b 100644 --- a/sdk/src/types/block/protocol/mod.rs +++ b/sdk/src/types/block/protocol/mod.rs @@ -179,6 +179,11 @@ impl ProtocolParameters { (duration.as_secs() / self.slot_duration_in_seconds() as u64) as u32 } + /// Calculates the [`Duration`] of a number of slots. + pub fn duration_of_slots(&self, slots: u32) -> Duration { + Duration::from_secs((slots * self.slot_duration_in_seconds() as u32) as u64) + } + /// Gets the [`EpochIndex`] of a given [`SlotIndex`]. pub fn epoch_index_of(&self, slot_index: impl Into) -> EpochIndex { EpochIndex::from_slot_index(slot_index, self.genesis_slot, self.slots_per_epoch_exponent()) diff --git a/sdk/tests/wallet/common/mod.rs b/sdk/tests/wallet/common/mod.rs index dce0bfa0a6..b452edce37 100644 --- a/sdk/tests/wallet/common/mod.rs +++ b/sdk/tests/wallet/common/mod.rs @@ -139,21 +139,19 @@ pub(crate) async fn request_funds(wallet: &Wallet) -> Result<(), Box Date: Thu, 21 Mar 2024 10:28:04 +0100 Subject: [PATCH 13/15] no_std --- sdk/Cargo.toml | 3 ++- sdk/src/types/block/protocol/mod.rs | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index f1ef155f12..22699a4911 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -37,7 +37,6 @@ hashbrown = { version = "0.14.3", default-features = false, features = [ "inline-more", ] } hex = { version = "0.4.3", default-features = false } -instant = { version = "0.1.12", default-features = false } iota-crypto = { version = "0.23.1", default-features = false, features = [ "blake2b", "ed25519", @@ -67,6 +66,7 @@ fern-logger = { version = "0.5.0", default-features = false, optional = true } futures = { version = "0.3.30", default-features = false, features = [ "thread-pool", ], optional = true } +instant = { version = "0.1.12", default-features = false, optional = true } iota-ledger-nano = { version = "1.0.4-alpha.3", default-features = false, features = [ "nova", ], optional = true } @@ -176,6 +176,7 @@ std = [ "iota_stronghold?/std", "iota-crypto/std", "once_cell?/std", + "dep:instant" ] storage = ["iota-crypto/chacha", "dep:time", "dep:anymap", "dep:once_cell"] stronghold = [ diff --git a/sdk/src/types/block/protocol/mod.rs b/sdk/src/types/block/protocol/mod.rs index 8b53b8959b..d6f5ea9140 100644 --- a/sdk/src/types/block/protocol/mod.rs +++ b/sdk/src/types/block/protocol/mod.rs @@ -10,6 +10,7 @@ use core::borrow::Borrow; use crypto::hashes::{blake2b::Blake2b256, Digest}; use getset::{CopyGetters, Getters}; +#[cfg(feature = "std")] use instant::Duration; use packable::{prefix::StringPrefix, Packable, PackableExt}; #[cfg(feature = "protocol_parameters_samples")] @@ -174,11 +175,13 @@ impl ProtocolParameters { } } + #[cfg(feature = "std")] /// Calculates the number of slots in a duration. pub fn slots_in_duration(&self, duration: Duration) -> u32 { (duration.as_secs() / self.slot_duration_in_seconds() as u64) as u32 } + #[cfg(feature = "std")] /// Calculates the [`Duration`] of a number of slots. pub fn duration_of_slots(&self, slots: u32) -> Duration { Duration::from_secs((slots * self.slot_duration_in_seconds() as u32) as u64) From 19ab6c00eb3dc673e6566d145b26da05864cf05e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Thu, 21 Mar 2024 18:17:26 +0100 Subject: [PATCH 14/15] comment before attribute, allow_additional_input_selection for consolidation since we need mana --- sdk/src/types/block/protocol/mod.rs | 4 ++-- sdk/src/wallet/operations/output_consolidation.rs | 1 - sdk/tests/wallet/consolidation.rs | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/sdk/src/types/block/protocol/mod.rs b/sdk/src/types/block/protocol/mod.rs index d6f5ea9140..94b9054132 100644 --- a/sdk/src/types/block/protocol/mod.rs +++ b/sdk/src/types/block/protocol/mod.rs @@ -175,14 +175,14 @@ impl ProtocolParameters { } } - #[cfg(feature = "std")] /// Calculates the number of slots in a duration. + #[cfg(feature = "std")] pub fn slots_in_duration(&self, duration: Duration) -> u32 { (duration.as_secs() / self.slot_duration_in_seconds() as u64) as u32 } - #[cfg(feature = "std")] /// Calculates the [`Duration`] of a number of slots. + #[cfg(feature = "std")] pub fn duration_of_slots(&self, slots: u32) -> Duration { Duration::from_secs((slots * self.slot_duration_in_seconds() as u32) as u64) } diff --git a/sdk/src/wallet/operations/output_consolidation.rs b/sdk/src/wallet/operations/output_consolidation.rs index 16e8d2332f..3210361b0b 100644 --- a/sdk/src/wallet/operations/output_consolidation.rs +++ b/sdk/src/wallet/operations/output_consolidation.rs @@ -116,7 +116,6 @@ where .map(|bech32| bech32.into_inner()) .unwrap_or_else(|| wallet_address.into_inner()), ), - allow_additional_input_selection: false, ..Default::default() }); diff --git a/sdk/tests/wallet/consolidation.rs b/sdk/tests/wallet/consolidation.rs index 900894b958..eb85b09afa 100644 --- a/sdk/tests/wallet/consolidation.rs +++ b/sdk/tests/wallet/consolidation.rs @@ -44,8 +44,8 @@ async fn consolidation() -> Result<(), Box> { let balance = wallet_1.sync(None).await.unwrap(); // Balance still the same assert_eq!(balance.base_coin().available(), 2009968300); - // Account and basic unspent output - assert_eq!(wallet_1.ledger().await.unspent_outputs().len(), 2); + // Account output + assert_eq!(wallet_1.ledger().await.unspent_outputs().len(), 1); tear_down(storage_path_0)?; tear_down(storage_path_1)?; From 50bfb18827b6eb598b9c17532df25da90b18d1ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thoralf=20M=C3=BCller?= Date: Thu, 21 Mar 2024 22:21:40 +0100 Subject: [PATCH 15/15] Fix inputs ordering --- .../api/block_builder/transaction_builder/mod.rs | 7 ++++--- .../api/block_builder/transaction_builder/remainder.rs | 2 +- sdk/tests/wallet/burn_outputs.rs | 10 ---------- 3 files changed, 5 insertions(+), 14 deletions(-) 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 ea26d99a5f..d3f8c7ea73 100644 --- a/sdk/src/client/api/block_builder/transaction_builder/mod.rs +++ b/sdk/src/client/api/block_builder/transaction_builder/mod.rs @@ -449,8 +449,9 @@ impl TransactionBuilder { return Err(TransactionBuilderError::InvalidOutputCount(outputs.len())); } + let inputs_data: Vec = self.selected_inputs.into_sorted_iter().collect(); for output_id in self.mana_rewards.keys() { - if !self.selected_inputs.iter().any(|i| output_id == i.output_id()) { + if !inputs_data.iter().any(|i| output_id == i.output_id()) { return Err(TransactionBuilderError::ExtraManaRewards(*output_id)); } } @@ -463,7 +464,7 @@ impl TransactionBuilder { .chain(self.commitment_context_input.map(ContextInput::from)) .collect::>(); - for (idx, input) in self.selected_inputs.iter().enumerate() { + for (idx, input) in inputs_data.iter().enumerate() { inputs.push(Input::Utxo(UtxoInput::from(*input.output_id()))); if self.reward_context_inputs.contains(input.output_id()) { context_inputs.push(RewardContextInput::new(idx as u16).unwrap().into()); @@ -494,7 +495,7 @@ impl TransactionBuilder { let data = PreparedTransactionData { transaction, - inputs_data: self.selected_inputs.into_sorted_iter().collect(), + inputs_data, remainders: self.remainders.data, mana_rewards: self.mana_rewards.into_iter().collect(), }; 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 de55b5ffc7..04fadac54f 100644 --- a/sdk/src/client/api/block_builder/transaction_builder/remainder.rs +++ b/sdk/src/client/api/block_builder/transaction_builder/remainder.rs @@ -293,7 +293,7 @@ impl TransactionBuilder { self.remainders.data.push(RemainderData { output: catchall, chain: remainder_address_chain, - address: remainder_address.clone(), + address: remainder_address, }); Ok(()) diff --git a/sdk/tests/wallet/burn_outputs.rs b/sdk/tests/wallet/burn_outputs.rs index 796bf4e38a..722eb77105 100644 --- a/sdk/tests/wallet/burn_outputs.rs +++ b/sdk/tests/wallet/burn_outputs.rs @@ -227,16 +227,6 @@ async fn destroy_account(wallet: &Wallet, account_id: AccountId) -> Result<(), B #[ignore] #[tokio::test] async fn create_and_burn_native_tokens() -> Result<(), Box> { - let logger_output_config = fern_logger::LoggerOutputConfigBuilder::new() - .name("client.log") - .target_exclusions(&["h2", "hyper", "rustls"]) - .level_filter(log::LevelFilter::Debug); - - let config = fern_logger::LoggerConfig::build() - .with_output(logger_output_config) - .finish(); - - fern_logger::logger_init(config).unwrap(); let storage_path = "test-storage/create_and_burn_native_tokens"; setup(storage_path)?;