extend electrum

This commit is contained in:
Matthew Fosse 2024-03-04 09:47:39 -08:00
parent 274540664a
commit 5ad0aa42fb
12 changed files with 133 additions and 128 deletions

View file

@ -23,6 +23,7 @@ import 'package:cw_bitcoin/litecoin_network.dart';
import 'package:cw_bitcoin/pending_bitcoin_transaction.dart'; import 'package:cw_bitcoin/pending_bitcoin_transaction.dart';
import 'package:cw_bitcoin/script_hash.dart'; import 'package:cw_bitcoin/script_hash.dart';
import 'package:cw_bitcoin/utils.dart'; import 'package:cw_bitcoin/utils.dart';
import 'package:cw_core/balance.dart';
import 'package:cw_core/crypto_currency.dart'; import 'package:cw_core/crypto_currency.dart';
import 'package:cw_core/node.dart'; import 'package:cw_core/node.dart';
import 'package:cw_core/pathForWallet.dart'; import 'package:cw_core/pathForWallet.dart';
@ -45,9 +46,8 @@ part 'electrum_wallet.g.dart';
class ElectrumWallet = ElectrumWalletBase with _$ElectrumWallet; class ElectrumWallet = ElectrumWalletBase with _$ElectrumWallet;
abstract class ElectrumWalletBase abstract class ElectrumWalletBase<T extends ElectrumBalance>
extends WalletBase<ElectrumBalance, ElectrumTransactionHistory, ElectrumTransactionInfo> extends WalletBase<T, ElectrumTransactionHistory, ElectrumTransactionInfo> with Store {
with Store {
ElectrumWalletBase( ElectrumWalletBase(
{required String password, {required String password,
required WalletInfo walletInfo, required WalletInfo walletInfo,
@ -55,9 +55,14 @@ abstract class ElectrumWalletBase
required this.networkType, required this.networkType,
required this.mnemonic, required this.mnemonic,
required Uint8List seedBytes, required Uint8List seedBytes,
required T Function({
required int confirmed,
required int unconfirmed,
required int frozen,
}) this.balanceFactory,
List<BitcoinAddressRecord>? initialAddresses, List<BitcoinAddressRecord>? initialAddresses,
ElectrumClient? electrumClient, ElectrumClient? electrumClient,
ElectrumBalance? initialBalance, T? initialBalance,
CryptoCurrency? currency}) CryptoCurrency? currency})
: hd = currency == CryptoCurrency.bch : hd = currency == CryptoCurrency.bch
? bitcoinCashHDWallet(seedBytes) ? bitcoinCashHDWallet(seedBytes)
@ -69,12 +74,8 @@ abstract class ElectrumWalletBase
isEnabledAutoGenerateSubaddress = true, isEnabledAutoGenerateSubaddress = true,
unspentCoins = [], unspentCoins = [],
_scripthashesUpdateSubject = {}, _scripthashesUpdateSubject = {},
balance = ObservableMap<CryptoCurrency, ElectrumBalance>.of(currency != null balance = ObservableMap<CryptoCurrency, T>.of(
? { currency != null ? {currency: initialBalance ?? balanceFactory(confirmed: 0, unconfirmed: 0, frozen: 0)} : {}),
currency:
initialBalance ?? const ElectrumBalance(confirmed: 0, unconfirmed: 0, frozen: 0)
}
: {}),
this.unspentCoinsInfo = unspentCoinsInfo, this.unspentCoinsInfo = unspentCoinsInfo,
this.network = networkType == bitcoin.bitcoin this.network = networkType == bitcoin.bitcoin
? BitcoinNetwork.mainnet ? BitcoinNetwork.mainnet
@ -96,6 +97,11 @@ abstract class ElectrumWalletBase
final bitcoin.HDWallet hd; final bitcoin.HDWallet hd;
final String mnemonic; final String mnemonic;
final T Function({
required int confirmed,
required int unconfirmed,
required int frozen,
}) balanceFactory;
@override @override
@observable @observable
@ -109,7 +115,7 @@ abstract class ElectrumWalletBase
@override @override
@observable @observable
late ObservableMap<CryptoCurrency, ElectrumBalance> balance; late ObservableMap<CryptoCurrency, T> balance;
@override @override
@observable @observable
@ -285,7 +291,7 @@ abstract class ElectrumWalletBase
final totalAmount = amount + fee; final totalAmount = amount + fee;
if (totalAmount > balance[currency]!.confirmed) { if (totalAmount > (balance[currency]!.confirmed as int)) {
throw BitcoinTransactionWrongBalanceException(currency); throw BitcoinTransactionWrongBalanceException(currency);
} }
@ -788,7 +794,7 @@ abstract class ElectrumWalletBase
}); });
} }
Future<ElectrumBalance> _fetchBalances() async { Future<T> _fetchBalances() async {
final addresses = walletAddresses.allAddresses.toList(); final addresses = walletAddresses.allAddresses.toList();
final balanceFutures = <Future<Map<String, dynamic>>>[]; final balanceFutures = <Future<Map<String, dynamic>>>[];
for (var i = 0; i < addresses.length; i++) { for (var i = 0; i < addresses.length; i++) {
@ -828,8 +834,15 @@ abstract class ElectrumWalletBase
} }
} }
return ElectrumBalance( // return balanceFactory()
confirmed: totalConfirmed, unconfirmed: totalUnconfirmed, frozen: totalFrozen); // ..confirmed = totalConfirmed
// ..unconfirmed = totalUnconfirmed
// ..frozen = totalFrozen;
return balanceFactory(
confirmed: totalConfirmed,
unconfirmed: totalUnconfirmed,
frozen: totalFrozen,
);
} }
Future<void> updateBalance() async { Future<void> updateBalance() async {

View file

@ -1,10 +1,15 @@
import 'dart:convert'; import 'dart:convert';
import 'package:cw_bitcoin/bitcoin_amount_format.dart'; import 'package:cw_bitcoin/bitcoin_amount_format.dart';
import 'package:cw_bitcoin/electrum_balance.dart';
import 'package:cw_core/balance.dart'; import 'package:cw_core/balance.dart';
class LightningBalance extends Balance { class LightningBalance extends ElectrumBalance {
const LightningBalance({required this.confirmed, required this.unconfirmed, required this.frozen}) const LightningBalance({required this.confirmed, required this.unconfirmed, required this.frozen})
: super(confirmed, unconfirmed); : super(
confirmed: confirmed,
unconfirmed: unconfirmed,
frozen: frozen,
);
static LightningBalance? fromJSON(String? jsonSource) { static LightningBalance? fromJSON(String? jsonSource) {
if (jsonSource == null) { if (jsonSource == null) {

View file

@ -1,12 +1,15 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:bitbox/bitbox.dart';
import 'package:bitcoin_base/bitcoin_base.dart'; import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:breez_sdk/breez_sdk.dart'; import 'package:breez_sdk/breez_sdk.dart';
import 'package:breez_sdk/bridge_generated.dart'; import 'package:breez_sdk/bridge_generated.dart';
import 'package:cw_bitcoin/bitcoin_mnemonic.dart'; import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
import 'package:cw_bitcoin/bitcoin_wallet_keys.dart'; import 'package:cw_bitcoin/bitcoin_wallet_keys.dart';
import 'package:cw_bitcoin/electrum.dart'; import 'package:cw_bitcoin/electrum.dart';
import 'package:cw_bitcoin/electrum_balance.dart';
import 'package:cw_bitcoin/electrum_transaction_info.dart';
import 'package:cw_bitcoin/electrum_wallet_addresses.dart'; import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
import 'package:cw_bitcoin/electrum_wallet_snapshot.dart'; import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
import 'package:cw_bitcoin/litecoin_network.dart'; import 'package:cw_bitcoin/litecoin_network.dart';
@ -33,33 +36,27 @@ import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:cw_lightning/.secrets.g.dart' as secrets; import 'package:cw_lightning/.secrets.g.dart' as secrets;
import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_base.dart';
import 'package:cw_bitcoin/electrum_wallet.dart';
part 'lightning_wallet.g.dart'; part 'lightning_wallet.g.dart';
class LightningWallet = LightningWalletBase with _$LightningWallet; class LightningWallet = LightningWalletBase with _$LightningWallet;
abstract class LightningWalletBase ElectrumBalance myBalanceFactory(
extends WalletBase<LightningBalance, LightningTransactionHistory, LightningTransactionInfo> {required int confirmed, required int unconfirmed, required int frozen}) {
with Store { return ElectrumBalance(
final bitcoin.HDWallet hd; confirmed: confirmed,
final String mnemonic; unconfirmed: unconfirmed,
final String _password; frozen: frozen,
);
}
abstract class LightningWalletBase extends ElectrumWalletBase<LightningBalance> with Store {
bool _isTransactionUpdating; bool _isTransactionUpdating;
late ElectrumClient electrumClient;
@override // @override
@observable // @observable
late ObservableMap<CryptoCurrency, LightningBalance> balance; // ObservableMap<CryptoCurrency, LightningBalance> lnbalance;
@override
late ElectrumWalletAddresses walletAddresses;
bitcoin.NetworkType networkType = bitcoin.bitcoin;
late BasedUtxoNetwork network;
@override
BitcoinWalletKeys get keys =>
BitcoinWalletKeys(wif: hd.wif!, privateKey: hd.privKey!, publicKey: hd.pubKey!);
@override @override
@observable @observable
@ -72,45 +69,43 @@ abstract class LightningWalletBase
required Box<UnspentCoinsInfo> unspentCoinsInfo, required Box<UnspentCoinsInfo> unspentCoinsInfo,
required Uint8List seedBytes, required Uint8List seedBytes,
String? addressPageType, String? addressPageType,
ElectrumClient? electrumClient,
BasedUtxoNetwork? networkParam,
List<BitcoinAddressRecord>? initialAddresses, List<BitcoinAddressRecord>? initialAddresses,
LightningBalance? initialBalance, LightningBalance? initialBalance,
Map<String, int>? initialRegularAddressIndex, Map<String, int>? initialRegularAddressIndex,
Map<String, int>? initialChangeAddressIndex, Map<String, int>? initialChangeAddressIndex,
}) : hd = bitcoin.HDWallet.fromSeed(seedBytes, network: bitcoin.bitcoin).derivePath("m/0'/0"), }) : _isTransactionUpdating = false,
syncStatus = NotConnectedSyncStatus(), syncStatus = NotConnectedSyncStatus(),
mnemonic = mnemonic, super(
_password = password, mnemonic: mnemonic,
_isTransactionUpdating = false, password: password,
balance = ObservableMap<CryptoCurrency, LightningBalance>.of({ walletInfo: walletInfo,
CryptoCurrency.btcln: unspentCoinsInfo: unspentCoinsInfo,
initialBalance ?? const LightningBalance(confirmed: 0, unconfirmed: 0, frozen: 0) networkType: bitcoin.bitcoin,
}), initialAddresses: initialAddresses,
super(walletInfo) { initialBalance: initialBalance,
transactionHistory = LightningTransactionHistory(walletInfo: walletInfo, password: password); seedBytes: seedBytes,
currency: CryptoCurrency.btcln,
this.network = networkType == bitcoin.bitcoin // balanceFactory: myBalanceFactory,
? BitcoinNetwork.mainnet balanceFactory: ({required int confirmed, required int unconfirmed, required int frozen}) {
: networkType == litecoinNetwork return LightningBalance(
? LitecoinNetwork.mainnet confirmed: 0,
: BitcoinNetwork.testnet; unconfirmed: 0,
this.isTestnet = networkType == bitcoin.testnet; frozen: 0,
);
},
) {
walletAddresses = BitcoinWalletAddresses( walletAddresses = BitcoinWalletAddresses(
walletInfo, walletInfo,
electrumClient: electrumClient ?? ElectrumClient(), electrumClient: electrumClient,
initialAddresses: initialAddresses, initialAddresses: initialAddresses,
initialRegularAddressIndex: initialRegularAddressIndex, initialRegularAddressIndex: initialRegularAddressIndex,
initialChangeAddressIndex: initialChangeAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex,
mainHd: hd, mainHd: hd,
sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"), sideHd: bitcoin.HDWallet.fromSeed(seedBytes, network: networkType).derivePath("m/0'/1"),
network: networkParam ?? network, network: network,
); );
this.electrumClient = electrumClient ?? ElectrumClient(); // initialize breez:
// initialize breeze:
try { try {
setupBreez(seedBytes); setupBreez(seedBytes);
} catch (e) { } catch (e) {
@ -122,25 +117,27 @@ abstract class LightningWalletBase
}); });
} }
static Future<LightningWallet> create({ static Future<LightningWallet> create(
required String mnemonic, {required String mnemonic,
required String password, required String password,
required WalletInfo walletInfo, required WalletInfo walletInfo,
required Box<UnspentCoinsInfo> unspentCoinsInfo, required Box<UnspentCoinsInfo> unspentCoinsInfo,
BasedUtxoNetwork? network, String? addressPageType,
List<BitcoinAddressRecord>? initialAddresses, List<BitcoinAddressRecord>? initialAddresses,
LightningBalance? initialBalance,
Map<String, int>? initialRegularAddressIndex, Map<String, int>? initialRegularAddressIndex,
Map<String, int>? initialChangeAddressIndex, Map<String, int>? initialChangeAddressIndex}) async {
}) async {
return LightningWallet( return LightningWallet(
mnemonic: mnemonic, mnemonic: mnemonic,
password: password, password: password,
walletInfo: walletInfo, walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfo, unspentCoinsInfo: unspentCoinsInfo,
initialAddresses: initialAddresses, initialAddresses: initialAddresses,
seedBytes: await mnemonicToSeedBytes(mnemonic), initialBalance: initialBalance,
seedBytes: await Mnemonic.toSeed(mnemonic),
initialRegularAddressIndex: initialRegularAddressIndex, initialRegularAddressIndex: initialRegularAddressIndex,
initialChangeAddressIndex: initialChangeAddressIndex, initialChangeAddressIndex: initialChangeAddressIndex,
addressPageType: addressPageType,
); );
} }
@ -150,20 +147,19 @@ abstract class LightningWalletBase
required Box<UnspentCoinsInfo> unspentCoinsInfo, required Box<UnspentCoinsInfo> unspentCoinsInfo,
required String password, required String password,
}) async { }) async {
final snp = await ElectrumWalletSnapshot.load(name, walletInfo.type, password, final snp = await ElectrumWalletSnapshot.load(
walletInfo.network != null ? BasedUtxoNetwork.fromName(walletInfo.network!) : null); name, walletInfo.type, password, BitcoinCashNetwork.mainnet);
return LightningWallet( return LightningWallet(
mnemonic: snp.mnemonic, mnemonic: snp.mnemonic,
password: password, password: password,
walletInfo: walletInfo, walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfo, unspentCoinsInfo: unspentCoinsInfo,
initialAddresses: snp.addresses, initialAddresses: snp.addresses,
initialBalance: snp.balance as LightningBalance?,
seedBytes: await mnemonicToSeedBytes(snp.mnemonic), seedBytes: await mnemonicToSeedBytes(snp.mnemonic),
initialRegularAddressIndex: snp.regularAddressIndex, initialRegularAddressIndex: snp.regularAddressIndex,
initialChangeAddressIndex: snp.changeAddressIndex, initialChangeAddressIndex: snp.changeAddressIndex,
addressPageType: snp.addressPageType, addressPageType: snp.addressPageType,
networkParam: snp.network,
); );
} }
@ -224,11 +220,6 @@ abstract class LightningWalletBase
print("initialized breez: ${(await sdk.isInitialized())}"); print("initialized breez: ${(await sdk.isInitialized())}");
} }
@override
int calculateEstimatedFee(TransactionPriority priority, int? amount) {
throw UnimplementedError("calculateEstimatedFee");
}
@action @action
@override @override
Future<void> startSync() async { Future<void> startSync() async {
@ -248,9 +239,6 @@ abstract class LightningWalletBase
throw UnimplementedError("changePassword"); throw UnimplementedError("changePassword");
} }
@override
void close() {}
@action @action
@override @override
Future<void> connectToNode({required Node node}) async { Future<void> connectToNode({required Node node}) async {
@ -287,15 +275,15 @@ abstract class LightningWalletBase
} }
} }
Map<String, LightningTransactionInfo> convertToTxInfo(List<Payment> payments) { Map<String, ElectrumTransactionInfo> convertToTxInfo(List<Payment> payments) {
Map<String, LightningTransactionInfo> transactions = {}; Map<String, ElectrumTransactionInfo> transactions = {};
for (Payment tx in payments) { for (Payment tx in payments) {
if (tx.paymentType == PaymentType.ClosedChannel) { if (tx.paymentType == PaymentType.ClosedChannel) {
continue; continue;
} }
bool isSend = tx.paymentType == PaymentType.Sent; bool isSend = tx.paymentType == PaymentType.Sent;
transactions[tx.id] = LightningTransactionInfo( transactions[tx.id] = ElectrumTransactionInfo(
WalletType.lightning, WalletType.lightning,
isPending: false, isPending: false,
id: tx.id, id: tx.id,
@ -303,13 +291,16 @@ abstract class LightningWalletBase
fee: tx.feeMsat ~/ 1000, fee: tx.feeMsat ~/ 1000,
date: DateTime.fromMillisecondsSinceEpoch(tx.paymentTime * 1000), date: DateTime.fromMillisecondsSinceEpoch(tx.paymentTime * 1000),
direction: isSend ? TransactionDirection.outgoing : TransactionDirection.incoming, direction: isSend ? TransactionDirection.outgoing : TransactionDirection.incoming,
// N/A for lightning:
height: 0,
confirmations: 0,
); );
} }
return transactions; return transactions;
} }
@override @override
Future<Map<String, LightningTransactionInfo>> fetchTransactions() async { Future<Map<String, ElectrumTransactionInfo>> fetchTransactions() async {
final sdk = await BreezSDK(); final sdk = await BreezSDK();
final payments = await sdk.listPayments(req: ListPaymentsRequest()); final payments = await sdk.listPayments(req: ListPaymentsRequest());
@ -341,13 +332,6 @@ abstract class LightningWalletBase
'network_type': network == BitcoinNetwork.testnet ? 'testnet' : 'mainnet', 'network_type': network == BitcoinNetwork.testnet ? 'testnet' : 'mainnet',
}); });
@override
Future<void> save() async {
final path = await makePath();
await write(path: path, password: _password, data: toJSON());
await transactionHistory.save();
}
Future<void> updateBalance() async { Future<void> updateBalance() async {
// balance is updated automatically // balance is updated automatically
} }

