import 'dart:core'; import 'dart:core' as core; import 'dart:io'; import 'dart:math'; import 'package:cw_core/node.dart'; import 'package:cw_core/unspent_coins_info.dart'; import 'package:cw_core/wallet_base.dart'; import 'package:cw_core/wallet_credentials.dart'; import 'package:cw_core/wallet_info.dart'; import 'package:cw_core/wallet_service.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:cw_monero/monero_wallet.dart'; import 'package:flutter_libmonero/core/key_service.dart'; import 'package:flutter_libmonero/core/wallet_creation_service.dart'; import 'package:flutter_libmonero/monero/monero.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:hive/hive.dart'; import 'package:hive_test/hive_test.dart'; import 'package:mockito/annotations.dart'; import 'package:path_provider/path_provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:stackwallet/services/wallets.dart'; import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'; // TODO trim down to the minimum imports above import 'monero_wallet_test_data.dart'; //FlutterSecureStorage? storage; FakeSecureStorage? storage; WalletService? walletService; SharedPreferences? prefs; KeyService? keysStorage; MoneroWalletBase? walletBase; late WalletCreationService _walletCreationService; dynamic _walletInfoSource; Wallets? walletsService; String path = ''; String name = 'namee${Random().nextInt(10000000)}'; int nettype = 0; WalletType type = WalletType.monero; @GenerateMocks([]) void main() async { storage = FakeSecureStorage(); prefs = await SharedPreferences.getInstance(); keysStorage = KeyService(storage!); WalletInfo walletInfo = WalletInfo.external( id: '', name: '', type: type, isRecovery: false, restoreHeight: 0, date: DateTime.now(), path: '', address: '', dirPath: ''); late WalletCredentials credentials; WidgetsFlutterBinding.ensureInitialized(); Directory appDir = (await getApplicationDocumentsDirectory()); if (Platform.isIOS) { appDir = (await getLibraryDirectory()); } monero.onStartup(); bool hiveAdaptersRegistered = false; bool hiveAdaptersRegistered = false; group("Mnemonic recovery", () { setUp(() async { await setUpTestHive(); if (!hiveAdaptersRegistered) { hiveAdaptersRegistered = true; Hive.registerAdapter(NodeAdapter()); Hive.registerAdapter(WalletInfoAdapter()); Hive.registerAdapter(WalletTypeAdapter()); Hive.registerAdapter(UnspentCoinsInfoAdapter()); final wallets = await Hive.openBox('wallets'); await wallets.put('currentWalletName', name); _walletInfoSource = await Hive.openBox(WalletInfo.boxName); walletService = monero.createMoneroWalletService(_walletInfoSource); } try { // if (name?.isEmpty ?? true) { // name = await generateName(); // } final dirPath = await pathForWalletDir(name: name, type: type); path = await pathForWallet(name: name, type: type); credentials = // // creating a new wallet // monero.createMoneroNewWalletCredentials( // name: name, language: "English"); // restoring a previous wallet monero.createMoneroRestoreWalletFromSeedCredentials( name: name, height: 2580000, mnemonic: testMnemonic); walletInfo = WalletInfo.external( id: WalletBase.idFor(name, type), name: name, type: type, isRecovery: false, restoreHeight: credentials.height ?? 0, date: DateTime.now(), path: path, address: "", dirPath: dirPath); credentials.walletInfo = walletInfo; _walletCreationService = WalletCreationService( secureStorage: storage, sharedPreferences: prefs, walletService: walletService, keyService: keysStorage, ); _walletCreationService.changeWalletType(); } catch (e, s) { print(e); print(s); } }); test("Test address validation", () async { // TODO I'd like to refactor/separate this out so I can test addresses alone, without having to first create a wallet. final wallet = await _walletCreationService.restoreFromSeed(credentials); walletBase = wallet as MoneroWalletBase; expect( await walletBase!.validateAddress(''), false); expect( await walletBase!.validateAddress('4AeRgkWZsMJhAWKMeCZ3h4ZSPnAcW5VBtRFyLd6gBEf6GgJU2FHXDA6i1DnQTd6h8R3VU5AkbGcWSNhtSwNNPgaD48gp4nn'), true); expect( await walletBase!.validateAddress('4asdfkWZsMJhAWKMeCZ3h4ZSPnAcW5VBtRFyLd6gBEf6GgJU2FHXDA6i1DnQTd6h8R3VU5AkbGcWSNhtSwNNPgaD48gpjkl'), false); expect( await walletBase!.validateAddress('8AeRgkWZsMJhAWKMeCZ3h4ZSPnAcW5VBtRFyLd6gBEf6GgJU2FHXDA6i1DnQTd6h8R3VU5AkbGcWSNhtSwNNPgaD48gp4nn'), false); expect( await walletBase!.validateAddress('84kYPuZ1eaVKGQhf26QPNWbSLQG16BywXdLYYShVrPNMLAUAWce5vcpRc78FxwRphrG6Cda7faCKdUMr8fUCH3peHPenvHy'), true); expect( await walletBase!.validateAddress('8asdfuZ1eaVKGQhf26QPNWbSLQG16BywXdLYYShVrPNMLAUAWce5vcpRc78FxwRphrG6Cda7faCKdUMr8fUCH3peHPenjkl'), false); expect( await walletBase!.validateAddress('44kYPuZ1eaVKGQhf26QPNWbSLQG16BywXdLYYShVrPNMLAUAWce5vcpRc78FxwRphrG6Cda7faCKdUMr8fUCH3peHPenvHy'), false); }); test("Test mainnet address generation from seed", () async { final wallet = await // _walletCreationService.create(credentials); _walletCreationService.restoreFromSeed(credentials); walletInfo.address = wallet.walletAddresses.address; //print(walletInfo.address); await _walletInfoSource.add(walletInfo); walletBase?.close(); walletBase = wallet as MoneroWalletBase; //print("${walletBase?.seed}"); // print(walletBase); // loggerPrint(walletBase.toString()); // loggerPrint("name: ${walletBase!.name} seed: ${walletBase!.seed} id: " // "${walletBase!.id} walletinfo: ${toStringForinfo(walletBase!.walletInfo)} type: ${walletBase!.type} balance: " // "${walletBase!.balance.entries.first.value.available} currency: ${walletBase!.currency}"); expect(walletInfo.address, mainnetTestData[0][0]); expect( await walletBase!.getTransactionAddress(0, 0), mainnetTestData[0][0]); expect( await walletBase!.getTransactionAddress(0, 1), mainnetTestData[0][1]); expect( await walletBase!.getTransactionAddress(0, 2), mainnetTestData[0][2]); expect( await walletBase!.getTransactionAddress(1, 0), mainnetTestData[1][0]); expect( await walletBase!.getTransactionAddress(1, 1), mainnetTestData[1][1]); expect( await walletBase!.getTransactionAddress(1, 2), mainnetTestData[1][2]); }); }); /* // Not needed; only folder created, wallet files not saved yet. TODO test saving and deleting wallet files and make sure to clean up leftover folder afterwards group("Mainnet wallet deletion test", () { test("Test mainnet wallet existence", () { expect(monero_wallet_manager.isWalletExistSync(path: path), true); }); test("Test mainnet wallet deletion", () { // Remove wallet from wallet service walletService?.remove(name); walletsService?.removeWallet(walletId: name); expect(monero_wallet_manager.isWalletExistSync(path: path), false); }); }); group("Mainnet node tests", () { test("Test mainnet node connection", () async { await walletBase?.connectToNode( node: Node( uri: "monero-stagenet.stackwallet.com:38081", type: WalletType.moneroStageNet)); await walletBase!.rescan( height: credentials.height); // Probably shouldn't be rescanning from 0... await walletBase!.getNodeHeight(); int height = await walletBase!.getNodeHeight(); print('height: $height'); bool connected = await walletBase!.isConnected(); print('connected: $connected'); //expect... }); }); */ // TODO test deletion of wallets ... and delete them } Future pathForWalletDir( {required String name, required WalletType type}) async { Directory root = (await getApplicationDocumentsDirectory()); if (Platform.isIOS) { root = (await getLibraryDirectory()); } final prefix = walletTypeToString(type).toLowerCase(); final walletsDir = Directory('${root.path}/wallets'); final walletDire = Directory('${walletsDir.path}/$prefix/$name'); if (!walletDire.existsSync()) { walletDire.createSync(recursive: true); } return walletDire.path; } Future pathForWallet( {required String name, required WalletType type}) async => await pathForWalletDir(name: name, type: type) .then((path) => path + '/$name');