Cw 872 nano enhancements (#1909)
* fix headers on all api calls * fix duplicate nano nodes on fresh install, api key fixes * fix liveness indicators + false positive responses to queries
Matthew Fosse committed
Dec 30, 2024 at 11:46 UTC
831a6d9f9a4449c2971b00e3297f9715e962cdd3
3 files changed
+62
-28
cw_core/lib/node.dart
+42
-10
@@ -99,8 +99,8 @@ class Node extends HiveObject with Keyable {
99
case WalletType.polygon:
100
case WalletType.solana:
101
case WalletType.tron:
102
- return Uri.parse(
103
- "http${isSSL ? "s" : ""}://$uriRaw${path!.startsWith("/") ? path : "/$path"}");
102
+ return Uri.parse(
103
+ "http${isSSL ? "s" : ""}://$uriRaw${path!.startsWith("/") ? path : "/$path"}");
104
case WalletType.none:
105
throw Exception('Unexpected type ${type.toString()} for Node uri');
106
}
@@ -152,6 +152,7 @@ class Node extends HiveObject with Keyable {
152
return requestMoneroNode();
153
case WalletType.nano:
154
case WalletType.banano:
155
+ return requestNanoNode();
156
case WalletType.bitcoin:
157
case WalletType.litecoin:
158
case WalletType.bitcoinCash:
@@ -198,14 +199,16 @@ class Node extends HiveObject with Keyable {
199
);
200
client.close();
201
201
- if ((
202
- response.body.contains("400 Bad Request") // Some other generic error
203
- || response.body.contains("plain HTTP request was sent to HTTPS port") // Cloudflare
204
- || response.headers["location"] != null // Generic reverse proxy
205
- || response.body.contains("301 Moved Permanently") // Poorly configured generic reverse proxy
206
- ) && !(useSSL??false)
207
- ) {
208
-
202
+ if ((response.body.contains("400 Bad Request") // Some other generic error
203
+ ||
204
+ response.body.contains("plain HTTP request was sent to HTTPS port") // Cloudflare
205
+ ||
206
+ response.headers["location"] != null // Generic reverse proxy
207
+ ||
208
+ response.body
209
+ .contains("301 Moved Permanently") // Poorly configured generic reverse proxy
210
+ ) &&
211
+ !(useSSL ?? false)) {
212
final oldUseSSL = useSSL;
213
useSSL = true;
214
try {
@@ -271,6 +274,35 @@ class Node extends HiveObject with Keyable {
274
}
275
}
276
277
+ Future<bool> requestNanoNode() async {
278
+ try {
279
+ final response = await http.post(
280
+ uri,
281
+ headers: {
282
+ "Content-Type": "application/json",
283
+ "nano-app": "cake-wallet"
284
+ },
285
+ body: jsonEncode(
286
+ {
287
+ "action": "account_balance",
288
+ "account": "nano_38713x95zyjsqzx6nm1dsom1jmm668owkeb9913ax6nfgj15az3nu8xkx579",
289
+ },
290
+ ),
291
+ );
292
+ final data = await jsonDecode(response.body);
293
+ if (response.statusCode != 200 ||
294
+ data["error"] != null ||
295
+ data["balance"] == null ||
296
+ data["receivable"] == null) {
297
+ throw Exception(
298
+ "Error while trying to get balance! ${data["error"] != null ? data["error"] : ""}");
299
+ }
300
+ return true;
301
+ } catch (_) {
302
+ return false;
303
+ }
304
+ }
305
+
306
Future<bool> requestEthereumServer() async {
307
try {
308
final response = await http.get(
cw_nano/lib/nano_client.dart
+19
-17
@@ -54,12 +54,12 @@ class NanoClient {
54
}
55
}
56
57
- Map<String, String> getHeaders() {
57
+ Map<String, String> getHeaders(String host) {
58
final headers = Map<String, String>.from(CAKE_HEADERS);
59
- if (_node!.uri.host == "rpc.nano.to") {
59
+ if (host == "rpc.nano.to") {
60
headers["key"] = nano_secrets.nano2ApiKey;
61
}
62
- if (_node!.uri.host == "nano.nownodes.io") {
62
+ if (host == "nano.nownodes.io") {
63
headers["api-key"] = nano_secrets.nanoNowNodesApiKey;
64
}
65
return headers;
@@ -68,7 +68,7 @@ class NanoClient {
68
Future<NanoBalance> getBalance(String address) async {
69
final response = await http.post(
70
_node!.uri,
71
- headers: getHeaders(),
71
+ headers: getHeaders(_node!.uri.host),
72
body: jsonEncode(
73
{
74
"action": "account_balance",
@@ -95,7 +95,7 @@ class NanoClient {
95
try {
96
final response = await http.post(
97
_node!.uri,
98
- headers: getHeaders(),
98
+ headers: getHeaders(_node!.uri.host),
99
body: jsonEncode(
100
{
101
"action": "account_info",
@@ -116,7 +116,7 @@ class NanoClient {
116
try {
117
final response = await http.post(
118
_node!.uri,
119
- headers: CAKE_HEADERS,
119
+ headers: getHeaders(_node!.uri.host),
120
body: jsonEncode(
121
{
122
"action": "block_info",
@@ -183,7 +183,7 @@ class NanoClient {
183
Future<String> requestWork(String hash) async {
184
final response = await http.post(
185
_powNode!.uri,
186
- headers: getHeaders(),
186
+ headers: getHeaders(_powNode!.uri.host),
187
body: json.encode(
188
{
189
"action": "work_generate",
@@ -226,7 +226,7 @@ class NanoClient {
226
227
final processResponse = await http.post(
228
_node!.uri,
229
- headers: getHeaders(),
229
+ headers: getHeaders(_node!.uri.host),
230
body: processBody,
231
);
232
@@ -425,7 +425,7 @@ class NanoClient {
425
});
426
final processResponse = await http.post(
427
_node!.uri,
428
- headers: getHeaders(),
428
+ headers: getHeaders(_node!.uri.host),
429
body: processBody,
430
);
431
@@ -441,7 +441,7 @@ class NanoClient {
441
required String privateKey,
442
}) async {
443
final receivableResponse = await http.post(_node!.uri,
444
- headers: getHeaders(),
444
+ headers: getHeaders(_node!.uri.host),
445
body: jsonEncode({
446
"action": "receivable",
447
"account": destinationAddress,
@@ -493,7 +493,7 @@ class NanoClient {
493
Future<List<NanoTransactionModel>> fetchTransactions(String address) async {
494
try {
495
final response = await http.post(_node!.uri,
496
- headers: getHeaders(),
496
+ headers: getHeaders(_node!.uri.host),
497
body: jsonEncode({
498
"action": "account_history",
499
"account": address,
@@ -509,15 +509,16 @@ class NanoClient {
509
.map<NanoTransactionModel>((transaction) => NanoTransactionModel.fromJson(transaction))
510
.toList();
511
} catch (e) {
512
- printV(e);
513
- return [];
512
+ printV("error fetching transactions: $e");
513
+ rethrow;
514
}
515
}
516
517
Future<List<N2Node>> getN2Reps() async {
518
+ final uri = Uri.parse(N2_REPS_ENDPOINT);
519
final response = await http.post(
519
- Uri.parse(N2_REPS_ENDPOINT),
520
- headers: CAKE_HEADERS,
520
+ uri,
521
+ headers: getHeaders(uri.host),
522
body: jsonEncode({"action": "reps"}),
523
);
524
try {
@@ -531,9 +532,10 @@ class NanoClient {
532
}
533
534
Future<int> getRepScore(String rep) async {
535
+ final uri = Uri.parse(N2_REPS_ENDPOINT);
536
final response = await http.post(
535
- Uri.parse(N2_REPS_ENDPOINT),
536
- headers: CAKE_HEADERS,
537
+ uri,
538
+ headers: getHeaders(uri.host),
539
body: jsonEncode({
540
"action": "rep_info",
541
"account": rep,
lib/entities/default_settings_migration.dart
+1
-1
@@ -505,7 +505,7 @@ Future<void> updateNanoNodeList({required Box<Node> nodes}) async {
505
];
506
// add new nodes:
507
for (final node in nodeList) {
508
- if (listOfNewEndpoints.contains(node.uriRaw)) {
508
+ if (listOfNewEndpoints.contains(node.uriRaw) && !nodes.values.contains(node)) {
509
await nodes.add(node);
510
}
511
}