use an OrdinalsResponse response type which can return an error

This commit is contained in:
sneurlax 2023-07-19 13:03:17 -05:00
parent d3b4be5d66
commit 8e17556e41
12 changed files with 148 additions and 98 deletions

View file

@ -1,6 +1,7 @@
import 'package:stackwallet/dto/ordinals/inscription_link.dart';
import 'package:stackwallet/dto/ordinals/ordinals_response.dart';
class AddressResponse {
class AddressResponse extends OrdinalsResponse<AddressResponse> {
final AddressLinks links;
final String address;
final List<InscriptionLink> inscriptions;
@ -11,15 +12,16 @@ class AddressResponse {
required this.inscriptions,
});
factory AddressResponse.fromJson(Map<String, dynamic> json) {
final inscriptionsJson = json['inscriptions'] as List;
factory AddressResponse.fromJson(OrdinalsResponse json) {
final data = json.data as Map<String, dynamic>;
final inscriptionsJson = data['inscriptions'] as List;
final inscriptions = inscriptionsJson
.map((inscriptionJson) => InscriptionLink.fromJson(inscriptionJson as Map<String, dynamic>))
.toList();
return AddressResponse(
links: AddressLinks.fromJson(json['_links'] as Map<String, dynamic>),
address: json['address'] as String,
links: AddressLinks.fromJson(data['_links'] as Map<String, dynamic>),
address: data['address'] as String,
inscriptions: inscriptions,
);
}
@ -34,7 +36,7 @@ class AddressLinks {
factory AddressLinks.fromJson(Map<String, dynamic> json) {
return AddressLinks(
self: AddressLink.fromJson(json['self'] as Map<String, dynamic>),
self: json['self'] != null ? AddressLink.fromJson(json['self'] as Map<String, dynamic>) : null,
);
}
}

View file

@ -1,4 +1,6 @@
class BlockResponse {
import 'package:stackwallet/dto/ordinals/ordinals_response.dart';
class BlockResponse extends OrdinalsResponse<BlockResponse> {
final BlockLinks links;
final String hash;
final String previousBlockhash;
@ -17,15 +19,16 @@ class BlockResponse {
required this.weight,
});
factory BlockResponse.fromJson(Map<String, dynamic> json) {
factory BlockResponse.fromJson(OrdinalsResponse json) {
final data = json.data as Map<String, dynamic>;
return BlockResponse(
links: BlockLinks.fromJson(json['_links'] as Map<String, dynamic>),
hash: json['hash'] as String,
previousBlockhash: json['previous_blockhash'] as String,
size: json['size'] as int,
target: json['target'] as String,
timestamp: json['timestamp'] as String,
weight: json['weight'] as int,
links: BlockLinks.fromJson(data['_links'] as Map<String, dynamic>),
hash: data['hash'] as String,
previousBlockhash: data['previous_blockhash'] as String,
size: data['size'] as int,
target: data['target'] as String,
timestamp: data['timestamp'] as String,
weight: data['weight'] as int,
);
}
}
@ -41,8 +44,8 @@ class BlockLinks {
factory BlockLinks.fromJson(Map<String, dynamic> json) {
return BlockLinks(
prev: BlockLink.fromJson(json['prev'] as Map<String, dynamic>),
self: BlockLink.fromJson(json['self'] as Map<String, dynamic>),
prev: json['prev'] != null ? BlockLink.fromJson(json['prev'] as Map<String, dynamic>) : null,
self: json['self'] != null ? BlockLink.fromJson(json['self'] as Map<String, dynamic>) : null,
);
}
}

View file

@ -1,10 +1,13 @@
class ContentResponse {
import 'package:stackwallet/dto/ordinals/ordinals_response.dart';
class ContentResponse extends OrdinalsResponse<ContentResponse> {
final FileLink fileLink;
ContentResponse({required this.fileLink});
factory ContentResponse.fromJson(Map<String, dynamic> json) {
return ContentResponse(fileLink: FileLink.fromJson(json['_links']['file'] as Map<String, dynamic>));
factory ContentResponse.fromJson(OrdinalsResponse json) {
final data = json.data as Map<String, dynamic>;
return ContentResponse(fileLink: FileLink.fromJson(data['_links']['file'] as Map<String, dynamic>)); // TODO don't cast as Map<String, dynamic>
}
}

View file

@ -1,12 +1,13 @@
import 'package:stackwallet/dto/ordinals/inscription_link.dart';
import 'package:stackwallet/dto/ordinals/ordinals_response.dart';
class FeedResponse {
class FeedResponse extends OrdinalsResponse<FeedResponse> {
final List<InscriptionLink> inscriptions;
FeedResponse({required this.inscriptions});
factory FeedResponse.fromJson(Map<String, dynamic> json) {
final List<dynamic> inscriptionsJson = json['_links']['inscriptions'] as List<dynamic>;
factory FeedResponse.fromJson(OrdinalsResponse json) {
final List<dynamic> inscriptionsJson = json.data['_links']['inscriptions'] as List<dynamic>;
final List<InscriptionLink> inscriptions = inscriptionsJson
.map((json) => InscriptionLink.fromJson(json as Map<String, dynamic>))
.toList();

View file

@ -1,4 +1,6 @@
class InscriptionResponse {
import 'package:stackwallet/dto/ordinals/ordinals_response.dart';
class InscriptionResponse extends OrdinalsResponse<InscriptionResponse> {
late final Links links;
late final String address;
late final int contentLength;
@ -29,20 +31,23 @@ class InscriptionResponse {
required this.timestamp,
});
InscriptionResponse.fromJson(Map<String, dynamic> json) {
links = Links.fromJson(json['_links'] as Map<String, dynamic>);
address = json['address'] as String;
contentLength = json['content_length'] as int;
contentType = json['content_type'] as String;
genesisFee = json['genesis_fee'] as int;
genesisHeight = json['genesis_height'] as int;
genesisTransaction = json['genesis_transaction'] as String;
location = json['location'] as String;
number = json['number'] as int;
offset = json['offset'] as int;
output = json['output'] as String;
sat = json['sat'] as String?;
timestamp = json['timestamp'] as String;
factory InscriptionResponse.fromJson(OrdinalsResponse json) {
final data = json.data as Map<String, dynamic>;
return InscriptionResponse(
links: Links.fromJson(data['_links'] as Map<String, dynamic>),
address: data['address'] as String,
contentLength: data['content_length'] as int,
contentType: data['content_type'] as String,
genesisFee: data['genesis_fee'] as int,
genesisHeight: data['genesis_height'] as int,
genesisTransaction: data['genesis_transaction'] as String,
location: data['location'] as String,
number: data['number'] as int,
offset: data['offset'] as int,
output: data['output'] as String,
sat: data['sat'] as String?,
timestamp: data['timestamp'] as String,
);
}
}
@ -67,15 +72,17 @@ class Links {
required this.self,
});
Links.fromJson(Map<String, dynamic> json) {
content = Link.fromJson(json['content'] as Map<String, dynamic>);
genesisTransaction = Link.fromJson(json['genesis_transaction'] as Map<String, dynamic>);
next = Link.fromJson(json['next'] as Map<String, dynamic>);
output = Link.fromJson(json['output'] as Map<String, dynamic>);
prev = Link.fromJson(json['prev'] as Map<String, dynamic>);
preview = Link.fromJson(json['preview'] as Map<String, dynamic>);
sat = json['sat'] != null ? Link.fromJson(json['sat'] as Map<String, dynamic>) : null;
self = Link.fromJson(json['self'] as Map<String, dynamic>);
factory Links.fromJson(Map<String, dynamic> json) {
return Links(
content: Link.fromJson(json['content'] as Map<String, dynamic>),
genesisTransaction: Link.fromJson(json['genesis_transaction'] as Map<String, dynamic>),
next: Link.fromJson(json['next'] as Map<String, dynamic>),
output: Link.fromJson(json['output'] as Map<String, dynamic>),
prev: Link.fromJson(json['prev'] as Map<String, dynamic>),
preview: Link.fromJson(json['preview'] as Map<String, dynamic>),
sat: json['sat'] != null ? Link.fromJson(json['sat'] as Map<String, dynamic>) : null,
self: Link.fromJson(json['self'] as Map<String, dynamic>),
);
}
}
@ -84,7 +91,7 @@ class Link {
Link({required this.href});
Link.fromJson(Map<String, dynamic> json) {
href = json['href'] as String;
factory Link.fromJson(Map<String, dynamic> json) {
return Link(href: json['href'] as String);
}
}

View file

@ -0,0 +1,6 @@
class OrdinalsResponse<T> {
final T? data;
final String? error;
OrdinalsResponse({this.data, this.error});
}

View file

@ -1,6 +1,7 @@
import 'package:stackwallet/dto/ordinals/transaction_response.dart';
import 'package:stackwallet/dto/ordinals/ordinals_response.dart';
class OutputResponse {
class OutputResponse extends OrdinalsResponse<OutputResponse> {
final OutputLinks links;
final String address;
final String scriptPubkey;
@ -15,13 +16,15 @@ class OutputResponse {
required this.value,
});
factory OutputResponse.fromJson(Map<String, dynamic> json) {
factory OutputResponse.fromJson(OrdinalsResponse json) {
final data = json.data as Map<String, dynamic>;
return OutputResponse(
links: OutputLinks.fromJson(json['_links'] as Map<String, dynamic>),
address: json['address'] as String,
scriptPubkey: json['script_pubkey'] as String,
transaction: json['transaction'] as String,
value: json['value'] as int,
links: OutputLinks.fromJson(data['_links'] as Map<String, dynamic>),
address: data['address'] as String,
scriptPubkey: data['script_pubkey'] as String,
transaction: data['transaction'] as String,
value: data['value'] as int,
);
}
}
@ -37,8 +40,8 @@ class OutputLinks {
factory OutputLinks.fromJson(Map<String, dynamic> json) {
return OutputLinks(
self: OutputLink.fromJson(json['self'] as Map<String, dynamic>),
transaction: TransactionLink.fromJson(json['transaction'] as Map<String, dynamic>),
self: json['self'] != null ? OutputLink.fromJson(json['self'] as Map<String, dynamic>) : null,
transaction: json['transaction'] != null ? TransactionLink.fromJson(json['transaction'] as Map<String, dynamic>) : null,
);
}
}

View file

@ -1,10 +1,13 @@
class PreviewResponse {
import 'package:stackwallet/dto/ordinals/ordinals_response.dart';
class PreviewResponse extends OrdinalsResponse<PreviewResponse> {
final ImageLink imageLink;
PreviewResponse({required this.imageLink});
factory PreviewResponse.fromJson(Map<String, dynamic> json) {
return PreviewResponse(imageLink: ImageLink.fromJson(json['_links']['image'] as Map<String, dynamic>));
factory PreviewResponse.fromJson(OrdinalsResponse json) {
final data = json.data as Map<String, dynamic>;
return PreviewResponse(imageLink: ImageLink.fromJson(data['_links']['image'] as Map<String, dynamic>));
}
}

View file

@ -1,4 +1,6 @@
class SatResponse {
import 'package:stackwallet/dto/ordinals/ordinals_response.dart';
class SatResponse extends OrdinalsResponse<SatResponse> {
final SatLinks links;
final int block;
final int cycle;
@ -27,20 +29,21 @@ class SatResponse {
required this.timestamp,
});
factory SatResponse.fromJson(Map<String, dynamic> json) {
factory SatResponse.fromJson(OrdinalsResponse json) {
final data = json.data as Map<String, dynamic>;
return SatResponse(
links: SatLinks.fromJson(json['_links'] as Map<String, dynamic>),
block: json['block'] as int,
cycle: json['cycle'] as int,
decimal: json['decimal'] as String,
degree: json['degree'] as String,
epoch: json['epoch'] as int,
name: json['name'] as String,
offset: json['offset'] as int,
percentile: json['percentile'] as String,
period: json['period'] as int,
rarity: json['rarity'] as String,
timestamp: json['timestamp'] as String,
links: SatLinks.fromJson(data['_links'] as Map<String, dynamic>),
block: data['block'] as int,
cycle: data['cycle'] as int,
decimal: data['decimal'] as String,
degree: data['degree'] as String,
epoch: data['epoch'] as int,
name: data['name'] as String,
offset: data['offset'] as int,
percentile: data['percentile'] as String,
period: data['period'] as int,
rarity: data['rarity'] as String,
timestamp: data['timestamp'] as String,
);
}
}
@ -62,11 +65,11 @@ class SatLinks {
factory SatLinks.fromJson(Map<String, dynamic> json) {
return SatLinks(
block: SatLink.fromJson(json['block'] as Map<String, dynamic>),
inscription: SatLink.fromJson(json['inscription'] as Map<String, dynamic>),
next: SatLink.fromJson(json['next'] as Map<String, dynamic>),
prev: SatLink.fromJson(json['prev'] as Map<String, dynamic>),
self: SatLink.fromJson(json['self'] as Map<String, dynamic>),
block: json['block'] != null ? SatLink.fromJson(json['block'] as Map<String, dynamic>) : null,
inscription: json['inscription'] != null ? SatLink.fromJson(json['inscription'] as Map<String, dynamic>) : null,
next: json['next'] != null ? SatLink.fromJson(json['next'] as Map<String, dynamic>) : null,
prev: json['prev'] != null ? SatLink.fromJson(json['prev'] as Map<String, dynamic>) : null,
self: json['self'] != null ? SatLink.fromJson(json['self'] as Map<String, dynamic>) : null,
);
}
}

View file

@ -1,6 +1,7 @@
import 'package:stackwallet/dto/ordinals/inscription_link.dart';
import 'package:stackwallet/dto/ordinals/ordinals_response.dart';
class TransactionResponse {
class TransactionResponse extends OrdinalsResponse<TransactionResponse> {
final TransactionLinks links;
final List<OutputLink> inputs;
final InscriptionLink inscription;
@ -17,24 +18,25 @@ class TransactionResponse {
required this.transaction,
});
factory TransactionResponse.fromJson(Map<String, dynamic> json) {
final inputsJson = json['_links']['inputs'] as List;
factory TransactionResponse.fromJson(OrdinalsResponse json) {
final data = json.data as Map<String, dynamic>;
final inputsJson = data['_links']['inputs'] as List;
final inputs = inputsJson
.map((inputJson) => OutputLink.fromJson(inputJson as Map<String, dynamic>))
.toList();
final outputsJson = json['_links']['outputs'] as List;
final outputsJson = data['_links']['outputs'] as List;
final outputs = outputsJson
.map((outputJson) => OutputLink.fromJson(outputJson as Map<String, dynamic>))
.toList();
return TransactionResponse(
links: TransactionLinks.fromJson(json['_links'] as Map<String, dynamic>),
links: TransactionLinks.fromJson(data['_links'] as Map<String, dynamic>),
inputs: inputs,
inscription: InscriptionLink.fromJson(json['_links']['inscription'] as Map<String, dynamic>),
inscription: InscriptionLink.fromJson(data['_links']['inscription'] as Map<String, dynamic>),
outputs: outputs,
self: TransactionLink.fromJson(json['_links']['self'] as Map<String, dynamic>),
transaction: json['transaction'] as String,
self: TransactionLink.fromJson(data['_links']['self'] as Map<String, dynamic>),
transaction: data['transaction'] as String,
);
}
}
@ -52,9 +54,9 @@ class TransactionLinks {
factory TransactionLinks.fromJson(Map<String, dynamic> json) {
return TransactionLinks(
block: TransactionLink.fromJson(json['block'] as Map<String, dynamic>),
inscription: InscriptionLink.fromJson(json['inscription'] as Map<String, dynamic>),
self: TransactionLink.fromJson(json['self'] as Map<String, dynamic>),
block: json['block'] != null ? TransactionLink.fromJson(json['block'] as Map<String, dynamic>) : null,
inscription: json['inscription'] != null ? InscriptionLink.fromJson(json['inscription'] as Map<String, dynamic>) : null,
self: json['self'] != null ? TransactionLink.fromJson(json['self'] as Map<String, dynamic>) : null,
);
}
}

View file

@ -1,3 +1,19 @@
import 'package:stackwallet/services/ordinals_api.dart';
import 'package:stackwallet/dto/ordinals/feed_response.dart';
mixin OrdinalsInterface {
// TODO wallet ordinals functionality
Future<FeedResponse> fetchLatestInscriptions(OrdinalsAPI ordinalsAPI) async {
try {
final feedResponse = await ordinalsAPI.getLatestInscriptions();
// Process the feedResponse data as needed
print('Latest Inscriptions:');
for (var inscription in feedResponse.inscriptions) {
print('Title: ${inscription.title}, Href: ${inscription.href}');
}
return feedResponse;
} catch (e) {
// Handle errors
throw Exception('Error in OrdinalsInterface: $e');
}
}
}

View file

@ -1,6 +1,7 @@
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:stackwallet/dto/ordinals/ordinals_response.dart';
import 'package:stackwallet/dto/ordinals/feed_response.dart';
import 'package:stackwallet/dto/ordinals/inscription_response.dart';
import 'package:stackwallet/dto/ordinals/sat_response.dart';
@ -16,10 +17,10 @@ class OrdinalsAPI {
OrdinalsAPI({required this.baseUrl});
Future<Map<String, dynamic>> _getResponse(String endpoint) async {
Future<OrdinalsResponse> _getResponse(String endpoint) async {
final response = await http.get(Uri.parse('$baseUrl$endpoint'));
if (response.statusCode == 200) {
return _validateJson(response.body);
return OrdinalsResponse(data: _validateJson(response.body));
} else {
throw Exception('Failed to load data');
}