diff --git a/lib/services/coins/firo/firo_wallet.dart b/lib/services/coins/firo/firo_wallet.dart index ea21721f5..a88f37996 100644 --- a/lib/services/coins/firo/firo_wallet.dart +++ b/lib/services/coins/firo/firo_wallet.dart @@ -3133,7 +3133,7 @@ class FiroWallet extends CoinServiceAPI { } final scripthash = AddressUtils.convertToScriptHash(allAddresses[i], _network); - final id = const Uuid().v1(); + final id = Logger.isTestEnv ? "$i" : const Uuid().v1(); requestIdToAddressMap[id] = allAddresses[i]; batches[batchNumber]!.addAll({ id: [scripthash] diff --git a/test/services/coins/firo/firo_wallet_test.dart b/test/services/coins/firo/firo_wallet_test.dart index dacb8883b..b309044b8 100644 --- a/test/services/coins/firo/firo_wallet_test.dart +++ b/test/services/coins/firo/firo_wallet_test.dart @@ -26,6 +26,7 @@ import 'firo_wallet_test.mocks.dart'; import 'firo_wallet_test_parameters.dart'; import 'sample_data/get_anonymity_set_sample_data.dart'; import 'sample_data/get_used_serials_sample_data.dart'; +import 'sample_data/get_utxos_sample_data.dart'; import 'sample_data/gethistory_samples.dart'; import 'sample_data/transaction_data_samples.dart'; @@ -1010,15 +1011,8 @@ void main() { "f4217364cbe6a81ef7ecaaeba0a6d6b576a9850b3e891fa7b88ed4927c505218")) .thenAnswer((realInvocation) => true); - // mock history calls - when(client.getHistory(scripthash: SampleGetHistoryData.scripthash0)) - .thenAnswer((_) async => SampleGetHistoryData.data0); - when(client.getHistory(scripthash: SampleGetHistoryData.scripthash1)) - .thenAnswer((_) async => SampleGetHistoryData.data1); - when(client.getHistory(scripthash: SampleGetHistoryData.scripthash2)) - .thenAnswer((_) async => SampleGetHistoryData.data2); - when(client.getHistory(scripthash: SampleGetHistoryData.scripthash3)) - .thenAnswer((_) async => SampleGetHistoryData.data3); + when(client.getBatchHistory(args: batchHistoryRequest0)) + .thenAnswer((realInvocation) async => batchHistoryResponse0); // mock transaction calls when(cachedClient.getTransaction( @@ -1313,6 +1307,48 @@ void main() { (_) async => GetAnonymitySetSampleData.data, ); + when(cachedClient.getTransaction( + txHash: SampleGetTransactionData.txHash0, + coin: Coin.firo, + )).thenAnswer((_) async { + return SampleGetTransactionData.txData0; + }); + when(cachedClient.getTransaction( + txHash: SampleGetTransactionData.txHash1, + coin: Coin.firo, + )).thenAnswer((_) async { + return SampleGetTransactionData.txData1; + }); + when(cachedClient.getTransaction( + txHash: SampleGetTransactionData.txHash2, + coin: Coin.firo, + )).thenAnswer((_) async { + return SampleGetTransactionData.txData2; + }); + when(cachedClient.getTransaction( + txHash: SampleGetTransactionData.txHash3, + coin: Coin.firo, + )).thenAnswer((_) async { + return SampleGetTransactionData.txData3; + }); + when(cachedClient.getTransaction( + txHash: SampleGetTransactionData.txHash4, + coin: Coin.firo, + )).thenAnswer((_) async { + return SampleGetTransactionData.txData4; + }); + when(cachedClient.getTransaction( + txHash: SampleGetTransactionData.txHash5, + coin: Coin.firo, + )).thenAnswer((_) async { + return SampleGetTransactionData.txData5; + }); + when(cachedClient.getTransaction( + txHash: SampleGetTransactionData.txHash6, + coin: Coin.firo, + )).thenAnswer((_) async { + return SampleGetTransactionData.txData6; + }); when(cachedClient.getTransaction( txHash: SampleGetTransactionData.txHash8, coin: Coin.firo, @@ -1407,6 +1443,14 @@ void main() { .thenAnswer((_) async => data); } + when(client.getBatchHistory(args: { + "0": [SampleGetHistoryData.scripthash0], + "1": [SampleGetHistoryData.scripthash3] + })).thenAnswer((realInvocation) async => { + "0": SampleGetHistoryData.data0, + "1": SampleGetHistoryData.data3, + }); + await firo.recoverFromMnemonic( mnemonic: TEST_MNEMONIC, maxUnusedAddressGap: 20, @@ -1465,8 +1509,8 @@ void main() { expect(jIndex, [2, 4, 6]); final lelantusTxModel = await wallet.get('latest_lelantus_tx_model'); - expect(lelantusTxModel.getAllTransactions().length, 3); - }, timeout: const Timeout(Duration(minutes: 3))); + expect(lelantusTxModel.getAllTransactions().length, 5); + }, timeout: const Timeout(Duration(minutes: 5))); test("fullRescan succeeds", () async { TestWidgetsFlutterBinding.ensureInitialized(); @@ -1572,6 +1616,14 @@ void main() { .thenAnswer((_) async => data); } + when(client.getBatchHistory(args: { + "0": [SampleGetHistoryData.scripthash0], + "1": [SampleGetHistoryData.scripthash3] + })).thenAnswer((realInvocation) async => { + "0": SampleGetHistoryData.data0, + "1": SampleGetHistoryData.data3, + }); + // mock transaction calls when(cachedClient.getTransaction( txHash: SampleGetTransactionData.txHash0, @@ -1672,8 +1724,8 @@ void main() { expect(jIndex, [2, 4, 6]); final lelantusTxModel = await wallet.get('latest_lelantus_tx_model'); - expect(lelantusTxModel.getAllTransactions().length, 3); - }, timeout: Timeout(Duration(minutes: 3))); + expect(lelantusTxModel.getAllTransactions().length, 5); + }, timeout: const Timeout(Duration(minutes: 3))); test("fullRescan fails", () async { TestWidgetsFlutterBinding.ensureInitialized(); @@ -1931,6 +1983,14 @@ void main() { .thenAnswer((_) async => data); } + when(client.getBatchHistory(args: { + "0": [SampleGetHistoryData.scripthash0], + "1": [SampleGetHistoryData.scripthash3] + })).thenAnswer((realInvocation) async => { + "0": SampleGetHistoryData.data0, + "1": SampleGetHistoryData.data3, + }); + // mock transaction calls when(cachedClient.getTransaction( txHash: SampleGetTransactionData.txHash0, @@ -2035,7 +2095,7 @@ void main() { expect(jIndex, [2, 4, 6]); final lelantusTxModel = await wallet.get('latest_lelantus_tx_model'); - expect(lelantusTxModel.getAllTransactions().length, 3); + expect(lelantusTxModel.getAllTransactions().length, 5); await firo.fullRescan(20, 1000); @@ -2091,7 +2151,7 @@ void main() { expect(_jIndex, [2, 4, 6]); final _lelantusTxModel = await wallet.get('latest_lelantus_tx_model'); - expect(_lelantusTxModel.getAllTransactions().length, 3); + expect(_lelantusTxModel.getAllTransactions().length, 5); }, timeout: const Timeout(Duration(minutes: 6))); test("recoverFromMnemonic fails testnet", () async { @@ -2389,7 +2449,11 @@ void main() { expect(serials, GetUsedSerialsSampleData.serials['serials']); }); - test("refresh", () async { + test("firo refresh", () async { + TestWidgetsFlutterBinding.ensureInitialized(); + const MethodChannel('uk.spiralarm.flutter/devicelocale') + .setMockMethodCallHandler((methodCall) async => 'en_US'); + final client = MockElectrumX(); final cachedClient = MockCachedElectrumX(); final secureStore = FakeSecureStorage(); @@ -2400,6 +2464,21 @@ void main() { key: "${testWalletId}refresh_mnemonic", value: RefreshTestParams.mnemonic); + when(client.getBatchUTXOs(args: batchUtxoRequest)) + .thenAnswer((realInvocation) async => {}); + + when(client.getBatchHistory(args: { + "0": [SampleGetHistoryData.scripthash1], + "1": [SampleGetHistoryData.scripthash0], + "2": [SampleGetHistoryData.scripthash2], + "3": [SampleGetHistoryData.scripthash3], + })).thenAnswer((realInvocation) async => { + "0": SampleGetHistoryData.data1, + "1": SampleGetHistoryData.data0, + "2": SampleGetHistoryData.data2, + "3": SampleGetHistoryData.data3, + }); + // mock electrumx client calls when(client.getServerFeatures()).thenAnswer((_) async => { "hosts": {}, @@ -2680,6 +2759,10 @@ void main() { // }, timeout: const Timeout(Duration(minutes: 3))); test("send fails due to insufficient balance", () async { + TestWidgetsFlutterBinding.ensureInitialized(); + const MethodChannel('uk.spiralarm.flutter/devicelocale') + .setMockMethodCallHandler((methodCall) async => 'en_US'); + final client = MockElectrumX(); final cachedClient = MockCachedElectrumX(); final secureStore = FakeSecureStorage(); @@ -2703,6 +2786,8 @@ void main() { final txid = Format.uint8listToString(reversedBytes); return txid; }); + when(client.getBatchHistory(args: batchHistoryRequest0)) + .thenAnswer((realInvocation) async => batchHistoryResponse0); when(cachedClient.getAnonymitySet( groupId: "1", @@ -2851,9 +2936,13 @@ void main() { () async => await firo.send( toAddress: "aHZJsucDrhr4Uzzx6XXrKnaTgLxsEAokvV", amount: 100), throwsA(isA())); - }, timeout: Timeout(const Duration(minutes: 3))); + }, timeout: const Timeout(Duration(minutes: 3))); test("send fails due to bad transaction created", () async { + TestWidgetsFlutterBinding.ensureInitialized(); + const MethodChannel('uk.spiralarm.flutter/devicelocale') + .setMockMethodCallHandler((methodCall) async => 'en_US'); + final client = MockElectrumX(); final cachedClient = MockCachedElectrumX(); final secureStore = FakeSecureStorage(); @@ -2867,6 +2956,9 @@ void main() { return "some bad txid"; }); + when(client.getBatchHistory(args: batchHistoryRequest0)) + .thenAnswer((realInvocation) async => batchHistoryResponse0); + when(cachedClient.getAnonymitySet( groupId: "1", coin: Coin.firo, @@ -3014,9 +3106,13 @@ void main() { () async => await firo.send( toAddress: "aHZJsucDrhr4Uzzx6XXrKnaTgLxsEAokvV", amount: 100), throwsA(isA())); - }, timeout: Timeout(const Duration(minutes: 3))); + }, timeout: const Timeout(Duration(minutes: 3))); test("wallet balances", () async { + TestWidgetsFlutterBinding.ensureInitialized(); + const MethodChannel('uk.spiralarm.flutter/devicelocale') + .setMockMethodCallHandler((methodCall) async => 'en_US'); + final client = MockElectrumX(); final cachedClient = MockCachedElectrumX(); final priceAPI = MockPriceAPI(); @@ -3034,6 +3130,12 @@ void main() { when(client.getHistory(scripthash: SampleGetHistoryData.scripthash3)) .thenAnswer((_) async => SampleGetHistoryData.data3); + when(client.getBatchHistory(args: batchHistoryRequest0)) + .thenAnswer((realInvocation) async => batchHistoryResponse0); + + when(client.getBatchUTXOs(args: batchUtxoRequest)) + .thenAnswer((realInvocation) async => {}); + // mock transaction calls when(cachedClient.getTransaction( txHash: SampleGetTransactionData.txHash0, @@ -3104,6 +3206,12 @@ void main() { final priceAPI = MockPriceAPI(); final secureStore = FakeSecureStorage(); + when(client.getBatchHistory(args: batchHistoryRequest0)) + .thenAnswer((realInvocation) async => batchHistoryResponse0); + + when(client.getBatchUTXOs(args: batchUtxoRequest)) + .thenAnswer((realInvocation) async => {}); + // mock price calls when(priceAPI.getPricesAnd24hChange(baseCurrency: "USD")).thenAnswer( (_) async => {Coin.firo: Tuple2(Decimal.fromInt(10), 1.0)}); @@ -3181,6 +3289,10 @@ void main() { }); test("wallet balance minus maxfee - wallet balance is not zero", () async { + TestWidgetsFlutterBinding.ensureInitialized(); + const MethodChannel('uk.spiralarm.flutter/devicelocale') + .setMockMethodCallHandler((methodCall) async => 'en_US'); + final client = MockElectrumX(); final cachedClient = MockCachedElectrumX(); final priceAPI = MockPriceAPI(); @@ -3200,6 +3312,12 @@ void main() { when(client.getHistory(scripthash: SampleGetHistoryData.scripthash3)) .thenAnswer((_) async => SampleGetHistoryData.data3); + when(client.getBatchHistory(args: batchHistoryRequest0)) + .thenAnswer((realInvocation) async => batchHistoryResponse0); + + when(client.getBatchUTXOs(args: batchUtxoRequest)) + .thenAnswer((realInvocation) async => {}); + // mock transaction calls when(cachedClient.getTransaction( txHash: SampleGetTransactionData.txHash0, diff --git a/test/services/coins/firo/sample_data/get_utxos_sample_data.dart b/test/services/coins/firo/sample_data/get_utxos_sample_data.dart index 398cca14d..f6c67b756 100644 --- a/test/services/coins/firo/sample_data/get_utxos_sample_data.dart +++ b/test/services/coins/firo/sample_data/get_utxos_sample_data.dart @@ -22,3 +22,18 @@ abstract class GetUtxoSampleData { } ]; } + +final batchUtxoRequest = { + "843be6c3b2d3fafc8a4eca78b1e1226961a3572357d7486b3a596cfaaf25fce8": [ + "843be6c3b2d3fafc8a4eca78b1e1226961a3572357d7486b3a596cfaaf25fce8" + ], + "477906c20249d06e4891c5c252957cdc4dd38b7932144a8b5407e2cdcdbf8be8": [ + "477906c20249d06e4891c5c252957cdc4dd38b7932144a8b5407e2cdcdbf8be8" + ], + "c6e07f2a0eec2f50d2938b79e4e570d7edd1c83ae1f4512d2041a1c07d84f3b2": [ + "c6e07f2a0eec2f50d2938b79e4e570d7edd1c83ae1f4512d2041a1c07d84f3b2" + ], + "0d23f206295307df70e97534c4ceb92f82b4ebe7983342f8fd287071f90caf38": [ + "0d23f206295307df70e97534c4ceb92f82b4ebe7983342f8fd287071f90caf38" + ] +}; diff --git a/test/services/coins/firo/sample_data/gethistory_samples.dart b/test/services/coins/firo/sample_data/gethistory_samples.dart index 7e87439fc..518826fbe 100644 --- a/test/services/coins/firo/sample_data/gethistory_samples.dart +++ b/test/services/coins/firo/sample_data/gethistory_samples.dart @@ -52,3 +52,54 @@ abstract class SampleGetHistoryData { "0d23f206295307df70e97534c4ceb92f82b4ebe7983342f8fd287071f90caf38"; static List> data3 = []; } + +final batchHistoryRequest0 = { + "0": ["477906c20249d06e4891c5c252957cdc4dd38b7932144a8b5407e2cdcdbf8be8"], + "1": ["843be6c3b2d3fafc8a4eca78b1e1226961a3572357d7486b3a596cfaaf25fce8"], + "2": ["c6e07f2a0eec2f50d2938b79e4e570d7edd1c83ae1f4512d2041a1c07d84f3b2"], + "3": ["0d23f206295307df70e97534c4ceb92f82b4ebe7983342f8fd287071f90caf38"], +}; + +final Map>> batchHistoryResponse0 = { + "0": [ + { + "tx_hash": + "76032a2408e7fefd62a0c7e793f93a2984621e37a625cc1f9e8febadbe583a40", + "height": 455866 + }, + { + "tx_hash": + "36c92daa4005d368e28cea917fdb2c1e7069319a4a79fb2ff45c089100680232", + "height": 455876 + } + ], + "1": [ + { + "tx_hash": + "9201d7a58185f000c312a8b0c19d8e5c61c1ce1b69201c1a4dc2bce289794280", + "height": 457339 + }, + { + "tx_hash": + "ea77e74edecd8c14ff5a8ddeb54e9e5e9c7c301c6f76f0ac1ac8119c6cc15e35", + "height": 457341 + }, + { + "tx_hash": + "ac0322cfdd008fa2a79bec525468fd05cf51a5a4e2c2e9c15598b659ec71ac68", + "height": 457373 + }, + { + "tx_hash": + "e8e4bfc080bd6133d38263d2ac7ef6f60dfd73eb29b464e34766ebb5a0d27dd8", + "height": 457376 + }, + { + "tx_hash": + "51576e2230c2911a508aabb85bb50045f04b8dc958790ce2372986c3ebbe7d3e", + "height": 457379 + }, + ], + "2": [], + "3": [], +};