146 lines
4.4 KiB
Swift
146 lines
4.4 KiB
Swift
import Combine
|
|
import Foundation
|
|
|
|
@MainActor
|
|
final class HermesRepository: ObservableObject {
|
|
@Published private(set) var currentSession: HermesSessionResponse?
|
|
@Published private(set) var currentRound: HermesRound?
|
|
@Published private(set) var isLoading = true
|
|
@Published private(set) var errorCause: Error?
|
|
@Published private(set) var serverClockOffset: TimeInterval?
|
|
|
|
private let apiClient: HermesAPIClient
|
|
|
|
init(apiClient: HermesAPIClient) {
|
|
self.apiClient = apiClient
|
|
}
|
|
|
|
func bootstrap(_ request: HermesSessionStartRequest) async throws -> HermesSessionResponse {
|
|
isLoading = true
|
|
errorCause = nil
|
|
|
|
do {
|
|
await syncClock()
|
|
|
|
let session: HermesSessionResponse
|
|
if let existingSession = currentSession {
|
|
session = existingSession
|
|
} else {
|
|
session = try await startSession(request)
|
|
}
|
|
|
|
if currentRound == nil {
|
|
currentRound = try await loadRoundFromNetwork()
|
|
}
|
|
|
|
isLoading = false
|
|
return session
|
|
} catch {
|
|
errorCause = error
|
|
isLoading = false
|
|
throw error
|
|
}
|
|
}
|
|
|
|
func refreshRoundFromNetwork() async throws -> HermesRound {
|
|
isLoading = true
|
|
errorCause = nil
|
|
|
|
do {
|
|
await syncClock()
|
|
|
|
let round = try await loadRoundFromNetwork()
|
|
currentRound = round
|
|
isLoading = false
|
|
return round
|
|
} catch {
|
|
errorCause = error
|
|
isLoading = false
|
|
throw error
|
|
}
|
|
}
|
|
|
|
func startSession(_ request: HermesSessionStartRequest) async throws -> HermesSessionResponse {
|
|
let session = try await apiClient.startSession(request)
|
|
currentSession = session
|
|
return session
|
|
}
|
|
|
|
func endSession() async throws -> HermesSessionResponse {
|
|
let session = try await apiClient.endSession()
|
|
currentSession = session
|
|
return session
|
|
}
|
|
|
|
func submitBetIntent(_ request: HermesBetIntentRequest) async throws -> HermesBetIntentResponse {
|
|
try await apiClient.submitBetIntent(request)
|
|
}
|
|
|
|
func currentOdds(marketID: UUID) async throws -> HermesOddsVersion {
|
|
try await apiClient.currentOdds(marketID: marketID)
|
|
}
|
|
|
|
func settlement(eventID: UUID) async throws -> HermesSettlement {
|
|
try await apiClient.settlement(eventID: eventID)
|
|
}
|
|
|
|
func experimentConfig() async throws -> HermesExperimentConfig {
|
|
try await apiClient.experimentConfig()
|
|
}
|
|
|
|
func localization(localeCode: String) async throws -> HermesLocalizationBundle {
|
|
try await apiClient.localization(localeCode: localeCode)
|
|
}
|
|
|
|
func submitAnalyticsBatch(_ payload: HermesAnalyticsBatchRequest) async throws {
|
|
try await apiClient.submitAnalyticsBatch(payload)
|
|
}
|
|
|
|
func serverNow() -> Date {
|
|
guard let serverClockOffset else {
|
|
return Date()
|
|
}
|
|
|
|
return Date().addingTimeInterval(serverClockOffset)
|
|
}
|
|
|
|
private func syncClock() async {
|
|
do {
|
|
let health = try await apiClient.health()
|
|
serverClockOffset = health.serverTime.timeIntervalSince(Date())
|
|
} catch {
|
|
return
|
|
}
|
|
}
|
|
|
|
private func loadRoundFromNetwork() async throws -> HermesRound {
|
|
let event = try await apiClient.nextEvent()
|
|
let manifest = try await apiClient.eventManifest(eventID: event.id)
|
|
guard let media = manifest.media.first(where: { $0.mediaType == "hls_main" }) ?? manifest.media.first else {
|
|
throw HermesAPIError.invalidResponse
|
|
}
|
|
|
|
let market: HermesMarket
|
|
if let manifestMarket = manifest.markets.first {
|
|
market = manifestMarket
|
|
} else {
|
|
let markets = try await apiClient.markets(eventID: event.id)
|
|
guard let fallbackMarket = markets.first else {
|
|
throw HermesAPIError.invalidResponse
|
|
}
|
|
market = fallbackMarket
|
|
}
|
|
|
|
let oddsVersion = try await apiClient.currentOdds(marketID: market.id)
|
|
let settlement = try await apiClient.settlement(eventID: event.id)
|
|
|
|
return HermesRound(
|
|
event: event,
|
|
media: media,
|
|
market: market,
|
|
oddsVersion: oddsVersion,
|
|
settlement: settlement
|
|
)
|
|
}
|
|
}
|