Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch '2.0' into prepare-claim-tx-options
Browse files Browse the repository at this point in the history
Thoralf-M authored Apr 30, 2024
2 parents a8f1288 + 3e44c80 commit de244a8
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
@@ -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)
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' });
@@ -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() ?? []
@@ -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()
28 changes: 11 additions & 17 deletions bindings/nodejs/lib/types/wallet/output.ts
Original file line number Diff line number Diff line change
@@ -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 {
@@ -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*/
12 changes: 6 additions & 6 deletions bindings/python/iota_sdk/types/output_data.py
Original file line number Diff line number Diff line change
@@ -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
@@ -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
8 changes: 4 additions & 4 deletions cli/src/wallet_cli/mod.rs
Original file line number Diff line number Diff line change
@@ -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 {
4 changes: 4 additions & 0 deletions sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
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."
Original file line number Diff line number Diff line change
@@ -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 {
@@ -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,
@@ -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(
@@ -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() {
3 changes: 2 additions & 1 deletion sdk/src/wallet/core/operations/background_syncing.rs
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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?;

@@ -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
@@ -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,
},
};

@@ -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())
}
@@ -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")]
@@ -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.