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
This commit is contained in:
Matthew Fosse 2024-12-30 11:46:09 -05:00 committed by GitHub
parent 214fc7113c
commit 831a6d9f9a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 62 additions and 28 deletions

View file

@ -99,8 +99,8 @@ class Node extends HiveObject with Keyable {
case WalletType.polygon: case WalletType.polygon:
case WalletType.solana: case WalletType.solana:
case WalletType.tron: case WalletType.tron:
return Uri.parse( return Uri.parse(
"http${isSSL ? "s" : ""}://$uriRaw${path!.startsWith("/") ? path : "/$path"}"); "http${isSSL ? "s" : ""}://$uriRaw${path!.startsWith("/") ? path : "/$path"}");
case WalletType.none: case WalletType.none:
throw Exception('Unexpected type ${type.toString()} for Node uri'); throw Exception('Unexpected type ${type.toString()} for Node uri');
} }
@ -152,6 +152,7 @@ class Node extends HiveObject with Keyable {
return requestMoneroNode(); return requestMoneroNode();
case WalletType.nano: case WalletType.nano:
case WalletType.banano: case WalletType.banano:
return requestNanoNode();
case WalletType.bitcoin: case WalletType.bitcoin:
case WalletType.litecoin: case WalletType.litecoin:
case WalletType.bitcoinCash: case WalletType.bitcoinCash:
@ -198,14 +199,16 @@ class Node extends HiveObject with Keyable {
); );
client.close(); client.close();
if (( if ((response.body.contains("400 Bad Request") // Some other generic error
response.body.contains("400 Bad Request") // Some other generic error ||
|| response.body.contains("plain HTTP request was sent to HTTPS port") // Cloudflare response.body.contains("plain HTTP request was sent to HTTPS port") // Cloudflare
|| response.headers["location"] != null // Generic reverse proxy ||
|| response.body.contains("301 Moved Permanently") // Poorly configured generic reverse proxy response.headers["location"] != null // Generic reverse proxy
) && !(useSSL??false) ||
) { response.body
.contains("301 Moved Permanently") // Poorly configured generic reverse proxy
) &&
!(useSSL ?? false)) {
final oldUseSSL = useSSL; final oldUseSSL = useSSL;
useSSL = true; useSSL = true;
try { try {
@ -271,6 +274,35 @@ class Node extends HiveObject with Keyable {
} }
} }
Future<bool> requestNanoNode() async {
try {
final response = await http.post(
uri,
headers: {
"Content-Type": "application/json",
"nano-app": "cake-wallet"
},
body: jsonEncode(
{
"action": "account_balance",
"account": "nano_38713x95zyjsqzx6nm1dsom1jmm668owkeb9913ax6nfgj15az3nu8xkx579",
},
),
);
final data = await jsonDecode(response.body);
if (response.statusCode != 200 ||
data["error"] != null ||
data["balance"] == null ||
data["receivable"] == null) {
throw Exception(
"Error while trying to get balance! ${data["error"] != null ? data["error"] : ""}");
}
return true;
} catch (_) {
return false;
}
}
Future<bool> requestEthereumServer() async { Future<bool> requestEthereumServer() async {
try { try {
final response = await http.get( final response = await http.get(

View file

@ -54,12 +54,12 @@ class NanoClient {
} }
} }
Map<String, String> getHeaders() { Map<String, String> getHeaders(String host) {
final headers = Map<String, String>.from(CAKE_HEADERS); final headers = Map<String, String>.from(CAKE_HEADERS);
if (_node!.uri.host == "rpc.nano.to") { if (host == "rpc.nano.to") {
headers["key"] = nano_secrets.nano2ApiKey; headers["key"] = nano_secrets.nano2ApiKey;
} }
if (_node!.uri.host == "nano.nownodes.io") { if (host == "nano.nownodes.io") {
headers["api-key"] = nano_secrets.nanoNowNodesApiKey; headers["api-key"] = nano_secrets.nanoNowNodesApiKey;
} }
return headers; return headers;
@ -68,7 +68,7 @@ class NanoClient {
Future<NanoBalance> getBalance(String address) async { Future<NanoBalance> getBalance(String address) async {
final response = await http.post( final response = await http.post(
_node!.uri, _node!.uri,
headers: getHeaders(), headers: getHeaders(_node!.uri.host),
body: jsonEncode( body: jsonEncode(
{ {
"action": "account_balance", "action": "account_balance",
@ -95,7 +95,7 @@ class NanoClient {
try { try {
final response = await http.post( final response = await http.post(
_node!.uri, _node!.uri,
headers: getHeaders(), headers: getHeaders(_node!.uri.host),
body: jsonEncode( body: jsonEncode(
{ {
"action": "account_info", "action": "account_info",
@ -116,7 +116,7 @@ class NanoClient {
try { try {
final response = await http.post( final response = await http.post(
_node!.uri, _node!.uri,
headers: CAKE_HEADERS, headers: getHeaders(_node!.uri.host),
body: jsonEncode( body: jsonEncode(
{ {
"action": "block_info", "action": "block_info",
@ -183,7 +183,7 @@ class NanoClient {
Future<String> requestWork(String hash) async { Future<String> requestWork(String hash) async {
final response = await http.post( final response = await http.post(
_powNode!.uri, _powNode!.uri,
headers: getHeaders(), headers: getHeaders(_powNode!.uri.host),
body: json.encode( body: json.encode(
{ {
"action": "work_generate", "action": "work_generate",
@ -226,7 +226,7 @@ class NanoClient {
final processResponse = await http.post( final processResponse = await http.post(
_node!.uri, _node!.uri,
headers: getHeaders(), headers: getHeaders(_node!.uri.host),
body: processBody, body: processBody,
); );
@ -425,7 +425,7 @@ class NanoClient {
}); });
final processResponse = await http.post( final processResponse = await http.post(
_node!.uri, _node!.uri,
headers: getHeaders(), headers: getHeaders(_node!.uri.host),
body: processBody, body: processBody,
); );
@ -441,7 +441,7 @@ class NanoClient {
required String privateKey, required String privateKey,
}) async { }) async {
final receivableResponse = await http.post(_node!.uri, final receivableResponse = await http.post(_node!.uri,
headers: getHeaders(), headers: getHeaders(_node!.uri.host),
body: jsonEncode({ body: jsonEncode({
"action": "receivable", "action": "receivable",
"account": destinationAddress, "account": destinationAddress,
@ -493,7 +493,7 @@ class NanoClient {
Future<List<NanoTransactionModel>> fetchTransactions(String address) async { Future<List<NanoTransactionModel>> fetchTransactions(String address) async {
try { try {
final response = await http.post(_node!.uri, final response = await http.post(_node!.uri,
headers: getHeaders(), headers: getHeaders(_node!.uri.host),
body: jsonEncode({ body: jsonEncode({
"action": "account_history", "action": "account_history",
"account": address, "account": address,
@ -509,15 +509,16 @@ class NanoClient {
.map<NanoTransactionModel>((transaction) => NanoTransactionModel.fromJson(transaction)) .map<NanoTransactionModel>((transaction) => NanoTransactionModel.fromJson(transaction))
.toList(); .toList();
} catch (e) { } catch (e) {
printV(e); printV("error fetching transactions: $e");
return []; rethrow;
} }
} }
Future<List<N2Node>> getN2Reps() async { Future<List<N2Node>> getN2Reps() async {
final uri = Uri.parse(N2_REPS_ENDPOINT);
final response = await http.post( final response = await http.post(
Uri.parse(N2_REPS_ENDPOINT), uri,
headers: CAKE_HEADERS, headers: getHeaders(uri.host),
body: jsonEncode({"action": "reps"}), body: jsonEncode({"action": "reps"}),
); );
try { try {
@ -531,9 +532,10 @@ class NanoClient {
} }
Future<int> getRepScore(String rep) async { Future<int> getRepScore(String rep) async {
final uri = Uri.parse(N2_REPS_ENDPOINT);
final response = await http.post( final response = await http.post(
Uri.parse(N2_REPS_ENDPOINT), uri,
headers: CAKE_HEADERS, headers: getHeaders(uri.host),
body: jsonEncode({ body: jsonEncode({
"action": "rep_info", "action": "rep_info",
"account": rep, "account": rep,

View file

@ -505,7 +505,7 @@ Future<void> updateNanoNodeList({required Box<Node> nodes}) async {
]; ];
// add new nodes: // add new nodes:
for (final node in nodeList) { for (final node in nodeList) {
if (listOfNewEndpoints.contains(node.uriRaw)) { if (listOfNewEndpoints.contains(node.uriRaw) && !nodes.values.contains(node)) {
await nodes.add(node); await nodes.add(node);
} }
} }