Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Commit

Permalink
Add protocol field (#198)
Browse files Browse the repository at this point in the history
* update submodule
  • Loading branch information
phoebe-lew authored Mar 13, 2024
1 parent a089bdc commit cbc1530
Show file tree
Hide file tree
Showing 22 changed files with 116 additions and 13 deletions.
2 changes: 2 additions & 0 deletions config/detekt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ complexity:
includePrivateDeclarations: false
MethodOverloading:
active: true
LongParameterList:
active: false

exceptions:
NotImplementedDeclaration:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ suspend fun submitClose(
return
}

if(message.metadata.protocol != exchange.first().metadata.protocol) {
val errorDetail = ErrorDetail(detail = "Protocol mismatch: ${message.metadata.protocol} != ${exchange.first().metadata.protocol}")
call.respond(HttpStatusCode.Conflict, ErrorResponse(listOf(errorDetail)))
return
}

if (!exchange.last().validNext.contains(MessageKind.close)) {
val errorDetail =
ErrorDetail(detail = "cannot submit Order for an exchange where the last message is kind: ${exchange.last().metadata.kind}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ suspend fun submitOrder(
call.respond(HttpStatusCode.BadRequest, errorResponse)
return
}
val exchangeId = message.metadata.exchangeId.toString()
val exchangeId = message.metadata.exchangeId

val exchange: List<Message>
try {
Expand All @@ -49,6 +49,12 @@ suspend fun submitOrder(
return
}

if(message.metadata.protocol != exchange.first().metadata.protocol) {
val errorDetail = ErrorDetail(detail = "Protocol mismatch: ${message.metadata.protocol} != ${exchange.first().metadata.protocol}")
call.respond(HttpStatusCode.Conflict, ErrorResponse(listOf(errorDetail)))
return
}

if (!exchange.last().validNext.contains(MessageKind.order)) {
val errorDetail =
ErrorDetail(detail = "cannot submit Order for an exchange where the last message is kind: ${exchange.last().metadata.kind}")
Expand Down
8 changes: 5 additions & 3 deletions httpserver/src/test/kotlin/TestData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,18 @@ object TestData {
)
}

fun createOrder(exchangeId: String) = Order.create(
fun createOrder(exchangeId: String, protocol: String = "1.0") = Order.create(
to = pfiDid.uri,
from = aliceDid.uri,
exchangeId = exchangeId
exchangeId = exchangeId,
protocol = protocol
)

fun createClose(exchangeId: String) = Close.create(
fun createClose(exchangeId: String, protocol: String = "1.0") = Close.create(
to = pfiDid.uri,
from = aliceDid.uri,
exchangeId = exchangeId,
protocol = protocol,
closeData = CloseData(reason = "test close reason")
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import ServerTest
import TestData.aliceDid
import TestData.createClose
import TestData.createRfq
import assertk.assertThat
import assertk.assertions.contains
import de.fxlae.typeid.TypeId
import io.ktor.client.request.post
import io.ktor.client.request.setBody
Expand Down Expand Up @@ -33,6 +35,26 @@ class SubmitCloseTest : ServerTest() {
assertContains(errorResponse.errors.first().detail, "Parsing of TBDex message failed")
}

@Test
fun `returns Conflict if close has a different protocol version than the rest of the exchange`() = runBlocking {
val rfq = createRfq()
rfq.sign(aliceDid)
exchangesApi.addMessage(rfq)

val close = createClose(exchangeId = rfq.metadata.exchangeId, protocol = "2.0")
close.sign(aliceDid)

val response = client.post("/exchanges/123/close") {
contentType(ContentType.Application.Json)
setBody(close)
}

val errorResponse = Json.jsonMapper.readValue(response.bodyAsText(), ErrorResponse::class.java)

assertEquals(HttpStatusCode.Conflict, response.status)
assertThat(errorResponse.errors.first().detail).contains("Protocol mismatch")
}

@Test
fun `returns Conflict if close is not allowed based on exchange state`() = runBlocking {
val close = createClose(TypeId.generate(MessageKind.rfq.name).toString())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import TestData.createOrder
import TestData.createQuote
import TestData.createRfq
import TestData.pfiDid
import assertk.assertThat
import assertk.assertions.contains
import de.fxlae.typeid.TypeId
import io.ktor.client.request.post
import io.ktor.client.request.setBody
Expand Down Expand Up @@ -73,6 +75,26 @@ class SubmitOrderTest : ServerTest() {
)
}

@Test
fun `returns Conflict if order has a different protocol version than the rest of the exchange`() = runBlocking {
val rfq = createRfq()
rfq.sign(aliceDid)
exchangesApi.addMessage(rfq)

val order = createOrder(exchangeId = rfq.metadata.exchangeId, protocol = "2.0")
order.sign(aliceDid)

val response = client.post("/exchanges/123/order") {
contentType(ContentType.Application.Json)
setBody(order)
}

val errorResponse = Json.jsonMapper.readValue(response.bodyAsText(), ErrorResponse::class.java)

assertEquals(HttpStatusCode.Conflict, response.status)
assertThat(errorResponse.errors.first().detail).contains("Protocol mismatch")
}

@Test
fun `returns Forbidden if quote has expired`() = runBlocking {
val quote = createQuote(expiresAt = OffsetDateTime.now().minusDays(1))
Expand Down
4 changes: 4 additions & 0 deletions protocol/src/main/kotlin/tbdex/sdk/protocol/models/Close.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ class Close private constructor(
* @param from DID of the sender.
* @param exchangeId ID of the exchange.
* @param closeData Specific parameters relevant to a Close.
* @param protocol version of the tbdex protocol.
* @param externalId external reference for the Close. Optional.
* @return Close instance.
*/
fun create(
to: String,
from: String,
exchangeId: String,
closeData: CloseData,
protocol: String = "1.0",
externalId: String? = null
): Close {
validateExchangeId(exchangeId)
Expand All @@ -50,6 +53,7 @@ class Close private constructor(
id = TypeId.generate(MessageKind.close.name).toString(),
exchangeId = exchangeId,
createdAt = OffsetDateTime.now(),
protocol = protocol,
externalId = externalId
)
Validator.validateData(closeData, "close")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ enum class MessageKind {
/**
* A data class representing the metadata present on every [Message].
*/
@Suppress("LongParameterList")
class MessageMetadata(
val kind: MessageKind,
val to: String,
Expand All @@ -34,6 +33,7 @@ class MessageMetadata(
val exchangeId: String,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = dateTimeFormat, timezone = "UTC")
val createdAt: OffsetDateTime,
val protocol: String,
val externalId: String? = null
) : Metadata

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,16 @@ class Offering private constructor(
*
* @param from DID of the PFI.
* @param data Specific parameters relevant to an Offering.
* @param protocol version of the tbdex protocol.
* @return Offering instance.
*/
fun create(from: String, data: OfferingData): Offering {
fun create(from: String, data: OfferingData, protocol: String = "1.0"): Offering {
val now = OffsetDateTime.now()
val metadata = ResourceMetadata(
kind = ResourceKind.offering,
from = from,
id = TypeId.generate(ResourceKind.offering.name).toString(),
protocol = protocol,
createdAt = now,
updatedAt = now
)
Expand Down
11 changes: 10 additions & 1 deletion protocol/src/main/kotlin/tbdex/sdk/protocol/models/Order.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,17 @@ class Order private constructor(
* @param to DID that the message is being sent to.
* @param from DID of the sender.
* @param exchangeId ID of the exchange.
* @param protocol version of the tbdex protocol.
* @param externalId external reference for the order. Optional.
* @return Order instance.
*/
fun create(to: String, from: String, exchangeId: String, externalId: String? = null): Order {
fun create(
to: String,
from: String,
exchangeId: String,
protocol: String = "1.0",
externalId: String? = null
): Order {
validateExchangeId(exchangeId)

val metadata = MessageMetadata(
Expand All @@ -43,6 +51,7 @@ class Order private constructor(
id = TypeId.generate(MessageKind.order.name).toString(),
exchangeId = exchangeId,
createdAt = OffsetDateTime.now(),
protocol = protocol,
externalId = externalId
)
return Order(metadata, OrderData())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ class OrderStatus private constructor(
* @param from DID of the sender.
* @param exchangeId ID of the exchange.
* @param orderStatusData Specific parameters relevant to an OrderStatus.
* @param protocol version of the tbdex protocol.
* @param externalId external reference for the order status. Optional.
* @return OrderStatus instance.
*/
fun create(
to: String,
from: String,
exchangeId: String,
orderStatusData: OrderStatusData,
protocol: String = "1.0",
externalId: String? = null
): OrderStatus {
validateExchangeId(exchangeId)
Expand All @@ -50,6 +53,7 @@ class OrderStatus private constructor(
id = TypeId.generate(MessageKind.orderstatus.name).toString(),
exchangeId = exchangeId,
createdAt = OffsetDateTime.now(),
protocol = protocol,
externalId = externalId
)
Validator.validateData(orderStatusData, "orderstatus")
Expand Down
4 changes: 4 additions & 0 deletions protocol/src/main/kotlin/tbdex/sdk/protocol/models/Quote.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ class Quote private constructor(
* @param from DID of the sender.
* @param exchangeId ID of the exchange.
* @param quoteData Specific parameters relevant to a Quote.
* @param protocol version of the tbdex protocol.
* @param externalId external reference for the Quote. Optional.
* @return Quote instance.
*/
fun create(
to: String,
from: String,
exchangeId: String,
quoteData: QuoteData,
protocol: String = "1.0",
externalId: String? = null
): Quote {
validateExchangeId(exchangeId)
Expand All @@ -49,6 +52,7 @@ class Quote private constructor(
id = TypeId.generate(MessageKind.quote.name).toString(),
exchangeId = exchangeId,
createdAt = OffsetDateTime.now(),
protocol = protocol,
externalId = externalId
)
Validator.validateData(quoteData, "quote")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ 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")
Expand Down
4 changes: 4 additions & 0 deletions protocol/src/main/kotlin/tbdex/sdk/protocol/models/Rfq.kt
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,16 @@ class Rfq private constructor(
* @param to DID that the message is being sent to.
* @param from DID of the sender.
* @param rfqData Specific parameters relevant to a Rfq.
* @param protocol version of the tbdex protocol.
* @param externalId external reference for the Rfq. Optional.
* @param private Sensitive information that will be ephemeral.
* @return Rfq instance.
*/
fun create(
to: String,
from: String,
rfqData: RfqData,
protocol: String = "1.0",
externalId: String? = null,
private: Map<String, Any>? = null
): Rfq {
Expand All @@ -95,6 +98,7 @@ class Rfq private constructor(
id = id,
exchangeId = id,
createdAt = OffsetDateTime.now(),
protocol = protocol,
externalId = externalId
)
Validator.validateData(rfqData, "rfq")
Expand Down
6 changes: 4 additions & 2 deletions protocol/src/test/kotlin/tbdex/sdk/protocol/ValidatorTest.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package tbdex.sdk.protocol

import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.support.appendName
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.module.kotlin.convertValue
Expand Down Expand Up @@ -77,7 +78,8 @@ class ValidatorTest {
"kind": "rfq",
"id": "rfq_01hkx53kgafbmrg2xp87n5htfb",
"exchangeId": "rfq_01hkx53kgafbmrg2xp87n5htfb",
"createdAt": "2024-01-11T20:58:34.378Z"
"createdAt": "2024-01-11T20:58:34.378Z",
"protocol": "1.0"
},
"data": {
"offeringId": "abcd123",
Expand Down Expand Up @@ -111,6 +113,6 @@ class ValidatorTest {
}

assertEquals(1, exception.errors.size)
assertContains(exception.errors, "$.payinAmount: is missing but it is required")
assertThat(exception.errors).contains("$.payinAmount: is missing but it is required")
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package tbdex.sdk.protocol.models

import assertk.assertAll
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.isNotNull
Expand All @@ -19,10 +20,12 @@ class CloseTest {
to = "pfi",
from = "alice",
exchangeId = TypeId.generate(MessageKind.rfq.name).toString(),
protocol = "2.0",
closeData = CloseData("my reason")
)

assertk.assertAll {
assertAll {
assertThat(close.metadata.protocol).isEqualTo("2.0")
assertThat(close.metadata.id).startsWith("close")
assertThat(close.data.reason).isEqualTo("my reason")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class OfferingTest {
assertAll {
assertThat(offering.data.description).isEqualTo("my fake offering")
assertThat(offering.metadata.id).startsWith("offering")
assertThat(offering.metadata.protocol).isEqualTo("1.0")
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package tbdex.sdk.protocol.models

import assertk.assertAll
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.startsWith
Expand All @@ -20,8 +21,9 @@ class OrderStatusTest {
orderStatusData = OrderStatusData("my status")
)

assertk.assertAll {
assertAll {
assertThat(orderStatus.metadata.id).startsWith("orderstatus")
assertThat(orderStatus.metadata.protocol).isEqualTo("1.0")
assertThat(orderStatus.data.orderStatus).isEqualTo("my status")
}
}
Expand Down
Loading

0 comments on commit cbc1530

Please sign in to comment.