Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bindings/wasm/identity_wasm/src/common/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ extern "C" {
#[wasm_bindgen(typescript_type = "VerificationMethod[]")]
pub type ArrayVerificationMethod;

#[wasm_bindgen(typescript_type = "Array<DIDUrl | VerificationMethod>")]
#[wasm_bindgen(typescript_type = "Array<MethodRef>")]
pub type ArrayCoreMethodRef;

#[wasm_bindgen(typescript_type = "DIDUrl | string")]
Expand Down
2 changes: 2 additions & 0 deletions bindings/wasm/identity_wasm/src/did/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod wasm_core_did;
mod wasm_core_document;
mod wasm_did_jwk_document_ext;
mod wasm_did_url;
mod wasm_method_ref;

pub use self::jws_verification_options::*;
pub use self::service::IService;
Expand All @@ -23,5 +24,6 @@ pub use self::wasm_core_document::PromiseJws;
pub use self::wasm_core_document::PromiseJwt;
pub use self::wasm_core_document::WasmCoreDocument;
pub use self::wasm_did_url::WasmDIDUrl;
pub use self::wasm_method_ref::WasmMethodRef;
pub use did_compositejwk::*;
pub use did_jwk::*;
32 changes: 7 additions & 25 deletions bindings/wasm/identity_wasm/src/did/wasm_core_document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::rc::Rc;

use super::WasmCoreDID;
use super::WasmJwsVerificationOptions;
use super::WasmMethodRef;
use crate::common::ArrayCoreMethodRef;
use crate::common::ArrayService;
use crate::common::ArrayString;
Expand Down Expand Up @@ -58,7 +59,6 @@ use identity_iota::storage::key_storage::KeyType;
use identity_iota::storage::storage::JwkDocumentExt;
use identity_iota::storage::storage::JwsSignatureOptions;
use identity_iota::verification::jose::jws::JwsAlgorithm;
use identity_iota::verification::MethodRef;
use identity_iota::verification::MethodScope;
use identity_iota::verification::VerificationMethod;

Expand Down Expand Up @@ -220,10 +220,7 @@ impl WasmCoreDocument {
.authentication()
.iter()
.cloned()
.map(|method_ref| match method_ref {
MethodRef::Embed(verification_method) => JsValue::from(WasmVerificationMethod(verification_method)),
MethodRef::Refer(did_url) => JsValue::from(WasmDIDUrl(did_url)),
})
.map(|method_ref| JsValue::from(WasmMethodRef(method_ref)))
.collect::<js_sys::Array>()
.unchecked_into::<ArrayCoreMethodRef>(),
)
Expand All @@ -239,10 +236,7 @@ impl WasmCoreDocument {
.assertion_method()
.iter()
.cloned()
.map(|method_ref| match method_ref {
MethodRef::Embed(verification_method) => JsValue::from(WasmVerificationMethod(verification_method)),
MethodRef::Refer(did_url) => JsValue::from(WasmDIDUrl(did_url)),
})
.map(|method_ref| JsValue::from(WasmMethodRef(method_ref)))
.collect::<js_sys::Array>()
.unchecked_into::<ArrayCoreMethodRef>(),
)
Expand All @@ -258,10 +252,7 @@ impl WasmCoreDocument {
.key_agreement()
.iter()
.cloned()
.map(|method_ref| match method_ref {
MethodRef::Embed(verification_method) => JsValue::from(WasmVerificationMethod(verification_method)),
MethodRef::Refer(did_url) => JsValue::from(WasmDIDUrl(did_url)),
})
.map(|method_ref| JsValue::from(WasmMethodRef(method_ref)))
.collect::<js_sys::Array>()
.unchecked_into::<ArrayCoreMethodRef>(),
)
Expand All @@ -277,10 +268,7 @@ impl WasmCoreDocument {
.capability_delegation()
.iter()
.cloned()
.map(|method_ref| match method_ref {
MethodRef::Embed(verification_method) => JsValue::from(WasmVerificationMethod(verification_method)),
MethodRef::Refer(did_url) => JsValue::from(WasmDIDUrl(did_url)),
})
.map(|method_ref| JsValue::from(WasmMethodRef(method_ref)))
.collect::<js_sys::Array>()
.unchecked_into::<ArrayCoreMethodRef>(),
)
Expand All @@ -296,10 +284,7 @@ impl WasmCoreDocument {
.capability_invocation()
.iter()
.cloned()
.map(|method_ref| match method_ref {
MethodRef::Embed(verification_method) => JsValue::from(WasmVerificationMethod(verification_method)),
MethodRef::Refer(did_url) => JsValue::from(WasmDIDUrl(did_url)),
})
.map(|method_ref| JsValue::from(WasmMethodRef(method_ref)))
.collect::<js_sys::Array>()
.unchecked_into::<ArrayCoreMethodRef>(),
)
Expand Down Expand Up @@ -417,10 +402,7 @@ impl WasmCoreDocument {
.try_read()?
.verification_relationships()
.cloned()
.map(|method_ref| match method_ref {
MethodRef::Embed(verification_method) => JsValue::from(WasmVerificationMethod(verification_method)),
MethodRef::Refer(did_url) => JsValue::from(WasmDIDUrl(did_url)),
})
.map(|method_ref| JsValue::from(WasmMethodRef(method_ref)))
.collect::<js_sys::Array>()
.unchecked_into::<ArrayCoreMethodRef>(),
)
Expand Down
75 changes: 75 additions & 0 deletions bindings/wasm/identity_wasm/src/did/wasm_method_ref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright 2020-2026 IOTA Stiftung
// SPDX-License-Identifier: Apache-2.0

use crate::did::WasmDIDUrl;
use crate::error::Result;
use crate::error::WasmResult;
use crate::verification::WasmVerificationMethod;
use identity_iota::verification::MethodRef;
use wasm_bindgen::prelude::*;

/// A reference held inside a verification relationship: either an embedded
/// {@link VerificationMethod}, an absolute DID URL (`"refer"`), or a relative
/// DID URL resolved against the document DID (`"relativeRefer"`).
#[wasm_bindgen(js_name = MethodRef, inspectable)]
pub struct WasmMethodRef(pub(crate) MethodRef);

#[wasm_bindgen(js_class = MethodRef)]
impl WasmMethodRef {
/// Returns the variant: `"embedded"`, `"refer"`, or `"relativeRefer"`.
#[wasm_bindgen(getter, js_name = type)]
pub fn kind(&self) -> String {
match &self.0 {
MethodRef::Embed(_) => "embedded",
MethodRef::Refer(_) => "refer",
MethodRef::RelativeRefer(_) => "relativeRefer",
}
.to_owned()
}

/// Returns the embedded {@link VerificationMethod}, or `undefined` for references.
#[wasm_bindgen(js_name = asVerificationMethod)]
pub fn as_verification_method(&self) -> Option<WasmVerificationMethod> {
if let MethodRef::Embed(method) = &self.0 {
Some(WasmVerificationMethod(method.clone()))
} else {
None
}
}

/// Returns the resolved absolute {@link DIDUrl} for `"refer"` and `"relativeRefer"`,
/// or `undefined` for embedded methods.
///
/// Note: for `"relativeRefer"` this is the *resolved* URL (e.g. `did:example:123#key-1`).
/// Use {@link MethodRef#toString} to obtain the original relative string (e.g. `"#key-1"`).
#[wasm_bindgen(js_name = asDIDUrl)]
pub fn as_did_url(&self) -> Option<WasmDIDUrl> {
match &self.0 {
MethodRef::Refer(did_url) | MethodRef::RelativeRefer(did_url) => Some(WasmDIDUrl(did_url.clone())),
MethodRef::Embed(_) => None,
}
}

/// Serializes as the document JSON representation:
/// - `"embedded"` → the full verification method object
/// - `"refer"` → the absolute DID URL string
/// - `"relativeRefer"` → the relative reference string (e.g. `"#key-1"`)
#[wasm_bindgen(js_name = toJSON)]
pub fn to_json(&self) -> Result<JsValue> {
JsValue::from_serde(&self.0).wasm_result()
}

/// Returns the string form consistent with the document JSON:
/// the relative string for `"relativeRefer"`, the full DID URL string for all others.
#[allow(clippy::inherent_to_string)]
#[wasm_bindgen(js_name = toString)]
pub fn to_string(&self) -> String {
match &self.0 {
MethodRef::Embed(method) => method.id().to_string(),
MethodRef::Refer(did_url) => did_url.to_string(),
MethodRef::RelativeRefer(did_url) => did_url.url().to_string(),
}
}
}

impl_wasm_clone!(WasmMethodRef, MethodRef);
61 changes: 61 additions & 0 deletions bindings/wasm/identity_wasm/tests/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
EdCurve,
Jwk,
JwkType,
MethodRef,
MethodRelationship,
MethodScope,
MethodType,
Expand Down Expand Up @@ -314,6 +315,66 @@ describe("CoreDocument", function() {
assert.deepStrictEqual(doc.service().length, 0);
});
});
describe("#fromJSON / MethodRef types", function() {
const JSON_DOCUMENT = {
"@context": [
"https://www.w3.org/ns/did/v1",
"https://w3id.org/security/suites/ed25519-2020/v1",
],
"id": "did:example:123",
"verificationMethod": [{
"id": "did:example:1234#key1",
"controller": "did:example:1234",
"type": "Ed25519VerificationKey2018",
"publicKeyBase58": "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J",
}],
"authentication": [
{
"id": "did:example:123#embedded-key",
"controller": "did:example:123",
"type": "Ed25519VerificationKey2018",
"publicKeyBase58": "3M5RCDjPTWPkKSN3sxUmmMqHbmRPegYP1tjcKyrDbt9J",
},
"did:example:1234#key1",
"#key-1",
],
};

it("deserializes all three MethodRef types", () => {
const auth = CoreDocument.fromJSON(JSON_DOCUMENT).authentication();

assert.strictEqual(auth[0].type, "embedded");
assert.strictEqual(auth[0].asVerificationMethod()!.id().toString(), "did:example:123#embedded-key");

assert.strictEqual(auth[1].type, "refer");
assert.strictEqual(auth[1].toString(), "did:example:1234#key1");

assert.strictEqual(auth[2].type, "relativeRefer");
assert.strictEqual(auth[2].toString(), "#key-1");
assert.strictEqual(auth[2].asDIDUrl()!.toString(), "did:example:123#key-1");
});

it("extracts relative reference string from RelativeRefer", () => {
const auth: MethodRef[] = CoreDocument.fromJSON(JSON_DOCUMENT).authentication();

assert.strictEqual(auth[0].asVerificationMethod()!.id().toString(), "did:example:123#embedded-key");
assert.strictEqual(auth[1].asDIDUrl()!.toString(), "did:example:1234#key1");
// asDIDUrl() returns the resolved absolute URL; toString() returns the original relative reference
assert.strictEqual(auth[2].asDIDUrl()!.toString(), "did:example:123#key-1");
assert.strictEqual(auth[2].toString(), "#key-1");
});

it("serializes all three MethodRef types correctly", () => {
const auth = CoreDocument.fromJSON(JSON_DOCUMENT).toJSON().authentication;

assert.strictEqual(typeof auth[0], "object");
assert.strictEqual(auth[0].id, "did:example:123#embedded-key");

assert.strictEqual(auth[1], "did:example:1234#key1");

assert.strictEqual(auth[2], "#key-1");
});
});
describe("#properties", function() {
it("should work", () => {
const doc = new CoreDocument({
Expand Down
2 changes: 1 addition & 1 deletion identity_document/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ identity_did = { version = "=1.9.10-beta.1", path = "../identity_did" }
identity_verification = { version = "=1.9.10-beta.1", path = "../identity_verification", default-features = false }
indexmap = { version = "2.0", default-features = false, features = ["std", "serde"] }
serde.workspace = true
serde_json.workspace = true
strum.workspace = true
thiserror.workspace = true

[dev-dependencies]
criterion = { version = "0.4.0", default-features = false, features = ["cargo_bench_support"] }
serde_json.workspace = true

[[bench]]
name = "deserialize_document"
Expand Down
Loading
Loading