@ducatjs/money 0.0.0 → 0.1.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.
Files changed (285) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +51 -0
  3. package/README.md +617 -3
  4. package/assets/CREDITS.md +12 -0
  5. package/data/adyen-fx.json +19 -0
  6. package/data/adyen.json +171 -0
  7. package/data/braintree.json +223 -0
  8. package/data/cash-rounding.json +399 -0
  9. package/data/checkout.json +230 -0
  10. package/data/iso4217-list-one.xml +1956 -0
  11. package/data/klarna.json +95 -0
  12. package/data/paypal.json +65 -0
  13. package/data/stripe-fx.json +17 -0
  14. package/data/stripe.json +285 -0
  15. package/dist/adyen-fx.d.ts +25 -0
  16. package/dist/adyen-fx.d.ts.map +1 -0
  17. package/dist/adyen-fx.js +122 -0
  18. package/dist/adyen-fx.js.map +1 -0
  19. package/dist/adyen.d.ts +25 -0
  20. package/dist/adyen.d.ts.map +1 -0
  21. package/dist/adyen.js +34 -0
  22. package/dist/adyen.js.map +1 -0
  23. package/dist/allocate.d.ts +72 -0
  24. package/dist/allocate.d.ts.map +1 -0
  25. package/dist/allocate.js +314 -0
  26. package/dist/allocate.js.map +1 -0
  27. package/dist/bag.d.ts +58 -0
  28. package/dist/bag.d.ts.map +1 -0
  29. package/dist/bag.js +122 -0
  30. package/dist/bag.js.map +1 -0
  31. package/dist/braintree.d.ts +34 -0
  32. package/dist/braintree.d.ts.map +1 -0
  33. package/dist/braintree.js +45 -0
  34. package/dist/braintree.js.map +1 -0
  35. package/dist/cash.d.ts +35 -0
  36. package/dist/cash.d.ts.map +1 -0
  37. package/dist/cash.js +86 -0
  38. package/dist/cash.js.map +1 -0
  39. package/dist/checkout.d.ts +42 -0
  40. package/dist/checkout.d.ts.map +1 -0
  41. package/dist/checkout.js +52 -0
  42. package/dist/checkout.js.map +1 -0
  43. package/dist/convert.d.ts +51 -0
  44. package/dist/convert.d.ts.map +1 -0
  45. package/dist/convert.js +55 -0
  46. package/dist/convert.js.map +1 -0
  47. package/dist/currency.d.ts +22 -0
  48. package/dist/currency.d.ts.map +1 -0
  49. package/dist/currency.js +38 -0
  50. package/dist/currency.js.map +1 -0
  51. package/dist/decimal.d.ts +52 -0
  52. package/dist/decimal.d.ts.map +1 -0
  53. package/dist/decimal.js +251 -0
  54. package/dist/decimal.js.map +1 -0
  55. package/dist/ecb.d.ts +17 -0
  56. package/dist/ecb.d.ts.map +1 -0
  57. package/dist/ecb.js +147 -0
  58. package/dist/ecb.js.map +1 -0
  59. package/dist/exact.d.ts +62 -0
  60. package/dist/exact.d.ts.map +1 -0
  61. package/dist/exact.js +147 -0
  62. package/dist/exact.js.map +1 -0
  63. package/dist/fetch.d.ts +58 -0
  64. package/dist/fetch.d.ts.map +1 -0
  65. package/dist/fetch.js +79 -0
  66. package/dist/fetch.js.map +1 -0
  67. package/dist/fixed.d.ts +121 -0
  68. package/dist/fixed.d.ts.map +1 -0
  69. package/dist/fixed.js +420 -0
  70. package/dist/fixed.js.map +1 -0
  71. package/dist/fn.d.ts +27 -0
  72. package/dist/fn.d.ts.map +1 -0
  73. package/dist/fn.js +30 -0
  74. package/dist/fn.js.map +1 -0
  75. package/dist/format.d.ts +13 -0
  76. package/dist/format.d.ts.map +1 -0
  77. package/dist/format.js +90 -0
  78. package/dist/format.js.map +1 -0
  79. package/dist/generated/adyen.d.ts +3 -0
  80. package/dist/generated/adyen.d.ts.map +1 -0
  81. package/dist/generated/adyen.js +144 -0
  82. package/dist/generated/adyen.js.map +1 -0
  83. package/dist/generated/braintree.d.ts +3 -0
  84. package/dist/generated/braintree.d.ts.map +1 -0
  85. package/dist/generated/braintree.js +140 -0
  86. package/dist/generated/braintree.js.map +1 -0
  87. package/dist/generated/cash.d.ts +12 -0
  88. package/dist/generated/cash.d.ts.map +1 -0
  89. package/dist/generated/cash.js +364 -0
  90. package/dist/generated/cash.js.map +1 -0
  91. package/dist/generated/checkout.d.ts +3 -0
  92. package/dist/generated/checkout.d.ts.map +1 -0
  93. package/dist/generated/checkout.js +151 -0
  94. package/dist/generated/checkout.js.map +1 -0
  95. package/dist/generated/iso4217.d.ts +174 -0
  96. package/dist/generated/iso4217.d.ts.map +1 -0
  97. package/dist/generated/iso4217.js +175 -0
  98. package/dist/generated/iso4217.js.map +1 -0
  99. package/dist/generated/kernel.d.ts +17 -0
  100. package/dist/generated/kernel.d.ts.map +1 -0
  101. package/dist/generated/kernel.js +208 -0
  102. package/dist/generated/kernel.js.map +1 -0
  103. package/dist/generated/klarna.d.ts +3 -0
  104. package/dist/generated/klarna.d.ts.map +1 -0
  105. package/dist/generated/klarna.js +21 -0
  106. package/dist/generated/klarna.js.map +1 -0
  107. package/dist/generated/paypal.d.ts +3 -0
  108. package/dist/generated/paypal.d.ts.map +1 -0
  109. package/dist/generated/paypal.js +31 -0
  110. package/dist/generated/paypal.js.map +1 -0
  111. package/dist/generated/stripe.d.ts +8 -0
  112. package/dist/generated/stripe.d.ts.map +1 -0
  113. package/dist/generated/stripe.js +150 -0
  114. package/dist/generated/stripe.js.map +1 -0
  115. package/dist/index.d.ts +11 -0
  116. package/dist/index.d.ts.map +1 -0
  117. package/dist/index.js +11 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/klarna.d.ts +31 -0
  120. package/dist/klarna.d.ts.map +1 -0
  121. package/dist/klarna.js +38 -0
  122. package/dist/klarna.js.map +1 -0
  123. package/dist/money.d.ts +218 -0
  124. package/dist/money.d.ts.map +1 -0
  125. package/dist/money.js +577 -0
  126. package/dist/money.js.map +1 -0
  127. package/dist/parse.d.ts +11 -0
  128. package/dist/parse.d.ts.map +1 -0
  129. package/dist/parse.js +132 -0
  130. package/dist/parse.js.map +1 -0
  131. package/dist/paypal.d.ts +41 -0
  132. package/dist/paypal.d.ts.map +1 -0
  133. package/dist/paypal.js +58 -0
  134. package/dist/paypal.js.map +1 -0
  135. package/dist/plugins/adyen.d.ts +15 -0
  136. package/dist/plugins/adyen.d.ts.map +1 -0
  137. package/dist/plugins/adyen.js +10 -0
  138. package/dist/plugins/adyen.js.map +1 -0
  139. package/dist/plugins/all.d.ts +22 -0
  140. package/dist/plugins/all.d.ts.map +1 -0
  141. package/dist/plugins/all.js +23 -0
  142. package/dist/plugins/all.js.map +1 -0
  143. package/dist/plugins/allocate.d.ts +20 -0
  144. package/dist/plugins/allocate.d.ts.map +1 -0
  145. package/dist/plugins/allocate.js +26 -0
  146. package/dist/plugins/allocate.js.map +1 -0
  147. package/dist/plugins/braintree.d.ts +12 -0
  148. package/dist/plugins/braintree.d.ts.map +1 -0
  149. package/dist/plugins/braintree.js +12 -0
  150. package/dist/plugins/braintree.js.map +1 -0
  151. package/dist/plugins/cash.d.ts +19 -0
  152. package/dist/plugins/cash.d.ts.map +1 -0
  153. package/dist/plugins/cash.js +16 -0
  154. package/dist/plugins/cash.js.map +1 -0
  155. package/dist/plugins/checkout.d.ts +21 -0
  156. package/dist/plugins/checkout.d.ts.map +1 -0
  157. package/dist/plugins/checkout.js +16 -0
  158. package/dist/plugins/checkout.js.map +1 -0
  159. package/dist/plugins/convert.d.ts +20 -0
  160. package/dist/plugins/convert.d.ts.map +1 -0
  161. package/dist/plugins/convert.js +13 -0
  162. package/dist/plugins/convert.js.map +1 -0
  163. package/dist/plugins/exact.d.ts +15 -0
  164. package/dist/plugins/exact.d.ts.map +1 -0
  165. package/dist/plugins/exact.js +13 -0
  166. package/dist/plugins/exact.js.map +1 -0
  167. package/dist/plugins/fixed.d.ts +17 -0
  168. package/dist/plugins/fixed.d.ts.map +1 -0
  169. package/dist/plugins/fixed.js +13 -0
  170. package/dist/plugins/fixed.js.map +1 -0
  171. package/dist/plugins/format.d.ts +9 -0
  172. package/dist/plugins/format.d.ts.map +1 -0
  173. package/dist/plugins/format.js +16 -0
  174. package/dist/plugins/format.js.map +1 -0
  175. package/dist/plugins/klarna.d.ts +10 -0
  176. package/dist/plugins/klarna.d.ts.map +1 -0
  177. package/dist/plugins/klarna.js +10 -0
  178. package/dist/plugins/klarna.js.map +1 -0
  179. package/dist/plugins/paypal.d.ts +14 -0
  180. package/dist/plugins/paypal.d.ts.map +1 -0
  181. package/dist/plugins/paypal.js +16 -0
  182. package/dist/plugins/paypal.js.map +1 -0
  183. package/dist/plugins/prisma.d.ts +8 -0
  184. package/dist/plugins/prisma.d.ts.map +1 -0
  185. package/dist/plugins/prisma.js +13 -0
  186. package/dist/plugins/prisma.js.map +1 -0
  187. package/dist/plugins/stripe.d.ts +14 -0
  188. package/dist/plugins/stripe.d.ts.map +1 -0
  189. package/dist/plugins/stripe.js +16 -0
  190. package/dist/plugins/stripe.js.map +1 -0
  191. package/dist/plugins/tax.d.ts +21 -0
  192. package/dist/plugins/tax.d.ts.map +1 -0
  193. package/dist/plugins/tax.js +18 -0
  194. package/dist/plugins/tax.js.map +1 -0
  195. package/dist/prisma.d.ts +66 -0
  196. package/dist/prisma.d.ts.map +1 -0
  197. package/dist/prisma.js +66 -0
  198. package/dist/prisma.js.map +1 -0
  199. package/dist/processor.d.ts +28 -0
  200. package/dist/processor.d.ts.map +1 -0
  201. package/dist/processor.js +118 -0
  202. package/dist/processor.js.map +1 -0
  203. package/dist/provider.d.ts +89 -0
  204. package/dist/provider.d.ts.map +1 -0
  205. package/dist/provider.js +240 -0
  206. package/dist/provider.js.map +1 -0
  207. package/dist/rate.d.ts +119 -0
  208. package/dist/rate.d.ts.map +1 -0
  209. package/dist/rate.js +271 -0
  210. package/dist/rate.js.map +1 -0
  211. package/dist/rounding-error.d.ts +9 -0
  212. package/dist/rounding-error.d.ts.map +1 -0
  213. package/dist/rounding-error.js +9 -0
  214. package/dist/rounding-error.js.map +1 -0
  215. package/dist/rounding.d.ts +50 -0
  216. package/dist/rounding.d.ts.map +1 -0
  217. package/dist/rounding.js +87 -0
  218. package/dist/rounding.js.map +1 -0
  219. package/dist/stripe-fx.d.ts +22 -0
  220. package/dist/stripe-fx.d.ts.map +1 -0
  221. package/dist/stripe-fx.js +30 -0
  222. package/dist/stripe-fx.js.map +1 -0
  223. package/dist/stripe.d.ts +36 -0
  224. package/dist/stripe.d.ts.map +1 -0
  225. package/dist/stripe.js +39 -0
  226. package/dist/stripe.js.map +1 -0
  227. package/dist/tax.d.ts +29 -0
  228. package/dist/tax.d.ts.map +1 -0
  229. package/dist/tax.js +39 -0
  230. package/dist/tax.js.map +1 -0
  231. package/package.json +169 -5
  232. package/src/adyen-fx.ts +154 -0
  233. package/src/adyen.ts +46 -0
  234. package/src/allocate.ts +393 -0
  235. package/src/bag.ts +170 -0
  236. package/src/braintree.ts +71 -0
  237. package/src/cash.ts +115 -0
  238. package/src/checkout.ts +77 -0
  239. package/src/convert.ts +159 -0
  240. package/src/currency.ts +61 -0
  241. package/src/decimal.ts +283 -0
  242. package/src/ecb.ts +162 -0
  243. package/src/exact.ts +182 -0
  244. package/src/fetch.ts +127 -0
  245. package/src/fixed.ts +558 -0
  246. package/src/fn.ts +80 -0
  247. package/src/format.ts +106 -0
  248. package/src/generated/adyen.ts +144 -0
  249. package/src/generated/braintree.ts +140 -0
  250. package/src/generated/cash.ts +375 -0
  251. package/src/generated/checkout.ts +151 -0
  252. package/src/generated/iso4217.ts +179 -0
  253. package/src/generated/kernel.ts +230 -0
  254. package/src/generated/klarna.ts +21 -0
  255. package/src/generated/paypal.ts +31 -0
  256. package/src/generated/stripe.ts +150 -0
  257. package/src/index.ts +37 -0
  258. package/src/klarna.ts +54 -0
  259. package/src/money.ts +781 -0
  260. package/src/parse.ts +144 -0
  261. package/src/paypal.ts +93 -0
  262. package/src/plugins/adyen.ts +25 -0
  263. package/src/plugins/all.ts +47 -0
  264. package/src/plugins/allocate.ts +53 -0
  265. package/src/plugins/braintree.ts +23 -0
  266. package/src/plugins/cash.ts +33 -0
  267. package/src/plugins/checkout.ts +32 -0
  268. package/src/plugins/convert.ts +50 -0
  269. package/src/plugins/exact.ts +23 -0
  270. package/src/plugins/fixed.ts +28 -0
  271. package/src/plugins/format.ts +28 -0
  272. package/src/plugins/klarna.ts +21 -0
  273. package/src/plugins/paypal.ts +29 -0
  274. package/src/plugins/prisma.ts +24 -0
  275. package/src/plugins/stripe.ts +29 -0
  276. package/src/plugins/tax.ts +41 -0
  277. package/src/prisma.ts +118 -0
  278. package/src/processor.ts +181 -0
  279. package/src/provider.ts +324 -0
  280. package/src/rate.ts +377 -0
  281. package/src/rounding-error.ts +8 -0
  282. package/src/rounding.ts +122 -0
  283. package/src/stripe-fx.ts +49 -0
  284. package/src/stripe.ts +69 -0
  285. package/src/tax.ts +71 -0
