Skip to main content
Complete reference for the ZeroSettleEscrow SDK.

ZeroSettleEscrow

The main entry point singleton for all escrow operations.
import ZeroSettleEscrow

let escrow = ZeroSettleEscrow.shared

Published Properties

These properties are @Published and can be observed in SwiftUI:
PropertyTypeDescription
isConfiguredBoolWhether configure() has been called
isAuthInitializedBoolWhether auth initialization is complete
isAuthenticatedBoolWhether user is logged in
userIdUUID?ZeroSettle user ID
walletAddressSolanaAddress?User’s Solana wallet address
balanceCentsIntCurrent balance in cents
activeSessionGameSession?Current game session

Delegate

public weak var delegate: ZeroSettleEscrowDelegate?
Set this to receive callbacks for auth, balance, and session events.

Configuration

configure(_:)

Configure the SDK. Must be called before any other methods.
public func configure(_ config: EscrowConfig)
Example:
ZeroSettleEscrow.shared.configure(EscrowConfig(
    privyAppId: "clxxxxxxxxxxxxxxxx",
    privyClientId: "client-xxxxxxxx",
    partnerAppId: 123,
    environment: .production
))

setGameAdminBackend(_:)

Set your game admin backend for server integration.
public func setGameAdminBackend(_ backend: GameAdminBackend)
Example:
let backend = MyGameAdminBackend(baseURL: URL(string: "https://api.mygame.com")!)
ZeroSettleEscrow.shared.setGameAdminBackend(backend)

Authentication

initializeAuth()

Initialize authentication and restore any existing session.
public func initializeAuth() async
Call this once on app launch:
.task {
    await ZeroSettleEscrow.shared.initializeAuth()
}

sendOTP(to:)

Send OTP code to phone number.
public func sendOTP(to phoneNumber: String) async throws
ParameterTypeDescription
phoneNumberStringPhone in E.164 format (e.g., +14155551234)
Throws: Error if sending fails.

verifyOTP(code:phoneNumber:)

Verify OTP and complete login.
public func verifyOTP(code: String, phoneNumber: String) async throws
ParameterTypeDescription
codeStringThe 6-digit OTP code
phoneNumberStringPhone in E.164 format
On success:
  • isAuthenticated becomes true
  • userId and walletAddress are set
  • Delegate receives zeroSettleEscrowDidAuthenticate
  • Balance subscription starts

logout()

Logout the current user.
public func logout() async
Clears all state and disconnects balance subscription.

Balance

balanceCents

Current balance in cents, updated in real-time via WebSocket.
@Published public private(set) var balanceCents: Int

forceRefreshBalance()

Manually refresh balance (triggers RPC call).
public func forceRefreshBalance() async
Usually not needed—WebSocket updates automatically.

addDevFunds(cents:) [DEBUG ONLY]

Add test funds to displayed balance.
#if DEBUG
public func addDevFunds(cents: Int)
#endif
Only affects local display. Does not create real on-chain funds.

Game Sessions

startSession(…)

Start a new game session.
@discardableResult
public func startSession(
    gameDefinitionId: UUID,
    mode: GameMode = .singlePlayer,
    entryFeeCents: Int,
    maxPayoutMultiplier: Double
) async throws -> GameSession
ParameterTypeDescription
gameDefinitionIdUUIDGame definition from dashboard
modeGameMode.singlePlayer, .duel, or .tournament
entryFeeCentsIntEntry fee in cents
maxPayoutMultiplierDoubleMaximum payout multiplier
Returns: GameSession Throws:
  • ZeroSettleEscrowError.notAuthenticated
  • ZeroSettleEscrowError.insufficientBalance(required:available:)
  • Other errors

confirmEscrow(sessionId:)

Confirm escrow after staking.
public func confirmEscrow(sessionId: UUID) async throws
Validates both player and house stakes are confirmed on-chain.

submitResult(sessionId:playerResults:)

Submit game result and trigger settlement.
@discardableResult
public func submitResult(
    sessionId: UUID,
    playerResults: [PlayerResult]
) async throws
ParameterTypeDescription
sessionIdUUIDSession to settle
playerResults[PlayerResult]Final results for each player

clearActiveSession()

Clear the active session.
public func clearActiveSession()
Call when returning to menu after game completion.

Game Configuration

getGameDefinition(name:)

Get a game definition by name.
public func getGameDefinition(name: String) async throws -> GameDefinition
Returns the game definition including its payout table.

Types

EscrowConfig

Configuration for the SDK.
public struct EscrowConfig: Sendable {
    let privyAppId: String
    let privyClientId: String
    let partnerAppId: Int
    let environment: NetworkEnvironment
    let blockchainEnvironment: NetworkEnvironment
    let localTokenMint: SolanaAddress?
    let gameBackendURL: URL?
}

NetworkEnvironment

public enum NetworkEnvironment: String {
    case production
    case development
    case local
}

GameMode

public enum GameMode: String, Sendable, Codable {
    case singlePlayer = "single_player"
    case duel = "duel"
    case tournament = "tournament"
}

