diff --git a/bindings/web5_uniffi/libtargets/build_all.sh b/bindings/web5_uniffi/libtargets/build_all.sh new file mode 100755 index 00000000..a40e3d3f --- /dev/null +++ b/bindings/web5_uniffi/libtargets/build_all.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +for dir in */; do + echo "Entering directory: $dir" + (cd "$dir" && ./build) + echo "Finished building in $dir" + echo "------------------------" +done + +echo "All builds completed" diff --git a/bindings/web5_uniffi/src/web5.udl b/bindings/web5_uniffi/src/web5.udl index 624f8ef3..d16f75fa 100644 --- a/bindings/web5_uniffi/src/web5.udl +++ b/bindings/web5_uniffi/src/web5.udl @@ -171,6 +171,8 @@ dictionary DidWebData { }; interface DidWeb { + [Name=from_public_jwk, Throws=RustCoreError] + constructor([ByRef] string domain, JwkData public_jwk); [Async, Name=from_uri, Throws=RustCoreError] constructor([ByRef] string uri); DidWebData get_data(); diff --git a/bindings/web5_uniffi_wrapper/src/dids/methods/did_web.rs b/bindings/web5_uniffi_wrapper/src/dids/methods/did_web.rs index d2f501dd..79de0131 100644 --- a/bindings/web5_uniffi_wrapper/src/dids/methods/did_web.rs +++ b/bindings/web5_uniffi_wrapper/src/dids/methods/did_web.rs @@ -1,5 +1,6 @@ use crate::{dids::resolution::resolution_result::ResolutionResult, errors::Result}; use std::sync::Arc; +use web5::crypto::jwk::Jwk; use web5::dids::methods::did_web::DidWeb as InnerDidWeb; pub struct DidWeb(pub InnerDidWeb); @@ -10,6 +11,11 @@ pub async fn did_web_resolve(uri: &str) -> Result> { } impl DidWeb { + pub fn from_public_jwk(domain: &str, public_key: Jwk) -> Result { + let did_web = InnerDidWeb::new(domain, public_key)?; + Ok(Self(did_web)) + } + pub async fn from_uri(uri: &str) -> Result { let did_web = InnerDidWeb::from_uri(uri).await?; Ok(Self(did_web)) diff --git a/bound/kt/pom.xml b/bound/kt/pom.xml index 1dd58b95..3dae4668 100644 --- a/bound/kt/pom.xml +++ b/bound/kt/pom.xml @@ -25,12 +25,6 @@ jna 5.12.0 - - org.junit.jupiter - junit-jupiter-api - 5.10.2 - test - org.jetbrains.kotlinx kotlinx-coroutines-core @@ -56,6 +50,14 @@ jackson-module-kotlin 2.17.0 + + + + org.junit.jupiter + junit-jupiter-api + 5.10.2 + test + diff --git a/bound/kt/src/main/kotlin/web5/sdk/dids/methods/web/DidWeb.kt b/bound/kt/src/main/kotlin/web5/sdk/dids/methods/web/DidWeb.kt new file mode 100644 index 00000000..6ec25ab1 --- /dev/null +++ b/bound/kt/src/main/kotlin/web5/sdk/dids/methods/web/DidWeb.kt @@ -0,0 +1,71 @@ +package web5.sdk.dids.methods.web + +import kotlinx.coroutines.runBlocking +import web5.sdk.crypto.keys.Jwk +import web5.sdk.dids.Did +import web5.sdk.dids.Document +import web5.sdk.dids.ResolutionResult +import web5.sdk.rust.SystemTarget + +import web5.sdk.rust.didWebResolve as rustCoreDidWebResolve +import web5.sdk.rust.DidWeb as RustCoreDidWeb + +/** + * A class representing a DID (Decentralized Identifier) using the Web method. + * + * @property did The DID associated with this instance. + * @property document The DID document associated with this instance. + */ +class DidWeb { + init { + SystemTarget.set() // ensure the sys arch is set for first-time loading + } + + val did: Did + val document: Document + + /** + * Constructs a DidWeb instance using a DID URI. + * + * @param uri The DID URI. + */ + constructor(uri: String) { + val rustCoreDidWeb = runBlocking { + RustCoreDidWeb.fromUri(uri) + } + + this.did = rustCoreDidWeb.getData().did + this.document = rustCoreDidWeb.getData().document + } + + /** + * Constructs a DidWeb instance using a domain and public key jwk + * + * @param domain The DID domain name. + */ + constructor(domain: String, publicKey: Jwk) { + val rustCoreDidWeb = runBlocking { + RustCoreDidWeb.fromPublicJwk(domain, publicKey); + } + + this.did = rustCoreDidWeb.getData().did + this.document = rustCoreDidWeb.getData().document + } + + companion object { + /** + * Resolves a DID URI to a DidResolutionResult. + * + * @param uri The DID URI to resolve. + * @return DidResolutionResult The result of the DID resolution. + */ + @JvmStatic + fun resolve(uri: String): ResolutionResult { + val rustCoreResolutionObject = + runBlocking { + rustCoreDidWebResolve(uri).getData() + } + return rustCoreResolutionObject + } + } +} diff --git a/bound/kt/src/main/kotlin/web5/sdk/rust/UniFFI.kt b/bound/kt/src/main/kotlin/web5/sdk/rust/UniFFI.kt index 694f2356..9ab044e0 100644 --- a/bound/kt/src/main/kotlin/web5/sdk/rust/UniFFI.kt +++ b/bound/kt/src/main/kotlin/web5/sdk/rust/UniFFI.kt @@ -881,6 +881,8 @@ internal open class UniffiVTableCallbackInterfaceVerifier( + + @@ -954,6 +956,8 @@ internal interface UniffiLib : Library { ): Pointer fun uniffi_web5_uniffi_fn_free_didweb(`ptr`: Pointer,uniffi_out_err: UniffiRustCallStatus, ): Unit + fun uniffi_web5_uniffi_fn_constructor_didweb_from_public_jwk(`domain`: RustBuffer.ByValue,`publicJwk`: RustBuffer.ByValue,uniffi_out_err: UniffiRustCallStatus, + ): Pointer fun uniffi_web5_uniffi_fn_constructor_didweb_from_uri(`uri`: RustBuffer.ByValue, ): Long fun uniffi_web5_uniffi_fn_method_didweb_get_data(`ptr`: Pointer,uniffi_out_err: UniffiRustCallStatus, @@ -1254,6 +1258,8 @@ internal interface UniffiLib : Library { ): Short fun uniffi_web5_uniffi_checksum_constructor_didjwk_from_uri( ): Short + fun uniffi_web5_uniffi_checksum_constructor_didweb_from_public_jwk( + ): Short fun uniffi_web5_uniffi_checksum_constructor_didweb_from_uri( ): Short fun uniffi_web5_uniffi_checksum_constructor_document_new( @@ -1401,6 +1407,9 @@ private fun uniffiCheckApiChecksums(lib: UniffiLib) { if (lib.uniffi_web5_uniffi_checksum_constructor_didjwk_from_uri() != 10422.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } + if (lib.uniffi_web5_uniffi_checksum_constructor_didweb_from_public_jwk() != 58059.toShort()) { + throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") + } if (lib.uniffi_web5_uniffi_checksum_constructor_didweb_from_uri() != 44078.toShort()) { throw RuntimeException("UniFFI API checksum mismatch: try cleaning and rebuilding your project") } @@ -2950,6 +2959,17 @@ open class DidWeb: Disposable, AutoCloseable, DidWebInterface { companion object { + @Throws(RustCoreException::class) fun `fromPublicJwk`(`domain`: kotlin.String, `publicJwk`: JwkData): DidWeb { + return FfiConverterTypeDidWeb.lift( + uniffiRustCallWithError(RustCoreException) { _status -> + UniffiLib.INSTANCE.uniffi_web5_uniffi_fn_constructor_didweb_from_public_jwk( + FfiConverterString.lower(`domain`),FfiConverterTypeJwkData.lower(`publicJwk`),_status) +} + ) + } + + + @Throws(RustCoreException::class) @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") suspend fun `fromUri`(`uri`: kotlin.String) : DidWeb { diff --git a/bound/kt/src/main/resources/libweb5_uniffi_aarch64_apple_darwin.dylib b/bound/kt/src/main/resources/libweb5_uniffi_aarch64_apple_darwin.dylib index cbb67ea7..10d84835 100755 Binary files a/bound/kt/src/main/resources/libweb5_uniffi_aarch64_apple_darwin.dylib and b/bound/kt/src/main/resources/libweb5_uniffi_aarch64_apple_darwin.dylib differ diff --git a/bound/kt/src/main/resources/libweb5_uniffi_x86_64_apple_darwin.dylib b/bound/kt/src/main/resources/libweb5_uniffi_x86_64_apple_darwin.dylib index 513fb245..5db2e256 100755 Binary files a/bound/kt/src/main/resources/libweb5_uniffi_x86_64_apple_darwin.dylib and b/bound/kt/src/main/resources/libweb5_uniffi_x86_64_apple_darwin.dylib differ diff --git a/bound/kt/src/main/resources/libweb5_uniffi_x86_64_unknown_linux_gnu.so b/bound/kt/src/main/resources/libweb5_uniffi_x86_64_unknown_linux_gnu.so index e96c1759..cc80cdec 100755 Binary files a/bound/kt/src/main/resources/libweb5_uniffi_x86_64_unknown_linux_gnu.so and b/bound/kt/src/main/resources/libweb5_uniffi_x86_64_unknown_linux_gnu.so differ diff --git a/bound/kt/src/main/resources/libweb5_uniffi_x86_64_unknown_linux_musl.so b/bound/kt/src/main/resources/libweb5_uniffi_x86_64_unknown_linux_musl.so index b2e0f41d..ea9210b0 100755 Binary files a/bound/kt/src/main/resources/libweb5_uniffi_x86_64_unknown_linux_musl.so and b/bound/kt/src/main/resources/libweb5_uniffi_x86_64_unknown_linux_musl.so differ diff --git a/bound/kt/src/test/kotlin/web5/sdk/dids/methods/jwk/DidJwkTests.kt b/bound/kt/src/test/kotlin/web5/sdk/dids/methods/jwk/DidJwkTests.kt index ccc7dbc8..38acd0d2 100644 --- a/bound/kt/src/test/kotlin/web5/sdk/dids/methods/jwk/DidJwkTests.kt +++ b/bound/kt/src/test/kotlin/web5/sdk/dids/methods/jwk/DidJwkTests.kt @@ -15,8 +15,6 @@ class DidJwkTests { val didJwk = DidJwk(jwk) - println(didJwk.document.id) - val rustCoreDidJwk = RustCoreDidJwk.fromPublicJwk(jwk); assertEquals(rustCoreDidJwk.getData().did.uri, didJwk.did.uri) assertEquals(rustCoreDidJwk.getData().document.id, didJwk.document.id) diff --git a/bound/kt/src/test/kotlin/web5/sdk/dids/methods/web/DidWebTests.kt b/bound/kt/src/test/kotlin/web5/sdk/dids/methods/web/DidWebTests.kt new file mode 100644 index 00000000..e56cdcc3 --- /dev/null +++ b/bound/kt/src/test/kotlin/web5/sdk/dids/methods/web/DidWebTests.kt @@ -0,0 +1,49 @@ +package web5.sdk.dids.methods.web + +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.Test +import web5.sdk.rust.ed25519GeneratorGenerate + +class DidWebTests { + + @Test + fun `can create did web`() { + val domain = "example.com" + val jwk = ed25519GeneratorGenerate(); + + val didWeb = DidWeb(domain, jwk) + assertEquals(didWeb.did.uri, "did:web:example.com") + assertEquals(didWeb.document.verificationMethod.get(0).publicKeyJwk, jwk) + } + + @Test + fun `can resolve did web uri`() { +// Works if you host a local did web document You must host this json at http://localhost:1234/.well-known/did.json +// val didDocumentJson = """ +// { +// "id":"did:web.tbd.website", +// "@context":[ +// "https://www.w3.org/ns/did/v1" +// ], +// "verificationMethod":[ +// { +// "id":"did:web:www.tbd.website#key-0", +// "type":"JsonWebKey", +// "controller":"did:web:www.tbd.website", +// "publicKeyJwk":{ +// "alg":"Ed25519", +// "kty":"OKP", +// "crv":"Ed25519", +// "x":"gNFtgCZhOYv00p48FHQYt4edkoBPOyw0oGAB20LrT0c" +// } +// } +// ] +// } +// """.trimIndent() +// +// val didUri = "did:web:localhost%3A1234" +// val resolvedDid = DidWeb.resolve(didUri) +// +// assertEquals(resolvedDid.document!!.id, "did:web:www.tbd.website") + } +} \ No newline at end of file diff --git a/crates/web5/src/dids/resolution/resolution_result.rs b/crates/web5/src/dids/resolution/resolution_result.rs index e3261a85..81542bc4 100644 --- a/crates/web5/src/dids/resolution/resolution_result.rs +++ b/crates/web5/src/dids/resolution/resolution_result.rs @@ -56,7 +56,7 @@ mod tests { } #[test] - fn can_resolve_did_web() { + fn can_resolve_invalid_did_web() { let did_uri = "did:web:tbd.website"; let resolution_result = ResolutionResult::new(did_uri); @@ -67,6 +67,16 @@ mod tests { ); } + // This works if you host a did web document json at http://localhost:1234/.well-known/did.json + // #[test] + // fn can_resolve_valid_did_web() { + // let did_uri = "did:web:localhost%3A1234"; + // let resolution_result = ResolutionResult::new(did_uri); + // + // assert_eq!(None, resolution_result.resolution_metadata.error); + // assert_eq!(resolution_result.document.unwrap().id, "did:web:tbd.website"); + // } + #[test] fn can_resolve_did_dht() { let did_uri = "did:dht:swit41ctrddy1s38c5j46yfgbxmwo1emau71zo5hn1tws1g63hiy";