Skip to content

Commit 4e9b3e4

Browse files
committed
Fix getTransactions pagination, add pagingToken to PaymentTransaction class
1 parent f3afde6 commit 4e9b3e4

File tree

2 files changed

+51
-50
lines changed

2 files changed

+51
-50
lines changed

packages/stellar_client/lib/models/transaction.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ class ITransaction {}
44

55
class PaymentTransaction extends ITransaction {
66
PaymentTransaction({
7+
required this.pagingToken,
78
required this.hash,
89
required this.from,
910
required this.to,
@@ -14,6 +15,7 @@ class PaymentTransaction extends ITransaction {
1415
required this.date,
1516
required this.type,
1617
});
18+
final String pagingToken;
1719
final String hash;
1820
final String from;
1921
final String to;
@@ -26,6 +28,6 @@ class PaymentTransaction extends ITransaction {
2628

2729
@override
2830
String toString() {
29-
return 'ITransaction(hash: $hash, from: $from, to: $to, asset: $asset, amount: $amount, memo: $memo, status: $status, date: $date)';
31+
return 'ITransaction(pagingToken: $pagingToken, hash: $hash, from: $from, to: $to, asset: $asset, amount: $amount, memo: $memo, status: $status, date: $date)';
3032
}
3133
}

packages/stellar_client/lib/src/client.dart

Lines changed: 48 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -401,67 +401,66 @@ class Client {
401401
}
402402
}
403403

404-
Future<List<ITransaction>> getTransactions(
405-
{String? assetCodeFilter, int? limit, int? offset}) async {
404+
Future<List<ITransaction>> getTransactions({
405+
String? assetCodeFilter,
406+
int limit = 10,
407+
String? pagingToken,
408+
}) async {
406409
try {
407-
var paymentsRequest =
408-
_sdk.payments.forAccount(accountId).order(RequestBuilderOrder.DESC);
410+
var paymentsRequest = _sdk.payments
411+
.forAccount(accountId)
412+
.order(RequestBuilderOrder.DESC)
413+
.limit(limit);
409414

410-
// Add pagination
411-
if (limit != null) {
412-
paymentsRequest = paymentsRequest.limit(limit);
415+
if (pagingToken != null) {
416+
paymentsRequest = paymentsRequest.cursor(pagingToken);
413417
}
414418

415-
// get first page
416-
if (offset != null && offset > 0) {
417-
var initialPage = await _sdk.payments
418-
.forAccount(accountId)
419-
.order(RequestBuilderOrder.DESC)
420-
.limit(offset)
421-
.execute();
422-
423-
if (initialPage.records.isNotEmpty) {
424-
// Use the last record's paging token as cursor
425-
paymentsRequest =
426-
paymentsRequest.cursor(initialPage.records.last.pagingToken);
419+
final Page<OperationResponse> payments = await paymentsRequest.execute();
420+
final List<ITransaction> transactionDetails = [];
421+
422+
// Keep track of the last raw paging token (even if filtered out later)
423+
String? lastRawPagingToken;
424+
425+
for (final response in payments.records) {
426+
// Save the last raw paging token no matter what.
427+
lastRawPagingToken = response.pagingToken;
428+
429+
if (response is! PaymentOperationResponse) {
430+
logger.i("Skipping non-payment operation: ${response.runtimeType}");
431+
continue;
427432
}
428-
}
429433

430-
Page<OperationResponse> payments = await paymentsRequest.execute();
431-
List<ITransaction> transactionDetails = [];
432-
433-
if (payments.records.isNotEmpty) {
434-
for (OperationResponse response in payments.records) {
435-
if (response is PaymentOperationResponse) {
436-
final memoText = await this
437-
.getMemoText(response.links.transaction.toJson()["href"]);
438-
String assetCode = response.assetCode ?? 'XLM';
439-
if (assetCodeFilter == null || assetCode == assetCodeFilter) {
440-
final details = PaymentTransaction(
441-
hash: response.transactionHash,
442-
from: response.from,
443-
to: response.to,
444-
asset: response.assetCode.toString(),
445-
amount: response.amount,
446-
type: response.to == this.accountId
447-
? TransactionType.Receive
448-
: TransactionType.Payment,
449-
status: response.transactionSuccessful,
450-
date: DateTime.parse(response.createdAt).toLocal().toString(),
451-
memo: memoText);
452-
453-
transactionDetails.add(details);
454-
}
455-
} else {
456-
logger.i("Unhandled operation type: ${response.runtimeType}");
457-
}
434+
final memoText =
435+
await getMemoText(response.links.transaction.toJson()["href"]);
436+
final assetCode = response.assetCode ?? 'XLM';
437+
438+
// Only include if it meets the asset code filter.
439+
if (assetCodeFilter != null && assetCode != assetCodeFilter) {
440+
continue;
458441
}
442+
443+
transactionDetails.add(PaymentTransaction(
444+
pagingToken: response.pagingToken,
445+
hash: response.transactionHash,
446+
from: response.from,
447+
to: response.to,
448+
asset: assetCode,
449+
amount: response.amount,
450+
type: response.to == accountId
451+
? TransactionType.Receive
452+
: TransactionType.Payment,
453+
status: response.transactionSuccessful,
454+
date: DateTime.parse(response.createdAt).toLocal().toString(),
455+
memo: memoText,
456+
));
459457
}
460458

459+
logger.i('Fetched ${transactionDetails.length} transactions');
461460
return transactionDetails;
462461
} catch (e) {
463462
logger.e('Failed to get transactions: $e');
464-
throw Exception('Could not get transactions due to $e');
463+
throw Exception('Could not get transactions: ${e.toString()}');
465464
}
466465
}
467466

0 commit comments

Comments
 (0)