See PR #19
Showing 3 of 25 files from the diff.
lib/wallet/network_info.dart
changed.
Other files ignored by Codecov
lib/proto/google/api/annotations.pb.dart
has changed.
scripts/generate_proto.sh
has changed.
lib/proto/tendermint/abci/types.pb.dart
has changed.
lib/proto/cosmos/evidence/v1beta1/evidence.pb.dart
has changed.
doc/wallet/overview.md
has changed.
pubspec.yaml
has changed.
test/wallet/wallet_test.dart
has changed.
lib/proto/google/api/httpbody.pb.dart
has changed.
doc/transactions/overview.md
has changed.
lib/wallet/network_info.g.dart
has changed.
lib/proto/cosmos/vesting/v1beta1/tx.pb.dart
has changed.
lib/proto/cosmos/vesting/v1beta1/vesting.pb.dart
has changed.
test/wallet/network_info_test.dart
has changed.
lib/proto/cosmos/evidence/v1beta1/query.pb.dart
has changed.
example/example.dart
has changed.
lib/proto/cosmos/evidence/v1beta1/genesis.pb.dart
has changed.
lib/proto/cosmos/evidence/v1beta1/tx.pb.dart
has changed.
CHANGELOG.md
has changed.
lib/proto/cosmos/gov/v1beta1/query.pbgrpc.dart
has changed.
doc/queries/overview.md
has changed.
test/transactions/signer/tx_signer_test.dart
has changed.
@@ -15,7 +15,7 @@
Loading
15 | 15 | TxSigner({ |
|
16 | 16 | required AuthQuerier authQuerier, |
|
17 | 17 | required NodeQuerier nodeQuerier, |
|
18 | - | }) : _authQuerier = authQuerier, |
|
18 | + | }) : _authQuerier = authQuerier, |
|
19 | 19 | _nodeQuerier = nodeQuerier; |
|
20 | 20 | ||
21 | 21 | /// Builds a new [TxSigner] from a given gRPC client channel and HTTP client. |
@@ -31,12 +31,8 @@
Loading
31 | 31 | ||
32 | 32 | /// Builds a new [TxSigner] from the given [NetworkInfo]. |
|
33 | 33 | factory TxSigner.fromNetworkInfo(NetworkInfo info) { |
|
34 | - | final clientChannel = grpc.ClientChannel( |
|
35 | - | info.fullNodeHost, |
|
36 | - | port: info.gRPCPort, |
|
37 | - | ); |
|
38 | 34 | final httpClient = http.Client(); |
|
39 | - | return TxSigner.build(clientChannel, httpClient); |
|
35 | + | return TxSigner.build(info.gRPCChannel, httpClient); |
|
40 | 36 | } |
|
41 | 37 | ||
42 | 38 | /// Creates a new [Tx] object containing the given [msgs] and signs it using |
@@ -55,6 +51,9 @@
Loading
55 | 51 | ||
56 | 52 | // Set the default fees |
|
57 | 53 | fee ??= Fee()..gasLimit = 200000.toInt64(); |
|
54 | + | if (!fee.hasGasLimit()) { |
|
55 | + | throw Exception('Invalid fees: invalid gas amount specified'); |
|
56 | + | } |
|
58 | 57 | ||
59 | 58 | // Get the account data and node info from the network |
|
60 | 59 | final account = await _authQuerier.getAccountData(wallet.bech32Address); |
@@ -66,7 +65,7 @@
Loading
66 | 65 | ||
67 | 66 | // Get the node info data |
|
68 | 67 | final nodeInfo = await _nodeQuerier.getNodeInfo( |
|
69 | - | wallet.networkInfo.lcdEndpoint, |
|
68 | + | wallet.networkInfo.restEndpoint, |
|
70 | 69 | ); |
|
71 | 70 | ||
72 | 71 | // Get the public key from the account, or generate it if the |
@@ -16,8 +16,7 @@
Loading
16 | 16 | ||
17 | 17 | /// Builds a new [TxSender] from the given [NetworkInfo]. |
|
18 | 18 | factory TxSender.fromNetworkInfo(NetworkInfo info) { |
|
19 | - | final clientChannel = ClientChannel(info.fullNodeHost, port: info.gRPCPort); |
|
20 | - | return TxSender.build(clientChannel); |
|
19 | + | return TxSender.build(info.gRPCChannel); |
|
21 | 20 | } |
|
22 | 21 | ||
23 | 22 | /// Broadcasts the given [tx] using the info contained |
@@ -1,8 +1,128 @@
Loading
1 | 1 | import 'package:equatable/equatable.dart'; |
|
2 | + | import 'package:grpc/grpc.dart'; |
|
2 | 3 | import 'package:json_annotation/json_annotation.dart'; |
|
3 | 4 | ||
4 | 5 | part 'network_info.g.dart'; |
|
5 | 6 | ||
7 | + | const _CHANNEL_CREDENTIAL_SECURE = 'secure'; |
|
8 | + | const _CHANNEL_CREDENTIAL_INSECURE = 'insecure'; |
|
9 | + | ||
10 | + | Object channelCredentialsToJson(ChannelCredentials credentials) { |
|
11 | + | if (credentials.isSecure) { |
|
12 | + | return _CHANNEL_CREDENTIAL_SECURE; |
|
13 | + | } |
|
14 | + | return _CHANNEL_CREDENTIAL_INSECURE; |
|
15 | + | } |
|
16 | + | ||
17 | + | ChannelCredentials channelOptionsFromJson(String value) { |
|
18 | + | if (value == _CHANNEL_CREDENTIAL_INSECURE) { |
|
19 | + | return ChannelCredentials.insecure(); |
|
20 | + | } |
|
21 | + | return ChannelCredentials.secure(); |
|
22 | + | } |
|
23 | + | ||
24 | + | /// Contains the information about the GRPC endpoint |
|
25 | + | @JsonSerializable(explicitToJson: true) |
|
26 | + | class GRPCInfo extends Equatable { |
|
27 | + | static ClientChannel? _clientChannel; |
|
28 | + | ||
29 | + | @JsonKey(name: 'host', required: true) |
|
30 | + | final String host; |
|
31 | + | ||
32 | + | @JsonKey(name: 'port', defaultValue: 9090) |
|
33 | + | final int port; |
|
34 | + | ||
35 | + | @JsonKey( |
|
36 | + | name: 'channel_credentials', |
|
37 | + | fromJson: channelOptionsFromJson, |
|
38 | + | toJson: channelCredentialsToJson, |
|
39 | + | ) |
|
40 | + | final ChannelCredentials credentials; |
|
41 | + | ||
42 | + | GRPCInfo({ |
|
43 | + | required this.host, |
|
44 | + | this.port = 9090, |
|
45 | + | this.credentials = const ChannelCredentials.insecure(), |
|
46 | + | }); |
|
47 | + | ||
48 | + | /// Creates a new [ClientChannel] using the optional given options. |
|
49 | + | ClientChannel getChannel() { |
|
50 | + | return _clientChannel ??= ClientChannel( |
|
51 | + | host.replaceFirst(RegExp('http(s)?:\/\/'), ''), |
|
52 | + | port: port, |
|
53 | + | options: ChannelOptions(credentials: credentials), |
|
54 | + | ); |
|
55 | + | } |
|
56 | + | ||
57 | + | factory GRPCInfo.fromJson(Map<String, dynamic> json) { |
|
58 | + | return _$GRPCInfoFromJson(json); |
|
59 | + | } |
|
60 | + | ||
61 | + | Map<String, dynamic> toJson() { |
|
62 | + | return _$GRPCInfoToJson(this); |
|
63 | + | } |
|
64 | + | ||
65 | + | @override |
|
66 | + | List<Object?> get props { |
|
67 | + | return [ |
|
68 | + | host, |
|
69 | + | port, |
|
70 | + | credentials.isSecure, |
|
71 | + | ]; |
|
72 | + | } |
|
73 | + | ||
74 | + | @override |
|
75 | + | String toString() { |
|
76 | + | return 'GRPCInfo {' |
|
77 | + | 'host: $host, ' |
|
78 | + | 'port: $port ' |
|
79 | + | '}'; |
|
80 | + | } |
|
81 | + | } |
|
82 | + | ||
83 | + | /// Contains the information about the LCD endpoint |
|
84 | + | @JsonSerializable(explicitToJson: true) |
|
85 | + | class LCDInfo extends Equatable { |
|
86 | + | @JsonKey(name: 'host', required: true) |
|
87 | + | final String host; |
|
88 | + | ||
89 | + | @JsonKey(name: 'port', defaultValue: 1317) |
|
90 | + | final int port; |
|
91 | + | ||
92 | + | LCDInfo({ |
|
93 | + | required this.host, |
|
94 | + | this.port = 1317, |
|
95 | + | }); |
|
96 | + | ||
97 | + | factory LCDInfo.fromJson(Map<String, dynamic> json) { |
|
98 | + | return _$LCDInfoFromJson(json); |
|
99 | + | } |
|
100 | + | ||
101 | + | Map<String, dynamic> toJson() { |
|
102 | + | return _$LCDInfoToJson(this); |
|
103 | + | } |
|
104 | + | ||
105 | + | /// Returns the full URL of the LCD endpoint |
|
106 | + | String get fullUrl { |
|
107 | + | var hostWithProtocol = host; |
|
108 | + | if (!hostWithProtocol.startsWith(RegExp('http(s)?:\/\/'))) { |
|
109 | + | hostWithProtocol = 'http://$hostWithProtocol'; |
|
110 | + | } |
|
111 | + | return '$hostWithProtocol:$port'; |
|
112 | + | } |
|
113 | + | ||
114 | + | @override |
|
115 | + | List<Object?> get props => [host, port]; |
|
116 | + | ||
117 | + | @override |
|
118 | + | String toString() { |
|
119 | + | return 'LCDInfo {' |
|
120 | + | 'host: $host, ' |
|
121 | + | 'port: $port ' |
|
122 | + | '}'; |
|
123 | + | } |
|
124 | + | } |
|
125 | + | ||
6 | 126 | /// Contains the information of a generic Cosmos-based network. |
|
7 | 127 | @JsonSerializable(explicitToJson: true) |
|
8 | 128 | class NetworkInfo extends Equatable { |
@@ -10,30 +130,31 @@
Loading
10 | 130 | @JsonKey(name: 'bech32_hrp', required: true) |
|
11 | 131 | final String bech32Hrp; |
|
12 | 132 | ||
13 | - | /// URL of the fullnode to be used when querying data and sending transactions. |
|
14 | - | @JsonKey(name: 'full_node_host', required: true) |
|
15 | - | final String fullNodeHost; |
|
16 | - | ||
17 | - | /// Port of the LCD endpoint used to query some chaing data. |
|
18 | - | @JsonKey(name: 'lcd_port', defaultValue: 1317) |
|
19 | - | final int lcdPort; |
|
20 | - | ||
21 | - | /// Returns the full endpoint to the LCD APIs. |
|
22 | - | String get lcdEndpoint { |
|
23 | - | return '$fullNodeHost:$lcdPort'; |
|
24 | - | } |
|
133 | + | /// Information about the LCD endpoint to use |
|
134 | + | @JsonKey(name: 'lcdInfo') |
|
135 | + | final LCDInfo lcdInfo; |
|
25 | 136 | ||
26 | - | /// Port of the gRPC endpoint used to query some chain data. |
|
27 | - | @JsonKey(name: 'grpc_port', defaultValue: 9090) |
|
28 | - | final int gRPCPort; |
|
137 | + | /// Information about the gRPC endpoint to use |
|
138 | + | @JsonKey(name: 'grpcInfo') |
|
139 | + | final GRPCInfo grpcInfo; |
|
29 | 140 | ||
30 | 141 | NetworkInfo({ |
|
31 | 142 | required this.bech32Hrp, |
|
32 | - | required this.fullNodeHost, |
|
33 | - | this.lcdPort = 1317, |
|
34 | - | this.gRPCPort = 9090, |
|
143 | + | required this.lcdInfo, |
|
144 | + | required this.grpcInfo, |
|
35 | 145 | }); |
|
36 | 146 | ||
147 | + | factory NetworkInfo.fromSingleHost({ |
|
148 | + | required String bech32Hrp, |
|
149 | + | required String host, |
|
150 | + | }) { |
|
151 | + | return NetworkInfo( |
|
152 | + | bech32Hrp: bech32Hrp, |
|
153 | + | lcdInfo: LCDInfo(host: host), |
|
154 | + | grpcInfo: GRPCInfo(host: host), |
|
155 | + | ); |
|
156 | + | } |
|
157 | + | ||
37 | 158 | factory NetworkInfo.fromJson(Map<String, dynamic> json) { |
|
38 | 159 | return _$NetworkInfoFromJson(json); |
|
39 | 160 | } |
@@ -42,18 +163,29 @@
Loading
42 | 163 | return _$NetworkInfoToJson(this); |
|
43 | 164 | } |
|
44 | 165 | ||
166 | + | /// Returns the ClientChannel that should be used to connect |
|
167 | + | /// to the gRPC endpoint. |
|
168 | + | ClientChannel get gRPCChannel { |
|
169 | + | return grpcInfo.getChannel(); |
|
170 | + | } |
|
171 | + | ||
172 | + | /// Returns the endpoint of the REST APIs that should be used to perform |
|
173 | + | /// legacy queries. |
|
174 | + | String get restEndpoint { |
|
175 | + | return lcdInfo.fullUrl; |
|
176 | + | } |
|
177 | + | ||
45 | 178 | @override |
|
46 | 179 | List<Object> get props { |
|
47 | - | return [bech32Hrp, fullNodeHost, lcdPort, gRPCPort]; |
|
180 | + | return [bech32Hrp, lcdInfo, grpcInfo]; |
|
48 | 181 | } |
|
49 | 182 | ||
50 | 183 | @override |
|
51 | 184 | String toString() { |
|
52 | 185 | return '{ ' |
|
53 | - | 'bech32Hrp: $bech32Hrp, ' |
|
54 | - | 'fullNodeHost: $fullNodeHost, ' |
|
55 | - | 'lcdPort: $lcdPort, ' |
|
56 | - | 'gRPCPort: $gRPCPort ' |
|
186 | + | 'bech32: $bech32Hrp, ' |
|
187 | + | 'lcdInfo: $lcdInfo, ' |
|
188 | + | 'grpcInfo: $grpcInfo ' |
|
57 | 189 | '}'; |
|
58 | 190 | } |
|
59 | 191 | } |
Files | Coverage |
---|---|
lib | 79.70% |
Project Totals (27 files) | 79.70% |
877856818
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file.
The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files.
The size and color of each slice is representing the number of statements and the coverage, respectively.