View file

@ -29,7 +29,8 @@ class LightningWalletService extends WalletService<BitcoinNewWalletCredentials,
mnemonic: await generateMnemonic(), mnemonic: await generateMnemonic(),
password: credentials.password!, password: credentials.password!,
walletInfo: credentials.walletInfo!, walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource); unspentCoinsInfo: unspentCoinsInfoSource,
);
await wallet.save(); await wallet.save();
await wallet.init(); await wallet.init();
return wallet; return wallet;
@ -48,7 +49,8 @@ class LightningWalletService extends WalletService<BitcoinNewWalletCredentials,
password: password, password: password,
name: name, name: name,
walletInfo: walletInfo, walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfoSource); unspentCoinsInfo: unspentCoinsInfoSource,
);
await wallet.init(); await wallet.init();
saveBackup(name); saveBackup(name);
return wallet; return wallet;
@ -58,7 +60,8 @@ class LightningWalletService extends WalletService<BitcoinNewWalletCredentials,
password: password, password: password,
name: name, name: name,
walletInfo: walletInfo, walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfoSource); unspentCoinsInfo: unspentCoinsInfoSource,
);
await wallet.init(); await wallet.init();
return wallet; return wallet;
} }
@ -93,7 +96,8 @@ class LightningWalletService extends WalletService<BitcoinNewWalletCredentials,
} }
@override @override
Future<LightningWallet> restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials, {bool? isTestnet}) async => Future<LightningWallet> restoreFromKeys(BitcoinRestoreWalletFromWIFCredentials credentials,
{bool? isTestnet}) async =>
throw UnimplementedError(); throw UnimplementedError();
@override @override
@ -111,7 +115,6 @@ class LightningWalletService extends WalletService<BitcoinNewWalletCredentials,
mnemonic: credentials.mnemonic, mnemonic: credentials.mnemonic,
walletInfo: credentials.walletInfo!, walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource, unspentCoinsInfo: unspentCoinsInfoSource,
network: network,
); );
await wallet.save(); await wallet.save();
await wallet.init(); await wallet.init();

