- all issues refactored - previous transactions replaced by new data type from the SDK - unit tests fixed
This commit is contained in:
parent
1aca887800
commit
fdd6ff19c0
|
@ -2617,7 +2617,7 @@
|
||||||
repositoryURL = "https://github.com/zcash/ZcashLightClientKit/";
|
repositoryURL = "https://github.com/zcash/ZcashLightClientKit/";
|
||||||
requirement = {
|
requirement = {
|
||||||
kind = upToNextMajorVersion;
|
kind = upToNextMajorVersion;
|
||||||
minimumVersion = "0.17.0-beta";
|
minimumVersion = "0.18.0-beta";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
6654C7382715A38000901167 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = {
|
6654C7382715A38000901167 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = {
|
||||||
|
|
|
@ -41,8 +41,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/stephencelis/SQLite.swift.git",
|
"location" : "https://github.com/stephencelis/SQLite.swift.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "4d543d811ee644fa4cc4bfa0be996b4dd6ba0f54",
|
"revision" : "7a2e3cd27de56f6d396e84f63beefd0267b55ccb",
|
||||||
"version" : "0.13.3"
|
"version" : "0.14.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -203,8 +203,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/zcash-hackworks/zcash-light-client-ffi.git",
|
"location" : "https://github.com/zcash-hackworks/zcash-light-client-ffi.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "fad9802b907822d5a1877584c91f3786824521b7",
|
"revision" : "b6013b8b313523b2c72ce62dbdc17f6ffad3a500",
|
||||||
"version" : "0.1.0"
|
"version" : "0.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -212,8 +212,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/zcash/ZcashLightClientKit",
|
"location" : "https://github.com/zcash/ZcashLightClientKit",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "d9b85b40ad36ac5183f44b6db9805e44171ee988",
|
"revision" : "731c7bbf4514a90b879c5c15968cdb41ac728e3a",
|
||||||
"version" : "0.17.0-beta"
|
"version" : "0.18.0-beta"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -59,6 +59,8 @@ protocol SDKSynchronizerClient {
|
||||||
|
|
||||||
func getShieldedBalance() -> WalletBalance?
|
func getShieldedBalance() -> WalletBalance?
|
||||||
func getTransparentBalance() -> WalletBalance?
|
func getTransparentBalance() -> WalletBalance?
|
||||||
|
func getAllSentTransactions() -> Effect<[WalletEvent], Never>
|
||||||
|
func getAllReceivedTransactions() -> Effect<[WalletEvent], Never>
|
||||||
func getAllClearedTransactions() -> Effect<[WalletEvent], Never>
|
func getAllClearedTransactions() -> Effect<[WalletEvent], Never>
|
||||||
func getAllPendingTransactions() -> Effect<[WalletEvent], Never>
|
func getAllPendingTransactions() -> Effect<[WalletEvent], Never>
|
||||||
func getAllTransactions() -> Effect<[WalletEvent], Never>
|
func getAllTransactions() -> Effect<[WalletEvent], Never>
|
||||||
|
|
|
@ -113,10 +113,35 @@ class LiveSDKSynchronizerClient: SDKSynchronizerClient {
|
||||||
latestScannedSynchronizerState?.transparentBalance
|
latestScannedSynchronizerState?.transparentBalance
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getAllSentTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
|
if let transactions = try? synchronizer?.allSentTransactions() {
|
||||||
|
return Effect(value: transactions.map {
|
||||||
|
let memos = try? synchronizer?.getMemos(for: $0)
|
||||||
|
let transaction = TransactionState.init(transaction: $0, memos: memos)
|
||||||
|
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return .none
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAllReceivedTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
|
if let transactions = try? synchronizer?.allReceivedTransactions() {
|
||||||
|
return Effect(value: transactions.map {
|
||||||
|
let memos = try? synchronizer?.getMemos(for: $0)
|
||||||
|
let transaction = TransactionState.init(transaction: $0, memos: memos)
|
||||||
|
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return .none
|
||||||
|
}
|
||||||
|
|
||||||
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> {
|
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
if let clearedTransactions = try? synchronizer?.allClearedTransactions() {
|
if let transactions = try? synchronizer?.allClearedTransactions() {
|
||||||
return Effect(value: clearedTransactions.map {
|
return Effect(value: transactions.map {
|
||||||
let transaction = TransactionState.init(confirmedTransaction: $0, sent: ($0.toAddress != nil))
|
let memos = try? synchronizer?.getMemos(for: $0)
|
||||||
|
let transaction = TransactionState.init(transaction: $0, memos: memos)
|
||||||
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -125,9 +150,9 @@ class LiveSDKSynchronizerClient: SDKSynchronizerClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAllPendingTransactions() -> Effect<[WalletEvent], Never> {
|
func getAllPendingTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
if let pendingTransactions = try? synchronizer?.allPendingTransactions(),
|
if let transactions = try? synchronizer?.allPendingTransactions(),
|
||||||
let syncedBlockHeight = synchronizer?.latestScannedHeight {
|
let syncedBlockHeight = synchronizer?.latestScannedHeight {
|
||||||
return Effect(value: pendingTransactions.map {
|
return Effect(value: transactions.map {
|
||||||
let transaction = TransactionState.init(pendingTransaction: $0, latestBlockHeight: syncedBlockHeight)
|
let transaction = TransactionState.init(pendingTransaction: $0, latestBlockHeight: syncedBlockHeight)
|
||||||
return WalletEvent(id: transaction.id, state: .pending(transaction), timestamp: transaction.timestamp)
|
return WalletEvent(id: transaction.id, state: .pending(transaction), timestamp: transaction.timestamp)
|
||||||
})
|
})
|
||||||
|
@ -141,21 +166,21 @@ class LiveSDKSynchronizerClient: SDKSynchronizerClient {
|
||||||
let clearedTransactions = try? synchronizer?.allClearedTransactions(),
|
let clearedTransactions = try? synchronizer?.allClearedTransactions(),
|
||||||
let syncedBlockHeight = synchronizer?.latestScannedHeight {
|
let syncedBlockHeight = synchronizer?.latestScannedHeight {
|
||||||
let clearedTxs: [WalletEvent] = clearedTransactions.map {
|
let clearedTxs: [WalletEvent] = clearedTransactions.map {
|
||||||
let transaction = TransactionState.init(confirmedTransaction: $0, sent: ($0.toAddress != nil))
|
let transaction = TransactionState.init(transaction: $0)
|
||||||
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||||
}
|
}
|
||||||
let pendingTxs: [WalletEvent] = pendingTransactions.map {
|
let pendingTxs: [WalletEvent] = pendingTransactions.map {
|
||||||
let transaction = TransactionState.init(pendingTransaction: $0, latestBlockHeight: syncedBlockHeight)
|
let transaction = TransactionState.init(pendingTransaction: $0, latestBlockHeight: syncedBlockHeight)
|
||||||
return WalletEvent(id: transaction.id, state: .pending(transaction), timestamp: transaction.timestamp)
|
return WalletEvent(id: transaction.id, state: .pending(transaction), timestamp: transaction.timestamp)
|
||||||
}
|
}
|
||||||
|
let cTxs = clearedTxs.filter { transaction in
|
||||||
let txs = clearedTxs.filter { cleared in
|
|
||||||
pendingTxs.first { pending in
|
pendingTxs.first { pending in
|
||||||
pending.id == cleared.id
|
pending.id == transaction.id
|
||||||
} == nil
|
} == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return .merge(
|
return .merge(
|
||||||
Effect(value: txs),
|
Effect(value: cTxs),
|
||||||
Effect(value: pendingTxs)
|
Effect(value: pendingTxs)
|
||||||
)
|
)
|
||||||
.flatMap(Publishers.Sequence.init(sequence:))
|
.flatMap(Publishers.Sequence.init(sequence:))
|
||||||
|
|
|
@ -47,6 +47,56 @@ class MockSDKSynchronizerClient: SDKSynchronizerClient {
|
||||||
WalletBalance(verified: Zatoshi(12345000), total: Zatoshi(12345000))
|
WalletBalance(verified: Zatoshi(12345000), total: Zatoshi(12345000))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getAllSentTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
|
let mocked: [TransactionStateMockHelper] = [
|
||||||
|
TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(1), status: .paid(success: false), uuid: "aa11"),
|
||||||
|
TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(2), uuid: "bb22"),
|
||||||
|
TransactionStateMockHelper(date: 1651039000, amount: Zatoshi(3), status: .paid(success: true), uuid: "cc33"),
|
||||||
|
TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(4), uuid: "dd44"),
|
||||||
|
TransactionStateMockHelper(date: 1651039404, amount: Zatoshi(5), uuid: "ee55")
|
||||||
|
]
|
||||||
|
|
||||||
|
return Effect(
|
||||||
|
value:
|
||||||
|
mocked.map {
|
||||||
|
let transaction = TransactionState.placeholder(
|
||||||
|
amount: $0.amount,
|
||||||
|
fee: Zatoshi(10),
|
||||||
|
shielded: $0.shielded,
|
||||||
|
status: $0.status,
|
||||||
|
timestamp: $0.date,
|
||||||
|
uuid: $0.uuid
|
||||||
|
)
|
||||||
|
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp ?? 0)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAllReceivedTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
|
let mocked: [TransactionStateMockHelper] = [
|
||||||
|
TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(1), status: .paid(success: false), uuid: "aa11"),
|
||||||
|
TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(2), uuid: "bb22"),
|
||||||
|
TransactionStateMockHelper(date: 1651039000, amount: Zatoshi(3), status: .paid(success: true), uuid: "cc33"),
|
||||||
|
TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(4), uuid: "dd44"),
|
||||||
|
TransactionStateMockHelper(date: 1651039404, amount: Zatoshi(5), uuid: "ee55")
|
||||||
|
]
|
||||||
|
|
||||||
|
return Effect(
|
||||||
|
value:
|
||||||
|
mocked.map {
|
||||||
|
let transaction = TransactionState.placeholder(
|
||||||
|
amount: $0.amount,
|
||||||
|
fee: Zatoshi(10),
|
||||||
|
shielded: $0.shielded,
|
||||||
|
status: $0.status,
|
||||||
|
timestamp: $0.date,
|
||||||
|
uuid: $0.uuid
|
||||||
|
)
|
||||||
|
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp ?? 0)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> {
|
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
let mocked: [TransactionStateMockHelper] = [
|
let mocked: [TransactionStateMockHelper] = [
|
||||||
TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(1), status: .paid(success: false), uuid: "aa11"),
|
TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(1), status: .paid(success: false), uuid: "aa11"),
|
||||||
|
@ -67,7 +117,7 @@ class MockSDKSynchronizerClient: SDKSynchronizerClient {
|
||||||
timestamp: $0.date,
|
timestamp: $0.date,
|
||||||
uuid: $0.uuid
|
uuid: $0.uuid
|
||||||
)
|
)
|
||||||
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp ?? 0)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -132,9 +182,12 @@ class MockSDKSynchronizerClient: SDKSynchronizerClient {
|
||||||
to recipientAddress: Recipient,
|
to recipientAddress: Recipient,
|
||||||
memo: Memo?
|
memo: Memo?
|
||||||
) -> Effect<Result<TransactionState, NSError>, Never> {
|
) -> Effect<Result<TransactionState, NSError>, Never> {
|
||||||
|
var memos: [Memo]? = []
|
||||||
|
if let memo { memos?.append(memo) }
|
||||||
|
|
||||||
let transactionState = TransactionState(
|
let transactionState = TransactionState(
|
||||||
expirationHeight: 40,
|
expiryHeight: 40,
|
||||||
memo: memo,
|
memos: memos,
|
||||||
minedHeight: 50,
|
minedHeight: 50,
|
||||||
shielded: true,
|
shielded: true,
|
||||||
zAddress: "tteafadlamnelkqe",
|
zAddress: "tteafadlamnelkqe",
|
||||||
|
|
|
@ -42,6 +42,10 @@ class NoopSDKSynchronizer: SDKSynchronizerClient {
|
||||||
|
|
||||||
func getTransparentBalance() -> WalletBalance? { nil }
|
func getTransparentBalance() -> WalletBalance? { nil }
|
||||||
|
|
||||||
|
func getAllSentTransactions() -> Effect<[WalletEvent], Never> { Effect(value: []) }
|
||||||
|
|
||||||
|
func getAllReceivedTransactions() -> Effect<[WalletEvent], Never> { Effect(value: []) }
|
||||||
|
|
||||||
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> { Effect(value: []) }
|
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> { Effect(value: []) }
|
||||||
|
|
||||||
func getAllPendingTransactions() -> Effect<[WalletEvent], Never> { Effect(value: []) }
|
func getAllPendingTransactions() -> Effect<[WalletEvent], Never> { Effect(value: []) }
|
||||||
|
@ -69,7 +73,6 @@ class NoopSDKSynchronizer: SDKSynchronizerClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestSDKSynchronizerClient: SDKSynchronizerClient {
|
class TestSDKSynchronizerClient: SDKSynchronizerClient {
|
||||||
private(set) var blockProcessor: CompactBlockProcessor?
|
|
||||||
private(set) var notificationCenter: NotificationCenterClient
|
private(set) var notificationCenter: NotificationCenterClient
|
||||||
private(set) var synchronizer: SDKSynchronizer?
|
private(set) var synchronizer: SDKSynchronizer?
|
||||||
private(set) var stateChanged: CurrentValueSubject<SDKSynchronizerState, Never>
|
private(set) var stateChanged: CurrentValueSubject<SDKSynchronizerState, Never>
|
||||||
|
@ -97,6 +100,56 @@ class TestSDKSynchronizerClient: SDKSynchronizerClient {
|
||||||
|
|
||||||
func getTransparentBalance() -> WalletBalance? { nil }
|
func getTransparentBalance() -> WalletBalance? { nil }
|
||||||
|
|
||||||
|
func getAllSentTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
|
let mocked: [TransactionStateMockHelper] = [
|
||||||
|
TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(1), status: .paid(success: false), uuid: "aa11"),
|
||||||
|
TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(2), uuid: "bb22"),
|
||||||
|
TransactionStateMockHelper(date: 1651039000, amount: Zatoshi(3), status: .paid(success: true), uuid: "cc33"),
|
||||||
|
TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(4), uuid: "dd44"),
|
||||||
|
TransactionStateMockHelper(date: 1651039404, amount: Zatoshi(5), uuid: "ee55")
|
||||||
|
]
|
||||||
|
|
||||||
|
return Effect(
|
||||||
|
value:
|
||||||
|
mocked.map {
|
||||||
|
let transaction = TransactionState.placeholder(
|
||||||
|
amount: $0.amount,
|
||||||
|
fee: Zatoshi(10),
|
||||||
|
shielded: $0.shielded,
|
||||||
|
status: $0.status,
|
||||||
|
timestamp: $0.date,
|
||||||
|
uuid: $0.uuid
|
||||||
|
)
|
||||||
|
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAllReceivedTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
|
let mocked: [TransactionStateMockHelper] = [
|
||||||
|
TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(1), status: .paid(success: false), uuid: "aa11"),
|
||||||
|
TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(2), uuid: "bb22"),
|
||||||
|
TransactionStateMockHelper(date: 1651039000, amount: Zatoshi(3), status: .paid(success: true), uuid: "cc33"),
|
||||||
|
TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(4), uuid: "dd44"),
|
||||||
|
TransactionStateMockHelper(date: 1651039404, amount: Zatoshi(5), uuid: "ee55")
|
||||||
|
]
|
||||||
|
|
||||||
|
return Effect(
|
||||||
|
value:
|
||||||
|
mocked.map {
|
||||||
|
let transaction = TransactionState.placeholder(
|
||||||
|
amount: $0.amount,
|
||||||
|
fee: Zatoshi(10),
|
||||||
|
shielded: $0.shielded,
|
||||||
|
status: $0.status,
|
||||||
|
timestamp: $0.date,
|
||||||
|
uuid: $0.uuid
|
||||||
|
)
|
||||||
|
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> {
|
func getAllClearedTransactions() -> Effect<[WalletEvent], Never> {
|
||||||
let mocked: [TransactionStateMockHelper] = [
|
let mocked: [TransactionStateMockHelper] = [
|
||||||
TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(1), status: .paid(success: false), uuid: "aa11"),
|
TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(1), status: .paid(success: false), uuid: "aa11"),
|
||||||
|
|
|
@ -40,8 +40,8 @@ struct HomeReducer: ReducerProtocol {
|
||||||
Zatoshi.from(decimal: shieldedBalance.total.decimalValue.decimalValue * zecPrice)
|
Zatoshi.from(decimal: shieldedBalance.total.decimalValue.decimalValue * zecPrice)
|
||||||
}
|
}
|
||||||
|
|
||||||
var isDownloading: Bool {
|
var isSyncing: Bool {
|
||||||
if case .downloading = synchronizerStatusSnapshot.syncStatus {
|
if case .syncing = synchronizerStatusSnapshot.syncStatus {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -120,7 +120,7 @@ struct HomeReducer: ReducerProtocol {
|
||||||
|
|
||||||
case .synchronizerStateChanged(.synced):
|
case .synchronizerStateChanged(.synced):
|
||||||
return .merge(
|
return .merge(
|
||||||
sdkSynchronizer.getAllClearedTransactions()
|
sdkSynchronizer.getAllTransactions()
|
||||||
.receive(on: mainQueue)
|
.receive(on: mainQueue)
|
||||||
.map(HomeReducer.Action.updateWalletEvents)
|
.map(HomeReducer.Action.updateWalletEvents)
|
||||||
.eraseToEffect(),
|
.eraseToEffect(),
|
||||||
|
|
|
@ -118,8 +118,8 @@ extension HomeView {
|
||||||
VStack {
|
VStack {
|
||||||
ZStack {
|
ZStack {
|
||||||
CircularProgress(
|
CircularProgress(
|
||||||
outerCircleProgress: viewStore.isDownloading ? 0 : viewStore.synchronizerStatusSnapshot.progress,
|
outerCircleProgress: viewStore.isSyncing ? 0 : viewStore.synchronizerStatusSnapshot.progress,
|
||||||
innerCircleProgress: viewStore.isDownloading ? viewStore.synchronizerStatusSnapshot.progress : 1,
|
innerCircleProgress: 1,
|
||||||
maxSegments: viewStore.requiredTransactionConfirmations,
|
maxSegments: viewStore.requiredTransactionConfirmations,
|
||||||
innerCircleHidden: viewStore.isUpToDate
|
innerCircleHidden: viewStore.isUpToDate
|
||||||
)
|
)
|
||||||
|
|
|
@ -25,26 +25,26 @@ struct TransactionDetailView: View {
|
||||||
plainText("fee \(transaction.fee.decimalString()) ZEC", mark: .inactive)
|
plainText("fee \(transaction.fee.decimalString()) ZEC", mark: .inactive)
|
||||||
plainText("total amount \(transaction.totalAmount.decimalString()) ZEC", mark: .inactive)
|
plainText("total amount \(transaction.totalAmount.decimalString()) ZEC", mark: .inactive)
|
||||||
address(mark: .inactive, viewStore: viewStore)
|
address(mark: .inactive, viewStore: viewStore)
|
||||||
if let text = transaction.memo?.toString() { memo(text, viewStore, mark: .highlight) }
|
if let text = transaction.memos?.first?.toString() { memo(text, viewStore, mark: .highlight) }
|
||||||
confirmed(mark: .success, viewStore: viewStore)
|
confirmed(mark: .success, viewStore: viewStore)
|
||||||
case .pending:
|
case .pending:
|
||||||
plainText("You are sending \(transaction.zecAmount.decimalString()) ZEC")
|
plainText("You are sending \(transaction.zecAmount.decimalString()) ZEC")
|
||||||
plainText("Includes network fee \(transaction.fee.decimalString()) ZEC", mark: .inactive)
|
plainText("Includes network fee \(transaction.fee.decimalString()) ZEC", mark: .inactive)
|
||||||
plainText("total amount \(transaction.totalAmount.decimalString()) ZEC", mark: .inactive)
|
plainText("total amount \(transaction.totalAmount.decimalString()) ZEC", mark: .inactive)
|
||||||
if let text = transaction.memo?.toString() { memo(text, viewStore, mark: .inactive) }
|
if let text = transaction.memos?.first?.toString() { memo(text, viewStore, mark: .inactive) }
|
||||||
confirming(mark: .highlight, viewStore: viewStore)
|
confirming(mark: .highlight, viewStore: viewStore)
|
||||||
case .received:
|
case .received:
|
||||||
plainText("You received \(transaction.zecAmount.decimalString()) ZEC")
|
plainText("You received \(transaction.zecAmount.decimalString()) ZEC")
|
||||||
plainText("fee \(transaction.fee.decimalString()) ZEC")
|
plainText("fee \(transaction.fee.decimalString()) ZEC")
|
||||||
plainText("total amount \(transaction.totalAmount.decimalString()) ZEC")
|
plainText("total amount \(transaction.totalAmount.decimalString()) ZEC")
|
||||||
address(mark: .inactive, viewStore: viewStore)
|
address(mark: .inactive, viewStore: viewStore)
|
||||||
if let text = transaction.memo?.toString() { memo(text, viewStore, mark: .highlight) }
|
if let text = transaction.memos?.first?.toString() { memo(text, viewStore, mark: .highlight) }
|
||||||
confirmed(mark: .success, viewStore: viewStore)
|
confirmed(mark: .success, viewStore: viewStore)
|
||||||
case .failed:
|
case .failed:
|
||||||
plainText("You DID NOT send \(transaction.zecAmount.decimalString()) ZEC", mark: .fail)
|
plainText("You DID NOT send \(transaction.zecAmount.decimalString()) ZEC", mark: .fail)
|
||||||
plainText("Includes network fee \(transaction.fee.decimalString()) ZEC", mark: .inactive)
|
plainText("Includes network fee \(transaction.fee.decimalString()) ZEC", mark: .inactive)
|
||||||
plainText("total amount \(transaction.totalAmount.decimalString()) ZEC", mark: .inactive)
|
plainText("total amount \(transaction.totalAmount.decimalString()) ZEC", mark: .inactive)
|
||||||
if let text = transaction.memo?.toString() { memo(text, viewStore, mark: .inactive) }
|
if let text = transaction.memos?.first?.toString() { memo(text, viewStore, mark: .inactive) }
|
||||||
if let errorMessage = transaction.errorMessage {
|
if let errorMessage = transaction.errorMessage {
|
||||||
plainTwoColumnText(left: "Failed", right: errorMessage, mark: .fail)
|
plainTwoColumnText(left: "Failed", right: errorMessage, mark: .fail)
|
||||||
}
|
}
|
||||||
|
@ -68,11 +68,11 @@ extension TransactionDetailView {
|
||||||
Text("PENDING")
|
Text("PENDING")
|
||||||
Spacer()
|
Spacer()
|
||||||
case .failed:
|
case .failed:
|
||||||
Text("\(transaction.date.asHumanReadable())")
|
Text("\(transaction.date?.asHumanReadable() ?? "date not available")")
|
||||||
Spacer()
|
Spacer()
|
||||||
Text("FAILED")
|
Text("FAILED")
|
||||||
default:
|
default:
|
||||||
Text("\(transaction.date.asHumanReadable())")
|
Text("\(transaction.date?.asHumanReadable() ?? "date not available")")
|
||||||
Spacer()
|
Spacer()
|
||||||
Text("HEIGHT \(heightText)")
|
Text("HEIGHT \(heightText)")
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,8 @@ extension TransactionDetailView {
|
||||||
}
|
}
|
||||||
|
|
||||||
var heightText: String {
|
var heightText: String {
|
||||||
transaction.minedHeight > 0 ? String(transaction.minedHeight) : "unconfirmed"
|
guard let minedHeight = transaction.minedHeight else { return "unconfirmed" }
|
||||||
|
return minedHeight > 0 ? String(minedHeight) : "unconfirmed"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,12 +254,7 @@ struct TransactionDetail_Previews: PreviewProvider {
|
||||||
transaction:
|
transaction:
|
||||||
TransactionState(
|
TransactionState(
|
||||||
errorMessage: "possible roll back",
|
errorMessage: "possible roll back",
|
||||||
memo: try? Memo(string:
|
memos: [Memo.placeholder],
|
||||||
"""
|
|
||||||
Testing some long memo so I can see many lines of text \
|
|
||||||
instead of just one. This can take some time and I'm \
|
|
||||||
bored to write all this stuff.
|
|
||||||
"""),
|
|
||||||
minedHeight: 1_875_256,
|
minedHeight: 1_875_256,
|
||||||
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
||||||
fee: Zatoshi(1_000_000),
|
fee: Zatoshi(1_000_000),
|
||||||
|
@ -273,3 +269,13 @@ struct TransactionDetail_Previews: PreviewProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private extension Memo {
|
||||||
|
// swiftlint:disable:next force_try
|
||||||
|
static let placeholder = try! Memo(string:
|
||||||
|
"""
|
||||||
|
Testing some long memo so I can see many lines of text \
|
||||||
|
instead of just one. This can take some time and I'm \
|
||||||
|
bored to write all this stuff.
|
||||||
|
""")
|
||||||
|
}
|
||||||
|
|
|
@ -62,14 +62,14 @@ extension TransactionRowView {
|
||||||
var operationTitle: String {
|
var operationTitle: String {
|
||||||
switch transaction.status {
|
switch transaction.status {
|
||||||
case .paid(success: _):
|
case .paid(success: _):
|
||||||
return "You sent to"
|
return "You sent"
|
||||||
case .received:
|
case .received:
|
||||||
return "Unknown paid you"
|
return "Unknown paid you"
|
||||||
case .failed:
|
case .failed:
|
||||||
// TODO: [#392] final text to be provided (https://github.com/zcash/secant-ios-wallet/issues/392)
|
// TODO: [#392] final text to be provided (https://github.com/zcash/secant-ios-wallet/issues/392)
|
||||||
return "Transaction failed"
|
return "Transaction failed"
|
||||||
case .pending:
|
case .pending:
|
||||||
return "You are sending to"
|
return "You are sending"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ struct WalletEventsFlowReducer: ReducerProtocol {
|
||||||
if let latestMinedHeight = sdkSynchronizer.synchronizer?.latestScannedHeight {
|
if let latestMinedHeight = sdkSynchronizer.synchronizer?.latestScannedHeight {
|
||||||
state.latestMinedHeight = latestMinedHeight
|
state.latestMinedHeight = latestMinedHeight
|
||||||
}
|
}
|
||||||
return sdkSynchronizer.getAllTransactions()
|
return sdkSynchronizer.getAllClearedTransactions()
|
||||||
.receive(on: mainQueue)
|
.receive(on: mainQueue)
|
||||||
.map(WalletEventsFlowReducer.Action.updateWalletEvents)
|
.map(WalletEventsFlowReducer.Action.updateWalletEvents)
|
||||||
.eraseToEffect()
|
.eraseToEffect()
|
||||||
|
@ -71,7 +71,10 @@ struct WalletEventsFlowReducer: ReducerProtocol {
|
||||||
case .updateWalletEvents(let walletEvents):
|
case .updateWalletEvents(let walletEvents):
|
||||||
let sortedWalletEvents = walletEvents
|
let sortedWalletEvents = walletEvents
|
||||||
.sorted(by: { lhs, rhs in
|
.sorted(by: { lhs, rhs in
|
||||||
lhs.timestamp > rhs.timestamp
|
guard let lhsTimestamp = lhs.timestamp, let rhsTimestamp = rhs.timestamp else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return lhsTimestamp > rhsTimestamp
|
||||||
})
|
})
|
||||||
state.walletEvents = IdentifiedArrayOf(uniqueElements: sortedWalletEvents)
|
state.walletEvents = IdentifiedArrayOf(uniqueElements: sortedWalletEvents)
|
||||||
return .none
|
return .none
|
||||||
|
|
|
@ -21,18 +21,12 @@ struct SyncStatusSnapshot: Equatable {
|
||||||
|
|
||||||
static func snapshotFor(state: SyncStatus) -> SyncStatusSnapshot {
|
static func snapshotFor(state: SyncStatus) -> SyncStatusSnapshot {
|
||||||
switch state {
|
switch state {
|
||||||
case .downloading(let progress):
|
|
||||||
return SyncStatusSnapshot(state, "downloading - \(String(format: "%d%%", Int(progress.progress * 100.0)))", progress.progress)
|
|
||||||
|
|
||||||
case .enhancing(let enhanceProgress):
|
case .enhancing(let enhanceProgress):
|
||||||
return SyncStatusSnapshot(state, "Enhancing tx \(enhanceProgress.enhancedTransactions) of \(enhanceProgress.totalTransactions)")
|
return SyncStatusSnapshot(state, "Enhancing tx \(enhanceProgress.enhancedTransactions) of \(enhanceProgress.totalTransactions)")
|
||||||
|
|
||||||
case .fetching:
|
case .fetching:
|
||||||
return SyncStatusSnapshot(state, "fetching UTXOs")
|
return SyncStatusSnapshot(state, "fetching UTXOs")
|
||||||
|
|
||||||
case .scanning(let progress):
|
|
||||||
return SyncStatusSnapshot(state, "scanning - \(String(format: "%d%%", Int(progress.progress * 100.0)))", progress.progress)
|
|
||||||
|
|
||||||
case .disconnected:
|
case .disconnected:
|
||||||
return SyncStatusSnapshot(state, "disconnected 💔")
|
return SyncStatusSnapshot(state, "disconnected 💔")
|
||||||
|
|
||||||
|
@ -45,11 +39,11 @@ struct SyncStatusSnapshot: Equatable {
|
||||||
case .unprepared:
|
case .unprepared:
|
||||||
return SyncStatusSnapshot(state, "Unprepared 😅")
|
return SyncStatusSnapshot(state, "Unprepared 😅")
|
||||||
|
|
||||||
case .validating:
|
|
||||||
return SyncStatusSnapshot(state, "Validating")
|
|
||||||
|
|
||||||
case .error(let err):
|
case .error(let err):
|
||||||
return SyncStatusSnapshot(state, "Error: \(err.localizedDescription)")
|
return SyncStatusSnapshot(state, "Error: \(err.localizedDescription)")
|
||||||
|
|
||||||
|
case .syncing(let progress):
|
||||||
|
return SyncStatusSnapshot(state, "Syncing \(progress)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,27 +18,38 @@ struct TransactionState: Equatable, Identifiable {
|
||||||
}
|
}
|
||||||
|
|
||||||
var errorMessage: String?
|
var errorMessage: String?
|
||||||
var expirationHeight = -1
|
var expiryHeight: BlockHeight?
|
||||||
var memo: Memo?
|
var memos: [Memo]?
|
||||||
var minedHeight = -1
|
var minedHeight: BlockHeight?
|
||||||
var shielded = true
|
var shielded = true
|
||||||
var zAddress: String?
|
var zAddress: String?
|
||||||
|
|
||||||
var fee: Zatoshi
|
var fee: Zatoshi
|
||||||
var id: String
|
var id: String
|
||||||
var status: Status
|
var status: Status
|
||||||
var timestamp: TimeInterval
|
var timestamp: TimeInterval?
|
||||||
var zecAmount: Zatoshi
|
var zecAmount: Zatoshi
|
||||||
|
|
||||||
var address: String { zAddress ?? "" }
|
var address: String {
|
||||||
var date: Date { Date(timeIntervalSince1970: timestamp) }
|
zAddress ?? ""
|
||||||
var totalAmount: Zatoshi { Zatoshi(zecAmount.amount + fee.amount) }
|
}
|
||||||
|
|
||||||
|
var date: Date? {
|
||||||
|
guard let timestamp else { return nil }
|
||||||
|
|
||||||
|
return Date(timeIntervalSince1970: timestamp)
|
||||||
|
}
|
||||||
|
|
||||||
|
var totalAmount: Zatoshi {
|
||||||
|
Zatoshi(zecAmount.amount + fee.amount)
|
||||||
|
}
|
||||||
|
|
||||||
var viewOnlineURL: URL? {
|
var viewOnlineURL: URL? {
|
||||||
URL(string: "https://zcashblockexplorer.com/transactions/\(id)")
|
URL(string: "https://zcashblockexplorer.com/transactions/\(id)")
|
||||||
}
|
}
|
||||||
|
|
||||||
func confirmationsWith(_ latestMinedHeight: BlockHeight?) -> BlockHeight {
|
func confirmationsWith(_ latestMinedHeight: BlockHeight?) -> BlockHeight {
|
||||||
guard let latestMinedHeight = latestMinedHeight, minedHeight > 0, latestMinedHeight > 0 else {
|
guard let minedHeight, let latestMinedHeight, minedHeight > 0, latestMinedHeight > 0 else {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,18 +58,37 @@ struct TransactionState: Equatable, Identifiable {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TransactionState {
|
extension TransactionState {
|
||||||
init(confirmedTransaction: ConfirmedTransactionEntity, sent: Bool = false) {
|
init(transaction: ZcashTransaction.Overview, memos: [Memo]? = nil) {
|
||||||
timestamp = confirmedTransaction.blockTimeInSeconds
|
expiryHeight = transaction.expiryHeight
|
||||||
id = confirmedTransaction.transactionEntity.transactionId.toHexStringTxId()
|
minedHeight = transaction.minedHeight
|
||||||
shielded = true
|
fee = transaction.fee ?? Zatoshi(0)
|
||||||
status = sent ? .paid(success: confirmedTransaction.minedHeight > 0) : .received
|
id = transaction.rawID.toHexStringTxId()
|
||||||
zAddress = confirmedTransaction.toAddress
|
status = transaction.isSentTransaction ? .paid(success: minedHeight ?? 0 > 0) : .received
|
||||||
zecAmount = sent ? Zatoshi(-confirmedTransaction.value.amount) : confirmedTransaction.value
|
timestamp = transaction.blockTime
|
||||||
fee = Zatoshi(10)
|
zecAmount = transaction.isSentTransaction ? Zatoshi(-transaction.value.amount) : transaction.value
|
||||||
if let memoData = confirmedTransaction.memo {
|
self.memos = memos
|
||||||
self.memo = try? Memo(bytes: Array(memoData))
|
|
||||||
}
|
}
|
||||||
minedHeight = confirmedTransaction.minedHeight
|
|
||||||
|
init(transaction: ZcashTransaction.Sent, memos: [Memo]? = nil) {
|
||||||
|
expiryHeight = transaction.expiryHeight
|
||||||
|
minedHeight = transaction.minedHeight
|
||||||
|
fee = .zero
|
||||||
|
id = transaction.rawID?.toHexStringTxId() ?? ""
|
||||||
|
status = .paid(success: minedHeight ?? 0 > 0)
|
||||||
|
timestamp = transaction.blockTime
|
||||||
|
zecAmount = transaction.value
|
||||||
|
self.memos = memos
|
||||||
|
}
|
||||||
|
|
||||||
|
init(transaction: ZcashTransaction.Received, memos: [Memo]? = nil) {
|
||||||
|
expiryHeight = transaction.expiryHeight
|
||||||
|
minedHeight = transaction.minedHeight
|
||||||
|
fee = .zero
|
||||||
|
id = transaction.rawID?.toHexStringTxId() ?? ""
|
||||||
|
status = .received
|
||||||
|
timestamp = transaction.blockTime
|
||||||
|
zecAmount = transaction.value
|
||||||
|
self.memos = memos
|
||||||
}
|
}
|
||||||
|
|
||||||
init(pendingTransaction: PendingTransactionEntity, latestBlockHeight: BlockHeight? = nil) {
|
init(pendingTransaction: PendingTransactionEntity, latestBlockHeight: BlockHeight? = nil) {
|
||||||
|
@ -69,12 +99,9 @@ extension TransactionState {
|
||||||
pendingTransaction.minedHeight > 0 ?
|
pendingTransaction.minedHeight > 0 ?
|
||||||
.paid(success: pendingTransaction.isSubmitSuccess) :
|
.paid(success: pendingTransaction.isSubmitSuccess) :
|
||||||
.pending
|
.pending
|
||||||
expirationHeight = pendingTransaction.expiryHeight
|
expiryHeight = pendingTransaction.expiryHeight
|
||||||
zecAmount = pendingTransaction.value
|
zecAmount = pendingTransaction.value
|
||||||
fee = Zatoshi(10)
|
fee = Zatoshi(10)
|
||||||
if let memoData = pendingTransaction.memo {
|
|
||||||
self.memo = try? Memo(bytes: Array(memoData))
|
|
||||||
}
|
|
||||||
minedHeight = pendingTransaction.minedHeight
|
minedHeight = pendingTransaction.minedHeight
|
||||||
errorMessage = pendingTransaction.errorMessage
|
errorMessage = pendingTransaction.errorMessage
|
||||||
|
|
||||||
|
@ -99,8 +126,8 @@ extension TransactionState {
|
||||||
uuid: String = UUID().debugDescription
|
uuid: String = UUID().debugDescription
|
||||||
) -> TransactionState {
|
) -> TransactionState {
|
||||||
.init(
|
.init(
|
||||||
expirationHeight: -1,
|
expiryHeight: -1,
|
||||||
memo: nil,
|
memos: nil,
|
||||||
minedHeight: -1,
|
minedHeight: -1,
|
||||||
shielded: shielded,
|
shielded: shielded,
|
||||||
zAddress: nil,
|
zAddress: nil,
|
||||||
|
|
|
@ -24,7 +24,7 @@ struct WalletEvent: Equatable, Identifiable {
|
||||||
|
|
||||||
let id: String
|
let id: String
|
||||||
let state: WalletEventState
|
let state: WalletEventState
|
||||||
var timestamp: TimeInterval
|
var timestamp: TimeInterval?
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Rows
|
// MARK: - Rows
|
||||||
|
|
|
@ -50,18 +50,27 @@ class HomeTests: XCTestCase {
|
||||||
TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(2), uuid: "bb22"),
|
TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(2), uuid: "bb22"),
|
||||||
TransactionStateMockHelper(date: 1651039000, amount: Zatoshi(3), status: .paid(success: true), uuid: "cc33"),
|
TransactionStateMockHelper(date: 1651039000, amount: Zatoshi(3), status: .paid(success: true), uuid: "cc33"),
|
||||||
TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(4), uuid: "dd44"),
|
TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(4), uuid: "dd44"),
|
||||||
TransactionStateMockHelper(date: 1651039404, amount: Zatoshi(5), uuid: "ee55")
|
TransactionStateMockHelper(date: 1651039404, amount: Zatoshi(5), uuid: "ee55"),
|
||||||
|
TransactionStateMockHelper(
|
||||||
|
date: 1651039606,
|
||||||
|
amount: Zatoshi(6),
|
||||||
|
status: .paid(success: false),
|
||||||
|
uuid: "ff66"
|
||||||
|
),
|
||||||
|
TransactionStateMockHelper(date: 1651039303, amount: Zatoshi(7), uuid: "gg77"),
|
||||||
|
TransactionStateMockHelper(date: 1651039707, amount: Zatoshi(8), status: .paid(success: true), uuid: "hh88"),
|
||||||
|
TransactionStateMockHelper(date: 1651039808, amount: Zatoshi(9), uuid: "ii99")
|
||||||
]
|
]
|
||||||
let walletEvents: [WalletEvent] = transactionsHelper.map {
|
let walletEvents: [WalletEvent] = transactionsHelper.map {
|
||||||
let transaction = TransactionState.placeholder(
|
let transaction = TransactionState.placeholder(
|
||||||
amount: $0.amount,
|
amount: $0.amount,
|
||||||
fee: Zatoshi(10),
|
fee: Zatoshi(10),
|
||||||
shielded: $0.shielded,
|
shielded: $0.shielded,
|
||||||
status: $0.status,
|
status: $0.amount.amount > 5 ? .pending : $0.status,
|
||||||
timestamp: $0.date,
|
timestamp: $0.date,
|
||||||
uuid: $0.uuid
|
uuid: $0.uuid
|
||||||
)
|
)
|
||||||
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
return WalletEvent(id: transaction.id, state: $0.amount.amount > 5 ? .pending(transaction) : .send(transaction), timestamp: transaction.timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
store.receive(.updateWalletEvents(walletEvents))
|
store.receive(.updateWalletEvents(walletEvents))
|
||||||
|
|
|
@ -62,10 +62,14 @@ class SendTests: XCTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
await testScheduler.advance(by: 0.01)
|
await testScheduler.advance(by: 0.01)
|
||||||
|
guard let memo = try? Memo(string: "test") else {
|
||||||
|
XCTFail("testSendSucceeded: memo is expected to be successfuly initialized.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let transactionState = TransactionState(
|
let transactionState = TransactionState(
|
||||||
expirationHeight: 40,
|
expiryHeight: 40,
|
||||||
memo: try? Memo(string: "test"),
|
memos: [memo],
|
||||||
minedHeight: 50,
|
minedHeight: 50,
|
||||||
shielded: true,
|
shielded: true,
|
||||||
zAddress: "tteafadlamnelkqe",
|
zAddress: "tteafadlamnelkqe",
|
||||||
|
@ -132,8 +136,8 @@ class SendTests: XCTestCase {
|
||||||
await testScheduler.advance(by: 0.01)
|
await testScheduler.advance(by: 0.01)
|
||||||
|
|
||||||
let transactionState = TransactionState(
|
let transactionState = TransactionState(
|
||||||
expirationHeight: 40,
|
expiryHeight: 40,
|
||||||
memo: nil,
|
memos: [],
|
||||||
minedHeight: 50,
|
minedHeight: 50,
|
||||||
shielded: true,
|
shielded: true,
|
||||||
zAddress: "tteafadlamnelkqe",
|
zAddress: "tteafadlamnelkqe",
|
||||||
|
|
|
@ -21,7 +21,7 @@ class HomeCircularProgressSnapshotTests: XCTestCase {
|
||||||
progressHeight: BlockHeight(55)
|
progressHeight: BlockHeight(55)
|
||||||
)
|
)
|
||||||
|
|
||||||
return SyncStatusSnapshot.snapshotFor(state: .downloading(blockProgress))
|
return SyncStatusSnapshot.snapshotFor(state: .syncing(blockProgress))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ class HomeCircularProgressSnapshotTests: XCTestCase {
|
||||||
progressHeight: BlockHeight(72)
|
progressHeight: BlockHeight(72)
|
||||||
)
|
)
|
||||||
|
|
||||||
return SyncStatusSnapshot.snapshotFor(state: .scanning(blockProgress))
|
return SyncStatusSnapshot.snapshotFor(state: .syncing(blockProgress))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,13 +63,19 @@ class WalletEventsSnapshotTests: XCTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testWalletEventDetailSnapshot_sent() throws {
|
func testWalletEventDetailSnapshot_sent() throws {
|
||||||
let transaction = TransactionState(
|
let memo = try? Memo(string:
|
||||||
memo: try? Memo(string:
|
|
||||||
"""
|
"""
|
||||||
Testing some long memo so I can see many lines of text \
|
Testing some long memo so I can see many lines of text \
|
||||||
instead of just one. This can take some time and I'm \
|
instead of just one. This can take some time and I'm \
|
||||||
bored to write all this stuff.
|
bored to write all this stuff.
|
||||||
"""),
|
""")
|
||||||
|
guard let memo else {
|
||||||
|
XCTFail("testWalletEventDetailSnapshot_sent: memo is expected to be successfuly initialized")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let transaction = TransactionState(
|
||||||
|
memos: [memo],
|
||||||
minedHeight: 1_875_256,
|
minedHeight: 1_875_256,
|
||||||
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
||||||
fee: Zatoshi(1_000_000),
|
fee: Zatoshi(1_000_000),
|
||||||
|
@ -110,13 +116,19 @@ class WalletEventsSnapshotTests: XCTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testWalletEventDetailSnapshot_received() throws {
|
func testWalletEventDetailSnapshot_received() throws {
|
||||||
let transaction = TransactionState(
|
let memo = try? Memo(string:
|
||||||
memo: try? Memo(string:
|
|
||||||
"""
|
"""
|
||||||
Testing some long memo so I can see many lines of text \
|
Testing some long memo so I can see many lines of text \
|
||||||
instead of just one. This can take some time and I'm \
|
instead of just one. This can take some time and I'm \
|
||||||
bored to write all this stuff.
|
bored to write all this stuff.
|
||||||
"""),
|
""")
|
||||||
|
guard let memo else {
|
||||||
|
XCTFail("testWalletEventDetailSnapshot_received: memo is expected to be successfuly initialized")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let transaction = TransactionState(
|
||||||
|
memos: [memo],
|
||||||
minedHeight: 1_875_256,
|
minedHeight: 1_875_256,
|
||||||
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
||||||
fee: Zatoshi(1_000_000),
|
fee: Zatoshi(1_000_000),
|
||||||
|
@ -157,13 +169,19 @@ class WalletEventsSnapshotTests: XCTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testWalletEventDetailSnapshot_pending() throws {
|
func testWalletEventDetailSnapshot_pending() throws {
|
||||||
let transaction = TransactionState(
|
let memo = try? Memo(string:
|
||||||
memo: try? Memo(string:
|
|
||||||
"""
|
"""
|
||||||
Testing some long memo so I can see many lines of text \
|
Testing some long memo so I can see many lines of text \
|
||||||
instead of just one. This can take some time and I'm \
|
instead of just one. This can take some time and I'm \
|
||||||
bored to write all this stuff.
|
bored to write all this stuff.
|
||||||
"""),
|
""")
|
||||||
|
guard let memo else {
|
||||||
|
XCTFail("testWalletEventDetailSnapshot_pending: memo is expected to be successfuly initialized")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let transaction = TransactionState(
|
||||||
|
memos: [memo],
|
||||||
minedHeight: 1_875_256,
|
minedHeight: 1_875_256,
|
||||||
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
||||||
fee: Zatoshi(1_000_000),
|
fee: Zatoshi(1_000_000),
|
||||||
|
@ -209,14 +227,20 @@ class WalletEventsSnapshotTests: XCTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testWalletEventDetailSnapshot_failed() throws {
|
func testWalletEventDetailSnapshot_failed() throws {
|
||||||
let transaction = TransactionState(
|
let memo = try? Memo(string:
|
||||||
errorMessage: "possible roll back",
|
|
||||||
memo: try? Memo(string:
|
|
||||||
"""
|
"""
|
||||||
Testing some long memo so I can see many lines of text \
|
Testing some long memo so I can see many lines of text \
|
||||||
instead of just one. This can take some time and I'm \
|
instead of just one. This can take some time and I'm \
|
||||||
bored to write all this stuff.
|
bored to write all this stuff.
|
||||||
"""),
|
""")
|
||||||
|
guard let memo else {
|
||||||
|
XCTFail("testWalletEventDetailSnapshot_failed: memo is expected to be successfuly initialized")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let transaction = TransactionState(
|
||||||
|
errorMessage: "possible roll back",
|
||||||
|
memos: [memo],
|
||||||
minedHeight: 1_875_256,
|
minedHeight: 1_875_256,
|
||||||
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
||||||
fee: Zatoshi(1_000_000),
|
fee: Zatoshi(1_000_000),
|
||||||
|
|
|
@ -39,16 +39,7 @@ class WalletEventsTests: XCTestCase {
|
||||||
TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(2), uuid: "bb22"),
|
TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(2), uuid: "bb22"),
|
||||||
TransactionStateMockHelper(date: 1651039000, amount: Zatoshi(3), status: .paid(success: true), uuid: "cc33"),
|
TransactionStateMockHelper(date: 1651039000, amount: Zatoshi(3), status: .paid(success: true), uuid: "cc33"),
|
||||||
TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(4), uuid: "dd44"),
|
TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(4), uuid: "dd44"),
|
||||||
TransactionStateMockHelper(date: 1651039404, amount: Zatoshi(5), uuid: "ee55"),
|
TransactionStateMockHelper(date: 1651039404, amount: Zatoshi(5), uuid: "ee55")
|
||||||
TransactionStateMockHelper(
|
|
||||||
date: 1651039606,
|
|
||||||
amount: Zatoshi(6),
|
|
||||||
status: .paid(success: false),
|
|
||||||
uuid: "ff66"
|
|
||||||
),
|
|
||||||
TransactionStateMockHelper(date: 1651039303, amount: Zatoshi(7), uuid: "gg77"),
|
|
||||||
TransactionStateMockHelper(date: 1651039707, amount: Zatoshi(8), status: .paid(success: true), uuid: "hh88"),
|
|
||||||
TransactionStateMockHelper(date: 1651039808, amount: Zatoshi(9), uuid: "ii99")
|
|
||||||
]
|
]
|
||||||
|
|
||||||
let walletEvents: [WalletEvent] = mocked.map {
|
let walletEvents: [WalletEvent] = mocked.map {
|
||||||
|
@ -56,7 +47,7 @@ class WalletEventsTests: XCTestCase {
|
||||||
amount: $0.amount,
|
amount: $0.amount,
|
||||||
fee: Zatoshi(10),
|
fee: Zatoshi(10),
|
||||||
shielded: $0.shielded,
|
shielded: $0.shielded,
|
||||||
status: $0.amount.amount > 5 ? .pending : $0.status,
|
status: $0.status,
|
||||||
timestamp: $0.date,
|
timestamp: $0.date,
|
||||||
uuid: $0.uuid
|
uuid: $0.uuid
|
||||||
)
|
)
|
||||||
|
@ -90,7 +81,10 @@ class WalletEventsTests: XCTestCase {
|
||||||
uniqueElements:
|
uniqueElements:
|
||||||
walletEvents
|
walletEvents
|
||||||
.sorted(by: { lhs, rhs in
|
.sorted(by: { lhs, rhs in
|
||||||
lhs.timestamp > rhs.timestamp
|
guard let lhsTimestamp = lhs.timestamp, let rhsTimestamp = rhs.timestamp else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return lhsTimestamp > rhsTimestamp
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue