Skip to content

Commit

Permalink
Make ISA a transaction builder (#2102)
Browse files Browse the repository at this point in the history
* Rename input selection to transaction builder. Move transaction options to client to support a client version of transaction builder.

* fmt

* revert flag name

* find/replace mistakes

* typo

* error swap

* review

* finish renaming

* Fix reward context inputs and tests

* remove context inputs from transaction options

* revert merge mistake

* remove comments

* usused import

* Remove unused ContextInput

* review

* more ts instances

* review

* double copyright

* review

* fix mana allotment not recalculating after changes are made

* remove error variant

* allow providing chains

* DRY

---------

Co-authored-by: Thibault Martinez <[email protected]>
  • Loading branch information
DaughterOfMars and thibault-martinez authored Mar 5, 2024
1 parent c8f3682 commit 55607c6
Show file tree
Hide file tree
Showing 78 changed files with 1,375 additions and 1,396 deletions.
6 changes: 3 additions & 3 deletions bindings/core/src/method/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ use std::path::PathBuf;

use crypto::keys::bip44::Bip44;
use derivative::Derivative;
use iota_sdk::utils::serde::string;
#[cfg(feature = "events")]
use iota_sdk::wallet::events::types::{WalletEvent, WalletEventType};
use iota_sdk::{client::api::options::TransactionOptions, utils::serde::string};
// #[cfg(feature = "participation")]
// use iota_sdk::{
// client::node_manager::node::Node,
Expand All @@ -17,7 +17,7 @@ use iota_sdk::wallet::events::types::{WalletEvent, WalletEventType};
// };
use iota_sdk::{
client::{
api::{input_selection::Burn, PreparedTransactionDataDto, SignedTransactionDataDto},
api::{transaction_builder::Burn, PreparedTransactionDataDto, SignedTransactionDataDto},
node_manager::node::NodeAuth,
secret::GenerateAddressOptions,
},
Expand All @@ -29,7 +29,7 @@ use iota_sdk::{
wallet::{
BeginStakingParams, ClientOptions, ConsolidationParams, CreateAccountParams, CreateDelegationParams,
CreateNativeTokenParams, FilterOptions, MintNftParams, OutputParams, OutputsToClaim, SendManaParams,
SendNativeTokenParams, SendNftParams, SendParams, SyncOptions, TransactionOptions,
SendNativeTokenParams, SendNftParams, SendParams, SyncOptions,
},
U256,
};
Expand Down
4 changes: 2 additions & 2 deletions bindings/core/src/method_handler/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ pub(crate) fn call_utils_method_internal(method: UtilsMethod) -> Result<Response
&transaction,
&inputs,
unlocks.as_deref(),
mana_rewards,
protocol_parameters,
mana_rewards.as_ref(),
&protocol_parameters,
);
context.validate()?;

Expand Down
6 changes: 4 additions & 2 deletions bindings/nodejs/examples/wallet/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import {
WalletEvent,
TransactionProgressWalletEvent,
SelectingInputsProgress,
BuildingTransactionProgress,
} from '@iota/sdk';
import { getUnlockedWallet } from './common';
require('dotenv').config({ path: '.env' });
Expand All @@ -30,7 +30,9 @@ async function run() {
await wallet.listen([], callback);

await wallet.emitTestEvent(
new TransactionProgressWalletEvent(new SelectingInputsProgress()),
new TransactionProgressWalletEvent(
new BuildingTransactionProgress(),
),
);

await wallet.destroy();
Expand Down
12 changes: 6 additions & 6 deletions bindings/nodejs/lib/types/wallet/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ class TransactionInclusionWalletEvent extends WalletEvent {
* All of the transaction progress types.
*/
enum TransactionProgressType {
/** Performing input selection. */
SelectingInputs = 0,
/** Building a transaction. */
BuildingTransaction = 0,
/** Generating remainder value deposit address. */
GeneratingRemainderDepositAddress = 1,
/** Prepared transaction. */
Expand Down Expand Up @@ -161,11 +161,11 @@ abstract class TransactionProgress {
}

/**
* A 'selecting inputs' progress.
* A 'building transaction' progress.
*/
class SelectingInputsProgress extends TransactionProgress {
class BuildingTransactionProgress extends TransactionProgress {
constructor() {
super(TransactionProgressType.SelectingInputs);
super(TransactionProgressType.BuildingTransaction);
}
}

Expand Down Expand Up @@ -266,7 +266,7 @@ export {
TransactionInclusionWalletEvent,
TransactionProgressWalletEvent,
TransactionProgress,
SelectingInputsProgress,
BuildingTransactionProgress,
GeneratingRemainderDepositAddressProgress,
PreparedTransactionProgress,
SigningTransactionProgress,
Expand Down
5 changes: 1 addition & 4 deletions bindings/nodejs/lib/types/wallet/transaction-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
AccountId,
Address,
Bech32Address,
ContextInput,
OutputId,
} from '../block';
import { TaggedDataPayload } from '../block/payload/tagged';
Expand All @@ -19,11 +18,9 @@ export interface TransactionOptions {
remainderValueStrategy?: RemainderValueStrategy;
/** An optional tagged data payload. */
taggedDataPayload?: TaggedDataPayload;
/** Transaction context inputs to include. */
contextInputs?: ContextInput[];
/** Inputs that must be used for the transaction. */
requiredInputs?: OutputId[];
/** Specifies what needs to be burned during input selection. */
/** Specifies what needs to be burned in the transaction. */
burn?: Burn;
/** Optional note, that is only stored locally. */
note?: string;
Expand Down
19 changes: 19 additions & 0 deletions bindings/python/iota_sdk/types/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,22 @@ class WalletEventType(IntEnum):
SpentOutput = 2
TransactionInclusion = 3
TransactionProgress = 4


class TransactionProgressEvent(IntEnum):
"""Types of transaction progress events.
Attributes:
BuildingTransaction (0): Building a transaction.
GeneratingRemainderDepositAddress (1): Generating remainder value deposit address.
PreparedTransaction (2): Prepared transaction.
PreparedTransactionSigningHash (3): Prepared transaction signing hash hex encoded, required for blindsigning with a Ledger Nano.
SigningTransaction (4): Signing the transaction.
Broadcasting (5): Broadcasting.
"""
BuildingTransaction = 0
GeneratingRemainderDepositAddress = 1
PreparedTransaction = 2
PreparedTransactionSigningHash = 3
SigningTransaction = 4
Broadcasting = 5
5 changes: 1 addition & 4 deletions bindings/python/iota_sdk/types/transaction_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from iota_sdk.types.address import Address
from iota_sdk.types.burn import Burn
from iota_sdk.types.common import HexStr, json
from iota_sdk.types.context_input import ContextInput
from iota_sdk.types.output_id import OutputId
from iota_sdk.types.payload import TaggedDataPayload

Expand Down Expand Up @@ -49,9 +48,8 @@ class TransactionOptions:
Attributes:
remainder_value_strategy: The strategy applied for base coin remainders.
tagged_data_payload: An optional tagged data payload.
context_inputs: Transaction context inputs to include.
required_inputs: Inputs that must be used for the transaction.
burn: Specifies what needs to be burned during input selection.
burn: Specifies what needs to be burned in the transaction.
note: A string attached to the transaction.
allow_micro_amount: Whether to allow sending a micro amount.
allow_additional_input_selection: Whether to allow the selection of additional inputs for this transaction.
Expand All @@ -61,7 +59,6 @@ class TransactionOptions:
remainder_value_strategy: Optional[Union[RemainderValueStrategy,
RemainderValueStrategyCustomAddress]] = None
tagged_data_payload: Optional[TaggedDataPayload] = None
context_inputs: Optional[List[ContextInput]] = None
required_inputs: Optional[List[OutputId]] = None
burn: Optional[Burn] = None
note: Optional[str] = None
Expand Down
4 changes: 2 additions & 2 deletions cli/src/wallet_cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use clap::{CommandFactory, Parser, Subcommand};
use colored::Colorize;
use eyre::Error;
use iota_sdk::{
client::{request_funds_from_faucet, secret::SecretManager},
client::{api::options::TransactionOptions, request_funds_from_faucet, secret::SecretManager},
types::block::{
address::{AccountAddress, Bech32Address, ToBech32Ext},
mana::ManaAllotment,
Expand All @@ -27,7 +27,7 @@ use iota_sdk::{
wallet::{
types::OutputData, BeginStakingParams, ConsolidationParams, CreateDelegationParams, CreateNativeTokenParams,
MintNftParams, OutputsToClaim, ReturnStrategy, SendManaParams, SendNativeTokenParams, SendNftParams,
SendParams, SyncOptions, TransactionOptions, Wallet, WalletError,
SendParams, SyncOptions, Wallet, WalletError,
},
U256,
};
Expand Down
53 changes: 32 additions & 21 deletions sdk/examples/client/send_all.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,19 @@
//! cargo run --release --example send_all
//! ```

use std::collections::BTreeSet;

use crypto::keys::bip44::Bip44;
use iota_sdk::{
client::{
api::{input_selection::InputSelection, GetAddressesOptions},
api::{options::TransactionOptions, GetAddressesOptions},
constants::IOTA_COIN_TYPE,
node_api::indexer::query_parameters::BasicOutputQueryParameters,
secret::{types::InputSigningData, SecretManage, SecretManager, SignBlock},
secret::{SecretManage, SecretManager, SignBlock},
Client,
},
types::block::{
address::{Address, Ed25519Address, ToBech32Ext},
output::{unlock_condition::AddressUnlockCondition, AccountId, BasicOutputBuilder},
payload::{Payload, SignedTransactionPayload},
},
Expand All @@ -45,10 +48,20 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let secret_manager_2 = SecretManager::try_from_mnemonic(std::env::var("MNEMONIC_2").unwrap())?;
let issuer_id = std::env::var("ISSUER_ID").unwrap().parse::<AccountId>().unwrap();

let from_address = secret_manager_1
.generate_ed25519_addresses(GetAddressesOptions::from_client(&client).await?.with_range(0..1))
.await?[0]
.clone();
let chain = Bip44::new(IOTA_COIN_TYPE);

let from_address = Address::from(Ed25519Address::from_public_key_bytes(
secret_manager_1
.generate_ed25519_public_keys(
chain.coin_type,
chain.account,
chain.address_index..chain.address_index + 1,
None,
)
.await?[0]
.to_bytes(),
))
.to_bech32(client.get_bech32_hrp().await?);

// Get output ids of outputs that can be controlled by this address without further unlock constraints
let output_ids_response = client
Expand All @@ -65,7 +78,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Calculate the total amount
let mut total_amount = 0;

let mut inputs = Vec::new();
let mut inputs = BTreeSet::new();
let mut outputs = Vec::new();

for res in outputs_responses {
Expand All @@ -80,11 +93,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
total_amount -= native_token_return.amount();
outputs.push(native_token_return);
}
inputs.push(InputSigningData {
output: res.output,
output_metadata: res.metadata,
chain: None,
});
inputs.insert(*res.metadata().output_id());
}

println!("Total amount: {total_amount}");
Expand All @@ -101,15 +110,17 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.finish_output()?,
);

let prepared_transaction = InputSelection::new(
inputs,
outputs,
[from_address.into_inner()],
client.get_slot_index().await?,
client.get_issuance().await?.latest_commitment.id(),
protocol_parameters.clone(),
)
.select()?;
let prepared_transaction = client
.build_transaction(
[(from_address.into_inner(), chain)],
outputs,
TransactionOptions {
required_inputs: inputs,
allow_additional_input_selection: false,
..Default::default()
},
)
.await?;
let unlocks = secret_manager_1
.transaction_unlocks(&prepared_transaction, &protocol_parameters)
.await?;
Expand Down
4 changes: 2 additions & 2 deletions sdk/examples/how_tos/account_output/send_amount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
//! `cargo run --release --all-features --example account_output_send_amount`

use iota_sdk::{
client::node_api::indexer::query_parameters::BasicOutputQueryParameters,
client::{api::options::TransactionOptions, node_api::indexer::query_parameters::BasicOutputQueryParameters},
types::block::address::{AccountAddress, ToBech32Ext},
wallet::{AccountSyncOptions, SyncOptions, TransactionOptions},
wallet::{AccountSyncOptions, SyncOptions},
Wallet,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
//! cargo run --release --all-features --example send_micro_transaction
//! ```

use iota_sdk::{wallet::TransactionOptions, Wallet};
use iota_sdk::{client::api::options::TransactionOptions, Wallet};

// The base coin micro amount to send
const SEND_MICRO_AMOUNT: u64 = 1;
Expand Down
7 changes: 2 additions & 5 deletions sdk/examples/wallet/offline_signing/2_sign_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@

use iota_sdk::{
client::{
api::{
transaction::validate_signed_transaction_payload_length, PreparedTransactionData, SignedTransactionData,
SignedTransactionDataDto,
},
api::{PreparedTransactionData, SignedTransactionData, SignedTransactionDataDto},
secret::{stronghold::StrongholdSecretManager, SecretManage, SecretManager},
},
types::{block::payload::SignedTransactionPayload, TryFromDto},
Expand Down Expand Up @@ -51,7 +48,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {

let signed_transaction = SignedTransactionPayload::new(prepared_transaction_data.transaction.clone(), unlocks)?;

validate_signed_transaction_payload_length(&signed_transaction)?;
signed_transaction.validate_length()?;

let signed_transaction_data = SignedTransactionData {
payload: signed_transaction,
Expand Down
4 changes: 2 additions & 2 deletions sdk/src/client/api/block_builder/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright 2021 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

pub mod input_selection;
pub mod options;
pub mod transaction;
pub mod transaction_builder;

pub use self::transaction::verify_semantic;
use crate::{
client::{constants::FIVE_MINUTES_IN_NANOSECONDS, Client, ClientError},
types::block::{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@ use alloc::collections::{BTreeMap, BTreeSet};
use serde::{Deserialize, Serialize};

use crate::{
client::api::input_selection::Burn,
client::api::transaction_builder::Burn,
types::block::{
address::Address,
context_input::ContextInput,
output::{AccountId, OutputId},
payload::tagged_data::TaggedDataPayload,
},
Expand All @@ -24,11 +23,9 @@ pub struct TransactionOptions {
pub remainder_value_strategy: RemainderValueStrategy,
/// An optional tagged data payload.
pub tagged_data_payload: Option<TaggedDataPayload>,
/// Transaction context inputs to include.
pub context_inputs: Vec<ContextInput>,
/// Inputs that must be used for the transaction.
pub required_inputs: BTreeSet<OutputId>,
/// Specifies what needs to be burned during input selection.
/// Specifies what needs to be burned in the transaction.
pub burn: Option<Burn>,
/// A string attached to the transaction.
pub note: Option<String>,
Expand All @@ -47,7 +44,6 @@ impl Default for TransactionOptions {
Self {
remainder_value_strategy: Default::default(),
tagged_data_payload: Default::default(),
context_inputs: Default::default(),
required_inputs: Default::default(),
burn: Default::default(),
note: Default::default(),
Expand Down
Loading

0 comments on commit 55607c6

Please sign in to comment.