Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass $ alongside TVL #489 #202

Merged
merged 13 commits into from
Feb 5, 2025
8 changes: 7 additions & 1 deletion config/config-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,10 @@ assets:
ordinals:
host: "http://ord-poc.devnet.babylonchain.io"
port: 8888
timeout: 1000
timeout: 1000
external_apis:
coinmarketcap:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to setup during deployment

api_key: ${COINMARKETCAP_API_KEY}
base_url: "https://pro-api.coinmarketcap.com/v1"
timeout: 10s # http client timeout
cache_ttl: 300s # mongodb ttl
8 changes: 7 additions & 1 deletion config/config-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,10 @@ assets:
ordinals:
host: "http://ord-poc.devnet.babylonchain.io"
port: 8888
timeout: 5000
timeout: 5000
external_apis:
coinmarketcap:
api_key: ${COINMARKETCAP_API_KEY}
base_url: "https://pro-api.coinmarketcap.com/v1"
timeout: 10s # http client timeout
cache_ttl: 300s # mongodb ttl
46 changes: 46 additions & 0 deletions docs/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,31 @@ const docTemplate = `{
}
}
},
"/v2/prices": {
"get": {
"description": "Get latest prices for all available symbols",
"produces": [
"application/json"
],
"tags": [
"v2"
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.PublicResponse-map_string_float64"
}
},
"400": {
"description": "Error: Bad Request",
"schema": {
"$ref": "#/definitions/github_com_babylonlabs-io_staking-api-service_internal_shared_types.Error"
}
}
}
}
},
"/v2/staker/stats": {
"get": {
"description": "Fetches staker stats for babylon staking including active tvl and active delegations.",
Expand Down Expand Up @@ -715,6 +740,17 @@ const docTemplate = `{
}
}
},
"handler.PublicResponse-map_string_float64": {
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/map_string_float64"
},
"pagination": {
"$ref": "#/definitions/handler.paginationResponse"
}
}
},
"handler.PublicResponse-map_string_string": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -870,6 +906,12 @@ const docTemplate = `{
}
}
},
"map_string_float64": {
"type": "object",
"additionalProperties": {
"type": "number"
}
},
"map_string_string": {
"type": "object",
"additionalProperties": {
Expand Down Expand Up @@ -1057,6 +1099,10 @@ const docTemplate = `{
"active_tvl": {
"type": "integer"
},
"btc_price_usd": {
"description": "Optional field",
"type": "number"
},
"pending_tvl": {
"type": "integer"
},
Expand Down
46 changes: 46 additions & 0 deletions docs/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,31 @@
}
}
},
"/v2/prices": {
"get": {
"description": "Get latest prices for all available symbols",
"produces": [
"application/json"
],
"tags": [
"v2"
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handler.PublicResponse-map_string_float64"
}
},
"400": {
"description": "Error: Bad Request",
"schema": {
"$ref": "#/definitions/github_com_babylonlabs-io_staking-api-service_internal_shared_types.Error"
}
}
}
}
},
"/v2/staker/stats": {
"get": {
"description": "Fetches staker stats for babylon staking including active tvl and active delegations.",
Expand Down Expand Up @@ -707,6 +732,17 @@
}
}
},
"handler.PublicResponse-map_string_float64": {
"type": "object",
"properties": {
"data": {
"$ref": "#/definitions/map_string_float64"
},
"pagination": {
"$ref": "#/definitions/handler.paginationResponse"
}
}
},
"handler.PublicResponse-map_string_string": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -862,6 +898,12 @@
}
}
},
"map_string_float64": {
"type": "object",
"additionalProperties": {
"type": "number"
}
},
"map_string_string": {
"type": "object",
"additionalProperties": {
Expand Down Expand Up @@ -1049,6 +1091,10 @@
"active_tvl": {
"type": "integer"
},
"btc_price_usd": {
"description": "Optional field",
"type": "number"
},
"pending_tvl": {
"type": "integer"
},
Expand Down
30 changes: 30 additions & 0 deletions docs/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ definitions:
pagination:
$ref: '#/definitions/handler.paginationResponse'
type: object
handler.PublicResponse-map_string_float64:
properties:
data:
$ref: '#/definitions/map_string_float64'
pagination:
$ref: '#/definitions/handler.paginationResponse'
type: object
handler.PublicResponse-map_string_string:
properties:
data:
Expand Down Expand Up @@ -152,6 +159,10 @@ definitions:
version:
type: integer
type: object
map_string_float64:
additionalProperties:
type: number
type: object
map_string_string:
additionalProperties:
type: string
Expand Down Expand Up @@ -279,6 +290,9 @@ definitions:
type: integer
active_tvl:
type: integer
btc_price_usd:
description: Optional field
type: number
pending_tvl:
type: integer
total_delegations:
Expand Down Expand Up @@ -914,6 +928,22 @@ paths:
$ref: '#/definitions/github_com_babylonlabs-io_staking-api-service_internal_shared_types.Error'
tags:
- v2
/v2/prices:
get:
description: Get latest prices for all available symbols
produces:
- application/json
responses:
"200":
description: OK
schema:
$ref: '#/definitions/handler.PublicResponse-map_string_float64'
"400":
description: 'Error: Bad Request'
schema:
$ref: '#/definitions/github_com_babylonlabs-io_staking-api-service_internal_shared_types.Error'
tags:
- v2
/v2/staker/stats:
get:
description: Fetches staker stats for babylon staking including active tvl and
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ require (
github.com/btcsuite/btcd/btcec/v2 v2.3.2
github.com/btcsuite/btcd/btcutil v1.1.6
github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0
github.com/miguelmota/go-coinmarketcap v0.1.8
github.com/robfig/cron/v3 v3.0.1
github.com/spf13/viper v1.19.0
github.com/swaggo/swag v1.16.3
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/anaskhan96/soup v1.0.1/go.mod h1:pT5vs4HXDwA5y4KQCsKvnkpQd3D+joP7IqpiGskfWW0=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
Expand Down Expand Up @@ -569,6 +570,8 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miguelmota/go-coinmarketcap v0.1.8 h1:rZhB7xs1j7qxxd1zftjADhAv6ECJQVhBom1dh3zURKY=
github.com/miguelmota/go-coinmarketcap v0.1.8/go.mod h1:hBjej1IiB5+pfj+0cZhnxRkAc2bgky8qWLhCJTQ3zjw=
github.com/minio/highwayhash v1.0.3 h1:kbnuUMoHYyVl7szWjSxJnxw11k2U709jqFPPmIUyD6Q=
github.com/minio/highwayhash v1.0.3/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
Expand Down Expand Up @@ -895,6 +898,7 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180215212450-dc948dff8834/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down
3 changes: 3 additions & 0 deletions internal/shared/api/handlers/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/babylonlabs-io/staking-api-service/internal/shared/types"
"github.com/babylonlabs-io/staking-api-service/internal/shared/utils"
"github.com/btcsuite/btcd/chaincfg"
"strings"
)

type Handler struct {
Expand Down Expand Up @@ -86,6 +87,8 @@ func ParsePublicKeyQuery(r *http.Request, queryName string, isOptional bool) (st

func ParseTxHashQuery(r *http.Request, queryName string) (string, *types.Error) {
txHashHex := r.URL.Query().Get(queryName)
txHashHex = strings.ToLower(txHashHex)

if txHashHex == "" {
return "", types.NewErrorWithMsg(
http.StatusBadRequest, types.BadRequest, queryName+" is required",
Expand Down
1 change: 1 addition & 0 deletions internal/shared/api/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func (a *Server) SetupRoutes(r *chi.Mux) {
r.Get("/v2/delegations", registerHandler(handlers.V2Handler.GetDelegations))
r.Get("/v2/stats", registerHandler(handlers.V2Handler.GetOverallStats))
r.Get("/v2/staker/stats", registerHandler(handlers.V2Handler.GetStakerStats))
r.Get("/v2/prices", registerHandler(handlers.V2Handler.GetPrices))

// Legacy endpoints needed to support phase-1 delegations to unbond.
// These will be deprecated once all phase-1 delegations are either withdrawn or registered into phase-2.
Expand Down
8 changes: 8 additions & 0 deletions internal/shared/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type Config struct {
Metrics *MetricsConfig `mapstructure:"metrics"`
Assets *AssetsConfig `mapstructure:"assets"`
DelegationTransition *DelegationTransitionConfig `mapstructure:"delegation-transition"`
ExternalAPIs *ExternalAPIsConfig `mapstructure:"external_apis"`
}

func (cfg *Config) Validate() error {
Expand Down Expand Up @@ -53,6 +54,13 @@ func (cfg *Config) Validate() error {
}
}

// ExternalAPIs is optional
if cfg.ExternalAPIs != nil {
if err := cfg.ExternalAPIs.Validate(); err != nil {
return err
}
}

return nil
}

Expand Down
45 changes: 45 additions & 0 deletions internal/shared/config/external_apis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package config

import (
"fmt"
"time"
)

type ExternalAPIsConfig struct {
CoinMarketCap *CoinMarketCapConfig `mapstructure:"coinmarketcap"`
}

type CoinMarketCapConfig struct {
APIKey string `mapstructure:"api_key"`
BaseURL string `mapstructure:"base_url"`
Timeout time.Duration `mapstructure:"timeout"`
CacheTTL time.Duration `mapstructure:"cache_ttl"`
}

func (cfg *ExternalAPIsConfig) Validate() error {
if cfg.CoinMarketCap == nil {
return fmt.Errorf("missing coinmarketcap config")
}

return cfg.CoinMarketCap.Validate()
}

func (cfg *CoinMarketCapConfig) Validate() error {
if cfg.APIKey == "" {
return fmt.Errorf("missing coinmarketcap api key")
}

if cfg.BaseURL == "" {
return fmt.Errorf("missing coinmarketcap base url")
}

if cfg.Timeout <= 0 {
return fmt.Errorf("invalid coinmarketcap timeout")
}

if cfg.CacheTTL <= 0 {
return fmt.Errorf("invalid coinmarketcap cache ttl")
}

return nil
}
39 changes: 39 additions & 0 deletions internal/shared/db/client/btc_price.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package dbclient

import (
"context"
model "github.com/babylonlabs-io/staking-api-service/internal/shared/db/model"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
"strings"
"time"
)

func (db *Database) GetLatestPrice(ctx context.Context, symbol string) (float64, error) {
symbol = strings.ToLower(symbol)

client := db.Client.Database(db.DbName).Collection(model.PriceCollection)
var doc model.CoinPrice
err := client.FindOne(ctx, bson.M{"_id": symbol}).Decode(&doc)
if err != nil {
return 0, err
}
return doc.Price, nil
}

func (db *Database) SetLatestPrice(ctx context.Context, symbol string, price float64) error {
symbol = strings.ToLower(symbol)

doc := model.CoinPrice{
ID: symbol,
Price: price,
CreatedAt: time.Now(), // For TTL index
}
opts := options.Update().SetUpsert(true)
filter := bson.M{"_id": symbol}
update := bson.M{"$set": doc}

client := db.Client.Database(db.DbName).Collection(model.PriceCollection)
_, err := client.UpdateOne(ctx, filter, update, opts)
return err
}
Loading
Loading