From 6696bfdff2f2a2e38d37b816c1dba792dca39624 Mon Sep 17 00:00:00 2001 From: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> Date: Thu, 2 May 2024 14:42:04 +0200 Subject: [PATCH] Add tx options param to prepare_claim_outputs() (#2237) * Add tx options param to prepare_claim_outputs() * Add new param * Bump version and set release data --- bindings/core/src/method/wallet.rs | 6 ++- bindings/core/src/method_handler/wallet.rs | 7 +++- bindings/nodejs/CHANGELOG.md | 6 +++ .../nodejs/lib/types/wallet/bridge/wallet.ts | 1 + bindings/nodejs/lib/wallet/wallet.ts | 7 +++- bindings/nodejs/package.json | 2 +- bindings/python/iota_sdk/wallet/wallet.py | 9 +++-- cli/src/wallet_cli/mod.rs | 4 +- .../claim_transaction.rs | 2 +- sdk/src/wallet/operations/output_claiming.rs | 37 +++++++++++++------ .../operations/transaction/prepare_output.rs | 2 +- sdk/tests/wallet/claim_outputs.rs | 22 +++++++---- 12 files changed, 72 insertions(+), 33 deletions(-) diff --git a/bindings/core/src/method/wallet.rs b/bindings/core/src/method/wallet.rs index eea0c5685d..8542fb0de6 100644 --- a/bindings/core/src/method/wallet.rs +++ b/bindings/core/src/method/wallet.rs @@ -226,7 +226,11 @@ pub enum WalletMethod { /// Claim outputs. /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) #[serde(rename_all = "camelCase")] - PrepareClaimOutputs { output_ids_to_claim: Vec }, + PrepareClaimOutputs { + output_ids_to_claim: Vec, + #[serde(default)] + options: Option, + }, /// Consolidate outputs. /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) PrepareConsolidateOutputs { params: ConsolidationParams }, diff --git a/bindings/core/src/method_handler/wallet.rs b/bindings/core/src/method_handler/wallet.rs index cc7086f978..47631b2f91 100644 --- a/bindings/core/src/method_handler/wallet.rs +++ b/bindings/core/src/method_handler/wallet.rs @@ -234,8 +234,11 @@ pub(crate) async fn call_wallet_method_internal( let data = wallet.prepare_burn(burn, options).await?; Response::PreparedTransaction(data) } - WalletMethod::PrepareClaimOutputs { output_ids_to_claim } => { - let data = wallet.prepare_claim_outputs(output_ids_to_claim).await?; + WalletMethod::PrepareClaimOutputs { + output_ids_to_claim, + options, + } => { + let data = wallet.prepare_claim_outputs(output_ids_to_claim, options).await?; Response::PreparedTransaction(data) } WalletMethod::PrepareConsolidateOutputs { params } => { diff --git a/bindings/nodejs/CHANGELOG.md b/bindings/nodejs/CHANGELOG.md index 1f095c9b70..59200f3240 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.9 - 2024-05-02 + +### Added + +- `Wallet::prepareClaimOutputs()` optional transactionOptions parameter; + ## 2.0.0-alpha.8 - 2024-04-22 ### Fixed diff --git a/bindings/nodejs/lib/types/wallet/bridge/wallet.ts b/bindings/nodejs/lib/types/wallet/bridge/wallet.ts index f6718b6b15..192458af2f 100644 --- a/bindings/nodejs/lib/types/wallet/bridge/wallet.ts +++ b/bindings/nodejs/lib/types/wallet/bridge/wallet.ts @@ -153,6 +153,7 @@ export type __PrepareClaimOutputsMethod__ = { name: 'prepareClaimOutputs'; data: { outputIdsToClaim: OutputId[]; + options?: TransactionOptions; }; }; diff --git a/bindings/nodejs/lib/wallet/wallet.ts b/bindings/nodejs/lib/wallet/wallet.ts index 8f5f33e3dd..e063712c68 100644 --- a/bindings/nodejs/lib/wallet/wallet.ts +++ b/bindings/nodejs/lib/wallet/wallet.ts @@ -419,8 +419,11 @@ export class Wallet { */ async claimOutputs( outputIds: OutputId[], + transactionOptions?: TransactionOptions, ): Promise { - return (await this.prepareClaimOutputs(outputIds)).send(); + return ( + await this.prepareClaimOutputs(outputIds, transactionOptions) + ).send(); } /** @@ -431,11 +434,13 @@ export class Wallet { */ async prepareClaimOutputs( outputIds: OutputId[], + transactionOptions?: TransactionOptions, ): Promise { const response = await this.methodHandler.callMethod({ name: 'prepareClaimOutputs', data: { outputIdsToClaim: outputIds, + options: transactionOptions, }, }); const parsed = JSON.parse( diff --git a/bindings/nodejs/package.json b/bindings/nodejs/package.json index 97db771f1b..24d2f67b1e 100644 --- a/bindings/nodejs/package.json +++ b/bindings/nodejs/package.json @@ -1,6 +1,6 @@ { "name": "@iota/sdk", - "version": "2.0.0-alpha.8", + "version": "2.0.0-alpha.9", "description": "Node.js binding to the IOTA SDK library", "main": "out/index.js", "types": "out/index.d.ts", diff --git a/bindings/python/iota_sdk/wallet/wallet.py b/bindings/python/iota_sdk/wallet/wallet.py index 8a8b88a576..41031eedd2 100644 --- a/bindings/python/iota_sdk/wallet/wallet.py +++ b/bindings/python/iota_sdk/wallet/wallet.py @@ -286,18 +286,19 @@ def prepare_burn_nft(self, return PreparedTransaction(self, prepared) def claim_outputs( - self, output_ids_to_claim: List[OutputId]) -> TransactionWithMetadata: + self, output_ids_to_claim: List[OutputId], options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Claim outputs. """ - return self.prepare_claim_outputs(output_ids_to_claim).send() + return self.prepare_claim_outputs(output_ids_to_claim, options).send() def prepare_claim_outputs( - self, output_ids_to_claim: List[OutputId]) -> PreparedTransaction: + self, output_ids_to_claim: List[OutputId], options: Optional[TransactionOptions] = None) -> PreparedTransaction: """Claim outputs. """ return PreparedTransaction(self, PreparedTransactionData.from_dict(self._call_method( 'prepareClaimOutputs', { - 'outputIdsToClaim': output_ids_to_claim + 'outputIdsToClaim': output_ids_to_claim, + 'options': options } ))) diff --git a/cli/src/wallet_cli/mod.rs b/cli/src/wallet_cli/mod.rs index 0deaa23576..03cda828c4 100644 --- a/cli/src/wallet_cli/mod.rs +++ b/cli/src/wallet_cli/mod.rs @@ -568,7 +568,7 @@ pub async fn claim_command(wallet: &Wallet, output_id: Option) -> Resu if let Some(output_id) = output_id { println_log_info!("Claiming output {output_id}"); - let transaction = wallet.claim_outputs([output_id]).await?; + let transaction = wallet.claim_outputs([output_id], None).await?; println_log_info!( "Claiming transaction sent:\n{:?}\n{:?}", @@ -587,7 +587,7 @@ pub async fn claim_command(wallet: &Wallet, output_id: Option) -> Resu // Doing chunks of only 60, because we might need to create the double amount of outputs, because of potential // storage deposit return unlock conditions and also consider the remainder output. for output_ids_chunk in output_ids.chunks(60) { - let transaction = wallet.claim_outputs(output_ids_chunk.to_vec()).await?; + let transaction = wallet.claim_outputs(output_ids_chunk.to_vec(), None).await?; println_log_info!( "Claiming transaction sent:\n{:?}\n{:?}", transaction.transaction_id, diff --git a/sdk/examples/how_tos/advanced_transactions/claim_transaction.rs b/sdk/examples/how_tos/advanced_transactions/claim_transaction.rs index 2b056b873c..9dc3b0cf70 100644 --- a/sdk/examples/how_tos/advanced_transactions/claim_transaction.rs +++ b/sdk/examples/how_tos/advanced_transactions/claim_transaction.rs @@ -37,7 +37,7 @@ async fn main() -> Result<(), Box> { println!("{}", output_id); } - let transaction = wallet.claim_outputs(output_ids).await?; + let transaction = wallet.claim_outputs(output_ids, None).await?; println!("Transaction sent: {}", transaction.transaction_id); wallet diff --git a/sdk/src/wallet/operations/output_claiming.rs b/sdk/src/wallet/operations/output_claiming.rs index e975ee5465..4270da5b72 100644 --- a/sdk/src/wallet/operations/output_claiming.rs +++ b/sdk/src/wallet/operations/output_claiming.rs @@ -230,12 +230,15 @@ where pub async fn claim_outputs + Send>( &self, output_ids_to_claim: I, + transaction_options: impl Into> + Send, ) -> Result where I::IntoIter: Send, { log::debug!("[OUTPUT_CLAIMING] claim_outputs"); - let prepared_transaction = self.prepare_claim_outputs(output_ids_to_claim).await?; + let prepared_transaction = self + .prepare_claim_outputs(output_ids_to_claim, transaction_options) + .await?; let claim_tx = self.sign_and_submit_transaction(prepared_transaction, None).await?; @@ -251,6 +254,7 @@ where pub async fn prepare_claim_outputs + Send>( &self, output_ids_to_claim: I, + transaction_options: impl Into> + Send, ) -> Result where I::IntoIter: Send, @@ -278,7 +282,8 @@ where )); } - let wallet_address = self.address().await; + let transaction_options = transaction_options.into(); + let remainder_address = self.get_remainder_address(transaction_options.clone()).await?; drop(wallet_ledger); let mut nft_outputs_to_send = Vec::new(); @@ -301,13 +306,13 @@ where // deposit for the remaining amount and possible native tokens NftOutputBuilder::from(nft_output) .with_nft_id(nft_output.nft_id_non_null(&output_data.output_id)) - .with_unlock_conditions([AddressUnlockCondition::new(&wallet_address)]) + .with_unlock_conditions([AddressUnlockCondition::new(remainder_address.clone())]) .finish_output()? } else { NftOutputBuilder::from(nft_output) .with_minimum_amount(storage_score_params) .with_nft_id(nft_output.nft_id_non_null(&output_data.output_id)) - .with_unlock_conditions([AddressUnlockCondition::new(&wallet_address)]) + .with_unlock_conditions([AddressUnlockCondition::new(remainder_address.clone())]) .finish_output()? }; @@ -315,17 +320,25 @@ where } } + let required_inputs = outputs_to_claim + .iter() + .map(|o| o.output_id) + // add additional inputs + .chain(possible_additional_inputs.iter().map(|o| o.output_id)) + .collect(); + self.prepare_send_outputs( // We only need to provide the NFT outputs, ISA automatically creates basic outputs as remainder outputs nft_outputs_to_send, - TransactionOptions { - required_inputs: outputs_to_claim - .iter() - .map(|o| o.output_id) - // add additional inputs - .chain(possible_additional_inputs.iter().map(|o| o.output_id)) - .collect(), - ..Default::default() + match transaction_options { + Some(mut tx_options) => { + tx_options.required_inputs = required_inputs; + tx_options + } + None => TransactionOptions { + required_inputs, + ..Default::default() + }, }, ) .await diff --git a/sdk/src/wallet/operations/transaction/prepare_output.rs b/sdk/src/wallet/operations/transaction/prepare_output.rs index 5ac8958ce6..d451541b7b 100644 --- a/sdk/src/wallet/operations/transaction/prepare_output.rs +++ b/sdk/src/wallet/operations/transaction/prepare_output.rs @@ -259,7 +259,7 @@ impl Wallet { } // Get a remainder address based on transaction_options or use the first account address - async fn get_remainder_address( + pub(crate) async fn get_remainder_address( &self, transaction_options: impl Into> + Send, ) -> Result { diff --git a/sdk/tests/wallet/claim_outputs.rs b/sdk/tests/wallet/claim_outputs.rs index 8c19b1f836..e8b0fc18d5 100644 --- a/sdk/tests/wallet/claim_outputs.rs +++ b/sdk/tests/wallet/claim_outputs.rs @@ -56,7 +56,10 @@ async fn claim_2_basic_micro_outputs() -> Result<(), Box> let base_coin_amount_before_claiming = balance.base_coin().available(); let tx = wallet_0 - .claim_outputs(wallet_0.claimable_outputs(OutputsToClaim::MicroTransactions).await?) + .claim_outputs( + wallet_0.claimable_outputs(OutputsToClaim::MicroTransactions).await?, + None, + ) .await?; wallet_0 .wait_for_transaction_acceptance(&tx.transaction_id, None, None) @@ -113,7 +116,7 @@ async fn claim_1_of_2_basic_outputs() -> Result<(), Box> let base_coin_amount_before_claiming = balance.base_coin().available(); let tx = wallet_0 - .claim_outputs(wallet_0.claimable_outputs(OutputsToClaim::Amount).await?) + .claim_outputs(wallet_0.claimable_outputs(OutputsToClaim::Amount).await?, None) .await?; wallet_0 .wait_for_transaction_acceptance(&tx.transaction_id, None, None) @@ -193,7 +196,7 @@ async fn claim_2_basic_outputs_no_available_in_claim_account() -> Result<(), Box let base_coin_amount_before_claiming = balance.base_coin().available(); let tx = wallet_1 - .claim_outputs(wallet_1.claimable_outputs(OutputsToClaim::All).await?) + .claim_outputs(wallet_1.claimable_outputs(OutputsToClaim::All).await?, None) .await?; wallet_1 .wait_for_transaction_acceptance(&tx.transaction_id, None, None) @@ -281,7 +284,7 @@ async fn claim_2_native_tokens() -> Result<(), Box> { assert_eq!(balance.potentially_locked_outputs().len(), 2); let tx = wallet_0 - .claim_outputs(wallet_0.claimable_outputs(OutputsToClaim::NativeTokens).await?) + .claim_outputs(wallet_0.claimable_outputs(OutputsToClaim::NativeTokens).await?, None) .await?; wallet_0 .wait_for_transaction_acceptance(&tx.transaction_id, None, None) @@ -404,7 +407,7 @@ async fn claim_2_native_tokens_no_available_balance_in_claim_account() -> Result assert_eq!(balance.potentially_locked_outputs().len(), 2); let tx = wallet_1 - .claim_outputs(wallet_1.claimable_outputs(OutputsToClaim::NativeTokens).await?) + .claim_outputs(wallet_1.claimable_outputs(OutputsToClaim::NativeTokens).await?, None) .await?; wallet_1 .wait_for_transaction_acceptance(&tx.transaction_id, None, None) @@ -470,7 +473,7 @@ async fn claim_2_nft_outputs() -> Result<(), Box> { assert_eq!(balance.potentially_locked_outputs().len(), 2); let tx = wallet_0 - .claim_outputs(wallet_0.claimable_outputs(OutputsToClaim::Nfts).await?) + .claim_outputs(wallet_0.claimable_outputs(OutputsToClaim::Nfts).await?, None) .await?; wallet_0 .wait_for_transaction_acceptance(&tx.transaction_id, None, None) @@ -547,7 +550,7 @@ async fn claim_2_nft_outputs_no_available_in_claim_account() -> Result<(), Box Result<(), Box