[#463] Migrate LightwalletService to Async/Await (#493)

- migration of the protocol's methods done
- split the code so there's blocking and non-blocking API separately

[463] Migrate LightwalletService to Async/Await

- draft

[463] Migrate LightwalletService to Async/Await

- failing tests under investigation

[463] Migrate LightwalletService to Async/Await

- code cleanup
- tests cleanup
- async throws unit tests added

[463] Migrate LightwalletService to Async/Await

- sample app updated to the latest API

[463] Migrate LightwalletService to Async/Await

- cleanup

[463] Migrate LightwalletService to Async/Await

- cleanup

[463] Migrate LightwalletService to Async/Await

- fixed non-building tests

[463] Migrate LightwalletService to Async/Await

- reverting back to lastHeight()

[463] Migrate LightwalletService to Async/Await

updated code to AsyncStream

[463] Migrate LightwalletService to Async/Await (493)

- tests fixed
- blockRange reimplemented to use AsyncStream
- grpc proto files regenerated to exclude Server
This commit is contained in:
Lukas Korba 2022-08-25 15:39:59 +02:00 committed by GitHub
parent 29e06d0b8a
commit f1a570bbc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1411 additions and 423 deletions

View File

@ -30,7 +30,7 @@ enum DemoAppConfig {
}()
static var endpoint: LightWalletEndpoint {
return LightWalletEndpoint(address: self.host, port: self.port, secure: true)
return LightWalletEndpoint(address: self.host, port: self.port, secure: true, streamingCallTimeoutInMillis: 10 * 60 * 60 * 1000)
}
}

View File

