diff --git a/.qodo/history.sqlite b/.qodo/history.sqlite new file mode 100644 index 0000000..8ec0664 Binary files /dev/null and b/.qodo/history.sqlite differ diff --git a/packages/stellar_client/lib/models/transaction.dart b/packages/stellar_client/lib/models/transaction.dart index b148df6..1605238 100644 --- a/packages/stellar_client/lib/models/transaction.dart +++ b/packages/stellar_client/lib/models/transaction.dart @@ -4,6 +4,7 @@ class ITransaction {} class PaymentTransaction extends ITransaction { PaymentTransaction({ + required this.pagingToken, required this.hash, required this.from, required this.to, @@ -14,6 +15,7 @@ class PaymentTransaction extends ITransaction { required this.date, required this.type, }); + final String pagingToken; final String hash; final String from; final String to; @@ -26,6 +28,6 @@ class PaymentTransaction extends ITransaction { @override String toString() { - return 'ITransaction(hash: $hash, from: $from, to: $to, asset: $asset, amount: $amount, memo: $memo, status: $status, date: $date)'; + return 'ITransaction(pagingToken: $pagingToken, hash: $hash, from: $from, to: $to, asset: $asset, amount: $amount, memo: $memo, status: $status, date: $date)'; } } diff --git a/packages/stellar_client/lib/src/client.dart b/packages/stellar_client/lib/src/client.dart index ed5606c..3a028b8 100644 --- a/packages/stellar_client/lib/src/client.dart +++ b/packages/stellar_client/lib/src/client.dart @@ -401,67 +401,68 @@ class Client { } } - Future> getTransactions( - {String? assetCodeFilter, int? limit, int? offset}) async { - try { - var paymentsRequest = - _sdk.payments.forAccount(accountId).order(RequestBuilderOrder.DESC); - - // Add pagination - if (limit != null) { - paymentsRequest = paymentsRequest.limit(limit); - } + Stream getTransactions({ + String? assetCodeFilter, + int limit = 10, + String? pagingToken, + }) async* { + String? currentCursor = pagingToken; + int count = 0; - // get first page - if (offset != null && offset > 0) { - var initialPage = await _sdk.payments + try { + while (count < limit) { + final request = _sdk.payments .forAccount(accountId) .order(RequestBuilderOrder.DESC) - .limit(offset) - .execute(); - - if (initialPage.records.isNotEmpty) { - // Use the last record's paging token as cursor - paymentsRequest = - paymentsRequest.cursor(initialPage.records.last.pagingToken); + .limit(limit) + .cursor(currentCursor ?? ''); + + final page = await request.execute(); + if (page.records.isEmpty) break; + + final tempList = <_TempTx>[]; + + for (final response in page.records) { + if (response is PaymentOperationResponse && + (assetCodeFilter == null || + response.assetCode == assetCodeFilter)) { + tempList.add(_TempTx( + response.links.transaction.toJson()["href"], + response, + )); + if (++count >= limit) break; + } } - } - Page payments = await paymentsRequest.execute(); - List transactionDetails = []; - - if (payments.records.isNotEmpty) { - for (OperationResponse response in payments.records) { - if (response is PaymentOperationResponse) { - final memoText = await this - .getMemoText(response.links.transaction.toJson()["href"]); - String assetCode = response.assetCode ?? 'XLM'; - if (assetCodeFilter == null || assetCode == assetCodeFilter) { - final details = PaymentTransaction( - hash: response.transactionHash, - from: response.from, - to: response.to, - asset: response.assetCode.toString(), - amount: response.amount, - type: response.to == this.accountId - ? TransactionType.Receive - : TransactionType.Payment, - status: response.transactionSuccessful, - date: DateTime.parse(response.createdAt).toLocal().toString(), - memo: memoText); - - transactionDetails.add(details); - } - } else { - logger.i("Unhandled operation type: ${response.runtimeType}"); - } + if (tempList.isEmpty) break; + + currentCursor = tempList.last.response.pagingToken; + + final memoList = await Future.wait( + tempList.map((tx) => getMemoText(tx.href)), + ); + + for (var i = 0; i < tempList.length; i++) { + final tx = tempList[i].response; + yield PaymentTransaction( + pagingToken: tx.pagingToken, + hash: tx.transactionHash, + from: tx.from, + to: tx.to, + asset: tx.assetCode ?? 'XLM', + amount: tx.amount, + type: tx.to == accountId + ? TransactionType.Receive + : TransactionType.Payment, + status: tx.transactionSuccessful, + date: DateTime.parse(tx.createdAt).toLocal().toString(), + memo: memoList[i], + ); } } - - return transactionDetails; } catch (e) { logger.e('Failed to get transactions: $e'); - throw Exception('Could not get transactions due to $e'); + throw Exception('Failed to get transactions'); } } diff --git a/packages/stellar_client/lib/src/helpers.dart b/packages/stellar_client/lib/src/helpers.dart index e5374d1..214493a 100644 --- a/packages/stellar_client/lib/src/helpers.dart +++ b/packages/stellar_client/lib/src/helpers.dart @@ -39,3 +39,9 @@ Future> getBalanceByAccountID({ throw Exception(e); } } + +class _TempTx { + final String href; + final PaymentOperationResponse response; + _TempTx(this.href, this.response); +}