From 9d6cdfd2c1cd3532f9fadad909fe1a167a97de8d Mon Sep 17 00:00:00 2001 From: julian Date: Fri, 8 Sep 2023 14:41:39 -0600 Subject: [PATCH] Modify HTTP to take in proxy info rather than rely on the tor service singleton --- lib/networking/http.dart | 53 ++- .../exchange/change_now/change_now_api.dart | 18 +- .../exchange/exchange_view_test.mocks.dart | 72 ++-- test/services/change_now/change_now_test.dart | 315 +++++++++--------- .../change_now/change_now_test.mocks.dart | 17 +- .../dogecoin/dogecoin_wallet_test.mocks.dart | 1 - 6 files changed, 250 insertions(+), 226 deletions(-) diff --git a/lib/networking/http.dart b/lib/networking/http.dart index 393b16bcd..6d4c775ae 100644 --- a/lib/networking/http.dart +++ b/lib/networking/http.dart @@ -1,9 +1,9 @@ +import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:socks5_proxy/socks_client.dart'; -import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; // WIP wrapper layer @@ -11,28 +11,29 @@ import 'package:stackwallet/utilities/logger.dart'; // TODO expand this class class Response { final int code; - final String body; + final List bodyBytes; - Response(this.body, this.code); + String get body => utf8.decode(bodyBytes, allowMalformed: true); + + Response(this.bodyBytes, this.code); } class HTTP { - /// Visible for testing so we can override with a mock TorService - @visibleForTesting - TorService torService = TorService.sharedInstance; - Future get({ required Uri url, Map? headers, - required bool routeOverTor, + required ({ + InternetAddress host, + int port, + })? proxyInfo, }) async { final httpClient = HttpClient(); try { - if (routeOverTor) { + if (proxyInfo != null) { SocksTCPClient.assignToHttpClient(httpClient, [ ProxySettings( - torService.proxyInfo.host, - torService.proxyInfo.port, + proxyInfo.host, + proxyInfo.port, ), ]); } @@ -46,8 +47,9 @@ class HTTP { } final response = await request.close(); + return Response( - await response.transform(utf8.decoder).join(), + await _bodyBytes(response), response.statusCode, ); } catch (e, s) { @@ -66,15 +68,18 @@ class HTTP { Map? headers, Object? body, Encoding? encoding, - required bool routeOverTor, + required ({ + InternetAddress host, + int port, + })? proxyInfo, }) async { final httpClient = HttpClient(); try { - if (routeOverTor) { + if (proxyInfo != null) { SocksTCPClient.assignToHttpClient(httpClient, [ ProxySettings( - torService.proxyInfo.host, - torService.proxyInfo.port, + proxyInfo.host, + proxyInfo.port, ), ]); } @@ -92,7 +97,7 @@ class HTTP { final response = await request.close(); return Response( - await response.transform(utf8.decoder).join(), + await _bodyBytes(response), response.statusCode, ); } catch (e, s) { @@ -105,4 +110,18 @@ class HTTP { httpClient.close(force: true); } } + + Future _bodyBytes(HttpClientResponse response) { + final completer = Completer(); + final List bytes = []; + response.listen( + (data) { + bytes.addAll(data); + }, + onDone: () => completer.complete( + Uint8List.fromList(bytes), + ), + ); + return completer.future; + } } diff --git a/lib/services/exchange/change_now/change_now_api.dart b/lib/services/exchange/change_now/change_now_api.dart index d7cd5bcb9..d8b260495 100644 --- a/lib/services/exchange/change_now/change_now_api.dart +++ b/lib/services/exchange/change_now/change_now_api.dart @@ -28,6 +28,7 @@ import 'package:stackwallet/models/isar/exchange_cache/pair.dart'; import 'package:stackwallet/networking/http.dart'; import 'package:stackwallet/services/exchange/change_now/change_now_exchange.dart'; import 'package:stackwallet/services/exchange/exchange_response.dart'; +import 'package:stackwallet/services/tor_service.dart'; import 'package:stackwallet/utilities/logger.dart'; import 'package:stackwallet/utilities/prefs.dart'; import 'package:tuple/tuple.dart'; @@ -38,10 +39,12 @@ class ChangeNowAPI { static const String apiVersion = "/v1"; static const String apiVersionV2 = "/v2"; - HTTP client = HTTP(); + final HTTP client; - ChangeNowAPI._(); - static final ChangeNowAPI _instance = ChangeNowAPI._(); + @visibleForTesting + ChangeNowAPI({HTTP? http}) : client = http ?? HTTP(); + + static final ChangeNowAPI _instance = ChangeNowAPI(); static ChangeNowAPI get instance => _instance; Uri _buildUri(String path, Map? params) { @@ -57,7 +60,8 @@ class ChangeNowAPI { final response = await client.get( url: uri, headers: {'Content-Type': 'application/json'}, - routeOverTor: Prefs.instance.useTor, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); String? data; try { @@ -86,7 +90,8 @@ class ChangeNowAPI { // 'Content-Type': 'application/json', 'x-changenow-api-key': apiKey, }, - routeOverTor: Prefs.instance.useTor, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); final data = response.body; @@ -109,7 +114,8 @@ class ChangeNowAPI { url: uri, headers: {'Content-Type': 'application/json'}, body: jsonEncode(body), - routeOverTor: Prefs.instance.useTor, + proxyInfo: + Prefs.instance.useTor ? TorService.sharedInstance.proxyInfo : null, ); String? data; diff --git a/test/screen_tests/exchange/exchange_view_test.mocks.dart b/test/screen_tests/exchange/exchange_view_test.mocks.dart index 1441aa4ad..5263fad93 100644 --- a/test/screen_tests/exchange/exchange_view_test.mocks.dart +++ b/test/screen_tests/exchange/exchange_view_test.mocks.dart @@ -802,14 +802,6 @@ class MockChangeNowAPI extends _i1.Mock implements _i14.ChangeNowAPI { ), ) as _i2.HTTP); @override - set client(_i2.HTTP? _client) => super.noSuchMethod( - Invocation.setter( - #client, - _client, - ), - returnValueForMissingStub: null, - ); - @override _i7.Future<_i3.ExchangeResponse>> getAvailableCurrencies({ bool? fixedRate, bool? active, @@ -1073,8 +1065,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i14.ChangeNowAPI { [], {#apiKey: apiKey}, ), - returnValue: _i7.Future< - _i3.ExchangeResponse>>.value( + returnValue: _i7 + .Future<_i3.ExchangeResponse>>.value( _FakeExchangeResponse_1>( this, Invocation.method( @@ -1115,8 +1107,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i14.ChangeNowAPI { #apiKey: apiKey, }, ), - returnValue: _i7.Future< - _i3.ExchangeResponse<_i21.ExchangeTransaction>>.value( + returnValue: _i7 + .Future<_i3.ExchangeResponse<_i21.ExchangeTransaction>>.value( _FakeExchangeResponse_1<_i21.ExchangeTransaction>( this, Invocation.method( @@ -1172,8 +1164,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i14.ChangeNowAPI { #apiKey: apiKey, }, ), - returnValue: _i7.Future< - _i3.ExchangeResponse<_i21.ExchangeTransaction>>.value( + returnValue: _i7 + .Future<_i3.ExchangeResponse<_i21.ExchangeTransaction>>.value( _FakeExchangeResponse_1<_i21.ExchangeTransaction>( this, Invocation.method( @@ -1197,35 +1189,35 @@ class MockChangeNowAPI extends _i1.Mock implements _i14.ChangeNowAPI { )), ) as _i7.Future<_i3.ExchangeResponse<_i21.ExchangeTransaction>>); @override - _i7.Future<_i3.ExchangeResponse<_i22.ExchangeTransactionStatus>> - getTransactionStatus({ + _i7.Future< + _i3 + .ExchangeResponse<_i22.ExchangeTransactionStatus>> getTransactionStatus({ required String? id, String? apiKey, }) => - (super.noSuchMethod( - Invocation.method( - #getTransactionStatus, - [], - { - #id: id, - #apiKey: apiKey, - }, - ), - returnValue: _i7.Future< - _i3.ExchangeResponse<_i22.ExchangeTransactionStatus>>.value( - _FakeExchangeResponse_1<_i22.ExchangeTransactionStatus>( - this, - Invocation.method( - #getTransactionStatus, - [], - { - #id: id, - #apiKey: apiKey, - }, - ), - )), - ) as _i7 - .Future<_i3.ExchangeResponse<_i22.ExchangeTransactionStatus>>); + (super.noSuchMethod( + Invocation.method( + #getTransactionStatus, + [], + { + #id: id, + #apiKey: apiKey, + }, + ), + returnValue: _i7 + .Future<_i3.ExchangeResponse<_i22.ExchangeTransactionStatus>>.value( + _FakeExchangeResponse_1<_i22.ExchangeTransactionStatus>( + this, + Invocation.method( + #getTransactionStatus, + [], + { + #id: id, + #apiKey: apiKey, + }, + ), + )), + ) as _i7.Future<_i3.ExchangeResponse<_i22.ExchangeTransactionStatus>>); @override _i7.Future<_i3.ExchangeResponse>> getAvailableFloatingRatePairs({bool? includePartners = false}) => diff --git a/test/services/change_now/change_now_test.dart b/test/services/change_now/change_now_test.dart index 0b909cf12..f49c52064 100644 --- a/test/services/change_now/change_now_test.dart +++ b/test/services/change_now/change_now_test.dart @@ -20,16 +20,17 @@ void main() { group("getAvailableCurrencies", () { test("getAvailableCurrencies succeeds without options", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, )).thenAnswer((realInvocation) async => - Response(jsonEncode(availableCurrenciesJSON), 200)); + Response(utf8.encode(jsonEncode(availableCurrenciesJSON)), 200)); - final result = await ChangeNowAPI.instance.getAvailableCurrencies(); + final result = await instance.getAvailableCurrencies(); expect(result.exception, null); expect(result.value == null, false); @@ -38,17 +39,16 @@ void main() { test("getAvailableCurrencies succeeds with active option", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies?active=true"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => - Response(jsonEncode(availableCurrenciesJSONActive), 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response( + utf8.encode(jsonEncode(availableCurrenciesJSONActive)), 200)); - final result = - await ChangeNowAPI.instance.getAvailableCurrencies(active: true); + final result = await instance.getAvailableCurrencies(active: true); expect(result.exception, null); expect(result.value == null, false); @@ -57,17 +57,16 @@ void main() { test("getAvailableCurrencies succeeds with fixedRate option", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies?fixedRate=true"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => - Response(jsonEncode(availableCurrenciesJSONFixedRate), 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response( + utf8.encode(jsonEncode(availableCurrenciesJSONFixedRate)), 200)); - final result = - await ChangeNowAPI.instance.getAvailableCurrencies(fixedRate: true); + final result = await instance.getAvailableCurrencies(fixedRate: true); expect(result.exception, null); expect(result.value == null, false); @@ -77,18 +76,19 @@ void main() { test("getAvailableCurrencies succeeds with fixedRate and active options", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/currencies?fixedRate=true&active=true"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => - Response(jsonEncode(availableCurrenciesJSONActiveFixedRate), 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response( + utf8.encode(jsonEncode(availableCurrenciesJSONActiveFixedRate)), + 200)); - final result = await ChangeNowAPI.instance - .getAvailableCurrencies(active: true, fixedRate: true); + final result = + await instance.getAvailableCurrencies(active: true, fixedRate: true); expect(result.exception, null); expect(result.value == null, false); @@ -99,16 +99,16 @@ void main() { "getAvailableCurrencies fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => - Response('{"some unexpected": "but valid json data"}', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response( + utf8.encode('{"some unexpected": "but valid json data"}'), 200)); - final result = await ChangeNowAPI.instance.getAvailableCurrencies(); + final result = await instance.getAvailableCurrencies(); expect( result.exception!.type, ExchangeExceptionType.serializeResponseError); @@ -117,15 +117,15 @@ void main() { test("getAvailableCurrencies fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response("", 400)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response(utf8.encode(""), 400)); - final result = await ChangeNowAPI.instance.getAvailableCurrencies(); + final result = await instance.getAvailableCurrencies(); expect( result.exception!.type, ExchangeExceptionType.serializeResponseError); @@ -136,17 +136,16 @@ void main() { group("getPairedCurrencies", () { test("getPairedCurrencies succeeds without fixedRate option", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies-to/XMR"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, )).thenAnswer((realInvocation) async => - Response(jsonEncode(getPairedCurrenciesJSON), 200)); + Response(utf8.encode(jsonEncode(getPairedCurrenciesJSON)), 200)); - final result = - await ChangeNowAPI.instance.getPairedCurrencies(ticker: "XMR"); + final result = await instance.getPairedCurrencies(ticker: "XMR"); expect(result.exception, null); expect(result.value == null, false); @@ -155,18 +154,18 @@ void main() { test("getPairedCurrencies succeeds with fixedRate option", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/currencies-to/XMR?fixedRate=true"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => - Response(jsonEncode(getPairedCurrenciesJSONFixedRate), 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response( + utf8.encode(jsonEncode(getPairedCurrenciesJSONFixedRate)), 200)); - final result = await ChangeNowAPI.instance - .getPairedCurrencies(ticker: "XMR", fixedRate: true); + final result = + await instance.getPairedCurrencies(ticker: "XMR", fixedRate: true); expect(result.exception, null); expect(result.value == null, false); @@ -177,17 +176,16 @@ void main() { "getPairedCurrencies fails with ChangeNowExceptionType.serializeResponseError A", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies-to/XMR"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => - Response('[{"some unexpected": "but valid json data"}]', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response( + utf8.encode('[{"some unexpected": "but valid json data"}]'), 200)); - final result = - await ChangeNowAPI.instance.getPairedCurrencies(ticker: "XMR"); + final result = await instance.getPairedCurrencies(ticker: "XMR"); expect( result.exception!.type, ExchangeExceptionType.serializeResponseError); @@ -196,16 +194,16 @@ void main() { test("getPairedCurrencies fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse("https://api.ChangeNow.io/v1/currencies"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response("", 400)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response(utf8.encode(""), 400)); - final result = await ChangeNowAPI.instance - .getPairedCurrencies(ticker: "XMR", fixedRate: true); + final result = + await instance.getPairedCurrencies(ticker: "XMR", fixedRate: true); expect(result.exception!.type, ExchangeExceptionType.generic); expect(result.value == null, true); @@ -215,17 +213,17 @@ void main() { group("getMinimalExchangeAmount", () { test("getMinimalExchangeAmount succeeds", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/min-amount/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer( - (realInvocation) async => Response('{"minAmount": 42}', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => + Response(utf8.encode('{"minAmount": 42}'), 200)); - final result = await ChangeNowAPI.instance.getMinimalExchangeAmount( + final result = await instance.getMinimalExchangeAmount( fromTicker: "xmr", toTicker: "btc", apiKey: "testAPIKEY", @@ -240,16 +238,17 @@ void main() { "getMinimalExchangeAmount fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/min-amount/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => + Response(utf8.encode('{"error": 42}'), 200)); - final result = await ChangeNowAPI.instance.getMinimalExchangeAmount( + final result = await instance.getMinimalExchangeAmount( fromTicker: "xmr", toTicker: "btc", apiKey: "testAPIKEY", @@ -262,16 +261,16 @@ void main() { test("getMinimalExchangeAmount fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/min-amount/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('', 400)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - final result = await ChangeNowAPI.instance.getMinimalExchangeAmount( + final result = await instance.getMinimalExchangeAmount( fromTicker: "xmr", toTicker: "btc", apiKey: "testAPIKEY", @@ -286,18 +285,19 @@ void main() { group("getEstimatedExchangeAmount", () { test("getEstimatedExchangeAmount succeeds", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/exchange-amount/42/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, )).thenAnswer((realInvocation) async => Response( - '{"estimatedAmount": 58.4142873, "transactionSpeedForecast": "10-60", "warningMessage": null}', + utf8.encode( + '{"estimatedAmount": 58.4142873, "transactionSpeedForecast": "10-60", "warningMessage": null}'), 200)); - final result = await ChangeNowAPI.instance.getEstimatedExchangeAmount( + final result = await instance.getEstimatedExchangeAmount( fromTicker: "xmr", toTicker: "btc", fromAmount: Decimal.fromInt(42), @@ -313,16 +313,17 @@ void main() { "getEstimatedExchangeAmount fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/exchange-amount/42/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => + Response(utf8.encode('{"error": 42}'), 200)); - final result = await ChangeNowAPI.instance.getEstimatedExchangeAmount( + final result = await instance.getEstimatedExchangeAmount( fromTicker: "xmr", toTicker: "btc", fromAmount: Decimal.fromInt(42), @@ -336,16 +337,16 @@ void main() { test("getEstimatedExchangeAmount fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/exchange-amount/42/xmr_btc?api_key=testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('', 400)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - final result = await ChangeNowAPI.instance.getEstimatedExchangeAmount( + final result = await instance.getEstimatedExchangeAmount( fromTicker: "xmr", toTicker: "btc", fromAmount: Decimal.fromInt(42), @@ -366,9 +367,9 @@ void main() { // Uri.parse( // "https://api.ChangeNow.io/v1/exchange-amount/fixed-rate/10/xmr_btc?api_key=testAPIKEY&useRateId=true"), // headers: {'Content-Type': 'application/json'}, - // routeOverTor: false, + // proxyInfo: null, // )).thenAnswer((realInvocation) async => - // Response(jsonEncode(estFixedRateExchangeAmountJSON), 200)); + // Response(utf8.encode(jsonEncode(estFixedRateExchangeAmountJSON )), 200)); // // final result = // await ChangeNow.instance.getEstimatedFixedRateExchangeAmount( @@ -394,7 +395,7 @@ void main() { // Uri.parse( // "https://api.ChangeNow.io/v1/exchange-amount/fixed-rate/10/xmr_btc?api_key=testAPIKEY&useRateId=true"), // headers: {'Content-Type': 'application/json'}, - // routeOverTor: false, + // proxyInfo: null, // )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); // // final result = @@ -419,7 +420,7 @@ void main() { // Uri.parse( // "https://api.ChangeNow.io/v1/exchange-amount/fixed-rate/10/xmr_btc?api_key=testAPIKEY&useRateId=true"), // headers: {'Content-Type': 'application/json'}, - // routeOverTor: false, + // proxyInfo: null, // )).thenAnswer((realInvocation) async => Response('', 400)); // // final result = @@ -438,17 +439,17 @@ void main() { group("getAvailableFixedRateMarkets", () { test("getAvailableFixedRateMarkets succeeds", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, )).thenAnswer((realInvocation) async => - Response(jsonEncode(fixedRateMarketsJSON), 200)); + Response(utf8.encode(jsonEncode(fixedRateMarketsJSON)), 200)); - final result = await ChangeNowAPI.instance.getAvailableFixedRateMarkets( + final result = await instance.getAvailableFixedRateMarkets( apiKey: "testAPIKEY", ); @@ -461,16 +462,17 @@ void main() { "getAvailableFixedRateMarkets fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => + Response(utf8.encode('{"error": 42}'), 200)); - final result = await ChangeNowAPI.instance.getAvailableFixedRateMarkets( + final result = await instance.getAvailableFixedRateMarkets( apiKey: "testAPIKEY", ); @@ -481,16 +483,16 @@ void main() { test("getAvailableFixedRateMarkets fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('', 400)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - final result = await ChangeNowAPI.instance.getAvailableFixedRateMarkets( + final result = await instance.getAvailableFixedRateMarkets( apiKey: "testAPIKEY", ); @@ -503,20 +505,19 @@ void main() { group("createStandardExchangeTransaction", () { test("createStandardExchangeTransaction succeeds", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.post( url: Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, body: '{"from":"xmr","to":"btc","address":"bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5","amount":"0.3","flow":"standard","extraId":"","userId":"","contactEmail":"","refundAddress":"888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H","refundExtraId":""}', encoding: null, - )).thenAnswer((realInvocation) async => - Response(jsonEncode(createStandardTransactionResponse), 200)); + )).thenAnswer((realInvocation) async => Response( + utf8.encode(jsonEncode(createStandardTransactionResponse)), 200)); - final result = - await ChangeNowAPI.instance.createStandardExchangeTransaction( + final result = await instance.createStandardExchangeTransaction( fromTicker: "xmr", toTicker: "btc", receivingAddress: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", @@ -535,19 +536,19 @@ void main() { "createStandardExchangeTransaction fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.post( url: Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, body: '{"from":"xmr","to":"btc","address":"bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5","amount":"0.3","flow":"standard","extraId":"","userId":"","contactEmail":"","refundAddress":"888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H","refundExtraId":""}', encoding: null, - )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); + )).thenAnswer((realInvocation) async => + Response(utf8.encode('{"error": 42}'), 200)); - final result = - await ChangeNowAPI.instance.createStandardExchangeTransaction( + final result = await instance.createStandardExchangeTransaction( fromTicker: "xmr", toTicker: "btc", receivingAddress: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", @@ -565,19 +566,18 @@ void main() { test("createStandardExchangeTransaction fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.post( url: Uri.parse("https://api.ChangeNow.io/v1/transactions/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, body: '{"from":"xmr","to":"btc","address":"bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5","amount":"0.3","flow":"standard","extraId":"","userId":"","contactEmail":"","refundAddress":"888tNkZrPN6JsEgekjMnABU4TBzc2Dt29EPAvkRxbANsAnjyPbb3iQ1YBRk1UXcdRsiKc9dhwMVgN5S9cQUiyoogDavup3H","refundExtraId":""}', encoding: null, - )).thenAnswer((realInvocation) async => Response('', 400)); + )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - final result = - await ChangeNowAPI.instance.createStandardExchangeTransaction( + final result = await instance.createStandardExchangeTransaction( fromTicker: "xmr", toTicker: "btc", receivingAddress: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", @@ -595,22 +595,26 @@ void main() { group("createFixedRateExchangeTransaction", () { test("createFixedRateExchangeTransaction succeeds", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.post( url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, body: '{"from":"btc","to":"eth","address":"0x57f31ad4b64095347F87eDB1675566DAfF5EC886","flow":"fixed-rate","extraId":"","userId":"","contactEmail":"","refundAddress":"","refundExtraId":"","rateId":"","amount":"0.3"}', encoding: null, )).thenAnswer((realInvocation) async => Response( - '{"payinAddress": "33eFX2jfeWbXMSmRe9ewUUTrmSVSxZi5cj", "payoutAddress": "0x57f31ad4b64095347F87eDB1675566DAfF5EC886","payoutExtraId": "", "fromCurrency": "btc", "toCurrency": "eth", "refundAddress": "","refundExtraId": "","validUntil": "2019-09-09T14:01:04.921Z","id": "a5c73e2603f40d","amount": 62.9737711}', + utf8.encode( + '{"payinAddress": "33eFX2jfeWbXMSmRe9ewUUTrmSVSxZi5cj", "payoutAddress":' + ' "0x57f31ad4b64095347F87eDB1675566DAfF5EC886","payoutExtraId": "",' + ' "fromCurrency": "btc", "toCurrency": "eth", "refundAddress": "",' + '"refundExtraId": "","validUntil": "2019-09-09T14:01:04.921Z","id":' + ' "a5c73e2603f40d","amount": 62.9737711}'), 200)); - final result = - await ChangeNowAPI.instance.createFixedRateExchangeTransaction( + final result = await instance.createFixedRateExchangeTransaction( fromTicker: "btc", toTicker: "eth", receivingAddress: "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", @@ -630,21 +634,20 @@ void main() { "createFixedRateExchangeTransaction fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.post( url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, body: '{"from":"btc","to":"eth","address":"0x57f31ad4b64095347F87eDB1675566DAfF5EC886","amount":"0.3","flow":"fixed-rate","extraId":"","userId":"","contactEmail":"","refundAddress":"","refundExtraId":"","rateId":""}', encoding: null, - )).thenAnswer((realInvocation) async => - Response('{"id": "a5c73e2603f40d","amount": 62.9737711}', 200)); + )).thenAnswer((realInvocation) async => Response( + utf8.encode('{"id": "a5c73e2603f40d","amount": 62.9737711}'), 200)); - final result = - await ChangeNowAPI.instance.createFixedRateExchangeTransaction( + final result = await instance.createFixedRateExchangeTransaction( fromTicker: "btc", toTicker: "eth", receivingAddress: "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", @@ -662,20 +665,19 @@ void main() { test("createFixedRateExchangeTransaction fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.post( url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/fixed-rate/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, body: '{"from": "btc","to": "eth","address": "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", "amount": "1.12345","extraId": "", "userId": "","contactEmail": "","refundAddress": "", "refundExtraId": "", "rateId": "" }', encoding: null, - )).thenAnswer((realInvocation) async => Response('', 400)); + )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - final result = - await ChangeNowAPI.instance.createFixedRateExchangeTransaction( + final result = await instance.createFixedRateExchangeTransaction( fromTicker: "xmr", toTicker: "btc", receivingAddress: "bc1qu58svs9983e2vuyqh7gq7ratf8k5qehz5k0cn5", @@ -695,18 +697,24 @@ void main() { group("getTransactionStatus", () { test("getTransactionStatus succeeds", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/47F87eDB1675566DAfF5EC886/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, + proxyInfo: null, )).thenAnswer((realInvocation) async => Response( - '{"status": "waiting", "payinAddress": "32Ge2ci26rj1sRGw2NjiQa9L7Xvxtgzhrj", "payoutAddress": "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", "fromCurrency": "btc", "toCurrency": "eth", "id": "50727663e5d9a4", "updatedAt": "2019-08-22T14:47:49.943Z", "expectedSendAmount": 1, "expectedReceiveAmount": 52.31667, "createdAt": "2019-08-22T14:47:49.943Z", "isPartner": false}', + utf8.encode( + '{"status": "waiting", "payinAddress": "32Ge2ci26rj1sRGw2NjiQa9L7Xvxtgzhrj", ' + '"payoutAddress": "0x57f31ad4b64095347F87eDB1675566DAfF5EC886", ' + '"fromCurrency": "btc", "toCurrency": "eth", "id": "50727663e5d9a4", ' + '"updatedAt": "2019-08-22T14:47:49.943Z", "expectedSendAmount": 1, ' + '"expectedReceiveAmount": 52.31667, "createdAt": "2019-08-22T14:47:49.943Z",' + ' "isPartner": false}'), 200)); - final result = await ChangeNowAPI.instance.getTransactionStatus( + final result = await instance.getTransactionStatus( id: "47F87eDB1675566DAfF5EC886", apiKey: "testAPIKEY", ); @@ -720,16 +728,17 @@ void main() { "getTransactionStatus fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/47F87eDB1675566DAfF5EC886/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => + Response(utf8.encode('{"error": 42}'), 200)); - final result = await ChangeNowAPI.instance.getTransactionStatus( + final result = await instance.getTransactionStatus( id: "47F87eDB1675566DAfF5EC886", apiKey: "testAPIKEY", ); @@ -741,16 +750,16 @@ void main() { test("getTransactionStatus fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/transactions/47F87eDB1675566DAfF5EC886/testAPIKEY"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('', 400)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - final result = await ChangeNowAPI.instance.getTransactionStatus( + final result = await instance.getTransactionStatus( id: "47F87eDB1675566DAfF5EC886", apiKey: "testAPIKEY", ); @@ -764,18 +773,17 @@ void main() { group("getAvailableFloatingRatePairs", () { test("getAvailableFloatingRatePairs succeeds", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/available-pairs?includePartners=false"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => - Response('["btc_xmr","btc_firo","btc_doge","eth_ltc"]', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response( + utf8.encode('["btc_xmr","btc_firo","btc_doge","eth_ltc"]'), 200)); - final result = - await ChangeNowAPI.instance.getAvailableFloatingRatePairs(); + final result = await instance.getAvailableFloatingRatePairs(); expect(result.exception, null); expect(result.value == null, false); @@ -786,17 +794,17 @@ void main() { "getAvailableFloatingRatePairs fails with ChangeNowExceptionType.serializeResponseError", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/available-pairs?includePartners=false"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('{"error": 42}', 200)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => + Response(utf8.encode('{"error": 42}'), 200)); - final result = - await ChangeNowAPI.instance.getAvailableFloatingRatePairs(); + final result = await instance.getAvailableFloatingRatePairs(); expect( result.exception!.type, ExchangeExceptionType.serializeResponseError); @@ -805,17 +813,16 @@ void main() { test("getAvailableFloatingRatePairs fails for any other reason", () async { final client = MockHTTP(); - ChangeNowAPI.instance.client = client; + final instance = ChangeNowAPI(http: client); when(client.get( url: Uri.parse( "https://api.ChangeNow.io/v1/market-info/available-pairs?includePartners=false"), headers: {'Content-Type': 'application/json'}, - routeOverTor: false, - )).thenAnswer((realInvocation) async => Response('', 400)); + proxyInfo: null, + )).thenAnswer((realInvocation) async => Response(utf8.encode(''), 400)); - final result = - await ChangeNowAPI.instance.getAvailableFloatingRatePairs(); + final result = await instance.getAvailableFloatingRatePairs(); expect( result.exception!.type, ExchangeExceptionType.serializeResponseError); diff --git a/test/services/change_now/change_now_test.mocks.dart b/test/services/change_now/change_now_test.mocks.dart index 71e4c0ad4..f0b375d72 100644 --- a/test/services/change_now/change_now_test.mocks.dart +++ b/test/services/change_now/change_now_test.mocks.dart @@ -4,7 +4,8 @@ // ignore_for_file: no_leading_underscores_for_library_prefixes import 'dart:async' as _i3; -import 'dart:convert' as _i4; +import 'dart:convert' as _i5; +import 'dart:io' as _i4; import 'package:mockito/mockito.dart' as _i1; import 'package:stackwallet/networking/http.dart' as _i2; @@ -42,7 +43,7 @@ class MockHTTP extends _i1.Mock implements _i2.HTTP { _i3.Future<_i2.Response> get({ required Uri? url, Map? headers, - required bool? routeOverTor, + required ({_i4.InternetAddress host, int port})? proxyInfo, }) => (super.noSuchMethod( Invocation.method( @@ -51,7 +52,7 @@ class MockHTTP extends _i1.Mock implements _i2.HTTP { { #url: url, #headers: headers, - #routeOverTor: routeOverTor, + #proxyInfo: proxyInfo, }, ), returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( @@ -62,7 +63,7 @@ class MockHTTP extends _i1.Mock implements _i2.HTTP { { #url: url, #headers: headers, - #routeOverTor: routeOverTor, + #proxyInfo: proxyInfo, }, ), )), @@ -72,8 +73,8 @@ class MockHTTP extends _i1.Mock implements _i2.HTTP { required Uri? url, Map? headers, Object? body, - _i4.Encoding? encoding, - required bool? routeOverTor, + _i5.Encoding? encoding, + required ({_i4.InternetAddress host, int port})? proxyInfo, }) => (super.noSuchMethod( Invocation.method( @@ -84,7 +85,7 @@ class MockHTTP extends _i1.Mock implements _i2.HTTP { #headers: headers, #body: body, #encoding: encoding, - #routeOverTor: routeOverTor, + #proxyInfo: proxyInfo, }, ), returnValue: _i3.Future<_i2.Response>.value(_FakeResponse_0( @@ -97,7 +98,7 @@ class MockHTTP extends _i1.Mock implements _i2.HTTP { #headers: headers, #body: body, #encoding: encoding, - #routeOverTor: routeOverTor, + #proxyInfo: proxyInfo, }, ), )), diff --git a/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart b/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart index c19e63a44..b084875f5 100644 --- a/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart +++ b/test/services/coins/dogecoin/dogecoin_wallet_test.mocks.dart @@ -537,7 +537,6 @@ class MockTransactionNotificationTracker extends _i1.Mock Invocation.getter(#confirmeds), returnValue: [], ) as List); - @override bool wasNotifiedPending(String? txid) => (super.noSuchMethod( Invocation.method(