包含 webapp(Next.js 用户端)、webapp-back(Go 后端)、 antdesign(管理后台)、landingpage(营销落地页)、 数据库 SQL 和配置文件。
122 lines
3.6 KiB
Go
122 lines
3.6 KiB
Go
package admin
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
appcfg "github.com/gothinkster/golang-gin-realworld-example-app/config"
|
|
"github.com/gothinkster/golang-gin-realworld-example-app/common"
|
|
"github.com/gothinkster/golang-gin-realworld-example-app/lending"
|
|
"github.com/gothinkster/golang-gin-realworld-example-app/models"
|
|
)
|
|
|
|
// ── Collateral Buyer Bot ───────────────────────────────────────────────────
|
|
|
|
func GetBuyerBotStatus(c *gin.Context) {
|
|
OK(c, lending.GetBuyerBotStatus())
|
|
}
|
|
|
|
func StartBuyerBot(c *gin.Context) {
|
|
cfg := appcfg.AppConfig
|
|
if cfg == nil {
|
|
Fail(c, http.StatusInternalServerError, "Configuration not loaded")
|
|
return
|
|
}
|
|
if cfg.CollateralBuyerPrivateKey == "" {
|
|
Fail(c, http.StatusBadRequest, "COLLATERAL_BUYER_PRIVATE_KEY not configured on server")
|
|
return
|
|
}
|
|
lending.StartCollateralBuyerBot(cfg)
|
|
OK(c, gin.H{"message": "Collateral buyer bot start signal sent"})
|
|
}
|
|
|
|
func StopBuyerBot(c *gin.Context) {
|
|
lending.StopCollateralBuyerBot()
|
|
OK(c, gin.H{"message": "Collateral buyer bot stop signal sent"})
|
|
}
|
|
|
|
func ListBuyRecords(c *gin.Context) {
|
|
db := common.GetDB()
|
|
p := ParsePagination(c)
|
|
|
|
query := db.Model(&models.CollateralBuyRecord{})
|
|
if v := c.Query("chain_id"); v != "" {
|
|
if id, err := strconv.Atoi(v); err == nil {
|
|
query = query.Where("chain_id = ?", id)
|
|
}
|
|
}
|
|
if v := c.Query("status"); v != "" {
|
|
query = query.Where("status = ?", v)
|
|
}
|
|
if v := c.Query("asset_addr"); v != "" {
|
|
query = query.Where("asset_addr = ?", v)
|
|
}
|
|
|
|
var total int64
|
|
query.Count(&total)
|
|
|
|
var records []models.CollateralBuyRecord
|
|
if err := query.Order("created_at DESC").Offset(p.Offset()).Limit(p.PageSize).Find(&records).Error; err != nil {
|
|
Fail(c, http.StatusInternalServerError, "Failed to fetch buy records")
|
|
return
|
|
}
|
|
OKList(c, records, total)
|
|
}
|
|
|
|
// GetLiquidationStatus returns the current liquidation bot status
|
|
func GetLiquidationStatus(c *gin.Context) {
|
|
status := lending.GetBotStatus()
|
|
OK(c, status)
|
|
}
|
|
|
|
// StartLiquidationBot starts the liquidation bot
|
|
func StartLiquidationBot(c *gin.Context) {
|
|
cfg := appcfg.AppConfig
|
|
if cfg == nil {
|
|
Fail(c, http.StatusInternalServerError, "Configuration not loaded")
|
|
return
|
|
}
|
|
if cfg.LiquidatorPrivateKey == "" {
|
|
Fail(c, http.StatusBadRequest, "LIQUIDATOR_PRIVATE_KEY not configured on server")
|
|
return
|
|
}
|
|
lending.StartLiquidationBot(cfg)
|
|
OK(c, gin.H{"message": "Liquidation bot start signal sent"})
|
|
}
|
|
|
|
// StopLiquidationBot stops the liquidation bot
|
|
func StopLiquidationBot(c *gin.Context) {
|
|
lending.StopLiquidationBot()
|
|
OK(c, gin.H{"message": "Liquidation bot stop signal sent"})
|
|
}
|
|
|
|
// ListLiquidationRecords returns paginated liquidation history
|
|
func ListLiquidationRecords(c *gin.Context) {
|
|
db := common.GetDB()
|
|
p := ParsePagination(c)
|
|
|
|
query := db.Model(&models.LiquidationRecord{})
|
|
if v := c.Query("chain_id"); v != "" {
|
|
if id, err := strconv.Atoi(v); err == nil {
|
|
query = query.Where("chain_id = ?", id)
|
|
}
|
|
}
|
|
if v := c.Query("status"); v != "" {
|
|
query = query.Where("status = ?", v)
|
|
}
|
|
if v := c.Query("liquidator_addr"); v != "" {
|
|
query = query.Where("liquidator_addr = ?", v)
|
|
}
|
|
|
|
var total int64
|
|
query.Count(&total)
|
|
|
|
var records []models.LiquidationRecord
|
|
if err := query.Order("created_at DESC").Offset(p.Offset()).Limit(p.PageSize).Find(&records).Error; err != nil {
|
|
Fail(c, http.StatusInternalServerError, "Failed to fetch liquidation records")
|
|
return
|
|
}
|
|
OKList(c, records, total)
|
|
}
|