wownero
/
wownerujo
Archived
4
0
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
wownerujo/app/src/main/java/com/wownero/wownerujo/data/BarcodeData.java

201 lines
6.4 KiB

/*
* Copyright (c) 2017 m2049r
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wownero.wownerujo.data;
import android.net.Uri;
import com.wownero.wownerujo.model.NetworkType;
import com.wownero.wownerujo.model.Wallet;
import com.wownero.wownerujo.model.WalletManager;
import com.wownero.wownerujo.util.BitcoinAddressValidator;
import java.util.HashMap;
import java.util.Map;
import timber.log.Timber;
public class BarcodeData {
public static final String XMR_SCHEME = "monero:";
public static final String XMR_PAYMENTID = "tx_payment_id";
public static final String XMR_AMOUNT = "tx_amount";
static final String BTC_SCHEME = "bitcoin:";
static final String BTC_AMOUNT = "amount";
public enum Asset {
XMR, BTC
}
public Asset asset = null;
public String address = null;
public String paymentId = null;
public String amount = null;
public BarcodeData(Asset asset, String address) {
this.asset = asset;
this.address = address;
}
public BarcodeData(Asset asset, String address, String amount) {
this.asset = asset;
this.address = address;
this.amount = amount;
}
public BarcodeData(Asset asset, String address, String paymentId, String amount) {
this.asset = asset;
this.address = address;
this.paymentId = paymentId;
this.amount = amount;
}
static public BarcodeData fromQrCode(String qrCode) {
// check for monero uri
BarcodeData bcData = parseMoneroUri(qrCode);
// check for naked monero address / integrated address
if (bcData == null) {
bcData = parseMoneroNaked(qrCode);
}
// check for btc uri
if (bcData == null) {
bcData = parseBitcoinUri(qrCode);
}
// check for naked btc addres
if (bcData == null) {
bcData = parseBitcoinNaked(qrCode);
}
return bcData;
}
/**
* Parse and decode a monero scheme string. It is here because it needs to validate the data.
*
* @param uri String containing a monero URL
* @return BarcodeData object or null if uri not valid
*/
static public BarcodeData parseMoneroUri(String uri) {
Timber.d("parseMoneroUri=%s", uri);
if (uri == null) return null;
if (!uri.startsWith(XMR_SCHEME)) return null;
String noScheme = uri.substring(XMR_SCHEME.length());
Uri monero = Uri.parse(noScheme);
Map<String, String> parms = new HashMap<>();
String query = monero.getQuery();
if (query != null) {
String[] args = query.split("&");
for (String arg : args) {
String[] namevalue = arg.split("=");
if (namevalue.length == 0) {
continue;
}
parms.put(Uri.decode(namevalue[0]).toLowerCase(),
namevalue.length > 1 ? Uri.decode(namevalue[1]) : "");
}
}
String address = monero.getPath();
String paymentId = parms.get(XMR_PAYMENTID);
String amount = parms.get(XMR_AMOUNT);
if (amount != null) {
try {
Double.parseDouble(amount);
} catch (NumberFormatException ex) {
Timber.d(ex.getLocalizedMessage());
return null; // we have an amount but its not a number!
}
}
if ((paymentId != null) && !Wallet.isPaymentIdValid(paymentId)) {
Timber.d("paymentId invalid");
return null;
}
if (!Wallet.isAddressValid(address)) {
Timber.d("address invalid");
return null;
}
return new BarcodeData(Asset.XMR, address, paymentId, amount);
}
static public BarcodeData parseMoneroNaked(String address) {
Timber.d("parseMoneroNaked=%s", address);
if (address == null) return null;
if (!Wallet.isAddressValid(address)) {
Timber.d("address invalid");
return null;
}
return new BarcodeData(Asset.XMR, address);
}
// bitcoin:mpQ84J43EURZHkCnXbyQ4PpNDLLBqdsMW2?amount=0.01
static public BarcodeData parseBitcoinUri(String uri) {
Timber.d("parseBitcoinUri=%s", uri);
if (uri == null) return null;
if (!uri.startsWith(BTC_SCHEME)) return null;
String noScheme = uri.substring(BTC_SCHEME.length());
Uri bitcoin = Uri.parse(noScheme);
Map<String, String> parms = new HashMap<>();
String query = bitcoin.getQuery();
if (query != null) {
String[] args = query.split("&");
for (String arg : args) {
String[] namevalue = arg.split("=");
if (namevalue.length == 0) {
continue;
}
parms.put(Uri.decode(namevalue[0]).toLowerCase(),
namevalue.length > 1 ? Uri.decode(namevalue[1]) : "");
}
}
String address = bitcoin.getPath();
String amount = parms.get(BTC_AMOUNT);
if (amount != null) {
try {
Double.parseDouble(amount);
} catch (NumberFormatException ex) {
Timber.d(ex.getLocalizedMessage());
return null; // we have an amount but its not a number!
}
}
if (!BitcoinAddressValidator.validate(address)) {
Timber.d("address invalid");
return null;
}
return new BarcodeData(BarcodeData.Asset.BTC, address, amount);
}
static public BarcodeData parseBitcoinNaked(String address) {
Timber.d("parseBitcoinNaked=%s", address);
if (address == null) return null;
if (!BitcoinAddressValidator.validate(address)) {
Timber.d("address invalid");
return null;
}
return new BarcodeData(BarcodeData.Asset.BTC, address);
}
}