mirror of
https://github.com/GrassrootsEconomics/cic-dw.git
synced 2025-02-01 10:27:32 +01:00
add (feat) pagination helpers and token endpoint
- see docs for pagination api usage - added control for syncer/api goroutines
This commit is contained in:
parent
2548e68c36
commit
37538c68ff
@ -33,6 +33,12 @@ type config struct {
|
||||
TokenRegistry string `koanf:"index"`
|
||||
BalanceResolver string `koanf:"balances_resolver"`
|
||||
}
|
||||
Syncer struct {
|
||||
Enabled bool `koanf:"enabled"`
|
||||
}
|
||||
Api struct {
|
||||
Enabled bool `koan:"enabled"`
|
||||
}
|
||||
Syncers map[string]string `koanf:"syncers"`
|
||||
}
|
||||
|
||||
|
@ -70,20 +70,25 @@ func main() {
|
||||
log.Fatal().Err(err).Msg("could not bootstrap scheduler")
|
||||
}
|
||||
|
||||
processor, mux := bootstrapProcessor(rClient)
|
||||
|
||||
if conf.Syncer.Enabled {
|
||||
go func() {
|
||||
if err := scheduler.Run(); err != nil {
|
||||
log.Fatal().Err(err).Msg("could not start scheduler")
|
||||
}
|
||||
}()
|
||||
|
||||
processor, mux := bootstrapProcessor(rClient)
|
||||
go func() {
|
||||
if err := processor.Run(mux); err != nil {
|
||||
log.Fatal().Err(err).Msg("failed to start job processor")
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
server := initHTTPServer()
|
||||
|
||||
if conf.Api.Enabled {
|
||||
go func() {
|
||||
if err := server.Start(conf.Server.Address); err != nil {
|
||||
if strings.Contains(err.Error(), "Server closed") {
|
||||
@ -93,6 +98,7 @@ func main() {
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, unix.SIGTERM, unix.SIGINT, unix.SIGTSTP)
|
||||
|
@ -16,6 +16,12 @@ index = "0x5A1EB529438D8b3cA943A45a48744f4c73d1f098"
|
||||
balances_resolver = "0xb9e215B789e9Ec6643Ba4ff7b98EA219F38c6fE5"
|
||||
rpc = "http://127.0.0.1:8545"
|
||||
|
||||
[syncer]
|
||||
enabled = true
|
||||
|
||||
[api]
|
||||
enabled = true
|
||||
|
||||
[syncers]
|
||||
cache = "@every 20s"
|
||||
ussd = "@every 30s"
|
||||
|
@ -27,5 +27,9 @@ func InitPublicApi(e *echo.Echo, db *pgxpool.Pool, batchBalance *batch_balance.B
|
||||
}
|
||||
})
|
||||
|
||||
// TODO: paginate schema validation
|
||||
|
||||
g.GET("/balances/:address", handleBalancesQuery)
|
||||
g.GET("/tokens-count", handleTokensCountQuery)
|
||||
g.GET("/tokens", handleTokenListQuery)
|
||||
}
|
||||
|
65
internal/public/tokens.go
Normal file
65
internal/public/tokens.go
Normal file
@ -0,0 +1,65 @@
|
||||
package public
|
||||
|
||||
import (
|
||||
"cic-dw/pkg/pagination"
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/georgysavva/scany/pgxscan"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type tokensRes struct {
|
||||
Id int `db:"id" json:"id"`
|
||||
TokenSymbol string `db:"token_symbol" json:"token_symbol"`
|
||||
TokenName string `db:"token_name" json:"token_name"`
|
||||
TokenAddress string `db:"token_address" json:"token_addres"`
|
||||
}
|
||||
|
||||
type tokenCountRes struct {
|
||||
Count int `db:"count" json:"count"`
|
||||
}
|
||||
|
||||
func handleTokenListQuery(c echo.Context) error {
|
||||
var (
|
||||
api = c.Get("api").(*api)
|
||||
pg = pagination.GetPagination(c.QueryParams())
|
||||
res []tokensRes
|
||||
q string
|
||||
)
|
||||
|
||||
if pg.Forward {
|
||||
q = api.q["list-tokens-fwd"]
|
||||
} else {
|
||||
q = api.q["list-tokens-bkwd"]
|
||||
}
|
||||
|
||||
rows, err := api.db.Query(context.Background(), q, pg.Cursor, pg.PerPage)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := pgxscan.ScanAll(&res, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, res)
|
||||
}
|
||||
|
||||
func handleTokensCountQuery(c echo.Context) error {
|
||||
var (
|
||||
api = c.Get("api").(*api)
|
||||
res tokenCountRes
|
||||
)
|
||||
|
||||
rows, err := api.db.Query(context.Background(), api.q["tokens-count"])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := pgxscan.ScanOne(&res, rows); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, res)
|
||||
}
|
34
pkg/pagination/pagination.go
Normal file
34
pkg/pagination/pagination.go
Normal file
@ -0,0 +1,34 @@
|
||||
package pagination
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type Pagination struct {
|
||||
PerPage int
|
||||
Cursor int
|
||||
Forward bool
|
||||
}
|
||||
|
||||
func GetPagination(q url.Values) Pagination {
|
||||
var (
|
||||
pp, _ = strconv.Atoi(q.Get("per_page"))
|
||||
cursor, _ = strconv.Atoi(q.Get("cursor"))
|
||||
forward, _ = strconv.ParseBool(q.Get("forward"))
|
||||
)
|
||||
|
||||
if pp > 100 {
|
||||
pp = 100
|
||||
}
|
||||
|
||||
if !forward && cursor < 1 {
|
||||
cursor = 1
|
||||
}
|
||||
|
||||
return Pagination{
|
||||
PerPage: pp,
|
||||
Cursor: cursor,
|
||||
Forward: forward,
|
||||
}
|
||||
}
|
@ -4,3 +4,16 @@ SELECT DISTINCT tokens.token_symbol, tokens.token_address FROM transactions
|
||||
INNER JOIN tokens on transactions.token_address = tokens.token_address
|
||||
WHERE transactions.sender_address = $1
|
||||
OR transactions.recipient_address = $1;
|
||||
|
||||
-- Bidirectional cursor pagianators
|
||||
-- name: list-tokens-fwd
|
||||
SELECT tokens.id, tokens.token_address, tokens.token_name, tokens.token_symbol FROM tokens
|
||||
WHERE tokens.id > $1 ORDER BY tokens.id ASC LIMIT $2;
|
||||
|
||||
-- name: list-tokens-bkwd
|
||||
SELECT tokens.id, tokens.token_address, tokens.token_name, tokens.token_symbol FROM tokens
|
||||
WHERE tokens.id < $1 ORDER BY tokens.id ASC LIMIT $2;
|
||||
|
||||
-- name: tokens-count
|
||||
-- Return total record count from individual i= tables/views
|
||||
SELECT COUNT(*) FROM tokens;
|
Loading…
Reference in New Issue
Block a user