add rescan from height feature and test workflow build

This commit is contained in:
Matthew Fosse 2024-06-28 09:16:54 -07:00
parent 1430c4487f
commit 29f77aae22
9 changed files with 68 additions and 45 deletions

View file

@ -163,6 +163,16 @@ jobs:
run: |
echo -e "id=com.cakewallet.test_${{ env.PR_NUMBER }}\nname=${{ env.BRANCH_NAME }}" > /opt/android/cake_wallet/android/app.properties
- name: build mweb
run: |
cd /opt/android/cake_wallet
git clone https://github.com/ltcmweb/mwebd
cd /opt/android/cake_wallet/mwebd
go install github.com/ltcmweb/mwebd/cmd/mwebd@latest
gomobile bind -target=android -androidapi 21 github.com/ltcmweb/mwebd
mkdir -p /opt/android/cake_wallet/cw_mweb/android/libs/
mv ./mwebd.aar $_
- name: Build
run: |
cd /opt/android/cake_wallet

View file

@ -712,26 +712,13 @@ abstract class ElectrumWalletBase
value: BigInt.from(amountLeftForChangeAndFee),
));
int estimatedSize;
if (network is BitcoinCashNetwork) {
estimatedSize = ForkedTransactionBuilder.estimateTransactionSize(
utxos: utxoDetails.utxos,
outputs: outputs,
network: network as BitcoinCashNetwork,
memo: memo,
);
} else {
estimatedSize = BitcoinTransactionBuilder.estimateTransactionSize(
utxos: utxoDetails.utxos,
outputs: outputs,
network: network,
memo: memo,
inputPrivKeyInfos: utxoDetails.inputPrivKeyInfos,
vinOutpoints: utxoDetails.vinOutpoints,
);
}
int fee = feeAmountWithFeeRate(feeRate, 0, 0, size: estimatedSize);
int fee = await calcFee(
utxos: utxoDetails.utxos,
outputs: outputs,
network: network,
memo: memo,
feeRate: feeRate,
);
if (fee == 0) {
throw BitcoinTransactionNoFeeException();
@ -741,6 +728,8 @@ abstract class ElectrumWalletBase
final lastOutput = outputs.last;
final amountLeftForChange = amountLeftForChangeAndFee - fee;
print(amountLeftForChangeAndFee);
if (!_isBelowDust(amountLeftForChange)) {
// Here, lastOutput already is change, return the amount left without the fee to the user's address.
outputs[outputs.length - 1] =
@ -1786,18 +1775,6 @@ abstract class ElectrumWalletBase
await save();
}
String getChangeAddress() {
const minCountOfHiddenAddresses = 5;
final random = Random();
var addresses = walletAddresses.allAddresses.where((addr) => addr.isHidden).toList();
if (addresses.length < minCountOfHiddenAddresses) {
addresses = walletAddresses.allAddresses.toList();
}
return addresses[random.nextInt(addresses.length)].address;
}
@override
void setExceptionHandler(void Function(FlutterErrorDetails) onError) => _onError = onError;

View file

@ -184,7 +184,6 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
final confirmations = mwebUtxosHeight - transaction.height + 1;
if (transaction.confirmations == confirmations) continue;
transaction.confirmations = confirmations;
print("BEING ADDED HERE@@@@@@@@@@@@@@@@@@@@@@@4");
transactionHistory.addOne(transaction);
}
await transactionHistory.save();
@ -200,6 +199,22 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
mwebUtxosBox = await CakeHive.openBox<MwebUtxo>(boxName);
}
@action
@override
Future<void> rescan({
required int height,
int? chainTip,
ScanData? scanData,
bool? doSingleScan,
bool? usingElectrs,
}) async {
await mwebUtxosBox.clear();
mwebUtxosHeight = height;
walletInfo.restoreHeight = height;
await walletInfo.save();
processMwebUtxos();
}
@override
Future<void> init() async {
await initMwebUtxosBox();
@ -208,9 +223,9 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
Future<void> processMwebUtxos() async {
final stub = await CwMweb.stub();
final scanSecret = mwebHd.derive(0x80000000).privKey!;
print("SCANNING FROM HEIGHT: ${walletInfo.restoreHeight}");
final req =
UtxosRequest(scanSecret: hex.decode(scanSecret), fromHeight: walletInfo.restoreHeight);
int restoreHeight = walletInfo.restoreHeight;
print("SCANNING FROM HEIGHT: $restoreHeight");
final req = UtxosRequest(scanSecret: hex.decode(scanSecret), fromHeight: restoreHeight);
bool initDone = false;
for (final utxo in mwebUtxosBox.values) {
@ -257,7 +272,11 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
if (isNew) {
final addressRecord = walletAddresses.allAddresses
.firstWhere((addressRecord) => addressRecord.address == utxo.address);
.firstWhereOrNull((addressRecord) => addressRecord.address == utxo.address);
if (addressRecord == null) {
print("addressRecord is null! TODO: handle this case 1");
continue;
}
if (!(tx.inputAddresses?.contains(utxo.address) ?? false)) addressRecord.txCount++;
addressRecord.balance += utxo.value.toInt();
addressRecord.setAsUsed();
@ -401,7 +420,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
// print(a.address);
// }
if (addressRecord == null) {
print("addressRecord is null! TODO: handle this case");
print("addressRecord is null! TODO: handle this case2");
return;
}
final unspent = BitcoinUnspent(
@ -423,7 +442,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
unconfirmed += utxo.value.toInt();
}
});
print("confirmed: $confirmed, unconfirmed: $unconfirmed");
// print("confirmed: $confirmed, unconfirmed: $unconfirmed");
return ElectrumBalance(confirmed: confirmed, unconfirmed: unconfirmed, frozen: balance.frozen);
}
@ -513,6 +532,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
Future<PendingTransaction> createTransaction(Object credentials) async {
try {
final tx = await super.createTransaction(credentials) as PendingBitcoinTransaction;
final stub = await CwMweb.stub();
final resp = await stub.create(CreateRequest(
rawTx: hex.decode(tx.hex),

View file

@ -68,6 +68,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
@action
@override
Future<String> getChangeAddress() async {
// super.getChangeAddress();
updateChangeAddresses();
// this means all change addresses used will be mweb addresses!:
await topUpMweb(0);

View file

@ -32,8 +32,8 @@ class PendingBitcoinTransaction with PendingTransaction {
final int fee;
final String feeRate;
final BasedUtxoNetwork? network;
final bool hasChange;
final bool isSendAll;
final bool hasChange;
final bool hasTaprootInputs;
String? idOverride;
String? hexOverride;
@ -91,19 +91,24 @@ class PendingBitcoinTransaction with PendingTransaction {
}
}
@override
Future<void> commit() async {
if (network is LitecoinNetwork) try {
Future<void> _ltcCommit() async {
try {
final stub = await CwMweb.stub();
final resp = await stub.broadcast(BroadcastRequest(rawTx: BytesUtils.fromHexString(hex)));
idOverride = resp.txid;
} on GrpcError catch (e) {
throw BitcoinTransactionCommitFailed(errorMessage: e.message);
}
}
@override
Future<void> commit() async {
if (network is LitecoinNetwork) {
await _ltcCommit();
} else {
await _commit();
}
_listeners.forEach((listener) => listener(transactionInfo()));
}

View file

@ -30,6 +30,7 @@ class RescanPage extends BasePage {
key: _blockchainHeightWidgetKey,
onHeightOrDateEntered: (value) => _rescanViewModel.isButtonEnabled = value,
isSilentPaymentsScan: _rescanViewModel.isSilentPaymentsScan,
isMwebScan: _rescanViewModel.isMwebScan,
doSingleScan: _rescanViewModel.doSingleScan,
toggleSingleScan: () =>
_rescanViewModel.doSingleScan = !_rescanViewModel.doSingleScan,

View file

@ -16,6 +16,7 @@ class BlockchainHeightWidget extends StatefulWidget {
this.onHeightOrDateEntered,
this.hasDatePicker = true,
this.isSilentPaymentsScan = false,
this.isMwebScan = false,
this.toggleSingleScan,
this.doSingleScan = false,
}) : super(key: key);
@ -25,6 +26,7 @@ class BlockchainHeightWidget extends StatefulWidget {
final FocusNode? focusNode;
final bool hasDatePicker;
final bool isSilentPaymentsScan;
final bool isMwebScan;
final bool doSingleScan;
final Function()? toggleSingleScan;
@ -157,7 +159,10 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
if (date != null) {
int height;
if (widget.isSilentPaymentsScan) {
if (widget.isMwebScan) {
throw UnimplementedError();
// height = bitcoin!.getMwebHeightByDate(date: date);
} else if (widget.isSilentPaymentsScan) {
height = bitcoin!.getHeightByDate(date: date);
} else {
height = monero!.getHeightByDate(date: date);

View file

@ -303,6 +303,7 @@ abstract class DashboardViewModelBase with Store {
bool get hasRescan =>
wallet.type == WalletType.bitcoin ||
wallet.type == WalletType.monero ||
wallet.type == WalletType.litecoin ||
wallet.type == WalletType.haven;
@computed

View file

@ -29,6 +29,9 @@ abstract class RescanViewModelBase with Store {
@computed
bool get isSilentPaymentsScan => wallet.type == WalletType.bitcoin;
@computed
bool get isMwebScan => wallet.type == WalletType.litecoin;
@action
Future<void> rescanCurrentWallet({required int restoreHeight}) async {
state = RescanWalletState.rescaning;