Basic Example

Parse a DID Document

val documentString = """{
  "@context": "https://www.w3.org/ns/did/v1",
  "id": "did:example:123456789abcdefghi",
  "keyAgreement": [
    "did:example:123456789abcdefghi#keys-1",
    {
      "id": "did:example:123#zC9ByQ8aJs8vrNXyDhPHHNNMSHPcaSgNpjjsBYpMMjsTdS",
      "type": "X25519KeyAgreementKey2019",
      "controller": "did:example:123",
      "publicKeyMultibase": "z9hFgmPVfmBZwRvFEyniQDBkz9LmV7gDEqytWyGZLmDXE"
    }
  ]
}"""
documentString.fromJson[DIDDocument]
// res0: Either[String, DIDDocument] = Right(
//   value = DIDDocumentClass(
//     id = "did:example:123456789abcdefghi",
//     alsoKnownAs = None,
//     verificationMethod = None,
//     authentication = None,
//     assertionMethod = None,
//     keyAgreement = Some(
//       value = Set(
//         VerificationMethodReferenced(
//           value = "did:example:123456789abcdefghi#keys-1"
//         ),
//         VerificationMethodEmbeddedMultibase(
//           id = "did:example:123#zC9ByQ8aJs8vrNXyDhPHHNNMSHPcaSgNpjjsBYpMMjsTdS",
//           controller = "did:example:123",
//           type = "X25519KeyAgreementKey2019",
//           expires = None,
//           revoked = None,
//           publicKeyMultibase = "z9hFgmPVfmBZwRvFEyniQDBkz9LmV7gDEqytWyGZLmDXE",
//           secretKeyMultibase = None
//         )
//       )
//     ),
//     capabilityInvocation = None,
//     capabilityDelegation = None,
//     service = None
//   )
// )

NOTE the return type is of type Either[String, DIDDocument] <br> Since the documentString is a valid json and which is also a valid DID Document. The value is Right of that class that implemente trait DIDDocument. <br> If the documentString was a invalid json or did not represented a DID Document. The return value would have been Left, containing the information why failed to parse.

"not a json".fromJson[DIDDocument]
// res1: Either[String, DIDDocument] = Left(value = "(expected '{' got 'n')")
"""{"some_json": "but_not_a_valid_document"}""".fromJson[DIDDocument]
// res2: Either[String, DIDDocument] = Left(value = ".id(missing)")

Another Important Point is that there is no failed here everywhere on this library! We work with values. (Any error/exception will be considered a bug and reports are appreciated)

This this allowed us to this allowed us to build programs build (ZIO) programs. That can are executed at any point in time.

Make DID Peer identities

import fmgp.crypto.*
import fmgp.did.method.peer.*

val alice = DIDPeer2.makeAgent(
  Seq(
    OKPPrivateKey( // keyAgreement
      kty = KTY.OKP,
      crv = Curve.X25519,
      d = "Z6D8LduZgZ6LnrOHPrMTS6uU2u5Btsrk1SGs4fn8M7c",
      x = "Sr4SkIskjN_VdKTn0zkjYbhGTWArdUNE4j_DmUpnQGw",
    ),
    OKPPrivateKey( // keyAuthentication
      kty = KTY.OKP,
      crv = Curve.Ed25519,
      d = "INXCnxFEl0atLIIQYruHzGd5sUivMRyQOzu87qVerug",
      x = "MBjnXZxkMcoQVVL21hahWAw43RuAG-i64ipbeKKqwoA",
    )
  ),
  Seq(DIDPeerServiceEncoded.fromEndpoint("https://alice.did.fmgp.app/"))
)
// alice: AgentDIDPeer = fmgp.did.method.peer.DIDPeer2$$anon$4@19fe49d3

alice.id.asDIDSubject
// res3: DIDSubject = "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0"

