mirror of
https://github.com/GrassrootsEconomics/cic-dw.git
synced 2024-11-10 18:36:46 +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"`
|
TokenRegistry string `koanf:"index"`
|
||||||
BalanceResolver string `koanf:"balances_resolver"`
|
BalanceResolver string `koanf:"balances_resolver"`
|
||||||
}
|
}
|
||||||
|
Syncer struct {
|
||||||
|
Enabled bool `koanf:"enabled"`
|
||||||
|
}
|
||||||
|
Api struct {
|
||||||
|
Enabled bool `koan:"enabled"`
|
||||||
|
}
|
||||||
Syncers map[string]string `koanf:"syncers"`
|
Syncers map[string]string `koanf:"syncers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,20 +70,25 @@ func main() {
|
|||||||
log.Fatal().Err(err).Msg("could not bootstrap scheduler")
|
log.Fatal().Err(err).Msg("could not bootstrap scheduler")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processor, mux := bootstrapProcessor(rClient)
|
||||||
|
|
||||||
|
if conf.Syncer.Enabled {
|
||||||
go func() {
|
go func() {
|
||||||
if err := scheduler.Run(); err != nil {
|
if err := scheduler.Run(); err != nil {
|
||||||
log.Fatal().Err(err).Msg("could not start scheduler")
|
log.Fatal().Err(err).Msg("could not start scheduler")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
processor, mux := bootstrapProcessor(rClient)
|
|
||||||
go func() {
|
go func() {
|
||||||
if err := processor.Run(mux); err != nil {
|
if err := processor.Run(mux); err != nil {
|
||||||
log.Fatal().Err(err).Msg("failed to start job processor")
|
log.Fatal().Err(err).Msg("failed to start job processor")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
server := initHTTPServer()
|
server := initHTTPServer()
|
||||||
|
|
||||||
|
if conf.Api.Enabled {
|
||||||
go func() {
|
go func() {
|
||||||
if err := server.Start(conf.Server.Address); err != nil {
|
if err := server.Start(conf.Server.Address); err != nil {
|
||||||
if strings.Contains(err.Error(), "Server closed") {
|
if strings.Contains(err.Error(), "Server closed") {
|
||||||
@ -93,6 +98,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
sigs := make(chan os.Signal, 1)
|
sigs := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigs, unix.SIGTERM, unix.SIGINT, unix.SIGTSTP)
|
signal.Notify(sigs, unix.SIGTERM, unix.SIGINT, unix.SIGTSTP)
|
||||||
|
@ -16,6 +16,12 @@ index = "0x5A1EB529438D8b3cA943A45a48744f4c73d1f098"
|
|||||||
balances_resolver = "0xb9e215B789e9Ec6643Ba4ff7b98EA219F38c6fE5"
|
balances_resolver = "0xb9e215B789e9Ec6643Ba4ff7b98EA219F38c6fE5"
|
||||||
rpc = "http://127.0.0.1:8545"
|
rpc = "http://127.0.0.1:8545"
|
||||||
|
|
||||||
|
[syncer]
|
||||||
|
enabled = true
|
||||||
|
|
||||||
|
[api]
|
||||||
|
enabled = true
|
||||||
|
|
||||||
[syncers]
|
[syncers]
|
||||||
cache = "@every 20s"
|
cache = "@every 20s"
|
||||||
ussd = "@every 30s"
|
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("/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
|
INNER JOIN tokens on transactions.token_address = tokens.token_address
|
||||||
WHERE transactions.sender_address = $1
|
WHERE transactions.sender_address = $1
|
||||||
OR transactions.recipient_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