Issue #166 Download UTXO set
This commit is contained in:
parent
7cb4750f29
commit
4abf914f9f
|
@ -824,13 +824,19 @@
|
||||||
<rect key="frame" x="20" y="88" width="374" height="774"/>
|
<rect key="frame" x="20" y="88" width="374" height="774"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="characterWrap" numberOfLines="0" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="X0E-Ba-xxX">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="characterWrap" numberOfLines="0" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="X0E-Ba-xxX">
|
||||||
<rect key="frame" x="166.5" y="0.0" width="41.5" height="387"/>
|
<rect key="frame" x="166.5" y="0.0" width="41.5" height="258"/>
|
||||||
|
<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="Label" textAlignment="center" lineBreakMode="characterWrap" numberOfLines="0" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ntO-Ig-rst">
|
||||||
|
<rect key="frame" x="166.5" y="258" width="41.5" height="258"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="characterWrap" numberOfLines="0" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hl0-9u-TsZ" userLabel="extended key">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="characterWrap" numberOfLines="0" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="hl0-9u-TsZ" userLabel="extended key">
|
||||||
<rect key="frame" x="0.0" y="387" width="374" height="387"/>
|
<rect key="frame" x="0.0" y="516" width="374" height="258"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
|
@ -853,8 +859,9 @@
|
||||||
</view>
|
</view>
|
||||||
<navigationItem key="navigationItem" title="Get Address" largeTitleDisplayMode="always" id="Uvy-EM-bSo"/>
|
<navigationItem key="navigationItem" title="Get Address" largeTitleDisplayMode="always" id="Uvy-EM-bSo"/>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="addressLabel" destination="X0E-Ba-xxX" id="9es-sw-gO5"/>
|
|
||||||
<outlet property="spendingKeyLabel" destination="hl0-9u-TsZ" id="afF-Yq-bty"/>
|
<outlet property="spendingKeyLabel" destination="hl0-9u-TsZ" id="afF-Yq-bty"/>
|
||||||
|
<outlet property="tAddressLabel" destination="ntO-Ig-rst" id="6ER-bQ-FVH"/>
|
||||||
|
<outlet property="zAddressLabel" destination="X0E-Ba-xxX" id="9es-sw-gO5"/>
|
||||||
</connections>
|
</connections>
|
||||||
</viewController>
|
</viewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="kr1-B6-akA" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="kr1-B6-akA" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
|
||||||
|
@ -955,16 +962,16 @@
|
||||||
</constraints>
|
</constraints>
|
||||||
</view>
|
</view>
|
||||||
<stackView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="246" verticalCompressionResistancePriority="250" alignment="center" spacing="13" translatesAutoresizingMaskIntoConstraints="NO" id="IIl-kO-2M8">
|
<stackView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="246" verticalCompressionResistancePriority="250" alignment="center" spacing="13" translatesAutoresizingMaskIntoConstraints="NO" id="IIl-kO-2M8">
|
||||||
<rect key="frame" x="0.0" y="152" width="398" height="112.5"/>
|
<rect key="frame" x="0.0" y="152" width="398" height="173"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" text="Status:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3t3-Tr-UlI">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" text="Status:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3t3-Tr-UlI">
|
||||||
<rect key="frame" x="0.0" y="37" width="95.5" height="38.5"/>
|
<rect key="frame" x="0.0" y="67.5" width="95.5" height="38.5"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="32"/>
|
<fontDescription key="fontDescription" type="system" pointSize="32"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Jj9-7r-s2Y">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Jj9-7r-s2Y">
|
||||||
<rect key="frame" x="108.5" y="42.5" width="289.5" height="27.5"/>
|
<rect key="frame" x="108.5" y="73" width="289.5" height="27.5"/>
|
||||||
<fontDescription key="fontDescription" type="italicSystem" pointSize="23"/>
|
<fontDescription key="fontDescription" type="italicSystem" pointSize="23"/>
|
||||||
<color key="textColor" systemColor="scrollViewTexturedBackgroundColor"/>
|
<color key="textColor" systemColor="scrollViewTexturedBackgroundColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
|
@ -975,22 +982,22 @@
|
||||||
</constraints>
|
</constraints>
|
||||||
</stackView>
|
</stackView>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Progress" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JPx-ol-2nc">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Progress" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JPx-ol-2nc">
|
||||||
<rect key="frame" x="0.0" y="288.5" width="390" height="43"/>
|
<rect key="frame" x="0.0" y="349" width="390" height="43"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="36"/>
|
<fontDescription key="fontDescription" type="system" pointSize="36"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" progressViewStyle="bar" progress="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="oKg-9s-8Ym">
|
<progressView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="750" progressViewStyle="bar" progress="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="oKg-9s-8Ym">
|
||||||
<rect key="frame" x="0.0" y="355.5" width="390" height="2.5"/>
|
<rect key="frame" x="0.0" y="416" width="390" height="2.5"/>
|
||||||
</progressView>
|
</progressView>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0%" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kXE-5z-HN2">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0%" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kXE-5z-HN2">
|
||||||
<rect key="frame" x="0.0" y="381" width="398" height="39.5"/>
|
<rect key="frame" x="0.0" y="441.5" width="398" height="39.5"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="33"/>
|
<fontDescription key="fontDescription" type="system" pointSize="33"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="G5M-gm-1ux">
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="G5M-gm-1ux">
|
||||||
<rect key="frame" x="0.0" y="444.5" width="398" height="45"/>
|
<rect key="frame" x="0.0" y="505" width="398" height="45"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="27"/>
|
<fontDescription key="fontDescription" type="system" pointSize="27"/>
|
||||||
<state key="normal" title="Start"/>
|
<state key="normal" title="Start"/>
|
||||||
<connections>
|
<connections>
|
||||||
|
@ -998,7 +1005,7 @@
|
||||||
</connections>
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
<view contentMode="scaleToFill" verticalHuggingPriority="750" verticalCompressionResistancePriority="737" translatesAutoresizingMaskIntoConstraints="NO" id="fB9-xh-4fl" userLabel="Trailing View">
|
<view contentMode="scaleToFill" verticalHuggingPriority="750" verticalCompressionResistancePriority="737" translatesAutoresizingMaskIntoConstraints="NO" id="fB9-xh-4fl" userLabel="Trailing View">
|
||||||
<rect key="frame" x="0.0" y="513.5" width="398" height="260.5"/>
|
<rect key="frame" x="0.0" y="574" width="398" height="200"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="height" relation="greaterThanOrEqual" priority="750" constant="200" id="Bpt-XM-IZA"/>
|
<constraint firstAttribute="height" relation="greaterThanOrEqual" priority="750" constant="200" id="Bpt-XM-IZA"/>
|
||||||
|
@ -1406,25 +1413,41 @@
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1h3-3y-iS9">
|
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="ZXk-2m-Kua">
|
||||||
<rect key="frame" x="131.5" y="225.5" width="151" height="50"/>
|
<rect key="frame" x="65.5" y="225.5" width="283" height="100"/>
|
||||||
<constraints>
|
<subviews>
|
||||||
<constraint firstAttribute="height" constant="50" id="v9k-94-gxX"/>
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1h3-3y-iS9">
|
||||||
</constraints>
|
<rect key="frame" x="0.0" y="0.0" width="283" height="50"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="29"/>
|
<constraints>
|
||||||
<state key="normal" title="Get UTXOs!"/>
|
<constraint firstAttribute="height" constant="50" id="v9k-94-gxX"/>
|
||||||
<connections>
|
</constraints>
|
||||||
<action selector="getButtonTapped:" destination="Ugl-B2-O3O" eventType="touchUpInside" id="Vlr-m4-asM"/>
|
<fontDescription key="fontDescription" type="system" pointSize="29"/>
|
||||||
</connections>
|
<state key="normal" title="Get UTXOs!"/>
|
||||||
</button>
|
<connections>
|
||||||
|
<action selector="getButtonTapped:" destination="Ugl-B2-O3O" eventType="touchUpInside" id="Vlr-m4-asM"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="tX1-H6-Zs8">
|
||||||
|
<rect key="frame" x="0.0" y="50" width="283" height="50"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="50" id="JJc-9O-Kdl"/>
|
||||||
|
</constraints>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="29"/>
|
||||||
|
<state key="normal" title="Get UTXO from cache!"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="getFromCacheTapped:" destination="Ugl-B2-O3O" eventType="touchUpInside" id="3Pl-RP-4qg"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
</subviews>
|
||||||
|
</stackView>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Mv9-ye-VIn">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Mv9-ye-VIn">
|
||||||
<rect key="frame" x="16" y="315.5" width="382" height="0.0"/>
|
<rect key="frame" x="16" y="365.5" width="382" height="0.0"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pcE-rS-DWU">
|
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pcE-rS-DWU">
|
||||||
<rect key="frame" x="0.0" y="355.5" width="414" height="418.5"/>
|
<rect key="frame" x="0.0" y="405.5" width="414" height="368.5"/>
|
||||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||||
</view>
|
</view>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
@ -1452,6 +1475,7 @@
|
||||||
<navigationItem key="navigationItem" id="VUG-Af-cu9"/>
|
<navigationItem key="navigationItem" id="VUG-Af-cu9"/>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="getButton" destination="1h3-3y-iS9" id="pdY-q5-oIL"/>
|
<outlet property="getButton" destination="1h3-3y-iS9" id="pdY-q5-oIL"/>
|
||||||
|
<outlet property="getFromCache" destination="tX1-H6-Zs8" id="FQS-Hl-Hl9"/>
|
||||||
<outlet property="messageLabel" destination="Mv9-ye-VIn" id="c6d-Fe-mrx"/>
|
<outlet property="messageLabel" destination="Mv9-ye-VIn" id="c6d-Fe-mrx"/>
|
||||||
<outlet property="tAddressField" destination="9yg-Sp-H2E" id="oQV-JY-09h"/>
|
<outlet property="tAddressField" destination="9yg-Sp-H2E" id="oQV-JY-09h"/>
|
||||||
<outlet property="validAddressLabel" destination="1NQ-co-Y8P" id="mHT-cp-vnn"/>
|
<outlet property="validAddressLabel" destination="1NQ-co-Y8P" id="mHT-cp-vnn"/>
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
import ZcashLightClientKit
|
import ZcashLightClientKit
|
||||||
class GetAddressViewController: UIViewController {
|
class GetAddressViewController: UIViewController {
|
||||||
@IBOutlet weak var addressLabel: UILabel!
|
@IBOutlet weak var zAddressLabel: UILabel!
|
||||||
|
@IBOutlet weak var tAddressLabel: UILabel!
|
||||||
@IBOutlet weak var spendingKeyLabel: UILabel! // THIS SHOULD BE SUPER SECRET!!!!!
|
@IBOutlet weak var spendingKeyLabel: UILabel! // THIS SHOULD BE SUPER SECRET!!!!!
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
|
@ -17,11 +18,14 @@ class GetAddressViewController: UIViewController {
|
||||||
|
|
||||||
// Do any additional setup after loading the view.
|
// Do any additional setup after loading the view.
|
||||||
|
|
||||||
addressLabel.text = legibleAddresses() ?? "No Addresses found"
|
zAddressLabel.text = (try? DerivationTool.default.deriveShieldedAddress(seed: DemoAppConfig.seed, accountIndex: 0)) ?? "No Addresses found"
|
||||||
|
tAddressLabel.text = (try? DerivationTool.default.deriveTransparentAddress(seed: DemoAppConfig.seed)) ?? "could not derive t-address"
|
||||||
spendingKeyLabel.text = SampleStorage.shared.privateKey ?? "No Spending Key found"
|
spendingKeyLabel.text = SampleStorage.shared.privateKey ?? "No Spending Key found"
|
||||||
addressLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(addressTapped(_:))))
|
zAddressLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(addressTapped(_:))))
|
||||||
addressLabel.isUserInteractionEnabled = true
|
zAddressLabel.isUserInteractionEnabled = true
|
||||||
|
|
||||||
|
tAddressLabel.isUserInteractionEnabled = true
|
||||||
|
tAddressLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tAddressTapped(_:))))
|
||||||
spendingKeyLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(spendingKeyTapped(_:))))
|
spendingKeyLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(spendingKeyTapped(_:))))
|
||||||
spendingKeyLabel.isUserInteractionEnabled = true
|
spendingKeyLabel.isUserInteractionEnabled = true
|
||||||
loggerProxy.info("Address: \(String(describing: Initializer.shared.getAddress()))")
|
loggerProxy.info("Address: \(String(describing: Initializer.shared.getAddress()))")
|
||||||
|
@ -40,10 +44,6 @@ class GetAddressViewController: UIViewController {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func legibleAddresses() -> String? {
|
|
||||||
Initializer.shared.getAddress()
|
|
||||||
}
|
|
||||||
|
|
||||||
@IBAction func spendingKeyTapped(_ gesture: UIGestureRecognizer) {
|
@IBAction func spendingKeyTapped(_ gesture: UIGestureRecognizer) {
|
||||||
guard let key = SampleStorage.shared.privateKey else {
|
guard let key = SampleStorage.shared.privateKey else {
|
||||||
loggerProxy.warn("nothing to copy")
|
loggerProxy.warn("nothing to copy")
|
||||||
|
@ -60,7 +60,15 @@ class GetAddressViewController: UIViewController {
|
||||||
|
|
||||||
@IBAction func addressTapped(_ gesture: UIGestureRecognizer) {
|
@IBAction func addressTapped(_ gesture: UIGestureRecognizer) {
|
||||||
loggerProxy.event("copied to clipboard")
|
loggerProxy.event("copied to clipboard")
|
||||||
UIPasteboard.general.string = legibleAddresses()
|
UIPasteboard.general.string = try? DerivationTool.default.deriveShieldedAddress(seed: DemoAppConfig.seed, accountIndex: 0)
|
||||||
|
let alert = UIAlertController(title: "", message: "Address 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
@IBAction func tAddressTapped(_ gesture: UIGestureRecognizer) {
|
||||||
|
loggerProxy.event("copied to clipboard")
|
||||||
|
UIPasteboard.general.string = try? DerivationTool.default.deriveTransparentAddress(seed: DemoAppConfig.seed)
|
||||||
let alert = UIAlertController(title: "", message: "Address Copied to clipboard", preferredStyle: UIAlertController.Style.alert)
|
let alert = UIAlertController(title: "", message: "Address Copied to clipboard", preferredStyle: UIAlertController.Style.alert)
|
||||||
alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
|
alert.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
|
||||||
self.present(alert, animated: true, completion: nil)
|
self.present(alert, animated: true, completion: nil)
|
||||||
|
|
|
@ -12,10 +12,10 @@ import KRProgressHUD
|
||||||
class GetUTXOsViewController: UIViewController {
|
class GetUTXOsViewController: UIViewController {
|
||||||
@IBOutlet weak var tAddressField: UITextField!
|
@IBOutlet weak var tAddressField: UITextField!
|
||||||
@IBOutlet weak var getButton: UIButton!
|
@IBOutlet weak var getButton: UIButton!
|
||||||
|
@IBOutlet weak var getFromCache: UIButton!
|
||||||
@IBOutlet weak var validAddressLabel: UILabel!
|
@IBOutlet weak var validAddressLabel: UILabel!
|
||||||
@IBOutlet weak var messageLabel: UILabel!
|
@IBOutlet weak var messageLabel: UILabel!
|
||||||
|
|
||||||
var service: LightWalletGRPCService = LightWalletGRPCService(endpoint: DemoAppConfig.endpoint)
|
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
@ -31,15 +31,17 @@ class GetUTXOsViewController: UIViewController {
|
||||||
self.validAddressLabel.textColor = valid ? UIColor.systemGreen : UIColor.systemRed
|
self.validAddressLabel.textColor = valid ? UIColor.systemGreen : UIColor.systemRed
|
||||||
|
|
||||||
self.getButton.isEnabled = valid
|
self.getButton.isEnabled = valid
|
||||||
|
self.getFromCache.isEnabled = valid
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func getButtonTapped(_ sender: Any) {
|
@IBAction func getButtonTapped(_ sender: Any) {
|
||||||
guard Initializer.shared.isValidTransparentAddress(tAddressField.text ?? ""),
|
guard Initializer.shared.isValidTransparentAddress(tAddressField.text ?? ""),
|
||||||
let tAddr = tAddressField.text else {
|
let tAddr = tAddressField.text else {
|
||||||
|
self.messageLabel.text = "Invalid t-Address"
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
KRProgressHUD.showMessage("fetching")
|
KRProgressHUD.showMessage("fetching")
|
||||||
service.fetchUTXOs(for: tAddr) { [weak self] (result) in
|
AppDelegate.shared.sharedSynchronizer.latestUTXOs(address: tAddr) { (result) in
|
||||||
DispatchQueue.main.async { [weak self] in
|
DispatchQueue.main.async { [weak self] in
|
||||||
KRProgressHUD.dismiss()
|
KRProgressHUD.dismiss()
|
||||||
switch result {
|
switch result {
|
||||||
|
@ -53,6 +55,21 @@ class GetUTXOsViewController: UIViewController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@IBAction func getFromCacheTapped(_ sender: Any) {
|
||||||
|
guard Initializer.shared.isValidTransparentAddress(tAddressField.text ?? ""),
|
||||||
|
let tAddr = tAddressField.text else {
|
||||||
|
self.messageLabel.text = "Invalid t-Address"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
let utxos = try AppDelegate.shared.sharedSynchronizer.cachedUTXOs(address: tAddr)
|
||||||
|
self.messageLabel.text = "found \(utxos.count) UTXOs for address \(tAddr) on cache"
|
||||||
|
} catch {
|
||||||
|
self.messageLabel.text = "Error \(error)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@IBAction func viewTapped(_ recognizer: UITapGestureRecognizer) {
|
@IBAction func viewTapped(_ recognizer: UITapGestureRecognizer) {
|
||||||
self.tAddressField.resignFirstResponder()
|
self.tAddressField.resignFirstResponder()
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,4 +15,5 @@ enum StorageError: Error {
|
||||||
case operationFailed
|
case operationFailed
|
||||||
case updateFailed
|
case updateFailed
|
||||||
case malformedEntity(fields: [String]?)
|
case malformedEntity(fields: [String]?)
|
||||||
|
case transactionFailed(underlyingError: Error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
//
|
|
||||||
// UnspentTransactionOutputDAO.swift
|
|
||||||
// ZcashLightClientKit
|
|
||||||
//
|
|
||||||
// Created by Francisco Gindre on 12/9/20.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
|
|
||||||
struct UTXO: UnspentTransactionOutputEntity {
|
|
||||||
var address: String
|
|
||||||
|
|
||||||
var txid: Data
|
|
||||||
|
|
||||||
var index: Int32
|
|
||||||
|
|
||||||
var script: Data
|
|
||||||
|
|
||||||
var valueZat: Int64
|
|
||||||
|
|
||||||
var height: UInt64
|
|
||||||
}
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
//
|
||||||
|
// UnspentTransactionOutputDAO.swift
|
||||||
|
// ZcashLightClientKit
|
||||||
|
//
|
||||||
|
// Created by Francisco Gindre on 12/9/20.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct UTXO: UnspentTransactionOutputEntity, Decodable, Encodable {
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case id
|
||||||
|
case address
|
||||||
|
case txid
|
||||||
|
case index
|
||||||
|
case script
|
||||||
|
case valueZat = "value_zat"
|
||||||
|
case height
|
||||||
|
}
|
||||||
|
|
||||||
|
var id: Int?
|
||||||
|
|
||||||
|
var address: String
|
||||||
|
|
||||||
|
var txid: Data
|
||||||
|
|
||||||
|
var index: Int
|
||||||
|
|
||||||
|
var script: Data
|
||||||
|
|
||||||
|
var valueZat: Int
|
||||||
|
|
||||||
|
var height: Int
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
import SQLite
|
||||||
|
class UnspentTransactionOutputSQLDAO: UnspentTransactionOutputRepository {
|
||||||
|
|
||||||
|
func store(utxos: [UnspentTransactionOutputEntity]) throws {
|
||||||
|
do {
|
||||||
|
|
||||||
|
let db = try dbProvider.connection()
|
||||||
|
try dbProvider.connection().transaction {
|
||||||
|
for utxo in utxos.map({ (u) -> UTXO in
|
||||||
|
u as? UTXO ?? UTXO(id: nil,
|
||||||
|
address: u.address,
|
||||||
|
txid: u.txid,
|
||||||
|
index: Int(u.index),
|
||||||
|
script: u.script,
|
||||||
|
valueZat: u.valueZat,
|
||||||
|
height: u.height)
|
||||||
|
}) {
|
||||||
|
try db.run(table.insert(utxo))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
throw StorageError.transactionFailed(underlyingError: error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func clearAll(address: String?) throws {
|
||||||
|
|
||||||
|
if let tAddr = address {
|
||||||
|
do {
|
||||||
|
try dbProvider.connection().run(table.filter(TableColumns.address == tAddr).delete())
|
||||||
|
} catch {
|
||||||
|
throw StorageError.operationFailed
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
try dbProvider.connection().run(table.delete())
|
||||||
|
} catch {
|
||||||
|
throw StorageError.operationFailed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let table = Table("utxos")
|
||||||
|
|
||||||
|
struct TableColumns {
|
||||||
|
static var id = Expression<Int>("id")
|
||||||
|
static var address = Expression<String>("address")
|
||||||
|
static var txid = Expression<Blob>("txid")
|
||||||
|
static var index = Expression<Int>("index")
|
||||||
|
static var script = Expression<Blob>("script")
|
||||||
|
static var valueZat = Expression<Int>("value_zat")
|
||||||
|
static var height = Expression<Int>("height")
|
||||||
|
}
|
||||||
|
|
||||||
|
var dbProvider: ConnectionProvider
|
||||||
|
|
||||||
|
init (dbProvider: ConnectionProvider) {
|
||||||
|
self.dbProvider = dbProvider
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTableIfNeeded() throws {
|
||||||
|
let statement = table.create(ifNotExists: true) { t in
|
||||||
|
t.column(TableColumns.id, primaryKey: .autoincrement)
|
||||||
|
t.column(TableColumns.address)
|
||||||
|
t.column(TableColumns.txid)
|
||||||
|
t.column(TableColumns.index)
|
||||||
|
t.column(TableColumns.script)
|
||||||
|
t.column(TableColumns.valueZat)
|
||||||
|
t.column(TableColumns.height)
|
||||||
|
}
|
||||||
|
try dbProvider.connection().run(statement)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAll(address: String?) throws -> [UnspentTransactionOutputEntity] {
|
||||||
|
if let tAddress = address {
|
||||||
|
let allTxs: [UTXO] = try dbProvider.connection().prepare(table.filter(TableColumns.address == tAddress)).map({ row in
|
||||||
|
try row.decode()
|
||||||
|
})
|
||||||
|
return allTxs
|
||||||
|
} else {
|
||||||
|
let allTxs: [UTXO] = try dbProvider.connection().prepare(table).map({ row in
|
||||||
|
try row.decode()
|
||||||
|
})
|
||||||
|
return allTxs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UTXORepositoryBuilder {
|
||||||
|
static func build(initializer: Initializer) throws -> UnspentTransactionOutputRepository {
|
||||||
|
let dao = UnspentTransactionOutputSQLDAO(dbProvider: SimpleConnectionProvider(path: initializer.pendingDbURL.path))
|
||||||
|
try dao.createTableIfNeeded()
|
||||||
|
return dao
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,14 +11,14 @@ public protocol UnspentTransactionOutputEntity {
|
||||||
|
|
||||||
var address: String { get set }
|
var address: String { get set }
|
||||||
|
|
||||||
var txid: Data {get set}
|
var txid: Data { get set }
|
||||||
|
|
||||||
var index: Int32 {get set}
|
var index: Int { get set }
|
||||||
|
|
||||||
var script: Data {get set}
|
var script: Data { get set }
|
||||||
|
|
||||||
var valueZat: Int64 {get set}
|
var valueZat: Int { get set }
|
||||||
|
|
||||||
var height: UInt64 {get set}
|
var height: Int { get set }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
//
|
||||||
|
// UnspentTransactionOutputRepository.swift
|
||||||
|
// ZcashLightClientKit
|
||||||
|
//
|
||||||
|
// Created by Francisco Gindre on 12/11/20.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
protocol UnspentTransactionOutputRepository {
|
||||||
|
|
||||||
|
func getAll(address: String?) throws -> [UnspentTransactionOutputEntity]
|
||||||
|
|
||||||
|
func store(utxos: [UnspentTransactionOutputEntity]) throws
|
||||||
|
|
||||||
|
func clearAll(address: String?) throws
|
||||||
|
}
|
|
@ -227,12 +227,13 @@ extension LightWalletGRPCService: LightWalletService {
|
||||||
var utxos = [UnspentTransactionOutputEntity]()
|
var utxos = [UnspentTransactionOutputEntity]()
|
||||||
let response = self.compactTxStreamer.getAddressUtxosStream(arg) { (reply) in
|
let response = self.compactTxStreamer.getAddressUtxosStream(arg) { (reply) in
|
||||||
utxos.append(
|
utxos.append(
|
||||||
UTXO(address: tAddress,
|
UTXO(id: nil,
|
||||||
|
address: tAddress,
|
||||||
txid: reply.txid,
|
txid: reply.txid,
|
||||||
index: reply.index,
|
index: Int(reply.index),
|
||||||
script: reply.script,
|
script: reply.script,
|
||||||
valueZat: reply.valueZat,
|
valueZat: Int(reply.valueZat),
|
||||||
height: UInt64(reply.valueZat)
|
height: Int(reply.valueZat)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,6 +169,5 @@ public protocol LightWalletService {
|
||||||
*/
|
*/
|
||||||
func fetchTransaction(txId: Data, result: @escaping (Result<TransactionEntity,LightWalletServiceError>) -> Void)
|
func fetchTransaction(txId: Data, result: @escaping (Result<TransactionEntity,LightWalletServiceError>) -> Void)
|
||||||
|
|
||||||
|
|
||||||
func fetchUTXOs(for tAddress: String, result: @escaping(Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void)
|
func fetchUTXOs(for tAddress: String, result: @escaping(Result<[UnspentTransactionOutputEntity], LightWalletServiceError>) -> Void)
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,6 +130,17 @@ public protocol Synchronizer {
|
||||||
Blocking
|
Blocking
|
||||||
*/
|
*/
|
||||||
func latestHeight() throws -> BlockHeight
|
func latestHeight() throws -> BlockHeight
|
||||||
|
|
||||||
|
/**
|
||||||
|
Gets the latest UTXOs for the given t-address and caches the result
|
||||||
|
*/
|
||||||
|
func latestUTXOs(address: String, result: @escaping (Result<[UnspentTransactionOutputEntity], Error>) -> Void)
|
||||||
|
|
||||||
|
/**
|
||||||
|
gets the latest cached UTXOs for the given t-address for the given address
|
||||||
|
*/
|
||||||
|
func cachedUTXOs(address: String) throws -> [UnspentTransactionOutputEntity]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -90,6 +90,7 @@ public class SDKSynchronizer: Synchronizer {
|
||||||
|
|
||||||
private var transactionManager: OutboundTransactionManager
|
private var transactionManager: OutboundTransactionManager
|
||||||
private var transactionRepository: TransactionRepository
|
private var transactionRepository: TransactionRepository
|
||||||
|
private var utxoRepository: UnspentTransactionOutputRepository
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Creates an SDKSynchronizer instance
|
Creates an SDKSynchronizer instance
|
||||||
|
@ -100,18 +101,21 @@ public class SDKSynchronizer: Synchronizer {
|
||||||
self.init(status: .disconnected,
|
self.init(status: .disconnected,
|
||||||
initializer: initializer,
|
initializer: initializer,
|
||||||
transactionManager: try OutboundTransactionManagerBuilder.build(initializer: initializer),
|
transactionManager: try OutboundTransactionManagerBuilder.build(initializer: initializer),
|
||||||
transactionRepository: initializer.transactionRepository)
|
transactionRepository: initializer.transactionRepository,
|
||||||
|
utxoRepository: try UTXORepositoryBuilder.build(initializer: initializer))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init(status: Status,
|
init(status: Status,
|
||||||
initializer: Initializer,
|
initializer: Initializer,
|
||||||
transactionManager: OutboundTransactionManager,
|
transactionManager: OutboundTransactionManager,
|
||||||
transactionRepository: TransactionRepository) {
|
transactionRepository: TransactionRepository,
|
||||||
|
utxoRepository: UnspentTransactionOutputRepository) {
|
||||||
self.status = status
|
self.status = status
|
||||||
self.initializer = initializer
|
self.initializer = initializer
|
||||||
self.transactionManager = transactionManager
|
self.transactionManager = transactionManager
|
||||||
self.transactionRepository = transactionRepository
|
self.transactionRepository = transactionRepository
|
||||||
|
self.utxoRepository = utxoRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
@ -415,6 +419,33 @@ public class SDKSynchronizer: Synchronizer {
|
||||||
try initializer.downloader.latestBlockHeight()
|
try initializer.downloader.latestBlockHeight()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func latestUTXOs(address: String, result: @escaping (Result<[UnspentTransactionOutputEntity], Error>) -> Void) {
|
||||||
|
guard initializer.isValidTransparentAddress(address) else {
|
||||||
|
result(.failure(SynchronizerError.generalError(message: "invalid t-address")))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
initializer.lightWalletService.fetchUTXOs(for: address, result: { [weak self] r in
|
||||||
|
guard let self = self else { return }
|
||||||
|
switch r {
|
||||||
|
case .success(let utxos):
|
||||||
|
do {
|
||||||
|
try self.utxoRepository.clearAll(address: address)
|
||||||
|
try self.utxoRepository.store(utxos: utxos)
|
||||||
|
result(.success(utxos))
|
||||||
|
} catch {
|
||||||
|
result(.failure(SynchronizerError.generalError(message: "\(error)")))
|
||||||
|
}
|
||||||
|
case .failure(let error):
|
||||||
|
result(.failure(SynchronizerError.connectionFailed(message: error)))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
public func cachedUTXOs(address: String) throws -> [UnspentTransactionOutputEntity] {
|
||||||
|
try utxoRepository.getAll(address: address)
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: notify state
|
// MARK: notify state
|
||||||
private func notify(progress: Float, height: BlockHeight) {
|
private func notify(progress: Float, height: BlockHeight) {
|
||||||
NotificationCenter.default.post(name: Notification.Name.synchronizerProgressUpdated, object: self, userInfo: [
|
NotificationCenter.default.post(name: Notification.Name.synchronizerProgressUpdated, object: self, userInfo: [
|
||||||
|
|
Loading…
Reference in New Issue