Closes #381 This commit brings a Zatoshi type developed on the Secant project, helper classes like Clamped and tests. Zatoshi has been incorporated as a Codable type for SQLite Swift to allow serialization into the pending database. FIXES on Demo App fix comments
This commit is contained in:
parent
516d605d22
commit
b9ae012e09
|
@ -6,8 +6,8 @@
|
|||
"repositoryURL": "https://github.com/grpc/grpc-swift.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "5cc08ebf77e68598bfe4c793927d0f2838598607",
|
||||
"version": "1.6.1"
|
||||
"revision": "466cc881f1760ed8c0e685900ed62dab7846a571",
|
||||
"version": "1.8.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -105,8 +105,8 @@
|
|||
"repositoryURL": "https://github.com/apple/swift-nio-http2.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "6e94a7be32891d1b303a3fcfde8b5bf64d162e74",
|
||||
"version": "1.19.1"
|
||||
"revision": "108ac15087ea9b79abb6f6742699cf31de0e8772",
|
||||
"version": "1.22.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -132,17 +132,17 @@
|
|||
"repositoryURL": "https://github.com/apple/swift-protobuf.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "7e2c5f3cbbeea68e004915e3a8961e20bd11d824",
|
||||
"version": "1.18.0"
|
||||
"revision": "e1499bc69b9040b29184f7f2996f7bab467c1639",
|
||||
"version": "1.19.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "libzcashlc",
|
||||
"repositoryURL": "https://github.com/zcash-hackworks/zcash-light-client-ffi.git",
|
||||
"state": {
|
||||
"branch": "main",
|
||||
"revision": "e5aaf60faf16554e47e4bb123a8b4e5c22475e9f",
|
||||
"version": null
|
||||
"branch": null,
|
||||
"revision": "b7e8a2abab84c44046b4afe4ee4522a0fa2fcc7f",
|
||||
"version": "0.0.3"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0D8BB44E23B1DA0700D5E2A1"
|
||||
BuildableName = "ZcashLightClientSample.app"
|
||||
BlueprintIdentifier = "0DA1C4B027D11D9500E5006E"
|
||||
BuildableName = "ZcashLightClientSample-Mainnet.app"
|
||||
BlueprintName = "ZcashLightClientSample-Mainnet"
|
||||
ReferencedContainer = "container:ZcashLightClientSample.xcodeproj">
|
||||
</BuildableReference>
|
||||
|
@ -50,15 +50,6 @@
|
|||
ReferencedContainer = "container:ZcashLightClientSample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0D8BB44E23B1DA0700D5E2A1"
|
||||
BuildableName = "ZcashLightClientSample.app"
|
||||
BlueprintName = "ZcashLightClientSample-Mainnet"
|
||||
ReferencedContainer = "container:ZcashLightClientSample.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
@ -70,8 +61,8 @@
|
|||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "0D8BB44E23B1DA0700D5E2A1"
|
||||
BuildableName = "ZcashLightClientSample.app"
|
||||
BlueprintIdentifier = "0DA1C4B027D11D9500E5006E"
|
||||
BuildableName = "ZcashLightClientSample-Mainnet.app"
|
||||
BlueprintName = "ZcashLightClientSample-Mainnet"
|
||||
ReferencedContainer = "container:ZcashLightClientSample.xcodeproj">
|
||||
</BuildableReference>
|
||||
|
|
|
@ -16,19 +16,13 @@ class GetBalanceViewController: UIViewController {
|
|||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "Account 0 Balance"
|
||||
self.balance.text = "\(Initializer.shared.getBalance().asHumanReadableZecBalance()) ZEC"
|
||||
self.verified.text = "\(Initializer.shared.getVerifiedBalance().asHumanReadableZecBalance()) ZEC"
|
||||
self.balance.text = "\(Initializer.shared.getBalance().formattedString ?? "0.0") ZEC"
|
||||
self.verified.text = "\(Initializer.shared.getVerifiedBalance().formattedString ?? "0.0") ZEC"
|
||||
}
|
||||
}
|
||||
|
||||
extension Int64 {
|
||||
func asHumanReadableZecBalance() -> Double {
|
||||
Double(self) / Double(ZcashSDK.zatoshiPerZEC)
|
||||
}
|
||||
}
|
||||
|
||||
extension Double {
|
||||
func toZatoshi() -> Int64 {
|
||||
Int64(self * Double(ZcashSDK.zatoshiPerZEC))
|
||||
extension Zatoshi {
|
||||
var formattedString: String? {
|
||||
NumberFormatter.zcashNumberFormatter.string(from: NSNumber(value: self.amount))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ class GetUTXOsViewController: UIViewController {
|
|||
// swiftlint:disable:next force_try
|
||||
let balance = try! AppDelegate.shared.sharedSynchronizer.getTransparentBalance(accountIndex: 0)
|
||||
|
||||
self.totalBalanceLabel.text = String(balance.total.asHumanReadableZecBalance())
|
||||
self.verifiedBalanceLabel.text = String(balance.verified.asHumanReadableZecBalance())
|
||||
self.totalBalanceLabel.text = NumberFormatter.zcashNumberFormatter.string(from: NSNumber(value: balance.total.amount))
|
||||
self.verifiedBalanceLabel.text = NumberFormatter.zcashNumberFormatter.string(from: NSNumber(value: balance.verified.amount))
|
||||
}
|
||||
|
||||
@IBAction func shieldFunds(_ sender: Any) {
|
||||
|
|
|
@ -102,8 +102,8 @@ class SendViewController: UIViewController {
|
|||
)
|
||||
}
|
||||
|
||||
func format(balance: Int64 = 0) -> String {
|
||||
"Zec \(balance.asHumanReadableZecBalance())"
|
||||
func format(balance: Zatoshi = Zatoshi()) -> String {
|
||||
"Zec \(balance.formattedString ?? "0.0")"
|
||||
}
|
||||
|
||||
func toggleSendButton() {
|
||||
|
@ -111,9 +111,9 @@ class SendViewController: UIViewController {
|
|||
}
|
||||
|
||||
func maxFundsOn() {
|
||||
let fee: Int64 = 10000
|
||||
let max = wallet.getVerifiedBalance() - fee
|
||||
amountTextField.text = String(max.asHumanReadableZecBalance())
|
||||
let fee = Zatoshi(10000)
|
||||
let max: Zatoshi = wallet.getVerifiedBalance() - fee
|
||||
amountTextField.text = format(balance: max)
|
||||
amountTextField.isEnabled = false
|
||||
}
|
||||
|
||||
|
@ -131,14 +131,14 @@ class SendViewController: UIViewController {
|
|||
}
|
||||
|
||||
func isBalanceValid() -> Bool {
|
||||
wallet.getVerifiedBalance() > 0
|
||||
wallet.getVerifiedBalance() > .zero
|
||||
}
|
||||
|
||||
func isAmountValid() -> Bool {
|
||||
guard
|
||||
let value = amountTextField.text,
|
||||
let amount = Double(value),
|
||||
amount.toZatoshi() <= wallet.getVerifiedBalance()
|
||||
let amount = NumberFormatter.zcashNumberFormatter.number(from: value).flatMap({ Zatoshi($0.int64Value) }),
|
||||
amount <= wallet.getVerifiedBalance()
|
||||
else {
|
||||
return false
|
||||
}
|
||||
|
@ -197,7 +197,12 @@ class SendViewController: UIViewController {
|
|||
}
|
||||
|
||||
func send() {
|
||||
guard isFormValid(), let amount = amountTextField.text, let zec = Double(amount)?.toZatoshi(), let recipient = addressTextField.text else {
|
||||
guard
|
||||
isFormValid(),
|
||||
let amount = amountTextField.text,
|
||||
let zec = NumberFormatter.zcashNumberFormatter.number(from: amount).flatMap({ Zatoshi($0.int64Value) }),
|
||||
let recipient = addressTextField.text
|
||||
else {
|
||||
loggerProxy.warn("WARNING: Form is invalid")
|
||||
return
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ final class TransactionDetailModel {
|
|||
self.minedHeight = confirmedTransaction.minedHeight.description
|
||||
self.expiryHeight = confirmedTransaction.expiryHeight?.description
|
||||
self.created = Date(timeIntervalSince1970: confirmedTransaction.blockTimeInSeconds).description
|
||||
self.zatoshi = confirmedTransaction.value.description
|
||||
self.zatoshi = NumberFormatter.zcashNumberFormatter.string(from: NSNumber(value: confirmedTransaction.value.amount))
|
||||
if let memoData = confirmedTransaction.memo, let memoString = String(bytes: memoData, encoding: .utf8) {
|
||||
self.memo = memoString
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ final class TransactionDetailModel {
|
|||
self.minedHeight = pendingTransaction.minedHeight.description
|
||||
self.expiryHeight = pendingTransaction.expiryHeight.description
|
||||
self.created = Date(timeIntervalSince1970: pendingTransaction.createTime).description
|
||||
self.zatoshi = pendingTransaction.value.description
|
||||
self.zatoshi = NumberFormatter.zcashNumberFormatter.string(from: NSNumber(value: pendingTransaction.value.amount))
|
||||
}
|
||||
|
||||
init(transaction: TransactionEntity) {
|
||||
|
|
|
@ -56,155 +56,132 @@ class ZcashMainnet: ZcashNetwork {
|
|||
Constants of ZcashLightClientKit. this constants don't
|
||||
*/
|
||||
public enum ZcashSDK {
|
||||
/**
|
||||
The number of zatoshi that equal 1 ZEC.
|
||||
*/
|
||||
|
||||
/// The number of zatoshi that equal 1 ZEC.
|
||||
public static var zatoshiPerZEC: BlockHeight = 100_000_000
|
||||
|
||||
/**
|
||||
The theoretical maximum number of blocks in a reorg, due to other bottlenecks in the protocol design.
|
||||
*/
|
||||
|
||||
/// The theoretical maximum number of blocks in a reorg, due to other bottlenecks in the protocol design.
|
||||
public static var maxReorgSize = 100
|
||||
|
||||
/**
|
||||
The amount of blocks ahead of the current height where new transactions are set to expire. This value is controlled
|
||||
by the rust backend but it is helpful to know what it is set to and should be kept in sync.
|
||||
*/
|
||||
|
||||
/// The amount of blocks ahead of the current height where new transactions are set to expire. This value is controlled
|
||||
/// by the rust backend but it is helpful to know what it is set to and should be kept in sync.
|
||||
public static var expiryOffset = 20
|
||||
|
||||
//
|
||||
// Defaults
|
||||
//
|
||||
/**
|
||||
Default size of batches of blocks to request from the compact block service.
|
||||
*/
|
||||
|
||||
// mark: Defaults
|
||||
|
||||
/// Default size of batches of blocks to request from the compact block service.
|
||||
public static var DefaultBatchSize = 100
|
||||
|
||||
/**
|
||||
Default amount of time, in in seconds, to poll for new blocks. Typically, this should be about half the average
|
||||
block time.
|
||||
*/
|
||||
/// Default amount of time, in in seconds, to poll for new blocks. Typically, this should be about half the average
|
||||
/// block time.
|
||||
public static var defaultPollInterval: TimeInterval = 20
|
||||
|
||||
/**
|
||||
Default attempts at retrying.
|
||||
*/
|
||||
|
||||
/// Default attempts at retrying.
|
||||
public static var defaultRetries: Int = 5
|
||||
|
||||
/**
|
||||
The default maximum amount of time to wait during retry backoff intervals. Failed loops will never wait longer than
|
||||
this before retyring.
|
||||
*/
|
||||
|
||||
/// The default maximum amount of time to wait during retry backoff intervals. Failed loops will never wait longer than
|
||||
/// this before retyring.
|
||||
public static var defaultMaxBackOffInterval: TimeInterval = 600
|
||||
|
||||
/**
|
||||
Default number of blocks to rewind when a chain reorg is detected. This should be large enough to recover from the
|
||||
reorg but smaller than the theoretical max reorg size of 100.
|
||||
*/
|
||||
|
||||
/// Default number of blocks to rewind when a chain reorg is detected. This should be large enough to recover from the
|
||||
/// reorg but smaller than the theoretical max reorg size of 100.
|
||||
public static var defaultRewindDistance: Int = 10
|
||||
|
||||
/**
|
||||
The number of blocks to allow before considering our data to be stale. This usually helps with what to do when
|
||||
returning from the background and is exposed via the Synchronizer's isStale function.
|
||||
*/
|
||||
/// The number of blocks to allow before considering our data to be stale. This usually helps with what to do when
|
||||
/// returning from the background and is exposed via the Synchronizer's isStale function.
|
||||
public static var defaultStaleTolerance: Int = 10
|
||||
|
||||
/**
|
||||
Default Name for LibRustZcash data.db
|
||||
*/
|
||||
|
||||
/// Default Name for LibRustZcash data.db
|
||||
public static var defaultDataDbName = "data.db"
|
||||
|
||||
/**
|
||||
Default Name for Compact Block caches db
|
||||
*/
|
||||
|
||||
/// Default Name for Compact Block caches db
|
||||
public static var defaultCacheDbName = "caches.db"
|
||||
|
||||
/**
|
||||
Default name for pending transactions db
|
||||
*/
|
||||
/// Default name for pending transactions db
|
||||
public static var defaultPendingDbName = "pending.db"
|
||||
|
||||
/**
|
||||
File name for the sapling spend params
|
||||
*/
|
||||
|
||||
/// File name for the sapling spend params
|
||||
public static var spendParamFilename = "sapling-spend.params"
|
||||
|
||||
/**
|
||||
File name for the sapling output params
|
||||
*/
|
||||
/// File name for the sapling output params
|
||||
public static var outputParamFilename = "sapling-output.params"
|
||||
|
||||
/**
|
||||
The Url that is used by default in zcashd.
|
||||
We'll want to make this externally configurable, rather than baking it into the SDK but
|
||||
this will do for now, since we're using a cloudfront URL that already redirects.
|
||||
*/
|
||||
|
||||
/// The Url that is used by default in zcashd.
|
||||
/// We'll want to make this externally configurable, rather than baking it into the SDK but
|
||||
/// this will do for now, since we're using a cloudfront URL that already redirects.
|
||||
public static var cloudParameterURL = "https://z.cash/downloads/"
|
||||
}
|
||||
|
||||
public protocol NetworkConstants {
|
||||
/**
|
||||
The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks
|
||||
prior to this height, at all.
|
||||
*/
|
||||
|
||||
/// The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks
|
||||
/// prior to this height, at all.
|
||||
static var saplingActivationHeight: BlockHeight { get }
|
||||
|
||||
/**
|
||||
Default Name for LibRustZcash data.db
|
||||
*/
|
||||
|
||||
/// Default Name for LibRustZcash data.db
|
||||
static var defaultDataDbName: String { get }
|
||||
|
||||
/**
|
||||
Default Name for Compact Block caches db
|
||||
*/
|
||||
/// Default Name for Compact Block caches db
|
||||
static var defaultCacheDbName: String { get }
|
||||
|
||||
/**
|
||||
Default name for pending transactions db
|
||||
*/
|
||||
|
||||
/// Default name for pending transactions db
|
||||
static var defaultPendingDbName: String { get }
|
||||
|
||||
/// Default prefix for db filenames
|
||||
static var defaultDbNamePrefix: String { get }
|
||||
|
||||
/**
|
||||
fixed height where the SDK considers that the ZIP-321 was deployed. This is a workaround
|
||||
for librustzcash not figuring out the tx fee from the tx itself.
|
||||
*/
|
||||
|
||||
/// fixed height where the SDK considers that the ZIP-321 was deployed. This is a workaround
|
||||
/// for librustzcash not figuring out the tx fee from the tx itself.
|
||||
static var feeChangeHeight: BlockHeight { get }
|
||||
|
||||
|
||||
@available(*, deprecated, message: "This function will be removed soon. Use the one returning `Zatoshi` instead")
|
||||
static func defaultFee(for height: BlockHeight) -> Int64
|
||||
|
||||
/// Returns the default fee according to the blockheight. see [ZIP-313](https://zips.z.cash/zip-0313)
|
||||
static func defaultFee(for height: BlockHeight) -> Zatoshi
|
||||
}
|
||||
|
||||
public extension NetworkConstants {
|
||||
@available(*, deprecated, message: "This function will be removed soon. Use the one returning `Zatoshi` instead")
|
||||
static func defaultFee(for height: BlockHeight = BlockHeight.max) -> Int64 {
|
||||
guard height >= feeChangeHeight else { return 10_000 }
|
||||
guard height >= feeChangeHeight else { return 10_000 }
|
||||
|
||||
return 1_000
|
||||
}
|
||||
|
||||
static func defaultFee(for height: BlockHeight = BlockHeight.max) -> Zatoshi {
|
||||
guard height >= feeChangeHeight else { return Zatoshi(10_000) }
|
||||
|
||||
return Zatoshi(1_000)
|
||||
}
|
||||
}
|
||||
|
||||
public class ZcashSDKMainnetConstants: NetworkConstants {
|
||||
private init() {}
|
||||
|
||||
/**
|
||||
The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks
|
||||
prior to this height, at all.
|
||||
*/
|
||||
|
||||
/// The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks
|
||||
/// prior to this height, at all.
|
||||
public static var saplingActivationHeight: BlockHeight = 419_200
|
||||
|
||||
/**
|
||||
Default Name for LibRustZcash data.db
|
||||
*/
|
||||
|
||||
/// Default Name for LibRustZcash data.db
|
||||
public static var defaultDataDbName = "data.db"
|
||||
|
||||
/**
|
||||
Default Name for Compact Block caches db
|
||||
*/
|
||||
/// Default Name for Compact Block caches db
|
||||
public static var defaultCacheDbName = "caches.db"
|
||||
|
||||
/**
|
||||
Default name for pending transactions db
|
||||
*/
|
||||
/// Default name for pending transactions db
|
||||
public static var defaultPendingDbName = "pending.db"
|
||||
|
||||
public static var defaultDbNamePrefix = "ZcashSdk_mainnet_"
|
||||
|
@ -215,31 +192,26 @@ public class ZcashSDKMainnetConstants: NetworkConstants {
|
|||
public class ZcashSDKTestnetConstants: NetworkConstants {
|
||||
private init() {}
|
||||
|
||||
/**
|
||||
The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks
|
||||
prior to this height, at all.
|
||||
*/
|
||||
|
||||
/// The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks
|
||||
/// prior to this height, at all.
|
||||
public static var saplingActivationHeight: BlockHeight = 280_000
|
||||
|
||||
/**
|
||||
Default Name for LibRustZcash data.db
|
||||
*/
|
||||
|
||||
/// Default Name for LibRustZcash data.db
|
||||
public static var defaultDataDbName = "data.db"
|
||||
|
||||
/**
|
||||
Default Name for Compact Block caches db
|
||||
*/
|
||||
|
||||
/// Default Name for Compact Block caches db
|
||||
public static var defaultCacheDbName = "caches.db"
|
||||
|
||||
/**
|
||||
Default name for pending transactions db
|
||||
*/
|
||||
|
||||
/// Default name for pending transactions db
|
||||
public static var defaultPendingDbName = "pending.db"
|
||||
|
||||
public static var defaultDbNamePrefix = "ZcashSdk_testnet_"
|
||||
|
||||
/**
|
||||
Estimated height where wallets are supposed to change the fee
|
||||
*/
|
||||
|
||||
/// Estimated height where wallets are supposed to change the fee
|
||||
public static var feeChangeHeight: BlockHeight = 1_028_500
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import Foundation
|
||||
import SQLite
|
||||
struct PendingTransaction: PendingTransactionEntity, Decodable, Encodable {
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case toAddress = "to_address"
|
||||
case accountIndex = "account_index"
|
||||
|
@ -38,7 +39,7 @@ struct PendingTransaction: PendingTransactionEntity, Decodable, Encodable {
|
|||
var createTime: TimeInterval
|
||||
var raw: Data?
|
||||
var id: Int?
|
||||
var value: Int
|
||||
var value: Zatoshi
|
||||
var memo: Data?
|
||||
var rawTransactionId: Data?
|
||||
|
||||
|
@ -69,7 +70,7 @@ struct PendingTransaction: PendingTransactionEntity, Decodable, Encodable {
|
|||
|
||||
extension PendingTransaction {
|
||||
// TODO: Handle Memo
|
||||
init(value: Int, toAddress: String, memo: String?, account index: Int) {
|
||||
init(value: Zatoshi, toAddress: String, memo: String?, account index: Int) {
|
||||
self = PendingTransaction(
|
||||
toAddress: toAddress,
|
||||
accountIndex: index,
|
||||
|
@ -83,7 +84,7 @@ extension PendingTransaction {
|
|||
createTime: Date().timeIntervalSince1970,
|
||||
raw: nil,
|
||||
id: nil,
|
||||
value: Int(value),
|
||||
value: value,
|
||||
memo: memo?.encodeAsZcashTransactionMemo(),
|
||||
rawTransactionId: nil
|
||||
)
|
||||
|
@ -104,7 +105,7 @@ class PendingTransactionSQLDAO: PendingTransactionRepository {
|
|||
static var createTime = Expression<TimeInterval?>("create_time")
|
||||
static var raw = Expression<Blob?>("raw")
|
||||
static var id = Expression<Int>("id")
|
||||
static var value = Expression<Int>("value")
|
||||
static var value = Expression<Zatoshi>("value")
|
||||
static var memo = Expression<Blob?>("memo")
|
||||
static var rawTransactionId = Expression<Blob?>("txid")
|
||||
}
|
||||
|
@ -186,6 +187,7 @@ class PendingTransactionSQLDAO: PendingTransactionRepository {
|
|||
|
||||
do {
|
||||
let pendingTx: PendingTransaction = try row.decode()
|
||||
|
||||
return pendingTx
|
||||
} catch {
|
||||
throw StorageError.operationFailed
|
||||
|
|
|
@ -120,7 +120,7 @@ enum TransactionBuilder {
|
|||
transactionIndex: Int(transactionIndex),
|
||||
raw: raw,
|
||||
id: Int(id),
|
||||
value: Int(value),
|
||||
value: Zatoshi(value),
|
||||
memo: memo,
|
||||
rawTransactionId: transactionId
|
||||
)
|
||||
|
@ -161,7 +161,7 @@ enum TransactionBuilder {
|
|||
transactionIndex: Int(transactionIndex),
|
||||
raw: rawData,
|
||||
id: Int(id),
|
||||
value: Int(value),
|
||||
value: Zatoshi(value),
|
||||
memo: memo,
|
||||
rawTransactionId: transactionId
|
||||
)
|
||||
|
|
|
@ -37,7 +37,7 @@ struct ConfirmedTransaction: ConfirmedTransactionEntity {
|
|||
var transactionIndex: Int
|
||||
var raw: Data?
|
||||
var id: Int?
|
||||
var value: Int
|
||||
var value: Zatoshi
|
||||
var memo: Data?
|
||||
var rawTransactionId: Data?
|
||||
}
|
||||
|
|
|
@ -166,16 +166,18 @@ class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository {
|
|||
.filter(TableColumns.address == address)
|
||||
) ?? 0
|
||||
|
||||
return TransparentBalance(verified: Int64(verified), total: Int64(total), address: address)
|
||||
return WalletBalance(
|
||||
verified: Zatoshi(Int64(verified)),
|
||||
total: Zatoshi(Int64(total))
|
||||
)
|
||||
} catch {
|
||||
throw StorageError.operationFailed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TransparentBalance: WalletBalance {
|
||||
var verified: Int64
|
||||
var total: Int64
|
||||
struct TransparentBalance {
|
||||
var balance: WalletBalance
|
||||
var address: String
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ public protocol AbstractTransaction {
|
|||
/**
|
||||
value in zatoshi
|
||||
*/
|
||||
var value: Int { get set }
|
||||
var value: Zatoshi { get set }
|
||||
|
||||
/**
|
||||
data containing the memo if any
|
||||
|
@ -159,3 +159,9 @@ public extension ConfirmedTransactionEntity {
|
|||
self.blockTimeInSeconds * 1000
|
||||
}
|
||||
}
|
||||
|
||||
public extension AbstractTransaction {
|
||||
var intValue: Int {
|
||||
Int(self.value.amount)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// NumberFormatter+Zcash.swift
|
||||
//
|
||||
// Created by Lukáš Korba on 02.06.2022.
|
||||
// modified by Francisco Gindre on 6/17/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension NumberFormatter {
|
||||
static let zcashNumberFormatter: NumberFormatter = {
|
||||
var formatter = NumberFormatter()
|
||||
formatter.maximumFractionDigits = 8
|
||||
formatter.maximumIntegerDigits = 8
|
||||
formatter.numberStyle = .decimal
|
||||
formatter.usesGroupingSeparator = true
|
||||
return formatter
|
||||
}()
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// Zatoshi+Codable.swift
|
||||
//
|
||||
//
|
||||
// Created by Francisco Gindre on 6/20/22.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
/// This extension is needed to support SQLite Swift Codable Types
|
||||
extension Zatoshi: Codable {
|
||||
enum CodingError: Error {
|
||||
case encodingError(String)
|
||||
}
|
||||
/// This codable implementation responds to limitaitons that SQLite Swift explains
|
||||
/// on its documentation https://github.com/stephencelis/SQLite.swift/blob/master/Documentation/Index.md#codable-types
|
||||
/// SQLite Sqift will encode custom types into a string and stores it in a single column. They do so by
|
||||
/// leveraging the Codable interface so this has to abide by them and their choice.
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
let value = try container.decode(String.self)
|
||||
|
||||
guard let amount = Int64(value) else {
|
||||
throw CodingError.encodingError("Decoding Error")
|
||||
}
|
||||
|
||||
self.amount = amount
|
||||
}
|
||||
|
||||
/// This codable implementation responds to limitaitons that SQLite Swift explains
|
||||
/// on its documentation https://github.com/stephencelis/SQLite.swift/blob/master/Documentation/Index.md#codable-types
|
||||
/// SQLite Sqift will encode custom types into a string and stores it in a single column. They do so by
|
||||
/// leveraging the Codable interface so this has to abide by them and their choice.
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
|
||||
try container.encode(String(self.amount))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
//
|
||||
// Zatoshi+SQLite.swift
|
||||
//
|
||||
//
|
||||
// Created by Francisco Gindre on 6/20/22.
|
||||
//
|
||||
|
||||
import SQLite
|
||||
|
||||
extension Zatoshi: Value {
|
||||
public static var declaredDatatype = Int64.declaredDatatype
|
||||
|
||||
public static func fromDatatypeValue(_ datatypeValue: Int64) -> Zatoshi {
|
||||
Zatoshi(datatypeValue)
|
||||
}
|
||||
|
||||
public var datatypeValue: Int64 {
|
||||
self.amount
|
||||
}
|
||||
}
|
|
@ -252,21 +252,47 @@ public class Initializer {
|
|||
try? accountRepository.findBy(account: account)?.address
|
||||
}
|
||||
|
||||
/**
|
||||
get (unverified) balance from the given account index
|
||||
- Parameter account: the index of the account
|
||||
*/
|
||||
|
||||
/// get (unverified) balance from the given account index
|
||||
/// - Parameter account: the index of the account
|
||||
@available(*, deprecated, message: "This function will be removed soon. Use the function returning `Zatoshi` instead")
|
||||
public func getBalance(account index: Int = 0) -> Int64 {
|
||||
rustBackend.getBalance(dbData: dataDbURL, account: Int32(index), networkType: network.networkType)
|
||||
}
|
||||
|
||||
/**
|
||||
get verified balance from the given account index
|
||||
- Parameter account: the index of the account
|
||||
*/
|
||||
|
||||
|
||||
/// get (unverified) balance from the given account index
|
||||
/// - Parameter account: the index of the account
|
||||
/// - Returns: balance in `Zatoshi`
|
||||
public func getBalance(account index: Int = 0) -> Zatoshi {
|
||||
Zatoshi(
|
||||
rustBackend.getBalance(
|
||||
dbData: dataDbURL,
|
||||
account: Int32(index),
|
||||
networkType: network.networkType
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/// get verified balance from the given account index
|
||||
/// - Parameter account: the index of the account
|
||||
@available(*, deprecated, message: "This function will be removed soon. Use the one returning `Zatoshi` instead")
|
||||
public func getVerifiedBalance(account index: Int = 0) -> Int64 {
|
||||
rustBackend.getVerifiedBalance(dbData: dataDbURL, account: Int32(index), networkType: network.networkType)
|
||||
}
|
||||
|
||||
/// get verified balance from the given account index
|
||||
/// - Parameter account: the index of the account
|
||||
/// - Returns: balance in `Zatoshi`
|
||||
public func getVerifiedBalance(account index: Int = 0) -> Zatoshi {
|
||||
Zatoshi(
|
||||
rustBackend.getVerifiedBalance(
|
||||
dbData: dataDbURL,
|
||||
account: Int32(index),
|
||||
networkType: network.networkType
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
checks if the provided address is a valid shielded zAddress
|
||||
|
|
|
@ -102,7 +102,7 @@ public protocol UnifiedAddress {
|
|||
var zAddress: SaplingShieldedAddress { get }
|
||||
}
|
||||
|
||||
public protocol WalletBalance {
|
||||
var verified: Int64 { get set }
|
||||
var total: Int64 { get set }
|
||||
public struct WalletBalance {
|
||||
public var verified: Zatoshi
|
||||
public var total: Zatoshi
|
||||
}
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
//
|
||||
// Zatoshi.swift
|
||||
// secant-testnet
|
||||
//
|
||||
// Created by Lukáš Korba on 26.05.2022.
|
||||
// Modified and ported to ZcashLightClientKit by Francisco Gindre
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct Zatoshi {
|
||||
public enum Constants {
|
||||
public static let oneZecInZatoshi: Int64 = 100_000_000
|
||||
public static let maxZecSupply: Int64 = 21_000_000
|
||||
public static let maxZatoshi: Int64 = Constants.oneZecInZatoshi * Constants.maxZecSupply
|
||||
}
|
||||
|
||||
public static var zero: Zatoshi { Zatoshi() }
|
||||
|
||||
static let decimalHandler = NSDecimalNumberHandler(
|
||||
roundingMode: NSDecimalNumber.RoundingMode.bankers,
|
||||
scale: 8,
|
||||
raiseOnExactness: true,
|
||||
raiseOnOverflow: true,
|
||||
raiseOnUnderflow: true,
|
||||
raiseOnDivideByZero: true
|
||||
)
|
||||
|
||||
@Clamped(-Constants.maxZatoshi...Constants.maxZatoshi)
|
||||
public var amount: Int64 = 0
|
||||
|
||||
/// Converts `Zatoshi` to `NSDecimalNumber`
|
||||
public var decimalValue: NSDecimalNumber {
|
||||
NSDecimalNumber(decimal: Decimal(amount) / Decimal(Constants.oneZecInZatoshi))
|
||||
}
|
||||
|
||||
public init(_ amount: Int64 = 0) {
|
||||
self.amount = amount
|
||||
}
|
||||
/// Converts `Zatoshi` to human readable format, up to 8 fraction digits
|
||||
public func decimalString(formatter: NumberFormatter = NumberFormatter.zcashNumberFormatter) -> String {
|
||||
formatter.string(from: decimalValue.roundedZec) ?? ""
|
||||
}
|
||||
|
||||
/// Converts `Decimal` to `Zatoshi`
|
||||
public static func from(decimal: Decimal) -> Zatoshi {
|
||||
let roundedZec = NSDecimalNumber(decimal: decimal).roundedZec
|
||||
let zec2zatoshi = Decimal(Constants.oneZecInZatoshi) * roundedZec.decimalValue
|
||||
return Zatoshi(NSDecimalNumber(decimal: zec2zatoshi).int64Value)
|
||||
}
|
||||
|
||||
/// Converts `String` to `Zatoshi`
|
||||
public static func from(decimalString: String, formatter: NumberFormatter = NumberFormatter.zcashNumberFormatter) -> Zatoshi? {
|
||||
if let number = formatter.number(from: decimalString) {
|
||||
return Zatoshi.from(decimal: number.decimalValue)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
public static func + (left: Zatoshi, right: Zatoshi) -> Zatoshi {
|
||||
Zatoshi(left.amount + right.amount)
|
||||
}
|
||||
|
||||
public static func - (left: Zatoshi, right: Zatoshi) -> Zatoshi {
|
||||
Zatoshi(left.amount - right.amount)
|
||||
}
|
||||
}
|
||||
|
||||
extension Zatoshi: Equatable {
|
||||
public static func == (lhs: Zatoshi, rhs: Zatoshi) -> Bool {
|
||||
lhs.amount == rhs.amount
|
||||
}
|
||||
}
|
||||
|
||||
extension Zatoshi: Comparable {
|
||||
public static func < (lhs: Zatoshi, rhs: Zatoshi) -> Bool {
|
||||
lhs.amount < rhs.amount
|
||||
}
|
||||
}
|
||||
|
||||
extension NSDecimalNumber {
|
||||
/// Round the decimal to 8 fraction digits
|
||||
var roundedZec: NSDecimalNumber {
|
||||
self.rounding(accordingToBehavior: Zatoshi.decimalHandler)
|
||||
}
|
||||
|
||||
/// Converts `NSDecimalNumber` to human readable format, up to 8 fraction digits
|
||||
var decimalString: String {
|
||||
self.roundedZec.stringValue
|
||||
}
|
||||
}
|
|
@ -294,7 +294,8 @@ class ZcashRustBackend: ZcashRustBackendWelding {
|
|||
static func downloadedUtxoBalance(dbData: URL, address: String, networkType: NetworkType) throws -> WalletBalance {
|
||||
let verified = try getVerifiedTransparentBalance(dbData: dbData, address: address, networkType: networkType)
|
||||
let total = try getTransparentBalance(dbData: dbData, address: address, networkType: networkType)
|
||||
return TransparentBalance(verified: verified, total: total, address: address)
|
||||
|
||||
return WalletBalance(verified: Zatoshi(verified), total: Zatoshi(total))
|
||||
}
|
||||
|
||||
static func getReceivedMemoAsUTF8(dbData: URL, idNote: Int64, networkType: NetworkType) -> String? {
|
||||
|
|
|
@ -8,9 +8,8 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Represents errors thrown by a Synchronizer
|
||||
*/
|
||||
|
||||
/// Represents errors thrown by a Synchronizer
|
||||
public enum SynchronizerError: Error {
|
||||
case initFailed(message: String)
|
||||
case notPrepared
|
||||
|
@ -48,98 +47,74 @@ extension ShieldFundsError: LocalizedError {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Represent the connection state to the lightwalletd server
|
||||
*/
|
||||
|
||||
/// Represent the connection state to the lightwalletd server
|
||||
public enum ConnectionState {
|
||||
/**
|
||||
not in use
|
||||
*/
|
||||
/// not in use
|
||||
case idle
|
||||
|
||||
/**
|
||||
there's a connection being attempted from a non error state
|
||||
*/
|
||||
/// there's a connection being attempted from a non error state
|
||||
case connecting
|
||||
|
||||
/**
|
||||
connection is established, ready to use or in use
|
||||
*/
|
||||
/// connection is established, ready to use or in use
|
||||
case online
|
||||
|
||||
/**
|
||||
the connection is being re-established after losing it temporarily
|
||||
*/
|
||||
/// the connection is being re-established after losing it temporarily
|
||||
case reconnecting
|
||||
|
||||
/**
|
||||
the connection has been closed
|
||||
*/
|
||||
/// the connection has been closed
|
||||
case shutdown
|
||||
}
|
||||
|
||||
/**
|
||||
Primary interface for interacting with the SDK. Defines the contract that specific
|
||||
implementations like SdkSynchronizer fulfill.
|
||||
*/
|
||||
|
||||
/// Primary interface for interacting with the SDK. Defines the contract that specific
|
||||
/// implementations like SdkSynchronizer fulfill.
|
||||
public protocol Synchronizer {
|
||||
/**
|
||||
Value representing the Status of this Synchronizer. As the status changes, it will be also notified
|
||||
*/
|
||||
|
||||
/// Value representing the Status of this Synchronizer. As the status changes, it will be also notified
|
||||
var status: SyncStatus { get }
|
||||
|
||||
/**
|
||||
reflects current connection state to LightwalletEndpoint
|
||||
*/
|
||||
|
||||
/// reflects current connection state to LightwalletEndpoint
|
||||
var connectionState: ConnectionState { get }
|
||||
|
||||
/**
|
||||
prepares this initializer to operate. Initializes the internal state with the given Extended Viewing Keys and a wallet birthday found in the initializer object
|
||||
*/
|
||||
|
||||
/// prepares this initializer to operate. Initializes the internal state with the given
|
||||
/// Extended Viewing Keys and a wallet birthday found in the initializer object
|
||||
func prepare() throws
|
||||
/**
|
||||
Starts this synchronizer within the given scope.
|
||||
|
||||
Implementations should leverage structured concurrency and
|
||||
cancel all jobs when this scope completes.
|
||||
*/
|
||||
|
||||
///Starts this synchronizer within the given scope.
|
||||
///
|
||||
///Implementations should leverage structured concurrency and
|
||||
///cancel all jobs when this scope completes.
|
||||
func start(retry: Bool) throws
|
||||
|
||||
/**
|
||||
Stop this synchronizer. Implementations should ensure that calling this method cancels all jobs that were created by this instance.
|
||||
*/
|
||||
|
||||
/// Stop this synchronizer. Implementations should ensure that calling this method cancels all jobs that were created by this instance.
|
||||
func stop() throws
|
||||
|
||||
/**
|
||||
Gets the sapling shielded address for the given account.
|
||||
- Parameter accountIndex: the optional accountId whose address is of interest. By default, the first account is used.
|
||||
- Returns the address or nil if account index is incorrect
|
||||
*/
|
||||
|
||||
/// Gets the sapling shielded address for the given account.
|
||||
/// - Parameter accountIndex: the optional accountId whose address is of interest. By default, the first account is used.
|
||||
/// - Returns the address or nil if account index is incorrect
|
||||
func getShieldedAddress(accountIndex: Int) -> SaplingShieldedAddress?
|
||||
|
||||
/**
|
||||
Gets the unified address for the given account.
|
||||
- Parameter accountIndex: the optional accountId whose address is of interest. By default, the first account is used.
|
||||
- Returns the address or nil if account index is incorrect
|
||||
*/
|
||||
|
||||
/// Gets the unified address for the given account.
|
||||
/// - Parameter accountIndex: the optional accountId whose address is of interest. By default, the first account is used.
|
||||
/// - Returns the address or nil if account index is incorrect
|
||||
func getUnifiedAddress(accountIndex: Int) -> UnifiedAddress?
|
||||
|
||||
/**
|
||||
Gets the transparent address for the given account.
|
||||
- Parameter accountIndex: the optional accountId whose address is of interest. By default, the first account is used.
|
||||
- Returns the address or nil if account index is incorrect
|
||||
*/
|
||||
|
||||
/// Gets the transparent address for the given account.
|
||||
/// - Parameter accountIndex: the optional accountId whose address is of interest. By default, the first account is used.
|
||||
/// - Returns the address or nil if account index is incorrect
|
||||
func getTransparentAddress(accountIndex: Int) -> TransparentAddress?
|
||||
|
||||
/**
|
||||
Sends zatoshi.
|
||||
- Parameter spendingKey: the key that allows spends to occur.
|
||||
- Parameter zatoshi: the amount of zatoshi to send.
|
||||
- Parameter toAddress: the recipient's address.
|
||||
- Parameter memo: the optional memo to include as part of the transaction.
|
||||
- Parameter accountIndex: the optional account id to use. By default, the first account is used.
|
||||
*/
|
||||
|
||||
/// Sends zatoshi.
|
||||
/// - Parameter spendingKey: the key that allows spends to occur.
|
||||
/// - Parameter zatoshi: the amount of zatoshi to send.
|
||||
/// - Parameter toAddress: the recipient's address.
|
||||
/// - Parameter memo: the optional memo to include as part of the transaction.
|
||||
/// - Parameter accountIndex: the optional account id to use. By default, the first account is used.
|
||||
@available(*, deprecated, message: "This function will be removed soon, use the one reveiving a `Zatoshi` value instead")
|
||||
// swiftlint:disable:next function_parameter_count
|
||||
func sendToAddress(
|
||||
spendingKey: String,
|
||||
|
@ -149,14 +124,29 @@ public protocol Synchronizer {
|
|||
from accountIndex: Int,
|
||||
resultBlock: @escaping (_ result: Result<PendingTransactionEntity, Error>) -> Void
|
||||
)
|
||||
|
||||
/**
|
||||
Sends zatoshi.
|
||||
- Parameter spendingKey: the key that allows spends to occur.
|
||||
- Parameter transparentSecretKey: the key that allows to spend transaprent funds
|
||||
- Parameter memo: the optional memo to include as part of the transaction.
|
||||
- Parameter accountIndex: the optional account id that will be used to shield your funds to. By default, the first account is used.
|
||||
*/
|
||||
|
||||
|
||||
/// Sends zatoshi.
|
||||
/// - Parameter spendingKey: the key that allows spends to occur.
|
||||
/// - Parameter zatoshi: the amount to send in Zatoshi.
|
||||
/// - Parameter toAddress: the recipient's address.
|
||||
/// - Parameter memo: the optional memo to include as part of the transaction.
|
||||
/// - Parameter accountIndex: the optional account id to use. By default, the first account is used.
|
||||
// swiftlint:disable:next function_parameter_count
|
||||
func sendToAddress(
|
||||
spendingKey: String,
|
||||
zatoshi: Zatoshi,
|
||||
toAddress: String,
|
||||
memo: String?,
|
||||
from accountIndex: Int,
|
||||
resultBlock: @escaping (_ result: Result<PendingTransactionEntity, Error>) -> Void
|
||||
)
|
||||
|
||||
/// Sends zatoshi.
|
||||
/// - Parameter spendingKey: the key that allows spends to occur.
|
||||
/// - Parameter transparentSecretKey: the key that allows to spend transaprent funds
|
||||
/// - Parameter memo: the optional memo to include as part of the transaction.
|
||||
/// - Parameter accountIndex: the optional account id that will be used to shield your funds to. By default, the first account is used.
|
||||
func shieldFunds(
|
||||
spendingKey: String,
|
||||
transparentSecretKey: String,
|
||||
|
@ -164,142 +154,124 @@ public protocol Synchronizer {
|
|||
from accountIndex: Int,
|
||||
resultBlock: @escaping (_ result: Result<PendingTransactionEntity, Error>) -> Void
|
||||
)
|
||||
|
||||
/**
|
||||
Attempts to cancel a transaction that is about to be sent. Typically, cancellation is only
|
||||
an option if the transaction has not yet been submitted to the server.
|
||||
- Parameter transaction: the transaction to cancel.
|
||||
- Returns: true when the cancellation request was successful. False when it is too late.
|
||||
*/
|
||||
|
||||
|
||||
/// Attempts to cancel a transaction that is about to be sent. Typically, cancellation is only
|
||||
/// an option if the transaction has not yet been submitted to the server.
|
||||
/// - Parameter transaction: the transaction to cancel.
|
||||
/// - Returns: true when the cancellation request was successful. False when it is too late.
|
||||
func cancelSpend(transaction: PendingTransactionEntity) -> Bool
|
||||
|
||||
/**
|
||||
all outbound pending transactions that have been sent but are awaiting confirmations
|
||||
*/
|
||||
|
||||
/// all outbound pending transactions that have been sent but are awaiting confirmations
|
||||
var pendingTransactions: [PendingTransactionEntity] { get }
|
||||
/**
|
||||
all the transactions that are on the blockchain
|
||||
*/
|
||||
|
||||
/// all the transactions that are on the blockchain
|
||||
var clearedTransactions: [ConfirmedTransactionEntity] { get }
|
||||
/**
|
||||
All transactions that are related to sending funds
|
||||
*/
|
||||
|
||||
/// All transactions that are related to sending funds
|
||||
var sentTransactions: [ConfirmedTransactionEntity] { get }
|
||||
/**
|
||||
all transactions related to receiving funds
|
||||
*/
|
||||
|
||||
/// all transactions related to receiving funds
|
||||
var receivedTransactions: [ConfirmedTransactionEntity] { get }
|
||||
|
||||
/**
|
||||
A repository serving transactions in a paginated manner
|
||||
- Parameter kind: Transaction Kind expected from this PaginatedTransactionRepository
|
||||
*/
|
||||
|
||||
/// A repository serving transactions in a paginated manner
|
||||
/// - Parameter kind: Transaction Kind expected from this PaginatedTransactionRepository
|
||||
func paginatedTransactions(of kind: TransactionKind) -> PaginatedTransactionRepository
|
||||
|
||||
/**
|
||||
Returns a list of confirmed transactions that preceed the given transaction with a limit count.
|
||||
- Parameters:
|
||||
- from: the confirmed transaction from which the query should start from or nil to retrieve from the most recent transaction
|
||||
- limit: the maximum amount of items this should return if available
|
||||
- Returns: an array with the given Transactions or nil
|
||||
*/
|
||||
|
||||
/// Returns a list of confirmed transactions that preceed the given transaction with a limit count.
|
||||
/// - Parameters:
|
||||
/// - from: the confirmed transaction from which the query should start from or nil to retrieve from the most recent transaction
|
||||
/// - limit: the maximum amount of items this should return if available
|
||||
/// - Returns: an array with the given Transactions or nil
|
||||
func allConfirmedTransactions(from transaction: ConfirmedTransactionEntity?, limit: Int) throws -> [ConfirmedTransactionEntity]?
|
||||
|
||||
/**
|
||||
Returns the latest downloaded height from the compact block cache
|
||||
*/
|
||||
|
||||
/// Returns the latest downloaded height from the compact block cache
|
||||
func latestDownloadedHeight() throws -> BlockHeight
|
||||
|
||||
/**
|
||||
Returns the latest block height from the provided Lightwallet endpoint
|
||||
*/
|
||||
|
||||
/// Returns the latest block height from the provided Lightwallet endpoint
|
||||
func latestHeight(result: @escaping (Result<BlockHeight, Error>) -> Void)
|
||||
|
||||
/**
|
||||
Returns the latest block height from the provided Lightwallet endpoint
|
||||
Blocking
|
||||
*/
|
||||
|
||||
/// Returns the latest block height from the provided Lightwallet endpoint
|
||||
/// Blocking
|
||||
func latestHeight() throws -> BlockHeight
|
||||
|
||||
/**
|
||||
Returns the latests UTXOs for the given address from the specified height on
|
||||
*/
|
||||
|
||||
/// Returns the latests UTXOs for the given address from the specified height on
|
||||
func refreshUTXOs(address: String, from height: BlockHeight, result: @escaping (Result<RefreshedUTXOs, Error>) -> Void)
|
||||
|
||||
/**
|
||||
Returns the last stored unshielded balance
|
||||
*/
|
||||
|
||||
/// Returns the last stored unshielded balance
|
||||
func getTransparentBalance(accountIndex: Int) throws -> WalletBalance
|
||||
|
||||
/**
|
||||
Returns the shielded total balance (includes verified and unverified balance)
|
||||
*/
|
||||
|
||||
/// Returns the shielded total balance (includes verified and unverified balance)
|
||||
@available(*, deprecated, message: "This function will be removed soon, use the one returning a `Zatoshi` value instead")
|
||||
func getShieldedBalance(accountIndex: Int) -> Int64
|
||||
|
||||
/**
|
||||
Returns the shielded verified balance (anchor is 10 blocks back)
|
||||
*/
|
||||
|
||||
|
||||
/// Returns the shielded total balance (includes verified and unverified balance)
|
||||
func getShieldedBalance(accountIndex: Int) -> Zatoshi
|
||||
|
||||
/// Returns the shielded verified balance (anchor is 10 blocks back)
|
||||
@available(*, deprecated, message: "This function will be removed soon, use the one returning a `Zatoshi` value instead")
|
||||
func getShieldedVerifiedBalance(accountIndex: Int) -> Int64
|
||||
|
||||
/// Returns the shielded verified balance (anchor is 10 blocks back)
|
||||
func getShieldedVerifiedBalance(accountIndex: Int) -> Zatoshi
|
||||
|
||||
/**
|
||||
Stops the synchronizer and rescans the known blocks with the current keys.
|
||||
- Parameter policy: the rewind policy
|
||||
- Throws rewindErrorUnknownArchorHeight when the rewind points to an invalid height
|
||||
- Throws rewindError for other errors
|
||||
- Note rewind does not trigger notifications as a reorg would. You need to restart the synchronizer afterwards
|
||||
*/
|
||||
|
||||
/// Stops the synchronizer and rescans the known blocks with the current keys.
|
||||
/// - Parameter policy: the rewind policy
|
||||
/// - Throws rewindErrorUnknownArchorHeight when the rewind points to an invalid height
|
||||
/// - Throws rewindError for other errors
|
||||
/// - Note rewind does not trigger notifications as a reorg would. You need to restart the synchronizer afterwards
|
||||
func rewind(_ policy: RewindPolicy) throws
|
||||
}
|
||||
|
||||
public enum SyncStatus: Equatable {
|
||||
/**
|
||||
Indicates that this Synchronizer is actively preparing to start, which usually involves setting up database tables, migrations or taking other maintenance steps that need to occur after an upgrade.
|
||||
*/
|
||||
|
||||
/// Indicates that this Synchronizer is actively preparing to start,
|
||||
/// which usually involves setting up database tables, migrations or
|
||||
/// taking other maintenance steps that need to occur after an upgrade.
|
||||
case unprepared
|
||||
|
||||
/**
|
||||
Indicates that this Synchronizer is actively downloading new blocks from the server.
|
||||
*/
|
||||
/// Indicates that this Synchronizer is actively downloading new blocks from the server.
|
||||
case downloading(_ status: BlockProgress)
|
||||
|
||||
/**
|
||||
Indicates that this Synchronizer is actively validating new blocks that were downloaded
|
||||
from the server. Blocks need to be verified before they are scanned. This confirms that
|
||||
each block is chain-sequential, thereby detecting missing blocks and reorgs.
|
||||
*/
|
||||
|
||||
/// Indicates that this Synchronizer is actively validating new blocks that were downloaded
|
||||
/// from the server. Blocks need to be verified before they are scanned. This confirms that
|
||||
/// each block is chain-sequential, thereby detecting missing blocks and reorgs.
|
||||
case validating
|
||||
|
||||
/**
|
||||
Indicates that this Synchronizer is actively scanning new valid blocks that were downloaded from the server.
|
||||
*/
|
||||
|
||||
/// Indicates that this Synchronizer is actively scanning new valid blocks that were
|
||||
/// downloaded from the server.
|
||||
case scanning(_ progress: BlockProgress)
|
||||
|
||||
/**
|
||||
Indicates that this Synchronizer is actively enhancing newly scanned blocks with additional transaction details, fetched from the server.
|
||||
*/
|
||||
|
||||
/// Indicates that this Synchronizer is actively enhancing newly scanned blocks
|
||||
/// with additional transaction details, fetched from the server.
|
||||
case enhancing(_ progress: EnhancementProgress)
|
||||
|
||||
/**
|
||||
fetches the transparent balance and stores it locally
|
||||
*/
|
||||
|
||||
/// fetches the transparent balance and stores it locally
|
||||
case fetching
|
||||
|
||||
/**
|
||||
Indicates that this Synchronizer is fully up to date and ready for all wallet functions.
|
||||
When set, a UI element may want to turn green.
|
||||
*/
|
||||
/// Indicates that this Synchronizer is fully up to date and ready for all wallet functions.
|
||||
/// When set, a UI element may want to turn green.
|
||||
case synced
|
||||
|
||||
/**
|
||||
Indicates that [stop] has been called on this Synchronizer and it will no longer be used.
|
||||
*/
|
||||
|
||||
/// Indicates that [stop] has been called on this Synchronizer and it will no longer be used.
|
||||
case stopped
|
||||
|
||||
/**
|
||||
Indicates that this Synchronizer is disconnected from its lightwalletd server.
|
||||
When set, a UI element may want to turn red.
|
||||
*/
|
||||
|
||||
/// Indicates that this Synchronizer is disconnected from its lightwalletd server.
|
||||
/// When set, a UI element may want to turn red.
|
||||
case disconnected
|
||||
|
||||
case error(_ error: Error)
|
||||
|
@ -321,22 +293,19 @@ public enum SyncStatus: Equatable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Kind of transactions handled by a Synchronizer
|
||||
*/
|
||||
|
||||
/// Kind of transactions handled by a Synchronizer
|
||||
public enum TransactionKind {
|
||||
case sent
|
||||
case received
|
||||
case all
|
||||
}
|
||||
|
||||
/**
|
||||
Type of rewind available
|
||||
-birthday: rewinds the local state to this wallet's birthday
|
||||
-height: rewinds to the nearest blockheight to the one given as argument.
|
||||
-transaction: rewinds to the nearest height based on the anchor of the provided transaction.
|
||||
*/
|
||||
|
||||
/// Type of rewind available
|
||||
/// -birthday: rewinds the local state to this wallet's birthday
|
||||
/// -height: rewinds to the nearest blockheight to the one given as argument.
|
||||
/// -transaction: rewinds to the nearest height based on the anchor of the provided transaction.
|
||||
public enum RewindPolicy {
|
||||
case birthday
|
||||
case height(blockheight: BlockHeight)
|
||||
|
|
|
@ -9,98 +9,75 @@
|
|||
import Foundation
|
||||
|
||||
public extension Notification.Name {
|
||||
/**
|
||||
Notification is posted whenever transactions are updated
|
||||
|
||||
- Important: not yet posted
|
||||
*/
|
||||
/// Notification is posted whenever transactions are updated
|
||||
///
|
||||
/// - Important: not yet posted
|
||||
static let transactionsUpdated = Notification.Name("SDKSyncronizerTransactionUpdated")
|
||||
|
||||
/**
|
||||
Posted when the synchronizer is started.
|
||||
*/
|
||||
|
||||
/// Posted when the synchronizer is started.
|
||||
static let synchronizerStarted = Notification.Name("SDKSyncronizerStarted")
|
||||
|
||||
/**
|
||||
Posted when there are progress updates.
|
||||
|
||||
- Note: Query userInfo object for NotificationKeys.progress for Float progress percentage and NotificationKeys.blockHeight for the current progress height
|
||||
*/
|
||||
|
||||
/// Posted when there are progress updates.
|
||||
///
|
||||
/// - Note: Query userInfo object for NotificationKeys.progress for Float
|
||||
/// progress percentage and NotificationKeys.blockHeight /// for the current progress height
|
||||
static let synchronizerProgressUpdated = Notification.Name("SDKSyncronizerProgressUpdated")
|
||||
|
||||
static let synchronizerStatusWillUpdate = Notification.Name("SDKSynchronizerStatusWillUpdate")
|
||||
|
||||
/**
|
||||
Posted when the synchronizer is synced to latest height
|
||||
*/
|
||||
/// Posted when the synchronizer is synced to latest height
|
||||
static let synchronizerSynced = Notification.Name("SDKSyncronizerSynced")
|
||||
|
||||
/**
|
||||
Posted when the synchronizer is stopped
|
||||
*/
|
||||
|
||||
/// Posted when the synchronizer is stopped
|
||||
static let synchronizerStopped = Notification.Name("SDKSyncronizerStopped")
|
||||
|
||||
/**
|
||||
Posted when the synchronizer loses connection
|
||||
*/
|
||||
/// Posted when the synchronizer loses connection
|
||||
static let synchronizerDisconnected = Notification.Name("SDKSyncronizerDisconnected")
|
||||
|
||||
/**
|
||||
Posted when the synchronizer starts syncing
|
||||
*/
|
||||
/// Posted when the synchronizer starts syncing
|
||||
static let synchronizerSyncing = Notification.Name("SDKSyncronizerSyncing")
|
||||
|
||||
/**
|
||||
Posted when synchronizer starts downloading blocks
|
||||
*/
|
||||
|
||||
/// Posted when synchronizer starts downloading blocks
|
||||
static let synchronizerDownloading = Notification.Name("SDKSyncronizerDownloading")
|
||||
|
||||
/**
|
||||
Posted when synchronizer starts validating blocks
|
||||
*/
|
||||
|
||||
/// Posted when synchronizer starts validating blocks
|
||||
static let synchronizerValidating = Notification.Name("SDKSyncronizerValidating")
|
||||
|
||||
/**
|
||||
Posted when synchronizer starts scanning blocks
|
||||
*/
|
||||
|
||||
/// Posted when synchronizer starts scanning blocks
|
||||
static let synchronizerScanning = Notification.Name("SDKSyncronizerScanning")
|
||||
|
||||
/**
|
||||
Posted when the synchronizer starts Enhancing
|
||||
*/
|
||||
|
||||
/// Posted when the synchronizer starts Enhancing
|
||||
static let synchronizerEnhancing = Notification.Name("SDKSyncronizerEnhancing")
|
||||
|
||||
/**
|
||||
Posted when the synchronizer starts fetching UTXOs
|
||||
*/
|
||||
|
||||
/// Posted when the synchronizer starts fetching UTXOs
|
||||
static let synchronizerFetching = Notification.Name("SDKSyncronizerFetching")
|
||||
|
||||
/**
|
||||
Posted when the synchronizer finds a pendingTransaction that hast been newly mined
|
||||
- Note: query userInfo on NotificationKeys.minedTransaction for the transaction
|
||||
*/
|
||||
|
||||
/// Posted when the synchronizer finds a pendingTransaction that hast been newly mined
|
||||
/// - Note: query userInfo on NotificationKeys.minedTransaction for the transaction
|
||||
static let synchronizerMinedTransaction = Notification.Name("synchronizerMinedTransaction")
|
||||
|
||||
/**
|
||||
Posted when the synchronizer finds a mined transaction
|
||||
- Note: query userInfo on NotificationKeys.foundTransactions for the [ConfirmedTransactionEntity]. This notification could arrive in a background thread.
|
||||
*/
|
||||
|
||||
/// Posted when the synchronizer finds a mined transaction
|
||||
/// - Note: query userInfo on NotificationKeys.foundTransactions for
|
||||
/// the `[ConfirmedTransactionEntity]`. This notification could arrive in a background thread.
|
||||
static let synchronizerFoundTransactions = Notification.Name("synchronizerFoundTransactions")
|
||||
|
||||
/**
|
||||
Posted when the synchronizer presents an error
|
||||
- Note: query userInfo on NotificationKeys.error for an error
|
||||
*/
|
||||
|
||||
/// Posted when the synchronizer presents an error
|
||||
/// - Note: query userInfo on NotificationKeys.error for an error
|
||||
static let synchronizerFailed = Notification.Name("SDKSynchronizerFailed")
|
||||
|
||||
static let synchronizerConnectionStateChanged = Notification.Name("SynchronizerConnectionStateChanged")
|
||||
}
|
||||
|
||||
/**
|
||||
Synchronizer implementation for UIKit and iOS 12+
|
||||
*/
|
||||
/// Synchronizer implementation for UIKit and iOS 12+
|
||||
// swiftlint:disable type_body_length
|
||||
public class SDKSynchronizer: Synchronizer {
|
||||
|
||||
public enum NotificationKeys {
|
||||
public static let progress = "SDKSynchronizer.progress"
|
||||
public static let blockHeight = "SDKSynchronizer.blockHeight"
|
||||
|
@ -132,10 +109,8 @@ public class SDKSynchronizer: Synchronizer {
|
|||
private var transactionRepository: TransactionRepository
|
||||
private var utxoRepository: UnspentTransactionOutputRepository
|
||||
|
||||
/**
|
||||
Creates an SDKSynchronizer instance
|
||||
- Parameter initializer: a wallet Initializer object
|
||||
*/
|
||||
/// Creates an SDKSynchronizer instance
|
||||
/// - Parameter initializer: a wallet Initializer object
|
||||
public convenience init(initializer: Initializer) throws {
|
||||
try self.init(
|
||||
status: .unprepared,
|
||||
|
@ -183,10 +158,9 @@ public class SDKSynchronizer: Synchronizer {
|
|||
self.status = .disconnected
|
||||
}
|
||||
|
||||
/**
|
||||
Starts the synchronizer
|
||||
- Throws: CompactBlockProcessorError when failures occur
|
||||
*/
|
||||
|
||||
/// Starts the synchronizer
|
||||
/// - Throws: CompactBlockProcessorError when failures occur
|
||||
public func start(retry: Bool = false) throws {
|
||||
switch status {
|
||||
case .unprepared:
|
||||
|
@ -204,10 +178,8 @@ public class SDKSynchronizer: Synchronizer {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Stops the synchronizer
|
||||
*/
|
||||
|
||||
/// Stops the synchronizer
|
||||
public func stop() {
|
||||
guard status != .stopped, status != .disconnected else {
|
||||
LoggerProxy.info("attempted to stop when status was: \(status)")
|
||||
|
@ -482,7 +454,7 @@ public class SDKSynchronizer: Synchronizer {
|
|||
|
||||
// MARK: Synchronizer methods
|
||||
|
||||
// swiftlint:disable:next function_parameter_count
|
||||
@available(*, deprecated, message: "This function will be removed soon, use the one reveiving a `Zatoshi` value instead")
|
||||
public func sendToAddress(
|
||||
spendingKey: String,
|
||||
zatoshi: Int64,
|
||||
|
@ -490,6 +462,25 @@ public class SDKSynchronizer: Synchronizer {
|
|||
memo: String?,
|
||||
from accountIndex: Int,
|
||||
resultBlock: @escaping (Result<PendingTransactionEntity, Error>) -> Void
|
||||
) {
|
||||
sendToAddress(
|
||||
spendingKey: spendingKey,
|
||||
zatoshi: Zatoshi(zatoshi),
|
||||
toAddress: toAddress,
|
||||
memo: memo,
|
||||
from: accountIndex,
|
||||
resultBlock: resultBlock
|
||||
)
|
||||
}
|
||||
|
||||
// swiftlint:disable:next function_parameter_count
|
||||
public func sendToAddress(
|
||||
spendingKey: String,
|
||||
zatoshi: Zatoshi,
|
||||
toAddress: String,
|
||||
memo: String?,
|
||||
from accountIndex: Int,
|
||||
resultBlock: @escaping (Result<PendingTransactionEntity, Error>) -> Void
|
||||
) {
|
||||
initializer.downloadParametersIfNeeded { downloadResult in
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
|
@ -532,7 +523,7 @@ public class SDKSynchronizer: Synchronizer {
|
|||
let viewingKey = try derivationTool.deriveViewingKey(spendingKey: spendingKey)
|
||||
let zAddr = try derivationTool.deriveShieldedAddress(viewingKey: viewingKey)
|
||||
|
||||
let shieldingSpend = try transactionManager.initSpend(zatoshi: Int(tBalance.verified), toAddress: zAddr, memo: memo, from: 0)
|
||||
let shieldingSpend = try transactionManager.initSpend(zatoshi: tBalance.verified, toAddress: zAddr, memo: memo, from: 0)
|
||||
|
||||
transactionManager.encodeShieldingTransaction(
|
||||
spendingKey: spendingKey,
|
||||
|
@ -567,7 +558,7 @@ public class SDKSynchronizer: Synchronizer {
|
|||
// swiftlint:disable:next function_parameter_count
|
||||
func createToAddress(
|
||||
spendingKey: String,
|
||||
zatoshi: Int64,
|
||||
zatoshi: Zatoshi,
|
||||
toAddress: String,
|
||||
memo: String?,
|
||||
from accountIndex: Int,
|
||||
|
@ -575,7 +566,7 @@ public class SDKSynchronizer: Synchronizer {
|
|||
) {
|
||||
do {
|
||||
let spend = try transactionManager.initSpend(
|
||||
zatoshi: Int(zatoshi),
|
||||
zatoshi: zatoshi,
|
||||
toAddress: toAddress,
|
||||
memo: memo,
|
||||
from: accountIndex
|
||||
|
@ -671,15 +662,24 @@ public class SDKSynchronizer: Synchronizer {
|
|||
public func refreshUTXOs(address: String, from height: BlockHeight, result: @escaping (Result<RefreshedUTXOs, Error>) -> Void) {
|
||||
self.blockProcessor.refreshUTXOs(tAddress: address, startHeight: height, result: result)
|
||||
}
|
||||
|
||||
@available(*, deprecated, message: "This function will be removed soon, use the one returning a `Zatoshi` value instead")
|
||||
public func getShieldedBalance(accountIndex: Int = 0) -> Int64 {
|
||||
initializer.getBalance(account: accountIndex).amount
|
||||
}
|
||||
|
||||
public func getShieldedBalance(accountIndex: Int = 0) -> Zatoshi {
|
||||
initializer.getBalance(account: accountIndex)
|
||||
}
|
||||
|
||||
|
||||
@available(*, deprecated, message: "This function will be removed soon, use the one returning a `Zatoshi` value instead")
|
||||
public func getShieldedVerifiedBalance(accountIndex: Int = 0) -> Int64 {
|
||||
initializer.getVerifiedBalance(account: accountIndex).amount
|
||||
}
|
||||
|
||||
public func getShieldedVerifiedBalance(accountIndex: Int = 0) -> Zatoshi {
|
||||
initializer.getVerifiedBalance(account: accountIndex)
|
||||
}
|
||||
|
||||
|
||||
public func getShieldedAddress(accountIndex: Int) -> SaplingShieldedAddress? {
|
||||
blockProcessor.getShieldedAddress(accountIndex: accountIndex)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import Foundation
|
||||
|
||||
enum TransactionManagerError: Error {
|
||||
case couldNotCreateSpend(toAddress: String, account: Int, zatoshi: Int)
|
||||
case couldNotCreateSpend(toAddress: String, account: Int, zatoshi: Zatoshi)
|
||||
case encodingFailed(PendingTransactionEntity)
|
||||
case updateFailed(PendingTransactionEntity)
|
||||
case notPending(PendingTransactionEntity)
|
||||
|
@ -39,7 +39,7 @@ class PersistentTransactionManager: OutboundTransactionManager {
|
|||
}
|
||||
|
||||
func initSpend(
|
||||
zatoshi: Int,
|
||||
zatoshi: Zatoshi,
|
||||
toAddress: String,
|
||||
memo: String?,
|
||||
from accountIndex: Int
|
||||
|
@ -149,7 +149,7 @@ class PersistentTransactionManager: OutboundTransactionManager {
|
|||
do {
|
||||
let encodedTransaction = try self.encoder.createTransaction(
|
||||
spendingKey: spendingKey,
|
||||
zatoshi: pendingTransaction.value,
|
||||
zatoshi: pendingTransaction.intValue,
|
||||
to: pendingTransaction.toAddress,
|
||||
memo: pendingTransaction.memo?.asZcashTransactionMemo(),
|
||||
from: pendingTransaction.accountIndex
|
||||
|
|
|
@ -14,7 +14,7 @@ transactions through to completion.
|
|||
*/
|
||||
|
||||
protocol OutboundTransactionManager {
|
||||
func initSpend(zatoshi: Int, toAddress: String, memo: String?, from accountIndex: Int) throws -> PendingTransactionEntity
|
||||
func initSpend(zatoshi: Zatoshi, toAddress: String, memo: String?, from accountIndex: Int) throws -> PendingTransactionEntity
|
||||
|
||||
func encodeShieldingTransaction(spendingKey: String, tsk: String, pendingTransaction: PendingTransactionEntity, result: @escaping (Result<PendingTransactionEntity, Error>) -> Void)
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Clamped.swift
|
||||
// secant-testnet
|
||||
//
|
||||
// Created by Francisco Gindre on 10/20/21.
|
||||
//
|
||||
// credits: https://iteo.medium.com/swift-property-wrappers-how-to-use-them-right-77095817d1b
|
||||
import Foundation
|
||||
|
||||
/**
|
||||
Limits a value to an enclosing range
|
||||
*/
|
||||
@propertyWrapper
|
||||
public struct Clamped<Value: Comparable> {
|
||||
private var value: Value
|
||||
private let range: ClosedRange<Value>
|
||||
public var wrappedValue: Value {
|
||||
get { value }
|
||||
set { value = clamp(newValue, using: range) }
|
||||
}
|
||||
|
||||
init(wrappedValue: Value, _ range: ClosedRange<Value>) {
|
||||
self.value = wrappedValue
|
||||
self.range = range
|
||||
|
||||
value = clamp(wrappedValue, using: range)
|
||||
}
|
||||
|
||||
private func clamp(_ value: Value, using range: ClosedRange<Value>) -> Value {
|
||||
min(range.upperBound, max(range.lowerBound, value))
|
||||
}
|
||||
}
|
|
@ -18,7 +18,7 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
// TODO: Parameterize this from environment
|
||||
let testRecipientAddress = "zs17mg40levjezevuhdp5pqrd52zere7r7vrjgdwn5sj4xsqtm20euwahv9anxmwr3y3kmwuz8k55a"
|
||||
|
||||
let sendAmount: Int64 = 1000
|
||||
let sendAmount = Zatoshi(1000)
|
||||
var birthday: BlockHeight = 663150
|
||||
let defaultLatestHeight: BlockHeight = 663175
|
||||
var coordinator: TestCoordinator!
|
||||
|
@ -87,8 +87,8 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
|
||||
var shouldContinue = false
|
||||
let receivedTxHeight: BlockHeight = 663188
|
||||
var initialTotalBalance: Int64 = -1
|
||||
var initialVerifiedBalance: Int64 = -1
|
||||
var initialTotalBalance = Zatoshi(-1)
|
||||
var initialVerifiedBalance = Zatoshi(-1)
|
||||
self.expectedReorgHeight = receivedTxHeight + 1
|
||||
|
||||
/*
|
||||
|
@ -128,8 +128,8 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
3. sync up to received_Tx_height
|
||||
*/
|
||||
let receivedTxExpectation = XCTestExpectation(description: "received tx")
|
||||
var receivedTxTotalBalance = Int64(-1)
|
||||
var receivedTxVerifiedBalance = Int64(-1)
|
||||
var receivedTxTotalBalance = Zatoshi(-1)
|
||||
var receivedTxVerifiedBalance = Zatoshi(-1)
|
||||
|
||||
try coordinator.sync(completion: { synchro in
|
||||
synchronizer = synchro
|
||||
|
@ -153,7 +153,7 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
/*
|
||||
3a. verify that balance is previous balance + tx amount
|
||||
*/
|
||||
XCTAssertEqual(receivedTxTotalBalance, initialTotalBalance + Int64(receivedTx.value))
|
||||
XCTAssertEqual(receivedTxTotalBalance, initialTotalBalance + receivedTx.value)
|
||||
XCTAssertEqual(receivedTxVerifiedBalance, initialVerifiedBalance)
|
||||
|
||||
/*
|
||||
|
@ -192,8 +192,8 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
*/
|
||||
let reorgSyncexpectation = XCTestExpectation(description: "reorg expectation")
|
||||
|
||||
var afterReorgTxTotalBalance = Int64(-1)
|
||||
var afterReorgTxVerifiedBalance = Int64(-1)
|
||||
var afterReorgTxTotalBalance = Zatoshi(-1)
|
||||
var afterReorgTxVerifiedBalance = Zatoshi(-1)
|
||||
|
||||
try coordinator.sync(completion: { synchronizer in
|
||||
afterReorgTxTotalBalance = synchronizer.initializer.getBalance()
|
||||
|
@ -218,8 +218,8 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
*/
|
||||
let finalsyncExpectation = XCTestExpectation(description: "final sync")
|
||||
|
||||
var finalReorgTxTotalBalance = Int64(-1)
|
||||
var finalReorgTxVerifiedBalance = Int64(-1)
|
||||
var finalReorgTxTotalBalance = Zatoshi(-1)
|
||||
var finalReorgTxVerifiedBalance = Zatoshi(-1)
|
||||
|
||||
try coordinator.applyStaged(blockheight: reorgedTxheight + 1)
|
||||
sleep(3)
|
||||
|
@ -239,7 +239,7 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
|
||||
XCTAssertEqual(reorgedTx.minedHeight, reorgedTxheight)
|
||||
XCTAssertEqual(initialVerifiedBalance, finalReorgTxVerifiedBalance)
|
||||
XCTAssertEqual(initialTotalBalance + Int64(receivedTx.value), finalReorgTxTotalBalance)
|
||||
XCTAssertEqual(initialTotalBalance + receivedTx.value, finalReorgTxTotalBalance)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -271,7 +271,7 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
func testReorgChangesOutboundTxIndex() throws {
|
||||
try FakeChainBuilder.buildChain(darksideWallet: self.coordinator.service, branchID: branchID, chainName: chainName)
|
||||
let receivedTxHeight: BlockHeight = 663188
|
||||
var initialTotalBalance: Int64 = -1
|
||||
var initialTotalBalance = Zatoshi(-1)
|
||||
|
||||
/*
|
||||
2. applyStaged(received_Tx_height)
|
||||
|
@ -294,7 +294,7 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
let sendExpectation = XCTestExpectation(description: "sendToAddress")
|
||||
var pendingEntity: PendingTransactionEntity?
|
||||
var error: Error?
|
||||
let sendAmount: Int64 = 10000
|
||||
let sendAmount = Zatoshi(10000)
|
||||
|
||||
/*
|
||||
4. create transaction
|
||||
|
@ -382,7 +382,7 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
*/
|
||||
let pMinedHeight = synchronizer.pendingTransactions.first?.minedHeight
|
||||
XCTAssertEqual(pMinedHeight, sentTxHeight)
|
||||
XCTAssertEqual(initialTotalBalance - sendAmount - Int64(1000), synchronizer.initializer.getBalance()) // fee change on this branch
|
||||
XCTAssertEqual(initialTotalBalance - sendAmount - Zatoshi(1000), synchronizer.initializer.getBalance()) // fee change on this branch
|
||||
afterReOrgExpectation.fulfill()
|
||||
},
|
||||
error: self.handleError
|
||||
|
@ -408,8 +408,10 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
wait(for: [lastSyncExpectation], timeout: 5)
|
||||
|
||||
XCTAssertEqual(coordinator.synchronizer.pendingTransactions.count, 0)
|
||||
XCTAssertEqual(initialTotalBalance - Int64(pendingTx.value) - Int64(1000), coordinator.synchronizer.initializer.getVerifiedBalance())
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), coordinator.synchronizer.initializer.getVerifiedBalance())
|
||||
XCTAssertEqual(initialTotalBalance - pendingTx.value - Zatoshi(1000), coordinator.synchronizer.initializer.getVerifiedBalance())
|
||||
|
||||
let resultingBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
XCTAssertEqual(resultingBalance, coordinator.synchronizer.initializer.getVerifiedBalance())
|
||||
}
|
||||
|
||||
func testIncomingTransactionIndexChange() throws {
|
||||
|
@ -422,8 +424,8 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
sleep(1)
|
||||
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
|
||||
|
||||
var preReorgTotalBalance = Int64(0)
|
||||
var preReorgVerifiedBalance = Int64(0)
|
||||
var preReorgTotalBalance = Zatoshi.zero
|
||||
var preReorgVerifiedBalance = Zatoshi.zero
|
||||
try coordinator.sync(completion: { synchronizer in
|
||||
preReorgTotalBalance = synchronizer.initializer.getBalance()
|
||||
preReorgVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
|
||||
|
@ -442,8 +444,8 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
|
||||
let afterReorgSync = XCTestExpectation(description: "after reorg sync")
|
||||
|
||||
var postReorgTotalBalance = Int64(0)
|
||||
var postReorgVerifiedBalance = Int64(0)
|
||||
var postReorgTotalBalance = Zatoshi.zero
|
||||
var postReorgVerifiedBalance = Zatoshi.zero
|
||||
try coordinator.sync(completion: { synchronizer in
|
||||
postReorgTotalBalance = synchronizer.initializer.getBalance()
|
||||
postReorgVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
|
||||
|
@ -462,8 +464,8 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
try coordinator.applyStaged(blockheight: receivedTxHeight - 1)
|
||||
sleep(2)
|
||||
let expectation = XCTestExpectation(description: "sync to \(receivedTxHeight - 1) expectation")
|
||||
var initialBalance: Int64 = -1
|
||||
var initialVerifiedBalance: Int64 = -1
|
||||
var initialBalance = Zatoshi(-1)
|
||||
var initialVerifiedBalance = Zatoshi(-1)
|
||||
try coordinator.sync(completion: { synchronizer in
|
||||
initialBalance = synchronizer.initializer.getBalance()
|
||||
initialVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
|
||||
|
@ -477,8 +479,8 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
sleep(2)
|
||||
let afterTxSyncExpectation = XCTestExpectation(description: "sync to \(afterTxHeight) expectation")
|
||||
|
||||
var afterTxBalance: Int64 = -1
|
||||
var afterTxVerifiedBalance: Int64 = -1
|
||||
var afterTxBalance = Zatoshi(-1)
|
||||
var afterTxVerifiedBalance = Zatoshi(-1)
|
||||
try coordinator.sync(completion: { synchronizer in
|
||||
afterTxBalance = synchronizer.initializer.getBalance()
|
||||
afterTxVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
|
||||
|
@ -502,8 +504,8 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
sleep(2)
|
||||
let afterReorgExpectation = XCTestExpectation(description: "after reorg expectation")
|
||||
|
||||
var afterReOrgBalance: Int64 = -1
|
||||
var afterReOrgVerifiedBalance: Int64 = -1
|
||||
var afterReOrgBalance = Zatoshi(-1)
|
||||
var afterReOrgVerifiedBalance = Zatoshi(-1)
|
||||
try coordinator.sync(completion: { synchronizer in
|
||||
afterReOrgBalance = synchronizer.initializer.getBalance()
|
||||
afterReOrgVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
|
||||
|
@ -543,8 +545,8 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
*/
|
||||
let firstSyncExpectation = XCTestExpectation(description: "first sync test expectation")
|
||||
|
||||
var initialBalance: Int64 = -1
|
||||
var initialVerifiedBalance: Int64 = -1
|
||||
var initialBalance = Zatoshi(-1)
|
||||
var initialVerifiedBalance = Zatoshi(-1)
|
||||
var incomingTx: ConfirmedTransactionEntity?
|
||||
try coordinator.sync(completion: { _ in
|
||||
firstSyncExpectation.fulfill()
|
||||
|
@ -622,8 +624,8 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
let finalHeight = BlockHeight(663200)
|
||||
try coordinator.applyStaged(blockheight: txReorgHeight)
|
||||
let firstSyncExpectation = XCTestExpectation(description: "first sync test expectation")
|
||||
var initialBalance: Int64 = -1
|
||||
var initialVerifiedBalance: Int64 = -1
|
||||
var initialBalance = Zatoshi(-1)
|
||||
var initialVerifiedBalance = Zatoshi(-1)
|
||||
try coordinator.sync(completion: { synchronizer in
|
||||
initialBalance = synchronizer.initializer.getBalance()
|
||||
initialVerifiedBalance = synchronizer.initializer.getVerifiedBalance()
|
||||
|
@ -696,7 +698,7 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
wait(for: [firstSyncExpectation], timeout: 5)
|
||||
|
||||
sleep(1)
|
||||
let initialTotalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
let initialTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
|
||||
let sendExpectation = XCTestExpectation(description: "send expectation")
|
||||
var pendingEntity: PendingTransactionEntity?
|
||||
|
@ -706,7 +708,7 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
*/
|
||||
coordinator.synchronizer.sendToAddress(
|
||||
spendingKey: self.coordinator.spendingKeys!.first!,
|
||||
zatoshi: 20000,
|
||||
zatoshi: Zatoshi(20000),
|
||||
toAddress: self.testRecipientAddress,
|
||||
memo: "this is a test",
|
||||
from: 0,
|
||||
|
@ -877,12 +879,12 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
)
|
||||
|
||||
XCTAssertEqual(
|
||||
initialTotalBalance - Int64(newlyPendingTx.value) - Int64(1000),
|
||||
initialTotalBalance - newlyPendingTx.value - Zatoshi(1000),
|
||||
coordinator.synchronizer.initializer.getBalance()
|
||||
)
|
||||
|
||||
XCTAssertEqual(
|
||||
initialTotalBalance - Int64(newlyPendingTx.value) - Int64(1000),
|
||||
initialTotalBalance - newlyPendingTx.value - Zatoshi(1000),
|
||||
coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
)
|
||||
}
|
||||
|
@ -917,8 +919,8 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
|
||||
wait(for: [firstSyncExpectation], timeout: 5)
|
||||
|
||||
let initialBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
let initialVerifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let initialBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
let initialVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
guard let initialTxHeight = try coordinator.synchronizer.allReceivedTransactions().first?.minedHeight else {
|
||||
XCTFail("no incoming transaction found!")
|
||||
return
|
||||
|
@ -982,8 +984,8 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
|
||||
wait(for: [firstSyncExpectation], timeout: 5)
|
||||
|
||||
let initialTotalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
let initialVerifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let initialTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
let initialVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
|
||||
try coordinator.applyStaged(blockheight: reorgHeight)
|
||||
|
||||
|
@ -1056,7 +1058,7 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
wait(for: [firstSyncExpectation], timeout: 5)
|
||||
|
||||
sleep(1)
|
||||
let initialTotalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
let initialTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
|
||||
let sendExpectation = XCTestExpectation(description: "send expectation")
|
||||
var pendingEntity: PendingTransactionEntity?
|
||||
|
@ -1066,7 +1068,7 @@ class AdvancedReOrgTests: XCTestCase {
|
|||
*/
|
||||
coordinator.synchronizer.sendToAddress(
|
||||
spendingKey: self.coordinator.spendingKeys!.first!,
|
||||
zatoshi: 20000,
|
||||
zatoshi: Zatoshi(20000),
|
||||
toAddress: self.testRecipientAddress,
|
||||
memo: "this is a test",
|
||||
from: 0,
|
||||
|
|
|
@ -17,7 +17,7 @@ class BalanceTests: XCTestCase {
|
|||
|
||||
// TODO: Parameterize this from environment
|
||||
let testRecipientAddress = "zs17mg40levjezevuhdp5pqrd52zere7r7vrjgdwn5sj4xsqtm20euwahv9anxmwr3y3kmwuz8k55a"
|
||||
let sendAmount: Int64 = 1000
|
||||
let sendAmount = Zatoshi(1000)
|
||||
let defaultLatestHeight: BlockHeight = 663188
|
||||
let branchID = "2bb40e60"
|
||||
let chainName = "main"
|
||||
|
@ -64,12 +64,12 @@ class BalanceTests: XCTestCase {
|
|||
wait(for: [firstSyncExpectation], timeout: 12)
|
||||
// 2 check that there are no unconfirmed funds
|
||||
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
|
||||
XCTAssertEqual(verifiedBalance, totalBalance)
|
||||
|
||||
let maxBalance = verifiedBalance - Int64(network.constants.defaultFee(for: defaultLatestHeight))
|
||||
let maxBalance = verifiedBalance - network.constants.defaultFee(for: defaultLatestHeight)
|
||||
|
||||
// 3 create a transaction for the max amount possible
|
||||
// 4 send the transaction
|
||||
|
@ -179,8 +179,8 @@ class BalanceTests: XCTestCase {
|
|||
|
||||
XCTAssertNil(confirmedPending, "pending, now confirmed transaction found")
|
||||
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), 0)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), 0)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), .zero)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), .zero)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -208,12 +208,12 @@ class BalanceTests: XCTestCase {
|
|||
wait(for: [firstSyncExpectation], timeout: 12)
|
||||
// 2 check that there are no unconfirmed funds
|
||||
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
|
||||
XCTAssertEqual(verifiedBalance, totalBalance)
|
||||
|
||||
let maxBalanceMinusOne = verifiedBalance - Int64(network.constants.defaultFee(for: defaultLatestHeight)) - 1
|
||||
let maxBalanceMinusOne = verifiedBalance - network.constants.defaultFee(for: defaultLatestHeight) - Zatoshi(1)
|
||||
|
||||
// 3 create a transaction for the max amount possible
|
||||
// 4 send the transaction
|
||||
|
@ -321,8 +321,8 @@ class BalanceTests: XCTestCase {
|
|||
|
||||
XCTAssertNil(confirmedPending, "pending, now confirmed transaction found")
|
||||
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), 1)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), 1)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), Zatoshi(1))
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), Zatoshi(1))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -350,12 +350,12 @@ class BalanceTests: XCTestCase {
|
|||
wait(for: [firstSyncExpectation], timeout: 12)
|
||||
// 2 check that there are no unconfirmed funds
|
||||
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
|
||||
XCTAssertEqual(verifiedBalance, totalBalance)
|
||||
|
||||
let maxBalanceMinusOne = 100000 - network.constants.defaultFee(for: defaultLatestHeight)
|
||||
let maxBalanceMinusOne = Zatoshi(100000) - network.constants.defaultFee(for: defaultLatestHeight)
|
||||
|
||||
// 3 create a transaction for the max amount possible
|
||||
// 4 send the transaction
|
||||
|
@ -462,8 +462,8 @@ class BalanceTests: XCTestCase {
|
|||
|
||||
XCTAssertNil(confirmedPending, "pending, now confirmed transaction found")
|
||||
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), 100000)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), 100000)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), Zatoshi(100000))
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), Zatoshi(100000))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -499,17 +499,17 @@ class BalanceTests: XCTestCase {
|
|||
return
|
||||
}
|
||||
|
||||
let presendVerifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let presendVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
|
||||
/*
|
||||
there's more zatoshi to send than network fee
|
||||
*/
|
||||
XCTAssertTrue(presendVerifiedBalance >= (Int64(network.constants.defaultFee(for: defaultLatestHeight)) + sendAmount))
|
||||
XCTAssertTrue(presendVerifiedBalance >= network.constants.defaultFee(for: defaultLatestHeight) + sendAmount)
|
||||
|
||||
var pendingTx: PendingTransactionEntity?
|
||||
coordinator.synchronizer.sendToAddress(
|
||||
spendingKey: spendingKey,
|
||||
zatoshi: Int64(sendAmount),
|
||||
zatoshi: sendAmount,
|
||||
toAddress: testRecipientAddress,
|
||||
memo: "test send \(self.description) \(Date().description)",
|
||||
from: 0,
|
||||
|
@ -529,7 +529,7 @@ class BalanceTests: XCTestCase {
|
|||
}
|
||||
)
|
||||
|
||||
XCTAssertTrue(coordinator.synchronizer.initializer.getVerifiedBalance() > 0)
|
||||
XCTAssertTrue(coordinator.synchronizer.initializer.getVerifiedBalance() > .zero)
|
||||
wait(for: [sentTransactionExpectation], timeout: 12)
|
||||
|
||||
// sync and mine
|
||||
|
@ -579,7 +579,7 @@ class BalanceTests: XCTestCase {
|
|||
/*
|
||||
basic health check
|
||||
*/
|
||||
XCTAssertEqual(Int64(transaction.value), self.sendAmount)
|
||||
XCTAssertEqual(transaction.value, self.sendAmount)
|
||||
|
||||
/*
|
||||
build up repos to get data
|
||||
|
@ -631,9 +631,9 @@ class BalanceTests: XCTestCase {
|
|||
|
||||
self.verifiedBalanceValidation(
|
||||
previousBalance: presendVerifiedBalance,
|
||||
spentNoteValue: Int64(sentNote.value),
|
||||
changeValue: Int64(receivedNote.value),
|
||||
sentAmount: Int64(self.sendAmount),
|
||||
spentNoteValue: Zatoshi(Int64(sentNote.value)),
|
||||
changeValue: Zatoshi(Int64(receivedNote.value)),
|
||||
sentAmount: self.sendAmount,
|
||||
currentVerifiedBalance: self.coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
)
|
||||
}
|
||||
|
@ -671,16 +671,16 @@ class BalanceTests: XCTestCase {
|
|||
return
|
||||
}
|
||||
|
||||
let presendBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
let presendBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
|
||||
// there's more zatoshi to send than network fee
|
||||
XCTAssertTrue(presendBalance >= (Int64(network.constants.defaultFee(for: defaultLatestHeight)) + sendAmount))
|
||||
XCTAssertTrue(presendBalance >= network.constants.defaultFee(for: defaultLatestHeight) + sendAmount)
|
||||
var pendingTx: PendingTransactionEntity?
|
||||
|
||||
var error: Error?
|
||||
coordinator.synchronizer.sendToAddress(
|
||||
spendingKey: spendingKey,
|
||||
zatoshi: Int64(sendAmount),
|
||||
zatoshi: sendAmount,
|
||||
toAddress: testRecipientAddress,
|
||||
memo: "test send \(self.description) \(Date().description)",
|
||||
from: 0,
|
||||
|
@ -698,7 +698,7 @@ class BalanceTests: XCTestCase {
|
|||
}
|
||||
)
|
||||
|
||||
XCTAssertTrue(coordinator.synchronizer.initializer.getVerifiedBalance() > 0)
|
||||
XCTAssertTrue(coordinator.synchronizer.initializer.getVerifiedBalance() > .zero)
|
||||
wait(for: [sentTransactionExpectation], timeout: 12)
|
||||
|
||||
if let e = error {
|
||||
|
@ -711,11 +711,11 @@ class BalanceTests: XCTestCase {
|
|||
return
|
||||
}
|
||||
|
||||
XCTAssertEqual(Int64(transaction.value), self.sendAmount)
|
||||
XCTAssertEqual(transaction.value, self.sendAmount)
|
||||
|
||||
XCTAssertEqual(
|
||||
self.coordinator.synchronizer.initializer.getBalance(),
|
||||
presendBalance - Int64(self.sendAmount) - network.constants.defaultFee(for: defaultLatestHeight)
|
||||
presendBalance - self.sendAmount - network.constants.defaultFee(for: defaultLatestHeight)
|
||||
)
|
||||
|
||||
XCTAssertNil(transaction.errorCode)
|
||||
|
@ -747,7 +747,7 @@ class BalanceTests: XCTestCase {
|
|||
wait(for: [mineExpectation], timeout: 5)
|
||||
|
||||
XCTAssertEqual(
|
||||
presendBalance - self.sendAmount - Int64(network.constants.defaultFee(for: defaultLatestHeight)),
|
||||
presendBalance - self.sendAmount - network.constants.defaultFee(for: defaultLatestHeight),
|
||||
coordinator.synchronizer.initializer.getBalance()
|
||||
)
|
||||
}
|
||||
|
@ -777,7 +777,7 @@ class BalanceTests: XCTestCase {
|
|||
wait(for: [syncedExpectation], timeout: 5)
|
||||
|
||||
XCTAssertEqual(coordinator.synchronizer.clearedTransactions.count, 2)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), 200000)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), Zatoshi(200000))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -820,8 +820,8 @@ class BalanceTests: XCTestCase {
|
|||
|
||||
wait(for: [syncedExpectation], timeout: 6)
|
||||
|
||||
let previousVerifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let previousTotalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
let previousVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let previousTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
|
||||
guard let spendingKeys = coordinator.spendingKeys?.first else {
|
||||
XCTFail("null spending keys")
|
||||
|
@ -835,7 +835,7 @@ class BalanceTests: XCTestCase {
|
|||
var pendingTx: PendingTransactionEntity?
|
||||
coordinator.synchronizer.sendToAddress(
|
||||
spendingKey: spendingKeys,
|
||||
zatoshi: Int64(sendAmount),
|
||||
zatoshi: sendAmount,
|
||||
toAddress: testRecipientAddress,
|
||||
memo: memo,
|
||||
from: 0,
|
||||
|
@ -890,7 +890,7 @@ class BalanceTests: XCTestCase {
|
|||
/*
|
||||
There’s a sent transaction matching the amount sent to the given zAddr
|
||||
*/
|
||||
XCTAssertEqual(Int64(confirmedTx.value), self.sendAmount)
|
||||
XCTAssertEqual(confirmedTx.value, self.sendAmount)
|
||||
XCTAssertEqual(confirmedTx.toAddress, self.testRecipientAddress)
|
||||
XCTAssertEqual(confirmedTx.memo?.asZcashTransactionMemo(), memo)
|
||||
|
||||
|
@ -934,7 +934,7 @@ class BalanceTests: XCTestCase {
|
|||
*/
|
||||
XCTAssertEqual(
|
||||
previousVerifiedBalance - self.sendAmount - self.network.constants.defaultFee(for: self.defaultLatestHeight),
|
||||
Int64(receivedNote.value)
|
||||
Zatoshi(Int64(receivedNote.value))
|
||||
)
|
||||
|
||||
/*
|
||||
|
@ -942,16 +942,16 @@ class BalanceTests: XCTestCase {
|
|||
*/
|
||||
self.verifiedBalanceValidation(
|
||||
previousBalance: previousVerifiedBalance,
|
||||
spentNoteValue: Int64(sentNote.value),
|
||||
changeValue: Int64(receivedNote.value),
|
||||
sentAmount: Int64(self.sendAmount),
|
||||
spentNoteValue: Zatoshi(Int64(sentNote.value)),
|
||||
changeValue: Zatoshi(Int64(receivedNote.value)),
|
||||
sentAmount: self.sendAmount,
|
||||
currentVerifiedBalance: synchronizer.initializer.getVerifiedBalance()
|
||||
)
|
||||
|
||||
self.totalBalanceValidation(
|
||||
totalBalance: synchronizer.initializer.getBalance(),
|
||||
previousTotalbalance: previousTotalBalance,
|
||||
sentAmount: Int64(self.sendAmount)
|
||||
sentAmount: self.sendAmount
|
||||
)
|
||||
|
||||
syncToMinedheightExpectation.fulfill()
|
||||
|
@ -1001,8 +1001,8 @@ class BalanceTests: XCTestCase {
|
|||
return
|
||||
}
|
||||
|
||||
let previousVerifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let previousTotalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
let previousVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let previousTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
let sendExpectation = XCTestExpectation(description: "send expectation")
|
||||
var pendingTx: PendingTransactionEntity?
|
||||
coordinator.synchronizer.sendToAddress(
|
||||
|
@ -1089,21 +1089,21 @@ class BalanceTests: XCTestCase {
|
|||
check if (previous available funds - spent note + change) equals to (previous available funds - sent amount)
|
||||
*/
|
||||
func verifiedBalanceValidation(
|
||||
previousBalance: Int64,
|
||||
spentNoteValue: Int64,
|
||||
changeValue: Int64,
|
||||
sentAmount: Int64,
|
||||
currentVerifiedBalance: Int64
|
||||
previousBalance: Zatoshi,
|
||||
spentNoteValue: Zatoshi,
|
||||
changeValue: Zatoshi,
|
||||
sentAmount: Zatoshi,
|
||||
currentVerifiedBalance: Zatoshi
|
||||
) {
|
||||
XCTAssertEqual(previousBalance - spentNoteValue + changeValue, currentVerifiedBalance - sentAmount)
|
||||
}
|
||||
|
||||
func totalBalanceValidation(
|
||||
totalBalance: Int64,
|
||||
previousTotalbalance: Int64,
|
||||
sentAmount: Int64
|
||||
totalBalance: Zatoshi,
|
||||
previousTotalbalance: Zatoshi,
|
||||
sentAmount: Zatoshi
|
||||
) {
|
||||
XCTAssertEqual(totalBalance, previousTotalbalance - sentAmount - Int64(network.constants.defaultFee(for: defaultLatestHeight)))
|
||||
XCTAssertEqual(totalBalance, previousTotalbalance - sentAmount - network.constants.defaultFee(for: defaultLatestHeight))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ class NetworkUpgradeTests: XCTestCase {
|
|||
|
||||
// TODO: Parameterize this from environment
|
||||
let testRecipientAddress = "ztestsapling12k9m98wmpjts2m56wc60qzhgsfvlpxcwah268xk5yz4h942sd58jy3jamqyxjwums6hw7kfa4cc"
|
||||
let sendAmount: Int64 = 1000
|
||||
let sendAmount = Zatoshi(1000)
|
||||
let branchID = "2bb40e60"
|
||||
let chainName = "main"
|
||||
|
||||
|
@ -63,7 +63,7 @@ class NetworkUpgradeTests: XCTestCase {
|
|||
}, error: self.handleError)
|
||||
|
||||
wait(for: [firstSyncExpectation], timeout: 120)
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
guard verifiedBalance > network.constants.defaultFee(for: activationHeight) else {
|
||||
XCTFail("not enough balance to continue test")
|
||||
return
|
||||
|
@ -74,7 +74,7 @@ class NetworkUpgradeTests: XCTestCase {
|
|||
|
||||
let sendExpectation = XCTestExpectation(description: "send expectation")
|
||||
var pendingEntity: PendingTransactionEntity?
|
||||
let spendAmount: Int64 = 10000
|
||||
let spendAmount = Zatoshi(10000)
|
||||
|
||||
/*
|
||||
send transaction to recipient address
|
||||
|
@ -163,7 +163,7 @@ class NetworkUpgradeTests: XCTestCase {
|
|||
|
||||
let sendExpectation = XCTestExpectation(description: "send expectation")
|
||||
var pendingEntity: PendingTransactionEntity?
|
||||
let spendAmount: Int64 = 10000
|
||||
let spendAmount = Zatoshi(10000)
|
||||
|
||||
/*
|
||||
send transaction to recipient address
|
||||
|
@ -227,12 +227,12 @@ class NetworkUpgradeTests: XCTestCase {
|
|||
}, error: self.handleError)
|
||||
|
||||
wait(for: [firstSyncExpectation], timeout: 120)
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: activationHeight))
|
||||
|
||||
let sendExpectation = XCTestExpectation(description: "send expectation")
|
||||
var pendingEntity: PendingTransactionEntity?
|
||||
let spendAmount: Int64 = 10000
|
||||
let spendAmount = Zatoshi(10000)
|
||||
|
||||
/*
|
||||
send transaction to recipient address
|
||||
|
@ -318,14 +318,14 @@ class NetworkUpgradeTests: XCTestCase {
|
|||
try coordinator.applyStaged(blockheight: activationHeight - 10)
|
||||
sleep(3)
|
||||
|
||||
let verifiedBalancePreActivation = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let verifiedBalancePreActivation: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
|
||||
try coordinator.sync(completion: { _ in
|
||||
firstSyncExpectation.fulfill()
|
||||
}, error: self.handleError)
|
||||
|
||||
wait(for: [firstSyncExpectation], timeout: 120)
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
guard verifiedBalance > network.constants.defaultFee(for: activationHeight) else {
|
||||
XCTFail("balance is not enough to continue with this test")
|
||||
return
|
||||
|
@ -333,7 +333,7 @@ class NetworkUpgradeTests: XCTestCase {
|
|||
|
||||
let sendExpectation = XCTestExpectation(description: "send expectation")
|
||||
var pendingEntity: PendingTransactionEntity?
|
||||
let spendAmount: Int64 = 10000
|
||||
let spendAmount = Zatoshi(10000)
|
||||
|
||||
/*
|
||||
send transaction to recipient address
|
||||
|
@ -421,7 +421,7 @@ class NetworkUpgradeTests: XCTestCase {
|
|||
|
||||
wait(for: [firstSyncExpectation], timeout: 120)
|
||||
|
||||
let preActivationBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let preActivationBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
|
||||
try coordinator.applyStaged(blockheight: activationHeight + 30)
|
||||
sleep(2)
|
||||
|
@ -436,14 +436,16 @@ class NetworkUpgradeTests: XCTestCase {
|
|||
XCTFail("this test requires funds received after activation height")
|
||||
return
|
||||
}
|
||||
let postActivationBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let postActivationBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
|
||||
XCTAssertTrue(preActivationBalance < postActivationBalance, "This test requires that funds post activation are greater that pre activation")
|
||||
let sendExpectation = XCTestExpectation(description: "send expectation")
|
||||
var pendingEntity: PendingTransactionEntity?
|
||||
|
||||
// spend all the funds
|
||||
let spendAmount: Int64 = postActivationBalance - Int64(network.constants.defaultFee(for: activationHeight))
|
||||
let spendAmount = Zatoshi(
|
||||
postActivationBalance.amount - Int64(network.constants.defaultFee(for: activationHeight).amount)
|
||||
)
|
||||
|
||||
/*
|
||||
send transaction to recipient address
|
||||
|
@ -473,7 +475,7 @@ class NetworkUpgradeTests: XCTestCase {
|
|||
return
|
||||
}
|
||||
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), 0)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), .zero)
|
||||
}
|
||||
|
||||
func handleError(_ error: Error?) {
|
||||
|
|
|
@ -96,7 +96,7 @@ class PendingTransactionUpdatesTest: XCTestCase {
|
|||
coordinator.synchronizer.sendToAddress(
|
||||
// swiftlint:disable:next force_unwrapping
|
||||
spendingKey: self.coordinator.spendingKeys!.first!,
|
||||
zatoshi: 20000,
|
||||
zatoshi: Zatoshi(20000),
|
||||
toAddress: self.testRecipientAddress,
|
||||
memo: "this is a test",
|
||||
from: 0,
|
||||
|
|
|
@ -69,8 +69,8 @@ class RewindRescanTests: XCTestCase {
|
|||
try FakeChainBuilder.buildChain(darksideWallet: coordinator.service, branchID: branchID, chainName: chainName)
|
||||
|
||||
try coordinator.applyStaged(blockheight: defaultLatestHeight + 50)
|
||||
let initialVerifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let initialTotalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
let initialVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let initialTotalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
sleep(1)
|
||||
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
|
||||
|
||||
|
@ -79,8 +79,8 @@ class RewindRescanTests: XCTestCase {
|
|||
}, error: handleError)
|
||||
|
||||
wait(for: [firstSyncExpectation], timeout: 12)
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
// 2 check that there are no unconfirmed funds
|
||||
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
|
||||
XCTAssertEqual(verifiedBalance, totalBalance)
|
||||
|
@ -118,7 +118,7 @@ class RewindRescanTests: XCTestCase {
|
|||
let newChaintTip = defaultLatestHeight + 10000
|
||||
try coordinator.applyStaged(blockheight: newChaintTip)
|
||||
sleep(3)
|
||||
let initialVerifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let initialVerifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let firstSyncExpectation = XCTestExpectation(description: "first sync expectation")
|
||||
|
||||
try coordinator.sync(
|
||||
|
@ -129,8 +129,8 @@ class RewindRescanTests: XCTestCase {
|
|||
)
|
||||
|
||||
wait(for: [firstSyncExpectation], timeout: 20)
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
// 2 check that there are no unconfirmed funds
|
||||
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
|
||||
XCTAssertEqual(verifiedBalance, totalBalance)
|
||||
|
@ -168,7 +168,7 @@ class RewindRescanTests: XCTestCase {
|
|||
let sendExpectation = XCTestExpectation(description: "after rewind expectation")
|
||||
coordinator.synchronizer.sendToAddress(
|
||||
spendingKey: coordinator.spendingKey,
|
||||
zatoshi: 1000,
|
||||
zatoshi: Zatoshi(1000),
|
||||
toAddress: testRecipientAddress,
|
||||
memo: nil,
|
||||
from: 0
|
||||
|
@ -176,7 +176,7 @@ class RewindRescanTests: XCTestCase {
|
|||
sendExpectation.fulfill()
|
||||
switch result {
|
||||
case .success(let pendingTx):
|
||||
XCTAssertEqual(1000, pendingTx.value)
|
||||
XCTAssertEqual(Zatoshi(1000), pendingTx.value)
|
||||
case .failure(let error):
|
||||
XCTFail("sending fail: \(error)")
|
||||
}
|
||||
|
@ -198,8 +198,8 @@ class RewindRescanTests: XCTestCase {
|
|||
}, error: handleError)
|
||||
|
||||
wait(for: [firstSyncExpectation], timeout: 12)
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
// 2 check that there are no unconfirmed funds
|
||||
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
|
||||
XCTAssertEqual(verifiedBalance, totalBalance)
|
||||
|
@ -253,12 +253,12 @@ class RewindRescanTests: XCTestCase {
|
|||
wait(for: [firstSyncExpectation], timeout: 12)
|
||||
// 2 check that there are no unconfirmed funds
|
||||
|
||||
let verifiedBalance = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance = coordinator.synchronizer.initializer.getBalance()
|
||||
let verifiedBalance: Zatoshi = coordinator.synchronizer.initializer.getVerifiedBalance()
|
||||
let totalBalance: Zatoshi = coordinator.synchronizer.initializer.getBalance()
|
||||
XCTAssertTrue(verifiedBalance > network.constants.defaultFee(for: defaultLatestHeight))
|
||||
XCTAssertEqual(verifiedBalance, totalBalance)
|
||||
|
||||
let maxBalance = verifiedBalance - Int64(network.constants.defaultFee(for: defaultLatestHeight))
|
||||
let maxBalance = verifiedBalance - network.constants.defaultFee(for: defaultLatestHeight)
|
||||
|
||||
// 3 create a transaction for the max amount possible
|
||||
// 4 send the transaction
|
||||
|
@ -390,7 +390,7 @@ class RewindRescanTests: XCTestCase {
|
|||
.first(where: { $0.rawTransactionId == pendingTx.rawTransactionId })
|
||||
|
||||
XCTAssertNil(confirmedPending, "pending, now confirmed transaction found")
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), 0)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), 0)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getBalance(), .zero)
|
||||
XCTAssertEqual(coordinator.synchronizer.initializer.getVerifiedBalance(), .zero)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ class ShieldFundsTests: XCTestCase {
|
|||
// TODO: Parameterize this from environment
|
||||
let testRecipientAddress = "zs17mg40levjezevuhdp5pqrd52zere7r7vrjgdwn5sj4xsqtm20euwahv9anxmwr3y3kmwuz8k55a"
|
||||
|
||||
let sendAmount: Int64 = 1000
|
||||
let sendAmount = Zatoshi(1000)
|
||||
var birthday: BlockHeight = 1631000
|
||||
var coordinator: TestCoordinator!
|
||||
var syncedExpectation = XCTestExpectation(description: "synced")
|
||||
|
@ -90,8 +90,8 @@ class ShieldFundsTests: XCTestCase {
|
|||
|
||||
let utxoHeight = BlockHeight(1631177)
|
||||
var shouldContinue = false
|
||||
var initialTotalBalance: Int64 = -1
|
||||
var initialVerifiedBalance: Int64 = -1
|
||||
var initialTotalBalance = Zatoshi(-1)
|
||||
var initialVerifiedBalance = Zatoshi(-1)
|
||||
var initialTransparentBalance: WalletBalance = try coordinator.synchronizer.getTransparentBalance(accountIndex: 0)
|
||||
|
||||
let utxo = try GetAddressUtxosReply(jsonString: """
|
||||
|
@ -128,12 +128,12 @@ class ShieldFundsTests: XCTestCase {
|
|||
}
|
||||
|
||||
// at this point the balance should be all zeroes for transparent and shielded funds
|
||||
XCTAssertEqual(initialTotalBalance, 0)
|
||||
XCTAssertEqual(initialVerifiedBalance, 0)
|
||||
XCTAssertEqual(initialTotalBalance, Zatoshi.zero)
|
||||
XCTAssertEqual(initialVerifiedBalance, Zatoshi.zero)
|
||||
initialTransparentBalance = try coordinator.synchronizer.getTransparentBalance(accountIndex: 0)
|
||||
|
||||
XCTAssertEqual(initialTransparentBalance.total, 0)
|
||||
XCTAssertEqual(initialTransparentBalance.verified, 0)
|
||||
XCTAssertEqual(initialTransparentBalance.total, .zero)
|
||||
XCTAssertEqual(initialTransparentBalance.verified, .zero)
|
||||
|
||||
// 4. Add the UTXO to darksidewalletd fake chain
|
||||
try coordinator.service.addUTXO(utxo)
|
||||
|
@ -163,8 +163,8 @@ class ShieldFundsTests: XCTestCase {
|
|||
// and 10000 zatoshi of total (not verified) transparent funds.
|
||||
let tFundsDetectedBalance = try coordinator.synchronizer.getTransparentBalance(accountIndex: 0)
|
||||
|
||||
XCTAssertEqual(tFundsDetectedBalance.total, 10000)
|
||||
XCTAssertEqual(tFundsDetectedBalance.verified, 10000) //FIXME: this should be zero
|
||||
XCTAssertEqual(tFundsDetectedBalance.total, Zatoshi(10000))
|
||||
XCTAssertEqual(tFundsDetectedBalance.verified, Zatoshi(10000)) //FIXME: this should be zero
|
||||
|
||||
let tFundsConfirmationSyncExpectation = XCTestExpectation(description: "t funds confirmation")
|
||||
|
||||
|
@ -189,8 +189,8 @@ class ShieldFundsTests: XCTestCase {
|
|||
// the transparent funds should be 10000 zatoshis both total and verified
|
||||
let confirmedTFundsBalance = try coordinator.synchronizer.getTransparentBalance(accountIndex: 0)
|
||||
|
||||
XCTAssertEqual(confirmedTFundsBalance.total, 10000)
|
||||
XCTAssertEqual(confirmedTFundsBalance.verified, 10000)
|
||||
XCTAssertEqual(confirmedTFundsBalance.total, Zatoshi(10000))
|
||||
XCTAssertEqual(confirmedTFundsBalance.verified, Zatoshi(10000))
|
||||
|
||||
// 9. shield the funds
|
||||
let shieldFundsExpectation = XCTestExpectation(description: "shield funds")
|
||||
|
@ -221,7 +221,7 @@ class ShieldFundsTests: XCTestCase {
|
|||
|
||||
case .success(let pendingTx):
|
||||
shouldContinue = true
|
||||
XCTAssertEqual(pendingTx.value, 10000)
|
||||
XCTAssertEqual(pendingTx.value, Zatoshi(10000))
|
||||
shieldingPendingTx = pendingTx
|
||||
}
|
||||
shieldFundsExpectation.fulfill()
|
||||
|
@ -235,9 +235,9 @@ class ShieldFundsTests: XCTestCase {
|
|||
// when funds are shielded the UTXOs should be marked as spend and not shown on the balance.
|
||||
// now balance should be zero shielded, zero transaparent.
|
||||
// verify that the balance has been marked as spent regardless of confirmation
|
||||
XCTAssertEqual(postShieldingBalance.verified, 10000) //FIXME: this should be zero
|
||||
XCTAssertEqual(postShieldingBalance.total, 10000) //FIXME: this should be zero
|
||||
XCTAssertEqual(coordinator.synchronizer.getShieldedBalance(), 0)
|
||||
XCTAssertEqual(postShieldingBalance.verified, Zatoshi(10000)) //FIXME: this should be zero
|
||||
XCTAssertEqual(postShieldingBalance.total, Zatoshi(10000)) //FIXME: this should be zero
|
||||
XCTAssertEqual(coordinator.synchronizer.getShieldedBalance(), .zero)
|
||||
|
||||
// 10. clear the UTXO from darksidewalletd's cache
|
||||
try coordinator.service.clearAddedUTXOs()
|
||||
|
@ -281,9 +281,9 @@ class ShieldFundsTests: XCTestCase {
|
|||
// Fees at the time of writing the tests are 1000 zatoshi as defined on ZIP-313
|
||||
let postShieldingShieldedBalance = try coordinator.synchronizer.getTransparentBalance(accountIndex: 0)
|
||||
|
||||
XCTAssertEqual(postShieldingShieldedBalance.total, 10000) //FIXME: this should be zero
|
||||
XCTAssertEqual(postShieldingShieldedBalance.verified, 10000) //FIXME: this should be zero
|
||||
XCTAssertEqual(coordinator.synchronizer.getShieldedBalance(), 0) //FIXME: this should be 9000
|
||||
XCTAssertEqual(postShieldingShieldedBalance.total, Zatoshi(10000)) //FIXME: this should be zero
|
||||
XCTAssertEqual(postShieldingShieldedBalance.verified, Zatoshi(10000)) //FIXME: this should be zero
|
||||
XCTAssertEqual(coordinator.synchronizer.getShieldedBalance(), .zero) //FIXME: this should be 9000
|
||||
|
||||
// 14. proceed confirm the shielded funds by staging ten more blocks
|
||||
try coordinator.service.applyStaged(nextLatestHeight: utxoHeight + 10 + 1 + 10)
|
||||
|
@ -311,10 +311,10 @@ class ShieldFundsTests: XCTestCase {
|
|||
|
||||
XCTAssertNotNil(clearedTransaction)
|
||||
|
||||
XCTAssertEqual(coordinator.synchronizer.getShieldedBalance(), 9000)
|
||||
XCTAssertEqual(coordinator.synchronizer.getShieldedBalance(), Zatoshi(9000))
|
||||
let postShieldingConfirmationShieldedBalance = try coordinator.synchronizer.getTransparentBalance(accountIndex: 0)
|
||||
XCTAssertEqual(postShieldingConfirmationShieldedBalance.total, 0)
|
||||
XCTAssertEqual(postShieldingConfirmationShieldedBalance.verified, 0)
|
||||
XCTAssertEqual(postShieldingConfirmationShieldedBalance.total, .zero)
|
||||
XCTAssertEqual(postShieldingConfirmationShieldedBalance.verified, .zero)
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ class Z2TReceiveTests: XCTestCase {
|
|||
let sendExpectation = XCTestExpectation(description: "sendToAddress")
|
||||
var pendingEntity: PendingTransactionEntity?
|
||||
var error: Error?
|
||||
let sendAmount: Int64 = 10000
|
||||
let sendAmount = Zatoshi(10000)
|
||||
/*
|
||||
4. create transaction
|
||||
*/
|
||||
|
|
|
@ -125,7 +125,7 @@ class PendingTransactionRepositoryTests: XCTestCase {
|
|||
|
||||
func testUpdate() {
|
||||
let newAccountIndex = 1
|
||||
let newValue: Int = 123_456
|
||||
let newValue = Zatoshi(123_456)
|
||||
let transaction = createAndStoreMockedTransaction()
|
||||
|
||||
guard let id = transaction.id else {
|
||||
|
@ -174,6 +174,11 @@ class PendingTransactionRepositoryTests: XCTestCase {
|
|||
}
|
||||
|
||||
private func mockTransaction() -> PendingTransactionEntity {
|
||||
PendingTransaction(value: Int.random(in: 1 ... 1_000_000), toAddress: recipientAddress, memo: nil, account: 0)
|
||||
PendingTransaction(
|
||||
value: Zatoshi(Int64.random(in: 1 ... 1_000_000)),
|
||||
toAddress: recipientAddress,
|
||||
memo: nil,
|
||||
account: 0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
//
|
||||
// ZatoshiTests.swift
|
||||
// secantTests
|
||||
//
|
||||
// Created by Lukáš Korba on 26.05.2022.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import ZcashLightClientKit
|
||||
|
||||
class ZatoshiTests: XCTestCase {
|
||||
let usNumberFormatter = NumberFormatter()
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
usNumberFormatter.maximumFractionDigits = 8
|
||||
usNumberFormatter.maximumIntegerDigits = 8
|
||||
usNumberFormatter.numberStyle = .decimal
|
||||
usNumberFormatter.usesGroupingSeparator = true
|
||||
usNumberFormatter.locale = Locale(identifier: "en_US")
|
||||
}
|
||||
|
||||
func testLowerBound() throws {
|
||||
let number = Zatoshi(-Zatoshi.Constants.maxZatoshi - 1)
|
||||
|
||||
XCTAssertEqual(
|
||||
-Zatoshi.Constants.maxZatoshi,
|
||||
number.amount,
|
||||
"Zatoshi tests: `testLowerBound` the value is expected to be clamped to lower bound but it's \(number.amount)"
|
||||
)
|
||||
}
|
||||
|
||||
func testUpperBound() throws {
|
||||
let number = Zatoshi(Zatoshi.Constants.maxZatoshi + 1)
|
||||
|
||||
XCTAssertEqual(
|
||||
Zatoshi.Constants.maxZatoshi,
|
||||
number.amount,
|
||||
"Zatoshi tests: `testUpperBound` the value is expected to be clamped to upper bound but it's \(number.amount)"
|
||||
)
|
||||
}
|
||||
|
||||
func testAddingZatoshi() throws {
|
||||
let numberA1 = Zatoshi(100_000)
|
||||
let numberB1 = Zatoshi(200_000)
|
||||
let result1 = numberA1 + numberB1
|
||||
|
||||
XCTAssertEqual(
|
||||
result1.amount,
|
||||
Zatoshi(300_000).amount,
|
||||
"Zatoshi tests: `testAddingZatoshi` the value is expected to be 300_000 but it's \(result1.amount)"
|
||||
)
|
||||
|
||||
let numberA2 = Zatoshi(-100_000)
|
||||
let numberB2 = Zatoshi(200_000)
|
||||
let result2 = numberA2 + numberB2
|
||||
|
||||
XCTAssertEqual(
|
||||
result2.amount,
|
||||
Zatoshi(100_000).amount,
|
||||
"Zatoshi tests: `testAddingZatoshi` the value is expected to be 100_000 but it's \(result2.amount)"
|
||||
)
|
||||
|
||||
let numberA3 = Zatoshi(100_000)
|
||||
let numberB3 = Zatoshi(-200_000)
|
||||
let result3 = numberA3 + numberB3
|
||||
|
||||
XCTAssertEqual(
|
||||
result3.amount,
|
||||
Zatoshi(-100_000).amount,
|
||||
"Zatoshi tests: `testAddingZatoshi` the value is expected to be -100_000 but it's \(result3.amount)"
|
||||
)
|
||||
|
||||
let number = Zatoshi(Zatoshi.Constants.maxZatoshi)
|
||||
let result4 = number + number
|
||||
|
||||
XCTAssertEqual(
|
||||
result4.amount,
|
||||
Zatoshi.Constants.maxZatoshi,
|
||||
"Zatoshi tests: `testAddingZatoshi` the value is expected to be clapmed to upper bound but it's \(result4.amount)"
|
||||
)
|
||||
}
|
||||
|
||||
func testSubtractingZatoshi() throws {
|
||||
let numberA1 = Zatoshi(100_000)
|
||||
let numberB1 = Zatoshi(200_000)
|
||||
let result1 = numberA1 - numberB1
|
||||
|
||||
XCTAssertEqual(
|
||||
result1.amount,
|
||||
Zatoshi(-100_000).amount,
|
||||
"Zatoshi tests: `testSubtractingZatoshi` the value is expected to be -100_000 but it's \(result1.amount)"
|
||||
)
|
||||
|
||||
let numberA2 = Zatoshi(-100_000)
|
||||
let numberB2 = Zatoshi(200_000)
|
||||
let result2 = numberA2 - numberB2
|
||||
|
||||
XCTAssertEqual(
|
||||
result2.amount,
|
||||
Zatoshi(-300_000).amount,
|
||||
"Zatoshi tests: `testSubtractingZatoshi` the value is expected to be -300_000 but it's \(result2.amount)"
|
||||
)
|
||||
|
||||
let numberA3 = Zatoshi(100_000)
|
||||
let numberB3 = Zatoshi(-200_000)
|
||||
let result3 = numberA3 - numberB3
|
||||
|
||||
XCTAssertEqual(
|
||||
result3.amount,
|
||||
Zatoshi(300_000).amount,
|
||||
"Zatoshi tests: `testSubtractingZatoshi` the value is expected to be 300_000 but it's \(result3.amount)"
|
||||
)
|
||||
|
||||
let number = Zatoshi(-Zatoshi.Constants.maxZatoshi)
|
||||
let result4 = number + number
|
||||
|
||||
XCTAssertEqual(
|
||||
result4.amount,
|
||||
-Zatoshi.Constants.maxZatoshi,
|
||||
"Zatoshi tests: `testSubtractingZatoshi` the value is expected to be clapmed to lower bound but it's \(result4.amount)"
|
||||
)
|
||||
}
|
||||
|
||||
func testHumanReadable() throws {
|
||||
// result of this division is 1.4285714285714285714285714285714285714
|
||||
let number = Zatoshi.from(decimal: Decimal(200.0 / 140.0))
|
||||
|
||||
// IMPORTANT: the INTERNAL value of number is still 1.4285714285714285714285714285714285714!!!
|
||||
// but decimalString is rounding it to maximumFractionDigits set to be 8
|
||||
|
||||
// We can't compare it to double value 1.42857143 (or even Decimal(1.42857143))
|
||||
// so we convert it to string, in that case we are prooving it to be rendered
|
||||
// to the user exactly the way we want
|
||||
XCTAssertEqual(
|
||||
number.decimalString(formatter: usNumberFormatter),
|
||||
"1.42857143",
|
||||
"Zatoshi tests: the value is expected to be 1.42857143 but it's \(number.decimalString())"
|
||||
)
|
||||
}
|
||||
|
||||
func testUSDtoZecToUSD() throws {
|
||||
// The price of zec is $140, we want to send $200
|
||||
let usd2zec = NSDecimalNumber(decimal: 200.0 / 140.0)
|
||||
|
||||
XCTAssertEqual(
|
||||
usd2zec.decimalString,
|
||||
"1.42857143",
|
||||
"Zatoshi tests: `testUSDtoZatoshiToUSD` the value is expected to be 1.42857143 but it's \(usd2zec.decimalString)"
|
||||
)
|
||||
|
||||
// convert it back
|
||||
let zec2usd = NSDecimalNumber(decimal: usd2zec.decimalValue * 140.0)
|
||||
|
||||
XCTAssertEqual(
|
||||
zec2usd.decimalString,
|
||||
"200",
|
||||
"Zatoshi tests: `testUSDtoZatoshiToUSD` the value is expected to be 200 but it's \(zec2usd.decimalString)"
|
||||
)
|
||||
}
|
||||
|
||||
func testStringToZatoshi() throws {
|
||||
if let number = Zatoshi.from(decimalString: "200.0", formatter: usNumberFormatter) {
|
||||
XCTAssertEqual(
|
||||
number.decimalString(formatter: usNumberFormatter),
|
||||
"200",
|
||||
"Zatoshi tests: `testStringToZec` the value is expected to be 200 but it's \(number.decimalString())"
|
||||
)
|
||||
} else {
|
||||
XCTFail("Zatoshi tests: `testStringToZatoshi` failed to convert number.")
|
||||
}
|
||||
|
||||
if let number = Zatoshi.from(decimalString: "0.02836478949923", formatter: usNumberFormatter) {
|
||||
XCTAssertEqual(
|
||||
number.amount,
|
||||
2_836_479,
|
||||
"Zatoshi tests: the value is expected to be 2_836_478 but it's \(number.amount)"
|
||||
)
|
||||
} else {
|
||||
XCTFail("Zatoshi tests: `testStringToZatoshi` failed to convert number.")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -80,7 +80,7 @@ class MockTransactionRepository {
|
|||
transactionIndex: index,
|
||||
raw: Data(),
|
||||
id: index,
|
||||
value: Int.random(in: 1 ... ZcashSDK.zatoshiPerZEC),
|
||||
value: Zatoshi(Int64.random(in: 1 ... Zatoshi.Constants.oneZecInZatoshi)),
|
||||
memo: nil,
|
||||
rawTransactionId: Data()
|
||||
)
|
||||
|
@ -96,7 +96,7 @@ class MockTransactionRepository {
|
|||
transactionIndex: index,
|
||||
raw: Data(),
|
||||
id: index,
|
||||
value: Int.random(in: 1 ... ZcashSDK.zatoshiPerZEC),
|
||||
value: Zatoshi(Int64.random(in: 1 ... Zatoshi.Constants.oneZecInZatoshi)),
|
||||
memo: nil,
|
||||
rawTransactionId: Data()
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue