Reformat the whole codebase with 100 line width (#3403)

This commit is contained in:
Omar Hatem
2026-07-15 01:20:33 +03:00
committed by GitHub
parent 1241b28bec
commit 16ddc0837a
801 changed files with 17517 additions and 17091 deletions
+1 -1
View File
@@ -9,4 +9,4 @@ class Account {
final int id;
final String label;
final String? balance;
}
}
-1
View File
@@ -1,7 +1,6 @@
import 'package:mobx/mobx.dart';
abstract class AccountList<T> {
ObservableList<T> get accounts;
void update();
+1 -3
View File
@@ -41,7 +41,5 @@ class AddressInfoAdapter extends TypeAdapter<AddressInfo> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is AddressInfoAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
other is AddressInfoAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
}
-1
View File
@@ -10,7 +10,6 @@ String _smartAmountSanitizer(String amount) {
return amount.replaceAll(",", ".");
}
extension SanitizerUserAmounts on String {
String sanitized() => _smartAmountSanitizer(this);
}
+4 -5
View File
@@ -9,19 +9,18 @@ class AmountConverter {
amount = amount.replaceAll(',', '');
final parts = amount.split('.');
final whole = parts[0].isEmpty ? '0' : parts[0];
final frac = parts.length > 1 ? parts[1] : '';
final frac = parts.length > 1 ? parts[1] : '';
final fracPadded = (frac + '0' * decimals).substring(0, decimals);
final pow10 = BigInt.from(10).pow(decimals);
final wholeBI = BigInt.parse(whole);
final fracBI = fracPadded.isEmpty ? BigInt.zero : BigInt.parse(fracPadded);
final fracBI = fracPadded.isEmpty ? BigInt.zero : BigInt.parse(fracPadded);
final res = wholeBI * pow10 + fracBI;
return neg ? '-${res.toString()}' : res.toString();
}
static String fromBaseUnits(String units, int decimals) {
units = units.trim();
if (units.isEmpty) return '0';
@@ -35,14 +34,14 @@ class AmountConverter {
if (units.length <= decimals) {
final s = units.padLeft(decimals + 1, '0'); // ensures at least "0xxxx"
final intPart = s.substring(0, s.length - decimals);
var fracPart = s.substring(s.length - decimals);
var fracPart = s.substring(s.length - decimals);
fracPart = fracPart.replaceFirst(RegExp(r'0+$'), '');
final out = fracPart.isEmpty ? intPart : '$intPart.$fracPart';
return neg ? '-$out' : out;
}
final intPart = units.substring(0, units.length - decimals);
var fracPart = units.substring(units.length - decimals);
var fracPart = units.substring(units.length - decimals);
fracPart = fracPart.replaceFirst(RegExp(r'0+$'), '');
final out = fracPart.isEmpty ? intPart : '$intPart.$fracPart';
return neg ? '-$out' : out;
+13 -17
View File
@@ -14,13 +14,13 @@ class BalanceCardStyleSettings {
BalanceCardStyleSettings(
{required this.walletInfoId,
required this.accountIndex,
required this.gradientIndex,
required this.useSpecialDesign,
required this.backgroundImagePath,
this.iconStyleIndex = 0,
this.isGradientOnly = false,
required this.cardOrder});
required this.accountIndex,
required this.gradientIndex,
required this.useSpecialDesign,
required this.backgroundImagePath,
this.iconStyleIndex = 0,
this.isGradientOnly = false,
required this.cardOrder});
static const tableName = "BalanceCardStyleSettings";
@@ -59,21 +59,17 @@ class BalanceCardStyleSettings {
int iconStyleIndex = 0,
int? gradientIndexOverride,
}) {
final int gradientIndex = gradientIndexOverride ??
CardDesign.allGradients.indexOf(design.gradient);
final int gradientIndex =
gradientIndexOverride ?? CardDesign.allGradients.indexOf(design.gradient);
return BalanceCardStyleSettings(
walletInfoId: walletInfoId,
accountIndex: accountIndex,
gradientIndex: gradientIndex,
useSpecialDesign:
design.backgroundType == CardDesignBackgroundTypes.svgFull,
useSpecialDesign: design.backgroundType == CardDesignBackgroundTypes.svgFull,
backgroundImagePath:
design.backgroundType == CardDesignBackgroundTypes.image
? design.imagePath
: "",
design.backgroundType == CardDesignBackgroundTypes.image ? design.imagePath : "",
iconStyleIndex: iconStyleIndex,
isGradientOnly:
design.backgroundType == CardDesignBackgroundTypes.gradientOnly,
isGradientOnly: design.backgroundType == CardDesignBackgroundTypes.gradientOnly,
cardOrder: cardOrder,
);
}
@@ -104,4 +100,4 @@ class BalanceCardStyleSettings {
Future<void> insert() async {
db!.insert(tableName, toJson(), conflictAlgorithm: ConflictAlgorithm.replace);
}
}
}
+123 -110
View File
@@ -12,14 +12,13 @@ class CardColorCombination {
const CardColorCombination(
{required this.textColor,
required this.textColorSecondary,
required this.backgroundImageColor});
required this.textColorSecondary,
required this.backgroundImageColor});
static const light = CardColorCombination(
textColor: Color.fromARGB(200, 255, 255, 255),
textColorSecondary: Colors.white54,
backgroundImageColor: Color.fromARGB(200, 0, 0, 0)
);
backgroundImageColor: Color.fromARGB(200, 0, 0, 0));
static const dark = CardColorCombination(
textColor: Color.fromARGB(200, 0, 0, 0),
@@ -50,10 +49,11 @@ class CardDesign {
const CardDesign(
{this.backgroundType = CardDesignBackgroundTypes.svgIcon,
this.gradient = const LinearGradient(colors: [Colors.black], begin: Alignment.topCenter, end: Alignment.bottomCenter),
this.imagePath = "assets/new-ui/blank.svg",
this.colors = CardColorCombination.dark,
this.preColoredIcon = false});
this.gradient = const LinearGradient(
colors: [Colors.black], begin: Alignment.topCenter, end: Alignment.bottomCenter),
this.imagePath = "assets/new-ui/blank.svg",
this.colors = CardColorCombination.dark,
this.preColoredIcon = false});
static const LinearGradient gradientOrange = LinearGradient(
colors: <Color>[Color(0xFFFF7C02), Color(0xFFFF5602)],
@@ -129,71 +129,50 @@ class CardDesign {
static const genericDefault = CardDesign(gradient: gradientBlue);
static const gradientOnlyDesign = CardDesign(
backgroundType: CardDesignBackgroundTypes.gradientOnly,
gradient: gradientBlue);
static const gradientOnlyDesign =
CardDesign(backgroundType: CardDesignBackgroundTypes.gradientOnly, gradient: gradientBlue);
static const btc = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/bitcoin.svg");
static const btc = CardDesign(imagePath: "assets/new-ui/balance_card_icons/bitcoin.svg");
static const eth = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/ethereum.svg");
static const eth = CardDesign(imagePath: "assets/new-ui/balance_card_icons/ethereum.svg");
static const btcln = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/lightning.svg");
static const btcln = CardDesign(imagePath: "assets/new-ui/balance_card_icons/lightning.svg");
static const xmr = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/monero.svg");
static const xmr = CardDesign(imagePath: "assets/new-ui/balance_card_icons/monero.svg");
static const ltc = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/litecoin.svg");
static const ltc = CardDesign(imagePath: "assets/new-ui/balance_card_icons/litecoin.svg");
static const bch = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/bitcoin_cash.svg");
static const bch = CardDesign(imagePath: "assets/new-ui/balance_card_icons/bitcoin_cash.svg");
static const doge = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/dogecoin.svg");
static const doge = CardDesign(imagePath: "assets/new-ui/balance_card_icons/dogecoin.svg");
static const base = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/base.svg");
static const base = CardDesign(imagePath: "assets/new-ui/balance_card_icons/base.svg");
static const pol = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/polygon.svg");
static const pol = CardDesign(imagePath: "assets/new-ui/balance_card_icons/polygon.svg");
static const sol = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/solana.svg");
static const sol = CardDesign(imagePath: "assets/new-ui/balance_card_icons/solana.svg");
static const tron = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/tron.svg");
static const tron = CardDesign(imagePath: "assets/new-ui/balance_card_icons/tron.svg");
static const nano = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/nano.svg");
static const nano = CardDesign(imagePath: "assets/new-ui/balance_card_icons/nano.svg");
static const zano = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/zano.svg");
static const zano = CardDesign(imagePath: "assets/new-ui/balance_card_icons/zano.svg");
static const wow = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/wownero.svg");
static const wow = CardDesign(imagePath: "assets/new-ui/balance_card_icons/wownero.svg");
static const dcr = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/decred.svg");
static const dcr = CardDesign(imagePath: "assets/new-ui/balance_card_icons/decred.svg");
static const arbitrum = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/arbitrum.svg");
static const zec = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/zcash.svg");
static const bnb = CardDesign(
imagePath: "assets/new-ui/balance_card_icons/bnb.svg");
static const arbitrum = CardDesign(imagePath: "assets/new-ui/balance_card_icons/arbitrum.svg");
static const zec = CardDesign(imagePath: "assets/new-ui/balance_card_icons/zcash.svg");
static const bnb = CardDesign(imagePath: "assets/new-ui/balance_card_icons/bnb.svg");
static const ethSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFF6259FF), Color(0xFF3B20E6)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
backgroundType: CardDesignBackgroundTypes.svgFull,
colors: CardColorCombination.light,
imagePath: "assets/new-ui/balance_card_backgrounds/ethereum.svg");
@@ -201,24 +180,24 @@ class CardDesign {
static const btcSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFFFFBF00), Color(0xFFFF6A00)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
backgroundType: CardDesignBackgroundTypes.svgFull,
imagePath: "assets/new-ui/balance_card_backgrounds/bitcoin.svg");
static const xmrSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFFFF5900), Color(0xFFE62E00)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
backgroundType: CardDesignBackgroundTypes.svgFull,
imagePath: "assets/new-ui/balance_card_backgrounds/monero.svg");
static const ltcSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFF2145BF), Color(0xFF072071)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
backgroundType: CardDesignBackgroundTypes.svgFull,
colors: CardColorCombination.light,
imagePath: "assets/new-ui/balance_card_backgrounds/litecoin.svg");
@@ -226,8 +205,8 @@ class CardDesign {
static const lnSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFFFFBF00), Color(0xFFFF6A00)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
backgroundType: CardDesignBackgroundTypes.svgFull,
colors: CardColorCombination.dark,
imagePath: "assets/new-ui/balance_card_backgrounds/lightning.svg");
@@ -235,8 +214,8 @@ class CardDesign {
static const tronSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFFFF1313), Color(0xFFB40000)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
backgroundType: CardDesignBackgroundTypes.svgFull,
colors: CardColorCombination.light,
imagePath: "assets/new-ui/balance_card_backgrounds/tron.svg");
@@ -244,8 +223,8 @@ class CardDesign {
static const solSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFF4701AA), Color(0xFF19004B)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
backgroundType: CardDesignBackgroundTypes.svgFull,
colors: CardColorCombination.light,
imagePath: "assets/new-ui/balance_card_backgrounds/solana.svg");
@@ -253,40 +232,40 @@ class CardDesign {
static const bchSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFF36DA4C), Color(0xFF008D57)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
backgroundType: CardDesignBackgroundTypes.svgFull,
imagePath: "assets/new-ui/balance_card_backgrounds/bitcoin-cash.svg");
static const wowSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFFFF6CD3), Color(0xFFF200A9)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
backgroundType: CardDesignBackgroundTypes.svgFull,
imagePath: "assets/new-ui/balance_card_backgrounds/wownero.svg");
static const dogeSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFFCBA818), Color(0xFF885D00)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
backgroundType: CardDesignBackgroundTypes.svgFull,
imagePath: "assets/new-ui/balance_card_backgrounds/dogecoin.svg");
static const nanoSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFF209CE9), Color(0xFF0073CB)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
backgroundType: CardDesignBackgroundTypes.svgFull,
imagePath: "assets/new-ui/balance_card_backgrounds/nano.svg");
static const polSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFF863FE3), Color(0xFF59098E)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
backgroundType: CardDesignBackgroundTypes.svgFull,
colors: CardColorCombination.light,
imagePath: "assets/new-ui/balance_card_backgrounds/polygon.svg");
@@ -294,8 +273,8 @@ class CardDesign {
static const dcrSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFF2871FF), Color(0xFF0057FF)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
colors: CardColorCombination.light,
backgroundType: CardDesignBackgroundTypes.svgFull,
imagePath: "assets/new-ui/balance_card_backgrounds/decred.svg");
@@ -303,8 +282,8 @@ class CardDesign {
static const zanoSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFF0004B4), Color(0xFF170069)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
colors: CardColorCombination.black,
backgroundType: CardDesignBackgroundTypes.svgFull,
imagePath: "assets/new-ui/balance_card_backgrounds/zano.svg");
@@ -312,8 +291,8 @@ class CardDesign {
static const baseSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFF003CFF), Color(0xFF000087)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
colors: CardColorCombination.light,
backgroundType: CardDesignBackgroundTypes.svgFull,
imagePath: "assets/new-ui/balance_card_backgrounds/base.svg");
@@ -321,8 +300,8 @@ class CardDesign {
static const arbitrumSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFF173F76), Color(0xFF031A39)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
colors: CardColorCombination.light,
backgroundType: CardDesignBackgroundTypes.svgFull,
imagePath: "assets/new-ui/balance_card_backgrounds/arbitrum.svg");
@@ -330,16 +309,16 @@ class CardDesign {
static const zecSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFFF6C527), Color(0xFFCD8C00)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
backgroundType: CardDesignBackgroundTypes.svgFull,
imagePath: "assets/new-ui/balance_card_backgrounds/zcash.svg");
static const bnbSpecial = CardDesign(
gradient: const LinearGradient(
colors: <Color>[Color(0xFF603000), Color(0xFFF0B90B)],
begin: Alignment.topCenter, end: Alignment.bottomCenter
),
begin: Alignment.topCenter,
end: Alignment.bottomCenter),
colors: CardColorCombination.light,
backgroundType: CardDesignBackgroundTypes.svgFull,
imagePath: "assets/new-ui/balance_card_backgrounds/bnb.svg");
@@ -351,12 +330,14 @@ class CardDesign {
backgroundType: backgroundType,
preColoredIcon: preColoredIcon);
CardDesign withGradientAndColorCombination(Gradient gradient, CardColorCombination cardColorCombination) => CardDesign(
gradient: gradient,
colors: cardColorCombination,
imagePath: imagePath,
backgroundType: backgroundType,
preColoredIcon: preColoredIcon);
CardDesign withGradientAndColorCombination(
Gradient gradient, CardColorCombination cardColorCombination) =>
CardDesign(
gradient: gradient,
colors: cardColorCombination,
imagePath: imagePath,
backgroundType: backgroundType,
preColoredIcon: preColoredIcon);
CardDesign withIcon(CardIconPath icon) => CardDesign(
gradient: gradient,
@@ -374,8 +355,10 @@ class CardDesign {
static const Map<CryptoCurrency, _CurrencyIconNames> _iconNames = {
CryptoCurrency.arbEth: _CurrencyIconNames(ticker: 'arb', longName: 'arbitrum'),
CryptoCurrency.baseEth: _CurrencyIconNames(ticker: 'base', longName: 'base', chainFile: 'base_icon'),
CryptoCurrency.bch: _CurrencyIconNames(ticker: 'bch', longName: 'bitcoin_cash', chainFile: 'bitcoin-cash'),
CryptoCurrency.baseEth:
_CurrencyIconNames(ticker: 'base', longName: 'base', chainFile: 'base_icon'),
CryptoCurrency.bch:
_CurrencyIconNames(ticker: 'bch', longName: 'bitcoin_cash', chainFile: 'bitcoin-cash'),
CryptoCurrency.btc: _CurrencyIconNames(ticker: 'btc', longName: 'bitcoin', outlineFile: 'BTC'),
CryptoCurrency.bnb: _CurrencyIconNames(ticker: 'bnb', longName: 'bnb'),
CryptoCurrency.dcr: _CurrencyIconNames(ticker: 'dcr', longName: 'decred'),
@@ -383,13 +366,13 @@ class CardDesign {
CryptoCurrency.eth: _CurrencyIconNames(ticker: 'eth', longName: 'ethereum'),
CryptoCurrency.btcln: _CurrencyIconNames(ticker: 'ln', longName: 'lightning'),
CryptoCurrency.ltc: _CurrencyIconNames(ticker: 'ltc', longName: 'litecoin'),
CryptoCurrency.xmr: _CurrencyIconNames(
ticker: 'xmr', longName: 'monero', ogPath: 'assets/images/xmr-og.webp'),
CryptoCurrency.xmr:
_CurrencyIconNames(ticker: 'xmr', longName: 'monero', ogPath: 'assets/images/xmr-og.webp'),
CryptoCurrency.nano: _CurrencyIconNames(ticker: 'xno', longName: 'nano'),
CryptoCurrency.maticpoly: _CurrencyIconNames(ticker: 'pol', longName: 'polygon'),
CryptoCurrency.sol: _CurrencyIconNames(ticker: 'sol', longName: 'solana'),
CryptoCurrency.trx: _CurrencyIconNames(
ticker: 'trx', longName: 'tron', ogPath: '$_ogIconPrefix/tron-og.svg'),
CryptoCurrency.trx:
_CurrencyIconNames(ticker: 'trx', longName: 'tron', ogPath: '$_ogIconPrefix/tron-og.svg'),
CryptoCurrency.zano: _CurrencyIconNames(ticker: 'zano', longName: 'zano'),
CryptoCurrency.zec: _CurrencyIconNames(ticker: 'zec', longName: 'zcash'),
};
@@ -408,7 +391,40 @@ class CardDesign {
];
}
static const List<CardDesign> all = [genericDefault, btc, eth, xmr, ltc, eth, pol, doge, base, sol, btcln, tron, zano, dcr, arbitrum, zec, bnb, ethSpecial, btcSpecial, xmrSpecial, ltcSpecial, lnSpecial, tronSpecial, bchSpecial, wowSpecial, dogeSpecial, polSpecial, dcrSpecial, zanoSpecial, arbitrumSpecial, zecSpecial, bnbSpecial];
static const List<CardDesign> all = [
genericDefault,
btc,
eth,
xmr,
ltc,
eth,
pol,
doge,
base,
sol,
btcln,
tron,
zano,
dcr,
arbitrum,
zec,
bnb,
ethSpecial,
btcSpecial,
xmrSpecial,
ltcSpecial,
lnSpecial,
tronSpecial,
bchSpecial,
wowSpecial,
dogeSpecial,
polSpecial,
dcrSpecial,
zanoSpecial,
arbitrumSpecial,
zecSpecial,
bnbSpecial
];
static CardDesign forCurrencySpecial(CryptoCurrency currency) {
return specialDesignsForCurrencies[currency] ?? genericDefault;
@@ -437,7 +453,6 @@ class CardDesign {
CryptoCurrency.zec: zec,
CryptoCurrency.dcr: dcr,
CryptoCurrency.bnb: bnb,
};
static const Map<CryptoCurrency, CardDesign> specialDesignsForCurrencies = {
@@ -504,9 +519,9 @@ class CardDesign {
if (setting.isGradientOnly) {
final gradient = gradientForStoredIndex(setting.gradientIndex, walletCurrency);
final textColors = preferredColorCombinations[gradient]
?? specialDesignsForCurrencies[walletCurrency]?.colors
?? gradientOnlyDesign.colors;
final textColors = preferredColorCombinations[gradient] ??
specialDesignsForCurrencies[walletCurrency]?.colors ??
gradientOnlyDesign.colors;
return gradientOnlyDesign.withGradientAndColorCombination(gradient, textColors);
}
@@ -521,11 +536,9 @@ class CardDesign {
}
if (!setting.useSpecialDesign && setting.gradientIndex == -1) {
final specialColors =
specialDesignsForCurrencies[walletCurrency] ?? genericDefault;
final specialColors = specialDesignsForCurrencies[walletCurrency] ?? genericDefault;
final design = CardDesign.forCurrencyIcon(walletCurrency)
.withGradientAndColorCombination(
specialColors.gradient, specialColors.colors);
.withGradientAndColorCombination(specialColors.gradient, specialColors.colors);
return design.withIconStyleIndex(setting.iconStyleIndex, walletCurrency);
}
if (setting.useSpecialDesign) {
@@ -534,9 +547,9 @@ class CardDesign {
if (setting.gradientIndex != -1) {
final baseIcon = CardDesign.forCurrencyIcon(walletCurrency);
final gradient = gradientForStoredIndex(setting.gradientIndex, walletCurrency);
final textColors = preferredColorCombinations[gradient]
?? specialDesignsForCurrencies[walletCurrency]?.colors
?? baseIcon.colors;
final textColors = preferredColorCombinations[gradient] ??
specialDesignsForCurrencies[walletCurrency]?.colors ??
baseIcon.colors;
return baseIcon
.withGradientAndColorCombination(gradient, textColors)
.withIconStyleIndex(setting.iconStyleIndex, walletCurrency);
@@ -561,4 +574,4 @@ class _CurrencyIconNames {
this.chainFile,
this.ogPath,
});
}
}
-1
View File
@@ -37,7 +37,6 @@ extension MaxDecimals on String {
return parts.join(".");
}
/// Format a stringified number to a localized representation
/// 1.000.000,00 in de_DE
/// 1’000’000.00 in de_CH
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -90,7 +90,8 @@ int? getChainIdByCryptoCurrency(CryptoCurrency currency) {
}
}
CryptoCurrency getCryptoCurrencyForWalletListItem(WalletType type, {bool isTestnet = false, int? chainId}) {
CryptoCurrency getCryptoCurrencyForWalletListItem(WalletType type,
{bool isTestnet = false, int? chainId}) {
if (type == WalletType.arbitrum) {
return CryptoCurrency.arb;
}
+1 -1
View File
@@ -100,7 +100,7 @@ class _SqliteErrorHandlerState extends State<SqliteErrorHandler> {
final dbFile = File("${(await getAppDir()).path}/cake.db");
final jsonText = JsonEncoder.withIndent(" ").convert(await dumpCustomDb(dbFile.path));
setState(() {
log = jsonText;
log = jsonText;
});
} catch (e, s) {
setState(() {
+27 -28
View File
@@ -3,40 +3,39 @@ import 'dart:typed_data';
import 'package:cw_core/utils/file.dart' as file;
import 'package:cake_backup/backup.dart' as cwb;
EncryptionFileUtils encryptionFileUtilsFor(bool direct)
=> direct
? XChaCha20EncryptionFileUtils()
: Salsa20EncryhptionFileUtils();
EncryptionFileUtils encryptionFileUtilsFor(bool direct) =>
direct ? XChaCha20EncryptionFileUtils() : Salsa20EncryhptionFileUtils();
abstract class EncryptionFileUtils {
Future<void> write({required String path, required String password, required String data});
Future<String> read({required String path, required String password});
Future<void> write({required String path, required String password, required String data});
Future<String> read({required String path, required String password});
}
class Salsa20EncryhptionFileUtils extends EncryptionFileUtils {
// Requires legacy complex key + iv as password
@override
Future<void> write({required String path, required String password, required String data}) async
=> await file.write(path: path, password: password, data: data);
// Requires legacy complex key + iv as password
@override
Future<void> write(
{required String path, required String password, required String data}) async =>
await file.write(path: path, password: password, data: data);
// Requires legacy complex key + iv as password
@override
Future<String> read({required String path, required String password}) async
=> await file.read(path: path, password: password);
// Requires legacy complex key + iv as password
@override
Future<String> read({required String path, required String password}) async =>
await file.read(path: path, password: password);
}
class XChaCha20EncryptionFileUtils extends EncryptionFileUtils {
@override
Future<void> write({required String path, required String password, required String data}) async {
final encrypted = await cwb.encrypt(password, Uint8List.fromList(data.codeUnits));
await File(path).writeAsBytes(encrypted);
}
@override
Future<String> read({required String path, required String password}) async {
final file = File(path);
final encrypted = await file.readAsBytes();
final bytes = await cwb.decrypt(password, encrypted);
return String.fromCharCodes(bytes);
}
}
@override
Future<void> write({required String path, required String password, required String data}) async {
final encrypted = await cwb.encrypt(password, Uint8List.fromList(data.codeUnits));
await File(path).writeAsBytes(encrypted);
}
@override
Future<String> read({required String path, required String password}) async {
final file = File(path);
final encrypted = await file.readAsBytes();
final bytes = await cwb.decrypt(password, encrypted);
return String.fromCharCodes(bytes);
}
}
+2 -4
View File
@@ -1,4 +1,4 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'erc20_token.dart';
@@ -55,7 +55,5 @@ class Erc20TokenAdapter extends TypeAdapter<Erc20Token> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is Erc20TokenAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
other is Erc20TokenAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
}
+1 -1
View File
@@ -69,4 +69,4 @@ class WalletDeprecationException implements Exception {
String toString() => "Wallet type no longer supported";
WalletDeprecationException({required this.seed, required this.curr});
}
}
+3 -3
View File
@@ -1,8 +1,8 @@
String formatAmount(String amount) {
if ((!amount.contains('.'))&&(!amount.contains(','))) {
if ((!amount.contains('.')) && (!amount.contains(','))) {
return amount + '.00';
} else if ((amount.endsWith('.'))||(amount.endsWith(','))) {
} else if ((amount.endsWith('.')) || (amount.endsWith(','))) {
return amount + '00';
}
return amount;
}
}
+3 -6
View File
@@ -1,7 +1,6 @@
import 'package:cw_core/parse_fixed.dart';
String formatFixed(BigInt value, int? decimals,
{int? fractionalDigits, bool trimZeros = true}) {
String formatFixed(BigInt value, int? decimals, {int? fractionalDigits, bool trimZeros = true}) {
decimals ??= 0;
fractionalDigits ??= decimals;
@@ -10,10 +9,8 @@ String formatFixed(BigInt value, int? decimals,
var negative = value.isNegative;
if (negative) value = value * BigInt.from(-1);
var fraction = value
.modPow(BigInt.one, BigInt.parse(multiplier))
.toString()
.padLeft(decimals, "0");
var fraction =
value.modPow(BigInt.one, BigInt.parse(multiplier)).toString().padLeft(decimals, "0");
if (fractionalDigits < 0) fractionalDigits = 0;
if (fractionalDigits > decimals) fractionalDigits = decimals;
+2 -1
View File
@@ -6,7 +6,8 @@ import 'dart:convert';
// FIXME: Hardcoded values; Works only for monero
int getMoneroHeigthByDate({required DateTime date}) => MoneroHeight.getBlockHeightByTime(date..subtract(Duration(days: 1)));
int getMoneroHeigthByDate({required DateTime date}) =>
MoneroHeight.getBlockHeightByTime(date..subtract(Duration(days: 1)));
const havenDates = {
"2023-05": 1352995,
-1
View File
@@ -1,4 +1,3 @@
class MoneroHeight {
// for i in $(seq 1 364); do echo "_Checkpoint(_t($(curl https://xmrchain.net/block/${i}0000 | grep -E '[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}' | xargs | sed 's/ /\n/g' | head -5 | tail -1 | tr '()' ' ' | sed 's/ /\n/g' | head -2 | xargs)), ${i}0000),"; done > points.txt
static final List<_Checkpoint> _points = [
+24 -24
View File
@@ -1,24 +1,24 @@
const CONTACT_TYPE_ID = 0;
const NODE_TYPE_ID = 1;
const TRANSACTION_TYPE_ID = 2;
const TRADE_TYPE_ID = 3;
const WALLET_INFO_TYPE_ID = 4;
const WALLET_TYPE_TYPE_ID = 5;
const TEMPLATE_TYPE_ID = 6;
const EXCHANGE_TEMPLATE_TYPE_ID = 7;
const ORDER_TYPE_ID = 8;
const UNSPENT_COINS_INFO_TYPE_ID = 9;
const ANONPAY_INVOICE_INFO_TYPE_ID = 10;
const ADDRESS_INFO_TYPE_ID = 11;
const ERC20_TOKEN_TYPE_ID = 12;
const NANO_ACCOUNT_TYPE_ID = 13;
const POW_NODE_TYPE_ID = 14;
const DERIVATION_TYPE_TYPE_ID = 15;
const SPL_TOKEN_TYPE_ID = 16;
const DERIVATION_INFO_TYPE_ID = 17;
const TRON_TOKEN_TYPE_ID = 18;
const HARDWARE_WALLET_TYPE_TYPE_ID = 19;
const MWEB_UTXO_TYPE_ID = 20;
const HAVEN_SEED_STORE_TYPE_ID = 21;
const ZANO_ASSET_TYPE_ID = 22;
const PAYJOIN_SESSION_TYPE_ID = 23;
const CONTACT_TYPE_ID = 0;
const NODE_TYPE_ID = 1;
const TRANSACTION_TYPE_ID = 2;
const TRADE_TYPE_ID = 3;
const WALLET_INFO_TYPE_ID = 4;
const WALLET_TYPE_TYPE_ID = 5;
const TEMPLATE_TYPE_ID = 6;
const EXCHANGE_TEMPLATE_TYPE_ID = 7;
const ORDER_TYPE_ID = 8;
const UNSPENT_COINS_INFO_TYPE_ID = 9;
const ANONPAY_INVOICE_INFO_TYPE_ID = 10;
const ADDRESS_INFO_TYPE_ID = 11;
const ERC20_TOKEN_TYPE_ID = 12;
const NANO_ACCOUNT_TYPE_ID = 13;
const POW_NODE_TYPE_ID = 14;
const DERIVATION_TYPE_TYPE_ID = 15;
const SPL_TOKEN_TYPE_ID = 16;
const DERIVATION_INFO_TYPE_ID = 17;
const TRON_TOKEN_TYPE_ID = 18;
const HARDWARE_WALLET_TYPE_TYPE_ID = 19;
const MWEB_UTXO_TYPE_ID = 20;
const HAVEN_SEED_STORE_TYPE_ID = 21;
const ZANO_ASSET_TYPE_ID = 22;
const PAYJOIN_SESSION_TYPE_ID = 23;
+2 -1
View File
@@ -16,7 +16,8 @@ List<String> extractKeys(String key) {
return [_key, iv];
}
Future<String> encode({required encrypt.Key key, required encrypt.IV iv, required String data}) async {
Future<String> encode(
{required encrypt.Key key, required encrypt.IV iv, required String data}) async {
final encrypter = encrypt.Encrypter(encrypt.Salsa20(key));
final encrypted = encrypter.encrypt(data, iv: iv);
+1 -1
View File
@@ -1,3 +1,3 @@
mixin Keyable {
dynamic keyIndex;
}
}
+6 -9
View File
@@ -12,12 +12,11 @@ bool isBolt11ZeroInvoice(String invoice) {
try {
final request = Bech32Codec().decode(invoice.replaceFirst("lightning:", ""), invoice.length);
final prefix = _BOLT_PREFIXES
.firstWhere((prefix) => request.hrp.startsWith(prefix), orElse: () => "");
final prefix =
_BOLT_PREFIXES.firstWhere((prefix) => request.hrp.startsWith(prefix), orElse: () => "");
return request.hrp.length == prefix.length;
} catch(e) {
} catch (e) {
return false;
}
}
@@ -27,7 +26,7 @@ int? _getAmountBolt11Msat(String invoice) {
final request = Bech32Codec().decode(invoice.replaceFirst("lightning:", ""), invoice.length);
final prefix = _BOLT_PREFIXES.firstWhere(
(prefix) => request.hrp.startsWith(prefix),
(prefix) => request.hrp.startsWith(prefix),
orElse: () => throw FormatException('Invalid BOLT11 invoice: unknown HRP prefix.'),
);
@@ -86,8 +85,7 @@ class LNURL {
final maxSendable = body["maxSendable"] as int?;
// if minSendable and maxSendable are the same we assume a specific payment request
if (msat != maxSendable)
return null;
if (msat != maxSendable) return null;
if (msat == null || msat % 1000 != 0) return null;
return Money.fromInt(msat ~/ 1000, CryptoCurrency.btcln);
@@ -136,8 +134,7 @@ class LNURL {
String _findLnUrl(String input) {
final res = RegExp(r',*?((lnurl)([0-9]+[a-z0-9]+))').allMatches(input.toLowerCase());
if (res.length != 1)
throw ArgumentError('Not a valid lnurl string');
if (res.length != 1) throw ArgumentError('Not a valid lnurl string');
return res.first.group(0)!;
}
+6 -6
View File
@@ -1,11 +1,11 @@
class MoneroWalletKeys {
const MoneroWalletKeys(
{required this.primaryAddress,
required this.privateSpendKey,
required this.privateViewKey,
required this.publicSpendKey,
required this.publicViewKey,
required this.passphrase});
required this.privateSpendKey,
required this.privateViewKey,
required this.publicSpendKey,
required this.publicViewKey,
required this.passphrase});
final String primaryAddress;
final String publicViewKey;
@@ -13,4 +13,4 @@ class MoneroWalletKeys {
final String publicSpendKey;
final String privateSpendKey;
final String passphrase;
}
}
+1 -3
View File
@@ -50,7 +50,5 @@ class MwebUtxoAdapter extends TypeAdapter<MwebUtxo> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is MwebUtxoAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
other is MwebUtxoAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
}
+1 -3
View File
@@ -44,7 +44,5 @@ class NanoAccountAdapter extends TypeAdapter<NanoAccount> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is NanoAccountAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
other is NanoAccountAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
}
+30 -34
View File
@@ -25,11 +25,9 @@ Future<void> validateBuiltinNodes() async {
for (final listNode in builtinFromList) {
// preserve proxy settings from user
try {
final matchedDbNode = builtinFromDb.firstWhere(
(dbNode) => dbNode.uri == listNode.uri
);
final matchedDbNode = builtinFromDb.firstWhere((dbNode) => dbNode.uri == listNode.uri);
listNode.socksProxyAddress = matchedDbNode.socksProxyAddress;
} catch(e) {}
} catch (e) {}
}
final dbSet = builtinFromDb.toSet();
@@ -121,7 +119,7 @@ class Node {
"label": label,
'password': password,
"isPow": isPow ? 1 : 0,
'useSSL': (useSSL??false) ? 1 : 0,
'useSSL': (useSSL ?? false) ? 1 : 0,
"typeRaw": typeRaw,
'trusted': trusted ? 1 : 0,
'socksProxyAddress': socksProxyAddress,
@@ -165,7 +163,6 @@ class Node {
}
Future<int> save() async {
final json = toMap();
if (json[selfIdColumn] == 0) {
json[selfIdColumn] = null;
@@ -174,9 +171,9 @@ class Node {
return id;
}
static Future<List<Node>> selectList(String where, List<dynamic> whereArgs, {String? orderBy}) async {
if(orderBy == null) {
static Future<List<Node>> selectList(String where, List<dynamic> whereArgs,
{String? orderBy}) async {
if (orderBy == null) {
orderBy = selfIdColumn;
}
final list = await db!.query(
@@ -189,7 +186,7 @@ class Node {
}
static Future<Node?> select(String where, List<dynamic> whereArgs, {String? orderBy}) async {
if(orderBy == null) {
if (orderBy == null) {
orderBy = selfIdColumn;
}
final list = await db!.query(
@@ -201,7 +198,6 @@ class Node {
return list.isEmpty ? null : Node.fromMap(list.first);
}
static Future<List<Node>> getAll() async {
return selectList("isPow = ?", [0]);
}
@@ -219,11 +215,15 @@ class Node {
}
static Future<Node?> getDefaultForWalletType(WalletType type) async {
return (await selectList("typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), 0, 1])).firstOrNull;
return (await selectList(
"typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), 0, 1]))
.firstOrNull;
}
static Future<Node?> getDefaultPowForWalletType(WalletType type) async {
return (await selectList("typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), 1, 1])).firstOrNull;
return (await selectList(
"typeRaw = ? AND isPow = ? AND isDefault = ?", [serializeToInt(type), 1, 1]))
.firstOrNull;
}
static Future<List<Node>> getAllForWalletTypePow(WalletType type) async {
@@ -238,7 +238,6 @@ class Node {
return select("${selfIdColumn} = ?", [id]);
}
int id;
late String uriRaw;
String? login;
@@ -262,7 +261,6 @@ class Node {
static String get tableName => "Node";
static String get selfIdColumn => "${tableName}Id";
bool get isSSL => useSSL ?? false;
bool get useSocksProxy => socksProxyAddress == null ? false : socksProxyAddress!.isNotEmpty;
@@ -333,7 +331,6 @@ class Node {
socksProxyAddress.hashCode ^
path.hashCode;
WalletType get type => deserializeFromInt(typeRaw);
set type(WalletType type) => typeRaw = serializeToInt(type);
@@ -387,7 +384,6 @@ class Node {
body: jsonBody,
);
final resBody = json.decode(response.body) as Map<String, dynamic>;
return resBody['result']['height'] != null;
@@ -407,15 +403,13 @@ class Node {
final body = {'jsonrpc': '2.0', 'id': '0', 'method': methodName};
try {
final jsonBody = json.encode(body);
final response = await ProxyWrapper().post(
clearnetUri: rpcUri,
headers: {'Content-Type': 'application/json'},
body: jsonBody,
allowMitmMoneroBypassSSLCheck: true
);
clearnetUri: rpcUri,
headers: {'Content-Type': 'application/json'},
body: jsonBody,
allowMitmMoneroBypassSSLCheck: true);
// Check if we received a 401 Unauthorized response
if (response.statusCode == 401) {
final daemonRpc = DaemonRpc(
@@ -494,7 +488,6 @@ class Node {
final ProxySocket socket;
socket = await ProxyWrapper().getSocksSocket(useSSL ?? false, uri.host, uri.port);
socket.destroy();
return true;
} catch (_) {
@@ -531,9 +524,12 @@ class Node {
Future<bool> requestEthereumServer() async {
try {
final req = await ProxyWrapper().getHttpClient()
.getUrl(uri,)
.timeout(Duration(seconds: 15));
final req = await ProxyWrapper()
.getHttpClient()
.getUrl(
uri,
)
.timeout(Duration(seconds: 15));
final response = await req.close();
return response.statusCode >= 200 && response.statusCode < 300;
@@ -544,13 +540,13 @@ class Node {
}
Future<bool> requestDecredNode() async {
if (uri.host == "default-spv-nodes") {
// Just show default port as ok. The wallet will connect to a list of known
// nodes automatically.
return true;
}
try {
final socket = await Socket.connect(uri.host, uri.port, timeout: Duration(seconds: 5));
if (uri.host == "default-spv-nodes") {
// Just show default port as ok. The wallet will connect to a list of known
// nodes automatically.
return true;
}
try {
final socket = await Socket.connect(uri.host, uri.port, timeout: Duration(seconds: 5));
socket.destroy();
return true;
} catch (_) {
+18 -28
View File
@@ -19,17 +19,15 @@ import 'node.dart' as node_new;
part 'node_legacy.part.dart';
Future<void> performNodeHiveMigration() async {
if(!CakeHive.isAdapterRegistered(Node.typeId)) {
if (!CakeHive.isAdapterRegistered(Node.typeId)) {
CakeHive.registerAdapter(NodeAdapter());
}
final nodeBox = await CakeHive.openBox<Node>(Node.boxName);
final powNodeBox = await CakeHive.openBox<Node>(Node.boxName+"pow");
final powNodeBox = await CakeHive.openBox<Node>(Node.boxName + "pow");
final builtinNodes = await loadAllDefaultNodes();
final builtinPowNodes = await loadDefaultNanoPowNodes();
await Node.migrateAllToSqlite(nodeBox, powNodeBox, builtinNodes, builtinPowNodes);
}
Uri createUriFromElectrumAddress(String address, String path) =>
@@ -62,31 +60,26 @@ class Node extends HiveObject with Keyable {
final list = nodeBox.values.toList();
final powList = powNodeBox.values.toList();
for (final node in list) {
if(defaultNodes.any((item)=>item.uri == node.uri)) {
if (defaultNodes.any((item) => item.uri == node.uri)) {
// default nodes will be added by validateBuiltinNodes(), no need to migrate them.
await node.delete();
continue;
}
await node.migrateToSqlite(
isPow: false,
isBuiltin: false,
isOfficial: false);
await node.migrateToSqlite(isPow: false, isBuiltin: false, isOfficial: false);
await node.delete();
}
for (final node in powList) {
if(defaultPowNodes.any((item)=>item.uri == node.uri)) {
if (defaultPowNodes.any((item) => item.uri == node.uri)) {
await node.delete();
continue;
}
await node.migrateToSqlite(
isPow: true,
isBuiltin: false,
isOfficial: false);
await node.migrateToSqlite(isPow: true, isBuiltin: false, isOfficial: false);
await node.delete();
}
}
Future<void> migrateToSqlite({required bool isPow, required bool isBuiltin, required bool isOfficial}) async {
Future<void> migrateToSqlite(
{required bool isPow, required bool isBuiltin, required bool isOfficial}) async {
final newNode = node_new.Node(
id: key as int,
login: login,
@@ -106,7 +99,6 @@ class Node extends HiveObject with Keyable {
await newNode.save();
}
Node.fromMap(Map<String, Object?> map)
: uriRaw = map['uri'] as String? ?? '',
path = map['path'] as String? ?? '',
@@ -208,15 +200,15 @@ class Node extends HiveObject with Keyable {
@override
bool operator ==(other) =>
other is Node &&
(other.uriRaw == uriRaw &&
other.login == login &&
other.label == label &&
other.password == password &&
other.typeRaw == typeRaw &&
other.useSSL == useSSL &&
other.trusted == trusted &&
other.socksProxyAddress == socksProxyAddress &&
other.path == path);
(other.uriRaw == uriRaw &&
other.login == login &&
other.label == label &&
other.password == password &&
other.typeRaw == typeRaw &&
other.useSSL == useSSL &&
other.trusted == trusted &&
other.socksProxyAddress == socksProxyAddress &&
other.path == path);
@override
int get hashCode =>
@@ -241,6 +233,4 @@ class Node extends HiveObject with Keyable {
set type(WalletType type) => typeRaw = serializeToInt(type);
dynamic _keyIndex;
}
}
+2 -5
View File
@@ -24,8 +24,7 @@ class NodeAdapter extends TypeAdapter<Node> {
trusted: fields[5] == null ? false : fields[5] as bool,
socksProxyAddress: fields[6] as String?,
path: fields[7] == null ? '' : fields[7] as String?,
isEnabledForAutoSwitching:
fields[11] == null ? false : fields[11] as bool,
isEnabledForAutoSwitching: fields[11] == null ? false : fields[11] as bool,
)
..uriRaw = fields[0] == null ? '' : fields[0] as String
..typeRaw = fields[3] == null ? 0 : fields[3] as int
@@ -72,7 +71,5 @@ class NodeAdapter extends TypeAdapter<Node> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is NodeAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
other is NodeAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
}
+8 -13
View File
@@ -18,7 +18,7 @@ Future<List<Node>> loadDefaultNodes(WalletType type) async {
case WalletType.haven:
path = 'assets/haven_node_list.yml';
break;
// TODO: (refactoring) each wallet would have its path, so `wallet.nodePath` would be decided based on chain id in Evm wallet
// TODO: (refactoring) each wallet would have its path, so `wallet.nodePath` would be decided based on chain id in Evm wallet
case WalletType.ethereum:
path = 'assets/ethereum_server_list.yml';
break;
@@ -147,7 +147,6 @@ Future<List<Node>> loadAllDefaultNodes() async {
}
Future<void> resetToDefault() async {
final nodes = await loadAllDefaultNodes();
final currentNodes = await Node.getAll();
@@ -157,15 +156,14 @@ Future<void> resetToDefault() async {
for (final node in nodes) {
try {
final curr = currentNodes.firstWhere(
(item) => item.uri == node.uri && item.typeRaw == node.typeRaw,
(item) => item.uri == node.uri && item.typeRaw == node.typeRaw,
);
node.id = curr.id;
} catch(e) {}
node.id = curr.id;
} catch (e) {}
}
await Node.deleteAll();
for(final node in nodes) {
for (final node in nodes) {
await node.save();
}
}
@@ -173,7 +171,7 @@ Future<void> resetToDefault() async {
Future<void> resetPowToDefault() async {
final nanoPowNodes = await loadDefaultNanoPowNodes();
await Node.deleteAllPow();
for(final node in nanoPowNodes) {
for (final node in nanoPowNodes) {
node.save();
}
}
@@ -181,12 +179,9 @@ Future<void> resetPowToDefault() async {
Future<Node> getDefaultNodeFromFiles(WalletType type, {bool isPow = false}) async {
final nodes = isPow ? await loadDefaultNanoPowNodes() : await loadDefaultNodes(type);
try {
return nodes.firstWhere((item)=>item.isDefault);
} catch(e) {
return nodes.firstWhere((item) => item.isDefault);
} catch (e) {
// ideally the yamls would always have a default, but this is better than nothing
return nodes.first;
}
}
+1 -1
View File
@@ -1,3 +1,3 @@
bool parseBoolFromString(String string) {
return string.toString() == 'true';
}
}
+2 -1
View File
@@ -52,7 +52,8 @@ BigInt parseFixed(String value, int decimals) {
var fraction = (comps.length == 2 ? comps[1] : "0").padRight(decimals, "0");
if (fraction.length > multiplier.length - 1) {
throw FormatException("fractional component(${fraction.length}) exceeds decimals(${decimals}), underflow, parseFixed");
throw FormatException(
"fractional component(${fraction.length}) exceeds decimals(${decimals}), underflow, parseFixed");
}
final wholeValue = BigInt.parse(whole);
+1 -2
View File
@@ -28,8 +28,7 @@ Future<String> pathForWalletDir({required String name, required WalletType type}
}
Future<String> pathForWallet({required String name, required WalletType type}) async =>
await pathForWalletDir(name: name, type: type)
.then((path) => path + '/$name');
await pathForWalletDir(name: name, type: type).then((path) => path + '/$name');
Future<String> outdatedAndroidPathForWalletDir({required String name}) async {
final directory = await getAppDir();
-1
View File
@@ -56,7 +56,6 @@ class PayjoinSession extends HiveObject {
BigInt get amount => BigInt.parse(rawAmount ?? "0");
set amount(BigInt amount) => rawAmount = amount.toString();
}
enum PayjoinSessionStatus {
+1 -3
View File
@@ -59,7 +59,5 @@ class PayjoinSessionAdapter extends TypeAdapter<PayjoinSession> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is PayjoinSessionAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
other is PayjoinSessionAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
}
+3 -4
View File
@@ -408,14 +408,14 @@ class ERC681URI extends PaymentURI {
static int _getChainID(String path) {
return int.parse(RegExp(
r'@\d*',
).firstMatch(path)?.group(0)?.replaceAll("@", "") ??
r'@\d*',
).firstMatch(path)?.group(0)?.replaceAll("@", "") ??
"1");
}
static (bool, String) _getTargetAddress(String path) {
final targetAddress =
RegExp(r'^(0x)?[0-9a-f]{40}', caseSensitive: false).firstMatch(path)!.group(0)!;
RegExp(r'^(0x)?[0-9a-f]{40}', caseSensitive: false).firstMatch(path)!.group(0)!;
return (path.contains("/"), targetAddress);
}
@@ -508,4 +508,3 @@ class LightningPaymentRequest extends PaymentURI {
@override
String toString() => bolt11Invoice ?? "lightning:$lnURL";
}
+16 -12
View File
@@ -23,12 +23,11 @@ bool get isNonAmnesticTails {
bool showNotice = true;
void setRootDirFromEnv() =>
_rootDirPath = Platform.environment['CAKE_WALLET_DIR'];
void setRootDirFromEnv() => _rootDirPath = Platform.environment['CAKE_WALLET_DIR'];
void copyDirectory(Directory source, Directory destination) {
source.listSync(recursive: false).forEach((var entity) {
if (entity is Directory) {
if (entity is Directory) {
var newDirectory = Directory(p.join(destination.absolute.path, p.basename(entity.path)));
newDirectory.createSync(recursive: true);
copyDirectory(entity.absolute, newDirectory);
@@ -41,7 +40,8 @@ void copyDirectory(Directory source, Directory destination) {
Future<void> linuxSymlinkSharedPreferences() async {
if (!Platform.isLinux) return; // nuh-uh
final dataHome = Platform.environment["XDG_DATA_HOME"] ?? p.join(Platform.environment["HOME"] ?? "", ".local", "share");
final dataHome = Platform.environment["XDG_DATA_HOME"] ??
p.join(Platform.environment["HOME"] ?? "", ".local", "share");
var cakeNames = ['com.example.cake_wallet', 'cake_wallet'];
for (String name in cakeNames) {
final oldPath = p.join(dataHome, name);
@@ -53,8 +53,8 @@ Future<void> linuxSymlinkSharedPreferences() async {
if (oldLink.existsSync()) {
printV("not creating, link exists");
} else {
if (newDir.existsSync()) {
newDir.renameSync("${newPath}_${DateTime.now().millisecondsSinceEpoch~/1000}");
if (newDir.existsSync()) {
newDir.renameSync("${newPath}_${DateTime.now().millisecondsSinceEpoch ~/ 1000}");
}
copyDirectory(oldDir, newDir);
oldDir.deleteSync(recursive: true);
@@ -94,14 +94,16 @@ Future<Directory> getAppDir() async {
// for storing things that users in general back-up
var linuxAppPath = [
if (appDirPath != null) appDirPath, // old preferred
p.join('/home', Platform.environment['USER']??"null", appName), // old fallback
if (Platform.environment['HOME'] != null) p.join(Platform.environment['HOME']!, ".$appName"), // old fallback but using HOME
if (Platform.environment['HOME'] != null) p.join(Platform.environment['HOME']!, '.config', appName), // old fallback but using HOME
p.join('/home', Platform.environment['USER'] ?? "null", appName), // old fallback
if (Platform.environment['HOME'] != null)
p.join(Platform.environment['HOME']!, ".$appName"), // old fallback but using HOME
if (Platform.environment['HOME'] != null)
p.join(Platform.environment['HOME']!, '.config', appName), // old fallback but using HOME
if (isNonAmnesticTails) p.join(_tailsData, ".$appName") // tails (if persistance is enabled)
];
String preferredPath = linuxAppPath.last;
preferredLoop:
for (String notSoPreferredPath in linuxAppPath) {
if (notSoPreferredPath == linuxAppPath.last) continue;
@@ -109,8 +111,10 @@ Future<Directory> getAppDir() async {
if (useThisOne) {
if (showNotice) {
showNotice = false;
printV("Not using $preferredPath because $notSoPreferredPath exists, falling back for backwards compatibility");
printV("Can't see your wallet? Check\n - ${linuxAppPath.join("\n - ")}\n and move directory that to $preferredPath");
printV(
"Not using $preferredPath because $notSoPreferredPath exists, falling back for backwards compatibility");
printV(
"Can't see your wallet? Check\n - ${linuxAppPath.join("\n - ")}\n and move directory that to $preferredPath");
printV("Or use CAKE_WALLET_DIR=/path/to/app/ ${Platform.executable}");
}
preferredPath = notSoPreferredPath;
+2 -1
View File
@@ -14,7 +14,8 @@ Future<Uint8List> secRandom(int count) async {
final rng = Random.secure();
return Uint8List.fromList(List<int>.generate(count, (_) => rng.nextInt(byteSize)));
}
return await utils.invokeMethod<Uint8List>('sec_random', {'count': count}) ?? Uint8List.fromList([]);
return await utils.invokeMethod<Uint8List>('sec_random', {'count': count}) ??
Uint8List.fromList([]);
} on PlatformException catch (_) {
return Uint8List.fromList([]);
}
+2 -4
View File
@@ -4,14 +4,12 @@ import 'package:on_chain/solana/solana.dart';
class SolanaRPCHTTPService implements SolanaJSONRPCService {
SolanaRPCHTTPService(
{required this.url,
this.defaultRequestTimeout = const Duration(seconds: 30)});
{required this.url, this.defaultRequestTimeout = const Duration(seconds: 30)});
@override
final String url;
final Duration defaultRequestTimeout;
Future<Map<String, dynamic>> call(SolanaRequestDetails params,
[Duration? timeout]) async {
Future<Map<String, dynamic>> call(SolanaRequestDetails params, [Duration? timeout]) async {
final response = await ProxyWrapper().post(
clearnetUri: Uri.parse(url),
body: params.toRequestBody(),
+1 -3
View File
@@ -58,7 +58,5 @@ class SPLTokenAdapter extends TypeAdapter<SPLToken> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is SPLTokenAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
other is SPLTokenAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
}
+5 -3
View File
@@ -7,7 +7,8 @@ TransactionDirection parseTransactionDirectionFromInt(int raw) {
case 1:
return TransactionDirection.outgoing;
default:
throw Exception('Unexpected token: raw for TransactionDirection parseTransactionDirectionFromInt');
throw Exception(
'Unexpected token: raw for TransactionDirection parseTransactionDirectionFromInt');
}
}
@@ -18,6 +19,7 @@ TransactionDirection parseTransactionDirectionFromNumber(String raw) {
case "1":
return TransactionDirection.outgoing;
default:
throw Exception('Unexpected token: raw for TransactionDirection parseTransactionDirectionFromNumber');
throw Exception(
'Unexpected token: raw for TransactionDirection parseTransactionDirectionFromNumber');
}
}
}
+1 -2
View File
@@ -2,8 +2,7 @@ import 'package:mobx/mobx.dart';
import 'package:cw_core/transaction_info.dart';
abstract class TransactionHistoryBase<TransactionType extends TransactionInfo> {
TransactionHistoryBase()
: transactions = ObservableMap<String, TransactionType>();
TransactionHistoryBase() : transactions = ObservableMap<String, TransactionType>();
@observable
ObservableMap<String, TransactionType> transactions;
+3 -3
View File
@@ -1,9 +1,9 @@
import 'package:cw_core/enumerable_item.dart';
abstract class TransactionPriority extends EnumerableItem<int>
with Serializable<int> {
abstract class TransactionPriority extends EnumerableItem<int> with Serializable<int> {
final String? description;
final String? hint;
const TransactionPriority({required String title, required int raw, this.description, this.hint}) : super(title: title, raw: raw);
const TransactionPriority({required String title, required int raw, this.description, this.hint})
: super(title: title, raw: raw);
}
+1 -3
View File
@@ -55,7 +55,5 @@ class TronTokenAdapter extends TypeAdapter<TronToken> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is TronTokenAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
other is TronTokenAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
}
+1 -3
View File
@@ -6,9 +6,7 @@ Future<void> write({required String path, required String password, required Str
writeData(path: path, password: password, data: data);
Future<void> writeData(
{required String path,
required String password,
required String data}) async {
{required String path, required String password, required String data}) async {
final keys = extractKeys(password);
final key = encrypt.Key.fromBase64(keys.first);
final iv = encrypt.IV.fromBase64(keys.last);
+3 -3
View File
@@ -11,7 +11,7 @@ enum RequestMethod {
post,
put,
delete,
newHttpClient,
newHttpIOClient,
newProxySocket,
@@ -23,7 +23,7 @@ abstract class ProxyLogger {
required RequestMethod method,
required Uint8List body,
required very_insecure_http_do_not_use.Response? response,
required RequestNetwork network,
required RequestNetwork network,
required String? error,
});
}
}
@@ -46,18 +46,20 @@ class MemoryProxyLogger implements ProxyLogger {
required RequestMethod method,
required Uint8List body,
required very_insecure_http_do_not_use.Response? response,
required RequestNetwork network,
required RequestNetwork network,
required String? error,
}) {
final trace = StackTrace.current;
logs.add(MemoryProxyLoggerEntry(
method: method,
trace: trace,
uri: uri,
body: body,
network: network,
response: response,
error: error,),
logs.add(
MemoryProxyLoggerEntry(
method: method,
trace: trace,
uri: uri,
body: body,
network: network,
response: response,
error: error,
),
);
}
}
}
@@ -11,7 +11,7 @@ class SilentProxyLogger implements ProxyLogger {
required RequestMethod method,
required Uint8List body,
required very_insecure_http_do_not_use.Response? response,
required RequestNetwork network,
required RequestNetwork network,
required String? error,
}) {}
}
}
+10 -7
View File
@@ -16,19 +16,21 @@ class ProxyAddress {
}
abstract class ProxySocket {
static Future<ProxySocket> connect(bool sslEnabled, ProxyAddress address, {Duration? connectionTimeout}) async {
static Future<ProxySocket> connect(bool sslEnabled, ProxyAddress address,
{Duration? connectionTimeout}) async {
if (CakeTor.instance!.started) {
var socksSocket = await SOCKSSocket.create(
proxyHost: InternetAddress.loopbackIPv4.address,
proxyPort: CakeTor.instance!.port,
sslEnabled: sslEnabled,
proxyHost: InternetAddress.loopbackIPv4.address,
proxyPort: CakeTor.instance!.port,
sslEnabled: sslEnabled,
);
await socksSocket.connect();
await socksSocket.connectTo(address.host, address.port);
return ProxySocketSocks(socksSocket);
}
if (sslEnabled == false) {
return ProxySocketInsecure(await Socket.connect(address.host, address.port, timeout: connectionTimeout));
return ProxySocketInsecure(
await Socket.connect(address.host, address.port, timeout: connectionTimeout));
} else {
return ProxySocketSecure(await SecureSocket.connect(
address.host,
@@ -43,6 +45,7 @@ abstract class ProxySocket {
void destroy();
void write(String data);
bool get isClosed;
StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function (Object error)? onError, Function ()? onDone, bool cancelOnError = true});
StreamSubscription<List<int>> listen(Function(Uint8List event) onData,
{Function(Object error)? onError, Function()? onDone, bool cancelOnError = true});
ProxyAddress get address;
}
}
+11 -10
View File
@@ -1,4 +1,3 @@
import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/utils/proxy_socket/abstract.dart';
import 'dart:async';
@@ -9,15 +8,16 @@ class ProxySocketInsecure implements ProxySocket {
final Socket socket;
ProxySocketInsecure(this.socket);
bool isClosed = false;
ProxyAddress get address => ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort);
ProxyAddress get address =>
ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort);
@override
Future<void> close() async {
try {
if (isClosed) return;
if (isClosed) return;
isClosed = true;
return socket.close();
} catch (e) {
@@ -25,7 +25,7 @@ class ProxySocketInsecure implements ProxySocket {
return;
}
}
@override
void destroy() async {
try {
@@ -37,7 +37,7 @@ class ProxySocketInsecure implements ProxySocket {
return;
}
}
@override
void write(String data) {
try {
@@ -51,9 +51,10 @@ class ProxySocketInsecure implements ProxySocket {
return;
}
}
@override
StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
StreamSubscription<List<int>> listen(Function(Uint8List event) onData,
{Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
return socket.listen(
(data) {
onData(Uint8List.fromList(data));
@@ -63,4 +64,4 @@ class ProxySocketInsecure implements ProxySocket {
cancelOnError: cancelOnError,
);
}
}
}
+10 -8
View File
@@ -11,9 +11,10 @@ class ProxySocketSecure implements ProxySocket {
bool isClosed = false;
ProxySocketSecure(this.socket);
ProxyAddress get address => ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort);
ProxyAddress get address =>
ProxyAddress(host: socket.remoteAddress.host, port: socket.remotePort);
@override
Future<void> close() async {
try {
@@ -25,11 +26,11 @@ class ProxySocketSecure implements ProxySocket {
return;
}
}
@override
void destroy() async {
try {
if (isClosed) return;
if (isClosed) return;
isClosed = true;
socket.destroy();
} catch (e) {
@@ -37,7 +38,7 @@ class ProxySocketSecure implements ProxySocket {
return;
}
}
@override
void write(String data) {
runZonedGuarded(() {
@@ -57,9 +58,10 @@ class ProxySocketSecure implements ProxySocket {
printV("ProxySocketSecure: write (async error): $e");
});
}
@override
StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
StreamSubscription<List<int>> listen(Function(Uint8List event) onData,
{Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
return socket.listen(
(data) {
onData(Uint8List.fromList(data));
+6 -6
View File
@@ -9,10 +9,10 @@ class ProxySocketSocks implements ProxySocket {
final SOCKSSocket socket;
bool isClosed = false;
ProxySocketSocks(this.socket);
@override
ProxyAddress get address => ProxyAddress(host: socket.proxyHost, port: socket.proxyPort);
@override
Future<void> close() async {
try {
@@ -24,10 +24,10 @@ class ProxySocketSocks implements ProxySocket {
return;
}
}
@override
void destroy() => close();
@override
void write(String data) {
try {
@@ -43,7 +43,8 @@ class ProxySocketSocks implements ProxySocket {
}
@override
StreamSubscription<List<int>> listen(Function(Uint8List event) onData, {Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
StreamSubscription<List<int>> listen(Function(Uint8List event) onData,
{Function(Object error)? onError, Function()? onDone, bool cancelOnError = true}) {
return socket.listen(
(data) {
onData(Uint8List.fromList(data));
@@ -54,4 +55,3 @@ class ProxySocketSocks implements ProxySocket {
);
}
}
+23 -27
View File
@@ -16,22 +16,23 @@ class ProxyWrapper {
factory ProxyWrapper() {
return _proxyWrapper;
}
ProxyWrapper._internal();
Future<ProxySocket> getSocksSocket(bool sslEnabled, String host, int port, {Duration? connectionTimeout}) async {
Future<ProxySocket> getSocksSocket(bool sslEnabled, String host, int port,
{Duration? connectionTimeout}) async {
logger?.log(
uri: Uri(
scheme: sslEnabled ? "https" : "http",
host: host,
port: port,
),
method: RequestMethod.newProxySocket,
body: Uint8List(0),
response: null,
network: requestNetwork(),
error: null
);
return ProxySocket.connect(sslEnabled, ProxyAddress(host: host, port: port), connectionTimeout: connectionTimeout);
uri: Uri(
scheme: sslEnabled ? "https" : "http",
host: host,
port: port,
),
method: RequestMethod.newProxySocket,
body: Uint8List(0),
response: null,
network: requestNetwork(),
error: null);
return ProxySocket.connect(sslEnabled, ProxyAddress(host: host, port: port),
connectionTimeout: connectionTimeout);
}
RequestNetwork requestNetwork() {
@@ -56,17 +57,17 @@ class ProxyWrapper {
int getPort() => CakeTor.instance!.port;
@Deprecated('Use ProxyWrapper().get/post/put methods instead, and provide proper clearnet and onion uri.')
@Deprecated(
'Use ProxyWrapper().get/post/put methods instead, and provide proper clearnet and onion uri.')
HttpClient getHttpClient({int? portOverride, bool internal = false}) {
if (!internal) {
logger?.log(
uri: null,
method: RequestMethod.newProxySocket,
body: Uint8List(0),
response: null,
network: requestNetwork(),
error: null
);
uri: null,
method: RequestMethod.newProxySocket,
body: Uint8List(0),
response: null,
network: requestNetwork(),
error: null);
}
if (CakeTor.instance!.started) {
// Assign connection factory.
@@ -84,8 +85,6 @@ class ProxyWrapper {
}
}
Future<Response> _make({
required RequestMethod method,
required ioc.IOClient client,
@@ -216,7 +215,6 @@ class ProxyWrapper {
throw Exception("Unable to connect to server");
}
Future<Response> post({
Map<String, String>? headers,
@@ -235,7 +233,6 @@ class ProxyWrapper {
ioc.IOClient clearnetClient = ioc.IOClient(cleatnetHttpClient);
bool torEnabled = CakeTor.instance!.started;
if (torEnabled) {
@@ -439,7 +436,6 @@ class ProxyWrapper {
}
}
class CakeTor {
static CakeTorInstance? instance;
}
+1 -1
View File
@@ -65,4 +65,4 @@ CakeTorInstance(
)
""";
}
}
}
+1 -1
View File
@@ -30,4 +30,4 @@ CakeTorDisabled(
)
""";
}
}
}
+1 -1
View File
@@ -31,4 +31,4 @@ CakeTorSocks(
)
""";
}
}
}
+1 -1
View File
@@ -88,4 +88,4 @@ CakeTorTorch(
)
""";
}
}
}
+11 -11
View File
@@ -1,4 +1,3 @@
import 'dart:typed_data';
import 'package:blockchain_utils/blockchain_utils.dart';
@@ -15,31 +14,32 @@ String convertAnyToXpub(String any) {
String convertZpubToXpub(String zpub) {
try {
final decoded = Base58Decoder.checkDecode(zpub);
if (decoded.length < 4) {
throw ArgumentError('Invalid extended public key length');
}
final versionBytes = decoded.sublist(0, 4);
final zpubVersionBytes = [0x04, 0xb2, 0x47, 0x46]; // zpub mainnet version
final zpubTestnetVersionBytes = [0x04, 0x5f, 0x1c, 0xf6]; // vpub testnet version
bool isZpub = listEquals(versionBytes, zpubVersionBytes);
bool isVpub = listEquals(versionBytes, zpubTestnetVersionBytes);
if (!isZpub && !isVpub) {
return zpub;
}
final xpubVersionBytes = isZpub ?
[0x04, 0x88, 0xb2, 0x1e] : // xpub mainnet
[0x04, 0x35, 0x87, 0xcf]; // tpub testnet
final xpubVersionBytes = isZpub
? [0x04, 0x88, 0xb2, 0x1e]
: // xpub mainnet
[0x04, 0x35, 0x87, 0xcf]; // tpub testnet
final newExtendedKey = Uint8List.fromList([
...xpubVersionBytes,
...decoded.sublist(4),
]);
return Base58Encoder.checkEncode(newExtendedKey);
} catch (e) {
throw ArgumentError('Failed to convert zpub to xpub: $e');
+119 -121
View File
@@ -327,79 +327,77 @@ class DerivationInfo {
class WalletInfo {
WalletInfo(
this.internalId,
this.id,
this.name,
this.type,
this.isRecovery,
this.restoreHeight,
this.timestamp,
this.dirPath,
this.path,
this.address,
this.yatEid,
this.yatLastUsedAddressRaw,
this.showIntroCakePayCard,
this.derivationInfoId,
this.hardwareWalletType,
this.parentAddress,
this.hashedWalletIdentifier,
this.isNonSeedWallet,
this.sortOrder,
this.addressPageType,
this.receiveInfoboxDismissed,
this.showCombinedBalance,
this.favoriteTokenAddress
) : _yatLastUsedAddressController = StreamController<String>.broadcast();
this.internalId,
this.id,
this.name,
this.type,
this.isRecovery,
this.restoreHeight,
this.timestamp,
this.dirPath,
this.path,
this.address,
this.yatEid,
this.yatLastUsedAddressRaw,
this.showIntroCakePayCard,
this.derivationInfoId,
this.hardwareWalletType,
this.parentAddress,
this.hashedWalletIdentifier,
this.isNonSeedWallet,
this.sortOrder,
this.addressPageType,
this.receiveInfoboxDismissed,
this.showCombinedBalance,
this.favoriteTokenAddress)
: _yatLastUsedAddressController = StreamController<String>.broadcast();
factory WalletInfo.external({
required String id,
required String name,
required WalletType type,
required bool isRecovery,
required int restoreHeight,
required DateTime date,
required String dirPath,
required String path,
required String address,
bool? showIntroCakePayCard,
String yatEid = '',
String yatLastUsedAddressRaw = '',
int? derivationInfoId,
HardwareWalletType? hardwareWalletType,
String? parentAddress,
String? hashedWalletIdentifier,
bool? isNonSeedWallet,
int? sortOrder,
bool? receiveInfoboxDismissed,
bool? showCombinedBalance,
String? favoriteTokenAddress
}) {
factory WalletInfo.external(
{required String id,
required String name,
required WalletType type,
required bool isRecovery,
required int restoreHeight,
required DateTime date,
required String dirPath,
required String path,
required String address,
bool? showIntroCakePayCard,
String yatEid = '',
String yatLastUsedAddressRaw = '',
int? derivationInfoId,
HardwareWalletType? hardwareWalletType,
String? parentAddress,
String? hashedWalletIdentifier,
bool? isNonSeedWallet,
int? sortOrder,
bool? receiveInfoboxDismissed,
bool? showCombinedBalance,
String? favoriteTokenAddress}) {
return WalletInfo(
0,
id,
name,
type,
isRecovery,
restoreHeight,
date.millisecondsSinceEpoch,
dirPath,
path,
address,
yatEid,
yatLastUsedAddressRaw,
showIntroCakePayCard,
derivationInfoId ?? -1,
hardwareWalletType,
parentAddress,
hashedWalletIdentifier,
isNonSeedWallet ?? false,
sortOrder ?? 0,
null,
receiveInfoboxDismissed ?? false,
showCombinedBalance ?? true,
favoriteTokenAddress
);
0,
id,
name,
type,
isRecovery,
restoreHeight,
date.millisecondsSinceEpoch,
dirPath,
path,
address,
yatEid,
yatLastUsedAddressRaw,
showIntroCakePayCard,
derivationInfoId ?? -1,
hardwareWalletType,
parentAddress,
hashedWalletIdentifier,
isNonSeedWallet ?? false,
sortOrder ?? 0,
null,
receiveInfoboxDismissed ?? false,
showCombinedBalance ?? true,
favoriteTokenAddress);
}
static String get tableName => 'walletInfo';
@@ -565,59 +563,59 @@ class WalletInfo {
StreamController<String> _yatLastUsedAddressController;
Map<String, dynamic> toJson() => {
selfIdColumn: internalId,
"id": id,
"name": name,
"type": type.index,
"isRecovery": isRecovery ? 1 : 0,
"restoreHeight": restoreHeight,
"timestamp": timestamp,
"dirPath": dirPath,
"path": path,
"address": address,
"yatEid": yatEid,
"yatLastUsedAddressRaw": yatLastUsedAddressRaw,
"showIntroCakePayCard": showIntroCakePayCard == true ? 1 : 0, // SQL regression: null -> false
"walletInfoDerivationInfoId": derivationInfoId,
"hardwareWalletType": hardwareWalletType?.index,
"parentAddress": parentAddress,
"hashedWalletIdentifier": hashedWalletIdentifier,
"isNonSeedWallet": isNonSeedWallet ? 1 : 0,
"sortOrder": sortOrder,
"addressPageType": addressPageType,
"receiveInfoboxDismissed": receiveInfoboxDismissed ? 1 : 0,
"showCombinedBalance": showCombinedBalance ? 1 : 0,
"favoriteTokenAddress": favoriteTokenAddress
};
selfIdColumn: internalId,
"id": id,
"name": name,
"type": type.index,
"isRecovery": isRecovery ? 1 : 0,
"restoreHeight": restoreHeight,
"timestamp": timestamp,
"dirPath": dirPath,
"path": path,
"address": address,
"yatEid": yatEid,
"yatLastUsedAddressRaw": yatLastUsedAddressRaw,
"showIntroCakePayCard":
showIntroCakePayCard == true ? 1 : 0, // SQL regression: null -> false
"walletInfoDerivationInfoId": derivationInfoId,
"hardwareWalletType": hardwareWalletType?.index,
"parentAddress": parentAddress,
"hashedWalletIdentifier": hashedWalletIdentifier,
"isNonSeedWallet": isNonSeedWallet ? 1 : 0,
"sortOrder": sortOrder,
"addressPageType": addressPageType,
"receiveInfoboxDismissed": receiveInfoboxDismissed ? 1 : 0,
"showCombinedBalance": showCombinedBalance ? 1 : 0,
"favoriteTokenAddress": favoriteTokenAddress
};
factory WalletInfo.fromJson(Map<String, dynamic> json) {
return WalletInfo(
json[selfIdColumn] as int,
json['id'] as String,
json['name'] as String,
WalletType.values[json['type'] as int],
(json['isRecovery'] as int) == 1,
json['restoreHeight'] as int,
json['timestamp'] as int,
json['dirPath'] as String,
json['path'] as String,
json['address'] as String,
json['yatEid'] as String?,
json['yatLastUsedAddressRaw'] as String?,
(json['showIntroCakePayCard'] as int) == 1,
json['walletInfoDerivationInfoId'] as int,
json['hardwareWalletType'] == null
? null
: HardwareWalletType.values[json['hardwareWalletType'] as int],
json['parentAddress'] as String?,
json['hashedWalletIdentifier'] as String?,
(json['isNonSeedWallet'] as int) == 1,
json['sortOrder'] as int? ?? 0,
json['addressPageType'] as String? ?? null,
json['receiveInfoboxDismissed'] != 0,
json["showCombinedBalance"] != 0,
json["favoriteTokenAddress"] as String? ?? null
);
json[selfIdColumn] as int,
json['id'] as String,
json['name'] as String,
WalletType.values[json['type'] as int],
(json['isRecovery'] as int) == 1,
json['restoreHeight'] as int,
json['timestamp'] as int,
json['dirPath'] as String,
json['path'] as String,
json['address'] as String,
json['yatEid'] as String?,
json['yatLastUsedAddressRaw'] as String?,
(json['showIntroCakePayCard'] as int) == 1,
json['walletInfoDerivationInfoId'] as int,
json['hardwareWalletType'] == null
? null
: HardwareWalletType.values[json['hardwareWalletType'] as int],
json['parentAddress'] as String?,
json['hashedWalletIdentifier'] as String?,
(json['isNonSeedWallet'] as int) == 1,
json['sortOrder'] as int? ?? 0,
json['addressPageType'] as String? ?? null,
json['receiveInfoboxDismissed'] != 0,
json["showCombinedBalance"] != 0,
json["favoriteTokenAddress"] as String? ?? null);
}
Future<int> save() async {
+1 -1
View File
@@ -201,7 +201,7 @@ class WalletInfo extends HiveObject {
// @HiveField(22)
String? parentAddress;
// @HiveField(23)
List<String>? hiddenAddresses;
+5 -11
View File
@@ -53,9 +53,7 @@ class DerivationInfoAdapter extends TypeAdapter<DerivationInfo> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is DerivationInfoAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
other is DerivationInfoAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
}
class WalletInfoAdapter extends TypeAdapter<WalletInfo> {
@@ -88,8 +86,8 @@ class WalletInfoAdapter extends TypeAdapter<WalletInfo> {
fields[26] == null ? false : fields[26] as bool,
)
..addresses = (fields[10] as Map?)?.cast<String, String>()
..addressInfos = (fields[14] as Map?)?.map((dynamic k, dynamic v) =>
MapEntry(k as int, (v as List).cast<AddressInfo>()))
..addressInfos = (fields[14] as Map?)
?.map((dynamic k, dynamic v) => MapEntry(k as int, (v as List).cast<AddressInfo>()))
..usedAddresses = (fields[15] as List?)?.cast<String>()
..derivationType = fields[16] as newWi.DerivationType?
..derivationPath = fields[17] as String?
@@ -163,9 +161,7 @@ class WalletInfoAdapter extends TypeAdapter<WalletInfo> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is WalletInfoAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
other is WalletInfoAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
}
class DerivationTypeAdapter extends TypeAdapter<newWi.DerivationType> {
@@ -217,9 +213,7 @@ class DerivationTypeAdapter extends TypeAdapter<newWi.DerivationType> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is DerivationTypeAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
other is DerivationTypeAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
}
class HardwareWalletTypeAdapter extends TypeAdapter<newWi.HardwareWalletType> {
+8 -1
View File
@@ -101,7 +101,14 @@ class WalletKeysData {
final String? scanSecret;
final String? spendPubkey;
WalletKeysData({this.privateKey, this.mnemonic, this.altMnemonic, this.passphrase, this.xPub, this.scanSecret, this.spendPubkey});
WalletKeysData(
{this.privateKey,
this.mnemonic,
this.altMnemonic,
this.passphrase,
this.xPub,
this.scanSecret,
this.spendPubkey});
String toJSON() => jsonEncode({
"privateKey": privateKey,
+13 -12
View File
@@ -334,17 +334,18 @@ WalletType? _cryptoCurrencyToWalletType(CryptoCurrency type) {
WalletType? cryptoCurrencyOrTokenToWalletType(CryptoCurrency type) {
try {
if(type.tag == CryptoCurrency.bnb.tag) {
return _cryptoCurrencyToWalletType(CryptoCurrency.bnb);
if (type.tag == CryptoCurrency.bnb.tag) {
return _cryptoCurrencyToWalletType(CryptoCurrency.bnb);
}
if (type.tag != null &&
![CryptoCurrency.btcln.tag, CryptoCurrency.bnb.tag].contains(type.tag)) {
return _cryptoCurrencyToWalletType(CryptoCurrency.fromString(type.tag!));
} else {
return _cryptoCurrencyToWalletType(type);
}
} catch (e) {
printV(e);
return null;
}
if(type.tag != null && ![CryptoCurrency.btcln.tag, CryptoCurrency.bnb.tag].contains(type.tag)) {
return _cryptoCurrencyToWalletType(CryptoCurrency.fromString(type.tag!));
} else {
return _cryptoCurrencyToWalletType(type);
}
} catch (e) {
printV(e);
return null;
}
}
+1 -3
View File
@@ -130,7 +130,5 @@ class WalletTypeAdapter extends TypeAdapter<WalletType> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is WalletTypeAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
other is WalletTypeAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
}
+1 -1
View File
@@ -15,4 +15,4 @@ double wowneroAmountToDouble({required int amount}) =>
cryptoAmountToDouble(amount: amount, divider: wowneroAmountDivider);
int wowneroParseAmount({required String amount}) =>
(double.parse(amount) * wowneroAmountDivider).round();
(double.parse(amount) * wowneroAmountDivider).round();
+1 -3
View File
@@ -70,7 +70,5 @@ class ZanoAssetAdapter extends TypeAdapter<ZanoAsset> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ZanoAssetAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
other is ZanoAssetAdapter && runtimeType == other.runtimeType && typeId == other.typeId;
}
@@ -3,27 +3,27 @@ import 'package:flutter_test/flutter_test.dart';
void main() {
group('smartAmountSanitizer', () {
test('sanitize decimal dot', (){
test('sanitize decimal dot', () {
final amount = "1,000.00".sanitized();
expect(amount, "1000.00");
});
test('sanitize decimal comma', (){
test('sanitize decimal comma', () {
final amount = "1.000,00".sanitized();
expect(amount, "1000.00");
});
test('general case', (){
test('general case', () {
final amount = "1000.00".sanitized();
expect(amount, "1000.00");
});
test('no decimals', (){
test('no decimals', () {
final amount = "1,000".sanitized();
expect(amount, "1.000");
});
test('no decimals', (){
test('no decimals', () {
final amount = "1.000".sanitized();
expect(amount, "1.000");
});
+2 -2
View File
@@ -316,7 +316,7 @@ void main() {
});
});
group("toStringWithPrecision", (){
group("toStringWithPrecision", () {
test("with fractionalDigits and padded with zeros", () {
final money = Money.parse("1", CryptoCurrency.btc);
expect(money.amount, equals(BigInt.parse("100000000")));
@@ -332,7 +332,7 @@ void main() {
});
});
group("toStringWithSymbol", (){
group("toStringWithSymbol", () {
test("with fractionalDigits and padded with zeros", () {
final money = Money.parse("1", CryptoCurrency.btc);
expect(money.amount, equals(BigInt.parse("100000000")));
+3 -3
View File
@@ -35,7 +35,7 @@ void main() {
group('String.withLocalSeperator', () {
group('Locale en_US', () {
const locale = 'en_US';
test('should not have a grouping separator', () {
final input = '123.45';
final result = input.withLocalSeperator(locale);
@@ -57,10 +57,10 @@ void main() {
expect(result, equals('1,000,000.4567'));
});
});
group('Locale de_DE', () {
const locale = 'de_DE';
test('should not have a grouping separator', () {
final input = '123.45';
final result = input.withLocalSeperator(locale);
+4 -8
View File
@@ -14,14 +14,12 @@ void main() {
group('formatFixed, different fractional digits and trimming zeros', () {
test(
'should format 1000001 into 1',
() => expect(
formatFixed(BigInt.parse("1000001"), 6, fractionalDigits: 5), '1'),
() => expect(formatFixed(BigInt.parse("1000001"), 6, fractionalDigits: 5), '1'),
);
test(
'should format 1000000 into 1, fractionalDigits > decimals',
() => expect(
formatFixed(BigInt.parse("1000000"), 6, fractionalDigits: 12), '1'),
() => expect(formatFixed(BigInt.parse("1000000"), 6, fractionalDigits: 12), '1'),
);
test(
@@ -45,8 +43,7 @@ void main() {
test(
'should format 1000001 into 1.00000',
() => expect(
formatFixed(BigInt.parse("1000001"), 6,
fractionalDigits: 5, trimZeros: false),
formatFixed(BigInt.parse("1000001"), 6, fractionalDigits: 5, trimZeros: false),
'1.00000',
),
);
@@ -54,8 +51,7 @@ void main() {
test(
'should format 1000000 into 1.000000',
() => expect(
formatFixed(BigInt.parse("1000000"), 6,
fractionalDigits: 12, trimZeros: false),
formatFixed(BigInt.parse("1000000"), 6, fractionalDigits: 12, trimZeros: false),
'1.000000',
),
);
+18 -9
View File
@@ -39,49 +39,58 @@ void main() {
group("isBolt11ZeroInvoice", () {
test("should identify a zero amount invoice", () {
final invoice = "lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
final invoice =
"lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
expect(isBolt11ZeroInvoice(invoice), true);
});
test("should identify a non zero amount invoice", () {
final invoice = "lnbc1u1p5564nxpp5mrklx2pjaggkcfs9r5tfk84wszzy9gypcnrt9yjq7n6uf95s70xqsp59fph78twjra598n2mll2arw5enluy7a4uf4y9a94ddd30hm98njsxq9z0rgqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qcqzpgdql2djkuepqw3hjqsmpddjjq4mpd3kx2aq9qyyssq3nf60ey9fgkf0elu2y8j96rx5pm4gx2a976h8yadx83dyg0ltnysrxhep8e2p3yvz4kf597qk3rttgdy72wwqq0mwr8hdht3pqpchyqq0aa9v0";
final invoice =
"lnbc1u1p5564nxpp5mrklx2pjaggkcfs9r5tfk84wszzy9gypcnrt9yjq7n6uf95s70xqsp59fph78twjra598n2mll2arw5enluy7a4uf4y9a94ddd30hm98njsxq9z0rgqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qcqzpgdql2djkuepqw3hjqsmpddjjq4mpd3kx2aq9qyyssq3nf60ey9fgkf0elu2y8j96rx5pm4gx2a976h8yadx83dyg0ltnysrxhep8e2p3yvz4kf597qk3rttgdy72wwqq0mwr8hdht3pqpchyqq0aa9v0";
expect(isBolt11ZeroInvoice(invoice), false);
});
test("should identify a zero amount prefixed invoice", () {
final invoice = "lightning:lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
final invoice =
"lightning:lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
expect(isBolt11ZeroInvoice(invoice), true);
});
test("should identify a non zero amount prefixed invoice", () {
final invoice = "lightning:lnbc1u1p5564nxpp5mrklx2pjaggkcfs9r5tfk84wszzy9gypcnrt9yjq7n6uf95s70xqsp59fph78twjra598n2mll2arw5enluy7a4uf4y9a94ddd30hm98njsxq9z0rgqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qcqzpgdql2djkuepqw3hjqsmpddjjq4mpd3kx2aq9qyyssq3nf60ey9fgkf0elu2y8j96rx5pm4gx2a976h8yadx83dyg0ltnysrxhep8e2p3yvz4kf597qk3rttgdy72wwqq0mwr8hdht3pqpchyqq0aa9v0";
final invoice =
"lightning:lnbc1u1p5564nxpp5mrklx2pjaggkcfs9r5tfk84wszzy9gypcnrt9yjq7n6uf95s70xqsp59fph78twjra598n2mll2arw5enluy7a4uf4y9a94ddd30hm98njsxq9z0rgqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qcqzpgdql2djkuepqw3hjqsmpddjjq4mpd3kx2aq9qyyssq3nf60ey9fgkf0elu2y8j96rx5pm4gx2a976h8yadx83dyg0ltnysrxhep8e2p3yvz4kf597qk3rttgdy72wwqq0mwr8hdht3pqpchyqq0aa9v0";
expect(isBolt11ZeroInvoice(invoice), false);
});
});
group("getBolt11Amount", () {
test("should identify a zero amount invoice", () {
final invoice = "lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
final invoice =
"lnbc1p5564y8pp5vm48jp3w82yjssrtdhvrjacwwzp59hqjm2lq6fud5thfznyuswgqsp54mykkptx9mlqhpe93f9pcgt9p5ml5xhclyn7qsltqy9ldf25j3qqxqyz5vqnp4qvyndeaqzman7h898jxm98dzkm0mlrsx36s93smrur7h0azyyuxc5rzjqwghf7zxvfkxq5a6sr65g0gdkv768p83mhsnt0msszapamzx2qvuxqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjq25carzepgd4vqsyn44jrk85ezrpju92xyrk9apw4cdjh6yrwt5jgqqqqrt49lmtcqqqqqqqqqqq86qq9qrzjqfvmpdwfesckajzfcf7ff2vqaz9jdgpcsa9xc0fq8ny749dy8y5geapyqr6zgqqqq8hxk2qqae4jsqyugqcqzpgdqq9qyyssqycdyx8r09wgm8vny3n8pf2e0crcdq9mgx3ncxvzsrkljxyrcuwx8zjtje7du40nzdy7x2he67v9asp6ac6ed75r33yyt9pzeepygcmsptc4ve4";
expect(getBolt11Amount(invoice), null);
});
test("should get the amount 1 BTC encoded as bitcoin", () {
final invoice = "lnbc11p5exaxspp5u6e6lx90rw2vqr2e5axt8ur3v98qnmqfsmh8r0l0mcm7ry70vyvsdqqcqzzsxqrrsssp5eqydmrufk39dwhuxzajwx4xyffn0mlcu3qa8vjwry6qev5gsepkq9qxpqysgqt0zldve9uxt3txjt8wp0gev52lquljgugy26nneue85pjwk5yak4hs2d8533tus07pq5ka6zrnd0ruaeepwres8p7ws5mx63xlwff5sqlxcy8a";
final invoice =
"lnbc11p5exaxspp5u6e6lx90rw2vqr2e5axt8ur3v98qnmqfsmh8r0l0mcm7ry70vyvsdqqcqzzsxqrrsssp5eqydmrufk39dwhuxzajwx4xyffn0mlcu3qa8vjwry6qev5gsepkq9qxpqysgqt0zldve9uxt3txjt8wp0gev52lquljgugy26nneue85pjwk5yak4hs2d8533tus07pq5ka6zrnd0ruaeepwres8p7ws5mx63xlwff5sqlxcy8a";
expect(getBolt11Amount(invoice), Money.fromInt(100000000, CryptoCurrency.btcln));
});
test("should get the amount 0,1 BTC encoded as millibitcoin", () {
final invoice = "lnbc100m1p5exagmpp5n4c5tml3h8h7k4gthc9papkyeymceqqvcldkng4nvxwzj7nu9jnsdqqcqzzsxqrrsssp58kgzrh7y3pevantduc4yg33aa6r79ed6xgmhr0dy40zc8pxrz5ms9qxpqysgqcq27km3v3wcz6pntmsfnz259zy6tff0uwjz9kamdrvmxmdv09gp44mh0ygn7gweqf4zdev4x8e67p5kcvahethchdkkjexhtk7emuqcpasz0lp";
final invoice =
"lnbc100m1p5exagmpp5n4c5tml3h8h7k4gthc9papkyeymceqqvcldkng4nvxwzj7nu9jnsdqqcqzzsxqrrsssp58kgzrh7y3pevantduc4yg33aa6r79ed6xgmhr0dy40zc8pxrz5ms9qxpqysgqcq27km3v3wcz6pntmsfnz259zy6tff0uwjz9kamdrvmxmdv09gp44mh0ygn7gweqf4zdev4x8e67p5kcvahethchdkkjexhtk7emuqcpasz0lp";
expect(getBolt11Amount(invoice), Money.fromInt(10000000, CryptoCurrency.btcln));
});
test("should get the amount 1000 SATS encoded as microbitcoin", () {
final invoice = "lnbc10u1p5exfgvpp5n3s9dsw9ddax5c3h8437ya7y4g582uyufyna626yr9vqdfjrhwzqdqqcqzzsxqrrsssp5mmkyp5h35fpaxm4063f3kc7d4nmgd4gd8fv8086wxd784m76kmpq9qxpqysgqye9r0vahpjy9l2je6vakxzk3cjnsyx76r29c4amkz4cmapq5tqt5l7rl0emkd003jjvz2d8jqrw6wc4cduvapuyeseh7a855l82wutcpeq30kg";
final invoice =
"lnbc10u1p5exfgvpp5n3s9dsw9ddax5c3h8437ya7y4g582uyufyna626yr9vqdfjrhwzqdqqcqzzsxqrrsssp5mmkyp5h35fpaxm4063f3kc7d4nmgd4gd8fv8086wxd784m76kmpq9qxpqysgqye9r0vahpjy9l2je6vakxzk3cjnsyx76r29c4amkz4cmapq5tqt5l7rl0emkd003jjvz2d8jqrw6wc4cduvapuyeseh7a855l82wutcpeq30kg";
expect(getBolt11Amount(invoice), Money.fromInt(1000, CryptoCurrency.btcln));
});
test("should get the amount 1 SAT encoded as nanobitcoin", () {
final invoice = "lnbc10n1p5exazppp5szh273r6nzvwydzsdlg0ws0vhxwnc6nqtqt4sjt0vu6x6l8t5csqdqqcqzzsxqrrsssp5nkup6uht7xlfqaj8lxpe5kx0ejum9p4pvv3nlnndr9ykzge3393s9qxpqysgqufh05a7qs0ezeckvmh7tjkr9ngng96nq274twg20z45ysp7afpdrttm2ky73cpjwpjqsmtzzd79w6lyvszgmkanwn8mj0jcfunrwv3qprg3z3j";
final invoice =
"lnbc10n1p5exazppp5szh273r6nzvwydzsdlg0ws0vhxwnc6nqtqt4sjt0vu6x6l8t5csqdqqcqzzsxqrrsssp5nkup6uht7xlfqaj8lxpe5kx0ejum9p4pvv3nlnndr9ykzge3393s9qxpqysgqufh05a7qs0ezeckvmh7tjkr9ngng96nq274twg20z45ysp7afpdrttm2ky73cpjwpjqsmtzzd79w6lyvszgmkanwn8mj0jcfunrwv3qprg3z3j";
expect(getBolt11Amount(invoice), Money.fromInt(1, CryptoCurrency.btcln));
});
});