Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Wallet events improvements #2100

Merged
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 hash hex encoded, required for blindsigning with a Ledger Nano. */
PrepareBlockSigningHash = 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 hash' progress.
*/
class SigningTransactionProgress extends TransactionProgress {
constructor() {
super(TransactionProgressType.SigningTransaction);
class PreparedBlockSigningHashProgress extends TransactionProgress {
blockSigningHash: HexEncodedString;

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

Expand All @@ -252,8 +269,9 @@ export {
SelectingInputsProgress,
GeneratingRemainderDepositAddressProgress,
PreparedTransactionProgress,
PreparedTransactionSigningHashProgress,
SigningTransactionProgress,
PreparedTransactionSigningHashProgress,
PreparedBlockSigningHashProgress,
BroadcastingProgress,
TransactionProgressType,
};
12 changes: 12 additions & 0 deletions sdk/src/types/block/core/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ use crate::types::block::{
BlockBody,
};

crate::impl_id!(
/// The signing hash of a [`Block`]'s signing input.
pub BlockSigningHash {
pub const LENGTH: usize = 32;
}
);

/// Block without a signature. Can be finished into a [`Block`].
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct UnsignedBlock {
Expand Down Expand Up @@ -57,6 +64,11 @@ impl UnsignedBlock {
[self.header.hash(), self.body.hash()].concat()
}

/// Return the Blake2b hash of the block's signing input.
pub fn signing_hash(&self) -> BlockSigningHash {
BlockSigningHash::new(Blake2b256::digest(self.signing_input()).into())
Thoralf-M marked this conversation as resolved.
Show resolved Hide resolved
}

/// Finishes an [`UnsignedBlock`] into a [`Block`].
pub fn finish_with_params<'a>(
self,
Expand Down
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 hash hex encoded, required for blind signing with ledger nano
PreparedBlockSigningHash(String),
/// Broadcasting.
Broadcasting,
}
Expand All @@ -217,15 +219,22 @@ impl Serialize for TransactionProgressEvent {
signing_hash: &'a str,
}

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct PreparedBlockSigningHash_<'a> {
block_signing_hash: &'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(PreparedBlockSigningHash_<'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::PreparedBlockSigningHash(e) => TypedTransactionProgressEvent_ {
kind: 5,
event: TransactionProgressEvent_::T5,
event: TransactionProgressEvent_::T5(PreparedBlockSigningHash_ { block_signing_hash: 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 PreparedBlockSigningHash_ {
block_signing_hash: 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::PreparedBlockSigningHash(
PreparedBlockSigningHash_::deserialize(value)
.map_err(|e| {
serde::de::Error::custom(format!("cannot deserialize PreparedBlockSigningHash: {e}"))
})?
.block_signing_hash,
),
6 => Self::Broadcasting,
_ => return Err(serde::de::Error::custom("invalid transaction progress event type")),
},
)
Expand Down
8 changes: 8 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},
types::block::{output::AccountId, payload::Payload, BlockId},
Expand Down Expand Up @@ -39,6 +41,12 @@ where
}
}

#[cfg(feature = "events")]
self.emit(WalletEvent::TransactionProgress(
TransactionProgressEvent::PreparedBlockSigningHash(unsigned_block.signing_hash().to_string()),
))
.await;

let block = unsigned_block
.sign_ed25519(
&*self.get_secret_manager().read().await,
Expand Down
7 changes: 5 additions & 2 deletions sdk/src/wallet/operations/transaction/submit_transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,14 @@ where
) -> crate::wallet::Result<BlockId> {
log::debug!("[TRANSACTION] submit_signed_transaction");

let block_id = self
.submit_basic_block(Some(Payload::from(payload)), issuer_id, true)
.await?;

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

Thoralf-M marked this conversation as resolved.
Show resolved Hide resolved
self.submit_basic_block(Some(Payload::from(payload)), issuer_id, true)
.await
Ok(block_id)
}
}
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::PreparedBlockSigningHash(block.signing_hash().to_string()),
));
}

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
Loading