From 0694acfa2258fe3c28de2b88ea9c1a911de35051 Mon Sep 17 00:00:00 2001 From: Rajiv Shah Date: Wed, 17 Apr 2024 03:45:50 -0400 Subject: [PATCH 1/6] Use `gon` fork for notarizing macOS Node.js bindings (#2226) --- .github/workflows/bindings-nodejs-publish.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/bindings-nodejs-publish.yml b/.github/workflows/bindings-nodejs-publish.yml index 9abd347682..ecc0e4d7c1 100644 --- a/.github/workflows/bindings-nodejs-publish.yml +++ b/.github/workflows/bindings-nodejs-publish.yml @@ -113,9 +113,14 @@ jobs: run: echo "LIBCLANG_PATH=$((gcm clang).source -replace "clang.exe")" >> $env:GITHUB_ENV - name: Install gon (macOS) + # Fork of https://github.com/mitchellh/gon + # https://github.com/Bearer/gon + # Since we're dealing with code signing secrets we want to pin the version of gon if: ${{ startsWith(matrix.os, 'macos') }} - # https://github.com/mitchellh/gon - run: brew install mitchellh/gon/gon + run: | + wget https://raw.githubusercontent.com/Bearer/homebrew-tap/366bc999e14a8d04e07e24f9387bcbaf89c1bc53/Formula/gon.rb + brew install --formula gon.rb + rm gon.rb - name: Set deployment target (macOS) if: matrix.os == 'macos-13' From 6ba24703b3accc0044718d21ffbd02922f485bca Mon Sep 17 00:00:00 2001 From: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> Date: Wed, 17 Apr 2024 15:28:26 +0200 Subject: [PATCH 2/6] Bump nodejs version, add alpha tag for wasm releases (#2227) * Bump nodejs version, add alpha tag for wasm releases * format * Fix nodejs build on windows --- .github/workflows/bindings-wasm-publish.yml | 2 +- bindings/nodejs/CHANGELOG.md | 6 ++++++ bindings/nodejs/package.json | 2 +- bindings/nodejs/scripts/build.js | 1 + 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/bindings-wasm-publish.yml b/.github/workflows/bindings-wasm-publish.yml index f497331257..9c2e1a1689 100644 --- a/.github/workflows/bindings-wasm-publish.yml +++ b/.github/workflows/bindings-wasm-publish.yml @@ -46,7 +46,7 @@ jobs: shell: sh env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} - run: yarn publish --access public + run: yarn publish --access public --tag alpha - name: Prepare Github release id: prepare_release diff --git a/bindings/nodejs/CHANGELOG.md b/bindings/nodejs/CHANGELOG.md index 4caa5bb962..55f2b6cf25 100644 --- a/bindings/nodejs/CHANGELOG.md +++ b/bindings/nodejs/CHANGELOG.md @@ -19,6 +19,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Security --> +## 2.0.0-alpha.6 - 2024-04-17 + +### Fixed + +- MacOS binary build; + ## 2.0.0-alpha.5 - 2024-04-15 ### Added diff --git a/bindings/nodejs/package.json b/bindings/nodejs/package.json index a1d772639f..0fdaca0f3d 100644 --- a/bindings/nodejs/package.json +++ b/bindings/nodejs/package.json @@ -1,6 +1,6 @@ { "name": "@iota/sdk", - "version": "2.0.0-alpha.5", + "version": "2.0.0-alpha.6", "description": "Node.js binding to the IOTA SDK library", "main": "out/index.js", "types": "out/index.d.ts", diff --git a/bindings/nodejs/scripts/build.js b/bindings/nodejs/scripts/build.js index 6397cb0966..2216789111 100644 --- a/bindings/nodejs/scripts/build.js +++ b/bindings/nodejs/scripts/build.js @@ -6,6 +6,7 @@ const { spawnSync } = require('child_process'); const { status } = spawnSync(process.platform === 'win32' ? 'yarn.cmd' : 'yarn', ['build'], { stdio: 'inherit', cwd: resolve(__dirname, '../'), + shell: true }); if (status === null) { From 57a898984c6ab1ba06929b2b94ea7bc08bb1b694 Mon Sep 17 00:00:00 2001 From: Rajiv Shah Date: Wed, 17 Apr 2024 12:21:02 -0400 Subject: [PATCH 3/6] chore: Fix gon config for Node.js bindings (#2228) --- bindings/nodejs/gon-config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/nodejs/gon-config.json b/bindings/nodejs/gon-config.json index 4f46ea1456..1a21e2764c 100644 --- a/bindings/nodejs/gon-config.json +++ b/bindings/nodejs/gon-config.json @@ -2,7 +2,7 @@ "source": ["./build/Release/index.node"], "bundle_id": "org.iota.sdk-nodejs", "apple_id": { - "password": "@env:AC_PASSWORD" + "provider": "UG77RJKZHH" }, "sign": { "application_identity": "Developer ID Application: IOTA Stiftung (UG77RJKZHH)" From b2deb0395aaadbdc1a394b9bca69c92906050011 Mon Sep 17 00:00:00 2001 From: Thibault Martinez Date: Thu, 18 Apr 2024 12:01:22 +0200 Subject: [PATCH 4/6] Add softprops target_commitish (#2229) --- .github/workflows/bindings-nodejs-publish.yml | 1 + .github/workflows/bindings-python-publish.yml | 1 + .github/workflows/bindings-wasm-publish.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/bindings-nodejs-publish.yml b/.github/workflows/bindings-nodejs-publish.yml index ecc0e4d7c1..2234cc056d 100644 --- a/.github/workflows/bindings-nodejs-publish.yml +++ b/.github/workflows/bindings-nodejs-publish.yml @@ -263,3 +263,4 @@ jobs: body: https://github.com/iotaledger/iota-sdk/blob/develop/bindings/nodejs/CHANGELOG.md files: bindings/nodejs/prebuilds/@iota/* tag_name: ${{ steps.prepare_release.outputs.tag_name }} + target_commitish: ${{ github.sha }} diff --git a/.github/workflows/bindings-python-publish.yml b/.github/workflows/bindings-python-publish.yml index 91f5c56352..676d51acae 100644 --- a/.github/workflows/bindings-python-publish.yml +++ b/.github/workflows/bindings-python-publish.yml @@ -162,6 +162,7 @@ jobs: body: https://github.com/iotaledger/iota-sdk/blob/develop/bindings/python/CHANGELOG.md files: wheels/* tag_name: ${{ steps.tagname.outputs.TAG_NAME }} + target_commitish: ${{ github.sha }} - uses: actions/setup-python@v4 with: diff --git a/.github/workflows/bindings-wasm-publish.yml b/.github/workflows/bindings-wasm-publish.yml index 9c2e1a1689..49cc985c46 100644 --- a/.github/workflows/bindings-wasm-publish.yml +++ b/.github/workflows/bindings-wasm-publish.yml @@ -62,3 +62,4 @@ jobs: body: "https://github.com/iotaledger/iota-sdk/blob/develop/bindings/wasm/CHANGELOG.md \n https://github.com/iotaledger/iota-sdk/blob/develop/bindings/nodejs/CHANGELOG.md" files: bindings/wasm/*.tgz tag_name: ${{ steps.prepare_release.outputs.tag_name }} + target_commitish: ${{ github.sha }} From d4dab359a83b1513aba847a1249cc76b0eb4edce Mon Sep 17 00:00:00 2001 From: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> Date: Fri, 19 Apr 2024 12:33:55 +0200 Subject: [PATCH 5/6] Fix mana allotment when burning something/setting a TransactionCapabilityFlag (#2231) --- bindings/nodejs/CHANGELOG.md | 6 + bindings/nodejs/package.json | 2 +- bindings/wasm/CHANGELOG.md | 4 + bindings/wasm/package.json | 2 +- .../transaction_builder/requirement/mana.rs | 1 + sdk/tests/client/transaction_builder/burn.rs | 109 +++++++++++++++++- 6 files changed, 119 insertions(+), 5 deletions(-) diff --git a/bindings/nodejs/CHANGELOG.md b/bindings/nodejs/CHANGELOG.md index 55f2b6cf25..8622494683 100644 --- a/bindings/nodejs/CHANGELOG.md +++ b/bindings/nodejs/CHANGELOG.md @@ -19,6 +19,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Security --> +## 2.0.0-alpha.7 - 2024-04-19 + +### Fixed + +- Mana allotment when burning something/setting a TransactionCapabilityFlag; + ## 2.0.0-alpha.6 - 2024-04-17 ### Fixed diff --git a/bindings/nodejs/package.json b/bindings/nodejs/package.json index 0fdaca0f3d..cb52f6f006 100644 --- a/bindings/nodejs/package.json +++ b/bindings/nodejs/package.json @@ -1,6 +1,6 @@ { "name": "@iota/sdk", - "version": "2.0.0-alpha.6", + "version": "2.0.0-alpha.7", "description": "Node.js binding to the IOTA SDK library", "main": "out/index.js", "types": "out/index.d.ts", diff --git a/bindings/wasm/CHANGELOG.md b/bindings/wasm/CHANGELOG.md index 9b8bdc0022..9bf7b71336 100644 --- a/bindings/wasm/CHANGELOG.md +++ b/bindings/wasm/CHANGELOG.md @@ -19,6 +19,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Security --> +## 2.0.0-alpha.3 - 2024-04-19 + +Same changes as https://github.com/iotaledger/iota-sdk/blob/2.0/bindings/nodejs/CHANGELOG.md. + ## 2.0.0-alpha.2 - 2024-04-02 Same changes as https://github.com/iotaledger/iota-sdk/blob/2.0/bindings/nodejs/CHANGELOG.md. diff --git a/bindings/wasm/package.json b/bindings/wasm/package.json index 696f67687a..6f57fe61b7 100644 --- a/bindings/wasm/package.json +++ b/bindings/wasm/package.json @@ -1,6 +1,6 @@ { "name": "@iota/sdk-wasm", - "version": "2.0.0-alpha.2", + "version": "2.0.0-alpha.3", "description": "WebAssembly bindings for the IOTA SDK library", "repository": { "type": "git", 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 6aec255ce6..58e75b8aeb 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 @@ -113,6 +113,7 @@ impl TransactionBuilder { .iter() .map(|(&account_id, &mana)| ManaAllotment { account_id, mana }), ) + .with_capabilities(self.transaction_capabilities.clone()) .finish_with_params(&self.protocol_parameters)?; let signed_transaction = SignedTransactionPayload::new(transaction, self.null_transaction_unlocks()?)?; diff --git a/sdk/tests/client/transaction_builder/burn.rs b/sdk/tests/client/transaction_builder/burn.rs index 56d6c47542..165cf5f141 100644 --- a/sdk/tests/client/transaction_builder/burn.rs +++ b/sdk/tests/client/transaction_builder/burn.rs @@ -6,21 +6,32 @@ use std::{ str::FromStr, }; +use crypto::keys::bip44::Bip44; use iota_sdk::{ client::{ - api::transaction_builder::{Burn, Requirement, TransactionBuilder, TransactionBuilderError}, - secret::types::InputSigningData, + api::{ + transaction_builder::{Burn, Requirement, TransactionBuilder, TransactionBuilderError}, + GetAddressesOptions, + }, + constants::SHIMMER_COIN_TYPE, + secret::{types::InputSigningData, SecretManage, SecretManager}, + Client, }, types::block::{ address::Address, + core::basic::StrongParents, output::{ unlock_condition::AddressUnlockCondition, AccountId, AccountOutputBuilder, BasicOutputBuilder, ChainId, NftId, SimpleTokenScheme, TokenId, }, - payload::signed_transaction::{TransactionCapabilities, TransactionCapabilityFlag}, + payload::{ + signed_transaction::{TransactionCapabilities, TransactionCapabilityFlag}, + Payload, SignedTransactionPayload, + }, protocol::iota_mainnet_protocol_parameters, rand::output::{rand_output_id_with_slot_index, rand_output_metadata_with_id}, slot::SlotIndex, + BlockBody, BlockId, }, }; use pretty_assertions::assert_eq; @@ -771,6 +782,98 @@ fn burn_nfts_present() { assert!(unsorted_eq(selected.transaction.outputs(), &outputs)); } +#[tokio::test] +async fn burn_nft_correct_mana_allotment() { + let secret_manager = SecretManager::try_from_mnemonic(Client::generate_mnemonic().unwrap()).unwrap(); + + let ed25519_address = secret_manager + .generate_ed25519_addresses(GetAddressesOptions::default().with_range(0..1)) + .await + .unwrap()[0] + .clone() + .into_inner(); + + let protocol_parameters = iota_mainnet_protocol_parameters(); + let account_id_1 = AccountId::from_str(ACCOUNT_ID_1).unwrap(); + let nft_id_1 = NftId::from_str(NFT_ID_1).unwrap(); + let reference_mana_cost = 1; + + let inputs = build_inputs( + [( + Nft { + amount: 1_000_000, + mana: 1_000_000, + nft_id: nft_id_1, + address: ed25519_address.clone(), + sender: None, + issuer: None, + sdruc: None, + expiration: None, + }, + Some(Bip44::new(SHIMMER_COIN_TYPE)), + )], + Some(SLOT_INDEX), + ); + + let selected = TransactionBuilder::new( + inputs.clone(), + [], + [ed25519_address], + SLOT_INDEX, + SLOT_COMMITMENT_ID, + protocol_parameters.clone(), + ) + .with_burn(Burn::new().set_nfts(HashSet::from([nft_id_1]))) + .with_min_mana_allotment(account_id_1, reference_mana_cost) + .finish() + .unwrap(); + + assert_eq!( + selected.transaction.capabilities(), + &TransactionCapabilities::from([TransactionCapabilityFlag::DestroyNftOutputs]) + ); + assert!(unsorted_eq(&selected.inputs_data, &inputs)); + + let inputs = selected + .inputs_data + .iter() + .map(|input| (input.output_id(), &input.output)) + .collect::>(); + + iota_sdk::types::block::semantic::SemanticValidationContext::new( + &selected.transaction, + &inputs, + None, + None, + &protocol_parameters, + ) + .validate() + .unwrap(); + + assert_eq!(selected.transaction.outputs().len(), 1); + + let unlocks = secret_manager + .transaction_unlocks(&selected, &protocol_parameters) + .await + .unwrap(); + + let signed_transaction_payload = SignedTransactionPayload::new(selected.transaction.clone(), unlocks).unwrap(); + + let basic_block_body = BlockBody::build_basic( + StrongParents::from_vec(vec![BlockId::new([0; 36])]).unwrap(), + (protocol_parameters.work_score_parameters(), reference_mana_cost), + ) + .with_payload(Payload::from(signed_transaction_payload)) + .finish() + .unwrap(); + + assert_eq!(selected.transaction.allotments().len(), 1); + assert_eq!( + selected.transaction.allotments().first().unwrap().mana(), + basic_block_body.max_burned_mana(), + ); +} + #[test] fn burn_nft_in_outputs() { let protocol_parameters = iota_mainnet_protocol_parameters().clone(); From 48126d222d5ae116fc4720b4348ac9a9ab65118a Mon Sep 17 00:00:00 2001 From: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> Date: Fri, 19 Apr 2024 14:57:32 +0200 Subject: [PATCH 6/6] Fix stronghold backup/restore (#2233) * Fix stronghold backup/restore * Update bindings/nodejs/CHANGELOG.md --- bindings/nodejs/CHANGELOG.md | 1 + .../stronghold_backup/stronghold_snapshot.rs | 9 +- sdk/tests/wallet/backup_restore.rs | 255 +++++++++--------- 3 files changed, 136 insertions(+), 129 deletions(-) diff --git a/bindings/nodejs/CHANGELOG.md b/bindings/nodejs/CHANGELOG.md index 8622494683..5bece978d6 100644 --- a/bindings/nodejs/CHANGELOG.md +++ b/bindings/nodejs/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Mana allotment when burning something/setting a TransactionCapabilityFlag; +- Stronghold backup/restore; ## 2.0.0-alpha.6 - 2024-04-17 diff --git a/sdk/src/wallet/core/operations/stronghold_backup/stronghold_snapshot.rs b/sdk/src/wallet/core/operations/stronghold_backup/stronghold_snapshot.rs index 0be48f2efe..0bc6a88e2a 100644 --- a/sdk/src/wallet/core/operations/stronghold_backup/stronghold_snapshot.rs +++ b/sdk/src/wallet/core/operations/stronghold_backup/stronghold_snapshot.rs @@ -41,15 +41,15 @@ impl Wallet { } // Store the wallet address - stronghold - .set(WALLET_ADDRESS_KEY, self.address().await.as_ref()) - .await?; + stronghold.set(WALLET_ADDRESS_KEY, &self.address().await).await?; // Store the wallet bip path stronghold.set(WALLET_BIP_PATH_KEY, &self.bip_path().await).await?; // Store the wallet alias - stronghold.set(WALLET_ALIAS_KEY, &self.alias().await).await?; + if let Some(alias) = self.alias().await { + stronghold.set(WALLET_ALIAS_KEY, &alias).await?; + } let serialized_wallet_ledger = serde_json::to_value(&WalletLedgerDto::from(&*self.ledger.read().await))?; stronghold.set(WALLET_LEDGER_KEY, &serialized_wallet_ledger).await?; @@ -71,6 +71,7 @@ pub(crate) async fn read_fields_from_stronghold_snapshot { + log::debug!("[read_fields_from_stronghold_snapshot]"); migrate(stronghold).await?; // Get client_options diff --git a/sdk/tests/wallet/backup_restore.rs b/sdk/tests/wallet/backup_restore.rs index 779c7a41d2..663acd7744 100644 --- a/sdk/tests/wallet/backup_restore.rs +++ b/sdk/tests/wallet/backup_restore.rs @@ -1,130 +1,135 @@ -// Copyright 2022 IOTA Stiftung +// Copyright 2022-2024 IOTA Stiftung // SPDX-License-Identifier: Apache-2.0 -// use std::path::PathBuf; - -// use crypto::keys::bip39::Mnemonic; -// use iota_sdk::{ -// client::{ -// api::GetAddressesOptions, -// constants::{IOTA_COIN_TYPE, SHIMMER_COIN_TYPE}, -// node_manager::node::{Node, NodeDto}, -// secret::{mnemonic::MnemonicSecretManager, stronghold::StrongholdSecretManager, SecretManager}, -// }, -// crypto::keys::bip44::Bip44, -// wallet::{ClientOptions, Result, Wallet}, -// }; -// use pretty_assertions::assert_eq; -// use url::Url; - -// use crate::wallet::common::{setup, tear_down, NODE_LOCAL, NODE_OTHER}; - -// // Backup and restore with Stronghold -// #[tokio::test] -// async fn backup_and_restore() -> Result<(), WalletError> { -// iota_stronghold::engine::snapshot::try_set_encrypt_work_factor(0).unwrap(); - -// let storage_path = "test-storage/backup_and_restore"; -// setup(storage_path)?; - -// let client_options = ClientOptions::new().with_node(NODE_LOCAL)?; - -// let stronghold_password = "some_hopefully_secure_password".to_owned(); - -// // Create directory if not existing, because stronghold panics otherwise -// std::fs::create_dir_all(storage_path).ok(); -// let stronghold = StrongholdSecretManager::builder() -// .password(stronghold_password.clone()) -// .build("test-storage/backup_and_restore/1.stronghold")?; - -// stronghold.store_mnemonic(Mnemonic::from("inhale gorilla deny three celery song category owner lottery rent author wealth penalty crawl hobby obtain glad warm early rain clutch slab august bleak".to_string())).await.unwrap(); - -// let wallet = Wallet::builder() -// .with_secret_manager(SecretManager::Stronghold(stronghold)) -// .with_client_options(client_options.clone()) -// .with_bip_path(Bip44::new(SHIMMER_COIN_TYPE)) -// .with_storage_path("test-storage/backup_and_restore/1") -// .finish() -// .await?; - -// wallet -// .backup( -// PathBuf::from("test-storage/backup_and_restore/backup.stronghold"), -// stronghold_password.clone(), -// ) -// .await?; - -// // restore from backup - -// let stronghold = StrongholdSecretManager::builder().build("test-storage/backup_and_restore/2.stronghold")?; - -// let restored_wallet = Wallet::builder() -// .with_storage_path("test-storage/backup_and_restore/2") -// .with_secret_manager(SecretManager::Stronghold(stronghold)) -// .with_client_options(ClientOptions::new().with_node(NODE_OTHER)?) -// // Build with a different coin type, to check if it gets replaced by the one from the backup -// .with_bip_path(Bip44::new(IOTA_COIN_TYPE)) -// .finish() -// .await?; - -// // Wrong password fails -// restored_wallet -// .restore_backup( -// PathBuf::from("test-storage/backup_and_restore/backup.stronghold"), -// "wrong password".to_owned(), -// None, -// None, -// ) -// .await -// .unwrap_err(); - -// // Correct password works, even after trying with a wrong one before -// restored_wallet -// .restore_backup( -// PathBuf::from("test-storage/backup_and_restore/backup.stronghold"), -// stronghold_password, -// None, -// None, -// ) -// .await?; - -// // Validate restored data - -// // Restored coin type is used -// assert_eq!(restored_wallet.bip_path().await.unwrap().coin_type, SHIMMER_COIN_TYPE); - -// // compare restored client options -// let client_options = restored_wallet.client_options().await; -// let node_dto = NodeDto::Node(Node::from(Url::parse(NODE_LOCAL).unwrap())); -// assert!(client_options.node_manager_builder.nodes.contains(&node_dto)); - -// assert_eq!(wallet.address().clone(), restored_wallet.address().clone()); - -// // secret manager is the same -// assert_eq!( -// wallet -// .get_secret_manager() -// .read() -// .await -// .generate_ed25519_addresses(GetAddressesOptions { -// coin_type: SHIMMER_COIN_TYPE, -// range: 0..1, -// ..Default::default() -// }) -// .await?, -// restored_wallet -// .get_secret_manager() -// .read() -// .await -// .generate_ed25519_addresses(GetAddressesOptions { -// coin_type: SHIMMER_COIN_TYPE, -// range: 0..1, -// ..Default::default() -// }) -// .await?, -// ); -// tear_down(storage_path) -// } +use std::path::PathBuf; + +use crypto::keys::bip39::Mnemonic; +use iota_sdk::{ + client::{ + api::GetAddressesOptions, + constants::{IOTA_COIN_TYPE, SHIMMER_COIN_TYPE}, + node_manager::node::{Node, NodeDto}, + secret::{stronghold::StrongholdSecretManager, SecretManager}, + }, + crypto::keys::bip44::Bip44, + wallet::{ClientOptions, Wallet}, +}; +use pretty_assertions::assert_eq; +use url::Url; + +use crate::wallet::common::{setup, tear_down, NODE_LOCAL}; + +// Backup and restore with Stronghold +#[ignore] +#[tokio::test] +async fn backup_and_restore() -> Result<(), Box> { + iota_stronghold::engine::snapshot::try_set_encrypt_work_factor(0).unwrap(); + + let storage_path = "test-storage/backup_and_restore"; + setup(storage_path)?; + + let client_options = ClientOptions::new().with_node(NODE_LOCAL)?; + + let stronghold_password = "some_hopefully_secure_password".to_owned(); + + // Create directory if not existing, because stronghold panics otherwise + std::fs::create_dir_all(storage_path).ok(); + let stronghold = StrongholdSecretManager::builder() + .password(stronghold_password.clone()) + .build("test-storage/backup_and_restore/1.stronghold")?; + + stronghold.store_mnemonic(Mnemonic::from("inhale gorilla deny three celery song category owner lottery rent author wealth penalty crawl hobby obtain glad warm early rain clutch slab august bleak".to_string())).await.unwrap(); + + let wallet = Wallet::builder() + .with_secret_manager(SecretManager::Stronghold(stronghold)) + .with_client_options(client_options.clone()) + .with_bip_path(Bip44::new(SHIMMER_COIN_TYPE)) + .with_storage_path("test-storage/backup_and_restore/1") + .finish() + .await?; + + wallet + .backup_to_stronghold_snapshot( + PathBuf::from("test-storage/backup_and_restore/backup.stronghold"), + stronghold_password.clone(), + ) + .await?; + + // restore from backup + + let stronghold = StrongholdSecretManager::builder() + .password(stronghold_password.clone()) + .build("test-storage/backup_and_restore/2.stronghold")?; + + stronghold.store_mnemonic(Mnemonic::from("surprise own liquid gold embrace indoor cereal magnet wink purse similar unusual setup woman catch chuckle critic wet weasel ahead wasp cruise luggage pig".to_string())).await.unwrap(); + + let restored_wallet = Wallet::builder() + .with_storage_path("test-storage/backup_and_restore/2") + .with_secret_manager(SecretManager::Stronghold(stronghold)) + .with_client_options(ClientOptions::new().with_ignore_node_health().with_node(NODE_LOCAL)?) + // Build with a different coin type, to check if it gets replaced by the one from the backup + .with_bip_path(Bip44::new(IOTA_COIN_TYPE)) + .finish() + .await?; + + // Wrong password fails + restored_wallet + .restore_from_stronghold_snapshot( + PathBuf::from("test-storage/backup_and_restore/backup.stronghold"), + "wrong password".to_owned(), + None, + None, + ) + .await + .unwrap_err(); + + // Correct password works, even after trying with a wrong one before + restored_wallet + .restore_from_stronghold_snapshot( + PathBuf::from("test-storage/backup_and_restore/backup.stronghold"), + stronghold_password, + None, + None, + ) + .await?; + + // Validate restored data + + // Restored coin type is used + assert_eq!(restored_wallet.bip_path().await.unwrap().coin_type, SHIMMER_COIN_TYPE); + + // compare restored client options + let client_options = restored_wallet.client_options().await; + let node_dto = NodeDto::Node(Node::from(Url::parse(NODE_LOCAL).unwrap())); + assert!(client_options.node_manager_builder.nodes.contains(&node_dto)); + + assert_eq!(wallet.address().await.clone(), restored_wallet.address().await.clone()); + + // secret manager is the same + assert_eq!( + wallet + .secret_manager() + .read() + .await + .generate_ed25519_addresses(GetAddressesOptions { + coin_type: SHIMMER_COIN_TYPE, + range: 0..1, + ..Default::default() + }) + .await?, + restored_wallet + .secret_manager() + .read() + .await + .generate_ed25519_addresses(GetAddressesOptions { + coin_type: SHIMMER_COIN_TYPE, + range: 0..1, + ..Default::default() + }) + .await?, + ); + tear_down(storage_path) +} // // Backup and restore with Stronghold and MnemonicSecretManager // #[tokio::test]