alice.id.document.toJsonPretty
// res4: String = """{
//   "id" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0",
//   "authentication" : [
//     {
//       "id" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0#key-2",
//       "controller" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0",
//       "type" : "JsonWebKey2020",
//       "publicKeyJwk" : {
//         "kty" : "OKP",
//         "crv" : "Ed25519",
//         "x" : "MBjnXZxkMcoQVVL21hahWAw43RuAG-i64ipbeKKqwoA"
//       }
//     }
//   ],
//   "keyAgreement" : [
//     {
//       "id" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0#key-1",
//       "controller" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0",
//       "type" : "JsonWebKey2020",
//       "publicKeyJwk" : {
//         "kty" : "OKP",
//         "crv" : "X25519",
//         "x" : "Sr4SkIskjN_VdKTn0zkjYbhGTWArdUNE4j_DmUpnQGw"
//       }
//     }
//   ],
//   "service" : [
//     {
//       "id" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0#service",
//       "type" : "DIDCommMessaging",
//       "serviceEndpoint" : {
//         "uri" : "https://alice.did.fmgp.app/",
//         "accept" : [
//           "didcomm/v2"
//         ]
//       }
//     }
// ...

Resolve did:peer identities

import fmgp.did.method.peer.*

val program1 = DidPeerResolver.didDocument(DIDPeer(alice.id.asDIDSubject))
// program1: ZIO[Any, Nothing, DIDDocument] = Sync(
//   trace = "fmgp.did.method.peer.DidPeerResolver.genesisDocument(DidPeerResolver.scala:33)",
//   eval = fmgp.did.method.peer.DidPeerResolver$$$Lambda$24278/0x0000000805fa9c40@...

Unsafe.unsafe { implicit unsafe => // Run side effect
  Runtime.default.unsafe
    .run(program1)
    .getOrThrowFiberFailure()
}
// res5: DIDDocument = DIDDocumentClass(
//   id = "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0",
// ...

Trust Ping example

import fmgp.did.comm.protocol.trustping2.* // For the protocol

val ping = TrustPingWithRequestedResponse(
  from = alice.id,
  to = TO("did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9hbGljZS5kaWQuZm1ncC5hcHAvIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ")
)
// ping: TrustPingWithRequestedResponse = TrustPingWithRequestedResponse(
//   id = "406b2752-6736-4146-a9a3-797c3295d82b",
//   from = "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0",
//   to = "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9hbGljZS5kaWQuZm1ncC5hcHAvIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ"
// )

ping.toPlaintextMessage.toJsonPretty
// res6: String = """{
//   "id" : "406b2752-6736-4146-a9a3-797c3295d82b",
//   "type" : "https://didcomm.org/trust-ping/2.0/ping",
//   "to" : [
//     "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9hbGljZS5kaWQuZm1ncC5hcHAvIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ"
//   ],
//   "from" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0",
//   "body" : {
//     "response_requested" : true
//   }
// }"""

Encrypt

import Operations.*

