Step 7: request ZEC QR Code
This commit is contained in:
parent
c4bea8c3f1
commit
dbdeb8bcc7
31
README.md
31
README.md
|
@ -344,4 +344,35 @@ We can do this and many more things with the `DerivationTool` class of the Zcash
|
|||
Unfortunately this screen is really helpful. we need to get some QR code so that the user can scan the address! We will see that on the next step
|
||||
|
||||
|
||||
## Tag: `step-7-request-zec-qr-code`
|
||||
|
||||
On this step we are just going to request zec in a decent way that's useful to our customers. For that we will have to create a QR Code Image and display in on screen. Fortunately our ECC Wallet App already does this and we are going to borrow some code from it.
|
||||
|
||||
The first thing we need is a QR Code generator. iOS already does that pretty well, but the API is somewhat rough. So we created this helper class called `QRCodeGenerator`
|
||||
|
||||
We are going to add this snippet to the `RequestZec` screen struct
|
||||
````
|
||||
// This Generates the QR Image
|
||||
var qrImage: Image {
|
||||
if let zAddr = self.zAddress, let img = QRCodeGenerator.generate(from: zAddr) {
|
||||
return Image(img, scale: 1, label: Text(String(format:NSLocalizedString("QR Code for %@", comment: ""),"\(zAddr)") ))
|
||||
} else {
|
||||
return Image("zebra_profile")
|
||||
}
|
||||
}
|
||||
````
|
||||
|
||||
and also this one to the body of the view so that the qr code is show. or a nice zebra placeholder otherwise
|
||||
|
||||
````
|
||||
QRCodeContainer(qrImage: qrImage,
|
||||
badge: Image("QR-zcashlogo"))
|
||||
.frame(width: qrSize, height: qrSize, alignment: .center)
|
||||
.layoutPriority(1)
|
||||
````
|
||||
We borrowed some nice assets from the wallet too! A cool zebra, and a nice shield for our QR code.
|
||||
|
||||
And that's it! Customers will be able to scan our Zcash Sapling Address!
|
||||
|
||||
Our next step will be receiving the transactions.
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
0D08DEAA25E70D8400E08533 /* SettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D08DEA925E70D8400E08533 /* SettingsScreen.swift */; };
|
||||
0D08DEAD25E71D4500E08533 /* RequestZec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D08DEAC25E71D4500E08533 /* RequestZec.swift */; };
|
||||
0D08DEB025E732C900E08533 /* Zboto.otf in Resources */ = {isa = PBXBuildFile; fileRef = 0D08DEAF25E732C900E08533 /* Zboto.otf */; };
|
||||
0D08DEB325E7397A00E08533 /* QRCodeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D08DEB225E7397A00E08533 /* QRCodeGenerator.swift */; };
|
||||
0D08DEB625E73B7000E08533 /* QRCodeContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D08DEB525E73B7000E08533 /* QRCodeContainer.swift */; };
|
||||
0D475B2125E3ED600067978E /* CombineSynchronizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D475B2025E3ED600067978E /* CombineSynchronizer.swift */; };
|
||||
0D475B2725E3EEE10067978E /* DetailModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D475B2625E3EEE10067978E /* DetailModel.swift */; };
|
||||
0D475B2A25E3F04C0067978E /* String+Zcash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D475B2925E3F04C0067978E /* String+Zcash.swift */; };
|
||||
|
@ -51,6 +53,8 @@
|
|||
0D08DEA925E70D8400E08533 /* SettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreen.swift; sourceTree = "<group>"; };
|
||||
0D08DEAC25E71D4500E08533 /* RequestZec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestZec.swift; sourceTree = "<group>"; };
|
||||
0D08DEAF25E732C900E08533 /* Zboto.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Zboto.otf; sourceTree = "<group>"; };
|
||||
0D08DEB225E7397A00E08533 /* QRCodeGenerator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRCodeGenerator.swift; sourceTree = "<group>"; };
|
||||
0D08DEB525E73B7000E08533 /* QRCodeContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QRCodeContainer.swift; sourceTree = "<group>"; };
|
||||
0D475B2025E3ED600067978E /* CombineSynchronizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CombineSynchronizer.swift; sourceTree = "<group>"; };
|
||||
0D475B2625E3EEE10067978E /* DetailModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailModel.swift; sourceTree = "<group>"; };
|
||||
0D475B2925E3F04C0067978E /* String+Zcash.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Zcash.swift"; sourceTree = "<group>"; };
|
||||
|
@ -173,8 +177,9 @@
|
|||
0D5051A625E059D800E7A697 /* UI Elements */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0D475B2925E3F04C0067978E /* String+Zcash.swift */,
|
||||
0D08DEB525E73B7000E08533 /* QRCodeContainer.swift */,
|
||||
0D5051C325E079DE00E7A697 /* ZcashButton.swift */,
|
||||
0D475B2925E3F04C0067978E /* String+Zcash.swift */,
|
||||
0D5051C025E0797C00E7A697 /* ZcashButtonBackground.swift */,
|
||||
0D50519925E0591B00E7A697 /* ZcashBackground.swift */,
|
||||
0D50519C25E0596B00E7A697 /* ZcashTextField.swift */,
|
||||
|
@ -190,6 +195,7 @@
|
|||
0D5051B825E076C200E7A697 /* Utils */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0D08DEB225E7397A00E08533 /* QRCodeGenerator.swift */,
|
||||
0D475B2F25E3F34E0067978E /* SimpleLogger.swift */,
|
||||
0D475B2C25E3F2E50067978E /* BalanceUtils.swift */,
|
||||
0D5051BA25E0775800E7A697 /* UIResponder+Current.swift */,
|
||||
|
@ -346,9 +352,11 @@
|
|||
0D5051C425E079DE00E7A697 /* ZcashButton.swift in Sources */,
|
||||
0D5051AE25E066E300E7A697 /* ZcashLogo.swift in Sources */,
|
||||
0D50519D25E0596B00E7A697 /* ZcashTextField.swift in Sources */,
|
||||
0D08DEB325E7397A00E08533 /* QRCodeGenerator.swift in Sources */,
|
||||
0D5051BB25E0775800E7A697 /* UIResponder+Current.swift in Sources */,
|
||||
0D5051A325E0599800E7A697 /* ZcashSymbol.swift in Sources */,
|
||||
0D50519725E0583500E7A697 /* Colors.swift in Sources */,
|
||||
0D08DEB625E73B7000E08533 /* QRCodeContainer.swift in Sources */,
|
||||
0D5051A425E0599800E7A697 /* Ring.swift in Sources */,
|
||||
0D08DE7025E6CA6800E08533 /* AlertType.swift in Sources */,
|
||||
0D5051A225E0599800E7A697 /* Baseline.swift in Sources */,
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "QR-zcashlogo.pdf",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "zebra_profile.pdf",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,37 @@
|
|||
//
|
||||
// QRCodeContainer.swift
|
||||
// wallet
|
||||
//
|
||||
// Created by Francisco Gindre on 1/3/20.
|
||||
// Copyright © 2020 Francisco Gindre. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct QRCodeContainer: View {
|
||||
var qrImage: Image
|
||||
var badge: Image
|
||||
var body: some View {
|
||||
ZStack {
|
||||
qrImage
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
badge
|
||||
.resizable()
|
||||
.frame(width: 64, height: 64)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct QRCodeContainer_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
|
||||
ZStack {
|
||||
ZcashBackground()
|
||||
QRCodeContainer(qrImage: Image("QrCode"),
|
||||
badge: Image("QR-zcashlogo"))
|
||||
.frame(width: 285, height: 285)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// QRCodeGenerator.swift
|
||||
// wallet
|
||||
//
|
||||
// Created by Francisco Gindre on 2/3/20.
|
||||
// Copyright © 2020 MIT License
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
import CoreImage
|
||||
import CoreImage.CIFilterBuiltins
|
||||
import SwiftUI
|
||||
|
||||
|
||||
class QRCodeGenerator {
|
||||
enum QRCodeError: Error {
|
||||
case failedToGenerate
|
||||
}
|
||||
|
||||
static func generate(from string: String) -> Future<CGImage,QRCodeError> {
|
||||
|
||||
Future<CGImage,QRCodeError>() { promise in
|
||||
DispatchQueue.global().async {
|
||||
|
||||
guard let image = generate(from: string) else {
|
||||
promise(.failure(QRCodeGenerator.QRCodeError.failedToGenerate))
|
||||
return
|
||||
}
|
||||
|
||||
return promise(.success(image))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func generate(from string: String, scale: CGFloat = 5) -> CGImage? {
|
||||
let data = string.data(using: String.Encoding.utf8)
|
||||
|
||||
let context = CIContext()
|
||||
let filter = CoreImage.CIFilter.qrCodeGenerator()
|
||||
filter.setValue(data, forKey: "inputMessage")
|
||||
let transform = CGAffineTransform(scaleX: scale, y: scale)
|
||||
|
||||
|
||||
guard let output = filter.outputImage?.transformed(by: transform) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return context.createCGImage(output, from: output.extent)
|
||||
}
|
||||
}
|
|
@ -11,14 +11,23 @@ struct RequestZec: View {
|
|||
@EnvironmentObject var model: ZcashPoSModel
|
||||
@State var zAddress: String? = nil
|
||||
@State var alertType: AlertType? = nil
|
||||
// This Generates the QR Image
|
||||
var qrImage: Image {
|
||||
if let zAddr = self.zAddress, let img = QRCodeGenerator.generate(from: zAddr) {
|
||||
return Image(img, scale: 1, label: Text(String(format:NSLocalizedString("QR Code for %@", comment: ""),"\(zAddr)") ))
|
||||
} else {
|
||||
return Image("zebra_profile")
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
ZcashBackground()
|
||||
VStack(alignment: .center, spacing: 40){
|
||||
Text("To This address:")
|
||||
.foregroundColor(.white)
|
||||
Text(zAddress ?? "Error Deriving Address")
|
||||
.foregroundColor(.white)
|
||||
QRCodeContainer(qrImage: qrImage,
|
||||
badge: Image("QR-zcashlogo"))
|
||||
.frame(width: 150, height: 150, alignment: .center)
|
||||
.layoutPriority(1)
|
||||
|
||||
Text("$\(model.request.amount.toZecAmount())")
|
||||
.lineLimit(1)
|
||||
|
@ -29,10 +38,13 @@ struct RequestZec: View {
|
|||
)
|
||||
|
||||
Text("Append Memo With this Code")
|
||||
|
||||
.foregroundColor(.white)
|
||||
.font(.title2)
|
||||
Text(model.request.code)
|
||||
.foregroundColor(.white)
|
||||
.font(.title)
|
||||
.font(.system(size: 72))
|
||||
|
||||
}
|
||||
}.navigationTitle("Pay with ZEC")
|
||||
.onAppear() {
|
||||
|
|
Loading…
Reference in New Issue