205 lines
6.2 KiB
Swift
205 lines
6.2 KiB
Swift
//
|
|
// LightWalletService.swift
|
|
// ZcashLightClientKit
|
|
//
|
|
// Created by Francisco Gindre on 12/09/2019.
|
|
// Copyright © 2019 Electric Coin Company. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
/**
|
|
Wrapper for errors received from a Lightwalletd endpoint
|
|
*/
|
|
public enum LightWalletServiceError: Error {
|
|
case generalError(message: String)
|
|
case failed(statusCode: Int, message: String)
|
|
case invalidBlock
|
|
case sentFailed(error: Error)
|
|
case genericError(error: Error)
|
|
case timeOut
|
|
case criticalError
|
|
case userCancelled
|
|
case unknown
|
|
}
|
|
|
|
extension LightWalletServiceError: Equatable {
|
|
// swiftlint:disable cyclomatic_complexity
|
|
public static func == (lhs: Self, rhs: Self) -> Bool {
|
|
switch lhs {
|
|
case .generalError(let message):
|
|
switch rhs {
|
|
case .generalError(let msg):
|
|
return message == msg
|
|
default:
|
|
return false
|
|
}
|
|
case .failed(let statusCode, _):
|
|
switch rhs {
|
|
case .failed(let anotherStatus, _):
|
|
return statusCode == anotherStatus
|
|
default:
|
|
return false
|
|
}
|
|
|
|
case .invalidBlock:
|
|
switch rhs {
|
|
case .invalidBlock:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
case .sentFailed:
|
|
switch rhs {
|
|
case .sentFailed:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
case .genericError:
|
|
return false
|
|
|
|
case .timeOut:
|
|
switch rhs {
|
|
case .timeOut:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
case .criticalError:
|
|
switch rhs {
|
|
case .criticalError:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
case .userCancelled:
|
|
switch rhs {
|
|
case .userCancelled:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
case .unknown:
|
|
switch rhs {
|
|
case .unknown:
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protocol LightWalletdInfo {
|
|
var version: String { get }
|
|
|
|
var vendor: String { get }
|
|
|
|
/// true
|
|
var taddrSupport: Bool { get }
|
|
|
|
/// either "main" or "test"
|
|
var chainName: String { get }
|
|
|
|
/// depends on mainnet or testnet
|
|
var saplingActivationHeight: UInt64 { get }
|
|
|
|
/// protocol identifier, see consensus/upgrades.cpp
|
|
var consensusBranchID: String { get }
|
|
|
|
/// latest block on the best chain
|
|
var blockHeight: UInt64 { get }
|
|
|
|
var gitCommit: String { get }
|
|
|
|
var branch: String { get }
|
|
|
|
var buildDate: String { get }
|
|
|
|
var buildUser: String { get }
|
|
|
|
/// less than tip height if zcashd is syncing
|
|
var estimatedHeight: UInt64 { get }
|
|
|
|
/// example: "v4.1.1-877212414"
|
|
var zcashdBuild: String { get }
|
|
|
|
/// example: "/MagicBean:4.1.1/"
|
|
var zcashdSubversion: String { get }
|
|
}
|
|
|
|
protocol LightWalletServiceResponse {
|
|
var errorCode: Int32 { get }
|
|
var errorMessage: String { get }
|
|
}
|
|
|
|
struct LightWalletServiceFactory {
|
|
let endpoint: LightWalletEndpoint
|
|
let torURL: URL?
|
|
|
|
func make() -> LightWalletService {
|
|
return LightWalletGRPCService(endpoint: endpoint, torURL: torURL)
|
|
}
|
|
}
|
|
|
|
protocol LightWalletService: AnyObject {
|
|
/// Closure which is called when connection state changes.
|
|
var connectionStateChange: ((_ from: ConnectionState, _ to: ConnectionState) -> Void)? { get set }
|
|
|
|
/// Returns the info for this lightwalletd server
|
|
/// - Throws: `serviceGetInfoFailed` when GRPC call fails.
|
|
func getInfo() async throws -> LightWalletdInfo
|
|
|
|
/// - Throws: `serviceLatestBlockHeightFailed` when GRPC call fails.
|
|
func latestBlock() async throws -> BlockID
|
|
|
|
/// Return the latest block height known to the service.
|
|
/// - Throws: `serviceLatestBlockFailed` when GRPC call fails.
|
|
func latestBlockHeight() async throws -> BlockHeight
|
|
|
|
/// Return the given range of blocks.
|
|
/// - Parameter range: the inclusive range to fetch.
|
|
/// For instance if 1..5 is given, then every block in that will be fetched, including 1 and 5.
|
|
/// - Throws: `serviceBlockRangeFailed` when GRPC call fails.
|
|
func blockRange(_ range: CompactBlockRange) -> AsyncThrowingStream<ZcashCompactBlock, Error>
|
|
|
|
/// Submits a raw transaction over lightwalletd.
|
|
/// - Parameter spendTransaction: data representing the transaction to be sent
|
|
/// - Throws: `serviceSubmitFailed` when GRPC call fails.
|
|
func submit(spendTransaction: Data) async throws -> LightWalletServiceResponse
|
|
|
|
/// Gets a transaction by id
|
|
/// - Parameter txId: data representing the transaction ID
|
|
/// - Throws: LightWalletServiceError
|
|
/// - Returns: LightWalletServiceResponse
|
|
/// - Throws: `serviceFetchTransactionFailed` when GRPC call fails.
|
|
func fetchTransaction(txId: Data) async throws -> (tx: ZcashTransaction.Fetched?, status: TransactionStatus)
|
|
|
|
/// - Throws: `serviceFetchUTXOsFailed` when GRPC call fails.
|
|
// sourcery: mockedName="fetchUTXOsSingle"
|
|
func fetchUTXOs(for tAddress: String, height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>
|
|
|
|
/// - Throws: `serviceFetchUTXOsFailed` when GRPC call fails.
|
|
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>
|
|
|
|
/// - Throws: `serviceBlockStreamFailed` when GRPC call fails.
|
|
func blockStream(
|
|
startHeight: BlockHeight,
|
|
endHeight: BlockHeight
|
|
) -> AsyncThrowingStream<ZcashCompactBlock, Error>
|
|
|
|
func closeConnection()
|
|
|
|
/// Returns a stream of information about roots of subtrees of the Sapling and Orchard
|
|
/// note commitment trees.
|
|
///
|
|
/// - Parameters:
|
|
/// - request: Request to send to GetSubtreeRoots.
|
|
func getSubtreeRoots(_ request: GetSubtreeRootsArg) -> AsyncThrowingStream<SubtreeRoot, Error>
|
|
|
|
func getTreeState(_ id: BlockID) async throws -> TreeState
|
|
|
|
func getTaddressTxids(_ request: TransparentAddressBlockFilter) -> AsyncThrowingStream<RawTransaction, Error>
|
|
}
|