@ -28,18 +28,13 @@ class LatestHeightViewController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
service.latestBlockHeight { result in
switch result {
case .success(let height):
DispatchQueue.main.async { [weak self] in
self?.model = height
}
case .failure(let error):
DispatchQueue.main.async { [weak self] in
self?.fail(error)
}
/// Note: It's safe to modify model or call fail() because all methods of a UIViewController are MainActor methods by default.
Task {
do {
model = try await service.latestBlockHeightAsync()
} catch {
fail(error as? LightWalletServiceError ?? .unknown)
}
}
}

View File

@ -53,6 +53,7 @@ class CompactBlockStreamDownloadOperation: ZcashOperation {
private var service: LightWalletService
private var done = false
private var cancelable: CancellableCall?
private var cancelableTask: Task<Void, Error>?
private var startHeight: BlockHeight?
private var targetHeight: BlockHeight?
private var blockBufferSize: Int
@ -93,13 +94,13 @@ class CompactBlockStreamDownloadOperation: ZcashOperation {
self.name = "Download Stream Operation"
}
// swiftlint:disable cyclomatic_complexity
override func main() {
guard !shouldCancel() else {
cancel()
return
}
self.startedHandler?()
do {
if self.targetHeight == nil {
self.targetHeight = try service.latestBlockHeight()
@ -109,38 +110,32 @@ class CompactBlockStreamDownloadOperation: ZcashOperation {
}
let latestDownloaded = try storage.latestHeight()
let startHeight = max(self.startHeight ?? BlockHeight.empty(), latestDownloaded)
self.cancelable = self.service.blockStream(startHeight: startHeight, endHeight: latestHeight) { [weak self] blockResult in
switch blockResult {
case .success(let result):
switch result {
case .success:
do {
try self?.flush()
self?.done = true
} catch {
self?.fail(error: error)
}
return
case .error(let e):
self?.fail(error: e)
}
case .failure(let e):
if case .userCancelled = e {
self?.done = true
} else {
self?.fail(error: e)
}
}
} handler: {[weak self] block in
guard let self = self else { return }
let stream = service.blockStream(
startHeight: startHeight,
endHeight: latestHeight
)
cancelableTask = Task {
do {
try self.cache(block, flushCache: false)
for try await zcashCompactBlock in stream {
try self.cache(zcashCompactBlock, flushCache: false)
let progress = BlockProgress(
startHeight: startHeight,
targetHeight: latestHeight,
progressHeight: zcashCompactBlock.height
)
self.progressDelegate?.progressUpdated(.download(progress))
}
try self.flush()
self.done = true
} catch {
self.fail(error: error)
if let err = error as? LightWalletServiceError, case .userCancelled = err {
self.done = true
} else {
self.fail(error: error)
}
}
} progress: { progress in
self.progressDelegate?.progressUpdated(.download(progress))
}
while !done && !isCancelled {
@ -153,11 +148,13 @@ class CompactBlockStreamDownloadOperation: ZcashOperation {
override func fail(error: Error? = nil) {
self.cancelable?.cancel()
self.cancelableTask?.cancel()
super.fail(error: error)
}
override func cancel() {
self.cancelable?.cancel()
self.cancelableTask?.cancel()
super.cancel()
}

View File

@ -90,7 +90,8 @@ public extension BlockProgress {
public class LightWalletGRPCService {
let channel: Channel
let connectionManager: ConnectionStatusManager
let compactTxStreamer: CompactTxStreamerClient
let compactTxStreamer: CompactTxStreamerNIOClient
let compactTxStreamerAsync: CompactTxStreamerAsyncClient
let singleCallTimeout: TimeLimit
let streamingCallTimeout: TimeLimit
@ -135,7 +136,14 @@ public class LightWalletGRPCService {
self.channel = channel
compactTxStreamer = CompactTxStreamerClient(
compactTxStreamer = CompactTxStreamerNIOClient(
channel: self.channel,
defaultCallOptions: Self.callOptions(
timeLimit: self.singleCallTimeout
)
)
compactTxStreamerAsync = CompactTxStreamerAsyncClient(
channel: self.channel,
defaultCallOptions: Self.callOptions(
timeLimit: self.singleCallTimeout
@ -146,6 +154,7 @@ public class LightWalletGRPCService {
deinit {
_ = channel.close()
_ = compactTxStreamer.channel.close()
_ = compactTxStreamerAsync.channel.close()
}
func stop() {
@ -155,7 +164,7 @@ public class LightWalletGRPCService {
func blockRange(startHeight: BlockHeight, endHeight: BlockHeight? = nil, result: @escaping (CompactBlock) -> Void) throws -> ServerStreamingCall<BlockRange, CompactBlock> {
compactTxStreamer.getBlockRange(BlockRange(startHeight: startHeight, endHeight: endHeight), handler: result)
}
func latestBlock() throws -> BlockID {
try compactTxStreamer.getLatestBlock(ChainSpec()).response.wait()
}
@ -179,122 +188,18 @@ public class LightWalletGRPCService {
}
}
extension LightWalletGRPCService: LightWalletService {
@discardableResult
public func blockStream(
startHeight: BlockHeight,
endHeight: BlockHeight,
result: @escaping (Result<GRPCResult, LightWalletServiceError>) -> Void,
handler: @escaping (ZcashCompactBlock) -> Void,
progress: @escaping (BlockProgress) -> Void
) -> CancellableCall {
let future = compactTxStreamer.getBlockRange(
BlockRange(
startHeight: startHeight,
endHeight: endHeight
),
callOptions: Self.callOptions(timeLimit: self.streamingCallTimeout),
handler: { compactBlock in
handler(ZcashCompactBlock(compactBlock: compactBlock))
progress(
BlockProgress(
startHeight: startHeight,
targetHeight: endHeight,
progressHeight: BlockHeight(compactBlock.height)
)
)
}
)
future.status.whenComplete { completionResult in
switch completionResult {
case .success(let status):
switch status.code {
case .ok:
result(.success(GRPCResult.success))
default:
result(.failure(LightWalletServiceError.mapCode(status)))
}
case .failure(let error):
result(.failure(LightWalletServiceError.genericError(error: error)))
}
}
return future
}
// MARK: - LightWalletServiceBlockingAPI
extension LightWalletGRPCService: LightWalletServiceBlockingAPI {
public func getInfo() throws -> LightWalletdInfo {
try compactTxStreamer.getLightdInfo(Empty()).response.wait()
}
public func getInfo(result: @escaping (Result<LightWalletdInfo, LightWalletServiceError>) -> Void) {
compactTxStreamer.getLightdInfo(Empty()).response.whenComplete { completionResult in
switch completionResult {
case .success(let info):
result(.success(info))
case .failure(let error):
result(.failure(error.mapToServiceError()))
}
}
}
public func closeConnection() {
_ = channel.close()
}
public func fetchTransaction(txId: Data) throws -> TransactionEntity {
var txFilter = TxFilter()
txFilter.hash = txId
do {
let rawTx = try compactTxStreamer.getTransaction(txFilter).response.wait()
return TransactionBuilder.createTransactionEntity(txId: txId, rawTransaction: rawTx)
} catch {
throw error.mapToServiceError()
}
}
public func fetchTransaction(txId: Data, result: @escaping (Result<TransactionEntity, LightWalletServiceError>) -> Void) {
var txFilter = TxFilter()
txFilter.hash = txId
compactTxStreamer.getTransaction(txFilter).response.whenComplete { response in
switch response {
case .failure(let error):
result(.failure(error.mapToServiceError()))
case .success(let rawTx):
result(.success(TransactionBuilder.createTransactionEntity(txId: txId, rawTransaction: rawTx)))
}
}
}
public func submit(spendTransaction: Data, result: @escaping (Result<LightWalletServiceResponse, LightWalletServiceError>) -> Void) {
do {
let transaction = try RawTransaction(serializedData: spendTransaction)
let response = self.compactTxStreamer.sendTransaction(transaction).response
response.whenComplete { responseResult in
switch responseResult {
case .failure(let error):
result(.failure(LightWalletServiceError.sentFailed(error: error)))
case .success(let success):
result(.success(success))
}
}
} catch {
result(.failure(error.mapToServiceError()))
}
}
public func submit(spendTransaction: Data) throws -> LightWalletServiceResponse {
let rawTx = RawTransaction.with { raw in
raw.data = spendTransaction
}
do {
return try compactTxStreamer.sendTransaction(rawTx).response.wait()
} catch {
throw error.mapToServiceError()
public func latestBlockHeight() throws -> BlockHeight {
guard let height = try? compactTxStreamer.getLatestBlock(ChainSpec()).response.wait().compactBlockHeight() else {
throw LightWalletServiceError.timeOut
}
return height
}
public func blockRange(_ range: CompactBlockRange) throws -> [ZcashCompactBlock] {
@ -315,51 +220,30 @@ extension LightWalletGRPCService: LightWalletService {
}
}
public func latestBlockHeight(result: @escaping (Result<BlockHeight, LightWalletServiceError>) -> Void) {
let response = compactTxStreamer.getLatestBlock(ChainSpec()).response
response.whenSuccessBlocking(onto: queue) { blockID in
guard let blockHeight = Int(exactly: blockID.height) else {
result(.failure(LightWalletServiceError.generalError(message: "error creating blockheight from BlockID \(blockID)")))
return
}
result(.success(blockHeight))
public func submit(spendTransaction: Data) throws -> LightWalletServiceResponse {
let rawTx = RawTransaction.with { raw in
raw.data = spendTransaction
}
response.whenFailureBlocking(onto: queue) { error in
result(.failure(error.mapToServiceError()))
do {
return try compactTxStreamer.sendTransaction(rawTx).response.wait()
} catch {
throw error.mapToServiceError()
}
}
public func blockRange(_ range: CompactBlockRange, result: @escaping (Result<[ZcashCompactBlock], LightWalletServiceError>) -> Void) {
queue.async { [weak self] in
guard let self = self else { return }
var blocks: [CompactBlock] = []
let response = self.compactTxStreamer.getBlockRange(range.blockRange(), handler: { blocks.append($0) })
do {
let status = try response.status.wait()
switch status.code {
case .ok:
result(.success(blocks.asZcashCompactBlocks()))
default:
result(.failure(.mapCode(status)))
}
} catch {
result(.failure(error.mapToServiceError()))
}
public func fetchTransaction(txId: Data) throws -> TransactionEntity {
var txFilter = TxFilter()
txFilter.hash = txId
do {
let rawTx = try compactTxStreamer.getTransaction(txFilter).response.wait()
return TransactionBuilder.createTransactionEntity(txId: txId, rawTransaction: rawTx)
} catch {
throw error.mapToServiceError()
}
}
public func latestBlockHeight() throws -> BlockHeight {
guard let height = try? latestBlock().compactBlockHeight() else {
throw LightWalletServiceError.timeOut
}
return height
}
public func fetchUTXOs(for tAddress: String, height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
let arg = GetAddressUtxosArg.with { utxoArgs in
utxoArgs.addresses = [tAddress]
@ -383,7 +267,168 @@ extension LightWalletGRPCService: LightWalletService {
}
}
public func fetchUTXOs(for tAddress: String, height: BlockHeight, result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void) {
public func fetchUTXOs(for tAddresses: [String], height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
guard !tAddresses.isEmpty else {
return [] // FIXME: throw a real error
}
var utxos: [UnspentTransactionOutputEntity] = []
let arg = GetAddressUtxosArg.with { utxoArgs in
utxoArgs.addresses = tAddresses
utxoArgs.startHeight = UInt64(height)
}
utxos.append(
contentsOf:
try self.compactTxStreamer.getAddressUtxos(arg).response.wait().addressUtxos.map { reply in
UTXO(
id: nil,
address: reply.address,
prevoutTxId: reply.txid,
prevoutIndex: Int(reply.index),
script: reply.script,
valueZat: Int(reply.valueZat),
height: Int(reply.height),
spentInTx: nil
)
}
)
return utxos
}
}
// MARK: - LightWalletServiceNonBlockingAPI
extension LightWalletGRPCService: LightWalletServiceNonBlockingAPI {
public func getInfo(result: @escaping (Result<LightWalletdInfo, LightWalletServiceError>) -> Void) {
compactTxStreamer.getLightdInfo(Empty()).response.whenComplete { completionResult in
switch completionResult {
case .success(let info):
result(.success(info))
case .failure(let error):
result(.failure(error.mapToServiceError()))
}
}
}
public func getInfoAsync() async throws -> LightWalletdInfo {
try await compactTxStreamerAsync.getLightdInfo(Empty())
}
public func latestBlockHeight(result: @escaping (Result<BlockHeight, LightWalletServiceError>) -> Void) {
let response = compactTxStreamer.getLatestBlock(ChainSpec()).response
response.whenSuccessBlocking(onto: queue) { blockID in
guard let blockHeight = Int(exactly: blockID.height) else {
result(.failure(LightWalletServiceError.generalError(message: "error creating blockheight from BlockID \(blockID)")))
return
}
result(.success(blockHeight))
}
response.whenFailureBlocking(onto: queue) { error in
result(.failure(error.mapToServiceError()))
}
}
public func latestBlockHeightAsync() async throws -> BlockHeight {
try await BlockHeight(compactTxStreamerAsync.getLatestBlock(ChainSpec()).height)
}
public func blockRange(_ range: CompactBlockRange, result: @escaping (Result<[ZcashCompactBlock], LightWalletServiceError>) -> Void) {
queue.async { [weak self] in
guard let self = self else { return }
var blocks: [CompactBlock] = []
let response = self.compactTxStreamer.getBlockRange(range.blockRange(), handler: { blocks.append($0) })
do {
let status = try response.status.wait()
switch status.code {
case .ok:
result(.success(blocks.asZcashCompactBlocks()))
default:
result(.failure(.mapCode(status)))
}
} catch {
result(.failure(error.mapToServiceError()))
}
}
}
public func blockRange(_ range: CompactBlockRange) -> AsyncThrowingStream<ZcashCompactBlock, Error> {
let stream = compactTxStreamerAsync.getBlockRange(range.blockRange())
return AsyncThrowingStream { continuation in
Task {
do {
for try await block in stream {
continuation.yield(ZcashCompactBlock(compactBlock: block))
}
continuation.finish(throwing: nil)
} catch {
continuation.finish(throwing: error)
}
}
}
}
public func submit(spendTransaction: Data, result: @escaping (Result<LightWalletServiceResponse, LightWalletServiceError>) -> Void) {
do {
let transaction = try RawTransaction(serializedData: spendTransaction)
let response = self.compactTxStreamer.sendTransaction(transaction).response
response.whenComplete { responseResult in
switch responseResult {
case .failure(let error):
result(.failure(LightWalletServiceError.sentFailed(error: error)))
case .success(let success):
result(.success(success))
}
}
} catch {
result(.failure(error.mapToServiceError()))
}
}
public func submitAsync(spendTransaction: Data) async throws -> LightWalletServiceResponse {
do {
let transaction = try RawTransaction(serializedData: spendTransaction)
return try await compactTxStreamerAsync.sendTransaction(transaction)
} catch {
throw LightWalletServiceError.sentFailed(error: error)
}
}
public func fetchTransaction(txId: Data, result: @escaping (Result<TransactionEntity, LightWalletServiceError>) -> Void) {
var txFilter = TxFilter()
txFilter.hash = txId
compactTxStreamer.getTransaction(txFilter).response.whenComplete { response in
switch response {
case .failure(let error):
result(.failure(error.mapToServiceError()))
case .success(let rawTx):
result(.success(TransactionBuilder.createTransactionEntity(txId: txId, rawTransaction: rawTx)))
}
}
}
public func fetchTransactionAsync(txId: Data) async throws -> TransactionEntity {
var txFilter = TxFilter()
txFilter.hash = txId
let rawTx = try await compactTxStreamerAsync.getTransaction(txFilter)
return TransactionBuilder.createTransactionEntity(txId: txId, rawTransaction: rawTx)
}
public func fetchUTXOs(
for tAddress: String,
height: BlockHeight,
result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>
) -> Void) {
queue.async { [weak self] in
guard let self = self else { return }
let arg = GetAddressUtxosArg.with { utxoArgs in
@ -420,36 +465,13 @@ extension LightWalletGRPCService: LightWalletService {
}
}
public func fetchUTXOs(for tAddresses: [String], height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
guard !tAddresses.isEmpty else {
return [] // FIXME: throw a real error
}
var utxos: [UnspentTransactionOutputEntity] = []
let arg = GetAddressUtxosArg.with { utxoArgs in
utxoArgs.addresses = tAddresses
utxoArgs.startHeight = UInt64(height)
}
utxos.append(
contentsOf:
try self.compactTxStreamer.getAddressUtxos(arg).response.wait().addressUtxos.map { reply in
UTXO(
id: nil,
address: reply.address,
prevoutTxId: reply.txid,
prevoutIndex: Int(reply.index),
script: reply.script,
valueZat: Int(reply.valueZat),
height: Int(reply.height),
spentInTx: nil
)
}
)
return utxos
public func fetchUTXOs(
for tAddress: String,
height: BlockHeight
) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
return fetchUTXOs(for: [tAddress], height: height)
}
public func fetchUTXOs(
for tAddresses: [String],
height: BlockHeight,
@ -495,6 +517,119 @@ extension LightWalletGRPCService: LightWalletService {
}
}
}
public func fetchUTXOs(
for tAddresses: [String],
height: BlockHeight
) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
guard !tAddresses.isEmpty else {
return AsyncThrowingStream { _ in }
}
let args = GetAddressUtxosArg.with { utxoArgs in
utxoArgs.addresses = tAddresses
utxoArgs.startHeight = UInt64(height)
}
let stream = compactTxStreamerAsync.getAddressUtxosStream(args)
return AsyncThrowingStream { continuation in
Task {
do {
for try await reply in stream {
continuation.yield(
UTXO(
id: nil,
address: reply.address,
prevoutTxId: reply.txid,
prevoutIndex: Int(reply.index),
script: reply.script,
valueZat: Int(reply.valueZat),
height: Int(reply.height),
spentInTx: nil
)
)
}
continuation.finish(throwing: nil)
} catch {
continuation.finish(throwing: error)
}
}
}
}
@discardableResult
public func blockStream(
startHeight: BlockHeight,
endHeight: BlockHeight,
result: @escaping (Result<GRPCResult, LightWalletServiceError>) -> Void,
handler: @escaping (ZcashCompactBlock) -> Void,
progress: @escaping (BlockProgress) -> Void
) -> CancellableCall {
let future = compactTxStreamer.getBlockRange(
BlockRange(
startHeight: startHeight,
endHeight: endHeight
),
callOptions: Self.callOptions(timeLimit: self.streamingCallTimeout),
handler: { compactBlock in
handler(ZcashCompactBlock(compactBlock: compactBlock))
progress(
BlockProgress(
startHeight: startHeight,
targetHeight: endHeight,
progressHeight: BlockHeight(compactBlock.height)
)
)
}
)
future.status.whenComplete { completionResult in
switch completionResult {
case .success(let status):
switch status.code {
case .ok:
result(.success(GRPCResult.success))
default:
result(.failure(LightWalletServiceError.mapCode(status)))
}
case .failure(let error):
result(.failure(LightWalletServiceError.genericError(error: error)))
}
}
return future
}
public func blockStream(
startHeight: BlockHeight,
endHeight: BlockHeight
) -> AsyncThrowingStream<ZcashCompactBlock, Error> {
let stream = compactTxStreamerAsync.getBlockRange(
BlockRange(
startHeight: startHeight,
endHeight: endHeight
),
callOptions: Self.callOptions(timeLimit: self.streamingCallTimeout)
)
return AsyncThrowingStream { continuation in
Task {
do {
for try await compactBlock in stream {
continuation.yield(ZcashCompactBlock(compactBlock: compactBlock))
}
continuation.finish(throwing: nil)
} catch {
continuation.finish(throwing: error)
}
}
}
}
}
extension LightWalletGRPCService: LightWalletService {
public func closeConnection() {
_ = channel.close()
}
}
// MARK: - Extensions

View File

@ -101,49 +101,102 @@ public protocol LightWalletServiceResponse {
extension SendResponse: LightWalletServiceResponse {}
public protocol LightWalletService {
/**
returns the info for this lightwalletd server (blocking)
*/
/// Blocking API - used for the testing purposes
public protocol LightWalletServiceBlockingAPI {
/// Returns the info for this lightwalletd server (blocking)
func getInfo() throws -> LightWalletdInfo
/**
returns the info for this lightwalletd server
*/
func getInfo(result: @escaping (Result<LightWalletdInfo, LightWalletServiceError>) -> Void)
/**
Return the latest block height known to the service.
- Parameter result: a result containing the height or an Error
*/
func latestBlockHeight(result: @escaping (Result<BlockHeight, LightWalletServiceError>) -> Void)
/**
Return the latest block height known to the service.
- Parameter result: a result containing the height or an Error
*/
///
/// Return the latest block height known to the service.
/// - Parameter result: a result containing the height or an Error
func latestBlockHeight() 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.
Non blocking
*/
func blockRange(_ range: CompactBlockRange, result: @escaping (Result<[ZcashCompactBlock], LightWalletServiceError>) -> Void )
/**
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.
blocking
*/
/// 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.
func blockRange(_ range: CompactBlockRange) throws -> [ZcashCompactBlock]
/// Submits a raw transaction over lightwalletd. Blocking
/// - Parameter spendTransaction: data representing the transaction to be sent
/// - Throws: LightWalletServiceError
/// - Returns: LightWalletServiceResponse
func submit(spendTransaction: Data) throws -> LightWalletServiceResponse
/// Gets a transaction by id
/// - Parameter txId: data representing the transaction ID
/// - Throws: LightWalletServiceError
/// - Returns: LightWalletServiceResponse
func fetchTransaction(txId: Data) throws -> TransactionEntity
func fetchUTXOs(
for tAddress: String,
height: BlockHeight
) throws -> [UnspentTransactionOutputEntity]
func fetchUTXOs(
for tAddresses: [String],
height: BlockHeight
) throws -> [UnspentTransactionOutputEntity]
}
public protocol LightWalletServiceNonBlockingAPI {
/// Returns the info for this lightwalletd server
@available(*, deprecated, message: "This function will be removed soon. Use the `getInfoAsync()` instead.")
func getInfo(result: @escaping (Result<LightWalletdInfo, LightWalletServiceError>) -> Void)
func getInfoAsync() async throws -> LightWalletdInfo
///
/// Return the latest block height known to the service.
/// - Parameter result: a result containing the height or an Error
@available(*, deprecated, message: "This function will be removed soon. Use the `latestBlockHeightAsync()` instead.")
func latestBlockHeight(result: @escaping (Result<BlockHeight, LightWalletServiceError>) -> Void)
func latestBlockHeightAsync() 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.
@available(*, deprecated, message: "This function will be removed soon. Use the `blockRange(...) -> AsyncThrowingStream<ZcashCompactBlock, Error>` instead.")
func blockRange(_ range: CompactBlockRange, result: @escaping (Result<[ZcashCompactBlock], LightWalletServiceError>) -> Void)
func blockRange(_ range: CompactBlockRange) -> AsyncThrowingStream<ZcashCompactBlock, Error>
/// Submits a raw transaction over lightwalletd. Non-Blocking
/// - Parameter spendTransaction: data representing the transaction to be sent
/// - Parameter result: escaping closure that takes a result containing either LightWalletServiceResponse or LightWalletServiceError
@available(*, deprecated, message: "This function will be removed soon. Use the `submitAsync(spendTransaction: Data)` instead.")
func submit(spendTransaction: Data, result: @escaping(Result<LightWalletServiceResponse, LightWalletServiceError>) -> Void)
func submitAsync(spendTransaction: Data) async throws -> LightWalletServiceResponse
/// Gets a transaction by id
/// - Parameter txId: data representing the transaction ID
/// - Parameter result: handler for the result
/// - Throws: LightWalletServiceError
/// - Returns: LightWalletServiceResponse
@available(*, deprecated, message: "This function will be removed soon. Use the `fetchTransactionAsync(txId: Data)` instead.")
func fetchTransaction(
txId: Data,
result: @escaping (Result<TransactionEntity, LightWalletServiceError>) -> Void
)
func fetchTransactionAsync(txId: Data) async throws -> TransactionEntity
@available(*, deprecated, message: "This function will be removed soon. Use the `fetchUTXOs(for tAddress:...) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>` instead.")
func fetchUTXOs(
for tAddress: String,
height: BlockHeight,
result: @escaping(Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void
)
func fetchUTXOs(for tAddress: String, height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>
@available(*, deprecated, message: "This function will be removed soon. Use the `fetchUTXOs(for tAddresses:...) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>` instead.")
func fetchUTXOs(
for tAddresses: [String],
height: BlockHeight,
result: @escaping(Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void
)
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error>
@available(*, deprecated, message: "This function will be removed soon. Use the `blockStream(...) -> AsyncThrowingStream<ZcashCompactBlock, Error>` instead.")
@discardableResult
func blockStream(
startHeight: BlockHeight,
@ -153,62 +206,12 @@ public protocol LightWalletService {
progress: @escaping (BlockProgress) -> Void
) -> CancellableCall
/**
Submits a raw transaction over lightwalletd. Non-Blocking
- Parameter spendTransaction: data representing the transaction to be sent
- Parameter result: escaping closure that takes a result containing either LightWalletServiceResponse or LightWalletServiceError
*/
func submit(spendTransaction: Data, result: @escaping(Result<LightWalletServiceResponse, LightWalletServiceError>) -> Void)
/**
Submits a raw transaction over lightwalletd. Blocking
- Parameter spendTransaction: data representing the transaction to be sent
- Throws: LightWalletServiceError
- Returns: LightWalletServiceResponse
*/
func submit(spendTransaction: Data) throws -> LightWalletServiceResponse
/**
Gets a transaction by id
- Parameter txId: data representing the transaction ID
- Throws: LightWalletServiceError
- Returns: LightWalletServiceResponse
*/
func fetchTransaction(txId: Data) throws -> TransactionEntity
/**
Gets a transaction by id
- Parameter txId: data representing the transaction ID
- Parameter result: handler for the result
- Throws: LightWalletServiceError
- Returns: LightWalletServiceResponse
*/
func fetchTransaction(
txId: Data,
result: @escaping (Result<TransactionEntity, LightWalletServiceError>) -> Void
)
func fetchUTXOs(
for tAddress: String,
height: BlockHeight
) throws -> [UnspentTransactionOutputEntity]
func fetchUTXOs(
for tAddress: String,
height: BlockHeight,
result: @escaping(Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void
)
func fetchUTXOs(
for tAddresses: [String],
height: BlockHeight
) throws -> [UnspentTransactionOutputEntity]
func fetchUTXOs(
for tAddresses: [String],
height: BlockHeight,
result: @escaping(Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void
)
func blockStream(
startHeight: BlockHeight,
endHeight: BlockHeight
) -> AsyncThrowingStream<ZcashCompactBlock, Error>
}
public protocol LightWalletService: LightWalletServiceNonBlockingAPI, LightWalletServiceBlockingAPI {
func closeConnection()
}

View File

@ -22,11 +22,15 @@
//
import GRPC
import NIO
import NIOConcurrencyHelpers
import SwiftProtobuf
/// Usage: instantiate CompactTxStreamerClient, then call methods of this protocol to make API calls.
/// Usage: instantiate `CompactTxStreamerClient`, then call methods of this protocol to make API calls.
internal protocol CompactTxStreamerClientProtocol: GRPCClient {
var serviceName: String { get }
var interceptors: CompactTxStreamerClientInterceptorFactoryProtocol? { get }
func getLatestBlock(
_ request: ChainSpec,
callOptions: CallOptions?
@ -99,10 +103,12 @@ internal protocol CompactTxStreamerClientProtocol: GRPCClient {
_ request: Duration,
callOptions: CallOptions?
) -> UnaryCall<Duration, PingResponse>
}
extension CompactTxStreamerClientProtocol {
internal var serviceName: String {
return "cash.z.wallet.sdk.rpc.CompactTxStreamer"
}
/// Return the height of the tip of the best chain
///
@ -115,9 +121,10 @@ extension CompactTxStreamerClientProtocol {
callOptions: CallOptions? = nil
) -> UnaryCall<ChainSpec, BlockID> {
return self.makeUnaryCall(
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestBlock",
path: CompactTxStreamerClientMetadata.Methods.getLatestBlock.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetLatestBlockInterceptors() ?? []
)
}
@ -132,9 +139,10 @@ extension CompactTxStreamerClientProtocol {
callOptions: CallOptions? = nil
) -> UnaryCall<BlockID, CompactBlock> {
return self.makeUnaryCall(
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlock",
path: CompactTxStreamerClientMetadata.Methods.getBlock.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetBlockInterceptors() ?? []
)
}
@ -151,9 +159,10 @@ extension CompactTxStreamerClientProtocol {
handler: @escaping (CompactBlock) -> Void
) -> ServerStreamingCall<BlockRange, CompactBlock> {
return self.makeServerStreamingCall(
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockRange",
path: CompactTxStreamerClientMetadata.Methods.getBlockRange.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetBlockRangeInterceptors() ?? [],
handler: handler
)
}
@ -169,9 +178,10 @@ extension CompactTxStreamerClientProtocol {
callOptions: CallOptions? = nil
) -> UnaryCall<TxFilter, RawTransaction> {
return self.makeUnaryCall(
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTransaction",
path: CompactTxStreamerClientMetadata.Methods.getTransaction.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTransactionInterceptors() ?? []
)
}
@ -186,9 +196,10 @@ extension CompactTxStreamerClientProtocol {
callOptions: CallOptions? = nil
) -> UnaryCall<RawTransaction, SendResponse> {
return self.makeUnaryCall(
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/SendTransaction",
path: CompactTxStreamerClientMetadata.Methods.sendTransaction.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeSendTransactionInterceptors() ?? []
)
}
@ -205,9 +216,10 @@ extension CompactTxStreamerClientProtocol {
handler: @escaping (RawTransaction) -> Void
) -> ServerStreamingCall<TransparentAddressBlockFilter, RawTransaction> {
return self.makeServerStreamingCall(
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressTxids",
path: CompactTxStreamerClientMetadata.Methods.getTaddressTxids.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTaddressTxidsInterceptors() ?? [],
handler: handler
)
}
@ -223,9 +235,10 @@ extension CompactTxStreamerClientProtocol {
callOptions: CallOptions? = nil
) -> UnaryCall<AddressList, Balance> {
return self.makeUnaryCall(
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalance",
path: CompactTxStreamerClientMetadata.Methods.getTaddressBalance.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTaddressBalanceInterceptors() ?? []
)
}
@ -241,8 +254,9 @@ extension CompactTxStreamerClientProtocol {
callOptions: CallOptions? = nil
) -> ClientStreamingCall<Address, Balance> {
return self.makeClientStreamingCall(
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalanceStream",
callOptions: callOptions ?? self.defaultCallOptions
path: CompactTxStreamerClientMetadata.Methods.getTaddressBalanceStream.path,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTaddressBalanceStreamInterceptors() ?? []
)
}
@ -267,9 +281,10 @@ extension CompactTxStreamerClientProtocol {
handler: @escaping (CompactTx) -> Void
) -> ServerStreamingCall<Exclude, CompactTx> {
return self.makeServerStreamingCall(
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetMempoolTx",
path: CompactTxStreamerClientMetadata.Methods.getMempoolTx.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetMempoolTxInterceptors() ?? [],
handler: handler
)
}
@ -288,9 +303,10 @@ extension CompactTxStreamerClientProtocol {
callOptions: CallOptions? = nil
) -> UnaryCall<BlockID, TreeState> {
return self.makeUnaryCall(
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTreeState",
path: CompactTxStreamerClientMetadata.Methods.getTreeState.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTreeStateInterceptors() ?? []
)
}
@ -305,9 +321,10 @@ extension CompactTxStreamerClientProtocol {
callOptions: CallOptions? = nil
) -> UnaryCall<GetAddressUtxosArg, GetAddressUtxosReplyList> {
return self.makeUnaryCall(
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxos",
path: CompactTxStreamerClientMetadata.Methods.getAddressUtxos.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetAddressUtxosInterceptors() ?? []
)
}
@ -324,9 +341,10 @@ extension CompactTxStreamerClientProtocol {
handler: @escaping (GetAddressUtxosReply) -> Void
) -> ServerStreamingCall<GetAddressUtxosArg, GetAddressUtxosReply> {
return self.makeServerStreamingCall(
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxosStream",
path: CompactTxStreamerClientMetadata.Methods.getAddressUtxosStream.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetAddressUtxosStreamInterceptors() ?? [],
handler: handler
)
}
@ -342,9 +360,10 @@ extension CompactTxStreamerClientProtocol {
callOptions: CallOptions? = nil
) -> UnaryCall<Empty, LightdInfo> {
return self.makeUnaryCall(
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLightdInfo",
path: CompactTxStreamerClientMetadata.Methods.getLightdInfo.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetLightdInfoInterceptors() ?? []
)
}
@ -359,25 +378,679 @@ extension CompactTxStreamerClientProtocol {
callOptions: CallOptions? = nil
) -> UnaryCall<Duration, PingResponse> {
return self.makeUnaryCall(
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/Ping",
path: CompactTxStreamerClientMetadata.Methods.ping.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makePingInterceptors() ?? []
)
}
}
#if compiler(>=5.6)
@available(*, deprecated)
extension CompactTxStreamerClient: @unchecked Sendable {}
#endif // compiler(>=5.6)
@available(*, deprecated, renamed: "CompactTxStreamerNIOClient")
internal final class CompactTxStreamerClient: CompactTxStreamerClientProtocol {
private let lock = Lock()
private var _defaultCallOptions: CallOptions
private var _interceptors: CompactTxStreamerClientInterceptorFactoryProtocol?
internal let channel: GRPCChannel
internal var defaultCallOptions: CallOptions
internal var defaultCallOptions: CallOptions {
get { self.lock.withLock { return self._defaultCallOptions } }
set { self.lock.withLockVoid { self._defaultCallOptions = newValue } }
}
internal var interceptors: CompactTxStreamerClientInterceptorFactoryProtocol? {
get { self.lock.withLock { return self._interceptors } }
set { self.lock.withLockVoid { self._interceptors = newValue } }
}
/// Creates a client for the cash.z.wallet.sdk.rpc.CompactTxStreamer service.
///
/// - Parameters:
/// - channel: `GRPCChannel` to the service host.
/// - defaultCallOptions: Options to use for each service call if the user doesn't provide them.
internal init(channel: GRPCChannel, defaultCallOptions: CallOptions = CallOptions()) {
/// - interceptors: A factory providing interceptors for each RPC.
internal init(
channel: GRPCChannel,
defaultCallOptions: CallOptions = CallOptions(),
interceptors: CompactTxStreamerClientInterceptorFactoryProtocol? = nil
) {
self.channel = channel
self.defaultCallOptions = defaultCallOptions
self._defaultCallOptions = defaultCallOptions
self._interceptors = interceptors
}
}
internal struct CompactTxStreamerNIOClient: CompactTxStreamerClientProtocol {
internal var channel: GRPCChannel
internal var defaultCallOptions: CallOptions
internal var interceptors: CompactTxStreamerClientInterceptorFactoryProtocol?
/// Creates a client for the cash.z.wallet.sdk.rpc.CompactTxStreamer service.
///
/// - Parameters:
/// - channel: `GRPCChannel` to the service host.
/// - defaultCallOptions: Options to use for each service call if the user doesn't provide them.
/// - interceptors: A factory providing interceptors for each RPC.
internal init(
channel: GRPCChannel,
defaultCallOptions: CallOptions = CallOptions(),
interceptors: CompactTxStreamerClientInterceptorFactoryProtocol? = nil
) {
self.channel = channel
self.defaultCallOptions = defaultCallOptions
self.interceptors = interceptors
}
}
#if compiler(>=5.6)
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
internal protocol CompactTxStreamerAsyncClientProtocol: GRPCClient {
static var serviceDescriptor: GRPCServiceDescriptor { get }
var interceptors: CompactTxStreamerClientInterceptorFactoryProtocol? { get }
func makeGetLatestBlockCall(
_ request: ChainSpec,
callOptions: CallOptions?
) -> GRPCAsyncUnaryCall<ChainSpec, BlockID>
func makeGetBlockCall(
_ request: BlockID,
callOptions: CallOptions?
) -> GRPCAsyncUnaryCall<BlockID, CompactBlock>
func makeGetBlockRangeCall(
_ request: BlockRange,
callOptions: CallOptions?
) -> GRPCAsyncServerStreamingCall<BlockRange, CompactBlock>
func makeGetTransactionCall(
_ request: TxFilter,
callOptions: CallOptions?
) -> GRPCAsyncUnaryCall<TxFilter, RawTransaction>
func makeSendTransactionCall(
_ request: RawTransaction,
callOptions: CallOptions?
) -> GRPCAsyncUnaryCall<RawTransaction, SendResponse>
func makeGetTaddressTxidsCall(
_ request: TransparentAddressBlockFilter,
callOptions: CallOptions?
) -> GRPCAsyncServerStreamingCall<TransparentAddressBlockFilter, RawTransaction>
func makeGetTaddressBalanceCall(
_ request: AddressList,
callOptions: CallOptions?
) -> GRPCAsyncUnaryCall<AddressList, Balance>
func makeGetTaddressBalanceStreamCall(
callOptions: CallOptions?
) -> GRPCAsyncClientStreamingCall<Address, Balance>
func makeGetMempoolTxCall(
_ request: Exclude,
callOptions: CallOptions?
) -> GRPCAsyncServerStreamingCall<Exclude, CompactTx>
func makeGetTreeStateCall(
_ request: BlockID,
callOptions: CallOptions?
) -> GRPCAsyncUnaryCall<BlockID, TreeState>
func makeGetAddressUtxosCall(
_ request: GetAddressUtxosArg,
callOptions: CallOptions?
) -> GRPCAsyncUnaryCall<GetAddressUtxosArg, GetAddressUtxosReplyList>
func makeGetAddressUtxosStreamCall(
_ request: GetAddressUtxosArg,
callOptions: CallOptions?
) -> GRPCAsyncServerStreamingCall<GetAddressUtxosArg, GetAddressUtxosReply>
func makeGetLightdInfoCall(
_ request: Empty,
callOptions: CallOptions?
) -> GRPCAsyncUnaryCall<Empty, LightdInfo>
func makePingCall(
_ request: Duration,
callOptions: CallOptions?
) -> GRPCAsyncUnaryCall<Duration, PingResponse>
}
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
extension CompactTxStreamerAsyncClientProtocol {
internal static var serviceDescriptor: GRPCServiceDescriptor {
return CompactTxStreamerClientMetadata.serviceDescriptor
}
internal var interceptors: CompactTxStreamerClientInterceptorFactoryProtocol? {
return nil
}
internal func makeGetLatestBlockCall(
_ request: ChainSpec,
callOptions: CallOptions? = nil
) -> GRPCAsyncUnaryCall<ChainSpec, BlockID> {
return self.makeAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.getLatestBlock.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetLatestBlockInterceptors() ?? []
)
}
internal func makeGetBlockCall(
_ request: BlockID,
callOptions: CallOptions? = nil
) -> GRPCAsyncUnaryCall<BlockID, CompactBlock> {
return self.makeAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.getBlock.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetBlockInterceptors() ?? []
)
}
internal func makeGetBlockRangeCall(
_ request: BlockRange,
callOptions: CallOptions? = nil
) -> GRPCAsyncServerStreamingCall<BlockRange, CompactBlock> {
return self.makeAsyncServerStreamingCall(
path: CompactTxStreamerClientMetadata.Methods.getBlockRange.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetBlockRangeInterceptors() ?? []
)
}
internal func makeGetTransactionCall(
_ request: TxFilter,
callOptions: CallOptions? = nil
) -> GRPCAsyncUnaryCall<TxFilter, RawTransaction> {
return self.makeAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.getTransaction.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTransactionInterceptors() ?? []
)
}
internal func makeSendTransactionCall(
_ request: RawTransaction,
callOptions: CallOptions? = nil
) -> GRPCAsyncUnaryCall<RawTransaction, SendResponse> {
return self.makeAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.sendTransaction.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeSendTransactionInterceptors() ?? []
)
}
internal func makeGetTaddressTxidsCall(
_ request: TransparentAddressBlockFilter,
callOptions: CallOptions? = nil
) -> GRPCAsyncServerStreamingCall<TransparentAddressBlockFilter, RawTransaction> {
return self.makeAsyncServerStreamingCall(
path: CompactTxStreamerClientMetadata.Methods.getTaddressTxids.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTaddressTxidsInterceptors() ?? []
)
}
internal func makeGetTaddressBalanceCall(
_ request: AddressList,
callOptions: CallOptions? = nil
) -> GRPCAsyncUnaryCall<AddressList, Balance> {
return self.makeAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.getTaddressBalance.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTaddressBalanceInterceptors() ?? []
)
}
internal func makeGetTaddressBalanceStreamCall(
callOptions: CallOptions? = nil
) -> GRPCAsyncClientStreamingCall<Address, Balance> {
return self.makeAsyncClientStreamingCall(
path: CompactTxStreamerClientMetadata.Methods.getTaddressBalanceStream.path,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTaddressBalanceStreamInterceptors() ?? []
)
}
internal func makeGetMempoolTxCall(
_ request: Exclude,
callOptions: CallOptions? = nil
) -> GRPCAsyncServerStreamingCall<Exclude, CompactTx> {
return self.makeAsyncServerStreamingCall(
path: CompactTxStreamerClientMetadata.Methods.getMempoolTx.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetMempoolTxInterceptors() ?? []
)
}
internal func makeGetTreeStateCall(
_ request: BlockID,
callOptions: CallOptions? = nil
) -> GRPCAsyncUnaryCall<BlockID, TreeState> {
return self.makeAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.getTreeState.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTreeStateInterceptors() ?? []
)
}
internal func makeGetAddressUtxosCall(
_ request: GetAddressUtxosArg,
callOptions: CallOptions? = nil
) -> GRPCAsyncUnaryCall<GetAddressUtxosArg, GetAddressUtxosReplyList> {
return self.makeAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.getAddressUtxos.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetAddressUtxosInterceptors() ?? []
)
}
internal func makeGetAddressUtxosStreamCall(
_ request: GetAddressUtxosArg,
callOptions: CallOptions? = nil
) -> GRPCAsyncServerStreamingCall<GetAddressUtxosArg, GetAddressUtxosReply> {
return self.makeAsyncServerStreamingCall(
path: CompactTxStreamerClientMetadata.Methods.getAddressUtxosStream.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetAddressUtxosStreamInterceptors() ?? []
)
}
internal func makeGetLightdInfoCall(
_ request: Empty,
callOptions: CallOptions? = nil
) -> GRPCAsyncUnaryCall<Empty, LightdInfo> {
return self.makeAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.getLightdInfo.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetLightdInfoInterceptors() ?? []
)
}
internal func makePingCall(
_ request: Duration,
callOptions: CallOptions? = nil
) -> GRPCAsyncUnaryCall<Duration, PingResponse> {
return self.makeAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.ping.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makePingInterceptors() ?? []
)
}
}
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
extension CompactTxStreamerAsyncClientProtocol {
internal func getLatestBlock(
_ request: ChainSpec,
callOptions: CallOptions? = nil
) async throws -> BlockID {
return try await self.performAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.getLatestBlock.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetLatestBlockInterceptors() ?? []
)
}
internal func getBlock(
_ request: BlockID,
callOptions: CallOptions? = nil
) async throws -> CompactBlock {
return try await self.performAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.getBlock.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetBlockInterceptors() ?? []
)
}
internal func getBlockRange(
_ request: BlockRange,
callOptions: CallOptions? = nil
) -> GRPCAsyncResponseStream<CompactBlock> {
return self.performAsyncServerStreamingCall(
path: CompactTxStreamerClientMetadata.Methods.getBlockRange.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetBlockRangeInterceptors() ?? []
)
}
internal func getTransaction(
_ request: TxFilter,
callOptions: CallOptions? = nil
) async throws -> RawTransaction {
return try await self.performAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.getTransaction.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTransactionInterceptors() ?? []
)
}
internal func sendTransaction(
_ request: RawTransaction,
callOptions: CallOptions? = nil
) async throws -> SendResponse {
return try await self.performAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.sendTransaction.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeSendTransactionInterceptors() ?? []
)
}
internal func getTaddressTxids(
_ request: TransparentAddressBlockFilter,
callOptions: CallOptions? = nil
) -> GRPCAsyncResponseStream<RawTransaction> {
return self.performAsyncServerStreamingCall(
path: CompactTxStreamerClientMetadata.Methods.getTaddressTxids.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTaddressTxidsInterceptors() ?? []
)
}
internal func getTaddressBalance(
_ request: AddressList,
callOptions: CallOptions? = nil
) async throws -> Balance {
return try await self.performAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.getTaddressBalance.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTaddressBalanceInterceptors() ?? []
)
}
internal func getTaddressBalanceStream<RequestStream>(
_ requests: RequestStream,
callOptions: CallOptions? = nil
) async throws -> Balance where RequestStream: Sequence, RequestStream.Element == Address {
return try await self.performAsyncClientStreamingCall(
path: CompactTxStreamerClientMetadata.Methods.getTaddressBalanceStream.path,
requests: requests,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTaddressBalanceStreamInterceptors() ?? []
)
}
internal func getTaddressBalanceStream<RequestStream>(
_ requests: RequestStream,
callOptions: CallOptions? = nil
) async throws -> Balance where RequestStream: AsyncSequence & Sendable, RequestStream.Element == Address {
return try await self.performAsyncClientStreamingCall(
path: CompactTxStreamerClientMetadata.Methods.getTaddressBalanceStream.path,
requests: requests,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTaddressBalanceStreamInterceptors() ?? []
)
}
internal func getMempoolTx(
_ request: Exclude,
callOptions: CallOptions? = nil
) -> GRPCAsyncResponseStream<CompactTx> {
return self.performAsyncServerStreamingCall(
path: CompactTxStreamerClientMetadata.Methods.getMempoolTx.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetMempoolTxInterceptors() ?? []
)
}
internal func getTreeState(
_ request: BlockID,
callOptions: CallOptions? = nil
) async throws -> TreeState {
return try await self.performAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.getTreeState.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetTreeStateInterceptors() ?? []
)
}
internal func getAddressUtxos(
_ request: GetAddressUtxosArg,
callOptions: CallOptions? = nil
) async throws -> GetAddressUtxosReplyList {
return try await self.performAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.getAddressUtxos.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetAddressUtxosInterceptors() ?? []
)
}
internal func getAddressUtxosStream(
_ request: GetAddressUtxosArg,
callOptions: CallOptions? = nil
) -> GRPCAsyncResponseStream<GetAddressUtxosReply> {
return self.performAsyncServerStreamingCall(
path: CompactTxStreamerClientMetadata.Methods.getAddressUtxosStream.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetAddressUtxosStreamInterceptors() ?? []
)
}
internal func getLightdInfo(
_ request: Empty,
callOptions: CallOptions? = nil
) async throws -> LightdInfo {
return try await self.performAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.getLightdInfo.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makeGetLightdInfoInterceptors() ?? []
)
}
internal func ping(
_ request: Duration,
callOptions: CallOptions? = nil
) async throws -> PingResponse {
return try await self.performAsyncUnaryCall(
path: CompactTxStreamerClientMetadata.Methods.ping.path,
request: request,
callOptions: callOptions ?? self.defaultCallOptions,
interceptors: self.interceptors?.makePingInterceptors() ?? []
)
}
}
@available(macOS 10.15, iOS 13, tvOS 13, watchOS 6, *)
internal struct CompactTxStreamerAsyncClient: CompactTxStreamerAsyncClientProtocol {
internal var channel: GRPCChannel
internal var defaultCallOptions: CallOptions
internal var interceptors: CompactTxStreamerClientInterceptorFactoryProtocol?
internal init(
channel: GRPCChannel,
defaultCallOptions: CallOptions = CallOptions(),
interceptors: CompactTxStreamerClientInterceptorFactoryProtocol? = nil
) {
self.channel = channel
self.defaultCallOptions = defaultCallOptions
self.interceptors = interceptors
}
}
#endif // compiler(>=5.6)
internal protocol CompactTxStreamerClientInterceptorFactoryProtocol: GRPCSendable {
/// - Returns: Interceptors to use when invoking 'getLatestBlock'.
func makeGetLatestBlockInterceptors() -> [ClientInterceptor<ChainSpec, BlockID>]
/// - Returns: Interceptors to use when invoking 'getBlock'.
func makeGetBlockInterceptors() -> [ClientInterceptor<BlockID, CompactBlock>]
/// - Returns: Interceptors to use when invoking 'getBlockRange'.
func makeGetBlockRangeInterceptors() -> [ClientInterceptor<BlockRange, CompactBlock>]
/// - Returns: Interceptors to use when invoking 'getTransaction'.
func makeGetTransactionInterceptors() -> [ClientInterceptor<TxFilter, RawTransaction>]
/// - Returns: Interceptors to use when invoking 'sendTransaction'.
func makeSendTransactionInterceptors() -> [ClientInterceptor<RawTransaction, SendResponse>]
/// - Returns: Interceptors to use when invoking 'getTaddressTxids'.
func makeGetTaddressTxidsInterceptors() -> [ClientInterceptor<TransparentAddressBlockFilter, RawTransaction>]
/// - Returns: Interceptors to use when invoking 'getTaddressBalance'.
func makeGetTaddressBalanceInterceptors() -> [ClientInterceptor<AddressList, Balance>]
/// - Returns: Interceptors to use when invoking 'getTaddressBalanceStream'.
func makeGetTaddressBalanceStreamInterceptors() -> [ClientInterceptor<Address, Balance>]
/// - Returns: Interceptors to use when invoking 'getMempoolTx'.
func makeGetMempoolTxInterceptors() -> [ClientInterceptor<Exclude, CompactTx>]
/// - Returns: Interceptors to use when invoking 'getTreeState'.
func makeGetTreeStateInterceptors() -> [ClientInterceptor<BlockID, TreeState>]
/// - Returns: Interceptors to use when invoking 'getAddressUtxos'.
func makeGetAddressUtxosInterceptors() -> [ClientInterceptor<GetAddressUtxosArg, GetAddressUtxosReplyList>]
/// - Returns: Interceptors to use when invoking 'getAddressUtxosStream'.
func makeGetAddressUtxosStreamInterceptors() -> [ClientInterceptor<GetAddressUtxosArg, GetAddressUtxosReply>]
/// - Returns: Interceptors to use when invoking 'getLightdInfo'.
func makeGetLightdInfoInterceptors() -> [ClientInterceptor<Empty, LightdInfo>]
/// - Returns: Interceptors to use when invoking 'ping'.
func makePingInterceptors() -> [ClientInterceptor<Duration, PingResponse>]
}
internal enum CompactTxStreamerClientMetadata {
internal static let serviceDescriptor = GRPCServiceDescriptor(
name: "CompactTxStreamer",
fullName: "cash.z.wallet.sdk.rpc.CompactTxStreamer",
methods: [
CompactTxStreamerClientMetadata.Methods.getLatestBlock,
CompactTxStreamerClientMetadata.Methods.getBlock,
CompactTxStreamerClientMetadata.Methods.getBlockRange,
CompactTxStreamerClientMetadata.Methods.getTransaction,
CompactTxStreamerClientMetadata.Methods.sendTransaction,
CompactTxStreamerClientMetadata.Methods.getTaddressTxids,
CompactTxStreamerClientMetadata.Methods.getTaddressBalance,
CompactTxStreamerClientMetadata.Methods.getTaddressBalanceStream,
CompactTxStreamerClientMetadata.Methods.getMempoolTx,
CompactTxStreamerClientMetadata.Methods.getTreeState,
CompactTxStreamerClientMetadata.Methods.getAddressUtxos,
CompactTxStreamerClientMetadata.Methods.getAddressUtxosStream,
CompactTxStreamerClientMetadata.Methods.getLightdInfo,
CompactTxStreamerClientMetadata.Methods.ping,
]
)
internal enum Methods {
internal static let getLatestBlock = GRPCMethodDescriptor(
name: "GetLatestBlock",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLatestBlock",
type: GRPCCallType.unary
)
internal static let getBlock = GRPCMethodDescriptor(
name: "GetBlock",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlock",
type: GRPCCallType.unary
)
internal static let getBlockRange = GRPCMethodDescriptor(
name: "GetBlockRange",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetBlockRange",
type: GRPCCallType.serverStreaming
)
internal static let getTransaction = GRPCMethodDescriptor(
name: "GetTransaction",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTransaction",
type: GRPCCallType.unary
)
internal static let sendTransaction = GRPCMethodDescriptor(
name: "SendTransaction",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/SendTransaction",
type: GRPCCallType.unary
)
internal static let getTaddressTxids = GRPCMethodDescriptor(
name: "GetTaddressTxids",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressTxids",
type: GRPCCallType.serverStreaming
)
internal static let getTaddressBalance = GRPCMethodDescriptor(
name: "GetTaddressBalance",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalance",
type: GRPCCallType.unary
)
internal static let getTaddressBalanceStream = GRPCMethodDescriptor(
name: "GetTaddressBalanceStream",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTaddressBalanceStream",
type: GRPCCallType.clientStreaming
)
internal static let getMempoolTx = GRPCMethodDescriptor(
name: "GetMempoolTx",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetMempoolTx",
type: GRPCCallType.serverStreaming
)
internal static let getTreeState = GRPCMethodDescriptor(
name: "GetTreeState",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetTreeState",
type: GRPCCallType.unary
)
internal static let getAddressUtxos = GRPCMethodDescriptor(
name: "GetAddressUtxos",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxos",
type: GRPCCallType.unary
)
internal static let getAddressUtxosStream = GRPCMethodDescriptor(
name: "GetAddressUtxosStream",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetAddressUtxosStream",
type: GRPCCallType.serverStreaming
)
internal static let getLightdInfo = GRPCMethodDescriptor(
name: "GetLightdInfo",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/GetLightdInfo",
type: GRPCCallType.unary
)
internal static let ping = GRPCMethodDescriptor(
name: "Ping",
path: "/cash.z.wallet.sdk.rpc.CompactTxStreamer/Ping",
type: GRPCCallType.unary
)
}
}

View File

@ -33,7 +33,7 @@ struct BlockID {
var height: UInt64 = 0
var hash: Data = SwiftProtobuf.Internal.emptyData
var hash: Data = Data()
var unknownFields = SwiftProtobuf.UnknownStorage()
@ -95,7 +95,7 @@ struct TxFilter {
var index: UInt64 = 0
/// transaction ID (hash, txid)
var hash: Data = SwiftProtobuf.Internal.emptyData
var hash: Data = Data()
var unknownFields = SwiftProtobuf.UnknownStorage()
@ -112,7 +112,7 @@ struct RawTransaction {
// methods supported on all messages.
/// exact data returned by Zcash 'getrawtransaction'
var data: Data = SwiftProtobuf.Internal.emptyData
var data: Data = Data()
/// height that the transaction was mined (or -1)
var height: UInt64 = 0
@ -367,11 +367,11 @@ struct GetAddressUtxosReply {
var address: String = String()
var txid: Data = SwiftProtobuf.Internal.emptyData
var txid: Data = Data()
var index: Int32 = 0
var script: Data = SwiftProtobuf.Internal.emptyData
var script: Data = Data()
var valueZat: Int64 = 0
@ -394,6 +394,28 @@ struct GetAddressUtxosReplyList {
init() {}
}
#if swift(>=5.5) && canImport(_Concurrency)
extension BlockID: @unchecked Sendable {}
extension BlockRange: @unchecked Sendable {}
extension TxFilter: @unchecked Sendable {}
extension RawTransaction: @unchecked Sendable {}
extension SendResponse: @unchecked Sendable {}
extension ChainSpec: @unchecked Sendable {}
extension Empty: @unchecked Sendable {}
extension LightdInfo: @unchecked Sendable {}
extension TransparentAddressBlockFilter: @unchecked Sendable {}
extension Duration: @unchecked Sendable {}
extension PingResponse: @unchecked Sendable {}
extension Address: @unchecked Sendable {}
extension AddressList: @unchecked Sendable {}
extension Balance: @unchecked Sendable {}
extension Exclude: @unchecked Sendable {}
extension TreeState: @unchecked Sendable {}
extension GetAddressUtxosArg: @unchecked Sendable {}
extension GetAddressUtxosReply: @unchecked Sendable {}
extension GetAddressUtxosReplyList: @unchecked Sendable {}
#endif // swift(>=5.5) && canImport(_Concurrency)
// MARK: - Code below here is support for the SwiftProtobuf runtime.
fileprivate let _protobuf_package = "cash.z.wallet.sdk.rpc"
@ -407,9 +429,12 @@ extension BlockID: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBa
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeSingularUInt64Field(value: &self.height)
case 2: try decoder.decodeSingularBytesField(value: &self.hash)
case 1: try { try decoder.decodeSingularUInt64Field(value: &self.height) }()
case 2: try { try decoder.decodeSingularBytesField(value: &self.hash) }()
default: break
}
}
@ -442,21 +467,28 @@ extension BlockRange: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeSingularMessageField(value: &self._start)
case 2: try decoder.decodeSingularMessageField(value: &self._end)
case 1: try { try decoder.decodeSingularMessageField(value: &self._start) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._end) }()
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if let v = self._start {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every if/case branch local when no optimizations
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
// https://github.com/apple/swift-protobuf/issues/1182
try { if let v = self._start {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
}
if let v = self._end {
} }()
try { if let v = self._end {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
}
} }()
try unknownFields.traverse(visitor: &visitor)
}
@ -478,19 +510,26 @@ extension TxFilter: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeSingularMessageField(value: &self._block)
case 2: try decoder.decodeSingularUInt64Field(value: &self.index)
case 3: try decoder.decodeSingularBytesField(value: &self.hash)
case 1: try { try decoder.decodeSingularMessageField(value: &self._block) }()
case 2: try { try decoder.decodeSingularUInt64Field(value: &self.index) }()
case 3: try { try decoder.decodeSingularBytesField(value: &self.hash) }()
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
if let v = self._block {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every if/case branch local when no optimizations
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
// https://github.com/apple/swift-protobuf/issues/1182
try { if let v = self._block {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
}
} }()
if self.index != 0 {
try visitor.visitSingularUInt64Field(value: self.index, fieldNumber: 2)
}
@ -518,9 +557,12 @@ extension RawTransaction: SwiftProtobuf.Message, SwiftProtobuf._MessageImplement
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeSingularBytesField(value: &self.data)
case 2: try decoder.decodeSingularUInt64Field(value: &self.height)
case 1: try { try decoder.decodeSingularBytesField(value: &self.data) }()
case 2: try { try decoder.decodeSingularUInt64Field(value: &self.height) }()
default: break
}
}
@ -553,9 +595,12 @@ extension SendResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeSingularInt32Field(value: &self.errorCode)
case 2: try decoder.decodeSingularStringField(value: &self.errorMessage)
case 1: try { try decoder.decodeSingularInt32Field(value: &self.errorCode) }()
case 2: try { try decoder.decodeSingularStringField(value: &self.errorMessage) }()
default: break
}
}
@ -638,21 +683,24 @@ extension LightdInfo: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementatio
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeSingularStringField(value: &self.version)
case 2: try decoder.decodeSingularStringField(value: &self.vendor)
case 3: try decoder.decodeSingularBoolField(value: &self.taddrSupport)
case 4: try decoder.decodeSingularStringField(value: &self.chainName)
case 5: try decoder.decodeSingularUInt64Field(value: &self.saplingActivationHeight)
case 6: try decoder.decodeSingularStringField(value: &self.consensusBranchID)
case 7: try decoder.decodeSingularUInt64Field(value: &self.blockHeight)
case 8: try decoder.decodeSingularStringField(value: &self.gitCommit)
case 9: try decoder.decodeSingularStringField(value: &self.branch)
case 10: try decoder.decodeSingularStringField(value: &self.buildDate)
case 11: try decoder.decodeSingularStringField(value: &self.buildUser)
case 12: try decoder.decodeSingularUInt64Field(value: &self.estimatedHeight)
case 13: try decoder.decodeSingularStringField(value: &self.zcashdBuild)
case 14: try decoder.decodeSingularStringField(value: &self.zcashdSubversion)
case 1: try { try decoder.decodeSingularStringField(value: &self.version) }()
case 2: try { try decoder.decodeSingularStringField(value: &self.vendor) }()
case 3: try { try decoder.decodeSingularBoolField(value: &self.taddrSupport) }()
case 4: try { try decoder.decodeSingularStringField(value: &self.chainName) }()
case 5: try { try decoder.decodeSingularUInt64Field(value: &self.saplingActivationHeight) }()
case 6: try { try decoder.decodeSingularStringField(value: &self.consensusBranchID) }()
case 7: try { try decoder.decodeSingularUInt64Field(value: &self.blockHeight) }()
case 8: try { try decoder.decodeSingularStringField(value: &self.gitCommit) }()
case 9: try { try decoder.decodeSingularStringField(value: &self.branch) }()
case 10: try { try decoder.decodeSingularStringField(value: &self.buildDate) }()
case 11: try { try decoder.decodeSingularStringField(value: &self.buildUser) }()
case 12: try { try decoder.decodeSingularUInt64Field(value: &self.estimatedHeight) }()
case 13: try { try decoder.decodeSingularStringField(value: &self.zcashdBuild) }()
case 14: try { try decoder.decodeSingularStringField(value: &self.zcashdSubversion) }()
default: break
}
}
@ -733,21 +781,28 @@ extension TransparentAddressBlockFilter: SwiftProtobuf.Message, SwiftProtobuf._M
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeSingularStringField(value: &self.address)
case 2: try decoder.decodeSingularMessageField(value: &self._range)
case 1: try { try decoder.decodeSingularStringField(value: &self.address) }()
case 2: try { try decoder.decodeSingularMessageField(value: &self._range) }()
default: break
}
}
}
func traverse<V: SwiftProtobuf.Visitor>(visitor: inout V) throws {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every if/case branch local when no optimizations
// are enabled. https://github.com/apple/swift-protobuf/issues/1034 and
// https://github.com/apple/swift-protobuf/issues/1182
if !self.address.isEmpty {
try visitor.visitSingularStringField(value: self.address, fieldNumber: 1)
}
if let v = self._range {
try { if let v = self._range {
try visitor.visitSingularMessageField(value: v, fieldNumber: 2)
}
} }()
try unknownFields.traverse(visitor: &visitor)
}
@ -767,8 +822,11 @@ extension Duration: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationB
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeSingularInt64Field(value: &self.intervalUs)
case 1: try { try decoder.decodeSingularInt64Field(value: &self.intervalUs) }()
default: break
}
}
@ -797,9 +855,12 @@ extension PingResponse: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementat
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeSingularInt64Field(value: &self.entry)
case 2: try decoder.decodeSingularInt64Field(value: &self.exit)
case 1: try { try decoder.decodeSingularInt64Field(value: &self.entry) }()
case 2: try { try decoder.decodeSingularInt64Field(value: &self.exit) }()
default: break
}
}
@ -831,8 +892,11 @@ extension Address: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBa
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeSingularStringField(value: &self.address)
case 1: try { try decoder.decodeSingularStringField(value: &self.address) }()
default: break
}
}
@ -860,8 +924,11 @@ extension AddressList: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementati
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeRepeatedStringField(value: &self.addresses)
case 1: try { try decoder.decodeRepeatedStringField(value: &self.addresses) }()
default: break
}
}
@ -889,8 +956,11 @@ extension Balance: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBa
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeSingularInt64Field(value: &self.valueZat)
case 1: try { try decoder.decodeSingularInt64Field(value: &self.valueZat) }()
default: break
}
}
@ -918,8 +988,11 @@ extension Exclude: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBa
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeRepeatedBytesField(value: &self.txid)
case 1: try { try decoder.decodeRepeatedBytesField(value: &self.txid) }()
default: break
}
}
@ -951,12 +1024,15 @@ extension TreeState: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementation
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeSingularStringField(value: &self.network)
case 2: try decoder.decodeSingularUInt64Field(value: &self.height)
case 3: try decoder.decodeSingularStringField(value: &self.hash)
case 4: try decoder.decodeSingularUInt32Field(value: &self.time)
case 5: try decoder.decodeSingularStringField(value: &self.tree)
case 1: try { try decoder.decodeSingularStringField(value: &self.network) }()
case 2: try { try decoder.decodeSingularUInt64Field(value: &self.height) }()
case 3: try { try decoder.decodeSingularStringField(value: &self.hash) }()
case 4: try { try decoder.decodeSingularUInt32Field(value: &self.time) }()
case 5: try { try decoder.decodeSingularStringField(value: &self.tree) }()
default: break
}
}
@ -1002,10 +1078,13 @@ extension GetAddressUtxosArg: SwiftProtobuf.Message, SwiftProtobuf._MessageImple
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeRepeatedStringField(value: &self.addresses)
case 2: try decoder.decodeSingularUInt64Field(value: &self.startHeight)
case 3: try decoder.decodeSingularUInt32Field(value: &self.maxEntries)
case 1: try { try decoder.decodeRepeatedStringField(value: &self.addresses) }()
case 2: try { try decoder.decodeSingularUInt64Field(value: &self.startHeight) }()
case 3: try { try decoder.decodeSingularUInt32Field(value: &self.maxEntries) }()
default: break
}
}
@ -1046,13 +1125,16 @@ extension GetAddressUtxosReply: SwiftProtobuf.Message, SwiftProtobuf._MessageImp
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeSingularBytesField(value: &self.txid)
case 2: try decoder.decodeSingularInt32Field(value: &self.index)
case 3: try decoder.decodeSingularBytesField(value: &self.script)
case 4: try decoder.decodeSingularInt64Field(value: &self.valueZat)
case 5: try decoder.decodeSingularUInt64Field(value: &self.height)
case 6: try decoder.decodeSingularStringField(value: &self.address)
case 1: try { try decoder.decodeSingularBytesField(value: &self.txid) }()
case 2: try { try decoder.decodeSingularInt32Field(value: &self.index) }()
case 3: try { try decoder.decodeSingularBytesField(value: &self.script) }()
case 4: try { try decoder.decodeSingularInt64Field(value: &self.valueZat) }()
case 5: try { try decoder.decodeSingularUInt64Field(value: &self.height) }()
case 6: try { try decoder.decodeSingularStringField(value: &self.address) }()
default: break
}
}
@ -1100,8 +1182,11 @@ extension GetAddressUtxosReplyList: SwiftProtobuf.Message, SwiftProtobuf._Messag
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
while let fieldNumber = try decoder.nextFieldNumber() {
// The use of inline closures is to circumvent an issue where the compiler
// allocates stack space for every case branch when no optimizations are
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try decoder.decodeRepeatedMessageField(value: &self.addressUtxos)
case 1: try { try decoder.decodeRepeatedMessageField(value: &self.addressUtxos) }()
default: break
}
}

