From 6ebd1bdc98afbad4e86900bb7ec6a7f7d7e1981f Mon Sep 17 00:00:00 2001
From: dylanyang <yl976931569@163.com>
Date: Tue, 4 Jun 2024 20:50:05 +0800
Subject: [PATCH] resolve Comment

---
 common/utils/util.go                          |  16 ++
 rpc_server/api/v1/sponsor.go                  |  20 +-
 .../sponsor_changelog_repository.go           |   2 +-
 sponsor_manager/sponsor_service.go            | 255 +++++++++---------
 4 files changed, 152 insertions(+), 141 deletions(-)

diff --git a/common/utils/util.go b/common/utils/util.go
index 6dada604..25105bc6 100644
--- a/common/utils/util.go
+++ b/common/utils/util.go
@@ -14,6 +14,7 @@ import (
 	"github.com/ethereum/go-ethereum/rpc"
 	"github.com/sirupsen/logrus"
 	"golang.org/x/xerrors"
+	"gorm.io/gorm"
 	"math/big"
 	"regexp"
 	"runtime"
@@ -200,3 +201,18 @@ func GetCurrentGoroutineStack() string {
 	n := runtime.Stack(buf[:], false)
 	return string(buf[:n])
 }
+func DBTransactional(db *gorm.DB, handle func() error) (err error) {
+	tx := db.Begin()
+	defer func() {
+		if p := recover(); p != nil {
+			tx.Rollback()
+			panic(p)
+		} else if err != nil {
+			tx.Rollback()
+		} else {
+			err = tx.Commit().Error
+		}
+	}()
+	err = handle()
+	return
+}
diff --git a/rpc_server/api/v1/sponsor.go b/rpc_server/api/v1/sponsor.go
index fe4c09af..35c28ebb 100644
--- a/rpc_server/api/v1/sponsor.go
+++ b/rpc_server/api/v1/sponsor.go
@@ -66,7 +66,7 @@ func WithdrawSponsor(ctx *gin.Context) {
 	return
 }
 
-type SponsorDepositTransaction struct {
+type sponsorDepositTransaction struct {
 	TxHash     string                  `json:"tx_hash"`
 	Amount     string                  `json:"amount"`
 	UpdateType global_const.UpdateType `json:"update_type"`
@@ -90,12 +90,12 @@ func GetSponsorDepositAndWithdrawTransactions(ctx *gin.Context) {
 	models, err := sponsor_manager.GetDepositAndWithDrawLog(userId, isTestNet)
 	if err != nil {
 		if errors.Is(err, gorm.ErrRecordNotFound) {
-			response.FailCode(ctx, 301, "No Deposit Transactions")
+			response.FailCode(ctx, 400, "No Deposit Transactions")
 		}
 	}
-	trans := make([]SponsorDepositTransaction, 0)
+	trans := make([]sponsorDepositTransaction, 0)
 	for _, depositModel := range models {
-		tran := SponsorDepositTransaction{
+		tran := sponsorDepositTransaction{
 			TxHash: depositModel.TxHash,
 			Amount: depositModel.Amount.String(),
 		}
@@ -105,11 +105,6 @@ func GetSponsorDepositAndWithdrawTransactions(ctx *gin.Context) {
 	return
 }
 
-type SponsorMetaResponse struct {
-	AvailableBalance string `json:"available_balance"`
-	SponsorAddress   string `json:"sponsor_address"`
-}
-
 // GetSponsorMetaData
 // @Tags Sponsor
 // @Description Get Sponsor Balance
@@ -126,10 +121,13 @@ func GetSponsorMetaData(ctx *gin.Context) {
 	balance, err := sponsor_manager.FindUserSponsorBalance(userId, isTestNet)
 	if err != nil {
 		if errors.Is(err, gorm.ErrRecordNotFound) {
-			response.FailCode(ctx, 301, "No Balance")
+			response.FailCode(ctx, 400, "No Balance")
 		}
 	}
-	result := SponsorMetaResponse{
+	result := struct {
+		AvailableBalance string `json:"available_balance"`
+		SponsorAddress   string `json:"sponsor_address"`
+	}{
 		AvailableBalance: balance.AvailableBalance.String(),
 		SponsorAddress:   balance.SponsorAddress,
 	}
diff --git a/sponsor_manager/sponsor_changelog_repository.go b/sponsor_manager/sponsor_changelog_repository.go
index 7d0694f4..768ed50d 100644
--- a/sponsor_manager/sponsor_changelog_repository.go
+++ b/sponsor_manager/sponsor_changelog_repository.go
@@ -32,7 +32,7 @@ func LogBalanceChange(updateType global_const.UpdateType, balanceType global_con
 	return
 }
 func GetDepositAndWithDrawLog(userId string, IsTestNet bool) (models []*UserSponsorBalanceUpdateLogDBModel, err error) {
-	tx := relayDB.Model(&UserSponsorBalanceUpdateLogDBModel{}).Where("pay_user_id = ?", userId).Where("is_test_net = ?", IsTestNet).Where("update_type = ?", global_const.UpdateTypeDeposit).Or("update_type = ?", global_const.UpdateTypeWithdraw).Find(&models)
+	tx := relayDB.Model(&UserSponsorBalanceUpdateLogDBModel{}).Where("pay_user_id = ?", userId).Where("is_test_net = ?", IsTestNet).Where("update_type in (?)", []global_const.UpdateType{global_const.UpdateTypeDeposit, global_const.UpdateTypeWithdraw}).Find(&models)
 	if tx.Error != nil {
 		return nil, tx.Error
 	}
diff --git a/sponsor_manager/sponsor_service.go b/sponsor_manager/sponsor_service.go
index 4f6d72f2..009d001c 100644
--- a/sponsor_manager/sponsor_service.go
+++ b/sponsor_manager/sponsor_service.go
@@ -77,29 +77,25 @@ func LockUserBalance(userId string, userOpHash []byte, isTestNet bool,
 	availableBalance := new(big.Float).Sub(balanceModel.AvailableBalance.Float, lockAmount)
 	balanceModel.LockBalance = BigFloat{lockBalance}
 	balanceModel.AvailableBalance = BigFloat{availableBalance}
-	tx := relayDB.Begin()
-	if updateErr := tx.Model(&UserSponsorBalanceDBModel{}).
-		Where("pay_user_id = ?", balanceModel.PayUserId).
-		Where("is_test_net = ?", isTestNet).Updates(balanceModel).Error; updateErr != nil {
-		tx.Rollback()
-		return nil, updateErr
-	}
+	err = utils.DBTransactional(relayDB, func() error {
+		if updateErr := relayDB.Model(&UserSponsorBalanceDBModel{}).
+			Where("pay_user_id = ?", balanceModel.PayUserId).
+			Where("is_test_net = ?", isTestNet).Updates(balanceModel).Error; updateErr != nil {
+			return err
+		}
 
-	changeModel := &UserSponsorBalanceUpdateLogDBModel{
-		UserOpHash: UserOphashStr,
-		PayUserId:  userId,
-		Amount:     BigFloat{lockAmount},
-		IsTestNet:  isTestNet,
-		UpdateType: global_const.UpdateTypeLock,
-	}
-	if createErr := tx.Create(changeModel).Error; createErr != nil {
-		tx.Rollback()
-		return nil, createErr
-	}
-	if commitErr := tx.Commit().Error; commitErr != nil {
-		tx.Rollback()
-		return nil, commitErr
-	}
+		changeModel := &UserSponsorBalanceUpdateLogDBModel{
+			UserOpHash: UserOphashStr,
+			PayUserId:  userId,
+			Amount:     BigFloat{lockAmount},
+			IsTestNet:  isTestNet,
+			UpdateType: global_const.UpdateTypeLock,
+		}
+		if createErr := relayDB.Create(changeModel).Error; createErr != nil {
+			return err
+		}
+		return nil
+	})
 
 	return nil, nil
 }
@@ -119,31 +115,31 @@ func ReleaseBalanceWithActualCost(userId string, userOpHash []byte,
 	refundBalance := new(big.Float).Sub(lockBalance.Float, actualGasCost)
 	balanceModel.AvailableBalance = BigFloat{new(big.Float).Add(balanceModel.AvailableBalance.Float, refundBalance)}
 
-	tx := relayDB.Begin()
-	if updateErr := tx.Model(&UserSponsorBalanceDBModel{}).
-		Model(&UserSponsorBalanceDBModel{}).
-		Where("pay_user_id = ?", balanceModel.PayUserId).
-		Where("is_test_net = ?", isTestNet).Updates(balanceModel).Error; updateErr != nil {
-		tx.Rollback()
+	err = utils.DBTransactional(relayDB, func() error {
+		if updateErr := relayDB.Model(&UserSponsorBalanceDBModel{}).
+			Model(&UserSponsorBalanceDBModel{}).
+			Where("pay_user_id = ?", balanceModel.PayUserId).
+			Where("is_test_net = ?", isTestNet).Updates(balanceModel).Error; updateErr != nil {
+			return err
+		}
+
+		changeDBModel := &UserSponsorBalanceUpdateLogDBModel{
+			UserOpHash: userOpHashHex,
+			PayUserId:  changeModel.PayUserId,
+			Amount:     BigFloat{refundBalance},
+			Source:     "GasTank",
+			IsTestNet:  isTestNet,
+			UpdateType: global_const.UpdateTypeRelease,
+		}
+		if createErr := relayDB.Create(changeDBModel).Error; createErr != nil {
+			return createErr
+		}
+		return nil
+	})
+	if err != nil {
 		return nil, err
 	}
 
-	changeDBModel := &UserSponsorBalanceUpdateLogDBModel{
-		UserOpHash: userOpHashHex,
-		PayUserId:  changeModel.PayUserId,
-		Amount:     BigFloat{refundBalance},
-		Source:     "GasTank",
-		IsTestNet:  isTestNet,
-		UpdateType: global_const.UpdateTypeRelease,
-	}
-	if createErr := tx.Create(changeDBModel).Error; createErr != nil {
-		tx.Rollback()
-		return nil, createErr
-	}
-	if commitErr := tx.Commit().Error; commitErr != nil {
-		tx.Rollback()
-		return nil, commitErr
-	}
 	return balanceModel, nil
 }
 
@@ -163,30 +159,29 @@ func ReleaseUserOpHashLockWhenFail(userOpHash []byte, isTestNet bool) (*UserSpon
 	lockBalance := changeModel.Amount
 	balanceModel.LockBalance = BigFloat{new(big.Float).Sub(balanceModel.LockBalance.Float, lockBalance.Float)}
 	balanceModel.AvailableBalance = BigFloat{new(big.Float).Add(balanceModel.AvailableBalance.Float, lockBalance.Float)}
-	tx := relayDB.Begin()
-	if updateErr := tx.Model(&UserSponsorBalanceDBModel{}).
-		Where("pay_user_id = ?", balanceModel.PayUserId).
-		Where("is_test_net = ?", isTestNet).Updates(balanceModel).Error; updateErr != nil {
-		tx.Rollback()
-		return nil, err
-	}
+	err = utils.DBTransactional(relayDB, func() error {
+		if updateErr := relayDB.Model(&UserSponsorBalanceDBModel{}).
+			Where("pay_user_id = ?", balanceModel.PayUserId).
+			Where("is_test_net = ?", isTestNet).Updates(balanceModel).Error; updateErr != nil {
+			return err
+		}
 
-	changeDBModel := &UserSponsorBalanceUpdateLogDBModel{
-		UserOpHash: userOpHashHex,
-		PayUserId:  changeModel.PayUserId,
-		Amount:     lockBalance,
-		IsTestNet:  isTestNet,
-		UpdateType: global_const.UpdateTypeRelease,
-	}
-	if createErr := tx.Create(changeDBModel).Error; createErr != nil {
-		tx.Rollback()
-		return nil, createErr
-	}
-	if commitErr := tx.Commit().Error; commitErr != nil {
-		tx.Rollback()
-		return nil, commitErr
+		changeDBModel := &UserSponsorBalanceUpdateLogDBModel{
+			UserOpHash: userOpHashHex,
+			PayUserId:  changeModel.PayUserId,
+			Amount:     lockBalance,
+			IsTestNet:  isTestNet,
+			UpdateType: global_const.UpdateTypeRelease,
+		}
+		if createErr := relayDB.Create(changeDBModel).Error; createErr != nil {
+			return createErr
+		}
+		return nil
+	})
+	if err != nil {
+		return nil, err
 	}
-	return nil, err
+	return balanceModel, nil
 }
 
 //----------Functions----------
@@ -194,54 +189,57 @@ func ReleaseUserOpHashLockWhenFail(userOpHash []byte, isTestNet bool) (*UserSpon
 func DepositSponsor(input *model.DepositSponsorRequest) (*UserSponsorBalanceDBModel, error) {
 
 	balanceModel, err := FindUserSponsorBalance(input.PayUserId, input.IsTestNet)
+	if err != nil {
+		return nil, err
+	}
 
-	tx := relayDB.Begin()
-	if errors.Is(err, gorm.ErrRecordNotFound) {
-		//init Data
-		balanceModel = &UserSponsorBalanceDBModel{}
-		balanceModel.AvailableBalance = BigFloat{big.NewFloat(0)}
-		balanceModel.PayUserId = input.PayUserId
-		balanceModel.LockBalance = BigFloat{big.NewFloat(0)}
-		balanceModel.IsTestNet = input.IsTestNet
-		err = tx.Create(balanceModel).Error
+	err = utils.DBTransactional(relayDB, func() error {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			//init Data
+			balanceModel = &UserSponsorBalanceDBModel{}
+			balanceModel.AvailableBalance = BigFloat{big.NewFloat(0)}
+			balanceModel.PayUserId = input.PayUserId
+			balanceModel.LockBalance = BigFloat{big.NewFloat(0)}
+			balanceModel.IsTestNet = input.IsTestNet
+			err = relayDB.Create(balanceModel).Error
+			if err != nil {
+
+				return err
+			}
+		}
 		if err != nil {
-			tx.Rollback()
-			return nil, err
+
+			return err
 		}
-	}
+		newAvailableBalance := BigFloat{new(big.Float).Add(balanceModel.AvailableBalance.Float, input.Amount)}
+		balanceModel.AvailableBalance = newAvailableBalance
+
+		if updateErr := relayDB.Model(balanceModel).
+			Where("pay_user_id = ?", balanceModel.PayUserId).
+			Where("is_test_net = ?", input.IsTestNet).Updates(balanceModel).Error; updateErr != nil {
+
+			return updateErr
+		}
+
+		txInfoJSon, _ := json.Marshal(input.TxInfo)
+		changeModel := &UserSponsorBalanceUpdateLogDBModel{
+			PayUserId:  input.PayUserId,
+			Amount:     BigFloat{input.Amount},
+			Source:     "Deposit",
+			IsTestNet:  input.IsTestNet,
+			UpdateType: global_const.UpdateTypeDeposit,
+			TxHash:     input.TxHash,
+			TxInfo:     txInfoJSon,
+		}
+		if createErr := relayDB.Create(changeModel).Error; createErr != nil {
+			return createErr
+		}
+		return nil
+	})
 	if err != nil {
-		tx.Rollback()
 		return nil, err
 	}
-	newAvailableBalance := BigFloat{new(big.Float).Add(balanceModel.AvailableBalance.Float, input.Amount)}
-	balanceModel.AvailableBalance = newAvailableBalance
-
-	if updateErr := tx.Model(balanceModel).
-		Where("pay_user_id = ?", balanceModel.PayUserId).
-		Where("is_test_net = ?", input.IsTestNet).Updates(balanceModel).Error; updateErr != nil {
-		tx.Rollback()
-		return nil, updateErr
-	}
-
-	txInfoJSon, _ := json.Marshal(input.TxInfo)
-	chagneModel := &UserSponsorBalanceUpdateLogDBModel{
-		PayUserId:  input.PayUserId,
-		Amount:     BigFloat{input.Amount},
-		Source:     "Deposit",
-		IsTestNet:  input.IsTestNet,
-		UpdateType: global_const.UpdateTypeDeposit,
-		TxHash:     input.TxHash,
-		TxInfo:     txInfoJSon,
-	}
-	if createErr := tx.Create(chagneModel).Error; createErr != nil {
-		tx.Rollback()
-		return nil, createErr
-	}
 
-	if commitErr := tx.Commit().Error; commitErr != nil {
-		tx.Rollback()
-		return nil, commitErr
-	}
 	return balanceModel, nil
 }
 
@@ -255,28 +253,27 @@ func WithDrawSponsor(input *model.WithdrawSponsorRequest) (*UserSponsorBalanceDB
 	}
 	newAvailableBalance := new(big.Float).Sub(balanceModel.AvailableBalance.Float, input.Amount)
 	balanceModel.AvailableBalance = BigFloat{newAvailableBalance}
-	tx := relayDB.Begin()
-	if updateErr := tx.Model(&UserSponsorBalanceDBModel{}).
-		Where("pay_user_id = ?", balanceModel.PayUserId).
-		Where("is_test_net = ?", input.IsTestNet).Updates(balanceModel).Error; updateErr != nil {
-		tx.Rollback()
-		return nil, updateErr
-	}
-	changeModel := &UserSponsorBalanceUpdateLogDBModel{
-		PayUserId:  input.PayUserId,
-		Amount:     BigFloat{input.Amount},
-		Source:     "Withdraw",
-		IsTestNet:  input.IsTestNet,
-		UpdateType: global_const.UpdateTypeWithdraw,
-		TxHash:     input.TxHash,
-	}
-	if createErr := tx.Create(changeModel).Error; createErr != nil {
-		tx.Rollback()
-		return nil, createErr
-	}
-	if commitErr := tx.Commit().Error; commitErr != nil {
-		tx.Rollback()
-		return nil, commitErr
+	err = utils.DBTransactional(relayDB, func() error {
+		if updateErr := relayDB.Model(&UserSponsorBalanceDBModel{}).
+			Where("pay_user_id = ?", balanceModel.PayUserId).
+			Where("is_test_net = ?", input.IsTestNet).Updates(balanceModel).Error; updateErr != nil {
+			return updateErr
+		}
+		changeModel := &UserSponsorBalanceUpdateLogDBModel{
+			PayUserId:  input.PayUserId,
+			Amount:     BigFloat{input.Amount},
+			Source:     "Withdraw",
+			IsTestNet:  input.IsTestNet,
+			UpdateType: global_const.UpdateTypeWithdraw,
+			TxHash:     input.TxHash,
+		}
+		if createErr := relayDB.Create(changeModel).Error; createErr != nil {
+			return createErr
+		}
+		return nil
+	})
+	if err != nil {
+		return nil, err
 	}
 	return balanceModel, nil
 }