mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-04-15 02:31:57 +00:00
lint and code formatting
This commit is contained in:
parent
b190907cae
commit
fe2514e97e
2 changed files with 341 additions and 353 deletions
lib/wallets/wallet
|
@ -1,53 +1,29 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:decimal/decimal.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
import 'package:xelis_flutter/src/api/network.dart' as x_network;
|
||||
import 'package:xelis_flutter/src/api/wallet.dart' as x_wallet;
|
||||
import 'package:mutex/mutex.dart';
|
||||
import 'package:stack_wallet_backup/generate_password.dart';
|
||||
import 'package:xelis_dart_sdk/xelis_dart_sdk.dart' as xelis_sdk;
|
||||
import 'package:xelis_flutter/src/api/wallet.dart' as x_wallet;
|
||||
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import '../intermediate/lib_xelis_wallet.dart';
|
||||
|
||||
import '../../../utilities/stack_file_system.dart';
|
||||
import '../../../models/balance.dart';
|
||||
import '../../../models/isar/models/blockchain_data/address.dart';
|
||||
import '../../../models/isar/models/blockchain_data/transaction.dart';
|
||||
import '../../../models/isar/models/blockchain_data/v2/input_v2.dart';
|
||||
import '../../../models/isar/models/blockchain_data/v2/output_v2.dart';
|
||||
import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart';
|
||||
|
||||
import '../../../services/event_bus/events/global/blocks_remaining_event.dart';
|
||||
import '../../../services/event_bus/events/global/refresh_percent_changed_event.dart';
|
||||
import '../../../services/event_bus/events/global/tor_connection_status_changed_event.dart';
|
||||
import '../../../services/event_bus/events/global/tor_status_changed_event.dart';
|
||||
import '../../../services/event_bus/events/global/updated_in_background_event.dart';
|
||||
import '../../../models/paymint/fee_object_model.dart';
|
||||
import '../../../services/event_bus/events/global/wallet_sync_status_changed_event.dart';
|
||||
import '../../../services/event_bus/global_event_bus.dart';
|
||||
|
||||
import '../../../models/node_model.dart';
|
||||
import '../../../models/paymint/fee_object_model.dart';
|
||||
import '../../../models/balance.dart';
|
||||
import '../../../utilities/amount/amount.dart';
|
||||
import '../../../utilities/logger.dart';
|
||||
import '../../crypto_currency/crypto_currency.dart';
|
||||
import '../../models/tx_data.dart';
|
||||
import '../wallet.dart';
|
||||
|
||||
import '../../../providers/providers.dart';
|
||||
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mutex/mutex.dart';
|
||||
import 'package:stack_wallet_backup/generate_password.dart';
|
||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
import '../intermediate/lib_xelis_wallet.dart';
|
||||
|
||||
import 'dart:math';
|
||||
import '../wallet.dart';
|
||||
|
||||
class XelisWallet extends LibXelisWallet {
|
||||
XelisWallet(CryptoCurrencyNetwork network) : super(Xelis(network));
|
||||
|
@ -59,14 +35,15 @@ class XelisWallet extends LibXelisWallet {
|
|||
@override
|
||||
Future<void> init({bool? isRestore}) async {
|
||||
debugPrint("Xelis: init");
|
||||
|
||||
|
||||
if (isRestore == true) {
|
||||
await _restoreWallet();
|
||||
return await super.init();
|
||||
}
|
||||
|
||||
String? walletExists =
|
||||
await secureStorageInterface.read(key: "${walletId}_wallet");
|
||||
final String? walletExists = await secureStorageInterface.read(
|
||||
key: "${walletId}_wallet",
|
||||
);
|
||||
|
||||
if (walletExists == null) {
|
||||
await _createNewWallet();
|
||||
|
@ -79,7 +56,7 @@ class XelisWallet extends LibXelisWallet {
|
|||
|
||||
Future<void> _createNewWallet() async {
|
||||
final String password = generatePassword();
|
||||
|
||||
|
||||
debugPrint("Xelis: storing password");
|
||||
await secureStorageInterface.write(
|
||||
key: Wallet.mnemonicPassphraseKey(walletId: info.walletId),
|
||||
|
@ -128,9 +105,9 @@ class XelisWallet extends LibXelisWallet {
|
|||
await updateTransactions(isRescan: true, topoheight: 0);
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Borrowed from libmonero for now, need to refactor for Xelis view keys
|
||||
// Borrowed from libmonero for now, need to refactor for Xelis view keys
|
||||
// if (isViewOnly) {
|
||||
// await recoverViewOnly();
|
||||
// return;
|
||||
|
@ -138,7 +115,7 @@ class XelisWallet extends LibXelisWallet {
|
|||
|
||||
try {
|
||||
await open();
|
||||
} catch (e, s) {
|
||||
} catch (_) {
|
||||
// Logging.instance.log(
|
||||
// "Exception rethrown from recoverFromMnemonic(): $e\n$s",
|
||||
// level: LogLevel.Error,
|
||||
|
@ -147,17 +124,16 @@ class XelisWallet extends LibXelisWallet {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Future<bool> pingCheck() async {
|
||||
checkInitialized();
|
||||
try {
|
||||
final nodeInfo = await libXelisWallet!.getDaemonInfo();
|
||||
await libXelisWallet!.getDaemonInfo();
|
||||
await handleOnline();
|
||||
return true;
|
||||
} catch (_) {
|
||||
return false;
|
||||
await handleOffline();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,9 +144,11 @@ class XelisWallet extends LibXelisWallet {
|
|||
await _balanceUpdateMutex.protect(() async {
|
||||
try {
|
||||
if (await libXelisWallet!.hasXelisBalance()) {
|
||||
final BigInt xelBalance = newBalance != null
|
||||
? BigInt.from(newBalance)
|
||||
: await libXelisWallet!.getXelisBalanceRaw(); // in the future, use getAssetBalances and handle each
|
||||
final BigInt xelBalance =
|
||||
newBalance != null
|
||||
? BigInt.from(newBalance)
|
||||
: await libXelisWallet!
|
||||
.getXelisBalanceRaw(); // in the future, use getAssetBalances and handle each
|
||||
final balance = Balance(
|
||||
total: Amount(
|
||||
rawValue: xelBalance,
|
||||
|
@ -187,12 +165,9 @@ class XelisWallet extends LibXelisWallet {
|
|||
fractionDigits: cryptoCurrency.fractionDigits,
|
||||
),
|
||||
);
|
||||
await info.updateBalance(
|
||||
newBalance: balance,
|
||||
isar: mainDB.isar,
|
||||
);
|
||||
await info.updateBalance(newBalance: balance, isar: mainDB.isar);
|
||||
}
|
||||
} catch (e, s) {
|
||||
} catch (_) {
|
||||
// Logging.instance.log(
|
||||
// "Error in updateBalance(): $e\n$s",
|
||||
// level: LogLevel.Warning,
|
||||
|
@ -203,7 +178,8 @@ class XelisWallet extends LibXelisWallet {
|
|||
|
||||
Future<int> _fetchChainHeight() async {
|
||||
final infoString = await libXelisWallet!.getDaemonInfo();
|
||||
final Map<String, dynamic> nodeInfo = json.decode(infoString);
|
||||
final Map<String, dynamic> nodeInfo =
|
||||
(json.decode(infoString) as Map).cast();
|
||||
|
||||
pruningHeight = int.parse(nodeInfo['pruned_topoheight'].toString());
|
||||
return int.parse(nodeInfo['topoheight'].toString());
|
||||
|
@ -213,12 +189,12 @@ class XelisWallet extends LibXelisWallet {
|
|||
Future<void> updateChainHeight({int? topoheight}) async {
|
||||
try {
|
||||
final height = topoheight ?? await _fetchChainHeight();
|
||||
|
||||
|
||||
await info.updateCachedChainHeight(
|
||||
newHeight: height.toInt(),
|
||||
isar: mainDB.isar,
|
||||
);
|
||||
} catch (e, s) {
|
||||
} catch (_) {
|
||||
// Logging.instance.log(
|
||||
// "Error in updateChainHeight(): $e\n$s",
|
||||
// level: LogLevel.Warning,
|
||||
|
@ -235,7 +211,7 @@ class XelisWallet extends LibXelisWallet {
|
|||
await libXelisWallet!.offlineMode();
|
||||
}
|
||||
await super.connect();
|
||||
} catch (e, s) {
|
||||
} catch (_) {
|
||||
// Logging.instance.log(
|
||||
// "Error updating node: $e\n$s",
|
||||
// level: LogLevel.Error,
|
||||
|
@ -252,22 +228,24 @@ class XelisWallet extends LibXelisWallet {
|
|||
}) async {
|
||||
checkInitialized();
|
||||
|
||||
final newReceivingAddress = await getCurrentReceivingAddress() ??
|
||||
Address(
|
||||
walletId: walletId,
|
||||
derivationIndex: 0,
|
||||
derivationPath: null,
|
||||
value: libXelisWallet!.getAddressStr(),
|
||||
publicKey: [],
|
||||
type: AddressType.xelis,
|
||||
subType: AddressSubType.receiving,
|
||||
);
|
||||
final newReceivingAddress =
|
||||
await getCurrentReceivingAddress() ??
|
||||
Address(
|
||||
walletId: walletId,
|
||||
derivationIndex: 0,
|
||||
derivationPath: null,
|
||||
value: libXelisWallet!.getAddressStr(),
|
||||
publicKey: [],
|
||||
type: AddressType.xelis,
|
||||
subType: AddressSubType.receiving,
|
||||
);
|
||||
|
||||
final thisAddress = newReceivingAddress.value;
|
||||
|
||||
|
||||
int firstBlock = 0;
|
||||
if (!isRescan) {
|
||||
firstBlock = await mainDB.isar.transactionV2s
|
||||
firstBlock =
|
||||
await mainDB.isar.transactionV2s
|
||||
.where()
|
||||
.walletIdEqualTo(walletId)
|
||||
.heightProperty()
|
||||
|
@ -288,16 +266,19 @@ class XelisWallet extends LibXelisWallet {
|
|||
|
||||
for (final jsonString in txListJson) {
|
||||
try {
|
||||
final transactionEntry = xelis_sdk.TransactionEntry.fromJson(json.decode(jsonString));
|
||||
final transactionEntry = xelis_sdk.TransactionEntry.fromJson(
|
||||
(json.decode(jsonString) as Map).cast(),
|
||||
);
|
||||
|
||||
// Check for duplicates
|
||||
final storedTx = await mainDB.isar.transactionV2s
|
||||
.where()
|
||||
.txidWalletIdEqualTo(transactionEntry.hash, walletId)
|
||||
.findFirst();
|
||||
final storedTx =
|
||||
await mainDB.isar.transactionV2s
|
||||
.where()
|
||||
.txidWalletIdEqualTo(transactionEntry.hash, walletId)
|
||||
.findFirst();
|
||||
|
||||
if (storedTx != null &&
|
||||
storedTx.height != null &&
|
||||
if (storedTx != null &&
|
||||
storedTx.height != null &&
|
||||
storedTx.height! > 0) {
|
||||
continue; // Skip already processed transactions
|
||||
}
|
||||
|
@ -305,140 +286,150 @@ class XelisWallet extends LibXelisWallet {
|
|||
final List<OutputV2> outputs = [];
|
||||
final List<InputV2> inputs = [];
|
||||
TransactionType? txType;
|
||||
TransactionSubType txSubType = TransactionSubType.none;
|
||||
const TransactionSubType txSubType = TransactionSubType.none;
|
||||
int? nonce;
|
||||
Amount fee = Amount(
|
||||
rawValue: BigInt.zero,
|
||||
fractionDigits: cryptoCurrency.fractionDigits
|
||||
rawValue: BigInt.zero,
|
||||
fractionDigits: cryptoCurrency.fractionDigits,
|
||||
);
|
||||
Map<String, dynamic> otherData = {};
|
||||
final Map<String, dynamic> otherData = {};
|
||||
|
||||
final entryType = transactionEntry.txEntryType;
|
||||
|
||||
if (entryType is xelis_sdk.CoinbaseEntry) {
|
||||
final coinbase = entryType;
|
||||
txType = TransactionType.incoming;
|
||||
final coinbase = entryType;
|
||||
txType = TransactionType.incoming;
|
||||
|
||||
final int decimals = await libXelisWallet!.getAssetDecimals(
|
||||
asset: xelis_sdk.xelisAsset,
|
||||
);
|
||||
|
||||
fee = Amount(rawValue: BigInt.zero, fractionDigits: decimals);
|
||||
|
||||
outputs.add(
|
||||
OutputV2.isarCantDoRequiredInDefaultConstructor(
|
||||
scriptPubKeyHex: "",
|
||||
valueStringSats: coinbase.reward.toString(),
|
||||
addresses: [thisAddress],
|
||||
walletOwns: true,
|
||||
),
|
||||
);
|
||||
} else if (entryType is xelis_sdk.BurnEntry) {
|
||||
final burn = entryType;
|
||||
txType = TransactionType.outgoing;
|
||||
|
||||
final int decimals = await libXelisWallet!.getAssetDecimals(
|
||||
asset: burn.asset,
|
||||
);
|
||||
|
||||
fee = Amount(
|
||||
rawValue: BigInt.from(burn.fee),
|
||||
fractionDigits: decimals,
|
||||
);
|
||||
|
||||
inputs.add(
|
||||
InputV2.isarCantDoRequiredInDefaultConstructor(
|
||||
scriptSigAsm: null,
|
||||
scriptSigHex: null,
|
||||
sequence: null,
|
||||
outpoint: null,
|
||||
valueStringSats: burn.amount.toString(),
|
||||
addresses: [thisAddress],
|
||||
witness: null,
|
||||
innerRedeemScriptAsm: null,
|
||||
coinbase: null,
|
||||
walletOwns: true,
|
||||
),
|
||||
);
|
||||
|
||||
outputs.add(
|
||||
OutputV2.isarCantDoRequiredInDefaultConstructor(
|
||||
scriptPubKeyHex: "",
|
||||
valueStringSats: burn.amount.toString(),
|
||||
addresses: ['burn'],
|
||||
walletOwns: false,
|
||||
),
|
||||
);
|
||||
|
||||
otherData['burnAsset'] = burn.asset;
|
||||
} else if (entryType is xelis_sdk.IncomingEntry) {
|
||||
final incoming = entryType;
|
||||
txType =
|
||||
incoming.from == thisAddress
|
||||
? TransactionType.sentToSelf
|
||||
: TransactionType.incoming;
|
||||
|
||||
for (final transfer in incoming.transfers) {
|
||||
final int decimals = await libXelisWallet!.getAssetDecimals(
|
||||
asset: xelis_sdk.xelisAsset
|
||||
asset: transfer.asset,
|
||||
);
|
||||
|
||||
fee = Amount(
|
||||
rawValue: BigInt.zero,
|
||||
fractionDigits: decimals
|
||||
);
|
||||
fee = Amount(rawValue: BigInt.zero, fractionDigits: decimals);
|
||||
|
||||
outputs.add(OutputV2.isarCantDoRequiredInDefaultConstructor(
|
||||
outputs.add(
|
||||
OutputV2.isarCantDoRequiredInDefaultConstructor(
|
||||
scriptPubKeyHex: "",
|
||||
valueStringSats: coinbase.reward.toString(),
|
||||
valueStringSats: transfer.amount.toString(),
|
||||
addresses: [thisAddress],
|
||||
walletOwns: true,
|
||||
));
|
||||
} else if (entryType is xelis_sdk.BurnEntry) {
|
||||
final burn = entryType;
|
||||
txType = TransactionType.outgoing;
|
||||
),
|
||||
);
|
||||
|
||||
otherData['asset_${transfer.asset}'] = transfer.amount.toString();
|
||||
if (transfer.extraData != null) {
|
||||
otherData['extraData_${transfer.asset}'] =
|
||||
transfer.extraData!.toJson();
|
||||
}
|
||||
}
|
||||
} else if (entryType is xelis_sdk.OutgoingEntry) {
|
||||
final outgoing = entryType;
|
||||
txType = TransactionType.outgoing;
|
||||
nonce = outgoing.nonce;
|
||||
|
||||
for (final transfer in outgoing.transfers) {
|
||||
final int decimals = await libXelisWallet!.getAssetDecimals(
|
||||
asset: burn.asset
|
||||
asset: transfer.asset,
|
||||
);
|
||||
|
||||
fee = Amount(
|
||||
rawValue: BigInt.from(burn.fee),
|
||||
fractionDigits: decimals
|
||||
rawValue: BigInt.from(outgoing.fee),
|
||||
fractionDigits: decimals,
|
||||
);
|
||||
|
||||
inputs.add(InputV2.isarCantDoRequiredInDefaultConstructor(
|
||||
scriptSigAsm: null,
|
||||
inputs.add(
|
||||
InputV2.isarCantDoRequiredInDefaultConstructor(
|
||||
scriptSigHex: null,
|
||||
scriptSigAsm: null,
|
||||
sequence: null,
|
||||
outpoint: null,
|
||||
valueStringSats: burn.amount.toString(),
|
||||
addresses: [thisAddress],
|
||||
valueStringSats: (transfer.amount + outgoing.fee).toString(),
|
||||
witness: null,
|
||||
innerRedeemScriptAsm: null,
|
||||
coinbase: null,
|
||||
walletOwns: true,
|
||||
));
|
||||
),
|
||||
);
|
||||
|
||||
outputs.add(OutputV2.isarCantDoRequiredInDefaultConstructor(
|
||||
outputs.add(
|
||||
OutputV2.isarCantDoRequiredInDefaultConstructor(
|
||||
scriptPubKeyHex: "",
|
||||
valueStringSats: burn.amount.toString(),
|
||||
addresses: ['burn'],
|
||||
valueStringSats: transfer.amount.toString(),
|
||||
addresses: [transfer.destination],
|
||||
walletOwns: false,
|
||||
));
|
||||
),
|
||||
);
|
||||
|
||||
otherData['burnAsset'] = burn.asset;
|
||||
} else if (entryType is xelis_sdk.IncomingEntry) {
|
||||
final incoming = entryType;
|
||||
txType = incoming.from == thisAddress
|
||||
? TransactionType.sentToSelf
|
||||
: TransactionType.incoming;
|
||||
|
||||
for (final transfer in incoming.transfers) {
|
||||
final int decimals = await libXelisWallet!.getAssetDecimals(
|
||||
asset: transfer.asset
|
||||
);
|
||||
|
||||
fee = Amount(
|
||||
rawValue: BigInt.zero,
|
||||
fractionDigits: decimals
|
||||
);
|
||||
|
||||
outputs.add(OutputV2.isarCantDoRequiredInDefaultConstructor(
|
||||
scriptPubKeyHex: "",
|
||||
valueStringSats: transfer.amount.toString(),
|
||||
addresses: [thisAddress],
|
||||
walletOwns: true,
|
||||
));
|
||||
|
||||
otherData['asset_${transfer.asset}'] = transfer.amount.toString();
|
||||
if (transfer.extraData != null) {
|
||||
otherData['extraData_${transfer.asset}'] = transfer.extraData!.toJson();
|
||||
}
|
||||
}
|
||||
} else if (entryType is xelis_sdk.OutgoingEntry) {
|
||||
final outgoing = entryType;
|
||||
txType = TransactionType.outgoing;
|
||||
nonce = outgoing.nonce;
|
||||
|
||||
for (final transfer in outgoing.transfers) {
|
||||
final int decimals = await libXelisWallet!.getAssetDecimals(
|
||||
asset: transfer.asset
|
||||
);
|
||||
|
||||
fee = Amount(
|
||||
rawValue: BigInt.from(outgoing.fee),
|
||||
fractionDigits: decimals
|
||||
);
|
||||
|
||||
inputs.add(InputV2.isarCantDoRequiredInDefaultConstructor(
|
||||
scriptSigHex: null,
|
||||
scriptSigAsm: null,
|
||||
sequence: null,
|
||||
outpoint: null,
|
||||
addresses: [thisAddress],
|
||||
valueStringSats: (transfer.amount + outgoing.fee).toString(),
|
||||
witness: null,
|
||||
innerRedeemScriptAsm: null,
|
||||
coinbase: null,
|
||||
walletOwns: true,
|
||||
));
|
||||
|
||||
outputs.add(OutputV2.isarCantDoRequiredInDefaultConstructor(
|
||||
scriptPubKeyHex: "",
|
||||
valueStringSats: transfer.amount.toString(),
|
||||
addresses: [transfer.destination],
|
||||
walletOwns: false,
|
||||
));
|
||||
|
||||
otherData['asset_${transfer.asset}_amount'] = transfer.amount.toString();
|
||||
otherData['asset_${transfer.asset}_fee'] = fee.toString();
|
||||
if (transfer.extraData != null) {
|
||||
otherData['extraData_${transfer.asset}'] = transfer.extraData!.toJson();
|
||||
}
|
||||
otherData['asset_${transfer.asset}_amount'] =
|
||||
transfer.amount.toString();
|
||||
otherData['asset_${transfer.asset}_fee'] = fee.toString();
|
||||
if (transfer.extraData != null) {
|
||||
otherData['extraData_${transfer.asset}'] =
|
||||
transfer.extraData!.toJson();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Skip unknown entry types
|
||||
// Skip unknown entry types
|
||||
}
|
||||
|
||||
final txn = TransactionV2(
|
||||
|
@ -446,8 +437,9 @@ class XelisWallet extends LibXelisWallet {
|
|||
blockHash: "", // Not provided in Xelis data
|
||||
hash: transactionEntry.hash,
|
||||
txid: transactionEntry.hash,
|
||||
timestamp: (transactionEntry.timestamp?.millisecondsSinceEpoch ?? 0) ~/ 1000,
|
||||
height: transactionEntry?.topoheight,
|
||||
timestamp:
|
||||
(transactionEntry.timestamp?.millisecondsSinceEpoch ?? 0) ~/ 1000,
|
||||
height: transactionEntry.topoheight,
|
||||
inputs: List.unmodifiable(inputs),
|
||||
outputs: List.unmodifiable(outputs),
|
||||
version: -1, // Version not provided
|
||||
|
@ -456,7 +448,7 @@ class XelisWallet extends LibXelisWallet {
|
|||
otherData: jsonEncode({
|
||||
...otherData,
|
||||
if (nonce != null) 'nonce': nonce,
|
||||
if (fee != null) 'overrideFee': fee.toJsonString(),
|
||||
'overrideFee': fee.toJsonString(),
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -465,9 +457,8 @@ class XelisWallet extends LibXelisWallet {
|
|||
// level: LogLevel.Debug,
|
||||
// );
|
||||
|
||||
|
||||
txns.add(txn);
|
||||
} catch (e, s) {
|
||||
} catch (_) {
|
||||
// Logging.instance.log(
|
||||
// "Error handling tx $jsonString: $e\n$s",
|
||||
// level: LogLevel.Warning,
|
||||
|
@ -518,22 +509,29 @@ class XelisWallet extends LibXelisWallet {
|
|||
checkInitialized();
|
||||
|
||||
// Use default address if recipients list is empty
|
||||
final recipients = txData.recipients?.isNotEmpty == true
|
||||
? txData.recipients!
|
||||
: [(
|
||||
address: 'xel:xz9574c80c4xegnvurazpmxhw5dlg2n0g9qm60uwgt75uqyx3pcsqzzra9m',
|
||||
amount: Amount.zeroWith(
|
||||
fractionDigits: cryptoCurrency.fractionDigits,
|
||||
),
|
||||
isChange: false
|
||||
)];
|
||||
final recipients =
|
||||
txData.recipients?.isNotEmpty == true
|
||||
? txData.recipients!
|
||||
: [
|
||||
(
|
||||
address:
|
||||
'xel:xz9574c80c4xegnvurazpmxhw5dlg2n0g9qm60uwgt75uqyx3pcsqzzra9m',
|
||||
amount: Amount.zeroWith(
|
||||
fractionDigits: cryptoCurrency.fractionDigits,
|
||||
),
|
||||
isChange: false,
|
||||
),
|
||||
];
|
||||
|
||||
final asset = assetId ?? xelis_sdk.xelisAsset;
|
||||
|
||||
// Calculate total send amount
|
||||
final totalSendAmount = recipients.fold<Amount>(
|
||||
Amount(rawValue: BigInt.zero, fractionDigits: cryptoCurrency.fractionDigits),
|
||||
(sum, recipient) => sum + recipient.amount
|
||||
Amount(
|
||||
rawValue: BigInt.zero,
|
||||
fractionDigits: cryptoCurrency.fractionDigits,
|
||||
),
|
||||
(sum, recipient) => sum + recipient.amount,
|
||||
);
|
||||
|
||||
// Check balance using raw method
|
||||
|
@ -555,28 +553,26 @@ class XelisWallet extends LibXelisWallet {
|
|||
// Check if we have enough for both transfers and fee
|
||||
if (totalSendAmount + boostedFee > balance) {
|
||||
final requiredAmt = await libXelisWallet!.formatCoin(
|
||||
atomicAmount: (totalSendAmount + boostedFee).raw,
|
||||
assetHash: asset
|
||||
atomicAmount: (totalSendAmount + boostedFee).raw,
|
||||
assetHash: asset,
|
||||
);
|
||||
|
||||
final availableAmt = await libXelisWallet!.formatCoin(
|
||||
atomicAmount: xelBalance,
|
||||
assetHash: asset
|
||||
atomicAmount: xelBalance,
|
||||
assetHash: asset,
|
||||
);
|
||||
|
||||
throw Exception(
|
||||
"Insufficient balance to cover transfers and fees. "
|
||||
"Required: $requiredAmt, Available: $availableAmt"
|
||||
"Required: $requiredAmt, Available: $availableAmt",
|
||||
);
|
||||
}
|
||||
|
||||
return txData.copyWith(
|
||||
fee: boostedFee,
|
||||
otherData: jsonEncode({
|
||||
'asset': asset,
|
||||
}),
|
||||
otherData: jsonEncode({'asset': asset}),
|
||||
);
|
||||
} catch (e, s) {
|
||||
} catch (_) {
|
||||
// Logging.instance.log(
|
||||
// "Exception rethrown from prepareSend(): $e\n$s",
|
||||
// level: LogLevel.Error,
|
||||
|
@ -587,39 +583,43 @@ class XelisWallet extends LibXelisWallet {
|
|||
|
||||
@override
|
||||
Future<Amount> estimateFeeFor(
|
||||
Amount amount,
|
||||
int feeRate,
|
||||
{
|
||||
double? feeMultiplier,
|
||||
List<TxRecipient> recipients = const [],
|
||||
String? assetId
|
||||
}
|
||||
) async {
|
||||
Amount amount,
|
||||
int feeRate, {
|
||||
double? feeMultiplier,
|
||||
List<TxRecipient> recipients = const [],
|
||||
String? assetId,
|
||||
}) async {
|
||||
try {
|
||||
checkInitialized();
|
||||
final asset = assetId ?? xelis_sdk.xelisAsset;
|
||||
|
||||
// Default values for a new wallet or when estimation fails
|
||||
final defaultDecimals = 8;
|
||||
final defaultDecimals = cryptoCurrency.fractionDigits;
|
||||
final defaultFee = BigInt.from(0);
|
||||
|
||||
|
||||
// Use default address if recipients list is empty
|
||||
final effectiveRecipients = recipients.isNotEmpty
|
||||
? recipients
|
||||
: [(
|
||||
address: 'xel:xz9574c80c4xegnvurazpmxhw5dlg2n0g9qm60uwgt75uqyx3pcsqzzra9m',
|
||||
amount: amount,
|
||||
isChange: false
|
||||
)];
|
||||
final effectiveRecipients =
|
||||
recipients.isNotEmpty
|
||||
? recipients
|
||||
: [
|
||||
(
|
||||
address:
|
||||
'xel:xz9574c80c4xegnvurazpmxhw5dlg2n0g9qm60uwgt75uqyx3pcsqzzra9m',
|
||||
amount: amount,
|
||||
isChange: false,
|
||||
),
|
||||
];
|
||||
|
||||
try {
|
||||
final transfers = await Future.wait(
|
||||
effectiveRecipients.map((recipient) async {
|
||||
try {
|
||||
final amt = double.parse(await libXelisWallet!.formatCoin(
|
||||
atomicAmount: recipient.amount.raw,
|
||||
assetHash: asset
|
||||
));
|
||||
final amt = double.parse(
|
||||
await libXelisWallet!.formatCoin(
|
||||
atomicAmount: recipient.amount.raw,
|
||||
assetHash: asset,
|
||||
),
|
||||
);
|
||||
return x_wallet.Transfer(
|
||||
floatAmount: amt,
|
||||
strAddress: recipient.address,
|
||||
|
@ -630,7 +630,8 @@ class XelisWallet extends LibXelisWallet {
|
|||
// Handle formatCoin error - use default conversion
|
||||
debugPrint("formatCoin failed: $e, using fallback conversion");
|
||||
final rawAmount = recipient.amount.raw;
|
||||
final floatAmount = rawAmount / BigInt.from(10).pow(defaultDecimals);
|
||||
final floatAmount =
|
||||
rawAmount / BigInt.from(10).pow(defaultDecimals);
|
||||
return x_wallet.Transfer(
|
||||
floatAmount: floatAmount.toDouble(),
|
||||
strAddress: recipient.address,
|
||||
|
@ -638,28 +639,30 @@ class XelisWallet extends LibXelisWallet {
|
|||
extraData: null,
|
||||
);
|
||||
}
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
final decimals = await libXelisWallet!.getAssetDecimals(
|
||||
asset: asset
|
||||
final decimals = await libXelisWallet!.getAssetDecimals(asset: asset);
|
||||
final estimatedFee = double.parse(
|
||||
await libXelisWallet!.estimateFees(transfers: transfers),
|
||||
);
|
||||
final estimatedFee = double.parse(await libXelisWallet!.estimateFees(transfers: transfers));
|
||||
final rawFee = (estimatedFee * pow(10, decimals)).round();
|
||||
return Amount(
|
||||
rawValue: BigInt.from(rawFee),
|
||||
fractionDigits: cryptoCurrency.fractionDigits,
|
||||
);
|
||||
} catch (e, s) {
|
||||
debugPrint("Fee estimation failed: $e\n$s");
|
||||
|
||||
debugPrint("Using fallback fee: $defaultFee");
|
||||
Logging.instance.d(
|
||||
"Fee estimation failed. Using fallback fee: $defaultFee",
|
||||
error: e,
|
||||
stackTrace: s,
|
||||
);
|
||||
return Amount(
|
||||
rawValue: defaultFee,
|
||||
fractionDigits: cryptoCurrency.fractionDigits,
|
||||
);
|
||||
}
|
||||
} catch (e, s) {
|
||||
} catch (_) {
|
||||
// Logging.instance.log(
|
||||
// "Exception rethrown from estimateFeeFor(): $e\n$s",
|
||||
// level: LogLevel.Error,
|
||||
|
@ -681,12 +684,19 @@ class XelisWallet extends LibXelisWallet {
|
|||
final recipient = txData.recipients!.first;
|
||||
final Amount sendAmount = recipient.amount;
|
||||
|
||||
final asset = (txData.otherData != null ? jsonDecode(txData.otherData!) : null)?['asset'] ?? xelis_sdk.xelisAsset;
|
||||
final asset =
|
||||
(txData.otherData != null
|
||||
? jsonDecode(txData.otherData!)
|
||||
: null)?['asset']
|
||||
as String? ??
|
||||
xelis_sdk.xelisAsset;
|
||||
|
||||
final amt = double.parse(await libXelisWallet!.formatCoin(
|
||||
atomicAmount: sendAmount.raw,
|
||||
assetHash: asset
|
||||
));
|
||||
final amt = double.parse(
|
||||
await libXelisWallet!.formatCoin(
|
||||
atomicAmount: sendAmount.raw,
|
||||
assetHash: asset,
|
||||
),
|
||||
);
|
||||
|
||||
// Create a transfer transaction
|
||||
final txJson = await libXelisWallet!.createTransfersTransaction(
|
||||
|
@ -696,8 +706,8 @@ class XelisWallet extends LibXelisWallet {
|
|||
strAddress: recipient.address,
|
||||
assetHash: asset,
|
||||
extraData: null, // Add extra data if needed
|
||||
)
|
||||
]
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final txMap = jsonDecode(txJson);
|
||||
|
@ -706,10 +716,10 @@ class XelisWallet extends LibXelisWallet {
|
|||
// Broadcast the transaction
|
||||
await libXelisWallet!.broadcastTransaction(txHash: txHash);
|
||||
|
||||
return await updateSentCachedTxData(txData: txData.copyWith(
|
||||
txid: txHash,
|
||||
));
|
||||
} catch (e, s) {
|
||||
return await updateSentCachedTxData(
|
||||
txData: txData.copyWith(txid: txHash),
|
||||
);
|
||||
} catch (_) {
|
||||
// Logging.instance.log(
|
||||
// "Exception rethrown from confirmSend(): $e\n$s",
|
||||
// level: LogLevel.Error,
|
||||
|
@ -739,7 +749,7 @@ class XelisWallet extends LibXelisWallet {
|
|||
case HistorySynced(:final topoheight):
|
||||
await handleHistorySynced(topoheight);
|
||||
}
|
||||
} catch (e, s) {
|
||||
} catch (_) {
|
||||
// Logging.instance.log(
|
||||
// "Error handling wallet event: $e\n$s",
|
||||
// level: LogLevel.Error,
|
||||
|
@ -749,10 +759,7 @@ class XelisWallet extends LibXelisWallet {
|
|||
|
||||
@override
|
||||
Future<void> handleNewTopoHeight(int height) async {
|
||||
await info.updateCachedChainHeight(
|
||||
newHeight: height,
|
||||
isar: mainDB.isar,
|
||||
);
|
||||
await info.updateCachedChainHeight(newHeight: height, isar: mainDB.isar);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -765,12 +772,12 @@ class XelisWallet extends LibXelisWallet {
|
|||
);
|
||||
|
||||
await updateBalance();
|
||||
|
||||
|
||||
// Logging.instance.log(
|
||||
// "New transaction processed: ${newTxIds.first}",
|
||||
// level: LogLevel.Info,
|
||||
// );
|
||||
} catch (e, s) {
|
||||
} catch (_) {
|
||||
// Logging.instance.log(
|
||||
// "Error handling new transaction: $e\n$s",
|
||||
// level: LogLevel.Warning,
|
||||
|
@ -785,9 +792,9 @@ class XelisWallet extends LibXelisWallet {
|
|||
if (asset == xelis_sdk.xelisAsset) {
|
||||
await updateBalance(newBalance: event.balance);
|
||||
}
|
||||
|
||||
|
||||
// TODO: Update asset balances if needed
|
||||
} catch (e, s) {
|
||||
} catch (_) {
|
||||
// Logging.instance.log(
|
||||
// "Error handling balance change: $e\n$s",
|
||||
// level: LogLevel.Warning,
|
||||
|
@ -869,7 +876,7 @@ class XelisWallet extends LibXelisWallet {
|
|||
),
|
||||
);
|
||||
}
|
||||
} catch (e, s) {
|
||||
} catch (_) {
|
||||
// Logging.instance.log(
|
||||
// "Error in refresh(): $e\n$s",
|
||||
// level: LogLevel.Warning,
|
||||
|
@ -877,4 +884,4 @@ class XelisWallet extends LibXelisWallet {
|
|||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,46 +1,19 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mutex/mutex.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:xelis_dart_sdk/xelis_dart_sdk.dart' as xelis_sdk;
|
||||
import 'package:xelis_flutter/src/api/network.dart' as x_network;
|
||||
import 'package:xelis_flutter/src/api/wallet.dart' as x_wallet;
|
||||
|
||||
import '../../../models/isar/models/blockchain_data/address.dart';
|
||||
import '../../crypto_currency/crypto_currency.dart';
|
||||
import '../../crypto_currency/intermediate/electrum_currency.dart';
|
||||
import '../wallet.dart';
|
||||
import '../wallet_mixin_interfaces/mnemonic_interface.dart';
|
||||
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:decimal/decimal.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
import 'package:xelis_flutter/src/api/network.dart' as x_network;
|
||||
import 'package:xelis_flutter/src/api/wallet.dart' as x_wallet;
|
||||
import 'package:xelis_dart_sdk/xelis_dart_sdk.dart' as xelis_sdk;
|
||||
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import '../../../utilities/stack_file_system.dart';
|
||||
import '../../../models/isar/models/blockchain_data/transaction.dart';
|
||||
import '../../../models/isar/models/blockchain_data/v2/input_v2.dart';
|
||||
import '../../../models/isar/models/blockchain_data/v2/output_v2.dart';
|
||||
import '../../../models/isar/models/blockchain_data/v2/transaction_v2.dart';
|
||||
|
||||
import '../../../models/node_model.dart';
|
||||
import '../../../models/paymint/fee_object_model.dart';
|
||||
import '../../../models/balance.dart';
|
||||
import '../../../utilities/amount/amount.dart';
|
||||
import '../../../utilities/logger.dart';
|
||||
import '../../crypto_currency/crypto_currency.dart';
|
||||
import '../../models/tx_data.dart';
|
||||
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:mutex/mutex.dart';
|
||||
import 'package:stack_wallet_backup/generate_password.dart';
|
||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
|
||||
import 'external_wallet.dart';
|
||||
|
||||
enum XelisTableSize {
|
||||
|
@ -48,7 +21,7 @@ enum XelisTableSize {
|
|||
full;
|
||||
|
||||
bool get isLow => this == XelisTableSize.low;
|
||||
|
||||
|
||||
static XelisTableSize get platformDefault {
|
||||
if (kIsWeb) {
|
||||
return XelisTableSize.low;
|
||||
|
@ -83,7 +56,7 @@ class XelisTableState {
|
|||
return XelisTableState(
|
||||
isGenerating: isGenerating ?? this.isGenerating,
|
||||
currentSize: currentSize ?? this.currentSize,
|
||||
desiredSize: kIsWeb ? XelisTableSize.low : (desiredSize ?? this._desiredSize),
|
||||
desiredSize: kIsWeb ? XelisTableSize.low : (desiredSize ?? _desiredSize),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -170,14 +143,14 @@ final class HistorySynced extends Event {
|
|||
const HistorySynced(this.topoheight);
|
||||
}
|
||||
|
||||
abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet<T>
|
||||
abstract class LibXelisWallet<T extends ElectrumCurrency>
|
||||
extends ExternalWallet<T>
|
||||
with MnemonicInterface {
|
||||
LibXelisWallet(super.currency);
|
||||
|
||||
static const String _kHasFullTablesKey = 'xelis_has_full_tables';
|
||||
static const String _kGeneratingTablesKey = 'xelis_generating_tables';
|
||||
static const String _kWantsFullTablesKey = 'xelis_wants_full_tables';
|
||||
static bool _isAnyWalletGeneratingTables = false;
|
||||
static final _initMutex = Mutex();
|
||||
static final _tableGenerationMutex = Mutex();
|
||||
static Completer<void>? _tableGenerationCompleter;
|
||||
|
@ -200,7 +173,6 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet
|
|||
}
|
||||
|
||||
final syncMutex = Mutex();
|
||||
NodeModel? _xelisNode;
|
||||
Timer? timer;
|
||||
String? tablePath;
|
||||
|
||||
|
@ -216,9 +188,12 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet
|
|||
}
|
||||
|
||||
Future<XelisTableState> getTableState() async {
|
||||
final hasFullTables = await secureStorageInterface.read(key: _kHasFullTablesKey) == 'true';
|
||||
final isGenerating = await secureStorageInterface.read(key: _kGeneratingTablesKey) == 'true';
|
||||
final wantsFull = await secureStorageInterface.read(key: _kWantsFullTablesKey) != 'false';
|
||||
final hasFullTables =
|
||||
await secureStorageInterface.read(key: _kHasFullTablesKey) == 'true';
|
||||
final isGenerating =
|
||||
await secureStorageInterface.read(key: _kGeneratingTablesKey) == 'true';
|
||||
final wantsFull =
|
||||
await secureStorageInterface.read(key: _kWantsFullTablesKey) != 'false';
|
||||
|
||||
return XelisTableState(
|
||||
isGenerating: isGenerating,
|
||||
|
@ -249,21 +224,30 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet
|
|||
await for (final rawData in rawEventStream) {
|
||||
final json = jsonDecode(rawData);
|
||||
try {
|
||||
final eventType = xelis_sdk.WalletEvent.fromStr(json['event'] as String);
|
||||
final eventType = xelis_sdk.WalletEvent.fromStr(
|
||||
json['event'] as String,
|
||||
);
|
||||
switch (eventType) {
|
||||
case xelis_sdk.WalletEvent.newTopoHeight:
|
||||
yield NewTopoheight(json['data']['topoheight'] as int);
|
||||
case xelis_sdk.WalletEvent.newAsset:
|
||||
yield NewAsset(
|
||||
xelis_sdk.AssetData.fromJson(json['data'] as Map<String, dynamic>));
|
||||
xelis_sdk.AssetData.fromJson(
|
||||
json['data'] as Map<String, dynamic>,
|
||||
),
|
||||
);
|
||||
case xelis_sdk.WalletEvent.newTransaction:
|
||||
yield NewTransaction(
|
||||
xelis_sdk.TransactionEntry.fromJson(
|
||||
json['data'] as Map<String, dynamic>));
|
||||
xelis_sdk.TransactionEntry.fromJson(
|
||||
json['data'] as Map<String, dynamic>,
|
||||
),
|
||||
);
|
||||
case xelis_sdk.WalletEvent.balanceChanged:
|
||||
yield BalanceChanged(
|
||||
xelis_sdk.BalanceChangedEvent.fromJson(
|
||||
json['data'] as Map<String, dynamic>));
|
||||
xelis_sdk.BalanceChangedEvent.fromJson(
|
||||
json['data'] as Map<String, dynamic>,
|
||||
),
|
||||
);
|
||||
case xelis_sdk.WalletEvent.rescan:
|
||||
yield Rescan(json['data']['start_topoheight'] as int);
|
||||
case xelis_sdk.WalletEvent.online:
|
||||
|
@ -273,7 +257,7 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet
|
|||
case xelis_sdk.WalletEvent.historySynced:
|
||||
yield HistorySynced(json['data']['topoheight'] as int);
|
||||
}
|
||||
} catch (e, s) {
|
||||
} catch (_) {
|
||||
// Logging.instance.log(
|
||||
// "Error processing wallet event: $e\n$s",
|
||||
// level: LogLevel.Error,
|
||||
|
@ -293,12 +277,12 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet
|
|||
Future<void> handleHistorySynced(int topoheight) async {}
|
||||
Future<void> handleNewAsset(xelis_sdk.AssetData asset) async {}
|
||||
|
||||
@override
|
||||
Future<void> refresh({int? topoheight});
|
||||
|
||||
Future<void> connect() async {
|
||||
try {
|
||||
_eventSubscription =
|
||||
convertRawEvents().listen(handleEvent);
|
||||
_eventSubscription = convertRawEvents().listen(handleEvent);
|
||||
|
||||
final node = getCurrentNode();
|
||||
// Logging.instance.log(
|
||||
|
@ -306,10 +290,10 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet
|
|||
// level: LogLevel.Info,
|
||||
// );
|
||||
await libXelisWallet!.onlineMode(
|
||||
daemonAddress: "${node.host}:${node.port}"
|
||||
daemonAddress: "${node.host}:${node.port}",
|
||||
);
|
||||
await super.refresh();
|
||||
} catch (e, s) {
|
||||
} catch (_) {
|
||||
// Logging.instance.log(
|
||||
// "Error connecting to node: $e\n$s",
|
||||
// level: LogLevel.Error,
|
||||
|
@ -319,26 +303,20 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet
|
|||
}
|
||||
|
||||
List<FilterOperation> get standardReceivingAddressFilters => [
|
||||
FilterCondition.equalTo(
|
||||
property: r"type",
|
||||
value: info.mainAddressType,
|
||||
),
|
||||
const FilterCondition.equalTo(
|
||||
property: r"subType",
|
||||
value: AddressSubType.receiving,
|
||||
),
|
||||
];
|
||||
FilterCondition.equalTo(property: r"type", value: info.mainAddressType),
|
||||
const FilterCondition.equalTo(
|
||||
property: r"subType",
|
||||
value: AddressSubType.receiving,
|
||||
),
|
||||
];
|
||||
|
||||
List<FilterOperation> get standardChangeAddressFilters => [
|
||||
FilterCondition.equalTo(
|
||||
property: r"type",
|
||||
value: info.mainAddressType,
|
||||
),
|
||||
const FilterCondition.equalTo(
|
||||
property: r"subType",
|
||||
value: AddressSubType.change,
|
||||
),
|
||||
];
|
||||
FilterCondition.equalTo(property: r"type", value: info.mainAddressType),
|
||||
const FilterCondition.equalTo(
|
||||
property: r"subType",
|
||||
value: AddressSubType.change,
|
||||
),
|
||||
];
|
||||
|
||||
@override
|
||||
Future<void> open() async {
|
||||
|
@ -374,7 +352,7 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet
|
|||
password: password!,
|
||||
network: cryptoCurrency.network.xelisNetwork,
|
||||
precomputedTablesPath: tablePath,
|
||||
l1Low: tableState.currentSize.isLow
|
||||
l1Low: tableState.currentSize.isLow,
|
||||
);
|
||||
|
||||
final mnemonic = await wallet.getSeed();
|
||||
|
@ -382,7 +360,7 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet
|
|||
key: Wallet.mnemonicKey(walletId: walletId),
|
||||
value: mnemonic.trim(),
|
||||
);
|
||||
|
||||
|
||||
await secureStorageInterface.delete(
|
||||
key: '_${walletId}_needs_creation',
|
||||
);
|
||||
|
@ -402,14 +380,14 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet
|
|||
seed: mnemonic.trim(),
|
||||
network: cryptoCurrency.network.xelisNetwork,
|
||||
precomputedTablesPath: tablePath,
|
||||
l1Low: tableState.currentSize.isLow
|
||||
l1Low: tableState.currentSize.isLow,
|
||||
);
|
||||
|
||||
await secureStorageInterface.write(
|
||||
key: Wallet.mnemonicKey(walletId: walletId),
|
||||
value: mnemonic.trim(),
|
||||
);
|
||||
|
||||
|
||||
await secureStorageInterface.delete(
|
||||
key: '_${walletId}_needs_restoration',
|
||||
);
|
||||
|
@ -427,7 +405,7 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet
|
|||
);
|
||||
}
|
||||
});
|
||||
} catch (e, s) {
|
||||
} catch (_) {
|
||||
// Logging.instance.log(
|
||||
// "Failed to open/create wallet: $e\n$s",
|
||||
// level: LogLevel.Error,
|
||||
|
@ -435,7 +413,7 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet
|
|||
rethrow;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
debugPrint("Checking for upgradability");
|
||||
if (await isTableUpgradeAvailable()) {
|
||||
debugPrint("Generating large tables in background");
|
||||
|
@ -443,16 +421,17 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet
|
|||
}
|
||||
}
|
||||
|
||||
final newReceivingAddress = await getCurrentReceivingAddress() ??
|
||||
Address(
|
||||
walletId: walletId,
|
||||
derivationIndex: 0,
|
||||
derivationPath: null,
|
||||
value: libXelisWallet!.getAddressStr(),
|
||||
publicKey: [],
|
||||
type: AddressType.xelis,
|
||||
subType: AddressSubType.receiving,
|
||||
);
|
||||
final newReceivingAddress =
|
||||
await getCurrentReceivingAddress() ??
|
||||
Address(
|
||||
walletId: walletId,
|
||||
derivationIndex: 0,
|
||||
derivationPath: null,
|
||||
value: libXelisWallet!.getAddressStr(),
|
||||
publicKey: [],
|
||||
type: AddressType.xelis,
|
||||
subType: AddressSubType.receiving,
|
||||
);
|
||||
await mainDB.updateOrPutAddresses([newReceivingAddress]);
|
||||
|
||||
if (info.cachedReceivingAddress != newReceivingAddress.value) {
|
||||
|
@ -490,7 +469,7 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet
|
|||
await libXelisWallet?.close();
|
||||
libXelisWallet?.dispose();
|
||||
libXelisWallet = null;
|
||||
|
||||
|
||||
await super.exit();
|
||||
});
|
||||
}
|
||||
|
@ -505,15 +484,15 @@ abstract class LibXelisWallet<T extends ElectrumCurrency> extends ExternalWallet
|
|||
extension XelisTableManagement on LibXelisWallet {
|
||||
Future<bool> isTableUpgradeAvailable() async {
|
||||
if (kIsWeb) return false;
|
||||
|
||||
|
||||
final state = await getTableState();
|
||||
return state.currentSize != state.desiredSize;
|
||||
}
|
||||
|
||||
Future<void> updateTablesToDesiredSize() async {
|
||||
if (kIsWeb) return;
|
||||
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
|
||||
await Future<void>.delayed(const Duration(seconds: 1));
|
||||
if (LibXelisWallet._tableGenerationCompleter != null) {
|
||||
try {
|
||||
await LibXelisWallet._tableGenerationCompleter!.future;
|
||||
|
@ -522,7 +501,7 @@ extension XelisTableManagement on LibXelisWallet {
|
|||
// Previous generation failed, we'll try again
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
await LibXelisWallet._tableGenerationMutex.protect(() async {
|
||||
// Check again after acquiring mutex
|
||||
if (LibXelisWallet._tableGenerationCompleter != null) {
|
||||
|
@ -533,7 +512,7 @@ extension XelisTableManagement on LibXelisWallet {
|
|||
// Previous generation failed, we'll try again
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final state = await getTableState();
|
||||
if (state.currentSize == state.desiredSize) return;
|
||||
|
||||
|
@ -547,30 +526,32 @@ extension XelisTableManagement on LibXelisWallet {
|
|||
l1Low: state.desiredSize.isLow,
|
||||
);
|
||||
|
||||
await setTableState(XelisTableState(
|
||||
isGenerating: false,
|
||||
currentSize: state.desiredSize,
|
||||
desiredSize: state.desiredSize,
|
||||
));
|
||||
await setTableState(
|
||||
XelisTableState(
|
||||
isGenerating: false,
|
||||
currentSize: state.desiredSize,
|
||||
desiredSize: state.desiredSize,
|
||||
),
|
||||
);
|
||||
|
||||
debugPrint("Table upgrade done");
|
||||
LibXelisWallet._tableGenerationCompleter!.complete();
|
||||
} catch (e, s) {
|
||||
} catch (e) {
|
||||
// Logging.instance.log(
|
||||
// "Failed to update tables: $e\n$s",
|
||||
// level: LogLevel.Error,
|
||||
// );
|
||||
await setTableState(state.copyWith(isGenerating: false));
|
||||
|
||||
|
||||
LibXelisWallet._tableGenerationCompleter!.completeError(e);
|
||||
} finally {
|
||||
if (!LibXelisWallet._tableGenerationCompleter!.isCompleted) {
|
||||
LibXelisWallet._tableGenerationCompleter!.completeError(
|
||||
Exception('Table generation abandoned')
|
||||
Exception('Table generation abandoned'),
|
||||
);
|
||||
}
|
||||
LibXelisWallet._tableGenerationCompleter = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue