mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-11-17 09:47:37 +00:00
commit
03cc123f8a
29 changed files with 1738 additions and 39 deletions
7
assets/svg/coin_icons/Wownero.svg
Normal file
7
assets/svg/coin_icons/Wownero.svg
Normal file
|
@ -0,0 +1,7 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 23.8456C18.5421 23.8456 23.8456 18.5421 23.8456 12C23.8456 5.45778 18.5421 0.154297 12 0.154297C5.45778 0.154297 0.154297 5.45778 0.154297 12C0.154297 18.5421 5.45778 23.8456 12 23.8456Z" fill="white"/>
|
||||
<path d="M12 24C5.38264 24 0 18.6174 0 12C0 5.38264 5.38264 0 12 0C18.6174 0 24 5.38264 24 12C24 18.6174 18.6174 24 12 24ZM12 0.327974C5.55627 0.327974 0.327974 5.57556 0.327974 12C0.327974 18.4244 5.57556 23.672 12 23.672C18.4244 23.672 23.672 18.4244 23.672 12C23.672 5.57556 18.4437 0.327974 12 0.327974Z" fill="#D0509D"/>
|
||||
<path d="M11.9995 0.154297C6.75195 0.154297 2.29536 3.58838 0.751953 8.31507H6.73266V15.7427L11.961 10.0707H12.0381L17.2664 15.762V8.31507H23.2471C21.7037 3.58838 17.2471 0.154297 11.9995 0.154297Z" fill="#FFCD05"/>
|
||||
<path d="M6.56007 16.1672V8.48875H0.521484L0.598655 8.27653C2.19994 3.31833 6.79158 0 12.0006 0C17.2096 0 21.8012 3.31833 23.4025 8.27653L23.4797 8.48875H17.4411V16.1672L12.0006 10.283L6.56007 16.1672ZM11.9041 9.9164H12.1163L17.1131 15.3376V8.16077H23.036C21.3961 3.47267 16.9974 0.327974 12.0006 0.327974C7.0038 0.327974 2.60509 3.47267 0.965214 8.16077H6.88804V15.3376L11.9041 9.9164Z" fill="#D0509D"/>
|
||||
<path d="M18.2473 18.2508L16.5495 16.418L11.9965 11.4791L7.4434 16.418L5.74565 18.2508V15.762V9.5498H1.59774C1.40482 10.3601 1.28906 11.209 1.28906 12.0964C1.28906 18 6.07363 22.8038 11.9965 22.8038C17.9193 22.8038 22.7039 18.0193 22.7039 12.0964C22.7039 11.2283 22.5881 10.3794 22.3952 9.5498H18.228V15.762V18.2508H18.2473Z" fill="#D0519D"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
|
@ -1 +1 @@
|
|||
Subproject commit 4bffa40cb60ad3d98cf0ea5b5d819f3f4895dcd6
|
||||
Subproject commit 8e3afd002968d21a3de788569356587a70818022
|
|
@ -8,6 +8,7 @@ import 'package:cw_core/wallet_type.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_libmonero/monero/monero.dart';
|
||||
import 'package:flutter_libmonero/wownero/wownero.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
|
@ -84,7 +85,6 @@ void main() async {
|
|||
appDirectory = (await getLibraryDirectory());
|
||||
}
|
||||
// FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
||||
await Hive.initFlutter(appDirectory.path);
|
||||
if (!(Logging.isArmLinux || Logging.isTestEnv)) {
|
||||
final isar = await Isar.open(
|
||||
[LogSchema],
|
||||
|
@ -128,11 +128,14 @@ void main() async {
|
|||
|
||||
Hive.registerAdapter(NodeAdapter());
|
||||
|
||||
Hive.registerAdapter(WalletInfoAdapter());
|
||||
if (!Hive.isAdapterRegistered(WalletInfoAdapter().typeId)) {
|
||||
Hive.registerAdapter(WalletInfoAdapter());
|
||||
}
|
||||
|
||||
Hive.registerAdapter(WalletTypeAdapter());
|
||||
|
||||
Hive.registerAdapter(UnspentCoinsInfoAdapter());
|
||||
await Hive.initFlutter(appDirectory.path);
|
||||
|
||||
await Hive.openBox<dynamic>(DB.boxNameDBInfo);
|
||||
int dbVersion = DB.instance.get<dynamic>(
|
||||
|
@ -143,6 +146,7 @@ void main() async {
|
|||
}
|
||||
|
||||
monero.onStartup();
|
||||
wownero.onStartup();
|
||||
|
||||
await Hive.openBox<dynamic>(DB.boxNameTheme);
|
||||
|
||||
|
|
|
@ -59,7 +59,9 @@ class _NewWalletRecoveryPhraseWarningViewState
|
|||
|
||||
final _numberOfPhraseWords = coin == Coin.monero
|
||||
? Constants.seedPhraseWordCountMonero
|
||||
: Constants.seedPhraseWordCountBip39;
|
||||
: coin == Coin.wownero
|
||||
? 14
|
||||
: Constants.seedPhraseWordCountBip39;
|
||||
|
||||
return MasterScaffold(
|
||||
isDesktop: isDesktop,
|
||||
|
|
|
@ -200,7 +200,7 @@ class _RestoreWalletViewState extends ConsumerState<RestoreWalletView> {
|
|||
|
||||
// TODO: do actual check to make sure it is a valid mnemonic for monero
|
||||
if (bip39.validateMnemonic(mnemonic) == false &&
|
||||
!(widget.coin == Coin.monero)) {
|
||||
!(widget.coin == Coin.monero || widget.coin == Coin.wownero)) {
|
||||
unawaited(showFloatingFlushBar(
|
||||
type: FlushBarType.warning,
|
||||
message: "Invalid seed phrase!",
|
||||
|
|
|
@ -85,7 +85,7 @@ class _SendFromViewState extends ConsumerState<SendFromView> {
|
|||
height: 8,
|
||||
),
|
||||
Text(
|
||||
"You need to send ${amount.toStringAsFixed(coin == Coin.monero ? 12 : 8)} ${coin.ticker}",
|
||||
"You need to send ${amount.toStringAsFixed(coin == Coin.monero ? Constants.satsPerCoinMonero : coin == Coin.wownero ? Constants.satsPerCoinWownero : Constants.satsPerCoin)} ${coin.ticker}",
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
),
|
||||
const SizedBox(
|
||||
|
@ -307,7 +307,11 @@ class _SendFromCardState extends ConsumerState<SendFromCard> {
|
|||
"${Format.localizedStringAsFixed(
|
||||
value: snapshot.data!,
|
||||
locale: locale,
|
||||
decimalPlaces: coin == Coin.monero ? 12 : 8,
|
||||
decimalPlaces: coin == Coin.monero
|
||||
? Constants.satsPerCoinMonero
|
||||
: coin == Coin.wownero
|
||||
? Constants.satsPerCoinWownero
|
||||
: Constants.satsPerCoin,
|
||||
)} ${coin.ticker}",
|
||||
style: STextStyles.itemSubtitle(context),
|
||||
);
|
||||
|
|
|
@ -90,6 +90,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
|
|||
break;
|
||||
|
||||
case Coin.monero:
|
||||
case Coin.wownero:
|
||||
try {
|
||||
final uri = Uri.parse(formData.host!);
|
||||
if (uri.scheme.startsWith("http")) {
|
||||
|
@ -384,6 +385,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
|
|||
// strip unused path
|
||||
String address = formData.host!;
|
||||
if (coin == Coin.monero ||
|
||||
coin == Coin.wownero ||
|
||||
coin == Coin.epicCash) {
|
||||
if (address.startsWith("http")) {
|
||||
final uri = Uri.parse(address);
|
||||
|
@ -539,6 +541,7 @@ class _NodeFormState extends ConsumerState<NodeForm> {
|
|||
|
||||
case Coin.epicCash:
|
||||
case Coin.monero:
|
||||
case Coin.wownero:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -699,7 +702,9 @@ class _NodeFormState extends ConsumerState<NodeForm> {
|
|||
focusNode: _hostFocusNode,
|
||||
style: STextStyles.field(context),
|
||||
decoration: standardInputDecoration(
|
||||
(widget.coin != Coin.monero && widget.coin != Coin.epicCash)
|
||||
(widget.coin != Coin.monero &&
|
||||
widget.coin != Coin.wownero &&
|
||||
widget.coin != Coin.epicCash)
|
||||
? "IP address"
|
||||
: "Url",
|
||||
_hostFocusNode,
|
||||
|
@ -880,7 +885,9 @@ class _NodeFormState extends ConsumerState<NodeForm> {
|
|||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
if (widget.coin != Coin.monero && widget.coin != Coin.epicCash)
|
||||
if (widget.coin != Coin.monero &&
|
||||
widget.coin != Coin.wownero &&
|
||||
widget.coin != Coin.epicCash)
|
||||
Row(
|
||||
children: [
|
||||
GestureDetector(
|
||||
|
@ -931,11 +938,15 @@ class _NodeFormState extends ConsumerState<NodeForm> {
|
|||
),
|
||||
],
|
||||
),
|
||||
if (widget.coin != Coin.monero && widget.coin != Coin.epicCash)
|
||||
if (widget.coin != Coin.monero &&
|
||||
widget.coin != Coin.wownero &&
|
||||
widget.coin != Coin.epicCash)
|
||||
const SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
if (widget.coin != Coin.monero && widget.coin != Coin.epicCash)
|
||||
if (widget.coin != Coin.monero &&
|
||||
widget.coin != Coin.wownero &&
|
||||
widget.coin != Coin.epicCash)
|
||||
Row(
|
||||
children: [
|
||||
GestureDetector(
|
||||
|
|
|
@ -81,6 +81,7 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> {
|
|||
break;
|
||||
|
||||
case Coin.monero:
|
||||
case Coin.wownero:
|
||||
try {
|
||||
final uri = Uri.parse(node!.host);
|
||||
if (uri.scheme.startsWith("http")) {
|
||||
|
|
|
@ -12,6 +12,7 @@ import 'package:stackwallet/pages/settings_views/wallet_settings_view/wallet_net
|
|||
import 'package:stackwallet/providers/providers.dart';
|
||||
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/monero/monero_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart';
|
||||
import 'package:stackwallet/services/event_bus/events/global/blocks_remaining_event.dart';
|
||||
import 'package:stackwallet/services/event_bus/events/global/node_connection_status_changed_event.dart';
|
||||
import 'package:stackwallet/services/event_bus/events/global/refresh_percent_changed_event.dart';
|
||||
|
@ -205,7 +206,7 @@ class _WalletNetworkSettingsViewState
|
|||
.getManager(widget.walletId)
|
||||
.coin;
|
||||
|
||||
if (coin == Coin.monero || coin == Coin.epicCash) {
|
||||
if (coin == Coin.monero || coin == Coin.wownero || coin == Coin.epicCash) {
|
||||
_blocksRemainingSubscription = eventBus.on<BlocksRemainingEvent>().listen(
|
||||
(event) async {
|
||||
if (event.walletId == widget.walletId) {
|
||||
|
@ -271,6 +272,15 @@ class _WalletNetworkSettingsViewState
|
|||
if (_percent < highestPercent) {
|
||||
_percent = highestPercent.clamp(0.0, 1.0);
|
||||
}
|
||||
} else if (coin == Coin.wownero) {
|
||||
double highestPercent = (ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
.getManager(widget.walletId)
|
||||
.wallet as WowneroWallet)
|
||||
.highestPercentCached;
|
||||
if (_percent < highestPercent) {
|
||||
_percent = highestPercent.clamp(0.0, 1.0);
|
||||
}
|
||||
} else if (coin == Coin.epicCash) {
|
||||
double highestPercent = (ref
|
||||
.read(walletsChangeNotifierProvider)
|
||||
|
@ -545,6 +555,7 @@ class _WalletNetworkSettingsViewState
|
|||
),
|
||||
),
|
||||
if (coin == Coin.monero ||
|
||||
coin == Coin.wownero ||
|
||||
coin == Coin.epicCash)
|
||||
Text(
|
||||
" (Blocks to go: ${_blocksRemaining == -1 ? "?" : _blocksRemaining})",
|
||||
|
|
|
@ -241,7 +241,9 @@ class _TransactionDetailsViewState
|
|||
"$amountPrefix${Format.localizedStringAsFixed(
|
||||
value: coin == Coin.monero
|
||||
? (amount / 10000.toDecimal()).toDecimal()
|
||||
: amount,
|
||||
: coin == Coin.wownero
|
||||
? (amount / 1000.toDecimal()).toDecimal()
|
||||
: amount,
|
||||
locale: ref.watch(
|
||||
localeServiceChangeNotifierProvider
|
||||
.select((value) => value.locale),
|
||||
|
@ -254,7 +256,7 @@ class _TransactionDetailsViewState
|
|||
height: 2,
|
||||
),
|
||||
SelectableText(
|
||||
"${Format.localizedStringAsFixed(value: (coin == Coin.monero ? (amount / 10000.toDecimal()).toDecimal() : amount) * ref.watch(priceAnd24hChangeNotifierProvider.select((value) => value.getPrice(coin).item1)), locale: ref.watch(
|
||||
"${Format.localizedStringAsFixed(value: (coin == Coin.monero ? (amount / 10000.toDecimal()).toDecimal() : coin == Coin.wownero ? (amount / 1000.toDecimal()).toDecimal() : amount) * ref.watch(priceAnd24hChangeNotifierProvider.select((value) => value.getPrice(coin).item1)), locale: ref.watch(
|
||||
localeServiceChangeNotifierProvider
|
||||
.select((value) => value.locale),
|
||||
), decimalPlaces: 2)} ${ref.watch(
|
||||
|
@ -298,14 +300,14 @@ class _TransactionDetailsViewState
|
|||
],
|
||||
),
|
||||
),
|
||||
if (!(coin == Coin.monero &&
|
||||
if (!((coin == Coin.monero || coin == Coin.wownero) &&
|
||||
_transaction.txType.toLowerCase() == "sent") &&
|
||||
!((coin == Coin.firo || coin == Coin.firoTestNet) &&
|
||||
_transaction.subType == "mint"))
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
if (!(coin == Coin.monero &&
|
||||
if (!((coin == Coin.monero || coin == Coin.wownero) &&
|
||||
_transaction.txType.toLowerCase() == "sent") &&
|
||||
!((coin == Coin.firo || coin == Coin.firoTestNet) &&
|
||||
_transaction.subType == "mint"))
|
||||
|
@ -464,7 +466,10 @@ class _TransactionDetailsViewState
|
|||
? Format.localizedStringAsFixed(
|
||||
value: coin == Coin.monero
|
||||
? (fee / 10000.toDecimal()).toDecimal()
|
||||
: fee,
|
||||
: coin == Coin.wownero
|
||||
? (fee / 1000.toDecimal())
|
||||
.toDecimal()
|
||||
: fee,
|
||||
locale: ref.watch(
|
||||
localeServiceChangeNotifierProvider
|
||||
.select((value) => value.locale)),
|
||||
|
@ -473,7 +478,9 @@ class _TransactionDetailsViewState
|
|||
: Format.localizedStringAsFixed(
|
||||
value: coin == Coin.monero
|
||||
? (fee / 10000.toDecimal()).toDecimal()
|
||||
: fee,
|
||||
: coin == Coin.wownero
|
||||
? (fee / 1000.toDecimal()).toDecimal()
|
||||
: fee,
|
||||
locale: ref.watch(
|
||||
localeServiceChangeNotifierProvider
|
||||
.select((value) => value.locale)),
|
||||
|
|
|
@ -755,6 +755,11 @@ class _TransactionSearchViewState
|
|||
.floor()
|
||||
.toBigInt()
|
||||
.toInt();
|
||||
} else if (widget.coin == Coin.wownero) {
|
||||
amount = (amountDecimal * Decimal.fromInt(Constants.satsPerCoinWownero))
|
||||
.floor()
|
||||
.toBigInt()
|
||||
.toInt();
|
||||
} else {
|
||||
amount = (amountDecimal * Decimal.fromInt(Constants.satsPerCoin))
|
||||
.floor()
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart';
|
|||
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/monero/monero_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart';
|
||||
import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart';
|
||||
import 'package:stackwallet/services/transaction_notification_tracker.dart';
|
||||
import 'package:stackwallet/utilities/enums/coin_enum.dart';
|
||||
|
@ -145,6 +146,14 @@ abstract class CoinServiceAPI {
|
|||
// tracker: tracker,
|
||||
);
|
||||
|
||||
case Coin.wownero:
|
||||
return WowneroWallet(
|
||||
walletId: walletId,
|
||||
walletName: walletName,
|
||||
coin: coin,
|
||||
// tracker: tracker,
|
||||
);
|
||||
|
||||
case Coin.namecoin:
|
||||
return NamecoinWallet(
|
||||
walletId: walletId,
|
||||
|
|
1560
lib/services/coins/wownero/wownero_wallet.dart
Normal file
1560
lib/services/coins/wownero/wownero_wallet.dart
Normal file
File diff suppressed because it is too large
Load diff
|
@ -79,7 +79,7 @@ class PriceAPI {
|
|||
Map<Coin, Tuple2<Decimal, double>> result = {};
|
||||
try {
|
||||
final uri = Uri.parse(
|
||||
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=${baseCurrency.toLowerCase()}&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false");
|
||||
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=${baseCurrency.toLowerCase()}&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin,wownero&order=market_cap_desc&per_page=10&page=1&sparkline=false");
|
||||
// final uri = Uri.parse(
|
||||
// "https://api.coingecko.com/api/v3/coins/markets?vs_currency=${baseCurrency.toLowerCase()}&ids=monero%2Cbitcoin%2Cepic-cash%2Czcoin%2Cdogecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false");
|
||||
|
||||
|
|
|
@ -223,7 +223,7 @@ class Wallets extends ChangeNotifier {
|
|||
final shouldSetAutoSync = shouldAutoSyncAll ||
|
||||
walletIdsToEnableAutoSync.contains(manager.walletId);
|
||||
|
||||
if (manager.coin == Coin.monero) {
|
||||
if (manager.coin == Coin.monero || manager.coin == Coin.wownero) {
|
||||
walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync));
|
||||
} else {
|
||||
walletInitFutures.add(manager.initializeExisting().then((value) {
|
||||
|
@ -312,7 +312,7 @@ class Wallets extends ChangeNotifier {
|
|||
final shouldSetAutoSync = shouldAutoSyncAll ||
|
||||
walletIdsToEnableAutoSync.contains(manager.walletId);
|
||||
|
||||
if (manager.coin == Coin.monero) {
|
||||
if (manager.coin == Coin.monero || manager.coin == Coin.wownero) {
|
||||
walletsToInitLinearly.add(Tuple2(manager, shouldSetAutoSync));
|
||||
} else {
|
||||
walletInitFutures.add(manager.initializeExisting().then((value) {
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:convert';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_libmonero/monero/monero.dart';
|
||||
import 'package:flutter_libmonero/wownero/wownero.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:stackwallet/hive/db.dart';
|
||||
import 'package:stackwallet/services/coins/epiccash/epiccash_wallet.dart';
|
||||
|
@ -367,8 +368,13 @@ class WalletsService extends ChangeNotifier {
|
|||
await DB.instance.delete<dynamic>(
|
||||
boxName: DB.boxNameAllWalletsData,
|
||||
key: "${walletId}_mnemonicHasBeenVerified");
|
||||
|
||||
if (coinFromPrettyName(shell['coin'] as String) == Coin.monero) {
|
||||
if (coinFromPrettyName(shell['coin'] as String) == Coin.wownero) {
|
||||
final wowService =
|
||||
wownero.createWowneroWalletService(DB.instance.moneroWalletInfoBox);
|
||||
await wowService.remove(walletId);
|
||||
Logging.instance
|
||||
.log("monero wallet: $walletId deleted", level: LogLevel.Info);
|
||||
} else if (coinFromPrettyName(shell['coin'] as String) == Coin.monero) {
|
||||
final xmrService =
|
||||
monero.createMoneroWalletService(DB.instance.moneroWalletInfoBox);
|
||||
await xmrService.remove(walletId);
|
||||
|
|
|
@ -53,6 +53,9 @@ class AddressUtils {
|
|||
case Coin.monero:
|
||||
return RegExp("[a-zA-Z0-9]{95}").hasMatch(address) ||
|
||||
RegExp("[a-zA-Z0-9]{106}").hasMatch(address);
|
||||
case Coin.wownero:
|
||||
return RegExp("[a-zA-Z0-9]{95}").hasMatch(address) ||
|
||||
RegExp("[a-zA-Z0-9]{106}").hasMatch(address);
|
||||
case Coin.namecoin:
|
||||
return Address.validateAddress(address, namecoin, namecoin.bech32!);
|
||||
case Coin.bitcoinTestNet:
|
||||
|
|
|
@ -128,6 +128,7 @@ class _SVG {
|
|||
String get epicCash => "assets/svg/coin_icons/EpicCash.svg";
|
||||
String get firo => "assets/svg/coin_icons/Firo.svg";
|
||||
String get monero => "assets/svg/coin_icons/Monero.svg";
|
||||
String get wownero => "assets/svg/coin_icons/Wownero.svg";
|
||||
String get namecoin => "assets/svg/coin_icons/Namecoin.svg";
|
||||
|
||||
String get chevronRight => "assets/svg/chevron-right.svg";
|
||||
|
@ -156,6 +157,8 @@ class _SVG {
|
|||
return firo;
|
||||
case Coin.monero:
|
||||
return monero;
|
||||
case Coin.wownero:
|
||||
return wownero;
|
||||
case Coin.namecoin:
|
||||
return namecoin;
|
||||
case Coin.bitcoinTestNet:
|
||||
|
@ -177,6 +180,7 @@ class _PNG {
|
|||
String get splash => "assets/images/splash.png";
|
||||
|
||||
String get monero => "assets/images/monero.png";
|
||||
String get wownero => "assets/images/wownero.png";
|
||||
String get firo => "assets/images/firo.png";
|
||||
String get dogecoin => "assets/images/doge.png";
|
||||
String get bitcoin => "assets/images/bitcoin.png";
|
||||
|
@ -203,6 +207,8 @@ class _PNG {
|
|||
return firo;
|
||||
case Coin.monero:
|
||||
return monero;
|
||||
case Coin.wownero:
|
||||
return wownero;
|
||||
case Coin.namecoin:
|
||||
return namecoin;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ Uri getBlockExplorerTransactionUrlFor({
|
|||
throw UnimplementedError("missing block explorer for epic cash");
|
||||
case Coin.monero:
|
||||
return Uri.parse("https://xmrchain.net/tx/$txid");
|
||||
case Coin.wownero:
|
||||
return Uri.parse("https://explore.wownero.com/search?value=$txid");
|
||||
case Coin.firo:
|
||||
return Uri.parse("https://explorer.firo.org/tx/$txid");
|
||||
case Coin.firoTestNet:
|
||||
|
|
|
@ -18,6 +18,7 @@ abstract class Constants {
|
|||
|
||||
//TODO: correct for monero?
|
||||
static const int satsPerCoinMonero = 1000000000000;
|
||||
static const int satsPerCoinWownero = 100000000000;
|
||||
static const int satsPerCoin = 100000000;
|
||||
static const int decimalPlaces = 8;
|
||||
|
||||
|
@ -54,6 +55,9 @@ abstract class Constants {
|
|||
case Coin.monero:
|
||||
values.addAll([25]);
|
||||
break;
|
||||
case Coin.wownero:
|
||||
values.addAll([14]);
|
||||
break;
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
@ -83,6 +87,9 @@ abstract class Constants {
|
|||
case Coin.monero:
|
||||
return 120;
|
||||
|
||||
case Coin.wownero:
|
||||
return 120;
|
||||
|
||||
case Coin.namecoin:
|
||||
return 600;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ abstract class DefaultNodes {
|
|||
epicCash,
|
||||
bitcoincash,
|
||||
namecoin,
|
||||
wownero,
|
||||
bitcoinTestnet,
|
||||
bitcoincashTestnet,
|
||||
dogecoinTestnet,
|
||||
|
@ -83,6 +84,20 @@ abstract class DefaultNodes {
|
|||
isDown: false,
|
||||
);
|
||||
|
||||
// TODO: eventually enable ssl and set scheme to https
|
||||
// currently get certificate failure
|
||||
static NodeModel get wownero => NodeModel(
|
||||
host: "http://eu-west-2.wow.xmr.pm",
|
||||
port: 34568,
|
||||
name: defaultName,
|
||||
id: _nodeId(Coin.wownero),
|
||||
useSSL: false,
|
||||
enabled: true,
|
||||
coinName: Coin.wownero.name,
|
||||
isFailover: true,
|
||||
isDown: false,
|
||||
);
|
||||
|
||||
static NodeModel get epicCash => NodeModel(
|
||||
host: "http://epiccash.stackwallet.com",
|
||||
port: 3413,
|
||||
|
@ -175,6 +190,9 @@ abstract class DefaultNodes {
|
|||
case Coin.monero:
|
||||
return monero;
|
||||
|
||||
case Coin.wownero:
|
||||
return wownero;
|
||||
|
||||
case Coin.namecoin:
|
||||
return namecoin;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import 'package:stackwallet/services/coins/firo/firo_wallet.dart' as firo;
|
|||
import 'package:stackwallet/services/coins/monero/monero_wallet.dart' as xmr;
|
||||
import 'package:stackwallet/services/coins/namecoin/namecoin_wallet.dart'
|
||||
as nmc;
|
||||
import 'package:stackwallet/services/coins/wownero/wownero_wallet.dart' as wow;
|
||||
|
||||
enum Coin {
|
||||
bitcoin,
|
||||
|
@ -17,6 +18,7 @@ enum Coin {
|
|||
epicCash,
|
||||
firo,
|
||||
monero,
|
||||
wownero,
|
||||
namecoin,
|
||||
|
||||
///
|
||||
|
@ -47,6 +49,8 @@ extension CoinExt on Coin {
|
|||
return "Firo";
|
||||
case Coin.monero:
|
||||
return "Monero";
|
||||
case Coin.wownero:
|
||||
return "Wownero";
|
||||
case Coin.namecoin:
|
||||
return "Namecoin";
|
||||
case Coin.bitcoinTestNet:
|
||||
|
@ -74,6 +78,8 @@ extension CoinExt on Coin {
|
|||
return "FIRO";
|
||||
case Coin.monero:
|
||||
return "XMR";
|
||||
case Coin.wownero:
|
||||
return "WOW";
|
||||
case Coin.namecoin:
|
||||
return "NMC";
|
||||
case Coin.bitcoinTestNet:
|
||||
|
@ -102,6 +108,8 @@ extension CoinExt on Coin {
|
|||
return "firo";
|
||||
case Coin.monero:
|
||||
return "monero";
|
||||
case Coin.wownero:
|
||||
return "wownero";
|
||||
case Coin.namecoin:
|
||||
return "namecoin";
|
||||
case Coin.bitcoinTestNet:
|
||||
|
@ -130,6 +138,7 @@ extension CoinExt on Coin {
|
|||
|
||||
case Coin.epicCash:
|
||||
case Coin.monero:
|
||||
case Coin.wownero:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -157,6 +166,10 @@ extension CoinExt on Coin {
|
|||
|
||||
case Coin.monero:
|
||||
return xmr.MINIMUM_CONFIRMATIONS;
|
||||
|
||||
case Coin.wownero:
|
||||
return wow.MINIMUM_CONFIRMATIONS;
|
||||
|
||||
case Coin.namecoin:
|
||||
return nmc.MINIMUM_CONFIRMATIONS;
|
||||
}
|
||||
|
@ -204,6 +217,10 @@ Coin coinFromPrettyName(String name) {
|
|||
case "tDogecoin":
|
||||
case "dogecoinTestNet":
|
||||
return Coin.dogecoinTestNet;
|
||||
case "Wownero":
|
||||
case "tWownero":
|
||||
case "wownero":
|
||||
return Coin.wownero;
|
||||
default:
|
||||
throw ArgumentError.value(
|
||||
name, "name", "No Coin enum value with that prettyName");
|
||||
|
@ -234,6 +251,8 @@ Coin coinFromTickerCaseInsensitive(String ticker) {
|
|||
return Coin.firoTestNet;
|
||||
case "tdoge":
|
||||
return Coin.dogecoinTestNet;
|
||||
case "wow":
|
||||
return Coin.wownero;
|
||||
default:
|
||||
throw ArgumentError.value(
|
||||
ticker, "name", "No Coin enum value with that ticker");
|
||||
|
|
|
@ -209,8 +209,8 @@ class CoinThemeColor {
|
|||
return monero;
|
||||
case Coin.namecoin:
|
||||
return namecoin;
|
||||
// case Coin.wownero:
|
||||
// return wownero;
|
||||
case Coin.wownero:
|
||||
return wownero;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1422,8 +1422,8 @@ class StackColors extends ThemeExtension<StackColors> {
|
|||
return _coin.monero;
|
||||
case Coin.namecoin:
|
||||
return _coin.namecoin;
|
||||
// case Coin.wownero:
|
||||
// return wownero;
|
||||
case Coin.wownero:
|
||||
return _coin.wownero;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -85,6 +85,7 @@ class NodeOptionsSheet extends ConsumerWidget {
|
|||
break;
|
||||
|
||||
case Coin.monero:
|
||||
case Coin.wownero:
|
||||
try {
|
||||
final uri = Uri.parse(node.host);
|
||||
if (uri.scheme.startsWith("http")) {
|
||||
|
|
|
@ -172,7 +172,9 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
|
|||
builder: (_) {
|
||||
final amount = coin == Coin.monero
|
||||
? (_transaction.amount ~/ 10000)
|
||||
: _transaction.amount;
|
||||
: coin == Coin.wownero
|
||||
? (_transaction.amount ~/ 1000)
|
||||
: _transaction.amount;
|
||||
return Text(
|
||||
"${Format.satoshiAmountToPrettyString(amount, locale)} ${coin.ticker}",
|
||||
style:
|
||||
|
@ -212,6 +214,8 @@ class _TransactionCardState extends ConsumerState<TransactionCard> {
|
|||
int value = _transaction.amount;
|
||||
if (coin == Coin.monero) {
|
||||
value = (value ~/ 10000);
|
||||
} else if (coin == Coin.wownero) {
|
||||
value = (value ~/ 1000);
|
||||
}
|
||||
|
||||
return Text(
|
||||
|
|
|
@ -317,6 +317,13 @@ packages:
|
|||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
cw_wownero:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "crypto_plugins/flutter_libmonero/cw_wownero"
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
dart_numerics:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -11,7 +11,7 @@ description: Stack Wallet
|
|||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
||||
# Read more about iOS versioning at
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
version: 1.4.50+65
|
||||
version: 1.4.52+68
|
||||
|
||||
environment:
|
||||
sdk: ">=2.17.0 <3.0.0"
|
||||
|
@ -31,6 +31,9 @@ dependencies:
|
|||
cw_monero:
|
||||
path: ./crypto_plugins/flutter_libmonero/cw_monero
|
||||
|
||||
cw_wownero:
|
||||
path: ./crypto_plugins/flutter_libmonero/cw_wownero
|
||||
|
||||
cw_core:
|
||||
path: ./crypto_plugins/flutter_libmonero/cw_core
|
||||
|
||||
|
@ -189,6 +192,7 @@ flutter:
|
|||
- assets/svg/clipboard.svg
|
||||
- assets/images/stack.png
|
||||
- assets/images/monero.png
|
||||
- assets/images/wownero.png
|
||||
- assets/images/firo.png
|
||||
- assets/images/doge.png
|
||||
- assets/images/bitcoin.png
|
||||
|
@ -292,6 +296,7 @@ flutter:
|
|||
- assets/svg/coin_icons/EpicCash.svg
|
||||
- assets/svg/coin_icons/Firo.svg
|
||||
- assets/svg/coin_icons/Monero.svg
|
||||
- assets/svg/coin_icons/Wownero.svg
|
||||
- assets/svg/coin_icons/Namecoin.svg
|
||||
# lottie animations
|
||||
- assets/lottie/test.json
|
||||
|
|
|
@ -23,7 +23,7 @@ void main() {
|
|||
|
||||
when(client.get(
|
||||
Uri.parse(
|
||||
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
|
||||
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin,wownero&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
})).thenAnswer((_) async => Response(
|
||||
|
@ -36,10 +36,10 @@ void main() {
|
|||
final price = await priceAPI.getPricesAnd24hChange(baseCurrency: "btc");
|
||||
|
||||
expect(price.toString(),
|
||||
'{Coin.bitcoin: [1, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0.00000315, -2.68533], Coin.epicCash: [0.00002803, 7.27524], Coin.firo: [0.0001096, -0.89304], Coin.monero: [0.00717236, -0.77656], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
|
||||
'{Coin.bitcoin: [1, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0.00000315, -2.68533], Coin.epicCash: [0.00002803, 7.27524], Coin.firo: [0.0001096, -0.89304], Coin.monero: [0.00717236, -0.77656], Coin.wownero: [0, 0.0], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
|
||||
verify(client.get(
|
||||
Uri.parse(
|
||||
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
|
||||
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin,wownero&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
|
||||
headers: {'Content-Type': 'application/json'})).called(1);
|
||||
|
||||
verifyNoMoreInteractions(client);
|
||||
|
@ -50,7 +50,7 @@ void main() {
|
|||
|
||||
when(client.get(
|
||||
Uri.parse(
|
||||
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
|
||||
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin,wownero&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
})).thenAnswer((_) async => Response(
|
||||
|
@ -68,12 +68,12 @@ void main() {
|
|||
await priceAPI.getPricesAnd24hChange(baseCurrency: "btc");
|
||||
|
||||
expect(cachedPrice.toString(),
|
||||
'{Coin.bitcoin: [1, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0.00000315, -2.68533], Coin.epicCash: [0.00002803, 7.27524], Coin.firo: [0.0001096, -0.89304], Coin.monero: [0.00717236, -0.77656], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
|
||||
'{Coin.bitcoin: [1, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0.00000315, -2.68533], Coin.epicCash: [0.00002803, 7.27524], Coin.firo: [0.0001096, -0.89304], Coin.monero: [0.00717236, -0.77656], Coin.wownero: [0, 0.0], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
|
||||
|
||||
// verify only called once during filling of cache
|
||||
verify(client.get(
|
||||
Uri.parse(
|
||||
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
|
||||
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin,wownero&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
|
||||
headers: {'Content-Type': 'application/json'})).called(1);
|
||||
|
||||
verifyNoMoreInteractions(client);
|
||||
|
@ -84,7 +84,7 @@ void main() {
|
|||
|
||||
when(client.get(
|
||||
Uri.parse(
|
||||
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
|
||||
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin,wownero&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
})).thenAnswer((_) async => Response(
|
||||
|
@ -97,7 +97,7 @@ void main() {
|
|||
final price = await priceAPI.getPricesAnd24hChange(baseCurrency: "btc");
|
||||
|
||||
expect(price.toString(),
|
||||
'{Coin.bitcoin: [0, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0, 0.0], Coin.epicCash: [0, 0.0], Coin.firo: [0, 0.0], Coin.monero: [0, 0.0], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
|
||||
'{Coin.bitcoin: [0, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0, 0.0], Coin.epicCash: [0, 0.0], Coin.firo: [0, 0.0], Coin.monero: [0, 0.0], Coin.wownero: [0, 0.0], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
|
||||
});
|
||||
|
||||
test("no internet available", () async {
|
||||
|
@ -105,7 +105,7 @@ void main() {
|
|||
|
||||
when(client.get(
|
||||
Uri.parse(
|
||||
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
|
||||
"https://api.coingecko.com/api/v3/coins/markets?vs_currency=btc&ids=monero,bitcoin,epic-cash,zcoin,dogecoin,bitcoin-cash,namecoin,wownero&order=market_cap_desc&per_page=10&page=1&sparkline=false"),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
})).thenThrow(const SocketException(
|
||||
|
@ -117,7 +117,7 @@ void main() {
|
|||
final price = await priceAPI.getPricesAnd24hChange(baseCurrency: "btc");
|
||||
|
||||
expect(price.toString(),
|
||||
'{Coin.bitcoin: [0, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0, 0.0], Coin.epicCash: [0, 0.0], Coin.firo: [0, 0.0], Coin.monero: [0, 0.0], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
|
||||
'{Coin.bitcoin: [0, 0.0], Coin.bitcoincash: [0, 0.0], Coin.dogecoin: [0, 0.0], Coin.epicCash: [0, 0.0], Coin.firo: [0, 0.0], Coin.monero: [0, 0.0], Coin.wownero: [0, 0.0], Coin.namecoin: [0, 0.0], Coin.bitcoinTestNet: [0, 0.0], Coin.bitcoincashTestnet: [0, 0.0], Coin.dogecoinTestNet: [0, 0.0], Coin.firoTestNet: [0, 0.0]}');
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
|
|
Loading…
Reference in a new issue