diff --git a/assets/default_themes/dark.zip b/assets/default_themes/dark.zip index 2d8b45286..fe11a5463 100644 Binary files a/assets/default_themes/dark.zip and b/assets/default_themes/dark.zip differ diff --git a/assets/default_themes/light.zip b/assets/default_themes/light.zip index be20673a9..1453d6ba0 100644 Binary files a/assets/default_themes/light.zip and b/assets/default_themes/light.zip differ diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart index e7ce8b505..56b008093 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart @@ -197,6 +197,7 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> { case Coin.nano: case Coin.banano: case Coin.stellar: + case Coin.stellarTestnet: throw UnimplementedError(); //TODO: check network/node } @@ -739,6 +740,7 @@ class _NodeFormState extends ConsumerState<NodeForm> { case Coin.banano: case Coin.eCash: case Coin.stellar: + case Coin.stellarTestnet: return false; case Coin.ethereum: diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart index 819b9f5d7..59ff1efad 100644 --- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart +++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/node_details_view.dart @@ -173,6 +173,7 @@ class _NodeDetailsViewState extends ConsumerState<NodeDetailsView> { case Coin.nano: case Coin.banano: case Coin.stellar: + case Coin.stellarTestnet: throw UnimplementedError(); //TODO: check network/node } diff --git a/lib/services/coins/coin_service.dart b/lib/services/coins/coin_service.dart index ffb97a0a7..5aa6e382d 100644 --- a/lib/services/coins/coin_service.dart +++ b/lib/services/coins/coin_service.dart @@ -285,6 +285,15 @@ abstract class CoinServiceAPI { cachedClient: cachedClient, tracker: tracker, ); + + case Coin.stellarTestnet: + return StellarWallet( + walletId: walletId, + walletName: walletName, + coin: coin, + secureStore: secureStorageInterface, + tracker: tracker, + ); } } diff --git a/lib/services/coins/stellar/stellar_wallet.dart b/lib/services/coins/stellar/stellar_wallet.dart index c1fe652b6..1dd8eae77 100644 --- a/lib/services/coins/stellar/stellar_wallet.dart +++ b/lib/services/coins/stellar/stellar_wallet.dart @@ -41,6 +41,9 @@ const int MINIMUM_CONFIRMATIONS = 1; class StellarWallet extends CoinServiceAPI with WalletCache, WalletDB, CoinControlInterface { + late StellarSDK stellarSdk; + late Network stellarNetwork; + StellarWallet({ required String walletId, required String walletName, @@ -56,12 +59,20 @@ class StellarWallet extends CoinServiceAPI _secureStore = secureStore; initCache(walletId, coin); initWalletDB(mockableOverride: mockableOverride); + + if (coin.name == "stellarTestnet") { + stellarSdk = StellarSDK.TESTNET; + stellarNetwork = Network.TESTNET; + } else { + stellarSdk = StellarSDK.PUBLIC; + stellarNetwork = Network.PUBLIC; + } } late final TransactionNotificationTracker txTracker; late SecureStorageInterface _secureStore; - final StellarSDK stellarSdk = StellarSDK.PUBLIC; + // final StellarSDK stellarSdk = StellarSDK.PUBLIC; @override bool get isFavorite => _isFavorite ??= getCachedIsFavorite(); @@ -199,7 +210,7 @@ class StellarWallet extends CoinServiceAPI .build() ).build(); } - transaction.sign(senderKeyPair, Network.PUBLIC); + transaction.sign(senderKeyPair, stellarNetwork); try { SubmitTransactionResponse response = await stellarSdk.submitTransaction(transaction); diff --git a/lib/themes/color_theme.dart b/lib/themes/color_theme.dart index 87020ada7..c78d35c11 100644 --- a/lib/themes/color_theme.dart +++ b/lib/themes/color_theme.dart @@ -28,7 +28,7 @@ class CoinThemeColorDefault { Color get namecoin => const Color(0xFF91B1E1); Color get wownero => const Color(0xFFED80C1); Color get particl => const Color(0xFF8175BD); - Color get stellar => const Color(0xFFE8E8E8); // TODO: find color + Color get stellar => const Color(0xFF6600FF); Color get nano => const Color(0xFF209CE9); Color get banano => const Color(0xFFFBDD11); @@ -64,6 +64,7 @@ class CoinThemeColorDefault { case Coin.particl: return particl; case Coin.stellar: + case Coin.stellarTestnet: return stellar; case Coin.nano: return nano; diff --git a/lib/themes/stack_colors.dart b/lib/themes/stack_colors.dart index f653b7eac..5dbd55fe1 100644 --- a/lib/themes/stack_colors.dart +++ b/lib/themes/stack_colors.dart @@ -1708,6 +1708,7 @@ class StackColors extends ThemeExtension<StackColors> { case Coin.particl: return _coin.particl; case Coin.stellar: + case Coin.stellarTestnet: return _coin.stellar; case Coin.nano: return _coin.nano; diff --git a/lib/utilities/address_utils.dart b/lib/utilities/address_utils.dart index c2e759524..8766d706a 100644 --- a/lib/utilities/address_utils.dart +++ b/lib/utilities/address_utils.dart @@ -141,6 +141,8 @@ class AddressUtils { return Address.validateAddress(address, firoTestNetwork); case Coin.dogecoinTestNet: return Address.validateAddress(address, dogecointestnet); + case Coin.stellarTestnet: + return RegExp(r"^[G][A-Z0-9]{55}$").hasMatch(address); } } diff --git a/lib/utilities/amount/amount_unit.dart b/lib/utilities/amount/amount_unit.dart index 37939f1cc..ccdd4e095 100644 --- a/lib/utilities/amount/amount_unit.dart +++ b/lib/utilities/amount/amount_unit.dart @@ -51,6 +51,7 @@ enum AmountUnit { case Coin.eCash: case Coin.epicCash: case Coin.stellar: // TODO: check if this is correct + case Coin.stellarTestnet: return AmountUnit.values.sublist(0, 4); case Coin.monero: diff --git a/lib/utilities/block_explorers.dart b/lib/utilities/block_explorers.dart index ae27fae02..68c23479d 100644 --- a/lib/utilities/block_explorers.dart +++ b/lib/utilities/block_explorers.dart @@ -60,6 +60,8 @@ Uri getDefaultBlockExplorerUrlFor({ return Uri.parse("https://www.nanolooker.com/block/$txid"); case Coin.banano: return Uri.parse("https://www.bananolooker.com/block/$txid"); + case Coin.stellarTestnet: + return Uri.parse("https://horizon-testnet.stellar.org/transactions/$txid"); } } diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index 665ae3169..3e6f814a2 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -100,6 +100,7 @@ abstract class Constants { return _satsPerCoinECash; case Coin.stellar: + case Coin.stellarTestnet: return _satsPerCoinStellar; } } @@ -140,6 +141,7 @@ abstract class Constants { return _decimalPlacesECash; case Coin.stellar: + case Coin.stellarTestnet: return _decimalPlacesStellar; } } @@ -164,6 +166,7 @@ abstract class Constants { case Coin.particl: case Coin.nano: case Coin.stellar: + case Coin.stellarTestnet: values.addAll([24, 12]); break; case Coin.banano: @@ -225,6 +228,7 @@ abstract class Constants { return 1; case Coin.stellar: + case Coin.stellarTestnet: return 5; } } @@ -254,6 +258,7 @@ abstract class Constants { case Coin.nano: case Coin.banano: case Coin.stellar: + case Coin.stellarTestnet: return 24; case Coin.monero: diff --git a/lib/utilities/default_nodes.dart b/lib/utilities/default_nodes.dart index 6c8bf08e3..9a6a0d914 100644 --- a/lib/utilities/default_nodes.dart +++ b/lib/utilities/default_nodes.dart @@ -34,6 +34,7 @@ abstract class DefaultNodes { bitcoincashTestnet, dogecoinTestnet, firoTestnet, + stellarTestnet, ]; static NodeModel get bitcoin => NodeModel( @@ -275,6 +276,18 @@ abstract class DefaultNodes { isDown: false, ); + static NodeModel get stellarTestnet => NodeModel( + host: "https://horizon-testnet.stellar.org/", + port: 50022, + name: defaultName, + id: _nodeId(Coin.stellarTestnet), + useSSL: true, + enabled: true, + coinName: Coin.stellarTestnet.name, + isFailover: true, + isDown: false, + ); + static NodeModel getNodeFor(Coin coin) { switch (coin) { case Coin.bitcoin: @@ -336,6 +349,9 @@ abstract class DefaultNodes { case Coin.dogecoinTestNet: return dogecoinTestnet; + + case Coin.stellarTestnet: + return stellarTestnet; } } } diff --git a/lib/utilities/enums/coin_enum.dart b/lib/utilities/enums/coin_enum.dart index e66822738..677d474e7 100644 --- a/lib/utilities/enums/coin_enum.dart +++ b/lib/utilities/enums/coin_enum.dart @@ -58,6 +58,7 @@ enum Coin { dogecoinTestNet, firoTestNet, litecoinTestNet, + stellarTestnet, } final int kTestNetCoinCount = 4; // Util.isDesktop ? 5 : 4; @@ -106,6 +107,8 @@ extension CoinExt on Coin { return "tFiro"; case Coin.dogecoinTestNet: return "tDogecoin"; + case Coin.stellarTestnet: + return "tStellar"; } } @@ -151,6 +154,8 @@ extension CoinExt on Coin { return "tFIRO"; case Coin.dogecoinTestNet: return "tDOGE"; + case Coin.stellarTestnet: + return "tXLM"; } } @@ -197,6 +202,8 @@ extension CoinExt on Coin { return "firo"; case Coin.dogecoinTestNet: return "dogecoin"; + case Coin.stellarTestnet: + return "stellar"; } } @@ -224,6 +231,7 @@ extension CoinExt on Coin { case Coin.nano: case Coin.banano: case Coin.stellar: + case Coin.stellarTestnet: return false; } } @@ -252,6 +260,7 @@ extension CoinExt on Coin { case Coin.nano: case Coin.banano: case Coin.stellar: + case Coin.stellarTestnet: return false; } } @@ -280,6 +289,7 @@ extension CoinExt on Coin { case Coin.litecoinTestNet: case Coin.bitcoincashTestnet: case Coin.firoTestNet: + case Coin.stellarTestnet: return true; } } @@ -317,6 +327,9 @@ extension CoinExt on Coin { case Coin.firoTestNet: return Coin.firo; + + case Coin.stellarTestnet: + return Coin.stellar; } } @@ -358,6 +371,7 @@ extension CoinExt on Coin { return particl.MINIMUM_CONFIRMATIONS; case Coin.stellar: + case Coin.stellarTestnet: return xlm.MINIMUM_CONFIRMATIONS; case Coin.wownero: @@ -467,6 +481,11 @@ Coin coinFromPrettyName(String name) { case "banano": return Coin.banano; + case "Stellar Testnet": + case "stellarTestnet": + case "tStellar": + return Coin.stellarTestnet; + default: throw ArgumentError.value( name, @@ -518,6 +537,8 @@ Coin coinFromTickerCaseInsensitive(String ticker) { return Coin.nano; case "ban": return Coin.banano; + case "txlm": + return Coin.stellarTestnet; default: throw ArgumentError.value( ticker, "name", "No Coin enum value with that ticker"); diff --git a/lib/utilities/enums/derive_path_type_enum.dart b/lib/utilities/enums/derive_path_type_enum.dart index 1dbd3f79b..07785a5ee 100644 --- a/lib/utilities/enums/derive_path_type_enum.dart +++ b/lib/utilities/enums/derive_path_type_enum.dart @@ -50,6 +50,7 @@ extension DerivePathTypeExt on DerivePathType { case Coin.nano: case Coin.banano: case Coin.stellar: + case Coin.stellarTestnet: throw UnsupportedError( "$coin does not use bitcoin style derivation paths"); } diff --git a/lib/widgets/node_card.dart b/lib/widgets/node_card.dart index b906320d3..57482119c 100644 --- a/lib/widgets/node_card.dart +++ b/lib/widgets/node_card.dart @@ -195,6 +195,7 @@ class _NodeCardState extends ConsumerState<NodeCard> { case Coin.nano: case Coin.banano: case Coin.stellar: + case Coin.stellarTestnet: throw UnimplementedError(); //TODO: check network/node } diff --git a/lib/widgets/node_options_sheet.dart b/lib/widgets/node_options_sheet.dart index f8b788fed..b55f818a2 100644 --- a/lib/widgets/node_options_sheet.dart +++ b/lib/widgets/node_options_sheet.dart @@ -178,6 +178,7 @@ class NodeOptionsSheet extends ConsumerWidget { case Coin.nano: case Coin.banano: case Coin.stellar: + case Coin.stellarTestnet: throw UnimplementedError(); //TODO: check network/node }