Fill in payments by scanning a QR code or picking one from photos
This commit is contained in:
@@ -122,6 +122,11 @@ enum SelfTest {
|
||||
emit("KOINS_SELFTEST \(name): \(ok ? "PASS" : "FAIL") \(actual)")
|
||||
}
|
||||
|
||||
func expectTrue(_ name: String, _ value: Bool) {
|
||||
if !value { failures += 1 }
|
||||
emit("KOINS_SELFTEST \(name): \(value ? "PASS" : "FAIL")")
|
||||
}
|
||||
|
||||
expect("ripemd160", Hex.encode(RIPEMD160.hash(Array("abc".utf8))),
|
||||
"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc")
|
||||
|
||||
@@ -236,6 +241,55 @@ enum SelfTest {
|
||||
}
|
||||
}
|
||||
|
||||
// QR round trip: generate an image, read it back, parse the payment URI.
|
||||
let xmrAddress = "46cRPeU77sBVGSVXPyCjvJUdC9AjqvETWb6giUGskdnWN8ZifindmrH7mcztKU52iKgvWXY4dyPujg9LYUY1Q7dvDiwHNCE"
|
||||
let xrpAddress = "rHR6xtDW7BxeQN8VB8R9HzXzyMeS42n7C"
|
||||
|
||||
func roundTrip(_ name: String, _ text: String, checks: [(String, String)]) {
|
||||
guard let image = QRCodeImage.make(text) else {
|
||||
failures += 1
|
||||
emit("KOINS_SELFTEST \(name): FAIL could not render QR image")
|
||||
return
|
||||
}
|
||||
guard let decoded = QRCodeReader.decodeText(in: image) else {
|
||||
failures += 1
|
||||
emit("KOINS_SELFTEST \(name): FAIL vision could not read the QR image (\(Int(image.size.width))px)")
|
||||
return
|
||||
}
|
||||
guard let payload = QRCodeReader.parse(decoded) else {
|
||||
failures += 1
|
||||
emit("KOINS_SELFTEST \(name): FAIL parse of '\(decoded)'")
|
||||
return
|
||||
}
|
||||
for (label, expected) in checks {
|
||||
let actual: String
|
||||
switch label {
|
||||
case "address": actual = payload.address
|
||||
case "amount": actual = payload.amount ?? ""
|
||||
case "tag": actual = payload.tag.map(String.init) ?? ""
|
||||
case "paymentId": actual = payload.paymentId ?? ""
|
||||
case "memo": actual = payload.memo ?? ""
|
||||
default: actual = ""
|
||||
}
|
||||
expect("\(name) \(label)", actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
roundTrip("qr monero uri",
|
||||
"monero:\(xmrAddress)?tx_amount=1.5&tx_payment_id=abc123&tx_description=Rent",
|
||||
checks: [("address", xmrAddress), ("amount", "1.5"), ("paymentId", "abc123"), ("memo", "Rent")])
|
||||
roundTrip("qr monero plain", xmrAddress, checks: [("address", xmrAddress)])
|
||||
roundTrip("qr xrp uri",
|
||||
"ripple:\(xrpAddress)?amount=12.5&dt=99",
|
||||
checks: [("address", xrpAddress), ("amount", "12.5"), ("tag", "99")])
|
||||
roundTrip("qr xrp plain", xrpAddress, checks: [("address", xrpAddress)])
|
||||
|
||||
expectTrue("qr monero detected", AddressFormat.isMonero(xmrAddress))
|
||||
expectTrue("qr xrp detected", AddressFormat.isXRP(xrpAddress))
|
||||
expectTrue("qr rejects junk", QRCodeReader.parse("hello world")?.address == "hello world")
|
||||
expectTrue("qr not monero", !AddressFormat.isMonero(xrpAddress))
|
||||
expectTrue("qr not xrp", !AddressFormat.isXRP(xmrAddress))
|
||||
|
||||
// secp256k1 signing must produce a low-S DER signature.
|
||||
if let keypair = try? XRPKey.keypair(fromSeed: secpSeed),
|
||||
let message = Hex.decode(signingHex),
|
||||
|
||||
Reference in New Issue
Block a user