mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-02-02 11:16:26 +00:00
feat: beginning isolate, add compute
This commit is contained in:
parent
06d9231f8d
commit
41f2e4ab33
3 changed files with 237 additions and 121 deletions
|
@ -145,6 +145,10 @@ abstract class ElectrumWalletBase
|
|||
@action
|
||||
@override
|
||||
Future<void> startSync() async {
|
||||
compute(test, {
|
||||
"scanPrivateKeyCompressed": walletAddresses.silentAddress!.scanPrivkey.toCompressedHex(),
|
||||
"spendPubkeyCompressed": walletAddresses.silentAddress!.spendPubkey.toCompressedHex()
|
||||
});
|
||||
try {
|
||||
syncStatus = AttemptingSyncStatus();
|
||||
await walletAddresses.discoverAddresses();
|
||||
|
@ -349,13 +353,11 @@ abstract class ElectrumWalletBase
|
|||
|
||||
generatedOutputs.forEach((recipientSilentAddress, generatedOutput) {
|
||||
generatedOutput.forEach((output) {
|
||||
final generatedPubkey = output.$1.toCompressedHex();
|
||||
txb.addOutput(
|
||||
bitcoin.ECPublic.fromHex(generatedPubkey)
|
||||
.toTaprootAddress()
|
||||
.toScriptPubKey()
|
||||
.toBytes(),
|
||||
amount);
|
||||
final generatedPubkey = output.$1.toHex();
|
||||
// TODO: pubkeyToOutputScript (?)
|
||||
final point = bitcoin.ECPublic.fromHex(generatedPubkey).toTapPoint();
|
||||
final p2tr = bitcoin.P2trAddress(program: point);
|
||||
txb.addOutput(p2tr.toScriptPubKey().toBytes(), amount);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -525,69 +527,6 @@ abstract class ElectrumWalletBase
|
|||
return null;
|
||||
}
|
||||
}).whereNotNull())));
|
||||
final txid = "28a21e8b6373bf20928107f8f1f1ea5a98ada793f2676372d03466e874d4e762";
|
||||
final uri = Uri(scheme: 'https', host: 'blockstream.info', path: '/testnet/api/tx/$txid');
|
||||
// final uri = Uri(scheme: 'https', host: 'blockstream.info', path: 'testnet/api/block-height/0');
|
||||
|
||||
await http.get(uri).then((response) {
|
||||
// print(response.body);
|
||||
final obj = json.decode(response.body);
|
||||
final scanPrivateKey = walletAddresses.silentAddress!.scanPrivkey;
|
||||
final spendPublicKey = walletAddresses.silentAddress!.spendPubkey;
|
||||
|
||||
List<String> pubkeys = [];
|
||||
List<bitcoin.Outpoint> outpoints = [];
|
||||
obj["vin"].forEach((input) {
|
||||
final witness = input["witness"] as List<dynamic>;
|
||||
final pubkey = witness[1] as String;
|
||||
pubkeys.add(pubkey);
|
||||
outpoints.add(bitcoin.Outpoint(txid: input["txid"] as String, index: input["vout"] as int));
|
||||
});
|
||||
|
||||
Uint8List sumOfInputPublicKeys =
|
||||
bitcoin.getSumInputPubKeys(pubkeys).toCompressedHex().fromHex;
|
||||
final outpointHash = bitcoin.SilentPayment.hashOutpoints(outpoints);
|
||||
|
||||
Map<String, bitcoin.Outpoint> outpointsByP2TRpubkey = {};
|
||||
int i = 0;
|
||||
obj['vout'].forEach((out) {
|
||||
if (out["scriptpubkey_type"] == "v1_p2tr")
|
||||
outpointsByP2TRpubkey[out['scriptpubkey_address'] as String] =
|
||||
bitcoin.Outpoint(txid: txid, index: i, value: out["value"] as int);
|
||||
|
||||
i++;
|
||||
});
|
||||
final result = bitcoin.scanOutputs(
|
||||
scanPrivateKey.toCompressedHex().fromHex,
|
||||
spendPublicKey.toCompressedHex().fromHex,
|
||||
sumOfInputPublicKeys,
|
||||
outpointHash,
|
||||
outpointsByP2TRpubkey.keys.toList());
|
||||
|
||||
// print(result);
|
||||
|
||||
result.forEach((key, value) {
|
||||
final outpoint = outpointsByP2TRpubkey[key];
|
||||
// if (outpoint != null) {
|
||||
// unspentCoins.add(BitcoinUnspent(
|
||||
// BitcoinAddressRecord(walletAddresses.silentAddress.toString(), index: 0),
|
||||
// outpoint.txid,
|
||||
// outpoint.value!,
|
||||
// outpoint.n));
|
||||
|
||||
// final currentBalance = balance[currency];
|
||||
// if (currentBalance != null) {
|
||||
// balance[currency] = ElectrumBalance(
|
||||
// confirmed: currentBalance.confirmed + outpoint.value!,
|
||||
// unconfirmed: currentBalance.unconfirmed,
|
||||
// frozen: currentBalance.frozen);
|
||||
// } else {
|
||||
// balance[currency] =
|
||||
// ElectrumBalance(confirmed: outpoint.value!, unconfirmed: 0, frozen: 0);
|
||||
// }
|
||||
// }
|
||||
});
|
||||
});
|
||||
unspentCoins = unspent.expand((e) => e).toList();
|
||||
|
||||
if (unspentCoinsInfo.isEmpty) {
|
||||
|
@ -848,7 +787,7 @@ abstract class ElectrumWalletBase
|
|||
}
|
||||
|
||||
// int _getHeightByDate(DateTime date) {
|
||||
// final nodeHeight = monero_wallet.getNodeHeightSync();
|
||||
// final currentHeight = await electrumClient.getCurrentBlockChainTip();
|
||||
// final heightDistance = _getHeightDistance(date);
|
||||
|
||||
// if (nodeHeight <= 0) {
|
||||
|
@ -868,10 +807,73 @@ abstract class ElectrumWalletBase
|
|||
final currentHeight = await electrumClient.getCurrentBlockChainTip();
|
||||
if (currentHeight == null) return;
|
||||
|
||||
// if (currentHeight <= 1) {
|
||||
// final height = _getHeightByDate(walletInfo.date);
|
||||
// monero_wallet.setRecoveringFromSeed(isRecovery: true);
|
||||
// monero_wallet.setRefreshFromBlockHeight(height: height);
|
||||
// }
|
||||
if (currentHeight <= 1) {
|
||||
// final height = _getHeightByDate(walletInfo.date);
|
||||
// monero_wallet.setRecoveringFromSeed(isRecovery: true);
|
||||
// monero_wallet.setRefreshFromBlockHeight(height: height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test(Map<String, String> addrs) async {
|
||||
final txid = "920244856cba9d8421ea01f3930baec80642b2b908c0e83a7e6c918040d5656e";
|
||||
final uri = Uri(scheme: 'https', host: 'blockstream.info', path: '/testnet/api/tx/$txid');
|
||||
// final uri = Uri(scheme: 'https', host: 'blockstream.info', path: 'testnet/api/block-height/0');
|
||||
|
||||
await http.get(uri).then((response) {
|
||||
// print(response.body);
|
||||
final obj = json.decode(response.body);
|
||||
|
||||
List<String> pubkeys = [];
|
||||
List<bitcoin.Outpoint> outpoints = [];
|
||||
obj["vin"].forEach((input) {
|
||||
final witness = input["witness"] as List<dynamic>;
|
||||
final pubkey = witness[1] as String;
|
||||
pubkeys.add(pubkey);
|
||||
outpoints.add(bitcoin.Outpoint(txid: input["txid"] as String, index: input["vout"] as int));
|
||||
});
|
||||
|
||||
Uint8List sumOfInputPublicKeys = bitcoin.getSumInputPubKeys(pubkeys).toCompressedHex().fromHex;
|
||||
final outpointHash = bitcoin.SilentPayment.hashOutpoints(outpoints);
|
||||
|
||||
Map<String, bitcoin.Outpoint> outpointsByP2TRpubkey = {};
|
||||
int i = 0;
|
||||
obj['vout'].forEach((out) {
|
||||
if (out["scriptpubkey_type"] == "v1_p2tr")
|
||||
outpointsByP2TRpubkey[out['scriptpubkey_address'] as String] =
|
||||
bitcoin.Outpoint(txid: txid, index: i, value: out["value"] as int);
|
||||
|
||||
i++;
|
||||
});
|
||||
final result = bitcoin.scanOutputs(
|
||||
(addrs["scanPrivateKeyCompressed"] as String).fromHex,
|
||||
(addrs["spendPubkeyCompressed"] as String).fromHex,
|
||||
sumOfInputPublicKeys,
|
||||
outpointHash,
|
||||
outpointsByP2TRpubkey.keys.toList());
|
||||
|
||||
print(["RESULT:", result]);
|
||||
|
||||
result.forEach((key, value) {
|
||||
final outpoint = outpointsByP2TRpubkey[key];
|
||||
// if (outpoint != null) {
|
||||
// unspentCoins.add(BitcoinUnspent(
|
||||
// BitcoinAddressRecord(walletAddresses.silentAddress.toString(), index: 0),
|
||||
// outpoint.txid,
|
||||
// outpoint.value!,
|
||||
// outpoint.n));
|
||||
|
||||
// final currentBalance = balance[currency];
|
||||
// if (currentBalance != null) {
|
||||
// balance[currency] = ElectrumBalance(
|
||||
// confirmed: currentBalance.confirmed + outpoint.value!,
|
||||
// unconfirmed: currentBalance.unconfirmed,
|
||||
// frozen: currentBalance.frozen);
|
||||
// } else {
|
||||
// balance[currency] =
|
||||
// ElectrumBalance(confirmed: outpoint.value!, unconfirmed: 0, frozen: 0);
|
||||
// }
|
||||
// }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -44,11 +44,9 @@ packages:
|
|||
bech32:
|
||||
dependency: transitive
|
||||
description:
|
||||
path: "."
|
||||
ref: "cake-0.2.2"
|
||||
resolved-ref: "05755063b593aa6cca0a4820a318e0ce17de6192"
|
||||
url: "https://github.com/cake-tech/bech32.git"
|
||||
source: git
|
||||
path: "/home/rafael/Storage/Repositories/bech32"
|
||||
relative: false
|
||||
source: path
|
||||
version: "0.2.2"
|
||||
bip32:
|
||||
dependency: transitive
|
||||
|
@ -82,6 +80,13 @@ packages:
|
|||
relative: false
|
||||
source: path
|
||||
version: "2.0.2"
|
||||
blockchain_utils:
|
||||
dependency: transitive
|
||||
description:
|
||||
path: "/home/rafael/Storage/Repositories/blockchain_utils"
|
||||
relative: false
|
||||
source: path
|
||||
version: "1.0.3"
|
||||
boolean_selector:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -253,10 +258,9 @@ packages:
|
|||
dart_bech32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_bech32
|
||||
sha256: "0e1dc1ff39c9669c9ffeafd5d675104918f7b50799692491badfea7e1fb40888"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
path: "/home/rafael/Storage/Repositories/dart-bech32"
|
||||
relative: false
|
||||
source: path
|
||||
version: "2.0.0"
|
||||
dart_style:
|
||||
dependency: transitive
|
||||
|
@ -803,5 +807,5 @@ packages:
|
|||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.0.0 <4.0.0"
|
||||
dart: ">=3.0.6 <4.0.0"
|
||||
flutter: ">=3.7.0"
|
||||
|
|
|
@ -16,6 +16,7 @@ import 'package:cake_wallet/main.dart';
|
|||
import 'package:cake_wallet/di.dart';
|
||||
|
||||
const moneroSyncTaskKey = "com.fotolockr.cakewallet.monero_sync_task";
|
||||
const bitcoinSilentPaymentsSyncTaskKey = "com.fotolockr.cakewallet.bitcoin_sync_task";
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void callbackDispatcher() {
|
||||
|
@ -68,6 +69,62 @@ void callbackDispatcher() {
|
|||
return Future.error("No Monero wallet found");
|
||||
}
|
||||
|
||||
for (int i = 0;; i++) {
|
||||
await Future<void>.delayed(const Duration(seconds: 1));
|
||||
if (wallet?.syncStatus.progress() == 1.0) {
|
||||
break;
|
||||
}
|
||||
if (i > 600) {
|
||||
return Future.error("Synchronization Timed out");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case bitcoinSilentPaymentsSyncTaskKey:
|
||||
|
||||
/// The work manager runs on a separate isolate from the main flutter isolate.
|
||||
/// thus we initialize app configs first; hive, getIt, etc...
|
||||
await initializeAppConfigs();
|
||||
|
||||
final walletLoadingService = getIt.get<WalletLoadingService>();
|
||||
|
||||
final node = getIt.get<SettingsStore>().getCurrentNode(WalletType.bitcoin);
|
||||
|
||||
final typeRaw = getIt.get<SharedPreferences>().getInt(PreferencesKey.currentWalletType);
|
||||
|
||||
WalletBase? wallet;
|
||||
|
||||
if (inputData!['sync_all'] as bool) {
|
||||
// /// get all Monero wallets of the user and sync them
|
||||
// final List<WalletListItem> moneroWallets = getIt
|
||||
// .get<WalletListViewModel>()
|
||||
// .wallets
|
||||
// .where((element) => element.type == WalletType.monero)
|
||||
// .toList();
|
||||
|
||||
// for (int i = 0; i < moneroWallets.length; i++) {
|
||||
// wallet = await walletLoadingService.load(WalletType.monero, moneroWallets[i].name);
|
||||
|
||||
// await wallet.connectToNode(node: node);
|
||||
// await wallet.startSync();
|
||||
// }
|
||||
} else {
|
||||
/// if the user chose to sync only active wallet
|
||||
/// if the current wallet is monero; sync it only
|
||||
if (typeRaw == WalletType.bitcoin.index) {
|
||||
final name =
|
||||
getIt.get<SharedPreferences>().getString(PreferencesKey.currentWalletName);
|
||||
|
||||
wallet = await walletLoadingService.load(WalletType.bitcoin, name!);
|
||||
|
||||
await wallet.startSync();
|
||||
}
|
||||
}
|
||||
|
||||
if (wallet?.syncStatus.progress() == null) {
|
||||
return Future.error("No Bitcoin wallet with silent payments enabled found");
|
||||
}
|
||||
|
||||
for (int i = 0;; i++) {
|
||||
await Future<void>.delayed(const Duration(seconds: 1));
|
||||
if (wallet?.syncStatus.progress() == 1.0) {
|
||||
|
@ -98,55 +155,108 @@ class BackgroundTasks {
|
|||
.any((element) => element.type == WalletType.monero);
|
||||
|
||||
/// if its not android nor ios, or the user has no monero wallets; exit
|
||||
if (!DeviceInfo.instance.isMobile || !hasMonero) {
|
||||
return;
|
||||
}
|
||||
if (DeviceInfo.instance.isMobile && hasMonero) {
|
||||
final settingsStore = getIt.get<SettingsStore>();
|
||||
|
||||
final settingsStore = getIt.get<SettingsStore>();
|
||||
final SyncMode syncMode = settingsStore.currentSyncMode;
|
||||
final bool syncAll = settingsStore.currentSyncAll;
|
||||
|
||||
final SyncMode syncMode = settingsStore.currentSyncMode;
|
||||
final bool syncAll = settingsStore.currentSyncAll;
|
||||
if (syncMode.type == SyncType.disabled) {
|
||||
cancelSyncTask();
|
||||
return;
|
||||
}
|
||||
|
||||
if (syncMode.type == SyncType.disabled) {
|
||||
cancelSyncTask();
|
||||
return;
|
||||
}
|
||||
await Workmanager().initialize(
|
||||
callbackDispatcher,
|
||||
isInDebugMode: kDebugMode,
|
||||
);
|
||||
|
||||
await Workmanager().initialize(
|
||||
callbackDispatcher,
|
||||
isInDebugMode: kDebugMode,
|
||||
);
|
||||
final inputData = <String, dynamic>{"sync_all": syncAll};
|
||||
final constraints = Constraints(
|
||||
networkType:
|
||||
syncMode.type == SyncType.unobtrusive ? NetworkType.unmetered : NetworkType.connected,
|
||||
requiresBatteryNotLow: syncMode.type == SyncType.unobtrusive,
|
||||
requiresCharging: syncMode.type == SyncType.unobtrusive,
|
||||
requiresDeviceIdle: syncMode.type == SyncType.unobtrusive,
|
||||
);
|
||||
|
||||
final inputData = <String, dynamic>{"sync_all": syncAll};
|
||||
final constraints = Constraints(
|
||||
networkType:
|
||||
syncMode.type == SyncType.unobtrusive ? NetworkType.unmetered : NetworkType.connected,
|
||||
requiresBatteryNotLow: syncMode.type == SyncType.unobtrusive,
|
||||
requiresCharging: syncMode.type == SyncType.unobtrusive,
|
||||
requiresDeviceIdle: syncMode.type == SyncType.unobtrusive,
|
||||
);
|
||||
if (Platform.isIOS) {
|
||||
await Workmanager().registerOneOffTask(
|
||||
moneroSyncTaskKey,
|
||||
moneroSyncTaskKey,
|
||||
initialDelay: syncMode.frequency,
|
||||
existingWorkPolicy: ExistingWorkPolicy.replace,
|
||||
inputData: inputData,
|
||||
constraints: constraints,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Platform.isIOS) {
|
||||
await Workmanager().registerOneOffTask(
|
||||
await Workmanager().registerPeriodicTask(
|
||||
moneroSyncTaskKey,
|
||||
moneroSyncTaskKey,
|
||||
initialDelay: syncMode.frequency,
|
||||
existingWorkPolicy: ExistingWorkPolicy.replace,
|
||||
frequency: syncMode.frequency,
|
||||
existingWorkPolicy: changeExisting ? ExistingWorkPolicy.replace : ExistingWorkPolicy.keep,
|
||||
inputData: inputData,
|
||||
constraints: constraints,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
await Workmanager().registerPeriodicTask(
|
||||
moneroSyncTaskKey,
|
||||
moneroSyncTaskKey,
|
||||
initialDelay: syncMode.frequency,
|
||||
frequency: syncMode.frequency,
|
||||
existingWorkPolicy: changeExisting ? ExistingWorkPolicy.replace : ExistingWorkPolicy.keep,
|
||||
inputData: inputData,
|
||||
constraints: constraints,
|
||||
);
|
||||
bool hasBitcoin = getIt
|
||||
.get<WalletListViewModel>()
|
||||
.wallets
|
||||
.any((element) => element.type == WalletType.bitcoin);
|
||||
|
||||
/// if its not android nor ios, or the user has no monero wallets; exit
|
||||
// if (hasBitcoin) {
|
||||
if (false) {
|
||||
final settingsStore = getIt.get<SettingsStore>();
|
||||
|
||||
final SyncMode syncMode = settingsStore.currentSyncMode;
|
||||
final bool syncAll = settingsStore.currentSyncAll;
|
||||
|
||||
if (syncMode.type == SyncType.disabled) {
|
||||
cancelSyncTask();
|
||||
return;
|
||||
}
|
||||
|
||||
await Workmanager().initialize(
|
||||
callbackDispatcher,
|
||||
isInDebugMode: kDebugMode,
|
||||
);
|
||||
|
||||
final inputData = <String, dynamic>{"sync_all": syncAll};
|
||||
final constraints = Constraints(
|
||||
networkType:
|
||||
syncMode.type == SyncType.unobtrusive ? NetworkType.unmetered : NetworkType.connected,
|
||||
requiresBatteryNotLow: syncMode.type == SyncType.unobtrusive,
|
||||
requiresCharging: syncMode.type == SyncType.unobtrusive,
|
||||
requiresDeviceIdle: syncMode.type == SyncType.unobtrusive,
|
||||
);
|
||||
|
||||
if (Platform.isIOS) {
|
||||
await Workmanager().registerOneOffTask(
|
||||
bitcoinSilentPaymentsSyncTaskKey,
|
||||
bitcoinSilentPaymentsSyncTaskKey,
|
||||
initialDelay: syncMode.frequency,
|
||||
existingWorkPolicy: ExistingWorkPolicy.replace,
|
||||
inputData: inputData,
|
||||
constraints: constraints,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
await Workmanager().registerPeriodicTask(
|
||||
bitcoinSilentPaymentsSyncTaskKey,
|
||||
bitcoinSilentPaymentsSyncTaskKey,
|
||||
initialDelay: syncMode.frequency,
|
||||
frequency: syncMode.frequency,
|
||||
existingWorkPolicy: changeExisting ? ExistingWorkPolicy.replace : ExistingWorkPolicy.keep,
|
||||
inputData: inputData,
|
||||
constraints: constraints,
|
||||
);
|
||||
}
|
||||
} catch (error, stackTrace) {
|
||||
print(error);
|
||||
print(stackTrace);
|
||||
|
|
Loading…
Reference in a new issue