@ducatjs/money 0.2.1 → 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.
Files changed (1332) hide show
  1. package/NOTICE +47 -11
  2. package/README.md +346 -44
  3. package/data/cldr-territories.json +2791 -0
  4. package/data/crypto-units.json +68 -0
  5. package/data/rbnf/de.txt +243 -0
  6. package/data/rbnf/en.txt +166 -0
  7. package/data/rbnf/es.txt +261 -0
  8. package/data/rbnf/fr.txt +159 -0
  9. package/data/rbnf/it.txt +502 -0
  10. package/data/rbnf/nl.txt +103 -0
  11. package/data/rbnf/pt.txt +171 -0
  12. package/dist/adyen-fx.js +1 -1
  13. package/dist/adyen-fx.js.map +1 -1
  14. package/dist/allocate.d.ts.map +1 -1
  15. package/dist/allocate.js +2 -3
  16. package/dist/allocate.js.map +1 -1
  17. package/dist/cash.d.ts +15 -0
  18. package/dist/cash.d.ts.map +1 -1
  19. package/dist/cash.js +17 -0
  20. package/dist/cash.js.map +1 -1
  21. package/dist/convert.d.ts.map +1 -1
  22. package/dist/convert.js +2 -3
  23. package/dist/convert.js.map +1 -1
  24. package/dist/crypto.d.ts +54 -0
  25. package/dist/crypto.d.ts.map +1 -0
  26. package/dist/crypto.js +89 -0
  27. package/dist/crypto.js.map +1 -0
  28. package/dist/currencies.d.ts +43 -0
  29. package/dist/currencies.d.ts.map +1 -0
  30. package/dist/currencies.js +91 -0
  31. package/dist/currencies.js.map +1 -0
  32. package/dist/currency.d.ts +9 -1
  33. package/dist/currency.d.ts.map +1 -1
  34. package/dist/currency.js +41 -14
  35. package/dist/currency.js.map +1 -1
  36. package/dist/decimal.d.ts +25 -3
  37. package/dist/decimal.d.ts.map +1 -1
  38. package/dist/decimal.js +78 -8
  39. package/dist/decimal.js.map +1 -1
  40. package/dist/ecb.d.ts +23 -8
  41. package/dist/ecb.d.ts.map +1 -1
  42. package/dist/ecb.js +46 -15
  43. package/dist/ecb.js.map +1 -1
  44. package/dist/entries/adyen-fx.d.ts +3 -0
  45. package/dist/entries/adyen-fx.d.ts.map +1 -0
  46. package/dist/entries/adyen-fx.js +5 -0
  47. package/dist/entries/adyen-fx.js.map +1 -0
  48. package/dist/entries/boc.d.ts +3 -0
  49. package/dist/entries/boc.d.ts.map +1 -0
  50. package/dist/entries/boc.js +5 -0
  51. package/dist/entries/boc.js.map +1 -0
  52. package/dist/entries/boe.d.ts +3 -0
  53. package/dist/entries/boe.d.ts.map +1 -0
  54. package/dist/entries/boe.js +5 -0
  55. package/dist/entries/boe.js.map +1 -0
  56. package/dist/entries/crypto.d.ts +3 -0
  57. package/dist/entries/crypto.d.ts.map +1 -0
  58. package/dist/entries/crypto.js +5 -0
  59. package/dist/entries/crypto.js.map +1 -0
  60. package/dist/entries/currencies.d.ts +3 -0
  61. package/dist/entries/currencies.d.ts.map +1 -0
  62. package/dist/entries/currencies.js +5 -0
  63. package/dist/entries/currencies.js.map +1 -0
  64. package/dist/entries/drizzle-mysql.d.ts +3 -0
  65. package/dist/entries/drizzle-mysql.d.ts.map +1 -0
  66. package/dist/entries/drizzle-mysql.js +5 -0
  67. package/dist/entries/drizzle-mysql.js.map +1 -0
  68. package/dist/entries/drizzle-pg.d.ts +3 -0
  69. package/dist/entries/drizzle-pg.d.ts.map +1 -0
  70. package/dist/entries/drizzle-pg.js +5 -0
  71. package/dist/entries/drizzle-pg.js.map +1 -0
  72. package/dist/entries/drizzle-sqlite.d.ts +3 -0
  73. package/dist/entries/drizzle-sqlite.d.ts.map +1 -0
  74. package/dist/entries/drizzle-sqlite.js +5 -0
  75. package/dist/entries/drizzle-sqlite.js.map +1 -0
  76. package/dist/entries/ecb.d.ts +3 -0
  77. package/dist/entries/ecb.d.ts.map +1 -0
  78. package/dist/entries/ecb.js +5 -0
  79. package/dist/entries/ecb.js.map +1 -0
  80. package/dist/entries/fed.d.ts +3 -0
  81. package/dist/entries/fed.d.ts.map +1 -0
  82. package/dist/entries/fed.js +5 -0
  83. package/dist/entries/fed.js.map +1 -0
  84. package/dist/entries/fetch.d.ts +3 -0
  85. package/dist/entries/fetch.d.ts.map +1 -0
  86. package/dist/entries/fetch.js +5 -0
  87. package/dist/entries/fetch.js.map +1 -0
  88. package/dist/entries/finance.d.ts +3 -0
  89. package/dist/entries/finance.d.ts.map +1 -0
  90. package/dist/entries/finance.js +5 -0
  91. package/dist/entries/finance.js.map +1 -0
  92. package/dist/entries/historic.d.ts +3 -0
  93. package/dist/entries/historic.d.ts.map +1 -0
  94. package/dist/entries/historic.js +5 -0
  95. package/dist/entries/historic.js.map +1 -0
  96. package/dist/entries/history.d.ts +3 -0
  97. package/dist/entries/history.d.ts.map +1 -0
  98. package/dist/entries/history.js +5 -0
  99. package/dist/entries/history.js.map +1 -0
  100. package/dist/entries/hmrc.d.ts +3 -0
  101. package/dist/entries/hmrc.d.ts.map +1 -0
  102. package/dist/entries/hmrc.js +5 -0
  103. package/dist/entries/hmrc.js.map +1 -0
  104. package/dist/entries/kysely.d.ts +3 -0
  105. package/dist/entries/kysely.d.ts.map +1 -0
  106. package/dist/entries/kysely.js +5 -0
  107. package/dist/entries/kysely.js.map +1 -0
  108. package/dist/entries/parse.d.ts +3 -0
  109. package/dist/entries/parse.d.ts.map +1 -0
  110. package/dist/entries/parse.js +5 -0
  111. package/dist/entries/parse.js.map +1 -0
  112. package/dist/entries/pg.d.ts +3 -0
  113. package/dist/entries/pg.d.ts.map +1 -0
  114. package/dist/entries/pg.js +5 -0
  115. package/dist/entries/pg.js.map +1 -0
  116. package/dist/entries/policy.d.ts +3 -0
  117. package/dist/entries/policy.d.ts.map +1 -0
  118. package/dist/entries/policy.js +5 -0
  119. package/dist/entries/policy.js.map +1 -0
  120. package/dist/entries/pricing.d.ts +3 -0
  121. package/dist/entries/pricing.d.ts.map +1 -0
  122. package/dist/entries/pricing.js +5 -0
  123. package/dist/entries/pricing.js.map +1 -0
  124. package/dist/entries/stripe-fx.d.ts +3 -0
  125. package/dist/entries/stripe-fx.d.ts.map +1 -0
  126. package/dist/entries/stripe-fx.js +5 -0
  127. package/dist/entries/stripe-fx.js.map +1 -0
  128. package/dist/entries/testing-arbitraries.d.ts +3 -0
  129. package/dist/entries/testing-arbitraries.d.ts.map +1 -0
  130. package/dist/entries/testing-arbitraries.js +5 -0
  131. package/dist/entries/testing-arbitraries.js.map +1 -0
  132. package/dist/entries/testing-index.d.ts +3 -0
  133. package/dist/entries/testing-index.d.ts.map +1 -0
  134. package/dist/entries/testing-index.js +5 -0
  135. package/dist/entries/testing-index.js.map +1 -0
  136. package/dist/entries/testing-jest.d.ts +3 -0
  137. package/dist/entries/testing-jest.d.ts.map +1 -0
  138. package/dist/entries/testing-jest.js +5 -0
  139. package/dist/entries/testing-jest.js.map +1 -0
  140. package/dist/entries/testing-vitest.d.ts +3 -0
  141. package/dist/entries/testing-vitest.d.ts.map +1 -0
  142. package/dist/entries/testing-vitest.js +5 -0
  143. package/dist/entries/testing-vitest.js.map +1 -0
  144. package/dist/entries/valibot.d.ts +3 -0
  145. package/dist/entries/valibot.d.ts.map +1 -0
  146. package/dist/entries/valibot.js +5 -0
  147. package/dist/entries/valibot.js.map +1 -0
  148. package/dist/entries/wire.d.ts +3 -0
  149. package/dist/entries/wire.d.ts.map +1 -0
  150. package/dist/entries/wire.js +5 -0
  151. package/dist/entries/wire.js.map +1 -0
  152. package/dist/entries/zod.d.ts +3 -0
  153. package/dist/entries/zod.d.ts.map +1 -0
  154. package/dist/entries/zod.js +5 -0
  155. package/dist/entries/zod.js.map +1 -0
  156. package/dist/exact.d.ts.map +1 -1
  157. package/dist/exact.js +3 -3
  158. package/dist/exact.js.map +1 -1
  159. package/dist/fetch.d.ts +7 -1
  160. package/dist/fetch.d.ts.map +1 -1
  161. package/dist/fetch.js +11 -2
  162. package/dist/fetch.js.map +1 -1
  163. package/dist/finance.d.ts +296 -0
  164. package/dist/finance.d.ts.map +1 -0
  165. package/dist/finance.js +825 -0
  166. package/dist/finance.js.map +1 -0
  167. package/dist/fixed-money.d.ts +12 -0
  168. package/dist/fixed-money.d.ts.map +1 -0
  169. package/dist/fixed-money.js +32 -0
  170. package/dist/fixed-money.js.map +1 -0
  171. package/dist/fixed.d.ts +26 -9
  172. package/dist/fixed.d.ts.map +1 -1
  173. package/dist/fixed.js +75 -49
  174. package/dist/fixed.js.map +1 -1
  175. package/dist/fn.d.ts +17 -1
  176. package/dist/fn.d.ts.map +1 -1
  177. package/dist/fn.js +17 -1
  178. package/dist/fn.js.map +1 -1
  179. package/dist/format.d.ts.map +1 -1
  180. package/dist/format.js +28 -9
  181. package/dist/format.js.map +1 -1
  182. package/dist/generated/crypto.d.ts +58 -0
  183. package/dist/generated/crypto.d.ts.map +1 -0
  184. package/dist/generated/crypto.js +15 -0
  185. package/dist/generated/crypto.js.map +1 -0
  186. package/dist/generated/iso/AED.d.ts +2 -0
  187. package/dist/generated/iso/AED.d.ts.map +1 -0
  188. package/dist/generated/iso/AED.js +5 -0
  189. package/dist/generated/iso/AED.js.map +1 -0
  190. package/dist/generated/iso/AFN.d.ts +2 -0
  191. package/dist/generated/iso/AFN.d.ts.map +1 -0
  192. package/dist/generated/iso/AFN.js +5 -0
  193. package/dist/generated/iso/AFN.js.map +1 -0
  194. package/dist/generated/iso/ALL.d.ts +2 -0
  195. package/dist/generated/iso/ALL.d.ts.map +1 -0
  196. package/dist/generated/iso/ALL.js +5 -0
  197. package/dist/generated/iso/ALL.js.map +1 -0
  198. package/dist/generated/iso/AMD.d.ts +2 -0
  199. package/dist/generated/iso/AMD.d.ts.map +1 -0
  200. package/dist/generated/iso/AMD.js +5 -0
  201. package/dist/generated/iso/AMD.js.map +1 -0
  202. package/dist/generated/iso/AOA.d.ts +2 -0
  203. package/dist/generated/iso/AOA.d.ts.map +1 -0
  204. package/dist/generated/iso/AOA.js +5 -0
  205. package/dist/generated/iso/AOA.js.map +1 -0
  206. package/dist/generated/iso/ARS.d.ts +2 -0
  207. package/dist/generated/iso/ARS.d.ts.map +1 -0
  208. package/dist/generated/iso/ARS.js +5 -0
  209. package/dist/generated/iso/ARS.js.map +1 -0
  210. package/dist/generated/iso/AUD.d.ts +2 -0
  211. package/dist/generated/iso/AUD.d.ts.map +1 -0
  212. package/dist/generated/iso/AUD.js +5 -0
  213. package/dist/generated/iso/AUD.js.map +1 -0
  214. package/dist/generated/iso/AWG.d.ts +2 -0
  215. package/dist/generated/iso/AWG.d.ts.map +1 -0
  216. package/dist/generated/iso/AWG.js +5 -0
  217. package/dist/generated/iso/AWG.js.map +1 -0
  218. package/dist/generated/iso/AZN.d.ts +2 -0
  219. package/dist/generated/iso/AZN.d.ts.map +1 -0
  220. package/dist/generated/iso/AZN.js +5 -0
  221. package/dist/generated/iso/AZN.js.map +1 -0
  222. package/dist/generated/iso/BAM.d.ts +2 -0
  223. package/dist/generated/iso/BAM.d.ts.map +1 -0
  224. package/dist/generated/iso/BAM.js +5 -0
  225. package/dist/generated/iso/BAM.js.map +1 -0
  226. package/dist/generated/iso/BBD.d.ts +2 -0
  227. package/dist/generated/iso/BBD.d.ts.map +1 -0
  228. package/dist/generated/iso/BBD.js +5 -0
  229. package/dist/generated/iso/BBD.js.map +1 -0
  230. package/dist/generated/iso/BDT.d.ts +2 -0
  231. package/dist/generated/iso/BDT.d.ts.map +1 -0
  232. package/dist/generated/iso/BDT.js +5 -0
  233. package/dist/generated/iso/BDT.js.map +1 -0
  234. package/dist/generated/iso/BHD.d.ts +2 -0
  235. package/dist/generated/iso/BHD.d.ts.map +1 -0
  236. package/dist/generated/iso/BHD.js +5 -0
  237. package/dist/generated/iso/BHD.js.map +1 -0
  238. package/dist/generated/iso/BIF.d.ts +2 -0
  239. package/dist/generated/iso/BIF.d.ts.map +1 -0
  240. package/dist/generated/iso/BIF.js +5 -0
  241. package/dist/generated/iso/BIF.js.map +1 -0
  242. package/dist/generated/iso/BMD.d.ts +2 -0
  243. package/dist/generated/iso/BMD.d.ts.map +1 -0
  244. package/dist/generated/iso/BMD.js +5 -0
  245. package/dist/generated/iso/BMD.js.map +1 -0
  246. package/dist/generated/iso/BND.d.ts +2 -0
  247. package/dist/generated/iso/BND.d.ts.map +1 -0
  248. package/dist/generated/iso/BND.js +5 -0
  249. package/dist/generated/iso/BND.js.map +1 -0
  250. package/dist/generated/iso/BOB.d.ts +2 -0
  251. package/dist/generated/iso/BOB.d.ts.map +1 -0
  252. package/dist/generated/iso/BOB.js +5 -0
  253. package/dist/generated/iso/BOB.js.map +1 -0
  254. package/dist/generated/iso/BOV.d.ts +2 -0
  255. package/dist/generated/iso/BOV.d.ts.map +1 -0
  256. package/dist/generated/iso/BOV.js +5 -0
  257. package/dist/generated/iso/BOV.js.map +1 -0
  258. package/dist/generated/iso/BRL.d.ts +2 -0
  259. package/dist/generated/iso/BRL.d.ts.map +1 -0
  260. package/dist/generated/iso/BRL.js +5 -0
  261. package/dist/generated/iso/BRL.js.map +1 -0
  262. package/dist/generated/iso/BSD.d.ts +2 -0
  263. package/dist/generated/iso/BSD.d.ts.map +1 -0
  264. package/dist/generated/iso/BSD.js +5 -0
  265. package/dist/generated/iso/BSD.js.map +1 -0
  266. package/dist/generated/iso/BTN.d.ts +2 -0
  267. package/dist/generated/iso/BTN.d.ts.map +1 -0
  268. package/dist/generated/iso/BTN.js +5 -0
  269. package/dist/generated/iso/BTN.js.map +1 -0
  270. package/dist/generated/iso/BWP.d.ts +2 -0
  271. package/dist/generated/iso/BWP.d.ts.map +1 -0
  272. package/dist/generated/iso/BWP.js +5 -0
  273. package/dist/generated/iso/BWP.js.map +1 -0
  274. package/dist/generated/iso/BYN.d.ts +2 -0
  275. package/dist/generated/iso/BYN.d.ts.map +1 -0
  276. package/dist/generated/iso/BYN.js +5 -0
  277. package/dist/generated/iso/BYN.js.map +1 -0
  278. package/dist/generated/iso/BZD.d.ts +2 -0
  279. package/dist/generated/iso/BZD.d.ts.map +1 -0
  280. package/dist/generated/iso/BZD.js +5 -0
  281. package/dist/generated/iso/BZD.js.map +1 -0
  282. package/dist/generated/iso/CAD.d.ts +2 -0
  283. package/dist/generated/iso/CAD.d.ts.map +1 -0
  284. package/dist/generated/iso/CAD.js +5 -0
  285. package/dist/generated/iso/CAD.js.map +1 -0
  286. package/dist/generated/iso/CDF.d.ts +2 -0
  287. package/dist/generated/iso/CDF.d.ts.map +1 -0
  288. package/dist/generated/iso/CDF.js +5 -0
  289. package/dist/generated/iso/CDF.js.map +1 -0
  290. package/dist/generated/iso/CHE.d.ts +2 -0
  291. package/dist/generated/iso/CHE.d.ts.map +1 -0
  292. package/dist/generated/iso/CHE.js +5 -0
  293. package/dist/generated/iso/CHE.js.map +1 -0
  294. package/dist/generated/iso/CHF.d.ts +2 -0
  295. package/dist/generated/iso/CHF.d.ts.map +1 -0
  296. package/dist/generated/iso/CHF.js +5 -0
  297. package/dist/generated/iso/CHF.js.map +1 -0
  298. package/dist/generated/iso/CHW.d.ts +2 -0
  299. package/dist/generated/iso/CHW.d.ts.map +1 -0
  300. package/dist/generated/iso/CHW.js +5 -0
  301. package/dist/generated/iso/CHW.js.map +1 -0
  302. package/dist/generated/iso/CLF.d.ts +2 -0
  303. package/dist/generated/iso/CLF.d.ts.map +1 -0
  304. package/dist/generated/iso/CLF.js +5 -0
  305. package/dist/generated/iso/CLF.js.map +1 -0
  306. package/dist/generated/iso/CLP.d.ts +2 -0
  307. package/dist/generated/iso/CLP.d.ts.map +1 -0
  308. package/dist/generated/iso/CLP.js +5 -0
  309. package/dist/generated/iso/CLP.js.map +1 -0
  310. package/dist/generated/iso/CNY.d.ts +2 -0
  311. package/dist/generated/iso/CNY.d.ts.map +1 -0
  312. package/dist/generated/iso/CNY.js +5 -0
  313. package/dist/generated/iso/CNY.js.map +1 -0
  314. package/dist/generated/iso/COP.d.ts +2 -0
  315. package/dist/generated/iso/COP.d.ts.map +1 -0
  316. package/dist/generated/iso/COP.js +5 -0
  317. package/dist/generated/iso/COP.js.map +1 -0
  318. package/dist/generated/iso/COU.d.ts +2 -0
  319. package/dist/generated/iso/COU.d.ts.map +1 -0
  320. package/dist/generated/iso/COU.js +5 -0
  321. package/dist/generated/iso/COU.js.map +1 -0
  322. package/dist/generated/iso/CRC.d.ts +2 -0
  323. package/dist/generated/iso/CRC.d.ts.map +1 -0
  324. package/dist/generated/iso/CRC.js +5 -0
  325. package/dist/generated/iso/CRC.js.map +1 -0
  326. package/dist/generated/iso/CUP.d.ts +2 -0
  327. package/dist/generated/iso/CUP.d.ts.map +1 -0
  328. package/dist/generated/iso/CUP.js +5 -0
  329. package/dist/generated/iso/CUP.js.map +1 -0
  330. package/dist/generated/iso/CVE.d.ts +2 -0
  331. package/dist/generated/iso/CVE.d.ts.map +1 -0
  332. package/dist/generated/iso/CVE.js +5 -0
  333. package/dist/generated/iso/CVE.js.map +1 -0
  334. package/dist/generated/iso/CZK.d.ts +2 -0
  335. package/dist/generated/iso/CZK.d.ts.map +1 -0
  336. package/dist/generated/iso/CZK.js +5 -0
  337. package/dist/generated/iso/CZK.js.map +1 -0
  338. package/dist/generated/iso/DJF.d.ts +2 -0
  339. package/dist/generated/iso/DJF.d.ts.map +1 -0
  340. package/dist/generated/iso/DJF.js +5 -0
  341. package/dist/generated/iso/DJF.js.map +1 -0
  342. package/dist/generated/iso/DKK.d.ts +2 -0
  343. package/dist/generated/iso/DKK.d.ts.map +1 -0
  344. package/dist/generated/iso/DKK.js +5 -0
  345. package/dist/generated/iso/DKK.js.map +1 -0
  346. package/dist/generated/iso/DOP.d.ts +2 -0
  347. package/dist/generated/iso/DOP.d.ts.map +1 -0
  348. package/dist/generated/iso/DOP.js +5 -0
  349. package/dist/generated/iso/DOP.js.map +1 -0
  350. package/dist/generated/iso/DZD.d.ts +2 -0
  351. package/dist/generated/iso/DZD.d.ts.map +1 -0
  352. package/dist/generated/iso/DZD.js +5 -0
  353. package/dist/generated/iso/DZD.js.map +1 -0
  354. package/dist/generated/iso/EGP.d.ts +2 -0
  355. package/dist/generated/iso/EGP.d.ts.map +1 -0
  356. package/dist/generated/iso/EGP.js +5 -0
  357. package/dist/generated/iso/EGP.js.map +1 -0
  358. package/dist/generated/iso/ERN.d.ts +2 -0
  359. package/dist/generated/iso/ERN.d.ts.map +1 -0
  360. package/dist/generated/iso/ERN.js +5 -0
  361. package/dist/generated/iso/ERN.js.map +1 -0
  362. package/dist/generated/iso/ETB.d.ts +2 -0
  363. package/dist/generated/iso/ETB.d.ts.map +1 -0
  364. package/dist/generated/iso/ETB.js +5 -0
  365. package/dist/generated/iso/ETB.js.map +1 -0
  366. package/dist/generated/iso/EUR.d.ts +2 -0
  367. package/dist/generated/iso/EUR.d.ts.map +1 -0
  368. package/dist/generated/iso/EUR.js +5 -0
  369. package/dist/generated/iso/EUR.js.map +1 -0
  370. package/dist/generated/iso/FJD.d.ts +2 -0
  371. package/dist/generated/iso/FJD.d.ts.map +1 -0
  372. package/dist/generated/iso/FJD.js +5 -0
  373. package/dist/generated/iso/FJD.js.map +1 -0
  374. package/dist/generated/iso/FKP.d.ts +2 -0
  375. package/dist/generated/iso/FKP.d.ts.map +1 -0
  376. package/dist/generated/iso/FKP.js +5 -0
  377. package/dist/generated/iso/FKP.js.map +1 -0
  378. package/dist/generated/iso/GBP.d.ts +2 -0
  379. package/dist/generated/iso/GBP.d.ts.map +1 -0
  380. package/dist/generated/iso/GBP.js +5 -0
  381. package/dist/generated/iso/GBP.js.map +1 -0
  382. package/dist/generated/iso/GEL.d.ts +2 -0
  383. package/dist/generated/iso/GEL.d.ts.map +1 -0
  384. package/dist/generated/iso/GEL.js +5 -0
  385. package/dist/generated/iso/GEL.js.map +1 -0
  386. package/dist/generated/iso/GHS.d.ts +2 -0
  387. package/dist/generated/iso/GHS.d.ts.map +1 -0
  388. package/dist/generated/iso/GHS.js +5 -0
  389. package/dist/generated/iso/GHS.js.map +1 -0
  390. package/dist/generated/iso/GIP.d.ts +2 -0
  391. package/dist/generated/iso/GIP.d.ts.map +1 -0
  392. package/dist/generated/iso/GIP.js +5 -0
  393. package/dist/generated/iso/GIP.js.map +1 -0
  394. package/dist/generated/iso/GMD.d.ts +2 -0
  395. package/dist/generated/iso/GMD.d.ts.map +1 -0
  396. package/dist/generated/iso/GMD.js +5 -0
  397. package/dist/generated/iso/GMD.js.map +1 -0
  398. package/dist/generated/iso/GNF.d.ts +2 -0
  399. package/dist/generated/iso/GNF.d.ts.map +1 -0
  400. package/dist/generated/iso/GNF.js +5 -0
  401. package/dist/generated/iso/GNF.js.map +1 -0
  402. package/dist/generated/iso/GTQ.d.ts +2 -0
  403. package/dist/generated/iso/GTQ.d.ts.map +1 -0
  404. package/dist/generated/iso/GTQ.js +5 -0
  405. package/dist/generated/iso/GTQ.js.map +1 -0
  406. package/dist/generated/iso/GYD.d.ts +2 -0
  407. package/dist/generated/iso/GYD.d.ts.map +1 -0
  408. package/dist/generated/iso/GYD.js +5 -0
  409. package/dist/generated/iso/GYD.js.map +1 -0
  410. package/dist/generated/iso/HKD.d.ts +2 -0
  411. package/dist/generated/iso/HKD.d.ts.map +1 -0
  412. package/dist/generated/iso/HKD.js +5 -0
  413. package/dist/generated/iso/HKD.js.map +1 -0
  414. package/dist/generated/iso/HNL.d.ts +2 -0
  415. package/dist/generated/iso/HNL.d.ts.map +1 -0
  416. package/dist/generated/iso/HNL.js +5 -0
  417. package/dist/generated/iso/HNL.js.map +1 -0
  418. package/dist/generated/iso/HTG.d.ts +2 -0
  419. package/dist/generated/iso/HTG.d.ts.map +1 -0
  420. package/dist/generated/iso/HTG.js +5 -0
  421. package/dist/generated/iso/HTG.js.map +1 -0
  422. package/dist/generated/iso/HUF.d.ts +2 -0
  423. package/dist/generated/iso/HUF.d.ts.map +1 -0
  424. package/dist/generated/iso/HUF.js +5 -0
  425. package/dist/generated/iso/HUF.js.map +1 -0
  426. package/dist/generated/iso/IDR.d.ts +2 -0
  427. package/dist/generated/iso/IDR.d.ts.map +1 -0
  428. package/dist/generated/iso/IDR.js +5 -0
  429. package/dist/generated/iso/IDR.js.map +1 -0
  430. package/dist/generated/iso/ILS.d.ts +2 -0
  431. package/dist/generated/iso/ILS.d.ts.map +1 -0
  432. package/dist/generated/iso/ILS.js +5 -0
  433. package/dist/generated/iso/ILS.js.map +1 -0
  434. package/dist/generated/iso/INR.d.ts +2 -0
  435. package/dist/generated/iso/INR.d.ts.map +1 -0
  436. package/dist/generated/iso/INR.js +5 -0
  437. package/dist/generated/iso/INR.js.map +1 -0
  438. package/dist/generated/iso/IQD.d.ts +2 -0
  439. package/dist/generated/iso/IQD.d.ts.map +1 -0
  440. package/dist/generated/iso/IQD.js +5 -0
  441. package/dist/generated/iso/IQD.js.map +1 -0
  442. package/dist/generated/iso/IRR.d.ts +2 -0
  443. package/dist/generated/iso/IRR.d.ts.map +1 -0
  444. package/dist/generated/iso/IRR.js +5 -0
  445. package/dist/generated/iso/IRR.js.map +1 -0
  446. package/dist/generated/iso/ISK.d.ts +2 -0
  447. package/dist/generated/iso/ISK.d.ts.map +1 -0
  448. package/dist/generated/iso/ISK.js +5 -0
  449. package/dist/generated/iso/ISK.js.map +1 -0
  450. package/dist/generated/iso/JMD.d.ts +2 -0
  451. package/dist/generated/iso/JMD.d.ts.map +1 -0
  452. package/dist/generated/iso/JMD.js +5 -0
  453. package/dist/generated/iso/JMD.js.map +1 -0
  454. package/dist/generated/iso/JOD.d.ts +2 -0
  455. package/dist/generated/iso/JOD.d.ts.map +1 -0
  456. package/dist/generated/iso/JOD.js +5 -0
  457. package/dist/generated/iso/JOD.js.map +1 -0
  458. package/dist/generated/iso/JPY.d.ts +2 -0
  459. package/dist/generated/iso/JPY.d.ts.map +1 -0
  460. package/dist/generated/iso/JPY.js +5 -0
  461. package/dist/generated/iso/JPY.js.map +1 -0
  462. package/dist/generated/iso/KES.d.ts +2 -0
  463. package/dist/generated/iso/KES.d.ts.map +1 -0
  464. package/dist/generated/iso/KES.js +5 -0
  465. package/dist/generated/iso/KES.js.map +1 -0
  466. package/dist/generated/iso/KGS.d.ts +2 -0
  467. package/dist/generated/iso/KGS.d.ts.map +1 -0
  468. package/dist/generated/iso/KGS.js +5 -0
  469. package/dist/generated/iso/KGS.js.map +1 -0
  470. package/dist/generated/iso/KHR.d.ts +2 -0
  471. package/dist/generated/iso/KHR.d.ts.map +1 -0
  472. package/dist/generated/iso/KHR.js +5 -0
  473. package/dist/generated/iso/KHR.js.map +1 -0
  474. package/dist/generated/iso/KMF.d.ts +2 -0
  475. package/dist/generated/iso/KMF.d.ts.map +1 -0
  476. package/dist/generated/iso/KMF.js +5 -0
  477. package/dist/generated/iso/KMF.js.map +1 -0
  478. package/dist/generated/iso/KPW.d.ts +2 -0
  479. package/dist/generated/iso/KPW.d.ts.map +1 -0
  480. package/dist/generated/iso/KPW.js +5 -0
  481. package/dist/generated/iso/KPW.js.map +1 -0
  482. package/dist/generated/iso/KRW.d.ts +2 -0
  483. package/dist/generated/iso/KRW.d.ts.map +1 -0
  484. package/dist/generated/iso/KRW.js +5 -0
  485. package/dist/generated/iso/KRW.js.map +1 -0
  486. package/dist/generated/iso/KWD.d.ts +2 -0
  487. package/dist/generated/iso/KWD.d.ts.map +1 -0
  488. package/dist/generated/iso/KWD.js +5 -0
  489. package/dist/generated/iso/KWD.js.map +1 -0
  490. package/dist/generated/iso/KYD.d.ts +2 -0
  491. package/dist/generated/iso/KYD.d.ts.map +1 -0
  492. package/dist/generated/iso/KYD.js +5 -0
  493. package/dist/generated/iso/KYD.js.map +1 -0
  494. package/dist/generated/iso/KZT.d.ts +2 -0
  495. package/dist/generated/iso/KZT.d.ts.map +1 -0
  496. package/dist/generated/iso/KZT.js +5 -0
  497. package/dist/generated/iso/KZT.js.map +1 -0
  498. package/dist/generated/iso/LAK.d.ts +2 -0
  499. package/dist/generated/iso/LAK.d.ts.map +1 -0
  500. package/dist/generated/iso/LAK.js +5 -0
  501. package/dist/generated/iso/LAK.js.map +1 -0
  502. package/dist/generated/iso/LBP.d.ts +2 -0
  503. package/dist/generated/iso/LBP.d.ts.map +1 -0
  504. package/dist/generated/iso/LBP.js +5 -0
  505. package/dist/generated/iso/LBP.js.map +1 -0
  506. package/dist/generated/iso/LKR.d.ts +2 -0
  507. package/dist/generated/iso/LKR.d.ts.map +1 -0
  508. package/dist/generated/iso/LKR.js +5 -0
  509. package/dist/generated/iso/LKR.js.map +1 -0
  510. package/dist/generated/iso/LRD.d.ts +2 -0
  511. package/dist/generated/iso/LRD.d.ts.map +1 -0
  512. package/dist/generated/iso/LRD.js +5 -0
  513. package/dist/generated/iso/LRD.js.map +1 -0
  514. package/dist/generated/iso/LSL.d.ts +2 -0
  515. package/dist/generated/iso/LSL.d.ts.map +1 -0
  516. package/dist/generated/iso/LSL.js +5 -0
  517. package/dist/generated/iso/LSL.js.map +1 -0
  518. package/dist/generated/iso/LYD.d.ts +2 -0
  519. package/dist/generated/iso/LYD.d.ts.map +1 -0
  520. package/dist/generated/iso/LYD.js +5 -0
  521. package/dist/generated/iso/LYD.js.map +1 -0
  522. package/dist/generated/iso/MAD.d.ts +2 -0
  523. package/dist/generated/iso/MAD.d.ts.map +1 -0
  524. package/dist/generated/iso/MAD.js +5 -0
  525. package/dist/generated/iso/MAD.js.map +1 -0
  526. package/dist/generated/iso/MDL.d.ts +2 -0
  527. package/dist/generated/iso/MDL.d.ts.map +1 -0
  528. package/dist/generated/iso/MDL.js +5 -0
  529. package/dist/generated/iso/MDL.js.map +1 -0
  530. package/dist/generated/iso/MGA.d.ts +2 -0
  531. package/dist/generated/iso/MGA.d.ts.map +1 -0
  532. package/dist/generated/iso/MGA.js +5 -0
  533. package/dist/generated/iso/MGA.js.map +1 -0
  534. package/dist/generated/iso/MKD.d.ts +2 -0
  535. package/dist/generated/iso/MKD.d.ts.map +1 -0
  536. package/dist/generated/iso/MKD.js +5 -0
  537. package/dist/generated/iso/MKD.js.map +1 -0
  538. package/dist/generated/iso/MMK.d.ts +2 -0
  539. package/dist/generated/iso/MMK.d.ts.map +1 -0
  540. package/dist/generated/iso/MMK.js +5 -0
  541. package/dist/generated/iso/MMK.js.map +1 -0
  542. package/dist/generated/iso/MNT.d.ts +2 -0
  543. package/dist/generated/iso/MNT.d.ts.map +1 -0
  544. package/dist/generated/iso/MNT.js +5 -0
  545. package/dist/generated/iso/MNT.js.map +1 -0
  546. package/dist/generated/iso/MOP.d.ts +2 -0
  547. package/dist/generated/iso/MOP.d.ts.map +1 -0
  548. package/dist/generated/iso/MOP.js +5 -0
  549. package/dist/generated/iso/MOP.js.map +1 -0
  550. package/dist/generated/iso/MRU.d.ts +2 -0
  551. package/dist/generated/iso/MRU.d.ts.map +1 -0
  552. package/dist/generated/iso/MRU.js +5 -0
  553. package/dist/generated/iso/MRU.js.map +1 -0
  554. package/dist/generated/iso/MUR.d.ts +2 -0
  555. package/dist/generated/iso/MUR.d.ts.map +1 -0
  556. package/dist/generated/iso/MUR.js +5 -0
  557. package/dist/generated/iso/MUR.js.map +1 -0
  558. package/dist/generated/iso/MVR.d.ts +2 -0
  559. package/dist/generated/iso/MVR.d.ts.map +1 -0
  560. package/dist/generated/iso/MVR.js +5 -0
  561. package/dist/generated/iso/MVR.js.map +1 -0
  562. package/dist/generated/iso/MWK.d.ts +2 -0
  563. package/dist/generated/iso/MWK.d.ts.map +1 -0
  564. package/dist/generated/iso/MWK.js +5 -0
  565. package/dist/generated/iso/MWK.js.map +1 -0
  566. package/dist/generated/iso/MXN.d.ts +2 -0
  567. package/dist/generated/iso/MXN.d.ts.map +1 -0
  568. package/dist/generated/iso/MXN.js +5 -0
  569. package/dist/generated/iso/MXN.js.map +1 -0
  570. package/dist/generated/iso/MXV.d.ts +2 -0
  571. package/dist/generated/iso/MXV.d.ts.map +1 -0
  572. package/dist/generated/iso/MXV.js +5 -0
  573. package/dist/generated/iso/MXV.js.map +1 -0
  574. package/dist/generated/iso/MYR.d.ts +2 -0
  575. package/dist/generated/iso/MYR.d.ts.map +1 -0
  576. package/dist/generated/iso/MYR.js +5 -0
  577. package/dist/generated/iso/MYR.js.map +1 -0
  578. package/dist/generated/iso/MZN.d.ts +2 -0
  579. package/dist/generated/iso/MZN.d.ts.map +1 -0
  580. package/dist/generated/iso/MZN.js +5 -0
  581. package/dist/generated/iso/MZN.js.map +1 -0
  582. package/dist/generated/iso/NAD.d.ts +2 -0
  583. package/dist/generated/iso/NAD.d.ts.map +1 -0
  584. package/dist/generated/iso/NAD.js +5 -0
  585. package/dist/generated/iso/NAD.js.map +1 -0
  586. package/dist/generated/iso/NGN.d.ts +2 -0
  587. package/dist/generated/iso/NGN.d.ts.map +1 -0
  588. package/dist/generated/iso/NGN.js +5 -0
  589. package/dist/generated/iso/NGN.js.map +1 -0
  590. package/dist/generated/iso/NIO.d.ts +2 -0
  591. package/dist/generated/iso/NIO.d.ts.map +1 -0
  592. package/dist/generated/iso/NIO.js +5 -0
  593. package/dist/generated/iso/NIO.js.map +1 -0
  594. package/dist/generated/iso/NOK.d.ts +2 -0
  595. package/dist/generated/iso/NOK.d.ts.map +1 -0
  596. package/dist/generated/iso/NOK.js +5 -0
  597. package/dist/generated/iso/NOK.js.map +1 -0
  598. package/dist/generated/iso/NPR.d.ts +2 -0
  599. package/dist/generated/iso/NPR.d.ts.map +1 -0
  600. package/dist/generated/iso/NPR.js +5 -0
  601. package/dist/generated/iso/NPR.js.map +1 -0
  602. package/dist/generated/iso/NZD.d.ts +2 -0
  603. package/dist/generated/iso/NZD.d.ts.map +1 -0
  604. package/dist/generated/iso/NZD.js +5 -0
  605. package/dist/generated/iso/NZD.js.map +1 -0
  606. package/dist/generated/iso/OMR.d.ts +2 -0
  607. package/dist/generated/iso/OMR.d.ts.map +1 -0
  608. package/dist/generated/iso/OMR.js +5 -0
  609. package/dist/generated/iso/OMR.js.map +1 -0
  610. package/dist/generated/iso/PAB.d.ts +2 -0
  611. package/dist/generated/iso/PAB.d.ts.map +1 -0
  612. package/dist/generated/iso/PAB.js +5 -0
  613. package/dist/generated/iso/PAB.js.map +1 -0
  614. package/dist/generated/iso/PEN.d.ts +2 -0
  615. package/dist/generated/iso/PEN.d.ts.map +1 -0
  616. package/dist/generated/iso/PEN.js +5 -0
  617. package/dist/generated/iso/PEN.js.map +1 -0
  618. package/dist/generated/iso/PGK.d.ts +2 -0
  619. package/dist/generated/iso/PGK.d.ts.map +1 -0
  620. package/dist/generated/iso/PGK.js +5 -0
  621. package/dist/generated/iso/PGK.js.map +1 -0
  622. package/dist/generated/iso/PHP.d.ts +2 -0
  623. package/dist/generated/iso/PHP.d.ts.map +1 -0
  624. package/dist/generated/iso/PHP.js +5 -0
  625. package/dist/generated/iso/PHP.js.map +1 -0
  626. package/dist/generated/iso/PKR.d.ts +2 -0
  627. package/dist/generated/iso/PKR.d.ts.map +1 -0
  628. package/dist/generated/iso/PKR.js +5 -0
  629. package/dist/generated/iso/PKR.js.map +1 -0
  630. package/dist/generated/iso/PLN.d.ts +2 -0
  631. package/dist/generated/iso/PLN.d.ts.map +1 -0
  632. package/dist/generated/iso/PLN.js +5 -0
  633. package/dist/generated/iso/PLN.js.map +1 -0
  634. package/dist/generated/iso/PYG.d.ts +2 -0
  635. package/dist/generated/iso/PYG.d.ts.map +1 -0
  636. package/dist/generated/iso/PYG.js +5 -0
  637. package/dist/generated/iso/PYG.js.map +1 -0
  638. package/dist/generated/iso/QAR.d.ts +2 -0
  639. package/dist/generated/iso/QAR.d.ts.map +1 -0
  640. package/dist/generated/iso/QAR.js +5 -0
  641. package/dist/generated/iso/QAR.js.map +1 -0
  642. package/dist/generated/iso/RON.d.ts +2 -0
  643. package/dist/generated/iso/RON.d.ts.map +1 -0
  644. package/dist/generated/iso/RON.js +5 -0
  645. package/dist/generated/iso/RON.js.map +1 -0
  646. package/dist/generated/iso/RSD.d.ts +2 -0
  647. package/dist/generated/iso/RSD.d.ts.map +1 -0
  648. package/dist/generated/iso/RSD.js +5 -0
  649. package/dist/generated/iso/RSD.js.map +1 -0
  650. package/dist/generated/iso/RUB.d.ts +2 -0
  651. package/dist/generated/iso/RUB.d.ts.map +1 -0
  652. package/dist/generated/iso/RUB.js +5 -0
  653. package/dist/generated/iso/RUB.js.map +1 -0
  654. package/dist/generated/iso/RWF.d.ts +2 -0
  655. package/dist/generated/iso/RWF.d.ts.map +1 -0
  656. package/dist/generated/iso/RWF.js +5 -0
  657. package/dist/generated/iso/RWF.js.map +1 -0
  658. package/dist/generated/iso/SAR.d.ts +2 -0
  659. package/dist/generated/iso/SAR.d.ts.map +1 -0
  660. package/dist/generated/iso/SAR.js +5 -0
  661. package/dist/generated/iso/SAR.js.map +1 -0
  662. package/dist/generated/iso/SBD.d.ts +2 -0
  663. package/dist/generated/iso/SBD.d.ts.map +1 -0
  664. package/dist/generated/iso/SBD.js +5 -0
  665. package/dist/generated/iso/SBD.js.map +1 -0
  666. package/dist/generated/iso/SCR.d.ts +2 -0
  667. package/dist/generated/iso/SCR.d.ts.map +1 -0
  668. package/dist/generated/iso/SCR.js +5 -0
  669. package/dist/generated/iso/SCR.js.map +1 -0
  670. package/dist/generated/iso/SDG.d.ts +2 -0
  671. package/dist/generated/iso/SDG.d.ts.map +1 -0
  672. package/dist/generated/iso/SDG.js +5 -0
  673. package/dist/generated/iso/SDG.js.map +1 -0
  674. package/dist/generated/iso/SEK.d.ts +2 -0
  675. package/dist/generated/iso/SEK.d.ts.map +1 -0
  676. package/dist/generated/iso/SEK.js +5 -0
  677. package/dist/generated/iso/SEK.js.map +1 -0
  678. package/dist/generated/iso/SGD.d.ts +2 -0
  679. package/dist/generated/iso/SGD.d.ts.map +1 -0
  680. package/dist/generated/iso/SGD.js +5 -0
  681. package/dist/generated/iso/SGD.js.map +1 -0
  682. package/dist/generated/iso/SHP.d.ts +2 -0
  683. package/dist/generated/iso/SHP.d.ts.map +1 -0
  684. package/dist/generated/iso/SHP.js +5 -0
  685. package/dist/generated/iso/SHP.js.map +1 -0
  686. package/dist/generated/iso/SLE.d.ts +2 -0
  687. package/dist/generated/iso/SLE.d.ts.map +1 -0
  688. package/dist/generated/iso/SLE.js +5 -0
  689. package/dist/generated/iso/SLE.js.map +1 -0
  690. package/dist/generated/iso/SOS.d.ts +2 -0
  691. package/dist/generated/iso/SOS.d.ts.map +1 -0
  692. package/dist/generated/iso/SOS.js +5 -0
  693. package/dist/generated/iso/SOS.js.map +1 -0
  694. package/dist/generated/iso/SRD.d.ts +2 -0
  695. package/dist/generated/iso/SRD.d.ts.map +1 -0
  696. package/dist/generated/iso/SRD.js +5 -0
  697. package/dist/generated/iso/SRD.js.map +1 -0
  698. package/dist/generated/iso/SSP.d.ts +2 -0
  699. package/dist/generated/iso/SSP.d.ts.map +1 -0
  700. package/dist/generated/iso/SSP.js +5 -0
  701. package/dist/generated/iso/SSP.js.map +1 -0
  702. package/dist/generated/iso/STN.d.ts +2 -0
  703. package/dist/generated/iso/STN.d.ts.map +1 -0
  704. package/dist/generated/iso/STN.js +5 -0
  705. package/dist/generated/iso/STN.js.map +1 -0
  706. package/dist/generated/iso/SVC.d.ts +2 -0
  707. package/dist/generated/iso/SVC.d.ts.map +1 -0
  708. package/dist/generated/iso/SVC.js +5 -0
  709. package/dist/generated/iso/SVC.js.map +1 -0
  710. package/dist/generated/iso/SYP.d.ts +2 -0
  711. package/dist/generated/iso/SYP.d.ts.map +1 -0
  712. package/dist/generated/iso/SYP.js +5 -0
  713. package/dist/generated/iso/SYP.js.map +1 -0
  714. package/dist/generated/iso/SZL.d.ts +2 -0
  715. package/dist/generated/iso/SZL.d.ts.map +1 -0
  716. package/dist/generated/iso/SZL.js +5 -0
  717. package/dist/generated/iso/SZL.js.map +1 -0
  718. package/dist/generated/iso/THB.d.ts +2 -0
  719. package/dist/generated/iso/THB.d.ts.map +1 -0
  720. package/dist/generated/iso/THB.js +5 -0
  721. package/dist/generated/iso/THB.js.map +1 -0
  722. package/dist/generated/iso/TJS.d.ts +2 -0
  723. package/dist/generated/iso/TJS.d.ts.map +1 -0
  724. package/dist/generated/iso/TJS.js +5 -0
  725. package/dist/generated/iso/TJS.js.map +1 -0
  726. package/dist/generated/iso/TMT.d.ts +2 -0
  727. package/dist/generated/iso/TMT.d.ts.map +1 -0
  728. package/dist/generated/iso/TMT.js +5 -0
  729. package/dist/generated/iso/TMT.js.map +1 -0
  730. package/dist/generated/iso/TND.d.ts +2 -0
  731. package/dist/generated/iso/TND.d.ts.map +1 -0
  732. package/dist/generated/iso/TND.js +5 -0
  733. package/dist/generated/iso/TND.js.map +1 -0
  734. package/dist/generated/iso/TOP.d.ts +2 -0
  735. package/dist/generated/iso/TOP.d.ts.map +1 -0
  736. package/dist/generated/iso/TOP.js +5 -0
  737. package/dist/generated/iso/TOP.js.map +1 -0
  738. package/dist/generated/iso/TRY.d.ts +2 -0
  739. package/dist/generated/iso/TRY.d.ts.map +1 -0
  740. package/dist/generated/iso/TRY.js +5 -0
  741. package/dist/generated/iso/TRY.js.map +1 -0
  742. package/dist/generated/iso/TTD.d.ts +2 -0
  743. package/dist/generated/iso/TTD.d.ts.map +1 -0
  744. package/dist/generated/iso/TTD.js +5 -0
  745. package/dist/generated/iso/TTD.js.map +1 -0
  746. package/dist/generated/iso/TWD.d.ts +2 -0
  747. package/dist/generated/iso/TWD.d.ts.map +1 -0
  748. package/dist/generated/iso/TWD.js +5 -0
  749. package/dist/generated/iso/TWD.js.map +1 -0
  750. package/dist/generated/iso/TZS.d.ts +2 -0
  751. package/dist/generated/iso/TZS.d.ts.map +1 -0
  752. package/dist/generated/iso/TZS.js +5 -0
  753. package/dist/generated/iso/TZS.js.map +1 -0
  754. package/dist/generated/iso/UAH.d.ts +2 -0
  755. package/dist/generated/iso/UAH.d.ts.map +1 -0
  756. package/dist/generated/iso/UAH.js +5 -0
  757. package/dist/generated/iso/UAH.js.map +1 -0
  758. package/dist/generated/iso/UGX.d.ts +2 -0
  759. package/dist/generated/iso/UGX.d.ts.map +1 -0
  760. package/dist/generated/iso/UGX.js +5 -0
  761. package/dist/generated/iso/UGX.js.map +1 -0
  762. package/dist/generated/iso/USD.d.ts +2 -0
  763. package/dist/generated/iso/USD.d.ts.map +1 -0
  764. package/dist/generated/iso/USD.js +5 -0
  765. package/dist/generated/iso/USD.js.map +1 -0
  766. package/dist/generated/iso/USN.d.ts +2 -0
  767. package/dist/generated/iso/USN.d.ts.map +1 -0
  768. package/dist/generated/iso/USN.js +5 -0
  769. package/dist/generated/iso/USN.js.map +1 -0
  770. package/dist/generated/iso/UYI.d.ts +2 -0
  771. package/dist/generated/iso/UYI.d.ts.map +1 -0
  772. package/dist/generated/iso/UYI.js +5 -0
  773. package/dist/generated/iso/UYI.js.map +1 -0
  774. package/dist/generated/iso/UYU.d.ts +2 -0
  775. package/dist/generated/iso/UYU.d.ts.map +1 -0
  776. package/dist/generated/iso/UYU.js +5 -0
  777. package/dist/generated/iso/UYU.js.map +1 -0
  778. package/dist/generated/iso/UYW.d.ts +2 -0
  779. package/dist/generated/iso/UYW.d.ts.map +1 -0
  780. package/dist/generated/iso/UYW.js +5 -0
  781. package/dist/generated/iso/UYW.js.map +1 -0
  782. package/dist/generated/iso/UZS.d.ts +2 -0
  783. package/dist/generated/iso/UZS.d.ts.map +1 -0
  784. package/dist/generated/iso/UZS.js +5 -0
  785. package/dist/generated/iso/UZS.js.map +1 -0
  786. package/dist/generated/iso/VED.d.ts +2 -0
  787. package/dist/generated/iso/VED.d.ts.map +1 -0
  788. package/dist/generated/iso/VED.js +5 -0
  789. package/dist/generated/iso/VED.js.map +1 -0
  790. package/dist/generated/iso/VES.d.ts +2 -0
  791. package/dist/generated/iso/VES.d.ts.map +1 -0
  792. package/dist/generated/iso/VES.js +5 -0
  793. package/dist/generated/iso/VES.js.map +1 -0
  794. package/dist/generated/iso/VND.d.ts +2 -0
  795. package/dist/generated/iso/VND.d.ts.map +1 -0
  796. package/dist/generated/iso/VND.js +5 -0
  797. package/dist/generated/iso/VND.js.map +1 -0
  798. package/dist/generated/iso/VUV.d.ts +2 -0
  799. package/dist/generated/iso/VUV.d.ts.map +1 -0
  800. package/dist/generated/iso/VUV.js +5 -0
  801. package/dist/generated/iso/VUV.js.map +1 -0
  802. package/dist/generated/iso/WST.d.ts +2 -0
  803. package/dist/generated/iso/WST.d.ts.map +1 -0
  804. package/dist/generated/iso/WST.js +5 -0
  805. package/dist/generated/iso/WST.js.map +1 -0
  806. package/dist/generated/iso/XAD.d.ts +2 -0
  807. package/dist/generated/iso/XAD.d.ts.map +1 -0
  808. package/dist/generated/iso/XAD.js +5 -0
  809. package/dist/generated/iso/XAD.js.map +1 -0
  810. package/dist/generated/iso/XAF.d.ts +2 -0
  811. package/dist/generated/iso/XAF.d.ts.map +1 -0
  812. package/dist/generated/iso/XAF.js +5 -0
  813. package/dist/generated/iso/XAF.js.map +1 -0
  814. package/dist/generated/iso/XCD.d.ts +2 -0
  815. package/dist/generated/iso/XCD.d.ts.map +1 -0
  816. package/dist/generated/iso/XCD.js +5 -0
  817. package/dist/generated/iso/XCD.js.map +1 -0
  818. package/dist/generated/iso/XCG.d.ts +2 -0
  819. package/dist/generated/iso/XCG.d.ts.map +1 -0
  820. package/dist/generated/iso/XCG.js +5 -0
  821. package/dist/generated/iso/XCG.js.map +1 -0
  822. package/dist/generated/iso/XOF.d.ts +2 -0
  823. package/dist/generated/iso/XOF.d.ts.map +1 -0
  824. package/dist/generated/iso/XOF.js +5 -0
  825. package/dist/generated/iso/XOF.js.map +1 -0
  826. package/dist/generated/iso/XPF.d.ts +2 -0
  827. package/dist/generated/iso/XPF.d.ts.map +1 -0
  828. package/dist/generated/iso/XPF.js +5 -0
  829. package/dist/generated/iso/XPF.js.map +1 -0
  830. package/dist/generated/iso/YER.d.ts +2 -0
  831. package/dist/generated/iso/YER.d.ts.map +1 -0
  832. package/dist/generated/iso/YER.js +5 -0
  833. package/dist/generated/iso/YER.js.map +1 -0
  834. package/dist/generated/iso/ZAR.d.ts +2 -0
  835. package/dist/generated/iso/ZAR.d.ts.map +1 -0
  836. package/dist/generated/iso/ZAR.js +5 -0
  837. package/dist/generated/iso/ZAR.js.map +1 -0
  838. package/dist/generated/iso/ZMW.d.ts +2 -0
  839. package/dist/generated/iso/ZMW.d.ts.map +1 -0
  840. package/dist/generated/iso/ZMW.js +5 -0
  841. package/dist/generated/iso/ZMW.js.map +1 -0
  842. package/dist/generated/iso/ZWG.d.ts +2 -0
  843. package/dist/generated/iso/ZWG.d.ts.map +1 -0
  844. package/dist/generated/iso/ZWG.js +5 -0
  845. package/dist/generated/iso/ZWG.js.map +1 -0
  846. package/dist/generated/iso4217-numeric.d.ts +3 -0
  847. package/dist/generated/iso4217-numeric.d.ts.map +1 -0
  848. package/dist/generated/iso4217-numeric.js +184 -0
  849. package/dist/generated/iso4217-numeric.js.map +1 -0
  850. package/dist/generated/rbnf-de.d.ts +3 -0
  851. package/dist/generated/rbnf-de.d.ts.map +1 -0
  852. package/dist/generated/rbnf-de.js +5 -0
  853. package/dist/generated/rbnf-de.js.map +1 -0
  854. package/dist/generated/rbnf-en.d.ts +3 -0
  855. package/dist/generated/rbnf-en.d.ts.map +1 -0
  856. package/dist/generated/rbnf-en.js +5 -0
  857. package/dist/generated/rbnf-en.js.map +1 -0
  858. package/dist/generated/rbnf-es.d.ts +3 -0
  859. package/dist/generated/rbnf-es.d.ts.map +1 -0
  860. package/dist/generated/rbnf-es.js +5 -0
  861. package/dist/generated/rbnf-es.js.map +1 -0
  862. package/dist/generated/rbnf-fr.d.ts +3 -0
  863. package/dist/generated/rbnf-fr.d.ts.map +1 -0
  864. package/dist/generated/rbnf-fr.js +5 -0
  865. package/dist/generated/rbnf-fr.js.map +1 -0
  866. package/dist/generated/rbnf-it.d.ts +3 -0
  867. package/dist/generated/rbnf-it.d.ts.map +1 -0
  868. package/dist/generated/rbnf-it.js +5 -0
  869. package/dist/generated/rbnf-it.js.map +1 -0
  870. package/dist/generated/rbnf-nl.d.ts +3 -0
  871. package/dist/generated/rbnf-nl.d.ts.map +1 -0
  872. package/dist/generated/rbnf-nl.js +5 -0
  873. package/dist/generated/rbnf-nl.js.map +1 -0
  874. package/dist/generated/rbnf-pt.d.ts +3 -0
  875. package/dist/generated/rbnf-pt.d.ts.map +1 -0
  876. package/dist/generated/rbnf-pt.js +5 -0
  877. package/dist/generated/rbnf-pt.js.map +1 -0
  878. package/dist/generated/territories.d.ts +6 -0
  879. package/dist/generated/territories.d.ts.map +1 -0
  880. package/dist/generated/territories.js +275 -0
  881. package/dist/generated/territories.js.map +1 -0
  882. package/dist/index.d.ts +1 -0
  883. package/dist/index.d.ts.map +1 -1
  884. package/dist/index.js +2 -0
  885. package/dist/index.js.map +1 -1
  886. package/dist/kysely.d.ts.map +1 -1
  887. package/dist/kysely.js +2 -2
  888. package/dist/kysely.js.map +1 -1
  889. package/dist/math.d.ts +41 -0
  890. package/dist/math.d.ts.map +1 -0
  891. package/dist/math.js +132 -0
  892. package/dist/math.js.map +1 -0
  893. package/dist/money.d.ts +39 -57
  894. package/dist/money.d.ts.map +1 -1
  895. package/dist/money.js +118 -128
  896. package/dist/money.js.map +1 -1
  897. package/dist/parse.js +7 -7
  898. package/dist/parse.js.map +1 -1
  899. package/dist/plugins/adyen.d.ts +2 -0
  900. package/dist/plugins/adyen.d.ts.map +1 -1
  901. package/dist/plugins/adyen.js +2 -0
  902. package/dist/plugins/adyen.js.map +1 -1
  903. package/dist/plugins/all.d.ts +18 -2
  904. package/dist/plugins/all.d.ts.map +1 -1
  905. package/dist/plugins/all.js +19 -2
  906. package/dist/plugins/all.js.map +1 -1
  907. package/dist/plugins/allocate.d.ts +1 -0
  908. package/dist/plugins/allocate.d.ts.map +1 -1
  909. package/dist/plugins/allocate.js +2 -0
  910. package/dist/plugins/allocate.js.map +1 -1
  911. package/dist/plugins/braintree.d.ts +1 -0
  912. package/dist/plugins/braintree.d.ts.map +1 -1
  913. package/dist/plugins/braintree.js +2 -0
  914. package/dist/plugins/braintree.js.map +1 -1
  915. package/dist/plugins/cash.d.ts +1 -0
  916. package/dist/plugins/cash.d.ts.map +1 -1
  917. package/dist/plugins/cash.js +2 -0
  918. package/dist/plugins/cash.js.map +1 -1
  919. package/dist/plugins/checkout.d.ts +1 -0
  920. package/dist/plugins/checkout.d.ts.map +1 -1
  921. package/dist/plugins/checkout.js +2 -0
  922. package/dist/plugins/checkout.js.map +1 -1
  923. package/dist/plugins/convert.d.ts +5 -0
  924. package/dist/plugins/convert.d.ts.map +1 -1
  925. package/dist/plugins/convert.js +2 -0
  926. package/dist/plugins/convert.js.map +1 -1
  927. package/dist/plugins/core.d.ts +78 -0
  928. package/dist/plugins/core.d.ts.map +1 -0
  929. package/dist/plugins/core.js +104 -0
  930. package/dist/plugins/core.js.map +1 -0
  931. package/dist/plugins/exact.d.ts +1 -0
  932. package/dist/plugins/exact.d.ts.map +1 -1
  933. package/dist/plugins/exact.js +2 -0
  934. package/dist/plugins/exact.js.map +1 -1
  935. package/dist/plugins/fixed-money.d.ts +31 -0
  936. package/dist/plugins/fixed-money.d.ts.map +1 -0
  937. package/dist/plugins/fixed-money.js +29 -0
  938. package/dist/plugins/fixed-money.js.map +1 -0
  939. package/dist/plugins/format.d.ts +5 -0
  940. package/dist/plugins/format.d.ts.map +1 -1
  941. package/dist/plugins/format.js +2 -0
  942. package/dist/plugins/format.js.map +1 -1
  943. package/dist/plugins/iso.d.ts +2 -0
  944. package/dist/plugins/iso.d.ts.map +1 -0
  945. package/dist/plugins/iso.js +9 -0
  946. package/dist/plugins/iso.js.map +1 -0
  947. package/dist/plugins/klarna.d.ts +1 -0
  948. package/dist/plugins/klarna.d.ts.map +1 -1
  949. package/dist/plugins/klarna.js +2 -0
  950. package/dist/plugins/klarna.js.map +1 -1
  951. package/dist/plugins/math.d.ts +20 -0
  952. package/dist/plugins/math.d.ts.map +1 -0
  953. package/dist/plugins/math.js +24 -0
  954. package/dist/plugins/math.js.map +1 -0
  955. package/dist/plugins/paypal.d.ts +5 -0
  956. package/dist/plugins/paypal.d.ts.map +1 -1
  957. package/dist/plugins/paypal.js +6 -0
  958. package/dist/plugins/paypal.js.map +1 -1
  959. package/dist/plugins/prisma.d.ts +5 -0
  960. package/dist/plugins/prisma.d.ts.map +1 -1
  961. package/dist/plugins/prisma.js +6 -0
  962. package/dist/plugins/prisma.js.map +1 -1
  963. package/dist/plugins/stripe.d.ts +5 -0
  964. package/dist/plugins/stripe.d.ts.map +1 -1
  965. package/dist/plugins/stripe.js +6 -0
  966. package/dist/plugins/stripe.js.map +1 -1
  967. package/dist/plugins/tax.d.ts +1 -0
  968. package/dist/plugins/tax.d.ts.map +1 -1
  969. package/dist/plugins/tax.js +6 -0
  970. package/dist/plugins/tax.js.map +1 -1
  971. package/dist/policy.d.ts.map +1 -1
  972. package/dist/policy.js +5 -6
  973. package/dist/policy.js.map +1 -1
  974. package/dist/pricing.d.ts +52 -0
  975. package/dist/pricing.d.ts.map +1 -0
  976. package/dist/pricing.js +100 -0
  977. package/dist/pricing.js.map +1 -0
  978. package/dist/prisma.d.ts.map +1 -1
  979. package/dist/prisma.js +6 -2
  980. package/dist/prisma.js.map +1 -1
  981. package/dist/provider.js +2 -2
  982. package/dist/provider.js.map +1 -1
  983. package/dist/rate-text.d.ts +6 -0
  984. package/dist/rate-text.d.ts.map +1 -1
  985. package/dist/rate-text.js +24 -1
  986. package/dist/rate-text.js.map +1 -1
  987. package/dist/rate.d.ts.map +1 -1
  988. package/dist/rate.js +2 -3
  989. package/dist/rate.js.map +1 -1
  990. package/dist/rbnf.d.ts +29 -0
  991. package/dist/rbnf.d.ts.map +1 -0
  992. package/dist/rbnf.js +301 -0
  993. package/dist/rbnf.js.map +1 -0
  994. package/dist/rounding.d.ts +15 -0
  995. package/dist/rounding.d.ts.map +1 -1
  996. package/dist/rounding.js +32 -0
  997. package/dist/rounding.js.map +1 -1
  998. package/dist/scale.d.ts +8 -0
  999. package/dist/scale.d.ts.map +1 -0
  1000. package/dist/scale.js +34 -0
  1001. package/dist/scale.js.map +1 -0
  1002. package/dist/schema.d.ts.map +1 -1
  1003. package/dist/schema.js +4 -5
  1004. package/dist/schema.js.map +1 -1
  1005. package/dist/territories.d.ts +40 -0
  1006. package/dist/territories.d.ts.map +1 -0
  1007. package/dist/territories.js +71 -0
  1008. package/dist/territories.js.map +1 -0
  1009. package/dist/testing/arbitraries.d.ts.map +1 -1
  1010. package/dist/testing/arbitraries.js +4 -4
  1011. package/dist/testing/arbitraries.js.map +1 -1
  1012. package/dist/testing/index.js +1 -1
  1013. package/dist/testing/index.js.map +1 -1
  1014. package/dist/tiers.d.ts +95 -0
  1015. package/dist/tiers.d.ts.map +1 -0
  1016. package/dist/tiers.js +173 -0
  1017. package/dist/tiers.js.map +1 -0
  1018. package/dist/valibot.d.ts.map +1 -1
  1019. package/dist/valibot.js +4 -1
  1020. package/dist/valibot.js.map +1 -1
  1021. package/dist/wire.d.ts +105 -0
  1022. package/dist/wire.d.ts.map +1 -0
  1023. package/dist/wire.js +212 -0
  1024. package/dist/wire.js.map +1 -0
  1025. package/dist/words/de.d.ts +4 -0
  1026. package/dist/words/de.d.ts.map +1 -0
  1027. package/dist/words/de.js +8 -0
  1028. package/dist/words/de.js.map +1 -0
  1029. package/dist/words/en.d.ts +4 -0
  1030. package/dist/words/en.d.ts.map +1 -0
  1031. package/dist/words/en.js +8 -0
  1032. package/dist/words/en.js.map +1 -0
  1033. package/dist/words/es.d.ts +4 -0
  1034. package/dist/words/es.d.ts.map +1 -0
  1035. package/dist/words/es.js +8 -0
  1036. package/dist/words/es.js.map +1 -0
  1037. package/dist/words/fr.d.ts +4 -0
  1038. package/dist/words/fr.d.ts.map +1 -0
  1039. package/dist/words/fr.js +8 -0
  1040. package/dist/words/fr.js.map +1 -0
  1041. package/dist/words/it.d.ts +4 -0
  1042. package/dist/words/it.d.ts.map +1 -0
  1043. package/dist/words/it.js +8 -0
  1044. package/dist/words/it.js.map +1 -0
  1045. package/dist/words/nl.d.ts +4 -0
  1046. package/dist/words/nl.d.ts.map +1 -0
  1047. package/dist/words/nl.js +8 -0
  1048. package/dist/words/nl.js.map +1 -0
  1049. package/dist/words/pt.d.ts +4 -0
  1050. package/dist/words/pt.d.ts.map +1 -0
  1051. package/dist/words/pt.js +8 -0
  1052. package/dist/words/pt.js.map +1 -0
  1053. package/dist/words.d.ts +63 -0
  1054. package/dist/words.d.ts.map +1 -0
  1055. package/dist/words.js +107 -0
  1056. package/dist/words.js.map +1 -0
  1057. package/dist/zod.d.ts.map +1 -1
  1058. package/dist/zod.js +1 -1
  1059. package/dist/zod.js.map +1 -1
  1060. package/package.json +312 -54
  1061. package/src/adyen-fx.ts +1 -1
  1062. package/src/allocate.ts +4 -3
  1063. package/src/cash.ts +26 -0
  1064. package/src/convert.ts +2 -3
  1065. package/src/crypto.ts +129 -0
  1066. package/src/currencies.ts +123 -0
  1067. package/src/currency.ts +45 -14
  1068. package/src/decimal.ts +98 -10
  1069. package/src/ecb.ts +75 -16
  1070. package/src/entries/adyen-fx.ts +5 -0
  1071. package/src/entries/boc.ts +5 -0
  1072. package/src/entries/boe.ts +5 -0
  1073. package/src/entries/crypto.ts +5 -0
  1074. package/src/entries/currencies.ts +5 -0
  1075. package/src/entries/drizzle-mysql.ts +5 -0
  1076. package/src/entries/drizzle-pg.ts +5 -0
  1077. package/src/entries/drizzle-sqlite.ts +5 -0
  1078. package/src/entries/ecb.ts +5 -0
  1079. package/src/entries/fed.ts +5 -0
  1080. package/src/entries/fetch.ts +5 -0
  1081. package/src/entries/finance.ts +5 -0
  1082. package/src/entries/historic.ts +5 -0
  1083. package/src/entries/history.ts +5 -0
  1084. package/src/entries/hmrc.ts +5 -0
  1085. package/src/entries/kysely.ts +5 -0
  1086. package/src/entries/parse.ts +5 -0
  1087. package/src/entries/pg.ts +5 -0
  1088. package/src/entries/policy.ts +5 -0
  1089. package/src/entries/pricing.ts +5 -0
  1090. package/src/entries/stripe-fx.ts +5 -0
  1091. package/src/entries/testing-arbitraries.ts +5 -0
  1092. package/src/entries/testing-index.ts +5 -0
  1093. package/src/entries/testing-jest.ts +5 -0
  1094. package/src/entries/testing-vitest.ts +5 -0
  1095. package/src/entries/valibot.ts +5 -0
  1096. package/src/entries/wire.ts +5 -0
  1097. package/src/entries/zod.ts +5 -0
  1098. package/src/exact.ts +3 -3
  1099. package/src/fetch.ts +20 -4
  1100. package/src/finance.ts +1219 -0
  1101. package/src/fixed-money.ts +38 -0
  1102. package/src/fixed.ts +86 -66
  1103. package/src/fn.ts +17 -0
  1104. package/src/format.ts +28 -9
  1105. package/src/generated/crypto.ts +15 -0
  1106. package/src/generated/iso/AED.ts +5 -0
  1107. package/src/generated/iso/AFN.ts +5 -0
  1108. package/src/generated/iso/ALL.ts +5 -0
  1109. package/src/generated/iso/AMD.ts +5 -0
  1110. package/src/generated/iso/AOA.ts +5 -0
  1111. package/src/generated/iso/ARS.ts +5 -0
  1112. package/src/generated/iso/AUD.ts +5 -0
  1113. package/src/generated/iso/AWG.ts +5 -0
  1114. package/src/generated/iso/AZN.ts +5 -0
  1115. package/src/generated/iso/BAM.ts +5 -0
  1116. package/src/generated/iso/BBD.ts +5 -0
  1117. package/src/generated/iso/BDT.ts +5 -0
  1118. package/src/generated/iso/BHD.ts +5 -0
  1119. package/src/generated/iso/BIF.ts +5 -0
  1120. package/src/generated/iso/BMD.ts +5 -0
  1121. package/src/generated/iso/BND.ts +5 -0
  1122. package/src/generated/iso/BOB.ts +5 -0
  1123. package/src/generated/iso/BOV.ts +5 -0
  1124. package/src/generated/iso/BRL.ts +5 -0
  1125. package/src/generated/iso/BSD.ts +5 -0
  1126. package/src/generated/iso/BTN.ts +5 -0
  1127. package/src/generated/iso/BWP.ts +5 -0
  1128. package/src/generated/iso/BYN.ts +5 -0
  1129. package/src/generated/iso/BZD.ts +5 -0
  1130. package/src/generated/iso/CAD.ts +5 -0
  1131. package/src/generated/iso/CDF.ts +5 -0
  1132. package/src/generated/iso/CHE.ts +5 -0
  1133. package/src/generated/iso/CHF.ts +5 -0
  1134. package/src/generated/iso/CHW.ts +5 -0
  1135. package/src/generated/iso/CLF.ts +5 -0
  1136. package/src/generated/iso/CLP.ts +5 -0
  1137. package/src/generated/iso/CNY.ts +5 -0
  1138. package/src/generated/iso/COP.ts +5 -0
  1139. package/src/generated/iso/COU.ts +5 -0
  1140. package/src/generated/iso/CRC.ts +5 -0
  1141. package/src/generated/iso/CUP.ts +5 -0
  1142. package/src/generated/iso/CVE.ts +5 -0
  1143. package/src/generated/iso/CZK.ts +5 -0
  1144. package/src/generated/iso/DJF.ts +5 -0
  1145. package/src/generated/iso/DKK.ts +5 -0
  1146. package/src/generated/iso/DOP.ts +5 -0
  1147. package/src/generated/iso/DZD.ts +5 -0
  1148. package/src/generated/iso/EGP.ts +5 -0
  1149. package/src/generated/iso/ERN.ts +5 -0
  1150. package/src/generated/iso/ETB.ts +5 -0
  1151. package/src/generated/iso/EUR.ts +5 -0
  1152. package/src/generated/iso/FJD.ts +5 -0
  1153. package/src/generated/iso/FKP.ts +5 -0
  1154. package/src/generated/iso/GBP.ts +5 -0
  1155. package/src/generated/iso/GEL.ts +5 -0
  1156. package/src/generated/iso/GHS.ts +5 -0
  1157. package/src/generated/iso/GIP.ts +5 -0
  1158. package/src/generated/iso/GMD.ts +5 -0
  1159. package/src/generated/iso/GNF.ts +5 -0
  1160. package/src/generated/iso/GTQ.ts +5 -0
  1161. package/src/generated/iso/GYD.ts +5 -0
  1162. package/src/generated/iso/HKD.ts +5 -0
  1163. package/src/generated/iso/HNL.ts +5 -0
  1164. package/src/generated/iso/HTG.ts +5 -0
  1165. package/src/generated/iso/HUF.ts +5 -0
  1166. package/src/generated/iso/IDR.ts +5 -0
  1167. package/src/generated/iso/ILS.ts +5 -0
  1168. package/src/generated/iso/INR.ts +5 -0
  1169. package/src/generated/iso/IQD.ts +5 -0
  1170. package/src/generated/iso/IRR.ts +5 -0
  1171. package/src/generated/iso/ISK.ts +5 -0
  1172. package/src/generated/iso/JMD.ts +5 -0
  1173. package/src/generated/iso/JOD.ts +5 -0
  1174. package/src/generated/iso/JPY.ts +5 -0
  1175. package/src/generated/iso/KES.ts +5 -0
  1176. package/src/generated/iso/KGS.ts +5 -0
  1177. package/src/generated/iso/KHR.ts +5 -0
  1178. package/src/generated/iso/KMF.ts +5 -0
  1179. package/src/generated/iso/KPW.ts +5 -0
  1180. package/src/generated/iso/KRW.ts +5 -0
  1181. package/src/generated/iso/KWD.ts +5 -0
  1182. package/src/generated/iso/KYD.ts +5 -0
  1183. package/src/generated/iso/KZT.ts +5 -0
  1184. package/src/generated/iso/LAK.ts +5 -0
  1185. package/src/generated/iso/LBP.ts +5 -0
  1186. package/src/generated/iso/LKR.ts +5 -0
  1187. package/src/generated/iso/LRD.ts +5 -0
  1188. package/src/generated/iso/LSL.ts +5 -0
  1189. package/src/generated/iso/LYD.ts +5 -0
  1190. package/src/generated/iso/MAD.ts +5 -0
  1191. package/src/generated/iso/MDL.ts +5 -0
  1192. package/src/generated/iso/MGA.ts +5 -0
  1193. package/src/generated/iso/MKD.ts +5 -0
  1194. package/src/generated/iso/MMK.ts +5 -0
  1195. package/src/generated/iso/MNT.ts +5 -0
  1196. package/src/generated/iso/MOP.ts +5 -0
  1197. package/src/generated/iso/MRU.ts +5 -0
  1198. package/src/generated/iso/MUR.ts +5 -0
  1199. package/src/generated/iso/MVR.ts +5 -0
  1200. package/src/generated/iso/MWK.ts +5 -0
  1201. package/src/generated/iso/MXN.ts +5 -0
  1202. package/src/generated/iso/MXV.ts +5 -0
  1203. package/src/generated/iso/MYR.ts +5 -0
  1204. package/src/generated/iso/MZN.ts +5 -0
  1205. package/src/generated/iso/NAD.ts +5 -0
  1206. package/src/generated/iso/NGN.ts +5 -0
  1207. package/src/generated/iso/NIO.ts +5 -0
  1208. package/src/generated/iso/NOK.ts +5 -0
  1209. package/src/generated/iso/NPR.ts +5 -0
  1210. package/src/generated/iso/NZD.ts +5 -0
  1211. package/src/generated/iso/OMR.ts +5 -0
  1212. package/src/generated/iso/PAB.ts +5 -0
  1213. package/src/generated/iso/PEN.ts +5 -0
  1214. package/src/generated/iso/PGK.ts +5 -0
  1215. package/src/generated/iso/PHP.ts +5 -0
  1216. package/src/generated/iso/PKR.ts +5 -0
  1217. package/src/generated/iso/PLN.ts +5 -0
  1218. package/src/generated/iso/PYG.ts +5 -0
  1219. package/src/generated/iso/QAR.ts +5 -0
  1220. package/src/generated/iso/RON.ts +5 -0
  1221. package/src/generated/iso/RSD.ts +5 -0
  1222. package/src/generated/iso/RUB.ts +5 -0
  1223. package/src/generated/iso/RWF.ts +5 -0
  1224. package/src/generated/iso/SAR.ts +5 -0
  1225. package/src/generated/iso/SBD.ts +5 -0
  1226. package/src/generated/iso/SCR.ts +5 -0
  1227. package/src/generated/iso/SDG.ts +5 -0
  1228. package/src/generated/iso/SEK.ts +5 -0
  1229. package/src/generated/iso/SGD.ts +5 -0
  1230. package/src/generated/iso/SHP.ts +5 -0
  1231. package/src/generated/iso/SLE.ts +5 -0
  1232. package/src/generated/iso/SOS.ts +5 -0
  1233. package/src/generated/iso/SRD.ts +5 -0
  1234. package/src/generated/iso/SSP.ts +5 -0
  1235. package/src/generated/iso/STN.ts +5 -0
  1236. package/src/generated/iso/SVC.ts +5 -0
  1237. package/src/generated/iso/SYP.ts +5 -0
  1238. package/src/generated/iso/SZL.ts +5 -0
  1239. package/src/generated/iso/THB.ts +5 -0
  1240. package/src/generated/iso/TJS.ts +5 -0
  1241. package/src/generated/iso/TMT.ts +5 -0
  1242. package/src/generated/iso/TND.ts +5 -0
  1243. package/src/generated/iso/TOP.ts +5 -0
  1244. package/src/generated/iso/TRY.ts +5 -0
  1245. package/src/generated/iso/TTD.ts +5 -0
  1246. package/src/generated/iso/TWD.ts +5 -0
  1247. package/src/generated/iso/TZS.ts +5 -0
  1248. package/src/generated/iso/UAH.ts +5 -0
  1249. package/src/generated/iso/UGX.ts +5 -0
  1250. package/src/generated/iso/USD.ts +5 -0
  1251. package/src/generated/iso/USN.ts +5 -0
  1252. package/src/generated/iso/UYI.ts +5 -0
  1253. package/src/generated/iso/UYU.ts +5 -0
  1254. package/src/generated/iso/UYW.ts +5 -0
  1255. package/src/generated/iso/UZS.ts +5 -0
  1256. package/src/generated/iso/VED.ts +5 -0
  1257. package/src/generated/iso/VES.ts +5 -0
  1258. package/src/generated/iso/VND.ts +5 -0
  1259. package/src/generated/iso/VUV.ts +5 -0
  1260. package/src/generated/iso/WST.ts +5 -0
  1261. package/src/generated/iso/XAD.ts +5 -0
  1262. package/src/generated/iso/XAF.ts +5 -0
  1263. package/src/generated/iso/XCD.ts +5 -0
  1264. package/src/generated/iso/XCG.ts +5 -0
  1265. package/src/generated/iso/XOF.ts +5 -0
  1266. package/src/generated/iso/XPF.ts +5 -0
  1267. package/src/generated/iso/YER.ts +5 -0
  1268. package/src/generated/iso/ZAR.ts +5 -0
  1269. package/src/generated/iso/ZMW.ts +5 -0
  1270. package/src/generated/iso/ZWG.ts +5 -0
  1271. package/src/generated/iso4217-numeric.ts +184 -0
  1272. package/src/generated/rbnf-de.ts +5 -0
  1273. package/src/generated/rbnf-en.ts +5 -0
  1274. package/src/generated/rbnf-es.ts +5 -0
  1275. package/src/generated/rbnf-fr.ts +5 -0
  1276. package/src/generated/rbnf-it.ts +5 -0
  1277. package/src/generated/rbnf-nl.ts +5 -0
  1278. package/src/generated/rbnf-pt.ts +5 -0
  1279. package/src/generated/territories.ts +277 -0
  1280. package/src/index.ts +3 -0
  1281. package/src/kysely.ts +4 -3
  1282. package/src/math.ts +167 -0
  1283. package/src/money.ts +138 -140
  1284. package/src/parse.ts +7 -7
  1285. package/src/plugins/adyen.ts +2 -0
  1286. package/src/plugins/all.ts +19 -1
  1287. package/src/plugins/allocate.ts +2 -0
  1288. package/src/plugins/braintree.ts +2 -0
  1289. package/src/plugins/cash.ts +2 -0
  1290. package/src/plugins/checkout.ts +2 -0
  1291. package/src/plugins/convert.ts +2 -0
  1292. package/src/plugins/core.ts +195 -0
  1293. package/src/plugins/exact.ts +2 -0
  1294. package/src/plugins/fixed-money.ts +57 -0
  1295. package/src/plugins/format.ts +2 -0
  1296. package/src/plugins/iso.ts +9 -0
  1297. package/src/plugins/klarna.ts +2 -0
  1298. package/src/plugins/math.ts +43 -0
  1299. package/src/plugins/paypal.ts +2 -0
  1300. package/src/plugins/prisma.ts +2 -0
  1301. package/src/plugins/stripe.ts +2 -0
  1302. package/src/plugins/tax.ts +2 -0
  1303. package/src/policy.ts +5 -8
  1304. package/src/pricing.ts +155 -0
  1305. package/src/prisma.ts +6 -1
  1306. package/src/provider.ts +2 -2
  1307. package/src/rate-text.ts +27 -1
  1308. package/src/rate.ts +2 -2
  1309. package/src/rbnf.ts +389 -0
  1310. package/src/rounding.ts +34 -0
  1311. package/src/scale.ts +42 -0
  1312. package/src/schema.ts +4 -7
  1313. package/src/territories.ts +102 -0
  1314. package/src/testing/arbitraries.ts +4 -4
  1315. package/src/testing/index.ts +1 -1
  1316. package/src/tiers.ts +284 -0
  1317. package/src/valibot.ts +4 -1
  1318. package/src/wire.ts +322 -0
  1319. package/src/words/de.ts +9 -0
  1320. package/src/words/en.ts +9 -0
  1321. package/src/words/es.ts +9 -0
  1322. package/src/words/fr.ts +9 -0
  1323. package/src/words/it.ts +9 -0
  1324. package/src/words/nl.ts +9 -0
  1325. package/src/words/pt.ts +9 -0
  1326. package/src/words.ts +168 -0
  1327. package/src/zod.ts +1 -1
  1328. package/dist/plugins/fixed.d.ts +0 -17
  1329. package/dist/plugins/fixed.d.ts.map +0 -1
  1330. package/dist/plugins/fixed.js +0 -13
  1331. package/dist/plugins/fixed.js.map +0 -1
  1332. package/src/plugins/fixed.ts +0 -29
