This commit is contained in:
vekamo 2024-10-26 16:31:05 +04:00
parent 34ad1d9022
commit 356c640d82
65 changed files with 2466 additions and 131 deletions
.gitmodulesREADME.md
crypto_plugins
lib
linux/flutter
macos/Flutter
pubspec.lock
scripts
test
windows/flutter

3
.gitmodules vendored
View file

@ -7,3 +7,6 @@
[submodule "crypto_plugins/frostdart"]
path = crypto_plugins/frostdart
url = https://github.com/cypherstack/frostdart
[submodule "crypto_plugins/flutter_libmwc"]
path = crypto_plugins/flutter_libmwc
url = https://github.com/vekamo/flutter_libmwc

View file

@ -15,6 +15,7 @@ Highlights include:
- [Bitcoin Cash](https://bch.info/en/)
- [Dogecoin](https://dogecoin.com/)
- [Epic Cash](https://linktr.ee/epiccash)
- [MimbleWimbleCoin](https://mwc.mw)
- [Ethereum](https://ethereum.org/en/)
- [Firo](https://firo.org/)
- [Litecoin](https://litecoin.org/)

@ -0,0 +1 @@
Subproject commit 2008080fd8e3a68081f4ca1334c2568421539157

View file

@ -532,6 +532,71 @@ class DbVersionMigrator with WalletDB {
await MainDB.instance.addNewTransactionData(transactionsData, walletId);
}
// we need to manually migrate mimblewimblecoin transactions as they are not
// stored on the mimblewimblecoin blockchain
final mimblewimblecoin = Mimblewimblecoin(CryptoCurrencyNetwork.main);
if (info.coinIdentifier == mimblewimblecoin.identifier) {
final txnData = walletBox.get("latest_tx_model") as TransactionData?;
// we ever only used index 0 in the past
const rcvIndex = 0;
final List<Tuple2<isar_models.Transaction, isar_models.Address?>>
transactionsData = [];
if (txnData != null) {
final txns = txnData.getAllTransactions();
for (final tx in txns.values) {
final bool isIncoming = tx.txType == "Received";
final iTx = isar_models.Transaction(
walletId: walletId,
txid: tx.txid,
timestamp: tx.timestamp,
type: isIncoming
? isar_models.TransactionType.incoming
: isar_models.TransactionType.outgoing,
subType: isar_models.TransactionSubType.none,
amount: tx.amount,
amountString: Amount(
rawValue: BigInt.from(tx.amount),
fractionDigits: mimblewimblecoin.fractionDigits,
).toJsonString(),
fee: tx.fees,
height: tx.height,
isCancelled: tx.isCancelled,
isLelantus: false,
slateId: tx.slateId,
otherData: tx.otherData,
nonce: null,
inputs: [],
outputs: [],
numberOfMessages: tx.numberOfMessages,
);
if (tx.address.isEmpty) {
transactionsData.add(Tuple2(iTx, null));
} else {
final address = isar_models.Address(
walletId: walletId,
value: tx.address,
publicKey: [],
derivationIndex: isIncoming ? rcvIndex : -1,
derivationPath: null,
type: isIncoming
? isar_models.AddressType.mimbleWimble
: isar_models.AddressType.unknown,
subType: isIncoming
? isar_models.AddressSubType.receiving
: isar_models.AddressSubType.unknown,
);
transactionsData.add(Tuple2(iTx, address));
}
}
}
await MainDB.instance.addNewTransactionData(transactionsData, walletId);
}
// delete data from hive
await walletBox.delete(receiveAddressesPrefix);
await walletBox.delete("${receiveAddressesPrefix}P2PKH");
@ -553,9 +618,13 @@ class DbVersionMigrator with WalletDB {
);
}
// doing this for epic cash will delete transaction history as it is not
// stored on the epic cash blockchain
if (info.coinIdentifier != epic.identifier) {
// doing this for epiccash/mimblewimblecoin will delete transaction history as it is not
// stored on the epiccash/mimblewimblecoin blockchain
final excludedIdentifiers = [
epic.identifier,
mimblewimblecoin.identifier
];
if ((!excludedIdentifiers.contains(info.coinIdentifier))) {
// set flag to initiate full rescan on opening wallet
await DB.instance.put<dynamic>(
boxName: DB.boxNameDBInfo,

View file

@ -11,6 +11,7 @@ import '../wallets/isar/models/token_wallet_info.dart';
import '../wallets/isar/models/wallet_info.dart';
import '../wallets/isar/models/wallet_info_meta.dart';
import '../wallets/wallet/supporting/epiccash_wallet_info_extension.dart';
import '../wallets/wallet/supporting/mimblewimblecoin_wallet_info_extension.dart';
import 'hive/db.dart';
import 'isar/main_db.dart';
@ -146,6 +147,21 @@ Future<void> migrateWalletsToIsar({
otherData[WalletInfoKeys.epiccashData] = jsonEncode(
epicWalletInfo.toMap(),
);
} else if (old.coinIdentifier ==
Mimblewimblecoin(CryptoCurrencyNetwork.main)) {
final mimblewimblecoinWalletInfo =
ExtraMimblewimblecoinWalletInfo.fromMap({
"receivingIndex": walletBox.get("receivingIndex") as int? ?? 0,
"changeIndex": walletBox.get("changeIndex") as int? ?? 0,
"slatesToAddresses": walletBox.get("slate_to_address") as Map? ?? {},
"slatesToCommits": walletBox.get("slatesToCommits") as Map? ?? {},
"lastScannedBlock": walletBox.get("lastScannedBlock") as int? ?? 0,
"restoreHeight": walletBox.get("restoreHeight") as int? ?? 0,
"creationHeight": walletBox.get("creationHeight") as int? ?? 0,
});
otherData[WalletInfoKeys.mimblewimblecoinData] = jsonEncode(
mimblewimblecoinWalletInfo.toMap(),
);
} else if (old.coinIdentifier ==
Firo(CryptoCurrencyNetwork.main).identifier ||
old.coinIdentifier == Firo(CryptoCurrencyNetwork.test).identifier) {

View file

@ -95,6 +95,8 @@ class TransactionV2 {
bool get isEpiccashTransaction =>
_getFromOtherData(key: TxV2OdKeys.isEpiccashTransaction) == true;
bool get isMimblewimblecoinTransaction =>
_getFromOtherData(key: TxV2OdKeys.isMimblewimblecoinTransaction) == true;
int? get numberOfMessages =>
_getFromOtherData(key: TxV2OdKeys.numberOfMessages) as int?;
String? get slateId => _getFromOtherData(key: TxV2OdKeys.slateId) as String?;
@ -287,6 +289,40 @@ class TransactionV2 {
}
}
if (isMimblewimblecoinTransaction) {
if (slateId == null) {
return "Restored Funds";
}
if (isCancelled) {
return "Cancelled";
} else if (type == TransactionType.incoming) {
if (isConfirmed(currentChainHeight, minConfirms)) {
return "Received";
} else {
if (numberOfMessages == 1) {
return "Receiving (waiting for sender)";
} else if ((numberOfMessages ?? 0) > 1) {
return "Receiving (waiting for confirmations)"; // TODO test if the sender still has to open again after the receiver has 2 messages present, ie. sender->receiver->sender->node (yes) vs. sender->receiver->node (no)
} else {
return "Receiving ${prettyConfirms()}";
}
}
} else if (type == TransactionType.outgoing) {
if (isConfirmed(currentChainHeight, minConfirms)) {
return "Sent (confirmed)";
} else {
if (numberOfMessages == 1) {
return "Sending (waiting for receiver)";
} else if ((numberOfMessages ?? 0) > 1) {
return "Sending (waiting for confirmations)";
} else {
return "Sending ${prettyConfirms()}";
}
}
}
}
if (type == TransactionType.incoming) {
// if (_transaction.isMinting) {
// return "Minting";
@ -347,6 +383,7 @@ abstract final class TxV2OdKeys {
static const size = "size";
static const vSize = "vSize";
static const isEpiccashTransaction = "isEpiccashTransaction";
static const isMimblewimblecoinTransaction = "isMimblewimblecoinTransaction";
static const numberOfMessages = "numberOfMessages";
static const slateId = "slateId";
static const onChainNote = "onChainNote";

View file

@ -1939,6 +1939,7 @@ class ThemeAssets implements IThemeAssets {
late final String bitcoincash;
late final String dogecoin;
late final String epicCash;
late final String mimblewimblecoin;
late final String ethereum;
late final String firo;
late final String monero;
@ -1949,6 +1950,7 @@ class ThemeAssets implements IThemeAssets {
late final String bitcoincashImage;
late final String dogecoinImage;
late final String epicCashImage;
late final String mimblewimblecoinImage;
late final String ethereumImage;
late final String firoImage;
late final String litecoinImage;
@ -1960,6 +1962,7 @@ class ThemeAssets implements IThemeAssets {
late final String bitcoincashImageSecondary;
late final String dogecoinImageSecondary;
late final String epicCashImageSecondary;
late final String mimblewimblecoinImageSecondary;
late final String ethereumImageSecondary;
late final String firoImageSecondary;
late final String litecoinImageSecondary;
@ -2006,6 +2009,8 @@ class ThemeAssets implements IThemeAssets {
..bitcoincash = "$themeId/assets/${json["bitcoincash"] as String}"
..dogecoin = "$themeId/assets/${json["dogecoin"] as String}"
..epicCash = "$themeId/assets/${json["epicCash"] as String}"
..mimblewimblecoin =
"$themeId/assets/${json["mimblewimblecoin"] as String}"
..ethereum = "$themeId/assets/${json["ethereum"] as String}"
..firo = "$themeId/assets/${json["firo"] as String}"
..monero = "$themeId/assets/${json["monero"] as String}"
@ -2017,6 +2022,8 @@ class ThemeAssets implements IThemeAssets {
"$themeId/assets/${json["bitcoincash_image"] as String}"
..dogecoinImage = "$themeId/assets/${json["dogecoin_image"] as String}"
..epicCashImage = "$themeId/assets/${json["epicCash_image"] as String}"
..mimblewimblecoinImage =
"$themeId/assets/${json["mimblewimblecoin_image"] as String}"
..ethereumImage = "$themeId/assets/${json["ethereum_image"] as String}"
..firoImage = "$themeId/assets/${json["firo_image"] as String}"
..litecoinImage = "$themeId/assets/${json["litecoin_image"] as String}"
@ -2032,6 +2039,8 @@ class ThemeAssets implements IThemeAssets {
"$themeId/assets/${json["dogecoin_image_secondary"] as String}"
..epicCashImageSecondary =
"$themeId/assets/${json["epicCash_image_secondary"] as String}"
..mimblewimblecoinImageSecondary =
"$themeId/assets/${json["mimblewimblecoin_image_secondary"] as String}"
..ethereumImageSecondary =
"$themeId/assets/${json["ethereum_image_secondary"] as String}"
..firoImageSecondary =

View file

@ -46,10 +46,12 @@ import '../../../utilities/util.dart';
import '../../../wallets/crypto_currency/crypto_currency.dart';
import '../../../wallets/isar/models/wallet_info.dart';
import '../../../wallets/wallet/impl/epiccash_wallet.dart';
import '../../../wallets/wallet/impl/mimblewimblecoin_wallet.dart';
import '../../../wallets/wallet/impl/monero_wallet.dart';
import '../../../wallets/wallet/impl/wownero_wallet.dart';
import '../../../wallets/wallet/intermediate/lib_monero_wallet.dart';
import '../../../wallets/wallet/supporting/epiccash_wallet_info_extension.dart';
import '../../../wallets/wallet/supporting/mimblewimblecoin_wallet_info_extension.dart';
import '../../../wallets/wallet/wallet.dart';
import '../../../widgets/custom_buttons/app_bar_icon_button.dart';
import '../../../widgets/desktop/desktop_app_bar.dart';
@ -254,10 +256,27 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
height = 0;
}
// TODO: make more robust estimate of date maybe using https://explorer.epic.tech/api-index
if (widget.coin is Mimblewimblecoin) {
final int secondsSinceEpoch =
widget.restoreFromDate.millisecondsSinceEpoch ~/ 1000;
const int mimblewimblecoinFirstBlock = 1565370278;
const double overestimateSecondsPerBlock = 61;
final int chosenSeconds = secondsSinceEpoch - mimblewimblecoinFirstBlock;
final int approximateHeight =
chosenSeconds ~/ overestimateSecondsPerBlock;
//todo: check if print needed
// debugPrint(
// "approximate height: $approximateHeight chosen_seconds: $chosenSeconds");
height = approximateHeight;
if (height < 0) {
height = 0;
}
otherDataJsonString = jsonEncode(
{
WalletInfoKeys.epiccashData: jsonEncode(
ExtraEpiccashWalletInfo(
WalletInfoKeys.mimblewimblecoinData: jsonEncode(
ExtraMimblewimblecoinWalletInfo(
receivingIndex: 0,
changeIndex: 0,
slatesToAddresses: {},
@ -355,6 +374,10 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
case const (EpiccashWallet):
await (wallet as EpiccashWallet).init(isRestore: true);
break;
case const (MimblewimblecoinWallet):
await (wallet as MimblewimblecoinWallet).init(isRestore: true);
break;
case const (MoneroWallet):
await (wallet as MoneroWallet).init(isRestore: true);

View file

@ -14,6 +14,7 @@ import 'dart:io';
import 'package:decimal/decimal.dart';
import 'package:flutter/material.dart';
import 'package:flutter_libepiccash/lib.dart';
import 'package:flutter_libmwc/lib.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
@ -33,6 +34,7 @@ import '../../utilities/constants.dart';
import '../../utilities/text_styles.dart';
import '../../utilities/util.dart';
import '../../wallets/crypto_currency/coins/epiccash.dart';
import '../../wallets/crypto_currency/coins/mimblewimblecoin.dart';
import '../../wallets/crypto_currency/intermediate/nano_currency.dart';
import '../../wallets/isar/providers/eth/current_token_wallet_provider.dart';
import '../../wallets/isar/providers/wallet_info_provider.dart';
@ -159,7 +161,7 @@ class _ConfirmTransactionViewState
break;
}
} else {
if (coin is Epiccash) {
if (coin is Epiccash || coin is Mimblewimblecoin) {
txDataFuture = wallet.confirmSend(
txData: widget.txData.copyWith(
noteOnChain: onChainNoteController.text,
@ -578,11 +580,13 @@ class _ConfirmTransactionViewState
],
),
),
if (coin is Epiccash && widget.txData.noteOnChain!.isNotEmpty)
if ((coin is Epiccash || coin is Mimblewimblecoin) &&
widget.txData.noteOnChain!.isNotEmpty)
const SizedBox(
height: 12,
),
if (coin is Epiccash && widget.txData.noteOnChain!.isNotEmpty)
if ((coin is Epiccash || coin is Mimblewimblecoin) &&
widget.txData.noteOnChain!.isNotEmpty)
RoundedWhiteContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
@ -611,7 +615,9 @@ class _ConfirmTransactionViewState
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
(coin is Epiccash) ? "Local Note" : "Note",
(coin is Epiccash || coin is Mimblewimblecoin)
? "Local Note"
: "Note",
style: STextStyles.smallMed12(context),
),
const SizedBox(
@ -913,17 +919,17 @@ class _ConfirmTransactionViewState
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (coin is Epiccash)
if (coin is Epiccash || coin is Mimblewimblecoin)
Text(
"On chain Note (optional)",
style: STextStyles.smallMed12(context),
textAlign: TextAlign.left,
),
if (coin is Epiccash)
if (coin is Epiccash || coin is Mimblewimblecoin)
const SizedBox(
height: 8,
),
if (coin is Epiccash)
if (coin is Epiccash || coin is Mimblewimblecoin)
ClipRRect(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
@ -963,12 +969,12 @@ class _ConfirmTransactionViewState
),
),
),
if (coin is Epiccash)
if (coin is Epiccash || coin is Mimblewimblecoin)
const SizedBox(
height: 12,
),
SelectableText(
(coin is Epiccash)
(coin is Epiccash || coin is Mimblewimblecoin)
? "Local Note (optional)"
: "Note (optional)",
style:

View file

@ -311,7 +311,9 @@ class _SendViewState extends ConsumerState<SendView> {
_cryptoAmountChangedFeeUpdateTimer?.cancel();
_cryptoAmountChangedFeeUpdateTimer = Timer(updateFeesTimerDuration, () {
if (coin is! Epiccash && !_baseFocus.hasFocus) {
if (coin is! Epiccash &&
coin is! Mimblewimblecoin &&
!_baseFocus.hasFocus) {
setState(() {
_calculateFeesFuture = calculateFees(
amount == null
@ -332,7 +334,9 @@ class _SendViewState extends ConsumerState<SendView> {
void _baseAmountChanged() {
_baseAmountChangedFeeUpdateTimer?.cancel();
_baseAmountChangedFeeUpdateTimer = Timer(updateFeesTimerDuration, () {
if (coin is! Epiccash && !_cryptoFocus.hasFocus) {
if (coin is! Epiccash &&
coin is! Mimblewimblecoin &&
!_cryptoFocus.hasFocus) {
setState(() {
_calculateFeesFuture = calculateFees(
ref.read(pSendAmount) == null
@ -1116,6 +1120,21 @@ class _SendViewState extends ConsumerState<SendView> {
});
}
if (coin is Mimblewimblecoin) {
sendToController.addListener(() {
_address = sendToController.text.trim();
if (_address != null && _address!.isNotEmpty) {
_address = _address!.trim();
if (_address!.contains("\n")) {
_address = _address!.substring(0, _address!.indexOf("\n"));
}
sendToController.text = AddressUtils().formatAddress(_address!);
}
});
}
return Background(
child: Scaffold(
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
@ -1447,6 +1466,14 @@ class _SendViewState extends ConsumerState<SendView> {
content,
);
}
if (coin
is Mimblewimblecoin) {
// strip http:// and https:// if content contains @
content = AddressUtils()
.formatAddress(
content,
);
}
sendToController.text =
content.trim();
_address = content.trim();
@ -2030,17 +2057,17 @@ class _SendViewState extends ConsumerState<SendView> {
const SizedBox(
height: 12,
),
if (coin is Epiccash)
if (coin is Epiccash || coin is Mimblewimblecoin)
Text(
"On chain Note (optional)",
style: STextStyles.smallMed12(context),
textAlign: TextAlign.left,
),
if (coin is Epiccash)
if (coin is Epiccash || coin is Mimblewimblecoin)
const SizedBox(
height: 8,
),
if (coin is Epiccash)
if (coin is Epiccash || coin is Mimblewimblecoin)
ClipRRect(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
@ -2084,12 +2111,12 @@ class _SendViewState extends ConsumerState<SendView> {
),
),
),
if (coin is Epiccash)
if (coin is Epiccash || coin is Mimblewimblecoin)
const SizedBox(
height: 12,
),
Text(
(coin is Epiccash)
(coin is Epiccash || coin is Mimblewimblecoin)
? "Local Note (optional)"
: "Note (optional)",
style: STextStyles.smallMed12(context),
@ -2141,6 +2168,7 @@ class _SendViewState extends ConsumerState<SendView> {
height: 12,
),
if (coin is! Epiccash &&
coin is! Mimblewimblecoin &&
coin is! NanoCurrency &&
coin is! Tezos)
Text(
@ -2149,12 +2177,14 @@ class _SendViewState extends ConsumerState<SendView> {
textAlign: TextAlign.left,
),
if (coin is! Epiccash &&
coin is! Mimblewimblecoin &&
coin is! NanoCurrency &&
coin is! Tezos)
const SizedBox(
height: 8,
),
if (coin is! Epiccash &&
coin is! Mimblewimblecoin &&
coin is! NanoCurrency &&
coin is! Tezos)
Stack(

View file

@ -268,6 +268,54 @@ class AboutView extends ConsumerWidget {
);
},
),
if (AppConfig.coins
.whereType<Mimblewimblecoin>()
.isNotEmpty)
const SizedBox(
height: 12,
),
if (AppConfig.coins
.whereType<Mimblewimblecoin>()
.isNotEmpty)
FutureBuilder(
future: GitStatus.getMimblewimblecoinCommitStatus(),
builder: (
context,
AsyncSnapshot<CommitStatus> snapshot,
) {
CommitStatus stateOfCommit =
CommitStatus.notLoaded;
if (snapshot.connectionState ==
ConnectionState.done &&
snapshot.hasData) {
stateOfCommit = snapshot.data!;
}
return RoundedWhiteContainer(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
Text(
"Mimblewimblecoin Build Commit",
style: STextStyles.titleBold12(context),
),
const SizedBox(
height: 4,
),
SelectableText(
GitStatus.mimblewimblecoinCommit,
style: GitStatus.styleForStatus(
stateOfCommit,
context,
),
),
],
),
);
},
),
if (AppConfig.coins.whereType<Monero>().isNotEmpty)
const SizedBox(
height: 12,

View file

@ -19,6 +19,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_libepiccash/git_versions.dart' as EPIC_VERSIONS;
// import 'package:flutter_libmonero/git_versions.dart' as MONERO_VERSIONS;
import 'package:flutter_libmwc/git_versions.dart' as MIMBLEWIMBLECOIN_VERSIONS;
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:lelantus/git_versions.dart' as FIRO_VERSIONS;
@ -315,6 +316,9 @@ class _DebugViewState extends ConsumerState<DebugView> {
EPIC_VERSIONS.getPluginVersion();
// final String moneroCommit =
// MONERO_VERSIONS.getPluginVersion();
final String mimblewimblecoinCommit =
MIMBLEWIMBLECOIN_VERSIONS
.getPluginVersion();
final DeviceInfoPlugin deviceInfoPlugin =
DeviceInfoPlugin();
final deviceInfo =
@ -348,6 +352,8 @@ class _DebugViewState extends ConsumerState<DebugView> {
"firoCommit": firoCommit,
"epicCashCommit": epicCashCommit,
// "moneroCommit": moneroCommit,
"mimblewimblecoinCommit":
mimblewimblecoinCommit,
"deviceInfoMap": deviceInfoMap,
"errorLogs": errorLogs,
};

View file

@ -88,6 +88,17 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
ref.read(nodeFormDataProvider).host = data.host;
ref.read(nodeFormDataProvider).port = data.port;
ref.read(nodeFormDataProvider).useSSL = data.useSSL;
} else if (coin is Mimblewimblecoin) {
ref.read(nodeFormDataProvider).host = data.host;
ref.read(nodeFormDataProvider).port = data.port;
ref.read(nodeFormDataProvider).useSSL = data.useSSL;
} else if (coin is CryptonoteCurrency) {
ref.read(nodeFormDataProvider).host = data.host;
}
if (coin is Mimblewimblecoin) {
ref.read(nodeFormDataProvider).host = data.host;
ref.read(nodeFormDataProvider).port = data.port;
ref.read(nodeFormDataProvider).useSSL = data.useSSL;
} else if (coin is CryptonoteCurrency) {
ref.read(nodeFormDataProvider).host = data.host;
}
@ -917,6 +928,8 @@ class _NodeFormState extends ConsumerState<NodeForm> {
if (widget.coin is Epiccash) {
enableSSLCheckbox = !node.host.startsWith("http");
} else if (widget.coin is Mimblewimblecoin) {
enableSSLCheckbox = !node.host.startsWith("http");
} else {
enableSSLCheckbox = true;
}
@ -1058,6 +1071,25 @@ class _NodeFormState extends ConsumerState<NodeForm> {
_useSSL = true;
}
}
if (widget.coin is Mimblewimblecoin) {
if (newValue.startsWith("https://")) {
_useSSL = true;
enableSSLCheckbox = false;
} else if (newValue.startsWith("http://")) {
_useSSL = false;
enableSSLCheckbox = false;
} else {
enableSSLCheckbox = true;
}
} else if (widget.coin is CwBasedInterface) {
if (newValue.startsWith("https://")) {
_useSSL = true;
} else if (newValue.startsWith("http://")) {
_useSSL = false;
} else {
_useSSL = true;
}
}
_updateState();
setState(() {});
},
@ -1317,11 +1349,15 @@ class _NodeFormState extends ConsumerState<NodeForm> {
),
],
),
if (widget.coin is! CryptonoteCurrency && widget.coin is! Epiccash)
if (widget.coin is! CryptonoteCurrency &&
widget.coin is! Epiccash &&
widget.coin is! Mimblewimblecoin)
const SizedBox(
height: 8,
),
if (widget.coin is! CryptonoteCurrency && widget.coin is! Epiccash)
if (widget.coin is! CryptonoteCurrency &&
widget.coin is! Epiccash &&
widget.coin is! Mimblewimblecoin)
Row(
children: [
GestureDetector(

View file

@ -53,6 +53,7 @@ import '../../../../../wallets/isar/models/frost_wallet_info.dart';
import '../../../../../wallets/isar/models/wallet_info.dart';
import '../../../../../wallets/wallet/impl/bitcoin_frost_wallet.dart';
import '../../../../../wallets/wallet/impl/epiccash_wallet.dart';
import '../../../../../wallets/wallet/impl/mimblewimblecoin_wallet.dart';
import '../../../../../wallets/wallet/impl/monero_wallet.dart';
import '../../../../../wallets/wallet/impl/wownero_wallet.dart';
import '../../../../../wallets/wallet/intermediate/lib_monero_wallet.dart';
@ -507,6 +508,10 @@ abstract class SWB {
case const (EpiccashWallet):
await (wallet as EpiccashWallet).init(isRestore: true);
break;
case const (MimblewimblecoinWallet):
await (wallet as MimblewimblecoinWallet).init(isRestore: true);
break;
case const (MoneroWallet):
await (wallet as MoneroWallet).init(isRestore: true);
@ -522,7 +527,7 @@ abstract class SWB {
int restoreHeight = walletbackup['restoreHeight'] as int? ?? 0;
if (restoreHeight <= 0) {
if (wallet is EpiccashWallet || wallet is LibMoneroWallet) {
if (wallet is EpiccashWallet || wallet is MimblewimblecoinWallet || wallet is LibMoneroWallet) {
restoreHeight = 0;
} else {
restoreHeight = walletbackup['storedChainHeight'] as int? ?? 0;

View file

@ -33,10 +33,12 @@ import '../../../../utilities/constants.dart';
import '../../../../utilities/text_styles.dart';
import '../../../../utilities/util.dart';
import '../../../../wallets/crypto_currency/coins/epiccash.dart';
import '../../../../wallets/crypto_currency/coins/mimblewimblecoin.dart';
import '../../../../wallets/crypto_currency/coins/monero.dart';
import '../../../../wallets/crypto_currency/coins/wownero.dart';
import '../../../../wallets/isar/providers/wallet_info_provider.dart';
import '../../../../wallets/wallet/impl/epiccash_wallet.dart';
import '../../../../wallets/wallet/impl/mimblewimblecoin_wallet.dart';
import '../../../../wallets/wallet/impl/monero_wallet.dart';
import '../../../../wallets/wallet/impl/wownero_wallet.dart';
import '../../../../widgets/animated_text.dart';
@ -263,7 +265,10 @@ class _WalletNetworkSettingsViewState
final coin = ref.read(pWalletCoin(widget.walletId));
if (coin is Monero || coin is Wownero || coin is Epiccash) {
if (coin is Monero ||
coin is Wownero ||
coin is Epiccash ||
coin is Mimblewimblecoin) {
_blocksRemainingSubscription = eventBus.on<BlocksRemainingEvent>().listen(
(event) async {
if (event.walletId == widget.walletId) {
@ -343,6 +348,14 @@ class _WalletNetworkSettingsViewState
if (_percent < highestPercent) {
_percent = highestPercent.clamp(0.0, 1.0);
}
} else if (coin is Mimblewimblecoin) {
final double highestPercent = (ref
.watch(pWallets)
.getWallet(widget.walletId) as MimblewimblecoinWallet)
.highestPercent;
if (_percent < highestPercent) {
_percent = highestPercent.clamp(0.0, 1.0);
}
}
return ConditionalParent(
@ -363,7 +376,11 @@ class _WalletNetworkSettingsViewState
style: STextStyles.navBarTitle(context),
),
actions: [
if (ref.watch(pWalletCoin(widget.walletId)) is! Epiccash)
if (ref.watch(pWalletCoin(widget.walletId)) is! Epiccash &&
ref.watch(pWalletCoin(widget.walletId))
is! Mimblewimblecoin ||
ref.watch(pWalletCoin(widget.walletId))
is! Mimblewimblecoin)
Padding(
padding: const EdgeInsets.only(
top: 10,
@ -627,6 +644,7 @@ class _WalletNetworkSettingsViewState
),
if (coin is Monero ||
coin is Wownero ||
coin is Mimblewimblecoin ||
coin is Epiccash)
Text(
" (Blocks to go: ${_blocksRemaining == -1 ? "?" : _blocksRemaining})",
@ -950,11 +968,15 @@ class _WalletNetworkSettingsViewState
coin: ref.watch(pWalletCoin(widget.walletId)),
popBackToRoute: WalletNetworkSettingsView.routeName,
),
if (isDesktop && ref.watch(pWalletCoin(widget.walletId)) is! Epiccash)
if (isDesktop &&
ref.watch(pWalletCoin(widget.walletId)) is! Epiccash &&
ref.watch(pWalletCoin(widget.walletId)) is! Mimblewimblecoin)
const SizedBox(
height: 32,
),
if (isDesktop && ref.watch(pWalletCoin(widget.walletId)) is! Epiccash)
if (isDesktop &&
ref.watch(pWalletCoin(widget.walletId)) is! Epiccash &&
ref.watch(pWalletCoin(widget.walletId)) is! Mimblewimblecoin)
Padding(
padding: const EdgeInsets.only(
bottom: 12,
@ -970,7 +992,9 @@ class _WalletNetworkSettingsViewState
],
),
),
if (isDesktop && ref.watch(pWalletCoin(widget.walletId)) is! Epiccash)
if (isDesktop &&
ref.watch(pWalletCoin(widget.walletId)) is! Epiccash &&
ref.watch(pWalletCoin(widget.walletId)) is! Mimblewimblecoin)
RoundedWhiteContainer(
borderColor: isDesktop
? Theme.of(context).extension<StackColors>()!.background

View file

@ -18,6 +18,7 @@ import 'package:tuple/tuple.dart';
import '../../../db/hive/db.dart';
import '../../../db/sqlite/firo_cache.dart';
import '../../../models/epicbox_config_model.dart';
import '../../../models/mwcmqs_config_model.dart';
import '../../../models/keys/key_data_interface.dart';
import '../../../models/keys/view_only_wallet_data.dart';
import '../../../notifications/show_flush_bar.dart';
@ -38,6 +39,8 @@ import '../../../wallets/crypto_currency/intermediate/nano_currency.dart';
import '../../../wallets/wallet/impl/bitcoin_frost_wallet.dart';
import '../../../wallets/wallet/impl/epiccash_wallet.dart';
import '../../../wallets/wallet/intermediate/lib_monero_wallet.dart';
import '../../../wallets/wallet/impl/mimblewimblecoin_wallet.dart';
import '../../../wallets/wallet/wallet_mixin_interfaces/cw_based_interface.dart';
import '../../../wallets/wallet/wallet_mixin_interfaces/extended_keys_interface.dart';
import '../../../wallets/wallet/wallet_mixin_interfaces/mnemonic_interface.dart';
import '../../../wallets/wallet/wallet_mixin_interfaces/view_only_option_interface.dart';
@ -719,3 +722,103 @@ class _EpiBoxInfoFormState extends ConsumerState<EpicBoxInfoForm> {
);
}
}
class MwcMqsInfoForm extends ConsumerStatefulWidget {
const MwcMqsInfoForm({
super.key,
required this.walletId,
});
final String walletId;
@override
ConsumerState<MwcMqsInfoForm> createState() => _MwcMqsInfoFormState();
}
class _MwcmqsInfoFormState extends ConsumerState<MwcMqsInfoForm> {
final hostController = TextEditingController();
final portController = TextEditingController();
late MimblewimblecoinWallet wallet;
@override
void initState() {
wallet =
ref.read(pWallets).getWallet(widget.walletId) as MimblewimblecoinWallet;
wallet.getMwcMqsConfig().then((MwcMqsConfigModel mwcmqsConfig) {
hostController.text = mwcmqsConfig.host;
portController.text = "${mwcmqsConfig.port ?? 443}";
});
super.initState();
}
@override
void dispose() {
hostController.dispose();
portController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return RoundedWhiteContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextField(
autocorrect: Util.isDesktop ? false : true,
enableSuggestions: Util.isDesktop ? false : true,
controller: hostController,
decoration: const InputDecoration(hintText: "Host"),
),
const SizedBox(
height: 8,
),
TextField(
autocorrect: Util.isDesktop ? false : true,
enableSuggestions: Util.isDesktop ? false : true,
controller: portController,
decoration: const InputDecoration(hintText: "Port"),
keyboardType:
Util.isDesktop ? null : const TextInputType.numberWithOptions(),
),
const SizedBox(
height: 8,
),
TextButton(
onPressed: () async {
try {
await wallet.updateMwcmqsConfig(
hostController.text,
int.parse(portController.text),
);
if (mounted) {
await showFloatingFlushBar(
context: context,
message: "Mwcmqs info saved!",
type: FlushBarType.success,
);
}
unawaited(wallet.refresh());
} catch (e) {
await showFloatingFlushBar(
context: context,
message: "Failed to save mwcmqs info: $e",
type: FlushBarType.warning,
);
}
},
child: Text(
"Save",
style: STextStyles.button(context).copyWith(
color:
Theme.of(context).extension<StackColors>()!.accentColorDark,
),
),
),
],
),
);
}
}

View file

@ -873,6 +873,10 @@ class _DesktopTransactionCardRowState
return "Restored Funds";
}
if (coin is Mimblewimblecoin && _transaction.slateId == null) {
return "Restored Funds";
}
if (_transaction.subType == TransactionSubType.mint) {
if (_transaction.isConfirmed(height, minConfirms)) {
return "Anonymized";
@ -967,6 +971,19 @@ class _DesktopTransactionCardRowState
);
return;
}
if (coin is Mimblewimblecoin && _transaction.slateId == null) {
unawaited(
showFloatingFlushBar(
context: context,
message:
"Restored Mimblewimblecoin funds from your Seed have no Data.",
type: FlushBarType.warning,
duration: const Duration(seconds: 5),
),
);
return;
}
if (Util.isDesktop) {
await showDialog<void>(
context: context,

View file

@ -43,6 +43,7 @@ import '../../../../wallets/isar/models/spark_coin.dart';
import '../../../../wallets/isar/providers/wallet_info_provider.dart';
import '../../../../wallets/wallet/impl/epiccash_wallet.dart';
import '../../../../wallets/wallet/intermediate/lib_monero_wallet.dart';
import '../../../../wallets/wallet/impl/mimblewimblecoin_wallet.dart';
import '../../../../wallets/wallet/wallet_mixin_interfaces/rbf_interface.dart';
import '../../../../wallets/wallet/wallet_mixin_interfaces/spark_interface.dart';
import '../../../../widgets/background.dart';
@ -251,6 +252,33 @@ class _TransactionV2DetailsViewState
),
)
.toList();
} else if (_transaction.isMimblewimblecoinTransaction) {
switch (_transaction.type) {
case TransactionType.outgoing:
case TransactionType.unknown:
amount = _transaction.getAmountSentFromThisWallet(
fractionDigits: fractionDigits,
);
break;
case TransactionType.incoming:
case TransactionType.sentToSelf:
amount = _transaction.getAmountReceivedInThisWallet(
fractionDigits: fractionDigits,
);
break;
}
data = _transaction.outputs
.map(
(e) => (
addresses: e.addresses,
amount: Amount(
rawValue: e.value,
fractionDigits: coin.fractionDigits,
)
),
)
.toList();
} else if (_transaction.subType == TransactionSubType.cashFusion) {
amount = _transaction.getAmountReceivedInThisWallet(
fractionDigits: fractionDigits,
@ -1069,13 +1097,13 @@ class _TransactionV2DetailsViewState
],
),
),
if (coin is Epiccash)
if (coin is Epiccash || coin is Mimblewimblecoin)
isDesktop
? const _Divider()
: const SizedBox(
height: 12,
),
if (coin is Epiccash)
if (coin is Epiccash || coin is Mimblewimblecoin)
RoundedWhiteContainer(
padding: isDesktop
? const EdgeInsets.all(16)
@ -1147,7 +1175,8 @@ class _TransactionV2DetailsViewState
MainAxisAlignment.spaceBetween,
children: [
Text(
(coin is Epiccash)
(coin is Epiccash ||
coin is Mimblewimblecoin)
? "Local Note"
: "Note ",
style: isDesktop
@ -1218,7 +1247,9 @@ class _TransactionV2DetailsViewState
.watch(
pTransactionNote(
(
txid: (coin is Epiccash)
txid: (coin is Epiccash ||
coin
is Mimblewimblecoin)
? _transaction.slateId
.toString()
: _transaction.txid,
@ -1495,8 +1526,9 @@ class _TransactionV2DetailsViewState
? "${_transaction.height!}"
: "Pending";
confirmations = confirms.toString();
} else if (widget.coin is Epiccash &&
_transaction.slateId == null) {
} else if (widget.coin is Epiccash ||
coin is Mimblewimblecoin &&
_transaction.slateId == null) {
confirmations = "Unknown";
height = "Unknown";
} else {
@ -1504,7 +1536,9 @@ class _TransactionV2DetailsViewState
currentHeight,
minConfirms,
coin.minCoinbaseConfirms);
if (widget.coin is! Epiccash && confirmed) {
if (widget.coin is! Epiccash &&
widget.coin is! Mimblewimblecoin &&
confirmed) {
height =
"${_transaction.height == 0 ? "Unknown" : _transaction.height}";
} else {
@ -1787,11 +1821,13 @@ class _TransactionV2DetailsViewState
context,
),
),
if (coin is! Epiccash)
if (coin is! Epiccash &&
coin is! Mimblewimblecoin)
const SizedBox(
height: 8,
),
if (coin is! Epiccash)
if (coin is! Epiccash &&
coin is! Mimblewimblecoin)
CustomTextButton(
text: "Open in block explorer",
onTap: () async {
@ -1948,13 +1984,13 @@ class _TransactionV2DetailsViewState
// ],
// ),
// ),
if (coin is Epiccash)
if (coin is Epiccash || coin is Mimblewimblecoin)
isDesktop
? const _Divider()
: const SizedBox(
height: 12,
),
if (coin is Epiccash)
if (coin is Epiccash || coin is Mimblewimblecoin)
RoundedWhiteContainer(
padding: isDesktop
? const EdgeInsets.all(16)
@ -2038,9 +2074,10 @@ class _TransactionV2DetailsViewState
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: (coin is Epiccash &&
_transaction.getConfirmations(currentHeight) < 1 &&
_transaction.isCancelled == false)
floatingActionButton: (coin is Epiccash ||
coin is Mimblewimblecoin &&
_transaction.getConfirmations(currentHeight) < 1 &&
_transaction.isCancelled == false)
? ConditionalParent(
condition: isDesktop,
builder: (child) => Padding(
@ -2124,6 +2161,72 @@ class _TransactionV2DetailsViewState
);
return;
}
if (wallet is MimblewimblecoinWallet) {
final String? id = _transaction.slateId;
if (id == null) {
unawaited(
showFloatingFlushBar(
type: FlushBarType.warning,
message:
"Could not find Mimblewimblecoin transaction ID",
context: context,
),
);
return;
}
unawaited(
showDialog<void>(
barrierDismissible: false,
context: context,
builder: (_) =>
const CancellingTransactionProgressDialog(),
),
);
final result =
await wallet.cancelPendingTransactionAndPost(id);
if (mounted) {
// pop progress dialog
Navigator.of(context).pop();
if (result.isEmpty) {
await showDialog<dynamic>(
context: context,
builder: (_) => StackOkDialog(
title: "Transaction cancelled",
onOkPressed: (_) {
wallet.refresh();
Navigator.of(context).popUntil(
ModalRoute.withName(
WalletView.routeName,
),
);
},
),
);
} else {
await showDialog<dynamic>(
context: context,
builder: (_) => StackOkDialog(
title: "Failed to cancel transaction",
message: result,
),
);
}
}
} else {
unawaited(
showFloatingFlushBar(
type: FlushBarType.warning,
message:
"ERROR: Wallet type is not Mimblewimblecoin",
context: context,
),
);
return;
}
},
child: Text(
"Cancel Transaction",

View file

@ -488,6 +488,11 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
noteOnChain: _onChainNote ?? "",
);
}
if (coin is Mimblewimblecoin) {
txData = txData.copyWith(
noteOnChain: _onChainNote ?? "",
);
}
}
// pop building dialog
Navigator.of(
@ -790,6 +795,9 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
if (coin is Epiccash) {
content = AddressUtils().formatAddress(content);
}
if (coin is Mimblewimblecoin) {
content = AddressUtils().formatAddressMwc(content);
}
sendToController.text = content;
_address = content;
@ -805,6 +813,10 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
// strip http:// and https:// if content contains @
content = AddressUtils().formatAddress(content);
}
if (coin is Mimblewimblecoin) {
// strip http:// and https:// if content contains @
content = AddressUtils().formatAddressMwc(content);
}
sendToController.text = content;
_address = content;
@ -1042,6 +1054,21 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
});
}
if (coin is Mimblewimblecoin) {
sendToController.addListener(() {
_address = sendToController.text;
if (_address != null && _address!.isNotEmpty) {
_address = _address!.trim();
if (_address!.contains("\n")) {
_address = _address!.substring(0, _address!.indexOf("\n"));
}
sendToController.text = formatAddressMwc(_address!);
}
});
}
final firoType = ref.watch(publicPrivateBalanceStateProvider);
final isExchangeAddress = ref.watch(pIsExchangeAddress);
@ -1715,7 +1742,10 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
const SizedBox(
height: 20,
),
if (coin is! NanoCurrency && coin is! Epiccash && coin is! Tezos)
if (coin is! NanoCurrency &&
coin is! Epiccash &&
coin is! Mimblewimblecoin &&
coin is! Tezos)
ConditionalParent(
condition: ref.watch(pWallets).getWallet(walletId)
is ElectrumXInterface &&
@ -1771,11 +1801,17 @@ class _DesktopSendState extends ConsumerState<DesktopSend> {
textAlign: TextAlign.left,
),
),
if (coin is! NanoCurrency && coin is! Epiccash && coin is! Tezos)
if (coin is! NanoCurrency &&
coin is! Epiccash &&
coin is! Mimblewimblecoin &&
coin is! Tezos)
const SizedBox(
height: 10,
),
if (coin is! NanoCurrency && coin is! Epiccash && coin is! Tezos)
if (coin is! NanoCurrency &&
coin is! Epiccash &&
coin is! Mimblewimblecoin &&
coin is! Tezos)
if (!isCustomFee)
Padding(
padding: const EdgeInsets.all(10),
@ -1980,3 +2016,25 @@ String formatAddress(String epicAddress) {
}
return epicAddress;
}
String formatAddressMwc(String mimblewimblecoinAddress) {
// strip http:// or https:// prefixes if the address contains an @ symbol (and is thus an mwcmqs address)
if ((mimblewimblecoinAddress.startsWith("http://") ||
mimblewimblecoinAddress.startsWith("https://")) &&
mimblewimblecoinAddress.contains("@")) {
mimblewimblecoinAddress = mimblewimblecoinAddress.replaceAll("http://", "");
mimblewimblecoinAddress =
mimblewimblecoinAddress.replaceAll("https://", "");
}
// strip mailto: prefix
if (mimblewimblecoinAddress.startsWith("mailto:")) {
mimblewimblecoinAddress = mimblewimblecoinAddress.replaceAll("mailto:", "");
}
// strip / suffix if the address contains an @ symbol (and is thus an mwcmqs address)
if (mimblewimblecoinAddress.endsWith("/") &&
mimblewimblecoinAddress.contains("@")) {
mimblewimblecoinAddress = mimblewimblecoinAddress.substring(
0, mimblewimblecoinAddress.length - 1);
}
return mimblewimblecoinAddress;
}

View file

@ -63,6 +63,12 @@ class _ForgotPasswordDesktopViewState
await epicDir.delete(recursive: true);
}
final mimblewimblecoinDir =
Directory("${appRoot.path}/mimblewimblecoin");
if (mimblewimblecoinDir.existsSync()) {
await mimblewimblecoinDir.delete(recursive: true);
}
await Isar.getInstance("desktopStore")?.close(deleteFromDisk: true);
await (await StackFileSystem.applicationHiveDirectory())
@ -79,6 +85,12 @@ class _ForgotPasswordDesktopViewState
if (epicDir.existsSync()) {
await epicDir.delete(recursive: true);
}
final mimblewimblecoinDir =
Directory("${appRoot.path}/mimblewimblecoin");
if (mimblewimblecoinDir.existsSync()) {
await mimblewimblecoinDir.delete(recursive: true);
}
await (await StackFileSystem.applicationHiveDirectory())
.delete(recursive: true);
await (await StackFileSystem.applicationIsarDirectory())

View file

@ -434,63 +434,122 @@ class DesktopAboutView extends ConsumerWidget {
);
},
),
// if (AppConfig.coins
// .whereType<Monero>()
// .isNotEmpty)
// FutureBuilder(
// future: GitStatus
// .getMoneroCommitStatus(),
// builder: (
// context,
// AsyncSnapshot<CommitStatus>
// snapshot,
// ) {
// CommitStatus stateOfCommit =
// CommitStatus.notLoaded;
if (AppConfig.coins
.whereType<Mimblewimblecoin>()
.isNotEmpty)
FutureBuilder(
future: GitStatus
.getMimblewimblecoinCommitStatus(),
builder: (
context,
AsyncSnapshot<CommitStatus>
snapshot,
) {
CommitStatus stateOfCommit =
CommitStatus.notLoaded;
if (snapshot.connectionState ==
ConnectionState
.done &&
snapshot.hasData) {
stateOfCommit =
snapshot.data!;
}
return Column(
mainAxisSize:
MainAxisSize.min,
crossAxisAlignment:
CrossAxisAlignment
.start,
children: [
Text(
"Mimblewimblecoin Build Commit",
style: STextStyles
.desktopTextExtraExtraSmall(
context,
).copyWith(
color: Theme.of(
context,
)
.extension<
StackColors>()!
.textDark,
),
),
const SizedBox(
height: 2,
),
SelectableText(
GitStatus
.mimblewimblecoinCommit,
style: GitStatus
.styleForStatus(
stateOfCommit,
context,
),
),
],
);
},
),
//if (AppConfig.coins
// .whereType<Monero>()
// .isNotEmpty)
// FutureBuilder(
// future: GitStatus
// .getMoneroCommitStatus(),
// builder: (
// context,
// AsyncSnapshot<CommitStatus>
// snapshot,
// ) {
// CommitStatus stateOfCommit =
// CommitStatus.notLoaded;
//
// if (snapshot.connectionState ==
// ConnectionState
// .done &&
// snapshot.hasData) {
// stateOfCommit =
// snapshot.data!;
// }
// return Column(
// mainAxisSize:
// MainAxisSize.min,
// crossAxisAlignment:
// CrossAxisAlignment
// .start,
// children: [
// Text(
// "Monero Build Commit",
// style: STextStyles
// .desktopTextExtraExtraSmall(
// context,
// ).copyWith(
// color: Theme.of(
// context,
// )
// .extension<
// StackColors>()!
// .textDark,
// ),
// ),
// const SizedBox(
// height: 2,
// ),
// SelectableText(
// GitStatus.moneroCommit,
// style: GitStatus
// .styleForStatus(
// stateOfCommit,
// context,
// ),
// ),
// ],
// );
// },
// ),
// if (snapshot.connectionState ==
// ConnectionState
// .done &&
// snapshot.hasData) {
// stateOfCommit =
// snapshot.data!;
// }
// return Column(
// mainAxisSize:
// MainAxisSize.min,
// crossAxisAlignment:
// CrossAxisAlignment
// .start,
// children: [
// Text(
// "Monero Build Commit",
// style: STextStyles
// .desktopTextExtraExtraSmall(
// context,
// ).copyWith(
// color: Theme.of(
// context,
// )
// .extension<
// StackColors>()!
// .textDark,
// ),
// ),
// const SizedBox(
// height: 2,
// ),
// SelectableText(
// GitStatus.moneroCommit,
// style: GitStatus
// .styleForStatus(
// stateOfCommit,
// context,
// ),
// ),
// ],
// );
// },
// ),
],
),
const SizedBox(height: 35),

View file

@ -34,6 +34,7 @@ class PriceAPI {
Dash: "dash",
Dogecoin: "dogecoin",
Epiccash: "epic-cash",
Mimblewimblecoin: "mimblewimblecoin",
Ecash: "ecash",
Ethereum: "ethereum",
Firo: "zcoin",

View file

@ -25,6 +25,7 @@ import '../wallets/crypto_currency/crypto_currency.dart';
import '../wallets/isar/models/wallet_info.dart';
import '../wallets/wallet/impl/epiccash_wallet.dart';
import '../wallets/wallet/intermediate/lib_monero_wallet.dart';
import '../wallets/wallet/impl/mimblewimblecoin_wallet.dart';
import '../wallets/wallet/wallet.dart';
import 'event_bus/events/wallet_added_event.dart';
import 'event_bus/global_event_bus.dart';
@ -113,6 +114,15 @@ class Wallets {
"epic wallet: $walletId deleted with result: $deleteResult",
level: LogLevel.Info,
);
} else if (info.coin is Mimblewimblecoin) {
final deleteResult = await deleteMimblewimblecoinWallet(
walletId: walletId,
secureStore: secureStorage,
);
Logging.instance.log(
"Mimblewimblecoin wallet: $walletId deleted with result: $deleteResult",
level: LogLevel.Info,
);
}
// delete wallet data in main db

View file

@ -28,6 +28,8 @@ final coinIconProvider = Provider.family<String, CryptoCurrency>((ref, coin) {
return assets.dogecoin;
case const (Epiccash):
return assets.epicCash;
case const (Mimblewimblecoin):
return assets.mimblewimblecoin;
case const (Firo):
return assets.firo;
case const (Monero):

View file

@ -232,6 +232,31 @@ class AddressUtils {
}
return epicAddress;
}
/// Formats an address string to remove any unnecessary prefixes or suffixes.
String formatMimblewimblecoinAddress(String mimblewimblecoinAddress) {
// strip http:// or https:// prefixes if the address contains an @ symbol (and is thus an mwcmqs address)
if ((mimblewimblecoinAddress.startsWith("http://") ||
mimblewimblecoinAddress.startsWith("https://")) &&
mimblewimblecoinAddress.contains("@")) {
mimblewimblecoinAddress =
mimblewimblecoinAddress.replaceAll("http://", "");
mimblewimblecoinAddress =
mimblewimblecoinAddress.replaceAll("https://", "");
}
// strip mailto: prefix
if (mimblewimblecoinAddress.startsWith("mailto:")) {
mimblewimblecoinAddress =
mimblewimblecoinAddress.replaceAll("mailto:", "");
}
// strip / suffix if the address contains an @ symbol (and is thus an mwcmqs address)
if (mimblewimblecoinAddress.endsWith("/") &&
mimblewimblecoinAddress.contains("@")) {
mimblewimblecoinAddress = mimblewimblecoinAddress.substring(
0, mimblewimblecoinAddress.length - 1);
}
return mimblewimblecoinAddress;
}
}
class PaymentUriData {

View file

@ -63,6 +63,7 @@ enum AmountUnit {
// case Coin.dogecoin:
// case Coin.eCash:
// case Coin.epicCash:
// case Coin.mimblewimblecoin:
// case Coin.stellar: // TODO: check if this is correct
// case Coin.stellarTestnet:
// case Coin.tezos:

View file

@ -245,6 +245,7 @@ class _SVG {
String get bitcoincash => "assets/svg/coin_icons/Bitcoincash.svg";
String get dogecoin => "assets/svg/coin_icons/Dogecoin.svg";
String get epicCash => "assets/svg/coin_icons/EpicCash.svg";
String get mimblewimblecoin => "assets/svg/coin_icons/Mimblewimblecoin.svg";
String get ethereum => "assets/svg/coin_icons/Ethereum.svg";
String get firo => "assets/svg/coin_icons/Firo.svg";
String get monero => "assets/svg/coin_icons/Monero.svg";

View file

@ -0,0 +1,53 @@
/*
* This file is part of Stack Wallet.
*
* Copyright (c) 2023 Cypher Stack
* All Rights Reserved.
* The code is distributed under GPLv3 license, see LICENSE file for details.
* Generated by Cypher Stack on 2023-05-26
*
*/
import '../models/mwcmqs_server_model.dart';
abstract class DefaultMwcMqs {
static const String defaultName = "Default";
static List<MwcMqsServerModel> get all => [americas, asia, europe];
static List<String> get defaultIds => ['americas', 'asia', 'europe'];
static MwcMqsServerModel get americas => MwcMqsServerModel(
host: 'MwcMqs.stackwallet.com',
port: 443,
name: 'Americas',
id: 'americas',
useSSL: true,
enabled: true,
isFailover: true,
isDown: false,
);
static MwcMqsServerModel get asia => MwcMqsServerModel(
host: 'MwcMqs.hyperbig.com',
port: 443,
name: 'Asia',
id: 'asia',
useSSL: true,
enabled: true,
isFailover: true,
isDown: false,
);
static MwcMqsServerModel get europe => MwcMqsServerModel(
host: 'MwcMqs.fastepic.eu',
port: 443,
name: 'Europe',
id: 'europe',
useSSL: true,
enabled: true,
isFailover: true,
isDown: false,
);
static final defaultMwcMqsServer = americas;
}

View file

@ -3,6 +3,7 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_libepiccash/git_versions.dart' as epic_versions;
// import 'package:flutter_libmonero/git_versions.dart' as monero_versions;
import 'package:flutter_libmwc/git_versions.dart' as mimblewimblecoin_versions;
import 'package:http/http.dart';
import 'package:lelantus/git_versions.dart' as firo_versions;
@ -21,6 +22,8 @@ abstract class GitStatus {
static String get firoCommit => firo_versions.getPluginVersion();
static String get epicCashCommit => epic_versions.getPluginVersion();
// static String get moneroCommit => monero_versions.getPluginVersion();
static String get mimblewimblecoinCommit =>
mimblewimblecoin_versions.getPluginVersion();
static String get appCommitHash => AppConfig.commitHash;
@ -78,31 +81,60 @@ abstract class GitStatus {
return _cachedEpicStatus!;
}
static CommitStatus? _cachedMimblewimblecoinStatus;
static Future<CommitStatus> getMimblewimblecoinCommitStatus() async {
if (_cachedMimblewimblecoinStatus != null) {
return _cachedMimblewimblecoinStatus!;
}
final List<bool> results = await Future.wait([
_doesCommitExist("cypherstack", "flutter_libmwc", mimblewimblecoinCommit),
_isHeadCommit(
"cypherstack",
"flutter_libmwc",
"main",
mimblewimblecoinCommit,
),
]);
final commitExists = results[0];
final commitIsHead = results[1];
if (commitExists && commitIsHead) {
_cachedMimblewimblecoinStatus = CommitStatus.isHead;
} else if (commitExists) {
_cachedMimblewimblecoinStatus = CommitStatus.isOldCommit;
} else {
_cachedMimblewimblecoinStatus = CommitStatus.notACommit;
}
return _cachedMimblewimblecoinStatus!;
}
//static CommitStatus? _cachedMoneroStatus;
//static Future<CommitStatus> getMoneroCommitStatus() async {
// if (_cachedMoneroStatus != null) {
// return _cachedMoneroStatus!;
// }
//
// static CommitStatus? _cachedMoneroStatus;
// static Future<CommitStatus> getMoneroCommitStatus() async {
// if (_cachedMoneroStatus != null) {
// return _cachedMoneroStatus!;
// }
// final List<bool> results = await Future.wait([
// _doesCommitExist("cypherstack", "flutter_libmonero", moneroCommit),
// _isHeadCommit("cypherstack", "flutter_libmonero", "main", moneroCommit),
// ]);
//
// final List<bool> results = await Future.wait([
// _doesCommitExist("cypherstack", "flutter_libmonero", moneroCommit),
// _isHeadCommit("cypherstack", "flutter_libmonero", "main", moneroCommit),
// ]);
// final commitExists = results[0];
// final commitIsHead = results[1];
//
// final commitExists = results[0];
// final commitIsHead = results[1];
// if (commitExists && commitIsHead) {
// _cachedMoneroStatus = CommitStatus.isHead;
// } else if (commitExists) {
// _cachedMoneroStatus = CommitStatus.isOldCommit;
// } else {
// _cachedMoneroStatus = CommitStatus.notACommit;
// }
//
// if (commitExists && commitIsHead) {
// _cachedMoneroStatus = CommitStatus.isHead;
// } else if (commitExists) {
// _cachedMoneroStatus = CommitStatus.isOldCommit;
// } else {
// _cachedMoneroStatus = CommitStatus.notACommit;
// }
//
// return _cachedMoneroStatus!;
// }
// return _cachedMoneroStatus!;
//}
static TextStyle styleForStatus(CommitStatus status, BuildContext context) {
final Color color;

View file

@ -0,0 +1,128 @@
import 'package:flutter_libmwc/lib.dart' as mimblewimblecoin;
import '../../../models/isar/models/blockchain_data/address.dart';
import '../../../models/node_model.dart';
import '../../../utilities/default_nodes.dart';
import '../../../utilities/enums/derive_path_type_enum.dart';
import '../crypto_currency.dart';
import '../intermediate/bip39_currency.dart';
class Mimblewimblecoin extends Bip39Currency {
Mimblewimblecoin(super.network) {
_idMain = "mimblewimblecoin";
_uriScheme = "mimblewimblecoin"; // ?
switch (network) {
case CryptoCurrencyNetwork.main:
_id = _idMain;
_name = "Mimblewimblecoin";
_ticker = "MWC";
default:
throw Exception("Unsupported network: $network");
}
}
late final String _id;
@override
String get identifier => _id;
late final String _idMain;
@override
String get mainNetId => _idMain;
late final String _name;
@override
String get prettyName => _name;
late final String _uriScheme;
@override
String get uriScheme => _uriScheme;
late final String _ticker;
@override
String get ticker => _ticker;
@override
String get genesisHash {
return "not used in mimblewimblecoin";
}
@override
// change this to change the number of confirms a tx needs in order to show as confirmed
int get minConfirms => 3;
@override
bool validateAddress(String address) {
// Invalid address that contains HTTP and mwcmqs domain
if ((address.startsWith("http://") || address.startsWith("https://")) &&
address.contains("@")) {
return false;
}
if (address.startsWith("http://") || address.startsWith("https://")) {
if (Uri.tryParse(address) != null) {
return true;
}
}
return mimblewimblecoin.LibMwc.validateSendAddress(address: address);
}
@override
NodeModel get defaultNode {
switch (network) {
case CryptoCurrencyNetwork.main:
return NodeModel(
host: "http://epiccash.stackwallet.com",
port: 3413,
name: DefaultNodes.defaultName,
id: DefaultNodes.buildId(this),
useSSL: false,
enabled: true,
coinName: identifier,
isFailover: true,
isDown: false,
);
default:
throw UnimplementedError();
}
}
@override
int get defaultSeedPhraseLength => 24;
@override
int get fractionDigits => 8;
@override
bool get hasBuySupport => false;
@override
bool get hasMnemonicPassphraseSupport => false;
@override
List<int> get possibleMnemonicLengths => [defaultSeedPhraseLength, 12];
@override
AddressType get defaultAddressType => AddressType.mimbleWimble;
@override
BigInt get satsPerCoin => BigInt.from(100000000);
@override
int get targetBlockTimeSeconds => 60;
@override
DerivePathType get defaultDerivePathType => throw UnsupportedError(
"$runtimeType does not use bitcoin style derivation paths",
);
@override
Uri defaultBlockExplorer(String txid) {
switch (network) {
default:
throw Exception(
"Unsupported network for defaultBlockExplorer(): $network",
);
}
}
}

View file

@ -11,6 +11,7 @@ export 'coins/dash.dart';
export 'coins/dogecoin.dart';
export 'coins/ecash.dart';
export 'coins/epiccash.dart';
export 'coins/mimblewimblecoin.dart';
export 'coins/ethereum.dart';
export 'coins/firo.dart';
export 'coins/litecoin.dart';
@ -62,7 +63,7 @@ abstract class CryptoCurrency {
int get minConfirms;
int get minCoinbaseConfirms => minConfirms;
// TODO: [prio=low] could be handled differently as (at least) epiccash does not use this
// TODO: [prio=low] could be handled differently as (at least) epiccash/mimblewimblecoin does not use this
String get genesisHash;
bool validateAddress(String address);

View file

@ -515,6 +515,7 @@ class WalletInfo implements IsarId {
abstract class WalletInfoKeys {
static const String tokenContractAddresses = "tokenContractAddressesKey";
static const String epiccashData = "epiccashDataKey";
static const String mimblewimblecoinData = "mimblewimblecoinDataKey";
static const String bananoMonkeyImageBytes = "monkeyImageBytesKey";
static const String tezosDerivationPath = "tezosDerivationPathKey";
static const String lelantusCoinIsarRescanRequired =

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,111 @@
import 'dart:convert';
import 'package:isar/isar.dart';
import '../../../utilities/logger.dart';
import '../../isar/models/wallet_info.dart';
extension MimblewimblecoinWalletInfoExtension on WalletInfo {
ExtraMimblewimblecoinWalletInfo? get epicData {
final String? data =
otherData[WalletInfoKeys.mimblewimblecoinData] as String?;
if (data == null) {
return null;
}
try {
return ExtraMimblewimblecoinWalletInfo.fromMap(
Map<String, dynamic>.from(
jsonDecode(data) as Map,
),
);
} catch (e, s) {
Logging.instance.log(
"ExtraMimblewimblecoinWalletInfo.fromMap failed: $e\n$s",
level: LogLevel.Error,
);
return null;
}
}
Future<void> updateExtraMimblewimblecoinWalletInfo({
required ExtraMimblewimblecoinWalletInfo epicData,
required Isar isar,
}) async {
await updateOtherData(
newEntries: {
WalletInfoKeys.mimblewimblecoinData: jsonEncode(epicData.toMap()),
},
isar: isar,
);
}
}
/// Holds data previously stored in hive
class ExtraMimblewimblecoinWalletInfo {
final int receivingIndex;
final int changeIndex;
// TODO [prio=low] strongly type these maps at some point
final Map<dynamic, dynamic> slatesToAddresses;
final Map<dynamic, dynamic> slatesToCommits;
final int lastScannedBlock;
final int restoreHeight;
final int creationHeight;
ExtraMimblewimblecoinWalletInfo({
required this.receivingIndex,
required this.changeIndex,
required this.slatesToAddresses,
required this.slatesToCommits,
required this.lastScannedBlock,
required this.restoreHeight,
required this.creationHeight,
});
// Convert the object to JSON
Map<String, dynamic> toMap() {
return {
'receivingIndex': receivingIndex,
'changeIndex': changeIndex,
'slatesToAddresses': slatesToAddresses,
'slatesToCommits': slatesToCommits,
'lastScannedBlock': lastScannedBlock,
'restoreHeight': restoreHeight,
'creationHeight': creationHeight,
};
}
ExtraMimblewimblecoinWalletInfo.fromMap(Map<String, dynamic> json)
: receivingIndex = json['receivingIndex'] as int,
changeIndex = json['changeIndex'] as int,
slatesToAddresses = json['slatesToAddresses'] as Map,
slatesToCommits = json['slatesToCommits'] as Map,
lastScannedBlock = json['lastScannedBlock'] as int,
restoreHeight = json['restoreHeight'] as int,
creationHeight = json['creationHeight'] as int;
ExtraMimblewimblecoinWalletInfo copyWith({
int? receivingIndex,
int? changeIndex,
Map<dynamic, dynamic>? slatesToAddresses,
Map<dynamic, dynamic>? slatesToCommits,
int? lastScannedBlock,
int? restoreHeight,
int? creationHeight,
}) {
return ExtraMimblewimblecoinWalletInfo(
receivingIndex: receivingIndex ?? this.receivingIndex,
changeIndex: changeIndex ?? this.changeIndex,
slatesToAddresses: slatesToAddresses ?? this.slatesToAddresses,
slatesToCommits: slatesToCommits ?? this.slatesToCommits,
lastScannedBlock: lastScannedBlock ?? this.lastScannedBlock,
restoreHeight: restoreHeight ?? this.restoreHeight,
creationHeight: creationHeight ?? this.creationHeight,
);
}
@override
String toString() {
return toMap().toString();
}
}

View file

@ -34,6 +34,7 @@ import 'impl/dash_wallet.dart';
import 'impl/dogecoin_wallet.dart';
import 'impl/ecash_wallet.dart';
import 'impl/epiccash_wallet.dart';
import 'impl/mimblewimblecoin_wallet.dart';
import 'impl/ethereum_wallet.dart';
import 'impl/firo_wallet.dart';
import 'impl/litecoin_wallet.dart';
@ -359,6 +360,9 @@ abstract class Wallet<T extends CryptoCurrency> {
case const (Epiccash):
return EpiccashWallet(net);
case const (Mimblewimblecoin):
return Mimblewimblecoin(net);
case const (Ethereum):
return EthereumWallet(net);

View file

@ -153,7 +153,7 @@ class _TorHasBeenAddedDialogState extends State<_TorHasBeenAddedDialog> {
height: Util.isDesktop ? 24 : 16,
),
Text(
"Note: Tor does NOT yet work for Monero or Epic Cash wallets. "
"Note: Tor does NOT yet work for Monero, Mimblewimblecoin or Epic Cash wallets. "
"Opening one of these will leak your IP address.",
style: Util.isDesktop
? STextStyles.desktopTextMedium(context)

View file

@ -27,6 +27,7 @@ import '../utilities/constants.dart';
import '../utilities/format.dart';
import '../utilities/text_styles.dart';
import '../utilities/util.dart';
import '../wallets/crypto_currency/coins/mimblewimblecoin.dart';
import '../wallets/crypto_currency/crypto_currency.dart';
import 'desktop/desktop_dialog.dart';
@ -63,6 +64,10 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
return "Restored Funds";
}
if (coin is Mimblewimblecoin && _transaction.slateId == null) {
return "Restored Funds";
}
final confirmedStatus = _transaction.isConfirmed(
currentHeight,
minConfirms,
@ -188,6 +193,20 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
);
return;
}
if (coin is Mimblewimblecoin && _transaction.slateId == null) {
unawaited(
showFloatingFlushBar(
context: context,
message:
"Restored Mimblewimblecoin funds from your Seed have no Data.",
type: FlushBarType.warning,
duration: const Duration(seconds: 5),
),
);
return;
}
if (Util.isDesktop) {
await showDialog<void>(
context: context,

View file

@ -10,7 +10,7 @@
#include <desktop_drop/desktop_drop_plugin.h>
#include <devicelocale/devicelocale_plugin.h>
#include <flutter_libepiccash/flutter_libepiccash_plugin.h>
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
#include <flutter_libmwc/flutter_libmwc_plugin.h>
#include <isar_flutter_libs/isar_flutter_libs_plugin.h>
#include <sqlite3_flutter_libs/sqlite3_flutter_libs_plugin.h>
#include <stack_wallet_backup/stack_wallet_backup_plugin.h>
@ -30,6 +30,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) flutter_libepiccash_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterLibepiccashPlugin");
flutter_libepiccash_plugin_register_with_registrar(flutter_libepiccash_registrar);
g_autoptr(FlPluginRegistrar) flutter_libmwc_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterLibmwcPlugin");
flutter_libmwc_plugin_register_with_registrar(flutter_libmwc_registrar);
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);

View file

@ -7,6 +7,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
desktop_drop
devicelocale
flutter_libepiccash
flutter_libmwc
flutter_secure_storage_linux
isar_flutter_libs
sqlite3_flutter_libs

View file

@ -12,6 +12,7 @@ import desktop_drop
import device_info_plus
import devicelocale
import flutter_libepiccash
import flutter_libmwc
import flutter_local_notifications
import flutter_secure_storage_macos
import isar_flutter_libs
@ -34,6 +35,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))
FlutterLibepiccashPlugin.register(with: registry.registrar(forPlugin: "FlutterLibepiccashPlugin"))
FlutterLibmwcPlugin.register(with: registry.registrar(forPlugin: "FlutterLibmwcPlugin"))
FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
IsarFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "IsarFlutterLibsPlugin"))

View file

@ -812,6 +812,13 @@ packages:
relative: true
source: path
version: "0.0.1"
flutter_libmwc:
dependency: "direct main"
description:
path: "crypto_plugins/flutter_libmwc"
relative: true
source: path
version: "0.0.1"
flutter_libsparkmobile:
dependency: "direct main"
description:

View file

@ -62,6 +62,7 @@ final List<CryptoCurrency> _supportedCoins = List.unmodifiable([
Dogecoin(CryptoCurrencyNetwork.main),
Ecash(CryptoCurrencyNetwork.main),
Epiccash(CryptoCurrencyNetwork.main),
Mimblewimblecoin(CryptoCurrencyNetwork.main),
Ethereum(CryptoCurrencyNetwork.main),
Firo(CryptoCurrencyNetwork.main),
Litecoin(CryptoCurrencyNetwork.main),

View file

@ -137,7 +137,10 @@ install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libepiccash/scripts/linux/build/rust/target/x86_64-unknown-linux-gnu/release/libepic_cash_wallet.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_liblelantus/scripts/linux/build/libmobileliblelantus.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libemwc/scripts/linux/build/rust/target/x86_64-unknown-linux-gnu/release/libmwc_wallet.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_liblelantus/scripts/linux/build/libmobileliblelantus.so" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../scripts/linux/build/jsoncpp/build/src/lib_json/libjsoncpp.so.1.7.4" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"

View file

@ -45,6 +45,9 @@ dependencies:
flutter_libepiccash:
path: ./crypto_plugins/flutter_libepiccash
flutter_libmwc:
path: ./crypto_plugins/flutter_libmwc
bitcoindart:
git:
url: https://github.com/cypherstack/bitcoindart.git

View file

@ -83,6 +83,9 @@ install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libepiccash/scripts/windows/build/libepic_cash_wallet.dll" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_libmwc/scripts/windows/build/libmwc_cash_wallet.dll" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../crypto_plugins/flutter_liblelantus/scripts/windows/build/libmobileliblelantus.dll" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)

View file

@ -16,6 +16,8 @@ rustup target add x86_64-apple-ios
(cd ../../crypto_plugins/flutter_liblelantus/scripts/ios && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/ios && ./build_all.sh )
set_rust_to_1810
(cd ../../crypto_plugins/flutter_libmwc/scripts/ios/ && ./build_all.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/ios && ./build_all.sh )

View file

@ -16,6 +16,8 @@ rustup target add x86_64-apple-ios
(cd ../../crypto_plugins/flutter_liblelantus/scripts/ios && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/ios && ./build_all.sh )
set_rust_to_1810
(cd ../../crypto_plugins/flutter_libmwc/scripts/ios/ && ./build_all.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/ios && ./build_all.sh )

View file

@ -18,6 +18,8 @@ rustup target add x86_64-apple-ios
(cd ../../crypto_plugins/flutter_liblelantus/scripts/ios && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/ios && ./build_all.sh )
set_rust_to_1810
(cd ../../crypto_plugins/flutter_libmwc/scripts/ios/ && ./build_all.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/ios && ./build_all.sh )

View file

@ -14,6 +14,8 @@ mkdir -p build
./build_secure_storage_deps.sh
(cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/linux && ./build_all.sh )
set_rust_to_1810
(cd ../../crypto_plugins/flutter_libmwc/scripts/linux && ./build_all.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/linux && ./build_all.sh )

View file

@ -14,6 +14,8 @@ mkdir -p build
./build_secure_storage_deps.sh
(cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/linux && ./build_all.sh )
set_rust_to_1810
(cd ../../crypto_plugins/flutter_libmwc/scripts/linux && ./build_all.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/linux && ./build_all.sh )

View file

@ -16,6 +16,8 @@ mkdir -p build
./build_secure_storage_deps.sh &
(cd ../../crypto_plugins/flutter_liblelantus/scripts/linux && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/linux && ./build_all.sh )
set_rust_to_1810
(cd ../../crypto_plugins/flutter_libmwc/scripts/linux && ./build_all.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/linux && ./build_all.sh )

View file

@ -8,6 +8,8 @@ set_rust_to_1671
(cd ../../crypto_plugins/flutter_liblelantus/scripts/macos && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/macos && ./build_all.sh )
set_rust_to_1810
(cd ../../crypto_plugins/flutter_libmwc/scripts/macos && ./build_all.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/macos && ./build_all.sh )

View file

@ -8,6 +8,8 @@ set_rust_to_1671
(cd ../../crypto_plugins/flutter_liblelantus/scripts/macos && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/macos && ./build_all.sh )
set_rust_to_1810
(cd ../../crypto_plugins/flutter_libmwc/scripts/macos && ./build_all.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/macos && ./build_all.sh )

View file

@ -10,6 +10,8 @@ set_rust_to_1671
(cd ../../crypto_plugins/flutter_liblelantus/scripts/macos && ./build_all.sh )
(cd ../../crypto_plugins/flutter_libepiccash/scripts/macos && ./build_all.sh )
set_rust_to_1810
(cd ../../crypto_plugins/flutter_libmwc/scripts/macos && ./build_all.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/macos && ./build_all.sh )

View file

@ -16,4 +16,13 @@ set_rust_to_1720() {
echo "Rust version 1.72.0 is not installed. Please install it using 'rustup install 1.72.0'." >&2
exit 1
fi
}
set_rust_to_1810() {
if rustup toolchain list | grep -q "1.72.0"; then
rustup default 1.81.0
else
echo "Rust version 1.81.0 is not installed. Please install it using 'rustup install 1.81.0'." >&2
exit 1
fi
}

View file

@ -9,6 +9,8 @@ set_rust_to_1671
mkdir -p build
(cd ../../crypto_plugins/flutter_libepiccash/scripts/windows && ./build_all.sh )
(cd ../../crypto_plugins/flutter_liblelantus/scripts/windows && ./build_all.sh )
set_rust_to_1810
(cd ../../crypto_plugins/flutter_libmwc/scripts/windows && ./build_all.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/windows && ./build_all.sh )

View file

@ -9,6 +9,8 @@ set_rust_to_1671
mkdir -p build
(cd ../../crypto_plugins/flutter_libepiccash/scripts/windows && ./build_all.sh )
(cd ../../crypto_plugins/flutter_liblelantus/scripts/windows && ./build_all.sh )
set_rust_to_1810
(cd ../../crypto_plugins/flutter_libmwc/scripts/windows && ./build_all.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/windows && ./build_all.sh )

View file

@ -11,6 +11,8 @@ set_rust_to_1671
mkdir -p build
(cd ../../crypto_plugins/flutter_libepiccash/scripts/windows && ./build_all.sh )
(cd ../../crypto_plugins/flutter_liblelantus/scripts/windows && ./build_all.sh )
set_rust_to_1810
(cd ../../crypto_plugins/flutter_libmwc/scripts/windows && ./build_all.sh )
set_rust_to_1720
(cd ../../crypto_plugins/frostdart/scripts/windows && ./build_all.sh )

View file

@ -1,9 +1,9 @@
#!/bin/bash
cd ../../crypto_plugins/flutter_libepiccash/scripts/windows && ./deps.sh
cd ../../crypto_plugins/flutter_liblelantus/scripts/windows && ./mxedeps.sh
# cd ../../crypto_plugins/flutter_libmonero/scripts/windows && ./monerodeps.sh && ./mxedeps.sh
sudo apt install libgtk2.0-dev
(cd ../../crypto_plugins/flutter_libepiccash/scripts/windows && ./deps.sh )
(cd ../../crypto_plugins/flutter_liblelantus/scripts/windows && ./mxedeps.sh )
(cd ../../crypto_plugins/flutter_libmwc/scripts/windows && ./deps.sh)
# (cd ../../crypto_plugins/flutter_libmonero/scripts/windows && ./monerodeps.sh && ./mxedeps.sh) &
wait
echo "Done building"

View file

@ -1,3 +1,5 @@
// TODO MWC
import 'dart:convert';
import 'dart:io';

View file

@ -10,6 +10,7 @@ const Map<String, dynamic> lightThemeJsonMap = {
"firo": "0xFFFF897A",
"dogecoin": "0xFFFFE079",
"epicCash": "0xFFC5C7CB",
"mimblewimblecoin": "0xFFC5C7CB",
"ethereum": "0xFFA7ADE9",
"monero": "0xFFFF9E6B",
"namecoin": "0xFF91B1E1",
@ -186,6 +187,7 @@ const Map<String, dynamic> lightThemeJsonMap = {
"bitcoincash": "dummy.svg",
"dogecoin": "dummy.svg",
"epicCash": "dummy.svg",
"mimblewimblecoin": "dummy.svg",
"ethereum": "dummy.svg",
"firo": "dummy.svg",
"monero": "dummy.svg",
@ -197,6 +199,7 @@ const Map<String, dynamic> lightThemeJsonMap = {
"bitcoincash_image": "dummy.svg",
"dogecoin_image": "dummy.svg",
"epicCash_image": "dummy.svg.svg",
"mimblewimblecoin_image": "dummy.svg",
"ethereum_image": "dummy.svg",
"firo_image": "dummy.svg",
"monero_image": "dummy.svg",
@ -208,6 +211,7 @@ const Map<String, dynamic> lightThemeJsonMap = {
"bitcoincash_image_secondary": "dummy.svg",
"dogecoin_image_secondary": "dummy.svg",
"epicCash_image_secondary": "dummy.svg.svg",
"mimblewimblecoin_image_secondary": "dummy.svg",
"ethereum_image_secondary": "dummy.svg",
"firo_image_secondary": "dummy.svg",
"monero_image_secondary": "dummy.svg",

View file

@ -13,6 +13,7 @@ const Map<String, dynamic> lightThemeJsonMap = {
"dogecoin": "0xFFFFE079",
"eCash": "0xFFC5C7CB",
"epicCash": "0xFFC5C7CB",
"mimblewimblecoin": "0xFFC5C7CB",
"ethereum": "0xFFA7ADE9",
"monero": "0xFFFF9E6B",
"namecoin": "0xFF91B1E1",
@ -194,6 +195,7 @@ const Map<String, dynamic> lightThemeJsonMap = {
"dogecoin": "dummy.svg",
"eCash": "dummy.svg",
"epicCash": "dummy.svg",
"mimblewimblecoin": "dummy.svg",
"ethereum": "dummy.svg",
"firo": "dummy.svg",
"monero": "dummy.svg",
@ -208,6 +210,7 @@ const Map<String, dynamic> lightThemeJsonMap = {
"dogecoin": "dummy.svg",
"eCash": "dummy.svg",
"epicCash": "dummy.svg",
"mimblewimblecoin": "dummy.svg",
"ethereum": "dummy.svg",
"firo": "dummy.svg",
"monero": "dummy.svg",
@ -222,6 +225,7 @@ const Map<String, dynamic> lightThemeJsonMap = {
"dogecoin": "dummy.svg",
"eCash": "dummy.svg",
"epicCash": "dummy.svg",
"mimblewimblecoin": "dummy.svg",
"ethereum": "dummy.svg",
"firo": "dummy.svg",
"monero": "dummy.svg",

View file

@ -1,3 +1,5 @@
// TODO MWC
import 'package:flutter_test/flutter_test.dart';
import 'package:hive/hive.dart';
import 'package:hive_test/hive_test.dart';
@ -160,6 +162,17 @@ void main() {
torEnabled: true,
clearnetEnabled: true,
);
final nodeD = NodeModel(
host: "host3",
port: 423,
name: "btcnode",
id: "pnodeID3",
useSSL: true,
enabled: true,
coinName: "mimblewimblecoin",
isFailover: true,
isDown: false,
);
setUp(() async {
await NodeService(secureStorageInterface: FakeSecureStorage())

View file

@ -11,6 +11,7 @@
#include <cs_monero_flutter_libs_windows/cs_monero_flutter_libs_windows_plugin_c_api.h>
#include <desktop_drop/desktop_drop_plugin.h>
#include <flutter_libepiccash/flutter_libepiccash_plugin_c_api.h>
#include <flutter_libmwc/flutter_libmwc_plugin_c_api.h>
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
#include <isar_flutter_libs/isar_flutter_libs_plugin.h>
#include <local_auth_windows/local_auth_plugin.h>
@ -32,6 +33,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
registry->GetRegistrarForPlugin("DesktopDropPlugin"));
FlutterLibepiccashPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterLibepiccashPluginCApi"));
FlutterLibmwcPluginCApiRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterLibmwcPluginCApi"));
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
IsarFlutterLibsPluginRegisterWithRegistrar(

View file

@ -8,6 +8,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
cs_monero_flutter_libs_windows
desktop_drop
flutter_libepiccash
flutter_libmwc
flutter_secure_storage_windows
isar_flutter_libs
local_auth_windows