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

Commit

Permalink
feat: update tbDEX test vectors (#102)
Browse files Browse the repository at this point in the history
* update tbdex test vectors

* add `payoutUnitsPerPayinUnit`, `subtotal`, and `total` to `Quote`

* add `details` and `status` enums to `OrderStatus`

* add fallback date formatter to handle decoding dates without fractional seconds

* use updated `QuoteData` and `OrderStatusData` constructors

* update `OrderStatusTests`

* update `QuoteTests`

* add test vectors for `Cancel` and `OrderInstructions`
  • Loading branch information
ethan-tbd authored Aug 28, 2024
1 parent 6f72cd5 commit 7d7e6d5
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 26 deletions.
9 changes: 9 additions & 0 deletions Sources/tbDEX/Common/JSON/tbDEXDateFormatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,12 @@ let tbDEXDateFormatter: ISO8601DateFormatter = {
dateFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
return dateFormatter
}()


/// A date formatter that can be used to decode dates in the ISO8601 format
/// without fractional seconds.
let tbDEXFallbackDateFormatter: ISO8601DateFormatter = {
let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = [.withInternetDateTime]
return dateFormatter
}()
14 changes: 7 additions & 7 deletions Sources/tbDEX/Common/JSON/tbDEXJSONDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ public class tbDEXJSONDecoder: JSONDecoder {
dateDecodingStrategy = .custom { decoder in
let container = try decoder.singleValueContainer()
let dateString = try container.decode(String.self)

if let date = tbDEXDateFormatter.date(from: dateString) {
if let date = tbDEXDateFormatter.date(from: dateString) ?? tbDEXFallbackDateFormatter.date(from: dateString) {
return date
} else {
throw DecodingError.dataCorruptedError(
in: container,
debugDescription: "Invalid date: \(dateString)"
)
}

throw DecodingError.dataCorruptedError(
in: container,
debugDescription: "Invalid date: \(dateString)"
)
}
}
}
12 changes: 7 additions & 5 deletions Sources/tbDEX/Protocol/DevTools.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,17 @@ enum DevTools {

let quoteData = data ?? QuoteData(
expiresAt: expiresAt,
payoutUnitsPerPayinUnit: "1.0",
payin: .init(
currencyCode: "USD",
amount: "1.00"

subtotal: "1.00",
total: "1.00"
),
payout: .init(
currencyCode: "AUD",
amount: "2.00",
fee: "0.50"
subtotal: "2.00",
fee: "0.50",
total: "2.50"
)
)

Expand Down Expand Up @@ -250,7 +252,7 @@ enum DevTools {
protocol: String? = nil
) -> OrderStatus {
let orderStatusData = data ?? OrderStatusData(
orderStatus: "test status"
status: Status.payinInitiated
)

if let `protocol` = `protocol` {
Expand Down
30 changes: 27 additions & 3 deletions Sources/tbDEX/Protocol/Models/Messages/OrderStatus.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ public typealias OrderStatus = Message<OrderStatusData>
public struct OrderStatusData: MessageData {

/// Current status of Order that's being executed
public let orderStatus: String
public let status: Status

/// Additional details about the status
public let details: String?

/// Returns the MessageKind of orderstatus
public func kind() -> MessageKind {
Expand All @@ -17,8 +20,29 @@ public struct OrderStatusData: MessageData {

/// Default Initializer
public init(
orderStatus: String
status: Status,
details: String? = nil
) {
self.orderStatus = orderStatus
self.status = status
self.details = details
}
}

/// Enum representing the various statuses in the OrderStatus Message.
///
/// [Specification Reference](https://github.com/TBD54566975/tbdex/tree/main/specs/protocol#status)
public enum Status: String, Codable {
case payinPending = "PAYIN_PENDING"
case payinInitiated = "PAYIN_INITIATED"
case payinSettled = "PAYIN_SETTLED"
case payinFailed = "PAYIN_FAILED"
case payinExpired = "PAYIN_EXPIRED"
case payoutPending = "PAYOUT_PENDING"
case payoutInitiated = "PAYOUT_INITIATED"
case payoutSettled = "PAYOUT_SETTLED"
case payoutFailed = "PAYOUT_FAILED"
case refundPending = "REFUND_PENDING"
case refundInitiated = "REFUND_INITIATED"
case refundFailed = "REFUND_FAILED"
case refundSettled = "REFUND_SETTLED"
}
26 changes: 19 additions & 7 deletions Sources/tbDEX/Protocol/Models/Messages/Quote.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ public typealias Quote = Message<QuoteData>
/// [Specification Reference](https://github.com/TBD54566975/tbdex/tree/main/specs/protocol#quote)
public struct QuoteData: MessageData {

/// When this quote expires.
/// When this quote expires
public let expiresAt: Date

/// The exchange rate to convert from payin currency to payout currency
public let payoutUnitsPerPayinUnit: String

/// The amount of payin currency that the PFI will receive
public let payin: QuoteDetails
Expand All @@ -24,10 +27,12 @@ public struct QuoteData: MessageData {
/// Default Initializer
public init(
expiresAt: Date,
payoutUnitsPerPayinUnit: String,
payin: QuoteDetails,
payout: QuoteDetails
) {
self.expiresAt = expiresAt
self.payoutUnitsPerPayinUnit = payoutUnitsPerPayinUnit
self.payin = payin
self.payout = payout
}
Expand All @@ -41,20 +46,27 @@ public struct QuoteDetails: Codable, Equatable {
/// ISO 3166 currency code string
public let currencyCode: String

/// The amount of currency expressed in the smallest respective unit
public let amount: String

/// The amount of currency paid for the exchange, excluding fees
public let subtotal: String
/// The amount paid in fees
public let fee: String?

/// The total amount of currency to be paid in or paid out
public let total: String



/// Default Initializer
public init(
currencyCode: String,
amount: String,
fee: String? = nil
subtotal: String,
fee: String? = nil,
total: String
) {
self.currencyCode = currencyCode
self.amount = amount
self.subtotal = subtotal
self.fee = fee
self.total = total
}
}
28 changes: 28 additions & 0 deletions Tests/tbDEXTestVectors/tbDEXTestVectorsProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,20 @@ final class tbDEXTestVectorsProtocol: XCTestCase {

XCTAssertNoDifference(parsedClose, vector.output)
}

func test_parse_cancel() throws {
let vector = try TestVector<String, Cancel>(
fileName: "parse-cancel",
subdirectory: vectorSubdirectory
)

let parsedMessage = try AnyMessage.parse(vector.input)
guard case let .cancel(parsedCancel) = parsedMessage else {
return XCTFail("Parsed message is not a Cancel")
}

XCTAssertNoDifference(parsedCancel, vector.output)
}

func test_parse_order() throws {
let vector = try TestVector<String, Order>(
Expand All @@ -66,6 +80,20 @@ final class tbDEXTestVectorsProtocol: XCTestCase {

XCTAssertNoDifference(parsedOrder, vector.output)
}

func test_parse_orderinstructions() throws {
let vector = try TestVector<String, OrderInstructions>(
fileName: "parse-orderinstructions",
subdirectory: vectorSubdirectory
)

let parsedMessage = try AnyMessage.parse(vector.input)
guard case let .orderInstructions(parsedOrderInstructions) = parsedMessage else {
return XCTFail("Parsed message is not an OrderInstructions")
}

XCTAssertNoDifference(parsedOrderInstructions, vector.output)
}

func test_parse_orderstatus() throws {
let vector = try TestVector<String, OrderStatus>(
Expand Down
2 changes: 1 addition & 1 deletion Tests/tbDEXTestVectors/tbdex-spec
Submodule tbdex-spec updated 43 files
+62 −0 .github/workflows/format.yml
+45 −0 .github/workflows/lint.yml
+19 −0 .github/workflows/trigger-lint.yml
+2 −1 .gitignore
+1 −1 CODEOWNERS
+58 −0 Justfile
+93 −80 README.md
+1 −0 bin/.jq-1.7.1.pkg
+1 −0 bin/jq
+0 −1 discovery/.gitignore
+0 −81 discovery/README.md
+0 −52 discovery/create-and-anchor-did-web.mjs
+0 −57 discovery/create-and-anchor.mjs
+0 −55 discovery/discover.mjs
+8 −0 hooks/pre-commit
+1 −1 hosted/json-schemas/balance.schema.json
+11 −0 hosted/json-schemas/cancel.schema.json
+1 −1 hosted/json-schemas/close.schema.json
+2 −2 hosted/json-schemas/definitions.json
+23 −3 hosted/json-schemas/message.schema.json
+41 −9 hosted/json-schemas/offering.schema.json
+1 −1 hosted/json-schemas/order.schema.json
+34 −0 hosted/json-schemas/orderinstructions.schema.json
+25 −7 hosted/json-schemas/orderstatus.schema.json
+22 −22 hosted/json-schemas/quote.schema.json
+1 −1 hosted/json-schemas/reputation.schema.json
+16 −3 hosted/json-schemas/resource.schema.json
+4 −1 hosted/json-schemas/rfq-private.schema.json
+12 −3 hosted/json-schemas/rfq.schema.json
+1 −1 hosted/test-vectors/protocol/package.json
+6 −2 hosted/test-vectors/protocol/vector.schema.json
+6 −6 hosted/test-vectors/protocol/vectors/parse-balance.json
+20 −0 hosted/test-vectors/protocol/vectors/parse-cancel.json
+8 −8 hosted/test-vectors/protocol/vectors/parse-close.json
+27 −33 hosted/test-vectors/protocol/vectors/parse-offering.json
+8 −8 hosted/test-vectors/protocol/vectors/parse-order.json
+27 −0 hosted/test-vectors/protocol/vectors/parse-orderinstructions.json
+11 −10 hosted/test-vectors/protocol/vectors/parse-orderstatus.json
+19 −23 hosted/test-vectors/protocol/vectors/parse-quote.json
+12 −12 hosted/test-vectors/protocol/vectors/parse-rfq-omit-private-data.json
+14 −14 hosted/test-vectors/protocol/vectors/parse-rfq.json
+110 −122 specs/http-api/README.md
+219 −103 specs/protocol/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ final class OrderStatusTests: XCTestCase {
XCTAssertEqual(orderStatus.metadata.from, pfi.uri)
XCTAssertEqual(orderStatus.metadata.to, did.uri)
XCTAssertEqual(orderStatus.metadata.exchangeID, "exchange_123")
XCTAssertEqual(orderStatus.data.orderStatus, "test status")
XCTAssertEqual(orderStatus.data.status, Status.payinInitiated)
}

func test_verifySuccess() async throws {
Expand Down
6 changes: 4 additions & 2 deletions Tests/tbDEXTests/Protocol/Models/Messages/QuoteTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ final class QuoteTests: XCTestCase {
XCTAssertEqual(quote.metadata.exchangeID, "exchange_123")

XCTAssertEqual(quote.data.payin.currencyCode, "USD")
XCTAssertEqual(quote.data.payin.amount, "1.00")
XCTAssertEqual(quote.data.payin.total, "1.00")
XCTAssertNil(quote.data.payin.fee)

XCTAssertEqual(quote.data.payout.currencyCode, "AUD")
XCTAssertEqual(quote.data.payout.amount, "2.00")
XCTAssertEqual(quote.data.payout.subtotal, "2.00")
XCTAssertEqual(quote.data.payout.fee, "0.50")
XCTAssertEqual(quote.data.payout.total, "2.50")

}

func test_verifySuccess() async throws {
Expand Down

0 comments on commit 7d7e6d5

Please sign in to comment.