package/README.md CHANGED
@@ -12,7 +12,7 @@ import { money } from '@ducatjs/money';
12
12
  import '@ducatjs/money/allocate'; // opt-in modules add their methods to Money
13
13
  import '@ducatjs/money/tax';
14
14
  import '@ducatjs/money/convert';
15
- import '@ducatjs/money/format'; // or import '@ducatjs/money/all' for everything
15
+ import '@ducatjs/money/format'; // or import '@ducatjs/money/all' for everything except the integrations that need optional peers
16
16
 
17
17
  const price = money('19.99', 'EUR'); // Money<'EUR'>
18
18
  const total = price.add(money('5.01', 'EUR')); // → 25.00 EUR
@@ -25,9 +25,23 @@ total.format('de-DE'); // → '25,00 €'
25
25
  price.add(money('1', 'USD')); // compile error, and throws if types are erased
26
26
  ```
27
27
 
28
- Operations are methods on `Money`. For pipelines or code that prefers plain functions, `@ducatjs/money/fn` has each of them as a function of the same name (`add(price, fee)`, `allocate(m, [1, 1, 1])`). The core (`@ducatjs/money`) holds construction, arithmetic, rounding, comparison and serialisation; everything else is an opt-in module, so a bundle only pays for what it imports (see [Modules](#modules)).
28
+ Operations are methods on `Money`. For pipelines or code that prefers plain functions, `@ducatjs/money/fn` has each of them as a function of the same name (`add(price, fee)`, `allocate(m, [1, 1, 1])`), and a bundle keeps only the functions it imports: a program that only creates, adds and prints amounts is about 1.3 KiB gzipped through `/fn`. Importing `@ducatjs/money` installs the methods and registers every ISO 4217 currency; `/fn` does neither, so a `/fn` program imports the currencies it uses (`import '@ducatjs/money/iso/EUR'`, or `@ducatjs/money/iso` for all of them) and carries only those. The core (`@ducatjs/money`) holds construction, arithmetic, rounding, comparison and serialisation; everything else is an opt-in module, so a bundle only pays for what it imports (see [Modules](#modules)).
29
29
 
30
- Status: 0.x. The API is meant to stay small, but until 1.0 a minor version may change it; the [changelog](CHANGELOG.md) lists every breaking change. See [What's missing](#whats-missing-honest-list).
30
+ Status: 0.x. The API is meant to stay small, but until 1.0 a minor version may change it; the [changelog](https://github.com/public/ducat/blob/main/CHANGELOG.md) lists every breaking change. See [What's missing](#whats-missing-honest-list).
31
+
32
+ ## Why ducat
33
+
34
+ Choosing a money library for JavaScript today means choosing which problem to live with.
35
+
36
+ - **Wrong, to varying degrees.** On the same 41 correctness vectors, no other money library passes more than 34, and most return some wrong answers without an error: multiplying through floats turns 0.50 × 1.15 into 0.57, splitting −100.00 three ways loses a cent, amounts past 2⁵³ minor units drift, and a decimal string from another locale can parse as 100 times the amount. Their issue trackers are full of these bugs, some open for years.
37
+ - **Slow.** The libraries that get the arithmetic right pay for it in speed: dinero.js 2, the most careful of them, is 1.6× to 27× slower than ducat on the operations ducat leads.
38
+ - **Missing features.** Most stop at add, multiply, allocate and format. Exact currency conversion, rounding modes beyond half up, cash rounding, the amounts payment processors expect and database storage are left to you, and that hand-written code is where the bugs come back.
39
+
40
+ ducat is built to fix all three:
41
+
42
+ - **Exact, and tested to stay exact.** Amounts are integers of minor units: a JS number while safe, a bigint beyond, so nothing is ever a float. Every operation that can round takes one of nine rounding modes (or `'unnecessary'`, which throws), the rounding kernel is generated from Lean proofs, and allocation is checked against a proved model. It passes all 41 vectors, and the bug classes found in the issue trackers and fix histories of dinero.js, currency.js, js-money, decimal.js, big.js and bignumber.js each have a regression test in ducat's suite.
43
+ - **Fast.** Safe amounts stay on a plain-number fast path, so ducat is the fastest money library measured on creating, parsing, add, multiply, allocate and toDecimal on Node, Bun and Deno ([How it compares](#how-it-compares) has the numbers, and the cases where it isn't fastest).
44
+ - **Complete, but you only pay for what you use.** Conversion with exact rates and their sources, rounding policies, cash rounding, processor amounts (Stripe, Adyen, Checkout.com, PayPal, Braintree, Klarna), tax, a fixed-point `Fixed`, Intl formatting and strict parsing, and Prisma, Drizzle, Kysely and Postgres helpers are all opt-in modules. The core is 5.5 KiB gzipped.
31
45
 
32
46
  ---
33
47
 
@@ -35,11 +49,11 @@ Status: 0.x. The API is meant to stay small, but until 1.0 a minor version may c
35
49
 
36
50
  The same 41 correctness vectors, the same benchmark and the same bundle snippet for every library. The details, the
37
51
  other libraries' bugs, the fixed-point libraries and the money libraries in other languages are in
38
- [docs/COMPARISON.md](docs/COMPARISON.md), regenerated from [compare/](compare) for each release.
52
+ [docs/COMPARISON.md](https://github.com/public/ducat/blob/main/docs/COMPARISON.md), regenerated from [compare/](https://github.com/public/ducat/tree/main/compare) for each release.
39
53
 
40
54
  | library | correct (of 41) | wrong, silently | bundle (gzip) |
41
55
  | ---------------------------------- | --------------: | --------------: | -------------------: |
42
- | **ducat** | **41** | **0** | 4.0 KiB |
56
+ | **ducat** | **41** | **0** | 4.5 KiB |
43
57
  | dinero.js 2 (bigint calculator) | 34 | 0 | 1.8 KiB |
44
58
  | monetra | 34 | 3 | 4.5 KiB |
45
59
  | ts-money / js-money | 31 | 7 / 6 | 30.7 / 8.8 KiB |
@@ -51,23 +65,25 @@ other libraries' bugs, the fixed-point libraries and the money libraries in othe
51
65
  - **Correct everywhere:** ducat is the only library that passes every vector, including amounts beyond 2⁵³ minor
52
66
  units, float traps and negative allocations.
53
67
  - **Fastest on arithmetic:** with its methods API, it is the fastest money library on creating, parsing a decimal string
54
- (`money('12.34', 'EUR')`), add, multiply, allocate and toDecimal on Node, Bun and Deno, and on compare on Node and Deno. Against the fastest other money library
55
- the margin ranges from about 1.05× (compare on Node: 7.31 against 7.65 ns) to about 9.5× (allocate on Node: 46
56
- against bigint-money's 437 ns). Against dinero.js 2, on the operations where ducat is fastest, it ranges from 1.4× (creating on
57
- Deno) to about 28× (multiply on Bun).
58
- - **Where it isn't fastest:** formatting on Bun and Deno, where currency.js (formatting a float) is 3% faster (on Node,
59
- ducat and currency.js are level, 380 against 381 ns, and so are ducat and dinero.js 1 on Bun). On Bun, libraries that
60
- compare plain numbers are faster at compare (currency.js 6.4 against 9.8 ns).
61
- - **Fixed-point decimals:** ducat's `Fixed` is the fastest fixed-point library on parsing a decimal string (`fixed('12.34')`)
62
- and multiply on every runtime,
63
- and ahead of every other library on compare everywhere and on add on Node and Deno. bigdecimal.js is faster at
64
- dividing a `Fixed` on every runtime, though `Money` divides faster than either, and at add on Bun (11.9 against 12.3
65
- ns). js-big-decimal and ethers are faster on `toString` everywhere; see
66
- [docs/COMPARISON.md](docs/COMPARISON.md#fixed-point-decimal-libraries).
68
+ (`money('12.34', 'EUR')`), add, multiply, allocate and toDecimal on Node, Bun and Deno, and on compare on Node and
69
+ Deno. Against the fastest other money library the margin ranges from about 1.06× (compare on Node and Deno: 7.05
70
+ against currency.js's 7.46 ns on Node) to about 9.0× (allocate on Node: 47 against bigint-money's 419 ns). Against
71
+ dinero.js 2, on the operations where ducat is fastest, it ranges from 1.6× (creating on Node) to about 27× (compare
72
+ on Node), measured on Node and Bun: dinero.js 2's Deno cells vary several-fold between machines (see
73
+ [the run's notes](https://github.com/public/ducat/blob/main/compare/results/genoa-2026-11-09-v030-final/README.md)).
74
+ - **Where it isn't fastest:** formatting on Deno, where currency.js (formatting a float) is 6% faster (on Node and Bun
75
+ they are level, and ducat and dinero.js 1 are level everywhere). On Bun, libraries that compare plain numbers are
76
+ faster at compare (currency.js 6.5, js-money and ts-money 7.7 against 9.9 ns; Bun's compare cells vary a lot between
77
+ runs).
78
+ - **Fixed-point decimals:** ducat's `Fixed` is the fastest fixed-point library on parsing a decimal string
79
+ (`fixed('12.34')`), multiply, divide and compare on every runtime, and on add on Node and Deno (on Bun bigdecimal.js
80
+ is 3% faster, 11.9 against 12.3 ns). It divides by 3 in 28, 28 and 25 ns on Node, Bun and Deno, against
81
+ bigdecimal.js's 57, 35 and 49. js-big-decimal and ethers are faster on `toString` everywhere; see
82
+ [docs/COMPARISON.md](https://github.com/public/ducat/blob/main/docs/COMPARISON.md#fixed-point-decimal-libraries).
67
83
  - **Not the smallest:** currency.js, bigint-money, dinero.js 2, @screeny05/ts-money, big.js and dinero.js 1 are smaller
68
84
  for the same snippet. ducat's core includes exact decimal parsing, bigint support and the ISO table; everything else
69
85
  is opt-in.
70
- - **Measurement:** speed is from one quiet AMD EPYC Genoa vCPU, on ducat 0.2.0 (commit 7c9455a) under Node 24.22.2,
86
+ - **Measurement:** speed is from one quiet AMD EPYC Genoa vCPU, on ducat at commit 01753e5 (the 0.3.0 release candidate) under Node 24.22.2,
71
87
  Bun 1.4.4 and Deno 2.9.8; sizes are gzipped KiB. Differences within 2.5% are called level.
72
88
 
73
89
  ## Design
@@ -82,7 +98,7 @@ A `Money<C>` has three readonly fields:
82
98
  | `minor: number \| bigint` | Integer count of 10^-scale units. It is a **number whenever it is a safe integer** (absolute value ≤ 2^53−1) and a **bigint only beyond that**. The invariant is enforced everywhere, so ordinary amounts never allocate a bigint and huge amounts never lose a digit. |
83
99
  | `scale: number` | Decimal places. Defaults to the currency's ISO exponent (EUR 2, JPY 0, KWD 3, CLF 4). It can be larger for sub-minor precision (unit prices, FX intermediates). `round()` brings it back. |
84
100
 
85
- Why this representation, based on `bench/designs.ts` (the same seven operations written four ways and run on five engines; full tables in [bench/RESULTS.md](bench/RESULTS.md)):
101
+ Why this representation, based on `bench/designs.ts` (the same seven operations written four ways and run on five engines; full tables in [bench/RESULTS.md](https://github.com/public/ducat/blob/main/bench/RESULTS.md)):
86
102
 
87
103
  | ns/op, indicative | **A: number + bigint fallback** | B: bigint everywhere | C: decimal string | A + `Object.freeze` |
88
104
  | ------------------------------------ | ------------------------------: | -------------------: | --------------------: | ------------------: |
@@ -119,6 +135,8 @@ Engine notes (V8 vs JSC vs SpiderMonkey):
119
135
 
120
136
  ## API
121
137
 
138
+ **From CommonJS.** ducat is an ES module, and Node 24 can `require()` it, so a CommonJS project needs no build step: `const { money } = require('@ducatjs/money')` works, and so does every entry below. TypeScript finds the types with any `moduleResolution`. `nodenext` and `bundler` read `exports`, while `node10` (the default for `module: "commonjs"`) reads `types` and `typesVersions`, which name the same declarations. So no `paths` mapping into `dist/` is needed.
139
+
122
140
  ### Modules
123
141
 
124
142
  | import | adds to `Money` | also exports |
@@ -126,6 +144,7 @@ Engine notes (V8 vs JSC vs SpiderMonkey):
126
144
  | `@ducatjs/money` | the core: arithmetic, rounding, comparison, `toDecimal`, `toJSON`… | `money`, `fromMinor`, `zero`, `sum`, `fromJSON`, ISO exponents |
127
145
  | `@ducatjs/money/allocate` | `allocate`, `split`, `instalments`, `schedule`, `chunk` | the same as plain functions |
128
146
  | `@ducatjs/money/tax` | `percentage`, `discount`, `addTax`, `extractTax` | the same |
147
+ | `@ducatjs/money/math` | `ratioOf`, `divideToIntegral`, `remainder`, `trimScale` | the same, `average` |
129
148
  | `@ducatjs/money/convert` | `convert` | `exchangeRate`, providers, `bag`, `comparator`… |
130
149
  | `@ducatjs/money/exact` | `exact` | `ExactMoney`, `sumExact` |
131
150
  | `.../convert/ecb` | nothing | `parseEcbXml`, `parseEcbCsv`, `parseEcbSdmxCsv` |
@@ -137,8 +156,16 @@ Engine notes (V8 vs JSC vs SpiderMonkey):
137
156
  | `.../convert/fetch` | nothing | `fetchEcb`, `fetchEcbRange`, `fetchBankOfCanada` (network I/O) |
138
157
  | `.../stripe-fx`, `adyen-fx` | nothing | `stripeRate`, `stripeImpliedRate`, `adyenRate` |
139
158
  | `@ducatjs/money/policy` | nothing | `roundingPolicy`, `isoPolicy`, `assertScale` |
159
+ | `@ducatjs/money/pricing` | nothing | `priceEnding` (.99, .95, the nearest 5), `tieredPrice` (tiers) |
140
160
  | `@ducatjs/money/cash` | `cashRound`, `roundToIncrement` | the same, `cashPolicy`, `cashRule`, `currencyDigits` |
141
161
  | `@ducatjs/money/historic` | nothing | `defineHistoricCurrencies`, `historicCurrency` (withdrawn codes) |
162
+ | `@ducatjs/money/crypto` | nothing | `defineCryptoCurrencies`, `toBaseUnits`, `fromBaseUnits` |
163
+ | `@ducatjs/money/currencies` | nothing | numeric codes, `minorUnit`, `currencyName`, `currencySymbol` |
164
+ | `@ducatjs/money/territories` | nothing | `territoryCurrencies`, `currencyTerritories` (CLDR) |
165
+ | `@ducatjs/money/wire` | nothing | `google.type.Money`, ISO 20022 amounts, minor-unit JSON |
166
+ | `@ducatjs/money/words` | nothing | `amountInWords`, `spellOut` (CLDR rules, no Money loaded) |
167
+ | `@ducatjs/money/words/<language>` | nothing | `english`, `german`, `french`, `spanish`, `italian`… |
168
+ | `@ducatjs/money/finance` | nothing | `yearFraction`, `amortise`, `npv`, `irr`, `discountedSum`… |
142
169
  | `@ducatjs/money/format` | `format`, `formatToParts` | the same |
143
170
  | `@ducatjs/money/parse` | nothing | `parse`, `parseMoney` |
144
171
  | `@ducatjs/money/stripe` | `toStripe`, `toStripeAmount` | the same, `fromStripe`, `stripeExponent`… |
@@ -151,7 +178,8 @@ Engine notes (V8 vs JSC vs SpiderMonkey):
151
178
  | `.../drizzle/pg`, `mysql`, `sqlite` | nothing | `moneyMinor`, `moneyDecimal`, `moneyJson` Drizzle columns |
152
179
  | `@ducatjs/money/kysely` | nothing | `moneyHelpers`, `setMoney`, `MoneyResultPlugin` |
153
180
  | `@ducatjs/money/pg` | nothing | `exactTypes`, `moneyTypeSql`, `toNumeric`, composite I/O |
154
- | `@ducatjs/money/fixed` | `toFixedPoint` | `Fixed`, `fixed`, `fromScaled`, `isFixed`, `moneyToFixed` |
181
+ | `@ducatjs/money/fixed` | nothing | `Fixed`, `fixed`, `fromScaled`, `isFixed` (without Money) |
182
+ | `@ducatjs/money/fixed/money` | `toFixedPoint`, and `Fixed#toMoney` | `/fixed`, plus `moneyToFixed`, `fixedToMoney` |
155
183
  | `@ducatjs/money/zod` | nothing | `moneySchema`, `moneyJSONSchema` (Zod, an optional peer) |
