Merge pull request #8998 from Abdulkbk/trx-pagination

pagination: add pagination to wallet transactions
This commit is contained in:
Oliver Gugger authored and GitHub committed 2024-11-22 09:30:11 +01:00
commit 94f7ed46de
14 files changed
+329 -37

No files matched your search

+32 -5
View File
@@ -1554,7 +1554,9 @@ func unminedTransactionsToDetail(
//
// This is a part of the WalletController interface.
func (b *BtcWallet) ListTransactionDetails(startHeight, endHeight int32,
accountFilter string) ([]*lnwallet.TransactionDetail, error) {
accountFilter string, indexOffset uint32,
maxTransactions uint32) ([]*lnwallet.TransactionDetail, uint64, uint64,
error) {
// Grab the best block the wallet knows of, we'll use this to calculate
// # of confirmations shortly below.
@@ -1566,7 +1568,7 @@ func (b *BtcWallet) ListTransactionDetails(startHeight, endHeight int32,
stop := base.NewBlockIdentifierFromHeight(endHeight)
txns, err := b.wallet.GetTransactions(start, stop, accountFilter, nil)
if err != nil {
return nil, err
return nil, 0, 0, err
}
txDetails := make([]*lnwallet.TransactionDetail, 0,
@@ -1580,7 +1582,7 @@ func (b *BtcWallet) ListTransactionDetails(startHeight, endHeight int32,
currentHeight, blockPackage, b.netParams,
)
if err != nil {
return nil, err
return nil, 0, 0, err
}
txDetails = append(txDetails, details...)
@@ -1588,13 +1590,38 @@ func (b *BtcWallet) ListTransactionDetails(startHeight, endHeight int32,
for _, tx := range txns.UnminedTransactions {
detail, err := unminedTransactionsToDetail(tx, b.netParams)
if err != nil {
return nil, err
return nil, 0, 0, err
}
txDetails = append(txDetails, detail)
}
return txDetails, nil
// Return empty transaction list, if offset is more than all
// transactions.
if int(indexOffset) >= len(txDetails) {
txDetails = []*lnwallet.TransactionDetail{}
return txDetails, 0, 0, nil
}
end := indexOffset + maxTransactions
// If maxTransactions is set to 0, then we'll return all transactions
// starting from the offset.
if maxTransactions == 0 {
end = uint32(len(txDetails))
txDetails = txDetails[indexOffset:end]
return txDetails, uint64(indexOffset), uint64(end - 1), nil
}
if end > uint32(len(txDetails)) {
end = uint32(len(txDetails))
}
txDetails = txDetails[indexOffset:end]
return txDetails, uint64(indexOffset), uint64(end - 1), nil
}
// txSubscriptionClient encapsulates the transaction notification client from
+3 -1
View File
@@ -402,7 +402,9 @@ type WalletController interface {
// retrieve the transactions relevant to a specific account. When
// empty, transactions of all wallet accounts are returned.
ListTransactionDetails(startHeight, endHeight int32,
accountFilter string) ([]*TransactionDetail, error)
accountFilter string, indexOffset uint32,
maxTransactions uint32) ([]*TransactionDetail, uint64, uint64,
error)
// LeaseOutput locks an output to the given ID, preventing it from being
// available for any future coin selection attempts. The absolute time
+2 -2
View File
@@ -198,9 +198,9 @@ func (w *mockWalletController) ListUnspentWitness(int32, int32,
// ListTransactionDetails currently returns dummy values.
func (w *mockWalletController) ListTransactionDetails(int32, int32,
string) ([]*TransactionDetail, error) {
string, uint32, uint32) ([]*TransactionDetail, uint64, uint64, error) {
return nil, nil
return nil, 0, 0, nil
}
// LeaseOutput returns the current time and a nil error.
+118 -7
View File
@@ -199,7 +199,9 @@ func assertTxInWallet(t *testing.T, w *lnwallet.LightningWallet,
// We'll fetch all of our transaction and go through each one until
// finding the expected transaction with its expected confirmation
// status.
txs, err := w.ListTransactionDetails(0, btcwallet.UnconfirmedHeight, "")
txs, _, _, err := w.ListTransactionDetails(
0, btcwallet.UnconfirmedHeight, "", 0, 1000,
)
require.NoError(t, err, "unable to retrieve transactions")
for _, tx := range txs {
if tx.Hash != txHash {
@@ -1101,8 +1103,8 @@ func testListTransactionDetails(miner *rpctest.Harness,
// should be confirmed.
err = waitForWalletSync(miner, alice)
require.NoError(t, err, "Couldn't sync Alice's wallet")
txDetails, err := alice.ListTransactionDetails(
startHeight, chainTip, "",
txDetails, _, _, err := alice.ListTransactionDetails(
startHeight, chainTip, "", 0, 1000,
)
require.NoError(t, err, "unable to fetch tx details")
@@ -1213,8 +1215,8 @@ func testListTransactionDetails(miner *rpctest.Harness,
// unconfirmed transactions. The transaction above should be included
// with a confirmation height of 0, indicating that it has not been
// mined yet.
txDetails, err = alice.ListTransactionDetails(
chainTip, btcwallet.UnconfirmedHeight, "",
txDetails, _, _, err = alice.ListTransactionDetails(
chainTip, btcwallet.UnconfirmedHeight, "", 0, 1000,
)
require.NoError(t, err, "unable to fetch tx details")
var mempoolTxFound bool
@@ -1266,7 +1268,9 @@ func testListTransactionDetails(miner *rpctest.Harness,
// transactions from the last block.
err = waitForWalletSync(miner, alice)
require.NoError(t, err, "Couldn't sync Alice's wallet")
txDetails, err = alice.ListTransactionDetails(chainTip, chainTip, "")
txDetails, _, _, err = alice.ListTransactionDetails(
chainTip, chainTip, "", 0, 1000,
)
require.NoError(t, err, "unable to fetch tx details")
var burnTxFound bool
for _, txDetail := range txDetails {
@@ -1307,13 +1311,116 @@ func testListTransactionDetails(miner *rpctest.Harness,
// Query for transactions only in the latest block. We do not expect
// any transactions to be returned.
txDetails, err = alice.ListTransactionDetails(chainTip, chainTip, "")
txDetails, _, _, err = alice.ListTransactionDetails(
chainTip, chainTip, "", 0, 1000,
)
require.NoError(t, err, "unexpected error")
if len(txDetails) != 0 {
t.Fatalf("expected 0 transactions, got: %v", len(txDetails))
}
}
func testListTransactionDetailsOffset(miner *rpctest.Harness,
alice, _ *lnwallet.LightningWallet, t *testing.T) {
// Create 5 new outputs spendable by the wallet.
const numTxns = 5
const outputAmt = btcutil.SatoshiPerBitcoin
isOurAddress := make(map[string]bool)
txids := make(map[chainhash.Hash]struct{})
for i := 0; i < numTxns; i++ {
addr, err := alice.NewAddress(
lnwallet.WitnessPubKey, false,
lnwallet.DefaultAccountName,
)
require.NoError(t, err)
isOurAddress[addr.EncodeAddress()] = true
script, err := txscript.PayToAddrScript(addr)
require.NoError(t, err)
output := &wire.TxOut{
Value: outputAmt,
PkScript: script,
}
txid, err := miner.SendOutputs([]*wire.TxOut{output}, 2500)
require.NoError(t, err)
txids[*txid] = struct{}{}
}
// Get the miner's current best block height before we mine blocks.
_, startHeight, err := miner.Client.GetBestBlock()
require.NoError(t, err, "cannot get best block")
// Generate 10 blocks to mine all the transactions created above.
const numBlocksMined = 10
_, err = miner.Client.Generate(numBlocksMined)
require.NoError(t, err, "unable to mine blocks")
// Our new best block height should be our start height + the number of
// blocks we just mined.
chainTip := startHeight + numBlocksMined
err = waitForWalletSync(miner, alice)
require.NoError(t, err, "Couldn't sync Alice's wallet")
// Query for transactions, setting max_transactions to 5. We expect 5
// transactions to be returned.
txDetails, firstIdx, lastIdx, err := alice.ListTransactionDetails(
startHeight, chainTip, "", 0, 5,
)
require.NoError(t, err)
require.Len(t, txDetails, 5)
require.EqualValues(t, 0, firstIdx)
require.EqualValues(t, 4, lastIdx)
// Query for transactions, setting max_transactions to less than the
// number of transactions we have (5).
txDetails, _, _, err = alice.ListTransactionDetails(
startHeight, chainTip, "", 0, 1,
)
require.NoError(t, err)
require.Len(t, txDetails, 1)
// Query for transactions, setting indexOffset to 5 (equal to number
// of transactions we have) and max_transactions to 0.
txDetails, _, _, err = alice.ListTransactionDetails(
startHeight, chainTip, "", 5, 0,
)
require.NoError(t, err)
require.Len(t, txDetails, 0)
// Query for transactions, setting indexOffset to 4 (edge offset) and
// max_transactions to 0.
txDetails, _, _, err = alice.ListTransactionDetails(
startHeight, chainTip, "", 4, 0,
)
require.NoError(t, err)
require.Len(t, txDetails, 1)
// Query for transactions, setting max_transactions to 0.
txDetails, _, _, err = alice.ListTransactionDetails(
startHeight, chainTip, "", 0, 0,
)
require.NoError(t, err)
require.Len(t, txDetails, 5)
// Query for transactions, more than we have in the wallet (5).
txDetails, _, _, err = alice.ListTransactionDetails(
startHeight, chainTip, "", 0, 10,
)
require.NoError(t, err)
require.Len(t, txDetails, 5)
// Query for transactions where the offset is greater than the number
// of transactions available.
txDetails, _, _, err = alice.ListTransactionDetails(
startHeight, chainTip, "", 10, 100,
)
require.NoError(t, err)
require.Len(t, txDetails, 0)
}
func testTransactionSubscriptions(miner *rpctest.Harness,
alice, _ *lnwallet.LightningWallet, t *testing.T) {
@@ -2812,6 +2919,10 @@ var walletTests = []walletTestCase{
name: "transaction details",
test: testListTransactionDetails,
},
{
name: "transaction details offset",
test: testListTransactionDetailsOffset,
},
{
name: "get transaction details",
test: testGetTransactionDetails,