mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-03 09:19:22 +00:00
update (ba)nano servers
This commit is contained in:
parent
203744d4f0
commit
130e1b37d6
4 changed files with 107 additions and 60 deletions
|
@ -1,9 +1,10 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:nanodart/nanodart.dart';
|
import 'package:nanodart/nanodart.dart';
|
||||||
|
|
||||||
import '../networking/http.dart';
|
import '../networking/http.dart';
|
||||||
import 'tor_service.dart';
|
|
||||||
import '../utilities/prefs.dart';
|
import '../utilities/prefs.dart';
|
||||||
|
import 'tor_service.dart';
|
||||||
|
|
||||||
class NanoAPI {
|
class NanoAPI {
|
||||||
static Future<
|
static Future<
|
||||||
|
@ -14,6 +15,7 @@ class NanoAPI {
|
||||||
required Uri server,
|
required Uri server,
|
||||||
required bool representative,
|
required bool representative,
|
||||||
required String account,
|
required String account,
|
||||||
|
required Map<String, String> headers,
|
||||||
}) async {
|
}) async {
|
||||||
NAccountInfo? accountInfo;
|
NAccountInfo? accountInfo;
|
||||||
Exception? exception;
|
Exception? exception;
|
||||||
|
@ -23,9 +25,7 @@ class NanoAPI {
|
||||||
try {
|
try {
|
||||||
final response = await client.post(
|
final response = await client.post(
|
||||||
url: server,
|
url: server,
|
||||||
headers: {
|
headers: headers,
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
"action": "account_info",
|
"action": "account_info",
|
||||||
"representative": "true",
|
"representative": "true",
|
||||||
|
@ -64,6 +64,7 @@ class NanoAPI {
|
||||||
required String balance,
|
required String balance,
|
||||||
required String privateKey,
|
required String privateKey,
|
||||||
required String work,
|
required String work,
|
||||||
|
required Map<String, String> headers,
|
||||||
}) async {
|
}) async {
|
||||||
final Map<String, String> block = {
|
final Map<String, String> block = {
|
||||||
"type": "state",
|
"type": "state",
|
||||||
|
@ -98,7 +99,11 @@ class NanoAPI {
|
||||||
|
|
||||||
block["signature"] = signature;
|
block["signature"] = signature;
|
||||||
|
|
||||||
final map = await postBlock(server: server, block: block);
|
final map = await postBlock(
|
||||||
|
server: server,
|
||||||
|
block: block,
|
||||||
|
headers: headers,
|
||||||
|
);
|
||||||
|
|
||||||
if (map is Map && map["error"] != null) {
|
if (map is Map && map["error"] != null) {
|
||||||
throw Exception(map["error"].toString());
|
throw Exception(map["error"].toString());
|
||||||
|
@ -111,14 +116,13 @@ class NanoAPI {
|
||||||
static Future<dynamic> postBlock({
|
static Future<dynamic> postBlock({
|
||||||
required Uri server,
|
required Uri server,
|
||||||
required Map<String, dynamic> block,
|
required Map<String, dynamic> block,
|
||||||
|
required Map<String, String> headers,
|
||||||
}) async {
|
}) async {
|
||||||
final HTTP client = HTTP();
|
final HTTP client = HTTP();
|
||||||
|
|
||||||
final response = await client.post(
|
final response = await client.post(
|
||||||
url: server,
|
url: server,
|
||||||
headers: {
|
headers: headers,
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
"action": "process",
|
"action": "process",
|
||||||
"json_block": "true",
|
"json_block": "true",
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:nanodart/nanodart.dart';
|
import 'package:nanodart/nanodart.dart';
|
||||||
|
|
||||||
import '../../../models/isar/models/blockchain_data/address.dart';
|
import '../../../models/isar/models/blockchain_data/address.dart';
|
||||||
import '../../../models/node_model.dart';
|
import '../../../models/node_model.dart';
|
||||||
import '../../../utilities/default_nodes.dart';
|
import '../../../utilities/default_nodes.dart';
|
||||||
|
@ -66,7 +67,8 @@ class Banano extends NanoCurrency {
|
||||||
switch (network) {
|
switch (network) {
|
||||||
case CryptoCurrencyNetwork.main:
|
case CryptoCurrencyNetwork.main:
|
||||||
return NodeModel(
|
return NodeModel(
|
||||||
host: "https://kaliumapi.appditto.com/api",
|
// host: "https://kaliumapi.appditto.com/api",
|
||||||
|
host: "https://nodes.nanswap.com/BAN",
|
||||||
port: 443,
|
port: 443,
|
||||||
name: DefaultNodes.defaultName,
|
name: DefaultNodes.defaultName,
|
||||||
id: DefaultNodes.buildId(this),
|
id: DefaultNodes.buildId(this),
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:nanodart/nanodart.dart';
|
import 'package:nanodart/nanodart.dart';
|
||||||
|
|
||||||
import '../../../models/isar/models/isar_models.dart';
|
import '../../../models/isar/models/isar_models.dart';
|
||||||
import '../../../models/node_model.dart';
|
import '../../../models/node_model.dart';
|
||||||
import '../../../utilities/default_nodes.dart';
|
import '../../../utilities/default_nodes.dart';
|
||||||
|
@ -66,7 +67,8 @@ class Nano extends NanoCurrency {
|
||||||
switch (network) {
|
switch (network) {
|
||||||
case CryptoCurrencyNetwork.main:
|
case CryptoCurrencyNetwork.main:
|
||||||
return NodeModel(
|
return NodeModel(
|
||||||
host: "https://rainstorm.city/api",
|
// host: "https://rainstorm.city/api",
|
||||||
|
host: "https://nodes.nanswap.com/XNO",
|
||||||
port: 443,
|
port: 443,
|
||||||
name: DefaultNodes.defaultName,
|
name: DefaultNodes.defaultName,
|
||||||
id: DefaultNodes.buildId(this),
|
id: DefaultNodes.buildId(this),
|
||||||
|
|
|
@ -25,6 +25,17 @@ import '../intermediate/bip39_wallet.dart';
|
||||||
// const _kWorkServer = "https://rpc.nano.to";
|
// const _kWorkServer = "https://rpc.nano.to";
|
||||||
const _kWorkServer = "https://nodes.nanswap.com/XNO";
|
const _kWorkServer = "https://nodes.nanswap.com/XNO";
|
||||||
|
|
||||||
|
Map<String, String> _buildHeaders(String url) {
|
||||||
|
final result = {
|
||||||
|
'Content-type': 'application/json',
|
||||||
|
};
|
||||||
|
if (url
|
||||||
|
case "https://nodes.nanswap.com/XNO" || "https://nodes.nanswap.com/BAN") {
|
||||||
|
result["nodes-api-key"] = kNanoSwapRpcApiKey;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
// since nano based coins only have a single address/account we can cache
|
// since nano based coins only have a single address/account we can cache
|
||||||
// the address instead of fetching from db every time we need it in certain
|
// the address instead of fetching from db every time we need it in certain
|
||||||
|
@ -39,10 +50,7 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
return _httpClient
|
return _httpClient
|
||||||
.post(
|
.post(
|
||||||
url: Uri.parse(_kWorkServer), // this should be a
|
url: Uri.parse(_kWorkServer), // this should be a
|
||||||
headers: {
|
headers: _buildHeaders(_kWorkServer),
|
||||||
'Content-type': 'application/json',
|
|
||||||
"nodes-api-key": kNanoSwapRpcApiKey,
|
|
||||||
},
|
|
||||||
body: json.encode(
|
body: json.encode(
|
||||||
{
|
{
|
||||||
"action": "work_generate",
|
"action": "work_generate",
|
||||||
|
@ -99,10 +107,6 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
// TODO: the opening block of an account is a special case
|
// TODO: the opening block of an account is a special case
|
||||||
bool openBlock = false;
|
bool openBlock = false;
|
||||||
|
|
||||||
final headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
};
|
|
||||||
|
|
||||||
// first check if the account is open:
|
// first check if the account is open:
|
||||||
// get the account info (we need the frontier and representative):
|
// get the account info (we need the frontier and representative):
|
||||||
final infoBody = jsonEncode({
|
final infoBody = jsonEncode({
|
||||||
|
@ -110,9 +114,10 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
"representative": "true",
|
"representative": "true",
|
||||||
"account": publicAddress,
|
"account": publicAddress,
|
||||||
});
|
});
|
||||||
|
final node = getCurrentNode();
|
||||||
final infoResponse = await _httpClient.post(
|
final infoResponse = await _httpClient.post(
|
||||||
url: Uri.parse(getCurrentNode().host),
|
url: Uri.parse(node.host),
|
||||||
headers: headers,
|
headers: _buildHeaders(node.host),
|
||||||
body: infoBody,
|
body: infoBody,
|
||||||
proxyInfo: prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
proxyInfo: prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
||||||
);
|
);
|
||||||
|
@ -130,8 +135,8 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
});
|
});
|
||||||
|
|
||||||
final balanceResponse = await _httpClient.post(
|
final balanceResponse = await _httpClient.post(
|
||||||
url: Uri.parse(getCurrentNode().host),
|
url: Uri.parse(node.host),
|
||||||
headers: headers,
|
headers: _buildHeaders(node.host),
|
||||||
body: balanceBody,
|
body: balanceBody,
|
||||||
proxyInfo: prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
proxyInfo: prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
||||||
);
|
);
|
||||||
|
@ -204,8 +209,8 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
"block": receiveBlock,
|
"block": receiveBlock,
|
||||||
});
|
});
|
||||||
final processResponse = await _httpClient.post(
|
final processResponse = await _httpClient.post(
|
||||||
url: Uri.parse(getCurrentNode().host),
|
url: Uri.parse(node.host),
|
||||||
headers: headers,
|
headers: _buildHeaders(node.host),
|
||||||
body: processBody,
|
body: processBody,
|
||||||
proxyInfo: prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
proxyInfo: prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
||||||
);
|
);
|
||||||
|
@ -218,14 +223,14 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _confirmAllReceivable(String accountAddress) async {
|
Future<void> _confirmAllReceivable(String accountAddress) async {
|
||||||
|
final node = getCurrentNode();
|
||||||
final receivableResponse = await _httpClient.post(
|
final receivableResponse = await _httpClient.post(
|
||||||
url: Uri.parse(getCurrentNode().host),
|
url: Uri.parse(node.host),
|
||||||
headers: {"Content-Type": "application/json"},
|
headers: _buildHeaders(node.host),
|
||||||
body: jsonEncode({
|
body: jsonEncode({
|
||||||
"action": "receivable",
|
"action": "receivable",
|
||||||
"source": "true",
|
"source": "true",
|
||||||
"account": accountAddress,
|
"account": accountAddress,
|
||||||
"count": "-1",
|
|
||||||
}),
|
}),
|
||||||
proxyInfo: prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
proxyInfo: prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
||||||
);
|
);
|
||||||
|
@ -253,10 +258,12 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
final address =
|
final address =
|
||||||
(_cachedAddress ?? await getCurrentReceivingAddress())!.value;
|
(_cachedAddress ?? await getCurrentReceivingAddress())!.value;
|
||||||
|
|
||||||
|
final node = getCurrentNode();
|
||||||
final response = await NanoAPI.getAccountInfo(
|
final response = await NanoAPI.getAccountInfo(
|
||||||
server: serverURI,
|
server: serverURI,
|
||||||
representative: true,
|
representative: true,
|
||||||
account: address,
|
account: address,
|
||||||
|
headers: _buildHeaders(node.host),
|
||||||
);
|
);
|
||||||
|
|
||||||
return response.accountInfo?.representative ??
|
return response.accountInfo?.representative ??
|
||||||
|
@ -265,7 +272,8 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
|
|
||||||
Future<bool> changeRepresentative(String newRepresentative) async {
|
Future<bool> changeRepresentative(String newRepresentative) async {
|
||||||
try {
|
try {
|
||||||
final serverURI = Uri.parse(getCurrentNode().host);
|
final node = getCurrentNode();
|
||||||
|
final serverURI = Uri.parse(node.host);
|
||||||
await updateBalance();
|
await updateBalance();
|
||||||
final balance = info.cachedBalance.spendable.raw.toString();
|
final balance = info.cachedBalance.spendable.raw.toString();
|
||||||
final String privateKey = await _getPrivateKeyFromMnemonic();
|
final String privateKey = await _getPrivateKeyFromMnemonic();
|
||||||
|
@ -276,6 +284,7 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
server: serverURI,
|
server: serverURI,
|
||||||
representative: true,
|
representative: true,
|
||||||
account: address,
|
account: address,
|
||||||
|
headers: _buildHeaders(node.host),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.accountInfo == null) {
|
if (response.accountInfo == null) {
|
||||||
|
@ -293,6 +302,7 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
balance: balance,
|
balance: balance,
|
||||||
privateKey: privateKey,
|
privateKey: privateKey,
|
||||||
work: work!,
|
work: work!,
|
||||||
|
headers: _buildHeaders(node.host),
|
||||||
);
|
);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
rethrow;
|
rethrow;
|
||||||
|
@ -337,11 +347,11 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> pingCheck() async {
|
Future<bool> pingCheck() async {
|
||||||
final uri = Uri.parse(getCurrentNode().host);
|
final node = getCurrentNode();
|
||||||
|
final uri = Uri.parse(node.host);
|
||||||
final response = await _httpClient.post(
|
final response = await _httpClient.post(
|
||||||
url: uri,
|
url: uri,
|
||||||
headers: {"Content-Type": "application/json"},
|
headers: _buildHeaders(node.host),
|
||||||
body: jsonEncode(
|
body: jsonEncode(
|
||||||
{
|
{
|
||||||
"action": "version",
|
"action": "version",
|
||||||
|
@ -390,13 +400,10 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
"account": publicAddress,
|
"account": publicAddress,
|
||||||
});
|
});
|
||||||
|
|
||||||
final headers = {
|
final node = getCurrentNode();
|
||||||
"Content-Type": "application/json",
|
|
||||||
};
|
|
||||||
|
|
||||||
final infoResponse = await _httpClient.post(
|
final infoResponse = await _httpClient.post(
|
||||||
url: Uri.parse(getCurrentNode().host),
|
url: Uri.parse(node.host),
|
||||||
headers: headers,
|
headers: _buildHeaders(node.host),
|
||||||
body: infoBody,
|
body: infoBody,
|
||||||
proxyInfo:
|
proxyInfo:
|
||||||
prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
||||||
|
@ -449,8 +456,8 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
"block": sendBlock,
|
"block": sendBlock,
|
||||||
});
|
});
|
||||||
final processResponse = await _httpClient.post(
|
final processResponse = await _httpClient.post(
|
||||||
url: Uri.parse(getCurrentNode().host),
|
url: Uri.parse(node.host),
|
||||||
headers: headers,
|
headers: _buildHeaders(node.host),
|
||||||
body: processBody,
|
body: processBody,
|
||||||
proxyInfo:
|
proxyInfo:
|
||||||
prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
||||||
|
@ -491,6 +498,49 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// recurse over api calls if required
|
||||||
|
// (if more than 200 history items)
|
||||||
|
Future<Map<String, dynamic>> _fetchAll(
|
||||||
|
String publicAddress,
|
||||||
|
String? previous,
|
||||||
|
Map<String, dynamic>? data,
|
||||||
|
) async {
|
||||||
|
final node = getCurrentNode();
|
||||||
|
final body = {
|
||||||
|
"action": "account_history",
|
||||||
|
"account": publicAddress,
|
||||||
|
"count": "200",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (previous is String) {
|
||||||
|
body["head"] = previous;
|
||||||
|
}
|
||||||
|
|
||||||
|
final response = await _httpClient.post(
|
||||||
|
url: Uri.parse(node.host),
|
||||||
|
headers: _buildHeaders(node.host),
|
||||||
|
body: jsonEncode(body),
|
||||||
|
proxyInfo: prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
||||||
|
);
|
||||||
|
|
||||||
|
// this should really have proper type checking and error propagation but I'm out of time
|
||||||
|
final newData =
|
||||||
|
Map<String, dynamic>.from((await jsonDecode(response.body)) as Map);
|
||||||
|
|
||||||
|
if (newData["previous"] is String) {
|
||||||
|
if (data?["history"] is List) {
|
||||||
|
(newData["history"] as List).addAll(data!["history"] as List);
|
||||||
|
}
|
||||||
|
return await _fetchAll(
|
||||||
|
publicAddress,
|
||||||
|
newData["previous"] as String,
|
||||||
|
newData,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newData;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> updateTransactions() async {
|
Future<void> updateTransactions() async {
|
||||||
await updateChainHeight();
|
await updateChainHeight();
|
||||||
|
@ -498,17 +548,9 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
(_cachedAddress ?? await getCurrentReceivingAddress())!;
|
(_cachedAddress ?? await getCurrentReceivingAddress())!;
|
||||||
final String publicAddress = receivingAddress.value;
|
final String publicAddress = receivingAddress.value;
|
||||||
await _confirmAllReceivable(publicAddress);
|
await _confirmAllReceivable(publicAddress);
|
||||||
final response = await _httpClient.post(
|
|
||||||
url: Uri.parse(getCurrentNode().host),
|
final data = await _fetchAll(publicAddress, null, null);
|
||||||
headers: {"Content-Type": "application/json"},
|
|
||||||
body: jsonEncode({
|
|
||||||
"action": "account_history",
|
|
||||||
"account": publicAddress,
|
|
||||||
"count": "-1",
|
|
||||||
}),
|
|
||||||
proxyInfo: prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
|
||||||
);
|
|
||||||
final data = await jsonDecode(response.body);
|
|
||||||
final transactions = data["history"] is List
|
final transactions = data["history"] is List
|
||||||
? data["history"] as List<dynamic>
|
? data["history"] as List<dynamic>
|
||||||
: <dynamic>[];
|
: <dynamic>[];
|
||||||
|
@ -577,13 +619,11 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
"action": "account_balance",
|
"action": "account_balance",
|
||||||
"account": addressString,
|
"account": addressString,
|
||||||
});
|
});
|
||||||
final headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
};
|
|
||||||
|
|
||||||
|
final node = getCurrentNode();
|
||||||
final response = await _httpClient.post(
|
final response = await _httpClient.post(
|
||||||
url: Uri.parse(getCurrentNode().host),
|
url: Uri.parse(node.host),
|
||||||
headers: headers,
|
headers: _buildHeaders(node.host),
|
||||||
body: body,
|
body: body,
|
||||||
proxyInfo:
|
proxyInfo:
|
||||||
prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
||||||
|
@ -628,12 +668,11 @@ mixin NanoInterface<T extends NanoCurrency> on Bip39Wallet<T> {
|
||||||
"action": "account_info",
|
"action": "account_info",
|
||||||
"account": publicAddress,
|
"account": publicAddress,
|
||||||
});
|
});
|
||||||
final headers = {
|
|
||||||
"Content-Type": "application/json",
|
final node = getCurrentNode();
|
||||||
};
|
|
||||||
final infoResponse = await _httpClient.post(
|
final infoResponse = await _httpClient.post(
|
||||||
url: Uri.parse(getCurrentNode().host),
|
url: Uri.parse(node.host),
|
||||||
headers: headers,
|
headers: _buildHeaders(node.host),
|
||||||
body: infoBody,
|
body: infoBody,
|
||||||
proxyInfo:
|
proxyInfo:
|
||||||
prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
prefs.useTor ? TorService.sharedInstance.getProxyInfo() : null,
|
||||||
|
|
Loading…
Reference in a new issue