1
This commit is contained in:
		
							
								
								
									
										194
									
								
								app/admin/apis/wm_network.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								app/admin/apis/wm_network.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,194 @@ | ||||
| package apis | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/api" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" | ||||
| 	_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" | ||||
|  | ||||
| 	"go-admin/app/admin/models" | ||||
| 	"go-admin/app/admin/service" | ||||
| 	"go-admin/app/admin/service/dto" | ||||
| 	"go-admin/common/actions" | ||||
| ) | ||||
|  | ||||
| type WmNetwork struct { | ||||
| 	api.Api | ||||
| } | ||||
|  | ||||
| // GetPage 获取网络配置列表 | ||||
| // @Summary 获取网络配置列表 | ||||
| // @Description 获取网络配置列表 | ||||
| // @Tags 网络配置 | ||||
| // @Param networkName query string false "网络名称" | ||||
| // @Param code query string false "网络代码" | ||||
| // @Param receiveAddress query string false "接收钱包地址" | ||||
| // @Param pageSize query int false "页条数" | ||||
| // @Param pageIndex query int false "页码" | ||||
| // @Success 200 {object} response.Response{data=response.Page{list=[]models.WmNetwork}} "{"code": 200, "data": [...]}" | ||||
| // @Router /api/v1/wm-network [get] | ||||
| // @Security Bearer | ||||
| func (e WmNetwork) GetPage(c *gin.Context) { | ||||
| 	req := dto.WmNetworkGetPageReq{} | ||||
| 	s := service.WmNetwork{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
| 	list := make([]models.WmNetwork, 0) | ||||
| 	var count int64 | ||||
|  | ||||
| 	err = s.GetPage(&req, p, &list, &count) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("获取网络配置失败,\r\n失败信息 %s", err.Error())) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") | ||||
| } | ||||
|  | ||||
| // Get 获取网络配置 | ||||
| // @Summary 获取网络配置 | ||||
| // @Description 获取网络配置 | ||||
| // @Tags 网络配置 | ||||
| // @Param id path int false "id" | ||||
| // @Success 200 {object} response.Response{data=models.WmNetwork} "{"code": 200, "data": [...]}" | ||||
| // @Router /api/v1/wm-network/{id} [get] | ||||
| // @Security Bearer | ||||
| func (e WmNetwork) Get(c *gin.Context) { | ||||
| 	req := dto.WmNetworkGetReq{} | ||||
| 	s := service.WmNetwork{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	var object models.WmNetwork | ||||
|  | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
| 	err = s.Get(&req, p, &object) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("获取网络配置失败,\r\n失败信息 %s", err.Error())) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	e.OK(object, "查询成功") | ||||
| } | ||||
|  | ||||
| // Insert 创建网络配置 | ||||
| // @Summary 创建网络配置 | ||||
| // @Description 创建网络配置 | ||||
| // @Tags 网络配置 | ||||
| // @Accept application/json | ||||
| // @Product application/json | ||||
| // @Param data body dto.WmNetworkInsertReq true "data" | ||||
| // @Success 200 {object} response.Response	"{"code": 200, "message": "添加成功"}" | ||||
| // @Router /api/v1/wm-network [post] | ||||
| // @Security Bearer | ||||
| // func (e WmNetwork) Insert(c *gin.Context) { | ||||
| //     req := dto.WmNetworkInsertReq{} | ||||
| //     s := service.WmNetwork{} | ||||
| //     err := e.MakeContext(c). | ||||
| //         MakeOrm(). | ||||
| //         Bind(&req). | ||||
| //         MakeService(&s.Service). | ||||
| //         Errors | ||||
| //     if err != nil { | ||||
| //         e.Logger.Error(err) | ||||
| //         e.Error(500, err, err.Error()) | ||||
| //         return | ||||
| //     } | ||||
| // 	// 设置创建人 | ||||
| // 	req.SetCreateBy(user.GetUserId(c)) | ||||
|  | ||||
| // 	err = s.Insert(&req) | ||||
| // 	if err != nil { | ||||
| // 		e.Error(500, err, fmt.Sprintf("创建网络配置失败,\r\n失败信息 %s", err.Error())) | ||||
| //         return | ||||
| // 	} | ||||
|  | ||||
| // 	e.OK(req.GetId(), "创建成功") | ||||
| // } | ||||
|  | ||||
| // Update 修改网络配置 | ||||
| // @Summary 修改网络配置 | ||||
| // @Description 修改网络配置 | ||||
| // @Tags 网络配置 | ||||
| // @Accept application/json | ||||
| // @Product application/json | ||||
| // @Param id path int true "id" | ||||
| // @Param data body dto.WmNetworkUpdateReq true "body" | ||||
| // @Success 200 {object} response.Response	"{"code": 200, "message": "修改成功"}" | ||||
| // @Router /api/v1/wm-network/{id} [put] | ||||
| // @Security Bearer | ||||
| func (e WmNetwork) Update(c *gin.Context) { | ||||
| 	req := dto.WmNetworkUpdateReq{} | ||||
| 	s := service.WmNetwork{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	req.SetUpdateBy(user.GetUserId(c)) | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
|  | ||||
| 	err = s.Update(&req, p) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("修改网络配置失败,\r\n失败信息 %s", err.Error())) | ||||
| 		return | ||||
| 	} | ||||
| 	e.OK(req.GetId(), "修改成功") | ||||
| } | ||||
|  | ||||
| // Delete 删除网络配置 | ||||
| // @Summary 删除网络配置 | ||||
| // @Description 删除网络配置 | ||||
| // @Tags 网络配置 | ||||
| // @Param data body dto.WmNetworkDeleteReq true "body" | ||||
| // @Success 200 {object} response.Response	"{"code": 200, "message": "删除成功"}" | ||||
| // @Router /api/v1/wm-network [delete] | ||||
| // @Security Bearer | ||||
| // func (e WmNetwork) Delete(c *gin.Context) { | ||||
| //     s := service.WmNetwork{} | ||||
| //     req := dto.WmNetworkDeleteReq{} | ||||
| //     err := e.MakeContext(c). | ||||
| //         MakeOrm(). | ||||
| //         Bind(&req). | ||||
| //         MakeService(&s.Service). | ||||
| //         Errors | ||||
| //     if err != nil { | ||||
| //         e.Logger.Error(err) | ||||
| //         e.Error(500, err, err.Error()) | ||||
| //         return | ||||
| //     } | ||||
|  | ||||
| // 	// req.SetUpdateBy(user.GetUserId(c)) | ||||
| // 	p := actions.GetPermissionFromContext(c) | ||||
|  | ||||
| // 	err = s.Remove(&req, p) | ||||
| // 	if err != nil { | ||||
| // 		e.Error(500, err, fmt.Sprintf("删除网络配置失败,\r\n失败信息 %s", err.Error())) | ||||
| //         return | ||||
| // 	} | ||||
| // 	e.OK( req.GetId(), "删除成功") | ||||
| // } | ||||
							
								
								
									
										205
									
								
								app/admin/apis/wm_token.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								app/admin/apis/wm_token.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,205 @@ | ||||
