From 7ba0faf97482bf5d1650f35f38943758ae9daef3 Mon Sep 17 00:00:00 2001 From: redDwarf03 Date: Wed, 15 Jan 2025 15:32:57 +0100 Subject: [PATCH] feat: :sparkles: Implementation of GraphQL method: `chainUnspentOutputs` --- CHANGELOG.md | 3 ++ lib/src/model/transaction.dart | 3 ++ lib/src/services/api_service.dart | 64 +++++++++++++++++++++++++++++++ pubspec.yaml | 2 +- test/api_test.dart | 23 +++++++++++ 5 files changed, 94 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47e094ec..419b9a29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# 7.2.0 +- Implementation of GraphQL method: `chainUnspentOutputs` + # 7.1.0 - Integrate Transaction Version 4 features diff --git a/lib/src/model/transaction.dart b/lib/src/model/transaction.dart index 70881aa9..6cd6ec7d 100644 --- a/lib/src/model/transaction.dart +++ b/lib/src/model/transaction.dart @@ -704,4 +704,7 @@ class Transaction with _$Transaction { static const String kContractQueryAllFields = ' data { code, contract { bytecode, manifest { abi { functions, state } } } } '; + + static const String kUnspentOutputQueryFieldsWithoutState = + ' amount, from, timestamp, tokenAddress, tokenId, type'; } diff --git a/lib/src/services/api_service.dart b/lib/src/services/api_service.dart index e814dd60..c689bcc9 100644 --- a/lib/src/services/api_service.dart +++ b/lib/src/services/api_service.dart @@ -25,6 +25,7 @@ import 'package:archethic_lib_dart/src/model/transaction.dart'; import 'package:archethic_lib_dart/src/model/transaction_fee.dart'; import 'package:archethic_lib_dart/src/model/transaction_input.dart'; import 'package:archethic_lib_dart/src/model/transaction_status.dart'; +import 'package:archethic_lib_dart/src/model/unspent_outputs.dart'; import 'package:archethic_lib_dart/src/services/graph_ql_client_logger.dart'; import 'package:archethic_lib_dart/src/utils/collection_utils.dart'; import 'package:archethic_lib_dart/src/utils/crypto.dart'; @@ -985,4 +986,67 @@ class ApiService with JsonRPCUtil { exception.toString(), ); } + + /// Query the network to retrieve the unspent output of a chain (address should be the genesis address of the chain) + Future>> chainUnspentOutputs( + List genesisAddresses, { + String request = Transaction.kUnspentOutputQueryFieldsWithoutState, + int limit = 0, + // pagingOffset should be a Sha256Hash + String pagingOffset = '', + }) async { + if (genesisAddresses.isEmpty) { + return {}; + } + + final fragment = 'fragment fields on UnspentOutput { $request }'; + final body = StringBuffer()..write('query { '); + for (final genesisAddress in genesisAddresses) { + body.write( + ' _$genesisAddress: chainUnspentOutputs(address:"$genesisAddress" ', + ); + if (limit > 0) { + body.write( + ' limit:$limit ', + ); + } + if (pagingOffset.isNotEmpty) { + body.write( + ' pagingOffset:$pagingOffset ', + ); + } + body.write( + ' ) { ...fields } ', + ); + } + body.write(' } $fragment'); + + final result = await _client + .withLogger( + 'chainUnspentOutputs', + ) + .query( + QueryOptions( + document: gql(body.toString()), + parserFn: (json) { + final unspentOutputs = json.mapValues( + (unspentOutputs) => (unspentOutputs as List) + .map( + (unspentOutput) => UnspentOutputs.fromJson( + unspentOutput as Map, + ), + ) + .toList(), + keysToIgnore: _responseKeysToIgnore, + ); + return removeAliasPrefix>( + unspentOutputs, + ) ?? + {}; + }, + ), + ); + manageLinkException(result); + return result.parsedData ?? {}; + } } diff --git a/pubspec.yaml b/pubspec.yaml index 064d4d64..5be9ae25 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ name: archethic_lib_dart description: Archethic dart library for Flutter for Node and Browser. This library aims to provide a easy way to create Archethic transaction and to send them over the network homepage: https://github.com/archethic-foundation/libdart -version: 7.1.0 +version: 7.2.0 environment: sdk: ">=3.5.3 <4.0.0" diff --git a/test/api_test.dart b/test/api_test.dart index 94afea56..2d61c6e5 100644 --- a/test/api_test.dart +++ b/test/api_test.dart @@ -611,4 +611,27 @@ void main() { }); }, ); + + test('chainUnspentOutputs', () async { + final chainUnspentOutputsList = + await ApiService('https://testnet.archethic.net').chainUnspentOutputs([ + '00000bc0eba2dbce4455b46f5e51afaaba6eb4c7fba1d4e2e6dabd55dc70f9a04d6f', + '00003eeab3636e4017e961285f6f51c62db39a5ceb52dc5f1f8741b0b3b63ba00fd5', + ]); + + expect( + chainUnspentOutputsList.keys.first.length, + greaterThan(0), + ); + + expect( + chainUnspentOutputsList.keys.last.length, + greaterThan(0), + ); + + expect( + chainUnspentOutputsList.length, + 2, + ); + }); }