diff --git a/Sources/tbDEX/Protocol/DevTools.swift b/Sources/tbDEX/Protocol/DevTools.swift new file mode 100644 index 0000000..81495d3 --- /dev/null +++ b/Sources/tbDEX/Protocol/DevTools.swift @@ -0,0 +1,252 @@ +import Foundation +import TypeID + +/// DevTools provides a few utility helper methods for constructing Resources and Messages. +/// Should be used for internal testing purposes only. +enum DevTools { + /// Creates a mock `Offering`. Optionally override the `OfferingData` + /// - Parameters: + /// - from: The DID that the `Offering` should be from. Included in the metadata + /// - data: Optional. The data to override the default data with. + /// - protocol: Optional. The protocol version to use if different from the default. Included in the metadata. + /// - Returns: The `Offering` + static func createOffering( + from: String, + data: OfferingData? = nil, + protocol: String? = nil + ) -> Offering { + let offeringData = data ?? OfferingData( + description: "test offering", + payoutUnitsPerPayinUnit: "1", + payinCurrency: .init(currencyCode: "AUD"), + payoutCurrency: .init(currencyCode: "BTC"), + payinMethods: [], + payoutMethods: [], + requiredClaims: nil + ) + + if let `protocol` = `protocol` { + return Offering(from: from, data: offeringData, protocol: `protocol`) + } else { + return Offering(from: from, data: offeringData) + } + } + + /// Creates a mock `Balance`. Optionally override the `BalanceData` + /// - Parameters: + /// - from: The DID the `Balance` should be from. Included in the metadata. + /// - data: Optional. The data to override the default data with. + /// - protocol: Optional. The protocol version to use if different from the default. Included in the metadata. + /// - Returns: The `Balance` + static func createBalance( + from: String, + data: BalanceData? = nil, + protocol: String? = nil + ) -> Balance { + let balanceData = data ?? BalanceData( + currencyCode: "USD", + available: "100.00" + ) + + if let `protocol` = `protocol` { + return Balance(from: from, data: balanceData, protocol: `protocol`) + } else { + return Balance(from: from, data: balanceData) + } + } + + /// Creates a mock `RFQ`. Optionally override the `RFQData` + /// - Parameters: + /// - from: The DID the `RFQ` should be from. Included in the metadata. + /// - to: The DID the `RFQ` should be sent to. Included in the metadata. + /// - externalID: Optional. The externalID to associate with the `RFQ`. Included in the metadata. + /// - data: Optional. The data to override the default data with. + /// - protocol: Optional. The protocol version to use if different from the default. Included in the metadata. + /// - Returns: The `RFQ` + static func createRFQ( + from: String, + to: String, + externalID: String? = nil, + data: RFQData? = nil, + protocol: String? = nil + ) -> RFQ { + let rfqData = data ?? RFQData( + offeringId: TypeID(rawValue:"offering_01hmz7ehw6e5k9bavj0ywypfpy")!, + payinAmount: "1.00", + payinMethod: .init(kind: "DEBIT_CARD"), + payoutMethod: .init(kind: "BITCOIN_ADDRESS"), + claims: [] + ) + + if let `protocol` = `protocol` { + return RFQ( + to: to, + from: from, + data: rfqData, + externalID: externalID, + protocol: `protocol` + ) + } else { + return RFQ(to: to, from: from, data: rfqData, externalID: externalID) + } + } + + /// Creates a mock `Quote`. Optionally override the `QuoteData` + /// - Parameters: + /// - from: The DID the `Quote` should be from. Included in the metadata. + /// - to: The DID the `Quote` should be sent to. Included in the metadata. + /// - exchangeID: OptionalThe exchangeID of the associated exchange. Included in the metadata. + /// - data: Optional. The data to override the default data with. + /// - protocol: Optional. The protocol version to use if different from the default. Included in the metadata. + /// - Returns: The `Quote` + static func createQuote( + from: String, + to: String, + exchangeID: String = "exchange_123", + data: QuoteData? = nil, + protocol: String? = nil + ) -> Quote { + let now = Date() + let expiresAt = now.addingTimeInterval(60) + + let quoteData = data ?? QuoteData( + expiresAt: expiresAt, + payin: .init( + currencyCode: "USD", + amount: "1.00", + paymentInstruction: .init( + link: "https://example.com", + instruction: "test instruction" + ) + ), + payout: .init( + currencyCode: "AUD", + amount: "2.00", + fee: "0.50" + ) + ) + + if let `protocol` = `protocol` { + return Quote( + from: from, + to: to, + exchangeID: exchangeID, + data: quoteData, + protocol: `protocol` + ) + } else { + return Quote( + from: from, + to: to, + exchangeID: exchangeID, + data: quoteData + ) + } + } + + /// Creates a mock `Order`. Optionally override the `OrderData` + /// - Parameters: + /// - from: The DID the `Order` should be from. Included in the metadata. + /// - to: The DID the `Order` should be sent to. Included in the metadata. + /// - exchangeID: The exchangeID of the associated exchange. Included in the metadata. + /// - protocol: Optional. The protocol version to use if different from the default. Included in the metadata. + /// - Returns: The `Order` + static func createOrder( + from: String, + to: String, + exchangeID: String = "exchange_123", + protocol: String? = nil + ) -> Order { + if let `protocol` = `protocol` { + return Order( + from: from, + to: to, + exchangeID: exchangeID, + data: .init(), + protocol: `protocol` + ) + } else { + return Order( + from: from, + to: to, + exchangeID: exchangeID, + data: .init() + ) + } + } + + /// Creates a mock `OrderStatus`. Optionally override the `OrderStatusData` + /// - Parameters: + /// - from: The DID the `OrderStatus` should be from. Included in the metadata. + /// - to: The DID the `OrderStatus` should be sent to. Included in the metadata. + /// - exchangeID: The exchangeID of the associated exchange. Included in the metadata. + /// - protocol: Optional. The protocol version to use if different from the default. Included in the metadata. + /// - Returns: The `OrderStatus` + static func createOrderStatus( + from: String, + to: String, + exchangeID: String = "exchange_123", + data: OrderStatusData? = nil, + protocol: String? = nil + ) -> OrderStatus { + let orderStatusData = data ?? OrderStatusData( + orderStatus: "test status" + ) + + if let `protocol` = `protocol` { + return OrderStatus( + from: from, + to: to, + exchangeID: exchangeID, + data: orderStatusData, + protocol: `protocol` + ) + } else { + return OrderStatus( + from: from, + to: to, + exchangeID: exchangeID, + data: orderStatusData + ) + } + } + + /// Creates a mock `Close`. Optionally override the `CloseData` + /// - Parameters: + /// - from: The DID the `Close` should be from. Included in the metadata. + /// - to: The DID the `Close` should be sent to. Included in the metadata. + /// - exchangeID: The exchangeID of the associated exchange. Included in the metadata. + /// - protocol: Optional. The protocol version to use if different from the default. Included in the metadata. + /// - Returns: The `Close` + static func createClose( + from: String, + to: String, + exchangeID: String = "exchange_123", + data: OrderStatusData? = nil, + protocol: String? = nil + ) -> Close { + let closeData = CloseData( + reason: "test reason" + ) + + if let `protocol` = `protocol` { + return Close( + from: from, + to: to, + exchangeID: exchangeID, + data: closeData, + protocol: `protocol` + ) + } else { + return Close( + from: from, + to: to, + exchangeID: exchangeID, + data: closeData + ) + } + + } +} + + diff --git a/Sources/tbDEX/Protocol/Models/Messages/Close.swift b/Sources/tbDEX/Protocol/Models/Messages/Close.swift index eb59eca..e9c7eaf 100644 --- a/Sources/tbDEX/Protocol/Models/Messages/Close.swift +++ b/Sources/tbDEX/Protocol/Models/Messages/Close.swift @@ -20,8 +20,10 @@ public struct CloseData: MessageData { /// Default Initializer public init( - reason: String? = nil + reason: String? = nil, + success: Bool? = nil ) { self.reason = reason + self.success = success } } diff --git a/Sources/tbDEX/Protocol/Models/Resource.swift b/Sources/tbDEX/Protocol/Models/Resource.swift index 3abaec8..687d3bf 100644 --- a/Sources/tbDEX/Protocol/Models/Resource.swift +++ b/Sources/tbDEX/Protocol/Models/Resource.swift @@ -15,11 +15,45 @@ public struct Resource: Codable, Equatable { public let data: D /// Signature that verifies the authenticity and integrity of the Resource - public let signature: String? + public private(set) var signature: String? + + /// Default Initializer. `protocol` defaults to "1.0" if nil + public init( + from: String, + data: D, + `protocol`: String = "1.0" + ) { + let now = Date() + self.metadata = ResourceMetadata( + id: TypeID(prefix: data.kind().rawValue)!, + kind: data.kind(), + from: from, + createdAt: now, + updatedAt: now, + protocol: `protocol` + ) + self.data = data + self.signature = nil + } private func digest() throws -> Data { try CryptoUtils.digest(data: data, metadata: metadata) } + + /// Signs the message as a JWS with detached content with an optional key alias + /// - Parameters: + /// - did: The Bearer DID with which to sign the resource + /// - keyAlias: An optional key alias to use instead of the default provided by the Bearer DID + public mutating func sign(did: BearerDID, keyAlias: String? = nil) throws { + self.signature = try JWS.sign( + did: did, + payload: try digest(), + options: .init( + detached: true, + verificationMethodID: keyAlias + ) + ) + } /// Validates the resource structure and verifies the cryptographic signature public func verify() async throws -> Bool { diff --git a/Sources/tbDEX/Protocol/Models/Resources/Offering.swift b/Sources/tbDEX/Protocol/Models/Resources/Offering.swift index e200e02..c20e57f 100644 --- a/Sources/tbDEX/Protocol/Models/Resources/Offering.swift +++ b/Sources/tbDEX/Protocol/Models/Resources/Offering.swift @@ -52,6 +52,17 @@ public struct CurrencyDetails: Codable, Equatable { /// Maximum amount of currency that the offer is valid for public let maxAmount: String? + + /// Default initializer + init( + currencyCode: String, + minAmount: String? = nil, + maxAmount: String? = nil + ) { + self.currencyCode = currencyCode + self.minAmount = minAmount + self.maxAmount = maxAmount + } } @@ -66,5 +77,14 @@ public struct PaymentMethod: Codable, Equatable { // TODO: amika - Update to JSONSchema, requires third-party or custom implementation /// A JSON Schema containing the fields that need to be collected in order to use this payment method public let requiredPaymentDetails: AnyCodable? + + /// Default initializer + init( + kind: String, + requiredPaymentDetails: AnyCodable? = nil + ) { + self.kind = kind + self.requiredPaymentDetails = requiredPaymentDetails + } } diff --git a/Tests/tbDEXTests/Protocol/Models/Messages/CloseTests.swift b/Tests/tbDEXTests/Protocol/Models/Messages/CloseTests.swift index 1acaabe..2c597f7 100644 --- a/Tests/tbDEXTests/Protocol/Models/Messages/CloseTests.swift +++ b/Tests/tbDEXTests/Protocol/Models/Messages/CloseTests.swift @@ -9,7 +9,7 @@ final class CloseTests: XCTestCase { let pfi = try! DIDJWK.create(keyManager: InMemoryKeyManager()) func test_init() { - let close = createClose(from: did.uri, to: pfi.uri) + let close = DevTools.createClose(from: did.uri, to: pfi.uri) XCTAssertEqual(close.metadata.id.prefix, "close") XCTAssertEqual(close.metadata.from, did.uri) @@ -21,52 +21,34 @@ final class CloseTests: XCTestCase { } func test_overrideProtocolVersion() { - let close = Close( + let close = DevTools.createClose( from: did.uri, to: pfi.uri, - exchangeID: "exchange_123", - data: .init( - reason: "test reason" - ), protocol: "2.0" ) - XCTAssertEqual(close.metadata.id.prefix, "close") - XCTAssertEqual(close.metadata.from, did.uri) - XCTAssertEqual(close.metadata.to, pfi.uri) - XCTAssertEqual(close.metadata.exchangeID, "exchange_123") XCTAssertEqual(close.metadata.protocol, "2.0") } - func test_signAndVerify() async throws { - let did = try DIDJWK.create(keyManager: InMemoryKeyManager()) - let pfi = try DIDJWK.create(keyManager: InMemoryKeyManager()) - var close = createClose(from: did.uri, to: pfi.uri) + func test_signSuccess() async throws { + var close = DevTools.createClose(from: did.uri, to: pfi.uri) XCTAssertNil(close.signature) try close.sign(did: did) XCTAssertNotNil(close.signature) + } + + func test_verifySuccess() async throws { + var close = DevTools.createClose(from: did.uri, to: pfi.uri) + try close.sign(did: did) + let isValid = try await close.verify() XCTAssertTrue(isValid) } func test_verifyWithoutSigningFailure() async throws { - let close = createClose(from: did.uri, to: pfi.uri) + let close = DevTools.createClose(from: did.uri, to: pfi.uri) await XCTAssertThrowsErrorAsync(try await close.verify()) } - - private func createClose( - from: String, - to: String - ) -> Close { - Close( - from: from, - to: to, - exchangeID: "exchange_123", - data: .init( - reason: "test reason" - ) - ) - } } diff --git a/Tests/tbDEXTests/Protocol/Models/Messages/OrderStatusTests.swift b/Tests/tbDEXTests/Protocol/Models/Messages/OrderStatusTests.swift index 095f1b0..3f8b4c0 100644 --- a/Tests/tbDEXTests/Protocol/Models/Messages/OrderStatusTests.swift +++ b/Tests/tbDEXTests/Protocol/Models/Messages/OrderStatusTests.swift @@ -9,62 +9,26 @@ final class OrderStatusTests: XCTestCase { let pfi = try! DIDJWK.create(keyManager: InMemoryKeyManager()) func test_init() { - let orderStatus = createOrderStatus(from: did.uri, to: pfi.uri) + let orderStatus = DevTools.createOrderStatus(from: pfi.uri, to: did.uri) XCTAssertEqual(orderStatus.metadata.id.prefix, "orderstatus") - XCTAssertEqual(orderStatus.metadata.from, did.uri) - XCTAssertEqual(orderStatus.metadata.to, pfi.uri) + XCTAssertEqual(orderStatus.metadata.from, pfi.uri) + XCTAssertEqual(orderStatus.metadata.to, did.uri) XCTAssertEqual(orderStatus.metadata.exchangeID, "exchange_123") XCTAssertEqual(orderStatus.data.orderStatus, "test status") } - - func test_overrideProtocolVersion() { - let orderstatus = OrderStatus( - from: did.uri, - to: pfi.uri, - exchangeID: "exchange_123", - data: .init( - orderStatus: "test status" - ), - protocol: "2.0" - ) - - XCTAssertEqual(orderstatus.metadata.id.prefix, "orderstatus") - XCTAssertEqual(orderstatus.metadata.from, did.uri) - XCTAssertEqual(orderstatus.metadata.to, pfi.uri) - XCTAssertEqual(orderstatus.metadata.exchangeID, "exchange_123") - XCTAssertEqual(orderstatus.metadata.protocol, "2.0") - } - func test_signAndVerify() async throws { - let did = try DIDJWK.create(keyManager: InMemoryKeyManager()) - let pfi = try DIDJWK.create(keyManager: InMemoryKeyManager()) - var orderStatus = createOrderStatus(from: did.uri, to: pfi.uri) - - XCTAssertNil(orderStatus.signature) - try orderStatus.sign(did: did) - XCTAssertNotNil(orderStatus.signature) + func test_verifySuccess() async throws { + var orderStatus = DevTools.createOrderStatus(from: pfi.uri, to: did.uri) + try orderStatus.sign(did: pfi) + let isValid = try await orderStatus.verify() XCTAssertTrue(isValid) } func test_verifyWithoutSigningFailure() async throws { - let orderStatus = createOrderStatus(from: did.uri, to: pfi.uri) + let orderStatus = DevTools.createOrderStatus(from: pfi.uri, to: did.uri) await XCTAssertThrowsErrorAsync(try await orderStatus.verify()) } - - private func createOrderStatus( - from: String, - to: String - ) -> OrderStatus { - OrderStatus( - from: from, - to: to, - exchangeID: "exchange_123", - data: .init( - orderStatus: "test status" - ) - ) - } } diff --git a/Tests/tbDEXTests/Protocol/Models/Messages/OrderTests.swift b/Tests/tbDEXTests/Protocol/Models/Messages/OrderTests.swift index 9e4fa8f..a7284b7 100644 --- a/Tests/tbDEXTests/Protocol/Models/Messages/OrderTests.swift +++ b/Tests/tbDEXTests/Protocol/Models/Messages/OrderTests.swift @@ -9,7 +9,7 @@ final class OrderTests: XCTestCase { let pfi = try! DIDJWK.create(keyManager: InMemoryKeyManager()) func test_init() { - let order = createOrder(from: did.uri, to: pfi.uri) + let order = DevTools.createOrder(from: did.uri, to: pfi.uri) XCTAssertEqual(order.metadata.id.prefix, "order") XCTAssertEqual(order.metadata.from, did.uri) @@ -18,11 +18,9 @@ final class OrderTests: XCTestCase { } func test_overrideProtocolVersion() { - let order = Order( + let order = DevTools.createOrder( from: did.uri, to: pfi.uri, - exchangeID: "exchange_123", - data: .init(), protocol: "2.0" ) @@ -33,33 +31,26 @@ final class OrderTests: XCTestCase { XCTAssertEqual(order.metadata.protocol, "2.0") } - func test_signAndVerify() async throws { - let did = try DIDJWK.create(keyManager: InMemoryKeyManager()) - let pfi = try DIDJWK.create(keyManager: InMemoryKeyManager()) - var order = createOrder(from: did.uri, to: pfi.uri) + func test_signSuccess() async throws { + var order = DevTools.createOrder(from: did.uri, to: pfi.uri) XCTAssertNil(order.signature) try order.sign(did: did) XCTAssertNotNil(order.signature) + } + + func test_verifySuccess() async throws { + var order = DevTools.createOrder(from: did.uri, to: pfi.uri) + try order.sign(did: did) + let isValid = try await order.verify() XCTAssertTrue(isValid) } func test_verifyWithoutSigningFailure() async throws { - let order = createOrder(from: did.uri, to: pfi.uri) + let order = DevTools.createOrder(from: did.uri, to: pfi.uri) await XCTAssertThrowsErrorAsync(try await order.verify()) } - private func createOrder( - from: String, - to: String - ) -> Order { - Order( - from: from, - to: to, - exchangeID: "exchange_123", - data: .init() - ) - } } diff --git a/Tests/tbDEXTests/Protocol/Models/Messages/QuoteTests.swift b/Tests/tbDEXTests/Protocol/Models/Messages/QuoteTests.swift index b8e6f37..5ffc074 100644 --- a/Tests/tbDEXTests/Protocol/Models/Messages/QuoteTests.swift +++ b/Tests/tbDEXTests/Protocol/Models/Messages/QuoteTests.swift @@ -9,11 +9,11 @@ final class QuoteTests: XCTestCase { let pfi = try! DIDJWK.create(keyManager: InMemoryKeyManager()) func test_init() { - let quote = createQuote(from: did.uri, to: pfi.uri) + let quote = DevTools.createQuote(from: pfi.uri, to: did.uri) XCTAssertEqual(quote.metadata.id.prefix, "quote") - XCTAssertEqual(quote.metadata.from, did.uri) - XCTAssertEqual(quote.metadata.to, pfi.uri) + XCTAssertEqual(quote.metadata.from, pfi.uri) + XCTAssertEqual(quote.metadata.to, did.uri) XCTAssertEqual(quote.metadata.exchangeID, "exchange_123") XCTAssertEqual(quote.data.payin.currencyCode, "USD") @@ -27,81 +27,18 @@ final class QuoteTests: XCTestCase { XCTAssertEqual(quote.data.payout.fee, "0.50") XCTAssertNil(quote.data.payout.paymentInstruction) } - - func test_overrideProtocolVersion() { - let quote = Quote( - from: did.uri, - to: pfi.uri, - exchangeID: "exchange_123", - data: .init( - expiresAt: Date().addingTimeInterval(60), - payin: .init( - currencyCode: "USD", - amount: "1.00", - paymentInstruction: .init( - link: "https://example.com", - instruction: "test instruction" - ) - ), - payout: .init( - currencyCode: "AUD", - amount: "2.00", - fee: "0.50" - ) - ), - protocol: "2.0" - ) - XCTAssertEqual(quote.metadata.id.prefix, "quote") - XCTAssertEqual(quote.metadata.from, did.uri) - XCTAssertEqual(quote.metadata.to, pfi.uri) - XCTAssertEqual(quote.metadata.exchangeID, "exchange_123") - XCTAssertEqual(quote.metadata.protocol, "2.0") - } - - func test_signAndVerify() async throws { - var quote = createQuote(from: did.uri, to: pfi.uri) - - XCTAssertNil(quote.signature) - try quote.sign(did: did) - XCTAssertNotNil(quote.signature) + func test_verifySuccess() async throws { + var quote = DevTools.createQuote(from: pfi.uri, to: did.uri) + try quote.sign(did: pfi) + let isValid = try await quote.verify() XCTAssertTrue(isValid) } func test_verifyWithoutSigningFailure() async throws { - let quote = createQuote(from: did.uri, to: pfi.uri) + let quote = DevTools.createQuote(from: pfi.uri, to: did.uri) await XCTAssertThrowsErrorAsync(try await quote.verify()) } - - private func createQuote( - from: String, - to: String - ) -> Quote { - let now = Date() - let expiresAt = now.addingTimeInterval(60) - - return Quote( - from: from, - to: to, - exchangeID: "exchange_123", - data: .init( - expiresAt: expiresAt, - payin: .init( - currencyCode: "USD", - amount: "1.00", - paymentInstruction: .init( - link: "https://example.com", - instruction: "test instruction" - ) - ), - payout: .init( - currencyCode: "AUD", - amount: "2.00", - fee: "0.50" - ) - ) - ) - } } diff --git a/Tests/tbDEXTests/Protocol/Models/Messages/RFQTests.swift b/Tests/tbDEXTests/Protocol/Models/Messages/RFQTests.swift index 25579a9..e76ae49 100644 --- a/Tests/tbDEXTests/Protocol/Models/Messages/RFQTests.swift +++ b/Tests/tbDEXTests/Protocol/Models/Messages/RFQTests.swift @@ -10,7 +10,7 @@ final class RFQTests: XCTestCase { let pfi = try! DIDJWK.create(keyManager: InMemoryKeyManager()) func test_init() { - let rfq = createRFQ(from: did.uri, to: pfi.uri) + let rfq = DevTools.createRFQ(from: did.uri, to: pfi.uri) XCTAssertEqual(rfq.metadata.id.prefix, "rfq") XCTAssertEqual(rfq.metadata.from, did.uri) @@ -24,64 +24,34 @@ final class RFQTests: XCTestCase { } func test_overrideProtocolVersion() { - let rfq = RFQ( - to: pfi.uri, + let rfq = DevTools.createRFQ( from: did.uri, - data: .init( - offeringId: TypeID(rawValue:"offering_01hmz7ehw6e5k9bavj0ywypfpy")!, - payinAmount: "1.00", - payinMethod: .init( - kind: "DEBIT_CARD" - ), - payoutMethod: .init( - kind: "BITCOIN_ADDRESS" - ), - claims: [] - ), + to: pfi.uri, protocol: "2.0" ) - XCTAssertEqual(rfq.metadata.id.prefix, "rfq") - XCTAssertEqual(rfq.metadata.from, did.uri) - XCTAssertEqual(rfq.metadata.to, pfi.uri) - XCTAssertEqual(rfq.metadata.exchangeID, rfq.metadata.id.rawValue) XCTAssertEqual(rfq.metadata.protocol, "2.0") } - - func test_signAndVerify() async throws { - var rfq = createRFQ(from: did.uri, to: pfi.uri) + + func test_signSuccess() async throws { + var rfq = DevTools.createRFQ(from: did.uri, to: pfi.uri) XCTAssertNil(rfq.signature) try rfq.sign(did: did) XCTAssertNotNil(rfq.signature) + } + + func test_verifySuccess() async throws { + var rfq = DevTools.createRFQ(from: did.uri, to: pfi.uri) + try rfq.sign(did: did) + let isValid = try await rfq.verify() XCTAssertTrue(isValid) } func test_verifyWithoutSigningFailure() async throws { - let rfq = createRFQ(from: did.uri, to: pfi.uri) + let rfq = DevTools.createRFQ(from: did.uri, to: pfi.uri) await XCTAssertThrowsErrorAsync(try await rfq.verify()) } - - private func createRFQ( - from: String, - to: String - ) -> RFQ { - RFQ( - to: to, - from: from, - data: .init( - offeringId: TypeID(rawValue:"offering_01hmz7ehw6e5k9bavj0ywypfpy")!, - payinAmount: "1.00", - payinMethod: .init( - kind: "DEBIT_CARD" - ), - payoutMethod: .init( - kind: "BITCOIN_ADDRESS" - ), - claims: [] - ) - ) - } } diff --git a/Tests/tbDEXTests/Protocol/Models/Resources/BalanceTests.swift b/Tests/tbDEXTests/Protocol/Models/Resources/BalanceTests.swift index 14f1aef..6dca23e 100644 --- a/Tests/tbDEXTests/Protocol/Models/Resources/BalanceTests.swift +++ b/Tests/tbDEXTests/Protocol/Models/Resources/BalanceTests.swift @@ -5,44 +5,29 @@ import XCTest final class BalanceTests: XCTestCase { - func _test_parseBalanceFromStringified() throws { - if let balance = try parsedBalance(balance: balanceStringJSON) { - XCTAssertEqual(balance.metadata.kind, ResourceKind.balance) - } else { - XCTFail("Balance is not a parsed balance") - } - } - - func _test_parseBalanceFromPrettified() throws { - if let balance = try parsedBalance(balance: balancePrettyJSON) { - XCTAssertEqual(balance.metadata.kind, ResourceKind.balance) - } else { - XCTFail("Balance is not a parsed balance") - } - } + let pfi = try! DIDJWK.create(keyManager: InMemoryKeyManager()) + + func test_init() throws { + let balance = DevTools.createBalance(from: "pfi") - func _test_verifyBalanceIsValid() async throws { - if let balance = try parsedBalance(balance: balancePrettyJSON) { - XCTAssertNotNil(balance.signature) - XCTAssertNotNil(balance.data) - XCTAssertNotNil(balance.metadata) - } else { - XCTFail("Balance is not a parsed balance") - } + XCTAssertEqual(balance.metadata.id.prefix, "balance") + XCTAssertEqual(balance.metadata.from, "pfi") + XCTAssertEqual(balance.data.currencyCode, "USD") + XCTAssertEqual(balance.data.available, "100.00") } - private func parsedBalance(balance: String) throws -> Balance? { - let parsedResource = try AnyResource.parse(balance) - guard case let .balance(parsedBalance) = parsedResource else { - return nil - } - return parsedBalance + func test_verifySuccess() async throws { + var balance = DevTools.createBalance(from: pfi.uri) + try balance.sign(did: pfi) + + let isValid = try await balance.verify() + XCTAssertTrue(isValid) } - let balancePrettyJSON = """ - """ - - let balanceStringJSON = - "" + func test_verifyWithoutSigningFailure() async throws { + let balance = DevTools.createBalance(from: pfi.uri) + + await XCTAssertThrowsErrorAsync(try await balance.verify()) + } } diff --git a/Tests/tbDEXTests/Protocol/Models/Resources/OfferingTests.swift b/Tests/tbDEXTests/Protocol/Models/Resources/OfferingTests.swift index d990d58..953b7ea 100644 --- a/Tests/tbDEXTests/Protocol/Models/Resources/OfferingTests.swift +++ b/Tests/tbDEXTests/Protocol/Models/Resources/OfferingTests.swift @@ -5,34 +5,32 @@ import XCTest final class OfferingTests: XCTestCase { - func test_initOffering() throws { - if let offering = try parsedOffering() { - XCTAssertEqual(offering.metadata.kind, ResourceKind.offering) - } else { - XCTFail("Offering is not a parsed offering") - } + let pfi = try! DIDJWK.create(keyManager: InMemoryKeyManager()) + + func test_init() throws { + let offering = DevTools.createOffering(from: "pfi") + XCTAssertEqual(offering.metadata.id.prefix, "offering") + XCTAssertEqual(offering.metadata.from, "pfi") + XCTAssertEqual(offering.data.description, "test offering") + XCTAssertEqual(offering.data.payoutUnitsPerPayinUnit, "1") + XCTAssertEqual(offering.data.payinCurrency.currencyCode, "AUD") + XCTAssertEqual(offering.data.payoutCurrency.currencyCode, "BTC") } + + func test_verifySuccess() async throws { + var offering = DevTools.createOffering(from: pfi.uri) + try offering.sign(did: pfi) - func test_verifyOfferingIsValid() async throws { - if let offering = try parsedOffering() { - XCTAssertNotNil(offering.signature) - XCTAssertNotNil(offering.data) - XCTAssertNotNil(offering.metadata) - let isValid = try await offering.verify() - XCTAssertTrue(isValid) - } else { - XCTFail("Offering is not a parsed offering") - } + let isValid = try await offering.verify() + XCTAssertTrue(isValid) } - private func parsedOffering() throws -> Offering? { - let offeringJson = "{\"metadata\":{\"from\":\"did:dht:77em1f968c1gzwrrb15cgkzjxg8rft67ebxj6gjkocnz5p8sdniy\",\"protocol\":\"1.0\",\"kind\":\"offering\",\"id\":\"offering_01hrqn6ph3f00asxqvx46capbw\",\"createdAt\":\"2024-03-11T21:02:55.523Z\"},\"data\":{\"description\":\"Selling BTC for USD\",\"payinCurrency\":{\"currencyCode\":\"USD\",\"minAmount\":\"0.0\",\"maxAmount\":\"999999.99\"},\"payoutCurrency\":{\"currencyCode\":\"BTC\",\"maxAmount\":\"999526.11\"},\"payoutUnitsPerPayinUnit\":\"0.00003826\",\"payinMethods\":[{\"kind\":\"DEBIT_CARD\",\"requiredPaymentDetails\":{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"type\":\"object\",\"properties\":{\"cardNumber\":{\"type\":\"string\",\"description\":\"The 16-digit debit card number\",\"minLength\":16,\"maxLength\":16},\"expiryDate\":{\"type\":\"string\",\"description\":\"The expiry date of the card in MM/YY format\",\"pattern\":\"^(0[1-9]|1[0-2])\\\\/([0-9]{2})$\"},\"cardHolderName\":{\"type\":\"string\",\"description\":\"Name of the cardholder as it appears on the card\"},\"cvv\":{\"type\":\"string\",\"description\":\"The 3-digit CVV code\",\"minLength\":3,\"maxLength\":3}},\"required\":[\"cardNumber\",\"expiryDate\",\"cardHolderName\",\"cvv\"],\"additionalProperties\":false}}],\"payoutMethods\":[{\"kind\":\"BTC_ADDRESS\",\"requiredPaymentDetails\":{\"$schema\":\"http://json-schema.org/draft-07/schema\",\"type\":\"object\",\"properties\":{\"btcAddress\":{\"type\":\"string\",\"description\":\"your Bitcoin wallet address\"}},\"required\":[\"btcAddress\"],\"additionalProperties\":false}}],\"requiredClaims\":{\"id\":\"7ce4004c-3c38-4853-968b-e411bafcd945\",\"input_descriptors\":[{\"id\":\"bbdb9b7c-5754-4f46-b63b-590bada959e0\",\"constraints\":{\"fields\":[{\"path\":[\"$.type\"],\"filter\":{\"type\":\"string\",\"const\":\"YoloCredential\"}}]}}]}},\"signature\":\"eyJhbGciOiJFZERTQSIsImtpZCI6ImRpZDpkaHQ6NzdlbTFmOTY4YzFnendycmIxNWNna3pqeGc4cmZ0NjdlYnhqNmdqa29jbno1cDhzZG5peSMwIn0..puQwdTvi4KTfKedA6CXdHHldztoQ8udUrQrGmw1wvWfYW3ilMB8myoD3ATw7NGlt1NuizJ80i4ufZArgGrTiAA\"}" - let parsedResource = try AnyResource.parse(offeringJson) - guard case let .offering(parsedOffering) = parsedResource else { - return nil - } - return parsedOffering + func test_verifyWithoutSigningFailure() async throws { + let did = try DIDJWK.create(keyManager: InMemoryKeyManager()) + let offering = DevTools.createOffering(from: pfi.uri) + + await XCTAssertThrowsErrorAsync(try await offering.verify()) } }