Files
hash-wallet/cw_core/lib/crypto_currency.dart
T
75f3fe735b Introduce Money class and refactor currency handling (#3157)
* feat: add `Money` class for precise currency handling and amount parsing

- Introduced `Money` class for handling money values with fixed-point precision.
- Added parsing and comparison methods to `CryptoCurrency` and `FiatCurrency` interfaces.
- Implemented `smartAmountSanitizer` for format normalization.

Includes extensive unit tests for validation.

* refactor: optimize Money class with new factories and string formatting improvements

* refactor: unify balance handling with `Money` refactor

* refactor: update `ElectrumBalance` and transaction logic to use `Money` for currency precision

* refactor: standardize balance handling with `Money` across `Monero`, `Wownero`, and `Zano` wallets

* refactor: migrate EVM balance and transaction handling to `Money` for consistent currency precision

* refactor: migrate Decred balance and transaction handling to `Money` for consistent currency precision

* refactor: migrate nano balance and transaction handling to `Money` for consistent currency precision

* refactor: migrate Solana balance and transaction logic to `Money` for precise currency handling

* refactor: migrate Tron balance and transaction handling to `Money` for consistent currency precision

* refactor: migrate Zcash balance and transaction handling to `Money` for consistent currency precision

* refactor: adjust lib to handle money

* refactor: remove legacy Decred amount formatting and migrate to `Money`

* refactor: migrate pending transaction amount and fee to `Money`

* refactor: migrate dEuro savings and transaction logic to `Money` for improved precision and consistency

* refactor: migrate Bitcoin and lightning transaction logic to `Money` for consistent currency precision

* refactor: migrate Wownero, EVM, Zano, and Zcash transaction logic to `Money` for consistent and precise currency handling

* refactor: standardize balance handling across wallets, migrate to `Money.zero` and refine `Balance` class for consistency

* refactor: migrate Solana transaction and wallet logic to `Money` for consistent and precise currency handling

* refactor: improve fiat balance and formatting for consistency on dashboard

* fix: fiat input mode switching and standardize crypto amount display logic

* fix: cw_evm generator

* refactor: migrate exchange amount handling to `Money` for improved precision and consistency

* test: remove redundant and commented-out tests, tidy test cases, and apply minor formatting adjustments

* fix using Money wrapper in BridgeViewModel and USDT0Service

* refactor: streamline `AmountConverter` and `LightningWallet`, add `cw_core` tests to GitHub workflow, and remove unused/deprecated logic

* refactor: enhance `changeReceiveAmount` with `isCanonical` support, improve null handling, and refine amount parsing logic

* minor fix

* try/catch the lightning log file error

* feat: add copy-to-clipboard functionality for transaction amounts, fix typo in trailing widget method name (#3219)

* Cw 1234 disallow sp and mweb addresses as refund for swaps (#3187)

* disallow SP and MWEB for swaps

* Simplify address selection in addressForExchange

Refactor addressForExchange method to simplify address selection logic.

* validate refund and receive address types

* localize address validation messages

* minor ui fix [skip ci]

* minor fix [skip ci]

* Revert "localize address validation messages"

* fix translations

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>

* refactor: replace manual amount sanitization with `sanitized()` extension across the codebase, add unit tests for `AmountSanitizer`

* fix: correct `sanitized()` test expectations for decimal handling in `amount_sanitizer_test.dart`

* refactor: fee display logic and append currency symbol in `send_confirm_sheet.dart`

* refactor: simplify `ZcashBalance` class by replacing custom fields with inherited properties, update references accordingly

* refactor: replace hardcoded USDT contract address with `DefaultTronTokens` lookup, improve maintainability

* refactor: replace `currency` with `inputAmount.currency` in Solana transaction signing methods to avoid inconsistency

* fix: handle null `fee` in `electrum_transaction_info.dart` to prevent potential runtime errors

* refactor: replace raw fee and amount handling with `Money` object for improved consistency and maintainability

* fix: limit fiat balance display to 2 decimal places in `balance_view_model.dart`

* refactor: replace raw `amount` and `fee` types with `Money` in Solana transaction methods for consistency and precision

* refactor: replace raw `amount` and `fee` handling with `Money` and improve balance calculation consistency across view models

* refactor: replace raw balance strings with `Money` and simplify `UnconfirmedBalanceModal` widget logic

* refactor: replace `print` with `printV` for better logging, add equality and hashCode overrides to `ERC20Currency` for object comparison

* feat: prepare deuro savings migration

* feat: add V1 savings migration support and improve formatting consistency in DEuro view model

* feat: add V1 savings withdrawal support and update associated UI components and logic

* refactor: replace `Image.asset` with `CakeImageWidget`, update balance string handling, and streamline address validation logic

* refactor: use `Money.tryParse` with fallback to `Money.zero` in `NanoBalance.fromRawString` for safer balance parsing

* refactor: replace `ERC20Currency` with `Erc20Token` for consistency and remove unused `evm_erc20_currency.dart` file

* refactor: add computed `hasDepositAmount` for deposit null-checks, optimize balance handling in `zano_wallet`, update Breez SDK to v0.14.0, and implement equality/hashCode for `Currency`

* refactor: rename `amountSats` to `amount` in `PrepareLnurlPayRequest` for consistency

* revert: downgrade Breez SDK to v0.11.0 in `pubspec.yaml` and update relevant references in `pubspec.lock`

* fix: use `cryptoAmount.copyWith` for currency consistency and replace `Image.asset` with `CakeImageWidget` in swap address modal

* fix: ensure currency consistency by using `cryptoAmount.copyWith` in Solana and EVM wallet transactions

* refactor: simplify CSV row generation logic by removing `_splitAmountCurrency` and streamlining amount/fee handling

* fix: LateInitializationError Field 'sdk' has not been initialized

* fix: use `Money.tryParse` for safer parsing of deposit and receive amounts

* chore: remove debug print statement

* refactor: update transaction processing to consistently use `Money` for amounts and fees

* refactor: improve currency and amount handling, simplify logic, and enhance code readability in Send and Swap pages

* refactor: integrate `DecimalInputFormatter` for consistent decimal input across Send and Swap pages, simplify input handling logic

* fix: "fiatMode" per output on sendPage

* refactor: make transaction_details_height applicable more readable

* fix: use correct base unit for deposit

* refactor: use Money in estimateFakeSendAllTxAmount method

* fix decred frozen balance
minor fixes

* fix decred frozen balance
minor fixes

* fix: automatically switch to lightning if lnurl or invoice detected

* fix: getBolt11Amount test cases

* fix: standardise crypto amount formatting and display

* fix: use base unit for Tron transaction fee parsing
* refactor: hardcode fractional digits to 8 in `AmountParsingProxy` display methods
* refactor: ensure consistent 8-decimal precision for fee formatting in `PendingTransaction`
* fix: use `AmountParsingProxy` for available balance display in exchange view model
* fix: improve amount formatting and layout in swap and send confirmation sheets
* chore: remove redundant decimal truncation in balance view model and send confirmation sheet

* fix: allow for editing text field if it is filled with "ALL"

* fix: allow for editing text field if it is filled with "ALL"

* fix: update currency detection logic for lightning mode

* avoid potential infinite loop [skip ci]

* fix: getDisplayCryptoAmount

* fix: update estimated fee calculation

* chore: simplify fee calculation logic [skip-ci]

* fix value display in hidden mode

* fix stale state in send confirm sheet

* fix decimals for mweb

* fix available balance display for sol/trx on swap

* restore proper hint text

* fix swap receive amount calculation for xno

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
Co-authored-by: Serhii <17529954+serhii-bor@users.noreply.github.com>
Co-authored-by: Robert Malikowski <malikowskirobert@gmail.com>
2026-06-30 02:45:44 +03:00

457 lines
29 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'package:cw_core/amount/money.dart';
import 'package:cw_core/currency.dart';
import 'package:cw_core/currency_groups.dart';
import 'package:cw_core/enumerable_item.dart';
import 'package:collection/collection.dart';
import 'package:cw_core/format_fixed.dart';
class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implements Currency {
const CryptoCurrency({
String title = '',
int raw = -1,
required this.name,
required this.decimals,
this.fullName,
this.iconPath,
this.flatIconPath,
this.tag,
this.chainIconPath,
this.enabled = false,
this.isPotentialScam = false,
this.groups = const {},
}) : super(title: title, raw: raw);
final String? flatIconPath;
final String? chainIconPath;
final bool enabled;
final bool isPotentialScam;
final Set<String> groups;
@override
final String name;
@override
final String? fullName;
@override
final String? tag;
@override
final String? iconPath;
@override
final int decimals;
@override
String get symbol => title;
set enabled(bool value) => this.enabled = value;
static const all = [
CryptoCurrency.xmr,
CryptoCurrency.btc,
CryptoCurrency.btcln,
CryptoCurrency.eth,
CryptoCurrency.ltc,
CryptoCurrency.doge,
CryptoCurrency.usdterc20,
CryptoCurrency.usdtbsc,
CryptoCurrency.usdttrc20,
CryptoCurrency.usdc,
CryptoCurrency.deuro,
CryptoCurrency.maticpoly,
CryptoCurrency.sol,
CryptoCurrency.trx,
CryptoCurrency.bch,
CryptoCurrency.ada,
CryptoCurrency.bnb,
CryptoCurrency.dai,
CryptoCurrency.dash,
CryptoCurrency.eos,
CryptoCurrency.nano,
CryptoCurrency.xlm,
CryptoCurrency.xrp,
CryptoCurrency.xhv,
CryptoCurrency.ape,
CryptoCurrency.avaxc,
CryptoCurrency.btt,
CryptoCurrency.bttc,
CryptoCurrency.firo,
CryptoCurrency.usdt,
CryptoCurrency.hbar,
CryptoCurrency.sc,
CryptoCurrency.usdcsol,
CryptoCurrency.zec,
CryptoCurrency.zen,
CryptoCurrency.xvg,
CryptoCurrency.usdcpoly,
CryptoCurrency.dcr,
CryptoCurrency.kmd,
CryptoCurrency.mana,
CryptoCurrency.matic,
CryptoCurrency.mkr,
CryptoCurrency.near,
CryptoCurrency.oxt,
CryptoCurrency.paxg,
CryptoCurrency.pivx,
CryptoCurrency.rune,
CryptoCurrency.rvn,
CryptoCurrency.scrt,
CryptoCurrency.uni,
CryptoCurrency.stx,
CryptoCurrency.shib,
CryptoCurrency.aave,
CryptoCurrency.arb,
CryptoCurrency.bat,
CryptoCurrency.comp,
CryptoCurrency.cro,
CryptoCurrency.ens,
CryptoCurrency.ftm,
CryptoCurrency.frax,
CryptoCurrency.gusd,
CryptoCurrency.gtc,
CryptoCurrency.grt,
CryptoCurrency.ldo,
CryptoCurrency.nexo,
CryptoCurrency.cake,
CryptoCurrency.pepe,
CryptoCurrency.storj,
CryptoCurrency.tusd,
CryptoCurrency.wbtc,
CryptoCurrency.weth,
CryptoCurrency.zrx,
CryptoCurrency.dydx,
CryptoCurrency.steth,
CryptoCurrency.banano,
CryptoCurrency.usdtPoly,
CryptoCurrency.usdcEPoly,
CryptoCurrency.kaspa,
CryptoCurrency.digibyte,
CryptoCurrency.usdtSol,
CryptoCurrency.usdcTrc20,
CryptoCurrency.tbtc,
CryptoCurrency.wow,
CryptoCurrency.zano,
CryptoCurrency.ton,
CryptoCurrency.flip,
CryptoCurrency.ndeps,
CryptoCurrency.deps,
CryptoCurrency.baseEth,
CryptoCurrency.usde,
CryptoCurrency.arbEth,
CryptoCurrency.usdcArb,
CryptoCurrency.usdtArb,
];
static const havenCurrencies = [
xag,
xau,
xaud,
xbtc,
xcad,
xchf,
xcny,
xeur,
xgbp,
xjpy,
xnok,
xnzd,
xusd,
];
// well technically not currencies but since we had them a long time ago and don't want to break
// the app for users who had contacts saved for them
static const zcashCurrencies = [ zec, zaddr, tzec ];
// title, tag (if applicable), fullName (if unique), raw, name, iconPath
static const xmr = CryptoCurrency(title: 'XMR', fullName: 'Monero', raw: 0, name: 'xmr', iconPath: 'assets/new-ui/crypto_full_icons/monero.svg', decimals: 12, flatIconPath: "assets/new-ui/balance_card_icons/monero.svg");
static const ada = CryptoCurrency(title: 'ADA', fullName: 'Cardano', raw: 1, name: 'ada', iconPath: 'assets/images/ada_icon.png', decimals: 6);
static const bch = CryptoCurrency(title: 'BCH', fullName: 'Bitcoin Cash', raw: 2, name: 'bch', iconPath: 'assets/new-ui/crypto_full_icons/bitcoin-cash.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/bitcoin_cash.svg");
static const bnb = CryptoCurrency(title: 'BNB', tag: 'BSC', fullName: 'BNB', raw: 3, name: 'bnb', iconPath: 'assets/new-ui/crypto_full_icons/bnb.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/bnb.svg", chainIconPath: "assets/new-ui/chain_badges/bnb.svg");
static const btc = CryptoCurrency(title: 'BTC', fullName: 'Bitcoin', raw: 4, name: 'btc', iconPath: 'assets/new-ui/crypto_full_icons/bitcoin.svg' ,decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/bitcoin.svg");
static const dai = CryptoCurrency(title: 'DAI', tag: 'ETH', fullName: 'Dai', raw: 5, name: 'dai', iconPath: 'assets/new-ui/crypto_full_icons/dai.svg', decimals: 18, groups: const {CurrencyGroups.stablecoin});
static const dash = CryptoCurrency(title: 'DASH', fullName: 'Dash', raw: 6, name: 'dash', iconPath: 'assets/images/dash_icon.png', decimals: 8);
static const eos = CryptoCurrency(title: 'EOS', fullName: 'EOS', raw: 7, name: 'eos', iconPath: 'assets/images/eos_icon.png', decimals: 4);
static const eth = CryptoCurrency(title: 'ETH', fullName: 'Ethereum', raw: 8, name: 'eth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/ethereum.svg", chainIconPath: "assets/new-ui/chain_badges/ethereum.svg");
static const ltc = CryptoCurrency(title: 'LTC', fullName: 'Litecoin', raw: 9, name: 'ltc', iconPath: 'assets/new-ui/crypto_full_icons/litecoin.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/litecoin.svg", chainIconPath: "assets/new-ui/chain_badges/mweb.svg");
static const nano = CryptoCurrency(title: 'XNO', fullName: 'Nano', raw: 10, name: 'xno', iconPath: 'assets/new-ui/crypto_full_icons/nano.svg', decimals: 30, flatIconPath: "assets/new-ui/balance_card_icons/nano.svg");
static const trx = CryptoCurrency(title: 'TRX', fullName: 'TRON', raw: 11, name: 'trx', iconPath: 'assets/new-ui/crypto_full_icons/tron.svg', decimals: 6, flatIconPath: "assets/new-ui/balance_card_icons/tron.svg", chainIconPath: "assets/new-ui/chain_badges/tron.svg");
static const usdt = CryptoCurrency(title: 'USDT', tag: 'OMNI', fullName: 'Tether', raw: 12, name: 'usdt', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
static const usdterc20 = CryptoCurrency(title: 'USDT', tag: 'ETH', fullName: 'Tether', raw: 13, name: 'usdterc20', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
static const xlm = CryptoCurrency(title: 'XLM', fullName: 'Stellar', raw: 14, name: 'xlm', iconPath: 'assets/images/xlm_icon.png', decimals: 7);
static const xrp = CryptoCurrency(title: 'XRP', fullName: 'Ripple', raw: 15, name: 'xrp', iconPath: 'assets/images/xrp_icon.png', decimals: 6);
static const xhv = CryptoCurrency(title: 'XHV', fullName: 'Haven Protocol', raw: 16, name: 'xhv', iconPath: 'assets/images/xhv_logo.png', decimals: 12);
static const xag = CryptoCurrency(title: 'XAG', tag: 'XHV', raw: 17, name: 'xag', decimals: 12);
static const xau = CryptoCurrency(title: 'XAU', tag: 'XHV', raw: 18, name: 'xau', decimals: 12);
static const xaud = CryptoCurrency(title: 'XAUD', tag: 'XHV', raw: 19, name: 'xaud', decimals: 12);
static const xbtc = CryptoCurrency(title: 'XBTC', tag: 'XHV', raw: 20, name: 'xbtc', decimals: 12);
static const xcad = CryptoCurrency(title: 'XCAD', tag: 'XHV', raw: 21, name: 'xcad', decimals: 12);
static const xchf = CryptoCurrency(title: 'XCHF', tag: 'XHV', raw: 22, name: 'xchf', decimals: 12);
static const xcny = CryptoCurrency(title: 'XCNY', tag: 'XHV', raw: 23, name: 'xcny', decimals: 12);
static const xeur = CryptoCurrency(title: 'XEUR', tag: 'XHV', raw: 24, name: 'xeur', decimals: 12);
static const xgbp = CryptoCurrency(title: 'XGBP', tag: 'XHV', raw: 25, name: 'xgbp', decimals: 12);
static const xjpy = CryptoCurrency(title: 'XJPY', tag: 'XHV', raw: 26, name: 'xjpy', decimals: 12);
static const xnok = CryptoCurrency(title: 'XNOK', tag: 'XHV', raw: 27, name: 'xnok', decimals: 12);
static const xnzd = CryptoCurrency(title: 'XNZD', tag: 'XHV', raw: 28, name: 'xnzd', decimals: 12);
static const xusd = CryptoCurrency(title: 'XUSD', tag: 'XHV', raw: 29, name: 'xusd', decimals: 12);
static const ape = CryptoCurrency(title: 'APE', tag: 'ETH', fullName: 'ApeCoin', raw: 30, name: 'ape', iconPath: 'assets/images/ape_icon.png', decimals: 18);
static const avaxc = CryptoCurrency(title: 'AVAX', tag: 'AVAXC', fullName: 'Avalanche', raw: 31, name: 'avaxc', iconPath: 'assets/new-ui/crypto_full_icons/avax.svg', decimals: 9);
static const btt = CryptoCurrency(title: 'BTT', tag: 'ETH', fullName: 'BitTorrent', raw: 32, name: 'btt', iconPath: 'assets/images/btt_icon.png', decimals: 18);
static const bttc = CryptoCurrency(title: 'BTTC', tag: 'TRX', fullName: 'BitTorrent-NEW', raw: 33, name: 'bttc', iconPath: 'assets/images/btt_icon.png', decimals: 18);
static const doge = CryptoCurrency(title: 'DOGE', fullName: 'Dogecoin', raw: 34, name: 'doge', iconPath: 'assets/new-ui/crypto_full_icons/dogecoin.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/dogecoin.svg");
static const firo = CryptoCurrency(title: 'FIRO', raw: 35, name: 'firo', iconPath: 'assets/images/firo_icon.png', decimals: 8);
static const usdttrc20 = CryptoCurrency(title: 'USDT', tag: 'TRX', fullName: 'Tether', raw: 36, name: 'usdttrc20', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
static const hbar = CryptoCurrency(title: 'HBAR', fullName: 'Hedera', raw: 37, name: 'hbar', iconPath: 'assets/images/hbar_icon.png', decimals: 8);
static const sc = CryptoCurrency(title: 'SC', fullName: 'Siacoin', raw: 38, name: 'sc', iconPath: 'assets/images/sc_icon.png', decimals: 16);
static const sol = CryptoCurrency(title: 'SOL', fullName: 'Solana', raw: 39, name: 'sol', iconPath: 'assets/new-ui/crypto_full_icons/solana.svg', decimals: 9, flatIconPath: "assets/new-ui/balance_card_icons/solana.svg", chainIconPath: "assets/new-ui/chain_badges/solana.svg");
static const usdc = CryptoCurrency(title: 'USDC', tag: 'ETH', fullName: 'USDC', raw: 40, name: 'usdc', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
static const usdcsol = CryptoCurrency(title: 'USDC', tag: 'SOL', fullName: 'USDC Coin', raw: 41, name: 'usdcsol', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
static const zaddr = CryptoCurrency(title: 'ZZEC', tag: 'ZEC', fullName: 'Shielded Zcash', raw: 42, name: 'zaddr', iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg', decimals: 8);
static const tzec = CryptoCurrency(title: 'tZEC', tag: 'ZEC', fullName: 'Transparent Zcash', raw: 43, name: 'zec', iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg', decimals: 8);
static const zen = CryptoCurrency(title: 'ZEN', fullName: 'Horizen', raw: 44, name: 'zen', iconPath: 'assets/images/zen_icon.png', decimals: 8);
static const xvg = CryptoCurrency(title: 'XVG', fullName: 'Verge', raw: 45, name: 'xvg', iconPath: 'assets/images/xvg_icon.png', decimals: 8);
static const usdcpoly = CryptoCurrency(title: 'USDC', tag: 'POL', fullName: 'USDC', raw: 46, name: 'usdcpoly', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
static const dcr = CryptoCurrency(title: 'DCR', fullName: 'Decred', raw: 47, name: 'dcr', iconPath: 'assets/new-ui/crypto_full_icons/decred.svg', decimals: 8, flatIconPath: "assets/new-ui/balance_card_icons/decred.svg");
static const kmd = CryptoCurrency(title: 'KMD', fullName: 'Komodo', raw: 48, name: 'kmd', iconPath: 'assets/images/kmd_icon.png', decimals: 8);
static const mana = CryptoCurrency(title: 'MANA', tag: 'ETH', fullName: 'Decentraland', raw: 49, name: 'mana', iconPath: 'assets/images/mana_icon.png', decimals: 18);
static const maticpoly = CryptoCurrency(title: 'POL', tag: 'POL', fullName: 'Polygon', raw: 50, name: 'maticpoly', iconPath: 'assets/new-ui/crypto_full_icons/polygon.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/polygon.svg", chainIconPath: "assets/new-ui/chain_badges/polygon.svg");
static const matic = CryptoCurrency(title: 'MATIC', tag: 'ETH', fullName: 'Polygon', raw: 51, name: 'matic', iconPath: 'assets/new-ui/crypto_full_icons/polygon.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/polygon.svg");
static const mkr = CryptoCurrency(title: 'MKR', tag: 'ETH', fullName: 'Maker', raw: 52, name: 'mkr', iconPath: 'assets/images/mkr_icon.png', decimals: 18);
static const near = CryptoCurrency(title: 'NEAR', fullName: 'NEAR Protocol', raw: 53, name: 'near', iconPath: 'assets/images/near_icon.png', decimals: 24);
static const oxt = CryptoCurrency(title: 'OXT', tag: 'ETH', fullName: 'Orchid', raw: 54, name: 'oxt', iconPath: 'assets/images/oxt_icon.png', decimals: 18);
static const paxg = CryptoCurrency(title: 'PAXG', tag: 'ETH', fullName: 'Pax Gold', raw: 55, name: 'paxg', iconPath: 'assets/new-ui/crypto_full_icons/paxg.svg', decimals: 18);
static const pivx = CryptoCurrency(title: 'PIVX', raw: 56, name: 'pivx', iconPath: 'assets/images/pivx_icon.png', decimals: 8);
static const rune = CryptoCurrency(title: 'RUNE', fullName: 'Thorchain', raw: 57, name: 'rune', iconPath: 'assets/images/rune_icon.png', decimals: 18);
static const rvn = CryptoCurrency(title: 'RVN', fullName: 'Ravencoin', raw: 58, name: 'rvn', iconPath: 'assets/images/rvn_icon.png', decimals: 8);
static const scrt = CryptoCurrency(title: 'SCRT', fullName: 'Secret Network', raw: 59, name: 'scrt', iconPath: 'assets/images/scrt_icon.png', decimals: 6);
static const uni = CryptoCurrency(title: 'UNI', tag: 'ETH', fullName: 'Uniswap', raw: 60, name: 'uni', iconPath: 'assets/images/uni_icon.png', decimals: 18);
static const stx = CryptoCurrency(title: 'STX', fullName: 'Stacks', raw: 61, name: 'stx', iconPath: 'assets/images/stx_icon.png', decimals: 8);
static const btcln = CryptoCurrency(title: 'BTC', tag: 'LN', fullName: 'Bitcoin Lightning Network', raw: 62, name: 'btcln', iconPath: 'assets/new-ui/crypto_full_icons/lightning.svg', chainIconPath: "assets/new-ui/chain_badges/lightning.svg", decimals: 8);
static const shib = CryptoCurrency(title: 'SHIB', tag: 'ETH', fullName: 'Shiba Inu', raw: 63, name: 'shib', iconPath: 'assets/images/shib_icon.png', decimals: 18);
static const aave = CryptoCurrency(title: 'AAVE', tag: 'ETH', fullName: 'Aave', raw: 64, name: 'aave', iconPath: 'assets/images/aave_icon.png', decimals: 18);
static const arb = CryptoCurrency(title: 'ARB', fullName: 'Arbitrum', raw: 65, name: 'arb', iconPath: 'assets/new-ui/crypto_full_icons/arbitrum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/arbitrum.svg", chainIconPath: "assets/new-ui/chain_badges/arbitrum.svg");
static const bat = CryptoCurrency(title: 'BAT', tag: 'ETH', fullName: 'Basic Attention Token', raw: 66, name: 'bat', iconPath: 'assets/images/bat_icon.png', decimals: 18);
static const comp = CryptoCurrency(title: 'COMP', tag: 'ETH', fullName: 'Compound', raw: 67, name: 'comp', iconPath: 'assets/images/comp_icon.png', decimals: 18);
static const cro = CryptoCurrency(title: 'CRO', tag: 'ETH', fullName: 'Crypto.com Cronos', raw: 68, name: 'cro', iconPath: 'assets/images/cro_icon.png', decimals: 8);
static const ens = CryptoCurrency(title: 'ENS', tag: 'ETH', fullName: 'Ethereum Name Service', raw: 69, name: 'ens', iconPath: 'assets/images/ens_icon.png', decimals: 18);
static const ftm = CryptoCurrency(title: 'FTM', tag: 'ETH', fullName: 'Fantom', raw: 70, name: 'ftm', iconPath: 'assets/images/ftm_icon.png', decimals: 18);
static const frax = CryptoCurrency(title: 'FRAX', tag: 'ETH', fullName: 'Frax', raw: 71, name: 'frax', iconPath: 'assets/images/frax_icon.png', decimals: 18);
static const gusd = CryptoCurrency(title: 'GUSD', tag: 'ETH', fullName: 'Gemini USD', raw: 72, name: 'gusd', iconPath: 'assets/images/gusd_icon.png', decimals: 2);
static const gtc = CryptoCurrency(title: 'GTC', tag: 'ETH', fullName: 'Gitcoin', raw: 73, name: 'gtc', iconPath: 'assets/images/gtc_icon.png', decimals: 18);
static const grt = CryptoCurrency(title: 'GRT', tag: 'ETH', fullName: 'The Graph', raw: 74, name: 'grt', iconPath: 'assets/images/grt_icon.png', decimals: 18);
static const ldo = CryptoCurrency(title: 'LDO', tag: 'ETH', fullName: 'Lido DAO', raw: 75, name: 'ldo', iconPath: 'assets/images/ldo_icon.png', decimals: 18);
static const nexo = CryptoCurrency(title: 'NEXO', tag: 'ETH', fullName: 'Nexo', raw: 76, name: 'nexo', iconPath: 'assets/images/nexo_icon.png', decimals: 18);
static const cake = CryptoCurrency(title: 'CAKE', tag: 'BSC', fullName: 'PancakeSwap', raw: 77, name: 'cake', iconPath: 'assets/images/cake_icon.png', decimals: 18);
static const pepe = CryptoCurrency(title: 'PEPE', tag: 'ETH', fullName: 'Pepe', raw: 78, name: 'pepe', iconPath: 'assets/images/pepe_icon.png', decimals: 18);
static const storj = CryptoCurrency(title: 'STORJ', tag: 'ETH', fullName: 'Storj', raw: 79, name: 'storj', iconPath: 'assets/images/storj_icon.png', decimals: 8);
static const tusd = CryptoCurrency(title: 'TUSD', tag: 'ETH', fullName: 'TrueUSD', raw: 80, name: 'tusd', iconPath: 'assets/images/tusd_icon.png', decimals: 18);
static const wbtc = CryptoCurrency(title: 'WBTC', tag: 'ETH', fullName: 'Wrapped Bitcoin', raw: 81, name: 'wbtc', iconPath: 'assets/new-ui/crypto_full_icons/wbtc.svg', decimals: 8);
static const weth = CryptoCurrency(title: 'WETH', tag: 'ETH', fullName: 'Wrapped Ethereum', raw: 82, name: 'weth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18);
static const zrx = CryptoCurrency(title: 'ZRX', tag: 'ETH', fullName: '0x Protocol', raw: 83, name: 'zrx', iconPath: 'assets/images/zrx_icon.png', decimals: 18);
static const dydx = CryptoCurrency(title: 'DYDX', tag: 'ETH', fullName: 'dYdX', raw: 84, name: 'dydx', iconPath: 'assets/images/dydx_icon.png', decimals: 18);
static const steth = CryptoCurrency(title: 'STETH', tag: 'ETH', fullName: 'Lido Staked Ethereum', raw: 85, name: 'steth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18);
static const banano = CryptoCurrency(title: 'BAN', fullName: 'Banano', raw: 86, name: 'banano', iconPath: 'assets/images/nano_icon.png', decimals: 29,flatIconPath: "assets/new-ui/balance_card_icons/nano.svg");
static const usdtPoly = CryptoCurrency(title: 'USDT', tag: 'POL', fullName: 'Tether (PoS)', raw: 87, name: 'usdtpoly', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
static const usdcEPoly = CryptoCurrency(title: 'USDC.E', tag: 'POL', fullName: 'USDC (PoS)', raw: 88, name: 'usdcepoly', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6);
static const kaspa = CryptoCurrency(title: 'KAS', fullName: 'Kaspa', raw: 89, name: 'kas', iconPath: 'assets/images/kaspa_icon.png', decimals: 8);
static const digibyte = CryptoCurrency(title: 'DGB', fullName: 'DigiByte', raw: 90, name: 'dgb', iconPath: 'assets/images/digibyte.png', decimals: 8);
static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'Tether', raw: 91, name: 'usdtsol', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
static const usdcTrc20 = CryptoCurrency(title: 'USDC', tag: 'TRX', fullName: 'USDC Coin', raw: 92, name: 'usdctrc20', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
static const tbtc = CryptoCurrency(title: 'tBTC', fullName: 'Testnet Bitcoin', raw: 93, name: 'tbtc', iconPath: 'assets/images/tbtc.png', decimals: 8);
static const wow = CryptoCurrency(title: 'WOW', fullName: 'Wownero', raw: 94, name: 'wow', iconPath: 'assets/images/crypto/wownero.svg', decimals: 11);
static const ton = CryptoCurrency(title: 'TON', fullName: 'Toncoin', raw: 95, name: 'ton', iconPath: 'assets/new-ui/crypto_full_icons/ton.svg', decimals: 8);
static const zano = CryptoCurrency(title: 'ZANO', tag: 'ZANO', fullName: 'Zano', raw: 96, name: 'zano', iconPath: 'assets/new-ui/crypto_full_icons/zano.svg', decimals: 12, flatIconPath: "assets/new-ui/balance_card_icons/zano.svg", chainIconPath: "assets/new-ui/chain_badges/zano.svg");
static const flip = CryptoCurrency(title: 'FLIP', tag: 'ETH', fullName: 'Chainflip', raw: 97, name: 'flip', iconPath: 'assets/images/flip_icon.png', decimals: 18);
static const deuro = CryptoCurrency(title: 'DEURO', tag: 'ETH', fullName: 'Decentralized Euro', raw: 98, name: 'deuro', iconPath: 'assets/images/deuro_icon.png',decimals: 18, groups: const {CurrencyGroups.stablecoin});
static const usdtbsc = CryptoCurrency(title: 'USDT', tag: 'BSC', fullName: 'USDT Binance coin', raw: 99, name: 'usdtbsc', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 18, groups: const {CurrencyGroups.stablecoin});
static const ndeps = CryptoCurrency(title: 'NDEPS', tag: 'ETH', fullName: 'Native Decentralized Euro Protocol Share', raw: 100, name: 'ndeps', iconPath: 'assets/images/ndeps_icon.png', decimals: 18);
static const deps = CryptoCurrency(title: 'DEPS', tag: 'ETH', fullName: 'Decentralized Euro Protocol Share', raw: 101, name: 'deps', iconPath: 'assets/images/deps_icon.png', decimals: 18);
static const kbtc = CryptoCurrency(title: 'KBTC', tag: 'ETH', fullName: 'Kraken Wrapped Bitcoin', raw: 102, name: 'kbtc', iconPath: 'assets/images/kbtc_icon.png', decimals: 8);
static const cbbtc = CryptoCurrency(title: 'CBBTC', tag: 'ETH', fullName: 'Coinbase Wrapped BTC', raw: 103, name: 'cbbtc', iconPath: 'assets/images/cbbtc_icon.png', decimals: 8);
static const baseEth = CryptoCurrency(title: 'ETH', tag: 'BASE', fullName: 'Ethereum', raw: 104, name: 'baseth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/base.svg", chainIconPath: "assets/new-ui/chain_badges/base.svg");
static const usde = CryptoCurrency(title: 'USDE', tag: 'BASE', fullName: 'Ethena USDE', raw: 105, name: 'usde', iconPath: 'assets/new-ui/crypto_full_icons/usde.svg', decimals: 18);
static const arbEth = CryptoCurrency(title: 'ETH', tag: 'ARB', fullName: 'Ethereum', raw: 106, name: 'arbeth', iconPath: 'assets/new-ui/crypto_full_icons/ethereum.svg', decimals: 18, flatIconPath: "assets/new-ui/balance_card_icons/arbitrum.svg", chainIconPath: "assets/new-ui/chain_badges/arbitrum.svg");
static const zec = CryptoCurrency(title: 'ZEC', fullName: 'Zcash', raw: 107, name: 'zec', iconPath: 'assets/new-ui/crypto_full_icons/zcash.svg', decimals: 8,flatIconPath: "assets/new-ui/balance_card_icons/zcash.svg");
static const usdcArb = CryptoCurrency(title: 'USDC', tag: 'ARB', fullName: 'USDC Coin', raw: 108, name: 'usdcarb', iconPath: 'assets/new-ui/crypto_full_icons/usdc.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
static const usdtArb = CryptoCurrency(title: 'USDT', tag: 'ARB', fullName: 'USDT Tether', raw: 109, name: 'usdtarb', iconPath: 'assets/new-ui/crypto_full_icons/usdt.svg', decimals: 6, groups: const {CurrencyGroups.stablecoin});
static const ltcmweb = CryptoCurrency(title: 'LTC', fullName: 'Litecoin MWeb', raw: 110, name: 'ltcmweb', iconPath: 'assets/new-ui/crypto_full_icons/litecoin.svg', decimals: 8);
static final Map<int, CryptoCurrency> _rawCurrencyMap =
[...all, ...havenCurrencies, ...zcashCurrencies].fold<Map<int, CryptoCurrency>>(<int, CryptoCurrency>{}, (acc, item) {
acc.addAll({item.raw: item});
return acc;
});
static final Map<String, CryptoCurrency> _nameCurrencyMap =
[...all, ...havenCurrencies, ...zcashCurrencies].fold<Map<String, CryptoCurrency>>(<String, CryptoCurrency>{}, (acc, item) {
acc.addAll({item.name: item});
return acc;
});
static final Map<String, CryptoCurrency> _fullNameCurrencyMap =
[...all, ...havenCurrencies, ...zcashCurrencies].fold<Map<String, CryptoCurrency>>(<String, CryptoCurrency>{}, (acc, item) {
if(item.fullName != null){
acc.addAll({item.fullName!.toLowerCase(): item});
}
return acc;
});
// Scheme to currency mapping for URI scheme
static final Map<String, CryptoCurrency> _schemeCurrencyMap = {
'bitcoin': btc,
'bitcoincash': bch,
'polygon': maticpoly,
'nano-gpt': nano,
'secret': scrt,
'stellar': xlm,
'avalanche': avaxc,
'binance': bnb,
'tether': usdt,
'usdcoin': usdc,
'wrappedbitcoin': wbtc,
'wrappedether': weth,
'shibainu': shib,
'zcash': zec,
'lightning': btcln,
'base': baseEth,
'arbitrum': arbEth,
'bsc': bnb,
};
static CryptoCurrency deserialize({required int raw}) {
if (CryptoCurrency._rawCurrencyMap[raw] == null) {
final s = 'Unexpected token: $raw for CryptoCurrency deserialize';
throw ArgumentError.value(raw, 'raw', s);
}
return CryptoCurrency._rawCurrencyMap[raw]!;
}
static CryptoCurrency? safeDeserialize({int? raw}) {
if (raw == null || raw < 0) return null;
return _rawCurrencyMap[raw];
}
// TODO: refactor this
static CryptoCurrency fromString(String name, {CryptoCurrency? walletCurrency}) {
final schemeMatch = _schemeCurrencyMap[name.toLowerCase()];
if (schemeMatch != null) return schemeMatch;
try {
return CryptoCurrency.all.firstWhere((element) =>
element.title.toLowerCase() == name.toLowerCase() &&
(element.tag == null ||
element.tag == name ||
element.tag == walletCurrency?.title ||
element.tag == walletCurrency?.tag));
} catch (_) {}
// search by fullName if not found by title:
try {
return CryptoCurrency.all.firstWhere((element) => element.fullName?.toLowerCase() == name);
} catch (_) {}
if (CryptoCurrency._nameCurrencyMap[name.toLowerCase()] == null) {
final s = 'Unexpected token: $name for CryptoCurrency fromString';
throw ArgumentError.value(name, 'name', s);
}
return CryptoCurrency._nameCurrencyMap[name.toLowerCase()]!;
}
static CryptoCurrency fromFullName(String name) {
if (CryptoCurrency._fullNameCurrencyMap[name.split("(").first.trim().toLowerCase()] == null) {
final s = 'Unexpected token: $name for CryptoCurrency fromFullName';
throw ArgumentError.value(name, 'Fullname', s);
}
return CryptoCurrency._fullNameCurrencyMap[name.split("(").first.trim().toLowerCase()]!;
}
static CryptoCurrency? safeParseCurrencyFromString(
String? raw, {
String? tag,
CryptoCurrency? walletCurrency,
}) {
if (raw == null || raw.isEmpty) return null;
if(tag?.toLowerCase() == "lightning") tag = "LN";
if (tag != null && tag.isNotEmpty) {
final match = CryptoCurrency.all.firstWhereOrNull(
(e) =>
e.title.toUpperCase() == raw.toUpperCase() &&
e.tag?.toUpperCase() == tag?.toUpperCase(),
);
if (match != null) return match;
return null;
}
// Try for native currency with same title and tag
if (tag == null || tag.isEmpty) {
final match = CryptoCurrency.all.firstWhereOrNull(
(e) =>
e.title.toUpperCase() == raw.toUpperCase() && (e.tag == raw.toUpperCase()),
);
if (match != null) return match;
}
try {
return CryptoCurrency.fromString(raw, walletCurrency: walletCurrency);
} catch (_) {}
// try cleaned (keep only A–Z/0–9)
final cleaned = raw.trim().toUpperCase().replaceAll(RegExp(r'[^A-Z0-9]'), '');
try {
return CryptoCurrency.fromString(cleaned, walletCurrency: walletCurrency);
} catch (_) {}
return null;
}
CryptoCurrency copyWith({
String? title,
int? raw,
String? name,
String? fullName,
String? iconPath,
String? tag,
int? decimals,
bool? enabled,
bool? isPotentialScam,
Set<String>? groups,
}) =>
CryptoCurrency(
title: title ?? this.title,
raw: raw ?? this.raw,
name: name ?? this.name,
fullName: fullName ?? this.fullName,
iconPath: iconPath ?? this.iconPath,
tag: tag ?? this.tag,
decimals: decimals ?? this.decimals,
enabled: enabled ?? this.enabled,
isPotentialScam: isPotentialScam ?? this.isPotentialScam,
groups: groups ?? this.groups,
);
@override
String toString() => title;
bool titleAndTagEqual(CryptoCurrency other) => title == other.title && tag == other.tag;
@override
Money parseAmount(String value) => Money.parse(value, this);
@override
Money? tryParseAmount(String value) => Money.tryParse(value, this);
/// Format the raw amount into its decimal representation eg. turn Sats into Bitcoin
String formatAmount(BigInt amount, {int? fractionalDigits, bool trimZeros = true}) =>
formatFixed(amount, decimals, fractionalDigits: fractionalDigits, trimZeros: trimZeros);
}