View file

@ -1,5 +1,3 @@
import 'package:breez_sdk/breez_sdk.dart';
import 'package:breez_sdk/bridge_generated.dart';
import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart'; import 'package:cake_wallet/src/screens/new_wallet/widgets/select_button.dart';
import 'package:cake_wallet/themes/extensions/keyboard_theme.dart'; import 'package:cake_wallet/themes/extensions/keyboard_theme.dart';
import 'package:cake_wallet/di.dart'; import 'package:cake_wallet/di.dart';
@ -161,9 +159,7 @@ class AddressPage extends BasePage {
amountController: _amountController, amountController: _amountController,
isLight: dashboardViewModel.settingsStore.currentTheme.type == isLight: dashboardViewModel.settingsStore.currentTheme.type ==
ThemeType.light))), ThemeType.light))),
SizedBox( SizedBox(height: 16),
height: 40,
),
Observer(builder: (_) { Observer(builder: (_) {
if (addressListViewModel.hasAddressList) { if (addressListViewModel.hasAddressList) {
return SelectButton( return SelectButton(

View file

@ -27,7 +27,7 @@ class MenuWidgetState extends State<MenuWidget> {
this.fromBottomEdge = 25, this.fromBottomEdge = 25,
this.moneroIcon = Image.asset('assets/images/monero_menu.png'), this.moneroIcon = Image.asset('assets/images/monero_menu.png'),
this.bitcoinIcon = Image.asset('assets/images/bitcoin_menu.png'), this.bitcoinIcon = Image.asset('assets/images/bitcoin_menu.png'),
this.lightningIcon = Image.asset('assets/images/bitcoin_menu.png'), this.lightningIcon = Image.asset('assets/images/lightning_logo.png'),
this.litecoinIcon = Image.asset('assets/images/litecoin_menu.png'), this.litecoinIcon = Image.asset('assets/images/litecoin_menu.png'),
this.havenIcon = Image.asset('assets/images/haven_menu.png'), this.havenIcon = Image.asset('assets/images/haven_menu.png'),
this.ethereumIcon = Image.asset('assets/images/eth_icon.png'), this.ethereumIcon = Image.asset('assets/images/eth_icon.png'),
@ -100,7 +100,7 @@ class MenuWidgetState extends State<MenuWidget> {
color: Theme.of(context).extension<CakeMenuTheme>()!.iconColor); color: Theme.of(context).extension<CakeMenuTheme>()!.iconColor);
bitcoinIcon = Image.asset('assets/images/bitcoin_menu.png', bitcoinIcon = Image.asset('assets/images/bitcoin_menu.png',
color: Theme.of(context).extension<CakeMenuTheme>()!.iconColor); color: Theme.of(context).extension<CakeMenuTheme>()!.iconColor);
lightningIcon = Image.asset('assets/images/bitcoin_menu.png', lightningIcon = Image.asset('assets/images/lightning_logo.png',
color: Theme.of(context).extension<CakeMenuTheme>()!.iconColor); color: Theme.of(context).extension<CakeMenuTheme>()!.iconColor);
return Row( return Row(

View file

@ -208,9 +208,9 @@ class LightningReceiveOnchainPage extends BasePage {
return Expanded( return Expanded(
child: Container(child: Center(child: CircularProgressIndicator()))); child: Container(child: Center(child: CircularProgressIndicator())));
} }
int min = (snapshot.data as List<int>)[1]; int min = int.parse((snapshot.data as List<String>)[1]);
int max = (snapshot.data as List<int>)[2]; int max = int.parse((snapshot.data as List<String>)[2]);
int fee = (snapshot.data as List<int>)[3]; int fee = int.parse((snapshot.data as List<String>)[3]);
return Expanded( return Expanded(
child: Text( child: Text(
S.of(context).lightning_receive_limits( S.of(context).lightning_receive_limits(

View file

@ -23,7 +23,7 @@ class AnonpayCurrencyInputField extends StatelessWidget {
final String maxAmount; final String maxAmount;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
bool hasDecimals = selectedCurrency.name != "sats"; bool hasDecimals = selectedCurrency.name.toLowerCase() != "sats";
final arrowBottomPurple = Image.asset( final arrowBottomPurple = Image.asset(
'assets/images/arrow_bottom_purple_icon.png', 'assets/images/arrow_bottom_purple_icon.png',
color: Colors.white, color: Colors.white,

View file

@ -95,7 +95,7 @@ abstract class LightningInvoicePageViewModelBase with Store {
try { try {
String bolt11 = String bolt11 =
await lightningViewModel.createInvoice(amount: amount, description: description); await lightningViewModel.createInvoice(amountSats: amount, description: description);
state = ExecutedSuccessfullyState(payload: bolt11); state = ExecutedSuccessfullyState(payload: bolt11);
} catch (e) { } catch (e) {
state = FailureState(e.toString()); state = FailureState(e.toString());

View file

@ -27,10 +27,10 @@ abstract class LightningViewModelBase with Store {
]; ];
} }
Future<String> createInvoice({required String amount, String? description}) async { Future<String> createInvoice({required String amountSats, String? description}) async {
final sdk = await BreezSDK(); final sdk = await BreezSDK();
final req = ReceivePaymentRequest( final req = ReceivePaymentRequest(
amountMsat: (double.parse(amount) * 1000).round(), amountMsat: (double.parse(amountSats) * 1000).round(),
description: description ?? '', description: description ?? '',
); );
final res = await sdk.receivePayment(req: req); final res = await sdk.receivePayment(req: req);

View file

@ -42,6 +42,7 @@ Future<void> generateSecretsConfig(List<String> args) async {
} }
} }
// base:
SecretKey.base.forEach((sec) { SecretKey.base.forEach((sec) {
if (secrets[sec.name] != null) { if (secrets[sec.name] != null) {
return; return;
@ -49,12 +50,11 @@ Future<void> generateSecretsConfig(List<String> args) async {
secrets[sec.name] = sec.generate(); secrets[sec.name] = sec.generate();
}); });
var secretsJson = JsonEncoder.withIndent(' ').convert(secrets); var secretsJson = JsonEncoder.withIndent(' ').convert(secrets);
await configFile.writeAsString(secretsJson); await configFile.writeAsString(secretsJson);
secrets.clear(); secrets.clear();
// evm:
SecretKey.evmChainsSecrets.forEach((sec) { SecretKey.evmChainsSecrets.forEach((sec) {
if (secrets[sec.name] != null) { if (secrets[sec.name] != null) {
return; return;
@ -64,8 +64,9 @@ Future<void> generateSecretsConfig(List<String> args) async {
}); });
secretsJson = JsonEncoder.withIndent(' ').convert(secrets); secretsJson = JsonEncoder.withIndent(' ').convert(secrets);
await evmChainsConfigFile.writeAsString(secretsJson); await evmChainsConfigFile.writeAsString(secretsJson);
secrets.clear(); secrets.clear();
// btc / lightning:
SecretKey.bitcoinSecrets.forEach((sec) { SecretKey.bitcoinSecrets.forEach((sec) {
if (secrets[sec.name] != null) { if (secrets[sec.name] != null) {
return; return;
@ -74,7 +75,9 @@ Future<void> generateSecretsConfig(List<String> args) async {
}); });
secretsJson = JsonEncoder.withIndent(' ').convert(secrets); secretsJson = JsonEncoder.withIndent(' ').convert(secrets);
await bitcoinConfigFile.writeAsString(secretsJson); await bitcoinConfigFile.writeAsString(secretsJson);
secrets.clear();
// solana:
SecretKey.solanaSecrets.forEach((sec) { SecretKey.solanaSecrets.forEach((sec) {
if (secrets[sec.name] != null) { if (secrets[sec.name] != null) {
return; return;
@ -84,4 +87,5 @@ Future<void> generateSecretsConfig(List<String> args) async {
}); });
secretsJson = JsonEncoder.withIndent(' ').convert(secrets); secretsJson = JsonEncoder.withIndent(' ').convert(secrets);
await solanaConfigFile.writeAsString(secretsJson); await solanaConfigFile.writeAsString(secretsJson);
secrets.clear();
} }