scaffolding hermes flow and audit logging
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
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
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user