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@77e51198

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:34)",
//   eval = fmgp.did.method.peer.DidPeerResolver$$$Lambda$24416/0x00000008057f2440@...

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 = "a0eea379-e3ff-4614-87cb-3c0cafc2e694",
//   from = "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0",
//   to = "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9hbGljZS5kaWQuZm1ncC5hcHAvIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ"
// )

ping.toPlaintextMessage.toJsonPretty
// res6: String = """{
//   "id" : "a0eea379-e3ff-4614-87cb-3c0cafc2e694",
//   "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" : "z-UqBv9gd87Ttvl677HxiDEK2JHXrv7aPny2PhjbsmcpsWIRt7Dc98GbJzrVAgwwuh3w60nct0r73gGWXKP7MlN0n5n76nVAB9snOypTDChdBPA-NlD_SB85fFxV8_nK6T2EVzBKSLEECOkynkGL4okHxDbEls09ppPDt1CfGndmQsaSAPETVBfTPs_RCaROU206P_2WYTGugywiApEsaW_X35x17a_PtHk9xgJMthaTe1Whf67OBwIHeaEezyUalodMqF902I9H4Q12xp5yUy5AAQ28CiqiJnFPfIBsqPqSRI78snT1ZtjM1Q0u6cKV0j-Bs5_Kz6e5eJ184EvSL6KOrPMFOC8BUIMiyBdtIlg9brHUPJTUv76t6qojBIJnikZvwYbkNZkvMyI-Wa124gtIHbPE5mwMBy_KdumH5dLQ-Ztmw1_VxRTgABT01tFZYImPlcLedc0jumVwEOOGDhxfOzU7cfCgTa5j0KzHh-e2tVzmJsIa7meTuBbiWr96-5rdhAeW06EOR8J1OV-rD9htI8vmVUk6zoSp2l3URs3iU8XBxzAtpk5Tenew-7b4loxZ-6qSGA5CuZqJonVDZ0kaewjIV1VcJeOMqvSxyrz40j843opdMrmEmCRbdxO2D4jkGXqFu2hO6s-KrAudEI2KZknIW-hnSz9JnNi975Vfk_GptEGPxSCVYgU9nkNoDA2KLsEPJfqmOhez7bNQgPdTySPX6E5O3H8UKWS7ebWNgd8dSiefXjfzY1XDO78t",
//   "protected" : "eyJlcGsiOnsia3R5IjoiT0tQIiwiY3J2IjoiWDI1NTE5IiwieCI6Ik5jT2V2Z3g4MUhxcjhpM2FKQlI0MlMzMjYzSmVMSnlBbGR2V3lPdlVPbFEifSwiYXB2IjoiZXVXaDJHcEc0WUl3OVlXVFAyX1ZLUWhUVHRCN2VhR25CZk85OV9NZjhuZyIsInNraWQiOiJkaWQ6cGVlcjoyLkV6NkxTZ2h3U0U0Mzd3bkRFMXB0M1g2aFZEVVF6U2pzSHppbnBYM1hGdk1qUkFtN3kuVno2TWtoaDFlNUNFWVlxNkpCVWNUWjZDcDJyYW5DV1JydjdZYXgzTGU0TjU5UjZkZC5TZXlKMElqb2laRzBpTENKeklqcDdJblZ5YVNJNkltaDBkSEJ6T2k4dllXeHBZMlV1Wkdsa0xtWnRaM0F1WVhCd0x5SXNJbUVpT2xzaVpHbGtZMjl0YlM5Mk1pSmRmWDAja2V5LTEiLCJhcHUiOiJaR2xrT25CbFpYSTZNaTVGZWpaTVUyZG9kMU5GTkRNM2QyNUVSVEZ3ZEROWU5taFdSRlZSZWxOcWMwaDZhVzV3V0ROWVJuWk5hbEpCYlRkNUxsWjZOazFyYUdneFpUVkRSVmxaY1RaS1FsVmpWRm8yUTNBeWNtRnVRMWRTY25ZM1dXRjRNMHhsTkU0MU9WSTJaR1F1VTJWNVNqQkphbTlwV2tjd2FVeERTbnBKYW5BM1NXNVdlV0ZUU1RaSmJXZ3daRWhDZWs5cE9IWlpWM2h3V1RKVmRWcEhiR3RNYlZwMFdqTkJkVmxZUW5kTWVVbHpTVzFGYVU5c2MybGFSMnhyV1RJNWRHSlRPVEpOYVVwa1psZ3dJMnRsZVMweCIsInR5cCI6ImFwcGxpY2F0aW9uL2RpZGNvbW0tZW5jcnlwdGVkK2pzb24iLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiYWxnIjoiRUNESC0xUFUrQTI1NktXIn0",
//   "recipients" : [
//     {
//       "encrypted_key" : "bh1ma28_M0KknIP4TN3fRffB-e1OUY8Jt2mb2sTDv99L9kJYbIAPb1yQ8VcBC6uEUYpG6CSBPfqFRNuCFRh4v8XHmhO0bi7U",
//       "header" : {
//         "kid" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9hbGljZS5kaWQuZm1ncC5hcHAvIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ#key-1"
//       }
//     }
//   ],
//   "tag" : "bHOlIa0wT8FIp6eIOcNbAeZmJU3-VTyz8q7KgQtzgh8",
//   "iv" : "reDRvk_AZRk94wz7vHzktw"
// }