@p2pdotme/sdk 1.2.16 → 1.2.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/country.cjs +480 -62
- package/dist/country.cjs.map +1 -1
- package/dist/country.d.cts +144 -27
- package/dist/country.d.ts +144 -27
- package/dist/country.mjs +460 -62
- package/dist/country.mjs.map +1 -1
- package/dist/fraud-engine.cjs +1 -0
- package/dist/fraud-engine.cjs.map +1 -1
- package/dist/fraud-engine.mjs +1 -0
- package/dist/fraud-engine.mjs.map +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +2 -1
- package/dist/index.mjs.map +1 -1
- package/dist/orders.cjs +1 -0
- package/dist/orders.cjs.map +1 -1
- package/dist/orders.d.cts +2 -0
- package/dist/orders.d.ts +2 -0
- package/dist/orders.mjs +1 -0
- package/dist/orders.mjs.map +1 -1
- package/dist/prices.cjs +1 -0
- package/dist/prices.cjs.map +1 -1
- package/dist/prices.d.cts +1 -0
- package/dist/prices.d.ts +1 -0
- package/dist/prices.mjs +1 -0
- package/dist/prices.mjs.map +1 -1
- package/dist/profile.cjs +1 -0
- package/dist/profile.cjs.map +1 -1
- package/dist/profile.d.cts +2 -0
- package/dist/profile.d.ts +2 -0
- package/dist/profile.mjs +1 -0
- package/dist/profile.mjs.map +1 -1
- package/dist/qr-parsers.cjs +205 -11
- package/dist/qr-parsers.cjs.map +1 -1
- package/dist/qr-parsers.d.cts +9 -1
- package/dist/qr-parsers.d.ts +9 -1
- package/dist/qr-parsers.mjs +204 -11
- package/dist/qr-parsers.mjs.map +1 -1
- package/dist/react.cjs +1 -0
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +6 -0
- package/dist/react.d.ts +6 -0
- package/dist/react.mjs +1 -0
- package/dist/react.mjs.map +1 -1
- package/dist/stake.cjs +1 -0
- package/dist/stake.cjs.map +1 -1
- package/dist/stake.d.cts +1 -0
- package/dist/stake.d.ts +1 -0
- package/dist/stake.mjs +1 -0
- package/dist/stake.mjs.map +1 -1
- package/dist/zkkyc.cjs +1 -0
- package/dist/zkkyc.cjs.map +1 -1
- package/dist/zkkyc.mjs +1 -0
- package/dist/zkkyc.mjs.map +1 -1
- package/package.json +1 -1
package/dist/qr-parsers.cjs
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var qr_parsers_exports = {};
|
|
22
22
|
__export(qr_parsers_exports, {
|
|
23
23
|
QRParserError: () => QRParserError,
|
|
24
|
+
isPagoMovilQr: () => isPagoMovilQr,
|
|
24
25
|
parseQR: () => parseQR
|
|
25
26
|
});
|
|
26
27
|
module.exports = __toCommonJS(qr_parsers_exports);
|
|
@@ -47,6 +48,7 @@ var CURRENCY = {
|
|
|
47
48
|
ARS: "ARS",
|
|
48
49
|
MEX: "MEX",
|
|
49
50
|
VEN: "VEN",
|
|
51
|
+
BOB: "BOB",
|
|
50
52
|
EUR: "EUR",
|
|
51
53
|
NGN: "NGN",
|
|
52
54
|
USD: "USD",
|
|
@@ -80,6 +82,98 @@ var ARS_COUNTRY_OPTION = {
|
|
|
80
82
|
disabledPaymentTypes: []
|
|
81
83
|
};
|
|
82
84
|
|
|
85
|
+
// src/country/types.ts
|
|
86
|
+
var PACKED_PAYMENT_ID_SEP = "||";
|
|
87
|
+
|
|
88
|
+
// src/country/qr-validator.ts
|
|
89
|
+
function crc16ccitt(s) {
|
|
90
|
+
let crc = 65535;
|
|
91
|
+
for (let i = 0; i < s.length; i++) {
|
|
92
|
+
crc ^= s.charCodeAt(i) << 8;
|
|
93
|
+
for (let j = 0; j < 8; j++) {
|
|
94
|
+
crc = crc & 32768 ? crc << 1 ^ 4129 : crc << 1;
|
|
95
|
+
crc &= 65535;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return crc.toString(16).toUpperCase().padStart(4, "0");
|
|
99
|
+
}
|
|
100
|
+
function validateEmvcoQr(payload, country, currency) {
|
|
101
|
+
if (!payload || payload.trim().length === 0) return false;
|
|
102
|
+
const data = payload.trim();
|
|
103
|
+
const tags = {};
|
|
104
|
+
let pos = 0;
|
|
105
|
+
while (pos + 4 <= data.length) {
|
|
106
|
+
const tag = data.substring(pos, pos + 2);
|
|
107
|
+
const lengthStr = data.substring(pos + 2, pos + 4);
|
|
108
|
+
if (!/^[0-9]{2}$/.test(tag) || !/^[0-9]{2}$/.test(lengthStr)) break;
|
|
109
|
+
const length = Number.parseInt(lengthStr, 10);
|
|
110
|
+
if (pos + 4 + length > data.length) break;
|
|
111
|
+
tags[tag] = data.substring(pos + 4, pos + 4 + length);
|
|
112
|
+
pos += 4 + length;
|
|
113
|
+
}
|
|
114
|
+
if (tags["58"] !== country) return false;
|
|
115
|
+
if (tags["53"] !== currency) return false;
|
|
116
|
+
const crcTag = tags["63"];
|
|
117
|
+
if (!crcTag) return false;
|
|
118
|
+
const marker = data.lastIndexOf("6304");
|
|
119
|
+
if (marker === -1) return false;
|
|
120
|
+
const expected = crc16ccitt(data.substring(0, marker + 4));
|
|
121
|
+
return expected.toUpperCase() === crcTag.toUpperCase();
|
|
122
|
+
}
|
|
123
|
+
function validatePeruvianQr(payload) {
|
|
124
|
+
return validateEmvcoQr(payload, "PE", "604");
|
|
125
|
+
}
|
|
126
|
+
function isBolivianEncryptedQr(payload) {
|
|
127
|
+
const trimmed = payload.trim();
|
|
128
|
+
if (trimmed.includes(PACKED_PAYMENT_ID_SEP)) return false;
|
|
129
|
+
const sep = trimmed.lastIndexOf("|");
|
|
130
|
+
if (sep < 40) return false;
|
|
131
|
+
const blob = trimmed.slice(0, sep);
|
|
132
|
+
const tag = trimmed.slice(sep + 1);
|
|
133
|
+
if (blob.length % 4 !== 0) return false;
|
|
134
|
+
if (!/^[A-Za-z0-9+/]+={0,2}$/.test(blob)) return false;
|
|
135
|
+
return /^(?:[0-9A-Fa-f]{24}|[0-9A-Fa-f]{32})$/.test(tag);
|
|
136
|
+
}
|
|
137
|
+
function validateBolivianQr(payload) {
|
|
138
|
+
if (!payload || payload.trim().length === 0) return false;
|
|
139
|
+
return isBolivianEncryptedQr(payload) || validateEmvcoQr(payload, "BO", "068");
|
|
140
|
+
}
|
|
141
|
+
function validateVenezuelanQr(payload) {
|
|
142
|
+
if (!payload || typeof payload !== "string") return false;
|
|
143
|
+
const trimmed = payload.trim();
|
|
144
|
+
if (trimmed.includes(PACKED_PAYMENT_ID_SEP)) return false;
|
|
145
|
+
const qIdx = trimmed.indexOf("?");
|
|
146
|
+
if (qIdx < 40) return false;
|
|
147
|
+
const blob = trimmed.substring(0, qIdx);
|
|
148
|
+
if (!/^[A-Za-z0-9+/=]+$/.test(blob)) return false;
|
|
149
|
+
return /(?:^|[?&])merchantId=\d{3,4}(?:&|$)/.test(trimmed.substring(qIdx));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// src/country/currencies/bob.ts
|
|
153
|
+
var BOB_COUNTRY_OPTION = {
|
|
154
|
+
country: "Bolivia",
|
|
155
|
+
currency: CURRENCY.BOB,
|
|
156
|
+
internationalFormat: "BOB",
|
|
157
|
+
symbolNative: "Bs.",
|
|
158
|
+
locale: "es-BO",
|
|
159
|
+
paymentMethod: "QR_SIMPLE",
|
|
160
|
+
paymentAddressName: "QR_SIMPLE_DETAILS",
|
|
161
|
+
timezone: "America/La_Paz",
|
|
162
|
+
timezone_name: "BOT",
|
|
163
|
+
flag: "\u{1F1E7}\u{1F1F4}",
|
|
164
|
+
flagUrl: "https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/72x72/1f1e7-1f1f4.png",
|
|
165
|
+
phoneCode: "+591",
|
|
166
|
+
telegramSupportChannel: "https://t.me/p2pmebolivia",
|
|
167
|
+
twitterUsername: "p2pmebolivia",
|
|
168
|
+
smsCountryCodes: ["BO"],
|
|
169
|
+
precision: 2,
|
|
170
|
+
isAlpha: true,
|
|
171
|
+
disabled: false,
|
|
172
|
+
disabledPaymentTypes: [],
|
|
173
|
+
uploadPaymentQR: true,
|
|
174
|
+
validateQr: validateBolivianQr
|
|
175
|
+
};
|
|
176
|
+
|
|
83
177
|
// src/country/currencies/brl.ts
|
|
84
178
|
var BRL_COUNTRY_OPTION = {
|
|
85
179
|
country: "Brazil",
|
|
@@ -281,6 +375,55 @@ var NGN_COUNTRY_OPTION = {
|
|
|
281
375
|
};
|
|
282
376
|
|
|
283
377
|
// src/country/currencies/pen.ts
|
|
378
|
+
function validatePeruvianPhone(value) {
|
|
379
|
+
if (!value || value.trim().length === 0) return false;
|
|
380
|
+
const phone = value.trim().replace(/\s+/g, "").replace(/^\+?51/, "");
|
|
381
|
+
return /^9\d{8}$/.test(phone);
|
|
382
|
+
}
|
|
383
|
+
function normalizePeruvianPaymentKey(value) {
|
|
384
|
+
const trimmed = value.trim();
|
|
385
|
+
const cci = trimmed.replace(/\s+/g, "");
|
|
386
|
+
if (/^\d{20}$/.test(cci)) return cci;
|
|
387
|
+
const phone = trimmed.replace(/\s+/g, "").replace(/^\+?51/, "");
|
|
388
|
+
if (/^9\d{8}$/.test(phone)) return phone;
|
|
389
|
+
return cci;
|
|
390
|
+
}
|
|
391
|
+
function looksLikeTlv(value) {
|
|
392
|
+
if (value.length < 5 || !/^\d{4}/.test(value)) return false;
|
|
393
|
+
const len = Number.parseInt(value.slice(2, 4), 10);
|
|
394
|
+
return !Number.isNaN(len) && len >= 0 && 4 + len <= value.length;
|
|
395
|
+
}
|
|
396
|
+
function phoneFromTlvValue(value) {
|
|
397
|
+
const trimmed = value.trim();
|
|
398
|
+
if (!trimmed) return null;
|
|
399
|
+
if (validatePeruvianPhone(trimmed)) return normalizePeruvianPaymentKey(trimmed);
|
|
400
|
+
if (/^[0-9a-f]+$/i.test(trimmed) && /[a-f]/i.test(trimmed)) return null;
|
|
401
|
+
const match = trimmed.match(/(^|[^0-9])(\+?51)?(9\d{8})(?![0-9])/);
|
|
402
|
+
if (!match) return null;
|
|
403
|
+
const candidate = `${match[2] ?? ""}${match[3]}`;
|
|
404
|
+
return validatePeruvianPhone(candidate) ? normalizePeruvianPaymentKey(candidate) : null;
|
|
405
|
+
}
|
|
406
|
+
function extractPeruvianPhoneFromQr(payload) {
|
|
407
|
+
let pos = 0;
|
|
408
|
+
while (pos + 4 <= payload.length) {
|
|
409
|
+
const tag = payload.slice(pos, pos + 2);
|
|
410
|
+
const len = Number.parseInt(payload.slice(pos + 2, pos + 4), 10);
|
|
411
|
+
if (Number.isNaN(len) || len < 0 || pos + 4 + len > payload.length) break;
|
|
412
|
+
const value = payload.slice(pos + 4, pos + 4 + len);
|
|
413
|
+
const direct = phoneFromTlvValue(value);
|
|
414
|
+
if (direct) return direct;
|
|
415
|
+
if (tag >= "02" && tag <= "51" || tag === "62" || tag === "64" || looksLikeTlv(value)) {
|
|
416
|
+
const nested = extractPeruvianPhoneFromQr(value);
|
|
417
|
+
if (nested) return nested;
|
|
418
|
+
}
|
|
419
|
+
pos += 4 + len;
|
|
420
|
+
}
|
|
421
|
+
const glued = payload.match(/\+51\s*9\d{8}/);
|
|
422
|
+
if (glued && validatePeruvianPhone(glued[0])) {
|
|
423
|
+
return normalizePeruvianPaymentKey(glued[0]);
|
|
424
|
+
}
|
|
425
|
+
return null;
|
|
426
|
+
}
|
|
284
427
|
var PEN_COUNTRY_OPTION = {
|
|
285
428
|
country: "Peru",
|
|
286
429
|
currency: CURRENCY.PEN,
|
|
@@ -299,7 +442,13 @@ var PEN_COUNTRY_OPTION = {
|
|
|
299
442
|
precision: 2,
|
|
300
443
|
isAlpha: true,
|
|
301
444
|
disabled: false,
|
|
302
|
-
disabledPaymentTypes: []
|
|
445
|
+
disabledPaymentTypes: [],
|
|
446
|
+
uploadPaymentQR: true,
|
|
447
|
+
validateQr: validatePeruvianQr,
|
|
448
|
+
hydrateFieldsFromQr: (qr) => {
|
|
449
|
+
const phone = extractPeruvianPhoneFromQr(qr);
|
|
450
|
+
return phone ? { phone } : {};
|
|
451
|
+
}
|
|
303
452
|
};
|
|
304
453
|
|
|
305
454
|
// src/country/currencies/php.ts
|
|
@@ -366,7 +515,9 @@ var VEN_COUNTRY_OPTION = {
|
|
|
366
515
|
precision: 2,
|
|
367
516
|
isAlpha: false,
|
|
368
517
|
disabled: false,
|
|
369
|
-
disabledPaymentTypes: []
|
|
518
|
+
disabledPaymentTypes: [],
|
|
519
|
+
uploadPaymentQR: true,
|
|
520
|
+
validateQr: validateVenezuelanQr
|
|
370
521
|
};
|
|
371
522
|
|
|
372
523
|
// src/country/countries.ts
|
|
@@ -377,6 +528,7 @@ var COUNTRY_OPTIONS = [
|
|
|
377
528
|
ARS_COUNTRY_OPTION,
|
|
378
529
|
MEX_COUNTRY_OPTION,
|
|
379
530
|
VEN_COUNTRY_OPTION,
|
|
531
|
+
BOB_COUNTRY_OPTION,
|
|
380
532
|
NGN_COUNTRY_OPTION,
|
|
381
533
|
COP_COUNTRY_OPTION,
|
|
382
534
|
CUP_COUNTRY_OPTION,
|
|
@@ -492,9 +644,6 @@ function parseMercadoPago(qrData, _sellPrice) {
|
|
|
492
644
|
return success({ paymentAddress: merchantName });
|
|
493
645
|
}
|
|
494
646
|
|
|
495
|
-
// src/qr-parsers/parsers/brl.ts
|
|
496
|
-
var import_neverthrow2 = require("neverthrow");
|
|
497
|
-
|
|
498
647
|
// src/qr-parsers/utils/amount.ts
|
|
499
648
|
var DECIMAL_AMOUNT = /^\d+(\.\d+)?$/;
|
|
500
649
|
function parseAmount(amountStr, sellPrice) {
|
|
@@ -507,7 +656,44 @@ function parseAmount(amountStr, sellPrice) {
|
|
|
507
656
|
return { usdc: fiat / sellPrice, fiat };
|
|
508
657
|
}
|
|
509
658
|
|
|
659
|
+
// src/qr-parsers/parsers/bob.ts
|
|
660
|
+
var BOB_TAGS = { AMOUNT: "54", CURRENCY: "53", COUNTRY: "58" };
|
|
661
|
+
function isBolivianEncryptedQr2(payload) {
|
|
662
|
+
if (payload.includes("||")) return false;
|
|
663
|
+
const sep = payload.lastIndexOf("|");
|
|
664
|
+
if (sep < 40) return false;
|
|
665
|
+
const blob = payload.slice(0, sep);
|
|
666
|
+
const tag = payload.slice(sep + 1);
|
|
667
|
+
if (blob.length % 4 !== 0) return false;
|
|
668
|
+
if (!/^[A-Za-z0-9+/]+={0,2}$/.test(blob)) return false;
|
|
669
|
+
return /^(?:[0-9A-Fa-f]{24}|[0-9A-Fa-f]{32})$/.test(tag);
|
|
670
|
+
}
|
|
671
|
+
function parseBolivia(qrData, sellPrice) {
|
|
672
|
+
if (!qrData || typeof qrData !== "string" || qrData.trim().length === 0) {
|
|
673
|
+
return failure("INVALID_QR", "QR data is empty or invalid");
|
|
674
|
+
}
|
|
675
|
+
const trimmed = qrData.trim();
|
|
676
|
+
if (isBolivianEncryptedQr2(trimmed)) {
|
|
677
|
+
return success({ paymentAddress: trimmed });
|
|
678
|
+
}
|
|
679
|
+
const tags = extractTags(trimmed, [BOB_TAGS.AMOUNT, BOB_TAGS.CURRENCY, BOB_TAGS.COUNTRY]);
|
|
680
|
+
if (tags[BOB_TAGS.COUNTRY] !== "BO" || tags[BOB_TAGS.CURRENCY] !== "068") {
|
|
681
|
+
return failure("INVALID_QR", "Not a valid Bolivia QR Simple QR");
|
|
682
|
+
}
|
|
683
|
+
const result = { paymentAddress: trimmed };
|
|
684
|
+
const amountStr = tags[BOB_TAGS.AMOUNT];
|
|
685
|
+
if (amountStr) {
|
|
686
|
+
const amount = parseAmount(amountStr, sellPrice);
|
|
687
|
+
if (!amount) {
|
|
688
|
+
return failure("INVALID_AMOUNT", "Invalid amount in QR");
|
|
689
|
+
}
|
|
690
|
+
result.amount = amount;
|
|
691
|
+
}
|
|
692
|
+
return success(result);
|
|
693
|
+
}
|
|
694
|
+
|
|
510
695
|
// src/qr-parsers/parsers/brl.ts
|
|
696
|
+
var import_neverthrow2 = require("neverthrow");
|
|
511
697
|
var PIX_TAGS = {
|
|
512
698
|
PAYLOAD_FORMAT: "00",
|
|
513
699
|
PIX_KEY_INFO: "26",
|
|
@@ -927,17 +1113,22 @@ function parseQRPh(qrData, sellPrice) {
|
|
|
927
1113
|
}
|
|
928
1114
|
|
|
929
1115
|
// src/qr-parsers/parsers/ven.ts
|
|
930
|
-
function
|
|
1116
|
+
function isPagoMovilQr(qrData) {
|
|
931
1117
|
if (!qrData || typeof qrData !== "string" || qrData.trim().length === 0) {
|
|
932
|
-
return
|
|
1118
|
+
return false;
|
|
933
1119
|
}
|
|
934
1120
|
const trimmed = qrData.trim();
|
|
935
1121
|
const qIdx = trimmed.indexOf("?");
|
|
936
|
-
if (qIdx === -1)
|
|
937
|
-
return failure("INVALID_QR", "Not a valid Venezuelan QR code");
|
|
938
|
-
}
|
|
1122
|
+
if (qIdx === -1) return false;
|
|
939
1123
|
const payload = trimmed.substring(0, qIdx);
|
|
940
|
-
|
|
1124
|
+
return !!payload && /^[A-Za-z0-9+/=]+$/.test(payload);
|
|
1125
|
+
}
|
|
1126
|
+
function parsePagoMovil(qrData, _sellPrice) {
|
|
1127
|
+
if (!qrData || typeof qrData !== "string" || qrData.trim().length === 0) {
|
|
1128
|
+
return failure("INVALID_QR", "QR data is empty or invalid");
|
|
1129
|
+
}
|
|
1130
|
+
const trimmed = qrData.trim();
|
|
1131
|
+
if (!isPagoMovilQr(trimmed)) {
|
|
941
1132
|
return failure("INVALID_QR", "Not a valid Venezuelan QR code");
|
|
942
1133
|
}
|
|
943
1134
|
return success({ paymentAddress: trimmed });
|
|
@@ -960,6 +1151,8 @@ async function parseQR(params) {
|
|
|
960
1151
|
return parseMercadoPago(qrData, sellPrice);
|
|
961
1152
|
case CURRENCY.VEN:
|
|
962
1153
|
return parsePagoMovil(qrData, sellPrice);
|
|
1154
|
+
case CURRENCY.BOB:
|
|
1155
|
+
return parseBolivia(qrData, sellPrice);
|
|
963
1156
|
case CURRENCY.NGN:
|
|
964
1157
|
return parseNGN(qrData, sellPrice);
|
|
965
1158
|
case CURRENCY.COP:
|
|
@@ -979,6 +1172,7 @@ async function parseQR(params) {
|
|
|
979
1172
|
// Annotate the CommonJS export names for ESM import in node:
|
|
980
1173
|
0 && (module.exports = {
|
|
981
1174
|
QRParserError,
|
|
1175
|
+
isPagoMovilQr,
|
|
982
1176
|
parseQR
|
|
983
1177
|
});
|
|
984
1178
|
//# sourceMappingURL=qr-parsers.cjs.map
|