Skip to content

Commit

Permalink
feat: add ur:crypto-output for wallet export qr
Browse files Browse the repository at this point in the history
chore: prep for dmg
  • Loading branch information
Fonta1n3 committed Nov 4, 2021
1 parent c5e5578 commit 166987f
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 59 deletions.
8 changes: 4 additions & 4 deletions FullyNoded.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1506,7 +1506,7 @@
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 338;
CURRENT_PROJECT_VERSION = 339;
DEVELOPMENT_TEAM = 8JHDU5M9KD;
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = YES;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
Expand All @@ -1517,7 +1517,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.418;
MARKETING_VERSION = 1.419;
PRODUCT_BUNDLE_IDENTIFIER = com.fontaine.FullyNoded;
"PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*]" = com.fontaine.fullynodedmacos;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -1542,7 +1542,7 @@
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 338;
CURRENT_PROJECT_VERSION = 339;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 8JHDU5M9KD;
"ENABLE_HARDENED_RUNTIME[sdk=macosx*]" = YES;
Expand All @@ -1555,7 +1555,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.418;
MARKETING_VERSION = 1.419;
PRODUCT_BUNDLE_IDENTIFIER = com.fontaine.FullyNoded;
"PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*]" = com.fontaine.fullynodedmacos;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down
28 changes: 15 additions & 13 deletions FullyNoded/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
Expand Up @@ -3605,7 +3605,7 @@ xxxxx</string>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="natural" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="d1Y-lU-km0">
<rect key="frame" x="0.0" y="55" width="343" height="43"/>
<string key="text">Creates a brand new single signature wallet. Your node holds the public keys, Fully Noded holds the private keys encrypted on your device.</string>
<string key="text">Creates a new single signature wallet. Your node holds the public keys, Fully Noded holds the private keys encrypted on your device.</string>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
Expand All @@ -3625,19 +3625,21 @@ xxxxx</string>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="natural" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ti9-Jn-c8c">
<rect key="frame" x="0.0" y="164" width="343" height="43"/>
<string key="text">Allows you to add cosigners by scanning QR's, pasting text from other wallets or by deriving cosigners from existing signers stored on Fully Noded.</string>
<string key="text">Add cosigners by scanning QR's, pasting text from other wallets or by deriving cosigners from existing signers stored on Fully Noded.</string>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="natural" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="47C-HD-wcH">
<rect key="frame" x="16" y="364" width="343" height="107"/>
<constraints>
<constraint firstAttribute="height" constant="107" id="nNQ-1S-X4D"/>
</constraints>
<string key="text">Already have a wallet or cosigner? Use the buttons in the top right to import whatever you've got. From left to right: paste text, upload file and scan QR. Fully Noded does its best to support as many hardware and software wallets as possible.</string>
<rect key="frame" x="16" y="364" width="343" height="167.5"/>
<string key="text">Already have a wallet or cosigner?

Use the buttons in the top right to import whatever you've got. 

From left to right: paste text, upload file and scan QR.

