feat: isolate manual verification RPC usage

- add rpc node purpose support for general/manual_verify/both
- keep scan, WSS and health checks away from manual_verify nodes
- fallback manual hash verification from general RPC to manual_verify RPC
- add public cashier hash submission path and errno responses
- update tests for RPC selection, failover and manual payment flows
This commit is contained in:
line-6000
2026-05-27 19:36:56 +08:00
parent 13c81ee560
commit c69b0d6c0c
185 changed files with 2525 additions and 483 deletions
+17 -15
View File
@@ -1,13 +1,13 @@
package admin
import (
"errors"
"strconv"
"strings"
"github.com/GMWalletApp/epusdt/model/dao"
"github.com/GMWalletApp/epusdt/model/data"
"github.com/GMWalletApp/epusdt/model/mdb"
"github.com/GMWalletApp/epusdt/util/constant"
"github.com/labstack/echo/v4"
)
@@ -105,7 +105,7 @@ func (c *BaseAdminController) AdminListWallets(ctx echo.Context) error {
func (c *BaseAdminController) AdminAddWallet(ctx echo.Context) error {
req := new(AdminAddWalletRequest)
if err := ctx.Bind(req); err != nil {
return c.FailJson(ctx, err)
return c.FailJson(ctx, constant.ParamsMarshalErr)
}
if err := c.ValidateStruct(ctx, req); err != nil {
return c.FailJson(ctx, err)
@@ -140,14 +140,14 @@ func (c *BaseAdminController) AdminAddWallet(ctx echo.Context) error {
func (c *BaseAdminController) AdminGetWallet(ctx echo.Context) error {
id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
if err != nil {
return c.FailJson(ctx, err)
return c.FailJson(ctx, constant.ParamsMarshalErr)
}
wallet, err := data.GetWalletAddressById(id)
if err != nil {
return c.FailJson(ctx, err)
}
if wallet.ID == 0 {
return c.FailJson(ctx, errors.New("wallet not found"))
return c.FailJson(ctx, constant.WalletNotFoundErr)
}
counts, _ := data.CountOrdersByAddress()
return c.SucJson(ctx, WalletListItem{WalletAddress: *wallet, OrderCount: counts[wallet.Address]})
@@ -168,11 +168,11 @@ func (c *BaseAdminController) AdminGetWallet(ctx echo.Context) error {
func (c *BaseAdminController) AdminUpdateWallet(ctx echo.Context) error {
id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
if err != nil {
return c.FailJson(ctx, err)
return c.FailJson(ctx, constant.ParamsMarshalErr)
}
req := new(AdminUpdateWalletRequest)
if err := ctx.Bind(req); err != nil {
return c.FailJson(ctx, err)
return c.FailJson(ctx, constant.ParamsMarshalErr)
}
fields := map[string]interface{}{}
if req.Remark != nil {
@@ -202,11 +202,11 @@ func (c *BaseAdminController) AdminUpdateWallet(ctx echo.Context) error {
func (c *BaseAdminController) AdminChangeWalletStatus(ctx echo.Context) error {
id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
if err != nil {
return c.FailJson(ctx, err)
return c.FailJson(ctx, constant.ParamsMarshalErr)
}
req := new(AdminChangeWalletStatusRequest)
if err := ctx.Bind(req); err != nil {
return c.FailJson(ctx, err)
return c.FailJson(ctx, constant.ParamsMarshalErr)
}
if err := c.ValidateStruct(ctx, req); err != nil {
return c.FailJson(ctx, err)
@@ -230,7 +230,7 @@ func (c *BaseAdminController) AdminChangeWalletStatus(ctx echo.Context) error {
func (c *BaseAdminController) AdminDeleteWallet(ctx echo.Context) error {
id, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
if err != nil {
return c.FailJson(ctx, err)
return c.FailJson(ctx, constant.ParamsMarshalErr)
}
if err := data.DeleteWalletAddressById(id); err != nil {
return c.FailJson(ctx, err)
@@ -242,7 +242,7 @@ func (c *BaseAdminController) AdminDeleteWallet(ctx echo.Context) error {
// them all as observation wallets. Per-row failures are collected and
// returned so the UI can surface which addresses already existed.
// @Summary Batch import wallets
// @Description Import multiple wallet addresses at once. Per-row status is returned.
// @Description Import multiple wallet addresses at once. Per-row status is returned; failed rows include error_code for frontend i18n.
// @Tags Admin Wallets
// @Security AdminJWT
// @Accept json
@@ -254,21 +254,23 @@ func (c *BaseAdminController) AdminDeleteWallet(ctx echo.Context) error {
func (c *BaseAdminController) AdminBatchImportWallets(ctx echo.Context) error {
req := new(AdminBatchImportRequest)
if err := ctx.Bind(req); err != nil {
return c.FailJson(ctx, err)
return c.FailJson(ctx, constant.ParamsMarshalErr)
}
if err := c.ValidateStruct(ctx, req); err != nil {
return c.FailJson(ctx, err)
}
type result struct {
Address string `json:"address"`
OK bool `json:"ok"`
Error string `json:"error,omitempty"`
Address string `json:"address"`
OK bool `json:"ok"`
ErrorCode int `json:"error_code,omitempty"`
Error string `json:"error,omitempty"`
}
out := make([]result, 0, len(req.Addresses))
for _, addr := range req.Addresses {
row, err := data.AddWalletAddressWithNetwork(req.Network, addr)
if err != nil {
out = append(out, result{Address: addr, OK: false, Error: err.Error()})
code, msg := constant.ResolveErrno(err)
out = append(out, result{Address: addr, OK: false, ErrorCode: code, Error: msg})
continue
}
_ = dao.Mdb.Model(&mdb.WalletAddress{}).Where("id = ?", row.ID).