Skip to content
This repository has been archived by the owner on Sep 2, 2024. It is now read-only.

Commit

Permalink
feat: support limit and offset in list transactions (#13)
Browse files Browse the repository at this point in the history
* feat: support limit and offset in list transactions

* chore: add transaction hint in checklist

* chore: fix transactions and channels length check syntax

* chore: change transactions default limit to 100

* fix: haschannel
  • Loading branch information
im-adithya authored Jul 8, 2024
1 parent c2d6c5e commit e401a1e
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 20 deletions.
5 changes: 2 additions & 3 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -487,12 +487,11 @@ func (api *api) GetBalances(ctx context.Context) (*BalancesResponse, error) {
return balances, nil
}

// TODO: accept offset, limit params for pagination
func (api *api) ListTransactions(ctx context.Context) (*ListTransactionsResponse, error) {
func (api *api) ListTransactions(ctx context.Context, limit uint64, offset uint64) (*ListTransactionsResponse, error) {
if api.svc.GetLNClient() == nil {
return nil, errors.New("LNClient not started")
}
transactions, err := api.svc.GetLNClient().ListTransactions(ctx, 0, 0, 20, 0, false, "")
transactions, err := api.svc.GetLNClient().ListTransactions(ctx, 0, 0, limit, offset, false, "")
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion api/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type API interface {
SignMessage(ctx context.Context, message string) (*SignMessageResponse, error)
RedeemOnchainFunds(ctx context.Context, toAddress string) (*RedeemOnchainFundsResponse, error)
GetBalances(ctx context.Context) (*BalancesResponse, error)
ListTransactions(ctx context.Context) (*ListTransactionsResponse, error)
ListTransactions(ctx context.Context, limit uint64, offset uint64) (*ListTransactionsResponse, error)
SendPayment(ctx context.Context, invoice string) (*SendPaymentResponse, error)
CreateInvoice(ctx context.Context, amount int64, description string) (*MakeInvoiceResponse, error)
LookupInvoice(ctx context.Context, paymentHash string) (*LookupInvoiceResponse, error)
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/hooks/useTransactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ const pollConfiguration: SWRConfiguration = {
refreshInterval: 3000,
};

export function useTransactions(poll = false) {
export function useTransactions(poll = false, limit = 100, page = 1) {
const offset = (page - 1) * limit;
return useSWR<Transaction[]>(
"/api/transactions",
`/api/transactions?limit=${limit}&offset=${offset}`,
swrFetcher,
poll ? pollConfiguration : undefined
);
Expand Down
34 changes: 27 additions & 7 deletions frontend/src/screens/wallet/OnboardingChecklist.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useApps } from "src/hooks/useApps";
import { useChannels } from "src/hooks/useChannels";
import { useInfo } from "src/hooks/useInfo";
import { useNodeConnectionInfo } from "src/hooks/useNodeConnectionInfo";
import { useTransactions } from "src/hooks/useTransactions";
import { cn } from "src/lib/utils";

function OnboardingChecklist() {
Expand All @@ -21,9 +22,15 @@ function OnboardingChecklist() {
const { data: channels } = useChannels();
const { data: info, hasChannelManagement, hasMnemonic } = useInfo();
const { data: nodeConnectionInfo } = useNodeConnectionInfo();
const { data: transactions } = useTransactions(false, 1);

const isLoading =
!albyMe || !apps || !channels || !info || !nodeConnectionInfo;
!albyMe ||
!apps ||
!channels ||
!info ||
!nodeConnectionInfo ||
!transactions;

if (isLoading) {
return;
Expand All @@ -41,17 +48,23 @@ function OnboardingChecklist() {
nodeConnectionInfo &&
albyMe?.keysend_pubkey === nodeConnectionInfo?.pubkey;
const hasChannel =
!hasChannelManagement ||
(hasChannelManagement && channels && channels?.length > 0);
!hasChannelManagement || (hasChannelManagement && channels.length > 0);
const hasBackedUp =
hasMnemonic &&
info &&
info.nextBackupReminder &&
new Date(info.nextBackupReminder).getTime() > new Date().getTime();
const hasCustomApp =
apps && apps.find((x) => x.name !== "getalby.com") !== undefined;
const hasTransaction = transactions.length > 0;

if (isLinked && hasChannel && (!hasMnemonic || hasBackedUp) && hasCustomApp) {
if (
isLinked &&
hasChannel &&
(!hasMnemonic || hasBackedUp) &&
hasCustomApp &&
hasTransaction
) {
return;
}

Expand All @@ -63,23 +76,30 @@ function OnboardingChecklist() {
checked: hasChannel,
to: "/channels",
},
{
title: "Send or receive your first payment",
description:
"Use your newly opened channel to make a transaction on the Lightning Network.",
checked: hasTransaction,
to: "/wallet",
},
{
title: "Link your Alby Account",
description: "Link your lightning address & other apps to this hub.",
description: "Link your lightning address & other apps to this Hub.",
checked: isLinked,
to: "/apps",
},
// TODO: enable when we can always migrate funds
/*{
title: "Migrate your balance to your Alby Hub",
title: "Migrate your balance to your Hub",
description: "Move your existing funds into self-custody.",
checked: !hasAlbyBalance,
to: "/onboarding/lightning/migrate-alby",
},*/
{
title: "Connect your first app",
description:
"Seamlessly connect apps and integrate your wallet with other apps from your hub.",
"Seamlessly connect apps and integrate your wallet with other apps from your Hub.",
checked: hasCustomApp,
to: "/appstore",
},
Expand Down
18 changes: 17 additions & 1 deletion http/http_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"net/http"
"strconv"
"strings"

echologrus "github.com/davrux/echo-logrus/v4"
Expand Down Expand Up @@ -453,7 +454,22 @@ func (httpSvc *HttpService) lookupTransactionHandler(c echo.Context) error {
func (httpSvc *HttpService) listTransactionsHandler(c echo.Context) error {
ctx := c.Request().Context()

transactions, err := httpSvc.api.ListTransactions(ctx)
limit := uint64(20)
offset := uint64(0)

if limitParam := c.QueryParam("limit"); limitParam != "" {
if parsedLimit, err := strconv.ParseUint(limitParam, 10, 64); err == nil {
limit = parsedLimit
}
}

if offsetParam := c.QueryParam("offset"); offsetParam != "" {
if parsedOffset, err := strconv.ParseUint(offsetParam, 10, 64); err == nil {
offset = parsedOffset
}
}

transactions, err := httpSvc.api.ListTransactions(ctx, limit, offset)

if err != nil {
return c.JSON(http.StatusInternalServerError, ErrorResponse{
Expand Down
1 change: 1 addition & 0 deletions lnclient/lnd/lnd.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func (svc *LNDService) GetBalance(ctx context.Context) (balance int64, err error
return int64(resp.LocalBalance.Msat), nil
}

// FIXME: this always returns limit * 2 transactions and offset is not used correctly
func (svc *LNDService) ListTransactions(ctx context.Context, from, until, limit, offset uint64, unpaid bool, invoiceType string) (transactions []lnclient.Transaction, err error) {
// Fetch invoices
var invoices []*lnrpc.Invoice
Expand Down
39 changes: 33 additions & 6 deletions wails/wails_handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"os"
"regexp"
"strconv"
"strings"

"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -201,6 +202,38 @@ func (app *WailsApp) WailsRequestRouter(route string, method string, body string
return WailsRequestRouterResponse{Body: paymentInfo, Error: ""}
}

listTransactionsRegex := regexp.MustCompile(
`/api/transactions`,
)

switch {
case listTransactionsRegex.MatchString(route):
limit := uint64(20)
offset := uint64(0)

// Extract limit and offset parameters
paramRegex := regexp.MustCompile(`[?&](limit|offset)=([^&]+)`)
paramMatches := paramRegex.FindAllStringSubmatch(route, -1)
for _, match := range paramMatches {
switch match[1] {
case "limit":
if parsedLimit, err := strconv.ParseUint(match[2], 10, 64); err == nil {
limit = parsedLimit
}
case "offset":
if parsedOffset, err := strconv.ParseUint(match[2], 10, 64); err == nil {
offset = parsedOffset
}
}
}

transactions, err := app.api.ListTransactions(ctx, limit, offset)
if err != nil {
return WailsRequestRouterResponse{Body: nil, Error: err.Error()}
}
return WailsRequestRouterResponse{Body: transactions, Error: ""}
}

paymentRegex := regexp.MustCompile(
`/api/payments/([0-9a-zA-Z]+)`,
)
Expand Down Expand Up @@ -371,12 +404,6 @@ func (app *WailsApp) WailsRequestRouter(route string, method string, body string
}
res := WailsRequestRouterResponse{Body: invoice, Error: ""}
return res
case "/api/transactions":
transactions, err := app.api.ListTransactions(ctx)
if err != nil {
return WailsRequestRouterResponse{Body: nil, Error: err.Error()}
}
return WailsRequestRouterResponse{Body: transactions, Error: ""}
case "/api/wallet/sync":
app.api.SyncWallet()
return WailsRequestRouterResponse{Body: nil, Error: ""}
Expand Down

0 comments on commit e401a1e

Please sign in to comment.