GameSession

public struct GameSession: Identifiable, Sendable, Equatable, Codable {
    let id: UUID
    let gameDefinitionId: UUID
    let mode: GameMode
    let entryFeeCents: Int
    let maxPayoutMultiplier: Double
    let players: [SessionPlayer]
    let state: SessionState
    let createdAt: Date

    // Computed
    var totalPotCents: Int
    var stakedPlayerCount: Int
    var allPlayersStaked: Bool
}

SessionState

public enum SessionState: String, Sendable, Codable {
    case waitingForPlayers = "waiting_for_players"
    case pendingStakes = "pending_stakes"
    case escrowConfirmed = "escrow_confirmed"
    case inProgress = "in_progress"
    case pendingSettlement = "pending_settlement"
    case settled = "settled"
    case cancelled = "cancelled"
}

SessionPlayer

public struct SessionPlayer: Sendable, Equatable, Identifiable, Codable {
    let id: UUID
    let wallet: SolanaAddress
    let stakeStatus: StakeStatus
}

public enum StakeStatus: String, Sendable, Codable {
    case pending = "pending"
    case staked = "staked"
    case refunded = "refunded"
}

PlayerResult

public struct PlayerResult: Sendable, Codable {
    let userId: UUID
    let finalMultiplier: Double

    var multiplierBps: Int  // 2.5x = 250
}

SettlementResult

public struct SettlementResult: Sendable, Codable {
    let sessionId: UUID
    let transactionSignature: String
    let payouts: [PlayerPayout]
    let platformFeeCents: Int
}

public struct PlayerPayout: Sendable, Codable {
    let userId: UUID
    let wallet: SolanaAddress
    let amountCents: Int
}

GameDefinition

public struct GameDefinition: Sendable, Codable, Identifiable {
    let id: UUID
    let name: String
    let displayName: String
    let description: String?
    let payoutTable: PayoutTable
}

PayoutTable

public enum PayoutTable: Sendable, Codable {
    case discrete(DiscretePayoutTable)
    case continuous(ContinuousPayoutTable)

    var maxMultiplier: Double
    func multiplier(for value: Double) -> Double
}

SolanaAddress

Type-safe Solana address wrapper.
public struct SolanaAddress: Sendable, Equatable, Codable, Hashable {
    let base58: String

    init(_ base58String: String) throws  // Validates format
    init(trusted base58String: String)   // Skips validation
}

Errors

ZeroSettleEscrowError

public enum ZeroSettleEscrowError: Error, LocalizedError {
    case notConfigured
    case notAuthenticated
    case noActiveSession
    case sessionNotReady(currentState: SessionState)
    case insufficientBalance(required: Int, available: Int)
    case invalidConfiguration(String)
    case signingFailed(String)
}

Delegate Protocol

ZeroSettleEscrowDelegate

@MainActor
public protocol ZeroSettleEscrowDelegate: AnyObject {
    // Authentication
    func zeroSettleEscrowDidAuthenticate(userId: UUID, walletAddress: SolanaAddress)
    func zeroSettleEscrowDidLogout()
    func zeroSettleEscrowAuthenticationFailed(operation: String, error: Error)

    // Balance
    func zeroSettleEscrowDidUpdateBalance(_ balanceCents: Int)
    func zeroSettleEscrowBalanceFetchFailed(error: Error)

    // Sessions
    func zeroSettleEscrowDidCreateSession(_ session: GameSession)
    func zeroSettleEscrowSessionStateChanged(_ session: GameSession, from previousState: SessionState)
    func zeroSettleEscrowDidConfirm(session: GameSession)
    func zeroSettleEscrowDidSettleSession(_ result: SettlementResult)

    // Errors
    func zeroSettleEscrowSessionCreationFailed(request: SessionCreationRequest, error: Error, canRetry: Bool)
    func zeroSettleEscrowConfirmationFailed(sessionId: UUID, error: Error, canRetry: Bool)
    func zeroSettleEscrowSettlementFailed(sessionId: UUID, error: Error, canRetry: Bool)
}

SessionCreationRequest

Provided in failure callbacks to identify which creation attempt failed.
public struct SessionCreationRequest: Sendable {
    let gameDefinitionId: UUID
    let mode: GameMode
    let entryFeeCents: Int
    let maxPayoutMultiplier: Double
}

GameAdminBackend Protocol

Implement this protocol to integrate your game server.
public protocol GameAdminBackend: AnyObject, Sendable {
    /// Called when player has staked. Your server should stake the house side.
    func onPlayerStaked(
        sessionId: UUID,
        gameDefinitionId: Int,
        entryFeeLamports: Int,
        maxPayoutMultiplier: Double,
        playerWalletAddress: String
    ) async throws -> String  // Returns transaction signature

    /// Called when game ends. Your server should submit result on-chain.
    func submitResult(
        sessionId: UUID,
        finalMultiplierBps: Int,
        playerWalletAddress: String
    ) async throws
}