This commit is contained in:
2025-05-13 15:44:44 +08:00
parent 20a741ae11
commit 8e2324df0e
32 changed files with 2840 additions and 44 deletions

9
abis/ethereumabi/usdc.go Normal file
View File

@ -0,0 +1,9 @@
package ethereumabi
import "go-admin/abis"
var USDCErc20 = abis.TokenABI{
Address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
TestAddress: "0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238",
Decimals: 6,
}

10
abis/token.go Normal file
View File

@ -0,0 +1,10 @@
package abis
type TokenABI struct {
//token 合约地址
Address string
//测试网地址
TestAddress string
//token 最小单位位数
Decimals int
}

View File

@ -0,0 +1,193 @@
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 WmTransfer struct {
api.Api
}
// GetPage 获取批量转账任务列表
// @Summary 获取批量转账任务列表
// @Description 获取批量转账任务列表
// @Tags 批量转账任务
// @Param type query int64 false "类型 0-百分比 1-实际金额"
// @Param transferType query int64 false "转账类型 0-批量转出 1-批量汇总"
// @Param pageSize query int false "页条数"
// @Param pageIndex query int false "页码"
// @Success 200 {object} response.Response{data=response.Page{list=[]models.WmTransfer}} "{"code": 200, "data": [...]}"
// @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
}
p := actions.GetPermissionFromContext(c)
list := make([]models.WmTransfer, 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.WmTransfer} "{"code": 200, "data": [...]}"
// @Router /api/v1/wm-transfer/{id} [get]
// @Security Bearer
func (e WmTransfer) Get(c *gin.Context) {
req := dto.WmTransferGetReq{}
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
}
var object models.WmTransfer
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.WmTransferInsertReq true "data"
// @Success 200 {object} response.Response "{"code": 200, "message": "添加成功"}"
// @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.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.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 删除批量转账任务
// @Tags 批量转账任务
// @Param data body dto.WmTransferDeleteReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}"
// @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
}
// 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(), "删除成功")
}

View File

@ -0,0 +1,191 @@
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 WmTransferItem struct {
api.Api
}
// GetPage 获取批量转账明细列表
// @Summary 获取批量转账明细列表
// @Description 获取批量转账明细列表
// @Tags 批量转账明细
// @Param pageSize query int false "页条数"
// @Param pageIndex query int false "页码"
// @Success 200 {object} response.Response{data=response.Page{list=[]models.WmTransferItem}} "{"code": 200, "data": [...]}"
// @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
}
p := actions.GetPermissionFromContext(c)
list := make([]models.WmTransferItem, 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.WmTransferItem} "{"code": 200, "data": [...]}"
// @Router /api/v1/wm-transfer-item/{id} [get]
// @Security Bearer
func (e WmTransferItem) Get(c *gin.Context) {
req := dto.WmTransferItemGetReq{}
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
}
var object models.WmTransferItem
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.WmTransferItemInsertReq true "data"
// @Success 200 {object} response.Response "{"code": 200, "message": "添加成功"}"
// @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.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.WmTransferItemUpdateReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "message": "修改成功"}"
// @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.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.WmTransferItemDeleteReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}"
// @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
}
// 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(), "删除成功")
}

View File

@ -0,0 +1,154 @@
package apis
import (
"fmt"
"strings"
"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 WmWalletInfo struct {
api.Api
}
// GetPage 获取钱包信息列表
// @Summary 获取钱包信息列表
// @Description 获取钱包信息列表
// @Tags 钱包信息
// @Param privateKey query string false "钱包私钥"
// @Param pageSize query int false "页条数"
// @Param pageIndex query int false "页码"
// @Success 200 {object} response.Response{data=response.Page{list=[]models.WmWalletInfo}} "{"code": 200, "data": [...]}"
// @Router /api/v1/wm-wallet-info [get]
// @Security Bearer
func (e WmWalletInfo) GetPage(c *gin.Context) {
req := dto.WmWalletInfoGetPageReq{}
s := service.WmWalletInfo{}
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.WmWalletInfo, 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.WmWalletInfo} "{"code": 200, "data": [...]}"
// @Router /api/v1/wm-wallet-info/{id} [get]
// @Security Bearer
func (e WmWalletInfo) Get(c *gin.Context) {
req := dto.WmWalletInfoGetReq{}
s := service.WmWalletInfo{}
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.WmWalletInfo
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.WmWalletInfoInsertReq true "data"
// @Success 200 {object} response.Response "{"code": 200, "message": "添加成功"}"
// @Router /api/v1/wm-wallet-info [post]
// @Security Bearer
func (e WmWalletInfo) Insert(c *gin.Context) {
req := dto.WmWalletInfoBatchInsertReq{}
s := service.WmWalletInfo{}
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))
errs := s.Insert(&req)
e.OK(strings.Join(errs, "<br/>"), "创建成功")
}
// Delete 删除钱包信息
// @Summary 删除钱包信息
// @Description 删除钱包信息
// @Tags 钱包信息
// @Param data body dto.WmWalletInfoDeleteReq true "body"
// @Success 200 {object} response.Response "{"code": 200, "message": "删除成功"}"
// @Router /api/v1/wm-wallet-info [delete]
// @Security Bearer
func (e WmWalletInfo) Delete(c *gin.Context) {
s := service.WmWalletInfo{}
req := dto.WmWalletInfoDeleteReq{}
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(), "删除成功")
}

View File

@ -0,0 +1,31 @@
package models
import (
"go-admin/common/models"
)
type WmTransfer struct {
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
}
func (WmTransfer) TableName() string {
return "wm_transfer"
}
func (e *WmTransfer) Generate() models.ActiveRecord {
o := *e
return &o
}
func (e *WmTransfer) GetId() interface{} {
return e.Id
}

View File

@ -0,0 +1,34 @@
package models
import (
"go-admin/common/models"
)
type WmTransferItem struct {
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
}
func (WmTransferItem) TableName() string {
return "wm_transfer_item"
}
func (e *WmTransferItem) Generate() models.ActiveRecord {
o := *e
return &o
}
func (e *WmTransferItem) GetId() interface{} {
return e.Id
}

View File

@ -0,0 +1,30 @@
package models
import (
"go-admin/common/models"
"github.com/shopspring/decimal"
)
type WmWalletInfo struct {
models.Model
PrivateKey string `json:"privateKey" gorm:"type:varchar(50);comment:钱包私钥"`
Address string `json:"address" gorm:"type:varchar(50);comment:钱包地址"`
UsdcAmount decimal.Decimal `json:"usdcAmount" gorm:"type:decimal(18,8);comment:USDC余额"`
models.ModelTime
models.ControlBy
}
func (WmWalletInfo) TableName() string {
return "wm_wallet_info"
}
func (e *WmWalletInfo) Generate() models.ActiveRecord {
o := *e
return &o
}
func (e *WmWalletInfo) GetId() interface{} {
return e.Id
}

View 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, registerWmTransferRouter)
}
// registerWmTransferRouter
func registerWmTransferRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
api := apis.WmTransfer{}
r := v1.Group("/wm-transfer").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)
}
}

View 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, registerWmTransferItemRouter)
}
// registerWmTransferItemRouter
func registerWmTransferItemRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
api := apis.WmTransferItem{}
r := v1.Group("/wm-transfer-item").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)
}
}

View 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, registerWmWalletInfoRouter)
}
// registerWmWalletInfoRouter
func registerWmWalletInfoRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
api := apis.WmWalletInfo{}
r := v1.Group("/wm-wallet-info").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)
}
}

View File

@ -0,0 +1,98 @@
package dto
import (
"go-admin/app/admin/models"
"go-admin/common/dto"
common "go-admin/common/models"
)
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
}
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"`
}
func (m *WmTransferGetPageReq) GetNeedSearch() interface{} {
return *m
}
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
}
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 // 添加这而,需要记录是被谁创建的
}
func (s *WmTransferInsertReq) GetId() interface{} {
return s.Id
}
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
}
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{} {
return s.Id
}
// WmTransferGetReq 功能获取请求参数
type WmTransferGetReq struct {
Id int `uri:"id"`
}
func (s *WmTransferGetReq) GetId() interface{} {
return s.Id
}
// WmTransferDeleteReq 功能删除请求参数
type WmTransferDeleteReq struct {
Ids []int `json:"ids"`
}
func (s *WmTransferDeleteReq) GetId() interface{} {
return s.Ids
}

