Feature/single pod mainnet (#60)

* Mainnet changes [WIP]

* Separate pods approach [WIP]

* Create a single podfile and scripts to build mainnet or testnet [WIP]

* Added test spec to pod with TESTNET Script [WIP]

* pod install + sample app testnet build worked

* add prefix to database names

* Fix constants in tests

* fix plist

* fix stencils

* Force environment variable

* Get config from environment variable

* Save project settings and create new DemoAppConfig settings

* Fix Template. change demoApp config port

* Add extra warning when building to see environment in logs

* New Readme! + enhanced messaging on build_librustzcash_xcode.sh

* Fix Stencil if statement

* add our domain names to the demo app endpoints

* clean up Podfile

* fix: mainnet not building properly

* improve cleanup

* fixed weird seed change

* remove duplicated file reference

* Improve error handling on LightWalletService

* Improve error handling on Latest block height. fix get address pasteboard gesture

* fix mainnet walletbirthday stencil

* fix: demo app not syncing on mainnet

* Verified Balances and Send Max Funds fixed

* Add paths to preserve when installing pod

* add Stencil to preserved paths

* Fix $ZCASH_SDK_GENERATED_SOURCES_FOLDER not writable error

* Fixes from PR Comments

* Fixed TransactionId string generation

* Fixed Test build scripts + PR comments

* fix indentation

* Changes to script_commons

* fixes per PR

* remove else from mismatch function

* Add comment to poorly named function
This commit is contained in:
Francisco Gindre 2020-01-14 19:25:14 -03:00 committed by GitHub
parent 4f6e15bd9a
commit 750108252f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
51 changed files with 1211 additions and 423 deletions

1
.rustc_info.json Normal file
View File

@ -0,0 +1 @@
{"rustc_fingerprint":9702058127967770953,"outputs":{"7418947162089833526":["___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/pacu/.rustup/toolchains/stable-x86_64-apple-darwin\ndebug_assertions\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_feature=\"sse3\"\ntarget_feature=\"ssse3\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n",""],"1164083562126845933":["rustc 1.38.0 (625451e37 2019-09-23)\nbinary: rustc\ncommit-hash: 625451e376bb2e5283fc4741caa0a3e8a2ca4d54\ncommit-date: 2019-09-23\nhost: x86_64-apple-darwin\nrelease: 1.38.0\nLLVM version: 9.0\n",""],"1138116330425514636":["___\n",""],"4476964694761187371":["___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/pacu/.rustup/toolchains/stable-x86_64-apple-darwin\ndebug_assertions\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_feature=\"sse3\"\ntarget_feature=\"ssse3\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n",""]},"successes":{}}

View File

@ -38,3 +38,6 @@ crate-type = ["staticlib"]
[profile.release]
lto = true
[features]
mainnet = ["zcash_client_sqlite/mainnet"]

View File

@ -17,14 +17,29 @@ target 'ZcashLightClientSample' do
inherit! :search_paths
# Pods for testing
end
end
target 'ZcashLightClientSample-Mainnet' do
inherit! :search_paths
use_frameworks!
pod "KRProgressHUD"
pod 'PaginatedTableView'
pod 'NotificationBubbles'
pod 'ZcashLightClientKit', :path => '../../'
end
post_install do |installer|
installer.pods_project.targets.each do |target|
# if target.name.include? '-Unit-Tests'
# Xcodeproj::XCScheme.share_scheme(installer.pods_project.path, target.name)
# end
target.build_configurations.each do |config|
if target.name == 'ZcashLightClientKit'
config.build_settings['ZCASH_NETWORK_ENVIRONMENT'] = ENV["ZCASH_NETWORK_ENVIRONMENT"]
end
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end

View File

@ -72,8 +72,8 @@ SPEC CHECKSUMS:
SQLite.swift: d2b4642190917051ce6bd1d49aab565fe794eea3
SwiftGRPC: f8fcfecb547c96cc6913de619f95fa3cd09838ee
SwiftProtobuf: 4fd9645e69b72cbae6ec8da5be0cdd20ca6565dd
ZcashLightClientKit: 7c5c65f59cf49f9db5341bacd0504e4264689965
ZcashLightClientKit: ec2438a02fe464bb42b9d55f5001f905e2dcb0e2
PODFILE CHECKSUM: b697e82438d81ef3c882d0d75fa0f04e86b2cf17
PODFILE CHECKSUM: 5a1fb98512fa179a4e83d67d14dd402f6d129a4d
COCOAPODS: 1.8.4

View File

@ -0,0 +1,50 @@
<?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>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View File

@ -13,6 +13,24 @@
0D756A94236C761E009B041B /* GetAddressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D756A93236C761E009B041B /* GetAddressViewController.swift */; };
0D7A4A83236CCD88001F4DD8 /* SyncBlocksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7A4A82236CCD88001F4DD8 /* SyncBlocksViewController.swift */; };
0D7C85E523AD5A9B006878FC /* SampleStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7C85E423AD5A9B006878FC /* SampleStorage.swift */; };
0D8BB45223B1DA0700D5E2A1 /* GetBalanceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD3DC6238D88B100DD3EC4 /* GetBalanceViewController.swift */; };
0D8BB45323B1DA0700D5E2A1 /* GetAddressViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D756A93236C761E009B041B /* GetAddressViewController.swift */; };
0D8BB45423B1DA0700D5E2A1 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D907F172322CC5900D641FE /* ViewController.swift */; };
0D8BB45523B1DA0700D5E2A1 /* LatestHeightViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DDFB33B236B743000AED892 /* LatestHeightViewController.swift */; };
0D8BB45623B1DA0700D5E2A1 /* TransactionDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DBF8F9423A80F5A0010B85F /* TransactionDetailViewController.swift */; };
0D8BB45723B1DA0700D5E2A1 /* TransactionsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DA58B932397DDD9004596EA /* TransactionsTableViewController.swift */; };
0D8BB45823B1DA0700D5E2A1 /* SendViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D4EBA302396CFD70041B507 /* SendViewController.swift */; };
0D8BB45923B1DA0700D5E2A1 /* SyncBlocksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7A4A82236CCD88001F4DD8 /* SyncBlocksViewController.swift */; };
0D8BB45A23B1DA0700D5E2A1 /* DemoAppConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DDFB33D236B844900AED892 /* DemoAppConfig.swift */; };
0D8BB45B23B1DA0700D5E2A1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D907F152322CC5900D641FE /* AppDelegate.swift */; };
0D8BB45C23B1DA0700D5E2A1 /* SampleStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7C85E423AD5A9B006878FC /* SampleStorage.swift */; };
0D8BB45D23B1DA0700D5E2A1 /* TransactionsDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DA58B952397F2CB004596EA /* TransactionsDataSource.swift */; };
0D8BB45E23B1DA0700D5E2A1 /* PaginatedTransactionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DF53E6623A438F100D7249C /* PaginatedTransactionsViewController.swift */; };
0D8BB46223B1DA0700D5E2A1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0D907F1E2322CC5B00D641FE /* LaunchScreen.storyboard */; };
0D8BB46323B1DA0700D5E2A1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0D907F1C2322CC5B00D641FE /* Assets.xcassets */; };
0D8BB46423B1DA0700D5E2A1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0D907F192322CC5900D641FE /* Main.storyboard */; };
0D8BB46623B1DA0700D5E2A1 /* sapling-output.params in Resources */ = {isa = PBXBuildFile; fileRef = 0D2343EC238C91B900606F71 /* sapling-output.params */; };
0D8BB46723B1DA0700D5E2A1 /* sapling-spend.params in Resources */ = {isa = PBXBuildFile; fileRef = 0D2343ED238C91B900606F71 /* sapling-spend.params */; };
0D907F162322CC5900D641FE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D907F152322CC5900D641FE /* AppDelegate.swift */; };
0D907F182322CC5900D641FE /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D907F172322CC5900D641FE /* ViewController.swift */; };
0D907F1B2322CC5900D641FE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0D907F192322CC5900D641FE /* Main.storyboard */; };
@ -22,14 +40,15 @@
0D907F362322CC5B00D641FE /* ZcashLightClientSampleUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D907F352322CC5B00D641FE /* ZcashLightClientSampleUITests.swift */; };
0DA58B942397DDD9004596EA /* TransactionsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DA58B932397DDD9004596EA /* TransactionsTableViewController.swift */; };
0DA58B962397F2CB004596EA /* TransactionsDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DA58B952397F2CB004596EA /* TransactionsDataSource.swift */; };
0DA58BD323982785004596EA /* sapling-output.params in Resources */ = {isa = PBXBuildFile; fileRef = 0DA58BD123982785004596EA /* sapling-output.params */; };
0DBF8F9523A80F5A0010B85F /* TransactionDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DBF8F9423A80F5A0010B85F /* TransactionDetailViewController.swift */; };
0DC30CFDB2CDAF56E3066E8F /* (null) in Frameworks */ = {isa = PBXBuildFile; };
0DCD3DC7238D88B100DD3EC4 /* GetBalanceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DCD3DC6238D88B100DD3EC4 /* GetBalanceViewController.swift */; };
0DDFB33C236B743000AED892 /* LatestHeightViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DDFB33B236B743000AED892 /* LatestHeightViewController.swift */; };
0DDFB33E236B844900AED892 /* DemoAppConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DDFB33D236B844900AED892 /* DemoAppConfig.swift */; };
0DF53E6723A438F100D7249C /* PaginatedTransactionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DF53E6623A438F100D7249C /* PaginatedTransactionsViewController.swift */; };
30AB89006A2D6891F32BFBF0 /* Pods_ZcashLightClientSample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17A69D88CA6DB45FA9D21E75 /* Pods_ZcashLightClientSample.framework */; };
6355F11E6389A7F4FD9F21F7 /* Pods_ZcashLightClientSample_Mainnet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49540782BAF7E579947E23C4 /* Pods_ZcashLightClientSample_Mainnet.framework */; };
742DCA7AFF9FBEA217FD3EED /* Pods_ZcashLightClientSampleUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33F67E6BA5A27016288E77EB /* Pods_ZcashLightClientSampleUITests.framework */; };
96B47C51F3E49A248D9EB4D9 /* Pods_ZcashLightClientSample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5E1724A6A0F7C745C6E30D0 /* Pods_ZcashLightClientSample.framework */; };
A459F9A413C2AB70A02FE894 /* Pods_ZcashLightClientSampleTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C89C3AE14EA6993FECC643BC /* Pods_ZcashLightClientSampleTests.framework */; };
/* End PBXBuildFile section */
@ -57,6 +76,8 @@
0D756A93236C761E009B041B /* GetAddressViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetAddressViewController.swift; sourceTree = "<group>"; };
0D7A4A82236CCD88001F4DD8 /* SyncBlocksViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncBlocksViewController.swift; sourceTree = "<group>"; };
0D7C85E423AD5A9B006878FC /* SampleStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SampleStorage.swift; sourceTree = "<group>"; };
0D8BB46C23B1DA0700D5E2A1 /* ZcashLightClientSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ZcashLightClientSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
0D8BB46D23B1DA0700D5E2A1 /* ZcashLightClientSample-Mainnet-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "ZcashLightClientSample-Mainnet-Info.plist"; path = "/Users/pacu/Repos/ECC/ZcashLightClientKit/Example/ZcashLightClientSample/ZcashLightClientSample-Mainnet-Info.plist"; sourceTree = "<absolute>"; };
0D907F122322CC5900D641FE /* ZcashLightClientSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ZcashLightClientSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
0D907F152322CC5900D641FE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
0D907F172322CC5900D641FE /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
@ -72,29 +93,40 @@
0D907F372322CC5B00D641FE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0DA58B932397DDD9004596EA /* TransactionsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionsTableViewController.swift; sourceTree = "<group>"; };
0DA58B952397F2CB004596EA /* TransactionsDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionsDataSource.swift; sourceTree = "<group>"; };
0DA58BD123982785004596EA /* sapling-output.params */ = {isa = PBXFileReference; lastKnownFileType = file; name = "sapling-output.params"; path = "../../../ZcashLightClientKitTests/sapling-output.params"; sourceTree = "<group>"; };
0DBF8F9423A80F5A0010B85F /* TransactionDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionDetailViewController.swift; sourceTree = "<group>"; };
0DCD3DC6238D88B100DD3EC4 /* GetBalanceViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetBalanceViewController.swift; sourceTree = "<group>"; };
0DDFB33B236B743000AED892 /* LatestHeightViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LatestHeightViewController.swift; sourceTree = "<group>"; };
0DDFB33D236B844900AED892 /* DemoAppConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoAppConfig.swift; sourceTree = "<group>"; };
0DF53E6623A438F100D7249C /* PaginatedTransactionsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginatedTransactionsViewController.swift; sourceTree = "<group>"; };
17A69D88CA6DB45FA9D21E75 /* Pods_ZcashLightClientSample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ZcashLightClientSample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1BEB1273671D6E7883C81472 /* Pods-ZcashLightClientSample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZcashLightClientSample.release.xcconfig"; path = "Target Support Files/Pods-ZcashLightClientSample/Pods-ZcashLightClientSample.release.xcconfig"; sourceTree = "<group>"; };
2460FDF219C57FCA6113E129 /* Pods-ZcashLightClientSampleUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZcashLightClientSampleUITests.release.xcconfig"; path = "Target Support Files/Pods-ZcashLightClientSampleUITests/Pods-ZcashLightClientSampleUITests.release.xcconfig"; sourceTree = "<group>"; };
33F67E6BA5A27016288E77EB /* Pods_ZcashLightClientSampleUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ZcashLightClientSampleUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
47991618469ABD2A7FE69E73 /* Pods-ZcashLightClientSample-Mainnet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZcashLightClientSample-Mainnet.release.xcconfig"; path = "Target Support Files/Pods-ZcashLightClientSample-Mainnet/Pods-ZcashLightClientSample-Mainnet.release.xcconfig"; sourceTree = "<group>"; };
49540782BAF7E579947E23C4 /* Pods_ZcashLightClientSample_Mainnet.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ZcashLightClientSample_Mainnet.framework; sourceTree = BUILT_PRODUCTS_DIR; };
501B4B56030ED65B9C170CE2 /* Pods-ZcashLightClientSampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZcashLightClientSampleTests.debug.xcconfig"; path = "Target Support Files/Pods-ZcashLightClientSampleTests/Pods-ZcashLightClientSampleTests.debug.xcconfig"; sourceTree = "<group>"; };
81B2AC726EA5CC3FEF521F84 /* Pods-ZcashLightClientSampleUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZcashLightClientSampleUITests.debug.xcconfig"; path = "Target Support Files/Pods-ZcashLightClientSampleUITests/Pods-ZcashLightClientSampleUITests.debug.xcconfig"; sourceTree = "<group>"; };
90F55027AEE5406E35644223 /* Pods-ZcashLightClientSample-Mainnet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZcashLightClientSample-Mainnet.debug.xcconfig"; path = "Target Support Files/Pods-ZcashLightClientSample-Mainnet/Pods-ZcashLightClientSample-Mainnet.debug.xcconfig"; sourceTree = "<group>"; };
93F435FD5C95BEE3BC7BBC28 /* Pods-ZcashLightClientSample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZcashLightClientSample.debug.xcconfig"; path = "Target Support Files/Pods-ZcashLightClientSample/Pods-ZcashLightClientSample.debug.xcconfig"; sourceTree = "<group>"; };
A5E1724A6A0F7C745C6E30D0 /* Pods_ZcashLightClientSample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ZcashLightClientSample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
BEA142AE2F3C339269CBA120 /* Pods-ZcashLightClientSampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ZcashLightClientSampleTests.release.xcconfig"; path = "Target Support Files/Pods-ZcashLightClientSampleTests/Pods-ZcashLightClientSampleTests.release.xcconfig"; sourceTree = "<group>"; };
C89C3AE14EA6993FECC643BC /* Pods_ZcashLightClientSampleTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ZcashLightClientSampleTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
0D8BB45F23B1DA0700D5E2A1 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
6355F11E6389A7F4FD9F21F7 /* Pods_ZcashLightClientSample_Mainnet.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
0D907F0F2322CC5900D641FE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
30AB89006A2D6891F32BFBF0 /* Pods_ZcashLightClientSample.framework in Frameworks */,
0DC30CFDB2CDAF56E3066E8F /* (null) in Frameworks */,
96B47C51F3E49A248D9EB4D9 /* Pods_ZcashLightClientSample.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -150,6 +182,7 @@
0D907F132322CC5900D641FE /* Products */,
66EF5A44FD6A5AC92244F054 /* Pods */,
A4E309895AA511479901D67E /* Frameworks */,
0D8BB46D23B1DA0700D5E2A1 /* ZcashLightClientSample-Mainnet-Info.plist */,
);
sourceTree = "<group>";
};
@ -159,6 +192,7 @@
0D907F122322CC5900D641FE /* ZcashLightClientSample.app */,
0D907F262322CC5B00D641FE /* ZcashLightClientSampleTests.xctest */,
0D907F312322CC5B00D641FE /* ZcashLightClientSampleUITests.xctest */,
0D8BB46C23B1DA0700D5E2A1 /* ZcashLightClientSample.app */,
);
name = Products;
sourceTree = "<group>";
@ -183,7 +217,6 @@
0D907F1E2322CC5B00D641FE /* LaunchScreen.storyboard */,
0D907F212322CC5B00D641FE /* Info.plist */,
0DDFB33D236B844900AED892 /* DemoAppConfig.swift */,
0DA58BD123982785004596EA /* sapling-output.params */,
0D7C85E423AD5A9B006878FC /* SampleStorage.swift */,
);
path = ZcashLightClientSample;
@ -257,6 +290,8 @@
BEA142AE2F3C339269CBA120 /* Pods-ZcashLightClientSampleTests.release.xcconfig */,
81B2AC726EA5CC3FEF521F84 /* Pods-ZcashLightClientSampleUITests.debug.xcconfig */,
2460FDF219C57FCA6113E129 /* Pods-ZcashLightClientSampleUITests.release.xcconfig */,
90F55027AEE5406E35644223 /* Pods-ZcashLightClientSample-Mainnet.debug.xcconfig */,
47991618469ABD2A7FE69E73 /* Pods-ZcashLightClientSample-Mainnet.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
@ -264,9 +299,10 @@
A4E309895AA511479901D67E /* Frameworks */ = {
isa = PBXGroup;
children = (
17A69D88CA6DB45FA9D21E75 /* Pods_ZcashLightClientSample.framework */,
C89C3AE14EA6993FECC643BC /* Pods_ZcashLightClientSampleTests.framework */,
33F67E6BA5A27016288E77EB /* Pods_ZcashLightClientSampleUITests.framework */,
49540782BAF7E579947E23C4 /* Pods_ZcashLightClientSample_Mainnet.framework */,
A5E1724A6A0F7C745C6E30D0 /* Pods_ZcashLightClientSample.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -274,6 +310,26 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
0D8BB44E23B1DA0700D5E2A1 /* ZcashLightClientSample-Mainnet */ = {
isa = PBXNativeTarget;
buildConfigurationList = 0D8BB46923B1DA0700D5E2A1 /* Build configuration list for PBXNativeTarget "ZcashLightClientSample-Mainnet" */;
buildPhases = (
0D8BB44F23B1DA0700D5E2A1 /* [CP] Check Pods Manifest.lock */,
0D8BB45023B1DA0700D5E2A1 /* ShellScript */,
0D8BB45123B1DA0700D5E2A1 /* Sources */,
0D8BB45F23B1DA0700D5E2A1 /* Frameworks */,
0D8BB46123B1DA0700D5E2A1 /* Resources */,
A18B8A4D55F1DF8B808ABB67 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = "ZcashLightClientSample-Mainnet";
productName = ZcashLightClientSample;
productReference = 0D8BB46C23B1DA0700D5E2A1 /* ZcashLightClientSample.app */;
productType = "com.apple.product-type.application";
};
0D907F112322CC5900D641FE /* ZcashLightClientSample */ = {
isa = PBXNativeTarget;
buildConfigurationList = 0D907F3A2322CC5B00D641FE /* Build configuration list for PBXNativeTarget "ZcashLightClientSample" */;
@ -371,11 +427,24 @@
0D907F112322CC5900D641FE /* ZcashLightClientSample */,
0D907F252322CC5B00D641FE /* ZcashLightClientSampleTests */,
0D907F302322CC5B00D641FE /* ZcashLightClientSampleUITests */,
0D8BB44E23B1DA0700D5E2A1 /* ZcashLightClientSample-Mainnet */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
0D8BB46123B1DA0700D5E2A1 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0D8BB46223B1DA0700D5E2A1 /* LaunchScreen.storyboard in Resources */,
0D8BB46323B1DA0700D5E2A1 /* Assets.xcassets in Resources */,
0D8BB46423B1DA0700D5E2A1 /* Main.storyboard in Resources */,
0D8BB46623B1DA0700D5E2A1 /* sapling-output.params in Resources */,
0D8BB46723B1DA0700D5E2A1 /* sapling-spend.params in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
0D907F102322CC5900D641FE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -383,7 +452,6 @@
0D907F202322CC5B00D641FE /* LaunchScreen.storyboard in Resources */,
0D907F1D2322CC5B00D641FE /* Assets.xcassets in Resources */,
0D907F1B2322CC5900D641FE /* Main.storyboard in Resources */,
0DA58BD323982785004596EA /* sapling-output.params in Resources */,
0D2343EE238C91B900606F71 /* sapling-output.params in Resources */,
0D2343EF238C91B900606F71 /* sapling-spend.params in Resources */,
);
@ -406,6 +474,45 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
0D8BB44F23B1DA0700D5E2A1 /* [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-ZcashLightClientSample-Mainnet-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;
};
0D8BB45023B1DA0700D5E2A1 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "cd ../../\nif which swiftlint >/dev/null; then\n swiftlint lint --config .swiftlint.yml\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
};
0DCB58A4237B5B580040096C /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -462,6 +569,23 @@
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ZcashLightClientSample/Pods-ZcashLightClientSample-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
A18B8A4D55F1DF8B808ABB67 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-ZcashLightClientSample-Mainnet/Pods-ZcashLightClientSample-Mainnet-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-ZcashLightClientSample-Mainnet/Pods-ZcashLightClientSample-Mainnet-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ZcashLightClientSample-Mainnet/Pods-ZcashLightClientSample-Mainnet-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
A715D89E618E44427C0608E2 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -509,6 +633,26 @@
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
0D8BB45123B1DA0700D5E2A1 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0D8BB45223B1DA0700D5E2A1 /* GetBalanceViewController.swift in Sources */,
0D8BB45323B1DA0700D5E2A1 /* GetAddressViewController.swift in Sources */,
0D8BB45423B1DA0700D5E2A1 /* ViewController.swift in Sources */,
0D8BB45523B1DA0700D5E2A1 /* LatestHeightViewController.swift in Sources */,
0D8BB45623B1DA0700D5E2A1 /* TransactionDetailViewController.swift in Sources */,
0D8BB45723B1DA0700D5E2A1 /* TransactionsTableViewController.swift in Sources */,
0D8BB45823B1DA0700D5E2A1 /* SendViewController.swift in Sources */,
0D8BB45923B1DA0700D5E2A1 /* SyncBlocksViewController.swift in Sources */,
0D8BB45A23B1DA0700D5E2A1 /* DemoAppConfig.swift in Sources */,
0D8BB45B23B1DA0700D5E2A1 /* AppDelegate.swift in Sources */,
0D8BB45C23B1DA0700D5E2A1 /* SampleStorage.swift in Sources */,
0D8BB45D23B1DA0700D5E2A1 /* TransactionsDataSource.swift in Sources */,
0D8BB45E23B1DA0700D5E2A1 /* PaginatedTransactionsViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
0D907F0E2322CC5900D641FE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -580,6 +724,50 @@
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
0D8BB46A23B1DA0700D5E2A1 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 90F55027AEE5406E35644223 /* Pods-ZcashLightClientSample-Mainnet.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 6J82A38BF9;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "$(SRCROOT)/ZcashLightClientSample-Mainnet-Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS";
PRODUCT_BUNDLE_IDENTIFIER = "co.electriccoin.ZcashLightClientSample-Mainnet";
PRODUCT_MODULE_NAME = ZcashLightClientSample;
PRODUCT_NAME = ZcashLightClientSample;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
0D8BB46B23B1DA0700D5E2A1 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 47991618469ABD2A7FE69E73 /* Pods-ZcashLightClientSample-Mainnet.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 6J82A38BF9;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "$(SRCROOT)/ZcashLightClientSample-Mainnet-Info.plist";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS";
PRODUCT_BUNDLE_IDENTIFIER = "co.electriccoin.ZcashLightClientSample-Mainnet";
PRODUCT_MODULE_NAME = ZcashLightClientSample;
PRODUCT_NAME = ZcashLightClientSample;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
0D907F382322CC5B00D641FE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -709,7 +897,9 @@
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = co.electriccoin.ZcashLightClientSample;
OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS";
PRODUCT_BUNDLE_IDENTIFIER = "co.electriccoin.ZcashLightClientSample-Testnet";
PRODUCT_MODULE_NAME = ZcashLightClientSample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@ -729,7 +919,9 @@
"$(inherited)",
"@executable_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = co.electriccoin.ZcashLightClientSample;
OTHER_SWIFT_FLAGS = "$(inherited) -D COCOAPODS";
PRODUCT_BUNDLE_IDENTIFIER = "co.electriccoin.ZcashLightClientSample-Testnet";
PRODUCT_MODULE_NAME = ZcashLightClientSample;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@ -825,6 +1017,15 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
0D8BB46923B1DA0700D5E2A1 /* Build configuration list for PBXNativeTarget "ZcashLightClientSample-Mainnet" */ = {
isa = XCConfigurationList;
buildConfigurations = (
0D8BB46A23B1DA0700D5E2A1 /* Debug */,
0D8BB46B23B1DA0700D5E2A1 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
0D907F0D2322CC5900D641FE /* Build configuration list for PBXProject "ZcashLightClientSample" */ = {
isa = XCConfigurationList;
buildConfigurations = (

View File

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1120"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0D8BB44E23B1DA0700D5E2A1"
BuildableName = "ZcashLightClientSample.app"
BlueprintName = "ZcashLightClientSample-Mainnet"
ReferencedContainer = "container:ZcashLightClientSample.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0D8BB44E23B1DA0700D5E2A1"
BuildableName = "ZcashLightClientSample.app"
BlueprintName = "ZcashLightClientSample-Mainnet"
ReferencedContainer = "container:ZcashLightClientSample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "ZCASH_NETWORK_ENVIRONMENT"
value = "MAINNET"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0D8BB44E23B1DA0700D5E2A1"
BuildableName = "ZcashLightClientSample.app"
BlueprintName = "ZcashLightClientSample-Mainnet"
ReferencedContainer = "container:ZcashLightClientSample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1110"
LastUpgradeVersion = "1120"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
@ -27,15 +27,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "0D907F112322CC5900D641FE"
BuildableName = "ZcashLightClientSample.app"
BlueprintName = "ZcashLightClientSample"
ReferencedContainer = "container:ZcashLightClientSample.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO">
@ -79,13 +70,6 @@
ReferencedContainer = "container:ZcashLightClientSample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "OS_ACTIVITY_MODE"
value = "disable"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"

View File

@ -4,5 +4,7 @@
<dict>
<key>BuildSystemType</key>
<string>Original</string>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@ -113,10 +113,19 @@ extension AppDelegate {
} catch {
print("error clearing data db: \(error)")
}
var storage = SampleStorage.shared
storage!.seed = nil
storage!.privateKey = nil
}
}
extension DemoAppConfig: SeedProvider {}
extension DemoAppConfig: SeedProvider {
func seed() -> [UInt8] {
DemoAppConfig.seed
}
}
extension Initializer {
static var shared: Initializer {
@ -135,15 +144,15 @@ func __documentsDirectory() throws -> URL {
}
func __cacheDbURL() throws -> URL {
try __documentsDirectory().appendingPathComponent("cache.db", isDirectory: false)
try __documentsDirectory().appendingPathComponent(ZcashSDK.DEFAULT_DB_NAME_PREFIX+ZcashSDK.DEFAULT_CACHES_DB_NAME, isDirectory: false)
}
func __dataDbURL() throws -> URL {
try __documentsDirectory().appendingPathComponent("data.db", isDirectory: false)
try __documentsDirectory().appendingPathComponent(ZcashSDK.DEFAULT_DB_NAME_PREFIX+ZcashSDK.DEFAULT_DATA_DB_NAME, isDirectory: false)
}
func __pendingDbURL() throws -> URL {
try __documentsDirectory().appendingPathComponent("pending.db")
try __documentsDirectory().appendingPathComponent(ZcashSDK.DEFAULT_DB_NAME_PREFIX+ZcashSDK.DEFAULT_PENDING_DB_NAME)
}
func __spendParamsURL() throws -> URL {

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Ewq-Xy-xHb">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Ewq-Xy-xHb">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15509"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
@ -507,110 +507,125 @@
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Balance:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AFU-aL-aZ0">
<rect key="frame" x="20" y="143" width="99" height="32"/>
<constraints>
<constraint firstAttribute="height" constant="32" id="ARm-9g-ScV"/>
<constraint firstAttribute="width" constant="99" id="NTl-a4-dIa"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="26"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Amount:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0JH-Y9-k10">
<rect key="frame" x="20" y="194" width="96" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="96" id="3ea-kz-IHC"/>
<constraint firstAttribute="height" constant="32" id="WtS-hu-rud"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="26"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="0.0" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="QPl-ho-Vb5">
<rect key="frame" x="135" y="194" width="259" height="34"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardType="decimalPad" returnKeyType="next" enablesReturnKeyAutomatically="YES" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/>
<connections>
<outlet property="delegate" destination="6mH-Rv-HBn" id="LSD-br-RRX"/>
</connections>
</textField>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="zAddress" textAlignment="natural" minimumFontSize="17" clearButtonMode="always" translatesAutoresizingMaskIntoConstraints="NO" id="pMR-dt-N4H">
<rect key="frame" x="69" y="294" width="325" height="33"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardType="alphabet" returnKeyType="done" enablesReturnKeyAutomatically="YES" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/>
<connections>
<outlet property="delegate" destination="6mH-Rv-HBn" id="MKz-dP-jPU"/>
</connections>
</textField>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="to:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uPw-SX-zmP">
<rect key="frame" x="20" y="295" width="29" height="31"/>
<fontDescription key="fontDescription" type="system" pointSize="26"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="xns-dw-RD9">
<rect key="frame" x="347" y="248" width="51" height="31"/>
<connections>
<action selector="maxFundsValueChanged:" destination="6mH-Rv-HBn" eventType="valueChanged" id="Fbp-vd-U5h"/>
</connections>
</switch>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Max funds" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qUm-uc-jqe">
<rect key="frame" x="251" y="253" width="80" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Zec 0.0" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8RU-tm-VOE">
<rect key="frame" x="151" y="143" width="243" height="32"/>
<fontDescription key="fontDescription" type="system" pointSize="26"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="z5U-bH-L1J">
<rect key="frame" x="20" y="100" width="374" height="28"/>
<fontDescription key="fontDescription" type="italicSystem" pointSize="23"/>
<color key="textColor" cocoaTouchSystemColor="scrollViewTexturedBackgroundColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Amount:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0JH-Y9-k10">
<rect key="frame" x="19" y="252" width="96" height="32"/>
<fontDescription key="fontDescription" type="system" pointSize="26"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="0.0" textAlignment="natural" minimumFontSize="17" clearButtonMode="whileEditing" translatesAutoresizingMaskIntoConstraints="NO" id="QPl-ho-Vb5">
<rect key="frame" x="134" y="252" width="259" height="34"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardType="decimalPad" returnKeyType="next" enablesReturnKeyAutomatically="YES" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/>
<connections>
<outlet property="delegate" destination="6mH-Rv-HBn" id="LSD-br-RRX"/>
</connections>
</textField>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="zAddress" textAlignment="natural" minimumFontSize="17" clearButtonMode="always" translatesAutoresizingMaskIntoConstraints="NO" id="pMR-dt-N4H">
<rect key="frame" x="69" y="352" width="325" height="33"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardType="alphabet" returnKeyType="done" enablesReturnKeyAutomatically="YES" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/>
<connections>
<outlet property="delegate" destination="6mH-Rv-HBn" id="MKz-dP-jPU"/>
</connections>
</textField>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="to:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uPw-SX-zmP">
<rect key="frame" x="19" y="353" width="29" height="31"/>
<fontDescription key="fontDescription" type="system" pointSize="26"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="xns-dw-RD9">
<rect key="frame" x="346" y="306" width="51" height="31"/>
<connections>
<action selector="maxFundsValueChanged:" destination="6mH-Rv-HBn" eventType="valueChanged" id="Fbp-vd-U5h"/>
</connections>
</switch>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Max funds" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qUm-uc-jqe">
<rect key="frame" x="250" y="311" width="80" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Kti-hs-oWv">
<rect key="frame" x="172" y="423" width="70" height="50"/>
<rect key="frame" x="171" y="481" width="70" height="50"/>
<fontDescription key="fontDescription" type="system" pointSize="31"/>
<state key="normal" title="Send"/>
<connections>
<action selector="send:" destination="6mH-Rv-HBn" eventType="touchUpInside" id="1Om-8T-aEN"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="z5U-bH-L1J">
<rect key="frame" x="20" y="100" width="374" height="28"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="verified" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rBT-Aw-Qe1">
<rect key="frame" x="21" y="183" width="99" height="32"/>
<constraints>
<constraint firstAttribute="height" constant="28" id="bkk-o5-taY"/>
<constraint firstAttribute="height" constant="32" id="nSx-xw-VPA"/>
<constraint firstAttribute="width" constant="99" id="q5D-Ht-bpv"/>
</constraints>
<fontDescription key="fontDescription" type="italicSystem" pointSize="23"/>
<fontDescription key="fontDescription" type="italicSystem" pointSize="18"/>
<color key="textColor" cocoaTouchSystemColor="scrollViewTexturedBackgroundColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Zec 0.0" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="io7-QX-p59">
<rect key="frame" x="152" y="183" width="243" height="32"/>
<fontDescription key="fontDescription" type="italicSystem" pointSize="18"/>
<color key="textColor" cocoaTouchSystemColor="scrollViewTexturedBackgroundColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="xns-dw-RD9" firstAttribute="leading" secondItem="qUm-uc-jqe" secondAttribute="trailing" constant="16" id="0E6-oG-dJL"/>
<constraint firstItem="0JH-Y9-k10" firstAttribute="top" secondItem="QPl-ho-Vb5" secondAttribute="top" id="5Gt-7B-dSb"/>
<constraint firstItem="AFU-aL-aZ0" firstAttribute="leading" secondItem="0JH-Y9-k10" secondAttribute="leading" id="A5D-Ya-Idg"/>
<constraint firstItem="z5U-bH-L1J" firstAttribute="top" secondItem="jlC-eJ-vHy" secondAttribute="top" constant="12" id="By6-WK-xcz"/>
<constraint firstItem="Kti-hs-oWv" firstAttribute="centerY" secondItem="mzn-Gc-de9" secondAttribute="centerY" id="F0r-ot-xuI"/>
<constraint firstItem="0JH-Y9-k10" firstAttribute="top" secondItem="AFU-aL-aZ0" secondAttribute="bottom" constant="19" id="GK7-fs-1av"/>
<constraint firstItem="pMR-dt-N4H" firstAttribute="leading" secondItem="uPw-SX-zmP" secondAttribute="trailing" constant="20" id="I0Z-xk-u69"/>
<constraint firstItem="uPw-SX-zmP" firstAttribute="centerY" secondItem="pMR-dt-N4H" secondAttribute="centerY" id="Iqn-PL-8pq"/>
<constraint firstItem="AFU-aL-aZ0" firstAttribute="leading" secondItem="mzn-Gc-de9" secondAttribute="leadingMargin" id="L5K-Fn-ihc"/>
<constraint firstItem="8RU-tm-VOE" firstAttribute="trailing" secondItem="mzn-Gc-de9" secondAttribute="trailingMargin" id="OPN-RS-PU8"/>
<constraint firstItem="uPw-SX-zmP" firstAttribute="top" secondItem="0JH-Y9-k10" secondAttribute="bottom" constant="69" id="QIJ-dN-pDa"/>
<constraint firstItem="AFU-aL-aZ0" firstAttribute="top" secondItem="jlC-eJ-vHy" secondAttribute="top" constant="55" id="QIy-oY-DdN"/>
<constraint firstItem="jlC-eJ-vHy" firstAttribute="bottom" secondItem="Kti-hs-oWv" secondAttribute="bottom" constant="389" id="QUA-g4-o5F"/>
<constraint firstItem="Kti-hs-oWv" firstAttribute="top" secondItem="pMR-dt-N4H" secondAttribute="bottom" constant="96" id="Shi-6F-XSI"/>
<constraint firstItem="AFU-aL-aZ0" firstAttribute="baseline" secondItem="8RU-tm-VOE" secondAttribute="baseline" id="THD-Cd-14H"/>
<constraint firstItem="0JH-Y9-k10" firstAttribute="leading" secondItem="uPw-SX-zmP" secondAttribute="leading" id="UEy-ps-DRR"/>
<constraint firstItem="8RU-tm-VOE" firstAttribute="trailing" secondItem="QPl-ho-Vb5" secondAttribute="trailing" id="ZZB-XQ-K7l"/>
<constraint firstItem="xns-dw-RD9" firstAttribute="top" secondItem="QPl-ho-Vb5" secondAttribute="bottom" constant="20" id="Znx-4w-nuD"/>
<constraint firstItem="AFU-aL-aZ0" firstAttribute="centerX" secondItem="0JH-Y9-k10" secondAttribute="centerX" constant="1.5" id="ar1-AH-KBN"/>
<constraint firstItem="jlC-eJ-vHy" firstAttribute="trailing" secondItem="z5U-bH-L1J" secondAttribute="trailing" constant="20" id="cef-iw-Pmi"/>
<constraint firstItem="qUm-uc-jqe" firstAttribute="leading" secondItem="jlC-eJ-vHy" secondAttribute="leading" constant="251" id="dQ3-Xp-zlq"/>
<constraint firstItem="QPl-ho-Vb5" firstAttribute="leading" secondItem="0JH-Y9-k10" secondAttribute="trailing" constant="19" id="jQ0-Il-6i3"/>
<constraint firstItem="z5U-bH-L1J" firstAttribute="leading" secondItem="jlC-eJ-vHy" secondAttribute="leading" constant="20" id="nXT-Q1-not"/>
<constraint firstItem="pMR-dt-N4H" firstAttribute="top" secondItem="xns-dw-RD9" secondAttribute="bottom" constant="15" id="p19-th-e8f"/>
<constraint firstItem="Kti-hs-oWv" firstAttribute="centerX" secondItem="mzn-Gc-de9" secondAttribute="centerX" id="tLx-AD-tVB"/>
<constraint firstItem="QPl-ho-Vb5" firstAttribute="trailing" secondItem="pMR-dt-N4H" secondAttribute="trailing" id="wSz-7h-E8o"/>
<constraint firstItem="qUm-uc-jqe" firstAttribute="centerY" secondItem="xns-dw-RD9" secondAttribute="centerY" id="x01-Ee-l9q"/>
<constraint firstItem="8RU-tm-VOE" firstAttribute="leading" secondItem="AFU-aL-aZ0" secondAttribute="trailing" constant="32" id="zxm-R2-lRp"/>
<constraint firstItem="uPw-SX-zmP" firstAttribute="top" secondItem="0JH-Y9-k10" secondAttribute="bottom" constant="69" id="0t5-QR-qXZ"/>
<constraint firstItem="0JH-Y9-k10" firstAttribute="top" secondItem="rBT-Aw-Qe1" secondAttribute="bottom" constant="37" id="1Bt-pI-xJj"/>
<constraint firstItem="rBT-Aw-Qe1" firstAttribute="top" secondItem="AFU-aL-aZ0" secondAttribute="bottom" constant="8" id="2fM-dH-CNE"/>
<constraint firstItem="jlC-eJ-vHy" firstAttribute="bottom" secondItem="uPw-SX-zmP" secondAttribute="bottom" constant="478" id="46f-bx-joT"/>
<constraint firstItem="z5U-bH-L1J" firstAttribute="leading" secondItem="AFU-aL-aZ0" secondAttribute="leading" id="48A-yc-8or"/>
<constraint firstItem="rBT-Aw-Qe1" firstAttribute="leading" secondItem="jlC-eJ-vHy" secondAttribute="leading" constant="21" id="4EO-Ii-tlF"/>
<constraint firstItem="0JH-Y9-k10" firstAttribute="leading" secondItem="uPw-SX-zmP" secondAttribute="leading" id="56a-Hf-gpj"/>
<constraint firstItem="jlC-eJ-vHy" firstAttribute="bottom" secondItem="Kti-hs-oWv" secondAttribute="bottom" constant="331" id="5Ax-MG-s7Y"/>
<constraint firstItem="8RU-tm-VOE" firstAttribute="trailing" secondItem="pMR-dt-N4H" secondAttribute="trailing" id="5Ve-Rs-DpP"/>
<constraint firstItem="rBT-Aw-Qe1" firstAttribute="firstBaseline" secondItem="io7-QX-p59" secondAttribute="firstBaseline" id="6Mt-iQ-eOl"/>
<constraint firstItem="qUm-uc-jqe" firstAttribute="leading" secondItem="jlC-eJ-vHy" secondAttribute="leading" constant="250" id="C3n-ax-drt"/>
<constraint firstItem="jlC-eJ-vHy" firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="Kti-hs-oWv" secondAttribute="trailing" symbolic="YES" id="FzI-go-tnu"/>
<constraint firstItem="xns-dw-RD9" firstAttribute="leading" secondItem="qUm-uc-jqe" secondAttribute="trailing" constant="16" id="LW9-gq-IPB"/>
<constraint firstItem="io7-QX-p59" firstAttribute="leading" secondItem="rBT-Aw-Qe1" secondAttribute="trailing" constant="32" id="O9i-AM-cQb"/>
<constraint firstItem="z5U-bH-L1J" firstAttribute="trailing" secondItem="8RU-tm-VOE" secondAttribute="trailing" id="RCO-Hy-MKb"/>
<constraint firstItem="z5U-bH-L1J" firstAttribute="trailing" secondItem="mzn-Gc-de9" secondAttribute="trailingMargin" id="WZq-fd-gDO"/>
<constraint firstItem="8RU-tm-VOE" firstAttribute="leading" secondItem="AFU-aL-aZ0" secondAttribute="trailing" constant="32" id="Yc8-J9-l1L"/>
<constraint firstItem="z5U-bH-L1J" firstAttribute="top" secondItem="jlC-eJ-vHy" secondAttribute="top" constant="12" id="agO-5P-PHm"/>
<constraint firstItem="z5U-bH-L1J" firstAttribute="leading" secondItem="mzn-Gc-de9" secondAttribute="leadingMargin" id="cCV-IE-riT"/>
<constraint firstItem="uPw-SX-zmP" firstAttribute="centerY" secondItem="pMR-dt-N4H" secondAttribute="centerY" id="cLD-bc-ZqM"/>
<constraint firstItem="jlC-eJ-vHy" firstAttribute="trailing" secondItem="QPl-ho-Vb5" secondAttribute="trailing" constant="21" id="dfp-PQ-sOt"/>
<constraint firstItem="io7-QX-p59" firstAttribute="trailing" secondItem="xns-dw-RD9" secondAttribute="trailing" id="e9U-eG-qW1"/>
<constraint firstItem="0JH-Y9-k10" firstAttribute="leading" secondItem="jlC-eJ-vHy" secondAttribute="leading" constant="19" id="gTg-z0-7bx"/>
<constraint firstItem="Kti-hs-oWv" firstAttribute="top" secondItem="pMR-dt-N4H" secondAttribute="bottom" constant="96" id="h8J-Ty-CKZ"/>
<constraint firstItem="AFU-aL-aZ0" firstAttribute="baseline" secondItem="8RU-tm-VOE" secondAttribute="baseline" id="hdx-Kj-2yU"/>
<constraint firstItem="pMR-dt-N4H" firstAttribute="top" secondItem="0JH-Y9-k10" secondAttribute="bottom" constant="68" id="iwu-95-j31"/>
<constraint firstItem="AFU-aL-aZ0" firstAttribute="top" secondItem="z5U-bH-L1J" secondAttribute="bottom" constant="15" id="mE2-sa-OW8"/>
<constraint firstItem="Kti-hs-oWv" firstAttribute="leading" secondItem="jlC-eJ-vHy" secondAttribute="leading" constant="171" id="qdI-bV-ULf"/>
<constraint firstItem="rBT-Aw-Qe1" firstAttribute="baseline" secondItem="io7-QX-p59" secondAttribute="baseline" id="tLg-6E-xDj"/>
<constraint firstItem="pMR-dt-N4H" firstAttribute="top" secondItem="xns-dw-RD9" secondAttribute="bottom" constant="15" id="tXc-Oc-aMz"/>
<constraint firstItem="QPl-ho-Vb5" firstAttribute="leading" secondItem="0JH-Y9-k10" secondAttribute="trailing" constant="19" id="vFa-3F-TMH"/>
<constraint firstItem="pMR-dt-N4H" firstAttribute="leading" secondItem="uPw-SX-zmP" secondAttribute="trailing" constant="21" id="vwX-SR-zO1"/>
<constraint firstItem="qUm-uc-jqe" firstAttribute="centerY" secondItem="xns-dw-RD9" secondAttribute="centerY" id="wU1-Or-f8o"/>
<constraint firstItem="0JH-Y9-k10" firstAttribute="top" secondItem="QPl-ho-Vb5" secondAttribute="top" id="zhn-c5-Gqf"/>
</constraints>
<viewLayoutGuide key="safeArea" id="jlC-eJ-vHy"/>
</view>
@ -624,6 +639,7 @@
<outlet property="maxFunds" destination="xns-dw-RD9" id="cur-gN-J08"/>
<outlet property="sendButton" destination="Kti-hs-oWv" id="6Jq-Up-neP"/>
<outlet property="synchronizerStatusLabel" destination="z5U-bH-L1J" id="1V2-Qk-xI5"/>
<outlet property="verifiedBalanceLabel" destination="io7-QX-p59" id="VtQ-1V-ocI"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="MLi-t7-xoi" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
@ -851,25 +867,59 @@
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GbA-U2-oep">
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="Cep-qY-yP1">
<rect key="frame" x="0.0" y="88" width="414" height="774"/>
<fontDescription key="fontDescription" type="system" pointSize="32"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" distribution="fillProportionally" translatesAutoresizingMaskIntoConstraints="NO" id="B9u-6m-VRy">
<rect key="frame" x="0.0" y="0.0" width="414" height="387"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Balance:" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Goa-CE-fpy">
<rect key="frame" x="0.0" y="0.0" width="207" height="387"/>
<fontDescription key="fontDescription" type="system" pointSize="32"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Balance" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="GbA-U2-oep">
<rect key="frame" x="207" y="0.0" width="207" height="387"/>
<fontDescription key="fontDescription" type="system" pointSize="32"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5O3-ai-XUG">
<rect key="frame" x="0.0" y="387" width="414" height="387"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Verified:" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4IB-QM-xx6">
<rect key="frame" x="0.0" y="0.0" width="207" height="387"/>
<fontDescription key="fontDescription" type="system" pointSize="32"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Balance" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ibi-vm-1Jf">
<rect key="frame" x="207" y="0.0" width="207" height="387"/>
<fontDescription key="fontDescription" type="system" pointSize="32"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="GbA-U2-oep" firstAttribute="leading" secondItem="5sH-IW-gs5" secondAttribute="leading" id="FaP-La-2qn"/>
<constraint firstItem="5sH-IW-gs5" firstAttribute="trailing" secondItem="GbA-U2-oep" secondAttribute="trailing" id="FaU-Yc-Sfo"/>
<constraint firstItem="5sH-IW-gs5" firstAttribute="bottom" secondItem="GbA-U2-oep" secondAttribute="bottom" id="XAB-SE-nvz"/>
<constraint firstItem="GbA-U2-oep" firstAttribute="top" secondItem="5sH-IW-gs5" secondAttribute="top" id="icf-gK-HIL"/>
<constraint firstItem="5sH-IW-gs5" firstAttribute="bottom" secondItem="Cep-qY-yP1" secondAttribute="bottom" id="1wA-22-MWW"/>
<constraint firstItem="5sH-IW-gs5" firstAttribute="trailing" secondItem="Cep-qY-yP1" secondAttribute="trailing" id="5rX-6x-hht"/>
<constraint firstItem="Cep-qY-yP1" firstAttribute="leading" secondItem="5sH-IW-gs5" secondAttribute="leading" id="6mk-cr-RT1"/>
<constraint firstItem="Cep-qY-yP1" firstAttribute="top" secondItem="5sH-IW-gs5" secondAttribute="top" id="MhI-qH-RAz"/>
</constraints>
<viewLayoutGuide key="safeArea" id="5sH-IW-gs5"/>
</view>
<navigationItem key="navigationItem" id="HmT-B1-R92"/>
<connections>
<outlet property="balance" destination="GbA-U2-oep" id="Y61-Hu-0LP"/>
<outlet property="verified" destination="Ibi-vm-1Jf" id="GUd-Dv-egY"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="R73-h3-yvk" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
@ -879,6 +929,6 @@
</scenes>
<inferredMetricsTieBreakers>
<segue reference="oxP-eV-1Z2"/>
<segue reference="QwP-rC-Zbf"/>
<segue reference="snP-Bc-obL"/>
</inferredMetricsTieBreakers>
</document>

View File

@ -10,11 +10,11 @@ import Foundation
import ZcashLightClientKit
struct DemoAppConfig {
static var host = "127.0.0.1"//"34.68.177.238"
static var port = "18232"
static var birthdayHeight: BlockHeight = 620_000
static var network = ZcashNetwork.testNet
static var seed = Array("testreferencealice".utf8)
static var host = ZcashSDK.isMainnet ? "lightwalletd.z.cash" : "lightwalletd.testnet.z.cash"
static var port = "9067"
static var birthdayHeight: BlockHeight = ZcashSDK.isMainnet ? 643_500 : 620_000
static var network = ZcashSDK.isMainnet ? ZcashNetwork.mainNet : ZcashNetwork.testNet
static var seed = ZcashSDK.isMainnet ? Array("testreferencealice".utf8) : Array("testreferencealice".utf8)
static var address: String {
"\(host):\(port)"
}
@ -26,7 +26,7 @@ struct DemoAppConfig {
}
static var endpoint: LightWalletEndpoint {
return LightWalletEndpoint(address: self.host, port: self.port, secure: false)
return LightWalletEndpoint(address: self.host, port: self.port, secure: true)
}
}

View File

@ -44,8 +44,14 @@ class GetAddressViewController: UIViewController {
}
@IBAction func spendingKeyTapped(_ gesture: UIGestureRecognizer) {
guard let key = SampleStorage.shared.privateKey else {
print("nothing to copy")
return
}
print("copied to clipboard")
UIPasteboard.general.string = legibleAddresses()
UIPasteboard.general.string = key
let alert = UIAlertController(title: "", message: "Spending Key Copied to clipboard", preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
self.present(alert, animated: true, completion: nil)
@ -59,9 +65,3 @@ class GetAddressViewController: UIViewController {
self.present(alert, animated: true, completion: nil)
}
}
extension SeedProvider {
func seed() -> [UInt8] {
Array(DemoAppConfig.address.utf8)
}
}

View File

@ -11,10 +11,12 @@ import ZcashLightClientKit
class GetBalanceViewController: UIViewController {
@IBOutlet weak var balance: UILabel!
@IBOutlet weak var verified: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Account 0 Balance"
self.balance.text = "\(Initializer.shared.getBalance().asHumanReadableZecBalance()) ZEC"
self.verified.text = "\(Initializer.shared.getVerifiedBalance().asHumanReadableZecBalance()) ZEC"
// Do any additional setup after loading the view.
}
@ -33,12 +35,12 @@ class GetBalanceViewController: UIViewController {
extension Int64 {
func asHumanReadableZecBalance() -> Double {
Double(self) / Double(ZATOSHI_PER_ZEC)
Double(self) / Double(ZcashSDK.ZATOSHI_PER_ZEC)
}
}
extension Double {
func toZatoshi() -> Int64 {
Int64(self * Double(ZATOSHI_PER_ZEC))
Int64(self * Double(ZcashSDK.ZATOSHI_PER_ZEC))
}
}

View File

@ -20,6 +20,11 @@
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
@ -41,10 +46,5 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
</dict>
</plist>

View File

@ -13,7 +13,7 @@ class LatestHeightViewController: UIViewController {
@IBOutlet weak var blockHeightLabel: UILabel!
var service: LightWalletService = LightWalletGRPCService(host: DemoAppConfig.address, secure: false)
var service: LightWalletService = LightWalletGRPCService(endpoint: DemoAppConfig.endpoint)
var model: BlockHeight? {
didSet {
if viewIfLoaded != nil {
@ -53,7 +53,7 @@ class LatestHeightViewController: UIViewController {
func fail(_ error: LightWalletServiceError) {
self.blockHeightLabel.text = "Error"
let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert)
let alert = UIAlertController(title: "Error", message: String(describing: error), preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Ok", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}

View File

@ -16,6 +16,7 @@ class SendViewController: UIViewController {
@IBOutlet weak var addressTextField: UITextField!
@IBOutlet weak var amountTextField: UITextField!
@IBOutlet weak var balanceLabel: UILabel!
@IBOutlet weak var verifiedBalanceLabel: UILabel!
@IBOutlet weak var maxFunds: UISwitch!
@IBOutlet weak var sendButton: UIButton!
@IBOutlet weak var synchronizerStatusLabel: UILabel!
@ -36,7 +37,9 @@ class SendViewController: UIViewController {
super.viewDidAppear(animated)
do {
try synchronizer.start()
self.synchronizerStatusLabel.text = SDKSynchronizer.textFor(state: .syncing)
} catch {
self.synchronizerStatusLabel.text = SDKSynchronizer.textFor(state: .stopped)
fail(error)
}
}
@ -52,6 +55,7 @@ class SendViewController: UIViewController {
func setUp() {
balanceLabel.text = format(balance: wallet.getBalance())
verifiedBalanceLabel.text = format(balance: wallet.getVerifiedBalance())
toggleSendButton()
let center = NotificationCenter.default
@ -72,7 +76,9 @@ class SendViewController: UIViewController {
}
func maxFundsOn() {
amountTextField.text = String(wallet.getBalance().asHumanReadableZecBalance())
let fee: Int64 = 10000
let max = wallet.getVerifiedBalance() - fee
amountTextField.text = String(max.asHumanReadableZecBalance())
amountTextField.isEnabled = false
}
@ -90,13 +96,13 @@ class SendViewController: UIViewController {
}
func isBalanceValid() -> Bool {
wallet.getBalance() > 0
wallet.getVerifiedBalance() > 0
}
func isAmountValid() -> Bool {
guard let value = amountTextField.text,
let amount = Double(value),
amount.toZatoshi() <= wallet.getBalance() else {
amount.toZatoshi() <= wallet.getVerifiedBalance() else {
return false
}
return true
@ -171,7 +177,7 @@ class SendViewController: UIViewController {
}
func fail(_ error: Error) {
let alert = UIAlertController(title: "Send faile d!", message: "\(error)", preferredStyle: UIAlertController.Style.alert)
let alert = UIAlertController(title: "Send failed!", message: "\(error)", preferredStyle: UIAlertController.Style.alert)
let action = UIAlertAction(title: "OK :(", style: UIAlertAction.Style.default, handler: nil)
alert.addAction(action)
self.present(alert, animated: true, completion: nil)

View File

@ -30,88 +30,21 @@ class TransactionDetailViewController: UITableViewController {
func setup() {
guard model != nil else { return }
idLabel.text = model.transactionId.hexEncodedString()
idLabel.text = model.transactionId.toHexStringTxId()
minedHeightLabel.text = heightToString(height: model.minedHeight)
expiryHeightLabel.text = heightToString(height: model.expiryHeight)
createdLabel.text = model.created
print(model.transactionId.toHexStringTxId())
}
func formatMemo(_ memo: Data?) -> String {
guard let memo = memo, let string = String(bytes: memo, encoding: .utf8) else { return "No Memo" }
return string
}
func heightToString(height: BlockHeight?) -> String {
guard let height = height else { return "NULL" }
return String(height)
}
// MARK: - Table view data source
//
// override func numberOfSections(in tableView: UITableView) -> Int {
// // #warning Incomplete implementation, return the number of sections
// return 0
// }
//
// override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// // #warning Incomplete implementation, return the number of rows
// return 0
// }
/*
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
// Configure the cell...
return cell
}
*/
/*
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}

113
README.md
View File

@ -4,6 +4,8 @@ A Zcash Lightweight Client SDK for iOS
# Build dependencies
ZcashLightClientKit uses a rust library called Librustzcash. In order to build it, you need to have rust and cargo installed on your environment.
Install [Rust](https://www.rust-lang.org/learn/get-started), and then `cargo-lipo`:
```
@ -13,12 +15,115 @@ $ rustup target add aarch64-apple-ios x86_64-apple-ios
# Cocoapods Support
## Installing as a ZcashLightClientKit as a Contributor
```` ruby
use_frameworks!
pod 'ZcashLightClientKit'
pod 'ZcashLightClientKit', :path => '../../', :testspecs => ['Tests'] # include testspecs if you want to run the tests
````
## Installing a wallet app developer
```` ruby
use_frameworks!
pod 'ZcashLightClientKit'
````
### Set Testnet or Mainnet environment
Before building, make sure that your enviroment has the variable `ZCASH_NETWORK_ENVIRONMENT` set to `MAINNET` or `TESTNET`.
### Custom build phases warning
When running `pod install` you will see this warning upon sucess:
```` bash
[!] ZcashLightClientKit has added 2 script phases. Please inspect before executing a build.
See `https://guides.cocoapods.org/syntax/podspec.html#script_phases` for more information.
````
Integrating Rust code with Swift code and delivering it in a consistent and (build) reproducible way, is hard. We've taken the lead to get that burden off your shoulders as much as possible by leveraging the `prepare_command` and `script_phases` features from Cocoapods to carefully generate the `TESTNET` and `MAINNET` builds as simple and less error prone as we could think it could be. Which started as some simple vanilla scripts, ended up being some kind of "Build System" on its own. Nothing is written on stone, and we accept collaborations and improvements in this matter too.
## Build system
This section explains the 'Build System' that integrates the rust code and creates the corresponding environment
### Overview
There are some basic steps to build ZcashLightClientKit. Even though they are 'basic' they can be cumbersome. So we automated them in scripts.
**1. Pod install and `prepare_command`**
ZcashLightClientKit needs files to be present at pod installation time, but that can't be defined properly yet and depend on librustzcash building properly and for an environment to be set up at build time. For know we just need to let Cocoapods that these files exist:
- `${ZCASH_POD_SRCROOT}/zcashlc/libzcashlc.a` this is the librustzcash build .a file itself
- `lib/libzcashlc.a` (as vendored library that will be added as an asset by xcodeproj)
- `ZcashSDK.generated.swift` which contains sensitive values for the SDK that change depending on the network environment we are building for
- `WalletBirthday+saplingtree.generated.swift` helper functions to import existing wallets.
**2. Build Phase**
The build Phase scripts executes withing the Xcode Build Step and has all the known variables of a traditional build at hand.
```` ruby
s.script_phase = {
:name => 'Build generate constants and build librustzcash',
:script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/generate_zcashsdk_constants.sh && sh ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh',
:execution_position => :before_compile
}
````
This step will generate files needed on the next steps and build the librustzcash with Xcode but *not using cargo's built-in xcode integration*
**a. Generating ZcashSDK constants**
To run this you need `Sourcery`. We use `Stencil` templates to create this files based on the `ZCASH_NETWORK_ENVIRONMENT` value of your choice. You can either integrate sourcery with cocoapods or as part of your environment.
All generated files will be located in the Pods source root within the `Generated` folder. `ZCASH_SDK_GENERATED_SOURCES_FOLDER` represents that path in the build system
**b. Building librust zcash and integrating it to the pod structure.**
Where the magic happens. Here we will make sure that everything is set up properly to start building librustzcash. When on mainnet, the build will append a parameter to include mainnet features.
**Safeguards points**:
if it appears that you are about to build something smelly, we will let you know. Combining testnet and mainnet values and artifacts and viceversa leads to unstable builds and may cause lost of funds if ran on production.
````
if [ existing_build_mismatch = true ]; then
# clean
echo "build mismatch. You previously build a Different network environment. It appears that your build could be inconsistent if proceeding. Please clean your Pods/ folder and clean your build before running your next build."
exit 1
fi
````
**3. Xcode clean integration**
When performing a clean, we will clean the rust build folders.
### Scripts
On the Scripts folder you will find the following files:
````
| Scripts
|-/prepare_zcash_sdk.sh
|-/generate_test_constants.sh
|-/build_librustzcash_xcode.sh
|-/build_librustzcash.sh
|-/generate_zcashsdk_constants.sh
|-/script_commons.sh
````
#### prepare_zcash_sdk.sh
This script is run by the Cocoapods 'preapare_command'.
```` Ruby
s.prepare_command = <<-CMD
sh Scripts/prepare_zcash_sdk.sh
CMD
````
It basically creates empty files that cocoapods needs to pick up on it's pod structure but that are still not present in the file system and that will be generated in later build phases.
NOTE: pod install will only run this phase when no Pods/ folder is present or if your pod hash has changed or is not present on manifest.lock. When in doubt, just clean the Pods/ folder and start over. That usually gets rid of weirdness caused by Xcode caching a lot of stuff you are not aware of.
#### script_commons.sh
A lot of important environment variables and helper functions live in the `script_commons.sh`.
# Testing
Currently tests depend on a ```lightwalletd``` server instance runnning locally or remotely to pass.
To know more about running ```lightwalletd```, refer to its repo https://github.com/zcash-hackworks/lightwalletd
@ -38,6 +143,7 @@ export LIGHTWALLETD_ADDRESS="localhost%3a9067"
### Integrating with CD/CI
The ```LIGHTWALLETD_ADDRESS``` environment variable can also be added to your shell of choice and ```xcodebuild``` will pick it up accordingly.
We advice setting this value as a secret variable on your CD/CI environment when possible
# Swiftlint
@ -45,6 +151,11 @@ We don't like reinveing the wheel, so be gently borrowed swift lint rules from A
## Troubleshooting
#### No network environment....
if you see this message when building:
```No network environment. Set ZCASH_NETWORK_ENVIRONMENT to MAINNET or TESTNET```
make sure your dev environment is has this variable set before the build starts. *DO NOT CHANGE IT DURING THE BUILD PROCESS*.
#### _function_name referenced from...
if you get a build error similar to ```_function_name referenced from...```

View File

@ -0,0 +1,33 @@
#!/bin/bash
BASEPATH="${PWD}"
TARGET_DIR="target"
FEATURE_FLAGS=""
NETWORK_TYPE="TESTNET"
FLAVOR_FOLDER="Testnet"
if [ $1 = "--mainnet" ]; then
FEATURE_FLAGS="--features=mainnet"
NETWORK_TYPE="MAINNET"
FLAVOR_FOLDER="Mainnet"
fi
LIB_PATH="ZcashLightClientKit/$FLAVOR_FOLDER/zcashlc"
echo "++++ Building librustzcash $NETWORK_TYPE library ++++"
if [ -f $TARGET_DIR ]; then
rm -rf $TARGET_DIR
fi
cargo build --release $FEATURE_FLAGS && cargo lipo --release
if [ -f $LIB_PATH ]; then
rm -rf $LIB_PATH
mkdir -p $LIB_PATH
fi
cp -rf $TARGET_DIR/universal/release/* $LIB_PATH

View File

@ -0,0 +1,55 @@
#!/bin/sh
SCRIPT_COMMONS="${PODS_TARGET_SRCROOT}/Scripts/script_commons.sh"
if [ ! -f $SCRIPT_COMMONS ]; then
echo "Failed to load $SCRIPT_COMMONS"
exit 1
fi
source $SCRIPT_COMMONS
if [ "$1" = "--testing" ]; then
export ZCASH_NETWORK_ENVIRONMENT=$ZCASH_TESTNET
echo "Testing flag detected, forcing $ZCASH_TESTNET"
fi
check_environment
if [ "$ACTION" = "clean" ]; then
clean
exit 0
fi
if [ existing_build_mismatch = true ]; then
# clean
echo "build mismatch. You previously build a Different network environment. It appears that your build could be inconsistent if proceeding. Please clean your Pods/ folder and clean your build before running your next build."
exit 1
fi
if is_mainnet; then
FEATURE_FLAGS="--features=mainnet"
else
FEATURE_FLAGS=""
fi
echo "Building Rust backend"
echo ""
echo "cargo build $FEATURE_FLAGS --release && cargo lipo --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml $FEATURE_FLAGS --release"
if [ ! -f ${ZCASH_LIB_RUST_BUILD_PATH}/universal/release/${ZCASH_LIB_RUST_NAME} ]; then
cargo build --release $FEATURE_FLAGS && cargo lipo --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml --release
persist_environment
fi
if [ ! -d "${RUST_LIB_PATH}" ]; then
mkdir -p "${RUST_LIB_PATH}"
fi
echo "copying artifacts: cp -f ${ZCASH_LIB_RUST_BUILD_PATH}/universal/release/${ZCASH_LIB_RUST_NAME} ${ZCASH_SDK_RUST_LIB_PATH}/${ZCASH_LIB_RUST_NAME}"
# ALWAYS SHIP RELEASE NO MATTER WHAT YOUR BUILD IS (FOR NOW AT LEAST)
cp -f "${ZCASH_LIB_RUST_BUILD_PATH}/universal/release/${ZCASH_LIB_RUST_NAME}" "${ZCASH_SDK_RUST_LIB_PATH}/${ZCASH_LIB_RUST_NAME}"
echo "copying artifacts: cp -f ${ZCASH_LIB_RUST_BUILD_PATH}/universal/release/${ZCASH_LIB_RUST_NAME} ${RUST_LIB_PATH}/${ZCASH_LIB_RUST_NAME}"
cp -f "${ZCASH_LIB_RUST_BUILD_PATH}/universal/release/${ZCASH_LIB_RUST_NAME}" "${RUST_LIB_PATH}/${ZCASH_LIB_RUST_NAME}"

View File

@ -0,0 +1,16 @@
#!/bin/sh
#check if env-vars.sh exists
ENV_VARS_PATH=${PODS_TARGET_SRCROOT}/env-vars.sh
if [ -f $ENV_VARS_PATH ]; then
source $ENV_VARS_PATH
echo "importing $ENV_VARS_PATH"
fi
export ZCASH_TEST_SRC_PATH="${PODS_TARGET_SRCROOT}/ZcashLightClientKitTests"
if [ ! ${LIGHTWALLETD_ADDRESS} ]; then
echo "LIGHTWALLETD_ADDRESS VARIABLE NOT DEFINED"
exit 1
fi
echo "export ZCASH_TEST_SRC_PATH=$ZCASH_TEST_SRC_PATH"
#no `else` case needed if the CI works as expecteds
sourcery --templates "${ZCASH_TEST_SRC_PATH}/Stencil" --sources ${ZCASH_TEST_SRC_PATH} --output ${ZCASH_TEST_SRC_PATH} --args addr=$LIGHTWALLETD_ADDRESS

View File

@ -0,0 +1,42 @@
#!/bin/sh
SCRIPT_COMMONS="${PODS_TARGET_SRCROOT}/Scripts/script_commons.sh"
if [ -f $SCRIPT_COMMONS ]; then
source $SCRIPT_COMMONS
else
echo "Failed to load $SCRIPT_COMMONS"
exit 1
fi
if ! hash sourcery; then
echo "Sourcery not found on your PATH"
exit 1
fi
export ZCASH_SDK_TEMPLATE="${ZCASH_SRC_PATH}/Stencil"
echo "export ZCASH_SRC_PATH=${ZCASH_SRC_PATH}"
check_environment
if is_mainnet; then
SOURCERY_ARGS="--args dbprefix=ZcashSdk_mainnet_ --args ismainnet=true --args saplingActivationHeight=419_200"
else
SOURCERY_ARGS="--args dbprefix=ZcashSdk_testnet_ --args ismainnet=false --args saplingActivationHeight=280_000"
fi
if [ -d $ZCASH_SDK_GENERATED_SOURCES_FOLDER ]; then
echo "clean up before generating new files: $ZCASH_SDK_GENERATED_SOURCES_FOLDER"
echo "rm -rf ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}/*.generated*"
rm -rf "${ZCASH_SDK_GENERATED_SOURCES_FOLDER}/*.generated*"
else
echo "mkdir -p -v $ZCASH_SDK_GENERATED_SOURCES_FOLDER"
mkdir -p -v ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}
fi
echo "Set +w to ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}"
chmod -R +w ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}
echo "sourcery --prune --verbose --templates ${ZCASH_SDK_TEMPLATE} --sources ${ZCASH_SRC_PATH} --output ${ZCASH_SDK_GENERATED_SOURCES_FOLDER} $SOURCERY_ARGS "
sourcery --prune --verbose --templates ${ZCASH_SDK_TEMPLATE} --sources ${ZCASH_SRC_PATH} --output ${ZCASH_SDK_GENERATED_SOURCES_FOLDER} $SOURCERY_ARGS

View File

@ -0,0 +1,43 @@
#!/bin/sh
echo "PWD: ${PWD}"
echo "*********************************************"
echo "* create fake .a so pod install picks it up *"
echo "*********************************************"
RUST_LIB_PATH="${PWD}"/lib
mkdir -p -v $RUST_LIB_PATH
echo "******************************************************************************"
echo " touch $RUST_LIB_PATH/libzcashlc.a "
echo "******************************************************************************"
touch $RUST_LIB_PATH/libzcashlc.a
ZCASH_POD_ROOT="${PWD}"
ZCASH_POD_SRCROOT="${ZCASH_POD_ROOT}/ZcashLightClientKit"
ZCASH_SDK_GENERATED_SOURCES_FOLDER="${ZCASH_POD_SRCROOT}/Generated"
echo "***************************************************************************"
echo " touch ${ZCASH_POD_ROOT}/zcashlc/libzcashlc.a"
echo "***************************************************************************"
touch ${ZCASH_POD_SRCROOT}/zcashlc/libzcashlc.a
echo "make ${ZCASH_SDK_GENERATED_SOURCES_FOLDER} folder"
mkdir -p ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}
echo "**********************************************"
echo "* create empty ZcashSDK.generated.swift file *"
echo "**********************************************"
echo ""
echo "touch ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}/ZcashSDK.generated.swift"
touch ${ZCASH_SDK_GENERATED_SOURCES_FOLDER}/ZcashSDK.generated.swift
echo "****************************************************************"
echo "* create empty WalletBirthday+saplingtree.generated.swift file *"
echo "****************************************************************"
echo ""
echo "touch $ZCASH_SDK_GENERATED_SOURCES_FOLDER/WalletBirthday+saplingtree.generated.swift"
touch $ZCASH_SDK_GENERATED_SOURCES_FOLDER/WalletBirthday+saplingtree.generated.swift

95
Scripts/script_commons.sh Normal file
View File

@ -0,0 +1,95 @@
#!/bin/sh
export PATH="$HOME/.cargo/bin:$PATH"
export RUST_LIB_PATH="${PODS_TARGET_SRCROOT}/lib"
export ZCASH_POD_SCRIPTS="${PODS_TARGET_SRCROOT}/Scripts"
export ZCASH_LIB_RUST_BUILD_PATH="${PODS_TARGET_SRCROOT}/target"
export ZCASH_BUILD_TYPE_MAINNET_FLAG=".mainnet_build"
export ZCASH_BUILD_TYPE_TESTNET_FLAG=".testnet_build"
export ZCASH_LIB_RUST_NAME="libzcashlc.a"
export ZCASH_TESTNET="TESTNET"
export ZCASH_MAINNET="MAINNET"
export ZCASH_SRC_PATH="${PODS_TARGET_SRCROOT}/ZcashLightClientKit"
export ZCASH_SDK_RUST_LIB_PATH="${ZCASH_SRC_PATH}/zcashlc"
export ZCASH_SDK_GENERATED_SOURCES_FOLDER="${ZCASH_SRC_PATH}/Generated"
function clean {
cargo clean
if [ -d "${RUST_LIB_PATH}" ]; then
rm -rf "${RUST_LIB_PATH}"
fi
if [ -d "${ZCASH_LIB_RUST_BUILD_PATH}" ]; then
rm -rf "${ZCASH_LIB_RUST_BUILD_PATH}"
fi
}
function check_environment {
if [[ $ZCASH_NETWORK_ENVIRONMENT != $ZCASH_MAINNET ]] && [[ $ZCASH_NETWORK_ENVIRONMENT != $ZCASH_TESTNET ]]; then
echo "No network environment. Set ZCASH_NETWORK_ENVIRONMENT to $ZCASH_MAINNET or $ZCASH_TESTNET"
exit 1
fi
if [[ ! $ZCASH_SDK_GENERATED_SOURCES_FOLDER ]]; then
echo "No 'ZCASH_SDK_GENERATED_SOURCES_FOLDER' variable present. delete Pods/ and run 'pod install --verbose'"
exit 1
fi
echo "**** Building for $ZCASH_NETWORK_ENVIRONMENT environment ****"
}
function is_mainnet {
if [[ $ZCASH_NETWORK_ENVIRONMENT = $ZCASH_MAINNET ]]; then
true
else
false
fi
}
# Return success (0) if there is a build mismatch, else failure (1) if no mismatch.
function existing_build_mismatch {
#if build exists check that corresponds to the current network environment
if [! -d $ZCASH_LIB_RUST_BUILD_PATH ]; then
return 1
fi
# there's a MAINNET Flag and MAINNET ENVIRONMENT
if [ -f "$ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_MAINNET_FLAG" ] && [[ "$ZCASH_NETWORK_ENVIRONMENT" = "$ZCASH_MAINNET" ]]
then
return 1 # no build mismatch
fi
if [ -f "$ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_MAINNET_FLAG" ] && [[ "$ZCASH_NETWORK_ENVIRONMENT" = "$ZCASH_TESTNET" ]]
then
warn_mismatch $ZCASH_MAINNET $ZCASH_NETWORK_ENVIRONMENT
return 0 # build mismatch in place
fi
# There's a TESTNET flag and we are on TESTNET ENVIRONMENT
if [ -f "$ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_TESTNET_FLAG" ] && [[ "$ZCASH_NETWORK_ENVIRONMENT" = "$ZCASH_TESTNET" ]]
then
return 1 # no build mismatch
fi
# There's a TESTNET flag and we are on a MAINNET Environment
if [ -f "$ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_TESTNET_FLAG" ] && [[ "$ZCASH_NETWORK_ENVIRONMENT" = "$ZCASH_MAINNET" ]]
warn_mismatch $ZCASH_TESTNET $ZCASH_NETWORK_ENVIRONMENT
return 0 # build mismatch in place
fi
echo "=== NO BUILD FLAG, CHECKING ENVIRONMENT ==="
check_environment
return 1 # no build mismatch
}
function warn_mismatch {
echo "*** WARNING: *** build mismatch. found ${0} but environment is ${1}"
}
function persist_environment {
check_environment
if [ $ZCASH_NETWORK_ENVIRONMENT = "$ZCASH_MAINNET" ]
then
touch $ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_MAINNET_FLAG
elif [[ "$ZCASH_NETWORK_ENVIRONMENT" = "$ZCASH_TESTNET" ]]
then
touch $ZCASH_LIB_RUST_BUILD_PATH/$ZCASH_BUILD_TYPE_TESTNET_FLAG
fi
}

View File

@ -15,29 +15,34 @@ Pod::Spec.new do |s|
}
s.source = { :git => 'https://github.com/zcash/ZcashLightClientKit.git', :tag => s.version.to_s }
s.public_header_files = 'ZcashLightClientKit/**/*.h'
s.public_header_files = 'ZcashLightClientKit/ZcashLightClientKit.h'
s.private_header_files = 'ZcashLightClientKit/zcashlc/zcashlc.h'
s.source_files = 'ZcashLightClientKit/**/*.{swift,h,a}'
s.module_map = 'ZcashLightClientKit.modulemap'
s.swift_version = '5.1'
s.ios.deployment_target = '11.0'
s.ios.deployment_target = '12.0'
s.dependency 'SwiftGRPC'
s.dependency 'SQLite.swift'
s.ios.vendored_libraries = 'lib/libzcashlc.a'
s.preserve_paths = ['Scripts', 'rust','docs','Cargo.*','ZcashLightClientKit/Stencil']
s.prepare_command = <<-CMD
BASEPATH="${PWD}"
echo "Building librustzcash library..."
cargo build && cargo lipo --release
mkdir -p lib
cp target/universal/release/* lib/
cp -rf target/universal/release/* ZcashLightClientKit/zcashlc
sh Scripts/prepare_zcash_sdk.sh
CMD
s.test_spec 'Tests' do | test_spec |
test_spec.source_files = 'ZcashLightClientKitTests/**/*.{swift}'
test_spec.ios.resources = 'ZcashLightClientKitTests/**/*.{db,params}'
test_spec.dependency 'SwiftGRPC'
test_spec.dependency 'SQLite.swift'
end
s.script_phase = {
:name => 'Build generate constants and build librustzcash',
:script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/generate_zcashsdk_constants.sh && sh ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh',
:execution_position => :before_compile
}
s.test_spec 'Tests' do | test_spec |
test_spec.source_files = 'ZcashLightClientKitTests/**/*.{swift}'
test_spec.ios.resources = 'ZcashLightClientKitTests/**/*.{db,params}'
test_spec.script_phase = {
:name => 'Build generate constants and build librustzcash',
:script => 'sh ${PODS_TARGET_SRCROOT}/Scripts/generate_test_constants.sh && ${PODS_TARGET_SRCROOT}/Scripts/build_librustzcash_xcode.sh --testing}',
:execution_position => :before_compile
}
test_spec.dependency 'SwiftGRPC'
test_spec.dependency 'SQLite.swift'
end
end

View File

@ -8,15 +8,6 @@
import Foundation
protocol Storage {
func createDatabase(at path: String) throws
func closeDatabase()
var compactBlockDao: CompactBlockDAO { get }
}
enum StorageError: Error {
case couldNotCreate
case openFailed

View File

@ -50,14 +50,14 @@ public class CompactBlockProcessor {
public struct Configuration {
public var cacheDb: URL
public var dataDb: URL
public var downloadBatchSize = DEFAULT_BATCH_SIZE
public var blockPollInterval = DEFAULT_POLL_INTERVAL
public var retries = DEFAULT_RETRIES
public var maxBackoffInterval = DEFAULT_MAX_BACKOFF_INTERVAL
public var rewindDistance = DEFAULT_REWIND_DISTANCE
public var downloadBatchSize = ZcashSDK.DEFAULT_BATCH_SIZE
public var blockPollInterval = ZcashSDK.DEFAULT_POLL_INTERVAL
public var retries = ZcashSDK.DEFAULT_RETRIES
public var maxBackoffInterval = ZcashSDK.DEFAULT_MAX_BACKOFF_INTERVAL
public var rewindDistance = ZcashSDK.DEFAULT_REWIND_DISTANCE
public var walletBirthday: BlockHeight
public init(cacheDb: URL, dataDb: URL, walletBirthday: BlockHeight = SAPLING_ACTIVATION_HEIGHT){
public init(cacheDb: URL, dataDb: URL, walletBirthday: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT){
self.cacheDb = cacheDb
self.dataDb = dataDb
self.walletBirthday = walletBirthday
@ -340,8 +340,8 @@ public class CompactBlockProcessor {
}
func determineLowerBound(errorHeight: Int) -> BlockHeight {
let offset = min(MAX_REORG_SIZE, DEFAULT_REWIND_DISTANCE * (consecutiveChainValidationErrors + 1))
return max(errorHeight - offset, lowerBoundHeight ?? SAPLING_ACTIVATION_HEIGHT)
let offset = min(ZcashSDK.MAX_REORG_SIZE, ZcashSDK.DEFAULT_REWIND_DISTANCE * (consecutiveChainValidationErrors + 1))
return max(errorHeight - offset, lowerBoundHeight ?? ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
}
private func processBatchFinished(range: CompactBlockRange) {

View File

@ -1,84 +0,0 @@
//
// Constants.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 13/09/2019.
// Copyright © 2019 Electric Coin Company. All rights reserved.
//
import Foundation
/**
* Miner's fee in zatoshi.
*/
public let MINERS_FEE_ZATOSHI: BlockHeight = 10_000
/**
* The number of zatoshi that equal 1 ZEC.
*/
public let ZATOSHI_PER_ZEC: BlockHeight = 100_000_000
/**
* 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 let SAPLING_ACTIVATION_HEIGHT: BlockHeight = 280_000
/**
* The theoretical maximum number of blocks in a reorg, due to other bottlenecks in the protocol design.
*/
public let MAX_REORG_SIZE = 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 shdould be kept in sync.
*/
public let EXPIRY_OFFSET = 20
//
// Defaults
//
/**
* Default size of batches of blocks to request from the compact block service.
*/
public let DEFAULT_BATCH_SIZE = 100
/**
* Default amount of time, in in seconds, to poll for new blocks. Typically, this should be about half the average
* block time.
*/
public let DEFAULT_POLL_INTERVAL: TimeInterval = 37.5
/**
* Default attempts at retrying.
*/
public let DEFAULT_RETRIES = 5
/**
* The default maximum amount of time to wait during retry backoff intervals. Failed loops will never wait longer than
* this before retyring.
*/
public let DEFAULT_MAX_BACKOFF_INTERVAL: 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.
*/
public let DEFAULT_REWIND_DISTANCE = 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.
*/
public let DEFAULT_STALE_TOLERANCE = 10
/**
Default Name for LibRustZcash data.db
*/
public let DEFAULT_DATA_DB_NAME = "data.db"
/**
Default Name for Compact Block caches db
*/
public let DEFAULT_CACHES_DB_NAME = "caches.db"

View File

@ -0,0 +1,16 @@
//
// Data+Zcash.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 1/10/20.
//
import Foundation
public extension Data {
func toHexStringTxId() -> String {
String(self.hexEncodedString().reversed())
}
}

View File

@ -44,7 +44,7 @@ public struct LightWalletEndpoint {
public class Initializer {
private(set) var rustBackend: ZcashRustBackendWelding.Type = ZcashRustBackend.self
private var lowerBoundHeight: BlockHeight = SAPLING_ACTIVATION_HEIGHT
private var lowerBoundHeight: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
private(set) var cacheDbURL: URL
private(set) var dataDbURL: URL
private(set) var pendingDbURL: URL
@ -106,7 +106,7 @@ public class Initializer {
let downloader = CompactBlockStorage(url: cacheDbURL, readonly: true)
let lastDownloaded = (try? downloader.latestHeight()) ?? SAPLING_ACTIVATION_HEIGHT
let lastDownloaded = (try? downloader.latestHeight()) ?? ZcashSDK.SAPLING_ACTIVATION_HEIGHT
// resume from last downloaded block
lowerBoundHeight = max(birthday.height, lastDownloaded)
@ -125,6 +125,10 @@ public class Initializer {
rustBackend.getBalance(dbData: dataDbURL, account: Int32(index))
}
public func getVerifiedBalance(account index: Int = 0) -> Int64 {
rustBackend.getVerifiedBalance(dbData: dataDbURL, account: Int32(index))
}
// TODO: make internal
public func blockProcessor() -> CompactBlockProcessor? {
var configuration = CompactBlockProcessor.Configuration(cacheDb: cacheDbURL, dataDb: dataDbURL)
@ -163,25 +167,3 @@ public struct WalletBirthday {
var time: UInt32 = 0
var tree: String = ""
}
// TODO: remove this in favor of loading these from disk
public extension WalletBirthday {
static func birthday(with height: BlockHeight) -> WalletBirthday? {
switch height {
case 280_000:
return WalletBirthday(height: 280000, hash: "000420e7fcc3a49d729479fb0b560dd7b8617b178a08e9e389620a9d1dd6361a", time: 1535262293, tree: "000000")
case 421720:
return WalletBirthday(height: 421720, hash: "001ede53476a31a91da3313eddf4e41409fb7f4e003840700557b576024d09b4", time: 1550762014, tree: "015495a30aef9e18b9c774df6a9fcd583748c8bba1a6348e70f59bc9f0c2bc673b000f00000000018054b75173b577dc36f2c80dfc41f83d6716557597f74ec54436df32d4466d57000120f1825067a52ca973b07431199d5866a0d46ef231d08aa2f544665936d5b4520168d782e3d028131f59e9296c75de5a101898c5e53108e45baa223c608d6c3d3d01fb0a8d465b57c15d793c742df9470b116ddf06bd30d42123fdb7becef1fd63640001a86b141bdb55fd5f5b2e880ea4e07caf2bbf1ac7b52a9f504977913068a917270001dd960b6c11b157d1626f0768ec099af9385aea3f31c91111a8c5b899ffb99e6b0192acd61b1853311b0bf166057ca433e231c93ab5988844a09a91c113ebc58e18019fbfd76ad6d98cafa0174391546e7022afe62e870e20e16d57c4c419a5c2bb69")
case 425865:
return WalletBirthday(height: 425865, hash: "0011c4de26004e564347b8af218ca16cd07b08c4159b1cc9c43afa6cb8807bed", time: 1551215770, tree: "01881e4da7e4767ee8a144a32ab8a5719a513bb05854477773bb55e6cd7f15055201f8a99a3a5ae3528ec2fc0bda9652b6728aecb08bf364e06ac511fd6654d782720f019ef0b9bdd075c38519fa4ab8210fe7e94c609f52672796e33e3cab58b1602831000001f803bf338ff1526b2ca527288974cb9be3fe240a2eadb7507e46ba59eaddb9320129fc0148ac088a6aa509f8f64ef79fda92232020369b58a12b32c05b6f428f22015e3dd0950c442940bd015c2176f7c817f22104f54c61159727483188c539dc13000000013589be9e2d9e9e38fd78b1e8eaec5b5f5167bf7fd2b1c95c316fa366a24cac4c01a86b141bdb55fd5f5b2e880ea4e07caf2bbf1ac7b52a9f504977913068a917270001dd960b6c11b157d1626f0768ec099af9385aea3f31c91111a8c5b899ffb99e6b0192acd61b1853311b0bf166057ca433e231c93ab5988844a09a91c113ebc58e18019fbfd76ad6d98cafa0174391546e7022afe62e870e20e16d57c4c419a5c2bb69")
case 518000:
return WalletBirthday(height: 518000, hash: "000ba586d734c295f0bc034be229b1c96cb040f9d4929efdb5d2b187eeb238fb", time: 1560645743, tree: "01a4f5240a88a6eb4ffbda7961a1430506aad1a50ba011593f02c243d968feb0550010000140f91773b4ab669846e5bcb96f60e68256c49a27872a98e9d5ce50b30a0c434e0000018968663d6a7b444591de83f8a07223113f5de7e8203807adacc7677c3bcd4f420194c7ecac0ef6d702d475680ec32051fdf6368af0c459ab450009c001bcbf7a5300000001f0eead5192c3b3ab7208429877570676647e448210332c6da7e18660b142b80e01b98b14cab05247195b3b3be3dd8639bae99a0dd10bed1282ac25b62a134afd7200000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39")
case 523240:
return WalletBirthday(height: 523240, hash: "00000c33da2196f0ed1bda71043f671fc69a0212e01f892653e212ab358f6b79", time: 1561002603, tree: "01d3e02bc1c2d66762f370b329a3063067701ad66c44b40285686bc8ff25f5616f00100154bff87bd0bda3b70a6d7754eca261de15fee3cd9bc53073a232e07fc3261e27000001a54dcaccb4c5e578aef89f2a3b4e3c3d8a487e6e904c5da5916118d721948d07000000000118fa9c6fef4963049dc7002a13bb0021d5e950591e48c9e5f2cbd1199429b80401f0eead5192c3b3ab7208429877570676647e448210332c6da7e18660b142b80e01b98b14cab05247195b3b3be3dd8639bae99a0dd10bed1282ac25b62a134afd7200000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39")
case 620000:
return WalletBirthday(height: 620000, hash: "005f97953c8e1265d6b45f4435ffa32918e53e8f0025c286a4080c3eab167197", time: 1569572035, tree: "0170cf036ea1ea3c6e08432e18b6a372ca0b8b83671cc13ab0cf9e28c182f6c36f00100000013f3fc2c16ac4780f1c472ca65534ab08911f325a9edde5ea7f24364b47c9a95300017621b12e518cbbbdb7511ab423e0bddda412ed61ed3cff5be2140de65d6a0069010576153a5a2098812e7a028c37c3398e186f398c9b07bc199784ab97e5535c3e0000019a6ce2f0f7dbb2de493a315abf62d8ca96ccc701f116b6ddfae33870a2183d3c01c9d3564eff54ebc328eab2e4f1150c3637f4f47516f879a0cfebdf49fe7b1d5201c104705fac60a85596010e41260d07f3a64f38f37a112eaef41cd9d736edc5270145e3d4899fcd7f0f1236ae31eafb3f4b65ad6b11a17eae1729cec09bd3afa01a000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39")
default:
return nil
}
}
}

View File

@ -23,9 +23,9 @@ public struct DefaultResourceProvider: ResourceProvider {
public var dataDbURL: URL {
do {
let url = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
return url.appendingPathComponent(DEFAULT_DATA_DB_NAME)
return url.appendingPathComponent(ZcashSDK.DEFAULT_DATA_DB_NAME)
} catch {
return URL(fileURLWithPath: "file://\(DEFAULT_DATA_DB_NAME)")
return URL(fileURLWithPath: "file://\(ZcashSDK.DEFAULT_DATA_DB_NAME)")
}
}
@ -33,9 +33,9 @@ public struct DefaultResourceProvider: ResourceProvider {
public var cacheDbURL: URL {
do {
let path = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
return path.appendingPathComponent(DEFAULT_CACHES_DB_NAME)
return path.appendingPathComponent(ZcashSDK.DEFAULT_CACHES_DB_NAME)
} catch {
return URL(fileURLWithPath: "file://\(DEFAULT_CACHES_DB_NAME)")
return URL(fileURLWithPath: "file://\(ZcashSDK.DEFAULT_CACHES_DB_NAME)")
}
}

View File

@ -94,9 +94,9 @@ extension LightWalletGRPCService: LightWalletService {
public func latestBlockHeight(result: @escaping (Result<BlockHeight, LightWalletServiceError>) -> Void) {
do {
try compactTxStreamer.getLatestBlock(ChainSpec()) { (blockID, _) in
try compactTxStreamer.getLatestBlock(ChainSpec()) { (blockID, callResult) in
guard let rawHeight = blockID?.height, let blockHeight = Int(exactly: rawHeight) else {
result(.failure(LightWalletServiceError.generalError))
result(.failure(LightWalletServiceError.failed(statusCode: callResult.statusCode, message: callResult.statusMessage ?? "No message")))
return
}
result(.success(blockHeight))
@ -126,7 +126,7 @@ extension LightWalletGRPCService: LightWalletService {
result(.failure(LightWalletServiceError.generalError))
}
default:
result(.failure(LightWalletServiceError.failed(statusCode: code)))
result(.failure(LightWalletServiceError.failed(statusCode: code, message: callResult.statusMessage ?? "No Message")))
}
} else {

View File

@ -11,7 +11,7 @@ import SwiftGRPC
import SwiftProtobuf
public enum LightWalletServiceError: Error {
case generalError
case failed(statusCode: StatusCode)
case failed(statusCode: StatusCode, message: String)
case invalidBlock
case sentFailed(sendResponse: LightWalletServiceResponse)
case genericError(error: Error)

View File

@ -0,0 +1,38 @@
//swiftlint:disable all
import Foundation
{% if argument.ismainnet == "true" %}
public extension WalletBirthday {
static func birthday(with height: BlockHeight) -> WalletBirthday? {
switch height {
case 419_200:
return WalletBirthday(height: 419_200, hash: "00000000025a57200d898ac7f21e26bf29028bbe96ec46e05b2c17cc9db9e4f3", time: 1540779337, tree: "000000")
case 643_500:
return WalletBirthday(height: 643_500, hash: "000000000041005fd724ff6e29bd1738bed69a4d9ca028e124029525350bd789", time: 1574579149, tree: "01999fc372390699b15f71d41745abe6a2ea0db4ffa8894d3c5fe30b9261a1a43a01585112668685bd6783cb01b72d17dc86c6d740c27cccf66b75e959e4e4f5ea3710019b7f6b4457a97eadbe1a39bfcc6ba0a56d37010d0d799e1e652fc29733103e04016a0b4d2705e1feb2021d80e5785608536dde05aea5ef676a5427244228b19e2d00010973d03ad5f79fcac64ab3ffbdaaac1a24b74a3617770bf960fb004cbd422439000001984bfce9361025cc38574f944a3ed7b074b3bf88cfce6f14c4a9be4d91d6dc730105871ec1e3737a39bceb00b0c2d253ff36f472e92c361e7ef360d49ea8dc4c4200000001c145105e1bf401668a8f23ca70c47ee92d23bd366072020c83d26b855eeafd6d0001fa6980c053d84f809b6abcf35690f03a11f87b28e3240828e32e3f57af41e54e01319312241b0031e3a255b0d708750b4cb3f3fe79e3503fe488cc8db1dd00753801754bb593ea42d231a7ddf367640f09bbf59dc00f2c1d2003cc340e0c016b5b13")
default:
return nil
}
}
}
{% else %}
public extension WalletBirthday {
static func birthday(with height: BlockHeight) -> WalletBirthday? {
switch height {
case 280_000:
return WalletBirthday(height: 280000, hash: "000420e7fcc3a49d729479fb0b560dd7b8617b178a08e9e389620a9d1dd6361a", time: 1535262293, tree: "000000")
case 421720:
return WalletBirthday(height: 421720, hash: "001ede53476a31a91da3313eddf4e41409fb7f4e003840700557b576024d09b4", time: 1550762014, tree: "015495a30aef9e18b9c774df6a9fcd583748c8bba1a6348e70f59bc9f0c2bc673b000f00000000018054b75173b577dc36f2c80dfc41f83d6716557597f74ec54436df32d4466d57000120f1825067a52ca973b07431199d5866a0d46ef231d08aa2f544665936d5b4520168d782e3d028131f59e9296c75de5a101898c5e53108e45baa223c608d6c3d3d01fb0a8d465b57c15d793c742df9470b116ddf06bd30d42123fdb7becef1fd63640001a86b141bdb55fd5f5b2e880ea4e07caf2bbf1ac7b52a9f504977913068a917270001dd960b6c11b157d1626f0768ec099af9385aea3f31c91111a8c5b899ffb99e6b0192acd61b1853311b0bf166057ca433e231c93ab5988844a09a91c113ebc58e18019fbfd76ad6d98cafa0174391546e7022afe62e870e20e16d57c4c419a5c2bb69")
case 425865:
return WalletBirthday(height: 425865, hash: "0011c4de26004e564347b8af218ca16cd07b08c4159b1cc9c43afa6cb8807bed", time: 1551215770, tree: "01881e4da7e4767ee8a144a32ab8a5719a513bb05854477773bb55e6cd7f15055201f8a99a3a5ae3528ec2fc0bda9652b6728aecb08bf364e06ac511fd6654d782720f019ef0b9bdd075c38519fa4ab8210fe7e94c609f52672796e33e3cab58b1602831000001f803bf338ff1526b2ca527288974cb9be3fe240a2eadb7507e46ba59eaddb9320129fc0148ac088a6aa509f8f64ef79fda92232020369b58a12b32c05b6f428f22015e3dd0950c442940bd015c2176f7c817f22104f54c61159727483188c539dc13000000013589be9e2d9e9e38fd78b1e8eaec5b5f5167bf7fd2b1c95c316fa366a24cac4c01a86b141bdb55fd5f5b2e880ea4e07caf2bbf1ac7b52a9f504977913068a917270001dd960b6c11b157d1626f0768ec099af9385aea3f31c91111a8c5b899ffb99e6b0192acd61b1853311b0bf166057ca433e231c93ab5988844a09a91c113ebc58e18019fbfd76ad6d98cafa0174391546e7022afe62e870e20e16d57c4c419a5c2bb69")
case 518000:
return WalletBirthday(height: 518000, hash: "000ba586d734c295f0bc034be229b1c96cb040f9d4929efdb5d2b187eeb238fb", time: 1560645743, tree: "01a4f5240a88a6eb4ffbda7961a1430506aad1a50ba011593f02c243d968feb0550010000140f91773b4ab669846e5bcb96f60e68256c49a27872a98e9d5ce50b30a0c434e0000018968663d6a7b444591de83f8a07223113f5de7e8203807adacc7677c3bcd4f420194c7ecac0ef6d702d475680ec32051fdf6368af0c459ab450009c001bcbf7a5300000001f0eead5192c3b3ab7208429877570676647e448210332c6da7e18660b142b80e01b98b14cab05247195b3b3be3dd8639bae99a0dd10bed1282ac25b62a134afd7200000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39")
case 523240:
return WalletBirthday(height: 523240, hash: "00000c33da2196f0ed1bda71043f671fc69a0212e01f892653e212ab358f6b79", time: 1561002603, tree: "01d3e02bc1c2d66762f370b329a3063067701ad66c44b40285686bc8ff25f5616f00100154bff87bd0bda3b70a6d7754eca261de15fee3cd9bc53073a232e07fc3261e27000001a54dcaccb4c5e578aef89f2a3b4e3c3d8a487e6e904c5da5916118d721948d07000000000118fa9c6fef4963049dc7002a13bb0021d5e950591e48c9e5f2cbd1199429b80401f0eead5192c3b3ab7208429877570676647e448210332c6da7e18660b142b80e01b98b14cab05247195b3b3be3dd8639bae99a0dd10bed1282ac25b62a134afd7200000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39")
case 620000:
return WalletBirthday(height: 620000, hash: "005f97953c8e1265d6b45f4435ffa32918e53e8f0025c286a4080c3eab167197", time: 1569572035, tree: "0170cf036ea1ea3c6e08432e18b6a372ca0b8b83671cc13ab0cf9e28c182f6c36f00100000013f3fc2c16ac4780f1c472ca65534ab08911f325a9edde5ea7f24364b47c9a95300017621b12e518cbbbdb7511ab423e0bddda412ed61ed3cff5be2140de65d6a0069010576153a5a2098812e7a028c37c3398e186f398c9b07bc199784ab97e5535c3e0000019a6ce2f0f7dbb2de493a315abf62d8ca96ccc701f116b6ddfae33870a2183d3c01c9d3564eff54ebc328eab2e4f1150c3637f4f47516f879a0cfebdf49fe7b1d5201c104705fac60a85596010e41260d07f3a64f38f37a112eaef41cd9d736edc5270145e3d4899fcd7f0f1236ae31eafb3f4b65ad6b11a17eae1729cec09bd3afa01a000000011f8322ef806eb2430dc4a7a41c1b344bea5be946efc7b4349c1c9edb14ff9d39")
default:
return nil
}
}
}
{% endif %}

View File

@ -0,0 +1,114 @@
//swiftlint:disable all
import Foundation
/**
Wrapper for all the constant values in the SDK. It is important that these values stay fixed for
all users of the SDK. Otherwise, if individual wallet makers are using different values, it
becomes easier to reduce privacy by segmenting the anonymity set of users, particularly as it
relates to network requests.
*/
public class ZcashSDK {
/**
Miner's fee in zatoshi.
*/
public static let MINERS_FEE_ZATOSHI: BlockHeight = 10_000
/**
The number of zatoshi that equal 1 ZEC.
*/
public static let ZATOSHI_PER_ZEC: BlockHeight = 100_000_000
/**
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 let SAPLING_ACTIVATION_HEIGHT: BlockHeight = {{ argument.saplingActivationHeight }}
/**
The theoretical maximum number of blocks in a reorg, due to other bottlenecks in the protocol design.
*/
public static let MAX_REORG_SIZE = 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 shdould be kept in sync.
*/
public static let EXPIRY_OFFSET = 20
//
// Defaults
//
/**
Default size of batches of blocks to request from the compact block service.
*/
public static let DEFAULT_BATCH_SIZE = 100
/**
Default amount of time, in in seconds, to poll for new blocks. Typically, this should be about half the average
block time.
*/
public static let DEFAULT_POLL_INTERVAL: TimeInterval = 37.5
/**
Default attempts at retrying.
*/
public static let DEFAULT_RETRIES = 5
/**
The default maximum amount of time to wait during retry backoff intervals. Failed loops will never wait longer than
this before retyring.
*/
public static let DEFAULT_MAX_BACKOFF_INTERVAL: 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.
*/
public static let DEFAULT_REWIND_DISTANCE = 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.
*/
public static let DEFAULT_STALE_TOLERANCE = 10
/**
Default Name for LibRustZcash data.db
*/
public static let DEFAULT_DATA_DB_NAME = "data.db"
/**
Default Name for Compact Block caches db
*/
public static let DEFAULT_CACHES_DB_NAME = "caches.db"
/**
Default name for pending transactions db
*/
public static let DEFAULT_PENDING_DB_NAME = "pending.db"
public static let DEFAULT_DB_NAME_PREFIX = "{{ argument.dbprefix }}"
/**
File name for the sappling spend params
*/
public static let SPEND_PARAM_FILE_NAME = "sapling-spend.params"
/**
File name for the sapling output params
*/
public static let OUTPUT_PARAM_FILE_NAME = "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.
*/
public static let CLOUD_PARAM_DIR_URL = "https://z.cash/downloads/"
public static let isMainnet = {{ argument.ismainnet }}
}

View File

@ -405,7 +405,7 @@ public class SDKSynchronizer: Synchronizer {
private func removeConfirmedTransactions() throws {
let latestHeight = try transactionRepository.lastScannedHeight()
try transactionManager.allPendingTransactions()?.filter( { abs($0.minedHeight - latestHeight) >= DEFAULT_REWIND_DISTANCE } ).forEach( { try transactionManager.delete(pendingTransaction: $0) } )
try transactionManager.allPendingTransactions()?.filter( { abs($0.minedHeight - latestHeight) >= ZcashSDK.DEFAULT_REWIND_DISTANCE } ).forEach( { try transactionManager.delete(pendingTransaction: $0) } )
}
private func refreshPendingTransactions() {

View File

@ -1,4 +0,0 @@
module Zcashlc [system][extern_c] {
header "zcashlc.h"
export *
}

View File

@ -32,8 +32,8 @@ class BlockDownloaderTests: XCTestCase {
let expect = XCTestExpectation(description: self.description)
expect.expectedFulfillmentCount = 3
let lowerRange: BlockHeight = SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = SAPLING_ACTIVATION_HEIGHT + 99
let lowerRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 99
let range = CompactBlockRange(uncheckedBounds: (lowerRange,upperRange))
downloader.downloadBlockRange(range) { (error) in
@ -58,8 +58,8 @@ class BlockDownloaderTests: XCTestCase {
func testSmallDownload() {
let lowerRange: BlockHeight = SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = SAPLING_ACTIVATION_HEIGHT + 99
let lowerRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 99
let range = CompactBlockRange(uncheckedBounds: (lowerRange,upperRange))
var latest: BlockHeight = 0
@ -90,8 +90,8 @@ class BlockDownloaderTests: XCTestCase {
let expect = XCTestExpectation(description: self.description)
expect.expectedFulfillmentCount = 1
let lowerRange: BlockHeight = SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = SAPLING_ACTIVATION_HEIGHT + 99
let lowerRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 99
let range = CompactBlockRange(uncheckedBounds: (lowerRange,upperRange))

View File

@ -47,7 +47,7 @@ class BlockScanOperationTests: XCTestCase {
let latestScannedBlockExpect = XCTestExpectation(description: self.description + "latestScannedHeight")
let service = LightWalletGRPCService(channel: ChannelProvider().channel())
let blockCount = 100
let range = SAPLING_ACTIVATION_HEIGHT ..< SAPLING_ACTIVATION_HEIGHT + blockCount
let range = ZcashSDK.SAPLING_ACTIVATION_HEIGHT ..< ZcashSDK.SAPLING_ACTIVATION_HEIGHT + blockCount
let downloadOperation = CompactBlockDownloadOperation(downloader: CompactBlockDownloader.sqlDownloader(service: service, at: cacheDbURL)!, range: range)
let scanOperation = CompactBlockScanningOperation(rustWelding: rustWelding, cacheDb: cacheDbURL, dataDb: dataDbURL)

View File

@ -69,8 +69,8 @@ class CompactBlockReorgTests: XCTestCase {
XCTAssertNotNil(notification.userInfo)
if let reorg = notification.userInfo?[CompactBlockProcessorNotificationKey.reorgHeight] as? BlockHeight,
let rewind = notification.userInfo?[CompactBlockProcessorNotificationKey.rewindHeight] as? BlockHeight {
XCTAssertTrue( reorg == 0 || reorg > SAPLING_ACTIVATION_HEIGHT)
XCTAssertTrue( rewind == 0 || rewind > SAPLING_ACTIVATION_HEIGHT)
XCTAssertTrue( reorg == 0 || reorg > ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
XCTAssertTrue( rewind == 0 || rewind > ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
XCTAssertTrue( rewind <= reorg )
} else {
XCTFail("CompactBlockProcessor reorg notification is malformed")

View File

@ -19,7 +19,7 @@ class CompactBlockStorageTests: XCTestCase {
func testStoreThousandBlocks() {
let initialHeight = try! compactBlockDao.latestHeight()
let startHeight = SAPLING_ACTIVATION_HEIGHT
let startHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
let blockCount = Int(1_000)
let finalHeight = startHeight + blockCount
@ -62,7 +62,7 @@ class CompactBlockStorageTests: XCTestCase {
func testRewindTo() {
let startHeight = SAPLING_ACTIVATION_HEIGHT
let startHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
let blockCount = Int(1_000)
let finalHeight = startHeight + blockCount

View File

@ -25,7 +25,7 @@ class DownloadOperationTests: XCTestCase {
let storage = try! TestDbBuilder.inMemoryCompactBlockStorage()
let downloader = CompactBlockDownloader(service: service, storage: storage)
let blockCount = 100
let range = SAPLING_ACTIVATION_HEIGHT ..< SAPLING_ACTIVATION_HEIGHT + blockCount
let range = ZcashSDK.SAPLING_ACTIVATION_HEIGHT ..< ZcashSDK.SAPLING_ACTIVATION_HEIGHT + blockCount
let downloadOperation = CompactBlockDownloadOperation(downloader: downloader, range: range)
downloadOperation.completionHandler = { (finished, cancelled) in

View File

@ -41,8 +41,8 @@ class LightWalletServiceTests: XCTestCase {
func testHundredBlocks() {
let expect = XCTestExpectation(description: self.description)
let count = 99
let lowerRange: BlockHeight = SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = SAPLING_ACTIVATION_HEIGHT + count
let lowerRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + count
let blockRange = Range<BlockHeight>(uncheckedBounds: (lower: lowerRange, upper: upperRange))
service.blockRange(blockRange) { (result) in
@ -61,8 +61,8 @@ class LightWalletServiceTests: XCTestCase {
}
func testSyncBlockRange() {
let lowerRange: BlockHeight = SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = SAPLING_ACTIVATION_HEIGHT + 99
let lowerRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
let upperRange: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT + 99
let blockRange = CompactBlockRange(uncheckedBounds: (lower: lowerRange, upper: upperRange))
do {
@ -81,7 +81,7 @@ class LightWalletServiceTests: XCTestCase {
case .failure(let e):
XCTFail("error: \(e)")
case .success(let height):
XCTAssertTrue(height > SAPLING_ACTIVATION_HEIGHT)
XCTAssertTrue(height > ZcashSDK.SAPLING_ACTIVATION_HEIGHT)
}
}

View File

@ -0,0 +1,19 @@
//
// TxIdTests.swift
// ZcashLightClientKit-Unit-Tests
//
// Created by Francisco Gindre on 1/10/20.
//
import XCTest
class TxIdTests: XCTestCase {
func testTxIdAsString() {
let transactionId = "5cf915c5d01007c39d602e08ab59d98aba366e2fb7ac01f2cdad4bf4f8f300bb"
let expectedTxIdString = "bb003f8f4fb4dadc2f10ca7bf2e663aba89d95ba80e206d93c70010d5c519fc5"
XCTAssertEqual(transactionId.hexDecodedData().toHexStringTxId(), expectedTxIdString)
}
}

View File

@ -33,7 +33,7 @@ class WalletTests: XCTestCase {
let wallet = Initializer(cacheDbURL: cacheData, dataDbURL: dbData, pendingDbURL: try! TestDbBuilder.pendingTransactionsDbURL(), endpoint: LightWalletEndpointBuilder.default, spendParamsURL: try! __spendParamsURL(), outputParamsURL: try! __outputParamsURL())
XCTAssertNoThrow(try wallet.initialize(seedProvider: SampleSeedProvider(), walletBirthdayHeight: SAPLING_ACTIVATION_HEIGHT))
XCTAssertNoThrow(try wallet.initialize(seedProvider: SampleSeedProvider(), walletBirthdayHeight: ZcashSDK.SAPLING_ACTIVATION_HEIGHT))
// fileExists actually sucks, so attempting to delete the file and checking what happens is far better :)
XCTAssertNoThrow( try FileManager.default.removeItem(at: dbData!) )

View File

@ -1,5 +1,5 @@
//
// Storage.swift
// FakeStorage.swift
// ZcashLightClientKit
//
// Created by Francisco Gindre on 12/09/2019.

View File

@ -118,16 +118,16 @@ class MockTransactionRepository: TransactionRepository {
}
func mockSent(_ index: Int) -> ConfirmedTransactionEntity {
ConfirmedTransaction(toAddress: "some_address", expiryHeight: BlockHeight.max, minedHeight: randomBlockHeight(), noteId: index, blockTimeInSeconds: randomTimeInterval(), transactionIndex: index, raw: Data(), id: index, value: Int.random(in: 1 ... ZATOSHI_PER_ZEC), memo: nil, rawTransactionId: Data())
ConfirmedTransaction(toAddress: "some_address", expiryHeight: BlockHeight.max, minedHeight: randomBlockHeight(), noteId: index, blockTimeInSeconds: randomTimeInterval(), transactionIndex: index, raw: Data(), id: index, value: Int.random(in: 1 ... ZcashSDK.ZATOSHI_PER_ZEC), memo: nil, rawTransactionId: Data())
}
func mockReceived(_ index: Int) -> ConfirmedTransactionEntity {
ConfirmedTransaction(toAddress: nil, expiryHeight: BlockHeight.max, minedHeight: randomBlockHeight(), noteId: index, blockTimeInSeconds: randomTimeInterval(), transactionIndex: index, raw: Data(), id: index, value: Int.random(in: 1 ... ZATOSHI_PER_ZEC), memo: nil, rawTransactionId: Data())
ConfirmedTransaction(toAddress: nil, expiryHeight: BlockHeight.max, minedHeight: randomBlockHeight(), noteId: index, blockTimeInSeconds: randomTimeInterval(), transactionIndex: index, raw: Data(), id: index, value: Int.random(in: 1 ... ZcashSDK.ZATOSHI_PER_ZEC), memo: nil, rawTransactionId: Data())
}
func randomBlockHeight() -> BlockHeight {
BlockHeight.random(in: SAPLING_ACTIVATION_HEIGHT ... 1_000_000)
BlockHeight.random(in: ZcashSDK.SAPLING_ACTIVATION_HEIGHT ... 1_000_000)
}
func randomTimeInterval() -> TimeInterval {
Double.random(in: Date().timeIntervalSince1970 - 1000000.0 ... Date().timeIntervalSince1970)

View File

@ -1,22 +0,0 @@
export PATH="$HOME/.cargo/bin:$PATH"
export RUST_LIB_PATH="${PODS_TARGET_SRCROOT}/lib"
export ZCASH_LIB_RUST_PATH="${PODS_TARGET_SRCROOT}/target"
export ZCASH_LIB_RUST_NAME="libzcashlc.a"
if [ "$ACTION" = "clean" ]; then
cargo clean
if [ -d "${RUST_LIB_PATH}" ]; then
rm -rf "${RUST_LIB_PATH}"
fi
if [ -d "${ZCASH_LIB_RUST_PATH}" ]; then
rm -rf "${ZCASH_LIB_RUST_PATH}"
fi
else
cargo lipo --xcode-integ --manifest-path ${PODS_TARGET_SRCROOT}/Cargo.toml
if [ ! -d "${RUST_LIB_PATH}" ]; then
mkdir -p "${RUST_LIB_PATH}"
fi
cp -f "${ZCASH_LIB_RUST_PATH}/universal/${CONFIGURATION}/${ZCASH_LIB_RUST_NAME}" ${ZCASH_LIB_RUST_PATH}
fi

View File

@ -1,3 +0,0 @@
require 'xcodeproj'