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@48492bd2

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$23874/0x0000000805a39c40@...

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 = "5a81f28d-48e6-4122-a3c7-8bee41c43ed1",
//   from = "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjp7InVyaSI6Imh0dHBzOi8vYWxpY2UuZGlkLmZtZ3AuYXBwLyIsImEiOlsiZGlkY29tbS92MiJdfX0",
//   to = "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9hbGljZS5kaWQuZm1ncC5hcHAvIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ"
// )

ping.toPlaintextMessage.toJsonPretty
// res6: String = """{
//   "id" : "5a81f28d-48e6-4122-a3c7-8bee41c43ed1",
//   "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" : "HTVgQB-HIGum8gAuXQbJL3luJQk87NS2YybRyBzxncbVFVgurdrouZwXneCO9HNjLx58WRGnd_r9pdzXINXRrpidPcFzb2AipzeHBjuF-F4lQDUyu074AuivBLB4tjhRjaFTrszjGLwH3YQ183QLBM-2RKi2-u9pm-V7oNC5cmfl66Tub6M38QqYCTNx_IHt7m9p2_0KNfLkPO4HH6fGqb45-gKVD6o_doMeE_9RO2Gn290vE3FGuLi6TI2PsZYgdnotuiHDd4lSclgcRlb8WgvJ_mkJNioyMhbUnxha9o29E-Yywt0Es_fw4hkENq9ooADbZlh09tf0ywgxdnUx9eQWTeX2IwfZKYYBPcG96m8mRe4DIvG6Ko43yIPWf3vGlAA_wPx_isVskMhmk2JvWt1yqSdEoIHbJqHNORLjNGFInbv6-3vYmEHKr37C_MWOT9xjr7WbolYV9G8SJfH-0piKn6opfddXUzCSMCYiIO2zo3xco_M7W1EzOXSez_jhyh1OQHXGy749HoZZeszpb6foIvx_ByYwNzBm8eg9pqAZ7FNAXOqpHljtr2u42wogAjAcwp94lGCr9w5VPsYxahVUrngJWw91te8D4hFTjq30w6h1S_QI_ubiyyUJ1GBH0nZme5DRBkvQ6b9LdzQoH0wW5CkVHGXZJDkpcl52wi19I_lfXFDRGNS0_F0am62iW7GYCM_4X1wXXkN2od6jB9GVHdy8fUdtTVenOd7akfdlXGpjhNloIcEh90MTvK5N",
//   "protected" : "eyJlcGsiOnsia3R5IjoiT0tQIiwiY3J2IjoiWDI1NTE5IiwieCI6IldkMWM1blVfY2lUeE5YVThHVWd1VWljSWIwV0haRzJOUTJMaWpodnVYQ28ifSwiYXB2IjoiZXVXaDJHcEc0WUl3OVlXVFAyX1ZLUWhUVHRCN2VhR25CZk85OV9NZjhuZyIsInNraWQiOiJkaWQ6cGVlcjoyLkV6NkxTZ2h3U0U0Mzd3bkRFMXB0M1g2aFZEVVF6U2pzSHppbnBYM1hGdk1qUkFtN3kuVno2TWtoaDFlNUNFWVlxNkpCVWNUWjZDcDJyYW5DV1JydjdZYXgzTGU0TjU5UjZkZC5TZXlKMElqb2laRzBpTENKeklqcDdJblZ5YVNJNkltaDBkSEJ6T2k4dllXeHBZMlV1Wkdsa0xtWnRaM0F1WVhCd0x5SXNJbUVpT2xzaVpHbGtZMjl0YlM5Mk1pSmRmWDAja2V5LTEiLCJhcHUiOiJaR2xrT25CbFpYSTZNaTVGZWpaTVUyZG9kMU5GTkRNM2QyNUVSVEZ3ZEROWU5taFdSRlZSZWxOcWMwaDZhVzV3V0ROWVJuWk5hbEpCYlRkNUxsWjZOazFyYUdneFpUVkRSVmxaY1RaS1FsVmpWRm8yUTNBeWNtRnVRMWRTY25ZM1dXRjRNMHhsTkU0MU9WSTJaR1F1VTJWNVNqQkphbTlwV2tjd2FVeERTbnBKYW5BM1NXNVdlV0ZUU1RaSmJXZ3daRWhDZWs5cE9IWlpWM2h3V1RKVmRWcEhiR3RNYlZwMFdqTkJkVmxZUW5kTWVVbHpTVzFGYVU5c2MybGFSMnhyV1RJNWRHSlRPVEpOYVVwa1psZ3dJMnRsZVMweCIsInR5cCI6ImFwcGxpY2F0aW9uL2RpZGNvbW0tZW5jcnlwdGVkK2pzb24iLCJlbmMiOiJBMjU2Q0JDLUhTNTEyIiwiYWxnIjoiRUNESC0xUFUrQTI1NktXIn0",
//   "recipients" : [
//     {
//       "encrypted_key" : "RVW9-Gj19BJZ7TQuBkgI1fe0RTARINF6s1Quk7cuXeKmh6r0GD4OVq46KrIhGIqK23y3vKNMH7TD5eSkVpuGXWXBcNpLKx6L",
//       "header" : {
//         "kid" : "did:peer:2.Ez6LSghwSE437wnDE1pt3X6hVDUQzSjsHzinpX3XFvMjRAm7y.Vz6Mkhh1e5CEYYq6JBUcTZ6Cp2ranCWRrv7Yax3Le4N59R6dd.SeyJ0IjoiZG0iLCJzIjoiaHR0cHM6Ly9hbGljZS5kaWQuZm1ncC5hcHAvIiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ#key-1"
//       }
//     }
//   ],
//   "tag" : "Rtffr9M5SB0AUI4muNbwhICCkaSiFCmL3M-4zaLGfc8",
//   "iv" : "f2p8xF6mhxuUExloaBXR6A"
// }