mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-26 06:08:40 +01:00
Reformat the whole codebase with 100 line width (#3403)
This commit is contained in:
@@ -9,4 +9,4 @@ class Account {
|
||||
final int id;
|
||||
final String label;
|
||||
final String? balance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
||||
abstract class AccountList<T> {
|
||||
|
||||
ObservableList<T> get accounts;
|
||||
|
||||
void update();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ String _smartAmountSanitizer(String amount) {
|
||||
return amount.replaceAll(",", ".");
|
||||
}
|
||||
|
||||
|
||||
extension SanitizerUserAmounts on String {
|
||||
String sanitized() => _smartAmountSanitizer(this);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
+842
-143
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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(() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -69,4 +69,4 @@ class WalletDeprecationException implements Exception {
|
||||
String toString() => "Wallet type no longer supported";
|
||||
|
||||
WalletDeprecationException({required this.seed, required this.curr});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,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 = [
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,3 +1,3 @@
|
||||
mixin Keyable {
|
||||
dynamic keyIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)!;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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 (_) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,3 +1,3 @@
|
||||
bool parseBoolFromString(String string) {
|
||||
return string.toString() == 'true';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -56,7 +56,6 @@ class PayjoinSession extends HiveObject {
|
||||
|
||||
BigInt get amount => BigInt.parse(rawAmount ?? "0");
|
||||
set amount(BigInt amount) => rawAmount = amount.toString();
|
||||
|
||||
}
|
||||
|
||||
enum PayjoinSessionStatus {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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([]);
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
}) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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 {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -65,4 +65,4 @@ CakeTorInstance(
|
||||
)
|
||||
""";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,4 +30,4 @@ CakeTorDisabled(
|
||||
)
|
||||
""";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,4 +31,4 @@ CakeTorSocks(
|
||||
)
|
||||
""";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,4 +88,4 @@ CakeTorTorch(
|
||||
)
|
||||
""";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-11
@@ -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
@@ -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 {
|
||||
|
||||
@@ -201,7 +201,7 @@ class WalletInfo extends HiveObject {
|
||||
|
||||
// @HiveField(22)
|
||||
String? parentAddress;
|
||||
|
||||
|
||||
// @HiveField(23)
|
||||
List<String>? hiddenAddresses;
|
||||
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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");
|
||||
});
|
||||
|
||||
@@ -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")));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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',
|
||||
),
|
||||
);
|
||||
|
||||
@@ -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));
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user