Skip to content

Commit

Permalink
feat: sync delegations (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
gusin13 authored Oct 21, 2024
1 parent cca588f commit d6ecee3
Show file tree
Hide file tree
Showing 17 changed files with 524 additions and 49 deletions.
2 changes: 1 addition & 1 deletion config/config-local.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
db:
username: root
password: example
address: "mongodb://localhost:27017"
address: "mongodb://localhost:27019/?replicaSet=RS&directConnection=true"
db-name: babylon-staking-indexer
btc:
endpoint: localhost:18332
Expand Down
2 changes: 1 addition & 1 deletion contrib/images/babylon-staking-indexer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.21-alpine AS builder
FROM golang:1.22.3-alpine AS builder

ARG VERSION="HEAD"

Expand Down
8 changes: 4 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
version: "3.9"
services:
babylon-staking-indexer:
image: babylonlabs/babylon-staking-indexer:latest
image: babylonlabs-io/babylon-staking-indexer:latest
container_name: babylon-staking-indexer
environment:
- CONFIG=/home/babylon-staking-indexer/config.yml
depends_on:
- mongodb
- indexer-mongodb
- rabbitmq
volumes:
- ./config/config-docker.yml:/home/babylon-staking-indexer/config.yml:Z
mongodb:
indexer-mongodb:
image: mongo:latest
container_name: indexer-mongodb
hostname: indexer-mongodb
ports:
- "27017:27017"
- "27019:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
module github.com/babylonlabs-io/babylon-staking-indexer

go 1.23.2
go 1.22.3

require (
github.com/babylonlabs-io/babylon v0.12.1
github.com/babylonlabs-io/staking-queue-client v0.4.1
github.com/btcsuite/btcd v0.24.2
github.com/cometbft/cometbft v0.38.7
github.com/cosmos/cosmos-sdk v0.50.6
github.com/cosmos/gogoproto v1.7.0
github.com/go-chi/chi/v5 v5.1.0
github.com/spf13/viper v1.19.0
)
Expand Down Expand Up @@ -62,10 +64,8 @@ require (
github.com/cosmos/btcutil v1.0.5 // indirect
github.com/cosmos/cosmos-db v1.0.2 // indirect
github.com/cosmos/cosmos-proto v1.0.0-beta.5 // indirect
github.com/cosmos/cosmos-sdk v0.50.6 // indirect
github.com/cosmos/go-bip39 v1.0.0 // indirect
github.com/cosmos/gogogateway v1.2.0 // indirect
github.com/cosmos/gogoproto v1.7.0 // indirect
github.com/cosmos/iavl v1.1.2 // indirect
github.com/cosmos/ibc-go/modules/capability v1.0.0 // indirect
github.com/cosmos/ibc-go/v8 v8.3.0 // indirect
Expand Down
79 changes: 79 additions & 0 deletions internal/db/delegation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package db

import (
"context"
"errors"

"github.com/babylonlabs-io/babylon-staking-indexer/internal/db/model"
"github.com/babylonlabs-io/babylon-staking-indexer/internal/types"
"go.mongodb.org/mongo-driver/mongo"
)

func (db *Database) SaveNewBTCDelegation(
ctx context.Context, delegationDoc *model.BTCDelegationDetails,
) error {
_, err := db.client.Database(db.dbName).
Collection(model.BTCDelegationDetailsCollection).
InsertOne(ctx, delegationDoc)
if err != nil {
var writeErr mongo.WriteException
if errors.As(err, &writeErr) {
for _, e := range writeErr.WriteErrors {
if mongo.IsDuplicateKeyError(e) {
return &DuplicateKeyError{
Key: delegationDoc.StakingTxHashHex,
Message: "delegation already exists",
}
}
}
}
return err
}
return nil
}

func (db *Database) UpdateBTCDelegationState(
ctx context.Context, stakingTxHash string, newState types.DelegationState,
) error {
filter := map[string]interface{}{"_id": stakingTxHash}
update := map[string]interface{}{"$set": map[string]string{"state": newState.String()}}

res := db.client.Database(db.dbName).
Collection(model.BTCDelegationDetailsCollection).
FindOneAndUpdate(ctx, filter, update)

if res.Err() != nil {
if errors.Is(res.Err(), mongo.ErrNoDocuments) {
return &NotFoundError{
Key: stakingTxHash,
Message: "BTC delegation not found when updating state",
}
}
return res.Err()
}

return nil
}

func (db *Database) GetBTCDelegationByStakingTxHash(
ctx context.Context, stakingTxHash string,
) (*model.BTCDelegationDetails, error) {
filter := map[string]interface{}{"_id": stakingTxHash}
res := db.client.Database(db.dbName).
Collection(model.BTCDelegationDetailsCollection).
FindOne(ctx, filter)

var delegationDoc model.BTCDelegationDetails
err := res.Decode(&delegationDoc)
if err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
return nil, &NotFoundError{
Key: stakingTxHash,
Message: "BTC delegation not found when getting by staking tx hash",
}
}
return nil, err
}

return &delegationDoc, nil
}
30 changes: 30 additions & 0 deletions internal/db/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/babylonlabs-io/babylon-staking-indexer/internal/clients/bbnclient"
"github.com/babylonlabs-io/babylon-staking-indexer/internal/db/model"
"github.com/babylonlabs-io/babylon-staking-indexer/internal/types"
)