View File

@ -0,0 +1,111 @@
package dto
import (
"go-admin/app/admin/models"
"go-admin/common/dto"
common "go-admin/common/models"
)
type WmTransferItemGetPageReq struct {
dto.Pagination `search:"-"`
WmTransferItemOrder
}
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"`
}
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 (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{} {
return s.Id
}
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
}
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{} {
return s.Id
}
// WmTransferItemGetReq 功能获取请求参数
type WmTransferItemGetReq struct {
Id int `uri:"id"`
}
func (s *WmTransferItemGetReq) GetId() interface{} {
return s.Id
}
// WmTransferItemDeleteReq 功能删除请求参数
type WmTransferItemDeleteReq struct {
Ids []int `json:"ids"`
}
func (s *WmTransferItemDeleteReq) GetId() interface{} {
return s.Ids
}

View File

@ -0,0 +1,105 @@
package dto
import (
"errors"
"go-admin/app/admin/models"
"go-admin/common/dto"
common "go-admin/common/models"
"strings"
)
type WmWalletInfoGetPageReq struct {
dto.Pagination `search:"-"`
PrivateKey string `form:"privateKey" search:"type:exact;column:private_key;table:wm_wallet_info" comment:"钱包私钥"`
WmWalletInfoOrder
}
type WmWalletInfoOrder struct {
Id string `form:"idOrder" search:"type:order;column:id;table:wm_wallet_info"`
PrivateKey string `form:"privateKeyOrder" search:"type:order;column:private_key;table:wm_wallet_info"`
Address string `form:"addressOrder" search:"type:order;column:address;table:wm_wallet_info"`
CreateBy string `form:"createByOrder" search:"type:order;column:create_by;table:wm_wallet_info"`
UpdateBy string `form:"updateByOrder" search:"type:order;column:update_by;table:wm_wallet_info"`
CreatedAt string `form:"createdAtOrder" search:"type:order;column:created_at;table:wm_wallet_info"`
UpdatedAt string `form:"updatedAtOrder" search:"type:order;column:updated_at;table:wm_wallet_info"`
DeletedAt string `form:"deletedAtOrder" search:"type:order;column:deleted_at;table:wm_wallet_info"`
}
func (m *WmWalletInfoGetPageReq) GetNeedSearch() interface{} {
return *m
}
type WmWalletInfoBatchInsertReq struct {
Keys string `json:"keys"`
common.ControlBy
}
func (s *WmWalletInfoBatchInsertReq) Valid() error {
s.Keys = strings.ReplaceAll(s.Keys, " ", "")
s.Keys = strings.ReplaceAll(s.Keys, ",", "\n")
s.Keys = strings.ReplaceAll(s.Keys, "", "\n")
if s.Keys == "" {
return errors.New("请至少输入一条数据")
}
return nil
}
type WmWalletInfoInsertReq struct {
Id int `json:"-" comment:"主键Id"` // 主键Id
PrivateKey string `json:"privateKey" comment:"钱包私钥"`
Address string `json:"address" comment:"钱包地址"`
common.ControlBy
}
func (s *WmWalletInfoInsertReq) Generate(model *models.WmWalletInfo) {
if s.Id == 0 {
model.Model = common.Model{Id: s.Id}
}
model.PrivateKey = s.PrivateKey
model.Address = s.Address
model.CreateBy = s.CreateBy // 添加这而,需要记录是被谁创建的
}
func (s *WmWalletInfoInsertReq) GetId() interface{} {
return s.Id
}
type WmWalletInfoUpdateReq struct {
Id int `uri:"id" comment:"主键Id"` // 主键Id
PrivateKey string `json:"privateKey" comment:"钱包私钥"`
Address string `json:"address" comment:"钱包地址"`
common.ControlBy
}
func (s *WmWalletInfoUpdateReq) Generate(model *models.WmWalletInfo) {
if s.Id == 0 {
model.Model = common.Model{Id: s.Id}
}
model.PrivateKey = s.PrivateKey
model.Address = s.Address
model.UpdateBy = s.UpdateBy // 添加这而,需要记录是被谁更新的
}
func (s *WmWalletInfoUpdateReq) GetId() interface{} {
return s.Id
}
// WmWalletInfoGetReq 功能获取请求参数
type WmWalletInfoGetReq struct {
Id int `uri:"id"`
}
func (s *WmWalletInfoGetReq) GetId() interface{} {
return s.Id
}
// WmWalletInfoDeleteReq 功能删除请求参数
type WmWalletInfoDeleteReq struct {
Ids []int `json:"ids"`
}
func (s *WmWalletInfoDeleteReq) GetId() interface{} {
return s.Ids
}

View File

@ -0,0 +1,109 @@
package service
import (
"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"
)
type WmTransfer struct {
service.Service
}
// GetPage 获取WmTransfer列表
func (e *WmTransfer) GetPage(c *dto.WmTransferGetPageReq, p *actions.DataPermission, list *[]models.WmTransfer, count *int64) error {
var err error
var data models.WmTransfer
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("WmTransferService GetPage error:%s \r\n", err)
return err
}
return nil
}
// Get 获取WmTransfer对象
func (e *WmTransfer) Get(d *dto.WmTransferGetReq, p *actions.DataPermission, model *models.WmTransfer) error {
var data models.WmTransfer
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 GetWmTransfer error:%s \r\n", err)
return err
}
if err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
return nil
}
// 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
if err != nil {
e.Log.Errorf("WmTransferService Insert error:%s \r\n", err)
return err
}
return 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)
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
func (e *WmTransfer) Remove(d *dto.WmTransferDeleteReq, p *actions.DataPermission) error {
var data models.WmTransfer
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 RemoveWmTransfer error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权删除该数据")
}
return nil
}

View File

@ -0,0 +1,109 @@
package service
import (
"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"
)
type WmTransferItem struct {
service.Service
}
// GetPage 获取WmTransferItem列表
func (e *WmTransferItem) GetPage(c *dto.WmTransferItemGetPageReq, p *actions.DataPermission, list *[]models.WmTransferItem, count *int64) error {
var err error
var data models.WmTransferItem
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("WmTransferItemService GetPage error:%s \r\n", err)
return err
}
return nil
}
// Get 获取WmTransferItem对象
func (e *WmTransferItem) Get(d *dto.WmTransferItemGetReq, p *actions.DataPermission, model *models.WmTransferItem) error {
var data models.WmTransferItem
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 GetWmTransferItem error:%s \r\n", err)
return err
}
if err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
return nil
}
// Insert 创建WmTransferItem对象
func (e *WmTransferItem) Insert(c *dto.WmTransferItemInsertReq) error {
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)
return err
}
return nil
}
// 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)
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
func (e *WmTransferItem) Remove(d *dto.WmTransferItemDeleteReq, p *actions.DataPermission) error {
var data models.WmTransferItem
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 RemoveWmTransferItem error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权删除该数据")
}
return nil
}

View File

