nautilus_model/
currencies.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16//! Common `Currency` constants.
17//!
18//! Precision and metadata references:
19//! - ISO 4217 Maintenance Agency dataset (<https://github.com/datasets/currency-codes>):
20//!   authoritative alphabetic codes, numeric codes, and minor units for fiat and commodity-backed entries.
21//! - Cardano ledger documentation (<https://docs.cardano.org/native-tokens/understanding-assets>):
22//!   1 ADA = 1,000,000 lovelace, underpinning the six-decimal crypto precision we retain.
23//! - XRPL documentation on drops (<https://xrpl.org/xrp-ledger-tokens.html#drops-and-xrp>):
24//!   1 XRP = 1,000,000 drops, confirming the six-decimal allowance for XRP.
25//! - Tezos protocol reference (<https://tezos.gitlab.io/active/numismatics.html>):
26//!   1 tez = 1,000,000 mutez, informing the six-decimal precision for XTZ.
27//! - Stablecoin contract metadata on Etherscan for USDC, USDP, and BRZ
28//!   (e.g. <https://etherscan.io/token/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48#readContract>,
29//!   <https://etherscan.io/token/0x8e870d67f660d95d5be530380d0ec0bd388289e1#readContract>,
30//!   <https://etherscan.io/token/0x01d33fd36ec67c6ada32cf36b31e88ee190b1839#readContract>):
31//!   each exposes 6–18 on-chain decimals; we clamp to an 8-decimal internal default.
32
33use std::{
34    collections::HashMap,
35    sync::{LazyLock, Mutex, OnceLock},
36};
37
38use ustr::Ustr;
39
40use crate::{enums::CurrencyType, types::Currency};
41
42///////////////////////////////////////////////////////////////////////////////
43// Fiat currencies
44///////////////////////////////////////////////////////////////////////////////
45static AUD_LOCK: OnceLock<Currency> = OnceLock::new();
46static BRL_LOCK: OnceLock<Currency> = OnceLock::new();
47static CAD_LOCK: OnceLock<Currency> = OnceLock::new();
48static CHF_LOCK: OnceLock<Currency> = OnceLock::new();
49static CNY_LOCK: OnceLock<Currency> = OnceLock::new();
50static CNH_LOCK: OnceLock<Currency> = OnceLock::new();
51static CZK_LOCK: OnceLock<Currency> = OnceLock::new();
52static DKK_LOCK: OnceLock<Currency> = OnceLock::new();
53static EUR_LOCK: OnceLock<Currency> = OnceLock::new();
54static GBP_LOCK: OnceLock<Currency> = OnceLock::new();
55static HKD_LOCK: OnceLock<Currency> = OnceLock::new();
56static HUF_LOCK: OnceLock<Currency> = OnceLock::new();
57static ILS_LOCK: OnceLock<Currency> = OnceLock::new();
58static INR_LOCK: OnceLock<Currency> = OnceLock::new();
59static JPY_LOCK: OnceLock<Currency> = OnceLock::new();
60static KRW_LOCK: OnceLock<Currency> = OnceLock::new();
61static MXN_LOCK: OnceLock<Currency> = OnceLock::new();
62static NOK_LOCK: OnceLock<Currency> = OnceLock::new();
63static NZD_LOCK: OnceLock<Currency> = OnceLock::new();
64static PLN_LOCK: OnceLock<Currency> = OnceLock::new();
65static RUB_LOCK: OnceLock<Currency> = OnceLock::new();
66static SAR_LOCK: OnceLock<Currency> = OnceLock::new();
67static SEK_LOCK: OnceLock<Currency> = OnceLock::new();
68static SGD_LOCK: OnceLock<Currency> = OnceLock::new();
69static THB_LOCK: OnceLock<Currency> = OnceLock::new();
70static TRY_LOCK: OnceLock<Currency> = OnceLock::new();
71static TWD_LOCK: OnceLock<Currency> = OnceLock::new();
72static USD_LOCK: OnceLock<Currency> = OnceLock::new();
73static ZAR_LOCK: OnceLock<Currency> = OnceLock::new();
74
75///////////////////////////////////////////////////////////////////////////////
76// Commodity backed currencies
77///////////////////////////////////////////////////////////////////////////////
78static XAG_LOCK: OnceLock<Currency> = OnceLock::new();
79static XAU_LOCK: OnceLock<Currency> = OnceLock::new();
80static XPT_LOCK: OnceLock<Currency> = OnceLock::new();
81
82///////////////////////////////////////////////////////////////////////////////
83// Crypto currencies
84///////////////////////////////////////////////////////////////////////////////
85static ONEINCH_LOCK: OnceLock<Currency> = OnceLock::new();
86static AAVE_LOCK: OnceLock<Currency> = OnceLock::new();
87static ACA_LOCK: OnceLock<Currency> = OnceLock::new();
88static ADA_LOCK: OnceLock<Currency> = OnceLock::new();
89static APT_LOCK: OnceLock<Currency> = OnceLock::new();
90static ARB_LOCK: OnceLock<Currency> = OnceLock::new();
91static AVAX_LOCK: OnceLock<Currency> = OnceLock::new();
92static BCH_LOCK: OnceLock<Currency> = OnceLock::new();
93static BIO_LOCK: OnceLock<Currency> = OnceLock::new();
94static BTC_LOCK: OnceLock<Currency> = OnceLock::new();
95static BTTC_LOCK: OnceLock<Currency> = OnceLock::new();
96static BNB_LOCK: OnceLock<Currency> = OnceLock::new();
97static BRZ_LOCK: OnceLock<Currency> = OnceLock::new();
98static BSV_LOCK: OnceLock<Currency> = OnceLock::new();
99static BUSD_LOCK: OnceLock<Currency> = OnceLock::new();
100static CAKE_LOCK: OnceLock<Currency> = OnceLock::new();
101static CRV_LOCK: OnceLock<Currency> = OnceLock::new();
102static DASH_LOCK: OnceLock<Currency> = OnceLock::new();
103static DOGE_LOCK: OnceLock<Currency> = OnceLock::new();
104static DOT_LOCK: OnceLock<Currency> = OnceLock::new();
105static ENA_LOCK: OnceLock<Currency> = OnceLock::new();
106static EOS_LOCK: OnceLock<Currency> = OnceLock::new();
107static ETH_LOCK: OnceLock<Currency> = OnceLock::new();
108static ETHW_LOCK: OnceLock<Currency> = OnceLock::new();
109static FDUSD_LOCK: OnceLock<Currency> = OnceLock::new();
110static HYPE_LOCK: OnceLock<Currency> = OnceLock::new();
111static JOE_LOCK: OnceLock<Currency> = OnceLock::new();
112static LINK_LOCK: OnceLock<Currency> = OnceLock::new();
113static LTC_LOCK: OnceLock<Currency> = OnceLock::new();
114static LUNA_LOCK: OnceLock<Currency> = OnceLock::new();
115static NBT_LOCK: OnceLock<Currency> = OnceLock::new();
116static POL_LOCK: OnceLock<Currency> = OnceLock::new();
117static PROVE_LOCK: OnceLock<Currency> = OnceLock::new();
118static SOL_LOCK: OnceLock<Currency> = OnceLock::new();
119static SUI_LOCK: OnceLock<Currency> = OnceLock::new();
120static TON_LOCK: OnceLock<Currency> = OnceLock::new();
121static TRX_LOCK: OnceLock<Currency> = OnceLock::new();
122static TRYB_LOCK: OnceLock<Currency> = OnceLock::new();
123static TUSD_LOCK: OnceLock<Currency> = OnceLock::new();
124static SHIB_LOCK: OnceLock<Currency> = OnceLock::new();
125static UNI_LOCK: OnceLock<Currency> = OnceLock::new();
126static VTC_LOCK: OnceLock<Currency> = OnceLock::new();
127static WBTC_LOCK: OnceLock<Currency> = OnceLock::new();
128static WSB_LOCK: OnceLock<Currency> = OnceLock::new();
129static XBT_LOCK: OnceLock<Currency> = OnceLock::new();
130static XEC_LOCK: OnceLock<Currency> = OnceLock::new();
131static XLM_LOCK: OnceLock<Currency> = OnceLock::new();
132static XMR_LOCK: OnceLock<Currency> = OnceLock::new();
133static XRP_LOCK: OnceLock<Currency> = OnceLock::new();
134static XTZ_LOCK: OnceLock<Currency> = OnceLock::new();
135static USDC_LOCK: OnceLock<Currency> = OnceLock::new();
136static USDC_POS_LOCK: OnceLock<Currency> = OnceLock::new();
137static USDP_LOCK: OnceLock<Currency> = OnceLock::new();
138static USDT_LOCK: OnceLock<Currency> = OnceLock::new();
139static ZEC_LOCK: OnceLock<Currency> = OnceLock::new();
140
141impl Currency {
142    ///////////////////////////////////////////////////////////////////////////
143    // Fiat currencies
144    ///////////////////////////////////////////////////////////////////////////
145    #[allow(non_snake_case)]
146    #[must_use]
147    pub fn AUD() -> Self {
148        *AUD_LOCK.get_or_init(|| Self {
149            code: Ustr::from("AUD"),
150            precision: 2,
151            iso4217: 36,
152            name: Ustr::from("Australian dollar"),
153            currency_type: CurrencyType::Fiat,
154        })
155    }
156    #[allow(non_snake_case)]
157    #[must_use]
158    pub fn BRL() -> Self {
159        *BRL_LOCK.get_or_init(|| Self {
160            code: Ustr::from("BRL"),
161            precision: 2,
162            iso4217: 986,
163            name: Ustr::from("Brazilian real"),
164            currency_type: CurrencyType::Fiat,
165        })
166    }
167
168    #[allow(non_snake_case)]
169    #[must_use]
170    pub fn CAD() -> Self {
171        *CAD_LOCK.get_or_init(|| Self {
172            code: Ustr::from("CAD"),
173            precision: 2,
174            iso4217: 124,
175            name: Ustr::from("Canadian dollar"),
176            currency_type: CurrencyType::Fiat,
177        })
178    }
179
180    #[allow(non_snake_case)]
181    #[must_use]
182    pub fn CHF() -> Self {
183        *CHF_LOCK.get_or_init(|| Self {
184            code: Ustr::from("CHF"),
185            precision: 2,
186            iso4217: 756,
187            name: Ustr::from("Swiss franc"),
188            currency_type: CurrencyType::Fiat,
189        })
190    }
191
192    #[allow(non_snake_case)]
193    #[must_use]
194    pub fn CNY() -> Self {
195        *CNY_LOCK.get_or_init(|| Self {
196            code: Ustr::from("CNY"),
197            precision: 2,
198            iso4217: 156,
199            name: Ustr::from("Chinese yuan"),
200            currency_type: CurrencyType::Fiat,
201        })
202    }
203
204    #[allow(non_snake_case)]
205    #[must_use]
206    pub fn CNH() -> Self {
207        *CNH_LOCK.get_or_init(|| Self {
208            code: Ustr::from("CNH"),
209            precision: 2,
210            iso4217: 0,
211            name: Ustr::from("Chinese yuan (offshore)"),
212            currency_type: CurrencyType::Fiat,
213        })
214    }
215
216    #[allow(non_snake_case)]
217    #[must_use]
218    pub fn CZK() -> Self {
219        *CZK_LOCK.get_or_init(|| Self {
220            code: Ustr::from("CZK"),
221            precision: 2,
222            iso4217: 203,
223            name: Ustr::from("Czech koruna"),
224            currency_type: CurrencyType::Fiat,
225        })
226    }
227
228    #[allow(non_snake_case)]
229    #[must_use]
230    pub fn DKK() -> Self {
231        *DKK_LOCK.get_or_init(|| Self {
232            code: Ustr::from("DKK"),
233            precision: 2,
234            iso4217: 208,
235            name: Ustr::from("Danish krone"),
236            currency_type: CurrencyType::Fiat,
237        })
238    }
239
240    #[allow(non_snake_case)]
241    #[must_use]
242    pub fn EUR() -> Self {
243        *EUR_LOCK.get_or_init(|| Self {
244            code: Ustr::from("EUR"),
245            precision: 2,
246            iso4217: 978,
247            name: Ustr::from("Euro"),
248            currency_type: CurrencyType::Fiat,
249        })
250    }
251
252    #[allow(non_snake_case)]
253    #[must_use]
254    pub fn GBP() -> Self {
255        *GBP_LOCK.get_or_init(|| Self {
256            code: Ustr::from("GBP"),
257            precision: 2,
258            iso4217: 826,
259            name: Ustr::from("British Pound"),
260            currency_type: CurrencyType::Fiat,
261        })
262    }
263
264    #[allow(non_snake_case)]
265    #[must_use]
266    pub fn HKD() -> Self {
267        *HKD_LOCK.get_or_init(|| Self {
268            code: Ustr::from("HKD"),
269            precision: 2,
270            iso4217: 344,
271            name: Ustr::from("Hong Kong dollar"),
272            currency_type: CurrencyType::Fiat,
273        })
274    }
275
276    #[allow(non_snake_case)]
277    #[must_use]
278    pub fn HUF() -> Self {
279        *HUF_LOCK.get_or_init(|| Self {
280            code: Ustr::from("HUF"),
281            precision: 2,
282            iso4217: 348,
283            name: Ustr::from("Hungarian forint"),
284            currency_type: CurrencyType::Fiat,
285        })
286    }
287
288    #[allow(non_snake_case)]
289    #[must_use]
290    pub fn ILS() -> Self {
291        *ILS_LOCK.get_or_init(|| Self {
292            code: Ustr::from("ILS"),
293            precision: 2,
294            iso4217: 376,
295            name: Ustr::from("Israeli new shekel"),
296            currency_type: CurrencyType::Fiat,
297        })
298    }
299
300    #[allow(non_snake_case)]
301    #[must_use]
302    pub fn INR() -> Self {
303        *INR_LOCK.get_or_init(|| Self {
304            code: Ustr::from("INR"),
305            precision: 2,
306            iso4217: 356,
307            name: Ustr::from("Indian rupee"),
308            currency_type: CurrencyType::Fiat,
309        })
310    }
311
312    #[allow(non_snake_case)]
313    #[must_use]
314    pub fn JPY() -> Self {
315        *JPY_LOCK.get_or_init(|| Self {
316            code: Ustr::from("JPY"),
317            precision: 0,
318            iso4217: 392,
319            name: Ustr::from("Japanese yen"),
320            currency_type: CurrencyType::Fiat,
321        })
322    }
323    #[allow(non_snake_case)]
324    #[must_use]
325    pub fn KRW() -> Self {
326        *KRW_LOCK.get_or_init(|| Self {
327            code: Ustr::from("KRW"),
328            precision: 0,
329            iso4217: 410,
330            name: Ustr::from("South Korean won"),
331            currency_type: CurrencyType::Fiat,
332        })
333    }
334
335    #[allow(non_snake_case)]
336    #[must_use]
337    pub fn MXN() -> Self {
338        *MXN_LOCK.get_or_init(|| Self {
339            code: Ustr::from("MXN"),
340            precision: 2,
341            iso4217: 484,
342            name: Ustr::from("Mexican peso"),
343            currency_type: CurrencyType::Fiat,
344        })
345    }
346
347    #[allow(non_snake_case)]
348    #[must_use]
349    pub fn NOK() -> Self {
350        *NOK_LOCK.get_or_init(|| Self {
351            code: Ustr::from("NOK"),
352            precision: 2,
353            iso4217: 578,
354            name: Ustr::from("Norwegian krone"),
355            currency_type: CurrencyType::Fiat,
356        })
357    }
358
359    #[allow(non_snake_case)]
360    #[must_use]
361    pub fn NZD() -> Self {
362        *NZD_LOCK.get_or_init(|| Self {
363            code: Ustr::from("NZD"),
364            precision: 2,
365            iso4217: 554,
366            name: Ustr::from("New Zealand dollar"),
367            currency_type: CurrencyType::Fiat,
368        })
369    }
370
371    #[allow(non_snake_case)]
372    #[must_use]
373    pub fn PLN() -> Self {
374        *PLN_LOCK.get_or_init(|| Self {
375            code: Ustr::from("PLN"),
376            precision: 2,
377            iso4217: 985,
378            name: Ustr::from("Polish złoty"),
379            currency_type: CurrencyType::Fiat,
380        })
381    }
382
383    #[allow(non_snake_case)]
384    #[must_use]
385    pub fn RUB() -> Self {
386        *RUB_LOCK.get_or_init(|| Self {
387            code: Ustr::from("RUB"),
388            precision: 2,
389            iso4217: 643,
390            name: Ustr::from("Russian ruble"),
391            currency_type: CurrencyType::Fiat,
392        })
393    }
394
395    #[allow(non_snake_case)]
396    #[must_use]
397    pub fn SAR() -> Self {
398        *SAR_LOCK.get_or_init(|| Self {
399            code: Ustr::from("SAR"),
400            precision: 2,
401            iso4217: 682,
402            name: Ustr::from("Saudi riyal"),
403            currency_type: CurrencyType::Fiat,
404        })
405    }
406
407    #[allow(non_snake_case)]
408    #[must_use]
409    pub fn SEK() -> Self {
410        *SEK_LOCK.get_or_init(|| Self {
411            code: Ustr::from("SEK"),
412            precision: 2,
413            iso4217: 752,
414            name: Ustr::from("Swedish krona"),
415            currency_type: CurrencyType::Fiat,
416        })
417    }
418
419    #[allow(non_snake_case)]
420    #[must_use]
421    pub fn SGD() -> Self {
422        *SGD_LOCK.get_or_init(|| Self {
423            code: Ustr::from("SGD"),
424            precision: 2,
425            iso4217: 702,
426            name: Ustr::from("Singapore dollar"),
427            currency_type: CurrencyType::Fiat,
428        })
429    }
430
431    #[allow(non_snake_case)]
432    #[must_use]
433    pub fn THB() -> Self {
434        *THB_LOCK.get_or_init(|| Self {
435            code: Ustr::from("THB"),
436            precision: 2,
437            iso4217: 764,
438            name: Ustr::from("Thai baht"),
439            currency_type: CurrencyType::Fiat,
440        })
441    }
442
443    #[allow(non_snake_case)]
444    #[must_use]
445    pub fn TRY() -> Self {
446        *TRY_LOCK.get_or_init(|| Self {
447            code: Ustr::from("TRY"),
448            precision: 2,
449            iso4217: 949,
450            name: Ustr::from("Turkish lira"),
451            currency_type: CurrencyType::Fiat,
452        })
453    }
454
455    #[allow(non_snake_case)]
456    #[must_use]
457    pub fn TWD() -> Self {
458        *TWD_LOCK.get_or_init(|| Self {
459            code: Ustr::from("TWD"),
460            precision: 2,
461            iso4217: 901,
462            name: Ustr::from("New Taiwan dollar"),
463            currency_type: CurrencyType::Fiat,
464        })
465    }
466
467    #[allow(non_snake_case)]
468    #[must_use]
469    pub fn USD() -> Self {
470        *USD_LOCK.get_or_init(|| Self {
471            code: Ustr::from("USD"),
472            precision: 2,
473            iso4217: 840,
474            name: Ustr::from("United States dollar"),
475            currency_type: CurrencyType::Fiat,
476        })
477    }
478    #[allow(non_snake_case)]
479    #[must_use]
480    pub fn ZAR() -> Self {
481        *ZAR_LOCK.get_or_init(|| Self {
482            code: Ustr::from("ZAR"),
483            precision: 2,
484            iso4217: 710,
485            name: Ustr::from("South African rand"),
486            currency_type: CurrencyType::Fiat,
487        })
488    }
489
490    #[allow(non_snake_case)]
491    #[must_use]
492    pub fn XAG() -> Self {
493        *XAG_LOCK.get_or_init(|| Self {
494            code: Ustr::from("XAG"),
495            precision: 2,
496            iso4217: 961,
497            name: Ustr::from("Silver (one troy ounce)"),
498            currency_type: CurrencyType::CommodityBacked,
499        })
500    }
501
502    #[allow(non_snake_case)]
503    #[must_use]
504    pub fn XAU() -> Self {
505        *XAU_LOCK.get_or_init(|| Self {
506            code: Ustr::from("XAU"),
507            precision: 2,
508            iso4217: 959,
509            name: Ustr::from("Gold (one troy ounce)"),
510            currency_type: CurrencyType::CommodityBacked,
511        })
512    }
513
514    #[allow(non_snake_case)]
515    #[must_use]
516    pub fn XPT() -> Self {
517        *XPT_LOCK.get_or_init(|| Self {
518            code: Ustr::from("XPT"),
519            precision: 2,
520            iso4217: 962,
521            name: Ustr::from("Platinum (one troy ounce)"),
522            currency_type: CurrencyType::CommodityBacked,
523        })
524    }
525
526    ///////////////////////////////////////////////////////////////////////////
527    // Crypto currencies
528    ///////////////////////////////////////////////////////////////////////////
529    #[allow(non_snake_case)]
530    #[must_use]
531    pub fn ONEINCH() -> Self {
532        *ONEINCH_LOCK.get_or_init(|| Self {
533            code: Ustr::from("1INCH"),
534            precision: 8,
535            iso4217: 0,
536            name: Ustr::from("1inch Network"),
537            currency_type: CurrencyType::Crypto,
538        })
539    }
540
541    #[allow(non_snake_case)]
542    #[must_use]
543    pub fn AAVE() -> Self {
544        *AAVE_LOCK.get_or_init(|| Self {
545            code: Ustr::from("AAVE"),
546            precision: 8,
547            iso4217: 0,
548            name: Ustr::from("Aave"),
549            currency_type: CurrencyType::Crypto,
550        })
551    }
552
553    #[allow(non_snake_case)]
554    #[must_use]
555    pub fn ACA() -> Self {
556        *ACA_LOCK.get_or_init(|| Self {
557            code: Ustr::from("ACA"),
558            precision: 8,
559            iso4217: 0,
560            name: Ustr::from("Acala Token"),
561            currency_type: CurrencyType::Crypto,
562        })
563    }
564
565    #[allow(non_snake_case)]
566    #[must_use]
567    pub fn ADA() -> Self {
568        *ADA_LOCK.get_or_init(|| Self {
569            code: Ustr::from("ADA"),
570            precision: 6,
571            iso4217: 0,
572            name: Ustr::from("Cardano"),
573            currency_type: CurrencyType::Crypto,
574        })
575    }
576
577    #[allow(non_snake_case)]
578    #[must_use]
579    pub fn APT() -> Self {
580        *APT_LOCK.get_or_init(|| Self {
581            code: Ustr::from("APT"),
582            precision: 8,
583            iso4217: 0,
584            name: Ustr::from("Aptos"),
585            currency_type: CurrencyType::Crypto,
586        })
587    }
588
589    #[allow(non_snake_case)]
590    #[must_use]
591    pub fn ARB() -> Self {
592        *ARB_LOCK.get_or_init(|| Self {
593            code: Ustr::from("ARB"),
594            precision: 8,
595            iso4217: 0,
596            name: Ustr::from("Arbitrum"),
597            currency_type: CurrencyType::Crypto,
598        })
599    }
600
601    #[allow(non_snake_case)]
602    #[must_use]
603    pub fn AVAX() -> Self {
604        *AVAX_LOCK.get_or_init(|| Self {
605            code: Ustr::from("AVAX"),
606            precision: 8,
607            iso4217: 0,
608            name: Ustr::from("Avalanche"),
609            currency_type: CurrencyType::Crypto,
610        })
611    }
612
613    #[allow(non_snake_case)]
614    #[must_use]
615    pub fn BCH() -> Self {
616        *BCH_LOCK.get_or_init(|| Self {
617            code: Ustr::from("BCH"),
618            precision: 8,
619            iso4217: 0,
620            name: Ustr::from("Bitcoin Cash"),
621            currency_type: CurrencyType::Crypto,
622        })
623    }
624
625    #[allow(non_snake_case)]
626    #[must_use]
627    pub fn BIO() -> Self {
628        *BIO_LOCK.get_or_init(|| Self {
629            code: Ustr::from("BIO"),
630            precision: 8,
631            iso4217: 0,
632            name: Ustr::from("BioPassport"),
633            currency_type: CurrencyType::Crypto,
634        })
635    }
636
637    #[allow(non_snake_case)]
638    #[must_use]
639    pub fn BTC() -> Self {
640        *BTC_LOCK.get_or_init(|| Self {
641            code: Ustr::from("BTC"),
642            precision: 8,
643            iso4217: 0,
644            name: Ustr::from("Bitcoin"),
645            currency_type: CurrencyType::Crypto,
646        })
647    }
648
649    #[allow(non_snake_case)]
650    #[must_use]
651    pub fn BTTC() -> Self {
652        *BTTC_LOCK.get_or_init(|| Self {
653            code: Ustr::from("BTTC"),
654            precision: 8,
655            iso4217: 0,
656            name: Ustr::from("BitTorrent"),
657            currency_type: CurrencyType::Crypto,
658        })
659    }
660
661    #[allow(non_snake_case)]
662    #[must_use]
663    pub fn BNB() -> Self {
664        *BNB_LOCK.get_or_init(|| Self {
665            code: Ustr::from("BNB"),
666            precision: 8,
667            iso4217: 0,
668            name: Ustr::from("Binance Coin"),
669            currency_type: CurrencyType::Crypto,
670        })
671    }
672
673    #[allow(non_snake_case)]
674    #[must_use]
675    pub fn BRZ() -> Self {
676        *BRZ_LOCK.get_or_init(|| Self {
677            code: Ustr::from("BRZ"),
678            precision: 8,
679            iso4217: 0,
680            name: Ustr::from("Brazilian Digital Token"),
681            currency_type: CurrencyType::Crypto,
682        })
683    }
684
685    #[allow(non_snake_case)]
686    #[must_use]
687    pub fn BSV() -> Self {
688        *BSV_LOCK.get_or_init(|| Self {
689            code: Ustr::from("BSV"),
690            precision: 8,
691            iso4217: 0,
692            name: Ustr::from("Bitcoin SV"),
693            currency_type: CurrencyType::Crypto,
694        })
695    }
696
697    #[allow(non_snake_case)]
698    #[must_use]
699    pub fn BUSD() -> Self {
700        *BUSD_LOCK.get_or_init(|| Self {
701            code: Ustr::from("BUSD"),
702            precision: 8,
703            iso4217: 0,
704            name: Ustr::from("Binance USD"),
705            currency_type: CurrencyType::Crypto,
706        })
707    }
708
709    #[allow(non_snake_case)]
710    #[must_use]
711    pub fn CAKE() -> Self {
712        *CAKE_LOCK.get_or_init(|| Self {
713            code: Ustr::from("CAKE"),
714            precision: 8,
715            iso4217: 0,
716            name: Ustr::from("PancakeSwap"),
717            currency_type: CurrencyType::Crypto,
718        })
719    }
720
721    #[allow(non_snake_case)]
722    #[must_use]
723    pub fn CRV() -> Self {
724        *CRV_LOCK.get_or_init(|| Self {
725            code: Ustr::from("CRV"),
726            precision: 8,
727            iso4217: 0,
728            name: Ustr::from("Curve DAO Token"),
729            currency_type: CurrencyType::Crypto,
730        })
731    }
732
733    #[allow(non_snake_case)]
734    #[must_use]
735    pub fn DASH() -> Self {
736        *DASH_LOCK.get_or_init(|| Self {
737            code: Ustr::from("DASH"),
738            precision: 8,
739            iso4217: 0,
740            name: Ustr::from("Dash"),
741            currency_type: CurrencyType::Crypto,
742        })
743    }
744
745    #[allow(non_snake_case)]
746    #[must_use]
747    pub fn DOT() -> Self {
748        *DOT_LOCK.get_or_init(|| Self {
749            code: Ustr::from("DOT"),
750            precision: 8,
751            iso4217: 0,
752            name: Ustr::from("Polkadot"),
753            currency_type: CurrencyType::Crypto,
754        })
755    }
756
757    #[allow(non_snake_case)]
758    #[must_use]
759    pub fn DOGE() -> Self {
760        *DOGE_LOCK.get_or_init(|| Self {
761            code: Ustr::from("DOGE"),
762            precision: 8,
763            iso4217: 0,
764            name: Ustr::from("Dogecoin"),
765            currency_type: CurrencyType::Crypto,
766        })
767    }
768
769    #[allow(non_snake_case)]
770    #[must_use]
771    pub fn ENA() -> Self {
772        *ENA_LOCK.get_or_init(|| Self {
773            code: Ustr::from("ENA"),
774            precision: 8,
775            iso4217: 0,
776            name: Ustr::from("Ethena"),
777            currency_type: CurrencyType::Crypto,
778        })
779    }
780
781    #[allow(non_snake_case)]
782    #[must_use]
783    pub fn EOS() -> Self {
784        *EOS_LOCK.get_or_init(|| Self {
785            code: Ustr::from("EOS"),
786            precision: 8,
787            iso4217: 0,
788            name: Ustr::from("EOS"),
789            currency_type: CurrencyType::Crypto,
790        })
791    }
792
793    #[allow(non_snake_case)]
794    #[must_use]
795    pub fn ETH() -> Self {
796        *ETH_LOCK.get_or_init(|| Self {
797            code: Ustr::from("ETH"),
798            precision: 8,
799            iso4217: 0,
800            name: Ustr::from("Ethereum"),
801            currency_type: CurrencyType::Crypto,
802        })
803    }
804
805    #[allow(non_snake_case)]
806    #[must_use]
807    pub fn ETHW() -> Self {
808        *ETHW_LOCK.get_or_init(|| Self {
809            code: Ustr::from("ETHW"),
810            precision: 8,
811            iso4217: 0,
812            name: Ustr::from("EthereumPoW"),
813            currency_type: CurrencyType::Crypto,
814        })
815    }
816
817    #[allow(non_snake_case)]
818    #[must_use]
819    pub fn FDUSD() -> Self {
820        *FDUSD_LOCK.get_or_init(|| Self {
821            code: Ustr::from("FDUSD"),
822            precision: 8,
823            iso4217: 0,
824            name: Ustr::from("First Digital USD"),
825            currency_type: CurrencyType::Crypto,
826        })
827    }
828
829    #[allow(non_snake_case)]
830    #[must_use]
831    pub fn HYPE() -> Self {
832        *HYPE_LOCK.get_or_init(|| Self {
833            code: Ustr::from("HYPE"),
834            precision: 8,
835            iso4217: 0,
836            name: Ustr::from("Hyperliquid"),
837            currency_type: CurrencyType::Crypto,
838        })
839    }
840
841    #[allow(non_snake_case)]
842    #[must_use]
843    pub fn JOE() -> Self {
844        *JOE_LOCK.get_or_init(|| Self {
845            code: Ustr::from("JOE"),
846            precision: 8,
847            iso4217: 0,
848            name: Ustr::from("JOE"),
849            currency_type: CurrencyType::Crypto,
850        })
851    }
852
853    #[allow(non_snake_case)]
854    #[must_use]
855    pub fn LINK() -> Self {
856        *LINK_LOCK.get_or_init(|| Self {
857            code: Ustr::from("LINK"),
858            precision: 8,
859            iso4217: 0,
860            name: Ustr::from("Chainlink"),
861            currency_type: CurrencyType::Crypto,
862        })
863    }
864
865    #[allow(non_snake_case)]
866    #[must_use]
867    pub fn LTC() -> Self {
868        *LTC_LOCK.get_or_init(|| Self {
869            code: Ustr::from("LTC"),
870            precision: 8,
871            iso4217: 0,
872            name: Ustr::from("Litecoin"),
873            currency_type: CurrencyType::Crypto,
874        })
875    }
876
877    #[allow(non_snake_case)]
878    #[must_use]
879    pub fn LUNA() -> Self {
880        *LUNA_LOCK.get_or_init(|| Self {
881            code: Ustr::from("LUNA"),
882            precision: 8,
883            iso4217: 0,
884            name: Ustr::from("Terra"),
885            currency_type: CurrencyType::Crypto,
886        })
887    }
888
889    #[allow(non_snake_case)]
890    #[must_use]
891    pub fn NBT() -> Self {
892        *NBT_LOCK.get_or_init(|| Self {
893            code: Ustr::from("NBT"),
894            precision: 8,
895            iso4217: 0,
896            name: Ustr::from("NanoByte Token"),
897            currency_type: CurrencyType::Crypto,
898        })
899    }
900
901    #[allow(non_snake_case)]
902    #[must_use]
903    pub fn POL() -> Self {
904        *POL_LOCK.get_or_init(|| Self {
905            code: Ustr::from("POL"),
906            precision: 8,
907            iso4217: 0,
908            name: Ustr::from("Polygon"),
909            currency_type: CurrencyType::Crypto,
910        })
911    }
912
913    #[allow(non_snake_case)]
914    #[must_use]
915    pub fn PROVE() -> Self {
916        *PROVE_LOCK.get_or_init(|| Self {
917            code: Ustr::from("PROVE"),
918            precision: 8,
919            iso4217: 0,
920            name: Ustr::from("Prove AI"),
921            currency_type: CurrencyType::Crypto,
922        })
923    }
924
925    #[allow(non_snake_case)]
926    #[must_use]
927    pub fn SOL() -> Self {
928        *SOL_LOCK.get_or_init(|| Self {
929            code: Ustr::from("SOL"),
930            precision: 8,
931            iso4217: 0,
932            name: Ustr::from("Solana"),
933            currency_type: CurrencyType::Crypto,
934        })
935    }
936
937    #[allow(non_snake_case)]
938    #[must_use]
939    pub fn SHIB() -> Self {
940        *SHIB_LOCK.get_or_init(|| Self {
941            code: Ustr::from("SHIB"),
942            precision: 8,
943            iso4217: 0,
944            name: Ustr::from("Shiba Inu"),
945            currency_type: CurrencyType::Crypto,
946        })
947    }
948
949    #[allow(non_snake_case)]
950    #[must_use]
951    pub fn SUI() -> Self {
952        *SUI_LOCK.get_or_init(|| Self {
953            code: Ustr::from("SUI"),
954            precision: 8,
955            iso4217: 0,
956            name: Ustr::from("Sui"),
957            currency_type: CurrencyType::Crypto,
958        })
959    }
960
961    #[allow(non_snake_case)]
962    #[must_use]
963    pub fn TON() -> Self {
964        *TON_LOCK.get_or_init(|| Self {
965            code: Ustr::from("TON"),
966            precision: 8,
967            iso4217: 0,
968            name: Ustr::from("Toncoin"),
969            currency_type: CurrencyType::Crypto,
970        })
971    }
972
973    #[allow(non_snake_case)]
974    #[must_use]
975    pub fn TRX() -> Self {
976        *TRX_LOCK.get_or_init(|| Self {
977            code: Ustr::from("TRX"),
978            precision: 8,
979            iso4217: 0,
980            name: Ustr::from("TRON"),
981            currency_type: CurrencyType::Crypto,
982        })
983    }
984
985    #[allow(non_snake_case)]
986    #[must_use]
987    pub fn TRYB() -> Self {
988        *TRYB_LOCK.get_or_init(|| Self {
989            code: Ustr::from("TRYB"),
990            precision: 8,
991            iso4217: 0,
992            name: Ustr::from("BiLira"),
993            currency_type: CurrencyType::Crypto,
994        })
995    }
996
997    #[allow(non_snake_case)]
998    #[must_use]
999    pub fn TUSD() -> Self {
1000        *TUSD_LOCK.get_or_init(|| Self {
1001            code: Ustr::from("TUSD"),
1002            precision: 8,
1003            iso4217: 0,
1004            name: Ustr::from("TrueUSD"),
1005            currency_type: CurrencyType::Crypto,
1006        })
1007    }
1008
1009    #[allow(non_snake_case)]
1010    #[must_use]
1011    pub fn UNI() -> Self {
1012        *UNI_LOCK.get_or_init(|| Self {
1013            code: Ustr::from("UNI"),
1014            precision: 8,
1015            iso4217: 0,
1016            name: Ustr::from("Uniswap"),
1017            currency_type: CurrencyType::Crypto,
1018        })
1019    }
1020
1021    #[allow(non_snake_case)]
1022    #[must_use]
1023    pub fn VTC() -> Self {
1024        *VTC_LOCK.get_or_init(|| Self {
1025            code: Ustr::from("VTC"),
1026            precision: 8,
1027            iso4217: 0,
1028            name: Ustr::from("Vertcoin"),
1029            currency_type: CurrencyType::Crypto,
1030        })
1031    }
1032
1033    #[allow(non_snake_case)]
1034    #[must_use]
1035    pub fn WBTC() -> Self {
1036        *WBTC_LOCK.get_or_init(|| Self {
1037            code: Ustr::from("WBTC"),
1038            precision: 8,
1039            iso4217: 0,
1040            name: Ustr::from("Wrapped Bitcoin"),
1041            currency_type: CurrencyType::Crypto,
1042        })
1043    }
1044
1045    #[allow(non_snake_case)]
1046    #[must_use]
1047    pub fn WSB() -> Self {
1048        *WSB_LOCK.get_or_init(|| Self {
1049            code: Ustr::from("WSB"),
1050            precision: 8,
1051            iso4217: 0,
1052            name: Ustr::from("WallStreetBets DApp"),
1053            currency_type: CurrencyType::Crypto,
1054        })
1055    }
1056
1057    #[allow(non_snake_case)]
1058    #[must_use]
1059    pub fn XBT() -> Self {
1060        *XBT_LOCK.get_or_init(|| Self {
1061            code: Ustr::from("XBT"),
1062            precision: 8,
1063            iso4217: 0,
1064            name: Ustr::from("Bitcoin"),
1065            currency_type: CurrencyType::Crypto,
1066        })
1067    }
1068
1069    #[allow(non_snake_case)]
1070    #[must_use]
1071    pub fn XEC() -> Self {
1072        *XEC_LOCK.get_or_init(|| Self {
1073            code: Ustr::from("XEC"),
1074            precision: 8,
1075            iso4217: 0,
1076            name: Ustr::from("eCash"),
1077            currency_type: CurrencyType::Crypto,
1078        })
1079    }
1080
1081    #[allow(non_snake_case)]
1082    #[must_use]
1083    pub fn XLM() -> Self {
1084        *XLM_LOCK.get_or_init(|| Self {
1085            code: Ustr::from("XLM"),
1086            precision: 8,
1087            iso4217: 0,
1088            name: Ustr::from("Stellar Lumen"),
1089            currency_type: CurrencyType::Crypto,
1090        })
1091    }
1092
1093    #[allow(non_snake_case)]
1094    #[must_use]
1095    pub fn XMR() -> Self {
1096        *XMR_LOCK.get_or_init(|| Self {
1097            code: Ustr::from("XMR"),
1098            precision: 8,
1099            iso4217: 0,
1100            name: Ustr::from("Monero"),
1101            currency_type: CurrencyType::Crypto,
1102        })
1103    }
1104
1105    #[allow(non_snake_case)]
1106    #[must_use]
1107    pub fn USDT() -> Self {
1108        *USDT_LOCK.get_or_init(|| Self {
1109            code: Ustr::from("USDT"),
1110            precision: 8,
1111            iso4217: 0,
1112            name: Ustr::from("Tether"),
1113            currency_type: CurrencyType::Crypto,
1114        })
1115    }
1116
1117    #[allow(non_snake_case)]
1118    #[must_use]
1119    pub fn XRP() -> Self {
1120        *XRP_LOCK.get_or_init(|| Self {
1121            code: Ustr::from("XRP"),
1122            precision: 6,
1123            iso4217: 0,
1124            name: Ustr::from("XRP"),
1125            currency_type: CurrencyType::Crypto,
1126        })
1127    }
1128
1129    #[allow(non_snake_case)]
1130    #[must_use]
1131    pub fn XTZ() -> Self {
1132        *XTZ_LOCK.get_or_init(|| Self {
1133            code: Ustr::from("XTZ"),
1134            precision: 6,
1135            iso4217: 0,
1136            name: Ustr::from("Tezos"),
1137            currency_type: CurrencyType::Crypto,
1138        })
1139    }
1140
1141    #[must_use]
1142    #[allow(non_snake_case)]
1143    pub fn USDC() -> Self {
1144        *USDC_LOCK.get_or_init(|| Self {
1145            code: Ustr::from("USDC"),
1146            precision: 8,
1147            iso4217: 0,
1148            name: Ustr::from("USD Coin"),
1149            currency_type: CurrencyType::Crypto,
1150        })
1151    }
1152
1153    #[must_use]
1154    #[allow(non_snake_case)]
1155    pub fn USDC_POS() -> Self {
1156        *USDC_POS_LOCK.get_or_init(|| Self {
1157            code: Ustr::from("USDC.e"),
1158            precision: 6,
1159            iso4217: 0,
1160            name: Ustr::from("USD Coin (PoS)"),
1161            currency_type: CurrencyType::Crypto,
1162        })
1163    }
1164
1165    #[allow(non_snake_case)]
1166    #[must_use]
1167    pub fn USDP() -> Self {
1168        *USDP_LOCK.get_or_init(|| Self {
1169            code: Ustr::from("USDP"),
1170            precision: 8,
1171            iso4217: 0,
1172            name: Ustr::from("Pax Dollar"),
1173            currency_type: CurrencyType::Crypto,
1174        })
1175    }
1176
1177    #[allow(non_snake_case)]
1178    #[must_use]
1179    pub fn ZEC() -> Self {
1180        *ZEC_LOCK.get_or_init(|| Self {
1181            code: Ustr::from("ZEC"),
1182            precision: 8,
1183            iso4217: 0,
1184            name: Ustr::from("Zcash"),
1185            currency_type: CurrencyType::Crypto,
1186        })
1187    }
1188}
1189
1190/// A map of built-in `Currency` constants.
1191pub static CURRENCY_MAP: LazyLock<Mutex<HashMap<String, Currency>>> = LazyLock::new(|| {
1192    let mut map = HashMap::new();
1193    ///////////////////////////////////////////////////////////////////////////
1194    // Fiat currencies
1195    ///////////////////////////////////////////////////////////////////////////
1196    map.insert(Currency::AUD().code.to_string(), Currency::AUD());
1197    map.insert(Currency::BRL().code.to_string(), Currency::BRL());
1198    map.insert(Currency::CAD().code.to_string(), Currency::CAD());
1199    map.insert(Currency::CHF().code.to_string(), Currency::CHF());
1200    map.insert(Currency::CNY().code.to_string(), Currency::CNY());
1201    map.insert(Currency::CNH().code.to_string(), Currency::CNH());
1202    map.insert(Currency::CZK().code.to_string(), Currency::CZK());
1203    map.insert(Currency::DKK().code.to_string(), Currency::DKK());
1204    map.insert(Currency::EUR().code.to_string(), Currency::EUR());
1205    map.insert(Currency::GBP().code.to_string(), Currency::GBP());
1206    map.insert(Currency::HKD().code.to_string(), Currency::HKD());
1207    map.insert(Currency::HUF().code.to_string(), Currency::HUF());
1208    map.insert(Currency::ILS().code.to_string(), Currency::ILS());
1209    map.insert(Currency::INR().code.to_string(), Currency::INR());
1210    map.insert(Currency::JPY().code.to_string(), Currency::JPY());
1211    map.insert(Currency::KRW().code.to_string(), Currency::KRW());
1212    map.insert(Currency::MXN().code.to_string(), Currency::MXN());
1213    map.insert(Currency::NOK().code.to_string(), Currency::NOK());
1214    map.insert(Currency::NZD().code.to_string(), Currency::NZD());
1215    map.insert(Currency::PLN().code.to_string(), Currency::PLN());
1216    map.insert(Currency::RUB().code.to_string(), Currency::RUB());
1217    map.insert(Currency::SAR().code.to_string(), Currency::SAR());
1218    map.insert(Currency::SEK().code.to_string(), Currency::SEK());
1219    map.insert(Currency::SGD().code.to_string(), Currency::SGD());
1220    map.insert(Currency::THB().code.to_string(), Currency::THB());
1221    map.insert(Currency::TRY().code.to_string(), Currency::TRY());
1222    map.insert(Currency::USD().code.to_string(), Currency::USD());
1223    map.insert(Currency::XAG().code.to_string(), Currency::XAG());
1224    map.insert(Currency::XAU().code.to_string(), Currency::XAU());
1225    map.insert(Currency::XPT().code.to_string(), Currency::XPT());
1226    map.insert(Currency::ZAR().code.to_string(), Currency::ZAR());
1227    ///////////////////////////////////////////////////////////////////////////
1228    // Crypto currencies
1229    ///////////////////////////////////////////////////////////////////////////
1230    map.insert(Currency::AAVE().code.to_string(), Currency::AAVE());
1231    map.insert(Currency::ACA().code.to_string(), Currency::ACA());
1232    map.insert(Currency::ADA().code.to_string(), Currency::ADA());
1233    map.insert(Currency::APT().code.to_string(), Currency::APT());
1234    map.insert(Currency::ARB().code.to_string(), Currency::ARB());
1235    map.insert(Currency::AVAX().code.to_string(), Currency::AVAX());
1236    map.insert(Currency::BCH().code.to_string(), Currency::BCH());
1237    map.insert(Currency::BIO().code.to_string(), Currency::BIO());
1238    map.insert(Currency::BTC().code.to_string(), Currency::BTC());
1239    map.insert(Currency::BTTC().code.to_string(), Currency::BTTC());
1240    map.insert(Currency::BNB().code.to_string(), Currency::BNB());
1241    map.insert(Currency::BRZ().code.to_string(), Currency::BRZ());
1242    map.insert(Currency::BSV().code.to_string(), Currency::BSV());
1243    map.insert(Currency::BUSD().code.to_string(), Currency::BUSD());
1244    map.insert(Currency::CRV().code.to_string(), Currency::CRV());
1245    map.insert(Currency::DASH().code.to_string(), Currency::DASH());
1246    map.insert(Currency::DOGE().code.to_string(), Currency::DOGE());
1247    map.insert(Currency::DOT().code.to_string(), Currency::DOT());
1248    map.insert(Currency::ENA().code.to_string(), Currency::ENA());
1249    map.insert(Currency::EOS().code.to_string(), Currency::EOS());
1250    map.insert(Currency::ETH().code.to_string(), Currency::ETH());
1251    map.insert(Currency::ETHW().code.to_string(), Currency::ETHW());
1252    map.insert(Currency::FDUSD().code.to_string(), Currency::FDUSD());
1253    map.insert(Currency::HYPE().code.to_string(), Currency::HYPE());
1254    map.insert(Currency::JOE().code.to_string(), Currency::JOE());
1255    map.insert(Currency::LINK().code.to_string(), Currency::LINK());
1256    map.insert(Currency::LTC().code.to_string(), Currency::LTC());
1257    map.insert(Currency::LUNA().code.to_string(), Currency::LUNA());
1258    map.insert(Currency::NBT().code.to_string(), Currency::NBT());
1259    map.insert(Currency::POL().code.to_string(), Currency::POL());
1260    map.insert(Currency::PROVE().code.to_string(), Currency::PROVE());
1261    map.insert(Currency::SOL().code.to_string(), Currency::SOL());
1262    map.insert(Currency::SUI().code.to_string(), Currency::SUI());
1263    map.insert(Currency::TON().code.to_string(), Currency::TON());
1264    map.insert(Currency::TRX().code.to_string(), Currency::TRX());
1265    map.insert(Currency::TRYB().code.to_string(), Currency::TRYB());
1266    map.insert(Currency::TUSD().code.to_string(), Currency::TUSD());
1267    map.insert(Currency::UNI().code.to_string(), Currency::UNI());
1268    map.insert(Currency::VTC().code.to_string(), Currency::VTC());
1269    map.insert(Currency::WBTC().code.to_string(), Currency::WBTC());
1270    map.insert(Currency::WSB().code.to_string(), Currency::WSB());
1271    map.insert(Currency::XBT().code.to_string(), Currency::XBT());
1272    map.insert(Currency::XEC().code.to_string(), Currency::XEC());
1273    map.insert(Currency::XLM().code.to_string(), Currency::XLM());
1274    map.insert(Currency::XMR().code.to_string(), Currency::XMR());
1275    map.insert(Currency::XRP().code.to_string(), Currency::XRP());
1276    map.insert(Currency::XTZ().code.to_string(), Currency::XTZ());
1277    map.insert(Currency::USDC().code.to_string(), Currency::USDC());
1278    map.insert(Currency::USDC_POS().code.to_string(), Currency::USDC_POS());
1279    map.insert(Currency::USDP().code.to_string(), Currency::USDP());
1280    map.insert(Currency::USDT().code.to_string(), Currency::USDT());
1281    map.insert(Currency::ZEC().code.to_string(), Currency::ZEC());
1282    Mutex::new(map)
1283});