Skip to content
This repository was archived by the owner on Feb 4, 2022. It is now read-only.

Commit 83fdf99

Browse files
doscosimolus3
andauthored
Full null safety (#146)
* Full null safety * Fix analysis warnings * Remove mockito * Fix dependencies and integration test * Fix crash in dispose Co-authored-by: Simon Binder <[email protected]>
1 parent c797da1 commit 83fdf99

17 files changed

+276
-307
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
- uses: actions/cache@v2
2020
with:
2121
path: .dart_tool
22-
key: dart-dependencies
22+
key: dart-dependencies-${{ hashFiles('pubspec.yaml') }}
2323
- name: "Get dependencies"
2424
env:
2525
PUB_CACHE: ".dart_tool/pub_cache"

example/contracts.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// @dart=2.9
21
import 'dart:io';
32

43
import 'package:http/http.dart';
@@ -77,7 +76,7 @@ Future<void> main() async {
7776
.events(FilterOptions.events(contract: contract, event: transferEvent))
7877
.take(1)
7978
.listen((event) {
80-
final decoded = transferEvent.decodeResults(event.topics, event.data);
79+
final decoded = transferEvent.decodeResults(event.topics!, event.data!);
8180

8281
final from = decoded[0] as EthereumAddress;
8382
final to = decoded[1] as EthereumAddress;

example/main.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// @dart=2.9
21
import 'package:http/http.dart';
32
import 'package:web3dart/web3dart.dart';
43

lib/json_rpc.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import 'dart:convert';
66
import 'package:http/http.dart';
77

88
class JsonRPC {
9+
JsonRPC(this.url, this.client);
10+
911
final String url;
1012
final Client client;
1113

1214
int _currentRequestId = 1;
1315

14-
JsonRPC(this.url, this.client);
15-
1616
/// Performs an RPC request, asking the server to execute the function with
1717
/// the given name and the associated parameters, which need to be encodable
1818
/// with the [json] class of dart:convert.

lib/src/core/client.dart

Lines changed: 43 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// @dart=2.9
21
part of 'package:web3dart/web3dart.dart';
32

43
/// Signature for a function that opens a socket on which json-rpc operations
@@ -22,6 +21,16 @@ typedef SocketConnector = StreamChannel<String> Function();
2221
/// to create transactions, you will instead have to obtain private keys of
2322
/// accounts yourself.
2423
class Web3Client {
24+
/// Starts a client that connects to a JSON rpc API, available at [url]. The
25+
/// [httpClient] will be used to send requests to the rpc server.
26+
/// Am isolate will be used to perform expensive operations, such as signing
27+
/// transactions or computing private keys.
28+
Web3Client(String url, Client httpClient, {this.socketConnector})
29+
: _jsonRpc = JsonRPC(url, httpClient) {
30+
_operations = _ExpensiveOperations();
31+
_filters = _FilterEngine(this);
32+
}
33+
2534
static const BlockNum _defaultBlock = BlockNum.current();
2635

2736
final JsonRPC _jsonRpc;
@@ -31,32 +40,16 @@ class Web3Client {
3140
/// event requests and parse responses. Can be null, in which case a polling
3241
/// implementation for events will be used.
3342
@experimental
34-
final SocketConnector socketConnector;
35-
36-
rpc.Peer _streamRpcPeer;
43+
final SocketConnector? socketConnector;
3744

38-
_ExpensiveOperations _operations;
39-
_FilterEngine _filters;
45+
rpc.Peer? _streamRpcPeer;
46+
late _ExpensiveOperations _operations;
47+
late _FilterEngine _filters;
4048

4149
///Whether errors, handled or not, should be printed to the console.
4250
bool printErrors = false;
4351

44-
/// Starts a client that connects to a JSON rpc API, available at [url]. The
45-
/// [httpClient] will be used to send requests to the rpc server.
46-
/// The [runner] will be used to perform expensive operations, such as signing
47-
/// transactions or computing private keys. By default, a [Runner] on the same
48-
/// isolate will be used. You can use `IsolateRunner.spawn` to use a
49-
/// background runner instead.
50-
/// The runner will automatically be disposed by web3dart when [dispose] is
51-
/// called.
52-
Web3Client(String url, Client httpClient,
53-
{this.socketConnector, Runner runner})
54-
: _jsonRpc = JsonRPC(url, httpClient) {
55-
_operations = _ExpensiveOperations(runner ?? Runner());
56-
_filters = _FilterEngine(this);
57-
}
58-
59-
Future<T> _makeRPCCall<T>(String function, [List<dynamic> params]) async {
52+
Future<T> _makeRPCCall<T>(String function, [List<dynamic>? params]) async {
6053
try {
6154
final data = await _jsonRpc.call(function, params);
6255
// ignore: only_throw_errors
@@ -71,19 +64,19 @@ class Web3Client {
7164
}
7265
}
7366

74-
rpc.Peer _connectWithPeer() {
75-
if (_streamRpcPeer != null && !_streamRpcPeer.isClosed) {
67+
rpc.Peer? _connectWithPeer() {
68+
if (_streamRpcPeer != null && !_streamRpcPeer!.isClosed) {
7669
return _streamRpcPeer;
7770
}
7871
if (socketConnector == null) return null;
7972

80-
final socket = socketConnector();
73+
final socket = socketConnector!();
8174
_streamRpcPeer = rpc.Peer(socket)
8275
..registerMethod('eth_subscription', (rpc.Parameters params) {
8376
_filters.handlePubSubNotification(params);
8477
});
8578

86-
_streamRpcPeer.listen().then((_) {
79+
_streamRpcPeer?.listen().then((_) {
8780
// .listen() will complete when the socket is closed, so reset client
8881
_streamRpcPeer = null;
8982
_filters.handleConnectionClosed();
@@ -92,7 +85,7 @@ class Web3Client {
9285
return _streamRpcPeer;
9386
}
9487

95-
String _getBlockParam(BlockNum block) {
88+
String _getBlockParam(BlockNum? block) {
9689
return (block ?? _defaultBlock).toBlockParam();
9790
}
9891

@@ -191,7 +184,7 @@ class Web3Client {
191184
///
192185
/// This function allows specifying a custom block mined in the past to get
193186
/// historical data. By default, [BlockNum.current] will be used.
194-
Future<EtherAmount> getBalance(EthereumAddress address, {BlockNum atBlock}) {
187+
Future<EtherAmount> getBalance(EthereumAddress address, {BlockNum? atBlock}) {
195188
final blockParam = _getBlockParam(atBlock);
196189

197190
return _makeRPCCall<String>('eth_getBalance', [address.hex, blockParam])
@@ -207,7 +200,7 @@ class Web3Client {
207200
/// This function allows specifying a custom block mined in the past to get
208201
/// historical data. By default, [BlockNum.current] will be used.
209202
Future<Uint8List> getStorage(EthereumAddress address, BigInt position,
210-
{BlockNum atBlock}) {
203+
{BlockNum? atBlock}) {
211204
final blockParam = _getBlockParam(atBlock);
212205

213206
return _makeRPCCall<String>('eth_getStorageAt', [
@@ -221,7 +214,8 @@ class Web3Client {
221214
///
222215
/// This function allows specifying a custom block mined in the past to get
223216
/// historical data. By default, [BlockNum.current] will be used.
224-
Future<int> getTransactionCount(EthereumAddress address, {BlockNum atBlock}) {
217+
Future<int> getTransactionCount(EthereumAddress address,
218+
{BlockNum? atBlock}) {
225219
final blockParam = _getBlockParam(atBlock);
226220

227221
return _makeRPCCall<String>(
@@ -241,14 +235,14 @@ class Web3Client {
241235
Future<TransactionReceipt> getTransactionReceipt(String hash) {
242236
return _makeRPCCall<Map<String, dynamic>>(
243237
'eth_getTransactionReceipt', [hash])
244-
.then((s) => s != null ? TransactionReceipt.fromMap(s) : null);
238+
.then((s) => TransactionReceipt.fromMap(s));
245239
}
246240

247241
/// Gets the code of a contract at the specified [address]
248242
///
249243
/// This function allows specifying a custom block mined in the past to get
250244
/// historical data. By default, [BlockNum.current] will be used.
251-
Future<Uint8List> getCode(EthereumAddress address, {BlockNum atBlock}) {
245+
Future<Uint8List> getCode(EthereumAddress address, {BlockNum? atBlock}) {
252246
return _makeRPCCall<String>(
253247
'eth_getCode', [address.hex, _getBlockParam(atBlock)]).then(hexToBytes);
254248
}
@@ -262,7 +256,7 @@ class Web3Client {
262256
final filter = _EventFilter(options);
263257
return _makeRPCCall<List<dynamic>>(
264258
'eth_getLogs', [filter._createParamsObject(true)]).then((logs) {
265-
return logs?.map(filter.parseChanges)?.toList();
259+
return logs.map(filter.parseChanges).toList();
266260
});
267261
}
268262

@@ -325,11 +319,11 @@ class Web3Client {
325319
/// This function allows specifying a custom block mined in the past to get
326320
/// historical data. By default, [BlockNum.current] will be used.
327321
Future<List<dynamic>> call({
328-
EthereumAddress sender,
329-
@required DeployedContract contract,
330-
@required ContractFunction function,
331-
@required List<dynamic> params,
332-
BlockNum atBlock,
322+
EthereumAddress? sender,
323+
required DeployedContract contract,
324+
required ContractFunction function,
325+
required List<dynamic> params,
326+
BlockNum? atBlock,
333327
}) async {
334328
final encodedResult = await callRaw(
335329
sender: sender,
@@ -345,13 +339,13 @@ class Web3Client {
345339
/// sent via [sendTransaction]. Note that the estimate may be significantly
346340
/// higher than the amount of gas actually used by the transaction.
347341
Future<BigInt> estimateGas({
348-
EthereumAddress sender,
349-
EthereumAddress to,
350-
EtherAmount value,
351-
BigInt amountOfGas,
352-
EtherAmount gasPrice,
353-
Uint8List data,
354-
@Deprecated('Parameter is ignored') BlockNum atBlock,
342+
EthereumAddress? sender,
343+
EthereumAddress? to,
344+
EtherAmount? value,
345+
BigInt? amountOfGas,
346+
EtherAmount? gasPrice,
347+
Uint8List? data,
348+
@Deprecated('Parameter is ignored') BlockNum? atBlock,
355349
}) async {
356350
final amountHex = await _makeRPCCall<String>(
357351
'eth_estimateGas',
@@ -385,10 +379,10 @@ class Web3Client {
385379
/// - [call], which automatically encodes function parameters and parses a
386380
/// response.
387381
Future<String> callRaw({
388-
EthereumAddress sender,
389-
@required EthereumAddress contract,
390-
@required Uint8List data,
391-
BlockNum atBlock,
382+
EthereumAddress? sender,
383+
required EthereumAddress contract,
384+
required Uint8List data,
385+
BlockNum? atBlock,
392386
}) {
393387
final call = {
394388
'to': contract.hex,
@@ -440,7 +434,6 @@ class Web3Client {
440434
/// Closes resources managed by this client, such as the optional background
441435
/// isolate for calculations and managed streams.
442436
Future<void> dispose() async {
443-
await _operations.stop();
444437
await _filters.dispose();
445438
await _streamRpcPeer?.close();
446439
}

lib/src/core/expensive_operations.dart

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,24 @@
1-
// @dart=2.9
21
part of 'package:web3dart/web3dart.dart';
32

43
/// Wrapper around some potentially expensive operations so that they can
54
/// optionally be executed in a background isolate. This is mainly needed for
65
/// flutter apps where these would otherwise block the UI thread.
76
class _ExpensiveOperations {
8-
final Runner runner;
9-
10-
_ExpensiveOperations(this.runner);
11-
12-
Future stop() {
13-
return runner.close();
14-
}
7+
_ExpensiveOperations();
158

169
Future<EthPrivateKey> privateKeyFromHex(String privateKey) {
17-
return runner.run(_internalCreatePrivateKey, privateKey);
10+
return _internalCreatePrivateKey(privateKey);
1811
}
1912

2013
Future<Uint8List> signTransaction(_SigningInput t) {
21-
if (!t.credentials.isolateSafe) {
22-
// sign on this isolate
23-
return internalSign(t);
24-
} else {
25-
return runner.run(internalSign, t);
26-
}
14+
return internalSign(t);
15+
16+
// if (!t.credentials.isolateSafe) {
17+
// // sign on this isolate
18+
// return internalSign(t);
19+
// } else {
20+
// return compute(internalSign, t);
21+
// }
2722
}
2823
}
2924

0 commit comments

Comments
 (0)