@amboras-dev/money 0.2.0 → 0.4.0
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 +22 -11
- package/dist/ai.cjs +12 -13
- package/dist/ai.d.cts +5 -9
- package/dist/ai.d.ts +5 -9
- package/dist/ai.js +12 -13
- package/dist/{allocate-CZRg4TOP.cjs → allocate-AusholrC.cjs} +3 -4
- package/dist/{allocate-X7_jAtOj.js → allocate-BBRfdaSC.js} +3 -4
- package/dist/{amount-BV0O-aN8.cjs → amount-Bzxw9aD4.cjs} +32 -14
- package/dist/{amount-BoYBMgK9.js → amount-off8IMBJ.js} +32 -14
- package/dist/{arithmetic-BhNwisjb.js → arithmetic-C97-YafD.js} +4 -5
- package/dist/{arithmetic-DjT4Kzgt.cjs → arithmetic-D8A6IeZ0.cjs} +4 -5
- package/dist/billing.cjs +5 -8
- package/dist/billing.d.cts +1 -9
- package/dist/billing.d.ts +1 -9
- package/dist/billing.js +5 -8
- package/dist/commerce.cjs +15 -23
- package/dist/commerce.d.cts +2 -16
- package/dist/commerce.d.ts +2 -16
- package/dist/commerce.js +15 -23
- package/dist/{format-DLhno7eX.cjs → format-92fzvTXY.cjs} +9 -9
- package/dist/{format-BdPnijvn.js → format-BJC513u4.js} +9 -9
- package/dist/fx.cjs +12 -18
- package/dist/fx.d.cts +5 -15
- package/dist/fx.d.ts +5 -15
- package/dist/fx.js +12 -18
- package/dist/index.cjs +10 -12
- package/dist/index.d.cts +17 -23
- package/dist/index.d.ts +17 -23
- package/dist/index.js +10 -12
- package/dist/input.cjs +7 -10
- package/dist/input.d.cts +16 -22
- package/dist/input.d.ts +16 -22
- package/dist/input.js +7 -10
- package/dist/{iso-minor-wSwJN57T.cjs → iso-minor-DyNjT9A1.cjs} +2 -3
- package/dist/{iso-minor-CqkWDxHS.js → iso-minor-odkY-e6I.js} +2 -3
- package/dist/{medusa-lRY9xlsf.cjs → medusa-CzVK0bth.cjs} +3 -4
- package/dist/{medusa-DBXJXXvF.d.ts → medusa-DofdvIgQ.d.cts} +1 -3
- package/dist/{medusa-4K8N1pUc.d.cts → medusa-DrbYmD2Y.d.ts} +1 -3
- package/dist/{medusa-DqJY1qpj.js → medusa-pKGlImn9.js} +3 -4
- package/dist/{money-B-3aFjNJ.d.cts → money-BkMeYDEW.d.cts} +0 -6
- package/dist/{money-B-3aFjNJ.d.ts → money-BkMeYDEW.d.ts} +0 -6
- package/dist/{money-WhnGiI00.js → money-BxbAw7BP.js} +7 -15
- package/dist/{money-B3wH_Z4S.cjs → money-DWBjuuEK.cjs} +7 -15
- package/dist/{number-text-DE-q4jO5.js → number-text-Bj-gZXiF.js} +3 -4
- package/dist/{number-text-BWu67jUq.cjs → number-text-CWuVwrlg.cjs} +3 -4
- package/dist/{own-oP9DXFWv.cjs → own-C5imDkyB.cjs} +1 -2
- package/dist/{own-D7544D3k.js → own-DHxqIYqL.js} +1 -2
- package/dist/{percent-D1VB9xXG.js → percent-CB3Ixjc_.js} +2 -3
- package/dist/{percent-C0InC2t2.cjs → percent-DABHiSBs.cjs} +2 -3
- package/dist/{rate-DBPiYgT1.d.ts → rate-BvvZUdSu.d.ts} +1 -3
- package/dist/{rate-tqK8ijG0.d.cts → rate-CEakW3ia.d.cts} +1 -3
- package/dist/{rate-CVeMii4a.cjs → rate-CEjWTATc.cjs} +3 -4
- package/dist/{rate-DicStBue.js → rate-D6S2_wgZ.js} +3 -4
- package/dist/{reporting-tpGJbqYp.d.ts → reporting-DFNyDBdi.d.cts} +2 -4
- package/dist/{reporting-CG-ai2sM.d.cts → reporting-jIBILvnr.d.ts} +2 -4
- package/dist/{retail-DRUTTQoJ.d.ts → retail-B04CjW3b.d.ts} +1 -3
- package/dist/{retail-Cml8YSKg.cjs → retail-CYGPU4ea.cjs} +4 -5
- package/dist/{retail-C_BPLvMj.d.cts → retail-CmEyJQOH.d.cts} +1 -3
- package/dist/{retail-1mu888J1.js → retail-DXgs11ov.js} +4 -5
- package/dist/{rounding-DHBtNCHG.cjs → rounding-4QKTRbMQ.cjs} +2 -3
- package/dist/{rounding-g9rvye0k.js → rounding-CA1PVP3b.js} +2 -3
- package/dist/sql.cjs +9 -15
- package/dist/sql.d.cts +2 -12
- package/dist/sql.d.ts +2 -12
- package/dist/sql.js +9 -15
- package/dist/testing.cjs +39198 -12
- package/dist/testing.d.cts +20 -13
- package/dist/testing.d.ts +20 -13
- package/dist/testing.js +39198 -13
- package/dist/{wire-sW0yzqth.js → wire-B4QU8O3W.js} +350 -93
- package/dist/{wire-CaUN9Vf_.d.ts → wire-CVNicirK.d.ts} +165 -46
- package/dist/{wire-xjYXv4go.d.cts → wire-CtNJmWVP.d.cts} +165 -46
- package/dist/{wire-Bhuut8cW.cjs → wire-u2tmHY0Y.cjs} +403 -92
- package/dist/wire.cjs +10 -1
- package/dist/wire.d.cts +2 -2
- package/dist/wire.d.ts +2 -2
- package/dist/wire.js +1 -2
- package/package.json +4 -3
|
@@ -1,32 +1,9 @@
|
|
|
1
|
-
const require_money = require("./money-
|
|
2
|
-
const require_allocate = require("./allocate-
|
|
3
|
-
const require_own = require("./own-
|
|
4
|
-
const require_iso_minor = require("./iso-minor-
|
|
5
|
-
const require_number_text = require("./number-text-
|
|
6
|
-
|
|
7
|
-
const escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
8
|
-
/**
|
|
9
|
-
* The first `"<field>": <decimal>` (quoted or not) in a raw JSON body, verbatim: `JSON.parse`
|
|
10
|
-
* would turn the gateway's `43.00` into `43`. The value is the whole JSON token, held to
|
|
11
|
-
* `parseDecimal`'s `'plain'` grammar (`1e3` or `"43.10abc"` is not a decimal literal).
|
|
12
|
-
* Undefined when absent; there is no lossy fallback.
|
|
13
|
-
*/
|
|
14
|
-
function jsonDecimalLiteral(rawBody, field) {
|
|
15
|
-
if (typeof rawBody !== "string" || typeof field !== "string") return void 0;
|
|
16
|
-
const tokens = rawBody.matchAll(new RegExp(`"${escapeRegExp(field)}"\\s*:\\s*("?)([^"\\s,}\\]]+)\\1`, "g"));
|
|
17
|
-
for (const [, , token] of tokens) if (require_money.parseDecimal(token, "plain")) return token;
|
|
18
|
-
}
|
|
19
|
-
const isPositiveLiteral = (text) => {
|
|
20
|
-
const value = require_money.parseDecimal(text.trim());
|
|
21
|
-
return value !== null && value.units > 0n;
|
|
22
|
-
};
|
|
23
|
-
function authorizeNetReversibleAmount(details) {
|
|
24
|
-
const settle = details.settleAmount ?? void 0;
|
|
25
|
-
if (settle !== void 0 && isPositiveLiteral(settle)) return settle;
|
|
26
|
-
return details.authAmount ?? settle;
|
|
27
|
-
}
|
|
28
|
-
//#endregion
|
|
29
|
-
//#region src/data/psp.ts
|
|
1
|
+
const require_money = require("./money-DWBjuuEK.cjs");
|
|
2
|
+
const require_allocate = require("./allocate-AusholrC.cjs");
|
|
3
|
+
const require_own = require("./own-C5imDkyB.cjs");
|
|
4
|
+
const require_iso_minor = require("./iso-minor-DyNjT9A1.cjs");
|
|
5
|
+
const require_number_text = require("./number-text-CWuVwrlg.cjs");
|
|
6
|
+
// src/data/psp.ts
|
|
30
7
|
/** developer.paypal.com/reference/currency-codes ("Last updated: August 17, 2026"). */
|
|
31
8
|
const PAYPAL_CURRENCY_DIGITS = {
|
|
32
9
|
0: [
|
|
@@ -519,15 +496,17 @@ const RAZORPAY_CURRENCY_EXPONENTS = {
|
|
|
519
496
|
"TND"
|
|
520
497
|
]
|
|
521
498
|
};
|
|
522
|
-
/**
|
|
523
|
-
const
|
|
499
|
+
/** paystack.com/docs/api/#supported-currency (retrieved 2026-10-07): every currency a Paystack account can charge. */
|
|
500
|
+
const PAYSTACK_CURRENCIES = [
|
|
524
501
|
"GHS",
|
|
525
502
|
"KES",
|
|
526
503
|
"NGN",
|
|
527
504
|
"USD",
|
|
528
505
|
"XOF",
|
|
529
506
|
"ZAR"
|
|
530
|
-
]
|
|
507
|
+
];
|
|
508
|
+
/** Paystack: "If we notice a fractional part during processing, we ignore the fractional part." */
|
|
509
|
+
const PAYSTACK_CURRENCY_DIGITS = { 2: PAYSTACK_CURRENCIES };
|
|
531
510
|
/** Factor-1 overrides: ISO zero-decimal codes the PSP wants at two decimals (storage and wire agree). */
|
|
532
511
|
const STRIPE_SENT_AS_TWO_DECIMAL = ["ISK", "UGX"];
|
|
533
512
|
const ADYEN_SENT_AS_TWO_DECIMAL = ["ISK", "CLP"];
|
|
@@ -1000,6 +979,101 @@ const AUTHORIZE_NET_CURRENCIES = [
|
|
|
1000
979
|
"PLN"
|
|
1001
980
|
];
|
|
1002
981
|
const VND_ONLY = ["VND"];
|
|
982
|
+
/**
|
|
983
|
+
* The account countries a PSP onboards, for PSPs whose accounts each charge a per-country list.
|
|
984
|
+
* Paystack: support.paystack.com/en/articles/2130690 "Enabling international payments for your
|
|
985
|
+
* business" (retrieved 2026-10-26): "Côte d'Ivoire XOF", "Ghana GHS", "Kenya KES, USD", "Nigeria
|
|
986
|
+
* NGN, USD", "South Africa ZAR", and "At the moment, only Kenya and Nigeria-based businesses have
|
|
987
|
+
* the ability to accept payments for their business in USD and be paid out in USD". USD has to be
|
|
988
|
+
* enabled on the account first (the article is how to enable it), and no Paystack API reports
|
|
989
|
+
* whether it is, so USD is `optIn`, never in `currencies`.
|
|
990
|
+
*/
|
|
991
|
+
const PSP_ACCOUNT_COUNTRIES = { paystack: {
|
|
992
|
+
CI: { currencies: ["XOF"] },
|
|
993
|
+
GH: { currencies: ["GHS"] },
|
|
994
|
+
KE: {
|
|
995
|
+
currencies: ["KES"],
|
|
996
|
+
optIn: ["USD"]
|
|
997
|
+
},
|
|
998
|
+
NG: {
|
|
999
|
+
currencies: ["NGN"],
|
|
1000
|
+
optIn: ["USD"]
|
|
1001
|
+
},
|
|
1002
|
+
ZA: { currencies: ["ZAR"] }
|
|
1003
|
+
} };
|
|
1004
|
+
/**
|
|
1005
|
+
* The currency every account of a multi-currency PSP charges without enabling anything; any other
|
|
1006
|
+
* needs the account's international or multi-currency add-on. The single-currency PSPs (MoMo,
|
|
1007
|
+
* VNPay, Payoo: `VND_ONLY`) are not restated here: their home currency is their one currency.
|
|
1008
|
+
* Razorpay: razorpay.com/docs/payments/international-payments (retrieved 2026-10-26) says "The final
|
|
1009
|
+
* settlement is done in the bank accounts of Indian businesses in INR", with international
|
|
1010
|
+
* payments activated under Account & Settings, and razorpay.com/docs/sg/payments/international-payments/faqs
|
|
1011
|
+
* (retrieved 2026-10-27): "The Settlement currency is INR (Indian rupees) for all transactions made
|
|
1012
|
+
* using Razorpay". This is the settlement currency only; it says nothing about where the account is
|
|
1013
|
+
* registered (Razorpay has no entry in `PSP_HOME_COUNTRY`). iyzico help centre (quoted in Medusa
|
|
1014
|
+
* `capabilities/iyzico.ts`, 2026-10-07; re-read 2026-10-26): "payments you take in foreign
|
|
1015
|
+
* currencies are exchanged into Turkish Liras", taking them needs the paid Multi Currency add-on.
|
|
1016
|
+
*/
|
|
1017
|
+
const PSP_HOME_CURRENCY = {
|
|
1018
|
+
razorpay: "INR",
|
|
1019
|
+
iyzico: "TRY"
|
|
1020
|
+
};
|
|
1021
|
+
/**
|
|
1022
|
+
* The one country every account of a PSP is registered in, for PSPs whose accounts are all
|
|
1023
|
+
* registered in a single country. Razorpay is left out: the same FAQ lists it as available in India,
|
|
1024
|
+
* Malaysia (Curlec), Singapore and the United States, so its accounts are not all registered in one
|
|
1025
|
+
* country, and a Singapore or US account must not read as IN. iyzico: consistent with orch `account-facts.ts`
|
|
1026
|
+
* `PROVIDER_CONSTANT_FACTS` (2026-10-26), which records TR, and with its Turkish-lira settlement
|
|
1027
|
+
* above. MoMo, VNPay, Payoo: domestic Vietnamese rails that take VND only (`VND_ONLY`), carried over
|
|
1028
|
+
* from the same `PROVIDER_CONSTANT_FACTS`.
|
|
1029
|
+
*/
|
|
1030
|
+
const PSP_HOME_COUNTRY = {
|
|
1031
|
+
iyzico: "TR",
|
|
1032
|
+
momo: "VN",
|
|
1033
|
+
vnpay: "VN",
|
|
1034
|
+
payoo: "VN"
|
|
1035
|
+
};
|
|
1036
|
+
/**
|
|
1037
|
+
* The currency of a saved-method verification charge when the caller has none, where the PSP
|
|
1038
|
+
* documents one. `only`: the PSP verifies in that currency alone, so any other is refused.
|
|
1039
|
+
* Razorpay: recurring payment orders take a currency where "currently, only INR is allowed"
|
|
1040
|
+
* (razorpay.com/docs/api/payments/recurring-payments/emandate/create-subsequent-payments, retrieved
|
|
1041
|
+
* 2026-10-26), so its verification is INR only. Mollie: docs.mollie.com/docs/multicurrency
|
|
1042
|
+
* (retrieved 2026-10-27) lists EUR as supported by "All payment methods except BACS, Blik, Swish
|
|
1043
|
+
* and Twint", so every card method takes EUR and a card verification can fall back to it. Adyen
|
|
1044
|
+
* and Paystack publish no such currency: Adyen's zero-amount verification takes whatever the
|
|
1045
|
+
* merchant account processes, and a Paystack account charges its own country's currency, so their
|
|
1046
|
+
* callers must pass one.
|
|
1047
|
+
*/
|
|
1048
|
+
const VERIFICATION_CURRENCY = {
|
|
1049
|
+
razorpay: {
|
|
1050
|
+
code: "INR",
|
|
1051
|
+
only: true
|
|
1052
|
+
},
|
|
1053
|
+
mollie: {
|
|
1054
|
+
code: "EUR",
|
|
1055
|
+
only: false
|
|
1056
|
+
}
|
|
1057
|
+
};
|
|
1058
|
+
/**
|
|
1059
|
+
* The PSPs whose wire amount Medusa computed in floating point before it adopted 0.2.0: major
|
|
1060
|
+
* units as `(stored / storageScale).toFixed(wireDigits)` on a double (Airwallex and Payoo then
|
|
1061
|
+
* `Number(...)` of that text). Source: Medusa `src/common/money/codec.ts` `majorStringCodec` /
|
|
1062
|
+
* `majorNumberCodec` and `psp-codecs.ts` (staging 785bd0420, 2026-10-27), and the same expression
|
|
1063
|
+
* in each provider's `amount.ts` before that codec existed (`03989fd4e^`). The stored amount was
|
|
1064
|
+
* `Number()` of Medusa's amount, unrounded. At an exact tie the double can sit just below it, so
|
|
1065
|
+
* USD 1072.5 went as `'10.72'` where 0.2.0 sends `'10.73'`; `sameWireAmount`'s
|
|
1066
|
+
* `acceptLegacyFloatRounding` reads that spelling. Payoo is listed because it used the same codec,
|
|
1067
|
+
* but its whole-dong rule leaves it no tie, so its float spelling is always the exact one.
|
|
1068
|
+
*/
|
|
1069
|
+
const PSP_LEGACY_FLOAT_TO_FIXED = [
|
|
1070
|
+
"paypal",
|
|
1071
|
+
"mollie",
|
|
1072
|
+
"airwallex",
|
|
1073
|
+
"iyzico",
|
|
1074
|
+
"authorize-net",
|
|
1075
|
+
"payoo"
|
|
1076
|
+
];
|
|
1003
1077
|
/** orch `MINIMUM_AMOUNT_BY_CURRENCY`, majors. */
|
|
1004
1078
|
const PSP_MINIMUM_MAJOR = { paystack: { USD: "2.00" } };
|
|
1005
1079
|
/** RBI e-mandate AFA-free cap: INR 15,000 (razorpay-vault `15_000_00` paise, seam `1_500_000`). */
|
|
@@ -1014,8 +1088,29 @@ const PROVIDER_ONLY_CURRENCIES = { CNH: {
|
|
|
1014
1088
|
name: "Chinese Yuan (offshore)",
|
|
1015
1089
|
psps: ["adyen"]
|
|
1016
1090
|
} };
|
|
1017
|
-
|
|
1018
|
-
|
|
1091
|
+
// src/wire/anet.ts
|
|
1092
|
+
const escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1093
|
+
/**
|
|
1094
|
+
* The first `"<field>": <decimal>` (quoted or not) in a raw JSON body, verbatim: `JSON.parse`
|
|
1095
|
+
* would turn the gateway's `43.00` into `43`. The value is the whole JSON token, held to
|
|
1096
|
+
* `parseDecimal`'s `'plain'` grammar (`1e3` or `"43.10abc"` is not a decimal literal).
|
|
1097
|
+
* Undefined when absent; there is no lossy fallback.
|
|
1098
|
+
*/
|
|
1099
|
+
function jsonDecimalLiteral(rawBody, field) {
|
|
1100
|
+
if (typeof rawBody !== "string" || typeof field !== "string") return void 0;
|
|
1101
|
+
const tokens = rawBody.matchAll(new RegExp(`"${escapeRegExp(field)}"\\s*:\\s*("?)([^"\\s,}\\]]+)\\1`, "g"));
|
|
1102
|
+
for (const [, , token] of tokens) if (require_money.parseDecimal(token, "plain")) return token;
|
|
1103
|
+
}
|
|
1104
|
+
const isPositiveLiteral = (text) => {
|
|
1105
|
+
const value = require_money.parseDecimal(text.trim());
|
|
1106
|
+
return value !== null && value.units > 0n;
|
|
1107
|
+
};
|
|
1108
|
+
function authorizeNetReversibleAmount(details) {
|
|
1109
|
+
const settle = details.settleAmount ?? void 0;
|
|
1110
|
+
if (settle !== void 0 && isPositiveLiteral(settle)) return settle;
|
|
1111
|
+
return details.authAmount ?? settle;
|
|
1112
|
+
}
|
|
1113
|
+
// src/wire/currency.ts
|
|
1019
1114
|
/** The registry entry (any case, historic included) for `input`, else null. Never throws. */
|
|
1020
1115
|
function wireCurrency(input) {
|
|
1021
1116
|
return require_money.findCurrency(input, { allowHistoric: true });
|
|
@@ -1070,8 +1165,17 @@ function wireStoredDecimal(m) {
|
|
|
1070
1165
|
stored: require_money.normalizeDecimal(parsed)
|
|
1071
1166
|
};
|
|
1072
1167
|
}
|
|
1073
|
-
|
|
1074
|
-
|
|
1168
|
+
// src/wire/descriptors.ts
|
|
1169
|
+
function accountCountries(id) {
|
|
1170
|
+
const table = PSP_ACCOUNT_COUNTRIES[id] ?? {};
|
|
1171
|
+
return new Map(Object.keys(table).map((country) => {
|
|
1172
|
+
const entry = {
|
|
1173
|
+
currencies: new Set(table[country].currencies),
|
|
1174
|
+
optIn: new Set(table[country].optIn ?? [])
|
|
1175
|
+
};
|
|
1176
|
+
return [country, Object.freeze(entry)];
|
|
1177
|
+
}));
|
|
1178
|
+
}
|
|
1075
1179
|
function digitTable(groups) {
|
|
1076
1180
|
const table = /* @__PURE__ */ new Map();
|
|
1077
1181
|
for (const digits of [
|
|
@@ -1113,7 +1217,12 @@ function describe(id, input) {
|
|
|
1113
1217
|
singleCurrency: input.singleCurrency ?? null,
|
|
1114
1218
|
unsupported: input.unsupported ?? genericUnsupported(input.tag),
|
|
1115
1219
|
facadeAccepts: input.facadeAccepts ?? scalesAnyCurrency,
|
|
1116
|
-
inboundWholePositive: input.inboundWholePositive ?? false
|
|
1220
|
+
inboundWholePositive: input.inboundWholePositive ?? false,
|
|
1221
|
+
homeCurrency: PSP_HOME_CURRENCY[id] ?? input.singleCurrency ?? null,
|
|
1222
|
+
homeCountry: PSP_HOME_COUNTRY[id] ?? null,
|
|
1223
|
+
accountCountries: accountCountries(id),
|
|
1224
|
+
verificationCurrency: VERIFICATION_CURRENCY[id] ?? null,
|
|
1225
|
+
legacyFloatToFixed: PSP_LEGACY_FLOAT_TO_FIXED.includes(id)
|
|
1117
1226
|
});
|
|
1118
1227
|
}
|
|
1119
1228
|
const notTwoDecimalAtStripe = new Set(STRIPE_NOT_TWO_DECIMAL);
|
|
@@ -1266,8 +1375,7 @@ function pspDescriptor(psp) {
|
|
|
1266
1375
|
if (typeof psp === "string" && require_own.hasOwnKey(PSP_DESCRIPTORS, psp)) return PSP_DESCRIPTORS[psp];
|
|
1267
1376
|
throw new require_money.MoneyError("wire_unsupported", `Unknown payment provider: ${require_money.describeValue(psp)}`);
|
|
1268
1377
|
}
|
|
1269
|
-
|
|
1270
|
-
//#region src/wire/marker.ts
|
|
1378
|
+
// src/wire/marker.ts
|
|
1271
1379
|
const WIRE_SCALE_KEY = "amboras_wire_scale";
|
|
1272
1380
|
const WIRE_SCALE_ISO_MINOR_V2 = "iso-minor-v2";
|
|
1273
1381
|
const WIRE_SCALE_MARKER = Object.freeze({ [WIRE_SCALE_KEY]: WIRE_SCALE_ISO_MINOR_V2 });
|
|
@@ -1286,8 +1394,19 @@ function conventionKind(value) {
|
|
|
1286
1394
|
const kind = typeof value === "object" && value !== null ? value.kind : void 0;
|
|
1287
1395
|
return kind === "iso-minor-v2" || kind === "pre-cutover" ? kind : null;
|
|
1288
1396
|
}
|
|
1289
|
-
|
|
1290
|
-
|
|
1397
|
+
const WIRE_ROUNDING_KEY = "amboras_wire_rounding";
|
|
1398
|
+
const WIRE_ROUNDING_EXACT = "exact";
|
|
1399
|
+
const WIRE_ROUNDING_MARKER = Object.freeze({ [WIRE_ROUNDING_KEY]: WIRE_ROUNDING_EXACT });
|
|
1400
|
+
/**
|
|
1401
|
+
* Whether a payment may be held at the PSP in Medusa's pre-0.2.0 float spelling: no record is a
|
|
1402
|
+
* non-null object whose `amboras_wire_rounding` is strictly `'exact'`. Pass the result as
|
|
1403
|
+
* `sameWireAmount`'s `acceptLegacyFloatRounding`, so only sessions created before the deploy get
|
|
1404
|
+
* the legacy spelling. Reads already fetched records only.
|
|
1405
|
+
*/
|
|
1406
|
+
function mayHoldLegacyFloatRounding(...records) {
|
|
1407
|
+
return !records.some((r) => typeof r === "object" && r !== null && r["amboras_wire_rounding"] === "exact");
|
|
1408
|
+
}
|
|
1409
|
+
// src/wire/codec.ts
|
|
1291
1410
|
const isBlank = (value) => value === null || value === void 0 || typeof value === "string" && value.trim() === "";
|
|
1292
1411
|
const shownCode = (currency) => typeof currency === "string" ? currency.trim().toUpperCase() : require_money.describeValue(currency);
|
|
1293
1412
|
function missingCurrency(d) {
|
|
@@ -1318,7 +1437,8 @@ function pspCurrencies(psp) {
|
|
|
1318
1437
|
/**
|
|
1319
1438
|
* `currency` as a CurrencyCode `psp` takes. Empty throws `currency_missing` (`[<Tag>] Cannot
|
|
1320
1439
|
* scale an amount without a currency code; ...`); anything the PSP does not take throws
|
|
1321
|
-
* `wire_unsupported` with the provider's own message.
|
|
1440
|
+
* `wire_unsupported` with the provider's own message. Typed as the PSP's literal union where it
|
|
1441
|
+
* has a short fixed list (`assertPspCurrency('authorize-net', c)` is an `AuthorizeNetCurrency`).
|
|
1322
1442
|
*/
|
|
1323
1443
|
function assertPspCurrency(psp, currency) {
|
|
1324
1444
|
const d = pspDescriptor(psp);
|
|
@@ -1349,6 +1469,28 @@ function pspDefaultCurrency(psp) {
|
|
|
1349
1469
|
const single = pspDescriptor(psp).singleCurrency;
|
|
1350
1470
|
return single === null ? null : single;
|
|
1351
1471
|
}
|
|
1472
|
+
/**
|
|
1473
|
+
* The currency every account of `psp` charges without enabling anything (any other needs the
|
|
1474
|
+
* account's international or multi-currency add-on, or is never taken): Razorpay INR, iyzico TRY,
|
|
1475
|
+
* and for the single-currency PSPs their one currency (MoMo, VNPay and Payoo VND). Null for PSPs
|
|
1476
|
+
* whose accounts have no single home currency (Stripe, Adyen, PayPal, Mollie, Airwallex, Authorize.Net, and Paystack, whose home currency is the
|
|
1477
|
+
* account country's: `pspPresentment('paystack').accountCountries`). Unlike `pspDefaultCurrency`,
|
|
1478
|
+
* which is non-null only for the single-currency PSPs, a home currency does not mean the PSP takes
|
|
1479
|
+
* nothing else.
|
|
1480
|
+
*/
|
|
1481
|
+
function pspHomeCurrency(psp) {
|
|
1482
|
+
const home = pspDescriptor(psp).homeCurrency;
|
|
1483
|
+
return home === null ? null : home;
|
|
1484
|
+
}
|
|
1485
|
+
/**
|
|
1486
|
+
* The one country (ISO 3166 alpha-2) every account of `psp` is registered in, for PSPs whose
|
|
1487
|
+
* accounts are all registered in a single country: iyzico `'TR'`, MoMo, VNPay and Payoo `'VN'`. Null
|
|
1488
|
+
* for PSPs available in several countries: Razorpay (India, Malaysia, Singapore, the United States)
|
|
1489
|
+
* and Paystack (its country follows the account: `pspAccountCountryForCurrency`).
|
|
1490
|
+
*/
|
|
1491
|
+
function pspHomeCountry(psp) {
|
|
1492
|
+
return pspDescriptor(psp).homeCountry;
|
|
1493
|
+
}
|
|
1352
1494
|
function factorOf(d, info) {
|
|
1353
1495
|
if (d.sentAsTwoDecimal.has(info.code)) return 1n;
|
|
1354
1496
|
if (d.sentAsZeroDecimal.has(info.code)) return 100n;
|
|
@@ -1480,8 +1622,18 @@ function decodeChecked(d, wire, currency, convention, allowNegative, exact = fal
|
|
|
1480
1622
|
if (w.units < 0n && !allowNegative) throw new require_money.MoneyError("amount_invalid", `[${d.tag}] Negative wire amount: ${require_money.describeValue(wire)}`);
|
|
1481
1623
|
return decodeWith(d, w, info, kind, exact);
|
|
1482
1624
|
}
|
|
1483
|
-
function
|
|
1484
|
-
|
|
1625
|
+
function decodeOptions(d, options, extra) {
|
|
1626
|
+
const notAnOptionsObject = options !== void 0 && (typeof options !== "object" || options === null || require_own.hasOwnKey(options, "kind"));
|
|
1627
|
+
if (extra.length > 0 || notAnOptionsObject) {
|
|
1628
|
+
const message = `[${d.tag}] decodeWire takes one options object ({ convention, allowNegative }) as its fourth argument.`;
|
|
1629
|
+
throw new require_money.MoneyError("wire_refused", message);
|
|
1630
|
+
}
|
|
1631
|
+
return options ?? {};
|
|
1632
|
+
}
|
|
1633
|
+
function decodeWire(psp, wire, currency, options, ...extra) {
|
|
1634
|
+
const d = pspDescriptor(psp);
|
|
1635
|
+
const { convention, allowNegative } = decodeOptions(d, options, extra);
|
|
1636
|
+
return decodeChecked(d, wire, currency, convention, allowNegative === true);
|
|
1485
1637
|
}
|
|
1486
1638
|
/**
|
|
1487
1639
|
* `decodeWire` that never throws: undefined wherever it would throw (null, undefined, `''`,
|
|
@@ -1516,6 +1668,20 @@ function legacyIsoMajor(m) {
|
|
|
1516
1668
|
};
|
|
1517
1669
|
return require_money.formatDecimal(require_money.roundToScale(major, info.displayDigits, "half-up"));
|
|
1518
1670
|
}
|
|
1671
|
+
/**
|
|
1672
|
+
* Internal: `m` as Medusa's pre-0.2.0 float codec spelled it for a `legacyFloatToFixed` PSP, at
|
|
1673
|
+
* the PSP's wire digits, or with `isoDigits` at the display digits (the pre-PSP-table spelling):
|
|
1674
|
+
* `(Number(amount) / storageScale).toFixed(digits)`, computed on a double on purpose, because
|
|
1675
|
+
* that is what the PSP holds for a payment created before 0.2.0 (USD 1072.5 is `'10.72'`).
|
|
1676
|
+
* Null for a PSP that never encoded in floating point.
|
|
1677
|
+
*/
|
|
1678
|
+
function legacyFloatMajor(psp, m, isoDigits) {
|
|
1679
|
+
const d = pspDescriptor(psp);
|
|
1680
|
+
if (!d.legacyFloatToFixed) return null;
|
|
1681
|
+
const { info } = wireStoredDecimal(m);
|
|
1682
|
+
const digits = isoDigits ? info.displayDigits : wireDigitsOf(d, info);
|
|
1683
|
+
return (Number(m.amount) / info.storageScale).toFixed(digits);
|
|
1684
|
+
}
|
|
1519
1685
|
/** Internal: one unit of the PSP's last wire digit as Money. */
|
|
1520
1686
|
function wireUnit(psp, currency, convention) {
|
|
1521
1687
|
const d = pspDescriptor(psp);
|
|
@@ -1526,8 +1692,7 @@ function wireUnit(psp, currency, convention) {
|
|
|
1526
1692
|
}, info, d.gated ? requireConvention(d, convention) : null);
|
|
1527
1693
|
return require_money.boundedMoney(require_iso_minor.isoMinorFactor(info, wireDigitsOf(d, info)), info);
|
|
1528
1694
|
}
|
|
1529
|
-
|
|
1530
|
-
//#region src/wire/breakdown.ts
|
|
1695
|
+
// src/wire/breakdown.ts
|
|
1531
1696
|
/**
|
|
1532
1697
|
* `total` and its `parts` (same currency, non-negative, adding up to `total`) as integer wire
|
|
1533
1698
|
* amounts whose sum is exactly `encodeWire(psp, total)`: the wire total split by largest
|
|
@@ -1558,8 +1723,7 @@ function wireBreakdown(psp, total, parts, convention) {
|
|
|
1558
1723
|
parts: out
|
|
1559
1724
|
};
|
|
1560
1725
|
}
|
|
1561
|
-
|
|
1562
|
-
//#region src/wire/compare.ts
|
|
1726
|
+
// src/wire/compare.ts
|
|
1563
1727
|
/**
|
|
1564
1728
|
* Whether a PSP-reported amount is `expected`, a Money or a FractionalMoney (Medusa's unrounded
|
|
1565
1729
|
* session total). The expected wire is `encodeWire(psp, expected, { convention, allowZero: true })`
|
|
@@ -1574,7 +1738,10 @@ function sameWireAmount(psp, reported, expected, options = {}) {
|
|
|
1574
1738
|
const reportedInfo = wireCurrency(options.reportedCurrency);
|
|
1575
1739
|
if (reportedInfo === null || reportedInfo !== wireCurrency(expected.currency)) return false;
|
|
1576
1740
|
}
|
|
1577
|
-
const targets = expectedTargets(psp, expected, convention,
|
|
1741
|
+
const targets = expectedTargets(psp, expected, convention, {
|
|
1742
|
+
isoDigits: options.acceptLegacyIsoDigits === true,
|
|
1743
|
+
floatRounding: options.acceptLegacyFloatRounding === true
|
|
1744
|
+
});
|
|
1578
1745
|
if (targets === null) return false;
|
|
1579
1746
|
const { target, legacy } = targets;
|
|
1580
1747
|
const decode = (value) => options.textOnly && typeof value !== "string" ? void 0 : tryDecodeWireExactly(psp, value, expected.currency, convention);
|
|
@@ -1586,10 +1753,14 @@ function sameWireAmount(psp, reported, expected, options = {}) {
|
|
|
1586
1753
|
}
|
|
1587
1754
|
const got = decode(reported);
|
|
1588
1755
|
if (got === void 0) return false;
|
|
1589
|
-
return got.amount === target.amount ||
|
|
1756
|
+
return got.amount === target.amount || legacy.some((m) => m.amount === got.amount);
|
|
1590
1757
|
}
|
|
1591
|
-
/**
|
|
1592
|
-
|
|
1758
|
+
/**
|
|
1759
|
+
* What `expected` decodes to once sent, and to in each accepted legacy spelling (the exact
|
|
1760
|
+
* ISO-digit one; the pre-0.2.0 float one at the wire digits, and at the ISO digits too when both
|
|
1761
|
+
* are accepted), or null when it cannot be sent.
|
|
1762
|
+
*/
|
|
1763
|
+
function expectedTargets(psp, expected, convention, accept) {
|
|
1593
1764
|
try {
|
|
1594
1765
|
const d = pspDescriptor(psp);
|
|
1595
1766
|
const wire = encodeWire(psp, expected, {
|
|
@@ -1597,21 +1768,22 @@ function expectedTargets(psp, expected, convention, acceptLegacy) {
|
|
|
1597
1768
|
allowZero: true
|
|
1598
1769
|
});
|
|
1599
1770
|
const target = decodeAt(psp, wire, expected, convention);
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
const
|
|
1771
|
+
const spellings = [];
|
|
1772
|
+
if (accept.isoDigits && d.family !== "iso-minor") spellings.push(legacyIsoMajor(expected));
|
|
1773
|
+
if (accept.floatRounding) spellings.push(legacyFloatMajor(psp, expected, false));
|
|
1774
|
+
if (accept.floatRounding && accept.isoDigits) spellings.push(legacyFloatMajor(psp, expected, true));
|
|
1775
|
+
const legacy = [];
|
|
1776
|
+
for (const spelling of spellings) if (spelling !== null && spelling !== String(wire)) legacy.push(decodeAt(psp, spelling, expected, convention));
|
|
1605
1777
|
return {
|
|
1606
1778
|
target,
|
|
1607
|
-
legacy
|
|
1779
|
+
legacy
|
|
1608
1780
|
};
|
|
1609
1781
|
} catch {
|
|
1610
1782
|
return null;
|
|
1611
1783
|
}
|
|
1612
1784
|
}
|
|
1613
1785
|
function decodeAt(psp, wire, expected, convention) {
|
|
1614
|
-
return decodeWire(psp, wire, expected.currency, convention);
|
|
1786
|
+
return decodeWire(psp, wire, expected.currency, { convention });
|
|
1615
1787
|
}
|
|
1616
1788
|
/**
|
|
1617
1789
|
* One unit of the PSP's last wire digit, as Money: for ISO-minor PSPs `decodeWire(psp, 1)` (the
|
|
@@ -1625,8 +1797,7 @@ function oneWireUnit(psp, currency, convention) {
|
|
|
1625
1797
|
function wireKeyPart(wire) {
|
|
1626
1798
|
return String(wire);
|
|
1627
1799
|
}
|
|
1628
|
-
|
|
1629
|
-
//#region src/data/destinations.ts
|
|
1800
|
+
// src/data/destinations.ts
|
|
1630
1801
|
const pixel = (currencyCase, unit = "major-number") => ({
|
|
1631
1802
|
unit,
|
|
1632
1803
|
currencyCase,
|
|
@@ -1689,8 +1860,7 @@ const DESTINATIONS = {
|
|
|
1689
1860
|
verified: true
|
|
1690
1861
|
}
|
|
1691
1862
|
};
|
|
1692
|
-
|
|
1693
|
-
//#region src/wire/destinations.ts
|
|
1863
|
+
// src/wire/destinations.ts
|
|
1694
1864
|
function descriptorOf(dest) {
|
|
1695
1865
|
if (typeof dest === "string" && require_own.hasOwnKey(DESTINATIONS, dest)) return DESTINATIONS[dest];
|
|
1696
1866
|
throw new require_money.MoneyError("wire_unsupported", `Unknown destination: ${require_money.describeValue(dest)}`);
|
|
@@ -1737,8 +1907,52 @@ function eventMoney(m) {
|
|
|
1737
1907
|
currency: require_money.medusaCurrencyCode(info.code)
|
|
1738
1908
|
};
|
|
1739
1909
|
}
|
|
1740
|
-
|
|
1741
|
-
|
|
1910
|
+
// src/wire/legacy-refund.ts
|
|
1911
|
+
const minus = (a, b) => require_money.addDecimal(a, {
|
|
1912
|
+
units: -b.units,
|
|
1913
|
+
scale: b.scale
|
|
1914
|
+
});
|
|
1915
|
+
/**
|
|
1916
|
+
* The PSP's remaining amount, to refund instead of `refund`, when the PSP holds the capture only
|
|
1917
|
+
* in Medusa's pre-0.2.0 float spelling (`legacyFloatToFixed` PSPs: USD 1072.5 captured as
|
|
1918
|
+
* `'10.72'`, where today's spelling is `'10.73'`) and `refund` is Medusa's whole remaining amount
|
|
1919
|
+
* (`captured - refunded`, exactly). Medusa's remaining then encodes one wire unit above what the
|
|
1920
|
+
* PSP still holds (after a `'0.72'` refund, Medusa's 1000.5 is `'10.01'` against the PSP's
|
|
1921
|
+
* `'10.00'`), and the PSP refuses it (NOT_ALLOWED), so the refund could never complete.
|
|
1922
|
+
* Returns `{ wire, money }` for the PSP's remaining (`'10.00'`, USD 1000), never more than it and
|
|
1923
|
+
* never more than one legacy rounding below what `refund` encodes to. Null (send `refund` as
|
|
1924
|
+
* is) for every other case: a PSP that never encoded in floating point, a capture that matches
|
|
1925
|
+
* today's spelling or no spelling, a partial refund, a refund that already fits, mixed
|
|
1926
|
+
* currencies, and any amount or PSP fact that cannot be read. Never throws.
|
|
1927
|
+
*/
|
|
1928
|
+
function legacyFloatRefundClamp(psp, input) {
|
|
1929
|
+
try {
|
|
1930
|
+
if (!pspDescriptor(psp).legacyFloatToFixed) return null;
|
|
1931
|
+
const { captured, refunded, refund } = input;
|
|
1932
|
+
const info = wireCurrency(captured.currency);
|
|
1933
|
+
if (info === null || wireCurrency(refunded.currency) !== info || wireCurrency(refund.currency) !== info) return null;
|
|
1934
|
+
const pspCaptured = tryDecodeWireExactly(psp, input.capturedWire, info.code, void 0);
|
|
1935
|
+
const pspRefunded = tryDecodeWireExactly(psp, input.refundedWire, info.code, void 0);
|
|
1936
|
+
if (pspCaptured === void 0 || pspRefunded === void 0) return null;
|
|
1937
|
+
if (!(!sameWireAmount(psp, input.capturedWire, captured) && sameWireAmount(psp, input.capturedWire, captured, { acceptLegacyFloatRounding: true }))) return null;
|
|
1938
|
+
const medusaRemaining = minus(wireStoredDecimal(captured).stored, wireStoredDecimal(refunded).stored);
|
|
1939
|
+
if (require_money.compareDecimal(wireStoredDecimal(refund).stored, medusaRemaining) !== 0) return null;
|
|
1940
|
+
const encode = encodeWire;
|
|
1941
|
+
const decode = decodeWire;
|
|
1942
|
+
const sent = decode(psp, encode(psp, refund, { label: "refund amount" }), info.code).amount;
|
|
1943
|
+
const pspRemaining = pspCaptured.amount - pspRefunded.amount;
|
|
1944
|
+
const legacyGap = decode(psp, encode(psp, captured), info.code).amount - pspCaptured.amount;
|
|
1945
|
+
if (pspRemaining <= 0 || sent <= pspRemaining || sent - pspRemaining > legacyGap) return null;
|
|
1946
|
+
const money = require_money.boundedMoney(BigInt(pspRemaining), info);
|
|
1947
|
+
return {
|
|
1948
|
+
wire: encode(psp, money, { label: "refund amount" }),
|
|
1949
|
+
money
|
|
1950
|
+
};
|
|
1951
|
+
} catch {
|
|
1952
|
+
return null;
|
|
1953
|
+
}
|
|
1954
|
+
}
|
|
1955
|
+
// src/wire/presentment.ts
|
|
1742
1956
|
/** Registry codes only, sorted: a provider-only code (Adyen CNH) or one the registry does not know is left out. */
|
|
1743
1957
|
function knownCodes(codes) {
|
|
1744
1958
|
const known = [];
|
|
@@ -1759,33 +1973,75 @@ function pspPresentment(psp) {
|
|
|
1759
1973
|
const d = pspDescriptor(psp);
|
|
1760
1974
|
const requires = PRESENTMENT_REQUIRES_ACCOUNT_COUNTRY[d.id] ?? {};
|
|
1761
1975
|
const allowsOnly = PRESENTMENT_ACCOUNT_COUNTRY_ALLOWS_ONLY[d.id] ?? {};
|
|
1976
|
+
const countries = new Map([...d.accountCountries].map(([country, entry]) => {
|
|
1977
|
+
const lists = {
|
|
1978
|
+
currencies: new Set(knownCodes(entry.currencies)),
|
|
1979
|
+
optIn: new Set(knownCodes(entry.optIn))
|
|
1980
|
+
};
|
|
1981
|
+
return [country, Object.freeze(lists)];
|
|
1982
|
+
}));
|
|
1762
1983
|
return Object.freeze({
|
|
1763
1984
|
currencies: new Set(knownCodes(d.presentmentCurrencies)),
|
|
1764
1985
|
currencyRequiresAccountCountry: new Map(knownCodes(Object.keys(requires)).map((code) => [code, new Set(requires[code])])),
|
|
1765
|
-
accountCountryAllowsOnly: new Map(Object.keys(allowsOnly).map((country) => [country, new Set(knownCodes(allowsOnly[country]))]))
|
|
1986
|
+
accountCountryAllowsOnly: new Map(Object.keys(allowsOnly).map((country) => [country, new Set(knownCodes(allowsOnly[country]))])),
|
|
1987
|
+
accountCountries: countries,
|
|
1988
|
+
optInCompanions: optInCompanionsOf(countries)
|
|
1766
1989
|
});
|
|
1767
1990
|
}
|
|
1768
1991
|
/**
|
|
1992
|
+
* Internal: per currency that names one account country, that country's opt-in currencies. A
|
|
1993
|
+
* currency two countries share names neither, so it gets no companion (no Paystack currency is
|
|
1994
|
+
* shared today; the tests hold the rule with a fixture).
|
|
1995
|
+
*/
|
|
1996
|
+
function optInCompanionsOf(countries) {
|
|
1997
|
+
const companions = /* @__PURE__ */ new Map();
|
|
1998
|
+
for (const entry of countries.values()) {
|
|
1999
|
+
if (entry.optIn.size === 0) continue;
|
|
2000
|
+
for (const code of entry.currencies) if (impliedCountry(countries, code) !== null) companions.set(code, new Set(entry.optIn));
|
|
2001
|
+
}
|
|
2002
|
+
return companions;
|
|
2003
|
+
}
|
|
2004
|
+
/** The one account country whose list (always or opt-in) holds `code`, else null. */
|
|
2005
|
+
function impliedCountry(countries, code) {
|
|
2006
|
+
const holders = [...countries].filter(([, entry]) => entry.currencies.has(code) || entry.optIn.has(code));
|
|
2007
|
+
return holders.length === 1 ? holders[0][0] : null;
|
|
2008
|
+
}
|
|
2009
|
+
/**
|
|
2010
|
+
* The account country a currency names for `psp`: the one country whose accounts present it
|
|
2011
|
+
* (Paystack NGN: `'NG'`, XOF: `'CI'`, the only XOF country Paystack onboards). Null when several
|
|
2012
|
+
* countries' accounts can present it (Paystack USD, on NG and KE accounts), when the PSP has no
|
|
2013
|
+
* per-country lists, or for an unknown code. Never throws for a bad code; an unknown PSP throws
|
|
2014
|
+
* `wire_unsupported`.
|
|
2015
|
+
*/
|
|
2016
|
+
function pspAccountCountryForCurrency(psp, currency) {
|
|
2017
|
+
const d = pspDescriptor(psp);
|
|
2018
|
+
const info = wireCurrency(currency);
|
|
2019
|
+
return info === null ? null : impliedCountry(d.accountCountries, info.code);
|
|
2020
|
+
}
|
|
2021
|
+
/**
|
|
1769
2022
|
* The currencies `psp` lets an account present (charge buyers in). Without `accountCountry`, the
|
|
1770
|
-
* union over every account country; with it (ISO 3166 alpha-2, any
|
|
1771
|
-
* registered there can charge: Stripe's three-decimal five need a UAE
|
|
1772
|
-
* and MYR an in-country one, Airwallex cards on a US account take its
|
|
1773
|
-
*
|
|
1774
|
-
*
|
|
2023
|
+
* union over every account country, opt-in currencies included; with it (ISO 3166 alpha-2, any
|
|
2024
|
+
* case), only what an account registered there can charge: Stripe's three-decimal five need a UAE
|
|
2025
|
+
* account, PayPal's BRL, CNY and MYR an in-country one, Airwallex cards on a US account take its
|
|
2026
|
+
* documented 76 and on an MX account MXN only, a Paystack account its country's currency (plus USD
|
|
2027
|
+
* on NG and KE with `includeOptIn`, and nothing for a country Paystack does not onboard). Not
|
|
2028
|
+
* `pspCurrencies`, which is what the codec scales and the facade lets through (Stripe's adds every
|
|
2029
|
+
* two-decimal ISO code it accepts on the wire).
|
|
1775
2030
|
*/
|
|
1776
2031
|
function pspPresentmentCurrencies(psp, options = {}) {
|
|
1777
2032
|
const rules = pspPresentment(psp);
|
|
1778
2033
|
if (options.accountCountry === void 0) return rules.currencies;
|
|
1779
2034
|
const country = options.accountCountry.trim().toUpperCase();
|
|
1780
2035
|
const only = rules.accountCountryAllowsOnly.get(country);
|
|
2036
|
+
const listed = rules.accountCountries.get(country);
|
|
1781
2037
|
const codes = [...rules.currencies].filter((code) => {
|
|
1782
2038
|
const required = rules.currencyRequiresAccountCountry.get(code);
|
|
1783
|
-
|
|
2039
|
+
const inCountryList = rules.accountCountries.size === 0 || listed !== void 0 && (listed.currencies.has(code) || options.includeOptIn === true && listed.optIn.has(code));
|
|
2040
|
+
return (required === void 0 || required.has(country)) && (only === void 0 || only.has(code)) && inCountryList;
|
|
1784
2041
|
});
|
|
1785
2042
|
return new Set(codes);
|
|
1786
2043
|
}
|
|
1787
|
-
|
|
1788
|
-
//#region src/wire/provider-amount.ts
|
|
2044
|
+
// src/wire/provider-amount.ts
|
|
1789
2045
|
/**
|
|
1790
2046
|
* A provider's major-unit amount (finite number, or text read by the separator engine, which
|
|
1791
2047
|
* strips the currency's symbol and code) as Money, rounded once to the storage digits. Null on
|
|
@@ -1820,24 +2076,27 @@ function parseProviderAmount(value, currency, options = {}) {
|
|
|
1820
2076
|
return null;
|
|
1821
2077
|
}
|
|
1822
2078
|
}
|
|
1823
|
-
|
|
1824
|
-
//#region src/wire/providers.ts
|
|
2079
|
+
// src/wire/providers.ts
|
|
1825
2080
|
/** RBI e-mandate cap Razorpay token registrations carry as `max_amount`: INR 15,000 (1,500,000 paise = stored). */
|
|
1826
2081
|
const RAZORPAY_AFA_FREE_CAP = Object.freeze(require_money.fromMajor(RAZORPAY_AFA_FREE_CAP_MAJOR, "INR"));
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
2082
|
+
const VERIFICATION_AMOUNTS = {
|
|
2083
|
+
paystack: "one-major-unit",
|
|
2084
|
+
razorpay: "one-major-unit",
|
|
2085
|
+
mollie: "one-wire-unit",
|
|
2086
|
+
adyen: "zero"
|
|
2087
|
+
};
|
|
2088
|
+
function verificationMoney(psp, code) {
|
|
2089
|
+
const amount = VERIFICATION_AMOUNTS[psp];
|
|
2090
|
+
if (amount === "one-major-unit") return require_money.fromMajor("1", code);
|
|
2091
|
+
if (amount === "one-wire-unit") return wireUnit(psp, code);
|
|
2092
|
+
return require_money.boundedMoney(0n, resolveWireCurrency(code));
|
|
2093
|
+
}
|
|
1832
2094
|
function verificationCharge(psp, currency) {
|
|
1833
|
-
const
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
charge = require_money.fromMajor("1", code);
|
|
1839
|
-
} else if (psp === "mollie") charge = wireUnit("mollie", code);
|
|
1840
|
-
else charge = require_money.boundedMoney(0n, resolveWireCurrency(code));
|
|
2095
|
+
const d = pspDescriptor(psp);
|
|
2096
|
+
const documented = d.verificationCurrency;
|
|
2097
|
+
const code = assertPspCurrency(psp, currency === void 0 ? documented?.code : currency);
|
|
2098
|
+
if (documented?.only && code !== documented.code) throw new require_money.MoneyError("wire_unsupported", `[${d.tag}] Verification charges are made in ${documented.code} only, not ${code}.`);
|
|
2099
|
+
const charge = verificationMoney(psp, code);
|
|
1841
2100
|
return {
|
|
1842
2101
|
wire: encodeWire(psp, charge, {
|
|
1843
2102
|
convention: ISO_MINOR_V2,
|
|
@@ -1857,8 +2116,7 @@ function iyzicoPrice(wire) {
|
|
|
1857
2116
|
const text = require_money.toDecimalText(parsed);
|
|
1858
2117
|
return text.includes(".") ? text : `${text}.0`;
|
|
1859
2118
|
}
|
|
1860
|
-
|
|
1861
|
-
//#region src/wire/slot.ts
|
|
2119
|
+
// src/wire/slot.ts
|
|
1862
2120
|
/** `m` for a slot context's `money` key. */
|
|
1863
2121
|
function slotMoney(m) {
|
|
1864
2122
|
const { info } = require_money.storedDecimal(m);
|
|
@@ -1884,13 +2142,18 @@ function readSlotMoney(context) {
|
|
|
1884
2142
|
const money = context.money;
|
|
1885
2143
|
return (isRecord(money) ? read(money.amount, money.currency_code) : void 0) ?? read(context.total ?? context.price, context.currency_code, context.currency);
|
|
1886
2144
|
}
|
|
1887
|
-
//#endregion
|
|
1888
2145
|
Object.defineProperty(exports, "ISO_MINOR_V2", {
|
|
1889
2146
|
enumerable: true,
|
|
1890
2147
|
get: function() {
|
|
1891
2148
|
return ISO_MINOR_V2;
|
|
1892
2149
|
}
|
|
1893
2150
|
});
|
|
2151
|
+
Object.defineProperty(exports, "PAYSTACK_CURRENCIES", {
|
|
2152
|
+
enumerable: true,
|
|
2153
|
+
get: function() {
|
|
2154
|
+
return PAYSTACK_CURRENCIES;
|
|
2155
|
+
}
|
|
2156
|
+
});
|
|
1894
2157
|
Object.defineProperty(exports, "PRE_CUTOVER", {
|
|
1895
2158
|
enumerable: true,
|
|
1896
2159
|
get: function() {
|
|
@@ -1909,6 +2172,24 @@ Object.defineProperty(exports, "RAZORPAY_AFA_FREE_CAP", {
|
|
|
1909
2172
|
return RAZORPAY_AFA_FREE_CAP;
|
|
1910
2173
|
}
|
|
1911
2174
|
});
|
|
2175
|
+
Object.defineProperty(exports, "WIRE_ROUNDING_EXACT", {
|
|
2176
|
+
enumerable: true,
|
|
2177
|
+
get: function() {
|
|
2178
|
+
return WIRE_ROUNDING_EXACT;
|
|
2179
|
+
}
|
|
2180
|
+
});
|
|
2181
|
+
Object.defineProperty(exports, "WIRE_ROUNDING_KEY", {
|
|
2182
|
+
enumerable: true,
|
|
2183
|
+
get: function() {
|
|
2184
|
+
return WIRE_ROUNDING_KEY;
|
|
2185
|
+
}
|
|
2186
|
+
});
|
|
2187
|
+
Object.defineProperty(exports, "WIRE_ROUNDING_MARKER", {
|
|
2188
|
+
enumerable: true,
|
|
2189
|
+
get: function() {
|
|
2190
|
+
return WIRE_ROUNDING_MARKER;
|
|
2191
|
+
}
|
|
2192
|
+
});
|
|
1912
2193
|
Object.defineProperty(exports, "WIRE_SCALE_ISO_MINOR_V2", {
|
|
1913
2194
|
enumerable: true,
|
|
1914
2195
|
get: function() {
|
|
@@ -1993,6 +2274,18 @@ Object.defineProperty(exports, "jsonDecimalLiteral", {
|
|
|
1993
2274
|
return jsonDecimalLiteral;
|
|
1994
2275
|
}
|
|
1995
2276
|
});
|
|
2277
|
+
Object.defineProperty(exports, "legacyFloatRefundClamp", {
|
|
2278
|
+
enumerable: true,
|
|
2279
|
+
get: function() {
|
|
2280
|
+
return legacyFloatRefundClamp;
|
|
2281
|
+
}
|
|
2282
|
+
});
|
|
2283
|
+
Object.defineProperty(exports, "mayHoldLegacyFloatRounding", {
|
|
2284
|
+
enumerable: true,
|
|
2285
|
+
get: function() {
|
|
2286
|
+
return mayHoldLegacyFloatRounding;
|
|
2287
|
+
}
|
|
2288
|
+
});
|
|
1996
2289
|
Object.defineProperty(exports, "oneWireUnit", {
|
|
1997
2290
|
enumerable: true,
|
|
1998
2291
|
get: function() {
|
|
@@ -2005,6 +2298,12 @@ Object.defineProperty(exports, "parseProviderAmount", {
|
|
|
2005
2298
|
return parseProviderAmount;
|
|
2006
2299
|
}
|
|
2007
2300
|
});
|
|
2301
|
+
Object.defineProperty(exports, "pspAccountCountryForCurrency", {
|
|
2302
|
+
enumerable: true,
|
|
2303
|
+
get: function() {
|
|
2304
|
+
return pspAccountCountryForCurrency;
|
|
2305
|
+
}
|
|
2306
|
+
});
|
|
2008
2307
|
Object.defineProperty(exports, "pspCurrencies", {
|
|
2009
2308
|
enumerable: true,
|
|
2010
2309
|
get: function() {
|
|
@@ -2017,6 +2316,18 @@ Object.defineProperty(exports, "pspDefaultCurrency", {
|
|
|
2017
2316
|
return pspDefaultCurrency;
|
|
2018
2317
|
}
|
|
2019
2318
|
});
|
|
2319
|
+
Object.defineProperty(exports, "pspHomeCountry", {
|
|
2320
|
+
enumerable: true,
|
|
2321
|
+
get: function() {
|
|
2322
|
+
return pspHomeCountry;
|
|
2323
|
+
}
|
|
2324
|
+
});
|
|
2325
|
+
Object.defineProperty(exports, "pspHomeCurrency", {
|
|
2326
|
+
enumerable: true,
|
|
2327
|
+
get: function() {
|
|
2328
|
+
return pspHomeCurrency;
|
|
2329
|
+
}
|
|
2330
|
+
});
|
|
2020
2331
|
Object.defineProperty(exports, "pspMinimumAmount", {
|
|
2021
2332
|
enumerable: true,
|
|
2022
2333
|
get: function() {
|