Fully Noded does its best to support as many hardware and software wallet options as possible.</string>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
Expand Down Expand Up @@ -4817,7 +4819,7 @@ You can upload the wallets.fullynoded file that was created when you made the ba
</objects>
<point key="canvasLocation" x="2718" y="376"/>
</scene>
<!--v0.2.28-->
<!--v0.2.29-->
<scene sceneID="Ajv-p7-tUm">
<objects>
<viewController extendedLayoutIncludesOpaqueBars="YES" id="AS8-ke-Yxh" customClass="SettingsViewController" customModule="FullyNoded" customModuleProvider="target" sceneMemberID="viewController">
Expand Down Expand Up @@ -5058,7 +5060,7 @@ You can upload the wallets.fullynoded file that was created when you made the ba
</constraints>
</view>
<tabBarItem key="tabBarItem" title="" image="Settings" id="n34-O3-Fyo"/>
<navigationItem key="navigationItem" title="v0.2.28" id="YNb-Gd-Hqq"/>
<navigationItem key="navigationItem" title="v0.2.29" id="YNb-Gd-Hqq"/>
<connections>
<outlet property="settingsTable" destination="hcp-eG-lok" id="xPg-8r-KBs"/>
<segue destination="bKH-sI-MiM" kind="show" identifier="goLogIn" id="qed-hl-jG5"/>
Expand Down Expand Up @@ -5437,7 +5439,7 @@ You can upload the wallets.fullynoded file that was created when you made the ba
</connections>
</tableView>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="encryption password" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="qNH-Vh-gso">
<rect key="frame" x="16" y="201" width="282" height="34"/>
<rect key="frame" x="16" y="201" width="273" height="34"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" keyboardAppearance="alert" secureTextEntry="YES" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/>
</textField>
Expand All @@ -5452,9 +5454,9 @@ You can upload the wallets.fullynoded file that was created when you made the ba
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" showsTouchWhenHighlighted="YES" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="zK6-rs-BSE">
<rect key="frame" x="306" y="201" width="53" height="34"/>
<rect key="frame" x="297" y="201" width="62" height="34"/>
<constraints>
<constraint firstAttribute="width" constant="53" id="NIc-rq-uw3"/>
<constraint firstAttribute="width" constant="62" id="NIc-rq-uw3"/>
<constraint firstAttribute="height" constant="34" id="Xco-Lb-usr"/>
</constraints>
<state key="normal" title="decrypt">
Expand Down Expand Up @@ -7652,7 +7654,7 @@ COLD means no keys will be generated and no private keys can be imported.</strin
<segue reference="Cd3-qW-ujG"/>
<segue reference="IAz-j1-Gq6"/>
<segue reference="6KH-E3-p33"/>
<segue reference="CQp-9r-70w"/>
<segue reference="1fQ-PG-chF"/>
<segue reference="ods-Ql-GAw"/>
<segue reference="yAt-Ra-aPH"/>
<segue reference="7PS-EL-3d2"/>
Expand Down
6 changes: 0 additions & 6 deletions FullyNoded/FullyNoded.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.applesignin</key>
<array>
<string>Default</string>
</array>
<key>com.apple.developer.default-data-protection</key>
<string>NSFileProtectionComplete</string>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.com.fullynoded.backup</string>
Expand Down
6 changes: 0 additions & 6 deletions FullyNoded/FullyNodedRelease.entitlements
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,6 @@
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.applesignin</key>
<array>
<string>Default</string>
</array>
<key>com.apple.developer.default-data-protection</key>
<string>NSFileProtectionComplete</string>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.com.fullynoded.backup</string>
Expand Down
2 changes: 1 addition & 1 deletion FullyNoded/Helpers/UR/UR.swift
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,7 @@ class URHelper {

static func cosignerOutputCbor(_ descriptor: Descriptor) -> CBOR? {
switch descriptor {
case _ where descriptor.format == "P2WPKH":
case _ where descriptor.format == "P2WPKH" || descriptor.format == "Combo":
let wpkhTag:CBOR.Tag = .init(rawValue: 404)
guard let hdkeyCbor = taggedHdKeyCbor(descriptor) else { return nil }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,12 +177,12 @@ class SecurityCenterViewController: UIViewController, UITableViewDelegate, UITab
}

case 1:
if KeyChain.getData("userIdentifier") == nil {
add2fa()
} else {
promptToDisable2fa()
}
//showAlert(vc: self, title: "", message: "This feature is not available for the dmg.")
// if KeyChain.getData("userIdentifier") == nil {
// add2fa()
// } else {
// promptToDisable2fa()
// }
showAlert(vc: self, title: "", message: "This feature is not available for the dmg.")
case 2:
DispatchQueue.main.async { [unowned vc = self] in
vc.performSegue(withIdentifier: "addPasswordSegue", sender: vc)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ class SignersViewController: UIViewController, UITableViewDelegate, UITableViewD
private var isAuthenticating = false

override func viewDidLoad() {
super.viewDidLoad()


super.viewDidLoad()
}

override func viewDidAppear(_ animated: Bool) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ class WalletDetailViewController: UIViewController, UITextFieldDelegate, UITable
var coinType = "0"
var addresses = ""
var originalLabel = ""
var exportQrImage: UIImage!
var backupQrImage: UIImage!
var exportWalletImage: UIImage!
var backupText = ""
var exportText = ""
var textToShow = ""
var json = ""
var showReceive = 0
Expand All @@ -30,7 +32,8 @@ class WalletDetailViewController: UIViewController, UITextFieldDelegate, UITable

private enum Section: Int {
case label
case exportQr
case walletExport
case backupQr
case exportFile
case filename
case receiveDesc
Expand Down Expand Up @@ -108,7 +111,7 @@ class WalletDetailViewController: UIViewController, UITextFieldDelegate, UITable
}
}

} else if wallet.watching != nil/* && wallet.name.contains("Coldcard")*/ {
} else if wallet.watching != nil {
let descriptors = wallet.watching!
var prefix = ""
var descriptorToUse = ""
Expand Down Expand Up @@ -200,7 +203,17 @@ class WalletDetailViewController: UIViewController, UITextFieldDelegate, UITable
let generator = QRGenerator()
generator.textInput = self.json
self.backupText = self.json
self.exportQrImage = generator.getQRCode()
self.backupQrImage = generator.getQRCode()

guard let urOutput = URHelper.descriptorToUrOutput(Descriptor(self.wallet.receiveDescriptor)) else {
showAlert(vc: self, title: "", message: "Unable to convert your wallet to crypto-output.")
return
}

generator.textInput = urOutput.uppercased()
self.exportText = urOutput
self.exportWalletImage = generator.getQRCode()

self.findSigner()
self.getAddresses()
}
Expand Down Expand Up @@ -452,8 +465,11 @@ class WalletDetailViewController: UIViewController, UITextFieldDelegate, UITable
case .filename:
exportItem(wallet.name)

case .exportQr:
exportItem(exportQrImage as Any)
case .walletExport:
exportItem(exportWalletImage as Any)

case .backupQr:
exportItem(backupQrImage as Any)

case .exportFile:
exportJson()
Expand Down Expand Up @@ -495,7 +511,10 @@ class WalletDetailViewController: UIViewController, UITextFieldDelegate, UITable

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch Section(rawValue: indexPath.section) {
case .exportQr:
case .walletExport:
textToShow = exportText
showQr()
case .backupQr:
textToShow = backupText
showQr()
default:
Expand Down Expand Up @@ -657,13 +676,27 @@ class WalletDetailViewController: UIViewController, UITextFieldDelegate, UITable
return cell
}

private func exportQrCell(_ indexPath: IndexPath) -> UITableViewCell {
private func exportWalletCell(_ indexPath: IndexPath) -> UITableViewCell {
let cell = detailTable.dequeueReusableCell(withIdentifier: "walletExportQrCell", for: indexPath)
configureCell(cell)

let imageView = cell.viewWithTag(1) as! UIImageView

imageView.image = exportWalletImage

let exportButton = cell.viewWithTag(2) as! UIButton
configureExportButton(exportButton, indexPath: indexPath)

return cell
}

private func backupQrCell(_ indexPath: IndexPath) -> UITableViewCell {
let cell = detailTable.dequeueReusableCell(withIdentifier: "walletExportQrCell", for: indexPath)
configureCell(cell)

let imageView = cell.viewWithTag(1) as! UIImageView

imageView.image = exportQrImage
imageView.image = backupQrImage

let exportButton = cell.viewWithTag(2) as! UIButton
configureExportButton(exportButton, indexPath: indexPath)
Expand All @@ -685,7 +718,7 @@ class WalletDetailViewController: UIViewController, UITextFieldDelegate, UITable
}

func numberOfSections(in tableView: UITableView) -> Int {
return 12
return 13
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
Expand Down Expand Up @@ -715,8 +748,10 @@ class WalletDetailViewController: UIViewController, UITextFieldDelegate, UITable
switch Section(rawValue: indexPath.section) {
case .label:
return labelCell(indexPath)
case .exportQr:
return exportQrCell(indexPath)
case .walletExport:
return exportWalletCell(indexPath)
case .backupQr:
return backupQrCell(indexPath)
case .exportFile:
return exportFileCell(indexPath)
case .filename:
Expand Down Expand Up @@ -744,7 +779,7 @@ class WalletDetailViewController: UIViewController, UITextFieldDelegate, UITable
switch Section(rawValue: indexPath.section) {
case .label:
return 50
case .exportQr:
case .backupQr, .walletExport:
return 192
case .exportFile:
return 120
Expand Down Expand Up @@ -878,8 +913,7 @@ class WalletDetailViewController: UIViewController, UITextFieldDelegate, UITable
}

private func importDescriptors(index: Int, maxRange: Int, descriptorsToImport: [String]) {
//let descriptorParser = DescriptorParser()
let descriptorStruct = Descriptor(wallet.receiveDescriptor)//descriptorParser.descriptor(wallet.receiveDescriptor)
let descriptorStruct = Descriptor(wallet.receiveDescriptor)
var keypool = true

if descriptorStruct.isMulti {
Expand Down Expand Up @@ -986,11 +1020,11 @@ class WalletDetailViewController: UIViewController, UITextFieldDelegate, UITable
if textToShow == backupText {
vc.headerText = "Wallet Backup QR"
vc.headerIcon = UIImage(systemName: "rectangle.and.paperclip")
vc.descriptionText = "Save this QR in lots of places so you can always easily recreate this wallet as watch-only."
vc.descriptionText = "Save this QR in lots of places so you can always easily recreate this wallet as watch-only. This QR code is best used with Fully Noded only."
} else {
vc.headerText = "Uncle Jim QR"
vc.headerIcon = UIImage(systemName: "person.badge.plus")
vc.descriptionText = "Share this with Uncle Jim to get him set up properly on his Bitcoin journey, or use it to create joint accounts (multisig) wallets with people who do not have their own node and want to share yours. Uncle Jim QR codes share your node and this wallet so use with caution!"
vc.headerText = "Wallet Export QR"
vc.headerIcon = UIImage(systemName: "square.and.arrow.up")
vc.descriptionText = "This QR code is best for exporting this wallet to other software and hardware wallets."
}
}
default:
Expand All @@ -1006,7 +1040,9 @@ extension WalletDetailViewController {
switch section {
case .label:
return ("Label", UIImage(systemName: "rectangle.and.paperclip")!, .systemBlue)
case .exportQr:
case .walletExport:
return ("Wallet export", UIImage(systemName: "square.and.arrow.up")!, .systemIndigo)
case .backupQr:
return ("Backup QR", UIImage(systemName: "qrcode")!, .systemGreen)
case .exportFile:
return ("Backup file", UIImage(systemName: "folder")!, .systemPink)
Expand Down

0 comments on commit 166987f

Please sign in to comment.