subscan.dart 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import 'dart:async';
  2. import 'dart:convert';
  3. import 'dart:io';
  4. import 'dart:isolate';
  5. import 'package:flutter/foundation.dart';
  6. import 'package:http/http.dart';
  7. const int tx_list_page_size = 10;
  8. class MyHttpOverrides extends HttpOverrides {
  9. @override
  10. HttpClient createHttpClient(SecurityContext? context) {
  11. return super.createHttpClient(context)
  12. ..badCertificateCallback =
  13. (X509Certificate cert, String host, int port) => true;
  14. }
  15. }
  16. class SubScanRequestParams {
  17. SubScanRequestParams({
  18. this.sendPort,
  19. this.network,
  20. this.address,
  21. this.page,
  22. this.row,
  23. this.module,
  24. this.call,
  25. });
  26. /// exec in isolate with a message send port
  27. SendPort? sendPort;
  28. String? network;
  29. String? address;
  30. int? page;
  31. int? row;
  32. String? module;
  33. String? call;
  34. }
  35. const post_headers = {"Content-type": "application/json", "Accept": "*/*"};
  36. /// Querying txs from [subscan.io](https://subscan.io).
  37. class SubScanApi {
  38. final String moduleBalances = 'Balances';
  39. final String moduleStaking = 'Staking';
  40. final String moduleDemocracy = 'Democracy';
  41. final String moduleRecovery = 'Recovery';
  42. static String getSnEndpoint(String network) {
  43. return 'https://$network.api.subscan.io/api/v2/scan';
  44. }
  45. /// do the request in an isolate to avoid UI stall
  46. /// in IOS due to https issue: https://github.com/dart-lang/sdk/issues/41519
  47. Future<Map> fetchTransfersAsync(
  48. String address,
  49. int page, {
  50. int size = tx_list_page_size,
  51. String network = 'kusama',
  52. }) async {
  53. Completer completer = new Completer<Map>();
  54. ReceivePort receivePort = ReceivePort();
  55. Isolate isolateIns = await Isolate.spawn(
  56. SubScanApi.fetchTransfers,
  57. SubScanRequestParams(
  58. sendPort: receivePort.sendPort,
  59. network: network,
  60. address: address,
  61. page: page,
  62. row: size,
  63. ));
  64. receivePort.listen((msg) {
  65. receivePort.close();
  66. isolateIns.kill(priority: Isolate.immediate);
  67. completer.complete(msg);
  68. });
  69. return completer.future as FutureOr<Map<dynamic, dynamic>>;
  70. }
  71. Future<Map> fetchTxsAsync(
  72. String module, {
  73. String? call,
  74. int page = 0,
  75. int size = tx_list_page_size,
  76. String? sender,
  77. String network = 'kusama',
  78. }) async {
  79. Completer completer = new Completer<Map>();
  80. ReceivePort receivePort = ReceivePort();
  81. Isolate isolateIns = await Isolate.spawn(
  82. SubScanApi.fetchTxs,
  83. SubScanRequestParams(
  84. sendPort: receivePort.sendPort,
  85. network: network,
  86. module: module,
  87. call: call,
  88. address: sender,
  89. page: page,
  90. row: size,
  91. ));
  92. receivePort.listen((msg) {
  93. receivePort.close();
  94. isolateIns.kill(priority: Isolate.immediate);
  95. completer.complete(msg);
  96. });
  97. return completer.future as FutureOr<Map<dynamic, dynamic>>;
  98. }
  99. Future<Map> fetchRewardTxsAsync({
  100. int page = 0,
  101. int size = tx_list_page_size,
  102. String? sender,
  103. String network = 'kusama',
  104. }) async {
  105. Completer completer = new Completer<Map>();
  106. ReceivePort receivePort = ReceivePort();
  107. Isolate isolateIns = await Isolate.spawn(
  108. SubScanApi.fetchRewardTxs,
  109. SubScanRequestParams(
  110. sendPort: receivePort.sendPort,
  111. network: network,
  112. address: sender,
  113. page: page,
  114. row: size,
  115. ));
  116. receivePort.listen((msg) {
  117. receivePort.close();
  118. isolateIns.kill(priority: Isolate.immediate);
  119. completer.complete(msg);
  120. });
  121. return completer.future as FutureOr<Map<dynamic, dynamic>>;
  122. }
  123. static Future<Map?> fetchTransfers(SubScanRequestParams params) async {
  124. String url = '${getSnEndpoint(params.network!)}/transfers';
  125. String body = jsonEncode({
  126. "page": params.page,
  127. "row": params.row,
  128. "address": params.address,
  129. });
  130. Response res =
  131. await post(Uri.parse(url), headers: post_headers, body: body);
  132. final obj = await compute(jsonDecode, res.body);
  133. if (params.sendPort != null) {
  134. params.sendPort!.send(obj['data']);
  135. }
  136. return obj['data'];
  137. }
  138. static Future<Map?> fetchTxs(SubScanRequestParams para) async {
  139. String url = '${getSnEndpoint(para.network!)}/extrinsics';
  140. Map params = {
  141. "page": para.page,
  142. "row": para.row,
  143. "module": para.module,
  144. };
  145. if (para.address != null) {
  146. params['address'] = para.address;
  147. }
  148. if (para.call != null) {
  149. params['call'] = para.call;
  150. }
  151. String body = jsonEncode(params);
  152. Response res =
  153. await post(Uri.parse(url), headers: post_headers, body: body);
  154. final obj = await compute(jsonDecode, res.body);
  155. if (para.sendPort != null) {
  156. para.sendPort!.send(obj['data']);
  157. }
  158. return obj['data'];
  159. }
  160. static Future<Map?> fetchRewardTxs(SubScanRequestParams para) async {
  161. String url = '${getSnEndpoint(para.network!)}/account/reward_slash';
  162. Map params = {
  163. "address": para.address,
  164. "page": para.page,
  165. "row": para.row,
  166. };
  167. String body = jsonEncode(params);
  168. Response res =
  169. await post(Uri.parse(url), headers: post_headers, body: body);
  170. final obj = await compute(jsonDecode, res.body);
  171. if (para.sendPort != null) {
  172. para.sendPort!.send(obj['data']);
  173. }
  174. return obj['data'];
  175. }
  176. }