val program2 = for {
  msg <- authEncrypt(ping.toPlaintextMessage).provideSomeLayer(ZLayer.succeed(alice))
  _ <- Console.printLine(msg.toJsonPretty)
} yield ()
Unsafe.unsafe { implicit unsafe => // Run side effect
  Runtime.default.unsafe
    .run(program2.provide(Operations.layerOperations ++ DidPeerResolver.layer))
    .getOrThrowFiberFailure()
}
// {
//   "ciphertext" : "3qTpp9SnlDGKRB-zzNOX6Qw6PBUx3ajZJihgyMQirEUOB9yp4E-oaUsJUQoR1Dc7ihBeEIGmyMXpTCp98-da1t5PWK7tiMn5eR-nvqJ7YIim4_PY0fhj3u-c25Ex41egTdDHNmwyTG21bBwl4EgJggvymcQEK9qx3d9JSgD83Kd6Br07aYeiwFONO9ZzEc1a-3wjiUK1isz5QLNn1FRW3BXda-jiwnyo1U4mpsnwxxXKjvmNTWE906NyUtbqS-A1HTy-10jFtQW_UiT89Ipms_ld0FAp6q9RPDrWvLw7Wf6xRayEiEqe95C3As9fXGsRZDyjUrfj6F1dzZBH739WN4WUFv5i0GRIv-Bezd21nB1MVvM2VLWfFttpDsjDK_sSFJcy3757DqLsAAu3qyBv9LedYpMhoOpm4Q53G3cHjsjYwJoNSa-NtpUm--hhTWGDdH0SSgpxS495_wUDqfT_rbduKaSgLiZWQBqQxzXnDcu6VjscVlbc2789tMmNEnXZLVgFKsaEz3g9oBJcawNwxTSQ9bljtA-pxcQFBaUkx6GknKlR9pAi2IiL9W7FxYS3G4vUpjduuWa33IxMF83uw8gdIZXf3JoAEDTUJiMh9ImeSd0uU-t4XTs5gROBIu-rpmus4XbVIKoreGvCgC_jnctk21S9_rh2VyHQzfovCAhxREptRUqQ8gDVg8Si2hOy1jGkyIODDwfPjv8B-rs4ZYKDkN3skdSi7Czz5fO0f-3cHinAMiBFxEBthvjkB9St",
//   "protected" : "eyJlcGsiOnsia3R5IjoiT0tQIiwiY3J2IjoiWDI1NTE5IiwieCI6ImFYVUc0YUNEZkwyUHFoWkQyODhNaXhMX245a3BYTnRLaUIzaEZ3QjNGamsifSwiYXB2IjoiZXVXaDJHcEc0WUl3OVlXVFAyX1ZLUWhUVHRCN2VhR25CZk85OV9NZjhuZyIsInNraWQiOiJkaWQ6cGVlcjoyLkV6NkxTZ2h3U0U0Mzd3bkRFMXB0M1g2aFZEVVF6U2pzSHppbnBYM1hGdk1qUkFtN3kuVno2TWtoaDFlNUNFWVlxNkpCVWNUWjZDcDJyYW5DV1JydjdZYXgzTGU0TjU5UjZkZC5TZXlKMElqb2laRzBpTENKeklqcDdJblZ5YVNJNkltaDBkSEJ6T2k4dllXeHBZMlV1Wkdsa0xtWnRaM0F1WVhCd0x5SXNJbUVpT2xzaVpHbGtZMjl0YlM5Mk1pSmRmWDAja2V5LTEiLCJhcHUiOiJaR2xrT25CbFpYSTZNaTVGZWpaTVUyZG9kMU5GTkRNM2QyNUVSVEZ3ZEROWU5taFdSRlZSZWxOcWMwaDZhVzV3V0ROWVJuWk5hbEpCYlRkNUxsWjZOazFyYUdneFpUVkRSVmxaY1RaS1FsVmpWRm8yUTNBeWNtRnVRMWRTY25ZM1dXRjRNMHhsTkU0MU9WSTJaR1F1VTJWNVNqQkphbTlwV2tjd2FVeERTbnBKYW5BM1NXNVdlV0ZUU1RaSmJXZ3daRWhDZWs5cE9IWlpWM2h3V1RKVmRWcEhiR3RNYlZwMFdqTkJkVmxZUW5kTWVVbHpTVzFGYVU5c2MybGFSMnhyV1RJNWRHSlRPVEpOYVVwa1psZ3dJMnRsZVMweCIsInR5cCI6ImFwcGxpY2F0aW9uL2RpZGNvbW0tZW5jcnlwdGVkK2pzb24iLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiYWxnIjoiRUNESC0xUFUrQTI1NktXIn0",
//   "recipients" : [
//     {
//       "encrypted_key" : "XBe0HCCIjMUub9Ae29j324MEkLimUxbkW_6k_vDFu8PNMNZ-p1Om5bJN7AUKDLKxrGSeLREyNl0yGakZIMSuShlIm5Iu-eoI",
//       "header" : {
//         "kid" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9hbGljZS5kaWQuZm1ncC5hcHAvIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ#key-1"
//       }
//     }
//   ],
//   "tag" : "P0l-yOpKlYi35m3f-iSvQ-uxRSlS8aDFywlN19T8XqM",
//   "iv" : "rEFUoBTx3hD1T3YKe5AxcQ"
// }