From e9e49724bf40be8b6b4905626b6b2524256da20c Mon Sep 17 00:00:00 2001 From: zaelgohary Date: Tue, 8 Apr 2025 10:28:34 +0200 Subject: [PATCH 1/3] Fix transactions pagination, use pagingToken instead of offset --- app/lib/screens/wallets/transactions.dart | 58 +++++++++++++---------- app/lib/services/stellar_service.dart | 4 +- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/app/lib/screens/wallets/transactions.dart b/app/lib/screens/wallets/transactions.dart index 3f681e548..dca7ea17d 100644 --- a/app/lib/screens/wallets/transactions.dart +++ b/app/lib/screens/wallets/transactions.dart @@ -18,36 +18,44 @@ class WalletTransactionsWidget extends StatefulWidget { class _WalletTransactionsWidgetState extends State { final _pageSize = 10; - final PagingController _pagingController = - PagingController(firstPageKey: 1); // Start from page 1 + final PagingController _pagingController = + PagingController(firstPageKey: null); - Future _listTransactions(int pageKey) async { - try { - final offset = (pageKey - 1) * _pageSize; - final txs = await listTransactions( - widget.wallet.stellarSecret, offset, _pageSize); - final isLastPage = txs.length < _pageSize; - if (isLastPage) { + void _listTransactions(String? pagingToken) { + listTransactions(widget.wallet.stellarSecret, pagingToken, _pageSize) + .then((txs) { + if (txs.isEmpty) { + _pagingController.appendLastPage([]); + return; + } + + // Use the paging token of the last raw transaction. + // Make sure to adjust the token (subtract one) to avoid the duplicate record. + final lastTx = (txs.last as PaymentTransaction); + final adjustedPagingToken = + (BigInt.parse(lastTx.pagingToken) - BigInt.one).toString(); + + if (txs.length < _pageSize) { _pagingController.appendLastPage(txs); } else { - _pagingController.appendPage(txs, pageKey + 1); + _pagingController.appendPage(txs, adjustedPagingToken); } - } catch (e) { - logger.e('Failed to load transactions due to $e'); - _pagingController.error(e); - if (context.mounted) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text( - 'Failed to load transaction', - style: Theme.of(context) - .textTheme - .bodyMedium! - .copyWith(color: Theme.of(context).colorScheme.errorContainer), + }).catchError((e) { + logger.e('Failed to load transactions: $e'); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + 'Failed to load transaction', + style: Theme.of(context).textTheme.bodyMedium!.copyWith( + color: Theme.of(context).colorScheme.errorContainer), + ), + duration: const Duration(seconds: 3), ), - duration: const Duration(seconds: 3), - )); + ); } - } + _pagingController.error = e; + }); } @override @@ -78,7 +86,7 @@ class _WalletTransactionsWidgetState extends State { ); } - return PagedListView( + return PagedListView( pagingController: _pagingController, builderDelegate: PagedChildBuilderDelegate( itemBuilder: (context, item, index) => Column( diff --git a/app/lib/services/stellar_service.dart b/app/lib/services/stellar_service.dart index ac448ae4e..9e0379d6e 100644 --- a/app/lib/services/stellar_service.dart +++ b/app/lib/services/stellar_service.dart @@ -47,10 +47,10 @@ Future getBalance(String secret) async { } Future> listTransactions( - String secret, int offset, int limit) async { + String secret, String? pagingToken, int limit) async { final client = Client(NetworkType.PUBLIC, secret); return await client.getTransactions( - assetCodeFilter: 'TFT', limit: limit, offset: offset); + assetCodeFilter: 'TFT', limit: limit, pagingToken: pagingToken); } Future?> listVestedAccounts(String secret) async { From dcd3e1376eef3044902c063f3104830b54b0a362 Mon Sep 17 00:00:00 2001 From: zaelgohary Date: Wed, 9 Apr 2025 07:44:31 +0200 Subject: [PATCH 2/3] Edit listTransactions to return stream instead of list --- app/lib/screens/wallets/transactions.dart | 26 ++++++++++++++--------- app/lib/services/stellar_service.dart | 14 ++++++++---- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/app/lib/screens/wallets/transactions.dart b/app/lib/screens/wallets/transactions.dart index dca7ea17d..002888540 100644 --- a/app/lib/screens/wallets/transactions.dart +++ b/app/lib/screens/wallets/transactions.dart @@ -21,17 +21,22 @@ class _WalletTransactionsWidgetState extends State { final PagingController _pagingController = PagingController(firstPageKey: null); - void _listTransactions(String? pagingToken) { - listTransactions(widget.wallet.stellarSecret, pagingToken, _pageSize) - .then((txs) { + void _listTransactions(String? pagingToken) async { + try { + final txStream = listTransactions( + widget.wallet.stellarSecret, + pagingToken, + _pageSize, + ); + + final txs = await txStream.take(_pageSize).toList(); + if (txs.isEmpty) { _pagingController.appendLastPage([]); return; } - // Use the paging token of the last raw transaction. - // Make sure to adjust the token (subtract one) to avoid the duplicate record. - final lastTx = (txs.last as PaymentTransaction); + final lastTx = txs.last as PaymentTransaction; final adjustedPagingToken = (BigInt.parse(lastTx.pagingToken) - BigInt.one).toString(); @@ -40,22 +45,23 @@ class _WalletTransactionsWidgetState extends State { } else { _pagingController.appendPage(txs, adjustedPagingToken); } - }).catchError((e) { + } catch (e) { logger.e('Failed to load transactions: $e'); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( - 'Failed to load transaction', + 'Failed to load transactions', style: Theme.of(context).textTheme.bodyMedium!.copyWith( - color: Theme.of(context).colorScheme.errorContainer), + color: Theme.of(context).colorScheme.errorContainer, + ), ), duration: const Duration(seconds: 3), ), ); } _pagingController.error = e; - }); + } } @override diff --git a/app/lib/services/stellar_service.dart b/app/lib/services/stellar_service.dart index 9e0379d6e..262b27099 100644 --- a/app/lib/services/stellar_service.dart +++ b/app/lib/services/stellar_service.dart @@ -46,11 +46,17 @@ Future getBalance(String secret) async { return getBalanceByClient(client); } -Future> listTransactions( - String secret, String? pagingToken, int limit) async { +Stream listTransactions( + String secret, String? pagingToken, int limit) async* { final client = Client(NetworkType.PUBLIC, secret); - return await client.getTransactions( - assetCodeFilter: 'TFT', limit: limit, pagingToken: pagingToken); + + await for (var response in client.getTransactions( + assetCodeFilter: 'TFT', + limit: limit, + pagingToken: pagingToken, + )) { + yield response; + } } Future?> listVestedAccounts(String secret) async { From 4e5226f0887995370e72466d6e689fd9ab699fd7 Mon Sep 17 00:00:00 2001 From: zaelgohary Date: Wed, 9 Apr 2025 11:45:21 +0200 Subject: [PATCH 3/3] Update stellar client ref --- app/pubspec.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/pubspec.lock b/app/pubspec.lock index 03cdf7bba..802b54eb5 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -1715,7 +1715,7 @@ packages: description: path: "packages/stellar_client" ref: development - resolved-ref: f3afde66922dfbe836d0915fac8e152c5817626b + resolved-ref: "0ce3b575e2f3dcd371be2152042978113b4eadb1" url: "https://github.com/threefoldtech/tfgrid-sdk-dart" source: git version: "0.1.0"