Skip to content

Commit

Permalink
feat: Wallet events improvements (#2100)
Browse files Browse the repository at this point in the history
* feat: Reorder wallet events and add a new block event

* Add `BlockSigningHash` and update wallet events tests

* update comment

* add missing unlocks

* I hope this works

* fixes and improvements

* fix typo in nodejs bindings

* emit broadcasting event after block signing and before emitting

* python events

* revert wallet events

* improvements

* use HexEncodedString in ts

* clean up
  • Loading branch information
marc2332 authored Mar 5, 2024
1 parent 67b7af7 commit 9e70832
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 34 deletions.
36 changes: 27 additions & 9 deletions bindings/nodejs/lib/types/wallet/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,14 @@ enum TransactionProgressType {
GeneratingRemainderDepositAddress = 1,
/** Prepared transaction. */
PreparedTransaction = 2,
/** Prepared transaction signing hash hex encoded, required for blindsigning with a Ledger Nano. */
PreparedTransactionSigningHash = 3,
/** Signing the transaction. */
SigningTransaction = 4,
SigningTransaction = 3,
/** Prepared transaction signing hash hex encoded, required for blindsigning with a Ledger Nano. */
PreparedTransactionSigningHash = 4,
/** Prepared block signing input, required for blindsigning with a Ledger Nano. */
PreparedBlockSigningInput = 5,
/** Broadcasting. */
Broadcasting = 5,
Broadcasting = 6,
}

/**
Expand Down Expand Up @@ -207,6 +209,15 @@ class PreparedTransactionProgress extends TransactionProgress {
}
}

/**
* A 'signing transaction' progress.
*/
class SigningTransactionProgress extends TransactionProgress {
constructor() {
super(TransactionProgressType.SigningTransaction);
}
}

/**
* A 'prepared transaction hash' progress.
*/
Expand All @@ -223,11 +234,17 @@ class PreparedTransactionSigningHashProgress extends TransactionProgress {
}

/**
* A 'signing transaction' progress.
* A 'prepared block input' progress.
*/
class SigningTransactionProgress extends TransactionProgress {
constructor() {
super(TransactionProgressType.SigningTransaction);
class PreparedBlockSigningInputProgress extends TransactionProgress {
blockSigningInput: HexEncodedString;

/**
* @param signingHash The signing hash of the block.
*/
constructor(signingInput: HexEncodedString) {
super(TransactionProgressType.PreparedBlockSigningInput);
this.blockSigningInput = signingInput;
}
}

Expand All @@ -252,8 +269,9 @@ export {
SelectingInputsProgress,
GeneratingRemainderDepositAddressProgress,
PreparedTransactionProgress,
PreparedTransactionSigningHashProgress,
SigningTransactionProgress,
PreparedTransactionSigningHashProgress,
PreparedBlockSigningInputProgress,
BroadcastingProgress,
TransactionProgressType,
};
54 changes: 40 additions & 14 deletions sdk/src/wallet/events/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,12 @@ pub enum TransactionProgressEvent {
GeneratingRemainderDepositAddress(AddressData),
/// Prepared transaction.
PreparedTransaction(Box<PreparedTransactionDataDto>),
/// Prepared transaction signing hash hex encoded, required for blindsigning with a ledger nano
PreparedTransactionSigningHash(String),
/// Signing the transaction.
SigningTransaction,
/// Prepared transaction signing hash hex encoded, required for blindsigning with a ledger nano
PreparedTransactionSigningHash(String),
/// Prepared block signing input, required for blind signing with ledger nano
PreparedBlockSigningInput(String),
/// Broadcasting.
Broadcasting,
}
Expand All @@ -217,15 +219,22 @@ impl Serialize for TransactionProgressEvent {
signing_hash: &'a str,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct PreparedBlockSigningInput_<'a> {
block_signing_input: &'a str,
}

#[derive(Serialize)]
#[serde(untagged)]
enum TransactionProgressEvent_<'a> {
T0,
T1(&'a AddressData),
T2(&'a PreparedTransactionDataDto),
T3(PreparedTransactionSigningHash_<'a>),
T4,
T5,
T3,
T4(PreparedTransactionSigningHash_<'a>),
T5(PreparedBlockSigningInput_<'a>),
T6,
}
#[derive(Serialize)]
struct TypedTransactionProgressEvent_<'a> {
Expand All @@ -247,17 +256,21 @@ impl Serialize for TransactionProgressEvent {
kind: 2,
event: TransactionProgressEvent_::T2(e),
},
Self::PreparedTransactionSigningHash(e) => TypedTransactionProgressEvent_ {
Self::SigningTransaction => TypedTransactionProgressEvent_ {
kind: 3,
event: TransactionProgressEvent_::T3(PreparedTransactionSigningHash_ { signing_hash: e }),
event: TransactionProgressEvent_::T3,
},
Self::SigningTransaction => TypedTransactionProgressEvent_ {
Self::PreparedTransactionSigningHash(e) => TypedTransactionProgressEvent_ {
kind: 4,
event: TransactionProgressEvent_::T4,
event: TransactionProgressEvent_::T4(PreparedTransactionSigningHash_ { signing_hash: e }),
},
Self::Broadcasting => TypedTransactionProgressEvent_ {
Self::PreparedBlockSigningInput(e) => TypedTransactionProgressEvent_ {
kind: 5,
event: TransactionProgressEvent_::T5,
event: TransactionProgressEvent_::T5(PreparedBlockSigningInput_ { block_signing_input: e }),
},
Self::Broadcasting => TypedTransactionProgressEvent_ {
kind: 6,
event: TransactionProgressEvent_::T6,
},
};
event.serialize(serializer)
Expand All @@ -272,6 +285,12 @@ impl<'de> Deserialize<'de> for TransactionProgressEvent {
signing_hash: String,
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct PreparedBlockSigningInput_ {
block_signing_input: String,
}

let value = serde_json::Value::deserialize(d)?;
Ok(
match value
Expand All @@ -287,15 +306,22 @@ impl<'de> Deserialize<'de> for TransactionProgressEvent {
2 => Self::PreparedTransaction(Box::new(PreparedTransactionDataDto::deserialize(value).map_err(
|e| serde::de::Error::custom(format!("cannot deserialize PreparedTransactionDataDto: {e}")),
)?)),
3 => Self::PreparedTransactionSigningHash(
3 => Self::SigningTransaction,
4 => Self::PreparedTransactionSigningHash(
PreparedTransactionSigningHash_::deserialize(value)
.map_err(|e| {
serde::de::Error::custom(format!("cannot deserialize PreparedTransactionSigningHash: {e}"))
})?
.signing_hash,
),
4 => Self::SigningTransaction,
5 => Self::Broadcasting,
5 => Self::PreparedBlockSigningInput(
PreparedBlockSigningInput_::deserialize(value)
.map_err(|e| {
serde::de::Error::custom(format!("cannot deserialize PreparedBlockSigningInput: {e}"))
})?
.block_signing_input,
),
6 => Self::Broadcasting,
_ => return Err(serde::de::Error::custom("invalid transaction progress event type")),
},
)
Expand Down
12 changes: 12 additions & 0 deletions sdk/src/wallet/operations/block.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Copyright 2023 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

#[cfg(feature = "events")]
use crate::wallet::events::types::{TransactionProgressEvent, WalletEvent};
use crate::{
client::{
secret::{SecretManage, SignBlock},
Expand Down Expand Up @@ -46,13 +48,23 @@ where
}
}

#[cfg(feature = "events")]
self.emit(WalletEvent::TransactionProgress(
TransactionProgressEvent::PreparedBlockSigningInput(prefix_hex::encode(unsigned_block.signing_input())),
))
.await;

let block = unsigned_block
.sign_ed25519(
&*self.get_secret_manager().read().await,
self.bip_path().await.ok_or(WalletError::MissingBipPath)?,
)
.await?;

#[cfg(feature = "events")]
self.emit(WalletEvent::TransactionProgress(TransactionProgressEvent::Broadcasting))
.await;

let block_id = self.client().post_block(&block).await?;

log::debug!("submitted block {}", block_id);
Expand Down
6 changes: 0 additions & 6 deletions sdk/src/wallet/operations/transaction/submit_transaction.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright 2021 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

#[cfg(feature = "events")]
use crate::wallet::events::types::{TransactionProgressEvent, WalletEvent};
use crate::{
client::{secret::SecretManage, ClientError},
types::block::{output::AccountId, payload::Payload, BlockId},
Expand All @@ -22,10 +20,6 @@ where
) -> Result<BlockId, WalletError> {
log::debug!("[TRANSACTION] submit_signed_transaction");

#[cfg(feature = "events")]
self.emit(WalletEvent::TransactionProgress(TransactionProgressEvent::Broadcasting))
.await;

self.submit_basic_block(Some(Payload::from(payload)), issuer_id, true)
.await
}
Expand Down
47 changes: 42 additions & 5 deletions sdk/tests/wallet/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,27 @@ use iota_sdk::{
client::api::PreparedTransactionDataDto,
types::block::{
address::{Address, Bech32Address, Ed25519Address},
core::{
basic::{MaxBurnedManaAmount, StrongParents},
BlockHeader,
},
input::{Input, UtxoInput},
output::{
unlock_condition::AddressUnlockCondition, BasicOutput, LeafHash, Output, OutputCommitmentProof,
unlock_condition::AddressUnlockCondition, AccountId, BasicOutput, LeafHash, Output, OutputCommitmentProof,
OutputIdProof,
},
payload::signed_transaction::{Transaction, TransactionHash, TransactionId},
payload::{
signed_transaction::{Transaction, TransactionHash, TransactionId},
Payload, SignedTransactionPayload,
},
protocol::iota_mainnet_protocol_parameters,
rand::{
mana::rand_mana_allotment,
output::{rand_basic_output, rand_output_metadata},
},
slot::SlotIndex,
slot::{SlotCommitmentId, SlotIndex},
unlock::{EmptyUnlock, Unlock, Unlocks},
BlockBody, BlockId, UnsignedBlock,
},
wallet::{
events::types::{
Expand Down Expand Up @@ -115,14 +124,42 @@ fn wallet_events_serde() {
mana_rewards: Default::default(),
})),
));

let block_payload = SignedTransactionPayload::new(
transaction,
Unlocks::new([Unlock::Empty(EmptyUnlock), Unlock::Empty(EmptyUnlock)]).unwrap(),
)
.unwrap();
let payload = Payload::from(block_payload);
let block = UnsignedBlock::new(
BlockHeader::new(
protocol_parameters.version(),
protocol_parameters.network_id(),
0u64,
SlotCommitmentId::new([0; 36]),
SlotIndex(0),
AccountId::new([0; 32]),
),
BlockBody::build_basic(
StrongParents::from_vec(vec![BlockId::new([0; 36])]).unwrap(),
MaxBurnedManaAmount::Amount(0),
)
.with_payload(payload)
.finish_block_body()
.unwrap(),
);

assert_serde_eq(WalletEvent::TransactionProgress(
TransactionProgressEvent::PreparedBlockSigningInput(prefix_hex::encode(block.signing_input())),
));
}

assert_serde_eq(WalletEvent::TransactionProgress(
TransactionProgressEvent::PreparedTransactionSigningHash(ED25519_ADDRESS.to_string()),
TransactionProgressEvent::SigningTransaction,
));

assert_serde_eq(WalletEvent::TransactionProgress(
TransactionProgressEvent::SigningTransaction,
TransactionProgressEvent::PreparedTransactionSigningHash(ED25519_ADDRESS.to_string()),
));

assert_serde_eq(WalletEvent::TransactionProgress(TransactionProgressEvent::Broadcasting));
Expand Down

0 comments on commit 9e70832

Please sign in to comment.