Enable SwiftLint

This commit is contained in:
Adam Stener 2021-09-14 06:15:29 -05:00
parent d465d46956
commit 789333f234
39 changed files with 465 additions and 461 deletions

View File

@ -2,8 +2,8 @@
# https://github.com/raywenderlich/swift-style-guide
excluded:
- ${PWD}/Pods
- ${PWD}/xctemplates
- Pods
- xctemplates
disabled_rules:
- notification_center_detachment
@ -37,7 +37,7 @@ opt_in_rules:
- legacy_random
- literal_expression_end_indentation
- multiline_arguments
- multiline_argument_brackets
- multiline_arguments_brackets
- multiline_function_chains
- multiline_literal_brackets
- multiline_parameters
@ -70,26 +70,26 @@ custom_rules:
severity: warning
string_concatenation:
included: ".*\.swift"
excluded: ".*Test\.swift"
included: ".*\\.swift"
excluded: ".*Test\\.swift"
name: "String Concatenation"
regex: '' \+ "|" \+ |\+= "'
regex: " \\+ \"|\" \\+ |\\+= \""
message: "Please use string interpolation instead of concatenation"
severity: error
print_function_usage:
included: ".*\.swift"
excluded: ".*Test\.swift"
included: ".*\\.swift"
excluded: ".*Test\\.swift"
name: "Swift print() or debugPrint() should not be used in App Code"
regex: "print\(|debugPrint\("
regex: "print\\(|debugPrint\\("
message: "The Swift print() or debugPrint() functions should not be used."
severity: warning
nslog_function_usage:
included: ".*\.swift"
excluded: ".*Test\.swift"
included: ".*\\.swift"
excluded: ".*Test\\.swift"
name: "Swift NSLog() should not be used in App Code"
regex: "NSLog\("
regex: "NSLog\\("
message: "The swift NSLog function should not be used."
severity: error
@ -117,7 +117,7 @@ identifier_name:
- z
indentation_width:
indentation_width: 2
indentation_width: 4
line_length:
warning: 150
@ -127,7 +127,7 @@ line_length:
file_length:
warning: 600
ignore_comment_only_lines: false: true
ignore_comment_only_lines: true
multiline_arguments:
first_argument_location: next_line
@ -141,4 +141,4 @@ trailing_whitespace:
ignores_comments: true
vertical_whitespace:
max_empty_lines: 2
max_empty_lines: 1

View File