@@ -0,0 +1,230 @@
1
+ // lean-sources sha256:69cb179d69b98bf06518e6abae249369e163ca9ac7c318064680c59920517601 content sha256:dc3d761f86eb9b865b2cfa6a6dba6e6b3853afdab3ec5c8811415f9942c6231c
2
+ // GENERATED from proofs/Ducat/Rounding.lean by `pnpm gen:kernel`. Do not edit.
3
+ import { RoundingError } from '../rounding-error.js';
4
+ import type { RoundingMode } from '../rounding.js';
5
+
6
+ const ROUNDING_NECESSARY = 'Rounding necessary: the result is not exact; pass a rounding mode';
7
+
8
+ /**
9
+ * `dividend / divisor` rounded with `mode`; `divisor` must be positive.
10
+ *
11
+ * Each `case` is printed from the Lean kernel for that mode, which is proved correct in
12
+ * proofs/Ducat/Rounding.lean: `kernel_sound` (the result satisfies the specification `Rounds`),
13
+ * `rounds_unique` (only one value does) and `kernel_fails_iff` (it throws only for 'unnecessary' on an
14
+ * inexact division), hence `kernel_correct`. Unknown modes throw a RangeError.
15
+ */
16
+ export function divideAndRoundBigint(
17
+ dividend: bigint,
18
+ divisor: bigint,
19
+ mode: RoundingMode,
20
+ ): bigint {
21
+ const quotient = dividend / divisor;
22
+ const remainder = dividend - quotient * divisor;
23
+ return roundTruncatedQuotientBigint(dividend, divisor, quotient, remainder, mode);
24
+ }
25
+
26
+ /**
27
+ * Rounds the truncated `quotient` of `dividend / divisor` (with `remainder = dividend - quotient * divisor`)
28
+ * with `mode`; `divisor` must be positive.
29
+ *
30
+ * Each `case` is printed from the Lean kernel for that mode, which is proved correct in
31
+ * proofs/Ducat/Rounding.lean: `kernel_sound` (the result satisfies the specification `Rounds`),
32
+ * `rounds_unique` (only one value does) and `kernel_fails_iff` (it throws only for 'unnecessary' on an
33
+ * inexact division), hence `kernel_correct`. Unknown modes throw a RangeError.
34
+ */
35
+ function roundTruncatedQuotientBigint(
36
+ dividend: bigint,
37
+ divisor: bigint,
38
+ quotient: bigint,
39
+ remainder: bigint,
40
+ mode: RoundingMode,
41
+ ): bigint {
42
+ if (remainder === 0n) {
43
+ return quotient;
44
+ }
45
+ const twiceRemainder = remainder < 0n ? -2n * remainder : 2n * remainder;
46
+
47
+ switch (mode) {
48
+ // rounds to the nearest integer, ties away from zero
49
+ case 'halfExpand': {
50
+ if (divisor <= twiceRemainder) {
51
+ if (dividend < 0n) {
52
+ return quotient - 1n;
53
+ }
54
+ return quotient + 1n;
55
+ }
56
+ return quotient;
57
+ }
58
+ // rounds to the nearest integer, ties to the even neighbour
59
+ case 'halfEven': {
60
+ if (divisor < twiceRemainder || (twiceRemainder === divisor && quotient % 2n !== 0n)) {
61
+ if (dividend < 0n) {
62
+ return quotient - 1n;
63
+ }
64
+ return quotient + 1n;
65
+ }
66
+ return quotient;
67
+ }
68
+ // rounds to the nearest integer, ties towards zero
69
+ case 'halfTrunc': {
70
+ if (divisor < twiceRemainder) {
71
+ if (dividend < 0n) {
72
+ return quotient - 1n;
73
+ }
74
+ return quotient + 1n;
75
+ }
76
+ return quotient;
77
+ }
78
+ // rounds to the nearest integer, ties towards +infinity
79
+ case 'halfCeil': {
80
+ if (divisor < twiceRemainder || (twiceRemainder === divisor && !(dividend < 0n))) {
81
+ if (dividend < 0n) {
82
+ return quotient - 1n;
83
+ }
84
+ return quotient + 1n;
85
+ }
86
+ return quotient;
87
+ }
88
+ // rounds to the nearest integer, ties towards -infinity
89
+ case 'halfFloor': {
90
+ if (divisor < twiceRemainder || (twiceRemainder === divisor && dividend < 0n)) {
91
+ if (dividend < 0n) {
92
+ return quotient - 1n;
93
+ }
94
+ return quotient + 1n;
95
+ }
96
+ return quotient;
97
+ }
98
+ // rounds towards zero
99
+ case 'trunc': {
100
+ return quotient;
101
+ }
102
+ // rounds away from zero
103
+ case 'expand': {
104
+ if (dividend < 0n) {
105
+ return quotient - 1n;
106
+ }
107
+ return quotient + 1n;
108
+ }
109
+ // rounds towards +infinity
110
+ case 'ceil': {
111
+ if (dividend < 0n) {
112
+ return quotient;
113
+ }
114
+ return quotient + 1n;
115
+ }
116
+ // rounds towards -infinity
117
+ case 'floor': {
118
+ if (!(dividend < 0n)) {
119
+ return quotient;
120
+ }
121
+ return quotient - 1n;
122
+ }
123
+ // rounds not at all: throws RoundingError unless the division is exact
124
+ case 'unnecessary': {
125
+ throw new RoundingError(ROUNDING_NECESSARY);
126
+ }
127
+ }
128
+ throw new RangeError(`Unknown rounding mode "${String(mode)}"`);
129
+ }
130
+
131
+ /**
132
+ * The same switch over `number`: rounds the truncated `quotient` of `dividend / divisor`, where
133
+ * `remainder = dividend - quotient * divisor` exactly and `divisor` is positive. Every input must be a safe
134
+ * integer. This copy is not proved; test/kernel.test.ts compares it with the `bigint` one.
135
+ */
136
+ export function roundTruncatedQuotient(
137
+ dividend: number,
138
+ divisor: number,
139
+ quotient: number,
140
+ remainder: number,
141
+ mode: RoundingMode,
142
+ ): number {
143
+ if (remainder === 0) {
144
+ return quotient;
145
+ }
146
+ const twiceRemainder = remainder < 0 ? -2 * remainder : 2 * remainder;
147
+
148
+ switch (mode) {
149
+ // rounds to the nearest integer, ties away from zero
150
+ case 'halfExpand': {
151
+ if (divisor <= twiceRemainder) {
152
+ if (dividend < 0) {
153
+ return quotient - 1;
154
+ }
155
+ return quotient + 1;
156
+ }
157
+ return quotient;
158
+ }
159
+ // rounds to the nearest integer, ties to the even neighbour
160
+ case 'halfEven': {
161
+ if (divisor < twiceRemainder || (twiceRemainder === divisor && quotient % 2 !== 0)) {
162
+ if (dividend < 0) {
163
+ return quotient - 1;
164
+ }
165
+ return quotient + 1;
166
+ }
167
+ return quotient;
168
+ }
169
+ // rounds to the nearest integer, ties towards zero
170
+ case 'halfTrunc': {
171
+ if (divisor < twiceRemainder) {
172
+ if (dividend < 0) {
173
+ return quotient - 1;
174
+ }
175
+ return quotient + 1;
176
+ }
177
+ return quotient;
178
+ }
179
+ // rounds to the nearest integer, ties towards +infinity
180
+ case 'halfCeil': {
181
+ if (divisor < twiceRemainder || (twiceRemainder === divisor && !(dividend < 0))) {
182
+ if (dividend < 0) {
183
+ return quotient - 1;
184
+ }
185
+ return quotient + 1;
186
+ }
187
+ return quotient;
188
+ }
189
+ // rounds to the nearest integer, ties towards -infinity
190
+ case 'halfFloor': {
191
+ if (divisor < twiceRemainder || (twiceRemainder === divisor && dividend < 0)) {
192
+ if (dividend < 0) {
193
+ return quotient - 1;
194
+ }
195
+ return quotient + 1;
196
+ }
197
+ return quotient;
198
+ }
199
+ // rounds towards zero
200
+ case 'trunc': {
201
+ return quotient;
202
+ }
203
+ // rounds away from zero
204
+ case 'expand': {
205
+ if (dividend < 0) {
206
+ return quotient - 1;
207
+ }
208
+ return quotient + 1;
209
+ }
210
+ // rounds towards +infinity
211
+ case 'ceil': {
212
+ if (dividend < 0) {
213
+ return quotient;
214
+ }
215
+ return quotient + 1;
216
+ }
217
+ // rounds towards -infinity
218
+ case 'floor': {
219
+ if (!(dividend < 0)) {
220
+ return quotient;
221
+ }
222
+ return quotient - 1;
223
+ }
224
+ // rounds not at all: throws RoundingError unless the division is exact
225
+ case 'unnecessary': {
226
+ throw new RoundingError(ROUNDING_NECESSARY);
227
+ }
228
+ }
229
+ throw new RangeError(`Unknown rounding mode "${String(mode)}"`);
230
+ }
@@ -0,0 +1,21 @@
1
+ // GENERATED by scripts/gen-currencies.mjs from data/klarna.json (https://docs.klarna.com/acquirer/klarna/get-started/integration-resilience/data-types/, retrieved 2026-11-07). Do not edit by hand.
2
+ /* eslint-disable */
3
+
4
+ /** Klarna purchase currencies and their ISO 4217 exponents (amounts are integer minor units). */
5
+ export const KLARNA_EXPONENTS: Readonly<Record<string, number>> = {
6
+ AUD: 2,
7
+ CAD: 2,
8
+ CHF: 2,
9
+ CZK: 2,
10
+ DKK: 2,
11
+ EUR: 2,
12
+ GBP: 2,
13
+ HUF: 2,
14
+ MXN: 2,
15
+ NOK: 2,
16
+ NZD: 2,
17
+ PLN: 2,
18
+ RON: 2,
19
+ SEK: 2,
20
+ USD: 2,
21
+ };
@@ -0,0 +1,31 @@
1
+ // GENERATED by scripts/gen-currencies.mjs from data/paypal.json (https://developer.paypal.com/api/rest/reference/currency-codes/, retrieved 2026-11-07). Do not edit by hand.
2
+ /* eslint-disable */
3
+
4
+ /** PayPal decimals per currency (`value` is a decimal string). HUF, JPY and TWD take none. */
5
+ export const PAYPAL_EXPONENTS: Readonly<Record<string, number>> = {
6
+ AUD: 2,
7
+ BRL: 2,
8
+ CAD: 2,
9
+ CHF: 2,
10
+ CNY: 2,
11
+ CZK: 2,
12
+ DKK: 2,
13
+ EUR: 2,
14
+ GBP: 2,
15
+ HKD: 2,
16
+ HUF: 0,
17
+ ILS: 2,
18
+ JPY: 0,
19
+ MXN: 2,
20
+ MYR: 2,
21
+ NOK: 2,
22
+ NZD: 2,
23
+ PHP: 2,
24
+ PLN: 2,
25
+ RUB: 2,
26
+ SEK: 2,
27
+ SGD: 2,
28
+ THB: 2,
29
+ TWD: 0,
30
+ USD: 2,
31
+ };
@@ -0,0 +1,150 @@
1
+ // GENERATED by scripts/gen-currencies.mjs from data/stripe.json (https://docs.stripe.com/currencies, retrieved 2026-11-07). Do not edit by hand.
2
+ /* eslint-disable */
3
+
4
+ /**
5
+ * Stripe presentment currencies: [API exponent, charge amount multiple, payout amount multiple].
6
+ * A multiple of 100 means "send a two-decimal value whose decimal part is always 00" (ISK, UGX)
7
+ * or, for payouts only, whole units (HUF, TWD). A multiple of 10 is the three-decimal rule
8
+ * (last digit must be 0).
9
+ */
10
+ export const STRIPE_RULES: Readonly<Record<string, readonly [exponent: number, chargeMultiple: number, payoutMultiple: number]>> = {
11
+ AED: [2,1,1],
12
+ AFN: [2,1,1],
13
+ ALL: [2,1,1],
14
+ AMD: [2,1,1],
15
+ ANG: [2,1,1],
16
+ AOA: [2,1,1],
17
+ ARS: [2,1,1],
18
+ AUD: [2,1,1],
19
+ AWG: [2,1,1],
20
+ AZN: [2,1,1],
21
+ BAM: [2,1,1],
22
+ BBD: [2,1,1],
23
+ BDT: [2,1,1],
24
+ BHD: [3,10,10],
25
+ BIF: [0,1,1],
26
+ BMD: [2,1,1],
27
+ BND: [2,1,1],
28
+ BOB: [2,1,1],
29
+ BRL: [2,1,1],
30
+ BSD: [2,1,1],
31
+ BWP: [2,1,1],
32
+ BYN: [2,1,1],
33
+ BZD: [2,1,1],
34
+ CAD: [2,1,1],
35
+ CDF: [2,1,1],
36
+ CHF: [2,1,1],
37
+ CLP: [0,1,1],
38
+ CNY: [2,1,1],
39
+ COP: [2,1,1],
40
+ CRC: [2,1,1],
41
+ CVE: [2,1,1],
42
+ CZK: [2,1,1],
43
+ DJF: [0,1,1],
44
+ DKK: [2,1,1],
45
+ DOP: [2,1,1],
46
+ DZD: [2,1,1],
47
+ EGP: [2,1,1],
48
+ ETB: [2,1,1],
49
+ EUR: [2,1,1],
50
+ FJD: [2,1,1],
51
+ FKP: [2,1,1],
52
+ GBP: [2,1,1],
53
+ GEL: [2,1,1],
54
+ GIP: [2,1,1],
55
+ GMD: [2,1,1],
56
+ GNF: [0,1,1],
57
+ GTQ: [2,1,1],
58
+ GYD: [2,1,1],
59
+ HKD: [2,1,1],
60
+ HNL: [2,1,1],
61
+ HTG: [2,1,1],
62
+ HUF: [2,1,100],
63
+ IDR: [2,1,1],
64
+ ILS: [2,1,1],
65
+ INR: [2,1,1],
66
+ ISK: [2,100,100],
67
+ JMD: [2,1,1],
68
+ JOD: [3,10,10],
69
+ JPY: [0,1,1],
70
+ KES: [2,1,1],
71
+ KGS: [2,1,1],
72
+ KHR: [2,1,1],
73
+ KMF: [0,1,1],
74
+ KRW: [0,1,1],
75
+ KWD: [3,10,10],
76
+ KYD: [2,1,1],
77
+ KZT: [2,1,1],
78
+ LAK: [2,1,1],
79
+ LBP: [2,1,1],
80
+ LKR: [2,1,1],
81
+ LRD: [2,1,1],
82
+ LSL: [2,1,1],
83
+ MAD: [2,1,1],
84
+ MDL: [2,1,1],
85
+ MGA: [0,1,1],
86
+ MKD: [2,1,1],
87
+ MMK: [2,1,1],
88
+ MNT: [2,1,1],
89
+ MOP: [2,1,1],
90
+ MUR: [2,1,1],
91
+ MVR: [2,1,1],
92
+ MWK: [2,1,1],
93
+ MXN: [2,1,1],
94
+ MYR: [2,1,1],
95
+ MZN: [2,1,1],
96
+ NAD: [2,1,1],
97
+ NGN: [2,1,1],
98
+ NIO: [2,1,1],
99
+ NOK: [2,1,1],
100
+ NPR: [2,1,1],
101
+ NZD: [2,1,1],
102
+ OMR: [3,10,10],
103
+ PAB: [2,1,1],
104
+ PEN: [2,1,1],
105
+ PGK: [2,1,1],
106
+ PHP: [2,1,1],
107
+ PKR: [2,1,1],
108
+ PLN: [2,1,1],
109
+ PYG: [0,1,1],
110
+ QAR: [2,1,1],
111
+ RON: [2,1,1],
112
+ RSD: [2,1,1],
113
+ RUB: [2,1,1],
114
+ RWF: [0,1,1],
115
+ SAR: [2,1,1],
116
+ SBD: [2,1,1],
117
+ SCR: [2,1,1],
118
+ SEK: [2,1,1],
119
+ SGD: [2,1,1],
120
+ SHP: [2,1,1],
121
+ SLE: [2,1,1],
122
+ SOS: [2,1,1],
123
+ SRD: [2,1,1],
124
+ STD: [2,1,1],
125
+ SZL: [2,1,1],
126
+ THB: [2,1,1],
127
+ TJS: [2,1,1],
128
+ TND: [3,10,10],
129
+ TOP: [2,1,1],
130
+ TRY: [2,1,1],
131
+ TTD: [2,1,1],
132
+ TWD: [2,1,100],
133
+ TZS: [2,1,1],
134
+ UAH: [2,1,1],
135
+ UGX: [2,100,100],
136
+ USD: [2,1,1],
137
+ UYU: [2,1,1],
138
+ UZS: [2,1,1],
139
+ VND: [0,1,1],
140
+ VUV: [0,1,1],
141
+ WST: [2,1,1],
142
+ XAF: [0,1,1],
143
+ XCD: [2,1,1],
144
+ XCG: [2,1,1],
145
+ XOF: [0,1,1],
146
+ XPF: [0,1,1],
147
+ YER: [2,1,1],
148
+ ZAR: [2,1,1],
149
+ ZMW: [2,1,1],
150
+ };
package/src/index.ts ADDED
@@ -0,0 +1,37 @@
1
+ /**
2
+ * `@ducatjs/money`: the core. Money with construction, arithmetic, rounding, comparison and
3
+ * serialisation as methods (`price.add(fee).multiply('1.075')`), plus the ISO 4217 exponents.
4
+ * The same operations as plain functions (`add(price, fee)`) are in `@ducatjs/money/fn`. Allocation, tax, conversion, cash rounding,
5
+ * formatting, parsing and the processor and database views are opt-in modules
6
+ * (`@ducatjs/money/allocate`, `@ducatjs/money/tax`, ...; `@ducatjs/money/all` for everything).
7
+ */
8
+ export {
9
+ money,
10
+ fromMinor,
11
+ zero,
12
+ fromJSON,
13
+ isMoney,
14
+ extendMoney,
15
+ type ExtendMoneyOptions,
16
+ sum,
17
+ ratio,
18
+ CurrencyMismatchError,
19
+ type Money,
20
+ type MoneyJSON,
21
+ type MoneyOptions,
22
+ type CurrencyInput,
23
+ type Factor,
24
+ type Ratio,
25
+ } from './money.js';
26
+ export { DEFAULT_ROUNDING, Rounding, RoundingError, type RoundingMode } from './rounding.js';
27
+ export {
28
+ currencyExponent,
29
+ defineCurrency,
30
+ isCurrency,
31
+ ISO_EXPONENTS,
32
+ ISO_4217_PUBLISHED,
33
+ ISO_NON_MONETARY,
34
+ type CurrencyCode,
35
+ type IsoCurrencyCode,
36
+ type CustomCurrencies,
37
+ } from './currency.js';
package/src/klarna.ts ADDED
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Klarna's amount view (Klarna Payments and Order Management; https://docs.klarna.com/acquirer/klarna/get-started/integration-resilience/data-types/,
3
+ * encoded in data/klarna.json). Amounts (`order_amount`, `unit_price`, `total_amount`, ...) are
4
+ * integers "in minor units according to the ISO 4217 standard", in the one local currency of each
5
+ * purchase country: 25 EUR -> 2500, 1000 HUF -> 100000 (fillér; PayPal sends HUF without decimals).
6
+ */
7
+ import { KLARNA_EXPONENTS } from './generated/klarna.js';
8
+ import { type CurrencyInput, type Money } from './money.js';
9
+ import { fromProcessorAmount, toProcessorAmount } from './processor.js';
10
+ import type { RoundingMode } from './rounding.js';
11
+
12
+ export { KLARNA_EXPONENTS };
13
+
14
+ /** The ISO 4217 exponent of a Klarna purchase currency; throws for any other currency. */
15
+ export function klarnaExponent(currency: string): number {
16
+ const exponent = KLARNA_EXPONENTS[currency.toUpperCase()];
17
+ if (exponent === undefined) {
18
+ throw new RangeError(`${currency} is not a Klarna purchase currency`);
19
+ }
20
+ return exponent;
21
+ }
22
+
23
+ /** Whether the currency is one of Klarna's purchase currencies (case-insensitive). */
24
+ export function isKlarnaCurrency(currency: string): boolean {
25
+ return KLARNA_EXPONENTS[currency.toUpperCase()] !== undefined;
26
+ }
27
+
28
+ /** Options for the Klarna amount: how to round when Klarna needs a coarser amount. */
29
+ export interface KlarnaAmountOptions {
30
+ /**
31
+ * How to round when the value has more decimals than the currency (default 'unnecessary': throw).
32
+ */
33
+ readonly rounding?: RoundingMode;
34
+ }
35
+
36
+ /**
37
+ * The integer to send in any Klarna amount field: toKlarna(money('25', 'EUR')) === 2500.
38
+ * A bare number, because Klarna gives the currency once per order (`purchase_currency`).
39
+ * Negative amounts pass through: discount order lines are negative ("Negative when type is
40
+ * discount"), though `order_amount` itself must be non-negative.
41
+ */
42
+ export function toKlarna(money: Money, options?: KlarnaAmountOptions): number {
43
+ const rounding = options?.rounding ?? 'unnecessary';
44
+ return toProcessorAmount('Klarna', money, klarnaExponent(money.currency), 1, rounding);
45
+ }
46
+
47
+ /** Reads a Klarna amount field: fromKlarna(2500, 'EUR') is 25.00 EUR. */
48
+ export function fromKlarna<C extends CurrencyInput>(
49
+ amount: number | bigint,
50
+ currency: C,
51
+ ): Money<Uppercase<C>> {
52
+ const code = currency.toUpperCase() as Uppercase<C>;
53
+ return fromProcessorAmount('Klarna', amount, code, klarnaExponent(code));
54
+ }