diff --git a/bindings/core/src/lib.rs b/bindings/core/src/lib.rs index ea1bac6fdd..0d88cd4fbe 100644 --- a/bindings/core/src/lib.rs +++ b/bindings/core/src/lib.rs @@ -27,7 +27,7 @@ pub use self::method_handler::listen_mqtt; pub use self::method_handler::CallMethod; pub use self::{ error::{Error, Result}, - method::{ClientMethod, SecretManagerMethod, UtilsMethod, WalletCommandMethod, WalletMethod}, + method::{ClientMethod, SecretManagerMethod, UtilsMethod, WalletMethod}, method_handler::{call_client_method, call_secret_manager_method, call_utils_method, call_wallet_method}, response::Response, }; diff --git a/bindings/core/src/method/mod.rs b/bindings/core/src/method/mod.rs index 7aaf0baa5a..6e47c80767 100644 --- a/bindings/core/src/method/mod.rs +++ b/bindings/core/src/method/mod.rs @@ -5,9 +5,5 @@ mod client; mod secret_manager; mod utils; mod wallet; -mod wallet_command; -pub use self::{ - client::ClientMethod, secret_manager::SecretManagerMethod, utils::UtilsMethod, wallet::WalletMethod, - wallet_command::WalletCommandMethod, -}; +pub use self::{client::ClientMethod, secret_manager::SecretManagerMethod, utils::UtilsMethod, wallet::WalletMethod}; diff --git a/bindings/core/src/method/secret_manager.rs b/bindings/core/src/method/secret_manager.rs index c538f3aec2..b70c10db53 100644 --- a/bindings/core/src/method/secret_manager.rs +++ b/bindings/core/src/method/secret_manager.rs @@ -36,7 +36,7 @@ pub enum SecretManagerMethod { SignatureUnlock { /// Transaction signing hash transaction_signing_hash: String, - /// Chain to sign the hash with + /// Chain used to sign the hash #[serde(with = "Bip44Def")] chain: Bip44, }, @@ -44,7 +44,7 @@ pub enum SecretManagerMethod { SignEd25519 { /// The message to sign, hex encoded String message: String, - /// Chain to sign the message with + /// Chain used to sign the message #[serde(with = "Bip44Def")] chain: Bip44, }, @@ -52,7 +52,7 @@ pub enum SecretManagerMethod { SignSecp256k1Ecdsa { /// The message to sign, hex encoded String message: String, - /// Chain to sign the message with + /// Chain used to sign the message #[serde(with = "Bip44Def")] chain: Bip44, }, @@ -66,7 +66,7 @@ pub enum SecretManagerMethod { #[serde(rename_all = "camelCase")] SignBlock { unsigned_block: UnsignedBlockDto, - /// Chain to sign the essence hash with + /// Chain used to sign the block #[serde(with = "Bip44Def")] chain: Bip44, }, diff --git a/bindings/core/src/method/wallet.rs b/bindings/core/src/method/wallet.rs index e99dfa1831..2748e34864 100644 --- a/bindings/core/src/method/wallet.rs +++ b/bindings/core/src/method/wallet.rs @@ -7,15 +7,33 @@ use std::path::PathBuf; use derivative::Derivative; #[cfg(feature = "events")] use iota_sdk::wallet::events::types::{WalletEvent, WalletEventType}; +#[cfg(feature = "participation")] use iota_sdk::{ - client::{node_manager::node::NodeAuth, secret::GenerateAddressOptions}, - types::block::address::Hrp, - wallet::{ClientOptions, SyncOptions}, + client::node_manager::node::Node, + types::api::plugins::participation::types::{ParticipationEventId, ParticipationEventType}, + wallet::types::participation::ParticipationEventRegistrationOptions, +}; +use iota_sdk::{ + client::{ + api::{input_selection::Burn, PreparedTransactionDataDto, SignedTransactionDataDto}, + node_manager::node::NodeAuth, + secret::GenerateAddressOptions, + }, + types::block::{ + address::{Bech32Address, Hrp}, + output::{dto::OutputDto, OutputId, TokenId}, + payload::signed_transaction::TransactionId, + }, + wallet::{ + ClientOptions, ConsolidationParams, CreateAccountParams, CreateNativeTokenParams, FilterOptions, MintNftParams, + OutputParams, OutputsToClaim, SendNativeTokensParams, SendNftParams, SendParams, SyncOptions, + TransactionOptions, + }, + U256, }; use serde::{Deserialize, Serialize}; use url::Url; -use crate::method::WalletCommandMethod; #[cfg(feature = "stronghold")] use crate::OmittedDebug; @@ -25,13 +43,6 @@ use crate::OmittedDebug; #[serde(tag = "name", content = "data", rename_all = "camelCase")] #[non_exhaustive] pub enum WalletMethod { - /// Consume a wallet command method. - /// Returns [`Response`](crate::Response) - #[serde(rename_all = "camelCase")] - CallMethod { - /// The wallet command method to call. - method: WalletCommandMethod, - }, /// Backup storage. Password must be the current one, when Stronghold is used as SecretManager. /// Expected response: [`Ok`](crate::Response::Ok) #[cfg(feature = "stronghold")] @@ -43,28 +54,6 @@ pub enum WalletMethod { #[derivative(Debug(format_with = "OmittedDebug::omitted_fmt"))] password: String, }, - /// Change the Stronghold password to another one and also re-encrypt the values in the loaded snapshot with it. - /// Expected response: [`Ok`](crate::Response::Ok) - #[cfg(feature = "stronghold")] - #[cfg_attr(docsrs, doc(cfg(feature = "stronghold")))] - #[serde(rename_all = "camelCase")] - ChangeStrongholdPassword { - #[derivative(Debug(format_with = "OmittedDebug::omitted_fmt"))] - current_password: String, - #[derivative(Debug(format_with = "OmittedDebug::omitted_fmt"))] - new_password: String, - }, - /// Clears the Stronghold password from memory. - /// Expected response: [`Ok`](crate::Response::Ok) - #[cfg(feature = "stronghold")] - #[cfg_attr(docsrs, doc(cfg(feature = "stronghold")))] - ClearStrongholdPassword, - /// Checks if the Stronghold password is available. - /// Expected response: - /// [`Bool`](crate::Response::Bool) - #[cfg(feature = "stronghold")] - #[cfg_attr(docsrs, doc(cfg(feature = "stronghold")))] - IsStrongholdPasswordAvailable, /// Restore a backup from a Stronghold file /// Replaces client_options, coin_type, secret_manager and wallet. Returns an error if the wallet was already /// created If Stronghold is used as secret_manager, the existing Stronghold file will be overwritten. If a @@ -95,6 +84,329 @@ pub enum WalletMethod { /// Expected response: [`Ok`](crate::Response::Ok) #[serde(rename_all = "camelCase")] SetClientOptions { client_options: Box }, + /// Start background syncing. + /// Expected response: [`Ok`](crate::Response::Ok) + #[serde(rename_all = "camelCase")] + StartBackgroundSync { + /// Sync options + options: Option, + /// Interval in milliseconds + interval_in_milliseconds: Option, + }, + /// Stop background syncing. + /// Expected response: [`Ok`](crate::Response::Ok) + StopBackgroundSync, + // Remove all listeners of this type. Empty vec clears all listeners + /// Expected response: [`Ok`](crate::Response::Ok) + #[cfg(feature = "events")] + #[cfg_attr(docsrs, doc(cfg(feature = "events")))] + #[serde(rename_all = "camelCase")] + ClearListeners { event_types: Vec }, + /// Update the authentication for the provided node. + /// Expected response: [`Ok`](crate::Response::Ok) + UpdateNodeAuth { + /// Node url + url: Url, + /// Authentication options + auth: Option, + }, + /// Get outputs with additional unlock conditions + /// Expected response: [`OutputIds`](crate::Response::OutputIds) + #[serde(rename_all = "camelCase")] + ClaimableOutputs { outputs_to_claim: OutputsToClaim }, + /// Claim outputs. + /// Expected response: [`SentTransaction`](crate::Response::SentTransaction) + #[serde(rename_all = "camelCase")] + ClaimOutputs { output_ids_to_claim: Vec }, + /// Removes a previously registered participation event from local storage. + /// Expected response: [`Ok`](crate::Response::Ok) + #[cfg(feature = "participation")] + #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] + #[serde(rename_all = "camelCase")] + DeregisterParticipationEvent { event_id: ParticipationEventId }, + /// Get the wallet address. + /// Expected response: [`Address`](crate::Response::Address) + GetAddress, + /// Get wallet balance information. + /// Expected response: [`Balance`](crate::Response::Balance) + GetBalance, + /// Get the [`Output`](iota_sdk::types::block::output::Output) that minted a native token by its TokenId + /// Expected response: [`Output`](crate::Response::Output) + #[serde(rename_all = "camelCase")] + GetFoundryOutput { token_id: TokenId }, + /// Get the transaction with inputs of an incoming transaction stored in the wallet + /// List might not be complete, if the node pruned the data already + /// Expected response: [`Transaction`](crate::Response::Transaction) + #[serde(rename_all = "camelCase")] + GetIncomingTransaction { transaction_id: TransactionId }, + /// Get the [`OutputData`](iota_sdk::wallet::types::OutputData) of an output stored in the wallet + /// Expected response: [`OutputData`](crate::Response::OutputData) + #[serde(rename_all = "camelCase")] + GetOutput { output_id: OutputId }, + /// Expected response: [`ParticipationEvent`](crate::Response::ParticipationEvent) + #[cfg(feature = "participation")] + #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] + #[serde(rename_all = "camelCase")] + GetParticipationEvent { event_id: ParticipationEventId }, + /// Expected response: [`ParticipationEventIds`](crate::Response::ParticipationEventIds) + #[cfg(feature = "participation")] + #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] + #[serde(rename_all = "camelCase")] + GetParticipationEventIds { + node: Node, + event_type: Option, + }, + /// Expected response: + /// [`ParticipationEventStatus`](crate::Response::ParticipationEventStatus) + #[cfg(feature = "participation")] + #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] + #[serde(rename_all = "camelCase")] + GetParticipationEventStatus { event_id: ParticipationEventId }, + /// Expected response: [`ParticipationEvents`](crate::Response::ParticipationEvents) + #[cfg(feature = "participation")] + #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] + GetParticipationEvents, + /// Calculates a participation overview for the wallet. If event_ids are provided, only return outputs and tracked + /// participations for them. + /// Expected response: + /// [`ParticipationOverview`](crate::Response::ParticipationOverview) + #[cfg(feature = "participation")] + #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] + #[serde(rename_all = "camelCase")] + GetParticipationOverview { + event_ids: Option>, + }, + /// Get the [`Transaction`](iota_sdk::wallet::types::Transaction) of a transaction stored in the wallet + /// Expected response: [`Transaction`](crate::Response::Transaction) + #[serde(rename_all = "camelCase")] + GetTransaction { transaction_id: TransactionId }, + /// Get the wallet's total voting power (voting or NOT voting). + /// Expected response: [`VotingPower`](crate::Response::VotingPower) + #[cfg(feature = "participation")] + #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] + GetVotingPower, + /// Returns the implicit account creation address of the wallet if it is Ed25519 based. + /// Expected response: [`Bech32Address`](crate::Response::Bech32Address) + ImplicitAccountCreationAddress, + /// Returns all incoming transactions of the wallet + /// Expected response: + /// [`Transactions`](crate::Response::Transactions) + IncomingTransactions, + /// Returns all outputs of the wallet + /// Expected response: [`OutputsData`](crate::Response::OutputsData) + #[serde(rename_all = "camelCase")] + Outputs { filter_options: Option }, + /// Returns all pending transactions of the wallet + /// Expected response: [`Transactions`](crate::Response::Transactions) + PendingTransactions, + /// A generic function that can be used to burn native tokens, nfts, foundries and accounts. + /// + /// Note that burning **native tokens** doesn't require the foundry output which minted them, but will not + /// increase the foundries `melted_tokens` field, which makes it impossible to destroy the foundry output. + /// Therefore it's recommended to use melting, if the foundry output is available. + /// + /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) + PrepareBurn { + burn: Burn, + options: Option, + }, + /// Consolidate outputs. + /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) + PrepareConsolidateOutputs { params: ConsolidationParams }, + /// Create an alias output. + /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) + PrepareCreateAccountOutput { + params: Option, + options: Option, + }, + /// Prepare to create a native token. + /// Expected response: + /// [`PreparedCreateNativeTokenTransaction`](crate::Response::PreparedCreateNativeTokenTransaction) + PrepareCreateNativeToken { + params: CreateNativeTokenParams, + options: Option, + }, + /// Reduces a wallet's "voting power" by a given amount. + /// This will stop voting, but the voting data isn't lost and calling `Vote` without parameters will revote. + /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) + #[cfg(feature = "participation")] + #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] + PrepareDecreaseVotingPower { + #[serde(with = "iota_sdk::utils::serde::string")] + amount: u64, + }, + /// Designates a given amount of tokens towards a wallet's "voting power" by creating a + /// special output, which is really a basic one with some metadata. + /// This will stop voting in most cases (if there is a remainder output), but the voting data isn't lost and + /// calling `Vote` without parameters will revote. Expected response: + /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) + #[cfg(feature = "participation")] + #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] + PrepareIncreaseVotingPower { + #[serde(with = "iota_sdk::utils::serde::string")] + amount: u64, + }, + /// Prepare to melt native tokens. This happens with the foundry output which minted them, by increasing it's + /// `melted_tokens` field. + /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) + #[serde(rename_all = "camelCase")] + PrepareMeltNativeToken { + /// Native token id + token_id: TokenId, + /// To be melted amount + melt_amount: U256, + options: Option, + }, + /// Prepare to mint additional native tokens. + /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) + #[serde(rename_all = "camelCase")] + PrepareMintNativeToken { + /// Native token id + token_id: TokenId, + /// To be minted amount + mint_amount: U256, + options: Option, + }, + /// Prepare to mint NFTs. + /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) + PrepareMintNfts { + params: Vec, + options: Option, + }, + /// Prepare an output. + /// Expected response: [`Output`](crate::Response::Output) + #[serde(rename_all = "camelCase")] + PrepareOutput { + params: Box, + transaction_options: Option, + }, + /// Prepare to send base coins. + /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) + PrepareSend { + params: Vec, + options: Option, + }, + /// Prepare to send native tokens. + /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) + PrepareSendNativeTokens { + params: Vec, + options: Option, + }, + /// Prepare to Send nft. + /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) + PrepareSendNft { + params: Vec, + options: Option, + }, + /// Stop participating for an event. + /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) + #[cfg(feature = "participation")] + #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] + #[serde(rename_all = "camelCase")] + PrepareStopParticipating { event_id: ParticipationEventId }, + /// Prepare transaction. + /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) + PrepareTransaction { + outputs: Vec, + options: Option, + }, + /// Vote for a participation event. + /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) + #[cfg(feature = "participation")] + #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] + #[serde(rename_all = "camelCase")] + PrepareVote { + event_id: Option, + answers: Option>, + }, + /// Stores participation information locally and returns the event. + /// + /// This will NOT store the node url and auth inside the client options. + /// Expected response: [`ParticipationEvents`](crate::Response::ParticipationEvents) + #[cfg(feature = "participation")] + #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] + RegisterParticipationEvents { + options: ParticipationEventRegistrationOptions, + }, + /// Reissues a transaction sent from the wallet for a provided transaction id until it's + /// included (referenced by a milestone). Returns the included block id. + /// Expected response: [`BlockId`](crate::Response::BlockId) + #[serde(rename_all = "camelCase")] + ReissueTransactionUntilIncluded { + /// Transaction id + transaction_id: TransactionId, + /// Interval + interval: Option, + /// Maximum attempts + max_attempts: Option, + }, + /// Send base coins. + /// Expected response: [`SentTransaction`](crate::Response::SentTransaction) + Send { + #[serde(with = "iota_sdk::utils::serde::string")] + amount: u64, + address: Bech32Address, + options: Option, + }, + /// Send base coins to multiple addresses, or with additional parameters. + /// Expected response: [`SentTransaction`](crate::Response::SentTransaction) + SendWithParams { + params: Vec, + options: Option, + }, + /// Send outputs in a transaction. + /// Expected response: [`SentTransaction`](crate::Response::SentTransaction) + SendOutputs { + outputs: Vec, + options: Option, + }, + /// Set the alias of the wallet. + /// Expected response: [`Ok`](crate::Response::Ok) + SetAlias { alias: String }, + /// Set the fallback SyncOptions for wallet syncing. + /// If storage is enabled, will persist during restarts. + /// Expected response: [`Ok`](crate::Response::Ok) + SetDefaultSyncOptions { options: SyncOptions }, + /// Validate the transaction, sign it, submit it to a node and store it in the wallet. + /// Expected response: [`SentTransaction`](crate::Response::SentTransaction) + #[serde(rename_all = "camelCase")] + SignAndSubmitTransaction { + prepared_transaction_data: PreparedTransactionDataDto, + }, + /// Sign a prepared transaction. + /// Expected response: [`SignedTransactionData`](crate::Response::SignedTransactionData) + #[serde(rename_all = "camelCase")] + SignTransaction { + prepared_transaction_data: PreparedTransactionDataDto, + }, + /// Validate the transaction, submit it to a node and store it in the wallet. + /// Expected response: [`SentTransaction`](crate::Response::SentTransaction) + #[serde(rename_all = "camelCase")] + SubmitAndStoreTransaction { + signed_transaction_data: SignedTransactionDataDto, + }, + /// Sync the wallet by fetching new information from the nodes. Will also reissue pending transactions + /// if necessary. A custom default can be set using SetDefaultSyncOptions. + /// Expected response: [`Balance`](crate::Response::Balance) + Sync { + /// Sync options + options: Option, + }, + /// Returns all transactions of the wallet + /// Expected response: [`Transactions`](crate::Response::Transactions) + Transactions, + /// Returns all unspent outputs of the wallet + /// Expected response: [`OutputsData`](crate::Response::OutputsData) + #[serde(rename_all = "camelCase")] + UnspentOutputs { filter_options: Option }, + + /// Emits an event for testing if the event system is working + /// Expected response: [`Ok`](crate::Response::Ok) + #[cfg(feature = "events")] + #[cfg_attr(docsrs, doc(cfg(feature = "events")))] + EmitTestEvent { event: WalletEvent }, + + // TODO: reconsider whether to have the following methods on the wallet /// Generate an address without storing it /// Expected response: [`Bech32Address`](crate::Response::Bech32Address) #[serde(rename_all = "camelCase")] @@ -135,35 +447,26 @@ pub enum WalletMethod { #[derivative(Debug(format_with = "OmittedDebug::omitted_fmt"))] mnemonic: String, }, - /// Start background syncing. + /// Change the Stronghold password to another one and also re-encrypt the values in the loaded snapshot with it. /// Expected response: [`Ok`](crate::Response::Ok) + #[cfg(feature = "stronghold")] + #[cfg_attr(docsrs, doc(cfg(feature = "stronghold")))] #[serde(rename_all = "camelCase")] - StartBackgroundSync { - /// Sync options - options: Option, - /// Interval in milliseconds - interval_in_milliseconds: Option, + ChangeStrongholdPassword { + #[derivative(Debug(format_with = "OmittedDebug::omitted_fmt"))] + current_password: String, + #[derivative(Debug(format_with = "OmittedDebug::omitted_fmt"))] + new_password: String, }, - /// Stop background syncing. - /// Expected response: [`Ok`](crate::Response::Ok) - StopBackgroundSync, - /// Emits an event for testing if the event system is working - /// Expected response: [`Ok`](crate::Response::Ok) - #[cfg(feature = "events")] - #[cfg_attr(docsrs, doc(cfg(feature = "events")))] - EmitTestEvent { event: WalletEvent }, - // Remove all listeners of this type. Empty vec clears all listeners - /// Expected response: [`Ok`](crate::Response::Ok) - #[cfg(feature = "events")] - #[cfg_attr(docsrs, doc(cfg(feature = "events")))] - #[serde(rename_all = "camelCase")] - ClearListeners { event_types: Vec }, - /// Update the authentication for the provided node. + /// Clears the Stronghold password from memory. /// Expected response: [`Ok`](crate::Response::Ok) - UpdateNodeAuth { - /// Node url - url: Url, - /// Authentication options - auth: Option, - }, + #[cfg(feature = "stronghold")] + #[cfg_attr(docsrs, doc(cfg(feature = "stronghold")))] + ClearStrongholdPassword, + /// Checks if the Stronghold password is available. + /// Expected response: + /// [`Bool`](crate::Response::Bool) + #[cfg(feature = "stronghold")] + #[cfg_attr(docsrs, doc(cfg(feature = "stronghold")))] + IsStrongholdPasswordAvailable, } diff --git a/bindings/core/src/method/wallet_command.rs b/bindings/core/src/method/wallet_command.rs deleted file mode 100644 index 72aa622eaf..0000000000 --- a/bindings/core/src/method/wallet_command.rs +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright 2023 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use iota_sdk::{ - client::api::{input_selection::Burn, PreparedTransactionDataDto, SignedTransactionDataDto}, - types::block::{ - address::Bech32Address, - output::{dto::OutputDto, OutputId, TokenId}, - payload::signed_transaction::TransactionId, - }, - wallet::{ - ConsolidationParams, CreateAccountParams, CreateNativeTokenParams, FilterOptions, MintNftParams, OutputParams, - OutputsToClaim, SendNativeTokensParams, SendNftParams, SendParams, SyncOptions, TransactionOptions, - }, - U256, -}; -#[cfg(feature = "participation")] -use iota_sdk::{ - client::node_manager::node::Node, - types::api::plugins::participation::types::{ParticipationEventId, ParticipationEventType}, - wallet::types::participation::ParticipationEventRegistrationOptions, -}; -use serde::{Deserialize, Serialize}; - -/// Each public wallet command method. -#[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(tag = "name", content = "data", rename_all = "camelCase")] -#[non_exhaustive] -pub enum WalletCommandMethod { - /// Get outputs with additional unlock conditions - /// Expected response: [`OutputIds`](crate::Response::OutputIds) - #[serde(rename_all = "camelCase")] - ClaimableOutputs { outputs_to_claim: OutputsToClaim }, - /// Claim outputs. - /// Expected response: [`SentTransaction`](crate::Response::SentTransaction) - #[serde(rename_all = "camelCase")] - ClaimOutputs { output_ids_to_claim: Vec }, - /// Removes a previously registered participation event from local storage. - /// Expected response: [`Ok`](crate::Response::Ok) - #[cfg(feature = "participation")] - #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] - #[serde(rename_all = "camelCase")] - DeregisterParticipationEvent { event_id: ParticipationEventId }, - /// Get the wallet address. - /// Expected response: [`Address`](crate::Response::Address) - GetAddress, - /// Get wallet balance information. - /// Expected response: [`Balance`](crate::Response::Balance) - GetBalance, - /// Get the [`Output`](iota_sdk::types::block::output::Output) that minted a native token by its TokenId - /// Expected response: [`Output`](crate::Response::Output) - #[serde(rename_all = "camelCase")] - GetFoundryOutput { token_id: TokenId }, - /// Get the transaction with inputs of an incoming transaction stored in the wallet - /// List might not be complete, if the node pruned the data already - /// Expected response: [`Transaction`](crate::Response::Transaction) - #[serde(rename_all = "camelCase")] - GetIncomingTransaction { transaction_id: TransactionId }, - /// Get the [`OutputData`](iota_sdk::wallet::types::OutputData) of an output stored in the wallet - /// Expected response: [`OutputData`](crate::Response::OutputData) - #[serde(rename_all = "camelCase")] - GetOutput { output_id: OutputId }, - /// Expected response: [`ParticipationEvent`](crate::Response::ParticipationEvent) - #[cfg(feature = "participation")] - #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] - #[serde(rename_all = "camelCase")] - GetParticipationEvent { event_id: ParticipationEventId }, - /// Expected response: [`ParticipationEventIds`](crate::Response::ParticipationEventIds) - #[cfg(feature = "participation")] - #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] - #[serde(rename_all = "camelCase")] - GetParticipationEventIds { - node: Node, - event_type: Option, - }, - /// Expected response: - /// [`ParticipationEventStatus`](crate::Response::ParticipationEventStatus) - #[cfg(feature = "participation")] - #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] - #[serde(rename_all = "camelCase")] - GetParticipationEventStatus { event_id: ParticipationEventId }, - /// Expected response: [`ParticipationEvents`](crate::Response::ParticipationEvents) - #[cfg(feature = "participation")] - #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] - GetParticipationEvents, - /// Calculates a participation overview for the wallet. If event_ids are provided, only return outputs and tracked - /// participations for them. - /// Expected response: - /// [`ParticipationOverview`](crate::Response::ParticipationOverview) - #[cfg(feature = "participation")] - #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] - #[serde(rename_all = "camelCase")] - GetParticipationOverview { - event_ids: Option>, - }, - /// Get the [`Transaction`](iota_sdk::wallet::types::Transaction) of a transaction stored in the wallet - /// Expected response: [`Transaction`](crate::Response::Transaction) - #[serde(rename_all = "camelCase")] - GetTransaction { transaction_id: TransactionId }, - /// Get the wallet's total voting power (voting or NOT voting). - /// Expected response: [`VotingPower`](crate::Response::VotingPower) - #[cfg(feature = "participation")] - #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] - GetVotingPower, - /// Returns all incoming transactions of the wallet - /// Expected response: - /// [`Transactions`](crate::Response::Transactions) - IncomingTransactions, - /// Returns all outputs of the wallet - /// Expected response: [`OutputsData`](crate::Response::OutputsData) - #[serde(rename_all = "camelCase")] - Outputs { filter_options: Option }, - /// Returns all pending transactions of the wallet - /// Expected response: [`Transactions`](crate::Response::Transactions) - PendingTransactions, - /// A generic function that can be used to burn native tokens, nfts, foundries and accounts. - /// - /// Note that burning **native tokens** doesn't require the foundry output which minted them, but will not - /// increase the foundries `melted_tokens` field, which makes it impossible to destroy the foundry output. - /// Therefore it's recommended to use melting, if the foundry output is available. - /// - /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) - PrepareBurn { - burn: Burn, - options: Option, - }, - /// Consolidate outputs. - /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) - PrepareConsolidateOutputs { params: ConsolidationParams }, - /// Create an alias output. - /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) - PrepareCreateAccountOutput { - params: Option, - options: Option, - }, - /// Prepare to create a native token. - /// Expected response: - /// [`PreparedCreateNativeTokenTransaction`](crate::Response::PreparedCreateNativeTokenTransaction) - PrepareCreateNativeToken { - params: CreateNativeTokenParams, - options: Option, - }, - /// Reduces a wallet's "voting power" by a given amount. - /// This will stop voting, but the voting data isn't lost and calling `Vote` without parameters will revote. - /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) - #[cfg(feature = "participation")] - #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] - PrepareDecreaseVotingPower { - #[serde(with = "iota_sdk::utils::serde::string")] - amount: u64, - }, - /// Designates a given amount of tokens towards a wallet's "voting power" by creating a - /// special output, which is really a basic one with some metadata. - /// This will stop voting in most cases (if there is a remainder output), but the voting data isn't lost and - /// calling `Vote` without parameters will revote. Expected response: - /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) - #[cfg(feature = "participation")] - #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] - PrepareIncreaseVotingPower { - #[serde(with = "iota_sdk::utils::serde::string")] - amount: u64, - }, - /// Prepare to melt native tokens. This happens with the foundry output which minted them, by increasing it's - /// `melted_tokens` field. - /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) - #[serde(rename_all = "camelCase")] - PrepareMeltNativeToken { - /// Native token id - token_id: TokenId, - /// To be melted amount - melt_amount: U256, - options: Option, - }, - /// Prepare to mint additional native tokens. - /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) - #[serde(rename_all = "camelCase")] - PrepareMintNativeToken { - /// Native token id - token_id: TokenId, - /// To be minted amount - mint_amount: U256, - options: Option, - }, - /// Prepare to mint NFTs. - /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) - PrepareMintNfts { - params: Vec, - options: Option, - }, - /// Prepare an output. - /// Expected response: [`Output`](crate::Response::Output) - #[serde(rename_all = "camelCase")] - PrepareOutput { - params: Box, - transaction_options: Option, - }, - /// Prepare to send base coins. - /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) - PrepareSend { - params: Vec, - options: Option, - }, - /// Prepare to send native tokens. - /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) - PrepareSendNativeTokens { - params: Vec, - options: Option, - }, - /// Prepare to Send nft. - /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) - PrepareSendNft { - params: Vec, - options: Option, - }, - /// Stop participating for an event. - /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) - #[cfg(feature = "participation")] - #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] - #[serde(rename_all = "camelCase")] - PrepareStopParticipating { event_id: ParticipationEventId }, - /// Prepare transaction. - /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) - PrepareTransaction { - outputs: Vec, - options: Option, - }, - /// Vote for a participation event. - /// Expected response: [`PreparedTransaction`](crate::Response::PreparedTransaction) - #[cfg(feature = "participation")] - #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] - #[serde(rename_all = "camelCase")] - PrepareVote { - event_id: Option, - answers: Option>, - }, - /// Stores participation information locally and returns the event. - /// - /// This will NOT store the node url and auth inside the client options. - /// Expected response: [`ParticipationEvents`](crate::Response::ParticipationEvents) - #[cfg(feature = "participation")] - #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] - RegisterParticipationEvents { - options: ParticipationEventRegistrationOptions, - }, - /// Reissues a transaction sent from the wallet for a provided transaction id until it's - /// included (referenced by a milestone). Returns the included block id. - /// Expected response: [`BlockId`](crate::Response::BlockId) - #[serde(rename_all = "camelCase")] - ReissueTransactionUntilIncluded { - /// Transaction id - transaction_id: TransactionId, - /// Interval - interval: Option, - /// Maximum attempts - max_attempts: Option, - }, - /// Send base coins. - /// Expected response: [`SentTransaction`](crate::Response::SentTransaction) - Send { - #[serde(with = "iota_sdk::utils::serde::string")] - amount: u64, - address: Bech32Address, - options: Option, - }, - /// Send base coins to multiple addresses, or with additional parameters. - /// Expected response: [`SentTransaction`](crate::Response::SentTransaction) - SendWithParams { - params: Vec, - options: Option, - }, - /// Send outputs in a transaction. - /// Expected response: [`SentTransaction`](crate::Response::SentTransaction) - SendOutputs { - outputs: Vec, - options: Option, - }, - /// Set the alias of the wallet. - /// Expected response: [`Ok`](crate::Response::Ok) - SetAlias { alias: String }, - /// Set the fallback SyncOptions for wallet syncing. - /// If storage is enabled, will persist during restarts. - /// Expected response: [`Ok`](crate::Response::Ok) - SetDefaultSyncOptions { options: SyncOptions }, - /// Validate the transaction, sign it, submit it to a node and store it in the wallet. - /// Expected response: [`SentTransaction`](crate::Response::SentTransaction) - #[serde(rename_all = "camelCase")] - SignAndSubmitTransaction { - prepared_transaction_data: PreparedTransactionDataDto, - }, - /// Sign a prepared transaction. - /// Expected response: [`SignedTransactionData`](crate::Response::SignedTransactionData) - #[serde(rename_all = "camelCase")] - SignTransaction { - prepared_transaction_data: PreparedTransactionDataDto, - }, - /// Validate the transaction, submit it to a node and store it in the wallet. - /// Expected response: [`SentTransaction`](crate::Response::SentTransaction) - #[serde(rename_all = "camelCase")] - SubmitAndStoreTransaction { - signed_transaction_data: SignedTransactionDataDto, - }, - /// Sync the wallet by fetching new information from the nodes. Will also reissue pending transactions - /// if necessary. A custom default can be set using SetDefaultSyncOptions. - /// Expected response: [`Balance`](crate::Response::Balance) - Sync { - /// Sync options - options: Option, - }, - /// Returns all transactions of the wallet - /// Expected response: [`Transactions`](crate::Response::Transactions) - Transactions, - /// Returns all unspent outputs of the wallet - /// Expected response: [`OutputsData`](crate::Response::OutputsData) - #[serde(rename_all = "camelCase")] - UnspentOutputs { filter_options: Option }, -} diff --git a/bindings/core/src/method_handler/mod.rs b/bindings/core/src/method_handler/mod.rs index 35bccfbbc6..5b39e211fa 100644 --- a/bindings/core/src/method_handler/mod.rs +++ b/bindings/core/src/method_handler/mod.rs @@ -6,7 +6,6 @@ mod client; mod secret_manager; mod utils; mod wallet; -mod wallet_command; pub use call_method::{ call_client_method, call_secret_manager_method, call_utils_method, call_wallet_method, CallMethod, diff --git a/bindings/core/src/method_handler/wallet.rs b/bindings/core/src/method_handler/wallet.rs index b24ac505d7..b83cda4e7c 100644 --- a/bindings/core/src/method_handler/wallet.rs +++ b/bindings/core/src/method_handler/wallet.rs @@ -3,15 +3,25 @@ use std::time::Duration; -use iota_sdk::{types::block::address::ToBech32Ext, wallet::Wallet}; +use iota_sdk::{ + client::api::{ + PreparedTransactionData, PreparedTransactionDataDto, SignedTransactionData, SignedTransactionDataDto, + }, + types::{ + block::{ + address::ToBech32Ext, + output::{dto::OutputDto, Output}, + }, + TryFromDto, + }, + wallet::{types::TransactionWithMetadataDto, OutputDataDto, PreparedCreateNativeTokenTransactionDto, Wallet}, +}; -use super::wallet_command::call_wallet_command_method_internal; use crate::{method::WalletMethod, response::Response, Result}; /// Call a wallet method. pub(crate) async fn call_wallet_method_internal(wallet: &Wallet, method: WalletMethod) -> Result { let response = match method { - WalletMethod::CallMethod { method } => call_wallet_command_method_internal(&wallet, method).await?, #[cfg(feature = "stronghold")] WalletMethod::Backup { destination, password } => { wallet.backup(destination, password).await?; @@ -124,6 +134,269 @@ pub(crate) async fn call_wallet_method_internal(wallet: &Wallet, method: WalletM wallet.update_node_auth(url, auth).await?; Response::Ok } + WalletMethod::ClaimableOutputs { outputs_to_claim } => { + let output_ids = wallet.claimable_outputs(outputs_to_claim).await?; + Response::OutputIds(output_ids) + } + WalletMethod::ClaimOutputs { output_ids_to_claim } => { + let transaction = wallet.claim_outputs(output_ids_to_claim.to_vec()).await?; + Response::SentTransaction(TransactionWithMetadataDto::from(&transaction)) + } + #[cfg(feature = "participation")] + WalletMethod::DeregisterParticipationEvent { event_id } => { + wallet.deregister_participation_event(&event_id).await?; + Response::Ok + } + WalletMethod::GetAddress => { + let address = wallet.address().await; + Response::Address(address) + } + WalletMethod::GetBalance => Response::Balance(wallet.balance().await?), + WalletMethod::GetFoundryOutput { token_id } => { + let output = wallet.get_foundry_output(token_id).await?; + Response::Output(OutputDto::from(&output)) + } + WalletMethod::GetIncomingTransaction { transaction_id } => { + let transaction = wallet.get_incoming_transaction(&transaction_id).await; + + transaction.map_or_else( + || Response::Transaction(None), + |transaction| Response::Transaction(Some(Box::new(TransactionWithMetadataDto::from(&transaction)))), + ) + } + WalletMethod::GetOutput { output_id } => { + let output_data = wallet.get_output(&output_id).await; + Response::OutputData(output_data.as_ref().map(OutputDataDto::from).map(Box::new)) + } + #[cfg(feature = "participation")] + WalletMethod::GetParticipationEvent { event_id } => { + let event_and_nodes = wallet.get_participation_event(event_id).await?; + Response::ParticipationEvent(event_and_nodes) + } + #[cfg(feature = "participation")] + WalletMethod::GetParticipationEventIds { node, event_type } => { + let event_ids = wallet.get_participation_event_ids(&node, event_type).await?; + Response::ParticipationEventIds(event_ids) + } + #[cfg(feature = "participation")] + WalletMethod::GetParticipationEventStatus { event_id } => { + let event_status = wallet.get_participation_event_status(&event_id).await?; + Response::ParticipationEventStatus(event_status) + } + #[cfg(feature = "participation")] + WalletMethod::GetParticipationEvents => { + let events = wallet.get_participation_events().await?; + Response::ParticipationEvents(events) + } + #[cfg(feature = "participation")] + WalletMethod::GetParticipationOverview { event_ids } => { + let overview = wallet.get_participation_overview(event_ids).await?; + Response::ParticipationOverview(overview) + } + WalletMethod::GetTransaction { transaction_id } => { + let transaction = wallet.get_transaction(&transaction_id).await; + Response::Transaction(transaction.as_ref().map(TransactionWithMetadataDto::from).map(Box::new)) + } + #[cfg(feature = "participation")] + WalletMethod::GetVotingPower => { + let voting_power = wallet.get_voting_power().await?; + Response::VotingPower(voting_power.to_string()) + } + WalletMethod::ImplicitAccountCreationAddress => { + let implicit_account_creation_address = wallet.implicit_account_creation_address().await?; + Response::Bech32Address(implicit_account_creation_address) + } + WalletMethod::IncomingTransactions => { + let transactions = wallet.incoming_transactions().await; + Response::Transactions(transactions.iter().map(TransactionWithMetadataDto::from).collect()) + } + WalletMethod::Outputs { filter_options } => { + let outputs = wallet.outputs(filter_options).await?; + Response::OutputsData(outputs.iter().map(OutputDataDto::from).collect()) + } + WalletMethod::PendingTransactions => { + let transactions = wallet.pending_transactions().await; + Response::Transactions(transactions.iter().map(TransactionWithMetadataDto::from).collect()) + } + WalletMethod::PrepareBurn { burn, options } => { + let data = wallet.prepare_burn(burn, options).await?; + Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) + } + WalletMethod::PrepareConsolidateOutputs { params } => { + let data = wallet.prepare_consolidate_outputs(params).await?; + Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) + } + WalletMethod::PrepareCreateAccountOutput { params, options } => { + let data = wallet.prepare_create_account_output(params, options).await?; + Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) + } + WalletMethod::PrepareMeltNativeToken { + token_id, + melt_amount, + options, + } => { + let data = wallet.prepare_melt_native_token(token_id, melt_amount, options).await?; + Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) + } + #[cfg(feature = "participation")] + WalletMethod::PrepareDecreaseVotingPower { amount } => { + let data = wallet.prepare_decrease_voting_power(amount).await?; + Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) + } + WalletMethod::PrepareMintNativeToken { + token_id, + mint_amount, + options, + } => { + let data = wallet.prepare_mint_native_token(token_id, mint_amount, options).await?; + Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) + } + #[cfg(feature = "participation")] + WalletMethod::PrepareIncreaseVotingPower { amount } => { + let data = wallet.prepare_increase_voting_power(amount).await?; + Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) + } + WalletMethod::PrepareMintNfts { params, options } => { + let data = wallet.prepare_mint_nfts(params, options).await?; + Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) + } + WalletMethod::PrepareCreateNativeToken { params, options } => { + let data = wallet.prepare_create_native_token(params, options).await?; + Response::PreparedCreateNativeTokenTransaction(PreparedCreateNativeTokenTransactionDto::from(&data)) + } + WalletMethod::PrepareOutput { + params, + transaction_options, + } => { + let output = wallet.prepare_output(*params, transaction_options).await?; + Response::Output(OutputDto::from(&output)) + } + WalletMethod::PrepareSend { params, options } => { + let data = wallet.prepare_send(params, options).await?; + Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) + } + WalletMethod::PrepareSendNativeTokens { params, options } => { + let data = wallet.prepare_send_native_tokens(params.clone(), options).await?; + Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) + } + WalletMethod::PrepareSendNft { params, options } => { + let data = wallet.prepare_send_nft(params.clone(), options).await?; + Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) + } + #[cfg(feature = "participation")] + WalletMethod::PrepareStopParticipating { event_id } => { + let data = wallet.prepare_stop_participating(event_id).await?; + Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) + } + WalletMethod::PrepareTransaction { outputs, options } => { + let token_supply = wallet.client().get_token_supply().await?; + let data = wallet + .prepare_transaction( + outputs + .into_iter() + .map(|o| Ok(Output::try_from_dto_with_params(o, token_supply)?)) + .collect::>>()?, + options, + ) + .await?; + Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) + } + #[cfg(feature = "participation")] + WalletMethod::PrepareVote { event_id, answers } => { + let data = wallet.prepare_vote(event_id, answers).await?; + Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) + } + #[cfg(feature = "participation")] + WalletMethod::RegisterParticipationEvents { options } => { + let events = wallet.register_participation_events(&options).await?; + Response::ParticipationEvents(events) + } + WalletMethod::ReissueTransactionUntilIncluded { + transaction_id, + interval, + max_attempts, + } => { + let block_id = wallet + .reissue_transaction_until_included(&transaction_id, interval, max_attempts) + .await?; + Response::BlockId(block_id) + } + WalletMethod::Send { + amount, + address, + options, + } => { + let transaction = wallet.send(amount, address, options).await?; + Response::SentTransaction(TransactionWithMetadataDto::from(&transaction)) + } + WalletMethod::SendWithParams { params, options } => { + let transaction = wallet.send_with_params(params, options).await?; + Response::SentTransaction(TransactionWithMetadataDto::from(&transaction)) + } + WalletMethod::SendOutputs { outputs, options } => { + let token_supply = wallet.client().get_token_supply().await?; + let transaction = wallet + .send_outputs( + outputs + .into_iter() + .map(|o| Ok(Output::try_from_dto_with_params(o, token_supply)?)) + .collect::>>()?, + options, + ) + .await?; + Response::SentTransaction(TransactionWithMetadataDto::from(&transaction)) + } + WalletMethod::SetAlias { alias } => { + wallet.set_alias(&alias).await?; + Response::Ok + } + WalletMethod::SetDefaultSyncOptions { options } => { + wallet.set_default_sync_options(options).await?; + Response::Ok + } + WalletMethod::SignAndSubmitTransaction { + prepared_transaction_data, + } => { + let transaction = wallet + .sign_and_submit_transaction( + PreparedTransactionData::try_from_dto_with_params( + prepared_transaction_data, + wallet.client().get_protocol_parameters().await?, + )?, + None, + ) + .await?; + Response::SentTransaction(TransactionWithMetadataDto::from(&transaction)) + } + WalletMethod::SignTransaction { + prepared_transaction_data, + } => { + let signed_transaction_data = wallet + .sign_transaction(&PreparedTransactionData::try_from_dto(prepared_transaction_data)?) + .await?; + Response::SignedTransactionData(SignedTransactionDataDto::from(&signed_transaction_data)) + } + WalletMethod::SubmitAndStoreTransaction { + signed_transaction_data, + } => { + let signed_transaction_data = SignedTransactionData::try_from_dto_with_params( + signed_transaction_data, + wallet.client().get_protocol_parameters().await?, + )?; + let transaction = wallet + .submit_and_store_transaction(signed_transaction_data, None) + .await?; + Response::SentTransaction(TransactionWithMetadataDto::from(&transaction)) + } + WalletMethod::Sync { options } => Response::Balance(wallet.sync(options).await?), + WalletMethod::Transactions => { + let transactions = wallet.transactions().await; + Response::Transactions(transactions.iter().map(TransactionWithMetadataDto::from).collect()) + } + WalletMethod::UnspentOutputs { filter_options } => { + let outputs = wallet.unspent_outputs(filter_options).await?; + Response::OutputsData(outputs.iter().map(OutputDataDto::from).collect()) + } }; Ok(response) } diff --git a/bindings/core/src/method_handler/wallet_command.rs b/bindings/core/src/method_handler/wallet_command.rs deleted file mode 100644 index 562cdd370f..0000000000 --- a/bindings/core/src/method_handler/wallet_command.rs +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright 2023 IOTA Stiftung -// SPDX-License-Identifier: Apache-2.0 - -use iota_sdk::{ - client::api::{ - PreparedTransactionData, PreparedTransactionDataDto, SignedTransactionData, SignedTransactionDataDto, - }, - types::{ - block::output::{dto::OutputDto, Output}, - TryFromDto, - }, - wallet::{types::TransactionWithMetadataDto, OutputDataDto, PreparedCreateNativeTokenTransactionDto, Wallet}, -}; - -use crate::{method::WalletCommandMethod, Response, Result}; - -pub(crate) async fn call_wallet_command_method_internal( - wallet: &Wallet, - method: WalletCommandMethod, -) -> Result { - let response = match method { - WalletCommandMethod::ClaimableOutputs { outputs_to_claim } => { - let output_ids = wallet.claimable_outputs(outputs_to_claim).await?; - Response::OutputIds(output_ids) - } - WalletCommandMethod::ClaimOutputs { output_ids_to_claim } => { - let transaction = wallet.claim_outputs(output_ids_to_claim.to_vec()).await?; - Response::SentTransaction(TransactionWithMetadataDto::from(&transaction)) - } - #[cfg(feature = "participation")] - WalletCommandMethod::DeregisterParticipationEvent { event_id } => { - wallet.deregister_participation_event(&event_id).await?; - Response::Ok - } - WalletCommandMethod::GetAddress => { - let address = wallet.address().await; - Response::Address(address) - } - WalletCommandMethod::GetBalance => Response::Balance(wallet.balance().await?), - WalletCommandMethod::GetFoundryOutput { token_id } => { - let output = wallet.get_foundry_output(token_id).await?; - Response::Output(OutputDto::from(&output)) - } - WalletCommandMethod::GetIncomingTransaction { transaction_id } => { - let transaction = wallet.get_incoming_transaction(&transaction_id).await; - - transaction.map_or_else( - || Response::Transaction(None), - |transaction| Response::Transaction(Some(Box::new(TransactionWithMetadataDto::from(&transaction)))), - ) - } - WalletCommandMethod::GetOutput { output_id } => { - let output_data = wallet.get_output(&output_id).await; - Response::OutputData(output_data.as_ref().map(OutputDataDto::from).map(Box::new)) - } - #[cfg(feature = "participation")] - WalletCommandMethod::GetParticipationEvent { event_id } => { - let event_and_nodes = wallet.get_participation_event(event_id).await?; - Response::ParticipationEvent(event_and_nodes) - } - #[cfg(feature = "participation")] - WalletCommandMethod::GetParticipationEventIds { node, event_type } => { - let event_ids = wallet.get_participation_event_ids(&node, event_type).await?; - Response::ParticipationEventIds(event_ids) - } - #[cfg(feature = "participation")] - WalletCommandMethod::GetParticipationEventStatus { event_id } => { - let event_status = wallet.get_participation_event_status(&event_id).await?; - Response::ParticipationEventStatus(event_status) - } - #[cfg(feature = "participation")] - WalletCommandMethod::GetParticipationEvents => { - let events = wallet.get_participation_events().await?; - Response::ParticipationEvents(events) - } - #[cfg(feature = "participation")] - WalletCommandMethod::GetParticipationOverview { event_ids } => { - let overview = wallet.get_participation_overview(event_ids).await?; - Response::ParticipationOverview(overview) - } - WalletCommandMethod::GetTransaction { transaction_id } => { - let transaction = wallet.get_transaction(&transaction_id).await; - Response::Transaction(transaction.as_ref().map(TransactionWithMetadataDto::from).map(Box::new)) - } - #[cfg(feature = "participation")] - WalletCommandMethod::GetVotingPower => { - let voting_power = wallet.get_voting_power().await?; - Response::VotingPower(voting_power.to_string()) - } - WalletCommandMethod::IncomingTransactions => { - let transactions = wallet.incoming_transactions().await; - Response::Transactions(transactions.iter().map(TransactionWithMetadataDto::from).collect()) - } - WalletCommandMethod::Outputs { filter_options } => { - let outputs = wallet.outputs(filter_options).await?; - Response::OutputsData(outputs.iter().map(OutputDataDto::from).collect()) - } - WalletCommandMethod::PendingTransactions => { - let transactions = wallet.pending_transactions().await; - Response::Transactions(transactions.iter().map(TransactionWithMetadataDto::from).collect()) - } - WalletCommandMethod::PrepareBurn { burn, options } => { - let data = wallet.prepare_burn(burn, options).await?; - Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) - } - WalletCommandMethod::PrepareConsolidateOutputs { params } => { - let data = wallet.prepare_consolidate_outputs(params).await?; - Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) - } - WalletCommandMethod::PrepareCreateAccountOutput { params, options } => { - let data = wallet.prepare_create_account_output(params, options).await?; - Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) - } - WalletCommandMethod::PrepareMeltNativeToken { - token_id, - melt_amount, - options, - } => { - let data = wallet.prepare_melt_native_token(token_id, melt_amount, options).await?; - Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) - } - #[cfg(feature = "participation")] - WalletCommandMethod::PrepareDecreaseVotingPower { amount } => { - let data = wallet.prepare_decrease_voting_power(amount).await?; - Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) - } - WalletCommandMethod::PrepareMintNativeToken { - token_id, - mint_amount, - options, - } => { - let data = wallet.prepare_mint_native_token(token_id, mint_amount, options).await?; - Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) - } - #[cfg(feature = "participation")] - WalletCommandMethod::PrepareIncreaseVotingPower { amount } => { - let data = wallet.prepare_increase_voting_power(amount).await?; - Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) - } - WalletCommandMethod::PrepareMintNfts { params, options } => { - let data = wallet.prepare_mint_nfts(params, options).await?; - Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) - } - WalletCommandMethod::PrepareCreateNativeToken { params, options } => { - let data = wallet.prepare_create_native_token(params, options).await?; - Response::PreparedCreateNativeTokenTransaction(PreparedCreateNativeTokenTransactionDto::from(&data)) - } - WalletCommandMethod::PrepareOutput { - params, - transaction_options, - } => { - let output = wallet.prepare_output(*params, transaction_options).await?; - Response::Output(OutputDto::from(&output)) - } - WalletCommandMethod::PrepareSend { params, options } => { - let data = wallet.prepare_send(params, options).await?; - Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) - } - WalletCommandMethod::PrepareSendNativeTokens { params, options } => { - let data = wallet.prepare_send_native_tokens(params.clone(), options).await?; - Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) - } - WalletCommandMethod::PrepareSendNft { params, options } => { - let data = wallet.prepare_send_nft(params.clone(), options).await?; - Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) - } - #[cfg(feature = "participation")] - WalletCommandMethod::PrepareStopParticipating { event_id } => { - let data = wallet.prepare_stop_participating(event_id).await?; - Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) - } - WalletCommandMethod::PrepareTransaction { outputs, options } => { - let token_supply = wallet.client().get_token_supply().await?; - let data = wallet - .prepare_transaction( - outputs - .into_iter() - .map(|o| Ok(Output::try_from_dto_with_params(o, token_supply)?)) - .collect::>>()?, - options, - ) - .await?; - Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) - } - #[cfg(feature = "participation")] - WalletCommandMethod::PrepareVote { event_id, answers } => { - let data = wallet.prepare_vote(event_id, answers).await?; - Response::PreparedTransaction(PreparedTransactionDataDto::from(&data)) - } - #[cfg(feature = "participation")] - WalletCommandMethod::RegisterParticipationEvents { options } => { - let events = wallet.register_participation_events(&options).await?; - Response::ParticipationEvents(events) - } - WalletCommandMethod::ReissueTransactionUntilIncluded { - transaction_id, - interval, - max_attempts, - } => { - let block_id = wallet - .reissue_transaction_until_included(&transaction_id, interval, max_attempts) - .await?; - Response::BlockId(block_id) - } - WalletCommandMethod::Send { - amount, - address, - options, - } => { - let transaction = wallet.send(amount, address, options).await?; - Response::SentTransaction(TransactionWithMetadataDto::from(&transaction)) - } - WalletCommandMethod::SendWithParams { params, options } => { - let transaction = wallet.send_with_params(params, options).await?; - Response::SentTransaction(TransactionWithMetadataDto::from(&transaction)) - } - WalletCommandMethod::SendOutputs { outputs, options } => { - let token_supply = wallet.client().get_token_supply().await?; - let transaction = wallet - .send_outputs( - outputs - .into_iter() - .map(|o| Ok(Output::try_from_dto_with_params(o, token_supply)?)) - .collect::>>()?, - options, - ) - .await?; - Response::SentTransaction(TransactionWithMetadataDto::from(&transaction)) - } - WalletCommandMethod::SetAlias { alias } => { - wallet.set_alias(&alias).await?; - Response::Ok - } - WalletCommandMethod::SetDefaultSyncOptions { options } => { - wallet.set_default_sync_options(options).await?; - Response::Ok - } - WalletCommandMethod::SignAndSubmitTransaction { - prepared_transaction_data, - } => { - let transaction = wallet - .sign_and_submit_transaction( - PreparedTransactionData::try_from_dto_with_params( - prepared_transaction_data, - wallet.client().get_protocol_parameters().await?, - )?, - None, - ) - .await?; - Response::SentTransaction(TransactionWithMetadataDto::from(&transaction)) - } - WalletCommandMethod::SignTransaction { - prepared_transaction_data, - } => { - let signed_transaction_data = wallet - .sign_transaction(&PreparedTransactionData::try_from_dto(prepared_transaction_data)?) - .await?; - Response::SignedTransactionData(SignedTransactionDataDto::from(&signed_transaction_data)) - } - WalletCommandMethod::SubmitAndStoreTransaction { - signed_transaction_data, - } => { - let signed_transaction_data = SignedTransactionData::try_from_dto_with_params( - signed_transaction_data, - wallet.client().get_protocol_parameters().await?, - )?; - let transaction = wallet - .submit_and_store_transaction(signed_transaction_data, None) - .await?; - Response::SentTransaction(TransactionWithMetadataDto::from(&transaction)) - } - WalletCommandMethod::Sync { options } => Response::Balance(wallet.sync(options).await?), - WalletCommandMethod::Transactions => { - let transactions = wallet.transactions().await; - Response::Transactions(transactions.iter().map(TransactionWithMetadataDto::from).collect()) - } - WalletCommandMethod::UnspentOutputs { filter_options } => { - let outputs = wallet.unspent_outputs(filter_options).await?; - Response::OutputsData(outputs.iter().map(OutputDataDto::from).collect()) - } - }; - Ok(response) -} diff --git a/bindings/core/src/response.rs b/bindings/core/src/response.rs index 7a67f1076d..da8d25c5d2 100644 --- a/bindings/core/src/response.rs +++ b/bindings/core/src/response.rs @@ -198,14 +198,15 @@ pub enum Response { /// - [`BuildBasicOutput`](crate::method::ClientMethod::BuildBasicOutput) /// - [`BuildFoundryOutput`](crate::method::ClientMethod::BuildFoundryOutput) /// - [`BuildNftOutput`](crate::method::ClientMethod::BuildNftOutput) - /// - [`GetFoundryOutput`](crate::method::WalletCommandMethod::GetFoundryOutput) - /// - [`PrepareOutput`](crate::method::WalletCommandMethod::PrepareOutput) + /// - [`GetFoundryOutput`](crate::method::WalletMethod::GetFoundryOutput) + /// - [`PrepareOutput`](crate::method::WalletMethod::PrepareOutput) Output(OutputDto), /// Response for: /// - [`AccountIdToBech32`](crate::method::ClientMethod::AccountIdToBech32) /// - [`HexPublicKeyToBech32Address`](crate::method::ClientMethod::HexPublicKeyToBech32Address) /// - [`HexToBech32`](crate::method::ClientMethod::HexToBech32) /// - [`NftIdToBech32`](crate::method::ClientMethod::NftIdToBech32) + /// - [`ImplicitAccountCreationAddress`](crate::method::WalletMethod::ImplicitAccountCreationAddress) Bech32Address(Bech32Address), /// - [`Faucet`](crate::method::ClientMethod::RequestFundsFromFaucet) Faucet(String), @@ -221,7 +222,7 @@ pub enum Response { /// - [`BlockId`](crate::method::UtilsMethod::BlockId) /// - [`PostBlock`](crate::method::ClientMethod::PostBlock) /// - [`PostBlockRaw`](crate::method::ClientMethod::PostBlockRaw) - /// - [`ReissueTransactionUntilIncluded`](crate::method::WalletCommandMethod::ReissueTransactionUntilIncluded) + /// - [`ReissueTransactionUntilIncluded`](crate::method::WalletMethod::ReissueTransactionUntilIncluded) BlockId(BlockId), /// Response for: /// - [`GetHealth`](crate::method::ClientMethod::GetHealth) @@ -233,12 +234,12 @@ pub enum Response { /// - [`Backup`](crate::method::WalletMethod::Backup), /// - [`ClearListeners`](crate::method::WalletMethod::ClearListeners) /// - [`ClearStrongholdPassword`](crate::method::WalletMethod::ClearStrongholdPassword), - /// - [`DeregisterParticipationEvent`](crate::method::WalletCommandMethod::DeregisterParticipationEvent), + /// - [`DeregisterParticipationEvent`](crate::method::WalletMethod::DeregisterParticipationEvent), /// - [`EmitTestEvent`](crate::method::WalletMethod::EmitTestEvent), /// - [`RestoreBackup`](crate::method::WalletMethod::RestoreBackup), - /// - [`SetAlias`](crate::method::WalletCommandMethod::SetAlias), + /// - [`SetAlias`](crate::method::WalletMethod::SetAlias), /// - [`SetClientOptions`](crate::method::WalletMethod::SetClientOptions), - /// - [`SetDefaultSyncOptions`](crate::method::WalletCommandMethod::SetDefaultSyncOptions), + /// - [`SetDefaultSyncOptions`](crate::method::WalletMethod::SetDefaultSyncOptions), /// - [`SetStrongholdPassword`](crate::method::WalletMethod::SetStrongholdPassword), /// - [`SetStrongholdPasswordClearInterval`](crate::method::WalletMethod::SetStrongholdPasswordClearInterval), /// - [`StartBackgroundSync`](crate::method::WalletMethod::StartBackgroundSync), @@ -252,92 +253,92 @@ pub enum Response { // wallet responses /// Response for: - /// - [`GetAddress`](crate::method::WalletCommandMethod::GetAddress) + /// - [`GetAddress`](crate::method::WalletMethod::GetAddress) Address(Bech32Address), /// Response for: /// - [`MinimumRequiredStorageDeposit`](crate::method::ClientMethod::MinimumRequiredStorageDeposit) /// - [`ComputeStorageDeposit`](crate::method::UtilsMethod::ComputeStorageDeposit) MinimumRequiredStorageDeposit(String), /// Response for: - /// - [`ClaimableOutputs`](crate::method::WalletCommandMethod::ClaimableOutputs) + /// - [`ClaimableOutputs`](crate::method::WalletMethod::ClaimableOutputs) OutputIds(Vec), /// Response for: - /// - [`GetOutput`](crate::method::WalletCommandMethod::GetOutput) + /// - [`GetOutput`](crate::method::WalletMethod::GetOutput) OutputData(Option>), /// Response for: - /// - [`Outputs`](crate::method::WalletCommandMethod::Outputs), - /// - [`UnspentOutputs`](crate::method::WalletCommandMethod::UnspentOutputs) + /// - [`Outputs`](crate::method::WalletMethod::Outputs), + /// - [`UnspentOutputs`](crate::method::WalletMethod::UnspentOutputs) OutputsData(Vec), /// Response for: - /// - [`PrepareBurn`](crate::method::WalletCommandMethod::PrepareBurn), - /// - [`PrepareConsolidateOutputs`](crate::method::WalletCommandMethod::PrepareConsolidateOutputs) - /// - [`PrepareCreateAccountOutput`](crate::method::WalletCommandMethod::PrepareCreateAccountOutput) - /// - [`PrepareDecreaseVotingPower`](crate::method::WalletCommandMethod::PrepareDecreaseVotingPower) - /// - [`PrepareIncreaseVotingPower`](crate::method::WalletCommandMethod::PrepareIncreaseVotingPower) - /// - [`PrepareMeltNativeToken`](crate::method::WalletCommandMethod::PrepareMeltNativeToken) - /// - [`PrepareMintNativeToken`](crate::method::WalletCommandMethod::PrepareMintNativeToken), - /// - [`PrepareMintNfts`](crate::method::WalletCommandMethod::PrepareMintNfts), - /// - [`PrepareSend`](crate::method::WalletCommandMethod::PrepareSend), - /// - [`PrepareSendNativeTokens`](crate::method::WalletCommandMethod::PrepareSendNativeTokens), - /// - [`PrepareSendNft`](crate::method::WalletCommandMethod::PrepareSendNft), - /// - [`PrepareStopParticipating`](crate::method::WalletCommandMethod::PrepareStopParticipating) - /// - [`PrepareTransaction`](crate::method::WalletCommandMethod::PrepareTransaction) - /// - [`PrepareVote`](crate::method::WalletCommandMethod::PrepareVote) + /// - [`PrepareBurn`](crate::method::WalletMethod::PrepareBurn), + /// - [`PrepareConsolidateOutputs`](crate::method::WalletMethod::PrepareConsolidateOutputs) + /// - [`PrepareCreateAccountOutput`](crate::method::WalletMethod::PrepareCreateAccountOutput) + /// - [`PrepareDecreaseVotingPower`](crate::method::WalletMethod::PrepareDecreaseVotingPower) + /// - [`PrepareIncreaseVotingPower`](crate::method::WalletMethod::PrepareIncreaseVotingPower) + /// - [`PrepareMeltNativeToken`](crate::method::WalletMethod::PrepareMeltNativeToken) + /// - [`PrepareMintNativeToken`](crate::method::WalletMethod::PrepareMintNativeToken), + /// - [`PrepareMintNfts`](crate::method::WalletMethod::PrepareMintNfts), + /// - [`PrepareSend`](crate::method::WalletMethod::PrepareSend), + /// - [`PrepareSendNativeTokens`](crate::method::WalletMethod::PrepareSendNativeTokens), + /// - [`PrepareSendNft`](crate::method::WalletMethod::PrepareSendNft), + /// - [`PrepareStopParticipating`](crate::method::WalletMethod::PrepareStopParticipating) + /// - [`PrepareTransaction`](crate::method::WalletMethod::PrepareTransaction) + /// - [`PrepareVote`](crate::method::WalletMethod::PrepareVote) PreparedTransaction(PreparedTransactionDataDto), /// Response for: - /// - [`PrepareCreateNativeToken`](crate::method::WalletCommandMethod::PrepareCreateNativeToken), + /// - [`PrepareCreateNativeToken`](crate::method::WalletMethod::PrepareCreateNativeToken), PreparedCreateNativeTokenTransaction(PreparedCreateNativeTokenTransactionDto), /// Response for: - /// - [`GetIncomingTransaction`](crate::method::WalletCommandMethod::GetIncomingTransaction) - /// - [`GetTransaction`](crate::method::WalletCommandMethod::GetTransaction), + /// - [`GetIncomingTransaction`](crate::method::WalletMethod::GetIncomingTransaction) + /// - [`GetTransaction`](crate::method::WalletMethod::GetTransaction), Transaction(Option>), /// Response for: - /// - [`IncomingTransactions`](crate::method::WalletCommandMethod::IncomingTransactions) - /// - [`PendingTransactions`](crate::method::WalletCommandMethod::PendingTransactions), - /// - [`Transactions`](crate::method::WalletCommandMethod::Transactions), + /// - [`IncomingTransactions`](crate::method::WalletMethod::IncomingTransactions) + /// - [`PendingTransactions`](crate::method::WalletMethod::PendingTransactions), + /// - [`Transactions`](crate::method::WalletMethod::Transactions), Transactions(Vec), /// Response for: - /// - [`SignTransaction`](crate::method::WalletCommandMethod::SignTransaction) + /// - [`SignTransaction`](crate::method::WalletMethod::SignTransaction) SignedTransactionData(SignedTransactionDataDto), /// Response for: - /// - [`GetBalance`](crate::method::WalletCommandMethod::GetBalance), - /// - [`Sync`](crate::method::WalletCommandMethod::Sync) + /// - [`GetBalance`](crate::method::WalletMethod::GetBalance), + /// - [`Sync`](crate::method::WalletMethod::Sync) Balance(Balance), /// Response for: - /// - [`ClaimOutputs`](crate::method::WalletCommandMethod::ClaimOutputs) - /// - [`Send`](crate::method::WalletCommandMethod::Send) - /// - [`SendOutputs`](crate::method::WalletCommandMethod::SendOutputs) - /// - [`SignAndSubmitTransaction`](crate::method::WalletCommandMethod::SignAndSubmitTransaction) - /// - [`SubmitAndStoreTransaction`](crate::method::WalletCommandMethod::SubmitAndStoreTransaction) + /// - [`ClaimOutputs`](crate::method::WalletMethod::ClaimOutputs) + /// - [`Send`](crate::method::WalletMethod::Send) + /// - [`SendOutputs`](crate::method::WalletMethod::SendOutputs) + /// - [`SignAndSubmitTransaction`](crate::method::WalletMethod::SignAndSubmitTransaction) + /// - [`SubmitAndStoreTransaction`](crate::method::WalletMethod::SubmitAndStoreTransaction) SentTransaction(TransactionWithMetadataDto), /// Response for: - /// - [`GetParticipationEvent`](crate::method::WalletCommandMethod::GetParticipationEvent) + /// - [`GetParticipationEvent`](crate::method::WalletMethod::GetParticipationEvent) #[cfg(feature = "participation")] #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] ParticipationEvent(Option), /// Response for: - /// - [`GetParticipationEventIds`](crate::method::WalletCommandMethod::GetParticipationEventIds) + /// - [`GetParticipationEventIds`](crate::method::WalletMethod::GetParticipationEventIds) #[cfg(feature = "participation")] #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] ParticipationEventIds(Vec), /// Response for: - /// - [`GetParticipationEventStatus`](crate::method::WalletCommandMethod::GetParticipationEventStatus) + /// - [`GetParticipationEventStatus`](crate::method::WalletMethod::GetParticipationEventStatus) #[cfg(feature = "participation")] #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] ParticipationEventStatus(ParticipationEventStatus), /// Response for: - /// - [`GetParticipationEvents`](crate::method::WalletCommandMethod::GetParticipationEvents) - /// - [`RegisterParticipationEvents`](crate::method::WalletCommandMethod::RegisterParticipationEvents) + /// - [`GetParticipationEvents`](crate::method::WalletMethod::GetParticipationEvents) + /// - [`RegisterParticipationEvents`](crate::method::WalletMethod::RegisterParticipationEvents) #[cfg(feature = "participation")] #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] ParticipationEvents(HashMap), /// Response for: - /// - [`GetVotingPower`](crate::method::WalletCommandMethod::GetVotingPower) + /// - [`GetVotingPower`](crate::method::WalletMethod::GetVotingPower) #[cfg(feature = "participation")] #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] VotingPower(String), /// Response for: - /// - [`GetParticipationOverview`](crate::method::WalletCommandMethod::GetParticipationOverview) + /// - [`GetParticipationOverview`](crate::method::WalletMethod::GetParticipationOverview) #[cfg(feature = "participation")] #[cfg_attr(docsrs, doc(cfg(feature = "participation")))] ParticipationOverview(ParticipationOverview), diff --git a/bindings/core/tests/combined.rs b/bindings/core/tests/combined.rs index 7025bf713e..79d838ed83 100644 --- a/bindings/core/tests/combined.rs +++ b/bindings/core/tests/combined.rs @@ -20,7 +20,7 @@ use iota_sdk::{ }; use iota_sdk_bindings_core::{ call_client_method, call_secret_manager_method, CallMethod, ClientMethod, Response, Result, SecretManagerMethod, - WalletCommandMethod, WalletMethod, WalletOptions, + WalletMethod, WalletOptions, }; use pretty_assertions::assert_eq; @@ -49,9 +49,7 @@ async fn create_wallet() -> Result<()> { .await?; let response = wallet - .call_method(WalletMethod::CallMethod { - method: WalletCommandMethod::UnspentOutputs { filter_options: None }, - }) + .call_method(WalletMethod::UnspentOutputs { filter_options: None }) .await; match response { diff --git a/bindings/nodejs/lib/types/wallet/bridge/account.ts b/bindings/nodejs/lib/types/wallet/bridge/account.ts index 8c4b8cf6eb..363f743486 100644 --- a/bindings/nodejs/lib/types/wallet/bridge/account.ts +++ b/bindings/nodejs/lib/types/wallet/bridge/account.ts @@ -145,6 +145,10 @@ export type __PendingTransactionsMethod__ = { name: 'pendingTransactions'; }; +export type __ImplicitAccountCreationAddressMethod__ = { + name: 'implicitAccountCreationAddress'; +}; + export type __IncomingTransactionsMethod__ = { name: 'incomingTransactions'; }; diff --git a/bindings/nodejs/lib/types/wallet/bridge/index.ts b/bindings/nodejs/lib/types/wallet/bridge/index.ts index fc96daea69..f7cfaee903 100644 --- a/bindings/nodejs/lib/types/wallet/bridge/index.ts +++ b/bindings/nodejs/lib/types/wallet/bridge/index.ts @@ -15,6 +15,7 @@ import type { __AddressesWithUnspentOutputsMethod__, __OutputsMethod__, __PendingTransactionsMethod__, + __ImplicitAccountCreationAddressMethod__, __IncomingTransactionsMethod__, __TransactionsMethod__, __UnspentOutputsMethod__, @@ -96,6 +97,7 @@ export type __AccountMethod__ = | __AddressesWithUnspentOutputsMethod__ | __OutputsMethod__ | __PendingTransactionsMethod__ + | __ImplicitAccountCreationAddressMethod__ | __IncomingTransactionsMethod__ | __TransactionsMethod__ | __UnspentOutputsMethod__ diff --git a/bindings/nodejs/lib/wallet/account.ts b/bindings/nodejs/lib/wallet/account.ts index 7f292745e9..23cbc888d4 100644 --- a/bindings/nodejs/lib/wallet/account.ts +++ b/bindings/nodejs/lib/wallet/account.ts @@ -758,6 +758,22 @@ export class Account { return plainToInstance(TransactionWithMetadata, parsed.payload); } + /** + * Returns the implicit account creation address of the wallet if it is Ed25519 based. + * + * @returns The implicit account creation address. + */ + async implicitAccountCreationAddress(): Promise { + const response = await this.methodHandler.callAccountMethod( + this.meta.index, + { + name: 'implicitAccountCreationAddress', + }, + ); + + return JSON.parse(response).payload; + } + /** * List all incoming transactions of the account. * diff --git a/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py b/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py index 3d47fada8f..36e2897b9e 100644 --- a/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py +++ b/bindings/python/examples/how_tos/nft_collection/00_mint_issuer_nft.py @@ -28,21 +28,21 @@ ) -transaction = account.mint_nfts([params]) +tx = account.mint_nfts([params]) # Wait for transaction to get included block_id = account.reissue_transaction_until_included( - transaction.transaction_id) + tx.transaction_id) print( f'Block sent: {os.environ["EXPLORER_URL"]}/block/{block_id}') -essence = transaction.payload["essence"] +transaction = tx.payload.transaction -for outputIndex, output in enumerate(essence["outputs"]): +for outputIndex, output in enumerate(transaction.outputs): # New minted NFT id is empty in the output if output["type"] == 6 and output["nftId"] == '0x0000000000000000000000000000000000000000000000000000000000000000': outputId = Utils.compute_output_id( - transaction.transaction_id, outputIndex) + tx.transaction_id, outputIndex) nftId = Utils.compute_nft_id(outputId) print(f'New minted NFT id: {nftId}') diff --git a/bindings/python/examples/wallet/offline_signing/2_sign_transaction.py b/bindings/python/examples/wallet/offline_signing/2_sign_transaction.py index 12c74dfe07..6bbfb52dc6 100644 --- a/bindings/python/examples/wallet/offline_signing/2_sign_transaction.py +++ b/bindings/python/examples/wallet/offline_signing/2_sign_transaction.py @@ -34,7 +34,7 @@ wallet.set_stronghold_password(os.environ["STRONGHOLD_PASSWORD"]) # Signs prepared transaction offline. -signed_transaction_data = account.sign_transaction_essence( +signed_transaction_data = account.sign_transaction( prepared_transaction_data) print("Signed transaction.") diff --git a/bindings/python/iota_sdk/__init__.py b/bindings/python/iota_sdk/__init__.py index 7b244a3be0..a08515c175 100644 --- a/bindings/python/iota_sdk/__init__.py +++ b/bindings/python/iota_sdk/__init__.py @@ -41,6 +41,7 @@ from .types.send_params import * from .types.token_scheme import * from .types.transaction import * +from .types.transaction_with_metadata import * from .types.transaction_data import * from .types.transaction_options import * from .types.unlock import * diff --git a/bindings/python/iota_sdk/client/client.py b/bindings/python/iota_sdk/client/client.py index 79736ad1f8..fbcd621509 100644 --- a/bindings/python/iota_sdk/client/client.py +++ b/bindings/python/iota_sdk/client/client.py @@ -5,24 +5,21 @@ from datetime import timedelta from typing import Any, Dict, List, Optional, Union import humps -from dacite import from_dict from iota_sdk.external import create_client, call_client_method, listen_mqtt from iota_sdk.client._node_core_api import NodeCoreAPI from iota_sdk.client._node_indexer_api import NodeIndexerAPI from iota_sdk.client._high_level_api import HighLevelAPI from iota_sdk.client._utils import ClientUtils -from iota_sdk.secret_manager.secret_manager import LedgerNanoSecretManager, MnemonicSecretManager, StrongholdSecretManager, SeedSecretManager from iota_sdk.types.block.signed_block import UnsignedBlock from iota_sdk.types.common import HexStr, Node from iota_sdk.types.feature import Feature from iota_sdk.types.native_token import NativeToken from iota_sdk.types.network_info import NetworkInfo from iota_sdk.types.output import AccountOutput, BasicOutput, FoundryOutput, NftOutput, deserialize_output -from iota_sdk.types.payload import Payload, TransactionPayload +from iota_sdk.types.payload import Payload from iota_sdk.types.token_scheme import SimpleTokenScheme from iota_sdk.types.unlock_condition import UnlockCondition -from iota_sdk.types.transaction_data import PreparedTransactionData class ClientError(Exception): @@ -373,21 +370,6 @@ def unhealthy_nodes(self) -> List[Dict[str, Any]]: """ return self._call_method('unhealthyNodes') - def sign_transaction( - self, - secret_manager: Union[LedgerNanoSecretManager, MnemonicSecretManager, SeedSecretManager, StrongholdSecretManager], - prepared_transaction_data: PreparedTransactionData) -> TransactionPayload: - """Sign a transaction. - - Args: - secret_manager: One of the supported secret managers. - prepared_transaction_data: a prepared transaction to sign. - """ - return from_dict(TransactionPayload, self._call_method('signTransaction', { - 'secretManager': secret_manager, - 'preparedTransactionData': prepared_transaction_data - })) - def build_basic_block( self, issuer_id: HexStr, diff --git a/bindings/python/iota_sdk/secret_manager/secret_manager.py b/bindings/python/iota_sdk/secret_manager/secret_manager.py index 97c9fec4cc..1aa65e9886 100644 --- a/bindings/python/iota_sdk/secret_manager/secret_manager.py +++ b/bindings/python/iota_sdk/secret_manager/secret_manager.py @@ -11,7 +11,7 @@ from iota_sdk.types.common import HexStr from iota_sdk.types.signature import Ed25519Signature, Bip44 from iota_sdk.types.transaction_data import PreparedTransactionData -from iota_sdk.types.payload import TransactionPayload +from iota_sdk.types.payload import SignedTransactionPayload class LedgerNanoSecretManager(dict): @@ -268,13 +268,13 @@ def sign_secp256k1_ecdsa(self, message: HexStr, chain: Bip44): }) def sign_transaction( - self, prepared_transaction_data: PreparedTransactionData) -> TransactionPayload: + self, prepared_transaction_data: PreparedTransactionData) -> SignedTransactionPayload: """Sign a transaction. Args: prepare_transaction_data: The prepared transaction data that needs to be signed. """ - return from_dict(TransactionPayload, self._call_method('signTransaction', { + return from_dict(SignedTransactionPayload, self._call_method('signTransaction', { 'preparedTransactionData': prepared_transaction_data.to_dict() })) diff --git a/bindings/python/iota_sdk/types/balance.py b/bindings/python/iota_sdk/types/balance.py index 5144c0897b..791dbb96c3 100644 --- a/bindings/python/iota_sdk/types/balance.py +++ b/bindings/python/iota_sdk/types/balance.py @@ -5,7 +5,7 @@ from typing import List, Optional from dataclasses import dataclass, field from dataclasses_json import config -from iota_sdk.types.common import HexStr, json +from iota_sdk.types.common import hex_str_decoder, HexStr, json @json @@ -62,8 +62,14 @@ class NativeTokensBalance: metadata: Some metadata of the native token. """ token_id: HexStr - total: HexStr - available: HexStr + total: int = field(metadata=config( + encoder=hex, + decoder=hex_str_decoder, + )) + available: int = field(metadata=config( + encoder=hex, + decoder=hex_str_decoder, + )) metadata: Optional[HexStr] diff --git a/bindings/python/iota_sdk/types/block/basic.py b/bindings/python/iota_sdk/types/block/basic.py index 77495d54c8..b7c6661958 100644 --- a/bindings/python/iota_sdk/types/block/basic.py +++ b/bindings/python/iota_sdk/types/block/basic.py @@ -31,5 +31,5 @@ class BasicBlock: )) payload: Optional[Payload] = None type: int = field( - default_factory=lambda: BlockType.Basic, + default_factory=lambda: int(BlockType.Basic), init=False) diff --git a/bindings/python/iota_sdk/types/block/validation.py b/bindings/python/iota_sdk/types/block/validation.py index bd99ea61e1..9f9c070732 100644 --- a/bindings/python/iota_sdk/types/block/validation.py +++ b/bindings/python/iota_sdk/types/block/validation.py @@ -28,5 +28,5 @@ class ValidationBlock: highest_supported_version: int protocol_parameters_hash: HexStr type: int = field( - default_factory=lambda: BlockType.Validation, + default_factory=lambda: int(BlockType.Validation), init=False) diff --git a/bindings/python/iota_sdk/types/common.py b/bindings/python/iota_sdk/types/common.py index 261f62e3f2..3cd9ee4218 100644 --- a/bindings/python/iota_sdk/types/common.py +++ b/bindings/python/iota_sdk/types/common.py @@ -112,6 +112,11 @@ def opt_int_encoder(value): return None +def hex_str_decoder(value: str) -> int: + """Parses a given string as a hexadecimal integer.""" + return int(value, 16) + + @json @dataclass class AddressAndAmount(): diff --git a/bindings/python/iota_sdk/types/essence.py b/bindings/python/iota_sdk/types/essence.py deleted file mode 100644 index 32df2042e6..0000000000 --- a/bindings/python/iota_sdk/types/essence.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2023 IOTA Stiftung -# SPDX-License-Identifier: Apache-2.0 - -from __future__ import annotations -from enum import IntEnum -from typing import TYPE_CHECKING, Optional, List, TypeAlias - -from dataclasses import dataclass, field - -from iota_sdk.types.common import HexStr, json, SlotIndex -from iota_sdk.types.mana import ManaAllotment -from iota_sdk.types.input import UtxoInput -from iota_sdk.types.context_input import ContextInput -from iota_sdk.types.output import Output - -# Required to prevent circular import -if TYPE_CHECKING: - from iota_sdk.types.payload import Payload - - -class EssenceType(IntEnum): - """Block payload types. - - Attributes: - RegularTransactionEssence (2): A Regular Transaction Essence. - """ - RegularTransactionEssence = 2 - - -@json -@dataclass -class RegularTransactionEssence: - """Describes the essence data making up a transaction by defining its inputs, outputs, and an optional payload. - - Attributes: - network_id: The unique value denoting whether the block was meant for mainnet, shimmer, testnet, or a private network. - It consists of the first 8 bytes of the BLAKE2b-256 hash of the network name. - creation_slot: The slot index in which the transaction was created. - inputs: The inputs to consume in order to fund the outputs of the Transaction Payload. - inputs_commitment: BLAKE2b-256 hash serving as a commitment to the serialized outputs referenced by Inputs. - outputs: The outputs that are created by the Transaction Payload - context_inputs: The inputs that provide additional contextual information for the execution of a transaction. - allotments: The allotments of Mana which which will be added upon commitment of the slot. - capabilities: The capability bitflags of the transaction. - payload: An optional tagged data payload - """ - network_id: str - creation_slot: SlotIndex - inputs: List[UtxoInput] - inputs_commitment: HexStr - outputs: List[Output] - context_inputs: Optional[List[ContextInput]] = None - allotments: Optional[List[ManaAllotment]] = None - capabilities: HexStr = field(default='0x', init=False) - payload: Optional[Payload] = None - type: int = field( - default_factory=lambda: EssenceType.RegularTransactionEssence, - init=False) - - def with_capabilities(self, capabilities: bytes): - """Sets the transaction capabilities from a byte array. - Attributes: - capabilities: The transaction capabilities bitflags. - """ - self.capabilities = '0x' + capabilities.hex() - - -TransactionEssence: TypeAlias = RegularTransactionEssence diff --git a/bindings/python/iota_sdk/types/native_token.py b/bindings/python/iota_sdk/types/native_token.py index 7232f8dacc..c382c31070 100644 --- a/bindings/python/iota_sdk/types/native_token.py +++ b/bindings/python/iota_sdk/types/native_token.py @@ -1,9 +1,10 @@ # Copyright 2023 IOTA Stiftung # SPDX-License-Identifier: Apache-2.0 -from dataclasses import dataclass +from dataclasses import dataclass, field +from dataclasses_json import config -from iota_sdk.types.common import HexStr, json +from iota_sdk.types.common import hex_str_decoder, HexStr, json @json @@ -16,4 +17,7 @@ class NativeToken(): amount: The amount of native tokens. """ id: HexStr - amount: HexStr + amount: int = field(metadata=config( + encoder=hex, + decoder=hex_str_decoder, + )) diff --git a/bindings/python/iota_sdk/types/payload.py b/bindings/python/iota_sdk/types/payload.py index 9685c504d1..dd222b435a 100644 --- a/bindings/python/iota_sdk/types/payload.py +++ b/bindings/python/iota_sdk/types/payload.py @@ -6,7 +6,7 @@ from typing import Any, Dict, List, TypeAlias, Union from dataclasses import dataclass, field from iota_sdk.types.common import HexStr, json -from iota_sdk.types.essence import TransactionEssence +from iota_sdk.types.transaction import Transaction from iota_sdk.types.unlock import SignatureUnlock, ReferenceUnlock @@ -15,11 +15,11 @@ class PayloadType(IntEnum): Attributes: TaggedData (0): A tagged data payload. - Transaction (1): A transaction payload. + SignedTransaction (1): A signed transaction payload. CandidacyAnnouncement (2): A candidacy announcement payload. """ TaggedData = 0 - Transaction = 1 + SignedTransaction = 1 CandidacyAnnouncement = 2 @@ -42,18 +42,18 @@ class TaggedDataPayload: @json @dataclass -class TransactionPayload: - """A transaction payload. +class SignedTransactionPayload: + """A signed transaction payload. Attributes: - essence: The transaction essence. + transaction: The transaction. unlocks: The unlocks of the transaction. """ - essence: TransactionEssence + transaction: Transaction unlocks: List[Union[SignatureUnlock, ReferenceUnlock]] type: int = field( default_factory=lambda: int( - PayloadType.Transaction), + PayloadType.SignedTransaction), init=False) @@ -69,7 +69,7 @@ class CandidacyAnnouncementPayload: Payload: TypeAlias = Union[TaggedDataPayload, - TransactionPayload, CandidacyAnnouncementPayload] + SignedTransactionPayload, CandidacyAnnouncementPayload] def deserialize_payload(d: Dict[str, Any]) -> Payload: @@ -82,8 +82,8 @@ def deserialize_payload(d: Dict[str, Any]) -> Payload: payload_type = d['type'] if payload_type == PayloadType.TaggedData: return TaggedDataPayload.from_dict(d) - if payload_type == PayloadType.Transaction: - return TransactionPayload.from_dict(d) + if payload_type == PayloadType.SignedTransaction: + return SignedTransactionPayload.from_dict(d) if payload_type == PayloadType.CandidacyAnnouncement: return CandidacyAnnouncementPayload.from_dict(d) raise Exception(f'invalid payload type: {payload_type}') diff --git a/bindings/python/iota_sdk/types/send_params.py b/bindings/python/iota_sdk/types/send_params.py index 81036f1fea..cd3e404472 100644 --- a/bindings/python/iota_sdk/types/send_params.py +++ b/bindings/python/iota_sdk/types/send_params.py @@ -5,7 +5,7 @@ from dataclasses import dataclass, field from typing import Optional, List from dataclasses_json import config -from iota_sdk.types.common import HexStr, json +from iota_sdk.types.common import hex_str_decoder, HexStr, json from iota_sdk.types.native_token import NativeToken @@ -72,10 +72,12 @@ class CreateNativeTokenParams(): account_id: The ID of the corresponding account. """ circulating_supply: int = field(metadata=config( - encoder=str + encoder=hex, + decoder=hex_str_decoder, )) maximum_supply: int = field(metadata=config( - encoder=str + encoder=hex, + decoder=hex_str_decoder, )) foundry_metadata: Optional[str] = None account_id: Optional[str] = None diff --git a/bindings/python/iota_sdk/types/signature.py b/bindings/python/iota_sdk/types/signature.py index 0112b9a3f5..1ccf1b3551 100644 --- a/bindings/python/iota_sdk/types/signature.py +++ b/bindings/python/iota_sdk/types/signature.py @@ -18,7 +18,7 @@ class Ed25519Signature: """ public_key: HexStr signature: HexStr - type: int = field(default_factory=lambda: 0, init=False) + type: int = field(default=0, init=False) Signature: TypeAlias = Ed25519Signature diff --git a/bindings/python/iota_sdk/types/token_scheme.py b/bindings/python/iota_sdk/types/token_scheme.py index d243509d0c..3a60e9282d 100644 --- a/bindings/python/iota_sdk/types/token_scheme.py +++ b/bindings/python/iota_sdk/types/token_scheme.py @@ -1,9 +1,10 @@ # Copyright 2023 IOTA Stiftung # SPDX-License-Identifier: Apache-2.0 -from dataclasses import dataclass, field from typing import TypeAlias -from iota_sdk.types.common import HexStr, json +from dataclasses import dataclass, field +from dataclasses_json import config +from iota_sdk.types.common import hex_str_decoder, json @json @@ -17,10 +18,19 @@ class SimpleTokenScheme: maximum_supply: The maximum supply of the token. type: The type code of the token scheme. """ - minted_tokens: HexStr - melted_tokens: HexStr - maximum_supply: HexStr - type: int = field(default_factory=lambda: 0, init=False) + minted_tokens: int = field(metadata=config( + encoder=hex, + decoder=hex_str_decoder, + )) + melted_tokens: int = field(metadata=config( + encoder=hex, + decoder=hex_str_decoder, + )) + maximum_supply: int = field(metadata=config( + encoder=hex, + decoder=hex_str_decoder, + )) + type: int = field(default=0, init=False) TokenScheme: TypeAlias = SimpleTokenScheme diff --git a/bindings/python/iota_sdk/types/transaction.py b/bindings/python/iota_sdk/types/transaction.py index 7ae9266109..8fa4934843 100644 --- a/bindings/python/iota_sdk/types/transaction.py +++ b/bindings/python/iota_sdk/types/transaction.py @@ -2,51 +2,49 @@ # SPDX-License-Identifier: Apache-2.0 from __future__ import annotations -from dataclasses import dataclass -from typing import List, Optional -from enum import Enum -from iota_sdk.types.common import HexStr, json -from iota_sdk.types.output_metadata import OutputWithMetadata -from iota_sdk.types.payload import TransactionPayload +from typing import TYPE_CHECKING, Optional, List +from dataclasses import dataclass, field -class InclusionState(str, Enum): - """Inclusion state variants of a transaction. +from iota_sdk.types.common import HexStr, json, SlotIndex +from iota_sdk.types.mana import ManaAllotment +from iota_sdk.types.input import UtxoInput +from iota_sdk.types.context_input import ContextInput +from iota_sdk.types.output import Output - Attributes: - Pending: The transaction is pending. - Confirmed: The transaction is confirmed. - Conflicting: The transaction is conflicting. - UnknownPruned: The transaction is unknown or already pruned. - """ - Pending = 'pending' - Confirmed = 'confirmed' - Conflicting = 'conflicting' - UnknownPruned = 'unknownPruned' +# Required to prevent circular import +if TYPE_CHECKING: + from iota_sdk.types.payload import Payload @json @dataclass class Transaction: - """A transaction with some metadata. + """A transaction consuming inputs, creating outputs and carrying an optional payload. Attributes: - payload: The transaction payload. - inclusion_state: The inclusion state of the transaction. - timestamp: The timestamp of the transaction. - transaction_id: The ID of the corresponding transaction. - network_id: The ID of the network this transaction was issued in. - incoming: Indicates whether the transaction was created by the wallet or whether it was sent by someone else and is incoming. - inputs: The inputs of the transaction. - note: A note attached to the transaction. - block_id: The ID of the block that holds the transaction. + network_id: The unique value denoting whether the block was meant for mainnet, shimmer, testnet, or a private network. + It consists of the first 8 bytes of the BLAKE2b-256 hash of the network name. + creation_slot: The slot index in which the transaction was created. + context_inputs: The inputs that provide additional contextual information for the execution of a transaction. + inputs: The inputs to consume in order to fund the outputs of the Transaction Payload. + allotments: The allotments of Mana which which will be added upon commitment of the slot. + capabilities: The capability bitflags of the transaction. + outputs: The outputs that are created by the Transaction Payload + payload: An optional tagged data payload """ - payload: TransactionPayload - inclusion_state: InclusionState - timestamp: int - transaction_id: HexStr - network_id: int - incoming: bool - inputs = List[OutputWithMetadata] - note: Optional[str] = None - block_id: Optional[HexStr] = None + network_id: str + creation_slot: SlotIndex + context_inputs: List[ContextInput] + inputs: List[UtxoInput] + allotments: List[ManaAllotment] + capabilities: HexStr = field(default='0x', init=False) + outputs: List[Output] + payload: Optional[Payload] = None + + def with_capabilities(self, capabilities: bytes): + """Sets the transaction capabilities from a byte array. + Attributes: + capabilities: The transaction capabilities bitflags. + """ + self.capabilities = '0x' + capabilities.hex() diff --git a/bindings/python/iota_sdk/types/transaction_data.py b/bindings/python/iota_sdk/types/transaction_data.py index e7ab0f5092..0f38781bb4 100644 --- a/bindings/python/iota_sdk/types/transaction_data.py +++ b/bindings/python/iota_sdk/types/transaction_data.py @@ -7,8 +7,8 @@ from iota_sdk.types.address import Address from iota_sdk.types.output import Output from iota_sdk.types.output_metadata import OutputMetadata -from iota_sdk.types.essence import TransactionEssence -from iota_sdk.types.payload import TransactionPayload +from iota_sdk.types.transaction import Transaction +from iota_sdk.types.payload import SignedTransactionPayload from iota_sdk.types.signature import Bip44 from iota_sdk.types.common import json @@ -49,11 +49,11 @@ class PreparedTransactionData: """Helper class for offline signing. Attributes: - essence: The transaction essence. + transaction: The transaction. inputs_data: Data about the inputs which is required for signing. remainder: Data about a remainder. """ - essence: TransactionEssence + transaction: Transaction inputs_data: List[InputSigningData] remainder: Optional[RemainderData] = None @@ -64,8 +64,8 @@ class SignedTransactionData: """Helper class for offline signing. Attributes: - transaction_payload: The transaction payload. + payload: The transaction payload. inputs_data: Data about the inputs consumed in the transaction. """ - transaction_payload: TransactionPayload + payload: SignedTransactionPayload inputs_data: List[InputSigningData] diff --git a/bindings/python/iota_sdk/types/transaction_with_metadata.py b/bindings/python/iota_sdk/types/transaction_with_metadata.py new file mode 100644 index 0000000000..53dba6cd44 --- /dev/null +++ b/bindings/python/iota_sdk/types/transaction_with_metadata.py @@ -0,0 +1,52 @@ +# Copyright 2023 IOTA Stiftung +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations +from dataclasses import dataclass +from typing import List, Optional +from enum import Enum +from iota_sdk.types.common import HexStr, json +from iota_sdk.types.output_metadata import OutputWithMetadata +from iota_sdk.types.payload import SignedTransactionPayload + + +class InclusionState(str, Enum): + """Inclusion state variants of a transaction. + + Attributes: + Pending: The transaction is pending. + Confirmed: The transaction is confirmed. + Conflicting: The transaction is conflicting. + UnknownPruned: The transaction is unknown or already pruned. + """ + Pending = 'pending' + Confirmed = 'confirmed' + Conflicting = 'conflicting' + UnknownPruned = 'unknownPruned' + + +@json +@dataclass +class TransactionWithMetadata: + """A transaction with some metadata. + + Attributes: + payload: The transaction payload. + inclusion_state: The inclusion state of the transaction. + timestamp: The timestamp of the transaction. + transaction_id: The ID of the corresponding transaction. + network_id: The ID of the network this transaction was issued in. + incoming: Indicates whether the transaction was created by the wallet or whether it was sent by someone else and is incoming. + inputs: The inputs of the transaction. + note: A note attached to the transaction. + block_id: The ID of the block that holds the transaction. + """ + payload: SignedTransactionPayload + inclusion_state: InclusionState + timestamp: int + transaction_id: HexStr + network_id: int + incoming: bool + inputs = List[OutputWithMetadata] + note: Optional[str] = None + block_id: Optional[HexStr] = None diff --git a/bindings/python/iota_sdk/types/unlock.py b/bindings/python/iota_sdk/types/unlock.py index 4118ec5466..4a99672783 100644 --- a/bindings/python/iota_sdk/types/unlock.py +++ b/bindings/python/iota_sdk/types/unlock.py @@ -29,15 +29,7 @@ class UnlockType(IntEnum): @json @dataclass -class Unlock: - """Unlock type. - """ - type: int - - -@json -@dataclass -class SignatureUnlock(Unlock): +class SignatureUnlock: """An unlock holding a signature unlocking one or more inputs. """ signature: Ed25519Signature @@ -49,7 +41,7 @@ class SignatureUnlock(Unlock): @json @dataclass -class ReferenceUnlock(Unlock): +class ReferenceUnlock: """An unlock which must reference a previous unlock which unlocks also the input at the same index as this Reference Unlock. """ reference: int diff --git a/bindings/python/iota_sdk/utils.py b/bindings/python/iota_sdk/utils.py index e889f74cfb..687a507d9c 100644 --- a/bindings/python/iota_sdk/utils.py +++ b/bindings/python/iota_sdk/utils.py @@ -8,12 +8,12 @@ from iota_sdk.types.signature import Ed25519Signature from iota_sdk.types.address import Address, deserialize_address from iota_sdk.types.common import HexStr -from iota_sdk.types.essence import TransactionEssence +from iota_sdk.types.transaction import Transaction from iota_sdk.types.node_info import ProtocolParameters from iota_sdk.types.output_id import OutputId from iota_sdk.types.output import Output from iota_sdk.external import call_utils_method -from iota_sdk.types.payload import TransactionPayload +from iota_sdk.types.payload import SignedTransactionPayload # Required to prevent circular import if TYPE_CHECKING: @@ -177,19 +177,19 @@ def block_id(block: SignedBlock, params: ProtocolParameters) -> HexStr: }) @staticmethod - def transaction_id(transaction_payload: TransactionPayload) -> HexStr: + def transaction_id(payload: SignedTransactionPayload) -> HexStr: """ Compute the transaction ID (Blake2b256 hash of the provided transaction payload) of a transaction payload. """ return _call_method('transactionId', { - 'payload': transaction_payload.as_dict() + 'payload': payload.as_dict() }) @staticmethod - def transaction_signing_hash(essence: TransactionEssence) -> HexStr: + def transaction_signing_hash(transaction: Transaction) -> HexStr: """ Compute the signing hash of a transaction. """ return _call_method('transactionSigningHash', { - 'essence': essence.to_dict(), + 'transaction': transaction.to_dict(), }) @staticmethod diff --git a/bindings/python/iota_sdk/wallet/account.py b/bindings/python/iota_sdk/wallet/account.py index 4d434ea0cc..d5fd533047 100644 --- a/bindings/python/iota_sdk/wallet/account.py +++ b/bindings/python/iota_sdk/wallet/account.py @@ -20,7 +20,7 @@ from iota_sdk.types.output_params import OutputParams from iota_sdk.types.transaction_data import PreparedTransactionData, SignedTransactionData from iota_sdk.types.send_params import CreateAccountOutputParams, CreateNativeTokenParams, MintNftParams, SendNativeTokensParams, SendNftParams, SendParams -from iota_sdk.types.transaction import Transaction +from iota_sdk.types.transaction_with_metadata import TransactionWithMetadata from iota_sdk.types.transaction_options import TransactionOptions from iota_sdk.types.consolidation_params import ConsolidationParams @@ -82,7 +82,7 @@ def get_metadata(self) -> AccountMetadata: self.meta["alias"], self.meta["coinType"], self.meta["index"]) def burn( - self, burn: Burn, options: Optional[TransactionOptions] = None) -> Transaction: + self, burn: Burn, options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """A generic function that can be used to burn native tokens, nfts, foundries and aliases. """ return self.prepare_burn(burn, options).send() @@ -129,7 +129,7 @@ def prepare_burn_nft(self, return PreparedTransaction(self, prepared) def consolidate_outputs( - self, params: ConsolidationParams) -> Transaction: + self, params: ConsolidationParams) -> TransactionWithMetadata: """Consolidate outputs. """ return self.prepare_consolidate_outputs(params).send() @@ -147,7 +147,7 @@ def prepare_consolidate_outputs( def create_account_output(self, params: Optional[CreateAccountOutputParams] = None, - options: Optional[TransactionOptions] = None) -> Transaction: + options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Create an account output. """ return self.prepare_create_account_output(params, options).send() @@ -221,10 +221,10 @@ def get_output(self, output_id: OutputId) -> OutputData: } )) - def get_transaction(self, transaction_id: HexStr) -> Transaction: + def get_transaction(self, transaction_id: HexStr) -> TransactionWithMetadata: """Get transaction. """ - return Transaction.from_dict(self._call_account_method( + return TransactionWithMetadata.from_dict(self._call_account_method( 'getTransaction', { 'transactionId': transaction_id } @@ -270,21 +270,28 @@ def unspent_outputs( ) return [from_dict(OutputData, o) for o in outputs] - def incoming_transactions(self) -> List[Transaction]: + def implicit_account_creation_address(self) -> str: + """Returns the implicit account creation address of the wallet if it is Ed25519 based. + """ + return self._call_account_method( + 'implicitAccountCreationAddress' + ) + + def incoming_transactions(self) -> List[TransactionWithMetadata]: """Returns all incoming transactions of the account. """ transactions = self._call_account_method( 'incomingTransactions' ) - return [Transaction.from_dict(tx) for tx in transactions] + return [TransactionWithMetadata.from_dict(tx) for tx in transactions] - def transactions(self) -> List[Transaction]: + def transactions(self) -> List[TransactionWithMetadata]: """Returns all transaction of the account. """ transactions = self._call_account_method( 'transactions' ) - return [Transaction.from_dict(tx) for tx in transactions] + return [TransactionWithMetadata.from_dict(tx) for tx in transactions] def pending_transactions(self): """Returns all pending transactions of the account. @@ -292,10 +299,10 @@ def pending_transactions(self): transactions = self._call_account_method( 'pendingTransactions' ) - return [Transaction.from_dict(tx) for tx in transactions] + return [TransactionWithMetadata.from_dict(tx) for tx in transactions] def create_native_token(self, params: CreateNativeTokenParams, - options: Optional[TransactionOptions] = None) -> Transaction: + options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Create native token. """ return self.prepare_create_native_token(params, options).send() @@ -316,7 +323,7 @@ def prepare_create_native_token(self, params: CreateNativeTokenParams, def melt_native_token(self, token_id: HexStr, melt_amount: int, - options: Optional[TransactionOptions] = None) -> Transaction: + options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Melt native tokens. This happens with the foundry output which minted them, by increasing it's `melted_tokens` field. """ @@ -340,7 +347,7 @@ def prepare_melt_native_token(self, return PreparedTransaction(self, prepared) def mint_native_token(self, token_id: HexStr, mint_amount: int, - options: Optional[TransactionOptions] = None) -> Transaction: + options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Mint additional native tokens. """ return self.prepare_mint_native_token( @@ -360,7 +367,7 @@ def prepare_mint_native_token(self, token_id: HexStr, mint_amount: int, return PreparedTransaction(self, prepared) def mint_nfts(self, params: List[MintNftParams], - options: Optional[TransactionOptions] = None) -> Transaction: + options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Mint NFTs. """ return self.prepare_mint_nfts(params, options).send() @@ -413,7 +420,7 @@ def prepare_send(self, params: List[SendParams], return PreparedTransaction(self, prepared) def send_transaction( - self, outputs: List[Output], options: Optional[TransactionOptions] = None) -> Transaction: + self, outputs: List[Output], options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Send a transaction. """ return self.prepare_transaction(outputs, options).send() @@ -455,10 +462,10 @@ def sync(self, options: Optional[SyncOptions] = None) -> Balance: )) def send(self, amount: int, address: str, - options: Optional[TransactionOptions] = None) -> Transaction: + options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Send base coins. """ - return Transaction.from_dict(self._call_account_method( + return TransactionWithMetadata.from_dict(self._call_account_method( 'send', { 'amount': str(amount), 'address': address, @@ -467,10 +474,10 @@ def send(self, amount: int, address: str, )) def send_with_params( - self, params: List[SendParams], options: Optional[TransactionOptions] = None) -> Transaction: + self, params: List[SendParams], options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Send base coins to multiple addresses or with additional parameters. """ - return Transaction.from_dict(self._call_account_method( + return TransactionWithMetadata.from_dict(self._call_account_method( 'sendWithParams', { 'params': [param.to_dict() for param in params], 'options': options @@ -478,7 +485,7 @@ def send_with_params( )) def send_native_tokens( - self, params: List[SendNativeTokensParams], options: Optional[TransactionOptions] = None) -> Transaction: + self, params: List[SendNativeTokensParams], options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Send native tokens. """ return self.prepare_send_native_tokens(params, options).send() @@ -498,7 +505,7 @@ def prepare_send_native_tokens( return PreparedTransaction(self, prepared) def send_nft(self, params: List[SendNftParams], - options: Optional[TransactionOptions] = None) -> Transaction: + options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Send nft. """ return self.prepare_send_nft(params, options).send() @@ -534,51 +541,51 @@ def set_default_sync_options(self, options: SyncOptions): } ) - def sign_transaction_essence( + def sign_transaction( self, prepared_transaction_data: PreparedTransactionData) -> SignedTransactionData: - """Sign a transaction essence. + """Sign a transaction. """ return SignedTransactionData.from_dict(self._call_account_method( - 'signTransactionEssence', { + 'signTransaction', { 'preparedTransactionData': prepared_transaction_data } )) def sign_and_submit_transaction( - self, prepared_transaction_data: PreparedTransactionData) -> Transaction: + self, prepared_transaction_data: PreparedTransactionData) -> TransactionWithMetadata: """Validate the transaction, sign it, submit it to a node and store it in the account. """ - return Transaction.from_dict(self._call_account_method( + return TransactionWithMetadata.from_dict(self._call_account_method( 'signAndSubmitTransaction', { 'preparedTransactionData': prepared_transaction_data } )) def submit_and_store_transaction( - self, signed_transaction_data: SignedTransactionData) -> Transaction: + self, signed_transaction_data: SignedTransactionData) -> TransactionWithMetadata: """Submit and store transaction. """ - return Transaction.from_dict(self._call_account_method( + return TransactionWithMetadata.from_dict(self._call_account_method( 'submitAndStoreTransaction', { 'signedTransactionData': signed_transaction_data } )) def claim_outputs( - self, output_ids_to_claim: List[OutputId]) -> Transaction: + self, output_ids_to_claim: List[OutputId]) -> TransactionWithMetadata: """Claim outputs. """ - return Transaction.from_dict(self._call_account_method( + return TransactionWithMetadata.from_dict(self._call_account_method( 'claimOutputs', { 'outputIdsToClaim': output_ids_to_claim } )) def send_outputs( - self, outputs: List[Output], options: Optional[TransactionOptions] = None) -> Transaction: + self, outputs: List[Output], options: Optional[TransactionOptions] = None) -> TransactionWithMetadata: """Send outputs in a transaction. """ - return Transaction.from_dict(self._call_account_method( + return TransactionWithMetadata.from_dict(self._call_account_method( 'sendOutputs', { 'outputs': outputs, 'options': options, diff --git a/bindings/python/iota_sdk/wallet/prepared_transaction.py b/bindings/python/iota_sdk/wallet/prepared_transaction.py index c2a9e0b802..80c3fde12e 100644 --- a/bindings/python/iota_sdk/wallet/prepared_transaction.py +++ b/bindings/python/iota_sdk/wallet/prepared_transaction.py @@ -6,7 +6,7 @@ from typing import TYPE_CHECKING, Dict, Union from dacite import from_dict -from iota_sdk.types.transaction import Transaction +from iota_sdk.types.transaction_with_metadata import TransactionWithMetadata from iota_sdk.types.transaction_data import PreparedTransactionData # Required to prevent circular import @@ -42,7 +42,7 @@ def prepared_transaction_data(self) -> PreparedTransactionData: self.prepared_transaction_data_dto, PreparedTransactionData) else from_dict( PreparedTransactionData, self.prepared_transaction_data_dto) - def send(self) -> Transaction: + def send(self) -> TransactionWithMetadata: """Send a transaction. Internally just calls `sign_and_submit_transaction`. Returns: @@ -51,13 +51,13 @@ def send(self) -> Transaction: return self.sign_and_submit_transaction() def sign(self): - """Sign a prepared transaction essence using the account's private key and returns - the signed transaction essence. + """Sign a prepared transaction using the account's private key and returns + the signed transaction. """ - return self.account.sign_transaction_essence( + return self.account.sign_transaction( self.prepared_transaction_data()) - def sign_and_submit_transaction(self) -> Transaction: + def sign_and_submit_transaction(self) -> TransactionWithMetadata: """Sign and submit a transaction using prepared transaction data. Returns: diff --git a/bindings/python/tests/test_block.py b/bindings/python/tests/test_block.py index 222af92562..8a76a91b87 100644 --- a/bindings/python/tests/test_block.py +++ b/bindings/python/tests/test_block.py @@ -85,22 +85,21 @@ def test_basic_block_with_tx_payload(): "shallowLikeParents": [], "maxBurnedMana": "180500", "payload": {"type": 1, - "essence": {"type": 1, - "networkId": "1856588631910923207", - "inputs": [{"type": 0, - "transactionId": "0xc6765035e75e319e9cd55ab16e7619f6cd658e7f421c71d9fe276c77fdf3f5b3", - "transactionOutputIndex": 1}], - "inputsCommitment": "0x2468f946993ac949c890d7f895797c6b86075dc1e1556f04f3772903eaf51932", - "outputs": [{"type": 3, - "amount": "1000000", - "unlockConditions": [{"type": 0, - "address": {"type": 0, - "pubKeyHash": "0xa119005b26d46fc74cf9188b3cef8d01623e68146741ee698cabefd425dc01be"}}]}, - {"type": 3, - "amount": "995000000", - "unlockConditions": [{"type": 0, - "address": {"type": 0, - "pubKeyHash": "0xa119005b26d46fc74cf9188b3cef8d01623e68146741ee698cabefd425dc01be"}}]}]}, + "transaction": { + "networkId": "1856588631910923207", + "inputs": [{"type": 0, + "transactionId": "0xc6765035e75e319e9cd55ab16e7619f6cd658e7f421c71d9fe276c77fdf3f5b3", + "transactionOutputIndex": 1}], + "outputs": [{"type": 3, + "amount": "1000000", + "unlockConditions": [{"type": 0, + "address": {"type": 0, + "pubKeyHash": "0xa119005b26d46fc74cf9188b3cef8d01623e68146741ee698cabefd425dc01be"}}]}, + {"type": 3, + "amount": "995000000", + "unlockConditions": [{"type": 0, + "address": {"type": 0, + "pubKeyHash": "0xa119005b26d46fc74cf9188b3cef8d01623e68146741ee698cabefd425dc01be"}}]}]}, "unlocks": [{"type": 0, "signature": {"type": 0, "publicKey": "0xa7af600976f440ec97d7bddbf17eacf0bfbf710e8cfb4ae3eae475d4ae8e1b16", @@ -108,7 +107,7 @@ def test_basic_block_with_tx_payload(): block = BasicBlock.from_dict(block_dict) assert block.to_dict() == block_dict assert isinstance(block.payload, get_args(Payload)) - assert block.payload.type == PayloadType.Transaction + assert block.payload.type == PayloadType.SignedTransaction @pytest.mark.skip(reason="https://github.com/iotaledger/iota-sdk/issues/1387") @@ -117,8 +116,8 @@ def test_basic_block_with_tx_payload_all_output_types(): "type": 0, "strongParents": [ "0x053296e7434e8a4d602f8db30a5aaf16c01140212fe79d8132137cda1c38a60a", "0x559ec1d9a31c55bd27588ada2ade70fb5b13764ddd600e29c3b018761ba30e15", "0xe78e8cdbbeda89e3408eed51b77e0db5ba035f5f3bf79a8365435bba40697693", "0xee9d6e45dbc080694e6c827fecbc31ad9f654cf57404bc98f4cbca033f8e3139"], "weakParents": [], "shallowLikeParents": [], "payload": { - "type": 1, "essence": { - "type": 1, "networkId": "1856588631910923207", "inputs": [ + "type": 1, "transaction": { + "networkId": "1856588631910923207", "inputs": [ { "type": 0, "transactionId": "0xa49f5a764c3fe22f702b5b238a75a648faae1863f61c14fac51ba58d26acb823", "transactionOutputIndex": 9}, { "type": 0, "transactionId": "0x6f23b39ebe433f8b522d2e4360186cd3e6b21baf46c0a591c801161e505330b4", "transactionOutputIndex": 0}, { @@ -249,7 +248,7 @@ def test_basic_block_with_tx_payload_all_output_types(): block = BasicBlock.from_dict(block_dict) assert block.to_dict() == block_dict assert isinstance(block.payload, get_args(Payload)) - assert block.payload.type == PayloadType.Transaction + assert block.payload.type == PayloadType.SignedTransaction @pytest.mark.skip(reason="https://github.com/iotaledger/iota-sdk/issues/1387") @@ -264,28 +263,28 @@ def test_basic_block_with_tx_payload_with_tagged_data_payload(): "shallowLikeParents": [], "maxBurnedMana": "180500", "payload": {"type": 1, - "essence": {"type": 1, - "networkId": "1856588631910923207", - "inputs": [{"type": 0, - "transactionId": "0xeccfbdb73c0a4c9c0301b53a17e5aa301fbf0b079db9e88ff0e32e9e64214b28", - "transactionOutputIndex": 5}, - {"type": 0, - "transactionId": "0xf8052938858750c9c69b92b615a685fa2bb5833912b264142fc724e9510b0d0e", - "transactionOutputIndex": 0}], - "inputsCommitment": "0x9702f2a625db14db2f67289828a9fdbe342477393572b9165b19964b2449061a", - "outputs": [{"type": 3, - "amount": "1000000", - "unlockConditions": [{"type": 0, - "address": {"type": 0, - "pubKeyHash": "0x60200bad8137a704216e84f8f9acfe65b972d9f4155becb4815282b03cef99fe"}}]}, - {"type": 3, - "amount": "50600", - "unlockConditions": [{"type": 0, - "address": {"type": 0, - "pubKeyHash": "0x74e8b1f10396eb5e8aeb16d666416802722436a88b5dd1a88e59c170b724c9cc"}}]}], - "payload": {"type": 5, - "tag": "0x746167", - "data": "0x64617461"}}, + "transaction": { + "networkId": "1856588631910923207", + "inputs": [{"type": 0, + "transactionId": "0xeccfbdb73c0a4c9c0301b53a17e5aa301fbf0b079db9e88ff0e32e9e64214b28", + "transactionOutputIndex": 5}, + {"type": 0, + "transactionId": "0xf8052938858750c9c69b92b615a685fa2bb5833912b264142fc724e9510b0d0e", + "transactionOutputIndex": 0}], + "inputsCommitment": "0x9702f2a625db14db2f67289828a9fdbe342477393572b9165b19964b2449061a", + "outputs": [{"type": 3, + "amount": "1000000", + "unlockConditions": [{"type": 0, + "address": {"type": 0, + "pubKeyHash": "0x60200bad8137a704216e84f8f9acfe65b972d9f4155becb4815282b03cef99fe"}}]}, + {"type": 3, + "amount": "50600", + "unlockConditions": [{"type": 0, + "address": {"type": 0, + "pubKeyHash": "0x74e8b1f10396eb5e8aeb16d666416802722436a88b5dd1a88e59c170b724c9cc"}}]}], + "payload": {"type": 5, + "tag": "0x746167", + "data": "0x64617461"}}, "unlocks": [{"type": 0, "signature": {"type": 0, "publicKey": "0x67b7fc3f78763c9394fc4fcdb52cf3a973b6e064bdc3defb40a6cb2c880e6f5c", @@ -295,4 +294,4 @@ def test_basic_block_with_tx_payload_with_tagged_data_payload(): block = BasicBlock.from_dict(block_dict) assert block.to_dict() == block_dict assert isinstance(block.payload, get_args(Payload)) - assert block.payload.type == PayloadType.Transaction + assert block.payload.type == PayloadType.SignedTransaction diff --git a/cli/src/cli.rs b/cli/src/cli.rs index 92aa7b4764..49a40fc799 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -27,7 +27,7 @@ use crate::{ }; const DEFAULT_LOG_LEVEL: &str = "debug"; -const DEFAULT_NODE_URL: &str = "https://api.testnet.shimmer.network"; +const DEFAULT_NODE_URL: &str = "http://localhost:8080"; const DEFAULT_STRONGHOLD_SNAPSHOT_PATH: &str = "./stardust-cli-wallet.stronghold"; const DEFAULT_WALLET_DATABASE_PATH: &str = "./stardust-cli-wallet-db"; diff --git a/cli/src/wallet_cli/completer.rs b/cli/src/wallet_cli/completer.rs index ea2abb4748..c7ee9763b4 100644 --- a/cli/src/wallet_cli/completer.rs +++ b/cli/src/wallet_cli/completer.rs @@ -23,6 +23,7 @@ const WALLET_COMMANDS: &[&str] = &[ "destroy-foundry", "exit", "faucet", + "implicit-account-creation-address", "melt-native-token", "mint-native-token", "mint-nft", diff --git a/cli/src/wallet_cli/mod.rs b/cli/src/wallet_cli/mod.rs index 71b73dcb23..5044ba6311 100644 --- a/cli/src/wallet_cli/mod.rs +++ b/cli/src/wallet_cli/mod.rs @@ -113,9 +113,11 @@ pub enum WalletCommand { Faucet { /// Address the faucet sends the funds to, defaults to the wallet address. address: Option, - /// URL of the faucet, default to . + /// URL of the faucet, default to . url: Option, }, + /// Returns the implicit account creation address of the wallet if it is Ed25519 based. + ImplicitAccountCreationAddress, /// Mint additional native tokens. MintNativeToken { /// Token ID to be minted, e.g. 0x087d205988b733d97fb145ae340e27a8b19554d1ceee64574d7e5ff66c45f69e7a0100000000. @@ -552,15 +554,20 @@ pub async fn faucet_command(wallet: &Wallet, address: Option, url wallet.address().await }; - let faucet_url = url - .as_deref() - .unwrap_or("https://faucet.testnet.shimmer.network/api/enqueue"); + let faucet_url = url.as_deref().unwrap_or("http://localhost:8088/api/enqueue"); println_log_info!("{}", request_funds_from_faucet(faucet_url, &address).await?); Ok(()) } +// `implicit-account-creation-address` command +pub async fn implicit_account_creation_address(wallet: &Wallet) -> Result<(), Error> { + println_log_info!("{}", wallet.implicit_account_creation_address().await?); + + Ok(()) +} + // `melt-native-token` command pub async fn melt_native_token_command(wallet: &Wallet, token_id: String, amount: String) -> Result<(), Error> { let transaction = wallet @@ -1077,6 +1084,9 @@ pub async fn prompt_internal( return Ok(PromptResponse::Done); } WalletCommand::Faucet { address, url } => faucet_command(wallet, address, url).await, + WalletCommand::ImplicitAccountCreationAddress => { + implicit_account_creation_address(wallet).await + } WalletCommand::MeltNativeToken { token_id, amount } => { melt_native_token_command(wallet, token_id, amount).await } diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index 0b83ce34c8..0a7e81eb33 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -126,7 +126,9 @@ wasm-bindgen-futures = { version = "0.4.37", default-features = false, optional [dev-dependencies] iota-sdk = { path = ".", default-features = false, features = ["rand"] } -pretty_assertions = { version = "1.4.0", default-features = false, features = [ "alloc" ] } +pretty_assertions = { version = "1.4.0", default-features = false, features = [ + "alloc", +] } dotenvy = { version = "0.15.7", default-features = false } fern-logger = { version = "0.5.0", default-features = false } @@ -340,6 +342,11 @@ name = "destroy_account_output" path = "examples/how_tos/account/destroy.rs" required-features = ["wallet", "stronghold"] +[[example]] +name = "implicit_account_creation" +path = "examples/how_tos/account/implicit_account_creation.rs" +required-features = ["wallet"] + # Outputs [[example]] diff --git a/sdk/examples/how_tos/account/implicit_account_creation.rs b/sdk/examples/how_tos/account/implicit_account_creation.rs new file mode 100644 index 0000000000..9f565da0b8 --- /dev/null +++ b/sdk/examples/how_tos/account/implicit_account_creation.rs @@ -0,0 +1,38 @@ +// Copyright 2023 IOTA Stiftung +// SPDX-License-Identifier: Apache-2.0 + +//! In this example, we create an implicit account creation address. +//! +//! Rename `.env.example` to `.env` first, then run the command: +//! ```sh +//! cargo run --release --all-features --example implicit_account_creation +//! ``` + +use iota_sdk::{ + client::{constants::SHIMMER_COIN_TYPE, secret::SecretManager}, + crypto::keys::bip44::Bip44, + wallet::{ClientOptions, Result, Wallet}, +}; + +#[tokio::main] +async fn main() -> Result<()> { + //  This example uses secrets in environment variables for simplicity which should not be done in production. + dotenvy::dotenv().ok(); + + let secret_manager = SecretManager::try_from_mnemonic(std::env::var("MNEMONIC").unwrap())?; + let client_options = ClientOptions::new().with_node("https://api.testnet.shimmer.network")?; + + let wallet = Wallet::builder() + .with_secret_manager(secret_manager) + .with_client_options(client_options) + .with_storage_path("implicit_account_creation") + .with_bip_path(Bip44::new(SHIMMER_COIN_TYPE)) + .finish() + .await?; + + let implicit_account_creation_address = wallet.implicit_account_creation_address().await?; + + println!("{implicit_account_creation_address}"); + + Ok(()) +} diff --git a/sdk/src/wallet/core/mod.rs b/sdk/src/wallet/core/mod.rs index 568e26b4fc..44fb61d0df 100644 --- a/sdk/src/wallet/core/mod.rs +++ b/sdk/src/wallet/core/mod.rs @@ -32,7 +32,7 @@ use crate::{ }, types::{ block::{ - address::{Bech32Address, Hrp}, + address::{Address, Bech32Address, Hrp, ImplicitAccountCreationAddress}, output::{dto::FoundryOutputDto, AccountId, FoundryId, FoundryOutput, NftId, Output, OutputId, TokenId}, payload::signed_transaction::{dto::TransactionDto, Transaction, TransactionId}, }, @@ -41,7 +41,7 @@ use crate::{ wallet::{ operations::syncing::SyncOptions, types::{OutputData, OutputDataDto}, - FilterOptions, Result, + Error, FilterOptions, Result, }, }; @@ -252,6 +252,20 @@ where self.data().await.address.clone() } + /// Returns the implicit account creation address of the wallet if it is Ed25519 based. + pub async fn implicit_account_creation_address(&self) -> Result { + let bech32_address = &self.data().await.address; + + if let Address::Ed25519(address) = bech32_address.inner() { + Ok(Bech32Address::new( + *bech32_address.hrp(), + ImplicitAccountCreationAddress::from(address.clone()), + )) + } else { + return Err(Error::NonEd25519Address); + } + } + /// Get the wallet's configured Bech32 HRP. pub async fn bech32_hrp(&self) -> Hrp { self.data().await.address.hrp diff --git a/sdk/src/wallet/error.rs b/sdk/src/wallet/error.rs index c8d7c3b469..7cd3a7f177 100644 --- a/sdk/src/wallet/error.rs +++ b/sdk/src/wallet/error.rs @@ -116,6 +116,9 @@ pub enum Error { /// Address not the wallet address #[error("address {0} is not the wallet address")] WalletAddressMismatch(Bech32Address), + /// Action requires the wallet to be Ed25519 address based + #[error("tried to perform an action that requires the wallet to be Ed25519 address based")] + NonEd25519Address, } // Serialize type with Display error