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@d5407e5

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$24917/0x00000008062e8c40@...

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 = "2460254d-1f71-4de7-9fc7-8839c4d75ca8",
//   from = "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0",
//   to = "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9hbGljZS5kaWQuZm1ncC5hcHAvIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ"
// )

ping.toPlaintextMessage.toJsonPretty
// res6: String = """{
//   "id" : "2460254d-1f71-4de7-9fc7-8839c4d75ca8",
//   "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" : "5qkJa3EkOCB29R8tmc4PGboYCSc32eth1Dts9pJ1rOu__ciSQcj1uh4dC4xoNyT3IPXgycQCFWBf2hq7C6XVeNxp6l77vl7QcuaNIxAK1tInM2JuHm1Hnq70MgoPF-KHsXYE7kR_meQLktaQtu2JiUfBCG1UUd2bjciyYZKf7R0XA2ZkyBAjXZ1SlLS7FwInxf6QN6W41ZC4BzBncAqVW4CgQ9sGwCaYzgkIiD1YO1a6pmOeu4oLm4opm3S6AUDXWoK9Fo0hcIgvba58WwdGRNyra2Me-mSc6b1jCz91fdWhmVcWbUfiD7fD5trI3LAswSh04YGgzi2sSlgMtfhnBwR61G5_QkT-PY7W_oaMlXcWUNaU8GFxqN5koCiQ1SqvceCPmfGjvVpGC8WGe3b41hvtkjjdkr43YXNQYHxvx3PE8n_D9DA46UpySL0DGjpz6u0jpJ3z0UervK4uNuMi8ChLu6fdQUw2K10xCIOlSyIWimpqT7FfcPFZtEV4Nmp-Bu-hbViV6UquEo8Lxbm1Kh3Vgxw_8DjXOf6NppU0uwqZY2vQqmBUl6EpdLKYeazfVuoF0SyHAU_ICp9CiVJCmaPBaBLfqW4jsJ6pIFYe027hFkmNtvmWe_Rf7388zD_p1SqDjT93zdUWqSmIn4_p4g9GCgzE-FdClgPaS60inEbMAg22NA2AXtLM2m305Q02gWYE2-2lfsYMkE5VHunGYJRQqy7-OcGIUvog1lIbHziYqOdMVkQXKFXIKu7aUXwO",
//   "protected" : "eyJlcGsiOnsia3R5IjoiT0tQIiwiY3J2IjoiWDI1NTE5IiwieCI6IngxQXJ1a3Vob2VqSjdpNTQwcmVVRmhrNGtpMGh1QUloeGNFZ2Y2TmxaaTQifSwiYXB2IjoiZXVXaDJHcEc0WUl3OVlXVFAyX1ZLUWhUVHRCN2VhR25CZk85OV9NZjhuZyIsInNraWQiOiJkaWQ6cGVlcjoyLkV6NkxTZ2h3U0U0Mzd3bkRFMXB0M1g2aFZEVVF6U2pzSHppbnBYM1hGdk1qUkFtN3kuVno2TWtoaDFlNUNFWVlxNkpCVWNUWjZDcDJyYW5DV1JydjdZYXgzTGU0TjU5UjZkZC5TZXlKMElqb2laRzBpTENKeklqcDdJblZ5YVNJNkltaDBkSEJ6T2k4dllXeHBZMlV1Wkdsa0xtWnRaM0F1WVhCd0x5SXNJbUVpT2xzaVpHbGtZMjl0YlM5Mk1pSmRmWDAja2V5LTEiLCJhcHUiOiJaR2xrT25CbFpYSTZNaTVGZWpaTVUyZG9kMU5GTkRNM2QyNUVSVEZ3ZEROWU5taFdSRlZSZWxOcWMwaDZhVzV3V0ROWVJuWk5hbEpCYlRkNUxsWjZOazFyYUdneFpUVkRSVmxaY1RaS1FsVmpWRm8yUTNBeWNtRnVRMWRTY25ZM1dXRjRNMHhsTkU0MU9WSTJaR1F1VTJWNVNqQkphbTlwV2tjd2FVeERTbnBKYW5BM1NXNVdlV0ZUU1RaSmJXZ3daRWhDZWs5cE9IWlpWM2h3V1RKVmRWcEhiR3RNYlZwMFdqTkJkVmxZUW5kTWVVbHpTVzFGYVU5c2MybGFSMnhyV1RJNWRHSlRPVEpOYVVwa1psZ3dJMnRsZVMweCIsInR5cCI6ImFwcGxpY2F0aW9uL2RpZGNvbW0tZW5jcnlwdGVkK2pzb24iLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiYWxnIjoiRUNESC0xUFUrQTI1NktXIn0",
//   "recipients" : [
//     {
//       "encrypted_key" : "BS9JiBql64CUpiy2alBOUj_oAA5LduHFw6R0upzf7jA-7c_H25Fi6Ao4jyhZfwLcMaSZjHqm_lQ6zIRrF9tk39TJxHFv5qRZ",
//       "header" : {
//         "kid" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9hbGljZS5kaWQuZm1ncC5hcHAvIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ#key-1"
//       }
//     }
//   ],
//   "tag" : "Ah_typDXkukXPN6R3A4x0Q-f66mpTyu7fHV092H5a1Y",
//   "iv" : "oRBPR8iDfGdfj251Oe2sgg"
// }