From aad2cdb97dc3d39fa5d66fd4b03a3cfdf32ec3e4 Mon Sep 17 00:00:00 2001 From: Mathieu Bruneau Date: Mon, 20 May 2024 02:27:46 +0000 Subject: [PATCH] Added route for /address/:addresses/txs and output as expected by V4 --- httpd/handlers/addresses.go | 98 +++++++++++++++++++++++-------------- httpd/router.go | 4 ++ 2 files changed, 66 insertions(+), 36 deletions(-) diff --git a/httpd/handlers/addresses.go b/httpd/handlers/addresses.go index 71321e9..5c3b6ef 100644 --- a/httpd/handlers/addresses.go +++ b/httpd/handlers/addresses.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/ledgerhq/satstack/httpd/svc" + "github.com/ledgerhq/satstack/types" "github.com/ledgerhq/satstack/utils" "github.com/gin-gonic/gin" @@ -14,49 +15,74 @@ import ( func GetAddresses(s svc.AddressesService) gin.HandlerFunc { return func(ctx *gin.Context) { - param := ctx.Param("addresses") - blockHashQuery := ctx.Query("block_hash") - blockHeightQuery := ctx.Query("block_height") + addresses, shouldReturn := getAdresses(ctx, s) + if shouldReturn { + return + } - addressList := strings.Split(param, ",") + ctx.JSON(http.StatusOK, addresses) + } +} - var blockHash *string - if blockHashQuery != "" { - blockHash = &blockHashQuery - } +func getAdresses(ctx *gin.Context, s svc.AddressesService) (types.Addresses, bool) { + param := ctx.Param("addresses") + blockHashQuery := ctx.Query("block_hash") + blockHeightQuery := ctx.Query("block_height") + + addressList := strings.Split(param, ",") + + var blockHash *string + if blockHashQuery != "" { + blockHash = &blockHashQuery + } + + var blockHeight *int32 + if blockHeightQuery != "" { + n, _ := strconv.ParseInt(blockHeightQuery, 10, 32) + i32 := int32(n) + blockHeight = &i32 + } - var blockHeight *int32 - if blockHeightQuery != "" { - n, _ := strconv.ParseInt(blockHeightQuery, 10, 32) - i32 := int32(n) - blockHeight = &i32 + addresses, err := s.GetAddresses(addressList, blockHash, blockHeight) + if err != nil { + ctx.String(http.StatusNotFound, "text/plain", []byte(err.Error())) + return types.Addresses{}, true + } + + // FIXME: libcore relies on the order of the transactions, in order to + // correctly compute operation values (aka amounts). This order + // appears to be based on the ReceivedAt field, although it is + // not documented in the Ledger BE project. + // + // The bug seems to manifest itself only on accounts with a + // large number of operations. + sort.Slice(addresses.Transactions[:], func(i, j int) bool { + iReceivedAt, iErr := utils.ParseRFC3339Timestamp(addresses.Transactions[i].ReceivedAt) + jReceivedAt, jErr := utils.ParseRFC3339Timestamp(addresses.Transactions[j].ReceivedAt) + + if iErr != nil || jErr != nil { + // Still a semi-reliable way of comparing RFC3339 timestamps. + return addresses.Transactions[i].ReceivedAt < addresses.Transactions[j].ReceivedAt } - addresses, err := s.GetAddresses(addressList, blockHash, blockHeight) - if err != nil { - ctx.String(http.StatusNotFound, "text/plain", []byte(err.Error())) + return *iReceivedAt < *jReceivedAt + }) + return addresses, false +} + +func GetV4Addresses(s svc.AddressesService) gin.HandlerFunc { + return func(ctx *gin.Context) { + + addresses, shouldReturn := getAdresses(ctx, s) + if shouldReturn { return } + type resp struct { + Data []types.Transaction `json:"data"` + Token *string `json:"token"` + } - // FIXME: libcore relies on the order of the transactions, in order to - // correctly compute operation values (aka amounts). This order - // appears to be based on the ReceivedAt field, although it is - // not documented in the Ledger BE project. - // - // The bug seems to manifest itself only on accounts with a - // large number of operations. - sort.Slice(addresses.Transactions[:], func(i, j int) bool { - iReceivedAt, iErr := utils.ParseRFC3339Timestamp(addresses.Transactions[i].ReceivedAt) - jReceivedAt, jErr := utils.ParseRFC3339Timestamp(addresses.Transactions[j].ReceivedAt) - - if iErr != nil || jErr != nil { - // Still a semi-reliable way of comparing RFC3339 timestamps. - return addresses.Transactions[i].ReceivedAt < addresses.Transactions[j].ReceivedAt - } - - return *iReceivedAt < *jReceivedAt - }) - - ctx.JSON(http.StatusOK, addresses) + response := resp{Data: addresses.Transactions} + ctx.JSON(http.StatusOK, response) } } diff --git a/httpd/router.go b/httpd/router.go index 2440f99..db3cf0b 100644 --- a/httpd/router.go +++ b/httpd/router.go @@ -49,5 +49,9 @@ func GetRouter(s *svc.Service) *gin.Engine { addressesRouter.GET(":addresses/transactions", handlers.GetAddresses(s)) } + addressRouter := currencyRouter.Group("/address") + { + addressRouter.GET(":addresses/txs", handlers.GetV4Addresses(s)) + } return engine }