forked from ciphrex/mSIGNA
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpaymentrequest.cpp
137 lines (118 loc) · 4.32 KB
/
paymentrequest.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
///////////////////////////////////////////////////////////////////////////////
//
// mSIGNA
//
// paymentrequest.cpp
//
// Copyright (c) 2013 Eric Lombrozo
//
// All Rights Reserved.
#include "paymentrequest.h"
#include "numberformats.h"
#include <CoinCore/Base58Check.h>
#include <CoinQ/CoinQ_typedefs.h>
#include <QUrl>
#include <QUrlQuery>
#include <QStringList>
#include <QObject>
// TODO: Allow different coin parameters
const QString VALID_URL_SCHEME("bitcoin");
const unsigned char VALID_ADDRESS_VERSIONS[] = { 0x00, 0x05 };
const int VALID_VERSION_COUNT = sizeof(VALID_ADDRESS_VERSIONS)/sizeof(unsigned char);
const char* BASE58_CHARS = BITCOIN_BASE58_CHARS;
const unsigned int ADDRESS_DATA_SIZE = 20;
const uint64_t CURRENCY_MAX = 0xffffffffffffffffull;
const uint64_t CURRENCY_DIVISOR = 100000000ull;
const unsigned int CURRENCY_DECIMALS = 8;
PaymentRequest::PaymentRequest(const QUrl& url)
{
if (url.scheme().compare(VALID_URL_SCHEME, Qt::CaseInsensitive) != 0) {
throw std::runtime_error(QObject::tr("Invalid payment request URL scheme").toStdString());
}
QString path = url.path();
address_ = path.section(';', 0, 0);
hasAddress_ = !address_.isEmpty();
if (!hasAddress_) {
throw std::runtime_error(QObject::tr("Payment address is missing").toStdString());
}
QStringList versionParts = path.section(';', 1).split('=');
hasVersion_ = versionParts.count() != 1;
if (hasVersion_) {
if (versionParts.count() != 2 || versionParts[0] != "version") {
throw std::runtime_error(QObject::tr("Payment version is invalid").toStdString());
}
version_ = versionParts[1];
}
bytes_t payload;
unsigned int addressVersion;
if (!fromBase58Check(address_.toStdString(), payload, addressVersion, BASE58_CHARS) || payload.size() != ADDRESS_DATA_SIZE ||
[&]() { for (int i = 0; i < VALID_VERSION_COUNT; i++) { if (addressVersion == VALID_ADDRESS_VERSIONS[i]) return false; } return true; }()) {
throw std::runtime_error(QObject::tr("Invalid payment address").toStdString());
}
QUrlQuery query(url);
hasValue_ = query.hasQueryItem("amount");
if (hasValue_) value_ = parseAmount(query.queryItemValue("amount"));
hasLabel_ = query.hasQueryItem("label");
if (hasLabel_) label_ = query.queryItemValue("label");
hasMessage_ = query.hasQueryItem("message");
if (hasMessage_) message_ = query.queryItemValue("message");
hasSend_ = query.hasQueryItem("send");
if (hasSend_) send_ = query.queryItemValue("send");
}
uint64_t PaymentRequest::parseAmount(const QString& amountString)
{
// TODO: handle small amounts correctly
QString mantissa;
unsigned int exponent;
if (amountString.contains('X')) {
QString exp = amountString.section('X', 1);
if (exp.size() != 1 || exp[0] < '0' || exp[0] > '8') {
throw std::runtime_error(QObject::tr("Invalid payment address").toStdString());
}
mantissa = amountString.section('X', 0, 0);
exponent = exp[0].unicode() - '0';
}
else {
mantissa = amountString;
exponent = CURRENCY_DECIMALS;
}
uint64_t divisor = CURRENCY_DIVISOR;
for (unsigned int i = CURRENCY_DECIMALS; i > exponent; i--) { divisor *= 10; }
return decimalStringToInteger(mantissa.toStdString(), CURRENCY_MAX, divisor, CURRENCY_DECIMALS);
}
QString PaymentRequest::toJson() const
{
bool first = true;
QString json("{");
if (hasAddress_) {
first = false;
json += "\"address\":\"" + address_ + "\"";
}
if (hasVersion_) {
if (first) { first = false; }
else { json += ","; }
json += "\"version\":\"" + version_ + "\"";
}
if (hasValue_) {
if (first) { first = false; }
else { json += ","; }
json += "\"value\":\"" + QString::number(value_) + "\"";
}
if (hasLabel_) {
if (first) { first = false; }
else { json += ","; }
json += "\"label\":\"" + label_ + "\"";
}
if (hasMessage_) {
if (first) { first = false; }
else { json += ","; }
json += "\"message\":\"" + message_ + "\"";
}
if (hasSend_) {
if (first) { first = false; }
else { json += ","; }
json += "\"send\":\"" + send_ + "\"";
}
json += "}";
return json;
}