Skip to content

Commit

Permalink
Merge branch 'feat/wasm32-identity-client' into chore/reenable-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
eike-hass committed Feb 21, 2025
2 parents 6a9fb43 + b329aa9 commit 9628021
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 9 deletions.
1 change: 1 addition & 0 deletions bindings/wasm/identity_wasm/src/iota/iota_document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ impl IotaDocumentLock {
/// Note: All methods that involve reading from this class may potentially raise an error
/// if the object is being concurrently modified.
#[wasm_bindgen(js_name = IotaDocument, inspectable)]
#[derive(Clone)]
pub struct WasmIotaDocument(pub(crate) Rc<IotaDocumentLock>);

#[wasm_bindgen(js_class = IotaDocument)]
Expand Down
4 changes: 2 additions & 2 deletions bindings/wasm/identity_wasm/src/rebased/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ impl WasmOnChainIdentity {
#[wasm_bindgen(js_name = updateDidDocument)]
pub fn update_did_document(
&self,
updated_doc: WasmIotaDocument,
updated_doc: &WasmIotaDocument,
expiration_epoch: Option<u64>,
) -> WasmCreateUpdateDidProposalTx {
WasmCreateUpdateDidProposalTx::new(self, updated_doc, expiration_epoch)
WasmCreateUpdateDidProposalTx::new(self, updated_doc.clone(), expiration_epoch)
}

#[wasm_bindgen(js_name = deactivateDid)]
Expand Down
4 changes: 4 additions & 0 deletions bindings/wasm/iota_interaction_ts/lib/iota_client_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ export class IotaTransactionBlockResponseAdapter {
get_response(): IotaTransactionBlockResponse {
return this.response;
}

get_digest(): string {
return this.response.digest;
}
}

/**
Expand Down
52 changes: 52 additions & 0 deletions bindings/wasm/iota_interaction_ts/src/bindings/wasm_iota_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use identity_iota_interaction::generated_types::GetTransactionBlockParams;
use identity_iota_interaction::generated_types::QueryEventsParams;
use identity_iota_interaction::generated_types::SortOrder;
use identity_iota_interaction::generated_types::TryGetPastObjectParams;
use identity_iota_interaction::generated_types::WaitForTransactionParams;
use identity_iota_interaction::rpc_types::CoinPage;
use identity_iota_interaction::rpc_types::EventFilter;
use identity_iota_interaction::rpc_types::EventPage;
Expand All @@ -31,12 +32,14 @@ use identity_iota_interaction::types::quorum_driver_types::ExecuteTransactionReq
use identity_iota_interaction::SignatureBcs;
use identity_iota_interaction::TransactionDataBcs;
use js_sys::Promise;
use serde::Serialize;
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::JsFuture;

use super::wasm_types::IotaTransactionBlockResponseAdapter;
use super::wasm_types::PromiseIotaTransactionBlockResponse;
use super::wasm_types::WasmExecuteTransactionBlockParams;
use super::WasmWaitForTransactionParams;

use crate::bindings::PromiseIotaObjectResponse;
use crate::bindings::PromiseObjectRead;
Expand All @@ -55,6 +58,7 @@ use crate::common::PromiseBigint;
use crate::console_log;
use crate::error::into_ts_sdk_result;
use crate::error::TsSdkError;
use crate::error::WasmResult;

// This file contains the wasm-bindgen 'glue code' providing
// the interface of the TS Iota client to rust code.
Expand Down Expand Up @@ -114,6 +118,12 @@ extern "C" {

#[wasm_bindgen(method, js_name = getCoins)]
pub fn get_coins(this: &WasmIotaClient, input: &WasmGetCoinsParams) -> PromisePaginatedCoins;

#[wasm_bindgen(method, js_name = waitForTransaction)]
pub fn wait_for_transaction(
this: &WasmIotaClient,
input: &WasmWaitForTransactionParams,
) -> PromiseIotaTransactionBlockResponse;
}

// Helper struct used to convert TYPESCRIPT types to RUST types
Expand Down Expand Up @@ -372,4 +382,46 @@ impl ManagedWasmIotaClient {

Ok(result.into_serde()?)
}

/// Wait for a transaction block result to be available over the API.
/// This can be used in conjunction with `execute_transaction_block` to wait for the transaction to
/// be available via the API.
/// This currently polls the `getTransactionBlock` API to check for the transaction.
///
/// # Arguments
///
/// * `digest` - The digest of the queried transaction.
/// * `options` - Options for specifying the content to be returned.
/// * `timeout` - The amount of time to wait for a transaction block. Defaults to one minute.
/// * `poll_interval` - The amount of time to wait between checks for the transaction block. Defaults to 2 seconds.
pub async fn wait_for_transaction(
&self,
digest: TransactionDigest,
options: Option<IotaTransactionBlockResponseOptions>,
timeout: Option<u64>,
poll_interval: Option<u64>,
) -> IotaRpcResult<IotaTransactionBlockResponseAdapter> {
let params_object = WaitForTransactionParams::new(digest.to_string(), options, timeout, poll_interval);
let params: WasmWaitForTransactionParams = serde_json::to_value(&params_object)
.map_err(|e| {
console_log!("Error serializing WaitForTransactionParams to Value: {:?}", e);
IotaRpcError::FfiError(format!("{:?}", e))
})
.and_then(|v| {
v.serialize(&serde_wasm_bindgen::Serializer::json_compatible())
.map_err(|e| {
console_log!("Error serializing Value to WasmWaitForTransactionParams: {:?}", e);
IotaRpcError::FfiError(format!("{:?}", e))
})
})?
.into();

let promise: Promise = Promise::resolve(&WasmIotaClient::wait_for_transaction(&self.0, &params));
let result: JsValue = JsFuture::from(promise).await.map_err(|e| {
console_log!("Error executing JsFuture::from(promise): {:?}", e);
IotaRpcError::FfiError(format!("{:?}", e))
})?;

Ok(IotaTransactionBlockResponseAdapter::new(result.into()))
}
}
15 changes: 15 additions & 0 deletions bindings/wasm/iota_interaction_ts/src/bindings/wasm_types.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
// Copyright 2020-2025 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
use std::str::FromStr;

use identity_iota_interaction::rpc_types::OwnedObjectRef;
use identity_iota_interaction::types::base_types::IotaAddress;
use identity_iota_interaction::types::base_types::ObjectID;
use identity_iota_interaction::types::base_types::ObjectRef;
use identity_iota_interaction::types::base_types::SequenceNumber;
use identity_iota_interaction::types::digests::TransactionDigest;
use identity_iota_interaction::types::execution_status::CommandArgumentError;
use identity_iota_interaction::types::execution_status::ExecutionStatus;
use identity_iota_interaction::types::object::Owner;
Expand Down Expand Up @@ -39,6 +41,7 @@ const TS_SDK_TYPES: &str = r#"
GetObjectParams,
GetOwnedObjectsParams,
GetTransactionBlockParams,
IotaClient,
IotaObjectData,
IotaObjectResponse,
IotaTransactionBlockResponse,
Expand Down Expand Up @@ -151,6 +154,10 @@ extern "C" {
#[wasm_bindgen(typescript_type = "Promise<IotaTransactionBlockResponseAdapter>")]
#[derive(Clone)]
pub type PromiseIotaTransactionBlockResponseAdapter;

#[wasm_bindgen(typescript_type = "Parameters<IotaClient['waitForTransaction']>")]
#[derive(Clone, Debug)]
pub type WasmWaitForTransactionParams;
}

#[wasm_bindgen(module = "@iota/iota-sdk/transactions")]
Expand Down Expand Up @@ -261,6 +268,9 @@ extern "C" {
#[wasm_bindgen(method)]
fn effects_created_inner(this: &IotaTransactionBlockResponseAdapter) -> Option<Vec<WasmOwnedObjectRef>>;

#[wasm_bindgen(method, js_name = "get_digest")]
fn digest_inner(this: &IotaTransactionBlockResponseAdapter) -> String;

#[wasm_bindgen(method, js_name = "get_response")]
fn response(this: &IotaTransactionBlockResponseAdapter) -> WasmIotaTransactionBlockResponse;

Expand Down Expand Up @@ -362,6 +372,11 @@ impl IotaTransactionBlockResponseAdapter {
.collect()
})
}

pub fn digest(&self) -> Result<TransactionDigest, TsSdkError> {
TransactionDigest::from_str(&self.digest_inner())
.map_err(|err| TsSdkError::WasmError("Failed to parse transaction block digest".to_string(), err.to_string()))
}
}

pub async fn execute_transaction(
Expand Down
22 changes: 15 additions & 7 deletions bindings/wasm/iota_interaction_ts/src/iota_client_ts_sdk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ impl IotaTransactionBlockResponseT for IotaTransactionBlockResponseProvider {
fn clone_native_response(&self) -> Self::NativeResponse {
self.response.clone()
}

fn digest(&self) -> Result<TransactionDigest, Self::Error> {
self.response.digest()
}
}

pub struct ReadAdapter {
Expand Down Expand Up @@ -345,13 +349,17 @@ impl IotaClientTrait for IotaClientTsSdk {
.sdk_execute_transaction(sender_address, sender_public_key, tx, gas_budget, signer)
.await?;

// wait a certain amount to time before continuing
// a follow up step was fetching an object created with this tx, which - for some reason - wasn't available yet
// TODO: check timing issues related to transactions finality here
sleep(500)
.await
.map_err(WasmError::from)
.map_err(TsSdkError::from)?;
// wait until new transaction block is available
self
.iota_client
.wait_for_transaction(
response.digest()?,
Some(IotaTransactionBlockResponseOptions::new()),
None,
None,
)
.await
.unwrap();

Ok(Box::new(response))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ impl IotaTransactionBlockResponseT for IotaTransactionBlockResponseProvider {
fn clone_native_response(&self) -> Self::NativeResponse {
self.response.clone()
}

fn digest(&self) -> Result<TransactionDigest, Self::Error> {
Ok(self.response.digest)
}
}

pub(crate) struct QuorumDriverAdapter<'a> {
Expand Down
3 changes: 3 additions & 0 deletions identity_iota_interaction/src/iota_client_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ pub trait IotaTransactionBlockResponseT: OptionalSend {

/// Returns a clone of the wrapped platform specific client sdk response
fn clone_native_response(&self) -> Self::NativeResponse;

// Returns digest for transaction block.
fn digest(&self) -> Result<TransactionDigest, Self::Error>;
}

#[cfg_attr(not(feature = "send-sync-transaction"), async_trait(?Send))]
Expand Down
35 changes: 35 additions & 0 deletions identity_iota_interaction/src/sdk_types/generated_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ pub struct GetTransactionBlockParams {
/// the digest of the queried transaction
digest: String,
/// options for specifying the content to be returned
#[serde(skip_serializing_if = "Option::is_none")]
options: Option<IotaTransactionBlockResponseOptions>,
}

Expand Down Expand Up @@ -228,3 +229,37 @@ impl GetCoinsParams {
}
}
}

/// Params for `wait_for_transaction` / `wait_for_transaction`.
///
/// Be careful when serializing with `serde_wasm_bindgen::to_value`, as `#[serde(flatten)]`
/// will turn the object into a `Map` instead of a plain object in Js.
/// Prefer serializing with `serde_wasm_bindgen::Serializer::json_compatible` or perform custom serialization.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WaitForTransactionParams {
/// Block digest and options for content that should be returned.
#[serde(flatten)]
get_transaction_block_params: GetTransactionBlockParams,
/// The amount of time to wait for a transaction block. Defaults to one minute.
#[serde(skip_serializing_if = "Option::is_none")]
timeout: Option<u64>,
/// The amount of time to wait between checks for the transaction block. Defaults to 2 seconds.
#[serde(skip_serializing_if = "Option::is_none")]
poll_interval: Option<u64>,
}

impl WaitForTransactionParams {
pub fn new(
digest: String,
options: Option<IotaTransactionBlockResponseOptions>,
timeout: Option<u64>,
poll_interval: Option<u64>,
) -> Self {
WaitForTransactionParams {
get_transaction_block_params: GetTransactionBlockParams::new(digest, options),
timeout,
poll_interval,
}
}
}

0 comments on commit 9628021

Please sign in to comment.