2023-05-26 21:21:16 +00:00
/ *
* 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
*
* /
2022-08-26 08:11:35 +00:00
import ' package:stackwallet/electrumx_rpc/cached_electrumx.dart ' ;
import ' package:stackwallet/electrumx_rpc/electrumx.dart ' ;
2023-01-11 18:21:11 +00:00
import ' package:stackwallet/models/balance.dart ' ;
import ' package:stackwallet/models/isar/models/isar_models.dart ' as isar_models ;
2022-08-26 08:11:35 +00:00
import ' package:stackwallet/models/node_model.dart ' ;
2023-01-11 18:21:11 +00:00
import ' package:stackwallet/models/paymint/fee_object_model.dart ' ;
2022-08-26 08:11:35 +00:00
import ' package:stackwallet/services/coins/bitcoin/bitcoin_wallet.dart ' ;
2022-09-26 20:32:53 +00:00
import ' package:stackwallet/services/coins/bitcoincash/bitcoincash_wallet.dart ' ;
2022-08-26 08:11:35 +00:00
import ' package:stackwallet/services/coins/dogecoin/dogecoin_wallet.dart ' ;
2023-04-17 13:53:39 +00:00
import ' package:stackwallet/services/coins/ecash/ecash_wallet.dart ' ;
2022-08-26 08:11:35 +00:00
import ' package:stackwallet/services/coins/epiccash/epiccash_wallet.dart ' ;
2022-12-13 17:39:19 +00:00
import ' package:stackwallet/services/coins/ethereum/ethereum_wallet.dart ' ;
2022-08-26 08:11:35 +00:00
import ' package:stackwallet/services/coins/firo/firo_wallet.dart ' ;
2023-01-11 18:21:11 +00:00
import ' package:stackwallet/services/coins/litecoin/litecoin_wallet.dart ' ;
2022-08-26 08:11:35 +00:00
import ' package:stackwallet/services/coins/monero/monero_wallet.dart ' ;
2022-09-23 21:02:53 +00:00
import ' package:stackwallet/services/coins/namecoin/namecoin_wallet.dart ' ;
2023-05-30 23:19:31 +00:00
import ' package:stackwallet/services/coins/nano/banano_wallet.dart ' ;
2023-05-19 10:20:16 +00:00
import ' package:stackwallet/services/coins/nano/nano_wallet.dart ' ;
2022-11-29 19:11:30 +00:00
import ' package:stackwallet/services/coins/particl/particl_wallet.dart ' ;
2022-11-07 16:24:08 +00:00
import ' package:stackwallet/services/coins/wownero/wownero_wallet.dart ' ;
2022-08-26 08:11:35 +00:00
import ' package:stackwallet/services/transaction_notification_tracker.dart ' ;
2023-04-06 21:24:56 +00:00
import ' package:stackwallet/utilities/amount/amount.dart ' ;
2022-08-26 08:11:35 +00:00
import ' package:stackwallet/utilities/enums/coin_enum.dart ' ;
2022-11-09 22:43:26 +00:00
import ' package:stackwallet/utilities/flutter_secure_storage_interface.dart ' ;
2022-08-26 08:11:35 +00:00
import ' package:stackwallet/utilities/prefs.dart ' ;
2023-05-26 19:25:59 +00:00
/ *
* This file implements the CoinServiceAPI abstract class that is used by wallet files to implement the coin specific functionality .
* @ param coin: The coin type
* @ param walletId: The wallet id
* @ param walletName: The wallet name
* @ param secureStorageInterface: The interface for securely storing data like private keys , mnemonics , passphrases , etc .
* @ param node: The node to connect to
* @ param tracker: The transaction notification tracker
* @ param prefs: The preferences
* @ return : The coin service API
* /
2022-08-26 08:11:35 +00:00
abstract class CoinServiceAPI {
CoinServiceAPI ( ) ;
factory CoinServiceAPI . from (
Coin coin ,
String walletId ,
String walletName ,
2022-11-09 23:48:43 +00:00
SecureStorageInterface secureStorageInterface ,
2022-08-26 08:11:35 +00:00
NodeModel node ,
TransactionNotificationTracker tracker ,
Prefs prefs ,
List < NodeModel > failovers ,
) {
final electrumxNode = ElectrumXNode (
address: node . host ,
port: node . port ,
name: node . name ,
id: node . id ,
useSSL: node . useSSL ,
) ;
final client = ElectrumX . from (
node: electrumxNode ,
failovers: failovers
. map ( ( e ) = > ElectrumXNode (
address: e . host ,
port: e . port ,
name: e . name ,
id: e . id ,
useSSL: e . useSSL ,
) )
. toList ( ) ,
prefs: prefs ,
) ;
final cachedClient = CachedElectrumX . from (
2023-05-25 20:37:18 +00:00
electrumXClient: client ,
2022-08-26 08:11:35 +00:00
) ;
switch ( coin ) {
case Coin . firo:
return FiroWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
2022-11-09 22:43:26 +00:00
secureStore: secureStorageInterface ,
2022-08-26 08:11:35 +00:00
client: client ,
cachedClient: cachedClient ,
tracker: tracker ,
) ;
case Coin . firoTestNet:
return FiroWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
2022-11-09 22:43:26 +00:00
secureStore: secureStorageInterface ,
2022-08-26 08:11:35 +00:00
client: client ,
cachedClient: cachedClient ,
tracker: tracker ,
) ;
case Coin . bitcoin:
return BitcoinWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
2022-11-09 22:43:26 +00:00
secureStore: secureStorageInterface ,
2022-08-26 08:11:35 +00:00
client: client ,
cachedClient: cachedClient ,
2022-10-28 18:03:52 +00:00
tracker: tracker ,
) ;
case Coin . litecoin:
return LitecoinWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
2022-11-09 22:43:26 +00:00
secureStore: secureStorageInterface ,
2022-10-28 18:03:52 +00:00
client: client ,
cachedClient: cachedClient ,
tracker: tracker ,
) ;
case Coin . litecoinTestNet:
return LitecoinWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
2022-11-09 22:43:26 +00:00
secureStore: secureStorageInterface ,
2022-10-28 18:03:52 +00:00
client: client ,
cachedClient: cachedClient ,
2022-08-26 08:11:35 +00:00
tracker: tracker ,
) ;
case Coin . bitcoinTestNet:
return BitcoinWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
2022-11-09 22:43:26 +00:00
secureStore: secureStorageInterface ,
2022-08-26 08:11:35 +00:00
client: client ,
cachedClient: cachedClient ,
tracker: tracker ,
) ;
2022-09-26 20:32:53 +00:00
case Coin . bitcoincash:
return BitcoinCashWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
2022-11-09 22:43:26 +00:00
secureStore: secureStorageInterface ,
2022-09-26 20:32:53 +00:00
client: client ,
cachedClient: cachedClient ,
tracker: tracker ,
) ;
case Coin . bitcoincashTestnet:
return BitcoinCashWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
2022-11-09 22:43:26 +00:00
secureStore: secureStorageInterface ,
2022-09-26 20:32:53 +00:00
client: client ,
cachedClient: cachedClient ,
tracker: tracker ,
) ;
2022-09-16 11:13:30 +00:00
2022-08-26 08:11:35 +00:00
case Coin . dogecoin:
return DogecoinWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
2022-11-09 22:43:26 +00:00
secureStore: secureStorageInterface ,
2022-08-26 08:11:35 +00:00
client: client ,
cachedClient: cachedClient ,
tracker: tracker ,
) ;
case Coin . epicCash:
return EpicCashWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
2022-11-09 22:43:26 +00:00
secureStore: secureStorageInterface ,
2022-08-26 08:11:35 +00:00
// tracker: tracker,
) ;
2022-12-13 17:39:19 +00:00
case Coin . ethereum:
return EthereumWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
secureStore: secureStorageInterface ,
2023-01-08 15:19:58 +00:00
tracker: tracker ,
2022-12-13 17:39:19 +00:00
) ;
2022-08-26 08:11:35 +00:00
case Coin . monero:
return MoneroWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
2022-12-28 16:25:55 +00:00
secureStorage: secureStorageInterface ,
2022-08-26 08:11:35 +00:00
// tracker: tracker,
) ;
2022-11-29 19:11:30 +00:00
case Coin . particl:
return ParticlWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
2022-11-29 19:40:51 +00:00
secureStore: secureStorageInterface ,
2022-11-29 19:11:30 +00:00
client: client ,
cachedClient: cachedClient ,
tracker: tracker ) ;
2022-09-27 08:09:31 +00:00
case Coin . wownero:
return WowneroWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
2022-12-30 22:15:03 +00:00
secureStorage: secureStorageInterface ,
2022-09-27 08:09:31 +00:00
// tracker: tracker,
) ;
2022-09-23 21:02:53 +00:00
case Coin . namecoin:
return NamecoinWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
2022-11-09 22:43:26 +00:00
secureStore: secureStorageInterface ,
2022-09-23 21:02:53 +00:00
tracker: tracker ,
cachedClient: cachedClient ,
client: client ,
) ;
2022-09-12 12:01:42 +00:00
2023-05-19 10:20:16 +00:00
case Coin . nano:
return NanoWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
tracker: tracker ,
secureStore: secureStorageInterface
) ;
2023-05-30 23:19:31 +00:00
case Coin . banano:
return BananoWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
tracker: tracker ,
secureStore: secureStorageInterface
) ;
2022-08-26 08:11:35 +00:00
case Coin . dogecoinTestNet:
return DogecoinWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
2022-11-09 22:43:26 +00:00
secureStore: secureStorageInterface ,
2023-04-17 13:53:39 +00:00
client: client ,
cachedClient: cachedClient ,
tracker: tracker ,
) ;
case Coin . eCash:
return ECashWallet (
walletId: walletId ,
walletName: walletName ,
coin: coin ,
secureStore: secureStorageInterface ,
2022-08-26 08:11:35 +00:00
client: client ,
cachedClient: cachedClient ,
tracker: tracker ,
) ;
}
}
Coin get coin ;
bool get isRefreshing ;
bool get shouldAutoSync ;
set shouldAutoSync ( bool shouldAutoSync ) ;
bool get isFavorite ;
set isFavorite ( bool markFavorite ) ;
Future < Map < String , dynamic > > prepareSend ( {
required String address ,
2023-04-05 22:06:31 +00:00
required Amount amount ,
2022-08-26 08:11:35 +00:00
Map < String , dynamic > ? args ,
} ) ;
Future < String > confirmSend ( { required Map < String , dynamic > txData } ) ;
Future < FeeObject > get fees ;
Future < int > get maxFee ;
Future < String > get currentReceivingAddress ;
2023-01-11 18:21:11 +00:00
Balance get balance ;
2022-08-26 08:11:35 +00:00
2023-01-11 18:21:11 +00:00
Future < List < isar_models . Transaction > > get transactions ;
Future < List < isar_models . UTXO > > get utxos ;
2022-08-26 08:11:35 +00:00
Future < void > refresh ( ) ;
Future < void > updateNode ( bool shouldRefresh ) ;
// setter for updating on rename
set walletName ( String newName ) ;
String get walletName ;
String get walletId ;
bool validateAddress ( String address ) ;
Future < List < String > > get mnemonic ;
2023-02-03 22:34:06 +00:00
Future < String ? > get mnemonicString ;
Future < String ? > get mnemonicPassphrase ;
2022-08-26 08:11:35 +00:00
Future < bool > testNetworkConnection ( ) ;
Future < void > recoverFromMnemonic ( {
required String mnemonic ,
2023-02-03 22:34:06 +00:00
String ? mnemonicPassphrase ,
2022-08-26 08:11:35 +00:00
required int maxUnusedAddressGap ,
required int maxNumberOfIndexesToCheck ,
required int height ,
} ) ;
Future < void > initializeNew ( ) ;
Future < void > initializeExisting ( ) ;
Future < void > exit ( ) ;
bool get hasCalledExit ;
Future < void > fullRescan (
int maxUnusedAddressGap , int maxNumberOfIndexesToCheck ) ;
void Function ( bool isActive ) ? onIsActiveWalletChanged ;
bool get isConnected ;
2023-04-05 22:06:31 +00:00
Future < Amount > estimateFeeFor ( Amount amount , int feeRate ) ;
2022-09-06 01:18:45 +00:00
Future < bool > generateNewAddress ( ) ;
2022-11-07 16:24:08 +00:00
// used for electrumx coins
Future < void > updateSentCachedTxData ( Map < String , dynamic > txData ) ;
2023-01-05 16:50:36 +00:00
2023-01-10 23:50:22 +00:00
int get storedChainHeight ;
2023-01-20 21:30:48 +00:00
2023-01-05 16:50:36 +00:00
// Certain outputs return address as an array/list of strings like List<String> ["addresses"][0], some return it as a string like String ["address"]
String ? getAddress ( dynamic output ) {
2023-01-06 17:15:32 +00:00
// Julian's code from https://github.com/cypherstack/stack_wallet/blob/35a8172d35f1b5cdbd22f0d56c4db02f795fd032/lib/services/coins/coin_paynym_extension.dart#L170 wins codegolf for this, I'd love to commit it now but need to retest this section ... should make unit tests for this case
// final String? address = output["scriptPubKey"]?["addresses"]?[0] as String? ?? output["scriptPubKey"]?["address"] as String?;
2023-01-05 16:50:36 +00:00
String ? address ;
if ( output . containsKey ( ' scriptPubKey ' ) as bool ) {
// Make sure the key exists before using it
if ( output [ " scriptPubKey " ] . containsKey ( ' address ' ) as bool ) {
address = output [ " scriptPubKey " ] [ " address " ] as String ? ;
} else if ( output [ " scriptPubKey " ] . containsKey ( ' addresses ' ) as bool ) {
address = output [ " scriptPubKey " ] [ " addresses " ] [ 0 ] as String ? ;
// TODO determine cases in which there are multiple addresses in the array
}
} / * else {
// TODO detect cases in which no scriptPubKey exists
Logging . instance . log ( " output type not detected; output: ${ output } " ,
level: LogLevel . Info ) ;
} * /
return address ;
}
2023-01-05 18:13:54 +00:00
// Firo wants an array/list of address strings like List<String>
List ? getAddresses ( dynamic output ) {
2023-01-06 17:15:32 +00:00
// Inspired by Julian's code as referenced above, need to test before committing
// final List? addresses = output["scriptPubKey"]?["addresses"] as List? ?? [output["scriptPubKey"]?["address"]] as List?;
2023-01-05 18:13:54 +00:00
List ? addresses ;
if ( output . containsKey ( ' scriptPubKey ' ) as bool ) {
if ( output [ " scriptPubKey " ] . containsKey ( ' addresses ' ) as bool ) {
addresses = output [ " scriptPubKey " ] [ " addresses " ] as List ? ;
} else if ( output [ " scriptPubKey " ] . containsKey ( ' address ' ) as bool ) {
addresses = [ output [ " scriptPubKey " ] [ " address " ] ] ;
}
} / * else {
// TODO detect cases in which no scriptPubKey exists
Logging . instance . log ( " output type not detected; output: ${ output } " ,
level: LogLevel . Info ) ;
} * /
return addresses ;
}
2022-08-26 08:11:35 +00:00
}