All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tbdex.sdk.protocol.models.Resource.kt Maven / Gradle / Ivy

The newest version!
package tbdex.sdk.protocol.models

import com.fasterxml.jackson.annotation.JsonFormat
import com.fasterxml.jackson.core.JsonParseException
import com.fasterxml.jackson.databind.JsonNode
import tbdex.sdk.protocol.SignatureVerifier
import tbdex.sdk.protocol.Validator
import tbdex.sdk.protocol.serialization.Json
import tbdex.sdk.protocol.serialization.Json.jsonMapper
import tbdex.sdk.protocol.serialization.dateTimeFormat
import web5.sdk.dids.did.BearerDid
import web5.sdk.jose.jws.Jws
import java.time.OffsetDateTime

/**
 * An interface that represents the metadata of a tbDEX object.
 */
sealed interface Metadata

/**
 * An enum representing all possible [Resource] kinds.
 */
enum class ResourceKind {
  offering,
  balance
}

/**
 * A data class representing the metadata present on every [Resource].
 *
 * @property kind the data property's type. e.g. offering
 * @property from The author's DID
 * @property id The resource's ID
 * @property protocol Version of the protocol in use (x.x format).
 *                    The protocol version must remain consistent across messages in a given exchange.
 *                    Messages sharing the same exchangeId MUST also have the same protocol version.
 *                    Protocol versions are tracked in https://github.com/TBD54566975/tbdex
 * @property createdAt ISO 8601 timestamp
 * @property updatedAt ISO 8601 timestamp
 */
class ResourceMetadata(
  val kind: ResourceKind,
  val from: String,
  val id: String,
  val protocol: String,
  @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = dateTimeFormat, timezone = "UTC")
  val createdAt: OffsetDateTime,
  @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = dateTimeFormat, timezone = "UTC")
  val updatedAt: OffsetDateTime?
) : Metadata

/**
 * An abstract class representing the structure and common functionality available on all Resources.
 */
sealed class Resource {
  abstract val metadata: ResourceMetadata
  abstract val data: ResourceData
  abstract var signature: String?

  /**
   * Signs the Resource using the specified [BearerDid]
   *
   * @param did The DID (Decentralized Identifier) used for signing.
   * @throws Exception if the signing operation fails.
   */
  fun sign(did: BearerDid) {
    this.signature = Jws.sign(bearerDid = did, payload = this.digest(), detached = true)
  }

  /**
   * Verifies the signature of the Resource.
   *
   * This function verifies the signature using the previously set [signature] property.
   * It compares the signature against a hashed payload consisting of metadata and data.
   *
   * @throws Exception if the verification fails or if the signature is missing.
   */
  fun verify() {
    SignatureVerifier.verify(detachedPayload = digest(), signature = signature, did = metadata.from)
  }

  /**
   * Generates a digest of the message for signing or verification.
   *
   * @return The message digest as a byte array.
   */
  private fun digest(): ByteArray = SignatureVerifier.digestOf(metadata, data)

  /**
   * Uses [Json] to serialize the Resource as a json string.
   *
   * @return The json string
   */
  override fun toString(): String {
    return Json.stringify(this)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy