diff --git a/lib/domain/repositories/transaction/recent_transactions.repository.dart b/lib/domain/repositories/transaction/recent_transactions.repository.dart new file mode 100644 index 000000000..4ff5108c2 --- /dev/null +++ b/lib/domain/repositories/transaction/recent_transactions.repository.dart @@ -0,0 +1,7 @@ +import 'package:aewallet/model/blockchain/recent_transaction.dart'; + +abstract class RecentTransactionsRepository { + Future> getAccountRecentTransactions( + String genesisAddress, + ); +} diff --git a/lib/infrastructure/repositories/transaction/recent_transactions.repository.dart b/lib/infrastructure/repositories/transaction/recent_transactions.repository.dart new file mode 100644 index 000000000..cb1e70399 --- /dev/null +++ b/lib/infrastructure/repositories/transaction/recent_transactions.repository.dart @@ -0,0 +1,198 @@ +import 'package:aewallet/domain/models/token_parser.dart'; +import 'package:aewallet/domain/repositories/transaction/recent_transactions.repository.dart'; +import 'package:aewallet/infrastructure/repositories/tokens/tokens.repository.dart'; +import 'package:aewallet/model/blockchain/recent_transaction.dart'; +import 'package:archethic_dapp_framework_flutter/archethic_dapp_framework_flutter.dart' + as aedappfm; +import 'package:archethic_lib_dart/archethic_lib_dart.dart' as archethic; + +class RecentTransactionsRepositoryImpl + with TokenParser + implements RecentTransactionsRepository { + RecentTransactionsRepositoryImpl({ + required this.apiService, + required this.defTokensRepository, + }); + + final archethic.ApiService apiService; + final TokensRepositoryImpl defTokensRepository; + + @override + Future> getAccountRecentTransactions( + String genesisAddress, + ) async { + var recentTransactions = []; + + final results = await Future.wait([ + apiService.chainUnspentOutputs([genesisAddress]), + apiService.getTransactionChain({genesisAddress: ''}), + ]); + + final unspentOutputsResultMap = + results[0] as Map>; + final transactionChainResultMap = + results[1] as Map>; + + // Unspent Outputs list + final accountUnspentOutputs = transactionChainResultMap[genesisAddress]! + .first + .validationStamp! + .ledgerOperations! + .unspentOutputs; + + // Inputs list + final accountInputsFromChainUnspentOutputs = + unspentOutputsResultMap[genesisAddress] ?? []; + + final accountInputsFromConsumedInputsTxChain = + transactionChainResultMap[genesisAddress]! + .first + .validationStamp! + .ledgerOperations! + .consumedInputs; + + final accountInputs = []; + for (final accountInputsFromChainUnspentOutput + in accountInputsFromChainUnspentOutputs) { + accountInputs.add( + archethic.TransactionInput( + amount: accountInputsFromChainUnspentOutput.amount, + from: accountInputsFromChainUnspentOutput.from, + timestamp: accountInputsFromChainUnspentOutput.timestamp, + tokenAddress: accountInputsFromChainUnspentOutput.tokenAddress, + tokenId: accountInputsFromChainUnspentOutput.tokenId, + type: accountInputsFromChainUnspentOutput.type, + ), + ); + } + + for (final accountInputFromConsumedInputsTxChain + in accountInputsFromConsumedInputsTxChain) { + accountInputs.add( + archethic.TransactionInput( + amount: accountInputFromConsumedInputsTxChain.amount, + from: accountInputFromConsumedInputsTxChain.from, + timestamp: accountInputFromConsumedInputsTxChain.timestamp, + tokenAddress: accountInputFromConsumedInputsTxChain.tokenAddress, + tokenId: accountInputFromConsumedInputsTxChain.tokenId, + type: accountInputFromConsumedInputsTxChain.type, + ), + ); + } + + for (final accountInput in accountInputs) { + final recentTransaction = RecentTransaction() + ..amount = archethic.fromBigInt(accountInput.amount).toDouble() + ..typeTx = RecentTransaction.transferInput + ..tokenAddress = accountInput.tokenAddress + ..from = accountInput.from + ..address = accountInput.from + ..timestamp = accountInput.timestamp; + recentTransactions.add(recentTransaction); + } + + // Movements + final transaction = transactionChainResultMap[genesisAddress]!.first; + final accountTransactionMovements = + transaction.validationStamp!.ledgerOperations!.transactionMovements; + + for (final accountTransactionMovement in accountTransactionMovements) { + final recentTransaction = RecentTransaction() + ..amount = + archethic.fromBigInt(accountTransactionMovement.amount).toDouble() + ..address = transaction.address!.address + ..timestamp = transaction.validationStamp!.timestamp + ..fee = archethic + .fromBigInt( + transaction.validationStamp!.ledgerOperations!.fee, + ) + .toDouble(); + switch (transaction.type) { + case 'token': + recentTransaction.typeTx = RecentTransaction.tokenCreation; + break; + case 'hosting': + recentTransaction.typeTx = RecentTransaction.hosting; + break; + case 'transfer': + recentTransaction.typeTx = RecentTransaction.transferOutput; + break; + default: + } + + recentTransactions.add(recentTransaction); + } + + recentTransactions.sort((a, b) { + final compareTimestamp = b.timestamp!.compareTo(a.timestamp!); + if (compareTimestamp != 0) { + return compareTimestamp; + } else { + return b.indexInLedger.compareTo(a.indexInLedger); + } + }); + + recentTransactions = recentTransactions.sublist( + 0, + recentTransactions.length > 10 ? 10 : recentTransactions.length, + ); + + // Get token id + final tokensAddresses = []; + for (final recentTransaction in recentTransactions) { + if (recentTransaction.tokenAddress != null && + recentTransaction.tokenAddress!.isNotEmpty && + recentTransaction.tokenInformation == null) { + tokensAddresses.add(recentTransaction.tokenAddress!); + } + } + + // Search token Information + final tokensAddressMap = await defTokensRepository.getTokensFromAddresses( + tokensAddresses.toSet().toList(), + ); + + for (final recentTransaction in recentTransactions) { + // Get token Information + if (recentTransaction.tokenAddress != null && + recentTransaction.tokenAddress!.isNotEmpty && + recentTransaction.tokenInformation == null && + recentTransaction.timestamp! >= mostRecentTimestamp) { + final token = tokensAddressMap[recentTransaction.tokenAddress]; + if (token != null) { + recentTransaction + ..tokenAddress = token.address + ..tokenInformation = TokenInformation( + address: token.address, + name: token.name, + supply: archethic.fromBigInt(token.supply).toDouble(), + symbol: token.symbol, + type: token.type, + ); + } + } + + // Decrypt secrets + switch (recentTransaction.typeTx) { + case RecentTransaction.transferInput: + if (recentTransaction.from != null) { + if (recentTransaction.timestamp! > mostRecentTimestamp) { + ownershipsAddresses.add(recentTransaction.from!); + } + recentTransactionLastAddresses.add(recentTransaction.from!); + } + break; + case RecentTransaction.transferOutput: + if (recentTransaction.from != null) { + if (recentTransaction.timestamp! > mostRecentTimestamp) { + ownershipsAddresses.add(recentTransaction.from!); + } + recentTransactionLastAddresses.add(recentTransaction.from!); + } + break; + } + } + + return recentTransactions; + } +} diff --git a/pubspec.lock b/pubspec.lock index cad2d0d91..c938476d2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -58,26 +58,26 @@ packages: dependency: "direct main" description: name: archethic_dapp_framework_flutter - sha256: "3444edd8a468772bd16f7a079fd72d07c183e40a4f32f837f4dcf482ed56b903" + sha256: "4cc937ef0c23ad010b01e09641f809cc76095a13c007925253bfcdf82db4b404" url: "https://pub.dev" source: hosted - version: "3.2.7" + version: "3.2.8" archethic_lib_dart: dependency: transitive description: name: archethic_lib_dart - sha256: "3b00033e9aa6c69f323ca68b044be2d7b7ad5f38063572cace069ff9ded032b1" + sha256: "31e5b122df87c337d1ce189acc0f41db37a77b65a6638593ec856be90c8bfe2d" url: "https://pub.dev" source: hosted - version: "7.1.0" + version: "7.2.0" archethic_wallet_client: dependency: "direct main" description: name: archethic_wallet_client - sha256: ccf5c210985621b440bee3c3a7f28ed0d9bb0311c999f775e35f529cdffeba09 + sha256: "4dccce3738a96e33346cbd6f9316186aa7ea7f5399077b21174dba3160e7051c" url: "https://pub.dev" source: hosted - version: "2.1.9" + version: "2.1.10" archive: dependency: transitive description: @@ -692,10 +692,10 @@ packages: dependency: "direct main" description: name: flutter_secure_storage - sha256: "9cad52d75ebc511adfae3d447d5d13da15a55a92c9410e50f67335b6d21d16ea" + sha256: "1913841ac4c7bf57cd2e05b717e1fbff7841b542962feff827b16525a781b3e4" url: "https://pub.dev" source: hosted - version: "9.2.4" + version: "9.2.3" flutter_secure_storage_linux: dependency: transitive description: @@ -748,10 +748,10 @@ packages: dependency: "direct main" description: name: flutter_svg - sha256: c200fd79c918a40c5cd50ea0877fa13f81bdaf6f0a5d3dbcc2a13e3285d6aa1b + sha256: "54900a1a1243f3c4a5506d853a2b5c2dbc38d5f27e52a52618a8054401431123" url: "https://pub.dev" source: hosted - version: "2.0.17" + version: "2.0.16" flutter_test: dependency: "direct dev" description: flutter @@ -806,10 +806,10 @@ packages: dependency: "direct main" description: name: go_router - sha256: "7c2d40b59890a929824f30d442e810116caf5088482629c894b9e4478c67472d" + sha256: "2fd11229f59e23e967b0775df8d5948a519cd7e1e8b6e849729e010587b46539" url: "https://pub.dev" source: hosted - version: "14.6.3" + version: "14.6.2" gql: dependency: transitive description: @@ -1883,10 +1883,10 @@ packages: dependency: transitive description: name: url_launcher_windows - sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77" + sha256: "44cf3aabcedde30f2dba119a9dea3b0f2672fbe6fa96e85536251d678216b3c4" url: "https://pub.dev" source: hosted - version: "3.1.4" + version: "3.1.3" uuid: dependency: "direct main" description: @@ -1915,10 +1915,10 @@ packages: dependency: transitive description: name: vector_graphics_codec - sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" + sha256: "2430b973a4ca3c4dbc9999b62b8c719a160100dcbae5c819bae0cacce32c9cdb" url: "https://pub.dev" source: hosted - version: "1.1.13" + version: "1.1.12" vector_graphics_compiler: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index ca6f1d710..9ca573358 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -13,7 +13,7 @@ dependencies: # Retrieve version and url for local app update against store app Android and iOS app_version_update: ^5.0.2 - archethic_dapp_framework_flutter: ^3.2.7 + archethic_dapp_framework_flutter: ^3.2.8 #archethic_dapp_framework_flutter: ^3.2.6-beta.3 #archethic_dapp_framework_flutter: # git: @@ -23,7 +23,7 @@ dependencies: # path: ../archethic-dapp-framework-flutter # AWC - archethic_wallet_client: ^2.1.9 + archethic_wallet_client: ^2.1.10 #archethic_wallet_client: # git: # url: https://github.com/archethic-foundation/archethic-wallet-client-dart.git