Feature/mixpanel (#143)

* refactor podfile

* Basic Mixpanel integration

* Add basic trackers to screens and for the actions that already have buttons

* Add tracking to missing events and inject mix panel token with soucery

* Add readme entry about Mix Panel

* add token to mix panel

* add gitignore

* removed Constants from project. removed references from no logging target
This commit is contained in:
Francisco Gindre 2020-07-14 12:51:22 -03:00 committed by GitHub
parent 003d1a3a44
commit aa8da8cc1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 873 additions and 162 deletions

1
.gitignore vendored
View File

@ -79,3 +79,4 @@ lib
*.a
*.generated.swift
env-vars.sh
wallet/wallet/Generated/Constants.generated.swift

View File

@ -41,6 +41,31 @@ for more information about the security and privacy limitations of the wallet.
7. build and run on simulator.
# To Log or not to Log
This is our internal dogfooding app, and we implemented some level of event logging to be able to study user interactions and improve the User Experience with Zcash on mobile devices.
## No Logs please
*You can build and run the app **without it** by using the `wallet-no-logging`*
The "no logging" target does not even build or include the Mixpanel sdk on your build or any code related with it. You can make sure of this by looking at the code yourself. If you think there's a better way achieve this, please open an Issue with your proposal. :-)
## I want to use Mixpanel
If you wish to use mixpanel in your own build, make sure to include the following line in your env-vars.sh file
`export MIXPANEL_TOKEN="YOUR_TOKEN"`
And build the `wallet` target. Sourcery will pick it up and generate the Constants.generated.swift file that the Mixpanel SDK will use to send the events to your board
## I use some other kind of tracker...
that I would like to include in my project. The app does not care about the details of the event logger as long as it implements this protocol
````Swift
protocol EventLogging {
func track(_ event: LogEvent, properties: KeyValuePairs<String, String>)
}
````
You can implement your own tracker proxy
## Troubleshooting
### No network environment....

View File

@ -1,20 +1,30 @@
platform :ios, '13.0'
use_frameworks!
def base_pods
pod 'ZcashLightClientKit'
pod 'KeychainSwift', '~> 19.0.0'
pod 'MnemonicSwift'
pod 'TinyQRScanner'
pod 'lottie-ios'
end
inhibit_all_warnings!
target 'wallet-no-logging' do
base_pods
end
target 'wallet' do
pod 'ZcashLightClientKit'
pod 'KeychainSwift', '~> 19.0.0'
pod 'MnemonicSwift'
pod 'TinyQRScanner'
pod 'lottie-ios'
target 'walletTests' do
inherit! :search_paths
end
base_pods
pod 'Mixpanel-swift'
target 'walletTests' do
inherit! :search_paths
end
target 'walletUITests' do
inherit! :search_paths
end
target 'walletUITests' do
inherit! :search_paths
end
end
post_install do |installer|

View File

@ -1,77 +1,81 @@
PODS:
- CGRPCZlib (1.0.0-alpha.12)
- CNIOAtomics (2.15.0)
- CNIOBoringSSL (2.7.1)
- CNIOBoringSSLShims (2.7.1):
- CNIOBoringSSL (= 2.7.1)
- CNIODarwin (2.15.0)
- CNIOHTTPParser (2.15.0)
- CNIOLinux (2.15.0)
- CNIOSHA1 (2.15.0)
- gRPC-Swift (1.0.0-alpha.12):
- CGRPCZlib (= 1.0.0-alpha.12)
- Logging (= 1.2.0)
- SwiftNIO (= 2.15.0)
- SwiftNIOHTTP2 (= 1.11.0)
- SwiftNIOSSL (= 2.7.1)
- SwiftNIOTransportServices (= 1.3.0)
- SwiftProtobuf (= 1.8.0)
- CGRPCZlib (1.0.0-alpha.14)
- CNIOAtomics (2.18.0)
- CNIOBoringSSL (2.7.4)
- CNIOBoringSSLShims (2.7.4):
- CNIOBoringSSL (= 2.7.4)
- CNIODarwin (2.18.0)
- CNIOHTTPParser (2.18.0)
- CNIOLinux (2.18.0)
- CNIOSHA1 (2.18.0)
- gRPC-Swift (1.0.0-alpha.14):
- CGRPCZlib (= 1.0.0-alpha.14)
- Logging (< 2, >= 1.2.0)
- SwiftNIO (< 3, >= 2.18.0)
- SwiftNIOHTTP2 (< 2, >= 1.12.2)
- SwiftNIOSSL (< 3, >= 2.7.4)
- SwiftNIOTransportServices (< 2, >= 1.6.0)
- SwiftProtobuf (< 2, >= 1.9.0)
- KeychainSwift (19.0.0)
- Logging (1.2.0)
- lottie-ios (3.1.6)
- Mixpanel-swift (2.7.4):
- Mixpanel-swift/Complete (= 2.7.4)
- Mixpanel-swift/Complete (2.7.4)
- MnemonicSwift (1.0.0)
- SQLite.swift (0.12.2):
- SQLite.swift/standard (= 0.12.2)
- SQLite.swift/standard (0.12.2)
- SwiftNIO (2.15.0):
- CNIOAtomics (= 2.15.0)
- CNIODarwin (= 2.15.0)
- CNIOLinux (= 2.15.0)
- CNIOSHA1 (= 2.15.0)
- SwiftNIOConcurrencyHelpers (= 2.15.0)
- SwiftNIOConcurrencyHelpers (2.15.0):
- CNIOAtomics (= 2.15.0)
- SwiftNIOFoundationCompat (2.15.0):
- SwiftNIO (= 2.15.0)
- SwiftNIOHPACK (1.11.0):
- SwiftNIO (= 2.15.0)
- SwiftNIOConcurrencyHelpers (= 2.15.0)
- SwiftNIOHTTP1 (= 2.15.0)
- SwiftNIOHTTP1 (2.15.0):
- CNIOHTTPParser (= 2.15.0)
- SwiftNIO (= 2.15.0)
- SwiftNIOConcurrencyHelpers (= 2.15.0)
- SwiftNIOHTTP2 (1.11.0):
- SwiftNIO (= 2.15.0)
- SwiftNIOConcurrencyHelpers (= 2.15.0)
- SwiftNIOHPACK (= 1.11.0)
- SwiftNIOHTTP1 (= 2.15.0)
- SwiftNIOTLS (= 2.15.0)
- SwiftNIOSSL (2.7.1):
- CNIOBoringSSL (= 2.7.1)
- CNIOBoringSSLShims (= 2.7.1)
- SwiftNIO (= 2.15.0)
- SwiftNIOConcurrencyHelpers (= 2.15.0)
- SwiftNIOTLS (= 2.15.0)
- SwiftNIOTLS (2.15.0):
- SwiftNIO (= 2.15.0)
- SwiftNIOTransportServices (1.3.0):
- SwiftNIO (2.18.0):
- CNIOAtomics (= 2.18.0)
- CNIODarwin (= 2.18.0)
- CNIOLinux (= 2.18.0)
- CNIOSHA1 (= 2.18.0)
- SwiftNIOConcurrencyHelpers (= 2.18.0)
- SwiftNIOConcurrencyHelpers (2.18.0):
- CNIOAtomics (= 2.18.0)
- SwiftNIOFoundationCompat (2.18.0):
- SwiftNIO (= 2.18.0)
- SwiftNIOHPACK (1.12.2):
- SwiftNIO (= 2.18.0)
- SwiftNIOConcurrencyHelpers (= 2.18.0)
- SwiftNIOHTTP1 (= 2.18.0)
- SwiftNIOHTTP1 (2.18.0):
- CNIOHTTPParser (= 2.18.0)
- SwiftNIO (= 2.18.0)
- SwiftNIOConcurrencyHelpers (= 2.18.0)
- SwiftNIOHTTP2 (1.12.2):
- SwiftNIO (= 2.18.0)
- SwiftNIOConcurrencyHelpers (= 2.18.0)
- SwiftNIOHPACK (= 1.12.2)
- SwiftNIOHTTP1 (= 2.18.0)
- SwiftNIOTLS (= 2.18.0)
- SwiftNIOSSL (2.7.4):
- CNIOBoringSSL (= 2.7.4)
- CNIOBoringSSLShims (= 2.7.4)
- SwiftNIO (= 2.18.0)
- SwiftNIOConcurrencyHelpers (= 2.18.0)
- SwiftNIOTLS (= 2.18.0)
- SwiftNIOTLS (2.18.0):
- SwiftNIO (= 2.18.0)
- SwiftNIOTransportServices (1.6.0):
- SwiftNIO (~> 2.0)
- SwiftNIOConcurrencyHelpers (~> 2.0)
- SwiftNIOFoundationCompat (~> 2.0)
- SwiftNIOTLS (~> 2.0)
- SwiftProtobuf (1.8.0)
- SwiftProtobuf (1.9.0)
- TinyQRScanner (1.0.0)
- ZcashLightClientKit (0.4.0):
- ZcashLightClientKit (0.5.1):
- gRPC-Swift (~> 1.0.0-alpha.11)
- SQLite.swift (~> 0.12.2)
DEPENDENCIES:
- KeychainSwift (~> 19.0.0)
- lottie-ios
- Mixpanel-swift
- MnemonicSwift
- TinyQRScanner
- ZcashLightClientKit (from `../../ZcashLightClientKit`)
- ZcashLightClientKit
SPEC REPOS:
trunk:
@ -87,6 +91,7 @@ SPEC REPOS:
- KeychainSwift
- Logging
- lottie-ios
- Mixpanel-swift
- MnemonicSwift
- SQLite.swift
- SwiftNIO
@ -100,39 +105,37 @@ SPEC REPOS:
- SwiftNIOTransportServices
- SwiftProtobuf
- TinyQRScanner
EXTERNAL SOURCES:
ZcashLightClientKit:
:path: "../../ZcashLightClientKit"
- ZcashLightClientKit
SPEC CHECKSUMS:
CGRPCZlib: a53e43fb0567e720e753dd172911b96baa3910d7
CNIOAtomics: ba49b1c86f281e1ecfd84c9205fbc27a81826847
CNIOBoringSSL: e4766830ab6d7c7fcd3618331f05fcb11638314d
CNIOBoringSSLShims: c3f3c6f05b7ce9b576521328a5b1b566d8f4665b
CNIODarwin: 2e341dd283fa3972706568b12925366145a8e2cd
CNIOHTTPParser: 25e1d1bc84c0612cbbbd6baedc4be05d77a17e01
CNIOLinux: 61598a8e49510207acb74c87f8fc11f762f76b5a
CNIOSHA1: 7b1dcceef9682aef4c6578b9fc67f87a03f0c48e
gRPC-Swift: d4432e8659f1d075b9d07963c18e6791c8b159c3
CGRPCZlib: 06247b0687f3a3edbfbfb204d53721c3ba262a34
CNIOAtomics: b6053043649c8b9afbf2560d9d64899d5d7ce368
CNIOBoringSSL: 21bbd36e5a68c9d2ea1aea7bfea10eea60d25a82
CNIOBoringSSLShims: e9e57b1fd0e060a25f2f3b0b944cc84dd272368f
CNIODarwin: 2e814fe13ee1b16a6d7603affbd95b3fbf1e65b1
CNIOHTTPParser: 215fe669981deb6b7e4533b0b42a01e5c165d8ac
CNIOLinux: 45e91eaba50bb850a48135aabbd7671625f15188
CNIOSHA1: f8f5b0c8cbd067c195d1b44ab237927765bd4914
gRPC-Swift: fb8ff0d8cdd5a020c170ba827f50c393ae31e307
KeychainSwift: a06190cf933ad46b1e0abc3d77d29c06331715c7
Logging: 7838d379d234d7e5ae1265fa02804a9084caf04c
lottie-ios: 85ce835dd8c53e02509f20729fc7d6a4e6645a0a
Mixpanel-swift: 0905361a691604eba85ae5b257329ca4833cd5f6
MnemonicSwift: d743ec3dcc1cdce706a1876dba0b6250ad1ef90d
SQLite.swift: d2b4642190917051ce6bd1d49aab565fe794eea3
SwiftNIO: c9889dcd8aed2655af9163b42fc11ebd4ce94252
SwiftNIOConcurrencyHelpers: 2357037a16e9c51880c01b896a5ac3cd41066044
SwiftNIOFoundationCompat: f09ee499a8a9c636ec9007f73c5a1cedc23dcad3
SwiftNIOHPACK: 906596511ff9d1e095b7a72a0011351591bcae03
SwiftNIOHTTP1: b05f4061ba18482006a264a5aa087bbcd35d153c
SwiftNIOHTTP2: 3a52499594c6ec073af2a2801cf3c5d3d1c8700f
SwiftNIOSSL: 7c82b8393a6b69a3ef9b12fe74240e92c2bd7add
SwiftNIOTLS: 51580e51240d1a4d51efb2d317e92cf243181042
SwiftNIOTransportServices: 26d40c589fc8fe667af51b06ef0aa49fbc9ae7f2
SwiftProtobuf: 2cbd9409689b7df170d82a92a33443c8e3e14a70
SwiftNIO: c17d311e9006fc10c1d17fbc6a7a9cb21aa46368
SwiftNIOConcurrencyHelpers: 69762a04ed76d7254012e1f17787ee162d2cf764
SwiftNIOFoundationCompat: 9af7b2e265c4d55eb8599a515d63784c2691dc39
SwiftNIOHPACK: 871e4e893ecc1aeaf74435b73c13240f50d6853c
SwiftNIOHTTP1: 67eafb3f27c3aee867dc4c0ec947e2ab71f1e2ce
SwiftNIOHTTP2: c7ce23b714868de63dae083478b40da20d933e08
SwiftNIOSSL: 0f28ad98a39b4c625196c2c8f154a4fded66bd96
SwiftNIOTLS: 78c6d6798ea29f7eb0a4e1214a00bc8f07e7390c
SwiftNIOTransportServices: 775bcda101a0d921feb69d79b5884acfce0fc0f2
SwiftProtobuf: ecbec1be9036d15655f6b3443a1c4ea693c97932
TinyQRScanner: 9930c4514dc6f123f3b9d95fcedbc1f8c241c5eb
ZcashLightClientKit: 3a123d6e947680a66b466d884ca8cf5b23502a73
ZcashLightClientKit: d23fd0513acf929deb5b2a7ef803b03ceda7afb9
PODFILE CHECKSUM: f81e83a1c48570c6b0dfff52ef7abfcaefa65a0c
PODFILE CHECKSUM: f13c6a43956c68cde06ad33ee9a1b06f7cd32f3f
COCOAPODS: 1.9.3

View File

@ -0,0 +1,13 @@
#!/bin/sh
if ! hash sourcery; then
echo "Sourcery not found on your PATH"
exit 1
fi
SOURCERY_ARGS="--args mixpanel=${MIXPANEL_TOKEN}"
echo "sourcery --prune --verbose --templates wallet/Stencil --sources ${SRCROOT} --output ${SRCROOT}/Generated $SOURCERY_ARGS"
sourcery --prune --verbose --templates ./Stencil --sources ${SRCROOT} --output ${SRCROOT}/wallet/Generated $SOURCERY_ARGS

View File

@ -0,0 +1,5 @@
import Foundation
public struct Constants {
static let mixpanelProject: String = "{{ argument.mixpanel }}"
}

View File

@ -1 +1,2 @@
export LIGHTWALLETD_ADDRESS="localhost%3a9067"
export MIXPANEL_TOKEN="deadbeef"

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>ECC Wallet</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>0.1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSCameraUsageDescription</key>
<string>Scan zAddress Qr Codes</string>
<key>UIAppFonts</key>
<array>
<string>Zboto.otf</string>
</array>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
0BF91D06169AC881D248F0AA /* Pods_wallet_no_logging.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05755ABE887C0E4977E8BA96 /* Pods_wallet_no_logging.framework */; };
0D040F5923C3ECDD00ACD07E /* KeyPadViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D040F5823C3ECDD00ACD07E /* KeyPadViewModelTests.swift */; };
0D0AAE0F2410237A009CD8F9 /* LottieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D0AAE0E24102379009CD8F9 /* LottieView.swift */; };
0D0AAE1124102380009CD8F9 /* SyncingButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D0AAE1024102380009CD8F9 /* SyncingButton.swift */; };
@ -70,7 +71,80 @@
0DBAA0912419A77500B08BC7 /* NukeWarning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DBAA0902419A77500B08BC7 /* NukeWarning.swift */; };
0DC167AF23BE35B300332890 /* SendZecView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DC167AE23BE35B300332890 /* SendZecView.swift */; };
0DC167B123BE37B300332890 /* BalanceUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DC167B023BE37B300332890 /* BalanceUtils.swift */; };
0DCDFF9724B6722B000F6999 /* EnterRecipient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D27C4A623C4C3AE0044B48E /* EnterRecipient.swift */; };
0DCDFF9824B6722B000F6999 /* SyncingButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D0AAE1024102380009CD8F9 /* SyncingButton.swift */; };
0DCDFF9924B6722B000F6999 /* SeedBackup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D100EE123BAB1B80089DB22 /* SeedBackup.swift */; };
0DCDFF9A24B6722B000F6999 /* Fonts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE51DAD23BEB0E500709636 /* Fonts.swift */; };
0DCDFF9B24B6722B000F6999 /* CombineSynchronizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DCF43BD23DF7229007E9B49 /* CombineSynchronizer.swift */; };
0DCDFF9C24B6722B000F6999 /* SendZecView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DC167AE23BE35B300332890 /* SendZecView.swift */; };
0DCDFF9D24B6722B000F6999 /* ProfileScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D8C3E2C23D8B37900B94438 /* ProfileScreen.swift */; };
0DCDFF9E24B6722B000F6999 /* ZECCWalletEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D9E89C123DA620E00AFD118 /* ZECCWalletEnvironment.swift */; };
0DCDFF9F24B6722B000F6999 /* ZcashButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D100EDA23BA91F70089DB22 /* ZcashButton.swift */; };
0DCDFFA024B6722B000F6999 /* ZcashTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D27C4A823C4C4640044B48E /* ZcashTextField.swift */; };
0DCDFFA124B6722B000F6999 /* String+localized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D73958F24A40E6C00936DE3 /* String+localized.swift */; };
0DCDFFA224B6722B000F6999 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D100EDD23BA92A50089DB22 /* Colors.swift */; };
0DCDFFA324B6722B000F6999 /* KeyPad.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE51DAF23BEBE5100709636 /* KeyPad.swift */; };
0DCDFFA424B6722B000F6999 /* ZcashTapToSendButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D92AEBD2422D6F30028AD53 /* ZcashTapToSendButton.swift */; };
0DCDFFA524B6722B000F6999 /* WalletDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D9C203C23D77D4B006F1510 /* WalletDetails.swift */; };
0DCDFFA624B6722B000F6999 /* BalanceUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DC167B023BE37B300332890 /* BalanceUtils.swift */; };
0DCDFFA724B6722B000F6999 /* FundsAtRisk.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D0AAE14241048B4009CD8F9 /* FundsAtRisk.swift */; };
0DCDFFA824B6722B000F6999 /* LazyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D1B6D7724241C20004C75DB /* LazyView.swift */; };
0DCDFFA924B6722B000F6999 /* ShareScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D11C23623BFB666001CF6F7 /* ShareScreen.swift */; };
0DCDFFAA24B6722B000F6999 /* HoldToSend.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D421AF723C65B8F00E5E55E /* HoldToSend.swift */; };
0DCDFFAB24B6722B000F6999 /* BalanceDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D92967823BEEFFC001518F3 /* BalanceDetail.swift */; };
0DCDFFAC24B6722B000F6999 /* Home.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D60F2EA23BE1B87006F5FAD /* Home.swift */; };
0DCDFFAD24B6722B000F6999 /* ActionableMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE51DB123BED85C00709636 /* ActionableMessage.swift */; };
0DCDFFAE24B6722B000F6999 /* DetailCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D421AFE23C67DCE00E5E55E /* DetailCard.swift */; };
0DCDFFAF24B6722B000F6999 /* SeedManagement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D9E89BC23DA3BD600AFD118 /* SeedManagement.swift */; };
0DCDFFB024B6722B000F6999 /* SendFlowEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D4364C623CCF4CC008B7DAC /* SendFlowEnvironment.swift */; };
0DCDFFB124B6722B000F6999 /* URL+Zcash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DDF876623DB5400002BF158 /* URL+Zcash.swift */; };
0DCDFFB224B6722B000F6999 /* MnemonicSeedPhraseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DDAF3A824098D1000EA9427 /* MnemonicSeedPhraseProvider.swift */; };
0DCDFFB324B6722B000F6999 /* zECC+SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DF210FE23F4733000C31B08 /* zECC+SwiftUI.swift */; };
0DCDFFB424B6722B000F6999 /* ZcashLogo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D100ED423BA75EE0089DB22 /* ZcashLogo.swift */; };
0DCDFFB524B6722B000F6999 /* ZcashCheckCircle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D4C100623C542D800CD2854 /* ZcashCheckCircle.swift */; };
0DCDFFB624B6722B000F6999 /* CameraAccessHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D6BE0B223EB1348006A71C5 /* CameraAccessHelper.swift */; };
0DCDFFB724B6722B000F6999 /* ZcashHoldToSendButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DFC0CF023C7787F0009DD7E /* ZcashHoldToSendButton.swift */; };
0DCDFFB824B6722B000F6999 /* WalletDetailsHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D9C203E23D7827F006F1510 /* WalletDetailsHeader.swift */; };
0DCDFFB924B6722B000F6999 /* LottieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D0AAE0E24102379009CD8F9 /* LottieView.swift */; };
0DCDFFBA24B6722B000F6999 /* ZcashCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DFC0CF223C8EA1C0009DD7E /* ZcashCloseButton.swift */; };
0DCDFFBB24B6722B000F6999 /* NukeWarning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DBAA0902419A77500B08BC7 /* NukeWarning.swift */; };
0DCDFFBC24B6722B000F6999 /* TextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D41AF9E23FCAA4700EE4FC0 /* TextView.swift */; };
0DCDFFBD24B6722B000F6999 /* ZcashSeedPhraseGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D1C2F26240DAFE9001AA427 /* ZcashSeedPhraseGrid.swift */; };
0DCDFFBE24B6722B000F6999 /* Sending.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D421AF923C66B7500E5E55E /* Sending.swift */; };
0DCDFFBF24B6722B000F6999 /* String+Zcash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D8C3E2E23D8BA6500B94438 /* String+Zcash.swift */; };
0DCDFFC024B6722B000F6999 /* UIKit+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D4C100023C52A9B00CD2854 /* UIKit+Extensions.swift */; };
0DCDFFC124B6722B000F6999 /* ZcashButtonBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D87E2CB240ECEC500648C09 /* ZcashButtonBackground.swift */; };
0DCDFFC224B6722B000F6999 /* ReceiveFunds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D11C22C23BF807E001CF6F7 /* ReceiveFunds.swift */; };
0DCDFFC324B6722B000F6999 /* RestoreWallet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D9E89BA23DA3A9900AFD118 /* RestoreWallet.swift */; };
0DCDFFC424B6722B000F6999 /* NavigationConfigurator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D11C23423BFB33B001CF6F7 /* NavigationConfigurator.swift */; };
0DCDFFC524B6722B000F6999 /* ZcashSymbol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D100ED623BA78990089DB22 /* ZcashSymbol.swift */; };
0DCDFFC624B6722B000F6999 /* SimpleLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D75ECD82416D13800244CE4 /* SimpleLogger.swift */; };
0DCDFFC724B6722B000F6999 /* BackupWallet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D100EDF23BAAB170089DB22 /* BackupWallet.swift */; };
0DCDFFC824B6722B000F6999 /* AddMemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D4C100223C52CE200CD2854 /* AddMemo.swift */; };
0DCDFFC924B6722B000F6999 /* QRCodeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D2BCF5E23E8A59D0076C5B0 /* QRCodeGenerator.swift */; };
0DCDFFCA24B6722B000F6999 /* ScanAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D11C23023BF966C001CF6F7 /* ScanAddress.swift */; };
0DCDFFCB24B6722B000F6999 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D12510223B557E40014EE3A /* AppDelegate.swift */; };
0DCDFFCC24B6722B000F6999 /* Ring.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DEC5DF823BD60CF002EFD0D /* Ring.swift */; };
0DCDFFCD24B6722B000F6999 /* QRCodeScannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D72330723E9CFE40004B6D1 /* QRCodeScannerView.swift */; };
0DCDFFCE24B6722B000F6999 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D12510423B557E40014EE3A /* SceneDelegate.swift */; };
0DCDFFCF24B6722B000F6999 /* QRCodeContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D11C22E23BF8181001CF6F7 /* QRCodeContainer.swift */; };
0DCDFFD024B6722B000F6999 /* TransactionDetail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D3AAB44244652700010EA3C /* TransactionDetail.swift */; };
0DCDFFD124B6722B000F6999 /* ZcashSeedWordPill.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D1C2F24240D8655001AA427 /* ZcashSeedWordPill.swift */; };
0DCDFFD224B6722B000F6999 /* CreateNewWallet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D100ED823BA8DE80089DB22 /* CreateNewWallet.swift */; };
0DCDFFD324B6722B000F6999 /* ZcashMemoTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D4C100423C52D3400CD2854 /* ZcashMemoTextView.swift */; };
0DCDFFD424B6722B000F6999 /* HostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D11C23223BFA810001CF6F7 /* HostingController.swift */; };
0DCDFFD524B6722B000F6999 /* MnemonicSeedPhraseHandling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DDAF3A624097D6E00EA9427 /* MnemonicSeedPhraseHandling.swift */; };
0DCDFFD624B6722B000F6999 /* ZcashBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D60F2EC23BE1BC9006F5FAD /* ZcashBackground.swift */; };
0DCDFFDA24B6722B000F6999 /* sendbutton.json in Resources */ = {isa = PBXBuildFile; fileRef = 0D0AAE1224102747009CD8F9 /* sendbutton.json */; };
0DCDFFDB24B6722B000F6999 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0D12510D23B557E60014EE3A /* LaunchScreen.storyboard */; };
0DCDFFDC24B6722B000F6999 /* sapling-spend.params in Resources */ = {isa = PBXBuildFile; fileRef = 0D5BB97F23DB6FE3002BC9CF /* sapling-spend.params */; };
0DCDFFDD24B6722B000F6999 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0D12510B23B557E60014EE3A /* Preview Assets.xcassets */; };
0DCDFFDE24B6722B000F6999 /* Zboto.otf in Resources */ = {isa = PBXBuildFile; fileRef = 0DE51DAB23BEB03C00709636 /* Zboto.otf */; };
0DCDFFDF24B6722B000F6999 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8D3F362724A40FCF0087687A /* Localizable.strings */; };
0DCDFFE024B6722B000F6999 /* sapling-output.params in Resources */ = {isa = PBXBuildFile; fileRef = 0D5BB97E23DB6FE3002BC9CF /* sapling-output.params */; };
0DCDFFE124B6722B000F6999 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0D12510823B557E60014EE3A /* Assets.xcassets */; };
0DCF43BE23DF7229007E9B49 /* CombineSynchronizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DCF43BD23DF7229007E9B49 /* CombineSynchronizer.swift */; };
0DD8B9B824B6898F0031FF42 /* EventLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DD8B9B724B6898F0031FF42 /* EventLogger.swift */; };
0DDAF3A724097D6E00EA9427 /* MnemonicSeedPhraseHandling.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DDAF3A624097D6E00EA9427 /* MnemonicSeedPhraseHandling.swift */; };
0DDAF3A924098D1000EA9427 /* MnemonicSeedPhraseProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DDAF3A824098D1000EA9427 /* MnemonicSeedPhraseProvider.swift */; };
0DDF876723DB5400002BF158 /* URL+Zcash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DDF876623DB5400002BF158 /* URL+Zcash.swift */; };
@ -78,14 +152,16 @@
0DE51DAE23BEB0E500709636 /* Fonts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE51DAD23BEB0E500709636 /* Fonts.swift */; };
0DE51DB023BEBE5100709636 /* KeyPad.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE51DAF23BEBE5100709636 /* KeyPad.swift */; };
0DE51DB223BED85C00709636 /* ActionableMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE51DB123BED85C00709636 /* ActionableMessage.swift */; };
0DE8668524BCE55400F3B883 /* Constants.generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DE8668424BCE55400F3B883 /* Constants.generated.swift */; };
0DE8668724BD195C00F3B883 /* EventLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DD8B9B724B6898F0031FF42 /* EventLogger.swift */; };
0DEC5DF923BD60CF002EFD0D /* Ring.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DEC5DF823BD60CF002EFD0D /* Ring.swift */; };
0DF210FF23F4733000C31B08 /* zECC+SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DF210FE23F4733000C31B08 /* zECC+SwiftUI.swift */; };
0DFC0CF123C7787F0009DD7E /* ZcashHoldToSendButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DFC0CF023C7787F0009DD7E /* ZcashHoldToSendButton.swift */; };
0DFC0CF323C8EA1C0009DD7E /* ZcashCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DFC0CF223C8EA1C0009DD7E /* ZcashCloseButton.swift */; };
3B413006FADE74F203B484C0 /* Pods_wallet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AACB15604DA487A1AF476359 /* Pods_wallet.framework */; };
821BF1B75860B8BFA922A614 /* Pods_walletUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 41D5B43B5A8155F0D38949A4 /* Pods_walletUITests.framework */; };
8D3F362524A40FCF0087687A /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8D3F362724A40FCF0087687A /* Localizable.strings */; };
8D73959024A40E6C00936DE3 /* String+localized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D73958F24A40E6C00936DE3 /* String+localized.swift */; };
9140DCD4E6D8E81E86004A00 /* Pods_wallet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C97F088A3985ED71EDC7F7F6 /* Pods_wallet.framework */; };
DBAC4685D59CA6F781C82E3E /* Pods_walletTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E5D63A72F6B7D564AEC15C6D /* Pods_walletTests.framework */; };
/* End PBXBuildFile section */
@ -107,6 +183,7 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
05755ABE887C0E4977E8BA96 /* Pods_wallet_no_logging.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_wallet_no_logging.framework; sourceTree = BUILT_PRODUCTS_DIR; };
0D040F5823C3ECDD00ACD07E /* KeyPadViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyPadViewModelTests.swift; sourceTree = "<group>"; };
0D0AAE0E24102379009CD8F9 /* LottieView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LottieView.swift; sourceTree = "<group>"; };
0D0AAE1024102380009CD8F9 /* SyncingButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SyncingButton.swift; sourceTree = "<group>"; };
@ -125,7 +202,7 @@
0D11C23223BFA810001CF6F7 /* HostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingController.swift; sourceTree = "<group>"; };
0D11C23423BFB33B001CF6F7 /* NavigationConfigurator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationConfigurator.swift; sourceTree = "<group>"; };
0D11C23623BFB666001CF6F7 /* ShareScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareScreen.swift; sourceTree = "<group>"; };
0D1250FF23B557E40014EE3A /* zECC Wallet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; name = "zECC Wallet.app"; path = "ECC Wallet.app"; sourceTree = BUILT_PRODUCTS_DIR; };
0D1250FF23B557E40014EE3A /* ECC Wallet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ECC Wallet.app"; sourceTree = BUILT_PRODUCTS_DIR; };
0D12510223B557E40014EE3A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
0D12510423B557E40014EE3A /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
0D12510823B557E60014EE3A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@ -176,7 +253,10 @@
0DBAA0902419A77500B08BC7 /* NukeWarning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NukeWarning.swift; sourceTree = "<group>"; };
0DC167AE23BE35B300332890 /* SendZecView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendZecView.swift; sourceTree = "<group>"; };
0DC167B023BE37B300332890 /* BalanceUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalanceUtils.swift; sourceTree = "<group>"; };
0DCDFFE624B6722B000F6999 /* wallet-no-logs.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "wallet-no-logs.app"; sourceTree = BUILT_PRODUCTS_DIR; };
0DCDFFE724B6722B000F6999 /* wallet-no-logs-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "wallet-no-logs-Info.plist"; path = "/Users/pacu/Repos/ECC/zcash-ios-wallet/wallet/wallet-no-logs-Info.plist"; sourceTree = "<absolute>"; };
0DCF43BD23DF7229007E9B49 /* CombineSynchronizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombineSynchronizer.swift; sourceTree = "<group>"; };
0DD8B9B724B6898F0031FF42 /* EventLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventLogger.swift; sourceTree = "<group>"; };
0DDAF3A624097D6E00EA9427 /* MnemonicSeedPhraseHandling.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MnemonicSeedPhraseHandling.swift; sourceTree = "<group>"; };
0DDAF3A824098D1000EA9427 /* MnemonicSeedPhraseProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MnemonicSeedPhraseProvider.swift; sourceTree = "<group>"; };
0DDF876623DB5400002BF158 /* URL+Zcash.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URL+Zcash.swift"; sourceTree = "<group>"; };
@ -184,10 +264,12 @@
0DE51DAD23BEB0E500709636 /* Fonts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Fonts.swift; sourceTree = "<group>"; };
0DE51DAF23BEBE5100709636 /* KeyPad.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyPad.swift; sourceTree = "<group>"; };
0DE51DB123BED85C00709636 /* ActionableMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionableMessage.swift; sourceTree = "<group>"; };
0DE8668424BCE55400F3B883 /* Constants.generated.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.generated.swift; sourceTree = "<group>"; };
0DEC5DF823BD60CF002EFD0D /* Ring.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ring.swift; sourceTree = "<group>"; };
0DF210FE23F4733000C31B08 /* zECC+SwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "zECC+SwiftUI.swift"; sourceTree = "<group>"; };
0DFC0CF023C7787F0009DD7E /* ZcashHoldToSendButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZcashHoldToSendButton.swift; sourceTree = "<group>"; };
0DFC0CF223C8EA1C0009DD7E /* ZcashCloseButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZcashCloseButton.swift; sourceTree = "<group>"; };
18C69464FD3770D35A524106 /* Pods-wallet-no-logging.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-wallet-no-logging.debug.xcconfig"; path = "Target Support Files/Pods-wallet-no-logging/Pods-wallet-no-logging.debug.xcconfig"; sourceTree = "<group>"; };
29D1459C46D96D9D3DF2A55C /* Pods-walletUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-walletUITests.debug.xcconfig"; path = "Target Support Files/Pods-walletUITests/Pods-walletUITests.debug.xcconfig"; sourceTree = "<group>"; };
2E7FFE45D0C33A74C7344A5E /* Pods-walletTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-walletTests.release.xcconfig"; path = "Target Support Files/Pods-walletTests/Pods-walletTests.release.xcconfig"; sourceTree = "<group>"; };
41D5B43B5A8155F0D38949A4 /* Pods_walletUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_walletUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@ -198,7 +280,8 @@
8D73958F24A40E6C00936DE3 /* String+localized.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+localized.swift"; sourceTree = "<group>"; };
8F020BD1AB76698D896ED4C4 /* Pods-walletUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-walletUITests.release.xcconfig"; path = "Target Support Files/Pods-walletUITests/Pods-walletUITests.release.xcconfig"; sourceTree = "<group>"; };
A85B99A0F1C01CABADF33492 /* Pods-walletTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-walletTests.debug.xcconfig"; path = "Target Support Files/Pods-walletTests/Pods-walletTests.debug.xcconfig"; sourceTree = "<group>"; };
C97F088A3985ED71EDC7F7F6 /* Pods_wallet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_wallet.framework; sourceTree = BUILT_PRODUCTS_DIR; };
AA8163D8FC63C0383BA13D13 /* Pods-wallet-no-logging.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-wallet-no-logging.release.xcconfig"; path = "Target Support Files/Pods-wallet-no-logging/Pods-wallet-no-logging.release.xcconfig"; sourceTree = "<group>"; };
AACB15604DA487A1AF476359 /* Pods_wallet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_wallet.framework; sourceTree = BUILT_PRODUCTS_DIR; };
E5D63A72F6B7D564AEC15C6D /* Pods_walletTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_walletTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
@ -207,7 +290,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9140DCD4E6D8E81E86004A00 /* Pods_wallet.framework in Frameworks */,
3B413006FADE74F203B484C0 /* Pods_wallet.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -227,6 +310,14 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
0DCDFFD724B6722B000F6999 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0BF91D06169AC881D248F0AA /* Pods_wallet_no_logging.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@ -269,6 +360,7 @@
0DDAF3A824098D1000EA9427 /* MnemonicSeedPhraseProvider.swift */,
0D75ECD82416D13800244CE4 /* SimpleLogger.swift */,
8D73958F24A40E6C00936DE3 /* String+localized.swift */,
0DD8B9B724B6898F0031FF42 /* EventLogger.swift */,
);
path = Utils;
sourceTree = "<group>";
@ -282,6 +374,7 @@
0D12510023B557E40014EE3A /* Products */,
EA66A8F666D2E80F5C4EC4F5 /* Pods */,
0F65A46FFC0823E2EE87ED5E /* Frameworks */,
0DCDFFE724B6722B000F6999 /* wallet-no-logs-Info.plist */,
);
sourceTree = "<group>";
};
@ -291,6 +384,7 @@
0D1250FF23B557E40014EE3A /* ECC Wallet.app */,
0D12511523B557E60014EE3A /* walletTests.xctest */,
0D12512023B557E60014EE3A /* walletUITests.xctest */,
0DCDFFE624B6722B000F6999 /* wallet-no-logs.app */,
);
name = Products;
sourceTree = "<group>";
@ -298,6 +392,7 @@
0D12510123B557E40014EE3A /* wallet */ = {
isa = PBXGroup;
children = (
0DE8668324BCE52C00F3B883 /* Generated */,
0D4364C523CCF49E008B7DAC /* Environment */,
0DEC5DFA23BD63AA002EFD0D /* Components */,
0DEC5DF723BD60B0002EFD0D /* Shapes */,
@ -378,6 +473,14 @@
path = "Wallet Details";
sourceTree = "<group>";
};
0DE8668324BCE52C00F3B883 /* Generated */ = {
isa = PBXGroup;
children = (
0DE8668424BCE55400F3B883 /* Constants.generated.swift */,
);
path = Generated;
sourceTree = "<group>";
};
0DEC5DF723BD60B0002EFD0D /* Shapes */ = {
isa = PBXGroup;
children = (
@ -420,9 +523,10 @@
0F65A46FFC0823E2EE87ED5E /* Frameworks */ = {
isa = PBXGroup;
children = (
C97F088A3985ED71EDC7F7F6 /* Pods_wallet.framework */,
E5D63A72F6B7D564AEC15C6D /* Pods_walletTests.framework */,
41D5B43B5A8155F0D38949A4 /* Pods_walletUITests.framework */,
05755ABE887C0E4977E8BA96 /* Pods_wallet_no_logging.framework */,
AACB15604DA487A1AF476359 /* Pods_wallet.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -436,6 +540,8 @@
2E7FFE45D0C33A74C7344A5E /* Pods-walletTests.release.xcconfig */,
29D1459C46D96D9D3DF2A55C /* Pods-walletUITests.debug.xcconfig */,
8F020BD1AB76698D896ED4C4 /* Pods-walletUITests.release.xcconfig */,
18C69464FD3770D35A524106 /* Pods-wallet-no-logging.debug.xcconfig */,
AA8163D8FC63C0383BA13D13 /* Pods-wallet-no-logging.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
@ -501,6 +607,25 @@
productReference = 0D12512023B557E60014EE3A /* walletUITests.xctest */;
productType = "com.apple.product-type.bundle.ui-testing";
};
0DCDFF9324B6722B000F6999 /* wallet-no-logging */ = {
isa = PBXNativeTarget;
buildConfigurationList = 0DCDFFE324B6722B000F6999 /* Build configuration list for PBXNativeTarget "wallet-no-logging" */;
buildPhases = (
0DCDFF9424B6722B000F6999 /* [CP] Check Pods Manifest.lock */,
0DCDFF9624B6722B000F6999 /* Sources */,
0DCDFFD724B6722B000F6999 /* Frameworks */,
0DCDFFD924B6722B000F6999 /* Resources */,
0DCDFFE224B6722B000F6999 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = "wallet-no-logging";
productName = wallet;
productReference = 0DCDFFE624B6722B000F6999 /* wallet-no-logs.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@ -539,6 +664,7 @@
projectRoot = "";
targets = (
0D1250FE23B557E40014EE3A /* wallet */,
0DCDFF9324B6722B000F6999 /* wallet-no-logging */,
0D12511423B557E60014EE3A /* walletTests */,
0D12511F23B557E60014EE3A /* walletUITests */,
);
@ -575,6 +701,21 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
0DCDFFD924B6722B000F6999 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0DCDFFDA24B6722B000F6999 /* sendbutton.json in Resources */,
0DCDFFDB24B6722B000F6999 /* LaunchScreen.storyboard in Resources */,
0DCDFFDC24B6722B000F6999 /* sapling-spend.params in Resources */,
0DCDFFDD24B6722B000F6999 /* Preview Assets.xcassets in Resources */,
0DCDFFDE24B6722B000F6999 /* Zboto.otf in Resources */,
0DCDFFDF24B6722B000F6999 /* Localizable.strings in Resources */,
0DCDFFE024B6722B000F6999 /* sapling-output.params in Resources */,
0DCDFFE124B6722B000F6999 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
@ -615,7 +756,46 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "source ${SRCROOT}/env-vars.sh\n";
shellScript = "source ${SRCROOT}/env-vars.sh\nsh ${PROJECT_DIR}/Scripts/generate_constants.sh\n";
};
0DCDFF9424B6722B000F6999 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-wallet-no-logging-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
0DCDFFE224B6722B000F6999 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-wallet-no-logging/Pods-wallet-no-logging-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-wallet-no-logging/Pods-wallet-no-logging-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-wallet-no-logging/Pods-wallet-no-logging-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
8C3EAD89BAA309B5FC123070 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
@ -687,6 +867,7 @@
files = (
0D27C4A723C4C3AE0044B48E /* EnterRecipient.swift in Sources */,
0D0AAE1124102380009CD8F9 /* SyncingButton.swift in Sources */,
0DD8B9B824B6898F0031FF42 /* EventLogger.swift in Sources */,
0D100EE223BAB1B80089DB22 /* SeedBackup.swift in Sources */,
0DE51DAE23BEB0E500709636 /* Fonts.swift in Sources */,
0DCF43BE23DF7229007E9B49 /* CombineSynchronizer.swift in Sources */,
@ -707,6 +888,7 @@
0D421AF823C65B8F00E5E55E /* HoldToSend.swift in Sources */,
0D92967923BEEFFC001518F3 /* BalanceDetail.swift in Sources */,
0D60F2EB23BE1B87006F5FAD /* Home.swift in Sources */,
0DE8668524BCE55400F3B883 /* Constants.generated.swift in Sources */,
0DE51DB223BED85C00709636 /* ActionableMessage.swift in Sources */,
0D421AFF23C67DCF00E5E55E /* DetailCard.swift in Sources */,
0D9E89BD23DA3BD600AFD118 /* SeedManagement.swift in Sources */,
@ -771,6 +953,78 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
0DCDFF9624B6722B000F6999 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0DCDFF9724B6722B000F6999 /* EnterRecipient.swift in Sources */,
0DCDFF9824B6722B000F6999 /* SyncingButton.swift in Sources */,
0DE8668724BD195C00F3B883 /* EventLogger.swift in Sources */,
0DCDFF9924B6722B000F6999 /* SeedBackup.swift in Sources */,
0DCDFF9A24B6722B000F6999 /* Fonts.swift in Sources */,
0DCDFF9B24B6722B000F6999 /* CombineSynchronizer.swift in Sources */,
0DCDFF9C24B6722B000F6999 /* SendZecView.swift in Sources */,
0DCDFF9D24B6722B000F6999 /* ProfileScreen.swift in Sources */,
0DCDFF9E24B6722B000F6999 /* ZECCWalletEnvironment.swift in Sources */,
0DCDFF9F24B6722B000F6999 /* ZcashButton.swift in Sources */,
0DCDFFA024B6722B000F6999 /* ZcashTextField.swift in Sources */,
0DCDFFA124B6722B000F6999 /* String+localized.swift in Sources */,
0DCDFFA224B6722B000F6999 /* Colors.swift in Sources */,
0DCDFFA324B6722B000F6999 /* KeyPad.swift in Sources */,
0DCDFFA424B6722B000F6999 /* ZcashTapToSendButton.swift in Sources */,
0DCDFFA524B6722B000F6999 /* WalletDetails.swift in Sources */,
0DCDFFA624B6722B000F6999 /* BalanceUtils.swift in Sources */,
0DCDFFA724B6722B000F6999 /* FundsAtRisk.swift in Sources */,
0DCDFFA824B6722B000F6999 /* LazyView.swift in Sources */,
0DCDFFA924B6722B000F6999 /* ShareScreen.swift in Sources */,
0DCDFFAA24B6722B000F6999 /* HoldToSend.swift in Sources */,
0DCDFFAB24B6722B000F6999 /* BalanceDetail.swift in Sources */,
0DCDFFAC24B6722B000F6999 /* Home.swift in Sources */,
0DCDFFAD24B6722B000F6999 /* ActionableMessage.swift in Sources */,
0DCDFFAE24B6722B000F6999 /* DetailCard.swift in Sources */,
0DCDFFAF24B6722B000F6999 /* SeedManagement.swift in Sources */,
0DCDFFB024B6722B000F6999 /* SendFlowEnvironment.swift in Sources */,
0DCDFFB124B6722B000F6999 /* URL+Zcash.swift in Sources */,
0DCDFFB224B6722B000F6999 /* MnemonicSeedPhraseProvider.swift in Sources */,
0DCDFFB324B6722B000F6999 /* zECC+SwiftUI.swift in Sources */,
0DCDFFB424B6722B000F6999 /* ZcashLogo.swift in Sources */,
0DCDFFB524B6722B000F6999 /* ZcashCheckCircle.swift in Sources */,
0DCDFFB624B6722B000F6999 /* CameraAccessHelper.swift in Sources */,
0DCDFFB724B6722B000F6999 /* ZcashHoldToSendButton.swift in Sources */,
0DCDFFB824B6722B000F6999 /* WalletDetailsHeader.swift in Sources */,
0DCDFFB924B6722B000F6999 /* LottieView.swift in Sources */,
0DCDFFBA24B6722B000F6999 /* ZcashCloseButton.swift in Sources */,
0DCDFFBB24B6722B000F6999 /* NukeWarning.swift in Sources */,
0DCDFFBC24B6722B000F6999 /* TextView.swift in Sources */,
0DCDFFBD24B6722B000F6999 /* ZcashSeedPhraseGrid.swift in Sources */,
0DCDFFBE24B6722B000F6999 /* Sending.swift in Sources */,
0DCDFFBF24B6722B000F6999 /* String+Zcash.swift in Sources */,
0DCDFFC024B6722B000F6999 /* UIKit+Extensions.swift in Sources */,
0DCDFFC124B6722B000F6999 /* ZcashButtonBackground.swift in Sources */,
0DCDFFC224B6722B000F6999 /* ReceiveFunds.swift in Sources */,
0DCDFFC324B6722B000F6999 /* RestoreWallet.swift in Sources */,
0DCDFFC424B6722B000F6999 /* NavigationConfigurator.swift in Sources */,
0DCDFFC524B6722B000F6999 /* ZcashSymbol.swift in Sources */,
0DCDFFC624B6722B000F6999 /* SimpleLogger.swift in Sources */,
0DCDFFC724B6722B000F6999 /* BackupWallet.swift in Sources */,
0DCDFFC824B6722B000F6999 /* AddMemo.swift in Sources */,
0DCDFFC924B6722B000F6999 /* QRCodeGenerator.swift in Sources */,
0DCDFFCA24B6722B000F6999 /* ScanAddress.swift in Sources */,
0DCDFFCB24B6722B000F6999 /* AppDelegate.swift in Sources */,
0DCDFFCC24B6722B000F6999 /* Ring.swift in Sources */,
0DCDFFCD24B6722B000F6999 /* QRCodeScannerView.swift in Sources */,
0DCDFFCE24B6722B000F6999 /* SceneDelegate.swift in Sources */,
0DCDFFCF24B6722B000F6999 /* QRCodeContainer.swift in Sources */,
0DCDFFD024B6722B000F6999 /* TransactionDetail.swift in Sources */,
0DCDFFD124B6722B000F6999 /* ZcashSeedWordPill.swift in Sources */,
0DCDFFD224B6722B000F6999 /* CreateNewWallet.swift in Sources */,
0DCDFFD324B6722B000F6999 /* ZcashMemoTextView.swift in Sources */,
0DCDFFD424B6722B000F6999 /* HostingController.swift in Sources */,
0DCDFFD524B6722B000F6999 /* MnemonicSeedPhraseHandling.swift in Sources */,
0DCDFFD624B6722B000F6999 /* ZcashBackground.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
@ -941,6 +1195,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
OTHER_SWIFT_FLAGS = "$(inherited) -D ENABLE_LOGGING";
PRODUCT_BUNDLE_IDENTIFIER = co.electriccoin.wallet;
PRODUCT_NAME = "ECC Wallet";
SWIFT_VERSION = 5.0;
@ -965,6 +1220,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
OTHER_SWIFT_FLAGS = "$(inherited) -D ENABLE_LOGGING";
PRODUCT_BUNDLE_IDENTIFIER = co.electriccoin.wallet;
PRODUCT_NAME = "ECC Wallet";
SWIFT_VERSION = 5.0;
@ -1060,6 +1316,55 @@
};
name = Release;
};
0DCDFFE424B6722B000F6999 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 18C69464FD3770D35A524106 /* Pods-wallet-no-logging.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 40;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_ASSET_PATHS = "\"wallet/Preview Content\"";
DEVELOPMENT_TEAM = 6J82A38BF9;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = "wallet-no-logs-Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = co.electriccoin.wallet;
PRODUCT_NAME = "wallet-no-logs";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
name = Debug;
};
0DCDFFE524B6722B000F6999 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = AA8163D8FC63C0383BA13D13 /* Pods-wallet-no-logging.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 40;
DEVELOPMENT_ASSET_PATHS = "\"wallet/Preview Content\"";
DEVELOPMENT_TEAM = 6J82A38BF9;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = "wallet-no-logs-Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = co.electriccoin.wallet;
PRODUCT_NAME = "wallet-no-logs";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@ -1099,6 +1404,15 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
0DCDFFE324B6722B000F6999 /* Build configuration list for PBXNativeTarget "wallet-no-logging" */ = {
isa = XCConfigurationList;
buildConfigurations = (
0DCDFFE424B6722B000F6999 /* Debug */,
0DCDFFE524B6722B000F6999 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 0D1250F723B557E40014EE3A /* Project object */;

View File

@ -14,6 +14,12 @@ var logger = SimpleLogger(logLevel: .debug, type: SimpleLogger.LoggerType.printe
var logger = SimpleLogger(logLevel: .debug)
#endif
#if ENABLE_LOGGING
let tracker = MixPanelLogger(token: Constants.mixpanelProject)
#else
let tracker = NullLogger()
#endif
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

View File

@ -0,0 +1,163 @@
//
// EventLogger.swift
// wallet
//
// Created by Francisco Gindre on 7/8/20.
// Copyright © 2020 Francisco Gindre. All rights reserved.
//
import Foundation
import Combine
protocol EventLogging {
func track(_ event: LogEvent, properties: KeyValuePairs<String, String>)
}
enum Screen: String {
case backup
case home
case history = "wallet.detail"
case landing
case profile
case feedback
case receive
case restore
case scan
case sendAddress = "send.address"
case sendConfirm = "send.confirm"
case sendFinal = "send.final"
case sendMemo = "send.memo"
}
enum Action: String {
case backupDone = "backup.done"
case backupVerify = "backup.verify"
case walletPrompt = "landing.devwallet.prompt"
case walletImport = "landing.devwallet.import"
case walletCancel = "landing.devwallet.cancel"
case ladingRestoreWallet = "landing.restore"
case landingCreateNew = "landing.new"
case landingBackupWallet = "landing.backup"
case landingBackupSkipped1 = "landing.backup.skip.1"
case landingBackupSkipped2 = "landing.backup.skip.2"
case landingBackupSkipped3 = "landing.backup.skip.3"
case showProfile = "home.profile"
case receive = "home.scan"
case receiveBack = "receive.back"
case receiveScan = "receive.scan"
case scanBack = "scan.back"
case scanReceive = "scan.receive"
case scanTorch = "scan.torch"
case homeSend = "home.send"
case sendAddressNext = "send.address.next"
case sendAddressDoneAddress = "send.address.done.address"
case sendAddressDoneAmount = "send.address.done.amount"
case sendAddressPaste = "send.address.paste"
case sendAddressBack = "send.address.back"
case sendAddressScan = "send.address.scan"
case sendConfirmBack = "send.confirm.back"
case sendConfirmNext = "send.confirm.next"
case sendMemoInclude = "send.memo.include"
case sendMemoExclude = "send.memo.exclude"
case sendMemoSkip = "send.memo.skip"
case sendMemoNext = "send.memo.next"
case sendFinalExit = "send.final.exit"
case sendFinalClose = "send.final.close"
case profileClose = "profile.close"
case profileNuke = "profile.nuke"
case profileBackup = "profile.backup"
case copyAddress = "copy.address"
}
enum LogEvent: Equatable {
case screen(screen: Screen)
case tap(action: Action)
case error(severity: ErrorSeverity)
}
enum ErrorSeverity: String {
case critical = "error.critical"
case noncritical = "error.noncritical"
case warning = "error.warning"
static let messageKey = "message"
static let underlyingError = "error"
}
class NullLogger: EventLogging {
func track(_ event: LogEvent, properties: KeyValuePairs<String, String>) {}
}
#if ENABLE_LOGGING
import Mixpanel
class MixPanelLogger: EventLogging {
struct TrackingEvent: Equatable {
let event: LogEvent
let properties: [String : String]?
var description: String {
"Event: \(event) - Properties: \(properties ?? [:])"
}
}
func track(_ event: LogEvent, properties: KeyValuePairs<String, String>) {
let eventProperties = Dictionary<String,String>(uniqueKeysWithValues: Array(properties))
logSubject.send(TrackingEvent(event: event, properties: eventProperties))
}
var logSubject: PassthroughSubject<TrackingEvent, Never>
private func logEvent(_ event: TrackingEvent) {
logger.event("MockPanel - \(event)")
}
private func trackEvent(_ tracking: TrackingEvent) {
guard !test else {
logEvent(tracking)
return
}
switch tracking.event {
case .screen(let screen):
Mixpanel.mainInstance().track(event: screen.rawValue, properties: tracking.properties)
case .tap(let action):
Mixpanel.mainInstance().track(event: action.rawValue, properties: tracking.properties)
case .error(let severity):
Mixpanel.mainInstance().track(event: severity.rawValue, properties: tracking.properties)
}
}
var cancellables = [AnyCancellable]()
var scheduler = DispatchQueue.global()
/// Attempts to log to console logger if true
var test: Bool
/**
inits the Mixpanel logger
Parameters:
- Parameter token: the Mixpanel token
- Parameter test: attempts to send the logs to the console instead if such logger is set up. No logs are sent to MixPanel
*/
init(token: String, test: Bool = false) {
self.test = test
Mixpanel.initialize(token: token)
logSubject = PassthroughSubject<TrackingEvent,Never>()
logSubject.receive(on: scheduler)
.removeDuplicates()
.debounce(for: 0.3, scheduler: scheduler)
.sink { (event) in
self.trackEvent(event)
}
.store(in: &cancellables)
}
}
#endif

View File

@ -78,13 +78,20 @@ struct BackupWallet: View {
}.navigationBarBackButtonHidden(true)
.onAppear() {
do {
/// TODO: change previous navigation link to button to capture action
tracker.track(.tap(action: .landingBackupWallet), properties: [:])
try self.appEnvironment.createNewWallet()
self.viewModel.bindSync()
} catch {
logger.error("could not create new wallet: \(error)")
let message = "could not create new wallet:"
logger.error("\(message) \(error)")
tracker.track(.error(severity: .critical),
properties: [
ErrorSeverity.messageKey : message,
ErrorSeverity.underlyingError : "\(error)"
])
}
}
}
}

View File

@ -15,8 +15,7 @@ struct CreateNewWallet: View {
let buttonPadding: CGFloat = 24
let buttonHeight: CGFloat = 50
var body: some View {
ZStack {
ZcashBackground()
@ -28,8 +27,10 @@ struct CreateNewWallet: View {
Spacer()
NavigationLink(destination:
BackupWallet().environmentObject(appEnvironment)
LazyView (
BackupWallet().environmentObject(self.appEnvironment)
.navigationBarHidden(true)
)
) {
Text("Create New".localized())
@ -53,8 +54,10 @@ struct CreateNewWallet: View {
}
#endif
NavigationLink(
destination: RestoreWallet()
.environmentObject(appEnvironment)
destination: LazyView (
RestoreWallet()
.environmentObject(self.appEnvironment)
)
) {
Text("Restore".localized())
@ -64,8 +67,12 @@ struct CreateNewWallet: View {
}
} .padding([.horizontal, .bottom], self.buttonPadding)
}
}
.padding([.horizontal, .bottom], self.buttonPadding)
}
.onAppear {
tracker.track(.screen(screen: .landing), properties: [ : ])
}
}
}

View File

@ -61,6 +61,10 @@ struct FundsAtRisk: View {
}.padding([.horizontal, .bottom], 24)
}
.onAppear {
/// TODO: change Navigation links to buttons
tracker.track(.tap(action: .landingBackupSkipped1), properties: [:])
}
.navigationBarTitle("", displayMode: .inline)
.navigationBarHidden(true)

View File

@ -41,18 +41,11 @@ final class HomeViewModel: ObservableObject {
}
}
init(amount: Double = 0, balance: Double = 0) {
// verifiedBalance = balance
sendZecAmount = amount
showProfile = false
showReceiveFunds = false
let environment = ZECCWalletEnvironment.shared
// environment.synchronizer.verifiedBalance.receive(on: DispatchQueue.main)
// .sink(receiveValue: {
// self.verifiedBalance = $0
// })
// .store(in: &cancellable)
environment.synchronizer.balance.receive(on: DispatchQueue.main)
.sink(receiveValue: {
self.balance = $0
@ -74,6 +67,9 @@ final class HomeViewModel: ObservableObject {
.map( ZECCWalletEnvironment.mapError )
.sink { [weak self] error in
guard let self = self else { return }
tracker.track(.error(severity: .noncritical), properties: [
ErrorSeverity.underlyingError : "\(error)"
])
self.show(error: error)
}
.store(in: &cancellable)
@ -86,17 +82,31 @@ final class HomeViewModel: ObservableObject {
.sink(receiveCompletion: { (completion) in
switch completion {
case .failure(let error):
logger.error("error scanning: \(error)")
let message = "error scanning:"
tracker.track(.error(severity: .warning), properties: [
ErrorSeverity.underlyingError : "\(error)",
ErrorSeverity.messageKey : message
])
logger.error("\(message) \(error)")
case .finished:
logger.debug("finished scanning")
}
}) { (notification) in
guard let address = notification.userInfo?["zAddress"] as? String else {
logger.error("empty notification after scanning qr code")
let message = "empty notification after scanning qr code"
logger.error(message)
tracker.track(.error(severity: .warning), properties: [
ErrorSeverity.messageKey : message
])
return
}
guard ZECCWalletEnvironment.shared.isValidAddress(address) else {
logger.error("scanned qr but address is invalid")
let message = "scanned qr but address is invalid"
logger.error(message)
tracker.track(.error(severity: .warning), properties: [
ErrorSeverity.messageKey : message
])
return
}
self.showReceiveFunds = false
@ -217,8 +227,8 @@ struct Home: View {
var enterAddressButton: some View {
Button(action: {
tracker.track(.tap(action: .homeSend), properties: [:])
self.startSendFlow()
}) {
Text("Send")
.foregroundColor(.black)
@ -335,9 +345,11 @@ struct Home: View {
.opacity(0.4)
} else {
NavigationLink(
destination: WalletDetails()
.environmentObject(WalletDetailsViewModel())
.navigationBarTitle(Text(""), displayMode: .inline)
destination: LazyView(
WalletDetails()
.environmentObject(WalletDetailsViewModel())
.navigationBarTitle(Text(""), displayMode: .inline)
)
) {
walletDetails
}.isDetailLink(false)
@ -353,6 +365,7 @@ struct Home: View {
.navigationBarItems(leading:
Button(action: {
self.viewModel.showReceiveFunds = true
tracker.track(.tap(action: .receive), properties: [:])
}) {
Image("QRCodeIcon")
.accessibility(label: Text("Receive Funds"))
@ -365,6 +378,7 @@ struct Home: View {
}
, trailing:
Button(action: {
tracker.track(.tap(action: .showProfile), properties: [:])
self.viewModel.showProfile = true
}) {
Image(systemName: "person.crop.circle")
@ -379,6 +393,9 @@ struct Home: View {
ProfileScreen(isShown: self.$viewModel.showProfile)
.environmentObject(self.appEnvironment)
}
.onAppear {
tracker.track(.screen(screen: .home), properties: [:])
}
}
}

View File

@ -23,12 +23,14 @@ struct ProfileScreen: View {
VStack(alignment: .center, spacing: 16) {
Image("zebra_profile")
Button(action: {
tracker.track(.tap(action: .copyAddress),
properties: [:])
self.isCopyAlertShown = true
}) {
Text("Shielded User\n".localized() + (appEnvironment.initializer.getAddress()?.shortZaddress ?? ""))
.multilineTextAlignment(.center)
.font(.system(size: 18))
.foregroundColor(.white)
.multilineTextAlignment(.center)
.font(.system(size: 18))
.foregroundColor(.white)
}
Spacer()
@ -37,44 +39,49 @@ struct ProfileScreen: View {
.foregroundColor(.black)
.zcashButtonBackground(shape: .roundedCorners(fillStyle: .solid(color: Color.zYellow)))
.frame(height: Self.buttonHeight)
NavigationLink(destination: SeedBackup(hideNavBar: false).environmentObject(appEnvironment)
) {
NavigationLink(destination: LazyView(
SeedBackup(hideNavBar: false)
.environmentObject(self.appEnvironment)
)
) {
Text("Backup Wallet".localized())
.foregroundColor(.white)
.zcashButtonBackground(shape: .roundedCorners(fillStyle: .outline(color: .white, lineWidth: 1)))
.frame(height: Self.buttonHeight)
.frame(height: Self.buttonHeight)
}
Text("See Application Log".localized())
.font(.system(size: 20))
.foregroundColor(Color.zLightGray)
.opacity(0.6)
.frame(height: Self.buttonHeight)
ActionableMessage(message: "\("ECC Wallet".localized()) v\(ZECCWalletEnvironment.appVersion ?? "Unknown")", actionText: "Build \(ZECCWalletEnvironment.appBuild ?? "Unknown")", action: {})
.disabled(true)
NavigationLink(destination: NukeWarning().environmentObject(appEnvironment), isActive: self.$nukePressed) {
NavigationLink(destination: LazyView (
NukeWarning().environmentObject(self.appEnvironment)
), isActive: self.$nukePressed) {
EmptyView()
}.isDetailLink(false)
Button(action: {
tracker.track(.tap(action: .profileNuke), properties: [:])
self.nukePressed = true
}) {
Text("NUKE WALLET".localized())
.foregroundColor(.red)
.zcashButtonBackground(shape: .roundedCorners(fillStyle: .outline(color: .red, lineWidth: 1)))
Text("NUKE WALLET".localized())
.foregroundColor(.red)
.zcashButtonBackground(shape: .roundedCorners(fillStyle: .outline(color: .red, lineWidth: 1)))
.frame(height: Self.buttonHeight)
}
Spacer()
}.padding(.horizontal, Self.horizontalPadding)
}
.padding(.horizontal, Self.horizontalPadding)
.alert(isPresented: self.$isCopyAlertShown) {
Alert(title: Text(""),
message: Text("Address Copied to clipboard!".localized()),
@ -82,12 +89,16 @@ struct ProfileScreen: View {
)
}
}
.onAppear {
tracker.track(.screen(screen: .profile), properties: [:])
}
.navigationBarTitle("", displayMode: .inline)
.navigationBarHidden(false)
.navigationBarItems(trailing: ZcashCloseButton(action: {
tracker.track(.tap(action: .profileClose), properties: [:])
self.isShown = false
}).frame(width: 30, height: 30))
}
}
}

View File

@ -81,6 +81,7 @@ struct ReceiveFunds: View {
EmptyView()
}
Button(action: {
tracker.track(.tap(action: .receiveScan), properties: [:])
self.isScanAddressShown = true
}) {
Text("Scan Recipient Address")
@ -104,9 +105,14 @@ struct ReceiveFunds: View {
}
})
}.navigationBarTitle(Text(""), displayMode: .inline)
}
.onAppear {
tracker.track(.screen(screen: .receive), properties: [:])
}
.navigationBarTitle(Text(""), displayMode: .inline)
.navigationBarHidden(false)
.navigationBarItems(trailing: ZcashCloseButton(action: {
tracker.track(.tap(action: .receiveBack), properties: [:])
self.isShown = false
}).frame(width: 30, height: 30))
}

View File

@ -100,7 +100,7 @@ struct RestoreWallet: View {
logger.error("\(error)")
return
}
tracker.track(.tap(action: .walletImport), properties: [:])
self.proceed = true
}) {
Text("Proceed")
@ -110,12 +110,15 @@ struct RestoreWallet: View {
.disabled(disableProceed)
.opacity(disableProceed ? 0.4 : 1.0)
.frame(height: 58)
}.padding([.horizontal,.bottom], 30)
}
.padding([.horizontal,.bottom], 30)
}.onTapGesture {
UIApplication.shared.endEditing()
}.navigationBarTitle("Restore from Seed Phrase", displayMode: .inline)
}
.onAppear {
tracker.track(.screen(screen: .restore), properties: [:])
}
.navigationBarTitle("Restore from Seed Phrase", displayMode: .inline)
.navigationBarHidden(false)
}
}

View File

@ -73,6 +73,8 @@ struct ScanAddress: View {
return AnyView(
Button(action: {
self.toggleTorch(on: !self.torchEnabled)
tracker.track(.tap(action: .scanTorch),
properties: ["value" : String(!self.torchEnabled)])
self.torchEnabled.toggle()
}) {
Image("bolt")
@ -172,7 +174,10 @@ struct ScanAddress: View {
if viewModel.showCloseButton {
return AnyView(
auth.navigationBarItems(leading: torchButton, trailing: ZcashCloseButton(action: { self.isScanAddressShown = false }).frame(width: 30, height: 30))
auth.navigationBarItems(leading: torchButton, trailing: ZcashCloseButton(action: {
tracker.track(.tap(action: .scanBack), properties: [:])
self.isScanAddressShown = false
}).frame(width: 30, height: 30))
)
}
return AnyView(
@ -192,6 +197,9 @@ struct ScanAddress: View {
.onDisappear() {
self.toggleTorch(on: false)
}
.onAppear() {
tracker.track(.screen(screen: .scan), properties: [:])
}
}
private var torchAvailable: Bool {

View File

@ -56,7 +56,12 @@ struct SeedBackup: View {
)
} catch {
logger.error("error retrieving seed: \(error)")
let message = "error retrieving seed"
logger.error("\(message): \(error)")
tracker.track(.error(severity: .critical), properties: [
ErrorSeverity.messageKey : message,
ErrorSeverity.underlyingError : "\(error)"
])
}
return AnyView(EmptyView())
}
@ -84,6 +89,7 @@ struct SeedBackup: View {
.frame(alignment: .leading)
Button(action: {
tracker.track(.tap(action: .copyAddress), properties: [:])
UIPasteboard.general.string = self.copyText
self.isCopyAlertShown = true
}) {
@ -110,14 +116,18 @@ struct SeedBackup: View {
dismissButton: .default(Text("OK"))
)
}
} .navigationBarTitle("",displayMode: .inline)
.navigationBarHidden(hideNavBar)
}
.onAppear {
tracker.track(.screen(screen: .backup), properties: [:])
}
.navigationBarTitle("",displayMode: .inline)
.navigationBarHidden(hideNavBar)
}
}
struct SeedBackup_Previews: PreviewProvider {
static var previews: some View {
SeedBackup().environmentObject( ZECCWalletEnvironment.shared)
SeedBackup().environmentObject(ZECCWalletEnvironment.shared)
}
}

View File

@ -37,6 +37,11 @@ struct AddMemo: View {
HStack {
ZcashCheckCircle(isChecked: $flow.includeSendingAddress)
.onTapGesture {
self.flow.includeSendingAddress ?
tracker.track(.tap(action: .sendMemoExclude),
properties: [:]) :
tracker.track(.tap(action: .sendMemoInclude),
properties: [:])
self.flow.includeSendingAddress.toggle()
}
Text("Include your sending address in a memo".localized())
@ -53,6 +58,7 @@ struct AddMemo: View {
.layoutPriority(0.5)
Spacer()
Button(action: {
tracker.track(.tap(action: .sendMemoNext), properties: [:])
self.flow.includesMemo = true
self.isShown = true
}) {
@ -65,11 +71,7 @@ struct AddMemo: View {
}.disabled(isMemoEmpty)
NavigationLink(
destination: HoldToSend().environmentObject(flow)
) {
EmptyView()
}.isDetailLink(false)
NavigationLink(
destination: HoldToSend().environmentObject(flow),
isActive: self.$isShown
@ -77,6 +79,7 @@ struct AddMemo: View {
EmptyView()
}.isDetailLink(false)
Button(action: {
tracker.track(.tap(action: .sendMemoSkip), properties: [:])
self.flow.includesMemo = false
self.isShown = true
}) {
@ -93,7 +96,12 @@ struct AddMemo: View {
}.onTapGesture {
UIApplication.shared.endEditing()
}
.navigationBarTitle(Text("Add Memo (optional)".localized()), displayMode: .inline)
.onAppear {
tracker.track(.screen(screen: .sendMemo),
properties: [:])
}
.navigationBarTitle(Text("Add Memo (optional)".localized()),
displayMode: .inline)
}
}

View File

@ -67,7 +67,10 @@ struct EnterRecipient: View {
}
return AnyView(
ActionableMessage(message: "Zcash address in buffer".localized(), actionText: "Paste".localized(), action: { self.flow.address = clipboard })
ActionableMessage(message: "Zcash address in buffer".localized(), actionText: "Paste".localized(), action: {
tracker.track(.tap(action: .sendAddressPaste), properties: [:])
self.flow.address = clipboard
})
)
}
@ -86,12 +89,16 @@ struct EnterRecipient: View {
keyboardType: UIKeyboardType.alphabet,
binding: $flow.address,
action: {
tracker.track(.tap(action: .sendAddressScan),
properties: [:])
self.flow.showScanView = true
},
accessoryIcon: Image("QRCodeIcon")
.renderingMode(.original),
onEditingChanged: { _ in },
onCommit: { }
onCommit: {
tracker.track(.tap(action: .sendAddressDoneAddress), properties: [:])
}
).sheet(isPresented: self.$flow.showScanView) {
NavigationView {
LazyView(
@ -118,7 +125,10 @@ struct EnterRecipient: View {
keyboardType: UIKeyboardType.decimalPad,
binding: $flow.amount,
onEditingChanged: { _ in },
onCommit: {}
onCommit: {
tracker.track(.tap(action: .sendAddressDoneAmount),
properties: [:])
}
)
addressInBuffer
@ -140,6 +150,7 @@ struct EnterRecipient: View {
}
.onAppear() {
tracker.track(.screen(screen: .sendAddress), properties: [:])
self.flow.clearMemo()
}
.onTapGesture {

View File

@ -48,6 +48,8 @@ struct HoldToSend: View {
logger.debug("long press cancelled")
}, longPressSucceded: {
logger.debug("long press succeded")
tracker.track(.tap(action: .sendConfirmNext),
properties: [:])
self.holdOk = true
}, longPressStarted: {
logger.debug("long press started")
@ -59,9 +61,7 @@ struct HoldToSend: View {
Sending().environmentObject(flow)
.navigationBarTitle("", displayMode: .inline)
.navigationBarBackButtonHidden(true)
,
isActive: $holdOk
,isActive: $holdOk
) {
EmptyView()
}.isDetailLink(false)
@ -77,8 +77,14 @@ struct HoldToSend: View {
}
.padding([.horizontal], 40)
}
.onAppear {
tracker.track(.screen(screen: .sendConfirm),
properties: [:])
}
.navigationBarTitle("", displayMode: .inline)
.navigationBarItems(trailing: ZcashCloseButton(action: {
tracker.track(.tap(action: .sendConfirmBack),
properties: [:])
self.flow.close()
}).frame(width: 30, height: 30))
}

View File

@ -106,15 +106,18 @@ struct Sending: View {
includesMemoView
Spacer()
Button(action: {
tracker.track(.tap(action: .sendFinalClose), properties: [:])
self.flow.close()
}) {
doneButton
}
card
}.padding([.horizontal, .bottom], 40)
}
.padding([.horizontal, .bottom], 40)
}.navigationBarItems(trailing: Button(action: {
tracker.track(.tap(action: .sendFinalClose), properties: [:])
self.flow.close()
}) {
Image("close")
@ -123,10 +126,11 @@ struct Sending: View {
.opacity(self.flow.isDone ? 1.0 : 0.0)
)
.alert(isPresented: self.$flow.showError) {
showErrorAlert
showErrorAlert
}
.onAppear() {
self.flow.send()
tracker.track(.screen(screen: .sendFinal), properties: [:])
self.flow.send()
}
}
}