diff --git a/.gitignore b/.gitignore index 4a2a319..7867d5f 100755 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,10 @@ .history .svn/ +#Flutter version management +.fvm/ +.fmvrc + # IntelliJ related *.iml *.ipr diff --git a/example/pubspec.lock b/example/pubspec.lock index 369ae7b..f083261 100755 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: path: ".." relative: true source: path - version: "0.1.4" + version: "0.2.1" async: dependency: transitive description: @@ -76,26 +76,34 @@ packages: dependency: transitive description: name: decimal - sha256: eece91944f523657c75a3a008a90ec7f7eb3986191153a78570c7d0ac8ef3d01 + sha256: "4140a688f9e443e2f4de3a1162387bf25e1ac6d51e24c9da263f245210f41440" url: "https://pub.dev" source: hosted - version: "2.3.2" + version: "3.0.2" dio: dependency: transitive description: name: dio - sha256: "0894a098594263fe1caaba3520e3016d8a855caeb010a882273189cca10f11e9" + sha256: "0dfb6b6a1979dac1c1245e17cef824d7b452ea29bd33d3467269f9bef3715fb0" + url: "https://pub.dev" + source: hosted + version: "5.6.0" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: "33259a9276d6cea88774a0000cfae0d861003497755969c92faa223108620dc8" url: "https://pub.dev" source: hosted - version: "5.1.1" + version: "2.0.0" eip1559: dependency: transitive description: name: eip1559 - sha256: de454d6321bd753eb79116e9ec4f8df20895c2e97f9a3839a032f3a728985516 + sha256: c2b81ac85f3e0e71aaf558201dd9a4600f051ece7ebacd0c5d70065c9b458004 url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.6.2" eip55: dependency: transitive description: @@ -108,10 +116,10 @@ packages: dependency: transitive description: name: either_dart - sha256: "08eaa2eec0e11c2b6528e425c735b916f3b4ffdd7f8da6b94d3d83096bd00749" + sha256: "0b57f6a9410ce0ba2cc340220109f545bf4bad1b06b242219f0af11ab9e84f0e" url: "https://pub.dev" source: hosted - version: "0.4.0" + version: "1.0.0" fake_async: dependency: transitive description: @@ -120,6 +128,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -129,18 +145,18 @@ packages: dependency: "direct main" description: name: flutter_dotenv - sha256: d9283d92059a22e9834bc0a31336658ffba77089fb6f3cc36751f1fc7c6661a3 + sha256: "9357883bdd153ab78cbf9ffa07656e336b8bbb2b5a3ca596b0b27e119f7c7d77" url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "5.1.0" flutter_lints: dependency: "direct dev" description: name: flutter_lints - sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + sha256: "3f41d009ba7172d5ff9be5f6e6e6abb4300e263aab8866d2a0842ed2a70f8f0c" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "4.0.0" flutter_test: dependency: "direct dev" description: flutter @@ -150,10 +166,10 @@ packages: dependency: transitive description: name: http - sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" + sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 url: "https://pub.dev" source: hosted - version: "0.13.5" + version: "1.2.2" http_parser: dependency: transitive description: @@ -162,6 +178,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + intl: + dependency: transitive + description: + name: intl + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" + source: hosted + version: "0.19.0" js: dependency: transitive description: @@ -178,62 +202,86 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "3f87a60e8c63aecc975dda1ceedbc8f24de75f09e4856ea27daf8958f2f0ce05" + url: "https://pub.dev" + source: hosted + version: "10.0.5" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "932549fb305594d82d7183ecd9fa93463e9914e1b67cacc34bc40906594a1806" + url: "https://pub.dev" + source: hosted + version: "3.0.5" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" lints: dependency: transitive description: name: lints - sha256: "5e4a9cd06d447758280a8ac2405101e0e2094d2a1dbdd3756aec3fe7775ba593" + sha256: "976c774dd944a42e83e2467f4cc670daef7eed6295b10b36ae8c85bcbf828235" url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "4.0.0" logger: dependency: transitive description: name: logger - sha256: "6bbb9d6f7056729537a4309bda2e74e18e5d9f14302489cc1e93f33b3fe32cac" + sha256: "697d067c60c20999686a0add96cf6aba723b3aa1f83ecf806a8097231529ec32" url: "https://pub.dev" source: hosted - version: "2.0.2+1" + version: "2.4.0" matcher: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e + sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.15.0" path: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" pointycastle: dependency: transitive description: name: pointycastle - sha256: c3120a968135aead39699267f4c74bc9a08e4e909e86bc1b0af5bfd78691123c + sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe" url: "https://pub.dev" source: hosted - version: "3.7.2" + version: "3.9.1" rational: dependency: transitive description: @@ -263,6 +311,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" stack_trace: dependency: transitive description: @@ -307,26 +363,26 @@ packages: dependency: transitive description: name: test_api - sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + sha256: "5b8a98dafc4d5c4c9c72d8b31ab2b23fc13422348d2997120294d3bac86b4ddb" url: "https://pub.dev" source: hosted - version: "0.6.1" + version: "0.7.2" typed_data: dependency: transitive description: name: typed_data - sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" uuid: dependency: transitive description: name: uuid - sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313" + sha256: "83d37c7ad7aaf9aa8e275490669535c8080377cfa7a7004c24dfac53afffaa90" url: "https://pub.dev" source: hosted - version: "3.0.7" + version: "4.4.2" vector_math: dependency: transitive description: @@ -335,37 +391,54 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc + url: "https://pub.dev" + source: hosted + version: "14.2.4" wallet: dependency: transitive description: name: wallet - sha256: "569c91c2af13a9e1119c001f9c09218eccf3f383eb8d15ba13a5b558010c1bc0" + sha256: "687fd89a16557649b26189e597792962f405797fc64113e8758eabc2c2605c32" url: "https://pub.dev" source: hosted - version: "0.0.12+1" + version: "0.0.13" web: dependency: transitive description: name: web - sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 + sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062 url: "https://pub.dev" source: hosted - version: "0.3.0" + version: "1.0.0" web3dart: dependency: transitive description: name: web3dart - sha256: "0b96223a6b284e3146e65dc842ded139eca68a85c4ab79c5ba1a73284927d3cd" + sha256: "885e5e8f0cc3c87c09f160a7fce6279226ca41316806f7ece2001959c62ecced" + url: "https://pub.dev" + source: hosted + version: "2.7.3" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "3c12d96c0c9a4eec095246debcea7b86c0324f22df69893d538fcc6f1b8cce83" url: "https://pub.dev" source: hosted - version: "2.6.1" + version: "0.1.6" web_socket_channel: dependency: transitive description: name: web_socket_channel - sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b + sha256: "9f187088ed104edd8662ca07af4b124465893caf063ba29758f97af57e61da8f" url: "https://pub.dev" source: hosted - version: "2.3.0" + version: "3.0.1" sdks: - dart: ">=3.2.0-194.0.dev <4.0.0" + dart: ">=3.4.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 251f3b9..73c3944 100755 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -33,7 +33,7 @@ dependencies: alchemy_web3: path: ../ - flutter_dotenv: ^5.0.2 + flutter_dotenv: ^5.1.0 dev_dependencies: flutter_test: @@ -44,7 +44,7 @@ dev_dependencies: # activated in the `analysis_options.yaml` file located at the root of your # package. See that file for information about deactivating specific lint # rules and activating additional ones. - flutter_lints: ^2.0.0 + flutter_lints: ^4.0.0 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/lib/src/api/enhanced/nft.dart b/lib/src/api/enhanced/nft.dart index b963174..c45f929 100755 --- a/lib/src/api/enhanced/nft.dart +++ b/lib/src/api/enhanced/nft.dart @@ -35,6 +35,7 @@ class EnhancedNFTAPI with AlchemyConsoleMixin { bool withMetadata = true, int? tokenUriTimeoutInMs, List filters = const [], + List excludeFilters = const [], OrderBy orderBy = OrderBy.desc, SpamConfidenceLevel? spamConfidenceLevel, }) async { @@ -45,6 +46,7 @@ class EnhancedNFTAPI with AlchemyConsoleMixin { 'withMetadata': withMetadata, 'tokenUriTimeoutInMs': tokenUriTimeoutInMs, 'includeFilters[]': filters.map((e) => e.toParam()).toList(), + 'excludeFilters[]': excludeFilters.map((e) => e.toParam()).toList(), 'orderBy': orderBy.toParam(), }; @@ -128,6 +130,7 @@ class EnhancedNFTAPI with AlchemyConsoleMixin { required String owner, String? pageKey, List filters = const [], + List excludeFilters = const [], OrderBy orderBy = OrderBy.desc, }) async { final result = await httpClient.request( @@ -137,6 +140,7 @@ class EnhancedNFTAPI with AlchemyConsoleMixin { 'owner': owner, 'pageKey': pageKey, 'includeFilters[]': filters.map((e) => e.toParam()).toList(), + 'excludeFilters[]': excludeFilters.map((e) => e.toParam()).toList(), 'orderBy': orderBy.toParam(), }, ); diff --git a/lib/src/api/enhanced/token.dart b/lib/src/api/enhanced/token.dart index 5564b87..13056a1 100755 --- a/lib/src/api/enhanced/token.dart +++ b/lib/src/api/enhanced/token.dart @@ -47,18 +47,19 @@ class EnhancedTokenAPI with AlchemyConsoleMixin { ///pageKey: Applies only to the erc20 request type. A string address used for pagination. If more results are available, a pageKey will be returned in the response. // maxCount: Applies only to the erc20 request type. Specifies the maximum count of token balances to return per call. This value defaults to 100 and is currently capped at 100. - (String pageKey, String maxCount)? pageInfo, + String? pageKey, + int? maxCount, }) async { var params = [ address, contractAddresses.isNotEmpty ? contractAddresses : tokensSpecification, ]; - if (pageInfo != null) { - params.add({ - "pageKey": pageInfo.$1, - "maxCount": pageInfo.$2, - }); + if (pageKey != null) { + params.add({"pageKey": pageKey}); + } + if (maxCount != null) { + params.add({"maxCount": maxCount}); } final result = await wsClient.request( diff --git a/lib/src/client/rpc_http_client.dart b/lib/src/client/rpc_http_client.dart index 9254cf1..0bb3412 100755 --- a/lib/src/client/rpc_http_client.dart +++ b/lib/src/client/rpc_http_client.dart @@ -1,6 +1,5 @@ import 'dart:async'; import 'dart:convert'; - import 'package:alchemy_web3/alchemy_web3.dart'; import 'package:dio/dio.dart'; import 'package:either_dart/either.dart'; @@ -42,11 +41,23 @@ class RpcHttpClient with AlchemyConsoleMixin { this.sendTimeout = sendTimeout ?? this.sendTimeout; this.receiveTimeout = receiveTimeout ?? this.receiveTimeout; this.verbose = verbose ?? this.verbose; - // set base url _dio.options.baseUrl = url; } - Future> request({ + Future batchRequest({ + List> requests = const [], + }) async { + if (url.isEmpty) throw 'Client URL is empty'; + + var batchRequests = requests.map(_buildRpcRequest).toList(); + + return await _makePostRequest( + bodyData: batchRequests, + requestType: 'Batch Requesting', + ); + } + + Future request({ Map? queryParameters, String endpoint = '', HTTPMethod method = HTTPMethod.post, @@ -54,11 +65,45 @@ class RpcHttpClient with AlchemyConsoleMixin { }) async { if (url.isEmpty) throw 'Client URL is empty'; + var bodyData = _buildRpcRequest({ + 'method': endpoint, + 'params': bodyParameters, + }); + + if (method == HTTPMethod.post) { + return await _makePostRequest( + bodyData: [bodyData], + queryParameters: _sanitizeQueryParams(queryParameters), + endpoint: endpoint, + requestType: 'Requesting', + ); + } else { + return await _makeGetRequest( + queryParameters: _sanitizeQueryParams(queryParameters), + endpoint: endpoint, + requestType: 'GET Requesting', + ); + } + } + + // HELPER FUNCTIONS + + // Builds the standard JSON-RPC request body + Map _buildRpcRequest(Map request) { + return { + 'method': request['method'], + 'params': request['params'] ?? [], + 'jsonrpc': jsonRPCVersion.toString(), + 'id': _requestId = _requestId + 1, + }; + } + + // Sanitizes query parameters by removing null values + Map _sanitizeQueryParams(Map? queryParameters) { var updatedParametersMap = Map.from(queryParameters ?? {}); - // remove null map property values updatedParametersMap.removeWhere((key, value) => value == null); - // convert the arrays so it works in the query parameters + // Convert arrays for query parameters if (updatedParametersMap['filters'] != null && queryParameters?['filters'] is List) { updatedParametersMap['filters[]'] = List.filled(updatedParametersMap['filters'].length, ''); for (int i = 0; i < updatedParametersMap['filters'].length; i++) { @@ -66,51 +111,86 @@ class RpcHttpClient with AlchemyConsoleMixin { } } updatedParametersMap.remove('filters'); + return updatedParametersMap; + } - var bodyData = { - 'method': endpoint, - 'params': bodyParameters, - 'jsonrpc': jsonRPCVersion.toString(), - 'id': _requestId = _requestId + 1, - }; - + // Handles POST requests (including batch requests) + Future> _makePostRequest({ + required List> bodyData, + Map? queryParameters, + String? endpoint, + required String requestType, + }) async { if (verbose) { - console.trace( - 'Requesting... ${method.name.toUpperCase()}: $url, method: $endpoint, queryParameters: \n$updatedParametersMap, bodyParameters: $bodyParameters}', + console.trace('$requestType... POST: $url, method: $endpoint, body: \n$bodyData'); + } + + try { + var response = await _dio.post( + url, + queryParameters: queryParameters, + data: jsonEncode(bodyData), + options: Options( + receiveTimeout: receiveTimeout, + sendTimeout: sendTimeout, + responseType: ResponseType.plain, + ), + ); + + if (verbose) { + console.debug('${response.statusCode} : ${response.realUri}\n${response.data}'); + } + + return Right(jsonDecode(response.data!)); + } on DioException catch (e) { + if (verbose) { + console.error('${e.type}! ${e.response?.statusCode} : ${e.response?.realUri}\n${e.response?.data}'); + } + + return Left( + bodyData.map((request) { + return RpcResponse( + id: request['id'] ?? 0, + jsonrpc: jsonRPCVersion.toString(), + error: RPCError( + code: e.response?.statusCode ?? 0, + message: e.response?.data ?? e.message, + ), + ); + }).toList(), ); } + } - Response response; + // Handles GET requests + Future> _makeGetRequest({ + required Map queryParameters, + String? endpoint, + required String requestType, + }) async { + if (verbose) { + console.trace('$requestType... GET: $url, queryParameters: \n$queryParameters'); + } try { - if (method == HTTPMethod.post) { - response = await _dio.post( - url, - queryParameters: updatedParametersMap, - data: jsonEncode(bodyData), - options: Options( - receiveTimeout: receiveTimeout, - sendTimeout: sendTimeout, - responseType: ResponseType.plain, - ), - ); - } else { - response = await _dio.get( - '/$endpoint', - queryParameters: updatedParametersMap, - options: Options( - method: method.name.toUpperCase(), - receiveTimeout: receiveTimeout, - sendTimeout: sendTimeout, - responseType: ResponseType.plain, - ), - ); + var response = await _dio.get( + '/$endpoint', + queryParameters: queryParameters, + options: Options( + receiveTimeout: receiveTimeout, + sendTimeout: sendTimeout, + responseType: ResponseType.plain, + ), + ); + + if (verbose) { + console.debug('${response.statusCode} : ${response.realUri}\n${response.data}'); } + + return Right(jsonDecode(response.data!)); } on DioException catch (e) { if (verbose) { - console.error( - '${e.type}! ${e.response?.statusCode} : ${e.response?.realUri}\n${e.response?.data}', - ); + console.error('${e.type}! ${e.response?.statusCode} : ${e.response?.realUri}\n${e.response?.data}'); } return Left( @@ -124,14 +204,6 @@ class RpcHttpClient with AlchemyConsoleMixin { ), ); } - - if (verbose) { - console.debug( - '${response.statusCode} : ${response.realUri}\n${response.data}', - ); - } - - return Right(jsonDecode(response.data!)); } } diff --git a/lib/src/client/rpc_ws_client.dart b/lib/src/client/rpc_ws_client.dart index 31e9daa..5e42f86 100755 --- a/lib/src/client/rpc_ws_client.dart +++ b/lib/src/client/rpc_ws_client.dart @@ -48,52 +48,22 @@ class RpcWsClient with AlchemyConsoleMixin implements Client { required String method, required List params, }) async { - if (url.isEmpty) throw 'Client URL is empty'; - if (wsStatus != WsStatus.running) await restart(); if (verbose) console.trace('Requesting... $url -> $method\n$params'); - // RESTART IF NECESSARY - if (isClosed) { - await restart(); - - if (isClosed) { - return Left(RPCErrorData( - code: 0, - message: 'No Internet Connection', - )); - } - } - + final error = await _validateRequest(method, params); + if (error != null) return error; // SEND REQUEST try { final response = await sendRequest(method, params); if (verbose) console.debug('Response: $response'); if (response == null) { - return Left(RPCErrorData( - code: 200, - message: 'Null Response', - )); + return _nullResponseLeft(); } return Right(response ?? ''); - } on DioException catch (e) { - if (e.response == null) { - return Left( - RPCErrorData( - code: 0, - message: 'Local Error: ${e.type}: ${e.message}', - ), - ); - } - - return Left(RPCErrorData.fromJson(e.response!.data)); - } catch (e) { - // different error - return Left(RPCErrorData( - code: 0, - message: 'Unknown Error: $e', - )); + } catch (e, st) { + return _handleException(e, st); } } @@ -156,5 +126,59 @@ class RpcWsClient with AlchemyConsoleMixin implements Client { void sendNotification(String method, [parameters]) {} @override - void withBatch(Function() callback) {} + void withBatch(Function() callback) { + wsClient!.withBatch(callback); + } + + Left _nullResponseLeft() { + return Left(RPCErrorData( + code: 200, + message: 'Null Response', + )); + } + + Left _handleException(Object e, StackTrace? st) { + if (e is DioException) { + if (e.response == null) { + return Left( + RPCErrorData( + code: 0, + message: 'Local Error: ${e.type}: ${e.message}', + ), + ); + } + return Left(RPCErrorData.fromJson(e.response!.data)); + } + // different error + return Left( + RPCErrorData( + code: 0, + message: 'Unknown Error: $e', + ), + ); + } + + /// validate before sending request + /// return error if any of the the connection is closed even after restarting + Future?> _validateRequest( + String method, + List params, + ) async { + if (url.isEmpty) throw 'Client URL is empty'; + if (wsStatus != WsStatus.running) await restart(); + + // RESTART IF NECESSARY + if (isClosed) { + await restart(); + + if (isClosed) { + return Left(RPCErrorData( + code: 0, + message: 'No Internet Connection', + )); + } + } + + return null; + } } diff --git a/pubspec.yaml b/pubspec.yaml index 394a340..08f29fd 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,26 +1,26 @@ name: alchemy_web3 description: An Alchemy Platform client for Flutter & Dart -version: 0.2.0 +version: 0.2.1 homepage: https://github.com/oliverbytes/alchemy_web3 environment: sdk: '>=3.0.0 <4.0.0' dependencies: - logger: ^2.0.2+1 - decimal: ^2.3.2 - either_dart: ^0.4.0 + logger: ^2.4.0 + decimal: ^3.0.2 + either_dart: ^1.0.0 # NETWORK - dio: ^5.1.1 + dio: ^5.6.0 json_rpc_2: ^3.0.2 - web_socket_channel: ^2.3.0 + web_socket_channel: ^3.0.1 # CRYPTO - pointycastle: ^3.6.2 + pointycastle: ^3.9.1 convert: ^3.1.1 # WEB3 - web3dart: ^2.6.1 + web3dart: ^2.7.3 dev_dependencies: - lints: ^2.0.1 - test: ^1.21.4 + lints: ^4.0.0 + test: ^1.25.8 diff --git a/test/custom_api_test.dart b/test/custom_api_test.dart index 62e29a6..7935f6b 100644 --- a/test/custom_api_test.dart +++ b/test/custom_api_test.dart @@ -5,32 +5,42 @@ import 'package:test/test.dart'; const String _key = 'your_key'; void main() { - group('Custom API solana tests', () { - var solanaUrl = 'https://solana-mainnet.g.alchemy.com/v2/$_key'; - RpcHttpClient httpClient = RpcHttpClient(); - httpClient.init( - url: solanaUrl, - verbose: true, - ); + group('Custom API', () { + var api = _init(); - RpcWsClient wsClient = RpcWsClient(); - wsClient.init( - url: solanaUrl, - verbose: true, - ); + test('batch request', () async { + await api.httpClient.batchRequest(requests: [ + { + 'method': 'eth_getTransactionByHash', + 'params': ["0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b"], + }, + { + 'method': 'eth_blockNumber', + 'params': [], + }, + ]).then((result) { + expect(result.isRight, true); + }); + }); + }); +} - CustomApi api = CustomApi(); - api.setHttpClient(httpClient); - api.setWsClient(wsClient); +CustomApi _init() { + var url = 'https://eth-mainnet.g.alchemy.com/v2/$_key'; + RpcHttpClient httpClient = RpcHttpClient(); + httpClient.init( + url: url, + verbose: true, + ); - test('Custom API', () async { - final result = await api.httpRequest( - method: 'getBalance', - httpMethod: HTTPMethod.post, - bodyParameters: ["83astBRguLMdt2h5U1Tpdq5tjFoJ6noeGwaY3mDLVcri"], - ); + RpcWsClient wsClient = RpcWsClient(); + wsClient.init( + url: url, + verbose: true, + ); - expect(result.isRight, true); - }); - }); + CustomApi api = CustomApi(); + api.setHttpClient(httpClient); + api.setWsClient(wsClient); + return api; }