fixes and enhancements

This commit is contained in:
OmarHatem 2024-05-28 07:21:07 +03:00
parent c4b4d4e735
commit ce2a9cd99f
17 changed files with 110 additions and 141 deletions

View file

@ -230,7 +230,12 @@ abstract class ElectrumWalletBase
int? _currentChainTip;
Future<int> getCurrentChainTip() async {
return _currentChainTip ?? await electrumClient.getCurrentBlockChainTip() ?? 0;
if (_currentChainTip != null) {
return _currentChainTip!;
}
_currentChainTip = await electrumClient.getCurrentBlockChainTip() ?? 0;
return _currentChainTip!;
}
Future<int> getUpdatedChainTip() async {
@ -248,8 +253,10 @@ abstract class ElectrumWalletBase
String _password;
List<BitcoinUnspent> unspentCoins;
List<int> _feeRates;
// ignore: prefer_final_fields
Map<String, BehaviorSubject<Object>?> _scripthashesUpdateSubject;
// ignore: prefer_final_fields
BehaviorSubject<Object>? _chainTipUpdateSubject;
bool _isTransactionUpdating;
@ -262,6 +269,7 @@ abstract class ElectrumWalletBase
Future<void> init() async {
await walletAddresses.init();
await transactionHistory.init();
await save();
_autoSaveTimer =
Timer.periodic(Duration(seconds: _autoSaveInterval), (_) async => await save());
@ -313,30 +321,6 @@ abstract class ElectrumWalletBase
final existingTxInfo = transactionHistory.transactions[txid];
final txAlreadyExisted = existingTxInfo != null;
void updateSilentAddressRecord(BitcoinSilentPaymentsUnspent unspent) {
final silentAddress = walletAddresses.silentAddress!;
final silentPaymentAddress = SilentPaymentAddress(
version: silentAddress.version,
B_scan: silentAddress.B_scan,
B_spend: unspent.silentPaymentLabel != null
? silentAddress.B_spend.tweakAdd(
BigintUtils.fromBytes(
BytesUtils.fromHexString(unspent.silentPaymentLabel!)),
)
: silentAddress.B_spend,
hrp: silentAddress.hrp,
);
final addressRecord = walletAddresses.silentAddresses.firstWhereOrNull(
(address) => address.address == silentPaymentAddress.toString());
addressRecord?.txCount += 1;
addressRecord?.balance += unspent.value;
walletAddresses.addSilentAddresses(
[unspent.bitcoinAddressRecord as BitcoinSilentPaymentAddressRecord],
);
}
// Updating tx after re-scanned
if (txAlreadyExisted) {
existingTxInfo.amount = tx.amount;
@ -352,7 +336,7 @@ abstract class ElectrumWalletBase
.toList();
if (newUnspents.isNotEmpty) {
newUnspents.forEach(updateSilentAddressRecord);
newUnspents.forEach(_updateSilentAddressRecord);
existingTxInfo.unspents ??= [];
existingTxInfo.unspents!.addAll(newUnspents);
@ -372,7 +356,7 @@ abstract class ElectrumWalletBase
}
} else {
// else: First time seeing this TX after scanning
tx.unspents!.forEach(updateSilentAddressRecord);
tx.unspents!.forEach(_updateSilentAddressRecord);
// Add new TX record
transactionHistory.addMany(message);
@ -396,6 +380,30 @@ abstract class ElectrumWalletBase
}
}
void _updateSilentAddressRecord(BitcoinSilentPaymentsUnspent unspent) {
final silentAddress = walletAddresses.silentAddress!;
final silentPaymentAddress = SilentPaymentAddress(
version: silentAddress.version,
B_scan: silentAddress.B_scan,
B_spend: unspent.silentPaymentLabel != null
? silentAddress.B_spend.tweakAdd(
BigintUtils.fromBytes(
BytesUtils.fromHexString(unspent.silentPaymentLabel!)),
)
: silentAddress.B_spend,
hrp: silentAddress.hrp,
);
final addressRecord = walletAddresses.silentAddresses.firstWhereOrNull(
(address) => address.address == silentPaymentAddress.toString());
addressRecord?.txCount += 1;
addressRecord?.balance += unspent.value;
walletAddresses.addSilentAddresses(
[unspent.bitcoinAddressRecord as BitcoinSilentPaymentAddressRecord],
);
}
@action
@override
Future<void> startSync() async {
@ -412,7 +420,7 @@ abstract class ElectrumWalletBase
await updateAllUnspents();
await updateBalance();
await updateFeeRates();
Timer.periodic(const Duration(minutes: 1), (timer) async => await updateFeeRates());
if (alwaysScan == true) {
_setListeners(walletInfo.restoreHeight);
@ -1712,13 +1720,6 @@ abstract class ElectrumWalletBase
confirmed: totalConfirmed, unconfirmed: totalUnconfirmed, frozen: totalFrozen);
}
Future<ElectrumBalance> _fetchBalance(String sh) async {
final balance = await electrumClient.getBalance(sh);
final confirmed = balance['confirmed'] as int? ?? 0;
final unconfirmed = balance['unconfirmed'] as int? ?? 0;
return ElectrumBalance(confirmed: confirmed, unconfirmed: unconfirmed, frozen: 0);
}
Future<void> updateBalance() async {
balance[currency] = await _fetchBalances();
await save();

View file

@ -29,7 +29,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
Map<String, int>? initialRegularAddressIndex,
Map<String, int>? initialChangeAddressIndex,
List<BitcoinSilentPaymentAddressRecord>? initialSilentAddresses,
int initialSilentAddressIndex = 1,
int initialSilentAddressIndex = 0,
bitcoin.HDWallet? masterHd,
BitcoinAddressType? initialAddressPageType,
}) : _addresses = ObservableList<BitcoinAddressRecord>.of((initialAddresses ?? []).toSet()),

