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

Commit

Permalink
allow init in resources, add devtools and update all tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kirahsapong committed Mar 29, 2024
1 parent 6476eb1 commit e05310f
Show file tree
Hide file tree
Showing 11 changed files with 401 additions and 266 deletions.
252 changes: 252 additions & 0 deletions Sources/tbDEX/Protocol/DevTools.swift
Original file line number Diff line number Diff line change
@@ -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
)
}

}
}


4 changes: 3 additions & 1 deletion Sources/tbDEX/Protocol/Models/Messages/Close.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
36 changes: 35 additions & 1 deletion Sources/tbDEX/Protocol/Models/Resource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,45 @@ public struct Resource<D: ResourceData>: 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 {
Expand Down
20 changes: 20 additions & 0 deletions Sources/tbDEX/Protocol/Models/Resources/Offering.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

}

Expand All @@ -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
}

}
Loading

0 comments on commit e05310f

Please sign in to comment.