[#950] Sapling address when testnet build (#959)

- the sapling address and its QR code are present only for the testnet builds
- unit tests resolved and tweaked a bit - TCA actions have been merged into 1 copyToPasteboard
- snapshot tests for both mainnet and testnet version to prove sapling is missing on mainnet
This commit is contained in:
Lukas Korba 2023-12-04 16:20:51 +01:00 committed by GitHub
parent e27e4ed34d
commit ad4ac13e86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 103 additions and 29 deletions

View File

@ -14,7 +14,7 @@ directly impact users rather than highlighting other crucial architectural updat
- When the send button is tapped, the sending title + spinner is shown instead of just the spinner. Also, when the send is done, and redirect to the Account page is done, the sending transaction is already populated in the list. The lag between it was presented has been fixed.
### Removed
- The sapling address and the QR of it has been removed from the receive screen. The only meaningful options are the UA and the transparent addresses.
- [testnet only] The sapling address and the QR of it has been removed from the receive screen. The only meaningful options are the UA and the transparent addresses.
### Added
- Confirmation screen when sending funds. The initial screen is about filling in the address, amount and message (optional). The butoon `review` leads to a brand new screen where the summary of the transaction is presented. The send is confirmed by tapping the send button. Going back to update send data is possible via `go back` button.

View File

@ -10,10 +10,13 @@ import ComposableArchitecture
import ZcashLightClientKit
import Pasteboard
import Generated
import Utils
public typealias AddressDetailsStore = Store<AddressDetailsReducer.State, AddressDetailsReducer.Action>
public struct AddressDetailsReducer: Reducer {
let networkType: NetworkType
public struct State: Equatable {
public var uAddress: UnifiedAddress?
@ -21,6 +24,15 @@ public struct AddressDetailsReducer: Reducer {
uAddress?.stringEncoded ?? L10n.AddressDetails.Error.cantExtractUnifiedAddress
}
public var saplingAddress: String {
do {
let address = try uAddress?.saplingReceiver().stringEncoded ?? L10n.AddressDetails.Error.cantExtractSaplingAddress
return address
} catch {
return L10n.AddressDetails.Error.cantExtractSaplingAddress
}
}
public var transparentAddress: String {
do {
let address = try uAddress?.transparentReceiver().stringEncoded ?? L10n.AddressDetails.Error.cantExtractTransparentAddress
@ -38,21 +50,19 @@ public struct AddressDetailsReducer: Reducer {
}
public enum Action: Equatable {
case copyTransparentAddressToPastboard
case copyUnifiedAddressToPastboard
case copyToPastboard(RedactableString)
}
@Dependency(\.pasteboard) var pasteboard
public init() {}
public init(networkType: NetworkType) {
self.networkType = networkType
}
public func reduce(into state: inout State, action: Action) -> ComposableArchitecture.Effect<Action> {
switch action {
case .copyTransparentAddressToPastboard:
pasteboard.setString(state.transparentAddress.redacted)
case .copyUnifiedAddressToPastboard:
pasteboard.setString(state.unifiedAddress.redacted)
case .copyToPastboard(let text):
pasteboard.setString(text)
}
return .none
}
@ -74,6 +84,6 @@ extension AddressDetailsStore {
public static let placeholder = AddressDetailsStore(
initialState: .initial
) {
AddressDetailsReducer()
AddressDetailsReducer(networkType: .testnet)
}
}

View File

@ -7,28 +7,40 @@
import SwiftUI
import ComposableArchitecture
import ZcashLightClientKit
import Generated
import UIComponents
import Utils
public struct AddressDetailsView: View {
let store: AddressDetailsStore
public init(store: AddressDetailsStore) {
let networkType: NetworkType
public init(store: AddressDetailsStore, networkType: NetworkType) {
self.store = store
self.networkType = networkType
}
public var body: some View {
WithViewStore(store, observe: { $0 }) { viewStore in
ScrollView {
addressBlock(L10n.AddressDetails.ua, viewStore.unifiedAddress) {
viewStore.send(.copyUnifiedAddressToPastboard)
viewStore.send(.copyToPastboard(viewStore.unifiedAddress.redacted))
}
.frame(maxWidth: .infinity)
.padding(.top, 20)
#if DEBUG
if networkType == .testnet {
addressBlock(L10n.AddressDetails.sa, viewStore.saplingAddress) {
viewStore.send(.copyToPastboard(viewStore.saplingAddress.redacted))
}
}
#endif
addressBlock(L10n.AddressDetails.ta, viewStore.transparentAddress) {
viewStore.send(.copyTransparentAddressToPastboard)
viewStore.send(.copyToPastboard(viewStore.transparentAddress.redacted))
}
}
.padding(.vertical, 1)
@ -85,6 +97,6 @@ extension AddressDetailsView {
#Preview {
NavigationView {
AddressDetailsView(store: .placeholder)
AddressDetailsView(store: .placeholder, networkType: .testnet)
}
}

View File

@ -53,7 +53,8 @@ private extension RootView {
state: \.tabsState,
action: RootReducer.Action.tabs
),
tokenName: tokenName
tokenName: tokenName,
networkType: networkType
)
}
.navigationViewStyle(.stack)

View File

@ -96,7 +96,7 @@ public struct TabsReducer: Reducer {
}
Scope(state: \.addressDetailsState, action: /Action.addressDetails) {
AddressDetailsReducer()
AddressDetailsReducer(networkType: networkType)
}
Scope(state: \.balanceBreakdownState, action: /Action.balanceBreakdown) {

View File

@ -7,6 +7,8 @@
import SwiftUI
import ComposableArchitecture
import ZcashLightClientKit
import Generated
import AddressDetails
import BalanceBreakdown
@ -15,13 +17,15 @@ import SendFlow
import Settings
public struct TabsView: View {
let networkType: NetworkType
var store: TabsStore
let tokenName: String
@Namespace var tabsID
public init(store: TabsStore, tokenName: String) {
public init(store: TabsStore, tokenName: String, networkType: NetworkType) {
self.store = store
self.tokenName = tokenName
self.networkType = networkType
}
public var body: some View {
@ -51,7 +55,8 @@ public struct TabsView: View {
store: self.store.scope(
state: \.addressDetailsState,
action: TabsReducer.Action.addressDetails
)
),
networkType: networkType
)
.tag(TabsReducer.State.Tab.receive)
@ -147,6 +152,6 @@ public struct TabsView: View {
#Preview {
NavigationView {
TabsView(store: .demo, tokenName: "TAZ")
TabsView(store: .demo, tokenName: "TAZ", networkType: .testnet)
}
}

View File

@ -24,14 +24,14 @@ class AddressDetailsTests: XCTestCase {
let store = TestStore(
initialState: AddressDetailsReducer.State(uAddress: uAddress)
) {
AddressDetailsReducer()
AddressDetailsReducer(networkType: .testnet)
}
store.dependencies.pasteboard = testPasteboard
await store.send(.copyTransparentAddressToPastboard)
let expectedAddress = try uAddress.transparentReceiver().stringEncoded
await store.send(.copyToPastboard(expectedAddress.redacted))
XCTAssertEqual(
testPasteboard.getString()?.data,
@ -49,12 +49,12 @@ class AddressDetailsTests: XCTestCase {
let store = TestStore(
initialState: AddressDetailsReducer.State(uAddress: uAddress)
) {
AddressDetailsReducer()
AddressDetailsReducer(networkType: .testnet)
}
store.dependencies.pasteboard = testPasteboard
await store.send(.copyUnifiedAddressToPastboard)
await store.send(.copyToPastboard(uAddress.stringEncoded.redacted))
XCTAssertEqual(
testPasteboard.getString()?.data,
@ -64,4 +64,29 @@ class AddressDetailsTests: XCTestCase {
await store.finish()
}
func testCopySaplingAddressToPasteboard() async throws {
let testPasteboard = PasteboardClient.testPasteboard
let uAddress = try UnifiedAddress(encoding: uAddressEncoding, network: .testnet)
let store = TestStore(
initialState: AddressDetailsReducer.State(uAddress: uAddress)
) {
AddressDetailsReducer(networkType: .testnet)
}
store.dependencies.pasteboard = testPasteboard
let expectedAddress = try uAddress.saplingReceiver().stringEncoded
await store.send(.copyToPastboard(expectedAddress.redacted))
XCTAssertEqual(
testPasteboard.getString()?.data,
expectedAddress,
"AddressDetails: `testCopySaplingAddressToPasteboard` is expected to match the input `\(expectedAddress)`"
)
await store.finish()
}
}

View File

@ -13,20 +13,41 @@ import AddressDetails
@testable import secant_testnet
class AddressDetailsSnapshotTests: XCTestCase {
func testAddressDetailsSnapshot() throws {
func testAddressDetailsSnapshot_testnet() throws {
// swiftlint:disable line_length
let uAddress = try UnifiedAddress(
encoding: "utest1zkkkjfxkamagznjr6ayemffj2d2gacdwpzcyw669pvg06xevzqslpmm27zjsctlkstl2vsw62xrjktmzqcu4yu9zdhdxqz3kafa4j2q85y6mv74rzjcgjg8c0ytrg7dwyzwtgnuc76h",
network: .testnet
)
let networkType = NetworkType.testnet
let store = Store(
initialState: AddressDetailsReducer.State(uAddress: uAddress)
) {
AddressDetailsReducer()
AddressDetailsReducer(networkType: networkType)
.dependency(\.walletConfigProvider, .noOp)
}
addAttachments(AddressDetailsView(store: store))
addAttachments(AddressDetailsView(store: store, networkType: networkType))
}
func testAddressDetailsSnapshot_mainnet() throws {
// swiftlint:disable line_length
let uAddress = try UnifiedAddress(
encoding: "utest1zkkkjfxkamagznjr6ayemffj2d2gacdwpzcyw669pvg06xevzqslpmm27zjsctlkstl2vsw62xrjktmzqcu4yu9zdhdxqz3kafa4j2q85y6mv74rzjcgjg8c0ytrg7dwyzwtgnuc76h",
network: .testnet
)
let networkType = NetworkType.mainnet
let store = Store(
initialState: AddressDetailsReducer.State(uAddress: uAddress)
) {
AddressDetailsReducer(networkType: networkType)
.dependency(\.walletConfigProvider, .noOp)
}
addAttachments(AddressDetailsView(store: store, networkType: networkType))
}
}