diff --git a/bindings/wasm/docs/api-reference.md b/bindings/wasm/docs/api-reference.md
index 41d0f5f654..fe562d2d8f 100644
--- a/bindings/wasm/docs/api-reference.md
+++ b/bindings/wasm/docs/api-reference.md
@@ -179,11 +179,8 @@ See IVerifierOptions
.
## Members
-- MethodRelationship
+- StateMetadataEncoding
-- DIDType
-Supported types representing a DID that can be generated by the storage interface.
-
- StatusCheck
Controls validation behaviour when checking whether or not a credential has been revoked by its
credentialStatus
.
@@ -226,11 +223,14 @@ This variant is the default used if no other variant is specified when construct
- FirstError
Return after the first error occurs.
+- DIDType
+Supported types representing a DID that can be generated by the storage interface.
+
- KeyType
-- DIDMessageEncoding
+- MethodRelationship
-- StateMetadataEncoding
+- DIDMessageEncoding
@@ -274,10 +274,10 @@ publishing to the Tangle.
* [.unrevokeCredentials(fragment, indices)](#Account+unrevokeCredentials) ⇒ Promise.<void>
* [.encryptData(plaintext, associated_data, encryption_algorithm, cek_algorithm, public_key)](#Account+encryptData) ⇒ [Promise.<EncryptedData>
](#EncryptedData)
* [.decryptData(data, encryption_algorithm, cek_algorithm, fragment)](#Account+decryptData) ⇒ Promise.<Uint8Array>
- * [.deleteMethod(options)](#Account+deleteMethod) ⇒ Promise.<void>
* [.deleteService(options)](#Account+deleteService) ⇒ Promise.<void>
* [.setAlsoKnownAs(options)](#Account+setAlsoKnownAs) ⇒ Promise.<void>
* [.setController(options)](#Account+setController) ⇒ Promise.<void>
+ * [.deleteMethod(options)](#Account+deleteMethod) ⇒ Promise.<void>
@@ -517,17 +517,6 @@ Returns the decrypted text.
| cek_algorithm | [CekAlgorithm
](#CekAlgorithm) |
| fragment | string
|
-
-
-### account.deleteMethod(options) ⇒ Promise.<void>
-Deletes a verification method if the method exists.
-
-**Kind**: instance method of [Account
](#Account)
-
-| Param | Type |
-| --- | --- |
-| options | DeleteMethodOptions
|
-
### account.deleteService(options) ⇒ Promise.<void>
@@ -561,6 +550,17 @@ Sets the controllers of the DID document.
| --- | --- |
| options | SetControllerOptions
|
+
+
+### account.deleteMethod(options) ⇒ Promise.<void>
+Deletes a verification method if the method exists.
+
+**Kind**: instance method of [Account
](#Account)
+
+| Param | Type |
+| --- | --- |
+| options | DeleteMethodOptions
|
+
## AccountBuilder
@@ -5127,6 +5127,7 @@ Deserializes an instance from a JSON object.
* _static_
* [.newWithId(id)](#StardustDocument.newWithId) ⇒ [StardustDocument
](#StardustDocument)
* [.unpack(did, stateMetadata, allowEmpty)](#StardustDocument.unpack) ⇒ [StardustDocument
](#StardustDocument)
+ * [.unpackFromBlock(network, block)](#StardustDocument.unpackFromBlock) ⇒ [Array.<StardustDocument>
](#StardustDocument)
* [.fromJSON(json)](#StardustDocument.fromJSON) ⇒ [StardustDocument
](#StardustDocument)
@@ -5527,6 +5528,21 @@ encoded in the `AliasId` alone.
| stateMetadata | Uint8Array
|
| allowEmpty | boolean
|
+
+
+### StardustDocument.unpackFromBlock(network, block) ⇒ [Array.<StardustDocument>
](#StardustDocument)
+Returns all DID documents of the Alias Outputs contained in the block's transaction payload
+outputs, if any.
+
+Errors if any Alias Output does not contain a valid or empty DID Document.
+
+**Kind**: static method of [StardustDocument
](#StardustDocument)
+
+| Param | Type |
+| --- | --- |
+| network | string
|
+| block | IBlock
|
+
### StardustDocument.fromJSON(json) ⇒ [StardustDocument
](#StardustDocument)
@@ -6263,15 +6279,9 @@ This is possible because Ed25519 is birationally equivalent to Curve25519 used b
| --- | --- |
| publicKey | Uint8Array
|
-
-
-## MethodRelationship
-**Kind**: global variable
-
-
-## DIDType
-Supported types representing a DID that can be generated by the storage interface.
+
+## StateMetadataEncoding
**Kind**: global variable
@@ -6350,18 +6360,24 @@ Return all errors that occur during validation.
## FirstError
Return after the first error occurs.
+**Kind**: global variable
+
+
+## DIDType
+Supported types representing a DID that can be generated by the storage interface.
+
**Kind**: global variable
## KeyType
**Kind**: global variable
-
+
-## DIDMessageEncoding
+## MethodRelationship
**Kind**: global variable
-
+
-## StateMetadataEncoding
+## DIDMessageEncoding
**Kind**: global variable
diff --git a/bindings/wasm/examples-stardust/src/ex0_create_did.ts b/bindings/wasm/examples-stardust/src/ex0_create_did.ts
index f13a6df25d..ca690a9f05 100644
--- a/bindings/wasm/examples-stardust/src/ex0_create_did.ts
+++ b/bindings/wasm/examples-stardust/src/ex0_create_did.ts
@@ -10,8 +10,7 @@ import {
StardustIdentityClient,
StardustVerificationMethod
} from '../../node';
-
-import {Bech32Helper, IAliasOutput,} from '@iota/iota.js';
+import {Bech32Helper, IAliasOutput} from '@iota/iota.js';
import {Bip39} from "@iota/crypto.js";
import fetch from "node-fetch";
import {Client, MnemonicSecretManager, SecretManager} from "@cycraig/iota-client-wasm/node";
@@ -49,8 +48,8 @@ export async function createIdentity(): Promise<{
}))[0];
console.log("Wallet address Bech32:", walletAddressBech32);
- // Request funds for the newly-created wallet - only works on development networks.
- await requestFundsFromFaucet(walletAddressBech32);
+ // Request funds for the wallet, if needed - only works on development networks.
+ await ensureAddressHasFunds(client, walletAddressBech32);
// Create a new DID document with a placeholder DID.
// The DID will be derived from the Alias Id of the Alias Output after publishing.
@@ -78,7 +77,46 @@ export async function createIdentity(): Promise<{
};
}
-/** Request tokens from the faucet API. */
+/** Request funds from the testnet faucet API, if needed, and wait for them to show in the wallet. */
+async function ensureAddressHasFunds(client: Client, addressBech32: string) {
+ let balance = await getAddressBalance(client, addressBech32);
+ if (balance > 0) {
+ return;
+ }
+
+ await requestFundsFromFaucet(addressBech32);
+
+ for (let i = 0; i < 9; i++) {
+ // Wait for the funds to reflect.
+ await new Promise(f => setTimeout(f, 5000));
+
+ let balance = await getAddressBalance(client, addressBech32);
+ if (balance > 0) {
+ break;
+ }
+ }
+}
+
+/** Returns the balance of the given Bech32-encoded address. */
+async function getAddressBalance(client: Client, addressBech32: string): Promise {
+ // TODO: use the `addresses/ed25519/` API to get the balance?
+ const outputIds = await client.basicOutputIds([
+ {address: addressBech32},
+ {hasExpiration: false},
+ {hasTimelock: false},
+ {hasStorageDepositReturn: false}
+ ]);
+ const outputs = await client.getOutputs(outputIds);
+
+ let totalAmount = 0;
+ for (const output of outputs) {
+ totalAmount += Number(output.output.amount);
+ }
+
+ return totalAmount;
+}
+
+/** Request tokens from the testnet faucet API. */
async function requestFundsFromFaucet(addressBech32: string) {
const requestObj = JSON.stringify({address: addressBech32});
let errorMessage, data;
diff --git a/bindings/wasm/examples-stardust/src/ex1_update_did.ts b/bindings/wasm/examples-stardust/src/ex1_update_did.ts
index f4889db535..8fea877b66 100644
--- a/bindings/wasm/examples-stardust/src/ex1_update_did.ts
+++ b/bindings/wasm/examples-stardust/src/ex1_update_did.ts
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import {MethodRelationship, StardustDocument, StardustService, Timestamp} from '../../node';
-import {IAliasOutput, IRent, TransactionHelper,} from '@iota/iota.js';
+import {IAliasOutput, IRent, TransactionHelper} from '@iota/iota.js';
import {createIdentity} from "./ex0_create_did";
diff --git a/bindings/wasm/examples-stardust/src/ex4_delete_did.ts b/bindings/wasm/examples-stardust/src/ex4_delete_did.ts
index 342b39d409..976bc5977d 100644
--- a/bindings/wasm/examples-stardust/src/ex4_delete_did.ts
+++ b/bindings/wasm/examples-stardust/src/ex4_delete_did.ts
@@ -15,9 +15,6 @@ export async function deleteIdentity() {
const destinationAddress = Bech32Helper.addressFromBech32(walletAddressBech32, await didClient.getNetworkHrp());
await didClient.deleteDidOutput(secretManager, destinationAddress, did);
- // Wait for the node to index the new state.
- await new Promise(f => setTimeout(f, 5000));
-
// Attempting to resolve a deleted DID results in a `NotFound` error.
let deleted = false;
try {
diff --git a/bindings/wasm/lib/stardust_identity_client.ts b/bindings/wasm/lib/stardust_identity_client.ts
index e26b8d192f..9b2a046228 100644
--- a/bindings/wasm/lib/stardust_identity_client.ts
+++ b/bindings/wasm/lib/stardust_identity_client.ts
@@ -9,17 +9,11 @@ import {
AddressTypes,
ALIAS_OUTPUT_TYPE,
IAliasOutput,
- IBlock,
IOutputResponse,
IRent,
- ITransactionPayload,
IUTXOInput,
- OutputTypes,
- TRANSACTION_PAYLOAD_TYPE,
TransactionHelper
} from '@iota/iota.js';
-import {Converter} from '@iota/util.js';
-import {Blake2b} from '@iota/crypto.js';
/** Provides operations for IOTA UTXO DID Documents with Alias Outputs. */
export class StardustIdentityClient implements IStardustIdentityClient {
@@ -120,7 +114,7 @@ export class StardustIdentityClient implements IStardustIdentityClient {
await this.client.retryUntilIncluded(blockId);
// Extract document with computed AliasId.
- const documents = extractDocumentsFromBlock(networkHrp, block);
+ const documents = StardustDocument.unpackFromBlock(networkHrp, block);
if (documents.length < 1) {
throw new Error("publishDidOutput: no DID document in transaction payload");
}
@@ -166,60 +160,3 @@ export class StardustIdentityClient implements IStardustIdentityClient {
await this.client.retryUntilIncluded(blockId);
}
}
-
-/** Compute the AliasId as a prefix-hex encoded string. */
-function computeAliasId(transactionIdHex: string, outputIndex: number): string {
- const outputIdHex: string = TransactionHelper.outputIdFromTransactionData(transactionIdHex, outputIndex);
- return computeAliasIdFromOutputId(outputIdHex);
-}
-
-/** Compute the AliasId as a prefix-hex encoded string. */
-function computeAliasIdFromOutputId(outputIdHex: string): string {
- // Blake2b-256 digest of output id.
- const outputIdBytes: Uint8Array = Converter.hexToBytes(outputIdHex);
- const digest: Uint8Array = Blake2b.sum256(outputIdBytes);
- return Converter.bytesToHex(digest, true);
-}
-
-/** Extract all DID documents of the Alias Outputs contained in a transaction payload, if any. */
-function extractDocumentsFromBlock(networkHrp: string, block: IBlock): StardustDocument[] {
- const documents: StardustDocument[] = [];
-
- if (block.payload === undefined || block.payload?.type !== TRANSACTION_PAYLOAD_TYPE) {
- throw new Error("failed to extract documents from block, transaction payload missing or wrong type");
- }
- const payload: ITransactionPayload = block.payload;
-
- // Compute TransactionId.
- const transactionPayloadHash: Uint8Array = TransactionHelper.getTransactionPayloadHash(payload);
- const transactionId: string = Converter.bytesToHex(transactionPayloadHash, true);
-
- // Loop over Alias Outputs.
- const outputs: OutputTypes[] = payload.essence.outputs;
- for (let index = 0; index < outputs.length; index += 1) {
- const output = outputs[index];
- if (output.type !== ALIAS_OUTPUT_TYPE) {
- continue;
- }
-
- // Compute Alias Id.
- let aliasIdHex: string;
- if (output.stateIndex === 0) {
- aliasIdHex = computeAliasId(transactionId, index);
- } else {
- aliasIdHex = output.aliasId;
- }
- const aliasId: Uint8Array = Converter.hexToBytes(aliasIdHex);
-
- // Unpack document.
- const did: StardustDID = new StardustDID(aliasId, networkHrp);
- let stateMetadata: Uint8Array;
- if (output.stateMetadata === undefined) {
- stateMetadata = new Uint8Array(0);
- } else {
- stateMetadata = Converter.hexToBytes(output.stateMetadata);
- }
- documents.push(StardustDocument.unpack(did, stateMetadata, true));
- }
- return documents;
-}
diff --git a/bindings/wasm/package-lock.json b/bindings/wasm/package-lock.json
index e60260e666..697755f84d 100644
--- a/bindings/wasm/package-lock.json
+++ b/bindings/wasm/package-lock.json
@@ -14,6 +14,7 @@
"node-fetch": "^2.6.7"
},
"devDependencies": {
+ "@iota/crypto.js": "^1.9.0-stardust.6",
"@types/mocha": "^9.1.0",
"concurrently": "^7.0.0",
"copy-webpack-plugin": "^7.0.0",
@@ -38,9 +39,7 @@
},
"peerDependencies": {
"@cycraig/iota-client-wasm": "^0.5.0-alpha.1",
- "@iota/crypto.js": "^1.9.0-stardust.6",
- "@iota/iota.js": "^1.9.0-stardust.25",
- "@iota/util.js": "^1.9.0-stardust.5"
+ "@iota/iota.js": "^1.9.0-stardust.25"
}
},
"../../../iota.rs/bindings/wasm": {
@@ -190,7 +189,6 @@
"version": "1.9.0-stardust.6",
"resolved": "https://registry.npmjs.org/@iota/crypto.js/-/crypto.js-1.9.0-stardust.6.tgz",
"integrity": "sha512-jbruSRXlEKW2dgfPFG7e42ODBp4dVu2/CAh/oZrzMjehPdyF2tgAeN1woOqOAmVONWoGVV9GViZti3nShhGF1g==",
- "peer": true,
"dependencies": {
"@iota/util.js": "^1.9.0-stardust.5",
"big-integer": "^1.6.51"
@@ -222,7 +220,6 @@
"version": "1.9.0-stardust.5",
"resolved": "https://registry.npmjs.org/@iota/util.js/-/util.js-1.9.0-stardust.5.tgz",
"integrity": "sha512-BGXzzjUQQYaV/H0bXJYKW+Zgd9PIN+HLPH8BcYhubI65X4G2ID23/osmpK/za+Ds6t/MkpdPKIiBwZPGXuCUBw==",
- "peer": true,
"dependencies": {
"big-integer": "^1.6.51"
},
@@ -935,7 +932,6 @@
"version": "1.6.51",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
"integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==",
- "peer": true,
"engines": {
"node": ">=0.6"
}
@@ -6503,7 +6499,6 @@
"version": "1.9.0-stardust.6",
"resolved": "https://registry.npmjs.org/@iota/crypto.js/-/crypto.js-1.9.0-stardust.6.tgz",
"integrity": "sha512-jbruSRXlEKW2dgfPFG7e42ODBp4dVu2/CAh/oZrzMjehPdyF2tgAeN1woOqOAmVONWoGVV9GViZti3nShhGF1g==",
- "peer": true,
"requires": {
"@iota/util.js": "^1.9.0-stardust.5",
"big-integer": "^1.6.51"
@@ -6529,7 +6524,6 @@
"version": "1.9.0-stardust.5",
"resolved": "https://registry.npmjs.org/@iota/util.js/-/util.js-1.9.0-stardust.5.tgz",
"integrity": "sha512-BGXzzjUQQYaV/H0bXJYKW+Zgd9PIN+HLPH8BcYhubI65X4G2ID23/osmpK/za+Ds6t/MkpdPKIiBwZPGXuCUBw==",
- "peer": true,
"requires": {
"big-integer": "^1.6.51"
}
@@ -7111,8 +7105,7 @@
"big-integer": {
"version": "1.6.51",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
- "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==",
- "peer": true
+ "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg=="
},
"big.js": {
"version": "5.2.2",
diff --git a/bindings/wasm/package.json b/bindings/wasm/package.json
index 19abf98bcc..bf1a8039c9 100644
--- a/bindings/wasm/package.json
+++ b/bindings/wasm/package.json
@@ -54,6 +54,7 @@
"node/*"
],
"devDependencies": {
+ "@iota/crypto.js": "^1.9.0-stardust.6",
"@types/mocha": "^9.1.0",
"concurrently": "^7.0.0",
"copy-webpack-plugin": "^7.0.0",
@@ -80,9 +81,7 @@
},
"peerDependencies": {
"@cycraig/iota-client-wasm": "^0.5.0-alpha.1",
- "@iota/crypto.js": "^1.9.0-stardust.6",
- "@iota/iota.js": "^1.9.0-stardust.25",
- "@iota/util.js": "^1.9.0-stardust.5"
+ "@iota/iota.js": "^1.9.0-stardust.25"
},
"engines": {
"node": ">=16"
diff --git a/bindings/wasm/src/stardust/identity_client.rs b/bindings/wasm/src/stardust/identity_client.rs
index 9e983161a1..1620c20ed0 100644
--- a/bindings/wasm/src/stardust/identity_client.rs
+++ b/bindings/wasm/src/stardust/identity_client.rs
@@ -96,7 +96,7 @@ impl StardustIdentityClient for WasmStardustIdentityClient {
#[wasm_bindgen(typescript_custom_section)]
const I_STARDUST_IDENTITY_CLIENT: &'static str = r#"
-import { IAliasOutput, IRent } from '@iota/types';
+import type { IAliasOutput, IRent } from '@iota/types';
/** Helper interface necessary for `StardustIdentityClientExt`. */
interface IStardustIdentityClient {
/**
diff --git a/bindings/wasm/src/stardust/identity_client_ext.rs b/bindings/wasm/src/stardust/identity_client_ext.rs
index 3cc1f7b958..e6549c8175 100644
--- a/bindings/wasm/src/stardust/identity_client_ext.rs
+++ b/bindings/wasm/src/stardust/identity_client_ext.rs
@@ -23,7 +23,7 @@ use crate::stardust::WasmStardustDocument;
// `IAliasOutput`, `AddressTypes`, and `IRent` are external interfaces.
// See the custom TypeScript section in `identity_client.rs` for the first import statement.
#[wasm_bindgen(typescript_custom_section)]
-const TYPESCRIPT_IMPORTS: &'static str = r#"import { AddressTypes } from '@iota/types';"#;
+const TYPESCRIPT_IMPORTS: &'static str = r#"import type { AddressTypes } from '@iota/types';"#;
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(typescript_type = "Promise")]
diff --git a/bindings/wasm/src/stardust/stardust_document.rs b/bindings/wasm/src/stardust/stardust_document.rs
index 0f81487c4f..a342ac9d4d 100644
--- a/bindings/wasm/src/stardust/stardust_document.rs
+++ b/bindings/wasm/src/stardust/stardust_document.rs
@@ -396,6 +396,34 @@ impl WasmStardustDocument {
.wasm_result()
}
+ /// Returns all DID documents of the Alias Outputs contained in the block's transaction payload
+ /// outputs, if any.
+ ///
+ /// Errors if any Alias Output does not contain a valid or empty DID Document.
+ #[wasm_bindgen(js_name = unpackFromBlock)]
+ pub fn unpack_from_block(network: String, block: &IBlock) -> Result {
+ let network_name: NetworkName = NetworkName::try_from(network).wasm_result()?;
+ let block_dto: bee_block::BlockDto = block
+ .into_serde()
+ .map_err(|err| {
+ identity_stardust::Error::JsError(format!("unpackFromBlock failed to deserialize BlockDto: {}", err))
+ })
+ .wasm_result()?;
+ let block: bee_block::Block = bee_block::Block::try_from(&block_dto)
+ .map_err(|err| identity_stardust::Error::JsError(format!("unpackFromBlock failed to convert BlockDto: {}", err)))
+ .wasm_result()?;
+
+ Ok(
+ StardustDocument::unpack_from_block(&network_name, &block)
+ .wasm_result()?
+ .into_iter()
+ .map(WasmStardustDocument::from)
+ .map(JsValue::from)
+ .collect::()
+ .unchecked_into::(),
+ )
+ }
+
// ===========================================================================
// Metadata
// ===========================================================================
@@ -515,9 +543,19 @@ extern "C" {
#[wasm_bindgen(typescript_type = "StardustDID[]")]
pub type ArrayStardustDID;
+ #[wasm_bindgen(typescript_type = "StardustDocument[]")]
+ pub type ArrayStardustDocument;
+
#[wasm_bindgen(typescript_type = "StardustService[]")]
pub type ArrayStardustService;
#[wasm_bindgen(typescript_type = "StardustVerificationMethod[]")]
pub type ArrayStardustVerificationMethods;
+
+ // External interface from `@iota/types`, must be deserialized via BlockDto.
+ #[wasm_bindgen(typescript_type = "IBlock")]
+ pub type IBlock;
}
+
+#[wasm_bindgen(typescript_custom_section)]
+const TYPESCRIPT_IMPORTS: &'static str = r#"import type { IBlock } from '@iota/types';"#;
diff --git a/identity_stardust/src/client/client_ext.rs b/identity_stardust/src/client/client_ext.rs
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/identity_stardust/src/client/iota_client.rs b/identity_stardust/src/client/iota_client.rs
index 713a7cccae..fb76512f6b 100644
--- a/identity_stardust/src/client/iota_client.rs
+++ b/identity_stardust/src/client/iota_client.rs
@@ -1,8 +1,6 @@
// Copyright 2020-2022 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0
-use std::ops::Deref;
-
use iota_client::api_types::responses::OutputResponse;
use iota_client::secret::SecretManager;
use iota_client::Client;
@@ -16,8 +14,6 @@ use crate::block::output::Output;
use crate::block::output::OutputId;
use crate::block::output::RentStructure;
use crate::block::output::UnlockCondition;
-use crate::block::payload::transaction::TransactionEssence;
-use crate::block::payload::Payload;
use crate::block::Block;
use crate::client::identity_client::validate_network;
use crate::error::Result;
@@ -71,7 +67,7 @@ impl StardustClientExt for Client {
.map_err(|err| Error::DIDUpdateError("publish_did_output: publish failed", Some(err)))?;
let network: NetworkName = self.network_name().await?;
- extract_documents_from_block(&network, &block)?
+ StardustDocument::unpack_from_block(&network, &block)?
.into_iter()
.next()
.ok_or(Error::DIDUpdateError(
@@ -155,35 +151,3 @@ async fn publish_output(
Ok(block)
}
-
-/// Returns all DID documents of the Alias Outputs contained in the payload's transaction, if any.
-fn extract_documents_from_block(network: &NetworkName, block: &Block) -> Result> {
- let mut documents = Vec::new();
-
- if let Some(Payload::Transaction(tx_payload)) = block.payload() {
- let TransactionEssence::Regular(regular) = tx_payload.essence();
-
- for (index, output) in regular.outputs().iter().enumerate() {
- if let Output::Alias(alias_output) = output {
- let alias_id = if alias_output.alias_id().is_null() {
- AliasId::from(
- OutputId::new(
- tx_payload.id(),
- index
- .try_into()
- .map_err(|_| Error::OutputIdConversionError(format!("output index {index} must fit into a u16")))?,
- )
- .map_err(|err| Error::OutputIdConversionError(err.to_string()))?,
- )
- } else {
- alias_output.alias_id().to_owned()
- };
-
- let did: StardustDID = StardustDID::new(alias_id.deref(), network);
- documents.push(StardustDocument::unpack(&did, alias_output.state_metadata(), true)?);
- }
- }
- }
-
- Ok(documents)
-}
diff --git a/identity_stardust/src/document/stardust_document.rs b/identity_stardust/src/document/stardust_document.rs
index 2f8674426b..ed5f8b1789 100644
--- a/identity_stardust/src/document/stardust_document.rs
+++ b/identity_stardust/src/document/stardust_document.rs
@@ -303,6 +303,60 @@ impl StardustDocument {
}
}
+#[cfg(feature = "client")]
+mod client_document {
+ use std::ops::Deref;
+
+ use crate::block::output::AliasId;
+ use crate::block::output::Output;
+ use crate::block::output::OutputId;
+ use crate::block::payload::transaction::TransactionEssence;
+ use crate::block::payload::Payload;
+ use crate::block::Block;
+ use crate::error::Result;
+ use crate::Error;
+ use crate::NetworkName;
+
+ use super::*;
+
+ impl StardustDocument {
+ /// Returns all DID documents of the Alias Outputs contained in the block's transaction payload
+ /// outputs, if any.
+ ///
+ /// Errors if any Alias Output does not contain a valid or empty DID Document.
+ pub fn unpack_from_block(network: &NetworkName, block: &Block) -> Result> {
+ let mut documents = Vec::new();
+
+ if let Some(Payload::Transaction(tx_payload)) = block.payload() {
+ let TransactionEssence::Regular(regular) = tx_payload.essence();
+
+ for (index, output) in regular.outputs().iter().enumerate() {
+ if let Output::Alias(alias_output) = output {
+ let alias_id = if alias_output.alias_id().is_null() {
+ AliasId::from(
+ OutputId::new(
+ tx_payload.id(),
+ index
+ .try_into()
+ .map_err(|_| Error::OutputIdConversionError(format!("output index {index} must fit into a u16")))?,
+ )
+ .map_err(|err| Error::OutputIdConversionError(err.to_string()))?,
+ )
+ } else {
+ alias_output.alias_id().to_owned()
+ };
+
+ let did: StardustDID = StardustDID::new(alias_id.deref(), network);
+ documents.push(StardustDocument::unpack(&did, alias_output.state_metadata(), true)?);
+ }
+ }
+ }
+
+ Ok(documents)
+ }
+ }
+}
+
impl Document for StardustDocument {
type D = StardustDID;
type U = Object;