Skip to content

Commit

Permalink
Merge branch '2.0' into prepare-claim-tx-options
Browse files Browse the repository at this point in the history
  • Loading branch information
Thoralf-M authored Apr 30, 2024
2 parents a8f1288 + 3e44c80 commit de244a8
Show file tree
Hide file tree
Showing 20 changed files with 277 additions and 235 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions bindings/core/src/method/wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ pub enum WalletMethod {
/// 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)
/// 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)
Expand Down
12 changes: 5 additions & 7 deletions bindings/nodejs/examples/how_tos/wallet/consolidate-outputs.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2023 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

import { CommonOutput, Utils, Wallet, initLogger } from '@iota/sdk';
import { CommonOutput, Wallet, initLogger } from '@iota/sdk';

// This example uses secrets in environment variables for simplicity which should not be done in production.
require('dotenv').config({ path: '.env' });
Expand Down Expand Up @@ -46,11 +46,10 @@ async function run() {
const outputs = await wallet.unspentOutputs();
console.log('Outputs BEFORE consolidation:');

outputs.forEach(({ output, address }, i) => {
outputs.forEach(({ output }, i) => {
console.log(`OUTPUT #${i}`);
console.log(
'- address: %s\n- amount: %d\n- native token: %s',
Utils.addressToBech32(address, 'rms'),
'- amount: %d\n- native token: %s',
output.getAmount(),
output instanceof CommonOutput
? (output as CommonOutput).getNativeToken() ?? []
Expand Down Expand Up @@ -80,11 +79,10 @@ async function run() {

// Outputs after consolidation
console.log('Outputs AFTER consolidation:');
outputs.forEach(({ output, address }, i) => {
outputs.forEach(({ output }, i) => {
console.log(`OUTPUT #${i}`);
console.log(
'- address: %s\n- amount: %d\n- native tokens: %s',
Utils.addressToBech32(address, 'rms'),
'- amount: %d\n- native tokens: %s',
output.getAmount(),
output instanceof CommonOutput
? (output as CommonOutput).getNativeToken()
Expand Down
28 changes: 11 additions & 17 deletions bindings/nodejs/lib/types/wallet/output.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
// SPDX-License-Identifier: Apache-2.0

import { Type } from 'class-transformer';
import { Address, AddressDiscriminator } from '../block/address';
import { Output, OutputDiscriminator, OutputId } from '../block/output';
import { OutputMetadataResponse } from '../models/api';
import { OutputIdProof, OutputMetadataResponse } from '../models/api';

/** Output to claim */
export enum OutputsToClaim {
Expand All @@ -15,28 +14,23 @@ export enum OutputsToClaim {
All = 'All',
}

/** An output with metadata */
/** An output with additional data */
export class OutputData {
/** The identifier of an Output */
outputId!: OutputId;
/** The metadata of the output */
metadata!: OutputMetadataResponse;
/** The actual Output */
/** The output itself */
@Type(() => Output, {
discriminator: OutputDiscriminator,
})
output!: Output;
/** Associated account address */
@Type(() => Address, {
discriminator: AddressDiscriminator,
})
address!: Address;
/** Network ID */
/** The metadata of the output */
metadata!: OutputMetadataResponse;
/** The output ID proof */
OutputIdProof!: OutputIdProof;
/** The corresponding output ID */
outputId!: OutputId;
/** The network ID the output belongs to */
networkId!: string;
/** Remainder */
/** Whether the output represents a remainder amount */
remainder!: boolean;
/** BIP32 path */
chain?: Segment[];
}

/** A Segment of the BIP32 path*/
Expand Down
12 changes: 6 additions & 6 deletions bindings/python/iota_sdk/types/output_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@
@json
@dataclass
class OutputData:
"""Output data.
"""An output with additional data.
Attributes:
output_id: With the output data corresponding output ID.
metadata: With the output corresponding metadata.
output: The output object itself.
output: The output itself.
metadata: The metadata of the output.
output_id_proof: The output ID proof.
output_id: The corresponding output ID.
network_id: The network ID the output belongs to.
remainder: Whether the output represents a remainder amount.
"""
output_id: OutputId
metadata: OutputMetadata
output: Output
metadata: OutputMetadata
output_id_proof: OutputIdProof
output_id: OutputId
network_id: str
remainder: bool
2 changes: 1 addition & 1 deletion bindings/python/iota_sdk/wallet/wallet.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
from iota_sdk.types.client_options import ClientOptions
from iota_sdk.types.filter_options import FilterOptions
from iota_sdk.types.native_token import NativeToken
from iota_sdk.types.output import BasicOutput, NftOutput, Output, deserialize_output
from iota_sdk.types.output_data import OutputData
from iota_sdk.types.output_id import OutputId
from iota_sdk.types.output import BasicOutput, NftOutput, Output, deserialize_output
from iota_sdk.types.output_params import OutputParams
from iota_sdk.types.transaction_data import PreparedTransactionData, SignedTransactionData
from iota_sdk.types.transaction_id import TransactionId
Expand Down
8 changes: 4 additions & 4 deletions cli/src/wallet_cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1765,14 +1765,14 @@ pub async fn prompt_internal(
Ok(PromptResponse::Reprompt)
}

fn print_outputs(mut outputs: Vec<OutputData>, title: &str) -> Result<(), Error> {
if outputs.is_empty() {
fn print_outputs(mut outputs_data: Vec<OutputData>, title: &str) -> Result<(), Error> {
if outputs_data.is_empty() {
println_log_info!("No outputs found");
} else {
println_log_info!("{title}");
outputs.sort_unstable_by_key(|o| o.output_id);
outputs_data.sort_unstable_by_key(|o| o.output_id);

for (i, output_data) in outputs.into_iter().enumerate() {
for (i, output_data) in outputs_data.into_iter().enumerate() {
let kind_str = if output_data.output.is_implicit_account() {
"ImplicitAccount"
} else {
Expand Down
4 changes: 4 additions & 0 deletions sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Security -->

## 2.0.0-alpha.1 - 2024-04-29

Initial alpha release of the 2.0 SDK.

## 1.1.5 - 2024-MM-DD

### Added
Expand Down
2 changes: 1 addition & 1 deletion sdk/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "iota-sdk"
version = "1.1.4"
version = "2.0.0-alpha.1"
authors = ["IOTA Stiftung"]
edition = "2021"
description = "The IOTA SDK provides developers with a seamless experience to develop on IOTA by providing account abstractions and clients to interact with node APIs."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ impl TransactionBuilder {
.cloned()
.collect::<Vec<_>>();

let mut new_amount = None;

if let Some(change) = self.transitions.as_ref().and_then(|t| t.accounts.get(&account_id)) {
match change {
AccountChange::BeginStaking {
Expand All @@ -83,6 +85,7 @@ impl TransactionBuilder {
self.protocol_parameters
.past_bounded_slot(self.latest_slot_commitment_id),
);
new_amount = Some(*staked_amount);
features.push(
StakingFeature::new(
*staked_amount,
Expand All @@ -101,6 +104,7 @@ impl TransactionBuilder {
.protocol_parameters
.future_bounded_epoch(self.latest_slot_commitment_id);
let staking_feature = feature.as_staking();
new_amount = Some(staking_feature.staked_amount());
// Just extend the end epoch if it's still possible
if future_bounded_epoch <= staking_feature.end_epoch() {
*feature = StakingFeature::new(
Expand Down Expand Up @@ -162,11 +166,18 @@ impl TransactionBuilder {
}

let mut builder = AccountOutputBuilder::from(input)
.with_minimum_amount(self.protocol_parameters.storage_score_parameters())
.with_mana(0)
.with_account_id(account_id)
.with_foundry_counter(u32::max(highest_foundry_serial_number, input.foundry_counter()))
.with_features(features);
match new_amount {
Some(amount) => builder = builder.with_amount(amount),
None => {
if input.features().staking().is_none() {
builder = builder.with_minimum_amount(self.protocol_parameters.storage_score_parameters());
}
}
}

// Block issuers cannot move their mana elsewhere.
if input.is_block_issuer() {
Expand Down
3 changes: 2 additions & 1 deletion sdk/src/wallet/core/operations/background_syncing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ where
/// Start the background syncing process for the wallet, default interval is 7 seconds
pub async fn start_background_syncing(
&self,
options: Option<SyncOptions>,
options: impl Into<Option<SyncOptions>> + Send,
interval: Option<Duration>,
) -> Result<(), WalletError> {
log::debug!("[start_background_syncing]");

let options = options.into();
let (tx_background_sync, mut rx_background_sync) = self.background_syncing_status.clone();

// stop existing process if running
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl<S: 'static + SecretManage> Wallet<S> {
) -> Result<Vec<OutputId>, WalletError> {
log::debug!("[SYNC] get_foundry_output_ids");
// Get account outputs, so we can then get the foundry outputs with the account addresses
let account_outputs_with_meta = self.get_outputs(account_output_ids.to_vec()).await?;
let account_outputs_with_meta = self.get_outputs_request_unknown(account_output_ids).await?;

let bech32_hrp = self.client().get_bech32_hrp().await?;

Expand All @@ -77,14 +77,9 @@ impl<S: 'static + SecretManage> Wallet<S> {
}
}

let mut output_ids = HashSet::new();
let results: Vec<Result<OutputIdsResponse, WalletError>> = futures::future::try_join_all(tasks).await?;
let responses: Vec<OutputIdsResponse> = results.into_iter().collect::<Result<Vec<_>, _>>()?;

for res in results {
let foundry_output_ids = res?;
output_ids.extend(foundry_output_ids.items);
}

Ok(output_ids.into_iter().collect())
Ok(responses.into_iter().flat_map(|res| res.items).collect())
}
}
50 changes: 25 additions & 25 deletions sdk/src/wallet/operations/syncing/addresses/output_ids/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ use crate::{
},
types::block::{address::Bech32Address, output::OutputId},
wallet::{
constants::PARALLEL_REQUESTS_AMOUNT, operations::syncing::SyncOptions,
types::address::AddressWithUnspentOutputs, Wallet, WalletError,
constants::PARALLEL_REQUESTS_AMOUNT,
operations::syncing::SyncOptions,
types::address::{AddressWithUnspentOutputIds, SpentOutputId},
Wallet, WalletError,
},
};

Expand Down Expand Up @@ -217,11 +219,8 @@ impl<S: 'static + SecretManage> Wallet<S> {
let results = futures::future::try_join_all(tasks).await?;

// Get all results
let mut output_ids = HashSet::new();
for res in results {
let found_output_ids = res?;
output_ids.extend(found_output_ids);
}
let output_ids = results.into_iter().collect::<Result<Vec<_>, _>>()?;
let output_ids: HashSet<OutputId> = HashSet::from_iter(output_ids.into_iter().flat_map(|v| v.into_iter()));

Ok(output_ids.into_iter().collect())
}
Expand All @@ -230,20 +229,20 @@ impl<S: 'static + SecretManage> Wallet<S> {
/// return spent outputs separated
pub(crate) async fn get_output_ids_for_addresses(
&self,
addresses_with_unspent_outputs: Vec<AddressWithUnspentOutputs>,
addresses: &[AddressWithUnspentOutputIds],
options: &SyncOptions,
) -> Result<(Vec<AddressWithUnspentOutputs>, Vec<OutputId>), WalletError> {
) -> Result<(Vec<AddressWithUnspentOutputIds>, Vec<SpentOutputId>), WalletError> {
log::debug!("[SYNC] start get_output_ids_for_addresses");
let address_output_ids_start_time = Instant::now();

let mut addresses_with_outputs = Vec::new();
let mut addresses_with_unspent_outputs = Vec::new();
// spent outputs or account/nft/foundries that don't get synced anymore, because of other sync options
let mut spent_or_not_anymore_synced_outputs = Vec::new();
let mut spent_or_ignored_outputs = Vec::new();

// We split the addresses into chunks so we don't get timeouts if we have thousands
for addresses_chunk in &mut addresses_with_unspent_outputs
for addresses_chunk in addresses
.chunks(PARALLEL_REQUESTS_AMOUNT)
.map(|x: &[AddressWithUnspentOutputs]| x.to_vec())
.map(|x: &[AddressWithUnspentOutputIds]| x.to_vec())
{
let results: Vec<Result<_, WalletError>>;
#[cfg(target_family = "wasm")]
Expand Down Expand Up @@ -276,35 +275,36 @@ impl<S: 'static + SecretManage> Wallet<S> {
results = futures::future::try_join_all(tasks).await?;
}

for res in results {
let (mut address, output_ids): (AddressWithUnspentOutputs, Vec<OutputId>) = res?;
let addresses_with_new_unspent_output_ids = results.into_iter().collect::<Result<Vec<_>, _>>()?;

for (mut address, new_unspent_output_ids) in addresses_with_new_unspent_output_ids {
// only return addresses with outputs
if !output_ids.is_empty() {
if !new_unspent_output_ids.is_empty() {
// outputs we had before, but now not anymore, got spent or are account/nft/foundries that don't
// get synced anymore because of other sync options
for output_id in address.output_ids {
if !output_ids.contains(&output_id) {
spent_or_not_anymore_synced_outputs.push(output_id);
for output_id in address.unspent_output_ids {
if !new_unspent_output_ids.contains(&output_id) {
spent_or_ignored_outputs.push(output_id);
}
}
address.output_ids = output_ids;
addresses_with_outputs.push(address);
address.unspent_output_ids = new_unspent_output_ids;
addresses_with_unspent_outputs.push(address);
} else {
// outputs we had before, but now not anymore, got spent or are account/nft/foundries that don't
// get synced anymore because of other sync options
spent_or_not_anymore_synced_outputs.extend(address.output_ids);
spent_or_ignored_outputs.extend(address.unspent_output_ids);
}
}
}

log::debug!(
"[SYNC] spent or not anymore synced account/nft/foundries outputs: {:?}",
spent_or_not_anymore_synced_outputs
"[SYNC] spent or ignored account/nft/foundries outputs: {:?}",
spent_or_ignored_outputs
);
log::debug!(
"[SYNC] finished get_output_ids_for_addresses in {:.2?}",
address_output_ids_start_time.elapsed()
);
Ok((addresses_with_outputs, spent_or_not_anymore_synced_outputs))
Ok((addresses_with_unspent_outputs, spent_or_ignored_outputs))
}
}
Loading

0 comments on commit de244a8

Please sign in to comment.