type DbInterface interface {
Expand Down Expand Up @@ -73,4 +74,33 @@ type DbInterface interface {
SaveCheckpointParams(
ctx context.Context, params *bbnclient.CheckpointParams,
) error
/**
* SaveNewBTCDelegation saves a new BTC delegation to the database.
* If the BTC delegation already exists, DuplicateKeyError will be returned.
* @param ctx The context
* @param delegationDoc The BTC delegation details
* @return An error if the operation failed
*/
SaveNewBTCDelegation(
ctx context.Context, delegationDoc *model.BTCDelegationDetails,
) error
/**
* SaveBTCDelegationStateUpdate saves a BTC delegation state update to the database.
* @param ctx The context
* @param delegationDoc The BTC delegation details
* @return An error if the operation failed
*/
UpdateBTCDelegationState(
ctx context.Context, stakingTxHash string, newState types.DelegationState,
) error
/**
* GetBTCDelegationByStakingTxHash retrieves the BTC delegation details by the staking tx hash.
* If the BTC delegation does not exist, a NotFoundError will be returned.
* @param ctx The context
* @param stakingTxHash The staking tx hash
* @return The BTC delegation details or an error
*/
GetBTCDelegationByStakingTxHash(
ctx context.Context, stakingTxHash string,
) (*model.BTCDelegationDetails, error)
}
31 changes: 27 additions & 4 deletions internal/db/model/delegation.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,33 @@ package model

import (
"github.com/babylonlabs-io/babylon-staking-indexer/internal/types"
bbntypes "github.com/babylonlabs-io/babylon/x/btcstaking/types"
)

type DelegationDocument struct {
StakingTxHashHex string `bson:"_id"` // Primary key
State types.DelegationState `bson:"state"`
// TODO: Placeholder for more fields
type BTCDelegationDetails struct {
StakingTxHashHex string `bson:"_id"` // Primary key
ParamsVersion string `bson:"params_version"`
FinalityProviderBtcPksHex []string `bson:"finality_provider_btc_pks_hex"`
StakerBtcPkHex string `bson:"staker_btc_pk_hex"`
StakingTime string `bson:"staking_time"`
StakingAmount string `bson:"staking_amount"`
UnbondingTime string `bson:"unbonding_time"`
UnbondingTx string `bson:"unbonding_tx"`
State types.DelegationState `bson:"state"`
}

func FromEventBTCDelegationCreated(
event *bbntypes.EventBTCDelegationCreated,
) *BTCDelegationDetails {
return &BTCDelegationDetails{
StakingTxHashHex: event.StakingTxHash, // babylon returns a hex string
ParamsVersion: event.ParamsVersion,
FinalityProviderBtcPksHex: event.FinalityProviderBtcPksHex,
StakerBtcPkHex: event.StakerBtcPkHex,
StakingTime: event.StakingTime,
StakingAmount: event.StakingAmount,
UnbondingTime: event.UnbondingTime,
UnbondingTx: event.UnbondingTx,
State: types.DelegationState(event.NewState),
}
}
4 changes: 2 additions & 2 deletions internal/db/model/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (

const (
FinalityProviderDetailsCollection = "finality_provider_details"
DelegationCollection = "delegation"
BTCDelegationDetailsCollection = "btc_delegation_details"
GlobalParamsCollection = "global_params"
)

Expand All @@ -26,7 +26,7 @@ type index struct {

var collections = map[string][]index{
FinalityProviderDetailsCollection: {{Indexes: map[string]int{}}},
DelegationCollection: {{Indexes: map[string]int{}}},
BTCDelegationDetailsCollection: {{Indexes: map[string]int{}}},
GlobalParamsCollection: {{Indexes: map[string]int{}}},
}

Expand Down
1 change: 1 addition & 0 deletions internal/db/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,6 @@ func (db *Database) SaveCheckpointParams(
if err != nil {
return fmt.Errorf("failed to save checkpoint params: %w", err)
}

return nil
}
Loading

0 comments on commit d6ecee3

Please sign in to comment.