mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2024-12-24 04:19:23 +00:00
142 lines
3.4 KiB
Dart
142 lines
3.4 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:nanodart/nanodart.dart';
|
|
import 'package:stackwallet/networking/http.dart';
|
|
import 'package:stackwallet/services/tor_service.dart';
|
|
import 'package:stackwallet/utilities/prefs.dart';
|
|
|
|
class NanoAPI {
|
|
static Future<
|
|
({
|
|
NAccountInfo? accountInfo,
|
|
Exception? exception,
|
|
})> getAccountInfo({
|
|
required Uri server,
|
|
required bool representative,
|
|
required String account,
|
|
}) async {
|
|
NAccountInfo? accountInfo;
|
|
Exception? exception;
|
|
|
|
HTTP client = HTTP();
|
|
|
|
try {
|
|
final response = await client.post(
|
|
url: server,
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: jsonEncode({
|
|
"action": "account_info",
|
|
"representative": "true",
|
|
"account": account,
|
|
}),
|
|
proxyInfo: Prefs.instance.useTor
|
|
? TorService.sharedInstance.getProxyInfo()
|
|
: null,
|
|
);
|
|
|
|
final map = jsonDecode(response.body);
|
|
|
|
if (map is Map && map["error"] != null) {
|
|
throw Exception(map["error"].toString());
|
|
}
|
|
|
|
accountInfo = NAccountInfo(
|
|
frontier: map["frontier"] as String,
|
|
representative: map["representative"] as String,
|
|
);
|
|
} on Exception catch (e) {
|
|
exception = e;
|
|
} catch (e) {
|
|
exception = Exception(e.toString());
|
|
}
|
|
|
|
return (accountInfo: accountInfo, exception: exception);
|
|
}
|
|
|
|
static Future<bool> changeRepresentative({
|
|
required Uri server,
|
|
required int accountType,
|
|
required String account,
|
|
required String newRepresentative,
|
|
required String previousBlock,
|
|
required String balance,
|
|
required String privateKey,
|
|
required String work,
|
|
}) async {
|
|
Map<String, String> block = {
|
|
"type": "state",
|
|
"account": account,
|
|
"previous": previousBlock,
|
|
"representative": newRepresentative,
|
|
"balance": balance,
|
|
"link":
|
|
"0000000000000000000000000000000000000000000000000000000000000000",
|
|
"work": work,
|
|
};
|
|
|
|
final String hash;
|
|
|
|
try {
|
|
hash = NanoBlocks.computeStateHash(
|
|
accountType,
|
|
account,
|
|
previousBlock,
|
|
newRepresentative,
|
|
BigInt.parse(balance),
|
|
block["link"] as String,
|
|
);
|
|
} catch (e) {
|
|
if (e is RangeError) {
|
|
throw Exception("Invalid representative format");
|
|
}
|
|
rethrow;
|
|
}
|
|
|
|
final signature = NanoSignatures.signBlock(hash, privateKey);
|
|
|
|
block["signature"] = signature;
|
|
|
|
final map = await postBlock(server: server, block: block);
|
|
|
|
if (map is Map && map["error"] != null) {
|
|
throw Exception(map["error"].toString());
|
|
}
|
|
|
|
return map["error"] == null;
|
|
}
|
|
|
|
// TODO: GET RID OF DYNAMIC AND USED TYPED DATA
|
|
static Future<dynamic> postBlock({
|
|
required Uri server,
|
|
required Map<String, dynamic> block,
|
|
}) async {
|
|
HTTP client = HTTP();
|
|
|
|
final response = await client.post(
|
|
url: server,
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: jsonEncode({
|
|
"action": "process",
|
|
"json_block": "true",
|
|
"subtype": "change",
|
|
"block": block,
|
|
}),
|
|
proxyInfo: Prefs.instance.useTor
|
|
? TorService.sharedInstance.getProxyInfo()
|
|
: null,
|
|
);
|
|
|
|
return jsonDecode(response.body);
|
|
}
|
|
}
|
|
|
|
class NAccountInfo {
|
|
final String frontier;
|
|
final String representative;
|
|
|
|
NAccountInfo({required this.frontier, required this.representative});
|
|
}
|