@amboras-dev/money 0.1.0 → 0.3.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 +25 -10
- 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-D7tm_t_o.cjs → allocate-AusholrC.cjs} +3 -4
- package/dist/{allocate-CdnhvAda.js → allocate-BBRfdaSC.js} +3 -4
- package/dist/{amount-DHtvZSSm.cjs → amount-CwFzcxUl.cjs} +29 -12
- package/dist/{amount-D7dj76nH.js → amount-DHFOK2Yd.js} +29 -12
- package/dist/{arithmetic-C-Q_aI49.js → arithmetic-C97-YafD.js} +4 -5
- package/dist/{arithmetic-Bq-8mSal.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-BnA1aLJk.cjs → format-92fzvTXY.cjs} +21 -6
- package/dist/{format-BdB7LEIp.js → format-BJC513u4.js} +16 -7
- 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 +13 -12
- package/dist/index.d.cts +28 -22
- package/dist/index.d.ts +28 -22
- package/dist/index.js +11 -13
- package/dist/input.cjs +7 -10
- package/dist/input.d.cts +9 -16
- package/dist/input.d.ts +9 -16
- package/dist/input.js +7 -10
- package/dist/{iso-minor--gQWI1f2.cjs → iso-minor-DyNjT9A1.cjs} +2 -3
- package/dist/{iso-minor-CtaiIifs.js → iso-minor-odkY-e6I.js} +2 -3
- package/dist/{medusa-OJ2TJOxt.cjs → medusa-CzVK0bth.cjs} +24 -4
- package/dist/{medusa-DuQ3-KoD.d.cts → medusa-DofdvIgQ.d.cts} +11 -4
- package/dist/{medusa-RwqxaDGq.d.ts → medusa-DrbYmD2Y.d.ts} +11 -4
- package/dist/{medusa-CmxCni-G.js → medusa-pKGlImn9.js} +19 -5
- package/dist/{money-CbhsT0fB.d.cts → money-BkMeYDEW.d.cts} +19 -9
- package/dist/{money-CbhsT0fB.d.ts → money-BkMeYDEW.d.ts} +19 -9
- package/dist/{money-CIgELekG.js → money-BxbAw7BP.js} +25 -21
- package/dist/{money-D5-vlv0h.cjs → money-DWBjuuEK.cjs} +42 -20
- package/dist/{number-text-C82oh6JB.js → number-text-Bj-gZXiF.js} +3 -4
- package/dist/{number-text-BpvN6NAo.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-CKVI_c-m.js → percent-CB3Ixjc_.js} +2 -3
- package/dist/{percent-Dt8vNIAW.cjs → percent-DABHiSBs.cjs} +2 -3
- package/dist/{rate-CmeTGNex.d.ts → rate-BvvZUdSu.d.ts} +1 -3
- package/dist/{rate-toyS3EMf.d.cts → rate-CEakW3ia.d.cts} +1 -3
- package/dist/{rate-DGPfB_jc.cjs → rate-CEjWTATc.cjs} +3 -4
- package/dist/{rate-lLPViBuM.js → rate-D6S2_wgZ.js} +3 -4
- package/dist/{reporting-5xby-Zas.d.ts → reporting-DFNyDBdi.d.cts} +2 -4
- package/dist/{reporting-DEM97DhQ.d.cts → reporting-jIBILvnr.d.ts} +2 -4
- package/dist/{retail-BwcFJcVN.d.ts → retail-B04CjW3b.d.ts} +1 -3
- package/dist/{retail-DTk2XAMM.cjs → retail-CYGPU4ea.cjs} +4 -5
- package/dist/{retail-Mqd-sPMF.d.cts → retail-CmEyJQOH.d.cts} +1 -3
- package/dist/{retail-BsvpNv1F.js → retail-DXgs11ov.js} +4 -5
- package/dist/{rounding-oZ832yTD.cjs → rounding-4QKTRbMQ.cjs} +2 -3
- package/dist/{rounding-CVAPEfq_.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 +72675 -12
- package/dist/testing.d.cts +46 -11
- package/dist/testing.d.ts +46 -11
- package/dist/testing.js +72674 -13
- package/dist/{wire-CI3Sm1iC.js → wire-B4QU8O3W.js} +584 -114
- package/dist/wire-CVNicirK.d.ts +428 -0
- package/dist/wire-CtNJmWVP.d.cts +428 -0
- package/dist/{wire-DQZ6fA3c.cjs → wire-u2tmHY0Y.cjs} +649 -113
- package/dist/wire.cjs +12 -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
- package/dist/wire-Cd4Q1Jmm.d.ts +0 -269
- package/dist/wire-hWuixv3w.d.cts +0 -269
|
@@ -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"];
|
|
@@ -678,6 +657,118 @@ const STRIPE_PRESENTMENT_CURRENCIES = [
|
|
|
678
657
|
"ZAR",
|
|
679
658
|
"ZMW"
|
|
680
659
|
];
|
|
660
|
+
/**
|
|
661
|
+
* Presentment currencies only accounts registered in the named countries can charge.
|
|
662
|
+
* Stripe: support.stripe.com/questions/which-payments-methods-and-products-are-available-in-the-uae
|
|
663
|
+
* (retrieved 2026-10-07): "We also support charges in the following three-decimal currencies:
|
|
664
|
+
* Bahraini dinar (BHD), Jordanian dinar (JOD), Kuwaiti dinar (KWD), Omani rial (OMR), Tunisian
|
|
665
|
+
* dinar (TND)"; no other country's list on docs.stripe.com/currencies carries them.
|
|
666
|
+
* PayPal: developer.paypal.com/reference/currency-codes (retrieved 2026-10-07) footnotes BRL, CNY
|
|
667
|
+
* and MYR as supported "only for in-country PayPal accounts" (Medusa models the conservative
|
|
668
|
+
* reading: an out-of-country account cannot charge them; unverified by a sandbox probe).
|
|
669
|
+
*/
|
|
670
|
+
const PRESENTMENT_REQUIRES_ACCOUNT_COUNTRY = {
|
|
671
|
+
stripe: {
|
|
672
|
+
BHD: ["AE"],
|
|
673
|
+
JOD: ["AE"],
|
|
674
|
+
KWD: ["AE"],
|
|
675
|
+
OMR: ["AE"],
|
|
676
|
+
TND: ["AE"]
|
|
677
|
+
},
|
|
678
|
+
paypal: {
|
|
679
|
+
BRL: ["BR"],
|
|
680
|
+
CNY: ["CN"],
|
|
681
|
+
MYR: ["MY"]
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
/**
|
|
685
|
+
* Account countries whose card processing takes only the listed currencies.
|
|
686
|
+
* Airwallex: airwallex.com/docs/payments/payment-methods/global/cards (retrieved 2026-10-26,
|
|
687
|
+
* matching Medusa's 2026-10-07 copy): "Supported processing currencies can differ based on where
|
|
688
|
+
* your business is registered and the card scheme." US and MX are listed below; AU, CA, SG, HK,
|
|
689
|
+
* NZ, JP, MY, the EEA, CH, UK and IL take "Visa, MasterCard: All currencies".
|
|
690
|
+
*/
|
|
691
|
+
const PRESENTMENT_ACCOUNT_COUNTRY_ALLOWS_ONLY = { airwallex: {
|
|
692
|
+
US: [
|
|
693
|
+
"USD",
|
|
694
|
+
"EUR",
|
|
695
|
+
"GBP",
|
|
696
|
+
"AUD",
|
|
697
|
+
"SGD",
|
|
698
|
+
"JPY",
|
|
699
|
+
"CHF",
|
|
700
|
+
"NOK",
|
|
701
|
+
"DKK",
|
|
702
|
+
"CAD",
|
|
703
|
+
"NZD",
|
|
704
|
+
"HKD",
|
|
705
|
+
"KRW",
|
|
706
|
+
"PHP",
|
|
707
|
+
"MYR",
|
|
708
|
+
"TWD",
|
|
709
|
+
"VND",
|
|
710
|
+
"EGP",
|
|
711
|
+
"SAR",
|
|
712
|
+
"THB",
|
|
713
|
+
"MXN",
|
|
714
|
+
"TRY",
|
|
715
|
+
"INR",
|
|
716
|
+
"BRL",
|
|
717
|
+
"CNY",
|
|
718
|
+
"PKR",
|
|
719
|
+
"PLN",
|
|
720
|
+
"SEK",
|
|
721
|
+
"NGN",
|
|
722
|
+
"AED",
|
|
723
|
+
"IDR",
|
|
724
|
+
"BDT",
|
|
725
|
+
"ILS",
|
|
726
|
+
"ISK",
|
|
727
|
+
"MAD",
|
|
728
|
+
"ZAR",
|
|
729
|
+
"CZK",
|
|
730
|
+
"HUF",
|
|
731
|
+
"RON",
|
|
732
|
+
"CLP",
|
|
733
|
+
"QAR",
|
|
734
|
+
"COP",
|
|
735
|
+
"RUB",
|
|
736
|
+
"MWK",
|
|
737
|
+
"PEN",
|
|
738
|
+
"BGN",
|
|
739
|
+
"UAH",
|
|
740
|
+
"ARS",
|
|
741
|
+
"MOP",
|
|
742
|
+
"HRK",
|
|
743
|
+
"KZT",
|
|
744
|
+
"ALL",
|
|
745
|
+
"CRC",
|
|
746
|
+
"XOF",
|
|
747
|
+
"KES",
|
|
748
|
+
"UYU",
|
|
749
|
+
"LKR",
|
|
750
|
+
"BOB",
|
|
751
|
+
"PAB",
|
|
752
|
+
"GTQ",
|
|
753
|
+
"DOP",
|
|
754
|
+
"MMK",
|
|
755
|
+
"RSD",
|
|
756
|
+
"BZD",
|
|
757
|
+
"DZD",
|
|
758
|
+
"SHP",
|
|
759
|
+
"HNL",
|
|
760
|
+
"GEL",
|
|
761
|
+
"BAM",
|
|
762
|
+
"MKD",
|
|
763
|
+
"JMD",
|
|
764
|
+
"AWG",
|
|
765
|
+
"BBD",
|
|
766
|
+
"TTD",
|
|
767
|
+
"PYG",
|
|
768
|
+
"XAF"
|
|
769
|
+
],
|
|
770
|
+
MX: ["MXN"]
|
|
771
|
+
} };
|
|
681
772
|
/** Stripe's not-two-decimal set (capabilities/stripe-connect.ts:47), incl. the UAE-only five. */
|
|
682
773
|
const STRIPE_NOT_TWO_DECIMAL = [
|
|
683
774
|
"BIF",
|
|
@@ -888,6 +979,101 @@ const AUTHORIZE_NET_CURRENCIES = [
|
|
|
888
979
|
"PLN"
|
|
889
980
|
];
|
|
890
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
|
+
];
|
|
891
1077
|
/** orch `MINIMUM_AMOUNT_BY_CURRENCY`, majors. */
|
|
892
1078
|
const PSP_MINIMUM_MAJOR = { paystack: { USD: "2.00" } };
|
|
893
1079
|
/** RBI e-mandate AFA-free cap: INR 15,000 (razorpay-vault `15_000_00` paise, seam `1_500_000`). */
|
|
@@ -902,8 +1088,29 @@ const PROVIDER_ONLY_CURRENCIES = { CNH: {
|
|
|
902
1088
|
name: "Chinese Yuan (offshore)",
|
|
903
1089
|
psps: ["adyen"]
|
|
904
1090
|
} };
|
|
905
|
-
|
|
906
|
-
|
|
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
|
|
907
1114
|
/** The registry entry (any case, historic included) for `input`, else null. Never throws. */
|
|
908
1115
|
function wireCurrency(input) {
|
|
909
1116
|
return require_money.findCurrency(input, { allowHistoric: true });
|
|
@@ -933,8 +1140,42 @@ function wireStored(m) {
|
|
|
933
1140
|
units: BigInt(m.amount)
|
|
934
1141
|
};
|
|
935
1142
|
}
|
|
936
|
-
|
|
937
|
-
|
|
1143
|
+
const SAFE_LIMIT = BigInt(Number.MAX_SAFE_INTEGER);
|
|
1144
|
+
/**
|
|
1145
|
+
* A Money's or FractionalMoney's currency entry and its exact stored amount, normalized (scale 0
|
|
1146
|
+
* when whole, so a whole amount reads exactly as `wireStored` reads it). A number must be finite
|
|
1147
|
+
* and safe when whole, text plain decimal; the amount must round within the safe integers.
|
|
1148
|
+
*/
|
|
1149
|
+
function wireStoredDecimal(m) {
|
|
1150
|
+
const info = resolveWireCurrency(m.currency);
|
|
1151
|
+
const { amount } = m;
|
|
1152
|
+
if (typeof amount === "string") {
|
|
1153
|
+
const parsed = require_money.parseDecimal(amount, "plain");
|
|
1154
|
+
if (parsed === null) throw new require_money.MoneyError("amount_invalid", `Stored amount must be plain decimal text, got ${require_money.describeValue(amount)}`);
|
|
1155
|
+
if (!require_money.unitsWithin(require_money.roundToScale(parsed, 0, "up"), SAFE_LIMIT)) throw new require_money.MoneyError("amount_invalid", `Stored amount is beyond the safe integers: ${amount}`);
|
|
1156
|
+
return {
|
|
1157
|
+
info,
|
|
1158
|
+
stored: require_money.normalizeDecimal(parsed)
|
|
1159
|
+
};
|
|
1160
|
+
}
|
|
1161
|
+
const parsed = typeof amount === "number" ? require_money.strictNumberDecimal(amount) : null;
|
|
1162
|
+
if (parsed === null) throw new require_money.MoneyError("amount_invalid", `Stored amount must be a safe integer, got ${require_money.describeValue(amount)}`);
|
|
1163
|
+
return {
|
|
1164
|
+
info,
|
|
1165
|
+
stored: require_money.normalizeDecimal(parsed)
|
|
1166
|
+
};
|
|
1167
|
+
}
|
|
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
|
+
}
|
|
938
1179
|
function digitTable(groups) {
|
|
939
1180
|
const table = /* @__PURE__ */ new Map();
|
|
940
1181
|
for (const digits of [
|
|
@@ -957,6 +1198,7 @@ const vndOnlyFacade = (code) => code === "VND";
|
|
|
957
1198
|
const NONE = /* @__PURE__ */ new Set();
|
|
958
1199
|
const NO_DIGITS = /* @__PURE__ */ new Map();
|
|
959
1200
|
function describe(id, input) {
|
|
1201
|
+
const currencies = new Set(input.currencies);
|
|
960
1202
|
return Object.freeze({
|
|
961
1203
|
id,
|
|
962
1204
|
tag: input.tag,
|
|
@@ -964,7 +1206,9 @@ function describe(id, input) {
|
|
|
964
1206
|
gated: input.gated ?? false,
|
|
965
1207
|
encodeGated: input.encodeGated ?? false,
|
|
966
1208
|
preCutoverNeedsFactorOne: input.preCutoverNeedsFactorOne ?? false,
|
|
967
|
-
|
|
1209
|
+
roundsToStoredUnitFirst: input.roundsToStoredUnitFirst ?? false,
|
|
1210
|
+
currencies,
|
|
1211
|
+
presentmentCurrencies: input.presentmentCurrencies ? new Set(input.presentmentCurrencies) : currencies,
|
|
968
1212
|
digits: input.digits ?? NO_DIGITS,
|
|
969
1213
|
sentAsTwoDecimal: input.sentAsTwoDecimal ? new Set(input.sentAsTwoDecimal) : NONE,
|
|
970
1214
|
sentAsZeroDecimal: input.sentAsZeroDecimal ? new Set(input.sentAsZeroDecimal) : NONE,
|
|
@@ -973,7 +1217,12 @@ function describe(id, input) {
|
|
|
973
1217
|
singleCurrency: input.singleCurrency ?? null,
|
|
974
1218
|
unsupported: input.unsupported ?? genericUnsupported(input.tag),
|
|
975
1219
|
facadeAccepts: input.facadeAccepts ?? scalesAnyCurrency,
|
|
976
|
-
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)
|
|
977
1226
|
});
|
|
978
1227
|
}
|
|
979
1228
|
const notTwoDecimalAtStripe = new Set(STRIPE_NOT_TWO_DECIMAL);
|
|
@@ -996,7 +1245,9 @@ const PSP_DESCRIPTORS = Object.freeze({
|
|
|
996
1245
|
family: "iso-minor",
|
|
997
1246
|
gated: true,
|
|
998
1247
|
encodeGated: true,
|
|
1248
|
+
roundsToStoredUnitFirst: true,
|
|
999
1249
|
currencies: STRIPE_SENDABLE,
|
|
1250
|
+
presentmentCurrencies: STRIPE_PRESENTMENT_CURRENCIES,
|
|
1000
1251
|
sentAsTwoDecimal: STRIPE_SENT_AS_TWO_DECIMAL
|
|
1001
1252
|
}),
|
|
1002
1253
|
adyen: describe("adyen", {
|
|
@@ -1004,6 +1255,7 @@ const PSP_DESCRIPTORS = Object.freeze({
|
|
|
1004
1255
|
family: "iso-minor",
|
|
1005
1256
|
gated: true,
|
|
1006
1257
|
encodeGated: true,
|
|
1258
|
+
roundsToStoredUnitFirst: true,
|
|
1007
1259
|
currencies: digitTable(ADYEN_CURRENCY_DIGITS).keys(),
|
|
1008
1260
|
digits: digitTable(ADYEN_CURRENCY_DIGITS),
|
|
1009
1261
|
sentAsTwoDecimal: ADYEN_SENT_AS_TWO_DECIMAL,
|
|
@@ -1123,8 +1375,7 @@ function pspDescriptor(psp) {
|
|
|
1123
1375
|
if (typeof psp === "string" && require_own.hasOwnKey(PSP_DESCRIPTORS, psp)) return PSP_DESCRIPTORS[psp];
|
|
1124
1376
|
throw new require_money.MoneyError("wire_unsupported", `Unknown payment provider: ${require_money.describeValue(psp)}`);
|
|
1125
1377
|
}
|
|
1126
|
-
|
|
1127
|
-
//#region src/wire/marker.ts
|
|
1378
|
+
// src/wire/marker.ts
|
|
1128
1379
|
const WIRE_SCALE_KEY = "amboras_wire_scale";
|
|
1129
1380
|
const WIRE_SCALE_ISO_MINOR_V2 = "iso-minor-v2";
|
|
1130
1381
|
const WIRE_SCALE_MARKER = Object.freeze({ [WIRE_SCALE_KEY]: WIRE_SCALE_ISO_MINOR_V2 });
|
|
@@ -1143,8 +1394,19 @@ function conventionKind(value) {
|
|
|
1143
1394
|
const kind = typeof value === "object" && value !== null ? value.kind : void 0;
|
|
1144
1395
|
return kind === "iso-minor-v2" || kind === "pre-cutover" ? kind : null;
|
|
1145
1396
|
}
|
|
1146
|
-
|
|
1147
|
-
|
|
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
|
|
1148
1410
|
const isBlank = (value) => value === null || value === void 0 || typeof value === "string" && value.trim() === "";
|
|
1149
1411
|
const shownCode = (currency) => typeof currency === "string" ? currency.trim().toUpperCase() : require_money.describeValue(currency);
|
|
1150
1412
|
function missingCurrency(d) {
|
|
@@ -1175,7 +1437,8 @@ function pspCurrencies(psp) {
|
|
|
1175
1437
|
/**
|
|
1176
1438
|
* `currency` as a CurrencyCode `psp` takes. Empty throws `currency_missing` (`[<Tag>] Cannot
|
|
1177
1439
|
* scale an amount without a currency code; ...`); anything the PSP does not take throws
|
|
1178
|
-
* `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`).
|
|
1179
1442
|
*/
|
|
1180
1443
|
function assertPspCurrency(psp, currency) {
|
|
1181
1444
|
const d = pspDescriptor(psp);
|
|
@@ -1206,6 +1469,28 @@ function pspDefaultCurrency(psp) {
|
|
|
1206
1469
|
const single = pspDescriptor(psp).singleCurrency;
|
|
1207
1470
|
return single === null ? null : single;
|
|
1208
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
|
+
}
|
|
1209
1494
|
function factorOf(d, info) {
|
|
1210
1495
|
if (d.sentAsTwoDecimal.has(info.code)) return 1n;
|
|
1211
1496
|
if (d.sentAsZeroDecimal.has(info.code)) return 100n;
|
|
@@ -1258,32 +1543,39 @@ function requireConvention(d, convention) {
|
|
|
1258
1543
|
}
|
|
1259
1544
|
function encodeWire(psp, m, options = {}) {
|
|
1260
1545
|
const d = pspDescriptor(psp);
|
|
1261
|
-
const { info,
|
|
1262
|
-
const value = {
|
|
1263
|
-
units,
|
|
1264
|
-
scale: require_money.storageExponent(info)
|
|
1265
|
-
};
|
|
1546
|
+
const { info, stored: held } = wireStoredDecimal(m);
|
|
1266
1547
|
facadeCurrency(d, info.code);
|
|
1267
1548
|
const label = options.label ?? "amount";
|
|
1268
|
-
const
|
|
1269
|
-
|
|
1549
|
+
const shown = require_money.formatDecimal(held);
|
|
1550
|
+
const exponent = require_money.storageExponent(info);
|
|
1551
|
+
const majorText = require_money.formatDecimal({
|
|
1552
|
+
units: held.units,
|
|
1553
|
+
scale: exponent + held.scale
|
|
1554
|
+
});
|
|
1555
|
+
if (held.units < 0n || held.units === 0n && !options.allowZero) throw new require_money.MoneyError("wire_refused", `[${d.tag}] Invalid ${label}: ${shown}`);
|
|
1556
|
+
const stored = d.roundsToStoredUnitFirst ? require_money.roundToScale(held, 0, "half-up") : held;
|
|
1557
|
+
const positive = held.units > 0n;
|
|
1270
1558
|
const factor = d.family === "iso-minor" ? factorOf(d, info) : 1n;
|
|
1271
1559
|
if (d.encodeGated && requireConvention(d, options.convention) === "pre-cutover") {
|
|
1272
|
-
if (d.preCutoverNeedsFactorOne
|
|
1273
|
-
|
|
1560
|
+
if (!(stored.scale === 0 && (!d.preCutoverNeedsFactorOne || require_money.divRound(stored.units, factor, "half-up") === stored.units))) throw new require_money.MoneyError("wire_refused", preCutoverRefusal(d.tag, info.code));
|
|
1561
|
+
if (stored.units === 0n && positive) throw subUnitRefusal(d, info, majorText, exponent, label);
|
|
1562
|
+
return Number(stored.units);
|
|
1274
1563
|
}
|
|
1275
|
-
if (d.wholeUnit?.applies(info) && stored % BigInt(info.storageScale) !== 0n) throw new require_money.MoneyError("wire_refused", d.wholeUnit.message(info,
|
|
1564
|
+
if (d.wholeUnit?.applies(info) && stored.units % (BigInt(info.storageScale) * require_money.pow10(stored.scale)) !== 0n) throw new require_money.MoneyError("wire_refused", d.wholeUnit.message(info, shown, label, majorText));
|
|
1276
1565
|
const digits = wireDigitsOf(d, info);
|
|
1277
1566
|
if (d.family === "iso-minor") {
|
|
1278
|
-
const exact = require_money.divRound(stored, factor, "half-up");
|
|
1279
|
-
if (exact === 0n &&
|
|
1567
|
+
const exact = require_money.divRound(stored.units, factor * require_money.pow10(stored.scale), "half-up");
|
|
1568
|
+
if (exact === 0n && positive) throw subUnitRefusal(d, info, majorText, digits, label);
|
|
1280
1569
|
if (!d.threeDecimalStepOfTen || d.digits.get(info.code) !== 3) return Number(exact);
|
|
1281
1570
|
const stepped = exact - exact % 10n;
|
|
1282
|
-
if (stepped === 0n && exact > 0n) throw new require_money.MoneyError("wire_refused", roundsToNothing(d.tag, info.code,
|
|
1571
|
+
if (stepped === 0n && exact > 0n) throw new require_money.MoneyError("wire_refused", roundsToNothing(d.tag, info.code, majorText));
|
|
1283
1572
|
return Number(stepped);
|
|
1284
1573
|
}
|
|
1285
|
-
const rounded = require_money.roundToScale(
|
|
1286
|
-
|
|
1574
|
+
const rounded = require_money.roundToScale({
|
|
1575
|
+
units: stored.units,
|
|
1576
|
+
scale: exponent + stored.scale
|
|
1577
|
+
}, digits, "half-up");
|
|
1578
|
+
if (rounded.units === 0n && positive) throw subUnitRefusal(d, info, majorText, digits, label);
|
|
1287
1579
|
const text = require_money.formatDecimal(rounded);
|
|
1288
1580
|
return d.family === "major-number" ? Number(text) : text;
|
|
1289
1581
|
}
|
|
@@ -1305,11 +1597,13 @@ function roundsToNothing(tag, code, major) {
|
|
|
1305
1597
|
function wireDecimal(wire) {
|
|
1306
1598
|
return typeof wire === "number" ? require_money.strictNumberDecimal(wire) : require_money.parseDecimal(wire, "plain");
|
|
1307
1599
|
}
|
|
1308
|
-
|
|
1600
|
+
/** `w` at storage scale, half-up; with `exact`, a wire naming a fraction of a storage unit throws `amount_invalid`. */
|
|
1601
|
+
function decodeWith(d, w, info, kind, exact = false) {
|
|
1309
1602
|
const scale = require_money.pow10(w.scale);
|
|
1310
1603
|
let multiplier;
|
|
1311
1604
|
if (d.family !== "iso-minor") multiplier = BigInt(info.storageScale);
|
|
1312
1605
|
else multiplier = kind === "pre-cutover" ? 1n : factorOf(d, info);
|
|
1606
|
+
if (exact && w.units * multiplier % scale !== 0n) throw new require_money.MoneyError("amount_invalid", `[${d.tag}] ${require_money.formatDecimal(w)} is not a whole ${info.code} storage amount`);
|
|
1313
1607
|
return require_money.boundedMoney(require_money.mulDiv(w.units, multiplier, scale, "half-up"), info);
|
|
1314
1608
|
}
|
|
1315
1609
|
/** VNPay: a positive whole safe integer, as Medusa's `vnpayWireAmountToStorage` reads one. */
|
|
@@ -1318,7 +1612,7 @@ function isWholePositive(w) {
|
|
|
1318
1612
|
return w.units > 0n && w.units % scale === 0n && w.units / scale <= BigInt(Number.MAX_SAFE_INTEGER);
|
|
1319
1613
|
}
|
|
1320
1614
|
/** Every inbound check: facade currency gate, convention, strict wire text, VNPay's "no amount", the sign. */
|
|
1321
|
-
function decodeChecked(d, wire, currency, convention, allowNegative) {
|
|
1615
|
+
function decodeChecked(d, wire, currency, convention, allowNegative, exact = false) {
|
|
1322
1616
|
if (isBlank(currency)) throw missingCurrency(d);
|
|
1323
1617
|
const info = facadeCurrency(d, currency);
|
|
1324
1618
|
const kind = d.gated ? requireConvention(d, convention) : null;
|
|
@@ -1326,10 +1620,20 @@ function decodeChecked(d, wire, currency, convention, allowNegative) {
|
|
|
1326
1620
|
if (!w) throw new require_money.MoneyError("amount_invalid", `[${d.tag}] Not a wire amount: ${require_money.describeValue(wire)}`);
|
|
1327
1621
|
if (d.inboundWholePositive && !isWholePositive(w)) throw new require_money.MoneyError("amount_invalid", `[${d.tag}] No amount: ${d.tag} amounts are positive whole numbers, got ${require_money.describeValue(wire)}`);
|
|
1328
1622
|
if (w.units < 0n && !allowNegative) throw new require_money.MoneyError("amount_invalid", `[${d.tag}] Negative wire amount: ${require_money.describeValue(wire)}`);
|
|
1329
|
-
return decodeWith(d, w, info, kind);
|
|
1623
|
+
return decodeWith(d, w, info, kind, exact);
|
|
1330
1624
|
}
|
|
1331
|
-
function
|
|
1332
|
-
|
|
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);
|
|
1333
1637
|
}
|
|
1334
1638
|
/**
|
|
1335
1639
|
* `decodeWire` that never throws: undefined wherever it would throw (null, undefined, `''`,
|
|
@@ -1344,13 +1648,39 @@ function tryDecodeWire(psp, wire, currency, options = {}) {
|
|
|
1344
1648
|
return;
|
|
1345
1649
|
}
|
|
1346
1650
|
}
|
|
1347
|
-
/**
|
|
1651
|
+
/**
|
|
1652
|
+
* Internal: `tryDecodeWire` (no negatives) that is also undefined for a wire naming a fraction of a
|
|
1653
|
+
* storage unit (Airwallex 43.004 is not USD 43.00): the comparators' reading of a reported amount.
|
|
1654
|
+
*/
|
|
1655
|
+
function tryDecodeWireExactly(psp, wire, currency, convention) {
|
|
1656
|
+
try {
|
|
1657
|
+
return decodeChecked(pspDescriptor(psp), wire, currency, convention, false, true);
|
|
1658
|
+
} catch {
|
|
1659
|
+
return;
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
/** Internal: the major-unit text of `m` at its display digits, half-up (the pre-PSP-table ISO spelling). */
|
|
1348
1663
|
function legacyIsoMajor(m) {
|
|
1349
|
-
const { info,
|
|
1350
|
-
|
|
1351
|
-
units,
|
|
1352
|
-
scale: require_money.storageExponent(info)
|
|
1353
|
-
}
|
|
1664
|
+
const { info, stored } = wireStoredDecimal(m);
|
|
1665
|
+
const major = {
|
|
1666
|
+
units: stored.units,
|
|
1667
|
+
scale: require_money.storageExponent(info) + stored.scale
|
|
1668
|
+
};
|
|
1669
|
+
return require_money.formatDecimal(require_money.roundToScale(major, info.displayDigits, "half-up"));
|
|
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);
|
|
1354
1684
|
}
|
|
1355
1685
|
/** Internal: one unit of the PSP's last wire digit as Money. */
|
|
1356
1686
|
function wireUnit(psp, currency, convention) {
|
|
@@ -1362,8 +1692,7 @@ function wireUnit(psp, currency, convention) {
|
|
|
1362
1692
|
}, info, d.gated ? requireConvention(d, convention) : null);
|
|
1363
1693
|
return require_money.boundedMoney(require_iso_minor.isoMinorFactor(info, wireDigitsOf(d, info)), info);
|
|
1364
1694
|
}
|
|
1365
|
-
|
|
1366
|
-
//#region src/wire/breakdown.ts
|
|
1695
|
+
// src/wire/breakdown.ts
|
|
1367
1696
|
/**
|
|
1368
1697
|
* `total` and its `parts` (same currency, non-negative, adding up to `total`) as integer wire
|
|
1369
1698
|
* amounts whose sum is exactly `encodeWire(psp, total)`: the wire total split by largest
|
|
@@ -1394,13 +1723,14 @@ function wireBreakdown(psp, total, parts, convention) {
|
|
|
1394
1723
|
parts: out
|
|
1395
1724
|
};
|
|
1396
1725
|
}
|
|
1397
|
-
|
|
1398
|
-
//#region src/wire/compare.ts
|
|
1726
|
+
// src/wire/compare.ts
|
|
1399
1727
|
/**
|
|
1400
|
-
* Whether a PSP-reported amount is `expected
|
|
1401
|
-
* { convention, allowZero: true })`
|
|
1402
|
-
* (
|
|
1403
|
-
*
|
|
1728
|
+
* Whether a PSP-reported amount is `expected`, a Money or a FractionalMoney (Medusa's unrounded
|
|
1729
|
+
* session total). The expected wire is `encodeWire(psp, expected, { convention, allowZero: true })`
|
|
1730
|
+
* (a refusal means false); the reported one must decode exactly (strict like `tryDecodeWire`:
|
|
1731
|
+
* never `''` or an exponent, no negatives, and never a fraction of a storage unit) to the same
|
|
1732
|
+
* stored amount, so `'44.00'` matches a sent `'44'` and Airwallex `43.004` does not match `43`.
|
|
1733
|
+
* Never throws.
|
|
1404
1734
|
*/
|
|
1405
1735
|
function sameWireAmount(psp, reported, expected, options = {}) {
|
|
1406
1736
|
const { convention } = options;
|
|
@@ -1408,10 +1738,13 @@ function sameWireAmount(psp, reported, expected, options = {}) {
|
|
|
1408
1738
|
const reportedInfo = wireCurrency(options.reportedCurrency);
|
|
1409
1739
|
if (reportedInfo === null || reportedInfo !== wireCurrency(expected.currency)) return false;
|
|
1410
1740
|
}
|
|
1411
|
-
const targets = expectedTargets(psp, expected, convention,
|
|
1741
|
+
const targets = expectedTargets(psp, expected, convention, {
|
|
1742
|
+
isoDigits: options.acceptLegacyIsoDigits === true,
|
|
1743
|
+
floatRounding: options.acceptLegacyFloatRounding === true
|
|
1744
|
+
});
|
|
1412
1745
|
if (targets === null) return false;
|
|
1413
1746
|
const { target, legacy } = targets;
|
|
1414
|
-
const decode = (value) =>
|
|
1747
|
+
const decode = (value) => options.textOnly && typeof value !== "string" ? void 0 : tryDecodeWireExactly(psp, value, expected.currency, convention);
|
|
1415
1748
|
if (options.policy === "requested-exact-collected-covers" && options.requested !== void 0 && options.requested !== null) {
|
|
1416
1749
|
const requested = decode(options.requested);
|
|
1417
1750
|
const collected = decode(reported);
|
|
@@ -1420,10 +1753,14 @@ function sameWireAmount(psp, reported, expected, options = {}) {
|
|
|
1420
1753
|
}
|
|
1421
1754
|
const got = decode(reported);
|
|
1422
1755
|
if (got === void 0) return false;
|
|
1423
|
-
return got.amount === target.amount ||
|
|
1756
|
+
return got.amount === target.amount || legacy.some((m) => m.amount === got.amount);
|
|
1424
1757
|
}
|
|
1425
|
-
/**
|
|
1426
|
-
|
|
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) {
|
|
1427
1764
|
try {
|
|
1428
1765
|
const d = pspDescriptor(psp);
|
|
1429
1766
|
const wire = encodeWire(psp, expected, {
|
|
@@ -1431,21 +1768,22 @@ function expectedTargets(psp, expected, convention, acceptLegacy) {
|
|
|
1431
1768
|
allowZero: true
|
|
1432
1769
|
});
|
|
1433
1770
|
const target = decodeAt(psp, wire, expected, convention);
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
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));
|
|
1439
1777
|
return {
|
|
1440
1778
|
target,
|
|
1441
|
-
legacy
|
|
1779
|
+
legacy
|
|
1442
1780
|
};
|
|
1443
1781
|
} catch {
|
|
1444
1782
|
return null;
|
|
1445
1783
|
}
|
|
1446
1784
|
}
|
|
1447
1785
|
function decodeAt(psp, wire, expected, convention) {
|
|
1448
|
-
return decodeWire(psp, wire, expected.currency, convention);
|
|
1786
|
+
return decodeWire(psp, wire, expected.currency, { convention });
|
|
1449
1787
|
}
|
|
1450
1788
|
/**
|
|
1451
1789
|
* One unit of the PSP's last wire digit, as Money: for ISO-minor PSPs `decodeWire(psp, 1)` (the
|
|
@@ -1459,8 +1797,7 @@ function oneWireUnit(psp, currency, convention) {
|
|
|
1459
1797
|
function wireKeyPart(wire) {
|
|
1460
1798
|
return String(wire);
|
|
1461
1799
|
}
|
|
1462
|
-
|
|
1463
|
-
//#region src/data/destinations.ts
|
|
1800
|
+
// src/data/destinations.ts
|
|
1464
1801
|
const pixel = (currencyCase, unit = "major-number") => ({
|
|
1465
1802
|
unit,
|
|
1466
1803
|
currencyCase,
|
|
@@ -1523,8 +1860,7 @@ const DESTINATIONS = {
|
|
|
1523
1860
|
verified: true
|
|
1524
1861
|
}
|
|
1525
1862
|
};
|
|
1526
|
-
|
|
1527
|
-
//#region src/wire/destinations.ts
|
|
1863
|
+
// src/wire/destinations.ts
|
|
1528
1864
|
function descriptorOf(dest) {
|
|
1529
1865
|
if (typeof dest === "string" && require_own.hasOwnKey(DESTINATIONS, dest)) return DESTINATIONS[dest];
|
|
1530
1866
|
throw new require_money.MoneyError("wire_unsupported", `Unknown destination: ${require_money.describeValue(dest)}`);
|
|
@@ -1571,8 +1907,141 @@ function eventMoney(m) {
|
|
|
1571
1907
|
currency: require_money.medusaCurrencyCode(info.code)
|
|
1572
1908
|
};
|
|
1573
1909
|
}
|
|
1574
|
-
|
|
1575
|
-
|
|
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
|
|
1956
|
+
/** Registry codes only, sorted: a provider-only code (Adyen CNH) or one the registry does not know is left out. */
|
|
1957
|
+
function knownCodes(codes) {
|
|
1958
|
+
const known = [];
|
|
1959
|
+
for (const code of codes) {
|
|
1960
|
+
const info = wireCurrency(code);
|
|
1961
|
+
if (info) known.push(info.code);
|
|
1962
|
+
}
|
|
1963
|
+
return known.sort();
|
|
1964
|
+
}
|
|
1965
|
+
/**
|
|
1966
|
+
* The PSP's presentment rules, as data: the union of currencies some account can charge, the
|
|
1967
|
+
* currencies that need an account in particular countries, and the account countries limited to
|
|
1968
|
+
* a list. For capability declarations that hold the rules themselves; `pspPresentmentCurrencies`
|
|
1969
|
+
* applies them to one account. Fresh collections on every call. An unknown PSP throws
|
|
1970
|
+
* `wire_unsupported`.
|
|
1971
|
+
*/
|
|
1972
|
+
function pspPresentment(psp) {
|
|
1973
|
+
const d = pspDescriptor(psp);
|
|
1974
|
+
const requires = PRESENTMENT_REQUIRES_ACCOUNT_COUNTRY[d.id] ?? {};
|
|
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
|
+
}));
|
|
1983
|
+
return Object.freeze({
|
|
1984
|
+
currencies: new Set(knownCodes(d.presentmentCurrencies)),
|
|
1985
|
+
currencyRequiresAccountCountry: new Map(knownCodes(Object.keys(requires)).map((code) => [code, new Set(requires[code])])),
|
|
1986
|
+
accountCountryAllowsOnly: new Map(Object.keys(allowsOnly).map((country) => [country, new Set(knownCodes(allowsOnly[country]))])),
|
|
1987
|
+
accountCountries: countries,
|
|
1988
|
+
optInCompanions: optInCompanionsOf(countries)
|
|
1989
|
+
});
|
|
1990
|
+
}
|
|
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
|
+
/**
|
|
2022
|
+
* The currencies `psp` lets an account present (charge buyers in). Without `accountCountry`, the
|
|
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).
|
|
2030
|
+
*/
|
|
2031
|
+
function pspPresentmentCurrencies(psp, options = {}) {
|
|
2032
|
+
const rules = pspPresentment(psp);
|
|
2033
|
+
if (options.accountCountry === void 0) return rules.currencies;
|
|
2034
|
+
const country = options.accountCountry.trim().toUpperCase();
|
|
2035
|
+
const only = rules.accountCountryAllowsOnly.get(country);
|
|
2036
|
+
const listed = rules.accountCountries.get(country);
|
|
2037
|
+
const codes = [...rules.currencies].filter((code) => {
|
|
2038
|
+
const required = rules.currencyRequiresAccountCountry.get(code);
|
|
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;
|
|
2041
|
+
});
|
|
2042
|
+
return new Set(codes);
|
|
2043
|
+
}
|
|
2044
|
+
// src/wire/provider-amount.ts
|
|
1576
2045
|
/**
|
|
1577
2046
|
* A provider's major-unit amount (finite number, or text read by the separator engine, which
|
|
1578
2047
|
* strips the currency's symbol and code) as Money, rounded once to the storage digits. Null on
|
|
@@ -1607,24 +2076,27 @@ function parseProviderAmount(value, currency, options = {}) {
|
|
|
1607
2076
|
return null;
|
|
1608
2077
|
}
|
|
1609
2078
|
}
|
|
1610
|
-
|
|
1611
|
-
//#region src/wire/providers.ts
|
|
2079
|
+
// src/wire/providers.ts
|
|
1612
2080
|
/** RBI e-mandate cap Razorpay token registrations carry as `max_amount`: INR 15,000 (1,500,000 paise = stored). */
|
|
1613
2081
|
const RAZORPAY_AFA_FREE_CAP = Object.freeze(require_money.fromMajor(RAZORPAY_AFA_FREE_CAP_MAJOR, "INR"));
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
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
|
+
}
|
|
1619
2094
|
function verificationCharge(psp, currency) {
|
|
1620
|
-
const
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
charge = require_money.fromMajor("1", code);
|
|
1626
|
-
} else if (psp === "mollie") charge = wireUnit("mollie", code);
|
|
1627
|
-
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);
|
|
1628
2100
|
return {
|
|
1629
2101
|
wire: encodeWire(psp, charge, {
|
|
1630
2102
|
convention: ISO_MINOR_V2,
|
|
@@ -1644,8 +2116,7 @@ function iyzicoPrice(wire) {
|
|
|
1644
2116
|
const text = require_money.toDecimalText(parsed);
|
|
1645
2117
|
return text.includes(".") ? text : `${text}.0`;
|
|
1646
2118
|
}
|
|
1647
|
-
|
|
1648
|
-
//#region src/wire/slot.ts
|
|
2119
|
+
// src/wire/slot.ts
|
|
1649
2120
|
/** `m` for a slot context's `money` key. */
|
|
1650
2121
|
function slotMoney(m) {
|
|
1651
2122
|
const { info } = require_money.storedDecimal(m);
|
|
@@ -1671,13 +2142,18 @@ function readSlotMoney(context) {
|
|
|
1671
2142
|
const money = context.money;
|
|
1672
2143
|
return (isRecord(money) ? read(money.amount, money.currency_code) : void 0) ?? read(context.total ?? context.price, context.currency_code, context.currency);
|
|
1673
2144
|
}
|
|
1674
|
-
//#endregion
|
|
1675
2145
|
Object.defineProperty(exports, "ISO_MINOR_V2", {
|
|
1676
2146
|
enumerable: true,
|
|
1677
2147
|
get: function() {
|
|
1678
2148
|
return ISO_MINOR_V2;
|
|
1679
2149
|
}
|
|
1680
2150
|
});
|
|
2151
|
+
Object.defineProperty(exports, "PAYSTACK_CURRENCIES", {
|
|
2152
|
+
enumerable: true,
|
|
2153
|
+
get: function() {
|
|
2154
|
+
return PAYSTACK_CURRENCIES;
|
|
2155
|
+
}
|
|
2156
|
+
});
|
|
1681
2157
|
Object.defineProperty(exports, "PRE_CUTOVER", {
|
|
1682
2158
|
enumerable: true,
|
|
1683
2159
|
get: function() {
|
|
@@ -1696,6 +2172,24 @@ Object.defineProperty(exports, "RAZORPAY_AFA_FREE_CAP", {
|
|
|
1696
2172
|
return RAZORPAY_AFA_FREE_CAP;
|
|
1697
2173
|
}
|
|
1698
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
|
+
});
|
|
1699
2193
|
Object.defineProperty(exports, "WIRE_SCALE_ISO_MINOR_V2", {
|
|
1700
2194
|
enumerable: true,
|
|
1701
2195
|
get: function() {
|
|
@@ -1780,6 +2274,18 @@ Object.defineProperty(exports, "jsonDecimalLiteral", {
|
|
|
1780
2274
|
return jsonDecimalLiteral;
|
|
1781
2275
|
}
|
|
1782
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
|
+
});
|
|
1783
2289
|
Object.defineProperty(exports, "oneWireUnit", {
|
|
1784
2290
|
enumerable: true,
|
|
1785
2291
|
get: function() {
|
|
@@ -1792,6 +2298,12 @@ Object.defineProperty(exports, "parseProviderAmount", {
|
|
|
1792
2298
|
return parseProviderAmount;
|
|
1793
2299
|
}
|
|
1794
2300
|
});
|
|
2301
|
+
Object.defineProperty(exports, "pspAccountCountryForCurrency", {
|
|
2302
|
+
enumerable: true,
|
|
2303
|
+
get: function() {
|
|
2304
|
+
return pspAccountCountryForCurrency;
|
|
2305
|
+
}
|
|
2306
|
+
});
|
|
1795
2307
|
Object.defineProperty(exports, "pspCurrencies", {
|
|
1796
2308
|
enumerable: true,
|
|
1797
2309
|
get: function() {
|
|
@@ -1804,12 +2316,36 @@ Object.defineProperty(exports, "pspDefaultCurrency", {
|
|
|
1804
2316
|
return pspDefaultCurrency;
|
|
1805
2317
|
}
|
|
1806
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
|
+
});
|
|
1807
2331
|
Object.defineProperty(exports, "pspMinimumAmount", {
|
|
1808
2332
|
enumerable: true,
|
|
1809
2333
|
get: function() {
|
|
1810
2334
|
return pspMinimumAmount;
|
|
1811
2335
|
}
|
|
1812
2336
|
});
|
|
2337
|
+
Object.defineProperty(exports, "pspPresentment", {
|
|
2338
|
+
enumerable: true,
|
|
2339
|
+
get: function() {
|
|
2340
|
+
return pspPresentment;
|
|
2341
|
+
}
|
|
2342
|
+
});
|
|
2343
|
+
Object.defineProperty(exports, "pspPresentmentCurrencies", {
|
|
2344
|
+
enumerable: true,
|
|
2345
|
+
get: function() {
|
|
2346
|
+
return pspPresentmentCurrencies;
|
|
2347
|
+
}
|
|
2348
|
+
});
|
|
1813
2349
|
Object.defineProperty(exports, "pspSupportsCurrency", {
|
|
1814
2350
|
enumerable: true,
|
|
1815
2351
|
get: function() {
|