diff --git a/internal/v1/db/client/delegation.go b/internal/v1/db/client/delegation.go index b06aae2..5ab0ccd 100644 --- a/internal/v1/db/client/delegation.go +++ b/internal/v1/db/client/delegation.go @@ -156,10 +156,10 @@ func (v1dbclient *V1Database) ScanDelegationsPaginated( ) } -// MarkDelegationAsTransformed marks an existing delegation as transformed -func (v1dbclient *V1Database) MarkDelegationAsTransformed(ctx context.Context, stakingTxHashHex string) error { +// MarkDelegationAsTransitioned marks an existing delegation as transitioned +func (v1dbclient *V1Database) MarkDelegationAsTransitioned(ctx context.Context, stakingTxHashHex string) error { client := v1dbclient.Client.Database(v1dbclient.DbName).Collection(dbmodel.V1DelegationCollection) - update := bson.M{"$set": bson.M{"transformed": true}} + update := bson.M{"$set": bson.M{"transitioned": true}} result, err := client.UpdateOne(ctx, bson.M{"_id": stakingTxHashHex}, update) if err != nil { return err diff --git a/internal/v1/db/client/interface.go b/internal/v1/db/client/interface.go index 2576884..997bde0 100644 --- a/internal/v1/db/client/interface.go +++ b/internal/v1/db/client/interface.go @@ -30,7 +30,7 @@ type V1DBClient interface { ctx context.Context, stakingTxHashHex, unbondingTxHashHex, txHex, signatureHex string, ) error FindDelegationByTxHashHex(ctx context.Context, txHashHex string) (*v1dbmodel.DelegationDocument, error) - MarkDelegationAsTransformed(ctx context.Context, stakingTxHashHex string) error + MarkDelegationAsTransitioned(ctx context.Context, stakingTxHashHex string) error SaveTimeLockExpireCheck(ctx context.Context, stakingTxHashHex string, expireHeight uint64, txType string) error TransitionToUnbondedState( ctx context.Context, stakingTxHashHex string, eligiblePreviousState []types.DelegationState, diff --git a/internal/v1/db/model/delegation.go b/internal/v1/db/model/delegation.go index 8dafc89..8f64bd4 100644 --- a/internal/v1/db/model/delegation.go +++ b/internal/v1/db/model/delegation.go @@ -22,7 +22,7 @@ type DelegationDocument struct { StakingTx *TimelockTransaction `bson:"staking_tx"` // Always exist UnbondingTx *TimelockTransaction `bson:"unbonding_tx,omitempty"` IsOverflow bool `bson:"is_overflow"` - Transformed bool `bson:"transformed"` + IsTransitioned bool `bson:"is_transitioned"` } type DelegationByStakerPagination struct { diff --git a/internal/v1/service/delegation.go b/internal/v1/service/delegation.go index eb11d1c..594cb33 100644 --- a/internal/v1/service/delegation.go +++ b/internal/v1/service/delegation.go @@ -32,7 +32,7 @@ type DelegationPublic struct { IsOverflow bool `json:"is_overflow"` IsEligibleForTransition bool `json:"is_eligible_for_transition"` IsSlashed bool `json:"is_slashed"` - Transformed bool `json:"transformed"` + IsTransitioned bool `json:"is_transitioned"` } func (s *V1Service) DelegationsByStakerPk( @@ -213,7 +213,7 @@ func (s *V1Service) FromDelegationDocument( IsOverflow: d.IsOverflow, IsEligibleForTransition: isFpTransitioned && !isSlashed && s.isEligibleForTransition(d, bbnHeight), IsSlashed: isSlashed, - Transformed: d.Transformed, + IsTransitioned: d.IsTransitioned, } // Add unbonding transaction if it exists diff --git a/internal/v2/db/client/deelgation.go b/internal/v2/db/client/deelgation.go new file mode 100644 index 0000000..e9c309e --- /dev/null +++ b/internal/v2/db/client/deelgation.go @@ -0,0 +1,55 @@ +package v2dbclient + +import ( + "context" + "errors" + + "github.com/babylonlabs-io/staking-api-service/internal/shared/db" + dbmodel "github.com/babylonlabs-io/staking-api-service/internal/shared/db/model" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/mongo" +) + +func (v2dbclient *V2Database) MarkV1DelegationAsTransitioned(ctx context.Context, stakingTxHashHex string) error { + session, err := v2dbclient.Client.StartSession() + if err != nil { + return err + } + defer session.EndSession(ctx) + + transactionWork := func(sessCtx mongo.SessionContext) (interface{}, error) { + client := v2dbclient.Client.Database(v2dbclient.DbName).Collection(dbmodel.V1DelegationCollection) + filter := bson.M{"_id": stakingTxHashHex} + + var delegation interface{} + err := client.FindOne(sessCtx, filter).Decode(&delegation) + if err != nil { + if errors.Is(err, mongo.ErrNoDocuments) { + return nil, &db.NotFoundError{ + Key: stakingTxHashHex, + Message: "Delegation not found", + } + } + return nil, err + } + + update := bson.M{"$set": bson.M{"transitioned": true}} + result, err := client.UpdateOne(sessCtx, filter, update) + if err != nil { + return nil, err + } + + if result.MatchedCount == 0 { + return nil, &db.NotFoundError{ + Key: stakingTxHashHex, + Message: "Delegation not found", + } + } + + return nil, nil + } + + _, err = session.WithTransaction(ctx, transactionWork) + return err +} + diff --git a/internal/v2/db/client/interface.go b/internal/v2/db/client/interface.go index 61665cd..3c3e987 100644 --- a/internal/v2/db/client/interface.go +++ b/internal/v2/db/client/interface.go @@ -26,4 +26,5 @@ type V2DBClient interface { SubtractStakerStats( ctx context.Context, stakingTxHashHex, stakerPkHex string, amount uint64, ) error + MarkV1DelegationAsTransitioned(ctx context.Context, stakingTxHashHex string) error } diff --git a/internal/v2/queue/handler/staking.go b/internal/v2/queue/handler/staking.go index 900ddf5..9b17eb2 100644 --- a/internal/v2/queue/handler/staking.go +++ b/internal/v2/queue/handler/staking.go @@ -20,9 +20,10 @@ func (h *V2QueueHandler) ActiveStakingHandler(ctx context.Context, messageBody s return types.NewError(http.StatusBadRequest, types.BadRequest, err) } - // Mark as v1 delegation as transformed if it exists - if err := h.Service.MarkV1DelegationAsTransformed(ctx, activeStakingEvent.StakingTxHashHex); err != nil { - log.Ctx(ctx).Error().Err(err).Msg("Failed to mark v1 delegation as transformed") + // Mark as v1 delegation as transitioned if it exists + if err := h.Service.MarkV1DelegationAsTransitioned(ctx, activeStakingEvent.StakingTxHashHex); err != nil { + log.Ctx(ctx).Error().Err(err).Msg("Failed to mark v1 delegation as transitioned") + return err } // Perform the address lookup conversion diff --git a/internal/v2/service/delegation.go b/internal/v2/service/delegation.go index a5a80b4..b5b5c0d 100644 --- a/internal/v2/service/delegation.go +++ b/internal/v2/service/delegation.go @@ -171,19 +171,12 @@ func (s *V2Service) SaveUnprocessableMessages(ctx context.Context, messageBody, return nil } -func (s *V2Service) MarkV1DelegationAsTransformed(ctx context.Context, stakingTxHashHex string) *types.Error { - // check if v1 delegation exists - delegation, err := s.DbClients.V1DBClient.FindDelegationByTxHashHex(ctx, stakingTxHashHex) - if err != nil { - return types.NewInternalServiceError(err) - } - if delegation == nil { - return nil - } - - // mark as transformed - err = s.DbClients.V1DBClient.MarkDelegationAsTransformed(ctx, stakingTxHashHex) +func (s *V2Service) MarkV1DelegationAsTransitioned(ctx context.Context, stakingTxHashHex string) *types.Error { + err := s.DbClients.V2DBClient.MarkV1DelegationAsTransitioned(ctx, stakingTxHashHex) if err != nil { + if db.IsNotFoundError(err) { + return nil + } return types.NewInternalServiceError(err) } return nil diff --git a/internal/v2/service/interface.go b/internal/v2/service/interface.go index 238d344..8530eca 100644 --- a/internal/v2/service/interface.go +++ b/internal/v2/service/interface.go @@ -14,7 +14,7 @@ type V2ServiceProvider interface { IsDelegationPresent(ctx context.Context, txHashHex string) (bool, *types.Error) GetDelegation(ctx context.Context, stakingTxHashHex string) (*StakerDelegationPublic, *types.Error) GetDelegations(ctx context.Context, stakerPKHex string, paginationKey string) ([]*StakerDelegationPublic, string, *types.Error) - MarkV1DelegationAsTransformed(ctx context.Context, stakingTxHashHex string) *types.Error + MarkV1DelegationAsTransitioned(ctx context.Context, stakingTxHashHex string) *types.Error GetOverallStats(ctx context.Context) (*OverallStatsPublic, *types.Error) GetStakerStats(ctx context.Context, stakerPKHex string) (*StakerStatsPublic, *types.Error) ProcessAndSaveBtcAddresses(ctx context.Context, stakerPkHex string) *types.Error diff --git a/tests/mocks/mock_v1_db_client.go b/tests/mocks/mock_v1_db_client.go index c3e5d5d..c234b4e 100644 --- a/tests/mocks/mock_v1_db_client.go +++ b/tests/mocks/mock_v1_db_client.go @@ -500,12 +500,12 @@ func (_m *V1DBClient) InsertPkAddressMappings(ctx context.Context, stakerPkHex s return r0 } -// MarkDelegationAsTransformed provides a mock function with given fields: ctx, stakingTxHashHex -func (_m *V1DBClient) MarkDelegationAsTransformed(ctx context.Context, stakingTxHashHex string) error { +// MarkDelegationAsTransitioned provides a mock function with given fields: ctx, stakingTxHashHex +func (_m *V1DBClient) MarkDelegationAsTransitioned(ctx context.Context, stakingTxHashHex string) error { ret := _m.Called(ctx, stakingTxHashHex) if len(ret) == 0 { - panic("no return value specified for MarkDelegationAsTransformed") + panic("no return value specified for MarkDelegationAsTransitioned") } var r0 error diff --git a/tests/mocks/mock_v2_db_client.go b/tests/mocks/mock_v2_db_client.go index 5468bbf..4c43e41 100644 --- a/tests/mocks/mock_v2_db_client.go +++ b/tests/mocks/mock_v2_db_client.go @@ -268,6 +268,24 @@ func (_m *V2DBClient) InsertPkAddressMappings(ctx context.Context, stakerPkHex s return r0 } +// MarkV1DelegationAsTransitioned provides a mock function with given fields: ctx, stakingTxHashHex +func (_m *V2DBClient) MarkV1DelegationAsTransitioned(ctx context.Context, stakingTxHashHex string) error { + ret := _m.Called(ctx, stakingTxHashHex) + + if len(ret) == 0 { + panic("no return value specified for MarkV1DelegationAsTransitioned") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { + r0 = rf(ctx, stakingTxHashHex) + } else { + r0 = ret.Error(0) + } + + return r0 +} + // Ping provides a mock function with given fields: ctx func (_m *V2DBClient) Ping(ctx context.Context) error { ret := _m.Called(ctx)