@ -0,0 +1,174 @@
package service
import (
"errors"
"strings"
"github.com/go-admin-team/go-admin-core/sdk/service"
"gorm.io/gorm"
"go-admin/abis/ethereumabi"
"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"
"go-admin/utils/stringhelper"
)
type WmWalletInfo struct {
service.Service
}
// GetPage 获取WmWalletInfo列表
func (e *WmWalletInfo) GetPage(c *dto.WmWalletInfoGetPageReq, p *actions.DataPermission, list *[]models.WmWalletInfo, count *int64) error {
var err error
var data models.WmWalletInfo
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("WmWalletInfoService 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
}
// Get 获取WmWalletInfo对象
func (e *WmWalletInfo) Get(d *dto.WmWalletInfoGetReq, p *actions.DataPermission, model *models.WmWalletInfo) error {
var data models.WmWalletInfo
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 GetWmWalletInfo error:%s \r\n", err)
return err
}
if err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
return nil
}
// Insert 创建WmWalletInfo对象
func (e *WmWalletInfo) Insert(c *dto.WmWalletInfoBatchInsertReq) []string {
errs := []string{}
var count int64
keys := strings.Split(c.Keys, "\n")
for _, key := range keys {
if key == "" {
continue
}
var data models.WmWalletInfo
data.PrivateKey = aeshelper.AesEcbEncrypt(key)
_, address, _ := ethtransferhelper.GetAddressFromPrivateKey(key)
data.Address = address.String()
if err := e.Orm.Model(data).Where("private_key =?", data.PrivateKey).Count(&count).Error; err != nil {
e.Log.Errorf("db error:%s", err)
}
if count == 0 {
if err := e.Orm.Create(&data).Error; err != nil {
e.Log.Errorf("db error:%s", err)
errs = append(errs, key)
}
}
}
return errs
}
// Update 修改WmWalletInfo对象
func (e *WmWalletInfo) Update(c *dto.WmWalletInfoUpdateReq, p *actions.DataPermission) error {
var err error
var data = models.WmWalletInfo{}
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("WmWalletInfoService Save error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权更新该数据")
}
return nil
}
// Remove 删除WmWalletInfo
func (e *WmWalletInfo) Remove(d *dto.WmWalletInfoDeleteReq, p *actions.DataPermission) error {
var data models.WmWalletInfo
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 RemoveWmWalletInfo error:%s \r\n", err)
return err
}
if db.RowsAffected == 0 {
return errors.New("无权删除该数据")
}
return nil
}
// ScheduledTask 定时任务
func (e *WmWalletInfo) ScheduledTask() error {
var datas []models.WmWalletInfo
if err := e.Orm.Model(models.WmWalletInfo{}).Find(&datas).Error; err != nil {
e.Log.Errorf("db error:%s", err)
return err
}
client, err := ethbalanceofhelper.EthClientWithProxy(config.ExtConfig.ApiEndpoint, config.ExtConfig.ProxyUrl)
if err != nil {
e.Log.Errorf("ethclient error:%s", err)
return err
}
for i := range datas {
amount, err := ethbalanceofhelper.GetERC20Balance(client, ethereumabi.USDCErc20, datas[i].Address)
if err != nil {
e.Log.Errorf("GetERC20Balance error:%s", err)
continue
}
datas[i].UsdcAmount = amount
if err := e.Orm.Model(&datas[i]).Update("usdc_amount", amount).Error; err != nil {
e.Log.Errorf("db error:%s", err)
continue
}
}
return nil
}

31
app/jobs/transfer_job.go Normal file
View File

@ -0,0 +1,31 @@
package jobs
import (
"go-admin/app/admin/service"
"github.com/go-admin-team/go-admin-core/logger"
"github.com/go-admin-team/go-admin-core/sdk"
"gorm.io/gorm"
)
type TransferJob struct{}
// 定期转账
func (t TransferJob) Exec(arg interface{}) error {
walletService := service.WmWalletInfo{}
walletService.Orm = getDefaultDb()
walletService.Log = logger.NewHelper(logger.DefaultLogger)
return walletService.ScheduledTask()
}
func getDefaultDb() *gorm.DB {
dbs := sdk.Runtime.GetDb()
var db *gorm.DB
for _, item := range dbs {
db = item
break
}
return db
}

View File

