diff --git a/internal/v2/db/client/interface.go b/internal/v2/db/client/interface.go index 0a515a3..a7cd082 100644 --- a/internal/v2/db/client/interface.go +++ b/internal/v2/db/client/interface.go @@ -29,4 +29,7 @@ type V2DBClient interface { IncrementFinalityProviderStats( ctx context.Context, stakingTxHashHex string, fpPkHexes []string, amount uint64, ) error + SubtractFinalityProviderStats( + ctx context.Context, stakingTxHashHex string, fpPkHexes []string, amount uint64, + ) error } diff --git a/internal/v2/db/client/stats.go b/internal/v2/db/client/stats.go index ee8810a..c557431 100644 --- a/internal/v2/db/client/stats.go +++ b/internal/v2/db/client/stats.go @@ -339,6 +339,36 @@ func (v2dbclient *V2Database) IncrementFinalityProviderStats( ) } +func (v2dbclient *V2Database) SubtractFinalityProviderStats( + ctx context.Context, + stakingTxHashHex string, + fpPkHexes []string, + amount uint64, +) error { + + // Create bulk write operations for each FP + var operations []mongo.WriteModel + for _, fpPkHex := range fpPkHexes { + operation := mongo.NewUpdateOneModel(). + SetFilter(bson.M{"_id": fpPkHex}). + SetUpdate(bson.M{ + "$inc": bson.M{ + "active_tvl": -int64(amount), + "active_delegations": -1, + }, + }). + SetUpsert(true) + operations = append(operations, operation) + } + + return v2dbclient.updateFinalityProviderStats( + ctx, + types.Unbonded.ToString(), + stakingTxHashHex, + operations, + ) +} + func (v2dbclient *V2Database) updateFinalityProviderStats( ctx context.Context, state string, diff --git a/internal/v2/service/stats.go b/internal/v2/service/stats.go index f4cfca5..e374c07 100644 --- a/internal/v2/service/stats.go +++ b/internal/v2/service/stats.go @@ -135,7 +135,20 @@ func (s *V2Service) ProcessStakingStatsCalculation( } } case types.Unbonded: - // TODO: Add finality provider stats calculation + // Subtract from the finality stats + if !statsLockDocument.FinalityProviderStats { + err = s.DbClients.V2DBClient.SubtractFinalityProviderStats( + ctx, stakingTxHashHex, finalityProviderBtcPksHex, amount, + ) + if err != nil { + if db.IsNotFoundError(err) { + return nil + } + log.Ctx(ctx).Error().Err(err).Str("stakingTxHashHex", stakingTxHashHex). + Msg("error while subtracting finality stats") + return types.NewInternalServiceError(err) + } + } if !statsLockDocument.StakerStats { err = s.DbClients.V2DBClient.SubtractStakerStats( diff --git a/tests/mocks/mock_v2_db_client.go b/tests/mocks/mock_v2_db_client.go index 9796f7c..4766b63 100644 --- a/tests/mocks/mock_v2_db_client.go +++ b/tests/mocks/mock_v2_db_client.go @@ -214,6 +214,24 @@ func (_m *V2DBClient) GetStakerStats(ctx context.Context, stakerPKHex string) (* return r0, r1 } +// IncrementFinalityProviderStats provides a mock function with given fields: ctx, stakingTxHashHex, fpPkHexes, amount +func (_m *V2DBClient) IncrementFinalityProviderStats(ctx context.Context, stakingTxHashHex string, fpPkHexes []string, amount uint64) error { + ret := _m.Called(ctx, stakingTxHashHex, fpPkHexes, amount) + + if len(ret) == 0 { + panic("no return value specified for IncrementFinalityProviderStats") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, []string, uint64) error); ok { + r0 = rf(ctx, stakingTxHashHex, fpPkHexes, amount) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // IncrementOverallStats provides a mock function with given fields: ctx, stakingTxHashHex, stakerPkHex, amount func (_m *V2DBClient) IncrementOverallStats(ctx context.Context, stakingTxHashHex string, stakerPkHex string, amount uint64) error { ret := _m.Called(ctx, stakingTxHashHex, stakerPkHex, amount) @@ -304,6 +322,24 @@ func (_m *V2DBClient) SaveUnprocessableMessage(ctx context.Context, messageBody return r0 } +// SubtractFinalityProviderStats provides a mock function with given fields: ctx, stakingTxHashHex, fpPkHexes, amount +func (_m *V2DBClient) SubtractFinalityProviderStats(ctx context.Context, stakingTxHashHex string, fpPkHexes []string, amount uint64) error { + ret := _m.Called(ctx, stakingTxHashHex, fpPkHexes, amount) + + if len(ret) == 0 { + panic("no return value specified for SubtractFinalityProviderStats") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string, []string, uint64) error); ok { + r0 = rf(ctx, stakingTxHashHex, fpPkHexes, amount) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // SubtractOverallStats provides a mock function with given fields: ctx, stakingTxHashHex, stakerPkHex, amount func (_m *V2DBClient) SubtractOverallStats(ctx context.Context, stakingTxHashHex string, stakerPkHex string, amount uint64) error { ret := _m.Called(ctx, stakingTxHashHex, stakerPkHex, amount)