- transaction detail has been cut into pieces that can be composed to various versions of the detail - handling all 4 cases (sent, received, pending, failed) [362] [scaffold] Pending Transaction Details - confirmations counting - pending transaction status fixed [362] [scaffold] Pending Transaction Details - tests fixed [362] [scaffold] Pending Transaction Details - failed transactions [362] [scaffold] Pending Transaction Details (381) - snapshot tests [362] [scaffold] Pending Transaction Details (381) - comments resolved
This commit is contained in:
parent
df2c721d32
commit
3d615a32d8
|
@ -10,42 +10,46 @@ import ZcashLightClientKit
|
|||
|
||||
// swiftlint:disable:next private_over_fileprivate strict_fileprivate
|
||||
fileprivate enum ZcashSDKConstants {
|
||||
static let defaultBlockHeight = 1_629_724
|
||||
static let endpointMainnetAddress = "lightwalletd.electriccoin.co"
|
||||
static let endpointTestnetAddress = "lightwalletd.testnet.electriccoin.co"
|
||||
static let endpointPort = 9067
|
||||
static let defaultBlockHeight = 1_629_724
|
||||
static let mnemonicWordsMaxCount = 24
|
||||
static let requiredTransactionConfirmations = 10
|
||||
}
|
||||
|
||||
struct ZCashSDKEnvironment {
|
||||
let defaultBirthday: BlockHeight
|
||||
let endpoint: LightWalletEndpoint
|
||||
let lightWalletService: LightWalletService
|
||||
let network: ZcashNetwork
|
||||
let mnemonicWordsMaxCount: Int
|
||||
let isMainnet: () -> Bool
|
||||
let lightWalletService: LightWalletService
|
||||
let mnemonicWordsMaxCount: Int
|
||||
let network: ZcashNetwork
|
||||
let requiredTransactionConfirmations: Int
|
||||
}
|
||||
|
||||
extension ZCashSDKEnvironment {
|
||||
static let mainnet = ZCashSDKEnvironment(
|
||||
defaultBirthday: BlockHeight(ZcashSDKConstants.defaultBlockHeight),
|
||||
endpoint: LightWalletEndpoint(address: ZcashSDKConstants.endpointMainnetAddress, port: ZcashSDKConstants.endpointPort),
|
||||
isMainnet: { true },
|
||||
lightWalletService: LightWalletGRPCService(
|
||||
endpoint: LightWalletEndpoint(address: ZcashSDKConstants.endpointMainnetAddress, port: ZcashSDKConstants.endpointPort)
|
||||
),
|
||||
network: ZcashNetworkBuilder.network(for: .mainnet),
|
||||
mnemonicWordsMaxCount: ZcashSDKConstants.mnemonicWordsMaxCount,
|
||||
isMainnet: { true }
|
||||
network: ZcashNetworkBuilder.network(for: .mainnet),
|
||||
requiredTransactionConfirmations: ZcashSDKConstants.requiredTransactionConfirmations
|
||||
)
|
||||
|
||||
static let testnet = ZCashSDKEnvironment(
|
||||
defaultBirthday: BlockHeight(ZcashSDKConstants.defaultBlockHeight),
|
||||
endpoint: LightWalletEndpoint(address: ZcashSDKConstants.endpointTestnetAddress, port: ZcashSDKConstants.endpointPort),
|
||||
isMainnet: { false },
|
||||
lightWalletService: LightWalletGRPCService(
|
||||
endpoint: LightWalletEndpoint(address: ZcashSDKConstants.endpointTestnetAddress, port: ZcashSDKConstants.endpointPort)
|
||||
),
|
||||
network: ZcashNetworkBuilder.network(for: .testnet),
|
||||
mnemonicWordsMaxCount: ZcashSDKConstants.mnemonicWordsMaxCount,
|
||||
isMainnet: { false }
|
||||
network: ZcashNetworkBuilder.network(for: .testnet),
|
||||
requiredTransactionConfirmations: ZcashSDKConstants.requiredTransactionConfirmations
|
||||
)
|
||||
}
|
||||
|
|
|
@ -367,7 +367,8 @@ extension AppReducer {
|
|||
mnemonic: environment.mnemonic,
|
||||
scheduler: environment.scheduler,
|
||||
SDKSynchronizer: environment.SDKSynchronizer,
|
||||
walletStorage: environment.walletStorage
|
||||
walletStorage: environment.walletStorage,
|
||||
zcashSDKEnvironment: environment.zcashSDKEnvironment
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
@ -61,6 +61,7 @@ struct HomeEnvironment {
|
|||
let scheduler: AnySchedulerOf<DispatchQueue>
|
||||
let SDKSynchronizer: WrappedSDKSynchronizer
|
||||
let walletStorage: WrappedWalletStorage
|
||||
let zcashSDKEnvironment: ZCashSDKEnvironment
|
||||
}
|
||||
|
||||
extension HomeEnvironment {
|
||||
|
@ -71,7 +72,8 @@ extension HomeEnvironment {
|
|||
mnemonic: .mock,
|
||||
scheduler: DispatchQueue.main.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: MockWrappedSDKSynchronizer(),
|
||||
walletStorage: .throwing
|
||||
walletStorage: .throwing,
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -180,9 +182,10 @@ extension HomeReducer {
|
|||
action: /HomeAction.walletEvents,
|
||||
environment: { environment in
|
||||
WalletEventsFlowEnvironment(
|
||||
pasteboard: .live,
|
||||
scheduler: environment.scheduler,
|
||||
SDKSynchronizer: environment.SDKSynchronizer,
|
||||
pasteboard: .live
|
||||
zcashSDKEnvironment: environment.zcashSDKEnvironment
|
||||
)
|
||||
}
|
||||
)
|
||||
|
@ -315,7 +318,8 @@ extension HomeStore {
|
|||
mnemonic: .live,
|
||||
scheduler: DispatchQueue.main.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: LiveWrappedSDKSynchronizer(),
|
||||
walletStorage: .live()
|
||||
walletStorage: .live(),
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -49,9 +49,10 @@ extension SandboxReducer {
|
|||
&state.walletEventsState,
|
||||
walletEventsAction,
|
||||
WalletEventsFlowEnvironment(
|
||||
pasteboard: .live,
|
||||
scheduler: DispatchQueue.main.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: LiveWrappedSDKSynchronizer(),
|
||||
pasteboard: .live
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
)
|
||||
.map(SandboxAction.walletEvents)
|
||||
|
|
|
@ -121,6 +121,7 @@ extension SendFlowReducer {
|
|||
case .updateRoute(.confirmation):
|
||||
state.amount = Zatoshi(amount: state.transactionAmountInputState.amount)
|
||||
state.address = state.transactionAddressInputState.textFieldState.text
|
||||
state.route = .confirmation
|
||||
return .none
|
||||
|
||||
case let .updateRoute(route):
|
||||
|
|
|
@ -2,72 +2,160 @@ import SwiftUI
|
|||
import ComposableArchitecture
|
||||
|
||||
struct TransactionDetailView: View {
|
||||
enum RowMark {
|
||||
case neutral
|
||||
case success
|
||||
case fail
|
||||
case inactive
|
||||
case highlight
|
||||
}
|
||||
|
||||
var transaction: TransactionState
|
||||
var viewStore: WalletEventsFlowViewStore
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
HStack {
|
||||
header
|
||||
|
||||
switch transaction.status {
|
||||
case .paid(success: _):
|
||||
plainText("You sent \(transaction.zecAmount.decimalString()) ZEC")
|
||||
plainText("fee \(transaction.fee.decimalString()) ZEC", mark: .inactive)
|
||||
plainText("total amount \(transaction.totalAmount.decimalString()) ZEC", mark: .inactive)
|
||||
address(mark: .inactive)
|
||||
if let text = transaction.memo { memo(text, viewStore, mark: .highlight) }
|
||||
confirmed(mark: .success)
|
||||
case .pending:
|
||||
plainText("You are sending \(transaction.zecAmount.decimalString()) ZEC")
|
||||
plainText("Includes network fee \(transaction.fee.decimalString()) ZEC", mark: .inactive)
|
||||
plainText("total amount \(transaction.totalAmount.decimalString()) ZEC", mark: .inactive)
|
||||
if let text = transaction.memo { memo(text, viewStore, mark: .inactive) }
|
||||
confirming(mark: .highlight)
|
||||
case .received:
|
||||
plainText("You received \(transaction.zecAmount.decimalString()) ZEC")
|
||||
plainText("fee \(transaction.fee.decimalString()) ZEC")
|
||||
plainText("total amount \(transaction.totalAmount.decimalString()) ZEC")
|
||||
address(mark: .inactive)
|
||||
if let text = transaction.memo { memo(text, viewStore, mark: .highlight) }
|
||||
confirmed(mark: .success)
|
||||
case .failed:
|
||||
plainText("You DID NOT send \(transaction.zecAmount.decimalString()) ZEC", mark: .fail)
|
||||
plainText("Includes network fee \(transaction.fee.decimalString()) ZEC", mark: .inactive)
|
||||
plainText("total amount \(transaction.totalAmount.decimalString()) ZEC", mark: .inactive)
|
||||
if let text = transaction.memo { memo(text, viewStore, mark: .inactive) }
|
||||
if let errorMessage = transaction.errorMessage {
|
||||
plainTwoColumnText(left: "Failed", right: errorMessage, mark: .fail)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
footer
|
||||
}
|
||||
.applyScreenBackground()
|
||||
.navigationTitle("Transaction detail")
|
||||
}
|
||||
}
|
||||
|
||||
extension TransactionDetailView {
|
||||
var header: some View {
|
||||
HStack {
|
||||
switch transaction.status {
|
||||
case .pending:
|
||||
Text("PENDING")
|
||||
Spacer()
|
||||
case .failed:
|
||||
Text("\(transaction.date.asHumanReadable())")
|
||||
Spacer()
|
||||
Text("FAILED")
|
||||
default:
|
||||
Text("\(transaction.date.asHumanReadable())")
|
||||
Spacer()
|
||||
Text("HEIGHT \(heightText)")
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
|
||||
Text("\(amountPrefixText) \(transaction.zecAmount.decimalString()) ZEC")
|
||||
.transactionDetailRow()
|
||||
func plainText(_ text: String, mark: RowMark = .neutral) -> some View {
|
||||
Text(text)
|
||||
.transactionDetailRow(mark: mark)
|
||||
}
|
||||
|
||||
Text("fee \(transaction.fee.decimalString()) ZEC")
|
||||
.transactionDetailRow()
|
||||
func plainTwoColumnText(left: String, right: String, mark: RowMark = .neutral) -> some View {
|
||||
HStack {
|
||||
Text(left)
|
||||
Spacer()
|
||||
Text(right)
|
||||
}
|
||||
.transactionDetailRow(mark: mark)
|
||||
}
|
||||
|
||||
Text("total amount \(transaction.totalAmount.decimalString()) ZEC")
|
||||
.transactionDetailRow()
|
||||
func address(mark: RowMark = .neutral) -> some View {
|
||||
Button {
|
||||
viewStore.send(.copyToPastboard(transaction.address))
|
||||
} label: {
|
||||
Text("\(addressPrefixText) \(transaction.address)")
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
.transactionDetailRow(mark: mark)
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
viewStore.send(.copyToPastboard(transaction.address))
|
||||
} label: {
|
||||
Text("\(addressPrefixText) \(transaction.address)")
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
.transactionDetailRow()
|
||||
}
|
||||
func memo(
|
||||
_ memo: String,
|
||||
_ viewStore: WalletEventsFlowViewStore,
|
||||
mark: RowMark = .neutral
|
||||
) -> some View {
|
||||
Button {
|
||||
viewStore.send(.copyToPastboard(memo))
|
||||
} label: {
|
||||
VStack {
|
||||
HStack {
|
||||
Text("\(memo)")
|
||||
.multilineTextAlignment(.leading)
|
||||
Spacer()
|
||||
}
|
||||
|
||||
if let memo = transaction.memo {
|
||||
Button {
|
||||
viewStore.send(.copyToPastboard(memo))
|
||||
} label: {
|
||||
VStack {
|
||||
Text("\(memo)")
|
||||
.multilineTextAlignment(.leading)
|
||||
|
||||
HStack {
|
||||
Text("reply-to address included")
|
||||
Spacer()
|
||||
Button {
|
||||
viewStore.send(.replyTo(transaction.address))
|
||||
} label: {
|
||||
Text("reply now")
|
||||
.padding(5)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 6)
|
||||
.stroke(Asset.Colors.Text.transactionDetailText.color, lineWidth: 1)
|
||||
)
|
||||
}
|
||||
}
|
||||
HStack {
|
||||
Text("reply-to address included")
|
||||
Spacer()
|
||||
Button {
|
||||
viewStore.send(.replyTo(transaction.address))
|
||||
} label: {
|
||||
Text("reply now")
|
||||
.padding(5)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 6)
|
||||
.stroke(Asset.Colors.Text.transactionDetailText.color, lineWidth: 1)
|
||||
)
|
||||
}
|
||||
.transactionDetailRow()
|
||||
}
|
||||
}
|
||||
.transactionDetailRow(mark: mark)
|
||||
}
|
||||
}
|
||||
|
||||
HStack {
|
||||
Text("Confirmed")
|
||||
Spacer()
|
||||
Text("\(transaction.confirmations) times")
|
||||
}
|
||||
.transactionDetailRow()
|
||||
|
||||
func confirmed(mark: RowMark = .neutral) -> some View {
|
||||
HStack {
|
||||
Text("Confirmed")
|
||||
Spacer()
|
||||
Text("\(transaction.confirmationsWith(viewStore.latestMinedHeight)) times")
|
||||
}
|
||||
.transactionDetailRow(mark: mark)
|
||||
}
|
||||
|
||||
func confirming(mark: RowMark = .neutral) -> some View {
|
||||
HStack {
|
||||
Text("Confirming ~\(viewStore.requiredTransactionConfirmations)mins")
|
||||
Spacer()
|
||||
Text("\(transaction.confirmationsWith(viewStore.latestMinedHeight))/\(viewStore.requiredTransactionConfirmations)")
|
||||
}
|
||||
.transactionDetailRow(mark: mark)
|
||||
}
|
||||
|
||||
var footer: some View {
|
||||
VStack {
|
||||
Button {
|
||||
viewStore.send(.copyToPastboard(transaction.id))
|
||||
} label: {
|
||||
|
@ -93,16 +181,10 @@ struct TransactionDetailView: View {
|
|||
.frame(height: 50)
|
||||
.padding(.horizontal, 30)
|
||||
}
|
||||
.applyScreenBackground()
|
||||
.navigationTitle("Transaction detail")
|
||||
}
|
||||
}
|
||||
|
||||
extension TransactionDetailView {
|
||||
var amountPrefixText: String {
|
||||
transaction.status == .received ? "You received" : "You sent"
|
||||
}
|
||||
|
||||
var addressPrefixText: String {
|
||||
transaction.status == .received ? "from" : "to"
|
||||
}
|
||||
|
@ -112,8 +194,10 @@ extension TransactionDetailView {
|
|||
}
|
||||
}
|
||||
|
||||
// MARK: - Row modifier
|
||||
|
||||
struct TransactionDetailRow: ViewModifier {
|
||||
let tint: Color
|
||||
let mark: TransactionDetailView.RowMark
|
||||
let textColor: Color
|
||||
let backgroundColor: Color
|
||||
|
||||
|
@ -124,21 +208,35 @@ struct TransactionDetailRow: ViewModifier {
|
|||
.padding()
|
||||
.background(backgroundColor)
|
||||
.padding(.leading, 20)
|
||||
.background(tint)
|
||||
.background(markColor(mark))
|
||||
}
|
||||
|
||||
private func markColor(_ mark: TransactionDetailView.RowMark) -> Color {
|
||||
let markColor: Color
|
||||
|
||||
switch mark {
|
||||
case .neutral: markColor = Asset.Colors.TransactionDetail.neutralMark.color
|
||||
case .success: markColor = Asset.Colors.TransactionDetail.succeededMark.color
|
||||
case .fail: markColor = Asset.Colors.TransactionDetail.failedMark.color
|
||||
case .inactive: markColor = Asset.Colors.TransactionDetail.inactiveMark.color
|
||||
case .highlight: markColor = Asset.Colors.TransactionDetail.highlightMark.color
|
||||
}
|
||||
|
||||
return markColor
|
||||
}
|
||||
}
|
||||
|
||||
extension View {
|
||||
func transactionDetailRow(
|
||||
_ tint: Color = Asset.Colors.BackgroundColors.red.color,
|
||||
_ textColor: Color = Asset.Colors.Text.transactionDetailText.color,
|
||||
_ backgroundColor: Color = Asset.Colors.BackgroundColors.numberedChip.color
|
||||
mark: TransactionDetailView.RowMark = .neutral
|
||||
) -> some View {
|
||||
modifier(
|
||||
TransactionDetailRow(
|
||||
tint: tint,
|
||||
textColor: textColor,
|
||||
backgroundColor: backgroundColor
|
||||
mark: mark,
|
||||
textColor: mark == .inactive ?
|
||||
Asset.Colors.TransactionDetail.inactiveMark.color :
|
||||
Asset.Colors.Text.transactionDetailText.color,
|
||||
backgroundColor: Asset.Colors.BackgroundColors.numberedChip.color
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -152,6 +250,7 @@ struct TransactionDetail_Previews: PreviewProvider {
|
|||
TransactionDetailView(
|
||||
transaction:
|
||||
TransactionState(
|
||||
errorMessage: "possible roll back",
|
||||
memo:
|
||||
"""
|
||||
Testing some long memo so I can see many lines of text \
|
||||
|
@ -163,7 +262,6 @@ struct TransactionDetail_Previews: PreviewProvider {
|
|||
fee: Zatoshi(amount: 1_000_000),
|
||||
id: "ff3927e1f83df9b1b0dc75540ddc59ee435eecebae914d2e6dfe8576fbedc9a8",
|
||||
status: .paid(success: true),
|
||||
subtitle: "",
|
||||
timestamp: 1234567,
|
||||
zecAmount: Zatoshi(amount: 25_000_000)
|
||||
),
|
||||
|
@ -173,9 +271,10 @@ struct TransactionDetail_Previews: PreviewProvider {
|
|||
reducer: .default,
|
||||
environment:
|
||||
WalletEventsFlowEnvironment(
|
||||
pasteboard: .test,
|
||||
scheduler: DispatchQueue.main.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: MockWrappedSDKSynchronizer(),
|
||||
pasteboard: .test
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import ComposableArchitecture
|
||||
import SwiftUI
|
||||
import ZcashLightClientKit
|
||||
|
||||
typealias WalletEventsFlowReducer = Reducer<WalletEventsFlowState, WalletEventsFlowAction, WalletEventsFlowEnvironment>
|
||||
typealias WalletEventsFlowStore = Store<WalletEventsFlowState, WalletEventsFlowAction>
|
||||
|
@ -16,7 +17,9 @@ struct WalletEventsFlowState: Equatable {
|
|||
|
||||
var route: Route?
|
||||
|
||||
var latestMinedHeight: BlockHeight?
|
||||
var isScrollable = false
|
||||
var requiredTransactionConfirmations = 0
|
||||
var walletEvents = IdentifiedArrayOf<WalletEvent>.placeholder
|
||||
}
|
||||
|
||||
|
@ -35,9 +38,10 @@ enum WalletEventsFlowAction: Equatable {
|
|||
// MARK: - Environment
|
||||
|
||||
struct WalletEventsFlowEnvironment {
|
||||
let pasteboard: WrappedPasteboard
|
||||
let scheduler: AnySchedulerOf<DispatchQueue>
|
||||
let SDKSynchronizer: WrappedSDKSynchronizer
|
||||
let pasteboard: WrappedPasteboard
|
||||
let zcashSDKEnvironment: ZCashSDKEnvironment
|
||||
}
|
||||
|
||||
// MARK: - Reducer
|
||||
|
@ -48,6 +52,7 @@ extension WalletEventsFlowReducer {
|
|||
static let `default` = WalletEventsFlowReducer { state, action, environment in
|
||||
switch action {
|
||||
case .onAppear:
|
||||
state.requiredTransactionConfirmations = environment.zcashSDKEnvironment.requiredTransactionConfirmations
|
||||
return environment.SDKSynchronizer.stateChanged
|
||||
.map(WalletEventsFlowAction.synchronizerStateChanged)
|
||||
.eraseToEffect()
|
||||
|
@ -57,6 +62,9 @@ extension WalletEventsFlowReducer {
|
|||
return Effect.cancel(id: CancelId())
|
||||
|
||||
case .synchronizerStateChanged(.synced):
|
||||
if let latestMinedHeight = environment.SDKSynchronizer.synchronizer?.latestScannedHeight {
|
||||
state.latestMinedHeight = latestMinedHeight
|
||||
}
|
||||
return environment.SDKSynchronizer.getAllTransactions()
|
||||
.receive(on: environment.scheduler)
|
||||
.map(WalletEventsFlowAction.updateWalletEvents)
|
||||
|
@ -110,7 +118,6 @@ extension TransactionState {
|
|||
fee: Zatoshi(amount: 10),
|
||||
id: "2",
|
||||
status: .paid(success: true),
|
||||
subtitle: "",
|
||||
timestamp: 1234567,
|
||||
zecAmount: Zatoshi(amount: 25)
|
||||
)
|
||||
|
@ -133,9 +140,10 @@ extension WalletEventsFlowStore {
|
|||
initialState: .placeHolder,
|
||||
reducer: .default,
|
||||
environment: WalletEventsFlowEnvironment(
|
||||
pasteboard: .live,
|
||||
scheduler: DispatchQueue.main.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: LiveWrappedSDKSynchronizer(),
|
||||
pasteboard: .live
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -149,7 +157,6 @@ extension IdentifiedArrayOf where Element == TransactionState {
|
|||
fee: Zatoshi(amount: 10),
|
||||
id: String($0),
|
||||
status: .paid(success: true),
|
||||
subtitle: "",
|
||||
timestamp: 1234567,
|
||||
zecAmount: Zatoshi(amount: 25)
|
||||
)
|
||||
|
|
|
@ -14,9 +14,10 @@ struct TransactionState: Equatable, Identifiable {
|
|||
case paid(success: Bool)
|
||||
case received
|
||||
case failed
|
||||
case pending
|
||||
}
|
||||
|
||||
var confirmations = 0
|
||||
var errorMessage: String?
|
||||
var expirationHeight = -1
|
||||
var memo: String?
|
||||
var minedHeight = -1
|
||||
|
@ -26,7 +27,6 @@ struct TransactionState: Equatable, Identifiable {
|
|||
var fee: Zatoshi
|
||||
var id: String
|
||||
var status: Status
|
||||
var subtitle: String
|
||||
var timestamp: TimeInterval
|
||||
var zecAmount: Zatoshi
|
||||
|
||||
|
@ -36,6 +36,14 @@ struct TransactionState: Equatable, Identifiable {
|
|||
var viewOnlineURL: URL? {
|
||||
URL(string: "https://blockchair.com/zcash/transaction/\(id)")
|
||||
}
|
||||
|
||||
func confirmationsWith(_ latestMinedHeight: BlockHeight?) -> BlockHeight {
|
||||
guard let latestMinedHeight = latestMinedHeight, minedHeight > 0, latestMinedHeight > 0 else {
|
||||
return 0
|
||||
}
|
||||
|
||||
return latestMinedHeight - minedHeight
|
||||
}
|
||||
}
|
||||
|
||||
extension TransactionState {
|
||||
|
@ -44,7 +52,6 @@ extension TransactionState {
|
|||
id = confirmedTransaction.transactionEntity.transactionId.toHexStringTxId()
|
||||
shielded = true
|
||||
status = sent ? .paid(success: confirmedTransaction.minedHeight > 0) : .received
|
||||
subtitle = "sent"
|
||||
zAddress = confirmedTransaction.toAddress
|
||||
zecAmount = sent ? Zatoshi(amount: -Int64(confirmedTransaction.value)) : Zatoshi(amount: Int64(confirmedTransaction.value))
|
||||
fee = Zatoshi(amount: 10)
|
||||
|
@ -58,9 +65,11 @@ extension TransactionState {
|
|||
timestamp = pendingTransaction.createTime
|
||||
id = pendingTransaction.rawTransactionId?.toHexStringTxId() ?? String(pendingTransaction.createTime)
|
||||
shielded = true
|
||||
status = .paid(success: pendingTransaction.isSubmitSuccess)
|
||||
status = pendingTransaction.errorMessage != nil ? .failed :
|
||||
pendingTransaction.minedHeight > 0 ?
|
||||
.paid(success: pendingTransaction.isSubmitSuccess) :
|
||||
.pending
|
||||
expirationHeight = pendingTransaction.expiryHeight
|
||||
subtitle = "pending"
|
||||
zAddress = pendingTransaction.toAddress
|
||||
zecAmount = Zatoshi(amount: -Int64(pendingTransaction.value))
|
||||
fee = Zatoshi(amount: 10)
|
||||
|
@ -68,6 +77,7 @@ extension TransactionState {
|
|||
self.memo = memo.asZcashTransactionMemo()
|
||||
}
|
||||
minedHeight = pendingTransaction.minedHeight
|
||||
errorMessage = pendingTransaction.errorMessage
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +89,6 @@ extension TransactionState {
|
|||
fee: Zatoshi,
|
||||
shielded: Bool = true,
|
||||
status: Status = .received,
|
||||
subtitle: String = "",
|
||||
timestamp: TimeInterval,
|
||||
uuid: String = UUID().debugDescription
|
||||
) -> TransactionState {
|
||||
|
@ -92,7 +101,6 @@ extension TransactionState {
|
|||
fee: fee,
|
||||
id: uuid,
|
||||
status: status,
|
||||
subtitle: subtitle,
|
||||
timestamp: timestamp,
|
||||
zecAmount: status == .received ? amount : Zatoshi(amount: -amount.amount)
|
||||
)
|
||||
|
@ -104,6 +112,5 @@ struct TransactionStateMockHelper {
|
|||
var amount: Zatoshi
|
||||
var shielded = true
|
||||
var status: TransactionState.Status = .received
|
||||
var subtitle = "cleared"
|
||||
var uuid = ""
|
||||
}
|
||||
|
|
|
@ -32,14 +32,11 @@ struct WalletEvent: Equatable, Identifiable {
|
|||
extension WalletEvent {
|
||||
@ViewBuilder func rowView(_ viewStore: WalletEventsFlowViewStore) -> some View {
|
||||
switch state {
|
||||
case .send(let transaction):
|
||||
case .send(let transaction),
|
||||
.pending(let transaction),
|
||||
.received(let transaction),
|
||||
.failed(let transaction):
|
||||
TransactionRowView(transaction: transaction)
|
||||
case .pending:
|
||||
Text("pending wallet event")
|
||||
case .received:
|
||||
Text("received wallet event")
|
||||
case .failed:
|
||||
Text("failed wallet event")
|
||||
case .shielded(let zatoshi):
|
||||
Text("shielded wallet event \(zatoshi.decimalString())")
|
||||
case .walletImport:
|
||||
|
@ -53,14 +50,11 @@ extension WalletEvent {
|
|||
extension WalletEvent {
|
||||
@ViewBuilder func detailView(_ viewStore: WalletEventsFlowViewStore) -> some View {
|
||||
switch state {
|
||||
case .send(let transaction):
|
||||
case .send(let transaction),
|
||||
.pending(let transaction),
|
||||
.received(let transaction),
|
||||
.failed(let transaction):
|
||||
TransactionDetailView(transaction: transaction, viewStore: viewStore)
|
||||
case .pending:
|
||||
Text("pending transaction detail")
|
||||
case .received:
|
||||
Text("received transaction detail")
|
||||
case .failed:
|
||||
Text("failed transaction detail")
|
||||
case .shielded(let zatoshi):
|
||||
Text("shielded \(zatoshi.decimalString()) detail")
|
||||
case .walletImport:
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.173",
|
||||
"green" : "0.047",
|
||||
"red" : "0.780"
|
||||
"blue" : "0x2C",
|
||||
"green" : "0x0B",
|
||||
"red" : "0xC6"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.000",
|
||||
"green" : "0.810",
|
||||
"red" : "1.000"
|
||||
"blue" : "0x00",
|
||||
"green" : "0xCE",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "97",
|
||||
"green" : "172",
|
||||
"red" : "42"
|
||||
"blue" : "0x61",
|
||||
"green" : "0xAC",
|
||||
"red" : "0x2A"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x2C",
|
||||
"green" : "0x0B",
|
||||
"red" : "0xC6"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.173",
|
||||
"green" : "0.043",
|
||||
"red" : "0.776"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x00",
|
||||
"green" : "0xCE",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x00",
|
||||
"green" : "0xCE",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xAA",
|
||||
"green" : "0xAA",
|
||||
"red" : "0xAA"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xAA",
|
||||
"green" : "0xAA",
|
||||
"red" : "0xAA"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "1.000",
|
||||
"green" : "1.000",
|
||||
"red" : "1.000"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "1.000",
|
||||
"green" : "1.000",
|
||||
"red" : "1.000"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x61",
|
||||
"green" : "0xAC",
|
||||
"red" : "0x2A"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x61",
|
||||
"green" : "0xAC",
|
||||
"red" : "0x2A"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -125,6 +125,13 @@ internal enum Asset {
|
|||
internal static let purple = ColorAsset(name: "Purple")
|
||||
}
|
||||
}
|
||||
internal enum TransactionDetail {
|
||||
internal static let failedMark = ColorAsset(name: "FailedMark")
|
||||
internal static let highlightMark = ColorAsset(name: "HighlightMark")
|
||||
internal static let inactiveMark = ColorAsset(name: "InactiveMark")
|
||||
internal static let neutralMark = ColorAsset(name: "NeutralMark")
|
||||
internal static let succeededMark = ColorAsset(name: "SucceededMark")
|
||||
}
|
||||
internal enum ZcashBadge {
|
||||
internal static let zcashLogoFill = ColorAsset(name: "ZcashLogoFill")
|
||||
internal static let innerCircle = ColorAsset(name: "innerCircle")
|
||||
|
|
|
@ -310,7 +310,6 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
|||
fee: Zatoshi(amount: 10),
|
||||
shielded: $0.shielded,
|
||||
status: $0.status,
|
||||
subtitle: $0.subtitle,
|
||||
timestamp: $0.date,
|
||||
uuid: $0.uuid
|
||||
)
|
||||
|
@ -321,10 +320,10 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
|||
|
||||
func getAllPendingTransactions() -> Effect<[WalletEvent], Never> {
|
||||
let mocked: [TransactionStateMockHelper] = [
|
||||
TransactionStateMockHelper(date: 1651039606, amount: Zatoshi(amount: 6), status: .paid(success: false), subtitle: "pending"),
|
||||
TransactionStateMockHelper(date: 1651039303, amount: Zatoshi(amount: 7), subtitle: "pending"),
|
||||
TransactionStateMockHelper(date: 1651039707, amount: Zatoshi(amount: 8), status: .paid(success: true), subtitle: "pending"),
|
||||
TransactionStateMockHelper(date: 1651039808, amount: Zatoshi(amount: 9), subtitle: "pending")
|
||||
TransactionStateMockHelper(date: 1651039606, amount: Zatoshi(amount: 6), status: .paid(success: false)),
|
||||
TransactionStateMockHelper(date: 1651039303, amount: Zatoshi(amount: 7)),
|
||||
TransactionStateMockHelper(date: 1651039707, amount: Zatoshi(amount: 8), status: .paid(success: true)),
|
||||
TransactionStateMockHelper(date: 1651039808, amount: Zatoshi(amount: 9))
|
||||
]
|
||||
|
||||
return Effect(
|
||||
|
@ -335,7 +334,6 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
|||
fee: Zatoshi(amount: 10),
|
||||
shielded: $0.shielded,
|
||||
status: $0.status,
|
||||
subtitle: $0.subtitle,
|
||||
timestamp: $0.date
|
||||
)
|
||||
return WalletEvent(id: transaction.id, state: .pending(transaction), timestamp: transaction.timestamp)
|
||||
|
@ -373,7 +371,6 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
|||
fee: Zatoshi(amount: 10),
|
||||
id: "id",
|
||||
status: .paid(success: true),
|
||||
subtitle: "sub",
|
||||
timestamp: 1234567,
|
||||
zecAmount: Zatoshi(amount: 10)
|
||||
)
|
||||
|
@ -423,7 +420,6 @@ class TestWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
|||
fee: Zatoshi(amount: 10),
|
||||
shielded: $0.shielded,
|
||||
status: $0.status,
|
||||
subtitle: $0.subtitle,
|
||||
timestamp: $0.date,
|
||||
uuid: $0.uuid
|
||||
)
|
||||
|
@ -438,12 +434,11 @@ class TestWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
|||
date: 1651039606,
|
||||
amount: Zatoshi(amount: 6),
|
||||
status: .paid(success: false),
|
||||
subtitle: "pending",
|
||||
uuid: "ff66"
|
||||
),
|
||||
TransactionStateMockHelper(date: 1651039303, amount: Zatoshi(amount: 7), subtitle: "pending", uuid: "gg77"),
|
||||
TransactionStateMockHelper(date: 1651039707, amount: Zatoshi(amount: 8), status: .paid(success: true), subtitle: "pending", uuid: "hh88"),
|
||||
TransactionStateMockHelper(date: 1651039808, amount: Zatoshi(amount: 9), subtitle: "pending", uuid: "ii99")
|
||||
TransactionStateMockHelper(date: 1651039303, amount: Zatoshi(amount: 7), uuid: "gg77"),
|
||||
TransactionStateMockHelper(date: 1651039707, amount: Zatoshi(amount: 8), status: .paid(success: true), uuid: "hh88"),
|
||||
TransactionStateMockHelper(date: 1651039808, amount: Zatoshi(amount: 9), uuid: "ii99")
|
||||
]
|
||||
|
||||
return Effect(
|
||||
|
@ -453,8 +448,7 @@ class TestWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
|||
amount: $0.amount,
|
||||
fee: Zatoshi(amount: 10),
|
||||
shielded: $0.shielded,
|
||||
status: $0.status,
|
||||
subtitle: $0.subtitle,
|
||||
status: $0.amount.amount > 5 ? .pending : $0.status,
|
||||
timestamp: $0.date,
|
||||
uuid: $0.uuid
|
||||
)
|
||||
|
|
|
@ -21,7 +21,8 @@ class HomeTests: XCTestCase {
|
|||
mnemonic: .mock,
|
||||
scheduler: testScheduler.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: MockWrappedSDKSynchronizer(),
|
||||
walletStorage: .throwing
|
||||
walletStorage: .throwing,
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
let store = TestStore(
|
||||
|
@ -50,7 +51,8 @@ class HomeTests: XCTestCase {
|
|||
mnemonic: .mock,
|
||||
scheduler: testScheduler.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: MockWrappedSDKSynchronizer(),
|
||||
walletStorage: .throwing
|
||||
walletStorage: .throwing,
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
let store = TestStore(
|
||||
|
@ -80,7 +82,6 @@ class HomeTests: XCTestCase {
|
|||
fee: Zatoshi(amount: 10),
|
||||
shielded: $0.shielded,
|
||||
status: $0.status,
|
||||
subtitle: $0.subtitle,
|
||||
timestamp: $0.date,
|
||||
uuid: $0.uuid
|
||||
)
|
||||
|
@ -109,7 +110,8 @@ class HomeTests: XCTestCase {
|
|||
mnemonic: .mock,
|
||||
scheduler: testScheduler.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: MockWrappedSDKSynchronizer(),
|
||||
walletStorage: .throwing
|
||||
walletStorage: .throwing,
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
let homeState = HomeState(
|
||||
|
@ -151,7 +153,8 @@ class HomeTests: XCTestCase {
|
|||
mnemonic: .mock,
|
||||
scheduler: testScheduler.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: MockWrappedSDKSynchronizer(),
|
||||
walletStorage: .throwing
|
||||
walletStorage: .throwing,
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
let homeState = HomeState(
|
||||
|
@ -195,7 +198,8 @@ class HomeTests: XCTestCase {
|
|||
mnemonic: .mock,
|
||||
scheduler: testScheduler.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: MockWrappedSDKSynchronizer(),
|
||||
walletStorage: .throwing
|
||||
walletStorage: .throwing,
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
let store = TestStore(
|
||||
|
|
|
@ -67,7 +67,6 @@ class SendTests: XCTestCase {
|
|||
fee: Zatoshi(amount: 10),
|
||||
id: "id",
|
||||
status: .paid(success: true),
|
||||
subtitle: "sub",
|
||||
timestamp: 1234567,
|
||||
zecAmount: Zatoshi(amount: 10)
|
||||
)
|
||||
|
|
|
@ -25,7 +25,6 @@ class HomeSnapshotTests: XCTestCase {
|
|||
fee: Zatoshi(amount: 10),
|
||||
shielded: $0.shielded,
|
||||
status: $0.status,
|
||||
subtitle: $0.subtitle,
|
||||
timestamp: $0.date,
|
||||
uuid: $0.uuid
|
||||
)
|
||||
|
@ -77,7 +76,6 @@ class HomeSnapshotTests: XCTestCase {
|
|||
fee: Zatoshi(amount: 1_000_000),
|
||||
id: "ff3927e1f83df9b1b0dc75540ddc59ee435eecebae914d2e6dfe8576fbedc9a8",
|
||||
status: .paid(success: true),
|
||||
subtitle: "",
|
||||
timestamp: 1234567,
|
||||
zecAmount: Zatoshi(amount: 25_000_000)
|
||||
)
|
||||
|
@ -103,9 +101,10 @@ class HomeSnapshotTests: XCTestCase {
|
|||
|
||||
// wallet event detail
|
||||
let testEnvironment = WalletEventsFlowEnvironment(
|
||||
pasteboard: .test,
|
||||
scheduler: DispatchQueue.test.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: TestWrappedSDKSynchronizer(),
|
||||
pasteboard: .test
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
ViewStore(store).send(.walletEvents(.updateRoute(.showWalletEvent(walletEvent))))
|
||||
|
|
|
@ -10,7 +10,7 @@ import XCTest
|
|||
import ComposableArchitecture
|
||||
|
||||
class WalletEventsSnapshotTests: XCTestCase {
|
||||
func testWalletEventDetailSnapshot() throws {
|
||||
func testWalletEventDetailSnapshot_sent() throws {
|
||||
let transaction = TransactionState(
|
||||
memo:
|
||||
"""
|
||||
|
@ -23,7 +23,6 @@ class WalletEventsSnapshotTests: XCTestCase {
|
|||
fee: Zatoshi(amount: 1_000_000),
|
||||
id: "ff3927e1f83df9b1b0dc75540ddc59ee435eecebae914d2e6dfe8576fbedc9a8",
|
||||
status: .paid(success: true),
|
||||
subtitle: "",
|
||||
timestamp: 1234567,
|
||||
zecAmount: Zatoshi(amount: 25_000_000)
|
||||
)
|
||||
|
@ -49,9 +48,187 @@ class WalletEventsSnapshotTests: XCTestCase {
|
|||
|
||||
// wallet event detail
|
||||
let testEnvironment = WalletEventsFlowEnvironment(
|
||||
pasteboard: .test,
|
||||
scheduler: DispatchQueue.test.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: TestWrappedSDKSynchronizer(),
|
||||
pasteboard: .test
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
ViewStore(store).send(.walletEvents(.updateRoute(.showWalletEvent(walletEvent))))
|
||||
let walletEventsStore = WalletEventsFlowStore(
|
||||
initialState: .placeHolder,
|
||||
reducer: .default,
|
||||
environment: testEnvironment
|
||||
)
|
||||
|
||||
addAttachments(
|
||||
name: "\(#function)_WalletEventDetail",
|
||||
TransactionDetailView(transaction: transaction, viewStore: ViewStore(walletEventsStore))
|
||||
)
|
||||
}
|
||||
|
||||
func testWalletEventDetailSnapshot_received() throws {
|
||||
let transaction = TransactionState(
|
||||
memo:
|
||||
"""
|
||||
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,
|
||||
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
||||
fee: Zatoshi(amount: 1_000_000),
|
||||
id: "ff3927e1f83df9b1b0dc75540ddc59ee435eecebae914d2e6dfe8576fbedc9a8",
|
||||
status: .received,
|
||||
timestamp: 1234567,
|
||||
zecAmount: Zatoshi(amount: 25_000_000)
|
||||
)
|
||||
|
||||
let walletEvent = WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||
|
||||
let balance = Balance(verified: 12_345_000, total: 12_345_000)
|
||||
let store = HomeStore(
|
||||
initialState: .init(
|
||||
drawerOverlay: .partial,
|
||||
profileState: .placeholder,
|
||||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatus: "",
|
||||
totalBalance: Zatoshi(amount: balance.total),
|
||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent])),
|
||||
verifiedBalance: Zatoshi(amount: balance.verified)
|
||||
),
|
||||
reducer: .default,
|
||||
environment: .demo
|
||||
)
|
||||
|
||||
// wallet event detail
|
||||
let testEnvironment = WalletEventsFlowEnvironment(
|
||||
pasteboard: .test,
|
||||
scheduler: DispatchQueue.test.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: TestWrappedSDKSynchronizer(),
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
ViewStore(store).send(.walletEvents(.updateRoute(.showWalletEvent(walletEvent))))
|
||||
let walletEventsStore = WalletEventsFlowStore(
|
||||
initialState: .placeHolder,
|
||||
reducer: .default,
|
||||
environment: testEnvironment
|
||||
)
|
||||
|
||||
addAttachments(
|
||||
name: "\(#function)_WalletEventDetail",
|
||||
TransactionDetailView(transaction: transaction, viewStore: ViewStore(walletEventsStore))
|
||||
)
|
||||
}
|
||||
|
||||
func testWalletEventDetailSnapshot_pending() throws {
|
||||
let transaction = TransactionState(
|
||||
memo:
|
||||
"""
|
||||
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,
|
||||
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
||||
fee: Zatoshi(amount: 1_000_000),
|
||||
id: "ff3927e1f83df9b1b0dc75540ddc59ee435eecebae914d2e6dfe8576fbedc9a8",
|
||||
status: .pending,
|
||||
timestamp: 1234567,
|
||||
zecAmount: Zatoshi(amount: 25_000_000)
|
||||
)
|
||||
|
||||
let walletEvent = WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||
|
||||
let balance = Balance(verified: 12_345_000, total: 12_345_000)
|
||||
let store = HomeStore(
|
||||
initialState: .init(
|
||||
drawerOverlay: .partial,
|
||||
profileState: .placeholder,
|
||||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatus: "",
|
||||
totalBalance: Zatoshi(amount: balance.total),
|
||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent])),
|
||||
verifiedBalance: Zatoshi(amount: balance.verified)
|
||||
),
|
||||
reducer: .default,
|
||||
environment: .demo
|
||||
)
|
||||
|
||||
// wallet event detail
|
||||
let testEnvironment = WalletEventsFlowEnvironment(
|
||||
pasteboard: .test,
|
||||
scheduler: DispatchQueue.test.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: TestWrappedSDKSynchronizer(),
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
let walletEventsState = WalletEventsFlowState(
|
||||
requiredTransactionConfirmations: 10,
|
||||
walletEvents: .placeholder
|
||||
)
|
||||
|
||||
ViewStore(store).send(.walletEvents(.updateRoute(.showWalletEvent(walletEvent))))
|
||||
let walletEventsStore = WalletEventsFlowStore(
|
||||
initialState: walletEventsState,
|
||||
reducer: .default,
|
||||
environment: testEnvironment
|
||||
)
|
||||
|
||||
addAttachments(
|
||||
name: "\(#function)_WalletEventDetail",
|
||||
TransactionDetailView(transaction: transaction, viewStore: ViewStore(walletEventsStore))
|
||||
)
|
||||
}
|
||||
|
||||
func testWalletEventDetailSnapshot_failed() throws {
|
||||
let transaction = TransactionState(
|
||||
errorMessage: "possible roll back",
|
||||
memo:
|
||||
"""
|
||||
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,
|
||||
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
||||
fee: Zatoshi(amount: 1_000_000),
|
||||
id: "ff3927e1f83df9b1b0dc75540ddc59ee435eecebae914d2e6dfe8576fbedc9a8",
|
||||
status: .failed,
|
||||
timestamp: 1234567,
|
||||
zecAmount: Zatoshi(amount: 25_000_000)
|
||||
)
|
||||
|
||||
let walletEvent = WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||
|
||||
let balance = Balance(verified: 12_345_000, total: 12_345_000)
|
||||
let store = HomeStore(
|
||||
initialState: .init(
|
||||
drawerOverlay: .partial,
|
||||
profileState: .placeholder,
|
||||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatus: "",
|
||||
totalBalance: Zatoshi(amount: balance.total),
|
||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent])),
|
||||
verifiedBalance: Zatoshi(amount: balance.verified)
|
||||
),
|
||||
reducer: .default,
|
||||
environment: .demo
|
||||
)
|
||||
|
||||
// wallet event detail
|
||||
let testEnvironment = WalletEventsFlowEnvironment(
|
||||
pasteboard: .test,
|
||||
scheduler: DispatchQueue.test.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: TestWrappedSDKSynchronizer(),
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
ViewStore(store).send(.walletEvents(.updateRoute(.showWalletEvent(walletEvent))))
|
||||
|
|
|
@ -13,9 +13,10 @@ class WalletEventsTests: XCTestCase {
|
|||
static let testScheduler = DispatchQueue.test
|
||||
|
||||
let testEnvironment = WalletEventsFlowEnvironment(
|
||||
pasteboard: .test,
|
||||
scheduler: testScheduler.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: TestWrappedSDKSynchronizer(),
|
||||
pasteboard: .test
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
func testSynchronizerSubscription() throws {
|
||||
|
@ -48,12 +49,11 @@ class WalletEventsTests: XCTestCase {
|
|||
date: 1651039606,
|
||||
amount: Zatoshi(amount: 6),
|
||||
status: .paid(success: false),
|
||||
subtitle: "pending",
|
||||
uuid: "ff66"
|
||||
),
|
||||
TransactionStateMockHelper(date: 1651039303, amount: Zatoshi(amount: 7), subtitle: "pending", uuid: "gg77"),
|
||||
TransactionStateMockHelper(date: 1651039707, amount: Zatoshi(amount: 8), status: .paid(success: true), subtitle: "pending", uuid: "hh88"),
|
||||
TransactionStateMockHelper(date: 1651039808, amount: Zatoshi(amount: 9), subtitle: "pending", uuid: "ii99")
|
||||
TransactionStateMockHelper(date: 1651039303, amount: Zatoshi(amount: 7), uuid: "gg77"),
|
||||
TransactionStateMockHelper(date: 1651039707, amount: Zatoshi(amount: 8), status: .paid(success: true), uuid: "hh88"),
|
||||
TransactionStateMockHelper(date: 1651039808, amount: Zatoshi(amount: 9), uuid: "ii99")
|
||||
]
|
||||
|
||||
let walletEvents: [WalletEvent] = mocked.map {
|
||||
|
@ -61,14 +61,13 @@ class WalletEventsTests: XCTestCase {
|
|||
amount: $0.amount,
|
||||
fee: Zatoshi(amount: 10),
|
||||
shielded: $0.shielded,
|
||||
status: $0.status,
|
||||
subtitle: $0.subtitle,
|
||||
status: $0.amount.amount > 5 ? .pending : $0.status,
|
||||
timestamp: $0.date,
|
||||
uuid: $0.uuid
|
||||
)
|
||||
return WalletEvent(
|
||||
id: transaction.id,
|
||||
state: transaction.subtitle == "pending" ? .pending(transaction) : .send(transaction),
|
||||
state: transaction.status == .pending ? .pending(transaction) : .send(transaction),
|
||||
timestamp: transaction.timestamp
|
||||
)
|
||||
}
|
||||
|
@ -106,9 +105,10 @@ class WalletEventsTests: XCTestCase {
|
|||
let pasteboard = WrappedPasteboard.test
|
||||
|
||||
let testEnvironment = WalletEventsFlowEnvironment(
|
||||
pasteboard: pasteboard,
|
||||
scheduler: DispatchQueue.test.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: TestWrappedSDKSynchronizer(),
|
||||
pasteboard: pasteboard
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
let store = TestStore(
|
||||
|
|
Loading…
Reference in New Issue