This repository has been archived by the owner on Dec 12, 2024. It is now read-only.
generated from TBD54566975/tbd-project-template
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement fetching offerings from a PFI DID (#19)
- Loading branch information
Showing
4 changed files
with
106 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)") } | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters