From bd7c08f8b9a065312058a2279e161e8193f2a35a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tadeusz=20So=C5=9Bnierz?= Date: Thu, 16 Nov 2023 16:20:24 +0100 Subject: [PATCH] Add prepare_claim_outputs() (#1622) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Factor out prepare_claim_outputs() Signed-off-by: Tadeusz „tadzik” Sośnierz * Add node bindings for prepareClaimOutputs() Signed-off-by: Tadeusz „tadzik” Sośnierz * Add Python bindings for prepare_claim_outputs() Signed-off-by: Tadeusz „tadzik” Sośnierz * Fix an argument name Signed-off-by: Tadeusz „tadzik” Sośnierz * Add PrepareClaimOutputs to AccountMethod bindings Signed-off-by: Tadeusz „tadzik” Sośnierz * Fixup the nodejs bindings to prepareClaimOutputs() Signed-off-by: Tadeusz „tadzik” Sośnierz * Fixup Python bindings to prepareClaimOutputs() Signed-off-by: Tadeusz „tadzik” Sośnierz * Add Python and Typescript examples for prepareClaimOutputs() Signed-off-by: Tadeusz „tadzik” Sośnierz * Fix the explorer URL in consolidate_outputs() example Signed-off-by: Tadeusz „tadzik” Sośnierz * typo Signed-off-by: Tadeusz „tadzik” Sośnierz * Fix typescript formatting Signed-off-by: Tadeusz „tadzik” Sośnierz * Fix rust formatting Signed-off-by: Tadeusz „tadzik” Sośnierz * Remove new examples, per suggestion Signed-off-by: Tadeusz „tadzik” Sośnierz * sigh Signed-off-by: Tadeusz „tadzik” Sośnierz * Add changelogs for prepare_claim_outputs() Signed-off-by: Tadeusz „tadzik” Sośnierz * Update bindings/nodejs/CHANGELOG.md Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> --------- Signed-off-by: Tadeusz „tadzik” Sośnierz Co-authored-by: Thoralf-M <46689931+Thoralf-M@users.noreply.github.com> --- bindings/core/src/method/account.rs | 4 + bindings/core/src/method_handler/account.rs | 4 + bindings/core/src/response.rs | 1 + bindings/nodejs/CHANGELOG.md | 1 + .../nodejs/lib/types/wallet/bridge/account.ts | 7 ++ .../nodejs/lib/types/wallet/bridge/index.ts | 2 + bindings/nodejs/lib/wallet/account.ts | 23 ++++- bindings/python/CHANGELOG.md | 1 + .../consolidate_outputs.py | 2 +- bindings/python/iota_sdk/wallet/account.py | 10 +- sdk/CHANGELOG.md | 6 ++ .../account/operations/output_claiming.rs | 91 +++++++++---------- 12 files changed, 100 insertions(+), 52 deletions(-) diff --git a/bindings/core/src/method/account.rs b/bindings/core/src/method/account.rs index 4a1ca46b2a..4a0a71e425 100644 --- a/bindings/core/src/method/account.rs +++ b/bindings/core/src/method/account.rs @@ -140,6 +140,10 @@ pub enum AccountMethod { burn: BurnDto, options: Option, }, + /// Claim outputs. + /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) + #[serde(rename_all = "camelCase")] + PrepareClaimOutputs { output_ids_to_claim: Vec }, /// Consolidate outputs. /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) PrepareConsolidateOutputs { params: ConsolidationParams }, diff --git a/bindings/core/src/method_handler/account.rs b/bindings/core/src/method_handler/account.rs index 23e60bf4a1..c25a67db5b 100644 --- a/bindings/core/src/method_handler/account.rs +++ b/bindings/core/src/method_handler/account.rs @@ -115,6 +115,10 @@ pub(crate) async fn call_account_method_internal(account: &Account, method: Acco .await?; Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) } + AccountMethod::PrepareClaimOutputs { output_ids_to_claim } => { + let data = account.prepare_claim_outputs(output_ids_to_claim).await?; + Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) + } AccountMethod::PrepareConsolidateOutputs { params } => { let data = account.prepare_consolidate_outputs(params).await?; Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) diff --git a/bindings/core/src/response.rs b/bindings/core/src/response.rs index 69022b0d56..1ad54f6b42 100644 --- a/bindings/core/src/response.rs +++ b/bindings/core/src/response.rs @@ -332,6 +332,7 @@ pub enum Response { OutputsData(Vec), /// Response for: /// - [`PrepareBurn`](crate::method::AccountMethod::PrepareBurn), + /// - [`PrepareClaimOutputs`](crate::method::AccountMethod::PrepareClaimOutputs) /// - [`PrepareConsolidateOutputs`](crate::method::AccountMethod::PrepareConsolidateOutputs) /// - [`PrepareCreateAliasOutput`](crate::method::AccountMethod::PrepareCreateAliasOutput) /// - [`PrepareDecreaseVotingPower`](crate::method::AccountMethod::PrepareDecreaseVotingPower) diff --git a/bindings/nodejs/CHANGELOG.md b/bindings/nodejs/CHANGELOG.md index 262b03f24b..5dd21cd533 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 ### Added - `Utils:verifyTransactionSemantic()`; +- `Account::prepareClaimOutputs()` method; ### Fixed diff --git a/bindings/nodejs/lib/types/wallet/bridge/account.ts b/bindings/nodejs/lib/types/wallet/bridge/account.ts index 0996a8fc8a..4256e0c774 100644 --- a/bindings/nodejs/lib/types/wallet/bridge/account.ts +++ b/bindings/nodejs/lib/types/wallet/bridge/account.ts @@ -67,6 +67,13 @@ export type __PrepareBurnMethod__ = { }; }; +export type __PrepareClaimOutputsMethod__ = { + name: 'prepareClaimOutputs'; + data: { + outputIdsToClaim: OutputId[]; + }; +}; + export type __ClaimOutputsMethod__ = { name: 'claimOutputs'; data: { diff --git a/bindings/nodejs/lib/types/wallet/bridge/index.ts b/bindings/nodejs/lib/types/wallet/bridge/index.ts index 6f4cf77f67..02a1f96ec3 100644 --- a/bindings/nodejs/lib/types/wallet/bridge/index.ts +++ b/bindings/nodejs/lib/types/wallet/bridge/index.ts @@ -5,6 +5,7 @@ import type { __BuildFoundryOutputMethod__, __BuildNftOutputMethod__, __PrepareBurnMethod__, + __PrepareClaimOutputsMethod__, __ClaimOutputsMethod__, __PrepareConsolidateOutputsMethod__, __PrepareCreateAliasOutputMethod__, @@ -87,6 +88,7 @@ export type __AccountMethod__ = | __BuildNftOutputMethod__ | __PrepareBurnMethod__ | __ClaimOutputsMethod__ + | __PrepareClaimOutputsMethod__ | __PrepareConsolidateOutputsMethod__ | __PrepareCreateAliasOutputMethod__ | __DeregisterParticipationEventMethod__ diff --git a/bindings/nodejs/lib/wallet/account.ts b/bindings/nodejs/lib/wallet/account.ts index b829546148..333a25d2e2 100644 --- a/bindings/nodejs/lib/wallet/account.ts +++ b/bindings/nodejs/lib/wallet/account.ts @@ -242,17 +242,34 @@ export class Account { * @returns The resulting transaction. */ async claimOutputs(outputIds: OutputId[]): Promise { + return (await this.prepareClaimOutputs(outputIds)).send(); + } + + /** + * Claim basic or nft outputs that have additional unlock conditions + * to their `AddressUnlockCondition` from the account. + * @param outputIds The outputs to claim. + * @returns The prepared transaction. + */ + async prepareClaimOutputs( + outputIds: OutputId[], + ): Promise { const response = await this.methodHandler.callAccountMethod( this.meta.index, { - name: 'claimOutputs', + name: 'prepareClaimOutputs', data: { outputIdsToClaim: outputIds, }, }, ); - const parsed = JSON.parse(response) as Response; - return plainToInstance(Transaction, parsed.payload); + const parsed = JSON.parse( + response, + ) as Response; + return new PreparedTransaction( + plainToInstance(PreparedTransactionData, parsed.payload), + this, + ); } /** diff --git a/bindings/python/CHANGELOG.md b/bindings/python/CHANGELOG.md index 2e4d292eb3..70386b3a8b 100644 --- a/bindings/python/CHANGELOG.md +++ b/bindings/python/CHANGELOG.md @@ -24,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `Utils:verify_transaction_semantic()`; +- `Account::prepare_claim_outputs()` method; ## 1.1.1 - 2023-10-31 diff --git a/bindings/python/examples/how_tos/accounts_and_addresses/consolidate_outputs.py b/bindings/python/examples/how_tos/accounts_and_addresses/consolidate_outputs.py index 38810b71dd..a463a32e9a 100644 --- a/bindings/python/examples/how_tos/accounts_and_addresses/consolidate_outputs.py +++ b/bindings/python/examples/how_tos/accounts_and_addresses/consolidate_outputs.py @@ -50,7 +50,7 @@ block_id = account.retry_transaction_until_included(transaction.transactionId) print( - f'Transaction included: {os.environ["EXPLORER_ID"]}/block/{block_id}' + f'Transaction included: {os.environ["EXPLORER_URL"]}/block/{block_id}' ) # Sync account diff --git a/bindings/python/iota_sdk/wallet/account.py b/bindings/python/iota_sdk/wallet/account.py index 61acf7fa70..c6215a5193 100644 --- a/bindings/python/iota_sdk/wallet/account.py +++ b/bindings/python/iota_sdk/wallet/account.py @@ -564,8 +564,14 @@ def claim_outputs( self, output_ids_to_claim: List[OutputId]) -> Transaction: """Claim outputs. """ - return Transaction.from_dict(self._call_account_method( - 'claimOutputs', { + return self.prepare_claim_outputs(output_ids_to_claim).send() + + def prepare_claim_outputs( + self, output_ids_to_claim: List[OutputId]) -> PreparedTransaction: + """Claim outputs. + """ + return PreparedTransaction(self, self._call_account_method( + 'prepareClaimOutputs', { 'outputIdsToClaim': output_ids_to_claim } )) diff --git a/sdk/CHANGELOG.md b/sdk/CHANGELOG.md index f6cd51ec84..7910392051 100644 --- a/sdk/CHANGELOG.md +++ b/sdk/CHANGELOG.md @@ -19,6 +19,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Security --> +## Unreleased - 2023-MM-DD + +### Added + +- `Account::prepare_claim_outputs` method; + ## 1.1.2 - 2023-10-26 ### Added diff --git a/sdk/src/wallet/account/operations/output_claiming.rs b/sdk/src/wallet/account/operations/output_claiming.rs index f958837b2a..96cb3f656f 100644 --- a/sdk/src/wallet/account/operations/output_claiming.rs +++ b/sdk/src/wallet/account/operations/output_claiming.rs @@ -6,7 +6,7 @@ use std::collections::{HashMap, HashSet}; use serde::{Deserialize, Serialize}; use crate::{ - client::secret::SecretManage, + client::{api::PreparedTransactionData, secret::SecretManage}, types::block::{ address::Address, output::{ @@ -186,37 +186,44 @@ where I::IntoIter: Send, { log::debug!("[OUTPUT_CLAIMING] claim_outputs"); - let basic_outputs = self.get_basic_outputs_for_additional_inputs().await?; - self.claim_outputs_internal(output_ids_to_claim, basic_outputs) - .await - .map_err(|error| { - // Map InsufficientStorageDepositAmount error here because it's the result of InsufficientFunds in this - // case and then easier to handle - match error { - crate::wallet::Error::Block(block_error) => match *block_error { - crate::types::block::Error::InsufficientStorageDepositAmount { amount, required } => { - crate::wallet::Error::InsufficientFunds { - available: amount, - required, - } + let prepared_transaction = self.prepare_claim_outputs(output_ids_to_claim).await.map_err(|error| { + // Map InsufficientStorageDepositAmount error here because it's the result of InsufficientFunds in this + // case and then easier to handle + match error { + crate::wallet::Error::Block(block_error) => match *block_error { + crate::types::block::Error::InsufficientStorageDepositAmount { amount, required } => { + crate::wallet::Error::InsufficientFunds { + available: amount, + required, } - _ => crate::wallet::Error::Block(block_error), - }, - _ => error, - } - }) + } + _ => crate::wallet::Error::Block(block_error), + }, + _ => error, + } + })?; + + let claim_tx = self.sign_and_submit_transaction(prepared_transaction, None).await?; + + log::debug!( + "[OUTPUT_CLAIMING] Claiming transaction created: block_id: {:?} tx_id: {:?}", + claim_tx.block_id, + claim_tx.transaction_id + ); + Ok(claim_tx) } /// Try to claim basic outputs that have additional unlock conditions to their [AddressUnlockCondition]. - pub(crate) async fn claim_outputs_internal + Send>( + pub async fn prepare_claim_outputs + Send>( &self, output_ids_to_claim: I, - mut possible_additional_inputs: Vec, - ) -> crate::wallet::Result + ) -> crate::wallet::Result where I::IntoIter: Send, { - log::debug!("[OUTPUT_CLAIMING] claim_outputs_internal"); + log::debug!("[OUTPUT_CLAIMING] prepare_claim_outputs"); + + let mut possible_additional_inputs = self.get_basic_outputs_for_additional_inputs().await?; let current_time = self.client().get_time_checked().await?; let rent_structure = self.client().get_rent_structure().await?; @@ -406,29 +413,21 @@ where })?; } - let claim_tx = self - .finish_transaction( - outputs_to_send, - Some(TransactionOptions { - custom_inputs: Some( - outputs_to_claim - .iter() - .map(|o| o.output_id) - // add additional inputs - .chain(additional_inputs) - .collect::>(), - ), - ..Default::default() - }), - ) - .await?; - - log::debug!( - "[OUTPUT_CLAIMING] Claiming transaction created: block_id: {:?} tx_id: {:?}", - claim_tx.block_id, - claim_tx.transaction_id - ); - Ok(claim_tx) + self.prepare_transaction( + outputs_to_send, + Some(TransactionOptions { + custom_inputs: Some( + outputs_to_claim + .iter() + .map(|o| o.output_id) + // add additional inputs + .chain(additional_inputs) + .collect::>(), + ), + ..Default::default() + }), + ) + .await } }