| package apis | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/api" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" | ||||
| 	_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" | ||||
|  | ||||
| 	"go-admin/app/admin/models" | ||||
| 	"go-admin/app/admin/service" | ||||
| 	"go-admin/app/admin/service/dto" | ||||
| 	"go-admin/common/actions" | ||||
| ) | ||||
|  | ||||
| type WmToken struct { | ||||
| 	api.Api | ||||
| } | ||||
|  | ||||
| // GetPage 获取代币配置列表 | ||||
| // @Summary 获取代币配置列表 | ||||
| // @Description 获取代币配置列表 | ||||
| // @Tags 代币配置 | ||||
| // @Param networkId query string false "网络id" | ||||
| // @Param tokenName query string false "代币名称" | ||||
| // @Param pageSize query int false "页条数" | ||||
| // @Param pageIndex query int false "页码" | ||||
| // @Success 200 {object} response.Response{data=response.Page{list=[]models.WmToken}} "{"code": 200, "data": [...]}" | ||||
| // @Router /api/v1/wm-token [get] | ||||
| // @Security Bearer | ||||
| func (e WmToken) GetPage(c *gin.Context) { | ||||
| 	req := dto.WmTokenGetPageReq{} | ||||
| 	s := service.WmToken{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
| 	list := make([]models.WmToken, 0) | ||||
| 	var count int64 | ||||
|  | ||||
| 	err = s.GetPage(&req, p, &list, &count) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("获取代币配置失败,\r\n失败信息 %s", err.Error())) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") | ||||
| } | ||||
|  | ||||
| // Get 获取代币配置 | ||||
| // @Summary 获取代币配置 | ||||
| // @Description 获取代币配置 | ||||
| // @Tags 代币配置 | ||||
| // @Param id path int false "id" | ||||
| // @Success 200 {object} response.Response{data=models.WmToken} "{"code": 200, "data": [...]}" | ||||
| // @Router /api/v1/wm-token/{id} [get] | ||||
| // @Security Bearer | ||||
| func (e WmToken) Get(c *gin.Context) { | ||||
| 	req := dto.WmTokenGetReq{} | ||||
| 	s := service.WmToken{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	var object models.WmToken | ||||
|  | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
| 	err = s.Get(&req, p, &object) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("获取代币配置失败,\r\n失败信息 %s", err.Error())) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	e.OK(object, "查询成功") | ||||
| } | ||||
|  | ||||
| // Insert 创建代币配置 | ||||
| // @Summary 创建代币配置 | ||||
| // @Description 创建代币配置 | ||||
| // @Tags 代币配置 | ||||
| // @Accept application/json | ||||
| // @Product application/json | ||||
| // @Param data body dto.WmTokenInsertReq true "data" | ||||
| // @Success 200 {object} response.Response	"{"code": 200, "message": "添加成功"}" | ||||
| // @Router /api/v1/wm-token [post] | ||||
| // @Security Bearer | ||||
| func (e WmToken) Insert(c *gin.Context) { | ||||
| 	req := dto.WmTokenInsertReq{} | ||||
| 	s := service.WmToken{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if err := req.Valid(); err != nil { | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// 设置创建人 | ||||
| 	req.SetCreateBy(user.GetUserId(c)) | ||||
|  | ||||
| 	err = s.Insert(&req) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("创建代币配置失败,\r\n失败信息 %s", err.Error())) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	e.OK(req.GetId(), "创建成功") | ||||
| } | ||||
|  | ||||
| // Update 修改代币配置 | ||||
| // @Summary 修改代币配置 | ||||
| // @Description 修改代币配置 | ||||
| // @Tags 代币配置 | ||||
| // @Accept application/json | ||||
| // @Product application/json | ||||
| // @Param id path int true "id" | ||||
| // @Param data body dto.WmTokenUpdateReq true "body" | ||||
| // @Success 200 {object} response.Response	"{"code": 200, "message": "修改成功"}" | ||||
| // @Router /api/v1/wm-token/{id} [put] | ||||
| // @Security Bearer | ||||
| func (e WmToken) Update(c *gin.Context) { | ||||
| 	req := dto.WmTokenUpdateReq{} | ||||
| 	s := service.WmToken{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if err := req.Valid(); err != nil { | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	req.SetUpdateBy(user.GetUserId(c)) | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
|  | ||||
| 	err = s.Update(&req, p) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("修改代币配置失败,\r\n失败信息 %s", err.Error())) | ||||
| 		return | ||||
| 	} | ||||
| 	e.OK(req.GetId(), "修改成功") | ||||
| } | ||||
|  | ||||
| // Delete 删除代币配置 | ||||
| // @Summary 删除代币配置 | ||||
| // @Description 删除代币配置 | ||||
| // @Tags 代币配置 | ||||
| // @Param data body dto.WmTokenDeleteReq true "body" | ||||
| // @Success 200 {object} response.Response	"{"code": 200, "message": "删除成功"}" | ||||
| // @Router /api/v1/wm-token [delete] | ||||
| // @Security Bearer | ||||
| func (e WmToken) Delete(c *gin.Context) { | ||||
| 	s := service.WmToken{} | ||||
| 	req := dto.WmTokenDeleteReq{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// req.SetUpdateBy(user.GetUserId(c)) | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
|  | ||||
| 	err = s.Remove(&req, p) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("删除代币配置失败,\r\n失败信息 %s", err.Error())) | ||||
| 		return | ||||
| 	} | ||||
| 	e.OK(req.GetId(), "删除成功") | ||||
| } | ||||
| @ -1,9 +1,10 @@ | ||||
| package apis | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"github.com/gin-gonic/gin/binding" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/api" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" | ||||
| 	_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" | ||||
| @ -30,18 +31,18 @@ type WmTransfer struct { | ||||
| // @Router /api/v1/wm-transfer [get] | ||||
| // @Security Bearer | ||||
| func (e WmTransfer) GetPage(c *gin.Context) { | ||||
|     req := dto.WmTransferGetPageReq{} | ||||
|     s := service.WmTransfer{} | ||||
|     err := e.MakeContext(c). | ||||
|         MakeOrm(). | ||||
|         Bind(&req). | ||||
|         MakeService(&s.Service). | ||||
|         Errors | ||||
|    	if err != nil { | ||||
|    		e.Logger.Error(err) | ||||
|    		e.Error(500, err, err.Error()) | ||||
|    		return | ||||
|    	} | ||||
| 	req := dto.WmTransferGetPageReq{} | ||||
| 	s := service.WmTransfer{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req, binding.Form). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
| 	list := make([]models.WmTransfer, 0) | ||||
| @ -50,7 +51,7 @@ func (e WmTransfer) GetPage(c *gin.Context) { | ||||
| 	err = s.GetPage(&req, p, &list, &count) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("获取批量转账任务失败,\r\n失败信息 %s", err.Error())) | ||||
|         return | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") | ||||
| @ -67,7 +68,7 @@ func (e WmTransfer) GetPage(c *gin.Context) { | ||||
| func (e WmTransfer) Get(c *gin.Context) { | ||||
| 	req := dto.WmTransferGetReq{} | ||||
| 	s := service.WmTransfer{} | ||||
|     err := e.MakeContext(c). | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| @ -83,10 +84,10 @@ func (e WmTransfer) Get(c *gin.Context) { | ||||
| 	err = s.Get(&req, p, &object) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("获取批量转账任务失败,\r\n失败信息 %s", err.Error())) | ||||
|         return | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	e.OK( object, "查询成功") | ||||
| 	e.OK(object, "查询成功") | ||||
| } | ||||
|  | ||||
| // Insert 创建批量转账任务 | ||||
| @ -100,65 +101,36 @@ func (e WmTransfer) Get(c *gin.Context) { | ||||
| // @Router /api/v1/wm-transfer [post] | ||||
| // @Security Bearer | ||||
| func (e WmTransfer) Insert(c *gin.Context) { | ||||
|     req := dto.WmTransferInsertReq{} | ||||
|     s := service.WmTransfer{} | ||||
|     err := e.MakeContext(c). | ||||
|         MakeOrm(). | ||||
|         Bind(&req). | ||||
|         MakeService(&s.Service). | ||||
|         Errors | ||||
|     if err != nil { | ||||
|         e.Logger.Error(err) | ||||
|         e.Error(500, err, err.Error()) | ||||
|         return | ||||
|     } | ||||
| 	req := dto.WmTransferInsertReq{} | ||||
| 	s := service.WmTransfer{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if err := req.Valid(); err != nil { | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// 设置创建人 | ||||
| 	req.SetCreateBy(user.GetUserId(c)) | ||||
|  | ||||
| 	err = s.Insert(&req) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("创建批量转账任务失败,\r\n失败信息 %s", err.Error())) | ||||
|         return | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	e.OK(req.GetId(), "创建成功") | ||||
| } | ||||
|  | ||||
| // Update 修改批量转账任务 | ||||
| // @Summary 修改批量转账任务 | ||||
| // @Description 修改批量转账任务 | ||||
| // @Tags 批量转账任务 | ||||
| // @Accept application/json | ||||
| // @Product application/json | ||||
| // @Param id path int true "id" | ||||
| // @Param data body dto.WmTransferUpdateReq true "body" | ||||
| // @Success 200 {object} response.Response	"{"code": 200, "message": "修改成功"}" | ||||
| // @Router /api/v1/wm-transfer/{id} [put] | ||||
| // @Security Bearer | ||||
| func (e WmTransfer) Update(c *gin.Context) { | ||||
|     req := dto.WmTransferUpdateReq{} | ||||
|     s := service.WmTransfer{} | ||||
|     err := e.MakeContext(c). | ||||
|         MakeOrm(). | ||||
|         Bind(&req). | ||||
|         MakeService(&s.Service). | ||||
|         Errors | ||||
|     if err != nil { | ||||
|         e.Logger.Error(err) | ||||
|         e.Error(500, err, err.Error()) | ||||
|         return | ||||
|     } | ||||
| 	req.SetUpdateBy(user.GetUserId(c)) | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
|  | ||||
| 	err = s.Update(&req, p) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("修改批量转账任务失败,\r\n失败信息 %s", err.Error())) | ||||
|         return | ||||
| 	} | ||||
| 	e.OK( req.GetId(), "修改成功") | ||||
| } | ||||
|  | ||||
| // Delete 删除批量转账任务 | ||||
| // @Summary 删除批量转账任务 | ||||
| // @Description 删除批量转账任务 | ||||
| @ -168,18 +140,18 @@ func (e WmTransfer) Update(c *gin.Context) { | ||||
| // @Router /api/v1/wm-transfer [delete] | ||||
| // @Security Bearer | ||||
| func (e WmTransfer) Delete(c *gin.Context) { | ||||
|     s := service.WmTransfer{} | ||||
|     req := dto.WmTransferDeleteReq{} | ||||
|     err := e.MakeContext(c). | ||||
|         MakeOrm(). | ||||
|         Bind(&req). | ||||
|         MakeService(&s.Service). | ||||
|         Errors | ||||
|     if err != nil { | ||||
|         e.Logger.Error(err) | ||||
|         e.Error(500, err, err.Error()) | ||||
|         return | ||||
|     } | ||||
| 	s := service.WmTransfer{} | ||||
| 	req := dto.WmTransferDeleteReq{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// req.SetUpdateBy(user.GetUserId(c)) | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
| @ -187,7 +159,28 @@ func (e WmTransfer) Delete(c *gin.Context) { | ||||
| 	err = s.Remove(&req, p) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("删除批量转账任务失败,\r\n失败信息 %s", err.Error())) | ||||
|         return | ||||
| 		return | ||||
| 	} | ||||
| 	e.OK( req.GetId(), "删除成功") | ||||
| 	e.OK(req.GetId(), "删除成功") | ||||
| } | ||||
|  | ||||
| // 清理数据 | ||||
| func (e WmTransfer) ClearAll(c *gin.Context) { | ||||
| 	s := service.WmTransfer{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	err = s.ClearAll() | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("清理数据失败,\r\n失败信息 %s", err.Error())) | ||||
| 		return | ||||
| 	} | ||||
| 	e.OK(nil, "清理数据成功") | ||||
| } | ||||
|  | ||||
| @ -1,9 +1,10 @@ | ||||
| package apis | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"github.com/gin-gonic/gin/binding" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/api" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" | ||||
| 	_ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" | ||||
| @ -28,18 +29,18 @@ type WmTransferItem struct { | ||||
| // @Router /api/v1/wm-transfer-item [get] | ||||
| // @Security Bearer | ||||
| func (e WmTransferItem) GetPage(c *gin.Context) { | ||||
|     req := dto.WmTransferItemGetPageReq{} | ||||
|     s := service.WmTransferItem{} | ||||
|     err := e.MakeContext(c). | ||||
|         MakeOrm(). | ||||
|         Bind(&req). | ||||
|         MakeService(&s.Service). | ||||
|         Errors | ||||
|    	if err != nil { | ||||
|    		e.Logger.Error(err) | ||||
|    		e.Error(500, err, err.Error()) | ||||
|    		return | ||||
|    	} | ||||
| 	req := dto.WmTransferItemGetPageReq{} | ||||
| 	s := service.WmTransferItem{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
| 	list := make([]models.WmTransferItem, 0) | ||||
| @ -48,12 +49,59 @@ func (e WmTransferItem) GetPage(c *gin.Context) { | ||||
| 	err = s.GetPage(&req, p, &list, &count) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("获取批量转账明细失败,\r\n失败信息 %s", err.Error())) | ||||
|         return | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") | ||||
| } | ||||
|  | ||||
| // 导出excel | ||||
| func (e WmTransferItem) Export(c *gin.Context) { | ||||
| 	s := service.WmTransferItem{} | ||||
| 	req := dto.WmTransferItemExportReq{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req, binding.Form, binding.Query). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
|  | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
| 	err = s.ExportExcel(&req, p, c) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("导出excel失败,\r\n失败信息 %s", err.Error())) | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // ExportAutoLog 导出自动转账日志 | ||||
| func (e WmTransferItem) ExportAutoLog(c *gin.Context) { | ||||
| 	s := service.WmTransferItem{} | ||||
| 	req := dto.WmTransferItemAutoLogPageReq{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req, binding.Form, binding.Query). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
|  | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	err = s.ExportAutoLog(&req, c) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("导出自动转账日志失败,\r\n失败信息 %s", err.Error())) | ||||
| 		return | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Get 获取批量转账明细 | ||||
| // @Summary 获取批量转账明细 | ||||
| // @Description 获取批量转账明细 | ||||
| @ -65,7 +113,7 @@ func (e WmTransferItem) GetPage(c *gin.Context) { | ||||
| func (e WmTransferItem) Get(c *gin.Context) { | ||||
| 	req := dto.WmTransferItemGetReq{} | ||||
| 	s := service.WmTransferItem{} | ||||
|     err := e.MakeContext(c). | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| @ -81,10 +129,10 @@ func (e WmTransferItem) Get(c *gin.Context) { | ||||
| 	err = s.Get(&req, p, &object) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("获取批量转账明细失败,\r\n失败信息 %s", err.Error())) | ||||
|         return | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	e.OK( object, "查询成功") | ||||
| 	e.OK(object, "查询成功") | ||||
| } | ||||
|  | ||||
| // Insert 创建批量转账明细 | ||||
| @ -98,25 +146,25 @@ func (e WmTransferItem) Get(c *gin.Context) { | ||||
| // @Router /api/v1/wm-transfer-item [post] | ||||
| // @Security Bearer | ||||
| func (e WmTransferItem) Insert(c *gin.Context) { | ||||
|     req := dto.WmTransferItemInsertReq{} | ||||
|     s := service.WmTransferItem{} | ||||
|     err := e.MakeContext(c). | ||||
|         MakeOrm(). | ||||
|         Bind(&req). | ||||
|         MakeService(&s.Service). | ||||
|         Errors | ||||
|     if err != nil { | ||||
|         e.Logger.Error(err) | ||||
|         e.Error(500, err, err.Error()) | ||||
|         return | ||||
|     } | ||||
| 	req := dto.WmTransferItemInsertReq{} | ||||
| 	s := service.WmTransferItem{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	// 设置创建人 | ||||
| 	req.SetCreateBy(user.GetUserId(c)) | ||||
|  | ||||
| 	err = s.Insert(&req) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("创建批量转账明细失败,\r\n失败信息 %s", err.Error())) | ||||
|         return | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	e.OK(req.GetId(), "创建成功") | ||||
| @ -134,27 +182,27 @@ func (e WmTransferItem) Insert(c *gin.Context) { | ||||
| // @Router /api/v1/wm-transfer-item/{id} [put] | ||||
| // @Security Bearer | ||||
| func (e WmTransferItem) Update(c *gin.Context) { | ||||
|     req := dto.WmTransferItemUpdateReq{} | ||||
|     s := service.WmTransferItem{} | ||||
|     err := e.MakeContext(c). | ||||
|         MakeOrm(). | ||||
|         Bind(&req). | ||||
|         MakeService(&s.Service). | ||||
|         Errors | ||||
|     if err != nil { | ||||
|         e.Logger.Error(err) | ||||
|         e.Error(500, err, err.Error()) | ||||
|         return | ||||
|     } | ||||
| 	req := dto.WmTransferItemUpdateReq{} | ||||
| 	s := service.WmTransferItem{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	req.SetUpdateBy(user.GetUserId(c)) | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
|  | ||||
| 	err = s.Update(&req, p) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("修改批量转账明细失败,\r\n失败信息 %s", err.Error())) | ||||
|         return | ||||
| 		return | ||||
| 	} | ||||
| 	e.OK( req.GetId(), "修改成功") | ||||
| 	e.OK(req.GetId(), "修改成功") | ||||
| } | ||||
|  | ||||
| // Delete 删除批量转账明细 | ||||
| @ -166,18 +214,18 @@ func (e WmTransferItem) Update(c *gin.Context) { | ||||
| // @Router /api/v1/wm-transfer-item [delete] | ||||
| // @Security Bearer | ||||
| func (e WmTransferItem) Delete(c *gin.Context) { | ||||
|     s := service.WmTransferItem{} | ||||
|     req := dto.WmTransferItemDeleteReq{} | ||||
|     err := e.MakeContext(c). | ||||
|         MakeOrm(). | ||||
|         Bind(&req). | ||||
|         MakeService(&s.Service). | ||||
|         Errors | ||||
|     if err != nil { | ||||
|         e.Logger.Error(err) | ||||
|         e.Error(500, err, err.Error()) | ||||
|         return | ||||
|     } | ||||
| 	s := service.WmTransferItem{} | ||||
| 	req := dto.WmTransferItemDeleteReq{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	// req.SetUpdateBy(user.GetUserId(c)) | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
| @ -185,7 +233,32 @@ func (e WmTransferItem) Delete(c *gin.Context) { | ||||
| 	err = s.Remove(&req, p) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("删除批量转账明细失败,\r\n失败信息 %s", err.Error())) | ||||
|         return | ||||
| 		return | ||||
| 	} | ||||
| 	e.OK( req.GetId(), "删除成功") | ||||
| 	e.OK(req.GetId(), "删除成功") | ||||
| } | ||||
|  | ||||
| // GetAutoTransferLogPage 获取自动转账日志列表 | ||||
| func (e WmTransferItem) GetAutoTransferLogPage(c *gin.Context) { | ||||
| 	req := dto.WmTransferItemAutoLogPageReq{} | ||||
| 	s := service.WmTransferItem{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		Bind(&req, binding.Form, binding.Query). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
| 	list := make([]dto.WmTransferItemResp, 0) | ||||
| 	var count int64 | ||||
| 	err = s.GetAutoTransferLogPage(&req, p, &list, &count) | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("获取自动转账日志失败,\r\n失败信息 %s", err.Error())) | ||||
| 		return | ||||
| 	} | ||||
| 	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") | ||||
| } | ||||
|  | ||||
| @ -152,3 +152,25 @@ func (e WmWalletInfo) Delete(c *gin.Context) { | ||||
| 	} | ||||
| 	e.OK(req.GetId(), "删除成功") | ||||
| } | ||||
|  | ||||
| // ClearAll 清空所有钱包信息 | ||||
| func (e WmWalletInfo) ClearAll(c *gin.Context) { | ||||
| 	s := service.WmWalletInfo{} | ||||
| 	err := e.MakeContext(c). | ||||
| 		MakeOrm(). | ||||
| 		MakeService(&s.Service). | ||||
| 		Errors | ||||
| 	if err != nil { | ||||
| 		e.Logger.Error(err) | ||||
| 		e.Error(500, err, err.Error()) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	err = s.ClearAll() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		e.Error(500, err, fmt.Sprintf("清空所有钱包信息失败,\r\n失败信息 %s", err.Error())) | ||||
| 		return | ||||
| 	} | ||||
| 	e.OK(nil, "清空成功") | ||||
| } | ||||
|  | ||||
							
								
								
									
										28
									
								
								app/admin/models/wm_network.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/admin/models/wm_network.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| package models | ||||
|  | ||||
| import ( | ||||
| 	"go-admin/common/models" | ||||
| ) | ||||
|  | ||||
| type WmNetwork struct { | ||||
| 	models.Model | ||||
|  | ||||
| 	NetworkName    string `json:"networkName" gorm:"type:varchar(20);comment:网络名称"` | ||||
| 	Code           string `json:"code" gorm:"type:varchar(50);comment:网络代码"` | ||||
| 	ReceiveAddress string `json:"receiveAddress" gorm:"type:varchar(255);comment:接收钱包地址"` | ||||
| 	models.ModelTime | ||||
| 	models.ControlBy | ||||
| } | ||||
|  | ||||
| func (WmNetwork) TableName() string { | ||||
| 	return "wm_network" | ||||
| } | ||||
|  | ||||
| func (e *WmNetwork) Generate() models.ActiveRecord { | ||||
| 	o := *e | ||||
| 	return &o | ||||
| } | ||||
|  | ||||
| func (e *WmNetwork) GetId() interface{} { | ||||
| 	return e.Id | ||||
| } | ||||
							
								
								
									
										36
									
								
								app/admin/models/wm_token.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/admin/models/wm_token.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| package models | ||||
|  | ||||
| import ( | ||||
| 	"go-admin/common/models" | ||||
|  | ||||
| 	"github.com/shopspring/decimal" | ||||
| ) | ||||
|  | ||||
| type WmToken struct { | ||||
| 	models.Model | ||||
|  | ||||
| 	NetworkId     int             `json:"networkId" gorm:"type:bigint;comment:网络id"` | ||||
| 	NetworkCode   string          `json:"code" gorm:"-"` | ||||
| 	TokenName     string          `json:"tokenName" gorm:"type:varchar(20);comment:代币名称"` | ||||
| 	TokenAddress  string          `json:"tokenAddress" gorm:"type:varchar(50);comment:代币地址"` | ||||
| 	Decimals      int             `json:"decimals" gorm:"type:int;comment:代币精度"` | ||||
| 	IsAuto        int             `json:"isAuto" gorm:"type:tinyint;comment:开启自动转账 1-开启 2-关闭"` | ||||
| 	TriggerAmount decimal.Decimal `json:"triggerAmount" gorm:"type:decimal(18,8);comment:触发数量"` | ||||
| 	TransType     int             `json:"transType" gorm:"type:tinyint;comment:转账类型 1-百分比 2-实际金额"` | ||||
| 	TransValue    decimal.Decimal `json:"transValue" gorm:"type:decimal(18,8);comment:转账值"` | ||||
| 	models.ModelTime | ||||
| 	models.ControlBy | ||||
| } | ||||
|  | ||||
| func (WmToken) TableName() string { | ||||
| 	return "wm_token" | ||||
| } | ||||
|  | ||||
| func (e *WmToken) Generate() models.ActiveRecord { | ||||
| 	o := *e | ||||
| 	return &o | ||||
| } | ||||
|  | ||||
| func (e *WmToken) GetId() interface{} { | ||||
| 	return e.Id | ||||
| } | ||||
| @ -1,24 +1,28 @@ | ||||
| package models | ||||
|  | ||||
| import ( | ||||
|  | ||||
| 	"go-admin/common/models" | ||||
|  | ||||
| ) | ||||
|  | ||||
| type WmTransfer struct { | ||||
|     models.Model | ||||
| 	models.Model | ||||
|  | ||||
|     Type int64 `json:"type" gorm:"type:tinyint;comment:类型 0-百分比 1-实际金额"`  | ||||
|     TransferType int64 `json:"transferType" gorm:"type:tinyint;comment:转账类型 0-批量转出 1-批量汇总"`  | ||||
|     Status int64 `json:"status" gorm:"type:tinyint;comment:状态"`  | ||||
|     Remark string `json:"remark" gorm:"type:varchar(255);comment:备注信息"`  | ||||
|     models.ModelTime | ||||
|     models.ControlBy | ||||
| 	NetworkId    int    `json:"networkId" gorm:"type:int;comment:网络id"` | ||||
| 	TokenAddress string `json:"tokenAddress" gorm:"type:varchar(255);comment:代币地址"` | ||||
| 	Type         int    `json:"type" gorm:"type:tinyint;comment:类型 0-百分比 1-实际金额"` | ||||
| 	TransferType int    `json:"transferType" gorm:"type:tinyint;comment:转账类型 0-批量转出 1-批量汇总"` | ||||
| 	Status       int    `json:"status" gorm:"type:tinyint;comment:状态"` | ||||
| 	Remark       string `json:"remark" gorm:"type:varchar(255);comment:备注信息"` | ||||
| 	Total        int    `json:"total" gorm:"-"` | ||||
| 	Sucess       int    `json:"sucess" gorm:"-"` | ||||
| 	Fail         int    `json:"fail" gorm:"-"` | ||||
| 	Pending      int    `json:"pending" gorm:"-"` | ||||
| 	models.ModelTime | ||||
| 	models.ControlBy | ||||
| } | ||||
|  | ||||
| func (WmTransfer) TableName() string { | ||||
|     return "wm_transfer" | ||||
| 	return "wm_transfer" | ||||
| } | ||||
|  | ||||
| func (e *WmTransfer) Generate() models.ActiveRecord { | ||||
|  | ||||
| @ -1,27 +1,34 @@ | ||||
| package models | ||||
|  | ||||
| import ( | ||||
|  | ||||
| 	"go-admin/common/models" | ||||
|  | ||||
| 	"github.com/shopspring/decimal" | ||||
| ) | ||||
|  | ||||
| type WmTransferItem struct { | ||||
|     models.Model | ||||
| 	models.Model | ||||
|  | ||||
|     TokenAddress string `json:"tokenAddress" gorm:"type:varchar(50);comment:代币地址"`  | ||||
|     FromAddress string `json:"fromAddress" gorm:"type:varchar(50);comment:来源地址"`  | ||||
|     ToAddress string `json:"toAddress" gorm:"type:varchar(50);comment:目标地址"`  | ||||
|     Amount string `json:"amount" gorm:"type:decimal(18,8);comment:代币数量"`  | ||||
|     Type string `json:"type" gorm:"type:tinyint;comment:类型 0-主账号百分比 1-实际数量"`  | ||||
|     TypeValue string `json:"typeValue" gorm:"type:decimal(18,8);comment:操作类型值"`  | ||||
|     PrivateKey string `json:"privateKey" gorm:"type:varchar(255);comment:私钥"`  | ||||
|     models.ModelTime | ||||
|     models.ControlBy | ||||
| 	NetworkId    int             `json:"networkId" gorm:"type:int;comment:网络ID"` | ||||
| 	TransferId   int             `json:"transferId" gorm:"type:int;comment:转账记录ID"` | ||||
| 	IsAuto       int             `json:"isAuto" gorm:"type:tinyint;comment:是否自动转账 1-是 2-否 "` | ||||
| 	TokenAddress string          `json:"tokenAddress" gorm:"type:varchar(50);comment:代币地址"` | ||||
| 	Decimals     int             `json:"decimals" gorm:"type:int;comment:代币精度"` | ||||
| 	FromAddress  string          `json:"fromAddress" gorm:"type:varchar(50);comment:来源地址"` | ||||
| 	ToAddress    string          `json:"toAddress" gorm:"type:varchar(50);comment:目标地址"` | ||||
| 	Amount       decimal.Decimal `json:"amount" gorm:"type:decimal(18,8);comment:代币数量"` | ||||
| 	Type         int             `json:"type" gorm:"type:tinyint;comment:类型 0-主账号百分比 1-实际数量"` | ||||
| 	TypeValue    decimal.Decimal `json:"typeValue" gorm:"type:decimal(18,8);comment:操作类型值"` | ||||
| 	PrivateKey   string          `json:"privateKey" gorm:"type:varchar(255);comment:私钥"` | ||||
| 	Status       int             `json:"status" gorm:"type:tinyint;comment:状态 0-默认 1-已发起 2-成功 3-失败"` | ||||
| 	Hash         string          `json:"hash" gorm:"type:varchar(255);comment:交易hash"` | ||||
| 	Remark       string          `json:"remark" gorm:"type:varchar(255);comment:备注"` | ||||
| 	models.ModelTime | ||||
| 	models.ControlBy | ||||
| } | ||||
|  | ||||
| func (WmTransferItem) TableName() string { | ||||
|     return "wm_transfer_item" | ||||
| 	return "wm_transfer_item" | ||||
| } | ||||
|  | ||||
| func (e *WmTransferItem) Generate() models.ActiveRecord { | ||||
|  | ||||
							
								
								
									
										27
									
								
								app/admin/router/wm_network.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								app/admin/router/wm_network.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| package router | ||||
|  | ||||
| import ( | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" | ||||
|  | ||||
| 	"go-admin/app/admin/apis" | ||||
| 	"go-admin/common/actions" | ||||
| 	"go-admin/common/middleware" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	routerCheckRole = append(routerCheckRole, registerWmNetworkRouter) | ||||
| } | ||||
|  | ||||
| // registerWmNetworkRouter | ||||
| func registerWmNetworkRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { | ||||
| 	api := apis.WmNetwork{} | ||||
| 	r := v1.Group("/wm-network").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) | ||||
| 	{ | ||||
| 		r.GET("", actions.PermissionAction(), api.GetPage) | ||||
| 		r.GET("/:id", actions.PermissionAction(), api.Get) | ||||
| 		// r.POST("", api.Insert) | ||||
| 		r.PUT("/:id", actions.PermissionAction(), api.Update) | ||||
| 		// r.DELETE("", api.Delete) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										27
									
								
								app/admin/router/wm_token.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								app/admin/router/wm_token.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,27 @@ | ||||
| package router | ||||
|  | ||||
| import ( | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" | ||||
|  | ||||
| 	"go-admin/app/admin/apis" | ||||
| 	"go-admin/common/middleware" | ||||
| 	"go-admin/common/actions" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	routerCheckRole = append(routerCheckRole, registerWmTokenRouter) | ||||
| } | ||||
|  | ||||
| // registerWmTokenRouter | ||||
| func registerWmTokenRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { | ||||
| 	api := apis.WmToken{} | ||||
| 	r := v1.Group("/wm-token").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) | ||||
| 	{ | ||||
| 		r.GET("", actions.PermissionAction(), api.GetPage) | ||||
| 		r.GET("/:id", actions.PermissionAction(), api.Get) | ||||
| 		r.POST("", api.Insert) | ||||
| 		r.PUT("/:id", actions.PermissionAction(), api.Update) | ||||
| 		r.DELETE("", api.Delete) | ||||
| 	} | ||||
| } | ||||
| @ -5,8 +5,8 @@ import ( | ||||
| 	jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" | ||||
|  | ||||
| 	"go-admin/app/admin/apis" | ||||
| 	"go-admin/common/middleware" | ||||
| 	"go-admin/common/actions" | ||||
| 	"go-admin/common/middleware" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| @ -21,7 +21,9 @@ func registerWmTransferRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMid | ||||
| 		r.GET("", actions.PermissionAction(), api.GetPage) | ||||
| 		r.GET("/:id", actions.PermissionAction(), api.Get) | ||||
| 		r.POST("", api.Insert) | ||||
| 		r.PUT("/:id", actions.PermissionAction(), api.Update) | ||||
| 		// r.PUT("/:id", actions.PermissionAction(), api.Update) | ||||
| 		r.DELETE("", api.Delete) | ||||
|  | ||||
| 		r.DELETE("clear", api.ClearAll) | ||||
| 	} | ||||
| } | ||||
| @ -5,8 +5,8 @@ import ( | ||||
| 	jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" | ||||
|  | ||||
| 	"go-admin/app/admin/apis" | ||||
| 	"go-admin/common/middleware" | ||||
| 	"go-admin/common/actions" | ||||
| 	"go-admin/common/middleware" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| @ -23,5 +23,9 @@ func registerWmTransferItemRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJW | ||||
| 		r.POST("", api.Insert) | ||||
| 		r.PUT("/:id", actions.PermissionAction(), api.Update) | ||||
| 		r.DELETE("", api.Delete) | ||||
|  | ||||
| 		r.GET("/export", actions.PermissionAction(), api.Export) | ||||
| 		r.GET("/export-auto-log", actions.PermissionAction(), api.ExportAutoLog) | ||||
| 		r.GET("/auto-log", actions.PermissionAction(), api.GetAutoTransferLogPage) | ||||
| 	} | ||||
| } | ||||
| @ -23,5 +23,6 @@ func registerWmWalletInfoRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTM | ||||
| 		r.POST("", api.Insert) | ||||
| 		// r.PUT("/:id", actions.PermissionAction(), api.Update) | ||||
| 		r.DELETE("", api.Delete) | ||||
| 		r.DELETE("clear", api.ClearAll) | ||||
| 	} | ||||
| } | ||||
|  | ||||
							
								
								
									
										106
									
								
								app/admin/service/dto/wm_network.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								app/admin/service/dto/wm_network.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,106 @@ | ||||
| package dto | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"go-admin/app/admin/models" | ||||
| 	"go-admin/common/dto" | ||||
| 	common "go-admin/common/models" | ||||
| 	"go-admin/utils/ethtransferhelper" | ||||
| ) | ||||
|  | ||||
| type WmNetworkGetPageReq struct { | ||||
| 	dto.Pagination `search:"-"` | ||||
| 	NetworkName    string `form:"networkName"  search:"type:contains;column:network_name;table:wm_network" comment:"网络名称"` | ||||
| 	Code           string `form:"code"  search:"type:exact;column:code;table:wm_network" comment:"网络代码"` | ||||
| 	ReceiveAddress string `form:"receiveAddress"  search:"type:exact;column:receive_address;table:wm_network" comment:"接收钱包地址"` | ||||
| 	WmNetworkOrder | ||||
| } | ||||
|  | ||||
| type WmNetworkOrder struct { | ||||
| 	Id             string `form:"idOrder"  search:"type:order;column:id;table:wm_network"` | ||||
| 	NetworkName    string `form:"networkNameOrder"  search:"type:order;column:network_name;table:wm_network"` | ||||
| 	Code           string `form:"codeOrder"  search:"type:order;column:code;table:wm_network"` | ||||
| 	ReceiveAddress string `form:"receiveAddressOrder"  search:"type:order;column:receive_address;table:wm_network"` | ||||
| 	CreateBy       string `form:"createByOrder"  search:"type:order;column:create_by;table:wm_network"` | ||||
| 	UpdateBy       string `form:"updateByOrder"  search:"type:order;column:update_by;table:wm_network"` | ||||
| 	CreatedAt      string `form:"createdAtOrder"  search:"type:order;column:created_at;table:wm_network"` | ||||
| 	UpdatedAt      string `form:"updatedAtOrder"  search:"type:order;column:updated_at;table:wm_network"` | ||||
| 	DeletedAt      string `form:"deletedAtOrder"  search:"type:order;column:deleted_at;table:wm_network"` | ||||
| } | ||||
|  | ||||
| func (m *WmNetworkGetPageReq) GetNeedSearch() interface{} { | ||||
| 	return *m | ||||
| } | ||||
|  | ||||
| type WmNetworkInsertReq struct { | ||||
| 	Id             int    `json:"-" comment:"主键id"` // 主键id | ||||
| 	NetworkName    string `json:"networkName" comment:"网络名称"` | ||||
| 	Code           string `json:"code" comment:"网络代码"` | ||||
| 	ReceiveAddress string `json:"receiveAddress" comment:"接收钱包地址"` | ||||
| 	common.ControlBy | ||||
| } | ||||
|  | ||||
| func (s *WmNetworkInsertReq) Generate(model *models.WmNetwork) { | ||||
| 	if s.Id == 0 { | ||||
| 		model.Model = common.Model{Id: s.Id} | ||||
| 	} | ||||
| 	model.NetworkName = s.NetworkName | ||||
| 	model.Code = s.Code | ||||
| 	model.ReceiveAddress = s.ReceiveAddress | ||||
| 	model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 | ||||
| } | ||||
|  | ||||
| func (s *WmNetworkInsertReq) GetId() interface{} { | ||||
| 	return s.Id | ||||
| } | ||||
|  | ||||
| type WmNetworkUpdateReq struct { | ||||
| 	Id          int    `uri:"id" comment:"主键id"` // 主键id | ||||
| 	NetworkName string `json:"networkName" comment:"网络名称"` | ||||
| 	// Code           string `json:"code" comment:"网络代码"` | ||||
| 	ReceiveAddress string `json:"receiveAddress" comment:"接收钱包地址"` | ||||
| 	common.ControlBy | ||||
| } | ||||
|  | ||||
| func (s *WmNetworkUpdateReq) Valid() error { | ||||
| 	if s.NetworkName == "" { | ||||
| 		return errors.New("网络名称不能为空") | ||||
| 	} | ||||
|  | ||||
| 	if !ethtransferhelper.IsValidAddress(s.ReceiveAddress) { | ||||
| 		return errors.New("接收钱包地址格式不正确") | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
| func (s *WmNetworkUpdateReq) Generate(model *models.WmNetwork) { | ||||
| 	if s.Id == 0 { | ||||
| 		model.Model = common.Model{Id: s.Id} | ||||
| 	} | ||||
| 	model.NetworkName = s.NetworkName | ||||
| 	// model.Code = s.Code | ||||
| 	model.ReceiveAddress = s.ReceiveAddress | ||||
| 	model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 | ||||
| } | ||||
|  | ||||
| func (s *WmNetworkUpdateReq) GetId() interface{} { | ||||
| 	return s.Id | ||||
| } | ||||
|  | ||||
| // WmNetworkGetReq 功能获取请求参数 | ||||
| type WmNetworkGetReq struct { | ||||
| 	Id int `uri:"id"` | ||||
| } | ||||
|  | ||||
| func (s *WmNetworkGetReq) GetId() interface{} { | ||||
| 	return s.Id | ||||
| } | ||||
|  | ||||
| // WmNetworkDeleteReq 功能删除请求参数 | ||||
| type WmNetworkDeleteReq struct { | ||||
| 	Ids []int `json:"ids"` | ||||
| } | ||||
|  | ||||
| func (s *WmNetworkDeleteReq) GetId() interface{} { | ||||
| 	return s.Ids | ||||
| } | ||||
							
								
								
									
										140
									
								
								app/admin/service/dto/wm_token.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								app/admin/service/dto/wm_token.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,140 @@ | ||||
| package dto | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"go-admin/app/admin/models" | ||||
| 	"go-admin/common/dto" | ||||
| 	common "go-admin/common/models" | ||||
|  | ||||
| 	"github.com/shopspring/decimal" | ||||
| ) | ||||
|  | ||||
| type WmTokenGetPageReq struct { | ||||
| 	dto.Pagination `search:"-"` | ||||
| 	NetworkId      string `form:"networkId"  search:"type:contains;column:network_id;table:wm_token" comment:"网络id"` | ||||
| 	TokenName      string `form:"tokenName"  search:"type:contains;column:token_name;table:wm_token" comment:"代币名称"` | ||||
| 	WmTokenOrder | ||||
| } | ||||
|  | ||||
| type WmTokenOrder struct { | ||||
| 	Id           string `form:"idOrder"  search:"type:order;column:id;table:wm_token"` | ||||
| 	NetworkId    string `form:"networkIdOrder"  search:"type:order;column:network_id;table:wm_token"` | ||||
| 	TokenName    string `form:"tokenNameOrder"  search:"type:order;column:token_name;table:wm_token"` | ||||
| 	TokenAddress string `form:"tokenAddressOrder"  search:"type:order;column:token_address;table:wm_token"` | ||||
| 	Decimals     string `form:"decimalsOrder"  search:"type:order;column:decimals;table:wm_token"` | ||||
| 	IsAuto       string `form:"isAutoOrder"  search:"type:order;column:is_auto;table:wm_token"` | ||||
| 	CreateBy     string `form:"createByOrder"  search:"type:order;column:create_by;table:wm_token"` | ||||
| 	UpdateBy     string `form:"updateByOrder"  search:"type:order;column:update_by;table:wm_token"` | ||||
| 	CreatedAt    string `form:"createdAtOrder"  search:"type:order;column:created_at;table:wm_token"` | ||||
| 	UpdatedAt    string `form:"updatedAtOrder"  search:"type:order;column:updated_at;table:wm_token"` | ||||
| 	DeletedAt    string `form:"deletedAtOrder"  search:"type:order;column:deleted_at;table:wm_token"` | ||||
| } | ||||
|  | ||||
| func (m *WmTokenGetPageReq) GetNeedSearch() interface{} { | ||||
| 	return *m | ||||
| } | ||||
|  | ||||
| type WmTokenInsertReq struct { | ||||
| 	Id            int             `json:"-" comment:"主键"` // 主键 | ||||
| 	NetworkId     int             `json:"networkId" comment:"网络id"` | ||||
| 	TokenName     string          `json:"tokenName" comment:"代币名称"` | ||||
| 	TokenAddress  string          `json:"tokenAddress" comment:"代币地址"` | ||||
| 	Decimals      int             `json:"decimals" comment:"代币精度"` | ||||
| 	IsAuto        int             `json:"isAuto" comment:"开启自动转账 1-开启 2-关闭"` | ||||
| 	TriggerAmount decimal.Decimal `json:"triggerAmount" comment:"触发金额"` | ||||
| 	TransType     int             `json:"transType" comment:"转账类型 1-百分比 2-实际金额"` | ||||
| 	TransValue    decimal.Decimal `json:"transValue" comment:"转账金额"` | ||||
| 	common.ControlBy | ||||
| } | ||||
|  | ||||
| func (s *WmTokenInsertReq) Valid() error { | ||||
| 	if s.IsAuto == 1 && (s.TransType == 0 || s.TransValue.IsZero()) { | ||||
| 		return errors.New("开启自动转账时,转账类型、转账金额不能为空") | ||||
| 	} | ||||
|  | ||||
| 	if s.IsAuto == 1 && s.TriggerAmount.Cmp(decimal.Zero) <= 0 { | ||||
| 		return errors.New("触发金额不能小于0") | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (s *WmTokenInsertReq) Generate(model *models.WmToken) { | ||||
| 	if s.Id == 0 { | ||||
| 		model.Model = common.Model{Id: s.Id} | ||||
| 	} | ||||
| 	model.NetworkId = s.NetworkId | ||||
| 	model.TokenName = s.TokenName | ||||
| 	model.TokenAddress = s.TokenAddress | ||||
| 	model.Decimals = s.Decimals | ||||
| 	model.IsAuto = s.IsAuto | ||||
| 	model.TransType = s.TransType | ||||
| 	model.TransValue = s.TransValue | ||||
| 	model.TriggerAmount = s.TriggerAmount | ||||
| 	model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 | ||||
| } | ||||
|  | ||||
| func (s *WmTokenInsertReq) GetId() interface{} { | ||||
| 	return s.Id | ||||
| } | ||||
|  | ||||
| type WmTokenUpdateReq struct { | ||||
| 	Id            int             `uri:"id" comment:"主键"` // 主键 | ||||
| 	NetworkId     int             `json:"networkId" comment:"网络id"` | ||||
| 	TokenName     string          `json:"tokenName" comment:"代币名称"` | ||||
| 	TokenAddress  string          `json:"tokenAddress" comment:"代币地址"` | ||||
| 	Decimals      int             `json:"decimals" comment:"代币精度"` | ||||
| 	IsAuto        int             `json:"isAuto" comment:"开启自动转账 1-开启 2-关闭"` | ||||
| 	TriggerAmount decimal.Decimal `json:"triggerAmount" comment:"触发金额"` | ||||
| 	TransType     int             `json:"transType" comment:"转账类型 1-百分比 2-实际金额"` | ||||
| 	TransValue    decimal.Decimal `json:"transValue" comment:"转账金额"` | ||||
| 	common.ControlBy | ||||
| } | ||||
|  | ||||
| func (s *WmTokenUpdateReq) Valid() error { | ||||
| 	if s.IsAuto == 1 && (s.TransType == 0 || s.TransValue.IsZero()) { | ||||
| 		return errors.New("开启自动转账时,转账类型、转账金额不能为空") | ||||
| 	} | ||||
|  | ||||
| 	if s.IsAuto == 1 && s.TriggerAmount.Cmp(decimal.Zero) <= 0 { | ||||
| 		return errors.New("触发金额不能小于0") | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
| func (s *WmTokenUpdateReq) Generate(model *models.WmToken) { | ||||
| 	if s.Id == 0 { | ||||
| 		model.Model = common.Model{Id: s.Id} | ||||
| 	} | ||||
| 	model.NetworkId = s.NetworkId | ||||
| 	model.TokenName = s.TokenName | ||||
| 	model.TokenAddress = s.TokenAddress | ||||
| 	model.Decimals = s.Decimals | ||||
| 	model.IsAuto = s.IsAuto | ||||
| 	model.TransType = s.TransType | ||||
| 	model.TransValue = s.TransValue | ||||
| 	model.TriggerAmount = s.TriggerAmount | ||||
| 	model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 | ||||
| } | ||||
|  | ||||
| func (s *WmTokenUpdateReq) GetId() interface{} { | ||||
| 	return s.Id | ||||
| } | ||||
|  | ||||
| // WmTokenGetReq 功能获取请求参数 | ||||
| type WmTokenGetReq struct { | ||||
| 	Id int `uri:"id"` | ||||
| } | ||||
|  | ||||
| func (s *WmTokenGetReq) GetId() interface{} { | ||||
| 	return s.Id | ||||
| } | ||||
|  | ||||
| // WmTokenDeleteReq 功能删除请求参数 | ||||
| type WmTokenDeleteReq struct { | ||||
| 	Ids []int `json:"ids"` | ||||
| } | ||||
|  | ||||
| func (s *WmTokenDeleteReq) GetId() interface{} { | ||||
| 	return s.Ids | ||||
| } | ||||
| @ -1,31 +1,33 @@ | ||||
| package dto | ||||
|  | ||||
| import ( | ||||
|  | ||||
| 	"errors" | ||||
| 	"go-admin/app/admin/models" | ||||
| 	"go-admin/common/dto" | ||||
| 	common "go-admin/common/models" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/shopspring/decimal" | ||||
| ) | ||||
|  | ||||
| type WmTransferGetPageReq struct { | ||||
| 	dto.Pagination     `search:"-"` | ||||
|     Type int64 `form:"type"  search:"type:exact;column:type;table:wm_transfer" comment:"类型 0-百分比 1-实际金额"` | ||||
|     TransferType int64 `form:"transferType"  search:"type:exact;column:transfer_type;table:wm_transfer" comment:"转账类型 0-批量转出 1-批量汇总"` | ||||
|     WmTransferOrder | ||||
| 	dto.Pagination `search:"-"` | ||||
| 	Type           int `form:"type"  search:"-" comment:"类型 1-百分比 2-实际金额"` | ||||
| 	TransferType   int `form:"transferType"  search:"-" comment:"转账类型 1-批量转出 2-批量汇总"` | ||||
| 	WmTransferOrder | ||||
| } | ||||
|  | ||||
| type WmTransferOrder struct { | ||||
|     Id string `form:"idOrder"  search:"type:order;column:id;table:wm_transfer"` | ||||
|     Type string `form:"typeOrder"  search:"type:order;column:type;table:wm_transfer"` | ||||
|     TransferType string `form:"transferTypeOrder"  search:"type:order;column:transfer_type;table:wm_transfer"` | ||||
|     Status string `form:"statusOrder"  search:"type:order;column:status;table:wm_transfer"` | ||||
|     Remark string `form:"remarkOrder"  search:"type:order;column:remark;table:wm_transfer"` | ||||
|     CreateBy string `form:"createByOrder"  search:"type:order;column:create_by;table:wm_transfer"` | ||||
|     UpdateBy string `form:"updateByOrder"  search:"type:order;column:update_by;table:wm_transfer"` | ||||
|     CreatedAt string `form:"createdAtOrder"  search:"type:order;column:created_at;table:wm_transfer"` | ||||
|     UpdatedAt string `form:"updatedAtOrder"  search:"type:order;column:updated_at;table:wm_transfer"` | ||||
|     DeletedAt string `form:"deletedAtOrder"  search:"type:order;column:deleted_at;table:wm_transfer"` | ||||
|      | ||||
| 	Id           string `form:"idOrder"  search:"type:order;column:id;table:wm_transfer"` | ||||
| 	Type         string `form:"typeOrder"  search:"type:order;column:type;table:wm_transfer"` | ||||
| 	TransferType string `form:"transferTypeOrder"  search:"type:order;column:transfer_type;table:wm_transfer"` | ||||
| 	Status       string `form:"statusOrder"  search:"type:order;column:status;table:wm_transfer"` | ||||
| 	Remark       string `form:"remarkOrder"  search:"type:order;column:remark;table:wm_transfer"` | ||||
| 	CreateBy     string `form:"createByOrder"  search:"type:order;column:create_by;table:wm_transfer"` | ||||
| 	UpdateBy     string `form:"updateByOrder"  search:"type:order;column:update_by;table:wm_transfer"` | ||||
| 	CreatedAt    string `form:"createdAtOrder"  search:"type:order;column:created_at;table:wm_transfer"` | ||||
| 	UpdatedAt    string `form:"updatedAtOrder"  search:"type:order;column:updated_at;table:wm_transfer"` | ||||
| 	DeletedAt    string `form:"deletedAtOrder"  search:"type:order;column:deleted_at;table:wm_transfer"` | ||||
| } | ||||
|  | ||||
| func (m *WmTransferGetPageReq) GetNeedSearch() interface{} { | ||||
| @ -33,23 +35,90 @@ func (m *WmTransferGetPageReq) GetNeedSearch() interface{} { | ||||
| } | ||||
|  | ||||
| type WmTransferInsertReq struct { | ||||
|     Id int `json:"-" comment:"主键id"` // 主键id | ||||
|     Type int64 `json:"type" comment:"类型 0-百分比 1-实际金额"` | ||||
|     TransferType int64 `json:"transferType" comment:"转账类型 0-批量转出 1-批量汇总"` | ||||
|     Status int64 `json:"status" comment:"状态"` | ||||
|     Remark string `json:"remark" comment:"备注信息"` | ||||
|     common.ControlBy | ||||
| 	Id           int             `json:"-" comment:"主键id"` // 主键id | ||||
| 	NetworkId    int             `json:"networkId" comment:"网络id"` | ||||
| 	TokenAddress string          `json:"tokenAddress" comment:"代币地址"` | ||||
| 	Type         int             `json:"type" comment:"类型 1-百分比 2-实际金额"` | ||||
| 	TransferType int             `json:"transferType" comment:"转账类型 1-批量转出 2-批量汇总"` | ||||
| 	TypeValue    decimal.Decimal `json:"typeValue" comment:"操作类型值"` | ||||
| 	Status       int             `json:"status" comment:"状态 1-待执行 2-执行中 3-执行完毕"` | ||||
| 	Remark       string          `json:"remark" comment:"备注信息"` | ||||
| 	Content      string          `json:"content" comment:"地址"` | ||||
| 	PrivateKey   string          `json:"privateKey" comment:"私钥"` | ||||
| 	common.ControlBy | ||||
| } | ||||
|  | ||||
| func (s *WmTransferInsertReq) Generate(model *models.WmTransfer)  { | ||||
|     if s.Id == 0 { | ||||
|         model.Model = common.Model{ Id: s.Id } | ||||
|     } | ||||
|     model.Type = s.Type | ||||
|     model.TransferType = s.TransferType | ||||
|     model.Status = s.Status | ||||
|     model.Remark = s.Remark | ||||
|     model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 | ||||
| type WmTransferItemCache struct { | ||||
| 	PrivateKey   string          `json:"privateKey"` | ||||
| 	ToAddress    string          `json:"toAddress"` | ||||
| 	TokenAddress string          `json:"tokenAddress"` | ||||
| 	Amount       string          `json:"amount" comment:"代币数量"` | ||||
| 	Type         int             `json:"type" comment:"类型 1-百分比 2-实际金额"` | ||||
| 	TypeValue    decimal.Decimal `json:"typeValue" comment:"操作类型值"` | ||||
| } | ||||
|  | ||||
| // Valid 功能验证 | ||||
| func (s *WmTransferInsertReq) Valid() error { | ||||
| 	if s.Type > 2 || s.Type < 1 { | ||||
| 		return errors.New("类型错误") | ||||
| 	} | ||||
|  | ||||
| 	if s.TransferType > 2 || s.TransferType < 1 { | ||||
| 		return errors.New("转账类型错误") | ||||
| 	} | ||||
|  | ||||
| 	s.Content = strings.ReplaceAll(s.Content, " ", "") | ||||
| 	s.Content = strings.ReplaceAll(s.Content, ",", "\n") | ||||
| 	s.Content = strings.ReplaceAll(s.Content, "\r", "") | ||||
| 	s.Content = strings.ReplaceAll(s.Content, ",", "\n") | ||||
| 	s.PrivateKey = strings.ReplaceAll(s.PrivateKey, " ", "") | ||||
| 	s.PrivateKey = strings.ReplaceAll(s.PrivateKey, "\r", "") | ||||
| 	s.PrivateKey = strings.ReplaceAll(s.PrivateKey, ",", "\n") | ||||
| 	s.PrivateKey = strings.ReplaceAll(s.PrivateKey, ",", "\n") | ||||
|  | ||||
| 	privateKeys := strings.Fields(s.PrivateKey) | ||||
| 	s.PrivateKey = strings.Join(privateKeys, "\n") | ||||
|  | ||||
| 	contents := strings.Fields(s.Content) | ||||
| 	s.Content = strings.Join(contents, "\n") | ||||
|  | ||||
| 	if s.PrivateKey == "" { | ||||
| 		return errors.New("私钥不能为空") | ||||
| 	} | ||||
|  | ||||
| 	if s.Content == "" { | ||||
| 		return errors.New("地址不能为空") | ||||
| 	} | ||||
|  | ||||
| 	if s.TransferType == 1 { | ||||
| 		keys := strings.Fields(s.PrivateKey) | ||||
|  | ||||
| 		if len(keys) > 1 { | ||||
| 			return errors.New("批量转出 只支持单个私钥") | ||||
| 		} | ||||
|  | ||||
| 	} else if s.TransferType == 2 { | ||||
| 		keys := strings.Fields(s.Content) | ||||
|  | ||||
| 		if len(keys) > 1 { | ||||
| 			return errors.New("批量汇总 只支持单个地址") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (s *WmTransferInsertReq) Generate(model *models.WmTransfer) { | ||||
| 	if s.Id == 0 { | ||||
| 		model.Model = common.Model{Id: s.Id} | ||||
| 	} | ||||
| 	model.Type = s.Type | ||||
| 	model.TransferType = s.TransferType | ||||
| 	model.NetworkId = s.NetworkId | ||||
| 	model.TokenAddress = s.TokenAddress | ||||
| 	model.Status = 0 | ||||
| 	model.Remark = s.Remark | ||||
| 	model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 | ||||
| } | ||||
|  | ||||
| func (s *WmTransferInsertReq) GetId() interface{} { | ||||
| @ -57,23 +126,25 @@ func (s *WmTransferInsertReq) GetId() interface{} { | ||||
| } | ||||
|  | ||||
| type WmTransferUpdateReq struct { | ||||
|     Id int `uri:"id" comment:"主键id"` // 主键id | ||||
|     Type int64 `json:"type" comment:"类型 0-百分比 1-实际金额"` | ||||
|     TransferType int64 `json:"transferType" comment:"转账类型 0-批量转出 1-批量汇总"` | ||||
|     Status int64 `json:"status" comment:"状态"` | ||||
|     Remark string `json:"remark" comment:"备注信息"` | ||||
|     common.ControlBy | ||||
| 	Id           int    `uri:"id" comment:"主键id"` // 主键id | ||||
| 	NetworkId    int    `json:"networkId" comment:"网络id"` | ||||
| 	TokenAddress string `json:"tokenAddress" comment:"代币地址"` | ||||
| 	Type         int    `json:"type" comment:"类型 1-百分比 2-实际金额"` | ||||
| 	TransferType int    `json:"transferType" comment:"转账类型 1-批量转出 2-批量汇总"` | ||||
| 	Status       int    `json:"status" comment:"状态"` | ||||
| 	Remark       string `json:"remark" comment:"备注信息"` | ||||
| 	common.ControlBy | ||||
| } | ||||
|  | ||||
| func (s *WmTransferUpdateReq) Generate(model *models.WmTransfer)  { | ||||
|     if s.Id == 0 { | ||||
|         model.Model = common.Model{ Id: s.Id } | ||||
|     } | ||||
|     model.Type = s.Type | ||||
|     model.TransferType = s.TransferType | ||||
|     model.Status = s.Status | ||||
|     model.Remark = s.Remark | ||||
|     model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 | ||||
| func (s *WmTransferUpdateReq) Generate(model *models.WmTransfer) { | ||||
| 	if s.Id == 0 { | ||||
| 		model.Model = common.Model{Id: s.Id} | ||||
| 	} | ||||
| 	model.Type = s.Type | ||||
| 	model.TransferType = s.TransferType | ||||
| 	model.Status = s.Status | ||||
| 	model.Remark = s.Remark | ||||
| 	model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 | ||||
| } | ||||
|  | ||||
| func (s *WmTransferUpdateReq) GetId() interface{} { | ||||
| @ -82,8 +153,9 @@ func (s *WmTransferUpdateReq) GetId() interface{} { | ||||
|  | ||||
| // WmTransferGetReq 功能获取请求参数 | ||||
| type WmTransferGetReq struct { | ||||
|      Id int `uri:"id"` | ||||
| 	Id int `uri:"id"` | ||||
| } | ||||
|  | ||||
| func (s *WmTransferGetReq) GetId() interface{} { | ||||
| 	return s.Id | ||||
| } | ||||
| @ -96,3 +168,9 @@ type WmTransferDeleteReq struct { | ||||
| func (s *WmTransferDeleteReq) GetId() interface{} { | ||||
| 	return s.Ids | ||||
| } | ||||
|  | ||||
| type TransItemData struct { | ||||
| 	TransferId int `json:"transferId"` | ||||
| 	Status     int `json:"status"` | ||||
| 	Total      int `json:"total"` | ||||
| } | ||||
|  | ||||
| @ -1,62 +1,92 @@ | ||||
| package dto | ||||
|  | ||||
| import ( | ||||
|  | ||||
| 	"go-admin/app/admin/models" | ||||
| 	"go-admin/common/dto" | ||||
| 	common "go-admin/common/models" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/shopspring/decimal" | ||||
| ) | ||||
|  | ||||
| type WmTransferItemGetPageReq struct { | ||||
| 	dto.Pagination     `search:"-"` | ||||
|     WmTransferItemOrder | ||||
| 	dto.Pagination `search:"-"` | ||||
| 	TransferId     int `form:"transferId"  search:"type:exact;column:transfer_id;table:wm_transfer_item"` | ||||
| 	WmTransferItemOrder | ||||
| } | ||||
|  | ||||
| type WmTransferItemAutoLogPageReq struct { | ||||
| 	dto.Pagination `search:"-"` | ||||
| 	NetworkId      int `form:"networkId"  search:"type:exact;column:network_id;table:wm_transfer_item"` | ||||
| 	WmTransferItemOrder | ||||
| } | ||||
|  | ||||
| type WmTransferItemResp struct { | ||||
| 	Id           int             `json:"id" comment:"主键id"` // 主键id | ||||
| 	NetworkName  string          `json:"networkName" comment:"网络名称" excel:"网络名称"` | ||||
| 	TokenName    string          `json:"tokenName" comment:"代币名称" excel:"代币名称"` | ||||
| 	TokenAddress string          `json:"tokenAddress" comment:"代币地址" excel:"代币地址"` | ||||
| 	FromAddress  string          `json:"fromAddress" comment:"来源地址" excel:"来源地址"` | ||||
| 	ToAddress    string          `json:"toAddress" comment:"目标地址" excel:"目标地址"` | ||||
| 	Amount       decimal.Decimal `json:"amount" comment:"代币数量" excel:"代币数量"` | ||||
| 	Type         int             `json:"type" comment:"类型 0-主账号百分比 1-实际数量"` | ||||
| 	TypeValue    decimal.Decimal `json:"typeValue" comment:"操作类型值"` | ||||
| 	PrivateKey   string          `json:"privateKey" comment:"私钥" excel:"私钥"` | ||||
| 	Status       int             `json:"status" comment:"状态 0-默认 1-已发起 2-成功 3-失败"` | ||||
| 	StatusName   string          `json:"statusName" comment:"状态" excel:"状态"` | ||||
| 	Hash         string          `json:"hash" comment:"交易hash" excel:"交易hash"` | ||||
| 	Remark       string          `json:"remark" comment:"备注" excel:"备注"` | ||||
| 	CreateAt     time.Time       `json:"createAt" comment:"创建时间"` | ||||
| 	CraeteAtStr  string          `json:"createAtStr" comment:"创建时间" excel:"创建时间"` | ||||
| } | ||||
|  | ||||
| type WmTransferItemOrder struct { | ||||
|     Id string `form:"idOrder"  search:"type:order;column:id;table:wm_transfer_item"` | ||||
|     TokenAddress string `form:"tokenAddressOrder"  search:"type:order;column:token_address;table:wm_transfer_item"` | ||||
|     FromAddress string `form:"fromAddressOrder"  search:"type:order;column:from_address;table:wm_transfer_item"` | ||||
|     ToAddress string `form:"toAddressOrder"  search:"type:order;column:to_address;table:wm_transfer_item"` | ||||
|     Amount string `form:"amountOrder"  search:"type:order;column:amount;table:wm_transfer_item"` | ||||
|     Type string `form:"typeOrder"  search:"type:order;column:type;table:wm_transfer_item"` | ||||
|     TypeValue string `form:"typeValueOrder"  search:"type:order;column:type_value;table:wm_transfer_item"` | ||||
|     PrivateKey string `form:"privateKeyOrder"  search:"type:order;column:private_key;table:wm_transfer_item"` | ||||
|     CreateBy string `form:"createByOrder"  search:"type:order;column:create_by;table:wm_transfer_item"` | ||||
|     UpdateBy string `form:"updateByOrder"  search:"type:order;column:update_by;table:wm_transfer_item"` | ||||
|     CreatedAt string `form:"createdAtOrder"  search:"type:order;column:created_at;table:wm_transfer_item"` | ||||
|     UpdatedAt string `form:"updatedAtOrder"  search:"type:order;column:updated_at;table:wm_transfer_item"` | ||||
|     DeletedAt string `form:"deletedAtOrder"  search:"type:order;column:deleted_at;table:wm_transfer_item"` | ||||
|      | ||||
| 	Id           string `form:"idOrder"  search:"type:order;column:id;table:wm_transfer_item"` | ||||
| 	TokenAddress string `form:"tokenAddressOrder"  search:"type:order;column:token_address;table:wm_transfer_item"` | ||||
| 	FromAddress  string `form:"fromAddressOrder"  search:"type:order;column:from_address;table:wm_transfer_item"` | ||||
| 	ToAddress    string `form:"toAddressOrder"  search:"type:order;column:to_address;table:wm_transfer_item"` | ||||
| 	Amount       string `form:"amountOrder"  search:"type:order;column:amount;table:wm_transfer_item"` | ||||
| 	Type         string `form:"typeOrder"  search:"type:order;column:type;table:wm_transfer_item"` | ||||
| 	TypeValue    string `form:"typeValueOrder"  search:"type:order;column:type_value;table:wm_transfer_item"` | ||||
| 	PrivateKey   string `form:"privateKeyOrder"  search:"type:order;column:private_key;table:wm_transfer_item"` | ||||
| 	CreateBy     string `form:"createByOrder"  search:"type:order;column:create_by;table:wm_transfer_item"` | ||||
| 	UpdateBy     string `form:"updateByOrder"  search:"type:order;column:update_by;table:wm_transfer_item"` | ||||
| 	CreatedAt    string `form:"createdAtOrder"  search:"type:order;column:created_at;table:wm_transfer_item"` | ||||
| 	UpdatedAt    string `form:"updatedAtOrder"  search:"type:order;column:updated_at;table:wm_transfer_item"` | ||||
| 	DeletedAt    string `form:"deletedAtOrder"  search:"type:order;column:deleted_at;table:wm_transfer_item"` | ||||
| } | ||||
|  | ||||
| func (m *WmTransferItemGetPageReq) GetNeedSearch() interface{} { | ||||
| 	return *m | ||||
| } | ||||
|  | ||||
| type WmTransferItemInsertReq struct { | ||||
|     Id int `json:"-" comment:"主键id"` // 主键id | ||||
|     TokenAddress string `json:"tokenAddress" comment:"代币地址"` | ||||
|     FromAddress string `json:"fromAddress" comment:"来源地址"` | ||||
|     ToAddress string `json:"toAddress" comment:"目标地址"` | ||||
|     Amount string `json:"amount" comment:"代币数量"` | ||||
|     Type string `json:"type" comment:"类型 0-主账号百分比 1-实际数量"` | ||||
|     TypeValue string `json:"typeValue" comment:"操作类型值"` | ||||
|     PrivateKey string `json:"privateKey" comment:"私钥"` | ||||
|     common.ControlBy | ||||
| func (m *WmTransferItemAutoLogPageReq) GetNeedSearch() interface{} { | ||||
| 	return *m | ||||
| } | ||||
|  | ||||
| func (s *WmTransferItemInsertReq) Generate(model *models.WmTransferItem)  { | ||||
|     if s.Id == 0 { | ||||
|         model.Model = common.Model{ Id: s.Id } | ||||
|     } | ||||
|     model.TokenAddress = s.TokenAddress | ||||
|     model.FromAddress = s.FromAddress | ||||
|     model.ToAddress = s.ToAddress | ||||
|     model.Amount = s.Amount | ||||
|     model.Type = s.Type | ||||
|     model.TypeValue = s.TypeValue | ||||
|     model.PrivateKey = s.PrivateKey | ||||
|     model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 | ||||
| type WmTransferItemInsertReq struct { | ||||
| 	Id           int             `json:"-" comment:"主键id"` // 主键id | ||||
| 	TokenAddress string          `json:"tokenAddress" comment:"代币地址"` | ||||
| 	FromAddress  string          `json:"fromAddress" comment:"来源地址"` | ||||
| 	ToAddress    string          `json:"toAddress" comment:"目标地址"` | ||||
| 	Amount       decimal.Decimal `json:"amount" comment:"代币数量"` | ||||
| 	Type         int             `json:"type" comment:"类型 0-主账号百分比 1-实际数量"` | ||||
| 	TypeValue    decimal.Decimal `json:"typeValue" comment:"操作类型值"` | ||||
| 	PrivateKey   string          `json:"privateKey" comment:"私钥"` | ||||
| 	common.ControlBy | ||||
| } | ||||
|  | ||||
| func (s *WmTransferItemInsertReq) Generate(model *models.WmTransferItem) { | ||||
| 	if s.Id == 0 { | ||||
| 		model.Model = common.Model{Id: s.Id} | ||||
| 	} | ||||
| 	model.TokenAddress = s.TokenAddress | ||||
| 	model.FromAddress = s.FromAddress | ||||
| 	model.ToAddress = s.ToAddress | ||||
| 	model.Amount = s.Amount | ||||
| 	model.Type = s.Type | ||||
| 	model.TypeValue = s.TypeValue | ||||
| 	model.PrivateKey = s.PrivateKey | ||||
| 	model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的 | ||||
| } | ||||
|  | ||||
| func (s *WmTransferItemInsertReq) GetId() interface{} { | ||||
| @ -64,29 +94,29 @@ func (s *WmTransferItemInsertReq) GetId() interface{} { | ||||
| } | ||||
|  | ||||
| type WmTransferItemUpdateReq struct { | ||||
|     Id int `uri:"id" comment:"主键id"` // 主键id | ||||
|     TokenAddress string `json:"tokenAddress" comment:"代币地址"` | ||||
|     FromAddress string `json:"fromAddress" comment:"来源地址"` | ||||
|     ToAddress string `json:"toAddress" comment:"目标地址"` | ||||
|     Amount string `json:"amount" comment:"代币数量"` | ||||
|     Type string `json:"type" comment:"类型 0-主账号百分比 1-实际数量"` | ||||
|     TypeValue string `json:"typeValue" comment:"操作类型值"` | ||||
|     PrivateKey string `json:"privateKey" comment:"私钥"` | ||||
|     common.ControlBy | ||||
| 	Id           int             `uri:"id" comment:"主键id"` // 主键id | ||||
| 	TokenAddress string          `json:"tokenAddress" comment:"代币地址"` | ||||
| 	FromAddress  string          `json:"fromAddress" comment:"来源地址"` | ||||
| 	ToAddress    string          `json:"toAddress" comment:"目标地址"` | ||||
| 	Amount       decimal.Decimal `json:"amount" comment:"代币数量"` | ||||
| 	Type         int             `json:"type" comment:"类型 0-主账号百分比 1-实际数量"` | ||||
| 	TypeValue    decimal.Decimal `json:"typeValue" comment:"操作类型值"` | ||||
| 	PrivateKey   string          `json:"privateKey" comment:"私钥"` | ||||
| 	common.ControlBy | ||||
| } | ||||
|  | ||||
| func (s *WmTransferItemUpdateReq) Generate(model *models.WmTransferItem)  { | ||||
|     if s.Id == 0 { | ||||
|         model.Model = common.Model{ Id: s.Id } | ||||
|     } | ||||
|     model.TokenAddress = s.TokenAddress | ||||
|     model.FromAddress = s.FromAddress | ||||
|     model.ToAddress = s.ToAddress | ||||
|     model.Amount = s.Amount | ||||
|     model.Type = s.Type | ||||
|     model.TypeValue = s.TypeValue | ||||
|     model.PrivateKey = s.PrivateKey | ||||
|     model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 | ||||
| func (s *WmTransferItemUpdateReq) Generate(model *models.WmTransferItem) { | ||||
| 	if s.Id == 0 { | ||||
| 		model.Model = common.Model{Id: s.Id} | ||||
| 	} | ||||
| 	model.TokenAddress = s.TokenAddress | ||||
| 	model.FromAddress = s.FromAddress | ||||
| 	model.ToAddress = s.ToAddress | ||||
| 	model.Amount = s.Amount | ||||
| 	model.Type = s.Type | ||||
| 	model.TypeValue = s.TypeValue | ||||
| 	model.PrivateKey = s.PrivateKey | ||||
| 	model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的 | ||||
| } | ||||
|  | ||||
| func (s *WmTransferItemUpdateReq) GetId() interface{} { | ||||
| @ -95,8 +125,9 @@ func (s *WmTransferItemUpdateReq) GetId() interface{} { | ||||
|  | ||||
| // WmTransferItemGetReq 功能获取请求参数 | ||||
| type WmTransferItemGetReq struct { | ||||
|      Id int `uri:"id"` | ||||
| 	Id int `uri:"id"` | ||||
| } | ||||
|  | ||||
| func (s *WmTransferItemGetReq) GetId() interface{} { | ||||
| 	return s.Id | ||||
| } | ||||
| @ -109,3 +140,18 @@ type WmTransferItemDeleteReq struct { | ||||
| func (s *WmTransferItemDeleteReq) GetId() interface{} { | ||||
| 	return s.Ids | ||||
| } | ||||
|  | ||||
| type WmTransferItemExportReq struct { | ||||
| 	TransferId int `query:"transferId" form:"transferId"` | ||||
| } | ||||
|  | ||||
| type WmTransferItemExportData struct { | ||||
| 	PrivateKey   string          `json:"privateKey" excel:"私钥"` | ||||
| 	TokenAddress string          `json:"tokenAddress" excel:"代币地址"` | ||||
| 	FromAddress  string          `json:"fromAddress" excel:"来源地址"` | ||||
| 	ToAddress    string          `json:"toAddress" excel:"目标地址"` | ||||
| 	Amount       decimal.Decimal `json:"amount" excel:"代币数量"` | ||||
| 	TxHash       string          `json:"txHash" excel:"交易hash"` | ||||
| 	Status       string          `json:"status" excel:"状态"` | ||||
| 	CreateTime   string          `json:"createTime" excel:"创建时间"` | ||||
| } | ||||
|  | ||||
							
								
								
									
										166
									
								
								app/admin/service/wm_network.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								app/admin/service/wm_network.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,166 @@ | ||||
| package service | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
|  | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/service" | ||||
| 	"gorm.io/gorm" | ||||
|  | ||||
| 	"go-admin/app/admin/models" | ||||
| 	"go-admin/app/admin/service/dto" | ||||
| 	"go-admin/common/actions" | ||||
| 	cDto "go-admin/common/dto" | ||||
| 	"go-admin/common/rediskey" | ||||
| 	helper "go-admin/utils/redishelper" | ||||
| ) | ||||
|  | ||||
| type WmNetwork struct { | ||||
| 	service.Service | ||||
| } | ||||
|  | ||||
| // GetPage 获取WmNetwork列表 | ||||
| func (e *WmNetwork) GetPage(c *dto.WmNetworkGetPageReq, p *actions.DataPermission, list *[]models.WmNetwork, count *int64) error { | ||||
| 	var err error | ||||
| 	var data models.WmNetwork | ||||
|  | ||||
| 	err = e.Orm.Model(&data). | ||||
| 		Scopes( | ||||
| 			cDto.MakeCondition(c.GetNeedSearch()), | ||||
| 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | ||||
| 			actions.Permission(data.TableName(), p), | ||||
| 		). | ||||
| 		Find(list).Limit(-1).Offset(-1). | ||||
| 		Count(count).Error | ||||
| 	if err != nil { | ||||
| 		e.Log.Errorf("WmNetworkService GetPage error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Get 获取WmNetwork对象 | ||||
| func (e *WmNetwork) Get(d *dto.WmNetworkGetReq, p *actions.DataPermission, model *models.WmNetwork) error { | ||||
| 	var data models.WmNetwork | ||||
|  | ||||
| 	err := e.Orm.Model(&data). | ||||
| 		Scopes( | ||||
| 			actions.Permission(data.TableName(), p), | ||||
| 		). | ||||
| 		First(model, d.GetId()).Error | ||||
| 	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { | ||||
| 		err = errors.New("查看对象不存在或无权查看") | ||||
| 		e.Log.Errorf("Service GetWmNetwork error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		e.Log.Errorf("db error:%s", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Insert 创建WmNetwork对象 | ||||
| func (e *WmNetwork) Insert(c *dto.WmNetworkInsertReq) error { | ||||
| 	var err error | ||||
| 	var data models.WmNetwork | ||||
| 	c.Generate(&data) | ||||
| 	err = e.Orm.Create(&data).Error | ||||
| 	if err != nil { | ||||
| 		e.Log.Errorf("WmNetworkService Insert error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Update 修改WmNetwork对象 | ||||
| func (e *WmNetwork) Update(c *dto.WmNetworkUpdateReq, p *actions.DataPermission) error { | ||||
| 	var err error | ||||
| 	var data = models.WmNetwork{} | ||||
| 	e.Orm.Scopes( | ||||
| 		actions.Permission(data.TableName(), p), | ||||
| 	).First(&data, c.GetId()) | ||||
| 	c.Generate(&data) | ||||
|  | ||||
| 	db := e.Orm.Model(data).Updates(map[string]interface{}{"network_name": c.NetworkName, "receive_address": c.ReceiveAddress, "update_by": c.UpdateBy}) | ||||
| 	if err = db.Error; err != nil { | ||||
| 		e.Log.Errorf("WmNetworkService Save error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	if db.RowsAffected == 0 { | ||||
| 		return errors.New("无权更新该数据") | ||||
| 	} | ||||
|  | ||||
| 	//重置缓存 | ||||
| 	e.ReCache() | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (e *WmNetwork) ReCache() { | ||||
| 	var datas []models.WmNetwork | ||||
| 	items := make([]string, 0) | ||||
|  | ||||
| 	if err := e.Orm.Find(&datas).Error; err != nil { | ||||
| 		e.Log.Errorf("db error:%s", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	for _, v := range datas { | ||||
| 		contentByte, _ := json.Marshal(v) | ||||
|  | ||||
| 		if len(contentByte) > 0 { | ||||
| 			items = append(items, string(contentByte)) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(items) > 0 { | ||||
| 		helper.DefaultRedis.SetListCache(rediskey.NetWorks, 0, items...) | ||||
| 	} else { | ||||
| 		helper.DefaultRedis.DeleteString(rediskey.NetWorks) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Remove 删除WmNetwork | ||||
| func (e *WmNetwork) Remove(d *dto.WmNetworkDeleteReq, p *actions.DataPermission) error { | ||||
| 	var data models.WmNetwork | ||||
|  | ||||
| 	db := e.Orm.Model(&data). | ||||
| 		Scopes( | ||||
| 			actions.Permission(data.TableName(), p), | ||||
| 		).Delete(&data, d.GetId()) | ||||
| 	if err := db.Error; err != nil { | ||||
| 		e.Log.Errorf("Service RemoveWmNetwork error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	if db.RowsAffected == 0 { | ||||
| 		return errors.New("无权删除该数据") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // GetAll 获取所有WmNetwork | ||||
| func (e *WmNetwork) GetAll() ([]models.WmNetwork, error) { | ||||
| 	vals, _ := helper.DefaultRedis.GetAllList(rediskey.NetWorks) | ||||
| 	result := make([]models.WmNetwork, 0) | ||||
|  | ||||
| 	if len(vals) > 0 { | ||||
| 		for _, v := range vals { | ||||
| 			var item models.WmNetwork | ||||
| 			_ = json.Unmarshal([]byte(v), &item) | ||||
|  | ||||
| 			if item.Id > 0 { | ||||
| 				result = append(result, item) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(result) == 0 { | ||||
| 		if err := e.Orm.Model(&models.WmNetwork{}).Find(&result).Error; err != nil { | ||||
| 			e.Log.Errorf("db error:%s", err) | ||||
| 			return result, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return result, nil | ||||
| } | ||||
							
								
								
									
										234
									
								
								app/admin/service/wm_token.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								app/admin/service/wm_token.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,234 @@ | ||||
| package service | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"github.com/bytedance/sonic" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/service" | ||||
| 	"gorm.io/gorm" | ||||
|  | ||||
| 	"go-admin/app/admin/models" | ||||
| 	"go-admin/app/admin/service/dto" | ||||
| 	"go-admin/common/actions" | ||||
| 	cDto "go-admin/common/dto" | ||||
| 	"go-admin/common/rediskey" | ||||
| 	helper "go-admin/utils/redishelper" | ||||
| ) | ||||
|  | ||||
| type WmToken struct { | ||||
| 	service.Service | ||||
| } | ||||
|  | ||||
| // GetPage 获取WmToken列表 | ||||
| func (e *WmToken) GetPage(c *dto.WmTokenGetPageReq, p *actions.DataPermission, list *[]models.WmToken, count *int64) error { | ||||
| 	var err error | ||||
| 	var data models.WmToken | ||||
|  | ||||
| 	err = e.Orm.Model(&data). | ||||
| 		Scopes( | ||||
| 			cDto.MakeCondition(c.GetNeedSearch()), | ||||
| 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | ||||
| 			actions.Permission(data.TableName(), p), | ||||
| 		). | ||||
| 		Find(list).Limit(-1).Offset(-1). | ||||
| 		Count(count).Error | ||||
| 	if err != nil { | ||||
| 		e.Log.Errorf("WmTokenService GetPage error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Get 获取WmToken对象 | ||||
| func (e *WmToken) Get(d *dto.WmTokenGetReq, p *actions.DataPermission, model *models.WmToken) error { | ||||
| 	var data models.WmToken | ||||
|  | ||||
| 	err := e.Orm.Model(&data). | ||||
| 		Scopes( | ||||
| 			actions.Permission(data.TableName(), p), | ||||
| 		). | ||||
| 		First(model, d.GetId()).Error | ||||
| 	if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { | ||||
| 		err = errors.New("查看对象不存在或无权查看") | ||||
| 		e.Log.Errorf("Service GetWmToken error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	if err != nil { | ||||
| 		e.Log.Errorf("db error:%s", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Insert 创建WmToken对象 | ||||
| func (e *WmToken) Insert(c *dto.WmTokenInsertReq) error { | ||||
| 	var err error | ||||
| 	var data models.WmToken | ||||
| 	c.Generate(&data) | ||||
| 	err = e.Orm.Create(&data).Error | ||||
| 	if err != nil { | ||||
| 		e.Log.Errorf("WmTokenService Insert error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	e.ReCache("") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Update 修改WmToken对象 | ||||
| func (e *WmToken) Update(c *dto.WmTokenUpdateReq, p *actions.DataPermission) error { | ||||
| 	var err error | ||||
| 	var data = models.WmToken{} | ||||
| 	e.Orm.Scopes( | ||||
| 		actions.Permission(data.TableName(), p), | ||||
| 	).First(&data, c.GetId()) | ||||
| 	c.Generate(&data) | ||||
|  | ||||
| 	db := e.Orm.Save(&data) | ||||
| 	if err = db.Error; err != nil { | ||||
| 		e.Log.Errorf("WmTokenService Save error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	if db.RowsAffected == 0 { | ||||
| 		return errors.New("无权更新该数据") | ||||
| 	} | ||||
| 	e.ReCache("") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Remove 删除WmToken | ||||
| func (e *WmToken) Remove(d *dto.WmTokenDeleteReq, p *actions.DataPermission) error { | ||||
| 	var data models.WmToken | ||||
|  | ||||
| 	db := e.Orm.Model(&data). | ||||
| 		Scopes( | ||||
| 			actions.Permission(data.TableName(), p), | ||||
| 		).Delete(&data, d.GetId()) | ||||
| 	if err := db.Error; err != nil { | ||||
| 		e.Log.Errorf("Service RemoveWmToken error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	if db.RowsAffected == 0 { | ||||
| 		return errors.New("无权删除该数据") | ||||
| 	} | ||||
|  | ||||
| 	e.ReCache("") | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // 重置代币缓存 | ||||
| // networkCode 网络code(如果为空则重置所有网络的缓存) | ||||
| func (e *WmToken) ReCache(networkCode string) error { | ||||
| 	var datas []models.WmToken | ||||
| 	mapData := make(map[int][]string) | ||||
| 	query := e.Orm.Model(&models.WmToken{}) | ||||
|  | ||||
| 	if networkCode != "" { | ||||
| 		query.Where("network_id = ?", networkCode) | ||||
| 	} | ||||
|  | ||||
| 	if err := query.Find(&datas).Error; err != nil { | ||||
| 		e.Log.Errorf("Service ReCache error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for _, v := range datas { | ||||
| 		contentByte, _ := json.Marshal(v) | ||||
|  | ||||
| 		if len(contentByte) > 0 { | ||||
| 			mapData[v.NetworkId] = append(mapData[v.NetworkId], string(contentByte)) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for k, v := range mapData { | ||||
| 		key := fmt.Sprintf(rediskey.Tokens, k) | ||||
|  | ||||
| 		if err := helper.DefaultRedis.SetListCache(key, 0, v...); err != nil { | ||||
| 			e.Log.Errorf("Service ReCache key:%s error:%s \r\n", key, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // GetAll 获取所有代币信息 | ||||
| func (e *WmToken) GetAll() ([]models.WmToken, error) { | ||||
| 	result := make([]models.WmToken, 0) | ||||
| 	data := models.WmToken{} | ||||
| 	keys, _ := helper.DefaultRedis.ScanKeys(fmt.Sprintf(rediskey.Tokens, "*")) | ||||
|  | ||||
| 	if keys == nil || len(keys) == 0 { | ||||
| 		if err := e.Orm.Model(data).Find(&result).Error; err != nil { | ||||
| 			e.Log.Errorf("Service GetAll error:%s \r\n", err) | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} else { | ||||
| 		for _, key := range keys { | ||||
| 			tokenList, _ := helper.DefaultRedis.GetAllList(key) | ||||
|  | ||||
| 			for _, token := range tokenList { | ||||
| 				sonic.UnmarshalString(token, &data) | ||||
|  | ||||
| 				if data.Id > 0 { | ||||
| 					result = append(result, data) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return result, nil | ||||
| } | ||||
|  | ||||
| // GetByTokenId 根据networkId和tokenAddress获取代币信息 | ||||
| func (e *WmToken) GetByTokenId(networkId int, tokenAddress string) (models.WmToken, error) { | ||||
| 	key := fmt.Sprintf(rediskey.Tokens, networkId) | ||||
| 	token := models.WmToken{} | ||||
| 	tokens, _ := helper.DefaultRedis.GetAllList(key) | ||||
|  | ||||
| 	for _, v := range tokens { | ||||
| 		var data models.WmToken | ||||
| 		_ = json.Unmarshal([]byte(v), &data) | ||||
| 		if data.TokenAddress == tokenAddress { | ||||
| 			token = data | ||||
| 			return token, nil | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if token.Id == 0 { | ||||
| 		if err := e.Orm.Model(&models.WmToken{}).Where("network_id = ? and token_address = ?", networkId, tokenAddress).First(&token).Error; err != nil { | ||||
| 			e.Log.Errorf("Service GetByTokenId error:%s \r\n", err) | ||||
| 			return models.WmToken{}, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return token, nil | ||||
| } | ||||
|  | ||||
| // GetAutoTransTokens 获取自动转账的代币列表 | ||||
| func (e WmToken) GetAutoTransTokens(netowrkIds []int) ([]models.WmToken, error) { | ||||
| 	tokens := make([]models.WmToken, 0) | ||||
|  | ||||
| 	for _, networkId := range netowrkIds { | ||||
| 		key := fmt.Sprintf(rediskey.Tokens, networkId) | ||||
| 		tokensList, _ := helper.DefaultRedis.GetAllList(key) | ||||
|  | ||||
| 		for _, v := range tokensList { | ||||
| 			var data models.WmToken | ||||
| 			_ = json.Unmarshal([]byte(v), &data) | ||||
| 			if data.IsAuto == 1 { | ||||
| 				tokens = append(tokens, data) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(tokens) == 0 { | ||||
| 		if err := e.Orm.Model(&models.WmToken{}).Where("network_id in (?) and is_auto = ?", netowrkIds, 1).Find(&tokens).Error; err != nil { | ||||
| 			e.Log.Errorf("Service GetAutoTransTokens error:%s \r\n", err) | ||||
| 			return nil, err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return tokens, nil | ||||
| } | ||||
| @ -2,14 +2,21 @@ package service | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"strings" | ||||
|  | ||||
|     "github.com/go-admin-team/go-admin-core/sdk/service" | ||||
| 	"github.com/go-admin-team/go-admin-core/logger" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/service" | ||||
| 	"github.com/shopspring/decimal" | ||||
| 	"gorm.io/gorm" | ||||
|  | ||||
| 	"go-admin/app/admin/models" | ||||
| 	"go-admin/app/admin/service/dto" | ||||
| 	"go-admin/common/actions" | ||||
| 	cDto "go-admin/common/dto" | ||||
| 	"go-admin/config" | ||||
| 	"go-admin/utils/aeshelper" | ||||
| 	"go-admin/utils/ethbalanceofhelper" | ||||
| 	"go-admin/utils/ethtransferhelper" | ||||
| ) | ||||
|  | ||||
| type WmTransfer struct { | ||||
| @ -20,8 +27,17 @@ type WmTransfer struct { | ||||
| func (e *WmTransfer) GetPage(c *dto.WmTransferGetPageReq, p *actions.DataPermission, list *[]models.WmTransfer, count *int64) error { | ||||
| 	var err error | ||||
| 	var data models.WmTransfer | ||||
| 	query := e.Orm.Model(&data) | ||||
|  | ||||
| 	err = e.Orm.Model(&data). | ||||
| 	if c.Type > 0 { | ||||
| 		query.Where("type =?", c.Type) | ||||
| 	} | ||||
|  | ||||
| 	if c.TransferType > 0 { | ||||
| 		query.Where("transfer_type =?", c.TransferType) | ||||
| 	} | ||||
|  | ||||
| 	err = query. | ||||
| 		Scopes( | ||||
| 			cDto.MakeCondition(c.GetNeedSearch()), | ||||
| 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | ||||
| @ -33,9 +49,47 @@ func (e *WmTransfer) GetPage(c *dto.WmTransferGetPageReq, p *actions.DataPermiss | ||||
| 		e.Log.Errorf("WmTransferService GetPage error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	transferIds := make([]int, 0) | ||||
| 	for _, item := range *list { | ||||
| 		transferIds = append(transferIds, item.Id) | ||||
| 	} | ||||
|  | ||||
| 	itemData, _ := e.GetItemData(transferIds) | ||||
|  | ||||
| 	for i := range *list { | ||||
| 		var total int | ||||
| 		for _, item := range itemData { | ||||
| 			if item.TransferId == (*list)[i].Id { | ||||
| 				total += item.Total | ||||
|  | ||||
| 				switch item.Status { | ||||
| 				case 1: | ||||
| 					(*list)[i].Pending = item.Total | ||||
| 				case 2: | ||||
| 					(*list)[i].Sucess = item.Total | ||||
| 				case 3: | ||||
| 					(*list)[i].Fail = item.Total | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		(*list)[i].Total = total | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // GetItemData 获取转账明细数据 | ||||
| func (e *WmTransfer) GetItemData(transIds []int) ([]dto.TransItemData, error) { | ||||
| 	result := make([]dto.TransItemData, 0) | ||||
| 	if err := e.Orm.Raw("select t.transfer_id as TransferId,t.`status`,count(*) as total from wm_transfer_item t where t.transfer_id in ? group by t.transfer_id,t.`status`", transIds).Scan(&result).Error; err != nil { | ||||
| 		e.Log.Errorf("WmTransferService GetItemData error:%s \r\n", err) | ||||
| 	} | ||||
|  | ||||
| 	return result, nil | ||||
| } | ||||
|  | ||||
| // Get 获取WmTransfer对象 | ||||
| func (e *WmTransfer) Get(d *dto.WmTransferGetReq, p *actions.DataPermission, model *models.WmTransfer) error { | ||||
| 	var data models.WmTransfer | ||||
| @ -59,35 +113,151 @@ func (e *WmTransfer) Get(d *dto.WmTransferGetReq, p *actions.DataPermission, mod | ||||
|  | ||||
| // Insert 创建WmTransfer对象 | ||||
| func (e *WmTransfer) Insert(c *dto.WmTransferInsertReq) error { | ||||
|     var err error | ||||
|     var data models.WmTransfer | ||||
|     c.Generate(&data) | ||||
| 	err = e.Orm.Create(&data).Error | ||||
| 	var err error | ||||
| 	var data models.WmTransfer | ||||
| 	c.Generate(&data) | ||||
| 	caches := make([]models.WmTransferItem, 0) | ||||
| 	tokenService := WmToken{Service: e.Service} | ||||
| 	token, _ := tokenService.GetByTokenId(c.NetworkId, c.TokenAddress) | ||||
|  | ||||
| 	if token.Id == 0 { | ||||
| 		return errors.New("代币不存在") | ||||
| 	} | ||||
|  | ||||
| 	if c.TransferType == 1 { | ||||
| 		items := strings.Fields(c.Content) | ||||
| 		_, fromAddress, _ := ethtransferhelper.GetAddressFromPrivateKey(c.PrivateKey) | ||||
| 		aesKey := aeshelper.AesEcbEncrypt(c.PrivateKey) | ||||
|  | ||||
| 		if c.TypeValue.Cmp(decimal.Zero) <= 0 { | ||||
| 			return errors.New("比例值错误必须大于0") | ||||
| 		} | ||||
|  | ||||
| 		amount, err := e.getPrivateKeyAmount(c.PrivateKey, token.TokenAddress, token.Decimals, c.Type, c.TypeValue) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		if amount.Cmp(decimal.NewFromInt(0)) <= 0 { | ||||
| 			return errors.New("转账金额错误必须大于0") | ||||
| 		} | ||||
|  | ||||
| 		for _, item := range items { | ||||
| 			if item == "" { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			cache := models.WmTransferItem{} | ||||
| 			cache.NetworkId = c.NetworkId | ||||
| 			cache.PrivateKey = aesKey | ||||
| 			cache.FromAddress = fromAddress.String() | ||||
| 			cache.ToAddress = item | ||||
| 			cache.Type = c.Type | ||||
| 			cache.TypeValue = c.TypeValue | ||||
| 			cache.Amount = amount | ||||
|  | ||||
| 			caches = append(caches, cache) | ||||
| 		} | ||||
| 	} else { | ||||
| 		items := strings.Fields(c.PrivateKey) | ||||
|  | ||||
| 		for _, item := range items { | ||||
| 			if item == "" { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			amount, err := e.getPrivateKeyAmount(item, token.TokenAddress, token.Decimals, c.Type, c.TypeValue) | ||||
|  | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|  | ||||
| 			_, fromAddress, _ := ethtransferhelper.GetAddressFromPrivateKey(item) | ||||
| 			cache := models.WmTransferItem{} | ||||
| 			cache.NetworkId = c.NetworkId | ||||
| 			cache.PrivateKey = aeshelper.AesEcbEncrypt(item) | ||||
| 			cache.FromAddress = fromAddress.String() | ||||
| 			cache.ToAddress = c.Content | ||||
| 			cache.Type = c.Type | ||||
| 			cache.TypeValue = c.TypeValue | ||||
| 			cache.Amount = amount | ||||
|  | ||||
| 			caches = append(caches, cache) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	err = e.Orm.Transaction(func(tx *gorm.DB) error { | ||||
| 		if err := tx.Create(&data).Error; err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		for i := range caches { | ||||
| 			caches[i].TransferId = data.Id | ||||
| 			caches[i].IsAuto = 2 | ||||
| 			caches[i].TokenAddress = c.TokenAddress | ||||
| 		} | ||||
|  | ||||
| 		if err := tx.CreateInBatches(&caches, 100).Error; err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		return nil | ||||
| 	}) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		e.Log.Errorf("WmTransferService Insert error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	go e.RunTransferJob(caches) | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // 获取金额 | ||||
| func (e *WmTransfer) getPrivateKeyAmount(privateKey, tokenAddress string, decimals int, reqType int, typeValue decimal.Decimal) (decimal.Decimal, error) { | ||||
| 	var amount decimal.Decimal | ||||
| 	if reqType == 1 { | ||||
| 		_, accountAddress, _ := ethtransferhelper.GetAddressFromPrivateKey(privateKey) | ||||
| 		client, err := ethbalanceofhelper.EthClientWithProxy(config.ExtConfig.ApiEndpoint, config.ExtConfig.ProxyUrl) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return amount, errors.New("连接区块链失败") | ||||
| 		} | ||||
|  | ||||
| 		amount, err = ethbalanceofhelper.GetERC20Balance(client, tokenAddress, accountAddress.String(), decimals) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return amount, errors.New("查询主账号余额失败") | ||||
| 		} | ||||
|  | ||||
| 		amount = amount.Mul(typeValue.Div(decimal.NewFromInt(100))).Truncate(int32(decimals)) | ||||
| 	} else { | ||||
| 		amount = typeValue | ||||
| 	} | ||||
|  | ||||
| 	return amount, nil | ||||
| } | ||||
|  | ||||
| // Update 修改WmTransfer对象 | ||||
| func (e *WmTransfer) Update(c *dto.WmTransferUpdateReq, p *actions.DataPermission) error { | ||||
|     var err error | ||||
|     var data = models.WmTransfer{} | ||||
|     e.Orm.Scopes( | ||||
|             actions.Permission(data.TableName(), p), | ||||
|         ).First(&data, c.GetId()) | ||||
|     c.Generate(&data) | ||||
| 	var err error | ||||
| 	var data = models.WmTransfer{} | ||||
| 	e.Orm.Scopes( | ||||
| 		actions.Permission(data.TableName(), p), | ||||
| 	).First(&data, c.GetId()) | ||||
| 	c.Generate(&data) | ||||
|  | ||||
|     db := e.Orm.Save(&data) | ||||
|     if err = db.Error; err != nil { | ||||
|         e.Log.Errorf("WmTransferService Save error:%s \r\n", err) | ||||
|         return err | ||||
|     } | ||||
|     if db.RowsAffected == 0 { | ||||
|         return errors.New("无权更新该数据") | ||||
|     } | ||||
|     return nil | ||||
| 	db := e.Orm.Save(&data) | ||||
| 	if err = db.Error; err != nil { | ||||
| 		e.Log.Errorf("WmTransferService Save error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	if db.RowsAffected == 0 { | ||||
| 		return errors.New("无权更新该数据") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Remove 删除WmTransfer | ||||
| @ -99,11 +269,119 @@ func (e *WmTransfer) Remove(d *dto.WmTransferDeleteReq, p *actions.DataPermissio | ||||
| 			actions.Permission(data.TableName(), p), | ||||
| 		).Delete(&data, d.GetId()) | ||||
| 	if err := db.Error; err != nil { | ||||
|         e.Log.Errorf("Service RemoveWmTransfer error:%s \r\n", err) | ||||
|         return err | ||||
|     } | ||||
|     if db.RowsAffected == 0 { | ||||
|         return errors.New("无权删除该数据") | ||||
|     } | ||||
| 		e.Log.Errorf("Service RemoveWmTransfer error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	if db.RowsAffected == 0 { | ||||
| 		return errors.New("无权删除该数据") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // RunTransferJob 运行转账任务 | ||||
| func (e *WmTransfer) RunTransferJob(items []models.WmTransferItem) error { | ||||
| 	defer func() { | ||||
| 		if r := recover(); r != nil { | ||||
| 			logger.Error("RunTransferJob panic", r) | ||||
|  | ||||
| 			if err2 := e.Orm.Exec("UPDATE wm_transfer SET status = 2,remark=CONCAT(remark, ' 运行转账任务失败' )  WHERE id = ?", items[0].TransferId).Error; err2 != nil { | ||||
| 				logger.Error("更新转账记录失败", err2) | ||||
| 			} | ||||
| 		} | ||||
| 	}() | ||||
|  | ||||
| 	client, err := ethbalanceofhelper.EthClientWithProxy(config.ExtConfig.ApiEndpoint, config.ExtConfig.ProxyUrl) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		if err2 := e.Orm.Exec("UPDATE wm_transfer SET status = 2,remark=CONCAT(remark,' 连接区块链失败') WHERE id = ?", items[0].TransferId).Error; err2 != nil { | ||||
| 			logger.Error("更新转账记录失败", err2) | ||||
| 		} | ||||
| 		return errors.New("连接区块链失败") | ||||
| 	} | ||||
|  | ||||
| 	for _, item := range items { | ||||
| 		if item.Amount.Cmp(decimal.Zero) <= 0 { | ||||
| 			if err2 := e.Orm.Model(item).Updates(map[string]interface{}{"status": 2, "remark": "转账金额不能为0"}).Error; err2 != nil { | ||||
| 				logger.Error("更新转账记录失败", err2) | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		privateKey := aeshelper.AesEcbDecrypt(item.PrivateKey) | ||||
| 		privateKey = strings.Replace(privateKey, "0x", "", 1) | ||||
| 		trans, err := ethtransferhelper.TransferErc20(client, privateKey, item.TokenAddress, item.ToAddress, item.Amount, uint8(item.Decimals)) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			var hash string | ||||
|  | ||||
| 			if trans != nil { | ||||
| 				hash = trans.Hash().String() | ||||
| 			} | ||||
|  | ||||
| 			if err2 := e.Orm.Model(item).Updates(map[string]interface{}{"status": 3, "hash": hash, "remark": err.Error()}).Error; err2 != nil { | ||||
| 				logger.Error("更新转账记录失败", err2) | ||||
| 			} | ||||
| 		} else { | ||||
| 			if err2 := e.Orm.Model(item).Updates(map[string]interface{}{"status": 1, "hash": trans.Hash().String(), "remark": "发起交易"}).Error; err2 != nil { | ||||
| 				logger.Error("更新转账记录失败", err2) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // CheckHashStatus 检查转账hash状态 | ||||
| func (e *WmTransfer) CheckHashStatus() error { | ||||
| 	var datas []models.WmTransferItem | ||||
| 	err := e.Orm.Model(&models.WmTransferItem{}).Select("id,hash").Where("status = 1 and hash <> ''").Find(&datas).Error | ||||
| 	if err != nil { | ||||
| 		return errors.New("查询转账记录失败") | ||||
| 	} | ||||
|  | ||||
| 	client, err := ethbalanceofhelper.EthClientWithProxy(config.ExtConfig.ApiEndpoint, config.ExtConfig.ProxyUrl) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return errors.New("连接区块链失败") | ||||
| 	} | ||||
|  | ||||
| 	for _, item := range datas { | ||||
| 		status, err := ethtransferhelper.GetTransactionByHash(client, item.Hash) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			e.Log.Errorf("查询交易失败:%s error:%v", item.Hash, err) | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		if status == 1 { | ||||
| 			item.Status = 2 | ||||
| 			item.Remark = "交易成功" | ||||
| 		} else { | ||||
| 			item.Status = 3 | ||||
| 			item.Remark = "交易失败" | ||||
| 		} | ||||
|  | ||||
| 		if err := e.Orm.Model(item).Updates(map[string]interface{}{"status": item.Status, "remark": item.Remark}).Error; err != nil { | ||||
| 			e.Log.Errorf("更新转账记录失败:%s error:%v", item.Hash, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // 清理数据 | ||||
| func (e *WmTransfer) ClearAll() error { | ||||
| 	err := e.Orm.Transaction(func(tx *gorm.DB) error { | ||||
| 		if err1 := tx.Exec("truncate table wm_transfer_item").Error; err1 != nil { | ||||
| 			return err1 | ||||
| 		} | ||||
|  | ||||
| 		if err2 := tx.Exec("truncate table wm_transfer").Error; err2 != nil { | ||||
| 			return err2 | ||||
| 		} | ||||
|  | ||||
| 		return nil | ||||
| 	}) | ||||
|  | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| @ -3,13 +3,17 @@ package service | ||||
| import ( | ||||
| 	"errors" | ||||
|  | ||||
|     "github.com/go-admin-team/go-admin-core/sdk/service" | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/service" | ||||
| 	"gorm.io/gorm" | ||||
|  | ||||
| 	"go-admin/app/admin/models" | ||||
| 	"go-admin/app/admin/service/dto" | ||||
| 	"go-admin/common/actions" | ||||
| 	cDto "go-admin/common/dto" | ||||
| 	"go-admin/utils/aeshelper" | ||||
| 	"go-admin/utils/excelhelper" | ||||
| 	"go-admin/utils/stringhelper" | ||||
| ) | ||||
|  | ||||
| type WmTransferItem struct { | ||||
| @ -33,9 +37,144 @@ func (e *WmTransferItem) GetPage(c *dto.WmTransferItemGetPageReq, p *actions.Dat | ||||
| 		e.Log.Errorf("WmTransferItemService GetPage error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for i := 0; i < len(*list); i++ { | ||||
| 		(*list)[i].PrivateKey = stringhelper.DesensitizeWalletAddress(aeshelper.AesEcbDecrypt((*list)[i].PrivateKey)) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // GetAutoTransferLogPage 获取自动转账日志列表 | ||||
| func (e *WmTransferItem) GetAutoTransferLogPage(c *dto.WmTransferItemAutoLogPageReq, p *actions.DataPermission, list *[]dto.WmTransferItemResp, count *int64) error { | ||||
| 	var err error | ||||
| 	var data models.WmTransferItem | ||||
| 	var datas []models.WmTransferItem | ||||
|  | ||||
| 	err = e.Orm.Model(&data). | ||||
| 		Where("is_auto = 1"). | ||||
| 		Scopes( | ||||
| 			cDto.MakeCondition(c.GetNeedSearch()), | ||||
| 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | ||||
| 			actions.Permission(data.TableName(), p), | ||||
| 		). | ||||
| 		Find(&datas).Limit(-1).Offset(-1). | ||||
| 		Count(count).Error | ||||
| 	if err != nil { | ||||
| 		e.Log.Errorf("WmTransferItemService GetPage error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	networkService := WmNetwork{Service: e.Service} | ||||
| 	networks, _ := networkService.GetAll() | ||||
| 	tokenService := WmToken{Service: e.Service} | ||||
| 	tokens, _ := tokenService.GetAll() | ||||
|  | ||||
| 	for i := 0; i < len(datas); i++ { | ||||
| 		item := dto.WmTransferItemResp{} | ||||
| 		item.Id = datas[i].Id | ||||
| 		item.PrivateKey = stringhelper.DesensitizeWalletAddress(aeshelper.AesEcbDecrypt(datas[i].PrivateKey)) | ||||
| 		item.FromAddress = datas[i].FromAddress | ||||
| 		item.ToAddress = datas[i].ToAddress | ||||
| 		item.TokenAddress = datas[i].TokenAddress | ||||
| 		item.Amount = datas[i].Amount | ||||
| 		item.Status = datas[i].Status | ||||
| 		item.Remark = datas[i].Remark | ||||
| 		item.Type = datas[i].Type | ||||
| 		item.TypeValue = datas[i].TypeValue | ||||
| 		item.Hash = datas[i].Hash | ||||
| 		item.CreateAt = datas[i].CreatedAt | ||||
|  | ||||
| 		for _, network := range networks { | ||||
| 			if network.Id == datas[i].NetworkId { | ||||
| 				item.NetworkName = network.NetworkName | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		for _, token := range tokens { | ||||
| 			if token.NetworkId == datas[i].NetworkId && token.TokenAddress == datas[i].TokenAddress { | ||||
| 				item.TokenName = token.TokenName | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		*list = append(*list, item) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // 导出自动转账日志 | ||||
| func (e *WmTransferItem) ExportAutoLog(req *dto.WmTransferItemAutoLogPageReq, c *gin.Context) error { | ||||
| 	datas := make([]models.WmTransferItem, 0) | ||||
| 	var err error | ||||
| 	var data models.WmTransferItem | ||||
| 	exportDatas := make([]dto.WmTransferItemResp, 0) | ||||
|  | ||||
| 	err = e.Orm.Model(&data). | ||||
| 		Where("is_auto = 1"). | ||||
| 		Scopes( | ||||
| 			cDto.MakeCondition(req.GetNeedSearch()), | ||||
| 		). | ||||
| 		Find(&datas).Error | ||||
| 	if err != nil { | ||||
| 		e.Log.Errorf("Service ExportExcel error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	networkService := WmNetwork{Service: e.Service} | ||||
| 	networks, _ := networkService.GetAll() | ||||
| 	tokenService := WmToken{Service: e.Service} | ||||
| 	tokens, _ := tokenService.GetAll() | ||||
|  | ||||
| 	for i := 0; i < len(datas); i++ { | ||||
| 		(datas)[i].PrivateKey = stringhelper.DesensitizeWalletAddress(aeshelper.AesEcbDecrypt((datas)[i].PrivateKey)) | ||||
| 		exportData := dto.WmTransferItemResp{ | ||||
| 			PrivateKey:   (datas)[i].PrivateKey, | ||||
| 			TokenAddress: (datas)[i].TokenAddress, | ||||
| 			FromAddress:  (datas)[i].FromAddress, | ||||
| 			ToAddress:    (datas)[i].ToAddress, | ||||
| 			Amount:       (datas)[i].Amount, | ||||
| 			Hash:         (datas)[i].Hash, | ||||
| 			Remark:       (datas)[i].Remark, | ||||
| 			CraeteAtStr:  (datas)[i].CreatedAt.Format("2006-01-02 15:04:05"), | ||||
| 		} | ||||
|  | ||||
| 		for _, network := range networks { | ||||
| 			if network.Id == datas[i].NetworkId { | ||||
| 				exportData.NetworkName = network.NetworkName | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		for _, token := range tokens { | ||||
| 			if token.NetworkId == datas[i].NetworkId && token.TokenAddress == datas[i].TokenAddress { | ||||
| 				exportData.TokenName = token.TokenName | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		switch (datas)[i].Status { | ||||
| 		case 1: | ||||
| 			exportData.StatusName = "交易中" | ||||
| 		case 2: | ||||
| 			exportData.StatusName = "已成功" | ||||
| 		case 3: | ||||
| 			exportData.StatusName = "已失败" | ||||
| 		default: | ||||
| 			exportData.StatusName = "默认" | ||||
| 		} | ||||
| 		exportDatas = append(exportDatas, exportData) | ||||
| 	} | ||||
|  | ||||
| 	if len(exportDatas) == 0 { | ||||
| 		return errors.New("无数据") | ||||
| 	} | ||||
|  | ||||
| 	return excelhelper.ExportExcel(c, "自动转账明细", exportDatas, []string{}) | ||||
| } | ||||
|  | ||||
| // Get 获取WmTransferItem对象 | ||||
| func (e *WmTransferItem) Get(d *dto.WmTransferItemGetReq, p *actions.DataPermission, model *models.WmTransferItem) error { | ||||
| 	var data models.WmTransferItem | ||||
| @ -59,9 +198,9 @@ func (e *WmTransferItem) Get(d *dto.WmTransferItemGetReq, p *actions.DataPermiss | ||||
|  | ||||
| // Insert 创建WmTransferItem对象 | ||||
| func (e *WmTransferItem) Insert(c *dto.WmTransferItemInsertReq) error { | ||||
|     var err error | ||||
|     var data models.WmTransferItem | ||||
|     c.Generate(&data) | ||||
| 	var err error | ||||
| 	var data models.WmTransferItem | ||||
| 	c.Generate(&data) | ||||
| 	err = e.Orm.Create(&data).Error | ||||
| 	if err != nil { | ||||
| 		e.Log.Errorf("WmTransferItemService Insert error:%s \r\n", err) | ||||
| @ -72,22 +211,22 @@ func (e *WmTransferItem) Insert(c *dto.WmTransferItemInsertReq) error { | ||||
|  | ||||
| // Update 修改WmTransferItem对象 | ||||
| func (e *WmTransferItem) Update(c *dto.WmTransferItemUpdateReq, p *actions.DataPermission) error { | ||||
|     var err error | ||||
|     var data = models.WmTransferItem{} | ||||
|     e.Orm.Scopes( | ||||
|             actions.Permission(data.TableName(), p), | ||||
|         ).First(&data, c.GetId()) | ||||
|     c.Generate(&data) | ||||
| 	var err error | ||||
| 	var data = models.WmTransferItem{} | ||||
| 	e.Orm.Scopes( | ||||
| 		actions.Permission(data.TableName(), p), | ||||
| 	).First(&data, c.GetId()) | ||||
| 	c.Generate(&data) | ||||
|  | ||||
|     db := e.Orm.Save(&data) | ||||
|     if err = db.Error; err != nil { | ||||
|         e.Log.Errorf("WmTransferItemService Save error:%s \r\n", err) | ||||
|         return err | ||||
|     } | ||||
|     if db.RowsAffected == 0 { | ||||
|         return errors.New("无权更新该数据") | ||||
|     } | ||||
|     return nil | ||||
| 	db := e.Orm.Save(&data) | ||||
| 	if err = db.Error; err != nil { | ||||
| 		e.Log.Errorf("WmTransferItemService Save error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	if db.RowsAffected == 0 { | ||||
| 		return errors.New("无权更新该数据") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Remove 删除WmTransferItem | ||||
| @ -99,11 +238,55 @@ func (e *WmTransferItem) Remove(d *dto.WmTransferItemDeleteReq, p *actions.DataP | ||||
| 			actions.Permission(data.TableName(), p), | ||||
| 		).Delete(&data, d.GetId()) | ||||
| 	if err := db.Error; err != nil { | ||||
|         e.Log.Errorf("Service RemoveWmTransferItem error:%s \r\n", err) | ||||
|         return err | ||||
|     } | ||||
|     if db.RowsAffected == 0 { | ||||
|         return errors.New("无权删除该数据") | ||||
|     } | ||||
| 		e.Log.Errorf("Service RemoveWmTransferItem error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	if db.RowsAffected == 0 { | ||||
| 		return errors.New("无权删除该数据") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Export 导出WmTransferItem | ||||
| func (e *WmTransferItem) ExportExcel(req *dto.WmTransferItemExportReq, p *actions.DataPermission, c *gin.Context) error { | ||||
| 	datas := make([]models.WmTransferItem, 0) | ||||
| 	var err error | ||||
| 	var data models.WmTransferItem | ||||
| 	exportDatas := make([]dto.WmTransferItemExportData, 0) | ||||
|  | ||||
| 	if err = e.Orm.Model(&data).Where("transfer_id = ?", req.TransferId).Find(&datas).Error; err != nil { | ||||
| 		e.Log.Errorf("Service ExportExcel error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for i := 0; i < len(datas); i++ { | ||||
| 		(datas)[i].PrivateKey = stringhelper.DesensitizeWalletAddress(aeshelper.AesEcbDecrypt((datas)[i].PrivateKey)) | ||||
| 		exportData := dto.WmTransferItemExportData{ | ||||
| 			PrivateKey:   (datas)[i].PrivateKey, | ||||
| 			TokenAddress: (datas)[i].TokenAddress, | ||||
| 			FromAddress:  (datas)[i].FromAddress, | ||||
| 			ToAddress:    (datas)[i].ToAddress, | ||||
| 			Amount:       (datas)[i].Amount, | ||||
| 			TxHash:       (datas)[i].Hash, | ||||
| 			CreateTime:   (datas)[i].CreatedAt.Format("2006-01-02 15:04:05"), | ||||
| 		} | ||||
|  | ||||
| 		switch (datas)[i].Status { | ||||
| 		case 1: | ||||
| 			exportData.Status = "交易中" | ||||
| 		case 2: | ||||
| 			exportData.Status = "已成功" | ||||
| 		case 3: | ||||
| 			exportData.Status = "已失败" | ||||
| 		default: | ||||
| 			exportData.Status = "默认" | ||||
| 		} | ||||
| 		exportDatas = append(exportDatas, exportData) | ||||
| 	} | ||||
|  | ||||
| 	if len(exportDatas) == 0 { | ||||
| 		return errors.New("无数据") | ||||
| 	} | ||||
|  | ||||
| 	return excelhelper.ExportExcel(c, "转账明细", exportDatas, []string{}) | ||||
| } | ||||
|  | ||||
| @ -5,9 +5,9 @@ import ( | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/service" | ||||
| 	"github.com/shopspring/decimal" | ||||
| 	"gorm.io/gorm" | ||||
|  | ||||
| 	"go-admin/abis/ethereumabi" | ||||
| 	"go-admin/app/admin/models" | ||||
| 	"go-admin/app/admin/service/dto" | ||||
| 	"go-admin/common/actions" | ||||
| @ -141,6 +141,9 @@ func (e *WmWalletInfo) Remove(d *dto.WmWalletInfoDeleteReq, p *actions.DataPermi | ||||
| // ScheduledTask 定时任务 | ||||
| func (e *WmWalletInfo) ScheduledTask() error { | ||||
| 	var datas []models.WmWalletInfo | ||||
| 	transferItems := make([]models.WmTransferItem, 0) | ||||
| 	networkService := WmNetwork{Service: e.Service} | ||||
| 	tokenService := WmToken{Service: e.Service} | ||||
|  | ||||
| 	if err := e.Orm.Model(models.WmWalletInfo{}).Find(&datas).Error; err != nil { | ||||
| 		e.Log.Errorf("db error:%s", err) | ||||
| @ -154,21 +157,91 @@ func (e *WmWalletInfo) ScheduledTask() error { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for i := range datas { | ||||
| 		amount, err := ethbalanceofhelper.GetERC20Balance(client, ethereumabi.USDCErc20, datas[i].Address) | ||||
| 	networkIds := make([]int, 0) | ||||
| 	networks, _ := networkService.GetAll() | ||||
| 	networkMap := make(map[int]models.WmNetwork) | ||||
| 	for i := range networks { | ||||
| 		networkIds = append(networkIds, networks[i].Id) | ||||
| 		networkMap[networks[i].Id] = networks[i] | ||||
| 	} | ||||
| 	autoTokens, _ := tokenService.GetAutoTransTokens(networkIds) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			e.Log.Errorf("GetERC20Balance error:%s", err) | ||||
| 	for _, token := range autoTokens { | ||||
| 		network := networkMap[token.NetworkId] | ||||
|  | ||||
| 		if network.Id == 0 { | ||||
| 			continue | ||||
| 		} | ||||
|  | ||||
| 		datas[i].UsdcAmount = amount | ||||
| 		for i := range datas { | ||||
| 			amount, err := ethbalanceofhelper.GetERC20Balance(client, token.TokenAddress, datas[i].Address, token.Decimals) | ||||
|  | ||||
| 		if err := e.Orm.Model(&datas[i]).Update("usdc_amount", amount).Error; err != nil { | ||||
| 			e.Log.Errorf("db error:%s", err) | ||||
| 			continue | ||||
| 			if err != nil { | ||||
| 				e.Log.Errorf("GetERC20Balance error:%s", err) | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			if amount.Cmp(token.TriggerAmount) < 0 { | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			var count int64 | ||||
|  | ||||
| 			if err := e.Orm.Model(models.WmTransferItem{}). | ||||
| 				Where("private_key =? and token_address =? and  to_address =? and status =?", | ||||
| 					datas[i].PrivateKey, token.TokenAddress, network.ReceiveAddress, 1).Count(&count).Error; err != nil { | ||||
| 				e.Log.Errorf("fromAddress:%s, tokenAddress:%s, db error:%s", datas[i].Address, token.TokenAddress, err) | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			if count > 0 { | ||||
| 				e.Log.Errorf("fromAddress:%s, tokenAddress:%s, 交易中暂时不自动转账", datas[i].Address, token.TokenAddress) | ||||
| 				continue | ||||
| 			} | ||||
|  | ||||
| 			switch { | ||||
| 			case token.TransType == 1 && token.TransValue.Cmp(decimal.Zero) > 0: | ||||
| 				amount = amount.Mul(token.TransValue.Div(decimal.NewFromInt(100))).Truncate(int32(token.Decimals)) | ||||
| 			case token.TransType == 2 && token.TransValue.Cmp(decimal.Zero) > 0: | ||||
| 				amount = token.TransValue.Truncate(int32(token.Decimals)) | ||||
| 			} | ||||
|  | ||||
| 			//todo: 自动转账 | ||||
| 			transferItems = append(transferItems, models.WmTransferItem{ | ||||
| 				IsAuto:       1, | ||||
| 				NetworkId:    network.Id, | ||||
| 				TokenAddress: token.TokenAddress, | ||||
| 				FromAddress:  datas[i].Address, | ||||
| 				ToAddress:    network.ReceiveAddress, | ||||
| 				Amount:       amount, | ||||
| 				Decimals:     token.Decimals, | ||||
| 				Type:         token.TransType, | ||||
| 				TypeValue:    token.TransValue, | ||||
| 				PrivateKey:   datas[i].PrivateKey, | ||||
| 				Status:       0, | ||||
| 				Remark:       "自动转账", | ||||
| 			}) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(transferItems) > 0 { | ||||
| 		if err := e.Orm.CreateInBatches(transferItems, 100).Error; err != nil { | ||||
| 			e.Log.Errorf("定时转账保存数据库失败 error:%s", err) | ||||
| 			return err | ||||
| 		} | ||||
|  | ||||
| 		transService := WmTransfer{Service: e.Service} | ||||
| 		if err := transService.RunTransferJob(transferItems); err != nil { | ||||
| 			e.Log.Errorf("定时转账执行失败 error:%s", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // ClearAll 清空表数据 | ||||
| func (e *WmWalletInfo) ClearAll() error { | ||||
| 	err := e.Orm.Exec("TRUNCATE TABLE wm_wallet_info;").Error | ||||
|  | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| @ -10,7 +10,9 @@ import ( | ||||
| // 字典 key 可以配置到 自动任务 调用目标 中; | ||||
| func InitJob() { | ||||
| 	jobList = map[string]JobExec{ | ||||
| 		"ExamplesOne": ExamplesOne{}, | ||||
| 		"ExamplesOne":       ExamplesOne{}, | ||||
| 		"TransferStatusJob": TransferStatusJob{}, | ||||
| 		"TransferJob":       TransferJob{}, | ||||
| 		// ... | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -10,6 +10,8 @@ import ( | ||||
|  | ||||
| type TransferJob struct{} | ||||
|  | ||||
| type TransferStatusJob struct{} | ||||
|  | ||||
| // 定期转账 | ||||
| func (t TransferJob) Exec(arg interface{}) error { | ||||
| 	walletService := service.WmWalletInfo{} | ||||
| @ -29,3 +31,12 @@ func getDefaultDb() *gorm.DB { | ||||
| 	} | ||||
| 	return db | ||||
| } | ||||
|  | ||||
| // 定时查询交易状态 | ||||
| func (t TransferStatusJob) Exec(arg interface{}) error { | ||||
| 	walletService := service.WmTransfer{} | ||||
| 	walletService.Orm = getDefaultDb() | ||||
| 	walletService.Log = logger.NewHelper(logger.DefaultLogger) | ||||
|  | ||||
| 	return walletService.CheckHashStatus() | ||||
| } | ||||
|  | ||||
| @ -2,6 +2,7 @@ package jobs | ||||
|  | ||||
| import ( | ||||
| 	"go-admin/config" | ||||
| 	helper "go-admin/utils/redishelper" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk" | ||||
| @ -17,7 +18,23 @@ func TestTransferJob(t *testing.T) { | ||||
| 	config.ExtConfig.ApiEndpoint = "https://stylish-cool-fire.ethereum-sepolia.quiknode.pro/17572db4c091accfa5dc6faa0c60a805e5173459" | ||||
| 	config.ExtConfig.ProxyUrl = "http://127.0.0.1:7890" | ||||
|  | ||||
| 	helper.InitDefaultRedis("http://127.0.0.1:6379", "", 15) // 初始化配置 | ||||
|  | ||||
| 	job := TransferJob{} | ||||
|  | ||||
| 	job.Exec(nil) | ||||
| } | ||||
|  | ||||
| // 测试状态任务 | ||||
| func TestTransferStatusJob(t *testing.T) { | ||||
| 	dsn := "root:123456@tcp(127.0.0.1:3306)/eth_transfer?charset=utf8mb4&parseTime=True&loc=Local&timeout=1000ms" | ||||
| 	db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{}) | ||||
| 	sdk.Runtime.SetDb("default", db) | ||||
|  | ||||
| 	config.ExtConfig.ApiEndpoint = "https://stylish-cool-fire.ethereum-sepolia.quiknode.pro/17572db4c091accfa5dc6faa0c60a805e5173459" | ||||
| 	config.ExtConfig.ProxyUrl = "http://127.0.0.1:7890" | ||||
|  | ||||
| 	job := TransferStatusJob{} | ||||
|  | ||||
| 	job.Exec(nil) | ||||
| } | ||||
|  | ||||
| @ -3,13 +3,15 @@ package api | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/runtime" | ||||
| 	"log" | ||||
| 	"net/http" | ||||
| 	"os" | ||||
| 	"os/signal" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/go-admin-team/go-admin-core/logger" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/runtime" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"github.com/go-admin-team/go-admin-core/config/source/file" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk" | ||||
| @ -20,6 +22,7 @@ import ( | ||||
|  | ||||
| 	"go-admin/app/admin/models" | ||||
| 	"go-admin/app/admin/router" | ||||
| 	"go-admin/app/admin/service" | ||||
| 	"go-admin/app/jobs" | ||||
| 	"go-admin/common/database" | ||||
| 	"go-admin/common/global" | ||||
| @ -27,6 +30,7 @@ import ( | ||||
| 	"go-admin/common/middleware/handler" | ||||
| 	"go-admin/common/storage" | ||||
| 	ext "go-admin/config" | ||||
| 	helper "go-admin/utils/redishelper" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @ -86,6 +90,16 @@ func run() error { | ||||
| 		f() | ||||
| 	} | ||||
|  | ||||
| 	//初始化redis | ||||
| 	helper.InitDefaultRedis(config.CacheConfig.Redis.Addr, config.CacheConfig.Redis.Password, config.CacheConfig.Redis.DB) | ||||
|  | ||||
| 	if err := helper.DefaultRedis.Ping(); err != nil { | ||||
| 		fmt.Println("初始化redis失败") | ||||
| 		os.Exit(2) | ||||
| 	} | ||||
|  | ||||
| 	initCache() | ||||
|  | ||||
| 	srv := &http.Server{ | ||||
| 		Addr:    fmt.Sprintf("%s:%d", config.ApplicationConfig.Host, config.ApplicationConfig.Port), | ||||
| 		Handler: sdk.Runtime.GetEngine(), | ||||
| @ -184,3 +198,17 @@ func initRouter() { | ||||
| 	common.InitMiddleware(r) | ||||
|  | ||||
| } | ||||
|  | ||||
| // 初始化缓存 | ||||
| func initCache() { | ||||
| 	netWorkService := service.WmNetwork{} | ||||
| 	dbs := sdk.Runtime.GetDb() | ||||
| 	netWorkService.Orm = dbs["*"] | ||||
| 	netWorkService.Log = logger.NewHelper(logger.DefaultLogger) | ||||
| 	tokenService := service.WmToken{} | ||||
| 	tokenService.Orm = netWorkService.Orm | ||||
| 	tokenService.Log = netWorkService.Log | ||||
|  | ||||
| 	netWorkService.ReCache() | ||||
| 	tokenService.ReCache("") | ||||
| } | ||||
|  | ||||
							
								
								
									
										8
									
								
								common/rediskey/prefix_key.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								common/rediskey/prefix_key.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | ||||
| package rediskey | ||||
|  | ||||
| const ( | ||||
| 	//区块链网络列表 LIST | ||||
| 	NetWorks = "network" | ||||
| 	//代币信息 LIST {networkCode} | ||||
| 	Tokens = "token:%v" | ||||
| ) | ||||
| @ -50,6 +50,7 @@ settings: | ||||
|       name: data | ||||
|      | ||||
|     apiEndpoint: https://stylish-cool-fire.ethereum-sepolia.quiknode.pro/17572db4c091accfa5dc6faa0c60a805e5173459 | ||||
|     proxyUrl: http://127.0.0.1:7890 | ||||
|   cache: | ||||
|     redis: | ||||
|      addr: 127.0.0.1:6379 | ||||
|  | ||||
							
								
								
									
										14
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								go.mod
									
									
									
									
									
								
							| @ -49,12 +49,14 @@ require ( | ||||
| 	github.com/beorn7/perks v1.0.1 // indirect | ||||
| 	github.com/bits-and-blooms/bitset v1.20.0 // indirect | ||||
| 	github.com/bsm/redislock v0.5.0 // indirect | ||||
| 	github.com/bytedance/sonic v1.9.1 // indirect | ||||
| 	github.com/bytedance/sonic v1.13.2 // indirect | ||||
| 	github.com/bytedance/sonic/loader v0.2.4 // indirect | ||||
| 	github.com/casbin/redis-watcher/v2 v2.0.0-20220614104201-0e70bf2be930 // indirect | ||||
| 	github.com/cespare/xxhash/v2 v2.3.0 // indirect | ||||
| 	github.com/chanxuehong/rand v0.0.0-20201110082127-2f19a1bdd973 // indirect | ||||
| 	github.com/chanxuehong/wechat v0.0.0-20201110083048-0180211b69fd // indirect | ||||
| 	github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect | ||||
| 	github.com/cloudwego/base64x v0.1.5 // indirect | ||||
| 	github.com/consensys/bavard v0.1.27 // indirect | ||||
| 	github.com/consensys/gnark-crypto v0.16.0 // indirect | ||||
| 	github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect | ||||
| @ -133,6 +135,8 @@ require ( | ||||
| 	github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a // indirect | ||||
| 	github.com/prometheus/common v0.32.1 // indirect | ||||
| 	github.com/prometheus/procfs v0.7.3 // indirect | ||||
| 	github.com/richardlehane/mscfb v1.0.4 // indirect | ||||
| 	github.com/richardlehane/msoleps v1.0.4 // indirect | ||||
| 	github.com/robinjoseph08/redisqueue/v2 v2.1.0 // indirect | ||||
| 	github.com/russross/blackfriday/v2 v2.1.0 // indirect | ||||
| 	github.com/shamsher31/goimgext v1.0.0 // indirect | ||||
| @ -141,19 +145,23 @@ require ( | ||||
| 	github.com/spf13/cast v1.3.1 // indirect | ||||
| 	github.com/spf13/pflag v1.0.5 // indirect | ||||
| 	github.com/supranational/blst v0.3.14 // indirect | ||||
| 	github.com/tiendc/go-deepcopy v1.6.0 // indirect | ||||
| 	github.com/tklauser/go-sysconf v0.3.12 // indirect | ||||
| 	github.com/tklauser/numcpus v0.6.1 // indirect | ||||
| 	github.com/tsuyoshiwada/go-gitcmd v0.0.0-20180205145712-5f1f5f9475df // indirect | ||||
| 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect | ||||
| 	github.com/ugorji/go/codec v1.2.11 // indirect | ||||
| 	github.com/urfave/cli v1.22.1 // indirect | ||||
| 	github.com/xuri/efp v0.0.1 // indirect | ||||
| 	github.com/xuri/excelize/v2 v2.9.1 // indirect | ||||
| 	github.com/xuri/nfp v0.0.1 // indirect | ||||
| 	github.com/yusufpapurcu/wmi v1.2.2 // indirect | ||||
| 	go.uber.org/atomic v1.6.0 // indirect | ||||
| 	go.uber.org/multierr v1.5.0 // indirect | ||||
| 	go.uber.org/zap v1.15.0 // indirect | ||||
| 	golang.org/x/arch v0.3.0 // indirect | ||||
| 	golang.org/x/image v0.1.0 // indirect | ||||
| 	golang.org/x/net v0.36.0 // indirect | ||||
| 	golang.org/x/image v0.25.0 // indirect | ||||
| 	golang.org/x/net v0.40.0 // indirect | ||||
| 	golang.org/x/sync v0.14.0 // indirect | ||||
| 	golang.org/x/sys v0.33.0 // indirect | ||||
| 	golang.org/x/text v0.25.0 // indirect | ||||
|  | ||||
| @ -4,7 +4,6 @@ import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"go-admin/abis" | ||||
| 	"math/big" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| @ -38,7 +37,11 @@ const erc20ABI = `[ | ||||
| ]` | ||||
|  | ||||
| // GetERC20Balance 查询 ERC-20 代币余额并转换为正常单位 (使用 decimal) | ||||
| func GetERC20Balance(client *ethclient.Client, tokenAbi abis.TokenABI, accountAddress string) (decimal.Decimal, error) { | ||||
| // tokenAddress: 代币合约地址 | ||||
| // accountAddress: 账户地址 | ||||
| // decimals: 代币精度 | ||||
| // 返回值: 代币余额 (decimal.Decimal) | ||||
| func GetERC20Balance(client *ethclient.Client, tokenAddress, accountAddress string, decimals int) (decimal.Decimal, error) { | ||||
| 	// 1. 解析 ABI | ||||
| 	contractABI, err := abi.JSON(strings.NewReader(erc20ABI)) | ||||
| 	if err != nil { | ||||
| @ -51,7 +54,7 @@ func GetERC20Balance(client *ethclient.Client, tokenAbi abis.TokenABI, accountAd | ||||
| 		return decimal.Zero, fmt.Errorf("构造 balanceOf 调用数据失败: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	address := common.HexToAddress(tokenAbi.TestAddress) | ||||
| 	address := common.HexToAddress(tokenAddress) | ||||
| 	// 3. 执行 balanceOf 调用 | ||||
| 	balanceResult, err := client.CallContract(context.Background(), ethereum.CallMsg{ | ||||
| 		To:   &address, | ||||
| @ -74,7 +77,7 @@ func GetERC20Balance(client *ethclient.Client, tokenAbi abis.TokenABI, accountAd | ||||
|  | ||||
| 	// 8. 转换为正常单位 (使用 decimal) | ||||
| 	balanceDecimal := decimal.NewFromBigInt(balance, 0) // Create decimal from big.Int | ||||
| 	decimalFactor := decimal.NewFromInt(10).Pow(decimal.NewFromInt(int64(tokenAbi.Decimals))) | ||||
| 	decimalFactor := decimal.NewFromInt(10).Pow(decimal.NewFromInt(int64(decimals))) | ||||
| 	readableBalance := balanceDecimal.Div(decimalFactor) | ||||
|  | ||||
| 	return readableBalance, nil | ||||
|  | ||||
| @ -6,6 +6,7 @@ import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"math/big" | ||||
| 	"regexp" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/ethereum/go-ethereum" | ||||
| @ -13,21 +14,114 @@ import ( | ||||
| 	"github.com/ethereum/go-ethereum/core/types" | ||||
| 	"github.com/ethereum/go-ethereum/crypto" | ||||
| 	"github.com/ethereum/go-ethereum/ethclient" | ||||
| 	"github.com/shopspring/decimal" | ||||
| 	"golang.org/x/crypto/sha3" | ||||
| ) | ||||
|  | ||||
| // TransferErc20 发送 ERC-20 代币交易。 | ||||
| // tokenaddress: ERC-20 代币的合约地址。 如果为空则转移ETH | ||||
| func TransferErc20( | ||||
| 	client *ethclient.Client, | ||||
| 	fromPrivateKey string, | ||||
| 	tokenAddress string, | ||||
| 	toAddress string, | ||||
| 	tokenAmount decimal.Decimal, | ||||
| 	tokenDecimals uint8) (*types.Transaction, error) { | ||||
| 	switch tokenAddress { | ||||
| 	case "": | ||||
| 		return TransferEth(client, fromPrivateKey, toAddress, tokenAmount) | ||||
| 	default: | ||||
| 		return TransferErc20Token(client, fromPrivateKey, tokenAddress, toAddress, tokenAmount, tokenDecimals) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // TransferEth 发送 ETH 交易。 | ||||
| func TransferEth(client *ethclient.Client, fromPrivateKey string, toAddress string, tokenAmount decimal.Decimal) (*types.Transaction, error) { | ||||
| 	// 1. 解析私钥 | ||||
| 	privateKey, fromAddressCommon, err := GetAddressFromPrivateKey(fromPrivateKey) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// 3. 获取发送者的 nonce(交易序号) | ||||
| 	nonce, err := client.PendingNonceAt(context.Background(), fromAddressCommon) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("获取 nonce 失败: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// 4. 设置交易的 value (对于代币转账,value 是 0) | ||||
| 	value, _ := convertDecimalToBigInt(tokenAmount, 18) | ||||
|  | ||||
| 	// 5. 获取 Gas 价格 | ||||
| 	gasPrice, err := client.SuggestGasPrice(context.Background()) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("获取 Gas 价格失败: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// 6. 将地址字符串转换为 common.Address 类型 | ||||
| 	toAddressCommon := common.HexToAddress(toAddress) | ||||
|  | ||||
| 	// 7. 构造 ERC-20 transfer 函数的调用数据 | ||||
| 	// 7.1  函数签名:transfer(address,uint256) | ||||
| 	transferFnSignature := "transfer(address,uint256)" // 已经是标准化的 | ||||
| 	hash := sha3.NewLegacyKeccak256()                  //  或 sha3.NewLegacyKeccak256() | ||||
| 	hash.Write([]byte(transferFnSignature)) | ||||
|  | ||||
| 	// 7.4  拼接调用数据 | ||||
| 	var data []byte | ||||
|  | ||||
| 	// 8. 估算 Gas 消耗 | ||||
| 	gasLimit, err := client.EstimateGas(context.Background(), ethereum.CallMsg{ | ||||
| 		From: fromAddressCommon, | ||||
| 		To:   &toAddressCommon, | ||||
| 		Data: data, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("估算 Gas 消耗失败: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// 9. (预估gas+基础费用)*1.1 作为 GasLimit | ||||
| 	gasLimit = (gasLimit + 21000) * 12 / 10 // 增加 20% | ||||
| 	if gasLimit < 23000 { | ||||
| 		gasLimit = 23000 // 最小 Gas 限制 | ||||
| 	} | ||||
|  | ||||
| 	// 10. 创建交易 | ||||
| 	tx := types.NewTransaction(nonce, toAddressCommon, value, gasLimit, gasPrice, data) | ||||
|  | ||||
| 	// 11. 获取链 ID | ||||
| 	chainID, err := client.NetworkID(context.Background()) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("获取链 ID 失败: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// 12. 签名交易 | ||||
| 	signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("签名交易失败: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// 13. 发送交易 | ||||
| 	err = client.SendTransaction(context.Background(), signedTx) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("发送交易失败: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	return signedTx, nil | ||||
| } | ||||
|  | ||||
| // transferErc20Token 发送 ERC-20 代币交易。 | ||||
| // tokenAmount: 要发送的代币数量 (例如,1.0 代表 1 个代币)。 | ||||
| // fromPrivateKey: 发送者的私钥。 | ||||
| // tokenAddress: ERC-20 代币的合约地址。 | ||||
| // toAddress: 接收者的地址。 | ||||
| // tokenDecimals: 代币的小数位数 (例如,USDC 是 6,很多其他代币是 18)。 | ||||
| func transferErc20Token( | ||||
| func TransferErc20Token( | ||||
| 	client *ethclient.Client, | ||||
| 	fromPrivateKey string, | ||||
| 	tokenAddress string, | ||||
| 	toAddress string, | ||||
| 	tokenAmount float64, | ||||
| 	tokenAmount decimal.Decimal, | ||||
| 	tokenDecimals uint8, | ||||
| ) (*types.Transaction, error) { | ||||
| 	// 1. 解析私钥 | ||||
| @ -57,15 +151,15 @@ func transferErc20Token( | ||||
|  | ||||
| 	// 7. 构造 ERC-20 transfer 函数的调用数据 | ||||
| 	// 7.1  函数签名:transfer(address,uint256) | ||||
| 	transferFnSignature := []byte("transfer(address,uint256)") | ||||
| 	hash := sha3.New256() | ||||
| 	hash.Write(transferFnSignature) | ||||
| 	methodID := hash.Sum(nil)[:4] // 取前 4 个字节作为方法 ID | ||||
| 	transferFnSignature := "transfer(address,uint256)" // 已经是标准化的 | ||||
| 	hash := sha3.NewLegacyKeccak256()                  //  或 sha3.NewLegacyKeccak256() | ||||
| 	hash.Write([]byte(transferFnSignature)) | ||||
| 	methodID := hash.Sum(nil)[:4] | ||||
|  | ||||
| 	// 7.2  填充接收者地址和转账金额 | ||||
| 	paddedAddress := common.LeftPadBytes(toAddressCommon.Bytes(), 32) | ||||
| 	// 7.3  将代币数量转换为最小单位 | ||||
| 	amountBigInt, err := convertTokenAmountToBigInt(tokenAmount, tokenDecimals) | ||||
| 	amountBigInt, err := convertDecimalToBigInt(tokenAmount, tokenDecimals) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("转换代币数量失败: %w", err) | ||||
| 	} | ||||
| @ -80,15 +174,15 @@ func transferErc20Token( | ||||
| 	// 8. 估算 Gas 消耗 | ||||
| 	gasLimit, err := client.EstimateGas(context.Background(), ethereum.CallMsg{ | ||||
| 		From: fromAddressCommon, | ||||
| 		To:   &tokenAddressCommon, | ||||
| 		To:   &toAddressCommon, | ||||
| 		Data: data, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("估算 Gas 消耗失败: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// 9. 增加 Gas 限制的安全边际 | ||||
| 	gasLimit = gasLimit * 11 / 10 // 增加 10% | ||||
| 	// 9. (预估gas+基础费用)*1.1 作为 GasLimit | ||||
| 	gasLimit = (gasLimit + 21000) * 12 / 10 // 增加 20% | ||||
| 	if gasLimit < 23000 { | ||||
| 		gasLimit = 23000 // 最小 Gas 限制 | ||||
| 	} | ||||
| @ -140,36 +234,45 @@ func GetAddressFromPrivateKey(fromPrivateKey string) (*ecdsa.PrivateKey, common. | ||||
| } | ||||
|  | ||||
| // convertTokenAmountToBigInt 将代币数量 (例如,1.0) 转换为最小单位的整数表示 (例如,USDC 的 1000000)。 | ||||
| func convertTokenAmountToBigInt(tokenAmount float64, tokenDecimals uint8) (*big.Int, error) { | ||||
| 	// 1. 使用最大精度格式化浮点数 | ||||
| 	amountStr := fmt.Sprintf("%.18f", tokenAmount) // 使用最大精度 | ||||
| func convertDecimalToBigInt(amountDecimal decimal.Decimal, tokenDecimals uint8) (*big.Int, error) { | ||||
| 	// 1. 创建一个与 token decimals 精度相同的 10 的幂 | ||||
| 	exponent := new(big.Int).Exp(big.NewInt(10), big.NewInt(int64(tokenDecimals)), nil) | ||||
|  | ||||
| 	// 2. 找到小数点的位置 | ||||
| 	decimalPointIndex := strings.Index(amountStr, ".") | ||||
| 	// 2. 将 decimal 乘以该 10 的幂 | ||||
| 	amountScaled := amountDecimal.Mul(decimal.NewFromBigInt(exponent, 0)) | ||||
|  | ||||
| 	// 3. 如果没有小数点,则添加足够的 0 | ||||
| 	if decimalPointIndex == -1 { | ||||
| 		amountStr += "." + strings.Repeat("0", int(tokenDecimals)) | ||||
| 	} else { | ||||
| 		// 4. 计算需要填充的 0 的数量 | ||||
| 		paddingNeeded := int(tokenDecimals) - (len(amountStr) - decimalPointIndex - 1) | ||||
|  | ||||
| 		// 5. 填充 0 或截断多余的小数位 | ||||
| 		if paddingNeeded > 0 { | ||||
| 			amountStr += strings.Repeat("0", paddingNeeded) | ||||
| 		} else if paddingNeeded < 0 { | ||||
| 			amountStr = amountStr[:decimalPointIndex+int(tokenDecimals)+1] | ||||
| 		} | ||||
| 		// 6. 移除小数点 | ||||
| 		amountStr = strings.ReplaceAll(amountStr, ".", "") | ||||
| 	} | ||||
|  | ||||
| 	// 7. 将字符串转换为 big.Int | ||||
| 	amountBigInt := new(big.Int) | ||||
| 	amountBigInt, ok := amountBigInt.SetString(amountStr, 10) | ||||
| 	if !ok { | ||||
| 		return nil, fmt.Errorf("将金额字符串转换为 big.Int 失败: %s", amountStr) | ||||
| 	} | ||||
| 	// 3. 将 scaled decimal 转换为 big.Int | ||||
| 	amountBigInt := amountScaled.BigInt() | ||||
|  | ||||
| 	return amountBigInt, nil | ||||
| } | ||||
|  | ||||
| // GetTransactionByHash 获取交易的状态。 | ||||
| // status 0:失败 1-成功 | ||||
| // error: 交易未确认或不存在 | ||||
| func GetTransactionByHash(client *ethclient.Client, hash string) (int, error) { | ||||
| 	txHash := common.HexToHash(hash) | ||||
| 	// 获取交易收据(包含状态) | ||||
| 	receipt, err := client.TransactionReceipt(context.Background(), txHash) | ||||
| 	if err != nil { | ||||
| 		return 0, errors.New("交易未确认或不存在") | ||||
| 	} | ||||
|  | ||||
| 	return int(receipt.Status), nil | ||||
| } | ||||
|  | ||||
| // 校验钱包地址是否合法 | ||||
| func IsValidAddress(address string) bool { | ||||
| 	if !strings.HasPrefix(address, "0x") { | ||||
| 		address = "0x" + address | ||||
| 	} | ||||
| 	if len(address) != 42 { | ||||
| 		return false | ||||
| 	} | ||||
| 	if !regexp.MustCompile(`^0x[0-9a-fA-F]{40}$`).MatchString(address) { | ||||
| 		return false | ||||
| 	} | ||||
|  | ||||
| 	checksumAddress := common.HexToAddress(address).String() | ||||
| 	return address == checksumAddress | ||||
| } | ||||
|  | ||||
							
								
								
									
										169
									
								
								utils/excelhelper/excel_helper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								utils/excelhelper/excel_helper.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,169 @@ | ||||
| package excelhelper | ||||
|  | ||||
| import ( | ||||
| 	"encoding/csv" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	helper "go-admin/utils" | ||||
| 	"log" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/xuri/excelize/v2" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
| ) | ||||
|  | ||||
| /* | ||||
| 导出csv文件 | ||||
|  | ||||
|   - @fileName 文件名 不带拓展名 | ||||
|   - @header 文件头 | ||||
|   - @records 内容 | ||||
| */ | ||||
| func ExportCSV(c *gin.Context, fileName string, header []string, records [][]string) error { | ||||
| 	disposition := fmt.Sprintf("attachment; filename=%s.csv", fileName) | ||||
|  | ||||
| 	// Set headers | ||||
| 	c.Header("Content-Description", "File Transfer") | ||||
| 	c.Header("Content-Disposition", disposition) | ||||
| 	c.Header("Content-Type", "text/csv") | ||||
|  | ||||
| 	// Create a CSV writer using the response writer | ||||
| 	writer := csv.NewWriter(c.Writer) | ||||
| 	defer writer.Flush() | ||||
|  | ||||
| 	// Write CSV header | ||||
| 	writer.Write(header) | ||||
|  | ||||
| 	for _, record := range records { | ||||
| 		writer.Write(record) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| /* | ||||
| 导出excel | ||||
|  | ||||
|   - @fileName 文件名称 | ||||
|   - @data 数据源 | ||||
|   - @ingore 忽略header | ||||
| */ | ||||
| func ExportExcel[T any](c *gin.Context, fileName string, data []T, ingore []string) error { | ||||
| 	if len(data) == 0 { | ||||
| 		return errors.New("无导出记录") | ||||
| 	} | ||||
| 	// Create a new Excel file | ||||
| 	f := excelize.NewFile() | ||||
| 	// Use reflection to get the header from struct tags | ||||
| 	t := reflect.TypeOf(data[0]) | ||||
| 	headers := []string{} | ||||
| 	for i := 0; i < t.NumField(); i++ { | ||||
| 		field := t.Field(i) | ||||
| 		excelTag := field.Tag.Get("excel") | ||||
| 		if excelTag != "" && !helper.ArrayAny(ingore, excelTag) { | ||||
| 			headers = append(headers, excelTag) | ||||
| 		} | ||||
| 	} | ||||
| 	// Set headers | ||||
| 	for i, header := range headers { | ||||
| 		col := string('A' + i) | ||||
| 		cell := fmt.Sprintf("%s1", col) | ||||
| 		f.SetCellValue("Sheet1", cell, header) | ||||
| 	} | ||||
|  | ||||
| 	// Fill rows with data | ||||
| 	for rowIndex, item := range data { | ||||
| 		rowValue := reflect.ValueOf(item) | ||||
| 		rowType := rowValue.Type() | ||||
| 		for colIndex, header := range headers { | ||||
| 			col := string('A' + colIndex) | ||||
| 			cell := fmt.Sprintf("%s%d", col, rowIndex+2) | ||||
| 			var fieldValue reflect.Value | ||||
|  | ||||
| 			for i := 0; i < rowType.NumField(); i++ { | ||||
| 				field := rowType.Field(i) | ||||
| 				if strings.EqualFold(field.Tag.Get("excel"), header) { | ||||
| 					fieldValue = rowValue.Field(i) | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// Check if the fieldValue is valid before accessing it | ||||
| 			if fieldValue.IsValid() && fieldValue.CanInterface() { | ||||
| 				//f.SetCellValue("Sheet1", cell, fieldValue.Interface()) | ||||
| 				value := fieldValue.Interface() | ||||
|  | ||||
| 				// Ensure the value is a string, convert it if necessary | ||||
| 				var stringValue string | ||||
| 				if v, ok := value.(string); ok { | ||||
| 					stringValue = v // If it's a string, use it directly | ||||
| 				} else { | ||||
| 					stringValue = fmt.Sprintf("%v", value) // Otherwise, convert to string | ||||
| 				} | ||||
| 				f.SetCellValue("Sheet1", cell, stringValue) | ||||
| 			} else { | ||||
| 				// Handle the case where fieldValue is invalid or nil | ||||
| 				f.SetCellValue("Sheet1", cell, "") | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	// Set response headers and send the file to the client | ||||
|  | ||||
| 	// c.Writer.Header().Set("Content-Disposition", "attachment; filename=test.xlsx") | ||||
| 	// c.Writer.Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; charset=binary") | ||||
| 	// c.Writer.Header().Set("Content-Transfer-Encoding", "binary") | ||||
| 	// c.Writer.Header().Set("Expires", "0") | ||||
| 	// c.Writer.Header().Set("Cache-Control", "must-revalidate") | ||||
| 	// c.Writer.Header().Set("Pragma", "public") | ||||
| 	c.Header("Content-Description", "File Transfer") | ||||
| 	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s.xlsx", fileName)) | ||||
| 	c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") | ||||
| 	c.Header("Content-Transfer-Encoding", "binary") | ||||
| 	c.Header("Expires", "0") | ||||
| 	c.Header("Cache-Control", "must-revalidate") | ||||
| 	c.Header("Pragma", "public") | ||||
| 	c.Header("Content-Encoding", "") | ||||
| 	//fmt.Println("c.Writer.Header():", c.Writer.Header()) | ||||
| 	if _, err := f.WriteTo(c.Writer); err != nil { | ||||
| 		log.Println("Error writing file:", err) | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| 	//return f.WriteTo(c.Writer) | ||||
| } | ||||
|  | ||||
| func MapExcelToStruct[T any](rows [][]string, headers []string) ([]T, error) { | ||||
| 	var results []T | ||||
| 	if len(rows) == 0 { | ||||
| 		return results, nil | ||||
| 	} | ||||
|  | ||||
| 	for _, row := range rows { | ||||
| 		var result T | ||||
| 		v := reflect.ValueOf(&result).Elem() | ||||
|  | ||||
| 		for i, header := range headers { | ||||
| 			fieldName := "" | ||||
| 			for j := 0; j < v.NumField(); j++ { | ||||
| 				field := v.Type().Field(j) | ||||
| 				tag := field.Tag.Get("excel") | ||||
| 				if strings.EqualFold(tag, header) { | ||||
| 					fieldName = field.Name | ||||
| 					break | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if fieldName != "" && i < len(row) { | ||||
| 				field := v.FieldByName(fieldName) | ||||
| 				if field.IsValid() && field.CanSet() { | ||||
| 					field.Set(reflect.ValueOf(row[i]).Convert(field.Type())) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		results = append(results, result) | ||||
| 	} | ||||
|  | ||||
| 	return results, nil | ||||
| } | ||||
							
								
								
									
										52
									
								
								utils/extension_helper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								utils/extension_helper.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | ||||
| package helper | ||||
|  | ||||
| /* | ||||
| 判断是否存在 | ||||
|  | ||||
|   - @arr 数组 | ||||
|   - @value 值 | ||||
| */ | ||||
| func ArrayAny[T comparable](arr []T, value T) bool { | ||||
| 	for _, v := range arr { | ||||
| 		if v == value { | ||||
| 			return true | ||||
| 		} | ||||
| 	} | ||||
| 	return false | ||||
| } | ||||
|  | ||||
| // 定义一个条件函数类型 | ||||
| type ConditionFunc[T any] func(T) bool | ||||
|  | ||||
| /* | ||||
| 判断是否存在 | ||||
|  | ||||
|   - @arr 数组 | ||||
|  | ||||
|   - @condition 判断函数 | ||||
|  | ||||
|     @return 对象指针 | ||||
| */ | ||||
| func ArrayAnyExtension[T any](arr *[]T, condition ConditionFunc[T]) *T { | ||||
| 	for _, v := range *arr { | ||||
| 		if condition(v) { | ||||
| 			return &v | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func RemoveDuplicates(nums []int64) []int64 { | ||||
| 	m := make(map[int64]bool) | ||||
| 	result := []int64{} | ||||
|  | ||||
| 	for _, num := range nums { | ||||
| 		if !m[num] { | ||||
| 			m[num] = true | ||||
| 			result = append(result, num) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return result | ||||
| } | ||||
							
								
								
									
										779
									
								
								utils/redishelper/redis_helper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										779
									
								
								utils/redishelper/redis_helper.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,779 @@ | ||||
| package helper | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"math" | ||||
| 	"reflect" | ||||
| 	"strconv" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/bytedance/sonic" | ||||
| 	"github.com/go-redis/redis/v8" | ||||
| ) | ||||
|  | ||||
| // RedisHelper 结构体封装了 Redis 客户端及上下文 | ||||
| type RedisHelper struct { | ||||
| 	client          *redis.Client   // Redis 客户端 | ||||
| 	ctx             context.Context // 上下文 | ||||
| 	emptyCacheValue string          // 缓存空值的标志 | ||||
| } | ||||
|  | ||||
| var DefaultRedis *RedisHelper | ||||
|  | ||||
| // 初始化默认链接 | ||||
| func InitDefaultRedis(addr, password string, db int) { | ||||
| 	if DefaultRedis == nil { | ||||
| 		DefaultRedis = NewRedisHelper(addr, password, db) | ||||
| 	} | ||||
|  | ||||
| 	log.Printf("初始化redis链接") | ||||
| } | ||||
|  | ||||
| // NewRedisHelper 创建一个新的 RedisHelper 实例 | ||||
| func NewRedisHelper(addr, password string, db int) *RedisHelper { | ||||
| 	rdb := redis.NewClient(&redis.Options{ | ||||
| 		Addr:         addr,     // Redis 服务器地址 | ||||
| 		Password:     password, // Redis 密码 | ||||
| 		DB:           db,       // 使用的数据库编号 | ||||
| 		PoolSize:     50, | ||||
| 		MinIdleConns: 10, | ||||
| 		DialTimeout:  10 * time.Second, // 调整连接超时时间 | ||||
| 		ReadTimeout:  10 * time.Second, // 调整读超时时间 | ||||
| 		WriteTimeout: 10 * time.Second, // 调整写超时时间 | ||||
| 	}) | ||||
|  | ||||
| 	return &RedisHelper{ | ||||
| 		client: rdb, | ||||
| 		ctx:    context.Background(), // 创建背景上下文 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // 测试连接 | ||||
| func (r *RedisHelper) Ping() error { | ||||
| 	return r.client.Ping(r.ctx).Err() | ||||
| } | ||||
|  | ||||
| // SetString 设置字符串值 | ||||
| func (r *RedisHelper) SetString(key, value string) error { | ||||
| 	return r.client.Set(r.ctx, key, value, 0).Err() // 将值存储到指定的键 | ||||
| } | ||||
|  | ||||
| // 批量设置 | ||||
| func (r *RedisHelper) BatchSet(maps *map[string]string) error { | ||||
| 	pipe := r.client.Pipeline() | ||||
|  | ||||
| 	for key, val := range *maps { | ||||
| 		pipe.Set(r.ctx, key, val, 0) | ||||
| 	} | ||||
|  | ||||
| 	_, err := pipe.Exec(r.ctx) | ||||
|  | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // SetString 设置字符串值 | ||||
| func (r *RedisHelper) SetStringExpire(key, value string, expireTime time.Duration) error { | ||||
| 	return r.client.Set(r.ctx, key, value, expireTime).Err() // 将值存储到指定的键 | ||||
| } | ||||
|  | ||||
| // SetString 设置字符串值 | ||||
| func (r *RedisHelper) SetAdd(key, value string, expireTime time.Duration) error { | ||||
| 	// 存储到 SET 中 | ||||
| 	result, err := r.client.SAdd(r.ctx, key, value).Result() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if result == 1 { | ||||
| 		// 设置 SET 的过期时间 | ||||
| 		err = r.client.Expire(r.ctx, key, expireTime).Err() | ||||
| 		if err != nil { | ||||
| 			return errors.New("设置过期时间失败:" + err.Error()) | ||||
| 		} | ||||
|  | ||||
| 		return nil | ||||
| 	} else { | ||||
| 		return errors.New("key已存在") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // 设置对象 | ||||
| func SetObjString[T any](r *RedisHelper, key string, value T) error { | ||||
| 	keyValue, err := sonic.Marshal(value) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return r.SetString(key, string(keyValue)) | ||||
| } | ||||
|  | ||||
| // 获取对象 | ||||
| func GetObjString[T any](r *RedisHelper, key string) (T, error) { | ||||
| 	var result T | ||||
| 	value, err := r.GetString(key) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return result, err | ||||
| 	} | ||||
|  | ||||
| 	err = sonic.Unmarshal([]byte(value), &result) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return result, err | ||||
| 	} | ||||
|  | ||||
| 	return result, nil | ||||
| } | ||||
|  | ||||
| func (r *RedisHelper) Get(key string) *redis.StringCmd { | ||||
| 	return r.client.Get(r.ctx, key) | ||||
| } | ||||
|  | ||||
| /* | ||||
| 获取剩余时间 | ||||
|   - @key redis key | ||||
| */ | ||||
| func (r *RedisHelper) TTL(key string) *redis.DurationCmd { | ||||
| 	return r.client.TTL(r.ctx, key) | ||||
| } | ||||
|  | ||||
| // GetString 获取字符串值 | ||||
| func (r *RedisHelper) GetString(key string) (string, error) { | ||||
| 	return r.client.Get(r.ctx, key).Result() // 从指定的键获取值 | ||||
| } | ||||
|  | ||||
| // DeleteString 删除字符串键 | ||||
| func (r *RedisHelper) DeleteString(key string) error { | ||||
| 	return r.client.Del(r.ctx, key).Err() // 删除指定的键 | ||||
| } | ||||
|  | ||||
| // DeleteString 删除目录下所有key | ||||
| func (r *RedisHelper) DeleteAll(key string) error { | ||||
| 	keys, err := r.ScanKeys(key) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	_, err = r.BatchDeleteKeys(keys) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| /* | ||||
| 递增 | ||||
|   - @key rediskey | ||||
| */ | ||||
| func (r *RedisHelper) Incr(key string) *redis.IntCmd { | ||||
| 	return r.client.Incr(r.ctx, key) | ||||
| } | ||||
|  | ||||
| /* | ||||
| 设置过期时间 | ||||
|   - @key redis key | ||||
|   - @expiration 过期时间 | ||||
| */ | ||||
| func (r *RedisHelper) Expire(key string, expiration time.Duration) *redis.BoolCmd { | ||||
| 	return r.client.Expire(r.ctx, key, expiration) | ||||
| } | ||||
|  | ||||
| /* | ||||
| 批量删除 | ||||
|  | ||||
|   - @keys 键数组 | ||||
| */ | ||||
| func (r *RedisHelper) BatchDeleteKeys(keys []string) (int, error) { | ||||
| 	if r.client == nil { | ||||
| 		return 0, errors.New("Redis client is nil") | ||||
| 	} | ||||
| 	if len(keys) == 0 { | ||||
| 		return 0, nil | ||||
| 	} | ||||
|  | ||||
| 	deletedCount := 0 | ||||
| 	batchSize := 1000 // 每批次删除的键数量 | ||||
| 	for i := 0; i < len(keys); i += batchSize { | ||||
| 		end := i + batchSize | ||||
| 		if end > len(keys) { | ||||
| 			end = len(keys) | ||||
| 		} | ||||
| 		batch := keys[i:end] | ||||
|  | ||||
| 		_, err := r.client.Pipelined(r.ctx, func(pipe redis.Pipeliner) error { | ||||
| 			for _, key := range batch { | ||||
| 				pipe.Del(r.ctx, key) | ||||
| 				deletedCount++ | ||||
| 			} | ||||
| 			return nil | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			return deletedCount, fmt.Errorf("failed to delete keys in batch: %v", err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return deletedCount, nil | ||||
| } | ||||
|  | ||||
| // DeleteKeysByPrefix 删除指定前缀的键 | ||||
| func (r *RedisHelper) DeleteKeysByPrefix(prefixes ...string) error { | ||||
| 	ctx := context.Background() | ||||
| 	// 遍历每个前缀 | ||||
| 	for _, prefix := range prefixes { | ||||
| 		var cursor uint64 | ||||
| 		var keys []string | ||||
|  | ||||
| 		// 使用 SCAN 命令查找匹配的键 | ||||
| 		for { | ||||
| 			var err error | ||||
| 			keys, cursor, err = r.client.Scan(ctx, cursor, prefix+"*", 1000).Result() | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
|  | ||||
| 			// 删除匹配的键 | ||||
| 			if len(keys) > 0 { | ||||
| 				_, err := r.client.Del(ctx, keys...).Result() | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				fmt.Printf("Deleted keys with prefix '%s': %v\n", prefix, keys) | ||||
| 			} | ||||
|  | ||||
| 			// 如果游标为 0,表示迭代结束 | ||||
| 			if cursor == 0 { | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // 查找所有value | ||||
| func (r *RedisHelper) GetAllKeysAndValues(pattern string) ([]string, error) { | ||||
| 	var cursor uint64 | ||||
| 	var result = []string{} | ||||
|  | ||||
| 	for { | ||||
| 		// 使用 SCAN 命令获取匹配的键 | ||||
| 		keys, nextCursor, err := r.client.Scan(r.ctx, cursor, pattern+"*", 1000).Result() | ||||
| 		if err != nil { | ||||
| 			log.Printf("Error scanning keys: %v", err) | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		// 处理匹配到的键 | ||||
| 		for _, key := range keys { | ||||
| 			value, err := r.client.Get(r.ctx, key).Result() | ||||
| 			if err != nil { | ||||
| 				if err == redis.Nil { | ||||
| 					fmt.Printf("Key %s does not exist\n", key) | ||||
| 				} else { | ||||
| 					fmt.Printf("Error getting value for key %s: %v", key, err) | ||||
| 				} | ||||
| 			} else { | ||||
| 				result = append(result, value) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// 如果 cursor 为 0,表示扫描完成 | ||||
| 		if nextCursor == 0 { | ||||
| 			break | ||||
| 		} | ||||
| 		cursor = nextCursor | ||||
| 	} | ||||
|  | ||||
| 	return result, nil | ||||
| } | ||||
|  | ||||
| // LPushList 将一个或多个值插入到列表的头部 | ||||
| func (r *RedisHelper) LPushList(key string, values ...string) error { | ||||
| 	return r.client.LPush(r.ctx, key, values).Err() // 将值插入到列表的头部 | ||||
| } | ||||
|  | ||||
| // RPushList 将一个或多个值插入到列表的尾部 | ||||
| func (r *RedisHelper) RPushList(key string, values ...string) error { | ||||
| 	return r.client.RPush(r.ctx, key, values).Err() // 将值插入到列表的尾部 | ||||
| } | ||||
|  | ||||
| // LPopList 从列表的头部弹出一个元素 | ||||
| func (r *RedisHelper) LPopList(key string) (string, error) { | ||||
| 	return r.client.LPop(r.ctx, key).Result() // 从列表的头部移除并返回第一个元素 | ||||
| } | ||||
|  | ||||
| // RPopList 从列表的尾部弹出一个元素 | ||||
| func (r *RedisHelper) RPopList(key string) (string, error) { | ||||
| 	return r.client.RPop(r.ctx, key).Result() // 从列表的尾部移除并返回最后一个元素 | ||||
| } | ||||
|  | ||||
| // LRangeList 获取列表中指定范围的元素 | ||||
| func (r *RedisHelper) LRangeList(key string, start, stop int64) ([]string, error) { | ||||
| 	return r.client.LRange(r.ctx, key, start, stop).Result() // 获取列表中指定范围的元素 | ||||
| } | ||||
|  | ||||
| // GetAllList 获取列表中的所有元素 | ||||
| func (r *RedisHelper) GetAllList(key string) ([]string, error) { | ||||
| 	values, err := r.client.LRange(r.ctx, key, 0, -1).Result() | ||||
| 	if err == redis.Nil { | ||||
| 		return nil, nil | ||||
| 	} else if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	// 检查是否包含空值标志 | ||||
| 	if len(values) == 1 && values[0] == r.emptyCacheValue { | ||||
| 		return nil, nil | ||||
| 	} | ||||
|  | ||||
| 	return values, nil | ||||
| } | ||||
|  | ||||
| func (r *RedisHelper) LRem(key, val string) (int64, error) { | ||||
| 	count := 0 // 删除所有与 valueToRemove 相等的元素 | ||||
| 	result, err := r.client.LRem(r.ctx, key, int64(count), val).Result() | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("删除元素失败: %v\n", err) | ||||
| 	} | ||||
|  | ||||
| 	return result, nil | ||||
| } | ||||
|  | ||||
| func (r *RedisHelper) IsElementInList(key string, element string) (bool, error) { | ||||
| 	var cursor int64 = 0 | ||||
| 	const batchSize int64 = 1000 // 每批次获取的元素数量 | ||||
|  | ||||
| 	for { | ||||
| 		// 分批次获取列表元素 | ||||
| 		elements, err := r.client.LRange(r.ctx, key, cursor, cursor+batchSize-1).Result() | ||||
| 		if err != nil { | ||||
| 			return false, err | ||||
| 		} | ||||
| 		if len(elements) == 0 { | ||||
| 			break // 没有更多数据 | ||||
| 		} | ||||
|  | ||||
| 		// 遍历当前批次的元素 | ||||
| 		for _, e := range elements { | ||||
| 			if e == element { | ||||
| 				return true, nil | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		cursor += batchSize // 移动到下一批次 | ||||
| 	} | ||||
|  | ||||
| 	return false, nil | ||||
| } | ||||
|  | ||||
| /* | ||||
| SetListCache 重新设置列表缓存 | ||||
|   - @expiration 0-过期 1-过期时间 | ||||
| */ | ||||
| func (r *RedisHelper) SetListCache(key string, expiration time.Duration, values ...string) error { | ||||
| 	tempKey := key + ":temp" | ||||
|  | ||||
| 	// 使用事务来确保操作的原子性 | ||||
| 	pipe := r.client.TxPipeline() | ||||
|  | ||||
| 	// 将新数据插入到临时列表中 | ||||
| 	pipe.RPush(r.ctx, tempKey, values) | ||||
|  | ||||
| 	// 重命名临时列表为目标列表 | ||||
| 	pipe.Rename(r.ctx, tempKey, key) | ||||
|  | ||||
| 	if expiration > 0 { | ||||
| 		// 设置目标列表的过期时间 | ||||
| 		pipe.Expire(r.ctx, key, expiration) | ||||
| 	} | ||||
|  | ||||
| 	// 执行事务 | ||||
| 	_, err := pipe.Exec(r.ctx) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // SetEmptyListCache 设置空值缓存 | ||||
| func (r *RedisHelper) SetEmptyListCache(key string, expiration time.Duration) error { | ||||
| 	// 使用一个特殊标志值表示列表为空 | ||||
| 	_, err := r.client.RPush(r.ctx, key, r.emptyCacheValue).Result() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	// 设置列表的过期时间 | ||||
| 	return r.client.Expire(r.ctx, key, expiration).Err() | ||||
| } | ||||
|  | ||||
| // scanKeys 使用 SCAN 命令获取所有匹配的键 | ||||
| func (r *RedisHelper) ScanKeys(pattern string) ([]string, error) { | ||||
|  | ||||
| 	var cursor uint64 | ||||
| 	var keys []string | ||||
| 	for { | ||||
| 		var newKeys []string | ||||
| 		var err error | ||||
|  | ||||
| 		// SCAN 命令每次返回部分匹配的键 | ||||
| 		newKeys, cursor, err = r.client.Scan(r.ctx, cursor, pattern, 1000).Result() | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		keys = append(keys, newKeys...) | ||||
| 		if cursor == 0 { | ||||
| 			break | ||||
| 		} | ||||
| 	} | ||||
| 	return keys, nil | ||||
| } | ||||
|  | ||||
| // 泛型函数,用于获取所有键的列表数据并合并为一个数组 | ||||
| func GetAndMergeLists[T any](r *RedisHelper, keys []string) ([]T, error) { | ||||
| 	var combinedList []T | ||||
| 	for _, key := range keys { | ||||
| 		// 获取每个键的列表数据 | ||||
| 		listData, err := r.client.LRange(r.ctx, key, 0, -1).Result() | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
|  | ||||
| 		// 解码每个数据项为类型 T,并添加到结果列表中 | ||||
| 		for _, data := range listData { | ||||
| 			var item T | ||||
| 			if err := sonic.Unmarshal([]byte(data), &item); err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			combinedList = append(combinedList, item) | ||||
| 		} | ||||
| 	} | ||||
| 	return combinedList, nil | ||||
| } | ||||
|  | ||||
| // SetNX 实现类似于 Redis 的 SETNX 命令 | ||||
| func (r *RedisHelper) SetNX(key string, value interface{}, expiration time.Duration) (bool, error) { | ||||
| 	result, err := r.client.Set(r.ctx, key, value, expiration).Result() | ||||
| 	if err != nil { | ||||
| 		return false, err | ||||
| 	} | ||||
|  | ||||
| 	// 如果键不存在则 result 会等于 "OK" | ||||
| 	return result == "OK", nil | ||||
| } | ||||
|  | ||||
| func getFieldsFromStruct(obj interface{}) map[string]interface{} { | ||||
| 	fields := make(map[string]interface{}) | ||||
| 	val := reflect.ValueOf(obj) | ||||
| 	typ := reflect.TypeOf(obj) | ||||
|  | ||||
| 	for i := 0; i < val.NumField(); i++ { | ||||
| 		field := typ.Field(i) | ||||
| 		tag := field.Tag.Get("redis") | ||||
| 		if tag != "" { | ||||
| 			fieldVal := val.Field(i) | ||||
| 			if fieldVal.Kind() == reflect.Slice || fieldVal.Kind() == reflect.Map { | ||||
| 				// 处理切片或映射类型 | ||||
| 				// 对于切片,使用索引作为字段名 | ||||
| 				if fieldVal.Kind() == reflect.Slice { | ||||
| 					for j := 0; j < fieldVal.Len(); j++ { | ||||
| 						elem := fieldVal.Index(j).Interface() | ||||
| 						fields[fmt.Sprintf("%s_%d", tag, j)] = elem | ||||
| 					} | ||||
| 				} else if fieldVal.Kind() == reflect.Map { | ||||
| 					// 对于映射,使用键作为字段名 | ||||
| 					for _, key := range fieldVal.MapKeys() { | ||||
| 						elem := fieldVal.MapIndex(key).Interface() | ||||
| 						fields[fmt.Sprintf("%s_%v", tag, key.Interface())] = elem | ||||
| 					} | ||||
| 				} | ||||
| 			} else { | ||||
| 				fields[tag] = fieldVal.Interface() | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return fields | ||||
| } | ||||
|  | ||||
| func (r *RedisHelper) SetHashWithTags(key string, obj interface{}) error { | ||||
| 	fields := getFieldsFromStruct(obj) | ||||
| 	_, err := r.client.HSet(r.ctx, key, fields).Result() | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // HSetField 设置哈希中的一个字段 | ||||
| func (r *RedisHelper) HSetField(key, field string, value interface{}) error { | ||||
| 	_, err := r.client.HSet(r.ctx, key, field, value).Result() | ||||
| 	if err != nil { | ||||
| 		log.Printf("Error setting field %s in hash %s: %v", field, key, err) | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // HSetMultipleFields 设置哈希中的多个字段 | ||||
| func (r *RedisHelper) HSetMultipleFields(key string, fields map[string]interface{}) error { | ||||
| 	_, err := r.client.HSet(r.ctx, key, fields).Result() | ||||
| 	if err != nil { | ||||
| 		log.Printf("Error setting multiple fields in hash %s: %v", key, err) | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // HGetField 获取哈希中某个字段的值 | ||||
| func (r *RedisHelper) HGetField(key, field string) (string, error) { | ||||
| 	val, err := r.client.HGet(r.ctx, key, field).Result() | ||||
| 	if err != nil { | ||||
| 		if err == redis.Nil { | ||||
| 			return "", nil // Field does not exist | ||||
| 		} | ||||
| 		log.Printf("Error getting field %s from hash %s: %v", field, key, err) | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return val, nil | ||||
| } | ||||
|  | ||||
| // HGetAllFields 获取哈希中所有字段的值 | ||||
| func (r *RedisHelper) HGetAllFields(key string) (map[string]string, error) { | ||||
| 	fields, err := r.client.HGetAll(r.ctx, key).Result() | ||||
| 	if err != nil { | ||||
| 		log.Printf("Error getting all fields from hash %s: %v", key, err) | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return fields, nil | ||||
| } | ||||
|  | ||||
| // HDelField 删除哈希中的某个字段 | ||||
| func (r *RedisHelper) HDelField(key, field string) error { | ||||
| 	_, err := r.client.HDel(r.ctx, key, field).Result() | ||||
| 	if err != nil { | ||||
| 		log.Printf("Error deleting field %s from hash %s: %v", field, key, err) | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // 删除哈希 | ||||
| func (r *RedisHelper) HDelAll(key string) error { | ||||
| 	_, err := r.client.Del(r.ctx, key).Result() | ||||
| 	if err != nil { | ||||
| 		log.Printf("Error deleting from hash %s: %v", key, err) | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // HKeys 获取哈希中所有字段的名字 | ||||
| func (r *RedisHelper) HKeys(key string) ([]string, error) { | ||||
| 	fields, err := r.client.HKeys(r.ctx, key).Result() | ||||
| 	if err != nil { | ||||
| 		log.Printf("Error getting keys from hash %s: %v", key, err) | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return fields, nil | ||||
| } | ||||
|  | ||||
| func (r *RedisHelper) HExists(key, field, value string) (bool, error) { | ||||
| 	exists, err := r.client.HExists(r.ctx, key, field).Result() | ||||
| 	if err != nil { | ||||
| 		return false, fmt.Errorf("check existence failed: %v", err) | ||||
| 	} | ||||
| 	if !exists { | ||||
| 		return false, nil | ||||
| 	} | ||||
|  | ||||
| 	storedValue, err := r.client.HGet(r.ctx, key, field).Result() | ||||
| 	if err != nil { | ||||
| 		return false, fmt.Errorf("get value failed: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	// 如果值是 JSON,比较前反序列化 | ||||
| 	var storedObj, inputObj interface{} | ||||
| 	if err := sonic.UnmarshalString(storedValue, &storedObj); err != nil { | ||||
| 		return false, fmt.Errorf("unmarshal stored value failed: %v", err) | ||||
| 	} | ||||
| 	if err := sonic.UnmarshalString(value, &inputObj); err != nil { | ||||
| 		return false, fmt.Errorf("unmarshal input value failed: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	// 比较两个对象(需要根据实际类型调整) | ||||
| 	return fmt.Sprintf("%v", storedObj) == fmt.Sprintf("%v", inputObj), nil | ||||
| } | ||||
|  | ||||
| // DelSet 从集合中删除元素 | ||||
| func (r *RedisHelper) DelSet(key string, value string) error { | ||||
| 	_, err := r.client.SRem(r.ctx, key, value).Result() | ||||
| 	if err != nil { | ||||
| 		log.Printf("Error del value from set %s: %v", key, err) | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (r *RedisHelper) Sismember(key string, value string) (bool, error) { | ||||
| 	result, err := r.client.SIsMember(r.ctx, key, value).Result() | ||||
| 	if err != nil { | ||||
| 		log.Printf("Error Sismember value from set %s: %v", key, err) | ||||
| 	} | ||||
| 	return result, err | ||||
| } | ||||
|  | ||||
| // sort set start | ||||
| // 批量添加 | ||||
| func (r *RedisHelper) BatchSortSet(key string, array []*redis.Z) error { | ||||
| 	pipe := r.client.Pipeline() | ||||
| 	for _, val := range array { | ||||
| 		pipe.ZAdd(r.ctx, key, val) | ||||
| 	} | ||||
|  | ||||
| 	_, err := pipe.Exec(r.ctx) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // 单一写入 sort set | ||||
| func (e *RedisHelper) SignelAdd(key string, score float64, member string) error { | ||||
| 	// 先删除具有相同 score 的所有成员 | ||||
| 	scoreStr := strconv.FormatFloat(score, 'g', -1, 64) | ||||
| 	_, err := e.client.ZRemRangeByScore(e.ctx, key, scoreStr, scoreStr).Result() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		fmt.Printf("删除score失败,err:%s", err.Error()) | ||||
| 	} | ||||
| 	_, err = e.client.ZAdd(e.ctx, key, &redis.Z{ | ||||
| 		Score:  score, | ||||
| 		Member: member, | ||||
| 	}).Result() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // 写入数据 | ||||
| func (e *RedisHelper) AddSortSet(key string, score float64, member string) error { | ||||
| 	_, err := e.client.ZAdd(e.ctx, key, &redis.Z{ | ||||
| 		Score:  score, | ||||
| 		Member: member, | ||||
| 	}).Result() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // 删除指定元素 | ||||
| func (e *RedisHelper) DelSortSet(key, member string) error { | ||||
| 	return e.client.ZRem(e.ctx, key, member).Err() | ||||
| } | ||||
|  | ||||
| // RemoveBeforeScore 移除 Sorted Set 中分数小于等于指定值的数据 | ||||
| // key: Sorted Set 的键 | ||||
| // score: 分数上限,所有小于等于此分数的元素将被移除 | ||||
| // 返回值: 移除的元素数量和可能的错误 | ||||
| func (e *RedisHelper) RemoveBeforeScore(key string, score float64) (int64, error) { | ||||
| 	if key == "" { | ||||
| 		return 0, errors.New("key 不能为空") | ||||
| 	} | ||||
| 	if math.IsNaN(score) || math.IsInf(score, 0) { | ||||
| 		return 0, errors.New("score 必须是有效数字") | ||||
| 	} | ||||
|  | ||||
| 	// 使用 ZRemRangeByScore 移除数据 | ||||
| 	count, err := e.client.ZRemRangeByScore(e.ctx, key, "-inf", strconv.FormatFloat(score, 'f', -1, 64)).Result() | ||||
| 	if err != nil { | ||||
| 		return 0, fmt.Errorf("移除 Sorted Set 数据失败, key: %s, score: %f, err: %v", key, score, err) | ||||
| 	} | ||||
|  | ||||
| 	return count, nil | ||||
| } | ||||
|  | ||||
| // GetNextAfterScore 获取指定分数及之后的第一条数据(包含指定分数) | ||||
| func (e *RedisHelper) GetNextAfterScore(key string, score float64) (string, error) { | ||||
| 	// 使用 ZRangeByScore 获取大于等于 score 的第一条数据 | ||||
| 	zs, err := e.client.ZRangeByScoreWithScores(e.ctx, key, &redis.ZRangeBy{ | ||||
| 		Min:    fmt.Sprintf("%f", score), // 包含指定分数 | ||||
| 		Max:    "+inf",                   // 上限为正无穷 | ||||
| 		Offset: 0,                        // 从第 0 条开始 | ||||
| 		Count:  1,                        // 只取 1 条 | ||||
| 	}).Result() | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return "", fmt.Errorf("获取数据失败: %v", err) | ||||
| 	} | ||||
| 	if len(zs) == 0 { | ||||
| 		return "", nil // 没有符合条件的元素 | ||||
| 	} | ||||
| 	return zs[0].Member.(string), nil | ||||
| } | ||||
|  | ||||
| /* | ||||
| 获取sort set 所有数据 | ||||
| */ | ||||
| func (e *RedisHelper) GetAllSortSet(key string) ([]string, error) { | ||||
| 	return e.client.ZRange(e.ctx, key, 0, -1).Result() | ||||
| } | ||||
|  | ||||
| /* | ||||
| 获取sort set 所有数据和score | ||||
| */ | ||||
| func (e *RedisHelper) GetRevRangeScoresSortSet(key string) ([]redis.Z, error) { | ||||
| 	return e.client.ZRevRangeWithScores(e.ctx, key, 0, -1).Result() | ||||
| } | ||||
|  | ||||
| // 获取最后一条数据 | ||||
| func (e *RedisHelper) GetLastSortSet(key string) ([]redis.Z, error) { | ||||
| 	// 获取最后一个元素及其分数 | ||||
| 	results, err := e.client.ZRevRangeWithScores(e.ctx, key, 0, 0).Result() | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("failed to get last member: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	// 如果没有数据,返回空 | ||||
| 	if len(results) == 0 { | ||||
| 		return []redis.Z{}, nil | ||||
| 	} | ||||
|  | ||||
| 	return results, nil | ||||
| } | ||||
|  | ||||
| // 获取指定区间数据 | ||||
| func (e *RedisHelper) GetSortSetMembers(key string, start, stop int64) ([]string, error) { | ||||
| 	return e.client.ZRange(e.ctx, key, start, stop).Result() | ||||
| } | ||||
|  | ||||
| // 获取最后N条数据 | ||||
| func (e *RedisHelper) GetLastSortSetMembers(key string, num int64) ([]string, error) { | ||||
| 	return e.client.ZRevRange(e.ctx, key, 0, num).Result() | ||||
| } | ||||
|  | ||||
| // func (e *RedisHelper) DelSortSet(key,) | ||||
|  | ||||
| // 根据索引范围删除 | ||||
| func (e *RedisHelper) DelByRank(key string, start, stop int64) error { | ||||
| 	return e.client.ZRemRangeByRank(e.ctx, key, start, stop).Err() | ||||
| } | ||||
|  | ||||
| // sort set end | ||||
|  | ||||
| // GetUserLoginPwdErrFre 获取用户登录密码错误频次 | ||||
| func (e *RedisHelper) GetUserLoginPwdErrFre(key string) (total int, wait time.Duration, err error) { | ||||
| 	total, _ = e.client.Get(e.ctx, key).Int() | ||||
| 	wait = e.client.TTL(e.ctx, key).Val() | ||||
| 	return | ||||
| } | ||||
|  | ||||
| // SetUserLoginPwdErrFre 设置用户登录密码错误频次 | ||||
| func (e *RedisHelper) SetUserLoginPwdErrFre(key string, expire time.Duration) (val int64, err error) { | ||||
| 	val, err = e.client.Incr(e.ctx, key).Result() | ||||
| 	if err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	if err = e.client.Expire(e.ctx, key, expire).Err(); err != nil { | ||||
| 		return | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
		Reference in New Issue
	
	Block a user