Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion FlipcashAPI/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ enum ContractPackage: String, CaseIterable {
/// The pinned version consumed when this package isn't building against a local checkout.
var version: Version {
switch self {
case .ocp: return "0.3.0"
case .ocp: return "0.4.0"
case .flipcash2: return "0.6.0"
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,38 @@ final class BalanceService: Sendable {
self.service = Ocp_Balance_V1_Balance.Client(wrapping: client)
}

/// Fetches the core-mint balance for any owner account. Unlike every other
/// Payments API request, `GetBalanceRequest` carries no auth/signature field —
/// the server allows reading balance for any owner, not just the caller's own,
/// so this takes a bare `PublicKey` rather than a signing `KeyPair`.
/// Fetches the core-mint balance for a single owner account. Unlike every
/// other Payments API request, `GetBalancesRequest` carries no auth/signature
/// field — the server allows reading balance for any owner, not just the
/// caller's own, so this takes a bare `PublicKey` rather than a signing
/// `KeyPair`.
///
/// The underlying RPC is batched — `GetBalances` takes a list of owners and
/// an optional mint filter, returning an owner → mint → value map — but
/// nothing in the app currently needs more than one owner's balance at a
/// time, so this wrapper stays single-owner-shaped and reads the one entry
/// it asked for back out of the map.
func getBalance(owner: PublicKey, completion: @Sendable @escaping (Result<TokenAmount, ErrorGetBalance>) -> Void) {
logger.info("Fetching balance")

let request = Ocp_Balance_V1_GetBalanceRequest.with {
$0.owner = owner.solanaAccountID
let request = Ocp_Balance_V1_GetBalancesRequest.with {
$0.owners = [owner.solanaAccountID]
}

Task {
do {
let response = try await service.getBalance(request, options: .unaryDefault)
let response = try await service.getBalances(request, options: .unaryDefault)
let error = ErrorGetBalance(rawValue: response.result.rawValue) ?? .unknown
guard error == .ok else {
logger.error("Failed to fetch balance", metadata: ["error": "\(error)"])
await MainActor.run { completion(.failure(error)) }
return
}
let balance = TokenAmount(quarks: response.coreMintValue, mint: .usdf)
// An owner absent from the map simply has no balances — that's
// zero, not an error. (The old response's NOT_FOUND result case
// is gone; this replaces it.)
let quarks = response.balancesByOwner[owner.base58]?.coreMintValue ?? 0
let balance = TokenAmount(quarks: quarks, mint: .usdf)
await MainActor.run { completion(.success(balance)) }
} catch let error as RPCError {
await MainActor.run { completion(.failure(.from(transportError: error))) }
Expand All @@ -53,7 +64,6 @@ final class BalanceService: Sendable {
public enum ErrorGetBalance: Int, Error, Equatable, Sendable {
case ok
case denied
case notFound
case unknown = -1
case transportFailure = -2
case cancelled = -3
Expand All @@ -65,7 +75,7 @@ extension ErrorGetBalance: ServerError, TransportClassifiableError {
switch self {
case .ok, .transportFailure: .suppressed
case .cancelled: .info
case .denied, .notFound: .info
case .denied: .info
case .unknown, .rejected: .error
}
}
Expand Down
Loading