@ -0,0 +1,23 @@
package jobs
import (
"go-admin/config"
"testing"
"github.com/go-admin-team/go-admin-core/sdk"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func TestTransferJob(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 := TransferJob{}
job.Exec(nil)
}

View File

@ -3,12 +3,17 @@ package config
var ExtConfig Extend var ExtConfig Extend
// Extend 扩展配置 // Extend 扩展配置
// extend: //
// demo: // extend:
// name: demo-name // demo:
// name: demo-name
//
// 使用方法: config.ExtConfig......即可!! // 使用方法: config.ExtConfig......即可!!
type Extend struct { type Extend struct {
AMap AMap // 这里配置对应配置文件的结构即可 AMap AMap // 这里配置对应配置文件的结构即可
ApiEndpoint string //rpc api地址
ProxyUrl string //代理地址
} }
type AMap struct { type AMap struct {

View File

@ -5,7 +5,7 @@ settings:
# 服务器ip默认使用 0.0.0.0 # 服务器ip默认使用 0.0.0.0
host: 0.0.0.0 host: 0.0.0.0
# 服务名称 # 服务名称
name: testApp name: ethTransfer
# 端口号 # 端口号
port: 8000 # 服务端口号 port: 8000 # 服务端口号
readtimeout: 1 readtimeout: 1
@ -23,7 +23,7 @@ settings:
enableddb: false enableddb: false
jwt: jwt:
# token 密钥,生产环境时及的修改 # token 密钥,生产环境时及的修改
secret: go-admin secret: eth-transfer-admin
# token 过期时间 单位:秒 # token 过期时间 单位:秒
timeout: 3600 timeout: 3600
database: database:
@ -31,7 +31,7 @@ settings:
# sqlserver: sqlserver://用户名:密码@地址?database=数据库名 # sqlserver: sqlserver://用户名:密码@地址?database=数据库名
driver: mysql driver: mysql
# 数据库连接字符串 mysql 缺省信息 charset=utf8&parseTime=True&loc=Local&timeout=1000ms # 数据库连接字符串 mysql 缺省信息 charset=utf8&parseTime=True&loc=Local&timeout=1000ms
source: user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8&parseTime=True&loc=Local&timeout=1000ms source: root:123456@tcp(127.0.0.1:3306)/eth_transfer?charset=utf8&parseTime=True&loc=Local&timeout=1000ms
# databases: # databases:
# 'locaohost:8000': # 'locaohost:8000':
# driver: mysql # driver: mysql
@ -42,17 +42,19 @@ settings:
# - user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8&parseTime=True&loc=Local&timeout=1000ms # - user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8&parseTime=True&loc=Local&timeout=1000ms
gen: gen:
# 代码生成读取的数据库名称 # 代码生成读取的数据库名称
dbname: dbname dbname: eth_transfer
# 代码生成是使用前端代码存放位置需要指定到src文件夹相对路径 # 代码生成是使用前端代码存放位置需要指定到src文件夹相对路径
frontpath: ../go-admin-ui/src frontpath: ../go-admin-ui/src
extend: # 扩展项使用说明 extend: # 扩展项使用说明
demo: demo:
name: data name: data
apiEndpoint: https://stylish-cool-fire.ethereum-sepolia.quiknode.pro/17572db4c091accfa5dc6faa0c60a805e5173459
cache: cache:
# redis: redis:
# addr: 127.0.0.1:6379 addr: 127.0.0.1:6379
# password: xxxxxx password: ''
# db: 2 db: 15
# key存在即可 # key存在即可
memory: '' memory: ''
queue: queue:

92
go.mod
View File

@ -1,6 +1,8 @@
module go-admin module go-admin
go 1.18 go 1.23.0
toolchain go1.24.2
require ( require (
github.com/alibaba/sentinel-golang v1.0.4 github.com/alibaba/sentinel-golang v1.0.4
@ -9,6 +11,7 @@ require (
github.com/bitly/go-simplejson v0.5.0 github.com/bitly/go-simplejson v0.5.0
github.com/bytedance/go-tagexpr/v2 v2.7.12 github.com/bytedance/go-tagexpr/v2 v2.7.12
github.com/casbin/casbin/v2 v2.51.2 github.com/casbin/casbin/v2 v2.51.2
github.com/ethereum/go-ethereum v1.15.11
github.com/gin-gonic/gin v1.9.1 github.com/gin-gonic/gin v1.9.1
github.com/go-admin-team/go-admin-core v1.4.1-0.20220809101213-21187928f7d9 github.com/go-admin-team/go-admin-core v1.4.1-0.20220809101213-21187928f7d9
github.com/go-admin-team/go-admin-core/sdk v1.4.1-0.20220809101213-21187928f7d9 github.com/go-admin-team/go-admin-core/sdk v1.4.1-0.20220809101213-21187928f7d9
@ -17,16 +20,16 @@ require (
github.com/mssola/user_agent v0.5.2 github.com/mssola/user_agent v0.5.2
github.com/opentracing/opentracing-go v1.1.0 github.com/opentracing/opentracing-go v1.1.0
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.11.1 github.com/prometheus/client_golang v1.12.0
github.com/qiniu/go-sdk/v7 v7.11.1 github.com/qiniu/go-sdk/v7 v7.11.1
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
github.com/shirou/gopsutil/v3 v3.22.1 github.com/shirou/gopsutil/v3 v3.22.1
github.com/spf13/cobra v1.0.0 github.com/spf13/cobra v1.8.1
github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a
github.com/swaggo/gin-swagger v1.5.0 github.com/swaggo/gin-swagger v1.5.0
github.com/swaggo/swag v1.8.3 github.com/swaggo/swag v1.8.3
github.com/unrolled/secure v1.0.8 github.com/unrolled/secure v1.0.8
golang.org/x/crypto v0.9.0 golang.org/x/crypto v0.38.0
gorm.io/driver/mysql v1.3.5 gorm.io/driver/mysql v1.3.5
gorm.io/driver/postgres v1.3.8 gorm.io/driver/postgres v1.3.8
gorm.io/driver/sqlite v1.3.6 gorm.io/driver/sqlite v1.3.6
@ -38,26 +41,41 @@ require (
github.com/BurntSushi/toml v0.3.1 // indirect github.com/BurntSushi/toml v0.3.1 // indirect
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
github.com/KyleBanks/depth v1.2.1 // indirect github.com/KyleBanks/depth v1.2.1 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect github.com/baiyubin/aliyun-sts-go-sdk v0.0.0-20180326062324-cfa1a18b161f // indirect
github.com/beorn7/perks v1.0.1 // indirect 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/bsm/redislock v0.5.0 // indirect
github.com/bytedance/sonic v1.9.1 // indirect
github.com/casbin/redis-watcher/v2 v2.0.0-20220614104201-0e70bf2be930 // indirect github.com/casbin/redis-watcher/v2 v2.0.0-20220614104201-0e70bf2be930 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/chanxuehong/rand v0.0.0-20201110082127-2f19a1bdd973 // indirect github.com/chanxuehong/rand v0.0.0-20201110082127-2f19a1bdd973 // indirect
github.com/chanxuehong/wechat v0.0.0-20201110083048-0180211b69fd // indirect github.com/chanxuehong/wechat v0.0.0-20201110083048-0180211b69fd // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // 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
github.com/crate-crypto/go-eth-kzg v1.3.0 // indirect
github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/denisenkom/go-mssqldb v0.12.0 // indirect github.com/denisenkom/go-mssqldb v0.12.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/fatih/color v1.9.0 // indirect github.com/ethereum/c-kzg-4844/v2 v2.1.0 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/ethereum/go-verkle v0.2.2 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/forgoer/openssl v1.6.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/ghodss/yaml v1.0.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect
github.com/git-chglog/git-chglog v0.0.0-20190611050339-63a4e637021f // indirect github.com/git-chglog/git-chglog v0.0.0-20190611050339-63a4e637021f // indirect
github.com/go-admin-team/go-admin-core/plugins/logger/zap v0.0.0-20210610020726-2db73adb505d // indirect github.com/go-admin-team/go-admin-core/plugins/logger/zap v0.0.0-20210610020726-2db73adb505d // indirect
github.com/go-admin-team/gorm-adapter/v3 v3.7.8-0.20220809100335-eaf9f67b3d21 // indirect github.com/go-admin-team/gorm-adapter/v3 v3.7.8-0.20220809100335-eaf9f67b3d21 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.6 // indirect github.com/go-openapi/jsonreference v0.19.6 // indirect
github.com/go-openapi/spec v0.20.4 // indirect github.com/go-openapi/spec v0.20.4 // indirect
@ -68,17 +86,19 @@ require (
github.com/go-redis/redis/v7 v7.4.0 // indirect github.com/go-redis/redis/v7 v7.4.0 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect github.com/goccy/go-json v0.10.4 // indirect
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 // indirect github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/protobuf v1.5.0 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.1 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/gorilla/websocket v1.4.2 // indirect github.com/gorilla/websocket v1.4.2 // indirect
github.com/henrylee2cn/ameda v1.4.10 // indirect github.com/henrylee2cn/ameda v1.4.10 // indirect
github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8 // indirect github.com/henrylee2cn/goutil v0.0.0-20210127050712-89660552f6f8 // indirect
github.com/holiman/uint256 v1.3.2 // indirect
github.com/imdario/mergo v0.3.9 // indirect github.com/imdario/mergo v0.3.9 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.12.1 // indirect github.com/jackc/pgconn v1.12.1 // indirect
github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgio v1.0.0 // indirect
@ -92,52 +112,60 @@ require (
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/leodido/go-urn v1.2.4 // indirect github.com/leodido/go-urn v1.2.4 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/mailru/easyjson v0.7.6 // indirect github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-colorable v0.1.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-sqlite3 v1.14.12 // indirect github.com/mattn/go-sqlite3 v1.14.12 // indirect
github.com/mattn/goveralls v0.0.2 // indirect github.com/mattn/goveralls v0.0.2 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mojocn/base64Captcha v1.3.1 // indirect github.com/mojocn/base64Captcha v1.3.1 // indirect
github.com/nsqio/go-nsq v1.0.8 // indirect github.com/nsqio/go-nsq v1.0.8 // indirect
github.com/nyaruka/phonenumbers v1.0.55 // indirect github.com/nyaruka/phonenumbers v1.0.55 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a // indirect
github.com/prometheus/common v0.26.0 // indirect github.com/prometheus/common v0.32.1 // indirect
github.com/prometheus/procfs v0.6.0 // indirect github.com/prometheus/procfs v0.7.3 // indirect
github.com/robinjoseph08/redisqueue/v2 v2.1.0 // indirect github.com/robinjoseph08/redisqueue/v2 v2.1.0 // indirect
github.com/russross/blackfriday/v2 v2.0.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shamsher31/goimgext v1.0.0 // indirect github.com/shamsher31/goimgext v1.0.0 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/spf13/cast v1.3.1 // indirect github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/pflag v1.0.3 // indirect github.com/spf13/pflag v1.0.5 // indirect
github.com/tklauser/go-sysconf v0.3.9 // indirect github.com/supranational/blst v0.3.14 // indirect
github.com/tklauser/numcpus v0.3.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/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/ugorji/go/codec v1.2.11 // indirect
github.com/urfave/cli v1.22.1 // indirect github.com/urfave/cli v1.22.1 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.uber.org/atomic v1.6.0 // indirect go.uber.org/atomic v1.6.0 // indirect
go.uber.org/multierr v1.5.0 // indirect go.uber.org/multierr v1.5.0 // indirect
go.uber.org/zap v1.15.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/image v0.1.0 // indirect
golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect golang.org/x/net v0.36.0 // indirect
golang.org/x/net v0.10.0 // indirect golang.org/x/sync v0.14.0 // indirect
golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.33.0 // indirect
golang.org/x/sys v0.8.0 // indirect golang.org/x/text v0.25.0 // indirect
golang.org/x/text v0.9.0 // indirect golang.org/x/time v0.9.0 // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect golang.org/x/tools v0.29.0 // indirect
golang.org/x/tools v0.6.0 // indirect google.golang.org/protobuf v1.34.2 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/AlecAivazis/survey.v1 v1.8.5 // indirect gopkg.in/AlecAivazis/survey.v1 v1.8.5 // indirect
gopkg.in/kyokomi/emoji.v1 v1.5.1 // indirect gopkg.in/kyokomi/emoji.v1 v1.5.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/plugin/dbresolver v1.2.2 // indirect gorm.io/plugin/dbresolver v1.2.2 // indirect
rsc.io/tmplfunc v0.0.3 // indirect
) )
//replace ( //replace (

1
static/abis/usdc.abi Normal file
View File

@ -0,0 +1 @@
[{"constant":false,"inputs":[{"name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newImplementation","type":"address"},{"name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"implementation","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"admin","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_implementation","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousAdmin","type":"address"},{"indexed":false,"name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"implementation","type":"address"}],"name":"Upgraded","type":"event"}]

596
static/abis/usdc.go Normal file
View File

@ -0,0 +1,596 @@
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package usdc
import (
"errors"
"math/big"
"strings"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = errors.New
_ = big.NewInt
_ = strings.NewReader
_ = ethereum.NotFound
_ = bind.Bind
_ = common.Big1
_ = types.BloomLookup
_ = event.NewSubscription
_ = abi.ConvertType
)
// UsdcMetaData contains all meta data concerning the Usdc contract.
var UsdcMetaData = &bind.MetaData{
ABI: "[{\"constant\":false,\"inputs\":[{\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"newImplementation\",\"type\":\"address\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_implementation\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"}]",
}
// UsdcABI is the input ABI used to generate the binding from.
// Deprecated: Use UsdcMetaData.ABI instead.
var UsdcABI = UsdcMetaData.ABI
// Usdc is an auto generated Go binding around an Ethereum contract.
type Usdc struct {
UsdcCaller // Read-only binding to the contract
UsdcTransactor // Write-only binding to the contract
UsdcFilterer // Log filterer for contract events
}
// UsdcCaller is an auto generated read-only Go binding around an Ethereum contract.
type UsdcCaller struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// UsdcTransactor is an auto generated write-only Go binding around an Ethereum contract.
type UsdcTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// UsdcFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
type UsdcFilterer struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// UsdcSession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type UsdcSession struct {
Contract *Usdc // Generic contract binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// UsdcCallerSession is an auto generated read-only Go binding around an Ethereum contract,
// with pre-set call options.
type UsdcCallerSession struct {
Contract *UsdcCaller // Generic contract caller binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
}
// UsdcTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
// with pre-set transact options.
type UsdcTransactorSession struct {
Contract *UsdcTransactor // Generic contract transactor binding to set the session for
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// UsdcRaw is an auto generated low-level Go binding around an Ethereum contract.
type UsdcRaw struct {
Contract *Usdc // Generic contract binding to access the raw methods on
}
// UsdcCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
type UsdcCallerRaw struct {
Contract *UsdcCaller // Generic read-only contract binding to access the raw methods on
}
// UsdcTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
type UsdcTransactorRaw struct {
Contract *UsdcTransactor // Generic write-only contract binding to access the raw methods on
}
// NewUsdc creates a new instance of Usdc, bound to a specific deployed contract.
func NewUsdc(address common.Address, backend bind.ContractBackend) (*Usdc, error) {
contract, err := bindUsdc(address, backend, backend, backend)
if err != nil {
return nil, err
}
return &Usdc{UsdcCaller: UsdcCaller{contract: contract}, UsdcTransactor: UsdcTransactor{contract: contract}, UsdcFilterer: UsdcFilterer{contract: contract}}, nil
}
// NewUsdcCaller creates a new read-only instance of Usdc, bound to a specific deployed contract.
func NewUsdcCaller(address common.Address, caller bind.ContractCaller) (*UsdcCaller, error) {
contract, err := bindUsdc(address, caller, nil, nil)
if err != nil {
return nil, err
}
return &UsdcCaller{contract: contract}, nil
}
// NewUsdcTransactor creates a new write-only instance of Usdc, bound to a specific deployed contract.
func NewUsdcTransactor(address common.Address, transactor bind.ContractTransactor) (*UsdcTransactor, error) {
contract, err := bindUsdc(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &UsdcTransactor{contract: contract}, nil
}
// NewUsdcFilterer creates a new log filterer instance of Usdc, bound to a specific deployed contract.
func NewUsdcFilterer(address common.Address, filterer bind.ContractFilterer) (*UsdcFilterer, error) {
contract, err := bindUsdc(address, nil, nil, filterer)
if err != nil {
return nil, err
}
return &UsdcFilterer{contract: contract}, nil
}
// bindUsdc binds a generic wrapper to an already deployed contract.
func bindUsdc(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := UsdcMetaData.GetAbi()
if err != nil {
return nil, err
}
return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_Usdc *UsdcRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _Usdc.Contract.UsdcCaller.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_Usdc *UsdcRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _Usdc.Contract.UsdcTransactor.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_Usdc *UsdcRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _Usdc.Contract.UsdcTransactor.contract.Transact(opts, method, params...)
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_Usdc *UsdcCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
return _Usdc.Contract.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_Usdc *UsdcTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _Usdc.Contract.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_Usdc *UsdcTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _Usdc.Contract.contract.Transact(opts, method, params...)
}
// Admin is a free data retrieval call binding the contract method 0xf851a440.
//
// Solidity: function admin() view returns(address)
func (_Usdc *UsdcCaller) Admin(opts *bind.CallOpts) (common.Address, error) {
var out []interface{}
err := _Usdc.contract.Call(opts, &out, "admin")
if err != nil {
return *new(common.Address), err
}
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
return out0, err
}
// Admin is a free data retrieval call binding the contract method 0xf851a440.
//
// Solidity: function admin() view returns(address)
func (_Usdc *UsdcSession) Admin() (common.Address, error) {
return _Usdc.Contract.Admin(&_Usdc.CallOpts)
}
// Admin is a free data retrieval call binding the contract method 0xf851a440.
//
// Solidity: function admin() view returns(address)
func (_Usdc *UsdcCallerSession) Admin() (common.Address, error) {
return _Usdc.Contract.Admin(&_Usdc.CallOpts)
}
// Implementation is a free data retrieval call binding the contract method 0x5c60da1b.
//
// Solidity: function implementation() view returns(address)
func (_Usdc *UsdcCaller) Implementation(opts *bind.CallOpts) (common.Address, error) {
var out []interface{}
err := _Usdc.contract.Call(opts, &out, "implementation")
if err != nil {
return *new(common.Address), err
}
out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address)
return out0, err
}
// Implementation is a free data retrieval call binding the contract method 0x5c60da1b.
//
// Solidity: function implementation() view returns(address)
func (_Usdc *UsdcSession) Implementation() (common.Address, error) {
return _Usdc.Contract.Implementation(&_Usdc.CallOpts)
}
// Implementation is a free data retrieval call binding the contract method 0x5c60da1b.
//
// Solidity: function implementation() view returns(address)
func (_Usdc *UsdcCallerSession) Implementation() (common.Address, error) {
return _Usdc.Contract.Implementation(&_Usdc.CallOpts)
}
// ChangeAdmin is a paid mutator transaction binding the contract method 0x8f283970.
//
// Solidity: function changeAdmin(address newAdmin) returns()
func (_Usdc *UsdcTransactor) ChangeAdmin(opts *bind.TransactOpts, newAdmin common.Address) (*types.Transaction, error) {
return _Usdc.contract.Transact(opts, "changeAdmin", newAdmin)
}
// ChangeAdmin is a paid mutator transaction binding the contract method 0x8f283970.
//
// Solidity: function changeAdmin(address newAdmin) returns()
func (_Usdc *UsdcSession) ChangeAdmin(newAdmin common.Address) (*types.Transaction, error) {
return _Usdc.Contract.ChangeAdmin(&_Usdc.TransactOpts, newAdmin)
}
// ChangeAdmin is a paid mutator transaction binding the contract method 0x8f283970.
//
// Solidity: function changeAdmin(address newAdmin) returns()
func (_Usdc *UsdcTransactorSession) ChangeAdmin(newAdmin common.Address) (*types.Transaction, error) {
return _Usdc.Contract.ChangeAdmin(&_Usdc.TransactOpts, newAdmin)
}
// UpgradeTo is a paid mutator transaction binding the contract method 0x3659cfe6.
//
// Solidity: function upgradeTo(address newImplementation) returns()
func (_Usdc *UsdcTransactor) UpgradeTo(opts *bind.TransactOpts, newImplementation common.Address) (*types.Transaction, error) {
return _Usdc.contract.Transact(opts, "upgradeTo", newImplementation)
}
// UpgradeTo is a paid mutator transaction binding the contract method 0x3659cfe6.
//
// Solidity: function upgradeTo(address newImplementation) returns()
func (_Usdc *UsdcSession) UpgradeTo(newImplementation common.Address) (*types.Transaction, error) {
return _Usdc.Contract.UpgradeTo(&_Usdc.TransactOpts, newImplementation)
}
// UpgradeTo is a paid mutator transaction binding the contract method 0x3659cfe6.
//
// Solidity: function upgradeTo(address newImplementation) returns()
func (_Usdc *UsdcTransactorSession) UpgradeTo(newImplementation common.Address) (*types.Transaction, error) {
return _Usdc.Contract.UpgradeTo(&_Usdc.TransactOpts, newImplementation)
}
// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286.
//
// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns()
func (_Usdc *UsdcTransactor) UpgradeToAndCall(opts *bind.TransactOpts, newImplementation common.Address, data []byte) (*types.Transaction, error) {
return _Usdc.contract.Transact(opts, "upgradeToAndCall", newImplementation, data)
}
// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286.
//
// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns()
func (_Usdc *UsdcSession) UpgradeToAndCall(newImplementation common.Address, data []byte) (*types.Transaction, error) {
return _Usdc.Contract.UpgradeToAndCall(&_Usdc.TransactOpts, newImplementation, data)
}
// UpgradeToAndCall is a paid mutator transaction binding the contract method 0x4f1ef286.
//
// Solidity: function upgradeToAndCall(address newImplementation, bytes data) payable returns()
func (_Usdc *UsdcTransactorSession) UpgradeToAndCall(newImplementation common.Address, data []byte) (*types.Transaction, error) {
return _Usdc.Contract.UpgradeToAndCall(&_Usdc.TransactOpts, newImplementation, data)
}
// Fallback is a paid mutator transaction binding the contract fallback function.
//
// Solidity: fallback() payable returns()
func (_Usdc *UsdcTransactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) {
return _Usdc.contract.RawTransact(opts, calldata)
}
// Fallback is a paid mutator transaction binding the contract fallback function.
//
// Solidity: fallback() payable returns()
func (_Usdc *UsdcSession) Fallback(calldata []byte) (*types.Transaction, error) {
return _Usdc.Contract.Fallback(&_Usdc.TransactOpts, calldata)
}
// Fallback is a paid mutator transaction binding the contract fallback function.
//
// Solidity: fallback() payable returns()
func (_Usdc *UsdcTransactorSession) Fallback(calldata []byte) (*types.Transaction, error) {
return _Usdc.Contract.Fallback(&_Usdc.TransactOpts, calldata)
}
// UsdcAdminChangedIterator is returned from FilterAdminChanged and is used to iterate over the raw logs and unpacked data for AdminChanged events raised by the Usdc contract.
type UsdcAdminChangedIterator struct {
Event *UsdcAdminChanged // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *UsdcAdminChangedIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(UsdcAdminChanged)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(UsdcAdminChanged)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *UsdcAdminChangedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *UsdcAdminChangedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// UsdcAdminChanged represents a AdminChanged event raised by the Usdc contract.
type UsdcAdminChanged struct {
PreviousAdmin common.Address
NewAdmin common.Address
Raw types.Log // Blockchain specific contextual infos
}
// FilterAdminChanged is a free log retrieval operation binding the contract event 0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f.
//
// Solidity: event AdminChanged(address previousAdmin, address newAdmin)
func (_Usdc *UsdcFilterer) FilterAdminChanged(opts *bind.FilterOpts) (*UsdcAdminChangedIterator, error) {
logs, sub, err := _Usdc.contract.FilterLogs(opts, "AdminChanged")
if err != nil {
return nil, err
}
return &UsdcAdminChangedIterator{contract: _Usdc.contract, event: "AdminChanged", logs: logs, sub: sub}, nil
}
// WatchAdminChanged is a free log subscription operation binding the contract event 0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f.
//
// Solidity: event AdminChanged(address previousAdmin, address newAdmin)
func (_Usdc *UsdcFilterer) WatchAdminChanged(opts *bind.WatchOpts, sink chan<- *UsdcAdminChanged) (event.Subscription, error) {
logs, sub, err := _Usdc.contract.WatchLogs(opts, "AdminChanged")
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(UsdcAdminChanged)
if err := _Usdc.contract.UnpackLog(event, "AdminChanged", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// ParseAdminChanged is a log parse operation binding the contract event 0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f.
//
// Solidity: event AdminChanged(address previousAdmin, address newAdmin)
func (_Usdc *UsdcFilterer) ParseAdminChanged(log types.Log) (*UsdcAdminChanged, error) {
event := new(UsdcAdminChanged)
if err := _Usdc.contract.UnpackLog(event, "AdminChanged", log); err != nil {
return nil, err
}
event.Raw = log
return event, nil
}
// UsdcUpgradedIterator is returned from FilterUpgraded and is used to iterate over the raw logs and unpacked data for Upgraded events raised by the Usdc contract.
type UsdcUpgradedIterator struct {
Event *UsdcUpgraded // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *UsdcUpgradedIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(UsdcUpgraded)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(UsdcUpgraded)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *UsdcUpgradedIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *UsdcUpgradedIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// UsdcUpgraded represents a Upgraded event raised by the Usdc contract.
type UsdcUpgraded struct {
Implementation common.Address
Raw types.Log // Blockchain specific contextual infos
}
// FilterUpgraded is a free log retrieval operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b.
//
// Solidity: event Upgraded(address implementation)
func (_Usdc *UsdcFilterer) FilterUpgraded(opts *bind.FilterOpts) (*UsdcUpgradedIterator, error) {
logs, sub, err := _Usdc.contract.FilterLogs(opts, "Upgraded")
if err != nil {
return nil, err
}
return &UsdcUpgradedIterator{contract: _Usdc.contract, event: "Upgraded", logs: logs, sub: sub}, nil
}
// WatchUpgraded is a free log subscription operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b.
//
// Solidity: event Upgraded(address implementation)
func (_Usdc *UsdcFilterer) WatchUpgraded(opts *bind.WatchOpts, sink chan<- *UsdcUpgraded) (event.Subscription, error) {
logs, sub, err := _Usdc.contract.WatchLogs(opts, "Upgraded")
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(UsdcUpgraded)
if err := _Usdc.contract.UnpackLog(event, "Upgraded", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// ParseUpgraded is a log parse operation binding the contract event 0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b.
//
// Solidity: event Upgraded(address implementation)
func (_Usdc *UsdcFilterer) ParseUpgraded(log types.Log) (*UsdcUpgraded, error) {
event := new(UsdcUpgraded)
if err := _Usdc.contract.UnpackLog(event, "Upgraded", log); err != nil {
return nil, err
}
event.Raw = log
return event, nil
}

88
utils/aeshelper/aes256.go Normal file
View File

@ -0,0 +1,88 @@
package aeshelper
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"crypto/rand"
"encoding/base64"
"io"
)
// Encrypt text with the passphrase
func Encrypt(text string, passphrase string) string {
salt := make([]byte, 8)
if _, err := io.ReadFull(rand.Reader, salt); err != nil {
panic(err.Error())
}
key, iv := DeriveKeyAndIv(passphrase, string(salt))
block, err := aes.NewCipher([]byte(key))
if err != nil {
panic(err)
}
pad := PKCS7Padding([]byte(text), block.BlockSize())
ecb := cipher.NewCBCEncrypter(block, []byte(iv))
encrypted := make([]byte, len(pad))
ecb.CryptBlocks(encrypted, pad)
return base64.StdEncoding.EncodeToString([]byte("Salted__" + string(salt) + string(encrypted)))
}
// Decrypt encrypted text with the passphrase
func Decrypt(encrypted string, passphrase string) string {
ct, _ := base64.StdEncoding.DecodeString(encrypted)
if len(ct) < 16 || string(ct[:8]) != "Salted__" {
return ""
}
salt := ct[8:16]
ct = ct[16:]
key, iv := DeriveKeyAndIv(passphrase, string(salt))
block, err := aes.NewCipher([]byte(key))
if err != nil {
panic(err)
}
cbc := cipher.NewCBCDecrypter(block, []byte(iv))
dst := make([]byte, len(ct))
cbc.CryptBlocks(dst, ct)
return string(PKCS7Trimming(dst))
}
// PKCS7Padding PKCS7Padding
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
// PKCS7Trimming PKCS7Trimming
func PKCS7Trimming(encrypt []byte) []byte {
padding := encrypt[len(encrypt)-1]
return encrypt[:len(encrypt)-int(padding)]
}
// DeriveKeyAndIv DeriveKeyAndIv
func DeriveKeyAndIv(passphrase string, salt string) (string, string) {
salted := ""
dI := ""
for len(salted) < 48 {
md := md5.New()
md.Write([]byte(dI + passphrase + salt))
dM := md.Sum(nil)
dI = string(dM[:16])
salted = salted + dI
}
key := salted[0:32]
iv := salted[32:48]
return key, iv
}

View File

@ -0,0 +1,108 @@
package aeshelper
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/hex"
"github.com/forgoer/openssl"
)
const (
sKey = "ptQJqRKyICCTeo6w" // "dde4b1f8a9e6b814"
ivParameter = "O3vZvOJSxQDP9hKT" // "dde4b1f8a9e6b814"
)
// PswEncrypt 加密
func PswEncrypt(src string) (string, error) {
key := []byte(sKey)
iv := []byte(ivParameter)
result, err := Aes128Encrypt([]byte(src), key, iv)
if err != nil {
return "", err
}
return base64.RawStdEncoding.EncodeToString(result), nil
}
// PswDecrypt 解密
func PswDecrypt(src string) (string, error) {
key := []byte(sKey)
iv := []byte(ivParameter)
var result []byte
var err error
result, err = base64.StdEncoding.DecodeString(src)
if err != nil {
return "", err
}
origData, err := Aes128Decrypt(result, key, iv)
if err != nil {
return "", err
}
return string(origData), nil
}
func Aes128Encrypt(origData, key []byte, IV []byte) ([]byte, error) {
if key == nil || len(key) != 16 {
return nil, nil
}
if IV != nil && len(IV) != 16 {
return nil, nil
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
origData = PKCS5Padding(origData, blockSize)
blockMode := cipher.NewCBCEncrypter(block, IV[:blockSize])
crypted := make([]byte, len(origData))
// 根据CryptBlocks方法的说明如下方式初始化crypted也可以
blockMode.CryptBlocks(crypted, origData)
return crypted, nil
}
func Aes128Decrypt(crypted, key []byte, IV []byte) ([]byte, error) {
if key == nil || len(key) != 16 {
return nil, nil
}
if IV != nil && len(IV) != 16 {
return nil, nil
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, IV[:blockSize])
origData := make([]byte, len(crypted))
blockMode.CryptBlocks(origData, crypted)
origData = PKCS5UnPadding(origData)
return origData, nil
}
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
// 去掉最后一个字节 unpadding 次
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
// 密码加密
func AesEcbEncrypt(origData string) string {
//加密
dst, _ := openssl.AesECBEncrypt([]byte(origData), []byte(sKey), openssl.PKCS7_PADDING)
return hex.EncodeToString(dst)
}
// 密码解密
func AesEcbDecrypt(origData string) string {
value, _ := hex.DecodeString(origData)
dst, _ := openssl.AesECBDecrypt(value, []byte(sKey), openssl.PKCS7_PADDING)
return string(dst)
}

View File

@ -0,0 +1,65 @@
package aeshelper
import (
"encoding/json"
"fmt"
"testing"
"time"
)
// 测试加密解密
func Test_EnDe(t *testing.T) {
a := `asg`
b := Encrypt(a, `code_verify_success`)
c := Decrypt(b, `code_verify_success`)
fmt.Println(`原始为`, a)
fmt.Println(`加密后`, b)
fmt.Println(`解密后`, c)
}
func TestAesEcbEncrypt(t *testing.T) {
//aes := AesEcbEncrypt("123456")
aes := AesEcbEncrypt(fmt.Sprintf("%v_%v", time.Now().Unix(), 1332355333))
dst := AesEcbDecrypt(aes)
fmt.Println(aes)
fmt.Println(dst)
}
// TODO:需要加密的接口
/**
1.合约下单接口 /api/futures/trade/order
2.合约撤单 /api/futures/trade/cancelorder
3.调整保证金 /api/futures/trade/adjustmargin
4.变换逐全仓模式 /api/futures/trade/marginType
5.更改持仓模式(方向) /api/futures/trade/positionSide/dual
6.资产划转 /api/futures/transfer
*/
func TestAesEcbEncryptOrder(t *testing.T) {
data := addFutOrderReq{
OrderType: 1,
BuyType: 3,
TriggerDecide: 3,
IsReduce: 2,
Coin: "asdf",
Price: "333.23",
Num: "23.20",
TriggerPrice: "1.023",
PositionSide: "long",
}
b, _ := json.Marshal(data)
aes := AesEcbEncrypt(string(b))
dst := AesEcbDecrypt(aes)
fmt.Println(aes)
fmt.Println(dst)
}
type addFutOrderReq struct {
OrderType int `json:"order_type"` // 订单类型1限价2限价止盈止损3市价,4市价止盈止损,5强平委托(就是限价委托)
BuyType int `json:"buy_type"` // 买卖类型1买2卖
TriggerDecide int `json:"trigger_decide"` // 触发条件 1按最新成交价格算2按标记价格算
IsReduce int `json:"is_reduce"` // 1是只减仓位(点击仓位列表中的平仓按钮)0正常
Coin string `json:"coin"` // 交易币
Price string `json:"price"` // 下单价格(限价+止盈止损时,该字段必填)
Num string `json:"num"` // 下单数量(市价时该字段必填)
TriggerPrice string `json:"trigger_price"` // 触发价格
PositionSide string `json:"position_side"` // 持仓方向单向持仓模式下可填both;在双向持仓模式下必填,且仅可选择 long 或 short
}

View File

@ -0,0 +1,94 @@
package aesoldhelper
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"errors"
"io"
"strings"
)
func addBase64Padding(value string) string {
m := len(value) % 4
if m != 0 {
value += strings.Repeat("=", 4-m)
}
return value
}
func removeBase64Padding(value string) string {
return strings.Replace(value, "=", "", -1)
}
// Pad Pad
func Pad(src []byte) []byte {
padding := aes.BlockSize - len(src)%aes.BlockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(src, padtext...)
}
// Unpad Unpad
func Unpad(src []byte) ([]byte, error) {
length := len(src)
unpadding := int(src[length-1])
if unpadding > length {
return nil, errors.New("unpad error. This could happen when incorrect encryption key is used")
}
return src[:(length - unpadding)], nil
}
// AesEncrypt AesEncrypt
func AesEncrypt(key []byte, text string) (string, error) {
block, err := aes.NewCipher(key)
if err != nil {
return "", err
}
msg := Pad([]byte(text))
ciphertext := make([]byte, aes.BlockSize+len(msg))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return "", err
}
cfb := cipher.NewCFBEncrypter(block, iv)
cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(msg))
finalMsg := removeBase64Padding(base64.URLEncoding.EncodeToString(ciphertext))
return finalMsg, nil
}
// AesDecrypt AesDecrypt
func AesDecrypt(key []byte, text string) (string, error) {
block, err := aes.NewCipher(key)
if err != nil {
return "", err
}
decodedMsg, err := base64.URLEncoding.DecodeString(addBase64Padding(text))
if err != nil {
return "", err
}
if (len(decodedMsg) % aes.BlockSize) != 0 {
return "", errors.New("blocksize must be multipe of decoded message length")
}
iv := decodedMsg[:aes.BlockSize]
msg := decodedMsg[aes.BlockSize:]
cfb := cipher.NewCFBDecrypter(block, iv)
cfb.XORKeyStream(msg, msg)
unpadMsg, err := Unpad(msg)
if err != nil {
return "", err
}
return string(unpadMsg), nil
}

19
utils/aeshelper/apikey.go Normal file
View File

@ -0,0 +1,19 @@
package aeshelper
var (
apiaeskey = "9jxFTkydwCJsmIA1TUrv"
)
// EncryptApi 加密apikey
func EncryptApi(apikey, secretkey string) (apikeyen, secrekeyen string) {
apikeyen = Encrypt(apikey, apiaeskey)
secrekeyen = Encrypt(secretkey, apiaeskey)
return apikeyen, secrekeyen
}
// DecryptApi 解密apikey
func DecryptApi(apikeyen, secrekeyen string) (apikey, secrekey string) {
apikey = Decrypt(apikeyen, apiaeskey)
secrekey = Decrypt(secrekeyen, apiaeskey)
return apikey, secrekey
}

View File

@ -0,0 +1,113 @@
package ethbalanceofhelper
import (
"context"
"errors"
"fmt"
"go-admin/abis"
"math/big"
"net/http"
"net/url"
"strings"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
"github.com/shopspring/decimal"
)
// ERC-20 代币合约 ABI (部分,只包含 balanceOf)
// ERC-20 代币合约 ABI (部分,只包含 balanceOf 和 decimals)
const erc20ABI = `[
{
"constant": true,
"inputs": [ { "name": "_owner", "type": "address" } ],
"name": "balanceOf",
"outputs": [ { "name": "balance", "type": "uint256" } ],
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [ { "name": "", "type": "uint8" } ],
"type": "function"
}
]`
// GetERC20Balance 查询 ERC-20 代币余额并转换为正常单位 (使用 decimal)
func GetERC20Balance(client *ethclient.Client, tokenAbi abis.TokenABI, accountAddress string) (decimal.Decimal, error) {
// 1. 解析 ABI
contractABI, err := abi.JSON(strings.NewReader(erc20ABI))
if err != nil {
return decimal.Zero, fmt.Errorf("解析 ABI 失败: %w", err)
}
// 2. 构造 balanceOf 函数调用数据
balanceOfCallData, err := contractABI.Pack("balanceOf", common.HexToAddress(accountAddress))
if err != nil {
return decimal.Zero, fmt.Errorf("构造 balanceOf 调用数据失败: %w", err)
}
address := common.HexToAddress(tokenAbi.TestAddress)
// 3. 执行 balanceOf 调用
balanceResult, err := client.CallContract(context.Background(), ethereum.CallMsg{
To: &address,
Data: balanceOfCallData,
}, nil)
if err != nil {
return decimal.Zero, fmt.Errorf("调用 balanceOf 失败: %w", err)
}
// 4. 解析 balanceOf 结果
unpackedBalance, err := contractABI.Unpack("balanceOf", balanceResult)
if err != nil {
return decimal.Zero, fmt.Errorf("解析 balanceOf 结果失败: %w", err)
}
balance, ok := unpackedBalance[0].(*big.Int)
if !ok {
return decimal.Zero, errors.New("解析 balanceOf 结果为 *big.Int 失败")
}
// 8. 转换为正常单位 (使用 decimal)
balanceDecimal := decimal.NewFromBigInt(balance, 0) // Create decimal from big.Int
decimalFactor := decimal.NewFromInt(10).Pow(decimal.NewFromInt(int64(tokenAbi.Decimals)))
readableBalance := balanceDecimal.Div(decimalFactor)
return readableBalance, nil
}
// 初始化以太坊客户端连接代理
func EthClientWithProxy(rawURL string, proxyURL string) (*ethclient.Client, error) {
u, err := url.Parse(rawURL)
if err != nil {
return nil, fmt.Errorf("invalid URL: %v", err)
}
if proxyURL == "" {
return ethclient.Dial(rawURL)
}
proxy, err := url.Parse(proxyURL)
if err != nil {
return nil, fmt.Errorf("invalid proxy URL: %v", err)
}
httpClient := &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(proxy),
},
}
dialOptions := []rpc.ClientOption{
rpc.WithHTTPClient(httpClient),
}
rpcClient, err := rpc.DialOptions(context.Background(), u.String(), dialOptions...)
if err != nil {
return nil, fmt.Errorf("failed to dial RPC client with options: %v", err)
}
return ethclient.NewClient(rpcClient), nil
}

View File

@ -0,0 +1,175 @@
package ethtransferhelper
import (
"context"
"crypto/ecdsa"
"errors"
"fmt"
"math/big"
"strings"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"golang.org/x/crypto/sha3"
)
// transferErc20Token 发送 ERC-20 代币交易。
// tokenAmount: 要发送的代币数量 (例如1.0 代表 1 个代币)。
// fromPrivateKey: 发送者的私钥。
// tokenAddress: ERC-20 代币的合约地址。
// toAddress: 接收者的地址。
// tokenDecimals: 代币的小数位数 (例如USDC 是 6很多其他代币是 18)。
func transferErc20Token(
client *ethclient.Client,
fromPrivateKey string,
tokenAddress string,
toAddress string,
tokenAmount float64,
tokenDecimals uint8,
) (*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 := big.NewInt(0) // 不发送 ETH
// 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)
tokenAddressCommon := common.HexToAddress(tokenAddress)
// 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
// 7.2 填充接收者地址和转账金额
paddedAddress := common.LeftPadBytes(toAddressCommon.Bytes(), 32)
// 7.3 将代币数量转换为最小单位
amountBigInt, err := convertTokenAmountToBigInt(tokenAmount, tokenDecimals)
if err != nil {
return nil, fmt.Errorf("转换代币数量失败: %w", err)
}
paddedAmount := common.LeftPadBytes(amountBigInt.Bytes(), 32)
// 7.4 拼接调用数据
var data []byte
data = append(data, methodID...)
data = append(data, paddedAddress...)
data = append(data, paddedAmount...)
// 8. 估算 Gas 消耗
gasLimit, err := client.EstimateGas(context.Background(), ethereum.CallMsg{
From: fromAddressCommon,
To: &tokenAddressCommon,
Data: data,
})
if err != nil {
return nil, fmt.Errorf("估算 Gas 消耗失败: %w", err)
}
// 9. 增加 Gas 限制的安全边际
gasLimit = gasLimit * 11 / 10 // 增加 10%
if gasLimit < 23000 {
gasLimit = 23000 // 最小 Gas 限制
}
// 10. 创建交易
tx := types.NewTransaction(nonce, tokenAddressCommon, 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
}
// getAddressFromPrivateKey 从私钥获取公钥和地址。
func GetAddressFromPrivateKey(fromPrivateKey string) (*ecdsa.PrivateKey, common.Address, error) {
// 1. 移除 "0x" 前缀(如果存在)
if strings.HasPrefix(fromPrivateKey, "0x") {
fromPrivateKey = fromPrivateKey[2:]
}
privateKey, err := crypto.HexToECDSA(fromPrivateKey)
if err != nil {
return nil, common.Address{}, fmt.Errorf("解析私钥失败: %w", err)
}
// 2. 从私钥获取公钥和发送者地址
publicKey := privateKey.Public()
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
if !ok {
return nil, common.Address{}, errors.New("无法将公钥转换为 ECDSA 类型")
}
fromAddressCommon := crypto.PubkeyToAddress(*publicKeyECDSA)
return privateKey, fromAddressCommon, nil
}
// convertTokenAmountToBigInt 将代币数量 (例如1.0) 转换为最小单位的整数表示 (例如USDC 的 1000000)。
func convertTokenAmountToBigInt(tokenAmount float64, tokenDecimals uint8) (*big.Int, error) {
// 1. 使用最大精度格式化浮点数
amountStr := fmt.Sprintf("%.18f", tokenAmount) // 使用最大精度
// 2. 找到小数点的位置
decimalPointIndex := strings.Index(amountStr, ".")
// 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)
}
return amountBigInt, nil
}

View File

@ -0,0 +1,9 @@
package stringhelper
func DesensitizeWalletAddress(address string) string {
if len(address) < 10 { // 更严格的长度检查
return "0x...invalid"
}
return address[:6] + "..." + address[len(address)-4:]
}