156
184
  | `@ducatjs/money/valibot` | nothing | `moneySchema`, `moneyJSONSchema` (Valibot, an optional peer) |
157
185
  | `@ducatjs/money/testing` | nothing | matchers, value equality, snapshot serializer |
@@ -159,8 +187,10 @@ Engine notes (V8 vs JSC vs SpiderMonkey):
159
187
  | `.../testing/arbitraries` | nothing | `arbMoney`, `arbCurrency` (fast-check) |
160
188
  | `@ducatjs/money/all` | the methods of every module above | everything except the database, schema and testing entries |
161
189
  | `@ducatjs/money/fn` | nothing | every operation as a plain function, core and modules |
190
+ | `@ducatjs/money/iso` | nothing (registers every ISO 4217 currency, for `/fn`) | nothing |
191
+ | `@ducatjs/money/iso/EUR`, ... | nothing (registers that one currency, for `/fn`) | nothing |
162
192
 
163
- Importing a module (`import '@ducatjs/money/allocate'`, or any named import from it) installs its methods on `Money.prototype`, and its `declare module` augmentation makes them type-check. Without the import, `m.allocate()` is a compile error. The trade-off: the methods are installed for the whole program, so one import anywhere makes them available everywhere at run time, while TypeScript only knows about them in a program that includes the import. Import a module in each file that uses its methods: the import is cheap and installing twice is harmless, and it keeps working where files run in isolation (test runners, workers), where a single import in the entry point would leave `m.allocate` undefined at run time even though the code type-checks. Code that must not change any prototype (a library built on ducat, for example) can use the plain functions from `@ducatjs/money/fn` instead.
193
+ Importing a module (`import '@ducatjs/money/allocate'`, or any named import from it) installs its methods on `Money.prototype`, and its `declare module` augmentation makes them type-check. Without the import, `m.allocate()` is a compile error. The trade-off: the methods are installed for the whole program, so one import anywhere makes them available everywhere at run time, while TypeScript only knows about them in a program that includes the import. Import a module in each file that uses its methods: the import is cheap and installing twice is harmless, and it keeps working where files run in isolation (test runners, workers), where a single import in the entry point would leave `m.allocate` undefined at run time even though the code type-checks. Code that must not change any prototype (a library built on ducat, for example) can use the plain functions from `@ducatjs/money/fn` instead, and imports the currencies it uses (`import '@ducatjs/money/iso'`), since `/fn` registers none. The core methods (`add`, `round`, `toDecimal`...) work the same way: the root entry `@ducatjs/money` installs them, so a program that imports only `/fn` has Money values without methods and keeps only the functions it calls. Currencies work the same way. Every entry except `/fn` registers the whole ISO 4217 table (`/fixed`, `/words` and `/territories` never build Money and don't need it); a program that imports only `/fn` registers what it uses with `import '@ducatjs/money/iso/EUR'` (one module per ISO code) or `import '@ducatjs/money/iso'` (all of them), and any other code throws "Unknown currency", naming the import. Registration is by import, so it's the same bundled and unbundled. It's per module, not per program: a module that imports only `/fn` and builds Money while it loads (`const FEE = money('0.30', 'EUR')` in a config file) runs before the modules that import it, so it throws even when the app's entry point imports `@ducatjs/money`; give such a module, and any library built on `/fn`, its own `import '@ducatjs/money/iso'` (or `/iso/EUR`). The per-code modules are named by the uppercase ISO code: `/iso/eur` may resolve on a case-insensitive file system and then fail elsewhere. The types don't track registration: `/fn` accepts any ISO code at compile time. `defineCurrency` checks the ISO table so ISO codes can't be redefined, so a `/fn` program that calls it carries the table again: about 0.6 kB gzipped with `defineCurrency` itself.
164
194
 
165
195
  Your own module can add methods the same way:
166
196
 
@@ -207,6 +237,28 @@ const other = fromJSON({ amount: '1', currency: 'USD' as string });
207
237
  assertCurrency(other, 'EUR'); // throws CurrencyMismatchError
208
238
  ```
209
239
 
240
+ **Decimal strings.** `money()`, `fixed()`, `ratio()` and every other place that takes an amount or a factor as a string accept exactly this, and nothing else:
241
+
242
+ - an optional sign, `+` or `-`;
243
+ - one or more ASCII digits;
244
+ - optionally a point followed by one or more digits;
245
+ - optionally an exponent: `e` or `E`, an optional sign, and digits.
246
+
247
+ The exponent is at most 1000 either way, and so is the number of decimal places once it is applied. `'.5'`, `'5.'`, `'-.5'`, grouping (`'1,000'`, `'1_000'`), other scripts' digits and surrounding whitespace are refused with a `SyntaxError`, because each is more often a truncated or mangled value than a deliberate one. Exponents are accepted because they're unambiguous and other systems write them: `String(1e-7)`, Java's `BigDecimal.toString()` and Python's `str(Decimal)` all do. For text as people write it, with grouping, symbols or another locale's separators, use `parse()` (below). A factor can also be written `'a/b'`, two of these strings around a slash.
248
+
249
+ ```ts
250
+ import { money } from '@ducatjs/money';
251
+
252
+ money('-12.34', 'EUR'); // → -12.34 EUR
253
+ money('+7', 'EUR'); // → 7.00 EUR
254
+ money('1.5e3', 'EUR'); // → 1500.00 EUR
255
+ money('125E-2', 'EUR'); // → 1.25 EUR
256
+ money('.5', 'EUR'); // throws SyntaxError
257
+ money('5.', 'EUR'); // throws SyntaxError
258
+ money(' 12.34', 'EUR'); // throws SyntaxError
259
+ money('1,000', 'EUR'); // throws SyntaxError
260
+ ```
261
+
210
262
  **Arithmetic.** All of these are immutable and return new values.
211
263
 
212
264
  - `add`, `subtract`, `sum(list, currency?)`, `negate`, `abs`
@@ -224,6 +276,19 @@ const toFiveRappen = (value: Money<'CHF'>) => value.divide(5).round('halfExpand'
224
276
  money('10.00', 'CHF').multiply('1.077').with(toFiveRappen); // → 10.75 CHF
225
277
  ```
226
278
 
279
+ **Averages, shares and remainders** (`@ducatjs/money/math`). `average(list, rounding?)` divides the exact sum by the count and rounds once. `ratioOf(part, total)` is the exact share as a `Ratio`, which `multiply` and `allocate` accept. `divideToIntegral(m, divisor)` counts how many whole times one amount fits into another (truncated toward zero), and `remainder(m, divisor)` is what is left, with `m`'s sign, so `m = divisor × count + remainder` exactly. `trimScale(m, minimumScale?)` drops trailing zeros down to the currency's exponent (or `minimumScale`).
280
+
281
+ ```ts
282
+ import { money } from '@ducatjs/money';
283
+ import { average } from '@ducatjs/money/math';
284
+
285
+ average([money('10', 'EUR'), money('10', 'EUR'), money('10.01', 'EUR')]); // → 10.00 EUR
286
+ money('25', 'EUR').ratioOf(money('100', 'EUR')); // → { num: 1n, den: 4n, n: 1, d: 4 }
287
+ money('9.99', 'EUR').divideToIntegral(money('2.50', 'EUR')); // → 3
288
+ money('9.99', 'EUR').remainder(money('2.50', 'EUR')); // → 2.49 EUR
289
+ money('1.2300', 'EUR', { scale: 4 }).trimScale(); // → 1.23 EUR
290
+ ```
291
+
227
292
  **Compare**
228
293
 
229
294
  - `compare` (returns −1, 0 or 1), `equals`, `lessThan`, `lessThanOrEqual`, `greaterThan`, `greaterThanOrEqual`
@@ -265,6 +330,20 @@ one.identical(money('1', 'EUR', { scale: 1 })); // → false
265
330
  | `Floor` | `'floor'` | always toward −∞ |
266
331
  | `Unnecessary` | `'unnecessary'` | throws `RoundingError` if rounding would be needed |
267
332
 
333
+ **Price endings** (`@ducatjs/money/pricing`). `priceEnding({ ending, step?, rounding? })` builds a rule that moves a computed price to a retail ending: the allowed prices are `ending + k × step` (step 1 by default), and `rounding` picks one: `'ceil'` (the default) the next one up, `'floor'` the next one down, `'halfCeil'` the nearest. The rule is a function, so `price.with(rule)` and `prices.map(rule)` work, and the result is exact, at the price's scale.
334
+
335
+ ```ts
336
+ import { money } from '@ducatjs/money';
337
+ import { priceEnding } from '@ducatjs/money/pricing';
338
+
339
+ const charm = priceEnding({ ending: '0.99' });
340
+ money('23.41', 'EUR').with(charm); // → 23.99 EUR
341
+ money('23.41', 'EUR').with(priceEnding({ ending: '9.90', step: 10 })); // → 29.90 EUR
342
+ money('22.50', 'EUR').with(priceEnding({ ending: 0, step: 5, rounding: 'halfCeil' })); // → 25.00 EUR
343
+ money('1234', 'JPY').with(priceEnding({ ending: 80, step: 100 })); // → 1280 JPY
344
+ money('100', 'JPY').with(charm); // throws RangeError: JPY has no cents
345
+ ```
346
+
268
347
  **Rounding policies** (`@ducatjs/money/policy`). A policy bundles a scale, an increment and a mode ("CHF cash", "4 decimals, half even") into one value that goes wherever a rounding mode goes: `multiply`, `divide`, `round`, `percentage`, `discount`, `addTax`, `extractTax`. The result is rounded once, straight to the policy, so it never rounds twice through the amount's own scale. A policy is also a function that rounds an amount, so `amounts.map(policy)` and `m.with(policy)` work.
269
348
 
270
349
  - `roundingPolicy({ scale?, increment?, rounding?, currency? })`. The scale defaults to the currency's exponent, the increment (counted in 10^-scale units) to 1, and the mode to `'halfExpand'`. With `currency`, the policy refuses amounts in other currencies.
@@ -287,6 +366,19 @@ money('10.00', 'EUR').divide(3, unitPrice); // → 3.3333 EUR
287
366
  assertScale(money('1.234', 'EUR', { scale: 3 }), isoPolicy); // throws RangeError
288
367
  ```
289
368
 
369
+ **Tens, hundreds and thousands.** A scale is never negative: it counts decimal places, from 0 to 1000, so `round('floor', -2)` throws. To round to whole hundreds (Swiss tax rounds taxable income down to 100 CHF, for example), use an increment: a policy at scale 0 with `increment: 100`, or `roundToIncrement` from `@ducatjs/money/cash`. The same increment does tens, thousands and cash rounding.
370
+
371
+ ```ts
372
+ import { money } from '@ducatjs/money';
373
+ import { roundingPolicy } from '@ducatjs/money/policy';
374
+ import { roundToIncrement } from '@ducatjs/money/cash';
375
+
376
+ const downToHundreds = roundingPolicy({ scale: 0, increment: 100, rounding: 'floor' });
377
+ money('12345.60', 'CHF').round(downToHundreds); // → 12300 CHF
378
+ roundToIncrement(money('12345.60', 'CHF'), money('100', 'CHF'), 'floor'); // → 12300.00 CHF
379
+ money('12345.60', 'CHF').round('floor', -2); // throws RangeError
380
+ ```
381
+
290
382
  **Cash rounding**
291
383
 
292
384
  - `cashRound(m, { country?, rounding?, includeUnverified? })` uses the table in `data/cash-rounding.json`:
@@ -333,7 +425,17 @@ parseMoney('12.34', 'en', { hint: 'EUR', lenient: true }); // → 12.34 EUR
333
425
  **Serialise**
334
426
 
335
427
  - `toDecimal(m)` gives `"12.34"` for NUMERIC/DECIMAL and wire formats.
336
- - `toMinor(m)` gives a bigint for BIGINT columns. `toMinorNumber(m)` gives a number and throws if it isn't safe.
428
+ - `toMinor(m)` gives the currency's minor units (cents for EUR) as a bigint, whatever the value's scale, and throws a `RoundingError` if that would need rounding. `toMinorNumber(m)` gives a number and also throws if it isn't safe. `toScaledUnits(m)` gives units of the value's own scale, to store next to that scale.
429
+
430
+ ```ts
431
+ import { money } from '@ducatjs/money';
432
+
433
+ money('12.340', 'EUR', { scale: 3 }).toMinor(); // → 1234n
434
+ money('1.5', 'EUR', { scale: 1 }).toMinor(); // → 150n
435
+ money('12.345', 'EUR', { scale: 3 }).toMinor(); // throws RoundingError: round() first
436
+ money('12.345', 'EUR', { scale: 3 }).toScaledUnits(); // → 12345n (pair it with scale 3)
437
+ ```
438
+
337
439
  - `majorPart(m)` and `minorPart(m)` split the amount at the decimal point, truncating toward zero, and both keep its sign: `money('-12.34', 'EUR').majorPart()` is `-12` and `.minorPart()` is `-34`. Each is a number while it is a safe integer and a bigint beyond, like `minor`.
338
440
  - `JSON.stringify(m)` gives `{"amount":"12.34","currency":"EUR"}`, and `fromJSON` reverses it. The amount is a string so it survives JSON parsers that turn numbers into floats.
339
441
 
@@ -364,7 +466,7 @@ v.parse(moneySchema({ currency: 'JPY' }), { amount: '1000', currency: 'JPY' });
364
466
 
365
467
  **Currencies**
366
468
 
367
- - `currencyExponent(code)`, `isCurrency(code)`, `ISO_EXPONENTS`, `ISO_4217_PUBLISHED`
469
+ - `currencyExponent(code)`, `isCurrency(code)`, `ISO_EXPONENTS`, `ISO_4217_PUBLISHED`. `isCurrency` and `currencyExponent` see the registered codes: every ISO code wherever an entry other than `/fn` is imported, and in a `/fn`-only program the ones imported from `@ducatjs/money/iso` (see [Modules](#modules)).
368
470
  - `defineCurrency('BTC', 8)` adds a non-ISO code. To also get it in the `CurrencyCode` type, augment `interface CustomCurrencies`.
369
471
  - Withdrawn codes (`@ducatjs/money/historic`): 54 codes ISO 4217 has withdrawn (HRK, BGN, ANG, STD, SLL, ZWL, CUC, VEF, the euro's predecessors…) and the offshore yuan CNH, each with the exponent ISO gave it while it was current, so old records and processor listings load. Nothing is registered until you call `defineHistoricCurrencies`, with a list of codes or none for all of them. `historicCurrency(code)` gives the name, exponent, ISO numeric code and the month ISO withdrew it, from ISO 4217 List Three. Older codes whose minor units aren't sourced are left out; register those with `defineCurrency`.
370
472
 
@@ -389,6 +491,128 @@ declare module '@ducatjs/money' {
389
491
  }
390
492
  ```
391
493
 
494
+ **Crypto currencies and tokens** (`@ducatjs/money/crypto`). BTC (8 decimals, satoshi), ETH (18, wei), SOL (9, lamport) and common Ethereum tokens (USDC, USDT, DAI, WBTC, EURC, PYUSD) as an opt-in table, registered by `defineCryptoCurrencies`, like the historic codes. Each unit's decimals are read from the source that defines it, pinned to a release or commit (Bitcoin Core's `COIN`, Ethereum mainnet in ethereum-lists/chains, the Solana SDK, and the Uniswap default token list for tokens). A token's decimals belong to its contract on one network: these are Ethereum mainnet's (USDT has 18 on BNB Chain, 6 here), so `cryptoUnit(code)` names the network and the contract. Define another network's tokens with `defineCurrency`, under codes of your own. `toBaseUnits(m)` gives the exact count of base units as a bigint, and `fromBaseUnits(count, code)` parses one strictly: digits and an optional minus sign only. Amounts at 18 decimals use Money's bigint path, so they stay exact.
495
+
496
+ ```ts
497
+ import { money } from '@ducatjs/money';
498
+ import { defineCryptoCurrencies, fromBaseUnits, toBaseUnits } from '@ducatjs/money/crypto';
499
+
500
+ defineCryptoCurrencies(['BTC', 'ETH']);
501
+ toBaseUnits(money('0.00000001', 'BTC')); // → 1n
502
+ fromBaseUnits('1500000000000000000', 'ETH'); // → 1.500000000000000000 ETH
503
+ money('0.1', 'ETH').add(money('0.2', 'ETH')).toDecimal(); // → '0.300000000000000000'
504
+ fromBaseUnits('1e18', 'ETH'); // throws SyntaxError
505
+ ```
506
+
507
+ **Currency metadata** (`@ducatjs/money/currencies`). ISO 4217 numeric codes both ways (`numericCode`, `currencyFromNumeric`), for card networks, ISO 8583 and ISO 20022 messages; `minorUnit(code)`, the size of the minor unit; and names and symbols per locale (`currencyName`, `currencySymbol`). Names and symbols come from the runtime's `Intl`, not a bundled table, so they follow its CLDR version. The smallest coin is `cashUnit(code, { country? })` in `@ducatjs/money/cash`, from the cash rules. Which currencies a territory uses, and since when, is in `@ducatjs/money/territories` (`territoryCurrencies`, `currencyTerritories`, from CLDR). It is a separate entry because the table is most of its 4.5 KiB gzipped.
508
+
509
+ ```ts
510
+ import { cashUnit } from '@ducatjs/money/cash';
511
+ import {
512
+ currencyFromNumeric,
513
+ currencySymbol,
514
+ minorUnit,
515
+ numericCode,
516
+ } from '@ducatjs/money/currencies';
517
+ import { territoryCurrencies } from '@ducatjs/money/territories';
518
+
519
+ numericCode('EUR'); // → '978'
520
+ currencyFromNumeric(8); // → 'ALL'
521
+ minorUnit('KWD'); // → '0.001'
522
+ currencySymbol('USD', 'en-CA'); // → 'US$'
523
+ cashUnit('CHF'); // → '0.05'
524
+ territoryCurrencies('DE', { on: '2001-06-01' }).map((use) => use.currency); // → ['EUR', 'DEM']
525
+ ```
526
+
527
+ ### Interest, loans, NPV and proration
528
+
529
+ `@ducatjs/money/finance` has the calculations billing and lending code keeps rewriting in floats, in exact arithmetic: every amount that is paid or booked is rounded once from its exact value, with a rounding mode or a policy. Dates are `'YYYY-MM-DD'` strings or `{ year, month, day }` objects (so a `Temporal.PlainDate` works), never `Date`. The design is in [docs/FINANCE.md](https://github.com/public/ducat/blob/main/docs/FINANCE.md).
530
+
531
+ - `yearFraction(start, end, convention)` is an exact `Ratio` under `ACT/360`, `ACT/365F`, `ACT/ACT ISDA`, `30/360` (Bond Basis), `30E/360` or `30E/360 ISDA` (pass `maturity: true` or `false` when the end date is the last day of February), as the 2006 ISDA Definitions §4.16 define them. It isn't Excel's YEARFRAC, whose bases differ (US 30/360, an average year length for actual/actual). `interest` is simple interest over a day count, and `compound` is periodic compounding over a whole number of periods.
532
+ - `amortise(loan, options)` builds an annuity, linear or interest-only schedule. Each period's interest is the balance times `rate / perYear`, rounded; the principal parts sum exactly to the loan and the balance ends at zero, because the rounding residual goes to the last payment (or, with `residual: 'lastInterest'`, to the last interest). It takes a `balloon` and a `firstPayment` date.
533
+ - Functions named after Excel's give Excel's values. `npv(rate, flows)` is Excel's NPV: the first flow is at the end of period 1, so, like Excel, an initial outlay at period 0 goes outside, `flows[0] + npv(rate, rest)`. `discountedSum(rate, flows)` takes flows from period 0. Both are exact and rounded once, so `npv` matches Excel to the cent.
534
+ - `irr(flows, { digits })` is Excel's IRR, exact to `digits` places (floored): it bisects in exact integer arithmetic, the IRR lies between `lower` and `upper`, 10^−digits apart, and `rate` is `lower`. Where Excel guesses, it throws: with no sign change (Excel's #NUM!), and with more than one unless a `bracket` (in place of Excel's `guess`) selects one root.
535
+ - `prorate(price, { period, used })` charges the used part of a period (by the day, or with `unit: 'second'` by the second), and `splitPeriod(price, { period, at })` splits a period's price at plan changes into pieces that sum exactly to it.
536
+
537
+ ```ts
538
+ import { money } from '@ducatjs/money';
539
+ import {
540
+ amortise,
541
+ interest,
542
+ irr,
543
+ npv,
544
+ discountedSum,
545
+ prorate,
546
+ splitPeriod,
547
+ } from '@ducatjs/money/finance';
548
+
549
+ const period = { from: '2026-01-15', to: '2026-07-15', dayCount: 'ACT/365F' } as const;
550
+ interest(money('10000', 'EUR'), '0.05', period, 'halfEven'); // → 247.95 EUR
551
+
552
+ const plan = amortise(money('200000', 'EUR'), { rate: '0.045', perYear: 12, periods: 300 });
553
+ plan.payment; // → 1111.66 EUR
554
+ plan.rows[0]?.interest; // → 750.00 EUR
555
+ plan.rows.at(-1)?.balance; // → 0.00 EUR
556
+ plan.totalInterest; // → 133500.69 EUR
557
+
558
+ const flows = ['-1000', '300', '400', '500'].map((amount) => money(amount, 'EUR'));
559
+ discountedSum('0.08', flows, 'halfEven'); // → 17.63 EUR
560
+ npv('0.08', flows.slice(1), 'halfEven'); // → 1017.63 EUR (Excel's NPV: add the outlay yourself)
561
+ irr(flows, { digits: 8 }); // → { rate: '0.08896339', lower: '0.08896339', upper: '0.08896340' }
562
+ irr(['-100', '230', '-132'].map((amount) => money(amount, 'EUR'))); // throws RangeError: two IRRs, 10% and 20%
563
+
564
+ const march = { start: '2026-03-01', end: '2026-04-01' };
565
+ prorate(money('30', 'EUR'), { period: march, used: { start: '2026-03-11', end: '2026-04-01' } }); // → 20.32 EUR
566
+ splitPeriod(money('30', 'EUR'), { period: march, at: ['2026-03-11', '2026-03-20'] }); // → [9.68 EUR, 8.71 EUR, 11.61 EUR]
567
+ ```
568
+
569
+ ### Tiered and volume pricing
570
+
571
+ `tieredPrice(quantity, { mode, tiers })` in `@ducatjs/money/pricing` prices a quantity under tiers in the style of Stripe's: each tier has an inclusive `upTo` (`'inf'` on the last), a `unitAmount` (sub-cent amounts are fine) and a `flatAmount`, either or both. In `'graduated'` mode each tier prices the units that fall in it; in `'volume'` mode the tier the whole quantity falls in prices every unit. Quantity 0 falls in the first tier, so its flat amount is billed, as Stripe does. The arithmetic is exact and the total is rounded once (with a mode or a policy). The breakdown has a line per tier with its exact charge and an `amount` rounded from the running total, so the lines always sum to the total.
572
+
573
+ ```ts
574
+ import { money } from '@ducatjs/money';
575
+ import { tieredPrice } from '@ducatjs/money/pricing';
576
+
577
+ const tiers = [
578
+ { upTo: 5, unitAmount: money('5', 'USD'), flatAmount: money('10', 'USD') },
579
+ { upTo: 10, unitAmount: money('4', 'USD'), flatAmount: money('20', 'USD') },
580
+ { upTo: 'inf', unitAmount: money('3', 'USD'), flatAmount: money('30', 'USD') },
581
+ ] as const;
582
+ tieredPrice(12, { mode: 'graduated', tiers }).total; // → 111.00 USD
583
+ tieredPrice(12, { mode: 'graduated', tiers }).lines.map((line) => line.amount); // → [35.00 USD, 40.00 USD, 36.00 USD]
584
+ tieredPrice(12, { mode: 'volume', tiers }).total; // → 66.00 USD
585
+ tieredPrice(0, { mode: 'volume', tiers }).total; // → 10.00 USD (the first tier's flat amount)
586
+ ```
587
+
588
+ Real tier tables need a few more things, and get them as options:
589
+
590
+ - **Quantities** can be fractional, exactly: a decimal string (`'12.25'` kWh), an `'a/b'` string (`'250/3'`), a `ratio()` or a `Fixed`.
591
+ - **The last tier** may be open with `upTo: 'inf'`, `null` or `Infinity`. Bounds must increase, and the error names the tier that doesn't.
592
+ - **Past a bounded last tier**, the quantity throws by default. With `beyondLastTier: 'cap'` it is charged as if it were the last `upTo`, so nothing more is charged past it.
593
+ - **Tier by one quantity, charge by another** (volume mode): `chargeQuantity` multiplies the chosen tier's `unitAmount`, for tiers chosen by meter count but priced per unit used. The tier's `flatAmount` is charged once. Tiers with only a `flatAmount` give flat-fee pricing, chosen by the quantity. Graduated tiers split the quantity across tiers, so there is no single tier to apply to another quantity, and `chargeQuantity` throws there.
594
+
595
+ ```ts
596
+ import { money } from '@ducatjs/money';
597
+ import { fixed } from '@ducatjs/money/fixed';
598
+ import { tieredPrice } from '@ducatjs/money/pricing';
599
+
600
+ const capped = [
601
+ { upTo: 10, unitAmount: money('2', 'EUR') },
602
+ { upTo: 100, unitAmount: money('1.50', 'EUR'), flatAmount: money('5', 'EUR') },
603
+ ];
604
+ tieredPrice(250, { mode: 'graduated', tiers: capped, beyondLastTier: 'cap' }).total; // → 160.00 EUR
605
+ tieredPrice(250, { mode: 'graduated', tiers: capped }); // throws RangeError
606
+ tieredPrice('250/3', { mode: 'volume', tiers: capped }).total; // → 130.00 EUR
607
+ tieredPrice(fixed('12.25'), { mode: 'volume', tiers: capped }).total; // → 23.38 EUR
608
+
609
+ const perMeter = [
610
+ { upTo: 1, unitAmount: money('0.30', 'EUR'), flatAmount: money('10', 'EUR') },
611
+ { upTo: null, unitAmount: money('0.25', 'EUR'), flatAmount: money('25', 'EUR') },
612
+ ];
613
+ tieredPrice(3, { mode: 'volume', tiers: perMeter, chargeQuantity: '1234.5' }).total; // → 333.63 EUR
614
+ ```
615
+
392
616
  ### Currency conversion
393
617
 
394
618
  `@ducatjs/money/convert` converts at exact rates and rounds once, at the end. A rate is a `Rate`, an exact rational with the pair in its type, so converting the wrong currency is a compile error. Inverses and chains of rates are exact too: nothing is rounded until an amount is converted.
@@ -464,7 +688,7 @@ nok.rate('NOK', 'JPY')?.quote; // → { rate: '6.50', per: 100, inverted: true }
464
688
  nok.missing; // → ['ISK']
465
689
  ```
466
690
 
467
- **Where rates come from.** ducat ships parsers for the ECB's euro reference rates (`@ducatjs/money/convert/ecb`): the daily, 90-day and full-history eurofxref XML and CSV files, and the ECB Data Portal's SDMX-CSV (`parseEcbSdmxCsv`), which has any date range back to 1999 in one file. The opt-in fetchers are in `@ducatjs/money/convert/fetch`: `fetchEcb()` for the eurofxref files and `fetchEcbRange({ start, end, currencies })` for the Data Portal, which needs no key and allows browsers (CORS). They use the platform `fetch` and have a 30-second default timeout. Nothing else in ducat touches the network. The ECB publishes once per TARGET working day at about 16:00 CET, for information only, so its rates are typed `'reference'`. The Data Portal strips trailing zeros (`147.2` for 147.20), so the parser rebuilds the published digits from each series' `DECIMALS` attribute. The Bank of Canada's daily rates come from its Valet API (`parseBankOfCanadaJson` in `@ducatjs/money/convert/boc`, and `fetchBankOfCanada()`, also keyless and CORS-enabled). The Bank quotes CAD per unit of each currency, so the tables hold exact inverses with the published quote kept, and its rates carry `availableAt` 16:30 Toronto time, when it says it publishes them. It quotes four decimals (up to six for small rates), so a small rate has only about four significant digits: JPY `0.008760`, KRW `0.000929`, and IDR `0.000082` with two. The inverse of such a rate is exact, but no more precise than the quote, so for those currencies prefer a source that quotes them the other way round. The Federal Reserve's H.10 rates (noon buying rates in New York, certified for US customs, daily since 1971) have a parser only, `parseFedH10Csv` in `@ducatjs/money/convert/fed`, for the CSV from the Board's Data Download Program (release H10, series in columns, with labels). H.10 quotes currency per USD except AUD, EUR, NZD and GBP, which it quotes as USD per unit; those four are stored as exact inverses with the published quote kept, so every table is USD → currency. Holidays are rows of `ND` and are left out. The Board is retiring the Data Download Program in favour of FRED, whose terms (an API key, no storing or caching, no commercial use without consent) rule out a fetcher in ducat, so download the CSV yourself. For sterling there are two parsers. HMRC's monthly exchange rates (`parseHmrcMonthlyCsv` in `@ducatjs/money/convert/hmrc`) are the UK's rates for customs and VAT, under the Open Government Licence. Each month's table is valid for that month (`asOf` the 1st, `validUntil` the last day) and is available from the end of the Wednesday HMRC publishes it, the day before the penultimate Thursday of the month before (the `publication_date` the trade tariff service's API gives every monthly file). The Bank of England's daily spot rates (`parseBankOfEnglandCsv` in `@ducatjs/money/convert/boe`) come from CSV downloaded from its database. The Bank's legal page excludes "selected exchange rate data and series" from its Open Government Licence as third-party data, and its spot rates may come from LSEG, whose content can't be redistributed without consent. So ducat ships no Bank of England data and no fetcher, and **you must check the licence of every Bank of England series you load** before you use or republish it. For what a payment actually settled at, read the processor's own rate: `stripeRate` and `stripeImpliedRate` from a Stripe balance transaction, and `adyenRate` from an Adyen settlement details row. Any other source is a small loader that returns a `rateTable`.
691
+ **Where rates come from.** ducat ships parsers for the ECB's euro reference rates (`@ducatjs/money/convert/ecb`): the daily, 90-day and full-history eurofxref XML and CSV files, and the ECB Data Portal's SDMX-CSV (`parseEcbSdmxCsv`), which has any date range back to 1999 in one file. The opt-in fetchers are in `@ducatjs/money/convert/fetch`: `fetchEcb()` for the eurofxref files and `fetchEcbRange({ start, end, currencies })` for the Data Portal, which needs no key and allows browsers (CORS). They use the platform `fetch` and have a 30-second default timeout. Nothing else in ducat touches the network. The ECB publishes once per TARGET working day at about 16:00 CET, for information only, so its rates are typed `'reference'`. Its files give no publication time, so the parsers set no `availableAt` unless asked: pass `availableAt: true` (to the parsers, `fetchEcb` or `fetchEcbRange`) for the documented 16:00 CET, which is Frankfurt time (15:00 UTC in winter, 14:00 in summer), or a function of the day for your own, and a historical lookup at 10:00 that day then gets the day before's rate. The Data Portal strips trailing zeros (`147.2` for 147.20), so the parser rebuilds the published digits from each series' `DECIMALS` attribute. The Bank of Canada's daily rates come from its Valet API (`parseBankOfCanadaJson` in `@ducatjs/money/convert/boc`, and `fetchBankOfCanada()`, also keyless and CORS-enabled). The Bank quotes CAD per unit of each currency, so the tables hold exact inverses with the published quote kept, and its rates carry `availableAt` 16:30 Toronto time, when it says it publishes them. It quotes four decimals (up to six for small rates), so a small rate has only about four significant digits: JPY `0.008760`, KRW `0.000929`, and IDR `0.000082` with two. The inverse of such a rate is exact, but no more precise than the quote, so for those currencies prefer a source that quotes them the other way round. The Federal Reserve's H.10 rates (noon buying rates in New York, certified for US customs, daily since 1971) have a parser only, `parseFedH10Csv` in `@ducatjs/money/convert/fed`, for the CSV from the Board's Data Download Program (release H10, series in columns, with labels). H.10 quotes currency per USD except AUD, EUR, NZD and GBP, which it quotes as USD per unit; those four are stored as exact inverses with the published quote kept, so every table is USD → currency. Holidays are rows of `ND` and are left out. The Board is retiring the Data Download Program in favour of FRED, whose terms (an API key, no storing or caching, no commercial use without consent) rule out a fetcher in ducat, so download the CSV yourself. For sterling there are two parsers. HMRC's monthly exchange rates (`parseHmrcMonthlyCsv` in `@ducatjs/money/convert/hmrc`) are the UK's rates for customs and VAT, under the Open Government Licence. Each month's table is valid for that month (`asOf` the 1st, `validUntil` the last day) and is available from the end of the Wednesday HMRC publishes it, the day before the penultimate Thursday of the month before (the `publication_date` the trade tariff service's API gives every monthly file). The Bank of England's daily spot rates (`parseBankOfEnglandCsv` in `@ducatjs/money/convert/boe`) come from CSV downloaded from its database. The Bank's legal page excludes "selected exchange rate data and series" from its Open Government Licence as third-party data, and its spot rates may come from LSEG, whose content can't be redistributed without consent. So ducat ships no Bank of England data and no fetcher, and **you must check the licence of every Bank of England series you load** before you use or republish it. For what a payment actually settled at, read the processor's own rate: `stripeRate` and `stripeImpliedRate` from a Stripe balance transaction, and `adyenRate` from an Adyen settlement details row. Any other source is a small loader that returns a `rateTable`.
468
692
 
469
693
  <!-- doctest: setup import { readFileSync } from 'node:fs'; const sdmxCsv = readFileSync('test/fixtures/ecb-sdmx/exr-d-full.csv', 'utf8'); -->
470
694
 
@@ -537,13 +761,37 @@ fixed('1.5').add('0.25'); // → 1.75: mixed scales align to the larger one
537
761
  fixed('2.5').round('halfEven'); // → 2: round() defaults to scale 0
538
762
  fromScaled(12345, 3).toString(); // → '12.345'
539
763
  JSON.stringify({ unitPrice }); // → '{"unitPrice":"0.0425"}'
764
+ fixed('12.3400').trimScale(); // → 12.34: the smallest exact scale (at least the argument, default 0)
765
+ fixed('0.1').toNumber(); // → 0.1: the nearest double, for display and charts only
540
766
  ```
541
767
 
768
+ `Number(fixed)` and `+fixed` throw, so a float never slips in unnoticed. `toNumber()` is the named way to accept one, where a chart or a UI library wants a number.
769
+
542
770
  Input is strict in the same way as `money()`. A string keeps its own scale. A number is read at its shortest decimal form, and only when that has at most 15 significant digits, which a double always holds faithfully. So `fixed(0.1 + 0.2)` throws instead of becoming 0.30000000000000004: pass the decimal as a string, or give `{ scale, rounding }`. With a `scale`, input that has more decimals throws unless `rounding` is also given.
543
771
 
772
+ **A Fixed is a factor** wherever Money takes one: `multiply`, `divide`, the tax and percentage functions, `ExactMoney`, conversion and rates. It is read exactly, as its scaled integer over 10^scale, so a rate kept as a Fixed needs no conversion. `toRatio()` gives the reduced `Ratio`, to keep for reuse.
773
+
774
+ ```ts
775
+ import { money } from '@ducatjs/money';
776
+ import { fixed } from '@ducatjs/money/fixed';
777
+
778
+ const vat = fixed('0.0725');
779
+ money('199.99', 'EUR').multiply(vat, 'halfEven'); // → 14.50 EUR
780
+ vat.toRatio(); // → { num: 29n, den: 400n, n: 29, d: 400 }
781
+ ```
782
+
544
783
  Arithmetic follows Money's rules. `add`, `subtract` and `compare` align to the larger scale exactly. `multiply` and `divide` take exact factors (integers, decimal strings, bigints, `ratio()` or another `Fixed`) and round once, with `'halfExpand'` by default. The result keeps this value's scale unless you pass another: `fixed('9.990').divide('1.2', 'halfEven', { scale: 2 })` is 8.32. Pass the scale instead of calling `toScale` afterwards, which would round twice. `toScale` and `round` take any of the ten rounding modes, including `'unnecessary'`, which throws if digits would be lost.
545
784
 
546
- To convert, `money.toFixedPoint()` gives the exact amount at the money's scale, and `fixedValue.toMoney('EUR')` makes Money at the currency's exponent. That conversion throws RoundingError when it would drop digits, unless a rounding mode is passed: `fixed('1.005').toMoney('EUR', 'halfEven')` is 1.00 EUR.
785
+ `@ducatjs/money/fixed` doesn't load Money or the currency table, so a program that uses only `Fixed` doesn't carry them. `toMoney()` needs `import '@ducatjs/money/fixed/money'`: that entry has everything in `/fixed`, and adds `money.toFixedPoint()`, the exact amount at the money's scale, and `fixedValue.toMoney('EUR')`, Money at the currency's exponent. That conversion throws RoundingError when it would drop digits, unless a rounding mode is passed.
786
+
787
+ ```ts
788
+ import { money } from '@ducatjs/money';
789
+ import { fixed } from '@ducatjs/money/fixed/money';
790
+
791
+ money('12.34', 'EUR').toFixedPoint(); // → 12.34
792
+ fixed('1.005').toMoney('EUR', 'halfEven'); // → 1.00 EUR
793
+ fixed('1.005').toMoney('EUR'); // throws RoundingError
794
+ ```
547
795
 
548
796
  ### Payment processors: the amount you send
549
797
 
@@ -586,6 +834,54 @@ When the processor needs less precision than the value has, the conversion throw
586
834
 
587
835
  Signs follow each processor's docs and are checked after rounding. Checkout.com (a card verification) and PayPal (breakdown fields) take zero, Braintree doesn't ("Amount must be greater than zero"), and none of the three takes negative amounts: refunds are sent as positive amounts. Klarna takes both, because its order lines document negative amounts for discounts ("Negative when type is discount").
588
836
 
837
+ ### Wire formats
838
+
839
+ `@ducatjs/money/wire` converts Money to and from formats other systems send, exactly both ways. Every reader checks the format strictly, and every writer throws rather than send a value the format can't hold.
840
+
841
+ - `toGoogleMoney(m)` and `fromGoogleMoney(value)`: `google.type.Money` in its proto3 JSON form (`currencyCode`, `units` as an int64 string, `nanos` with the same sign), as Google APIs and many gRPC services use. More than 9 decimals, or units beyond int64, don't fit.
842
+ - `toIso20022Amount(m)` and `fromIso20022Amount({ Ccy, value })`: the amount in `<InstdAmt Ccy="EUR">12.34</InstdAmt>`. It is written with the currency's decimals, as the payment networks' rules (CBPR+, HVPS+) require, whatever the Money's scale. The schema allows at most 5 decimals and 18 digits, and no negative amounts (the direction goes in the credit/debit indicator).
843
+ - `toMinorUnits(m)` and `fromMinorUnits({ value, currency })`: an integer count of ISO 4217 minor units, the JSON several processors and ledgers use. Where a processor's exponents differ from ISO, use its own view (`toAdyen`, `toCheckout`, ...).
844
+
845
+ The readers return Money at the currency's exponent, and throw a RoundingError for extra decimals unless `{ scale }` or `{ rounding }` says what to do.
846
+
847
+ ```ts
848
+ import { money } from '@ducatjs/money';
849
+ import {
850
+ fromGoogleMoney,
851
+ toGoogleMoney,
852
+ toIso20022Amount,
853
+ toMinorUnits,
854
+ } from '@ducatjs/money/wire';
855
+
856
+ toGoogleMoney(money('-1.75', 'EUR')); // → { currencyCode: 'EUR', units: '-1', nanos: -750000000 }
857
+ fromGoogleMoney({ currencyCode: 'USD', units: '12', nanos: 340000000 }); // → 12.34 USD
858
+ toIso20022Amount(money('12.34', 'EUR')); // → { Ccy: 'EUR', value: '12.34' }
859
+ toIso20022Amount(money('-5', 'EUR')); // throws RangeError: use the credit/debit indicator
860
+ toMinorUnits(money('500', 'JPY')); // → { value: 500, currency: 'JPY' }
861
+ ```
862
+
863
+ ### Amounts in words
864
+
865
+ `@ducatjs/money/words` writes amounts in words, as cheques, invoices and legal documents need. `Intl` can't spell numbers out, so the words come from CLDR's rule-based number formats (RBNF), the rules ICU uses, through a small interpreter that matches ICU on every test vector. Each language is its own entry, so a bundle carries only the ones it imports: `@ducatjs/money/words/en`, `/de`, `/fr`, `/es`, `/it`, `/pt` and `/nl`, from 0.6 to 1.8 KiB each. The currency's name, in the right plural and word order, comes from the runtime's `Intl`, and so do the word for "and" and the digit grouping of numbers the rules write as digits (from 10^18 in most rule sets). A currency code `Intl` can't name (not three letters) throws a `RangeError`.
866
+
867
+ - `amountInWords(m, language, options?)` writes the whole units, then the minor part as cheques do ("and 45/100"). CLDR has no names for minor units, so pass them to spell the minor part out: `{ minor: { one: 'cent', other: 'cents' } }`.
868
+ - `gender` picks the number's agreement where the language has genders (Spanish "veintiún euros", "veintiuna libras"); CLDR doesn't record a currency's gender, so it's the caller's. `ruleSet` picks any of the language's rule sets.
869
+ - `spellOut(n, language, ruleSet?)` spells a whole number: cardinals, ordinals (`'%spellout-ordinal'`) and the other public sets CLDR has, listed by `ruleSets(language)`. Where it can't give ICU's words it throws a `RangeError` instead: outside ±(2^63 − 1), the range of ICU's rules; for a private (`%%`) rule set; and for the few English ordinals from 10^18 whose suffix ICU takes from the number cut to 32 bits.
870
+
871
+ ```ts
872
+ import { money } from '@ducatjs/money';
873
+ import { amountInWords, spellOut } from '@ducatjs/money/words';
874
+ import { english } from '@ducatjs/money/words/en';
875
+ import { french } from '@ducatjs/money/words/fr';
876
+
877
+ amountInWords(money('123.45', 'EUR'), english); // → 'one hundred twenty-three euros and 45/100'
878
+ amountInWords(money('21', 'EUR'), french); // → 'vingt-et-un euros et 00/100'
879
+ amountInWords(money('1.01', 'USD'), english, { minor: { one: 'cent', other: 'cents' } }); // → 'one US dollar and one cent'
880
+ spellOut(21, english, '%spellout-ordinal'); // → 'twenty-first'
881
+ ```
882
+
883
+ German, Italian and Dutch words keep CLDR's soft hyphens (U+00AD), which show only where a line breaks. The grammar is CLDR's numbers plus Intl's currency name, so a preposition some languages put after a round million ("un million de yens") isn't added.
884
+
589
885
  ### Databases
590
886
 
591
887
  | storage | Postgres | MySQL | SQLite | helpers |
@@ -594,10 +890,11 @@ Signs follow each processor's docs and are checked after rounding. Checkout.com
594
890
  | **decimal** | `NUMERIC(19,4)` for most cases; `NUMERIC(38,8)` for crypto/FX | `DECIMAL(19,4)` | **avoid** (NUMERIC affinity may store REAL); use TEXT + `toDecimal` if you must | `toDecimalValue(m, Prisma.Decimal)`, `fromDecimal(d, 'EUR')`, `decimalMoneyField(...)` |
595
891
  | **JSON** | `jsonb` `{amount: "12.34", currency}` | `JSON` | `TEXT` | `JSON.stringify(m)`, `fromJSON` |
596
892
 
893
+ - **Writing a BIGINT minor-units column:** `toMinorColumns(m, 'amountMinor', 'currency')` (or `m.toMinor()` for the amount alone), and `fromMinor(row.amountMinor, row.currency)` to read it back. Both use the currency's ISO exponent; a value with digits below the minor unit throws, so `round()` it first. With a scale column, write `m.toScaledUnits()` and `m.scale`, as below.
597
894
  - BIGINT holds ±9.2·10^18 minor units, which is 92 quadrillion EUR. Postgres's `money` type is locale-dependent; don't use it.
598
895
  - Choose a NUMERIC scale of at least the largest exponent you store: 4 covers CLF/UYW, and 3 covers BHD/KWD.
599
896
  - Prisma maps `BigInt` to JS `bigint`. The helpers accept it, and `fromMinor` normalises it back to a number when it is safe.
600
- - **A scale column** makes minor units self-describing: `amount_scale SMALLINT NOT NULL` next to `amount_minor` and `currency`. Write with `toMinorColumns(m, 'amountMinor', 'currency', { scale: 'amountScale' })` and read with `minorMoneyField('amountMinor', 'currency', { scale: 'amountScale' })`. Any scale then round-trips, sub-minor amounts included, which `toMinorColumns` alone refuses. Stored rows also keep their meaning if a currency's exponent changes (see below). To add the column to existing rows, backfill each currency's current exponent in the migration; a missing (NULL) scale throws on read.
897
+ - **A scale column** (the Prisma helpers) makes minor units self-describing: `amount_scale SMALLINT NOT NULL` next to `amount_minor` and `currency`. Write with `toMinorColumns(m, 'amountMinor', 'currency', { scale: 'amountScale' })` and read with `minorMoneyField('amountMinor', 'currency', { scale: 'amountScale' })`. Any scale then round-trips, sub-minor amounts included, which `toMinorColumns` alone refuses. Stored rows also keep their meaning if a currency's exponent changes (see below). To add the column to existing rows, backfill each currency's current exponent in the migration; a missing (NULL) scale throws on read.
601
898
  - **Exponent changes.** Minor units stored without a scale are read at the currency's exponent in the installed version of ducat, so a changed exponent would silently change what old rows mean: 1234 stored as 12.34 would read as 1.234 or 123.4. So an exponent change is a breaking change (see [Decisions](#decisions)), listed under **Changed** in the changelog with the currencies affected. Before upgrading across one, migrate the affected rows, or store a scale column (or a decimal) so the question never arises. Custom currencies keep the exponent given to `defineCurrency`.
602
899
  - `fromDecimal` rejects values with more decimals than the currency allows (e.g. `12.3456` in NUMERIC(19,4) for EUR) unless you pass `{ scale }` or `{ rounding }`. Trailing zeros are fine.
603
900
 
@@ -755,17 +1052,19 @@ The columns check what the types can't: writing another currency, a value at a s
755
1052
 
756
1053
  ## Currency data: source, generation, verification
757
1054
 
758
- | file | source |
759
- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
760
- | `data/iso4217-list-one.xml` | ISO 4217 List One from SIX (the maintenance agency), published **2026-09-17**. It has 178 codes with minor units, plus N.A. codes such as XAU and XDR, which are excluded as non-monetary. |
761
- | `data/stripe.json` | https://docs.stripe.com/currencies, retrieved 2026-11-07, with verbatim quotes for every special case |
762
- | `data/adyen.json` | https://docs.adyen.com/development-resources/currency-codes, retrieved 2026-11-07 |
763
- | `data/checkout.json` | https://www.checkout.com/docs/payments/accept-payments/format-the-amount-value, the currency-codes page and the API reference, retrieved 2026-11-07, with verbatim quotes |
764
- | `data/paypal.json` | https://developer.paypal.com/api/rest/reference/currency-codes/, the other currency-codes page and the Orders v2 schema, retrieved 2026-11-07, with verbatim quotes |
765
- | `data/braintree.json` | https://developer.paypal.com/braintree/docs/reference/general/currencies, the transaction.sale reference, the validation-error list and the GraphQL `Amount` type, retrieved 2026-11-07, with verbatim quotes |
766
- | `data/klarna.json` | https://docs.klarna.com/acquirer/klarna/get-started/integration-resilience/data-types/, the purchase-countries page and the Payments API reference, retrieved 2026-11-07, with verbatim quotes |
767
- | `data/cash-rounding.json` | Central-bank, statute and government pages per rule. Each entry has a `source` URL and a `verified` flag. |
768
- | `data/cldr-cash.json` | CLDR release 49 `supplementalData.xml` cash digits and rounding, the second source for the cash rules (`scripts/fetch-cldr-cash.mjs` refreshes it) |
1055
+ | file | source |
1056
+ | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1057
+ | `data/iso4217-list-one.xml` | ISO 4217 List One from SIX (the maintenance agency), published **2026-09-17**. It has 178 codes with minor units, plus N.A. codes such as XAU and XDR, which are excluded as non-monetary. The numeric codes in `@ducatjs/money/currencies` come from it too. |
1058
+ | `data/stripe.json` | https://docs.stripe.com/currencies, retrieved 2026-11-07, with verbatim quotes for every special case |
1059
+ | `data/adyen.json` | https://docs.adyen.com/development-resources/currency-codes, retrieved 2026-11-07 |
1060
+ | `data/checkout.json` | https://www.checkout.com/docs/payments/accept-payments/format-the-amount-value, the currency-codes page and the API reference, retrieved 2026-11-07, with verbatim quotes |
1061
+ | `data/paypal.json` | https://developer.paypal.com/api/rest/reference/currency-codes/, the other currency-codes page and the Orders v2 schema, retrieved 2026-11-07, with verbatim quotes |
1062
+ | `data/braintree.json` | https://developer.paypal.com/braintree/docs/reference/general/currencies, the transaction.sale reference, the validation-error list and the GraphQL `Amount` type, retrieved 2026-11-07, with verbatim quotes |
1063
+ | `data/klarna.json` | https://docs.klarna.com/acquirer/klarna/get-started/integration-resilience/data-types/, the purchase-countries page and the Payments API reference, retrieved 2026-11-07, with verbatim quotes |
1064
+ | `data/cash-rounding.json` | Central-bank, statute and government pages per rule. Each entry has a `source` URL and a `verified` flag. |
1065
+ | `data/cldr-cash.json` | CLDR release 49 `supplementalData.xml` cash digits and rounding, the second source for the cash rules (`scripts/fetch-cldr-cash.mjs` refreshes it) |
1066
+ | `data/cldr-territories.json` | CLDR release 49 `supplementalData.xml` currencies per territory, with their first and last days (`scripts/fetch-cldr-territories.mjs` refreshes it) |
1067
+ | `data/rbnf/<language>.txt` | CLDR release 49 spell-out rules (RBNF) from the cldr-rbnf package (`scripts/fetch-cldr-rbnf.mjs` refreshes them). `test/vectors/rbnf.json` holds ICU 4C 79.1's output for them, the oracle the interpreter is tested against, and `test/vectors/rbnf-data.json` ICU 4C 74.2's engine run on this text for the other rule sets (`scripts/gen-rbnf-vectors.mjs`, `--from-data`). |
769
1068
 
770
1069
  - `pnpm gen` (`scripts/gen-currencies.mjs`) turns these into `src/generated/*.ts`.
771
1070
  - `pnpm gen:check` fails if the generated files are stale. It also runs inside the test suite.
@@ -974,20 +1273,23 @@ Vitest and fast-check are optional peer dependencies, used only by these entries
974
1273
  ## Benchmarks
975
1274
 
976
1275
  - Clean-machine numbers against the other money and fixed-point libraries are in [How it compares](#how-it-compares) and
977
- [docs/COMPARISON.md](docs/COMPARISON.md), generated from [compare/](compare) on one quiet AMD EPYC Genoa vCPU under
1276
+ [docs/COMPARISON.md](https://github.com/public/ducat/blob/main/docs/COMPARISON.md), generated from [compare/](https://github.com/public/ducat/tree/main/compare) on one quiet AMD EPYC Genoa vCPU under
978
1277
  Node, Bun and Deno.
979
1278
  - CodSpeed measures every pull request by instruction count, so speed regressions show up even on noisy CI machines.
980
1279
  - The benchmarks in `bench/` are for quick local comparisons; on a shared machine their run-to-run variation is often
981
1280
  ±20–30%.
982
1281
  - Bundle size (esbuild, minified + gzip; `pnpm size` checks every entry point and snippet against `scripts/size-budgets.json`):
983
- - `money('1.00', 'EUR').add(…).multiply('1.075', 'halfEven').toDecimal()`: **4.0 KiB**, of which about 0.55 KiB is the ISO table
984
- - the core entry point: 4.9 KiB; everything (`@ducatjs/money/all`): 27.6 KiB
1282
+ - `money('1.00', 'EUR').add(…).multiply('1.075', 'halfEven').toDecimal()`: **4.5 KiB**, of which about 0.55 KiB is the ISO table. 0.3 grew it from 4.0 KiB, and the core from 4.9: stricter input validation and clearer errors (the port-test fixes), and the root entry installing the methods and currencies so that `/fn` programs can leave them out
1283
+ - the core entry point: 5.5 KiB; everything (`@ducatjs/money/all`): 50.5 KiB
1284
+ - `Fixed` alone (`fixed('1.00')`, add, multiply, toString): 3.5 KiB
985
1285
  - the same snippet with dinero.js (EUR only): 1.8 KiB
1286
+ - the same snippet through `/fn`, with `import '@ducatjs/money/iso/EUR'`: 3.0 KiB; create, add and print only: 1.3 KiB
986
1287
 
987
1288
  ---
988
1289
 
989
1290
  ## Decisions
990
1291
 
1292
+ - **Amounts in words come from CLDR's RBNF rules, not hand-written grammars.** `Intl` has no spell-out, and ECMA-402 doesn't expose ICU's RuleBasedNumberFormat. CLDR's rules are small (about 1 KiB gzipped per language), carry every language's agreement and compounding rules, and are the same text ICU runs, so an interpreter can be tested against ICU itself. Each language is its own entry so bundles pay only for what they use. Minor-unit names (cent, centime) and a currency's grammatical gender are in no standard data, so the default is the cheque form ("and 45/100") and both are options the caller supplies.
991
1293
  - **JSON is a decimal string plus the currency, never minor units**: `{"amount":"12.34","currency":"EUR"}`. Minor units only mean something to a reader who knows the exponent, and the exponent isn't fixed:
992
1294
  - Processors disagree with ISO. Stripe sends ISK and UGX as two-decimal; Adyen has its own exceptions.
993
1295
  - ISO exponents change over time.
@@ -999,7 +1301,7 @@ Vitest and fast-check are optional peer dependencies, used only by these entries
999
1301
 
1000
1302
  - **The package is `@ducatjs/money`** (the brand and repo stay ducat). npm's name-similarity rule blocks the unscoped `ducat`, and the npm org `ducat` was taken, so it lives under the `ducatjs` org; one package, with opt-in subpath modules. The ducat was the Venetian gold trade coin, used across Europe for about 600 years.
1001
1303
  - **Methods on `Money`**, because free functions alone are awkward to use: `price.add(fee).multiply('1.075').split(3)`. The same operations as plain functions are in `@ducatjs/money/fn`, not in the root entry, so there is one way to write each in ordinary code. Operands are `Money` only, never bare numbers (monetra's `add(5)` means 5 minor units, a trap we avoid).
1002
- - **The core is small; everything else is an opt-in module that installs methods.** Methods on one class pull every feature into every bundle, so `Money` carries only the core, and `@ducatjs/money/allocate`, `/tax`, `/format`… add their methods when imported (types through `declare module` augmentation, as dayjs plugins do). The cost is that installed methods are global at run time. `@ducatjs/money/fn` offers the same functions without touching the prototype, for function-level tree-shaking.
1304
+ - **The core is small; everything else is an opt-in module that installs methods.** Methods on one class pull every feature into every bundle, so `Money` carries only the core, and `@ducatjs/money/allocate`, `/tax`, `/format`… add their methods when imported (types through `declare module` augmentation, as dayjs plugins do). The cost is that installed methods are global at run time. `@ducatjs/money/fn` offers the same functions without touching the prototype, for function-level tree-shaking: even the core methods are installed by the root entry rather than written into the class, so `/fn` programs carry only what they call.
1003
1305
  - **Correctness and features come before bundle size.** The core keeps the currency table, the comparison methods, bigint support and exact string parsing; everything else is an opt-in module, and size budgets in CI stop either from growing.
1004
1306
  - **Default rounding is `'halfExpand'`** (ties away from zero) for arithmetic, the most common default. It is the default of decimal.js, Prisma.Decimal, big.js, bignumber.js and `Intl.NumberFormat`, and what currency.js, js-money and ts-money intend with `Math.round` (which differs for negative ties). The minority defaults: half-even (dinero.js 1, bigint-money), throw (monetra), truncate (dinero.js 2 `transformScale`). Parsing (`money('1.005','EUR')`, `fromDecimal`) and processor amounts (`toStripeAmount`, `toAdyen`) still throw unless a mode is passed, as ts-money and monetra do for input. The default is exported as `DEFAULT_ROUNDING`.
1005
1307
  - **Rounding policies are explicit values.** A policy (scale, increment and mode) is passed to each operation that rounds, the way a rounding mode is. It is never attached to an amount or installed as a global default: a stored or global policy would make the same expression round differently depending on where a value came from or what ran earlier, which is the kind of action at a distance a money library should rule out.
@@ -1030,6 +1332,6 @@ Vitest and fast-check are optional peer dependencies, used only by these entries
1030
1332
  - Memory and GC pressure, which were reasoned about but not measured.
1031
1333
  - dinero.js's bigint calculator.
1032
1334
  - **No Money arrays or columnar ops** (e.g. summing a `Float64Array`/`BigInt64Array` of minor units).
1033
- - **The ISO table is always bundled** (about 0.55 KiB gzipped, 1 KiB minified). Per-currency imports like dinero's would make the minimum bundle smaller.
1034
- - **Minor-unit columns can't round-trip values with a non-ISO scale.** `toMinorColumns` refuses them by design. There is no `scale` column helper.
1335
+ - **The root entry always bundles the ISO table** (about 0.55 KiB gzipped, 1 KiB minified). A program written with `/fn` imports only the currencies it uses (`@ducatjs/money/iso/EUR`), like dinero.js's per-currency objects.
1336
+ - **Only the Prisma helpers have a scale column.** Without one, minor-unit columns can't round-trip values at a scale other than the currency's, so `toMinorColumns`, the Kysely `setMoney` and the Drizzle `moneyMinor` columns refuse them by design. With Prisma, `{ scale: 'amountScale' }` stores the scale alongside (see [Databases](#databases)). Elsewhere, store `m.toScaledUnits()` and `m.scale` yourself, or use a decimal, JSON or the node-postgres composite column, which keep the scale.
1035
1337
  - **No docs site yet.**