stack_wallet/lib/services/litescribe_api.dart

96 lines
3.1 KiB
Dart
Raw Normal View History

2023-07-20 19:38:56 +00:00
import 'dart:convert';
import '../dto/ordinals/inscription_data.dart';
import '../dto/ordinals/litescribe_response.dart';
import '../networking/http.dart';
import '../utilities/prefs.dart';
2024-05-27 23:56:22 +00:00
import 'tor_service.dart';
2023-07-20 19:38:56 +00:00
class LitescribeAPI {
static final LitescribeAPI _instance = LitescribeAPI._internal();
factory LitescribeAPI({required String baseUrl}) {
_instance.baseUrl = baseUrl;
return _instance;
}
LitescribeAPI._internal();
2023-09-08 21:09:59 +00:00
HTTP client = HTTP();
2023-07-20 19:38:56 +00:00
late String baseUrl;
Future<LitescribeResponse> _getResponse(String endpoint) async {
2023-09-08 21:09:59 +00:00
final response = await client.get(
url: Uri.parse('$baseUrl$endpoint'),
2023-09-15 19:51:20 +00:00
proxyInfo: Prefs.instance.useTor
? TorService.sharedInstance.getProxyInfo()
: null,
2023-09-08 21:09:59 +00:00
);
if (response.code == 200) {
2023-07-20 19:38:56 +00:00
return LitescribeResponse(data: _validateJson(response.body));
} else {
2023-07-27 19:47:22 +00:00
throw Exception(
2024-05-27 23:56:22 +00:00
'LitescribeAPI _getResponse exception: Failed to load data',
);
2023-07-20 19:38:56 +00:00
}
}
Map<String, dynamic> _validateJson(String responseBody) {
final parsed = jsonDecode(responseBody);
if (parsed is Map<String, dynamic>) {
return parsed;
} else {
2023-07-27 19:47:22 +00:00
throw const FormatException(
2024-05-27 23:56:22 +00:00
'LitescribeAPI _validateJson exception: Invalid JSON format',
);
2023-07-20 19:38:56 +00:00
}
}
2024-05-27 23:56:22 +00:00
Future<List<InscriptionData>> getInscriptionsByAddress(
String address, {
int cursor = 0,
int size = 1000,
}) async {
2023-07-20 19:46:15 +00:00
// size param determines how many inscriptions are returned per response
// default of 1000 is used to cover most addresses (I assume)
// if the total number of inscriptions at the address exceeds the length of the list of inscriptions returned, another call with a higher size is made
final int defaultLimit = 1000;
2023-07-27 19:47:22 +00:00
final response = await _getResponse(
2024-05-27 23:56:22 +00:00
'/address/inscriptions?address=$address&cursor=$cursor&size=$size',
);
2023-07-20 19:46:15 +00:00
// Check if the number of returned inscriptions equals the limit
final int total = response.data['result']['total'] as int;
2023-07-27 19:47:16 +00:00
int currentSize = 0;
if (total == 0) {
return <InscriptionData>[];
2023-07-27 19:47:16 +00:00
}
2023-07-20 19:46:15 +00:00
final list = response.data['result']!['list'];
currentSize = list.length as int;
2023-07-20 19:46:15 +00:00
if (currentSize == size && currentSize < total) {
// If the number of returned inscriptions equals the limit and there are more inscriptions available,
2023-07-20 19:48:12 +00:00
// increment the cursor and make the next API call to fetch the remaining inscriptions.
final int newCursor = cursor + size;
return getInscriptionsByAddress(address, cursor: newCursor, size: size);
2023-07-20 19:46:15 +00:00
} else {
try {
2023-07-20 21:49:26 +00:00
// Iterate through the list and create InscriptionData objects from each element
final List<InscriptionData> inscriptions = (list as List<dynamic>)
2024-05-27 23:56:22 +00:00
.map(
(json) => InscriptionData.fromJson(json as Map<String, dynamic>),
)
2023-07-20 21:49:26 +00:00
.toList();
return inscriptions;
2023-07-20 19:46:15 +00:00
} catch (e) {
2023-07-27 19:47:22 +00:00
throw const FormatException(
2024-05-27 23:56:22 +00:00
'LitescribeAPI getInscriptionsByAddress exception: AddressInscriptionResponse.fromJson failure',
);
2023-07-20 19:46:15 +00:00
}
2023-07-20 19:38:56 +00:00
}
}
2023-07-27 19:47:22 +00:00
}