View File

@ -61,6 +61,21 @@ class LightWalletServiceTests: XCTestCase {
wait(for: [expect], timeout: 10)
}
func testHundredBlocks() async throws {
let count = 99
let lowerRange: BlockHeight = network.constants.saplingActivationHeight
let upperRange: BlockHeight = network.constants.saplingActivationHeight + count
let blockRange = lowerRange ... upperRange
var blocks: [ZcashCompactBlock] = []
for try await block in service.blockRange(blockRange) {
blocks.append(block)
}
XCTAssertEqual(blocks.count, blockRange.count)
XCTAssertEqual(blocks[0].height, lowerRange)
XCTAssertEqual(blocks.last!.height, upperRange)
}
func testSyncBlockRange() {
let lowerRange: BlockHeight = network.constants.saplingActivationHeight
let upperRange: BlockHeight = network.constants.saplingActivationHeight + 99
@ -74,6 +89,18 @@ class LightWalletServiceTests: XCTestCase {
}
}
func testSyncBlockRange() async throws {
let lowerRange: BlockHeight = network.constants.saplingActivationHeight
let upperRange: BlockHeight = network.constants.saplingActivationHeight + 99
let blockRange = lowerRange ... upperRange
var blocks: [ZcashCompactBlock] = []
for try await block in service.blockRange(blockRange) {
blocks.append(block)
}
XCTAssertEqual(blocks.count, blockRange.count)
}
func testLatestBlock() {
let expect = XCTestExpectation(description: self.description)
service.latestBlockHeight { result in
@ -88,4 +115,9 @@ class LightWalletServiceTests: XCTestCase {
wait(for: [expect], timeout: 10)
}
func testLatestBlock() async throws {
let height = try await service.latestBlockHeightAsync()
XCTAssertTrue(height > self.network.constants.saplingActivationHeight)
}
}

View File

@ -75,6 +75,10 @@ class DarksideWalletService: LightWalletService {
)
}
func blockStream(startHeight: BlockHeight, endHeight: BlockHeight) -> AsyncThrowingStream<ZcashCompactBlock, Error> {
service.blockStream(startHeight: startHeight, endHeight: endHeight)
}
func getInfo() throws -> LightWalletdInfo {
try service.getInfo()
}
@ -87,7 +91,11 @@ class DarksideWalletService: LightWalletService {
}
func fetchUTXOs(for tAddress: String, height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
return []
try service.fetchUTXOs(for: tAddress, height: height)
}
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
try service.fetchUTXOs(for: tAddresses, height: height)
}
func fetchUTXOs(
@ -98,8 +106,8 @@ class DarksideWalletService: LightWalletService {
service.fetchUTXOs(for: tAddress, height: height, result: result)
}
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
try service.fetchUTXOs(for: tAddresses, height: height)
func fetchUTXOs(for tAddress: String, height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
service.fetchUTXOs(for: tAddress, height: height)
}
func fetchUTXOs(
@ -109,7 +117,10 @@ class DarksideWalletService: LightWalletService {
) {
service.fetchUTXOs(for: tAddresses, height: height, result: result)
}
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
service.fetchUTXOs(for: tAddresses, height: height)
}
func fetchTransaction(txId: Data) throws -> TransactionEntity {
try service.fetchTransaction(txId: txId)
@ -222,6 +233,26 @@ class DarksideWalletService: LightWalletService {
func clearAddedUTXOs() throws {
_ = try darksideService.clearAddressUtxo(Empty(), callOptions: nil).response.wait()
}
func getInfoAsync() async throws -> LightWalletdInfo {
try service.getInfo()
}
func latestBlockHeightAsync() async throws -> BlockHeight {
try service.latestBlockHeight()
}
func blockRange(_ range: CompactBlockRange) -> AsyncThrowingStream<ZcashCompactBlock, Error> {
service.blockRange(range)
}
func submitAsync(spendTransaction: Data) async throws -> LightWalletServiceResponse {
try service.submit(spendTransaction: spendTransaction)
}
func fetchTransactionAsync(txId: Data) async throws -> TransactionEntity {
try service.fetchTransaction(txId: txId)
}
}
enum DarksideWalletDConstants: NetworkConstants {

View File

@ -35,6 +35,10 @@ class MockLightWalletService: LightWalletService {
return MockCancellable()
}
func blockStream(startHeight: BlockHeight, endHeight: BlockHeight) -> AsyncThrowingStream<ZcashCompactBlock, Error> {
AsyncThrowingStream { _ in }
}
func getInfo() throws -> LightWalletdInfo {
guard let info = mockLightDInfo else {
throw LightWalletServiceError.generalError(message: "Not Implemented")
@ -59,28 +63,30 @@ class MockLightWalletService: LightWalletService {
[]
}
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
[]
}
func fetchUTXOs(
for tAddress: String,
height: BlockHeight,
result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void
) {
}
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) throws -> [UnspentTransactionOutputEntity] {
[]
func fetchUTXOs(for tAddress: String, height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
AsyncThrowingStream { _ in }
}
func fetchUTXOs(
for tAddresses: [String],
height: BlockHeight,
result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void
) {
}
func fetchUTXOs(
for tAddress: String,
result: @escaping (Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void
) {
func fetchUTXOs(for tAddresses: [String], height: BlockHeight) -> AsyncThrowingStream<UnspentTransactionOutputEntity, Error> {
AsyncThrowingStream { _ in }
}
private var service: LightWalletService
@ -126,4 +132,35 @@ class MockLightWalletService: LightWalletService {
func fetchTransaction(txId: Data, result: @escaping (Result<TransactionEntity, LightWalletServiceError>) -> Void) {
}
func getInfoAsync() async throws -> LightWalletdInfo {
guard let info = mockLightDInfo else {
throw LightWalletServiceError.generalError(message: "Not Implemented")
}
return info
}
func latestBlockHeightAsync() async throws -> BlockHeight {
latestHeight
}
func blockRange(_ range: CompactBlockRange) -> AsyncThrowingStream<ZcashCompactBlock, Error> {
service.blockRange(range)
}
func submitAsync(spendTransaction: Data) async throws -> LightWalletServiceResponse {
LightWalletServiceMockResponse(errorCode: 0, errorMessage: "", unknownFields: UnknownStorage())
}
func fetchTransactionAsync(txId: Data) async throws -> TransactionEntity {
Transaction(id: 1, transactionId: Data(), created: "Today", transactionIndex: 1, expiryHeight: -1, minedHeight: -1, raw: nil)
}
func fetchUTXOsAsync(for tAddress: String, height: BlockHeight) async throws -> [UnspentTransactionOutputEntity] {
[]
}
func fetchUTXOsAsync(for tAddresses: [String], height: BlockHeight) async throws -> [UnspentTransactionOutputEntity] {
[]
}
}