@ -385,6 +385,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 0D4E7A2A26B364180058B01E /* Build configuration list for PBXNativeTarget "secant-testnet" */;
buildPhases = (
6696BA8726F0B1D200D5C875 /* SwiftLint */,
0D4E7A0126B364170058B01E /* Sources */,
0D4E7A0226B364170058B01E /* Frameworks */,
0D4E7A0326B364170058B01E /* Resources */,
@ -503,6 +504,27 @@
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
6696BA8726F0B1D200D5C875 /* SwiftLint */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = SwiftLint;
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "swiftlint_version=0.44.0\n\nif which swiftlint >/dev/null; then\n if [ $(swiftlint version) = $swiftlint_version ]; then\n swiftlint\n else\n echo \"warning: Compatible SwiftLint version not installed, download version $swiftlint_version from https://github.com/realm/SwiftLint. Currently installed version is $(swiftlint version)\"\n fi \nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
0D4E7A0126B364170058B01E /* Sources */ = {
isa = PBXSourcesBuildPhase;

View File

@ -8,11 +8,9 @@
import Foundation
open class BaseViewModel<S> {
public var services: S
public init(services: S) {
self.services = services
}
}

View File

@ -7,13 +7,12 @@
import Foundation
protocol KeyStoring {
func importBirthday(_ height: BlockHeight) throws
func exportBirthday() throws -> BlockHeight
func importPhrase(bip39 phrase: String) throws
func exportPhrase() throws -> String
var keysPresent: Bool { get }
/**
Use carefully: Deletes the seed phrase from the keychain
*/
@ -28,6 +27,8 @@ protocol KeyStoring {
There's no fate but what we make for ourselves - Sarah Connor
*/
func nukeWallet()
var keysPresent: Bool { get }
}
enum KeyStoringError: Error {

View File

@ -7,6 +7,7 @@
//
import Foundation
enum MnemonicError: Error {
case invalidSeed
case checksumFailed
@ -14,26 +15,27 @@ enum MnemonicError: Error {
protocol MnemonicSeedPhraseHandling {
/**
random 24 words mnemonic phrase
Random 24 words mnemonic phrase
*/
func randomMnemonic() throws -> String
/**
random 24 words mnemonic phrase as array of words
Random 24 words mnemonic phrase as array of words
*/
func randomMnemonicWords() throws -> [String]
/**
generate deterministic seed from mnemonic phrase
Generate deterministic seed from mnemonic phrase
*/
func toSeed(mnemonic: String) throws -> [UInt8]
/**
get this mnemonic
Get this mnemonic
*/
func asWords(mnemonic: String) throws -> [String]
/**
validates whether the given mnemonic is correct
Validates whether the given mnemonic is correct
*/
func isValid(mnemonic: String) throws
}

View File

@ -13,7 +13,6 @@ protocol Services {
var keyStorage: KeyStoring { get }
}
protocol ZcashNetworkProvider {
func currentNetwork() -> ZcashNetwork
}

View File

@ -6,6 +6,7 @@
//
import Foundation
/**
Funds Expressed in Zatoshis
*/
@ -14,6 +15,7 @@ protocol Funds {
Confirmed, spendable funds
*/
var confirmed: Int64 { get }
/**
Unconfirmed, not yet spendable funds.
*/
@ -33,58 +35,45 @@ protocol WalletBalance {
Transparent funds. This is the sum of the UTXOs of the user found at a given time
*/
var transaparent: Funds { get }
/**
Funds on the Sapling shielded pool for a given user.
*/
var sapling: Funds { get }
/**
Funds on the Orchard shielded pool for a given user.
*/
var orchard: Funds { get }
/**
The sum of all confirmed funds, transparent, sapling and orchard funds (calculated)
*/
var totalAvailableBalance: Int64 { get }
/**
the sum of all unconfirmed funds: transparent, sapling, and orchard funds (calculated
The sum of all unconfirmed funds: transparent, sapling, and orchard funds (calculated
*/
var totalUnconfirmedBalance: Int64 { get }
/**
the sum of all funds confirmed and unconfirmed of all pools (transparent, sapling and orchard).
The sum of all funds confirmed and unconfirmed of all pools (transparent, sapling and orchard).
*/
var totalBalance: Int64 { get }
/**
represents a the value of Zero funds.
Represents a the value of Zero funds.
*/
static var nullBalance: WalletBalance { get }
}
/**
Concrete Wallet Balance.
*/
struct Balance: WalletBalance {
var transaparent: Funds
var sapling: Funds
var orchard: Funds
}
struct ZcashFunds: Funds {
static var noFunds: Funds {
ZcashFunds(confirmed: 0, unconfirmed: 0)
}
var confirmed: Int64
var unconfirmed: Int64
}
extension WalletBalance {
static var nullBalance: WalletBalance {
Balance(transaparent: ZcashFunds.noFunds, sapling: ZcashFunds.noFunds, orchard: ZcashFunds.noFunds)
Balance(
transaparent: ZcashFunds.noFunds,
sapling: ZcashFunds.noFunds,
orchard: ZcashFunds.noFunds
)
}
var totalAvailableBalance: Int64 {
@ -99,3 +88,21 @@ extension WalletBalance {
totalAvailableBalance + totalUnconfirmedBalance
}
}
/**
Concrete Wallet Balance.
*/
struct Balance: WalletBalance {
var transaparent: Funds
var sapling: Funds
var orchard: Funds
}
struct ZcashFunds: Funds {
static var noFunds: Funds {
ZcashFunds(confirmed: 0, unconfirmed: 0)
}
var confirmed: Int64
var unconfirmed: Int64
}

View File

@ -15,23 +15,14 @@ enum AppRouterScreen {
}
class AppRouter: Router {
// MARK: - Published vars
@Published var screen: AppRouterScreen = .appLoading
// MARK: - Private vars
// MARK: - Internal vars
var services: Services
// MARK: - Initialization
init(services: Services) {
self.services = services
}
// MARK: - Methods
@ViewBuilder func rootView() -> some View {
// Add your content here
NavigationView {
@ -52,23 +43,12 @@ class AppRouter: Router {
}
}
struct AppRouterView: View {
@StateObject var router: AppRouter
@ViewBuilder func viewForScreen(_ screen: AppRouterScreen) -> some View {
switch self.router.screen {
case .appLoading:
self.router.loadingScreen()
case .createRestoreWallet:
self.router.createNew()
case .home:
self.router.home()
}
}
var body: some View {
viewForScreen(router.screen)
.onAppear() {
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
if router.services.keyStorage.keysPresent {
router.screen = .home
@ -78,4 +58,12 @@ struct AppRouterView: View {
}
}
}
@ViewBuilder func viewForScreen(_ screen: AppRouterScreen) -> some View {
switch router.screen {
case .appLoading: router.loadingScreen()
case .createRestoreWallet: router.createNew()
case .home: router.home()
}
}
}

View File

@ -7,16 +7,15 @@
import SwiftUI
protocol BackupWalletScreenRouter: AnyObject {
}
protocol BackupWalletScreenRouter: AnyObject {}
struct BackupWalletScreen: View {
@State var router: BackupWalletScreenRouter?
@ObservedObject var viewModel: BackupWalletScreenViewModel
@State var router: BackupWalletScreenRouter?
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
Text("Hello, World!")
}
}

View File

@ -5,9 +5,7 @@
// Created by Francisco Gindre on 8/9/21.
//
import Foundation
import Combine
import Foundation
class BackupWalletScreenViewModel: BaseViewModel<Services>, ObservableObject {
}
class BackupWalletScreenViewModel: BaseViewModel<Services>, ObservableObject {}

View File

@ -7,16 +7,15 @@
import SwiftUI
protocol BalanceScreenRouter: AnyObject {
}
protocol BalanceScreenRouter: AnyObject {}
struct BalanceScreen: View {
@State var router: BalanceScreenRouter?
@ObservedObject var viewModel: BalanceScreenViewModel
@State var router: BalanceScreenRouter?
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
Text("Hello, World!")
}
}

View File

@ -5,9 +5,7 @@
// Created by Francisco Gindre on 8/12/21.
//
import Foundation
import Combine
import Foundation
class BalanceScreenViewModel: BaseViewModel<Services>, ObservableObject {
}
class BalanceScreenViewModel: BaseViewModel<Services>, ObservableObject {}

View File

@ -7,16 +7,15 @@
import SwiftUI
protocol HistoryScreenRouter: AnyObject {
}
protocol HistoryScreenRouter: AnyObject {}
struct HistoryScreen: View {
@State var router: HistoryScreenRouter?
@ObservedObject var viewModel: HistoryScreenViewModel
@State var router: HistoryScreenRouter?
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
Text("Hello, World!")
}
}

View File

@ -5,9 +5,7 @@
// Created by Francisco Gindre on 8/12/21.
//
import Foundation
import Combine
import Foundation
class HistoryScreenViewModel: BaseViewModel<Services>, ObservableObject {
}
class HistoryScreenViewModel: BaseViewModel<Services>, ObservableObject {}

View File

@ -17,10 +17,10 @@ protocol HomeScreenRouter: AnyObject {
}
struct HomeScreen: View {
@State var router: HomeScreenRouter?
@ObservedObject var viewModel: HomeScreenViewModel
@State var router: HomeScreenRouter?
var body: some View {
VStack {
Text("Hello, World!")
@ -32,16 +32,16 @@ struct HomeScreen: View {
.navigationBarTitle("", displayMode: .inline)
.navigationBarItems(
leading: qrCodeButton,
trailing: profileButton)
trailing: profileButton
)
}
@ViewBuilder var qrCodeButton: some View {
Button(action: {}, label: {
Image(systemName: "qrcode.viewfinder")
.frame(width: 20, height: 20, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
.frame(width: 20, height: 20, alignment: .center)
})
.contentShape(Circle())
}
@ViewBuilder var profileButton: some View {
@ -74,14 +74,33 @@ struct HomeScreen: View {
}
}
// MARK: - Previews
struct HomeScreenPreviews: PreviewProvider {
static var previews: some View {
NavigationView {
HomeScreen(viewModel: HomeScreenViewModel.mockWithValues(services: MockServices(), status: .offline, balance: mockBalance, fiatConversion: 1.12453))
HomeScreen(
viewModel: HomeScreenViewModel.mockWithValues(
services: MockServices(),
status: .offline,
balance: mockBalance,
fiatConversion: 1.12453
)
)
}
}
static var mockBalance: WalletBalance {
Balance(transaparent: ZcashFunds.noFunds, sapling: ZcashFunds(confirmed: 123456790, unconfirmed: 0), orchard: ZcashFunds(confirmed: 0, unconfirmed: 0))
Balance(
transaparent: ZcashFunds.noFunds,
sapling: ZcashFunds(
confirmed: 123456790,
unconfirmed: 0
),
orchard: ZcashFunds(
confirmed: 0,
unconfirmed: 0
)
)
}
}

View File

@ -5,8 +5,8 @@
// Created by Francisco Gindre on 8/9/21.
//
import Foundation
import Combine
import Foundation
class HomeScreenViewModel: BaseViewModel<Services>, ObservableObject {
enum Status {
@ -16,22 +16,22 @@ class HomeScreenViewModel: BaseViewModel<Services>, ObservableObject {
}
@Published var balance: WalletBalance = Balance.nullBalance
@Published var fiatConversion: Decimal = 0
@Published var status = Status.offline
}
extension HomeScreenViewModel {
static func mockWithValues(services: Services,
static func mockWithValues(
services: Services,
status: Status,
balance: WalletBalance,
fiatConversion: Decimal) -> HomeScreenViewModel {
let vm = HomeScreenViewModel(services: services)
vm.status = status
vm.balance = balance
vm.fiatConversion = fiatConversion
return vm
fiatConversion: Decimal
) -> HomeScreenViewModel {
let viewModel = HomeScreenViewModel(services: services)
viewModel.status = status
viewModel.balance = balance
viewModel.fiatConversion = fiatConversion
return viewModel
}
}

View File

@ -7,16 +7,15 @@
import SwiftUI
protocol ProfileScreenRouter: AnyObject {
}
protocol ProfileScreenRouter: AnyObject {}
struct ProfileScreen: View {
@State var router: ProfileScreenRouter?
@ObservedObject var viewModel: ProfileScreenViewModel
@State var router: ProfileScreenRouter?
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
Text("Hello, World!")
}
}

View File

@ -5,9 +5,7 @@
// Created by Francisco Gindre on 8/12/21.
//
import Foundation
import Combine
import Foundation
class ProfileScreenViewModel: BaseViewModel<Services>, ObservableObject {
}
class ProfileScreenViewModel: BaseViewModel<Services>, ObservableObject {}

View File

@ -7,16 +7,15 @@
import SwiftUI
protocol RequestZcashScreenRouter: AnyObject {
}
protocol RequestZcashScreenRouter: AnyObject {}
struct RequestZcashScreen: View {
@State var router: RequestZcashScreenRouter?
@ObservedObject var viewModel: RequestZcashScreenViewModel
@State var router: RequestZcashScreenRouter?
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
Text("Hello, World!")
}
}

View File

@ -5,9 +5,7 @@
// Created by Francisco Gindre on 8/12/21.
//
import Foundation
import Combine
import Foundation
class RequestZcashScreenViewModel: BaseViewModel<Services>, ObservableObject {
}
class RequestZcashScreenViewModel: BaseViewModel<Services>, ObservableObject {}

View File

@ -7,14 +7,13 @@
import SwiftUI
protocol RestoreWalletScreenRouter: AnyObject {
}
protocol RestoreWalletScreenRouter: AnyObject {}
struct RestoreWalletScreen: View {
@State var router: RestoreWalletScreenRouter?
@ObservedObject var viewModel: RestoreWalletScreenViewModel
@State var router: RestoreWalletScreenRouter?
var body: some View {
VStack {
Text("Enter Seed Phrase")

View File

@ -5,11 +5,10 @@
// Created by Francisco Gindre on 8/9/21.
//
import Foundation
import Combine
import Foundation
class RestoreWalletScreenViewModel: BaseViewModel<Services>, ObservableObject {
@Published var seedText: String = ""
func restore() {}

View File

@ -7,16 +7,15 @@
import SwiftUI
protocol ScanQrScreenRouter: AnyObject {
}
protocol ScanQrScreenRouter: AnyObject {}
struct ScanQrScreen: View {
@State var router: ScanQrScreenRouter?
@ObservedObject var viewModel: ScanQrScreenViewModel
@State var router: ScanQrScreenRouter?
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
Text("Hello, World!")
}
}

View File

@ -5,9 +5,7 @@
// Created by Francisco Gindre on 8/12/21.
//
import Foundation
import Combine
import Foundation
class ScanQrScreenViewModel: BaseViewModel<Services>, ObservableObject {
}
class ScanQrScreenViewModel: BaseViewModel<Services>, ObservableObject {}

View File

@ -7,16 +7,15 @@
import SwiftUI
protocol SendScreenRouter: AnyObject {
}
protocol SendScreenRouter: AnyObject {}
struct SendScreen: View {
@State var router: SendScreenRouter?
@ObservedObject var viewModel: SendScreenViewModel
@State var router: SendScreenRouter?
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
Text("Hello, World!")
}
}

View File

@ -5,9 +5,7 @@
// Created by Francisco Gindre on 8/12/21.
//
import Foundation
import Combine
import Foundation
class SendScreenViewModel: BaseViewModel<Services>, ObservableObject {
}
class SendScreenViewModel: BaseViewModel<Services>, ObservableObject {}

View File

@ -7,20 +7,19 @@
import SwiftUI
protocol WelcomeScreenRouter: AnyObject {
}
protocol WelcomeScreenRouter: AnyObject {}
struct WelcomeScreen: View {
@State var router: WelcomeScreenRouter?
@ObservedObject var viewModel: WelcomeScreenViewModel
@State var router: WelcomeScreenRouter?
var body: some View {
VStack {
Spacer()
Text("Welcome and Onboarding")
Spacer()
VStack(alignment: .center, spacing: 16) {

View File

@ -5,11 +5,10 @@
// Created by Francisco Gindre on 8/9/21.
//
import Foundation
import Combine
import Foundation
class WelcomeScreenViewModel: BaseViewModel<Services>, ObservableObject {
func createNew() {}
func restoreWallet() {}
}

View File

@ -9,8 +9,8 @@ import SwiftUI
@main
struct SecantApp: App {
@StateObject var appRouter = AppRouter(services: MockServices())
var body: some Scene {
WindowGroup {
appRouter.rootView()

View File

@ -7,11 +7,12 @@
import Foundation
// swiftlint:disable line_length
class MockServices: Services {
init(){}
var networkProvider: ZcashNetworkProvider {
MockNetworkProvider()
}
var seedHandler: MnemonicSeedPhraseHandling {
MockMnemonicPhraseHandling()
}
@ -19,6 +20,8 @@ class MockServices: Services {
var keyStorage: KeyStoring {
MockKeyStoring()
}
init() {}
}
class MockNetworkProvider: ZcashNetworkProvider {
@ -28,13 +31,13 @@ class MockNetworkProvider: ZcashNetworkProvider {
}
class MockMnemonicPhraseHandling: MnemonicSeedPhraseHandling {
class TestSeed {
/**
test account: "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread"
Test account: "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread"
*/
let seedString = Data(base64Encoded: "9VDVOZZZOWWHpZtq1Ebridp3Qeux5C+HwiRR0g7Oi7HgnMs8Gfln83+/Q1NnvClcaSwM4ADFL1uZHxypEWlWXg==")!
let seedString = Data(
base64Encoded: "9VDVOZZZOWWHpZtq1Ebridp3Qeux5C+HwiRR0g7Oi7HgnMs8Gfln83+/Q1NnvClcaSwM4ADFL1uZHxypEWlWXg=="
)!// swiftlint:disable:this force_unwrapping
func seed() -> [UInt8] {
[UInt8](seedString)
@ -46,7 +49,8 @@ class MockMnemonicPhraseHandling: MnemonicSeedPhraseHandling {
}
func randomMnemonicWords() throws -> [String] {
"still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread".components(separatedBy: " ")
"still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread"
.components(separatedBy: " ")
}
func toSeed(mnemonic: String) throws -> [UInt8] {
@ -54,43 +58,47 @@ class MockMnemonicPhraseHandling: MnemonicSeedPhraseHandling {
}
func asWords(mnemonic: String) throws -> [String] {
"still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread".components(separatedBy: " ")
"still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread"
.components(separatedBy: " ")
}
func isValid(mnemonic: String) throws {}
}
class MockKeyStoring: KeyStoring {
var birthday: BlockHeight?
var phrase: String?
func importBirthday(_ height: BlockHeight) throws {
guard birthday == nil else {
throw KeyStoringError.alreadyImported
}
birthday = height
}
func exportBirthday() throws -> BlockHeight {
guard let b = birthday else {
guard let birthday = birthday else {
throw KeyStoringError.uninitializedWallet
}
return b
return birthday
}
func importPhrase(bip39 phrase: String) throws {
guard self.phrase == nil else {
throw KeyStoringError.alreadyImported
}
self.phrase = phrase
}
func exportPhrase() throws -> String {
guard let p = self.phrase else {
guard let phrase = self.phrase else {
throw KeyStoringError.uninitializedWallet
}
return p
return phrase
}
var keysPresent: Bool {
@ -109,6 +117,4 @@ class MockKeyStoring: KeyStoring {
nukePhrase()
nukeBirthday()
}
}

View File

@ -6,7 +6,9 @@
//
import Foundation
public typealias BlockHeight = Int
public protocol ZcashNetwork {
var networkType: NetworkType { get }
var constants: NetworkConstants.Type { get }
@ -18,10 +20,8 @@ public enum NetworkType {
var networkId: UInt32 {
switch self {
case .mainnet:
return 1
case .testnet:
return 0
case .mainnet: return 1
case .testnet: return 0
}
}
}
@ -29,23 +29,18 @@ public enum NetworkType {
extension NetworkType {
static func forChainName(_ chainame: String) -> NetworkType? {
switch chainame {
case "test":
return .testnet
case "main":
return .mainnet
default:
return nil
case "test": return .testnet
case "main": return .mainnet
default: return nil
}
}
}
public class ZcashNetworkBuilder {
public enum ZcashNetworkBuilder {
public static func network(for networkType: NetworkType) -> ZcashNetwork {
switch networkType {
case .mainnet:
return ZcashMainnet()
case .testnet:
return ZcashTestnet()
case .mainnet: return ZcashMainnet()
case .testnet: return ZcashTestnet()
}
}
}
@ -61,182 +56,182 @@ class ZcashMainnet: ZcashNetwork {
}
/**
Constants of ZcashLightClientKit. this constants don't
Constants of ZcashLightClientKit.
*/
public class ZcashSDK {
public enum ZcashSDK {
/**
The number of zatoshi that equal 1 ZEC.
*/
public static var ZATOSHI_PER_ZEC: BlockHeight = 100_000_000
public static var zatoshiPerZEC: BlockHeight = 100_000_000
/**
The theoretical maximum number of blocks in a reorg, due to other bottlenecks in the protocol design.
*/
public static var MAX_REORG_SIZE = 100
public static var maxReorgSize = 100
/**
The amount of blocks ahead of the current height where new transactions are set to expire. This value is controlled
by the rust backend but it is helpful to know what it is set to and should be kept in sync.
The amount of blocks ahead of the current height where new transactions are set to expire. This value is controlled by the rust backend but it is helpful to know what it is set to and should be kept in sync.
*/
public static var EXPIRY_OFFSET = 20
public static var expiryOffset = 20
//
// Defaults
//
/**
Default size of batches of blocks to request from the compact block service.
*/
public static var DEFAULT_BATCH_SIZE = 100
public static var defaultBatchSize = 100
/**
Default amount of time, in in seconds, to poll for new blocks. Typically, this should be about half the average
block time.
Default amount of time, in in seconds, to poll for new blocks. Typically, this should be about half the average block time.
*/
public static var DEFAULT_POLL_INTERVAL: TimeInterval = 20
public static var defaultPollInterval: TimeInterval = 20
/**
Default attempts at retrying.
*/
public static var DEFAULT_RETRIES: Int = 5
public static var defaultRetrie: Int = 5
/**
The default maximum amount of time to wait during retry backoff intervals. Failed loops will never wait longer than
this before retyring.
The default maximum amount of time to wait during retry backoff intervals. Failed loops will never wait longer than this before retyring.
*/
public static var DEFAULT_MAX_BACKOFF_INTERVAL: TimeInterval = 600
public static var defaultMaxBackoffInterval: TimeInterval = 600
/**
Default number of blocks to rewind when a chain reorg is detected. This should be large enough to recover from the
reorg but smaller than the theoretical max reorg size of 100.
Default number of blocks to rewind when a chain reorg is detected. This should be large enough to recover from the reorg but smaller than the theoretical max reorg size of 100.
*/
public static var DEFAULT_REWIND_DISTANCE: Int = 10
public static var defaultRewindDistance: Int = 10
/**
The number of blocks to allow before considering our data to be stale. This usually helps with what to do when
returning from the background and is exposed via the Synchronizer's isStale function.
The number of blocks to allow before considering our data to be stale. This usually helps with what to do when returning from the background and is exposed via the Synchronizer's isStale function.
*/
public static var DEFAULT_STALE_TOLERANCE: Int = 10
public static var defaultStaleTolerance: Int = 10
/**
Default Name for LibRustZcash data.db
*/
public static var DEFAULT_DATA_DB_NAME = "data.db"
public static var defaultDataDbName = "data.db"
/**
Default Name for Compact Block caches db
*/
public static var DEFAULT_CACHES_DB_NAME = "caches.db"
public static var defaultCachesDbName = "caches.db"
/**
Default name for pending transactions db
*/
public static var DEFAULT_PENDING_DB_NAME = "pending.db"
public static var defaultPendingDbName = "pending.db"
/**
File name for the sapling spend params
*/
public static var SPEND_PARAM_FILE_NAME = "sapling-spend.params"
public static var spendParamFileName = "sapling-spend.params"
/**
File name for the sapling output params
*/
public static var OUTPUT_PARAM_FILE_NAME = "sapling-output.params"
public static var outputParamFileName = "sapling-output.params"
/**
The Url that is used by default in zcashd.
We'll want to make this externally configurable, rather than baking it into the SDK but
this will do for now, since we're using a cloudfront URL that already redirects.
The Url that is used by default in zcashd. We'll want to make this externally configurable, rather than baking it into the SDK but this will do for now, since we're using a cloudfront URL that already redirects.
*/
public static var CLOUD_PARAM_DIR_URL = "https://z.cash/downloads/"
public static var cloudParamDirURL = "https://z.cash/downloads/"
}
public protocol NetworkConstants {
/**
The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks
prior to this height, at all.
The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any block prior to this height, at all.
*/
static var SAPLING_ACTIVATION_HEIGHT: BlockHeight { get }
static var saplingActivationHeight: BlockHeight { get }
/**
Default Name for LibRustZcash data.db
*/
static var DEFAULT_DATA_DB_NAME: String { get }
static var defaultDataDbName: String { get }
/**
Default Name for Compact Block caches db
*/
static var DEFAULT_CACHES_DB_NAME: String { get }
static var defaultCachesDbName: String { get }
/**
Default name for pending transactions db
*/
static var DEFAULT_PENDING_DB_NAME: String { get }
static var DEFAULT_DB_NAME_PREFIX: String { get }
static var defaultPendingDbName: String { get }
static var defaultDbNamePrefix: String { get }
/**
fixed height where the SDK considers that the ZIP-321 was deployed. This is a workaround
for librustzcash not figuring out the tx fee from the tx itself.
Fixed height where the SDK considers that the ZIP-321 was deployed. This is a workaround for librustzcash not figuring out the tx fee from the tx itself.
*/
static var FEE_CHANGE_HEIGHT: BlockHeight { get }
static var feeChangeHeight: BlockHeight { get }
static func defaultFee(for height: BlockHeight) -> Int64
}
public extension NetworkConstants {
static func defaultFee(for height: BlockHeight = BlockHeight.max) -> Int64 {
guard height >= FEE_CHANGE_HEIGHT else { return 10_000 }
guard height >= feeChangeHeight else { return 10_000 }
return 1_000
}
}
public class ZcashSDKMainnetConstants: NetworkConstants {
private init() {}
/**
The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks
prior to this height, at all.
The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks prior to this height, at all.
*/
public static var SAPLING_ACTIVATION_HEIGHT: BlockHeight = 419_200
public static var saplingActivationHeight: BlockHeight = 419_200
/**
Default Name for LibRustZcash data.db
*/
public static var DEFAULT_DATA_DB_NAME = "data.db"
public static var defaultDataDbName = "data.db"
/**
Default Name for Compact Block caches db
*/
public static var DEFAULT_CACHES_DB_NAME = "caches.db"
public static var defaultCachesDbName = "caches.db"
/**
Default name for pending transactions db
*/
public static var DEFAULT_PENDING_DB_NAME = "pending.db"
public static var defaultPendingDbName = "pending.db"
public static var DEFAULT_DB_NAME_PREFIX = "ZcashSdk_mainnet_"
public static var defaultDbNamePrefix = "ZcashSdk_mainnet_"
public static var FEE_CHANGE_HEIGHT: BlockHeight = 1_077_550
public static var feeChangeHeight: BlockHeight = 1_077_550
private init() {}
}
public class ZcashSDKTestnetConstants: NetworkConstants {
private init() {}
/**
The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks
prior to this height, at all.
The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks prior to this height, at all.
*/
public static var SAPLING_ACTIVATION_HEIGHT: BlockHeight = 280_000
public static var saplingActivationHeight: BlockHeight = 280_000
/**
Default Name for LibRustZcash data.db
*/
public static var DEFAULT_DATA_DB_NAME = "data.db"
public static var defaultDataDbName = "data.db"
/**
Default Name for Compact Block caches db
*/
public static var DEFAULT_CACHES_DB_NAME = "caches.db"
public static var defaultCachesDbName = "caches.db"
/**
Default name for pending transactions db
*/
public static var DEFAULT_PENDING_DB_NAME = "pending.db"
public static var defaultPendingDbName = "pending.db"
public static var DEFAULT_DB_NAME_PREFIX = "ZcashSdk_testnet_"
public static var defaultDbNamePrefix = "ZcashSdk_testnet_"
/**
Estimated height where wallets are supposed to change the fee
*/
public static var FEE_CHANGE_HEIGHT: BlockHeight = 1_028_500
public static var feeChangeHeight: BlockHeight = 1_028_500
private init() {}
}

View File

@ -24,16 +24,18 @@ struct PlainButton: ButtonStyle {
}
}
// MARK: - Previews
struct PlainButton_Previews: PreviewProvider {
static var previews: some View {
VStack {
Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/, label: {
/*@START_MENU_TOKEN@*/Text("Button")/*@END_MENU_TOKEN@*/
Button(action: {}, label: {
Text("Button")
})
.buttonStyle(PlainButton())
Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/, label: {
/*@START_MENU_TOKEN@*/Text("Button")/*@END_MENU_TOKEN@*/
Button(action: {}, label: {
Text("Button")
})
.buttonStyle(PlainButton(style: .bold))
}
@ -41,22 +43,20 @@ struct PlainButton_Previews: PreviewProvider {
}
}
// MARK: - Theme
extension PlainButton.Theme {
var background: some View {
switch self {
case .bold:
return Color.black
default:
return Color.white
case .bold: return Color.black
default: return Color.white
}
}
var foregroundColor: Color {
switch self {
case .bold:
return Color.white
default:
return Color.black
case .bold: return Color.white
default: return Color.black
}
}
}

View File

@ -8,7 +8,6 @@
import Foundation
import SwiftUI
extension Font {
static func zboto(_ size: CGFloat) -> Font {
Font.custom("Zboto", size: size)

View File

@ -8,13 +8,14 @@
import XCTest
@testable import secant_testnet
class secantTests: XCTestCase {
override func setUpWithError() throws {
class SecantTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDownWithError() throws {
override func tearDown() {
super.tearDown()
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
@ -29,5 +30,4 @@ class secantTests: XCTestCase {
// Put the code you want to measure the time of here.
}
}
}

View File

@ -7,18 +7,21 @@
import XCTest
class secantUITests: XCTestCase {
override func setUpWithError() throws {
class SecantUITests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false
// In UI tests its important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
// In UI tests its important to set the initial state - such as interface
// orientation - required for your tests before they run.
// The setUp method is a good place to do this.
}
override func tearDownWithError() throws {
override func tearDown() {
super.tearDown()
// Put teardown code here. This method is called after the invocation of each test method in the class.
}

View File

@ -4,28 +4,16 @@ import Foundation
import SwiftUI
class ___FILEBASENAMEASIDENTIFIER___: Router {
// MARK: - Published vars
// Put published vars here
// MARK: - Private vars
// MARK: - Internal vars
var services: Services
// MARK: - Initialization
init(services: Services) {
self.services = services
}
// MARK: - Methods
func rootView() -> some View {
// Add your content here
NavigationView {
Text("Hello Word")
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
}
}
}

View File

@ -3,13 +3,14 @@
import SwiftUI
protocol ___FILEBASENAMEASIDENTIFIER___Router: AnyObject {
}
struct ___FILEBASENAMEASIDENTIFIER___: View {
@State var router: ___FILEBASENAMEASIDENTIFIER___Router?
@ObservedObject var viewModel: ___FILEBASENAME___ViewModel
@State var router: ___FILEBASENAMEASIDENTIFIER___Router?
var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
}

View File

@ -5,4 +5,5 @@ import Combine
class ___FILEBASENAMEASIDENTIFIER___: BaseViewModel<Services>, ObservableObject {
}