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

Commit

Permalink
Implement fetching offerings from a PFI DID (#19)
Browse files Browse the repository at this point in the history
  • Loading branch information
amika-sq authored Jan 12, 2024
1 parent f142008 commit 5b71ec1
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 8 deletions.
17 changes: 17 additions & 0 deletions Sources/tbDEX/HttpClient/GetOfferingsFilter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Foundation

public struct GetOfferingFilter: Codable {
let id: String?
let payinCurrency: String?
let payoutCurrency: String?

public init(
id: String? = nil,
payinCurrency: String? = nil,
payoutCurrency: String? = nil
) {
self.id = id
self.payinCurrency = payinCurrency
self.payoutCurrency = payoutCurrency
}
}
72 changes: 72 additions & 0 deletions Sources/tbDEX/HttpClient/HttpClient.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import Foundation

public enum HttpClient {

public struct HttpClientError: Error {
let reason: String
}

static let session = URLSession(configuration: .default)

public struct GetOfferingsResponse: Codable {
public let data: [Offering]
}

/// Get `Offering`s from a PFI.
public static func getOfferings(
pfiDidUri: String,
filter: GetOfferingFilter? = nil
) async -> Result<GetOfferingsResponse, HttpClientError> {
guard let pfiServiceEndpoint = await getPFIServiceEndpoint(pfiDidUri: pfiDidUri) else {
return .failure(.init(reason: "DID does not have service of type PFI"))
}

guard var components = URLComponents(string: "\(pfiServiceEndpoint)/offerings") else {
return .failure(.init(reason: "Could not create URLComponents from PFI service endpoint"))
}

components.queryItems = filter?.queryItems()

guard let url = components.url else {
return .failure(.init(reason: "Could not create URL from URLComponents"))
}

do {
let response = try await URLSession.shared.data(from: url)

// Set up the JSONDecoder with a custom date decoding strategy
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in
let container = try decoder.singleValueContainer()
let dateString = try container.decode(String.self)

// Create a custom ISO8601DateFormatter
let dateFormatter = ISO8601DateFormatter()
dateFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]

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

let offerings = try decoder.decode(GetOfferingsResponse.self, from: response.0)
return .success(offerings)
} catch {
return .failure(.init(reason: "Error while fetching offerings: \(error)"))
}
}

private static func getPFIServiceEndpoint(pfiDidUri: String) async -> String? {
let resolutionResult = await DidResolver.resolve(didUri: pfiDidUri)
if let service = resolutionResult.didDocument?.service?.first(where: { $0.type == "PFI" }) {
return service.serviceEndpoint
} else {
return nil
}
}
}
17 changes: 17 additions & 0 deletions Sources/tbDEX/Utilities/Encodable+QueryItems.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Foundation

extension Encodable {

/// Returns an array of `URLQueryItem` representing the `Encodable` object.
func queryItems() -> [URLQueryItem] {
let encoder = JSONEncoder()
guard let data = try? encoder.encode(self) else {
return []
}
guard let dictionary = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
return []
}
return dictionary.map { URLQueryItem(name: $0.key, value: "\($0.value)") }
}

}
8 changes: 0 additions & 8 deletions Tests/tbDEXTests/Dids/DidJwkTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,4 @@ final class DidJwkTests: XCTestCase {
XCTAssertNil(resolutionResult.didResolutionMetadata.error)
}

func test_resolveIon() async throws {
let didUri =
"did:ion:EiC8RWXbMYyFsqQ5hxP3k2GVvqPaeP8EAN6i9wQblzj__Q:eyJkZWx0YSI6eyJwYXRjaGVzIjpbeyJhY3Rpb24iOiJyZXBsYWNlIiwiZG9jdW1lbnQiOnsicHVibGljS2V5cyI6W3siaWQiOiJkd24tc2lnIiwicHVibGljS2V5SndrIjp7ImNydiI6IkVkMjU1MTkiLCJrdHkiOiJPS1AiLCJ4IjoiSUM3NnB5QnAtNXFYbFpHS2I1M1V3M1NEWXJfY3AzaUpyLTFzSlBqb2hsSSJ9LCJwdXJwb3NlcyI6WyJhdXRoZW50aWNhdGlvbiIsImFzc2VydGlvbk1ldGhvZCJdLCJ0eXBlIjoiSnNvbldlYktleTIwMjAifV0sInNlcnZpY2VzIjpbeyJpZCI6InBmaSIsInNlcnZpY2VFbmRwb2ludCI6Imh0dHA6Ly9sb2NhbGhvc3Q6OTAwMCIsInR5cGUiOiJQRkkifV19fV0sInVwZGF0ZUNvbW1pdG1lbnQiOiJFaUN6SENrVEJtNDIwbEo3alluZElCa1VzamktanJoMnhYdEt4NHoxWm1QVEpBIn0sInN1ZmZpeERhdGEiOnsiZGVsdGFIYXNoIjoiRWlBZFJYbHhJNlpadzhUbE9NR2xEcUtaLVkwdlF4WV8xanJWVVUtcWgtUWZHUSIsInJlY292ZXJ5Q29tbWl0bWVudCI6IkVpQ1hZaVEyOWdZTXEzWHk0WEt2QnVTcjItNFRVWHhBVEY0QXpKald2Y3ptc1EifX0"

let resolutionResult = await DidIon.resolve(didUri: didUri)
XCTAssertNotNil(resolutionResult.didDocument)
}

}

0 comments on commit 5b71ec1

Please sign in to comment.