View file

@ -29,7 +29,6 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
CryptoCurrency.bch,
CryptoCurrency.bnb,
CryptoCurrency.btc,
CryptoCurrency.tbtc,
CryptoCurrency.dai,
CryptoCurrency.dash,
CryptoCurrency.eos,
@ -105,6 +104,7 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
CryptoCurrency.digibyte,
CryptoCurrency.usdtSol,
CryptoCurrency.usdcTrc20,
CryptoCurrency.tbtc,
];
static const havenCurrencies = [
@ -129,7 +129,6 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
static const bch = CryptoCurrency(title: 'BCH', fullName: 'Bitcoin Cash', raw: 2, name: 'bch', iconPath: 'assets/images/bch_icon.png', decimals: 8);
static const bnb = CryptoCurrency(title: 'BNB', tag: 'BSC', fullName: 'Binance Coin', raw: 3, name: 'bnb', iconPath: 'assets/images/bnb_icon.png', decimals: 8);
static const btc = CryptoCurrency(title: 'BTC', fullName: 'Bitcoin', raw: 4, name: 'btc', iconPath: 'assets/images/btc.png', decimals: 8);
static const tbtc = CryptoCurrency(title: 'tBTC', fullName: 'Testnet Bitcoin', raw: 4, name: 'tbtc', iconPath: 'assets/images/tbtc.png', decimals: 8);
static const dai = CryptoCurrency(title: 'DAI', tag: 'ETH', fullName: 'Dai', raw: 5, name: 'dai', iconPath: 'assets/images/dai_icon.png', decimals: 18);
static const dash = CryptoCurrency(title: 'DASH', fullName: 'Dash', raw: 6, name: 'dash', iconPath: 'assets/images/dash_icon.png', decimals: 8);
static const eos = CryptoCurrency(title: 'EOS', fullName: 'EOS', raw: 7, name: 'eos', iconPath: 'assets/images/eos_icon.png', decimals: 4);
@ -220,7 +219,8 @@ class CryptoCurrency extends EnumerableItem<int> with Serializable<int> implemen
static const kaspa = CryptoCurrency(title: 'KAS', fullName: 'Kaspa', raw: 89, name: 'kas', iconPath: 'assets/images/kaspa_icon.png', decimals: 8);
static const digibyte = CryptoCurrency(title: 'DGB', fullName: 'DigiByte', raw: 90, name: 'dgb', iconPath: 'assets/images/digibyte.png', decimals: 8);
static const usdtSol = CryptoCurrency(title: 'USDT', tag: 'SOL', fullName: 'USDT Tether', raw: 91, name: 'usdtsol', iconPath: 'assets/images/usdt_icon.png', decimals: 6);
static const usdcTrc20 = CryptoCurrency(title: 'USDC', tag: 'TRX', fullName: 'USDC Coin', raw: 92, name: 'usdctrc20', iconPath: 'assets/images/usdc_icon.png', decimals: 6);
static const usdcTrc20 = CryptoCurrency(title: 'USDC', tag: 'TRX', fullName: 'USDC Coin', raw: 92, name: 'usdctrc20', iconPath: 'assets/images/usdc_icon.png', decimals: 6);
static const tbtc = CryptoCurrency(title: 'tBTC', fullName: 'Testnet Bitcoin', raw: 93, name: 'tbtc', iconPath: 'assets/images/tbtc.png', decimals: 8);
static final Map<int, CryptoCurrency> _rawCurrencyMap =

View file

@ -121,14 +121,6 @@ class CWBitcoin extends Bitcoin {
priority: priority != null ? priority as BitcoinTransactionPriority : null,
feeRate: feeRate);
@override
List<String> getAddresses(Object wallet) {
final bitcoinWallet = wallet as ElectrumWallet;
return bitcoinWallet.walletAddresses.addressesByReceiveType
.map((BaseBitcoinAddressRecord addr) => addr.address)
.toList();
}
@override
@computed
List<ElectrumSubAddress> getSubAddresses(Object wallet) {

View file

@ -934,8 +934,7 @@ Future<void> setup({
(onSuccessfulPinSetup, _) => SetupPinCodePage(getIt.get<SetupPinCodeViewModel>(),
onSuccessfulPinSetup: onSuccessfulPinSetup));
getIt.registerFactory(
() => RescanViewModel(getIt.get<AppStore>().wallet!, getIt.get<SettingsStore>()));
getIt.registerFactory(() => RescanViewModel(getIt.get<AppStore>().wallet!));
getIt.registerFactory(() => RescanPage(getIt.get<RescanViewModel>()));

View file

@ -882,7 +882,7 @@ Future<void> checkCurrentNodes(
if (currentLitecoinElectrumServer == null) {
final cakeWalletElectrum =
Node(uri: cakeWalletLitecoinElectrumUri, type: WalletType.litecoin, useSSL: true);
Node(uri: cakeWalletLitecoinElectrumUri, type: WalletType.litecoin, useSSL: false);
await nodeSource.add(cakeWalletElectrum);
await sharedPreferences.setInt(
PreferencesKey.currentLitecoinElectrumSererIdKey, cakeWalletElectrum.key as int);
@ -918,7 +918,7 @@ Future<void> checkCurrentNodes(
if (currentBitcoinCashNodeServer == null) {
final node =
Node(uri: cakeWalletBitcoinCashDefaultNodeUri, type: WalletType.bitcoinCash, useSSL: true);
Node(uri: cakeWalletBitcoinCashDefaultNodeUri, type: WalletType.bitcoinCash, useSSL: false);
await nodeSource.add(node);
await sharedPreferences.setInt(PreferencesKey.currentBitcoinCashNodeIdKey, node.key as int);
}

View file

@ -30,6 +30,7 @@ class DesktopWalletSelectionDropDown extends StatefulWidget {
class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionDropDown> {
final moneroIcon = Image.asset('assets/images/monero_logo.png', height: 24, width: 24);
final bitcoinIcon = Image.asset('assets/images/bitcoin.png', height: 24, width: 24);
final tBitcoinIcon = Image.asset('assets/images/tbtc.png', height: 24, width: 24);
final litecoinIcon = Image.asset('assets/images/litecoin_icon.png', height: 24, width: 24);
final havenIcon = Image.asset('assets/images/haven_logo.png', height: 24, width: 24);
final ethereumIcon = Image.asset('assets/images/eth_icon.png', height: 24, width: 24);
@ -68,8 +69,11 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
child: ConstrainedBox(
constraints: BoxConstraints(maxWidth: 500),
child: DropDownItemWidget(
title: wallet.name,
image: wallet.isEnabled ? _imageFor(type: wallet.type) : nonWalletTypeIcon),
title: wallet.name,
image: wallet.isEnabled
? _imageFor(type: wallet.type, isTestnet: wallet.isTestnet)
: nonWalletTypeIcon,
),
),
onSelected: () => _onSelectedWallet(wallet),
))
@ -120,16 +124,16 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
WidgetsBinding.instance.addPostFrameCallback((_) async {
final confirmed = await showPopUp<bool>(
context: context,
builder: (dialogContext) {
return AlertWithTwoActions(
alertTitle: S.of(context).change_wallet_alert_title,
alertContent: S.of(context).change_wallet_alert_content(selectedWallet.name),
leftButtonText: S.of(context).cancel,
rightButtonText: S.of(context).change,
actionLeftButton: () => Navigator.of(dialogContext).pop(false),
actionRightButton: () => Navigator.of(dialogContext).pop(true));
}) ??
context: context,
builder: (dialogContext) {
return AlertWithTwoActions(
alertTitle: S.of(context).change_wallet_alert_title,
alertContent: S.of(context).change_wallet_alert_content(selectedWallet.name),
leftButtonText: S.of(context).cancel,
rightButtonText: S.of(context).change,
actionLeftButton: () => Navigator.of(dialogContext).pop(false),
actionRightButton: () => Navigator.of(dialogContext).pop(true));
}) ??
false;
if (confirmed) {
@ -138,9 +142,12 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
});
}
Image _imageFor({required WalletType type}) {
Image _imageFor({required WalletType type, bool? isTestnet}) {
switch (type) {
case WalletType.bitcoin:
if (isTestnet == true) {
return tBitcoinIcon;
}
return bitcoinIcon;
case WalletType.monero:
return moneroIcon;
@ -160,7 +167,7 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
return polygonIcon;
case WalletType.solana:
return solanaIcon;
case WalletType.tron:
case WalletType.tron:
return tronIcon;
default:
return nonWalletTypeIcon;
@ -168,24 +175,25 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
}
Future<void> _loadWallet(WalletListItem wallet) async {
widget._authService.authenticateAction(context,
onAuthSuccess: (isAuthenticatedSuccessfully) async {
if (!isAuthenticatedSuccessfully) {
return;
}
widget._authService.authenticateAction(
context,
onAuthSuccess: (isAuthenticatedSuccessfully) async {
if (!isAuthenticatedSuccessfully) {
return;
}
try {
if (context.mounted) {
changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name));
try {
if (context.mounted) {
changeProcessText(S.of(context).wallet_list_loading_wallet(wallet.name));
}
await widget.walletListViewModel.loadWallet(wallet);
hideProgressText();
setState(() {});
} catch (e) {
if (context.mounted) {
changeProcessText(S.of(context).wallet_list_failed_to_load(wallet.name, e.toString()));
}
}
await widget.walletListViewModel.loadWallet(wallet);
hideProgressText();
setState(() {});
} catch (e) {
if (context.mounted) {
changeProcessText(S.of(context).wallet_list_failed_to_load(wallet.name, e.toString()));
}
}
},
conditionToDetermineIfToUse2FA:
widget.walletListViewModel.shouldRequireTOTP2FAForAccessingWallet,
@ -198,17 +206,16 @@ class _DesktopWalletSelectionDropDownState extends State<DesktopWalletSelectionD
context,
route: Routes.newWallet,
arguments: widget.walletListViewModel.currentWalletType,
conditionToDetermineIfToUse2FA: widget
.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets,
conditionToDetermineIfToUse2FA:
widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets,
);
} else {
widget._authService.authenticateAction(
context,
route: Routes.newWalletType,
conditionToDetermineIfToUse2FA: widget
.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets,
conditionToDetermineIfToUse2FA:
widget.walletListViewModel.shouldRequireTOTP2FAForCreatingNewWallets,
);
}
}

View file

@ -329,6 +329,8 @@ class CryptoBalanceWidget extends StatelessWidget {
final isSilentPaymentsScanningActive = dashboardViewModel.silentPaymentsScanningActive;
final newValue = !isSilentPaymentsScanningActive;
dashboardViewModel.silentPaymentsScanningActive = newValue;
final needsToSwitch = !isSilentPaymentsScanningActive &&
await bitcoin!.getNodeIsElectrsSPEnabled(dashboardViewModel.wallet) == false;
@ -344,7 +346,10 @@ class CryptoBalanceWidget extends StatelessWidget {
dashboardViewModel.setSilentPaymentsScanning(newValue);
Navigator.of(context).pop();
},
actionLeftButton: () => Navigator.of(context).pop(),
actionLeftButton: () {
dashboardViewModel.silentPaymentsScanningActive = isSilentPaymentsScanningActive;
Navigator.of(context).pop();
},
));
}

View file

@ -1,15 +1,6 @@
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/routes.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
import 'package:cake_wallet/src/widgets/dashboard_card_widget.dart';
import 'package:cake_wallet/src/widgets/standard_switch.dart';
import 'package:cake_wallet/themes/extensions/balance_page_theme.dart';
import 'package:cake_wallet/utils/show_pop_up.dart';
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
import 'package:cake_wallet/view_model/dashboard/cake_features_view_model.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:cake_wallet/generated/i18n.dart';
import 'package:url_launcher/url_launcher.dart';
@ -65,10 +56,7 @@ class CakeFeaturesPage extends StatelessWidget {
// ),
SizedBox(height: 20),
DashBoardRoundedCardWidget(
onTap: () => launchUrl(
Uri.https("buy.cakepay.com"),
mode: LaunchMode.externalApplication,
),
onTap: () => _launchUrl("buy.cakepay.com"),
title: S.of(context).cake_pay_web_cards_title,
subTitle: S.of(context).cake_pay_web_cards_subtitle,
svgPicture: SvgPicture.asset(
@ -82,10 +70,7 @@ class CakeFeaturesPage extends StatelessWidget {
DashBoardRoundedCardWidget(
title: "NanoGPT",
subTitle: S.of(context).nanogpt_subtitle,
onTap: () => launchUrl(
Uri.https("cake.nano-gpt.com"),
mode: LaunchMode.externalApplication,
),
onTap: () => _launchUrl("cake.nano-gpt.com"),
),
],
),
@ -97,30 +82,12 @@ class CakeFeaturesPage extends StatelessWidget {
);
}
// TODO: Remove ionia flow/files if we will discard it
void _navigatorToGiftCardsPage(BuildContext context) {
final walletType = dashboardViewModel.type;
switch (walletType) {
case WalletType.haven:
showPopUp<void>(
context: context,
builder: (BuildContext context) {
return AlertWithOneAction(
alertTitle: S.of(context).error,
alertContent: S.of(context).gift_cards_unavailable,
buttonText: S.of(context).ok,
buttonAction: () => Navigator.of(context).pop());
});
break;
default:
cakeFeaturesViewModel.isIoniaUserAuthenticated().then((value) {
if (value) {
Navigator.pushNamed(context, Routes.ioniaManageCardsPage);
return;
}
Navigator.of(context).pushNamed(Routes.ioniaWelcomePage);
});
}
void _launchUrl(String url) {
try {
launchUrl(
Uri.https(url),
mode: LaunchMode.externalApplication,
);
} catch (_) {}
}
}

View file

@ -39,7 +39,7 @@ class ConnectionSyncPage extends BasePage {
),
if (dashboardViewModel.hasRescan) ...[
SettingsCellWithArrow(
title: dashboardViewModel.hasRescan
title: dashboardViewModel.hasSilentPayments
? S.current.silent_payments_scanning
: S.current.rescan,
handler: (context) => Navigator.of(context).pushNamed(Routes.rescan),

View file

@ -53,7 +53,7 @@ abstract class ContactListViewModelBase with Store {
info.network == null ? false : info.network!.toLowerCase().contains("testnet")),
));
});
} else if (info.address != null) {
} else {
walletContacts.add(WalletContact(
info.address,
info.name,

View file

@ -1,4 +1,3 @@
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/entities/fiat_api_mode.dart';
import 'package:cake_wallet/entities/sort_balance_types.dart';
import 'package:cake_wallet/reactions/wallet_connect.dart';

View file

@ -306,7 +306,7 @@ abstract class DashboardViewModelBase with Store {
wallet.type == WalletType.haven;
@computed
bool get hasSilentPayments => hasRescan && wallet.type == WalletType.bitcoin;
bool get hasSilentPayments => wallet.type == WalletType.bitcoin;
@computed
bool get showSilentPaymentsCard => hasSilentPayments && settingsStore.silentPaymentsCardDisplay;

View file

@ -1,5 +1,4 @@
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/store/settings_store.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:mobx/mobx.dart';
@ -11,15 +10,13 @@ class RescanViewModel = RescanViewModelBase with _$RescanViewModel;
enum RescanWalletState { rescaning, none }
abstract class RescanViewModelBase with Store {
RescanViewModelBase(this.wallet, this.settingsStore)
RescanViewModelBase(this.wallet)
: state = RescanWalletState.none,
isButtonEnabled = false,
doSingleScan = false;
final WalletBase wallet;
final SettingsStore settingsStore;
@observable
RescanWalletState state;

View file

@ -1,10 +1,12 @@
import 'package:cake_wallet/bitcoin/bitcoin.dart';
import 'package:cake_wallet/monero/monero.dart';
import 'package:cake_wallet/utils/exception_handler.dart';
import 'package:cake_wallet/view_model/unspent_coins/unspent_coins_item.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:cw_core/unspent_transaction_output.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/cupertino.dart';
import 'package:hive/hive.dart';
import 'package:mobx/mobx.dart';
@ -109,6 +111,7 @@ abstract class UnspentCoinsListViewModelBase with Store {
} catch (e, s) {
print(s);
print(e.toString());
ExceptionHandler.onError(FlutterErrorDetails(exception: e, stack: s));
}
});

View file

@ -456,9 +456,9 @@ abstract class WalletAddressListViewModelBase extends WalletChangeListenerViewMo
wallet.type == WalletType.bitcoin && bitcoin!.hasSelectedSilentPayments(wallet);
@computed
bool get isAutoGenerateSubaddressEnabled => wallet.type == WalletType.bitcoin
? !isSilentPayments
: _settingsStore.autoGenerateSubaddressStatus != AutoGenerateSubaddressStatus.disabled;
bool get isAutoGenerateSubaddressEnabled =>
_settingsStore.autoGenerateSubaddressStatus != AutoGenerateSubaddressStatus.disabled &&
!isSilentPayments;
List<ListItem> _baseItems;

View file

@ -166,7 +166,6 @@ abstract class Bitcoin {
Object createBitcoinTransactionCredentials(List<Output> outputs, {required TransactionPriority priority, int? feeRate});
Object createBitcoinTransactionCredentialsRaw(List<OutputInfo> outputs, {TransactionPriority? priority, required int feeRate});
List<String> getAddresses(Object wallet);
String getAddress(Object wallet);
List<BitcoinSilentPaymentAddressRecord> getSilentPaymentAddresses(Object wallet);
List<BitcoinSilentPaymentAddressRecord> getSilentPaymentReceivedAddresses(Object wallet);