mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-01-19 09:15:11 +00:00
Merge branch 'mweb' of https://github.com/cake-tech/cake_wallet into mweb-bg-sync-2
This commit is contained in:
commit
910825dc82
20 changed files with 144 additions and 121 deletions
12
.github/workflows/pr_test_build_android.yml
vendored
12
.github/workflows/pr_test_build_android.yml
vendored
|
@ -109,16 +109,8 @@ jobs:
|
||||||
# paths are reset after each step, so we need to set them again:
|
# paths are reset after each step, so we need to set them again:
|
||||||
export PATH=$PATH:/usr/local/go/bin
|
export PATH=$PATH:/usr/local/go/bin
|
||||||
export PATH=$PATH:~/go/bin
|
export PATH=$PATH:~/go/bin
|
||||||
# build mwebd:
|
cd /opt/android/cake_wallet/scripts/android/
|
||||||
cd /opt/android/cake_wallet
|
./build_mwebd.sh --dont-install
|
||||||
git clone https://github.com/ltcmweb/mwebd
|
|
||||||
cd /opt/android/cake_wallet/mwebd
|
|
||||||
git reset --hard f6ea8a9e3d348b01bb44f03a1cc4ad65b0abe935
|
|
||||||
gomobile bind -target=android -androidapi 21 .
|
|
||||||
mkdir -p /opt/android/cake_wallet/cw_mweb/android/libs/
|
|
||||||
mv ./mwebd.aar $_
|
|
||||||
cd ..
|
|
||||||
rm -rf mwebd
|
|
||||||
|
|
||||||
- name: Generate KeyStore
|
- name: Generate KeyStore
|
||||||
run: |
|
run: |
|
||||||
|
|
11
.github/workflows/pr_test_build_linux.yml
vendored
11
.github/workflows/pr_test_build_linux.yml
vendored
|
@ -105,15 +105,8 @@ jobs:
|
||||||
export PATH=$PATH:/usr/local/go/bin
|
export PATH=$PATH:/usr/local/go/bin
|
||||||
export PATH=$PATH:~/go/bin
|
export PATH=$PATH:~/go/bin
|
||||||
# build mwebd:
|
# build mwebd:
|
||||||
cd /opt/android/cake_wallet
|
cd /opt/android/cake_wallet/scripts/android/
|
||||||
git clone https://github.com/ltcmweb/mwebd
|
./build_mwebd.sh --dont-install
|
||||||
cd /opt/android/cake_wallet/mwebd
|
|
||||||
git reset --hard f6ea8a9e3d348b01bb44f03a1cc4ad65b0abe935
|
|
||||||
gomobile bind -target=android -androidapi 21 .
|
|
||||||
mkdir -p /opt/android/cake_wallet/cw_mweb/android/libs/
|
|
||||||
mv ./mwebd.aar $_
|
|
||||||
cd ..
|
|
||||||
rm -rf mwebd
|
|
||||||
|
|
||||||
- name: Generate localization
|
- name: Generate localization
|
||||||
run: |
|
run: |
|
||||||
|
|
|
@ -8,6 +8,7 @@ import 'package:cw_core/sec_random_native.dart';
|
||||||
import 'package:cw_core/utils/text_normalizer.dart';
|
import 'package:cw_core/utils/text_normalizer.dart';
|
||||||
|
|
||||||
const segwit = '100';
|
const segwit = '100';
|
||||||
|
const mweb = 'eb';
|
||||||
final wordlist = englishWordlist;
|
final wordlist = englishWordlist;
|
||||||
|
|
||||||
double logBase(num x, num base) => log(x) / log(base);
|
double logBase(num x, num base) => log(x) / log(base);
|
||||||
|
@ -125,7 +126,7 @@ Future<Uint8List> mnemonicToSeedBytes(String mnemonic,
|
||||||
return Uint8List.fromList(bytes);
|
return Uint8List.fromList(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool matchesAnyPrefix(String mnemonic) => prefixMatches(mnemonic, [segwit]).any((el) => el);
|
bool matchesAnyPrefix(String mnemonic) => prefixMatches(mnemonic, [segwit, mweb]).any((el) => el);
|
||||||
|
|
||||||
bool validateMnemonic(String mnemonic, {String prefix = segwit}) {
|
bool validateMnemonic(String mnemonic, {String prefix = segwit}) {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -113,10 +113,14 @@ class ElectrumClient {
|
||||||
},
|
},
|
||||||
onDone: () {
|
onDone: () {
|
||||||
unterminatedString = '';
|
unterminatedString = '';
|
||||||
|
try {
|
||||||
if (host == socket?.address.host) {
|
if (host == socket?.address.host) {
|
||||||
socket = null;
|
socket?.destroy();
|
||||||
_setConnectionStatus(ConnectionStatus.disconnected);
|
_setConnectionStatus(ConnectionStatus.disconnected);
|
||||||
}
|
}
|
||||||
|
} catch(e) {
|
||||||
|
print(e.toString());
|
||||||
|
}
|
||||||
},
|
},
|
||||||
cancelOnError: true,
|
cancelOnError: true,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1689,12 +1689,14 @@ abstract class ElectrumWalletBase
|
||||||
final Map<String, ElectrumTransactionInfo> historiesWithDetails = {};
|
final Map<String, ElectrumTransactionInfo> historiesWithDetails = {};
|
||||||
|
|
||||||
if (type == WalletType.bitcoin) {
|
if (type == WalletType.bitcoin) {
|
||||||
await Future.wait(ADDRESS_TYPES
|
await Future.wait(BITCOIN_ADDRESS_TYPES
|
||||||
.map((type) => fetchTransactionsForAddressType(historiesWithDetails, type)));
|
.map((type) => fetchTransactionsForAddressType(historiesWithDetails, type)));
|
||||||
} else if (type == WalletType.bitcoinCash) {
|
} else if (type == WalletType.bitcoinCash) {
|
||||||
await fetchTransactionsForAddressType(historiesWithDetails, P2pkhAddressType.p2pkh);
|
await Future.wait(BITCOIN_CASH_ADDRESS_TYPES
|
||||||
|
.map((type) => fetchTransactionsForAddressType(historiesWithDetails, type)));
|
||||||
} else if (type == WalletType.litecoin) {
|
} else if (type == WalletType.litecoin) {
|
||||||
await fetchTransactionsForAddressType(historiesWithDetails, SegwitAddresType.p2wpkh);
|
await Future.wait(LITECOIN_ADDRESS_TYPES
|
||||||
|
.map((type) => fetchTransactionsForAddressType(historiesWithDetails, type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
transactionHistory.transactions.values.forEach((tx) async {
|
transactionHistory.transactions.values.forEach((tx) async {
|
||||||
|
@ -2064,9 +2066,8 @@ abstract class ElectrumWalletBase
|
||||||
|
|
||||||
_isTryingToConnect = true;
|
_isTryingToConnect = true;
|
||||||
|
|
||||||
Timer(Duration(seconds: 10), () {
|
Timer(Duration(seconds: 5), () {
|
||||||
if (this.syncStatus is NotConnectedSyncStatus ||
|
if (this.syncStatus is NotConnectedSyncStatus || this.syncStatus is LostConnectionSyncStatus) {
|
||||||
this.syncStatus is LostConnectionSyncStatus) {
|
|
||||||
this.electrumClient.connectToUri(
|
this.electrumClient.connectToUri(
|
||||||
node!.uri,
|
node!.uri,
|
||||||
useSSL: node!.useSSL ?? false,
|
useSSL: node!.useSSL ?? false,
|
||||||
|
|
|
@ -11,15 +11,23 @@ part 'electrum_wallet_addresses.g.dart';
|
||||||
|
|
||||||
class ElectrumWalletAddresses = ElectrumWalletAddressesBase with _$ElectrumWalletAddresses;
|
class ElectrumWalletAddresses = ElectrumWalletAddressesBase with _$ElectrumWalletAddresses;
|
||||||
|
|
||||||
const List<BitcoinAddressType> ADDRESS_TYPES = [
|
const List<BitcoinAddressType> BITCOIN_ADDRESS_TYPES = [
|
||||||
SegwitAddresType.p2wpkh,
|
SegwitAddresType.p2wpkh,
|
||||||
P2pkhAddressType.p2pkh,
|
P2pkhAddressType.p2pkh,
|
||||||
SegwitAddresType.p2tr,
|
SegwitAddresType.p2tr,
|
||||||
SegwitAddresType.p2wsh,
|
SegwitAddresType.p2wsh,
|
||||||
SegwitAddresType.mweb,
|
|
||||||
P2shAddressType.p2wpkhInP2sh,
|
P2shAddressType.p2wpkhInP2sh,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const List<BitcoinAddressType> LITECOIN_ADDRESS_TYPES = [
|
||||||
|
SegwitAddresType.p2wpkh,
|
||||||
|
SegwitAddresType.mweb,
|
||||||
|
];
|
||||||
|
|
||||||
|
const List<BitcoinAddressType> BITCOIN_CASH_ADDRESS_TYPES = [
|
||||||
|
P2pkhAddressType.p2pkh,
|
||||||
|
];
|
||||||
|
|
||||||
abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
ElectrumWalletAddressesBase(
|
ElectrumWalletAddressesBase(
|
||||||
WalletInfo walletInfo, {
|
WalletInfo walletInfo, {
|
||||||
|
@ -327,13 +335,6 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
}) =>
|
}) =>
|
||||||
'';
|
'';
|
||||||
|
|
||||||
Future<String> getAddressAsync({
|
|
||||||
required int index,
|
|
||||||
required Bip32Slip10Secp256k1 hd,
|
|
||||||
BitcoinAddressType? addressType,
|
|
||||||
}) async =>
|
|
||||||
getAddress(index: index, hd: hd, addressType: addressType);
|
|
||||||
|
|
||||||
void addBitcoinAddressTypes() {
|
void addBitcoinAddressTypes() {
|
||||||
final lastP2wpkh = _addresses
|
final lastP2wpkh = _addresses
|
||||||
.where((addressRecord) =>
|
.where((addressRecord) =>
|
||||||
|
@ -393,22 +394,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
void addLitecoinAddressTypes() {
|
||||||
Future<void> updateAddressesInBox() async {
|
|
||||||
try {
|
|
||||||
addressesMap.clear();
|
|
||||||
addressesMap[address] = 'Active';
|
|
||||||
|
|
||||||
allAddressesMap.clear();
|
|
||||||
_addresses.forEach((addressRecord) {
|
|
||||||
allAddressesMap[addressRecord.address] = addressRecord.name;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (walletInfo.type == WalletType.bitcoin) {
|
|
||||||
addBitcoinAddressTypes();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (walletInfo.type == WalletType.litecoin) {
|
|
||||||
final lastP2wpkh = _addresses
|
final lastP2wpkh = _addresses
|
||||||
.where((addressRecord) =>
|
.where((addressRecord) =>
|
||||||
_isUnusedReceiveAddressByType(addressRecord, SegwitAddresType.p2wpkh))
|
_isUnusedReceiveAddressByType(addressRecord, SegwitAddresType.p2wpkh))
|
||||||
|
@ -429,6 +415,41 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addBitcoinCashAddressTypes() {
|
||||||
|
final lastP2pkh = _addresses.firstWhere(
|
||||||
|
(addressRecord) => _isUnusedReceiveAddressByType(addressRecord, P2pkhAddressType.p2pkh));
|
||||||
|
if (lastP2pkh.address != address) {
|
||||||
|
addressesMap[lastP2pkh.address] = 'P2PKH';
|
||||||
|
} else {
|
||||||
|
addressesMap[address] = 'Active - P2PKH';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> updateAddressesInBox() async {
|
||||||
|
try {
|
||||||
|
addressesMap.clear();
|
||||||
|
addressesMap[address] = 'Active';
|
||||||
|
|
||||||
|
allAddressesMap.clear();
|
||||||
|
_addresses.forEach((addressRecord) {
|
||||||
|
allAddressesMap[addressRecord.address] = addressRecord.name;
|
||||||
|
});
|
||||||
|
|
||||||
|
switch (walletInfo.type) {
|
||||||
|
case WalletType.bitcoin:
|
||||||
|
addBitcoinAddressTypes();
|
||||||
|
break;
|
||||||
|
case WalletType.litecoin:
|
||||||
|
addLitecoinAddressTypes();
|
||||||
|
break;
|
||||||
|
case WalletType.bitcoinCash:
|
||||||
|
addBitcoinCashAddressTypes();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
await saveAddressesInBox();
|
await saveAddressesInBox();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print(e.toString());
|
print(e.toString());
|
||||||
|
@ -548,7 +569,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
|
||||||
|
|
||||||
for (var i = startIndex; i < count + startIndex; i++) {
|
for (var i = startIndex; i < count + startIndex; i++) {
|
||||||
final address = BitcoinAddressRecord(
|
final address = BitcoinAddressRecord(
|
||||||
await getAddressAsync(index: i, hd: _getHd(isHidden), addressType: type ?? addressPageType),
|
getAddress(index: i, hd: _getHd(isHidden), addressType: type ?? addressPageType),
|
||||||
index: i,
|
index: i,
|
||||||
isHidden: isHidden,
|
isHidden: isHidden,
|
||||||
type: type ?? addressPageType,
|
type: type ?? addressPageType,
|
||||||
|
|
|
@ -319,11 +319,12 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
final oldBoxName = "${walletInfo.name.replaceAll(" ", "_")}_${MwebUtxo.boxName}";
|
final oldBoxName = "${walletInfo.name.replaceAll(" ", "_")}_${MwebUtxo.boxName}";
|
||||||
final newBoxName = "${newWalletName.replaceAll(" ", "_")}_${MwebUtxo.boxName}";
|
final newBoxName = "${newWalletName.replaceAll(" ", "_")}_${MwebUtxo.boxName}";
|
||||||
|
|
||||||
final oldBox = await Hive.openBox<MwebUtxo>(oldBoxName);
|
final oldBox = await CakeHive.openBox<MwebUtxo>(oldBoxName);
|
||||||
mwebUtxosBox = await CakeHive.openBox<MwebUtxo>(newBoxName);
|
mwebUtxosBox = await CakeHive.openBox<MwebUtxo>(newBoxName);
|
||||||
for (final key in oldBox.keys) {
|
for (final key in oldBox.keys) {
|
||||||
await mwebUtxosBox.put(key, oldBox.get(key)!);
|
await mwebUtxosBox.put(key, oldBox.get(key)!);
|
||||||
}
|
}
|
||||||
|
oldBox.deleteFromDisk();
|
||||||
|
|
||||||
await super.renameWalletFiles(newWalletName);
|
await super.renameWalletFiles(newWalletName);
|
||||||
}
|
}
|
||||||
|
@ -777,6 +778,7 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
script: outputs[0].toOutput.scriptPubKey, value: utxos.sumOfUtxosValue())
|
script: outputs[0].toOutput.scriptPubKey, value: utxos.sumOfUtxosValue())
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
// https://github.com/ltcmweb/mwebd?tab=readme-ov-file#fee-estimation
|
||||||
final preOutputSum =
|
final preOutputSum =
|
||||||
outputs.fold<BigInt>(BigInt.zero, (acc, output) => acc + output.toOutput.amount);
|
outputs.fold<BigInt>(BigInt.zero, (acc, output) => acc + output.toOutput.amount);
|
||||||
final fee = utxos.sumOfUtxosValue() - preOutputSum;
|
final fee = utxos.sumOfUtxosValue() - preOutputSum;
|
||||||
|
@ -892,18 +894,15 @@ abstract class LitecoinWalletBase extends ElectrumWallet with Store {
|
||||||
_utxoStream?.cancel();
|
_utxoStream?.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setMwebEnabled(bool enabled) {
|
Future<void> setMwebEnabled(bool enabled) async {
|
||||||
if (mwebEnabled == enabled) {
|
if (mwebEnabled == enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mwebEnabled = enabled;
|
mwebEnabled = enabled;
|
||||||
(walletAddresses as LitecoinWalletAddresses).mwebEnabled = enabled;
|
(walletAddresses as LitecoinWalletAddresses).mwebEnabled = enabled;
|
||||||
if (enabled) {
|
await stopSync();
|
||||||
// generate inital mweb addresses:
|
await startSync();
|
||||||
(walletAddresses as LitecoinWalletAddresses).topUpMweb(0);
|
|
||||||
}
|
|
||||||
startSync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<RpcClient> getStub() async {
|
Future<RpcClient> getStub() async {
|
||||||
|
|
|
@ -2,20 +2,14 @@ import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:bech32/bech32.dart';
|
import 'package:bech32/bech32.dart';
|
||||||
import 'package:bitcoin_base/bitcoin_base.dart';
|
import 'package:bitcoin_base/bitcoin_base.dart';
|
||||||
import 'package:blockchain_utils/bech32/bech32_base.dart';
|
|
||||||
import 'package:blockchain_utils/blockchain_utils.dart';
|
import 'package:blockchain_utils/blockchain_utils.dart';
|
||||||
import 'package:cw_bitcoin/electrum_wallet.dart';
|
import 'package:cw_bitcoin/electrum_wallet.dart';
|
||||||
import 'package:cw_bitcoin/utils.dart';
|
import 'package:cw_bitcoin/utils.dart';
|
||||||
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cw_mweb/cw_mweb.dart';
|
import 'package:cw_mweb/cw_mweb.dart';
|
||||||
import 'package:cw_mweb/mwebd.pb.dart';
|
|
||||||
import 'package:mobx/mobx.dart';
|
import 'package:mobx/mobx.dart';
|
||||||
|
|
||||||
// import 'dart:typed_data';
|
|
||||||
// import 'package:bech32/bech32.dart';
|
|
||||||
// import 'package:r_crypto/r_crypto.dart';
|
|
||||||
|
|
||||||
part 'litecoin_wallet_addresses.g.dart';
|
part 'litecoin_wallet_addresses.g.dart';
|
||||||
|
|
||||||
String encodeMwebAddress(List<int> scriptPubKey) {
|
String encodeMwebAddress(List<int> scriptPubKey) {
|
||||||
|
@ -36,12 +30,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
||||||
super.initialRegularAddressIndex,
|
super.initialRegularAddressIndex,
|
||||||
super.initialChangeAddressIndex,
|
super.initialChangeAddressIndex,
|
||||||
}) : super(walletInfo) {
|
}) : super(walletInfo) {
|
||||||
if (mwebEnabled) {
|
topUpMweb(0);
|
||||||
// give the server a few seconds to start up before trying to get the addresses:
|
|
||||||
Future.delayed(const Duration(seconds: 5), () async {
|
|
||||||
await topUpMweb(0);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final Bip32Slip10Secp256k1 mwebHd;
|
final Bip32Slip10Secp256k1 mwebHd;
|
||||||
|
@ -73,24 +62,13 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
||||||
BitcoinAddressType? addressType,
|
BitcoinAddressType? addressType,
|
||||||
}) {
|
}) {
|
||||||
if (addressType == SegwitAddresType.mweb) {
|
if (addressType == SegwitAddresType.mweb) {
|
||||||
topUpMweb(index);
|
topUpMweb(index).then((value) {
|
||||||
return hd == sideHd ? mwebAddrs[0] : mwebAddrs[index + 1];
|
return hd == sideHd ? mwebAddrs[0] : mwebAddrs[index + 1];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return generateP2WPKHAddress(hd: hd, index: index, network: network);
|
return generateP2WPKHAddress(hd: hd, index: index, network: network);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<String> getAddressAsync({
|
|
||||||
required int index,
|
|
||||||
required Bip32Slip10Secp256k1 hd,
|
|
||||||
BitcoinAddressType? addressType,
|
|
||||||
}) async {
|
|
||||||
if (addressType == SegwitAddresType.mweb) {
|
|
||||||
await topUpMweb(index);
|
|
||||||
}
|
|
||||||
return getAddress(index: index, hd: hd, addressType: addressType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
@action
|
||||||
@override
|
@override
|
||||||
Future<String> getChangeAddress({List<BitcoinOutput>? outputs, UtxoDetails? utxoDetails}) async {
|
Future<String> getChangeAddress({List<BitcoinOutput>? outputs, UtxoDetails? utxoDetails}) async {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:cw_bitcoin/bitcoin_mnemonics_bip39.dart';
|
import 'package:cw_bitcoin/bitcoin_mnemonics_bip39.dart';
|
||||||
|
import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart';
|
||||||
import 'package:cw_core/encryption_file_utils.dart';
|
import 'package:cw_core/encryption_file_utils.dart';
|
||||||
import 'package:cw_core/unspent_coins_info.dart';
|
import 'package:cw_core/unspent_coins_info.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
|
||||||
import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart';
|
|
||||||
import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart';
|
import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart';
|
||||||
import 'package:cw_bitcoin/litecoin_wallet.dart';
|
import 'package:cw_bitcoin/litecoin_wallet.dart';
|
||||||
import 'package:cw_core/wallet_service.dart';
|
import 'package:cw_core/wallet_service.dart';
|
||||||
|
@ -150,9 +150,9 @@ class LitecoinWalletService extends WalletService<
|
||||||
@override
|
@override
|
||||||
Future<LitecoinWallet> restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials,
|
Future<LitecoinWallet> restoreFromSeed(BitcoinRestoreWalletFromSeedCredentials credentials,
|
||||||
{bool? isTestnet}) async {
|
{bool? isTestnet}) async {
|
||||||
// if (!validateMnemonic(credentials.mnemonic) && !bip39.validateMnemonic(credentials.mnemonic)) {
|
if (!validateMnemonic(credentials.mnemonic) && !bip39.validateMnemonic(credentials.mnemonic)) {
|
||||||
// throw LitecoinMnemonicIsIncorrectException();
|
throw LitecoinMnemonicIsIncorrectException();
|
||||||
// }
|
}
|
||||||
|
|
||||||
final wallet = await LitecoinWalletBase.create(
|
final wallet = await LitecoinWalletBase.create(
|
||||||
password: credentials.password!,
|
password: credentials.password!,
|
||||||
|
|
|
@ -267,6 +267,11 @@ const bitcoinDates = {
|
||||||
"2023-01": 769810,
|
"2023-01": 769810,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const Map<String, int> litecoinDates = {
|
||||||
|
// TODO: add litecoin dates
|
||||||
|
};
|
||||||
|
|
||||||
int getBitcoinHeightByDate({required DateTime date}) {
|
int getBitcoinHeightByDate({required DateTime date}) {
|
||||||
String dateKey = '${date.year}-${date.month.toString().padLeft(2, '0')}';
|
String dateKey = '${date.year}-${date.month.toString().padLeft(2, '0')}';
|
||||||
final closestKey = bitcoinDates.keys
|
final closestKey = bitcoinDates.keys
|
||||||
|
@ -300,6 +305,21 @@ DateTime getDateByBitcoinHeight(int height) {
|
||||||
return estimatedDate;
|
return estimatedDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getLitecoinHeightByDate({required DateTime date}) {
|
||||||
|
String dateKey = '${date.year}-${date.month.toString().padLeft(2, '0')}';
|
||||||
|
final closestKey = litecoinDates.keys
|
||||||
|
.firstWhere((key) => formatMapKey(key).isBefore(date), orElse: () => litecoinDates.keys.last);
|
||||||
|
final beginningBlock = litecoinDates[dateKey] ?? litecoinDates[closestKey]!;
|
||||||
|
|
||||||
|
final startOfMonth = DateTime(date.year, date.month);
|
||||||
|
final daysDifference = date.difference(startOfMonth).inDays;
|
||||||
|
|
||||||
|
// approximately 6 blocks per hour, 24 hours per day
|
||||||
|
int estimatedBlocksSinceStartOfMonth = (daysDifference * 24 * 6);
|
||||||
|
|
||||||
|
return beginningBlock + estimatedBlocksSinceStartOfMonth;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: enhance all of this global const lists
|
// TODO: enhance all of this global const lists
|
||||||
const wowDates = {
|
const wowDates = {
|
||||||
"2023-12": 583048,
|
"2023-12": 583048,
|
||||||
|
|
|
@ -529,6 +529,9 @@ class CWBitcoin extends Bitcoin {
|
||||||
@override
|
@override
|
||||||
int getHeightByDate({required DateTime date}) => getBitcoinHeightByDate(date: date);
|
int getHeightByDate({required DateTime date}) => getBitcoinHeightByDate(date: date);
|
||||||
|
|
||||||
|
@override
|
||||||
|
int getLitecoinHeightByDate({required DateTime date}) => getLitecoinHeightByDate(date: date);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> rescan(Object wallet, {required int height, bool? doSingleScan}) async {
|
Future<void> rescan(Object wallet, {required int height, bool? doSingleScan}) async {
|
||||||
final bitcoinWallet = wallet as ElectrumWallet;
|
final bitcoinWallet = wallet as ElectrumWallet;
|
||||||
|
@ -554,7 +557,7 @@ class CWBitcoin extends Bitcoin {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void setMwebEnabled(Object wallet, bool enabled) {
|
Future<void> setMwebEnabled(Object wallet, bool enabled) async {
|
||||||
final litecoinWallet = wallet as LitecoinWallet;
|
final litecoinWallet = wallet as LitecoinWallet;
|
||||||
litecoinWallet.setMwebEnabled(enabled);
|
litecoinWallet.setMwebEnabled(enabled);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,9 @@ class AddressValidator extends TextValidator {
|
||||||
return '^[0-9a-zA-Z]{59}\$|^[0-9a-zA-Z]{92}\$|^[0-9a-zA-Z]{104}\$'
|
return '^[0-9a-zA-Z]{59}\$|^[0-9a-zA-Z]{92}\$|^[0-9a-zA-Z]{104}\$'
|
||||||
'|^[0-9a-zA-Z]{105}\$|^addr1[0-9a-zA-Z]{98}\$';
|
'|^[0-9a-zA-Z]{105}\$|^addr1[0-9a-zA-Z]{98}\$';
|
||||||
case CryptoCurrency.btc:
|
case CryptoCurrency.btc:
|
||||||
return '^${P2pkhAddress.regex.pattern}\$|^${P2shAddress.regex.pattern}\$|^${P2wpkhAddress.regex.pattern}\$|${P2trAddress.regex.pattern}\$|^${P2wshAddress.regex.pattern}\$|^${SilentPaymentAddress.regex.pattern}\$';
|
return '^${P2pkhAddress.regex.pattern}\$|^${P2shAddress.regex.pattern}\$|^${P2wpkhAddress.regex.pattern}\$|^${P2trAddress.regex.pattern}\$|^${P2wshAddress.regex.pattern}\$|^${SilentPaymentAddress.regex.pattern}\$';
|
||||||
case CryptoCurrency.ltc:
|
case CryptoCurrency.ltc:
|
||||||
return '^${P2pkhAddress.regex.pattern}\$|^${P2shAddress.regex.pattern}\$|^${P2wpkhAddress.regex.pattern}\$|${P2trAddress.regex.pattern}\$|^${P2wshAddress.regex.pattern}\$|^${MwebAddress.regex.pattern}\$';
|
return '^${P2wpkhAddress.regex.pattern}\$|^${MwebAddress.regex.pattern}\$';
|
||||||
case CryptoCurrency.nano:
|
case CryptoCurrency.nano:
|
||||||
return '[0-9a-zA-Z_]';
|
return '[0-9a-zA-Z_]';
|
||||||
case CryptoCurrency.banano:
|
case CryptoCurrency.banano:
|
||||||
|
|
|
@ -1000,8 +1000,8 @@ Future<void> setup({
|
||||||
return bitcoin!.createLitecoinWalletService(
|
return bitcoin!.createLitecoinWalletService(
|
||||||
_walletInfoSource,
|
_walletInfoSource,
|
||||||
_unspentCoinsInfoSource,
|
_unspentCoinsInfoSource,
|
||||||
getIt.get<SettingsStore>().mwebAlwaysScan,
|
|
||||||
SettingsStoreBase.walletPasswordDirectInput,
|
SettingsStoreBase.walletPasswordDirectInput,
|
||||||
|
getIt.get<SettingsStore>().mwebAlwaysScan,
|
||||||
);
|
);
|
||||||
case WalletType.ethereum:
|
case WalletType.ethereum:
|
||||||
return ethereum!.createEthereumWalletService(
|
return ethereum!.createEthereumWalletService(
|
||||||
|
|
|
@ -168,8 +168,7 @@ class BlockchainHeightState extends State<BlockchainHeightWidget> {
|
||||||
if (date != null) {
|
if (date != null) {
|
||||||
int height;
|
int height;
|
||||||
if (widget.isMwebScan) {
|
if (widget.isMwebScan) {
|
||||||
throw UnimplementedError();
|
height = bitcoin!.getLitecoinHeightByDate(date: date);
|
||||||
// height = bitcoin!.getMwebHeightByDate(date: date);
|
|
||||||
} else if (widget.isSilentPaymentsScan) {
|
} else if (widget.isSilentPaymentsScan) {
|
||||||
height = bitcoin!.getHeightByDate(date: date);
|
height = bitcoin!.getHeightByDate(date: date);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -950,7 +950,7 @@ abstract class SettingsStoreBase with Store {
|
||||||
sharedPreferences.getBool(PreferencesKey.silentPaymentsAlwaysScan) ?? false;
|
sharedPreferences.getBool(PreferencesKey.silentPaymentsAlwaysScan) ?? false;
|
||||||
final mwebAlwaysScan = sharedPreferences.getBool(PreferencesKey.mwebAlwaysScan) ?? false;
|
final mwebAlwaysScan = sharedPreferences.getBool(PreferencesKey.mwebAlwaysScan) ?? false;
|
||||||
final mwebCardDisplay = sharedPreferences.getBool(PreferencesKey.mwebCardDisplay) ?? true;
|
final mwebCardDisplay = sharedPreferences.getBool(PreferencesKey.mwebCardDisplay) ?? true;
|
||||||
final mwebEnabled = sharedPreferences.getBool(PreferencesKey.hasEnabledMwebBefore) ?? false;
|
final mwebEnabled = sharedPreferences.getBool(PreferencesKey.mwebEnabled) ?? false;
|
||||||
final hasEnabledMwebBefore =
|
final hasEnabledMwebBefore =
|
||||||
sharedPreferences.getBool(PreferencesKey.hasEnabledMwebBefore) ?? false;
|
sharedPreferences.getBool(PreferencesKey.hasEnabledMwebBefore) ?? false;
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ DIR=$(dirname "$0")
|
||||||
case $APP_ANDROID_TYPE in
|
case $APP_ANDROID_TYPE in
|
||||||
"monero.com") $DIR/build_monero_all.sh ;;
|
"monero.com") $DIR/build_monero_all.sh ;;
|
||||||
"cakewallet") $DIR/build_monero_all.sh
|
"cakewallet") $DIR/build_monero_all.sh
|
||||||
$DIR/build_haven_all.sh ;;
|
$DIR/build_haven_all.sh
|
||||||
|
$DIR/build_mwebd.sh ;;
|
||||||
"haven") $DIR/build_haven_all.sh ;;
|
"haven") $DIR/build_haven_all.sh ;;
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
# install go > 1.23:
|
if [[ "$1" == "--dont-install" ]]; then
|
||||||
wget https://go.dev/dl/go1.23.1.linux-amd64.tar.gz
|
echo "Skipping Go installation as per --dont-install flag"
|
||||||
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.23.1.linux-amd64.tar.gz
|
else
|
||||||
export PATH=$PATH:/usr/local/go/bin
|
# install go > 1.23:
|
||||||
export PATH=$PATH:~/go/bin
|
wget https://go.dev/dl/go1.23.1.linux-amd64.tar.gz
|
||||||
go install golang.org/x/mobile/cmd/gomobile@latest
|
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.23.1.linux-amd64.tar.gz
|
||||||
gomobile init
|
export PATH=$PATH:/usr/local/go/bin
|
||||||
|
export PATH=$PATH:~/go/bin
|
||||||
|
go install golang.org/x/mobile/cmd/gomobile@latest
|
||||||
|
gomobile init
|
||||||
|
fi
|
||||||
|
|
||||||
# build mwebd:
|
# build mwebd:
|
||||||
git clone https://github.com/ltcmweb/mwebd
|
git clone https://github.com/ltcmweb/mwebd
|
||||||
cd mwebd
|
cd mwebd
|
||||||
|
|
|
@ -9,6 +9,6 @@ DIR=$(dirname "$0")
|
||||||
|
|
||||||
case $APP_IOS_TYPE in
|
case $APP_IOS_TYPE in
|
||||||
"monero.com") $DIR/build_monero_all.sh ;;
|
"monero.com") $DIR/build_monero_all.sh ;;
|
||||||
"cakewallet") $DIR/build_monero_all.sh && $DIR/build_haven.sh ;;
|
"cakewallet") $DIR/build_monero_all.sh && $DIR/build_haven.sh && $DIR/build_mwebd.sh ;;
|
||||||
"haven") $DIR/build_haven_all.sh ;;
|
"haven") $DIR/build_haven_all.sh ;;
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# install go > 1.23:
|
if [[ "$1" == "--dont-install" ]]; then
|
||||||
brew install go
|
echo "Skipping Go installation as per --dont-install flag"
|
||||||
export PATH=$PATH:~/go/bin
|
else
|
||||||
go install golang.org/x/mobile/cmd/gomobile@latest
|
# install go > 1.23:
|
||||||
gomobile init
|
brew install go
|
||||||
|
export PATH=$PATH:~/go/bin
|
||||||
|
go install golang.org/x/mobile/cmd/gomobile@latest
|
||||||
|
gomobile init
|
||||||
|
fi
|
||||||
|
|
||||||
# build mwebd:
|
# build mwebd:
|
||||||
git clone https://github.com/ltcmweb/mwebd
|
git clone https://github.com/ltcmweb/mwebd
|
||||||
cd mwebd
|
cd mwebd
|
||||||
|
|
|
@ -214,6 +214,7 @@ abstract class Bitcoin {
|
||||||
{int? outputsCount, int? size});
|
{int? outputsCount, int? size});
|
||||||
int feeAmountWithFeeRate(Object wallet, int feeRate, int inputsCount, int outputsCount, {int? size});
|
int feeAmountWithFeeRate(Object wallet, int feeRate, int inputsCount, int outputsCount, {int? size});
|
||||||
int getHeightByDate({required DateTime date});
|
int getHeightByDate({required DateTime date});
|
||||||
|
int getLitecoinHeightByDate({required DateTime date});
|
||||||
Future<void> rescan(Object wallet, {required int height, bool? doSingleScan});
|
Future<void> rescan(Object wallet, {required int height, bool? doSingleScan});
|
||||||
Future<bool> getNodeIsElectrsSPEnabled(Object wallet);
|
Future<bool> getNodeIsElectrsSPEnabled(Object wallet);
|
||||||
void deleteSilentPaymentAddress(Object wallet, String address);
|
void deleteSilentPaymentAddress(Object wallet, String address);
|
||||||
|
@ -224,7 +225,7 @@ abstract class Bitcoin {
|
||||||
Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5});
|
Future<List<HardwareAccountData>> getHardwareWalletAccounts(LedgerViewModel ledgerVM, {int index = 0, int limit = 5});
|
||||||
|
|
||||||
dynamic getStatusRequest(Object wallet);
|
dynamic getStatusRequest(Object wallet);
|
||||||
void setMwebEnabled(Object wallet, bool enabled);
|
Future<void> setMwebEnabled(Object wallet, bool enabled);
|
||||||
bool getMwebEnabled(Object wallet);
|
bool getMwebEnabled(Object wallet);
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
|
|
Loading…
Reference in a new issue