1、调整gas费浮动比例为90%
This commit is contained in:
		| @ -43,7 +43,7 @@ func (e WmTransferItem) GetPage(c *gin.Context) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	p := actions.GetPermissionFromContext(c) | 	p := actions.GetPermissionFromContext(c) | ||||||
| 	list := make([]models.WmTransferItem, 0) | 	list := make([]dto.WmTransferItemResp, 0) | ||||||
| 	var count int64 | 	var count int64 | ||||||
|  |  | ||||||
| 	err = s.GetPage(&req, p, &list, &count) | 	err = s.GetPage(&req, p, &list, &count) | ||||||
| @ -262,3 +262,23 @@ func (e WmTransferItem) GetAutoTransferLogPage(c *gin.Context) { | |||||||
| 	} | 	} | ||||||
| 	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") | 	e.PageOK(list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // 清除自动转账 | ||||||
|  | func (e WmTransferItem) ClearAutoLog(c *gin.Context) { | ||||||
|  | 	s := service.WmTransferItem{} | ||||||
|  | 	err := e.MakeContext(c). | ||||||
|  | 		MakeOrm(). | ||||||
|  | 		MakeService(&s.Service). | ||||||
|  | 		Errors | ||||||
|  | 	if err != nil { | ||||||
|  | 		e.Logger.Error(err) | ||||||
|  | 		e.Error(500, err, err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	err = s.ClearAutoLog() | ||||||
|  | 	if err != nil { | ||||||
|  | 		e.Error(500, err, fmt.Sprintf("清除自动转账日志失败,\r\n失败信息 %s", err.Error())) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	e.OK(nil, "清除成功") | ||||||
|  | } | ||||||
|  | |||||||
| @ -174,3 +174,49 @@ func (e WmWalletInfo) ClearAll(c *gin.Context) { | |||||||
| 	} | 	} | ||||||
| 	e.OK(nil, "清空成功") | 	e.OK(nil, "清空成功") | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // 根据excel导入钱包信息 | ||||||
|  | func (e WmWalletInfo) ExcelImport(c *gin.Context) { | ||||||
|  | 	s := service.WmWalletInfo{} | ||||||
|  | 	err := e.MakeContext(c). | ||||||
|  | 		MakeOrm(). | ||||||
|  | 		MakeService(&s.Service). | ||||||
|  | 		Errors | ||||||
|  | 	if err != nil { | ||||||
|  | 		e.Logger.Error(err) | ||||||
|  | 		e.Error(500, err, err.Error()) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	errs := s.ExcelImport(c) | ||||||
|  |  | ||||||
|  | 	e.OK(strings.Join(errs, "<br/>"), "创建成功") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // UpdateRemark 更新备注信息 | ||||||
|  | func (e WmWalletInfo) UpdateRemark(c *gin.Context) { | ||||||
|  | 	s := service.WmWalletInfo{} | ||||||
|  | 	req := dto.WmWalletInfoBatchUpdateReq{} | ||||||
|  |  | ||||||
|  | 	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)) | ||||||
|  |  | ||||||
|  | 	err = s.BatchUpdateRemark(&req) | ||||||
|  | 	if err != nil { | ||||||
|  | 		e.Error(500, err, fmt.Sprintf("更新备注信息失败,\r\n失败信息 %s", err.Error())) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	e.OK(nil, "更新成功") | ||||||
|  | } | ||||||
|  | |||||||
| @ -17,6 +17,8 @@ type WmTransfer struct { | |||||||
| 	Sucess       int    `json:"sucess" gorm:"-"` | 	Sucess       int    `json:"sucess" gorm:"-"` | ||||||
| 	Fail         int    `json:"fail" gorm:"-"` | 	Fail         int    `json:"fail" gorm:"-"` | ||||||
| 	Pending      int    `json:"pending" gorm:"-"` | 	Pending      int    `json:"pending" gorm:"-"` | ||||||
|  | 	NetworkName  string `json:"networkName" gorm:"-"` | ||||||
|  | 	TokenName    string `json:"tokenName" gorm:"-"` | ||||||
| 	models.ModelTime | 	models.ModelTime | ||||||
| 	models.ControlBy | 	models.ControlBy | ||||||
| } | } | ||||||
|  | |||||||
| @ -12,6 +12,7 @@ type WmWalletInfo struct { | |||||||
| 	PrivateKey string          `json:"privateKey" gorm:"type:varchar(50);comment:钱包私钥"` | 	PrivateKey string          `json:"privateKey" gorm:"type:varchar(50);comment:钱包私钥"` | ||||||
| 	Address    string          `json:"address" 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余额"` | 	UsdcAmount decimal.Decimal `json:"usdcAmount" gorm:"type:decimal(18,8);comment:USDC余额"` | ||||||
|  | 	Remark     string          `json:"remark" gorm:"type:varchar(255);comment:备注信息"` | ||||||
| 	models.ModelTime | 	models.ModelTime | ||||||
| 	models.ControlBy | 	models.ControlBy | ||||||
| } | } | ||||||
|  | |||||||
| @ -24,6 +24,7 @@ func registerWmTransferItemRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJW | |||||||
| 		r.PUT("/:id", actions.PermissionAction(), api.Update) | 		r.PUT("/:id", actions.PermissionAction(), api.Update) | ||||||
| 		r.DELETE("", api.Delete) | 		r.DELETE("", api.Delete) | ||||||
|  |  | ||||||
|  | 		r.DELETE("/clear", api.ClearAutoLog) | ||||||
| 		r.GET("/export", actions.PermissionAction(), api.Export) | 		r.GET("/export", actions.PermissionAction(), api.Export) | ||||||
| 		r.GET("/export-auto-log", actions.PermissionAction(), api.ExportAutoLog) | 		r.GET("/export-auto-log", actions.PermissionAction(), api.ExportAutoLog) | ||||||
| 		r.GET("/auto-log", actions.PermissionAction(), api.GetAutoTransferLogPage) | 		r.GET("/auto-log", actions.PermissionAction(), api.GetAutoTransferLogPage) | ||||||
|  | |||||||
| @ -24,5 +24,8 @@ func registerWmWalletInfoRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTM | |||||||
| 		// r.PUT("/:id", actions.PermissionAction(), api.Update) | 		// r.PUT("/:id", actions.PermissionAction(), api.Update) | ||||||
| 		r.DELETE("", api.Delete) | 		r.DELETE("", api.Delete) | ||||||
| 		r.DELETE("clear", api.ClearAll) | 		r.DELETE("clear", api.ClearAll) | ||||||
|  |  | ||||||
|  | 		r.POST("/excel-import", api.ExcelImport) //根据excel导入数据 | ||||||
|  | 		r.PUT("/batch", api.UpdateRemark)        //批量更新备注 | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -13,6 +13,7 @@ type WmTokenGetPageReq struct { | |||||||
| 	dto.Pagination `search:"-"` | 	dto.Pagination `search:"-"` | ||||||
| 	NetworkId      string `form:"networkId"  search:"type:contains;column:network_id;table:wm_token" comment:"网络id"` | 	NetworkId      string `form:"networkId"  search:"type:contains;column:network_id;table:wm_token" comment:"网络id"` | ||||||
| 	TokenName      string `form:"tokenName"  search:"type:contains;column:token_name;table:wm_token" comment:"代币名称"` | 	TokenName      string `form:"tokenName"  search:"type:contains;column:token_name;table:wm_token" comment:"代币名称"` | ||||||
|  | 	TransType      int    `form:"transType"  search:"-" comment:"转账类型 1-百分比 2-实际金额"` | ||||||
| 	WmTokenOrder | 	WmTokenOrder | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -2,9 +2,11 @@ package dto | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
|  | 	"fmt" | ||||||
| 	"go-admin/app/admin/models" | 	"go-admin/app/admin/models" | ||||||
| 	"go-admin/common/dto" | 	"go-admin/common/dto" | ||||||
| 	common "go-admin/common/models" | 	common "go-admin/common/models" | ||||||
|  | 	"go-admin/utils/ethtransferhelper" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	"github.com/shopspring/decimal" | 	"github.com/shopspring/decimal" | ||||||
| @ -105,6 +107,12 @@ func (s *WmTransferInsertReq) Valid() error { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	for _, content := range contents { | ||||||
|  | 		if !ethtransferhelper.IsValidAddress(content) { | ||||||
|  | 			return fmt.Errorf("%s 地址格式错误", content) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -17,7 +17,10 @@ type WmTransferItemGetPageReq struct { | |||||||
|  |  | ||||||
| type WmTransferItemAutoLogPageReq struct { | type WmTransferItemAutoLogPageReq struct { | ||||||
| 	dto.Pagination `search:"-"` | 	dto.Pagination `search:"-"` | ||||||
| 	NetworkId      int `form:"networkId"  search:"type:exact;column:network_id;table:wm_transfer_item"` | 	NetworkId      int     `form:"networkId"  search:"type:exact;column:network_id;table:wm_transfer_item"` | ||||||
|  | 	StartAmount    float64 `form:"startAmount" search:"-"` | ||||||
|  | 	EndAmount      float64 `form:"endAmount" search:"-"` | ||||||
|  | 	Status         int     `form:"status" search:"-"` | ||||||
| 	WmTransferItemOrder | 	WmTransferItemOrder | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -146,6 +149,8 @@ type WmTransferItemExportReq struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| type WmTransferItemExportData struct { | type WmTransferItemExportData struct { | ||||||
|  | 	NetworkName  string          `json:"networkName" excel:"网络名称"` | ||||||
|  | 	TokenName    string          `json:"tokenName" excel:"代币名称"` | ||||||
| 	PrivateKey   string          `json:"privateKey" excel:"私钥"` | 	PrivateKey   string          `json:"privateKey" excel:"私钥"` | ||||||
| 	TokenAddress string          `json:"tokenAddress" excel:"代币地址"` | 	TokenAddress string          `json:"tokenAddress" excel:"代币地址"` | ||||||
| 	FromAddress  string          `json:"fromAddress" excel:"来源地址"` | 	FromAddress  string          `json:"fromAddress" excel:"来源地址"` | ||||||
|  | |||||||
| @ -10,7 +10,7 @@ import ( | |||||||
|  |  | ||||||
| type WmWalletInfoGetPageReq struct { | type WmWalletInfoGetPageReq struct { | ||||||
| 	dto.Pagination `search:"-"` | 	dto.Pagination `search:"-"` | ||||||
| 	PrivateKey     string `form:"privateKey"  search:"type:exact;column:private_key;table:wm_wallet_info" comment:"钱包私钥"` | 	PrivateKey     string `form:"privateKey"  search:"-" comment:"钱包私钥"` | ||||||
| 	WmWalletInfoOrder | 	WmWalletInfoOrder | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -30,7 +30,8 @@ func (m *WmWalletInfoGetPageReq) GetNeedSearch() interface{} { | |||||||
| } | } | ||||||
|  |  | ||||||
| type WmWalletInfoBatchInsertReq struct { | type WmWalletInfoBatchInsertReq struct { | ||||||
| 	Keys string `json:"keys"` | 	Keys   string `json:"keys"` | ||||||
|  | 	Remark string `json:"remark"` | ||||||
| 	common.ControlBy | 	common.ControlBy | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -103,3 +104,14 @@ type WmWalletInfoDeleteReq struct { | |||||||
| func (s *WmWalletInfoDeleteReq) GetId() interface{} { | func (s *WmWalletInfoDeleteReq) GetId() interface{} { | ||||||
| 	return s.Ids | 	return s.Ids | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type WmWalletExcelImportReq struct { | ||||||
|  | 	PrivateKey string `json:"privateKey" excel:"钱包私钥"` | ||||||
|  | 	Remark     string `json:"remark" excel:"备注"` | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type WmWalletInfoBatchUpdateReq struct { | ||||||
|  | 	Ids    []int  `json:"ids" form:"ids"` | ||||||
|  | 	Remark string `json:"remark" form:"remark"` | ||||||
|  | 	common.ControlBy | ||||||
|  | } | ||||||
|  | |||||||
| @ -25,13 +25,18 @@ type WmToken struct { | |||||||
| func (e *WmToken) GetPage(c *dto.WmTokenGetPageReq, p *actions.DataPermission, list *[]models.WmToken, count *int64) error { | func (e *WmToken) GetPage(c *dto.WmTokenGetPageReq, p *actions.DataPermission, list *[]models.WmToken, count *int64) error { | ||||||
| 	var err error | 	var err error | ||||||
| 	var data models.WmToken | 	var data models.WmToken | ||||||
|  | 	query := e.Orm.Model(&data). | ||||||
| 	err = e.Orm.Model(&data). |  | ||||||
| 		Scopes( | 		Scopes( | ||||||
| 			cDto.MakeCondition(c.GetNeedSearch()), | 			cDto.MakeCondition(c.GetNeedSearch()), | ||||||
| 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | ||||||
| 			actions.Permission(data.TableName(), p), | 			actions.Permission(data.TableName(), p), | ||||||
| 		). | 		) | ||||||
|  |  | ||||||
|  | 	if c.TransType > 0 { | ||||||
|  | 		query.Where("trans_type = ?", c.TransType) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = query. | ||||||
| 		Find(list).Limit(-1).Offset(-1). | 		Find(list).Limit(-1).Offset(-1). | ||||||
| 		Count(count).Error | 		Count(count).Error | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  | |||||||
| @ -56,6 +56,10 @@ func (e *WmTransfer) GetPage(c *dto.WmTransferGetPageReq, p *actions.DataPermiss | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	itemData, _ := e.GetItemData(transferIds) | 	itemData, _ := e.GetItemData(transferIds) | ||||||
|  | 	networkService := WmNetwork{Service: e.Service} | ||||||
|  | 	networks, _ := networkService.GetAll() | ||||||
|  | 	tokenService := WmToken{Service: e.Service} | ||||||
|  | 	tokens, _ := tokenService.GetAll() | ||||||
|  |  | ||||||
| 	for i := range *list { | 	for i := range *list { | ||||||
| 		var total int | 		var total int | ||||||
| @ -74,6 +78,20 @@ func (e *WmTransfer) GetPage(c *dto.WmTransferGetPageReq, p *actions.DataPermiss | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		for _, network := range networks { | ||||||
|  | 			if network.Id == (*list)[i].NetworkId { | ||||||
|  | 				(*list)[i].NetworkName = network.NetworkName | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		for _, token := range tokens { | ||||||
|  | 			if token.NetworkId == (*list)[i].NetworkId && token.TokenAddress == (*list)[i].TokenAddress { | ||||||
|  | 				(*list)[i].TokenName = token.TokenName | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		(*list)[i].Total = total | 		(*list)[i].Total = total | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -196,6 +214,7 @@ func (e *WmTransfer) Insert(c *dto.WmTransferInsertReq) error { | |||||||
| 			caches[i].TransferId = data.Id | 			caches[i].TransferId = data.Id | ||||||
| 			caches[i].IsAuto = 2 | 			caches[i].IsAuto = 2 | ||||||
| 			caches[i].TokenAddress = c.TokenAddress | 			caches[i].TokenAddress = c.TokenAddress | ||||||
|  | 			caches[i].Decimals = token.Decimals | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if err := tx.CreateInBatches(&caches, 100).Error; err != nil { | 		if err := tx.CreateInBatches(&caches, 100).Error; err != nil { | ||||||
| @ -226,7 +245,7 @@ func (e *WmTransfer) getPrivateKeyAmount(privateKey, tokenAddress string, decima | |||||||
| 			return amount, errors.New("连接区块链失败") | 			return amount, errors.New("连接区块链失败") | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		amount, err = ethbalanceofhelper.GetERC20Balance(client, tokenAddress, accountAddress.String(), decimals) | 		amount, err = ethbalanceofhelper.GetBalance(client, tokenAddress, accountAddress.String(), decimals) | ||||||
|  |  | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return amount, errors.New("查询主账号余额失败") | 			return amount, errors.New("查询主账号余额失败") | ||||||
| @ -372,11 +391,11 @@ func (e *WmTransfer) CheckHashStatus() error { | |||||||
| // 清理数据 | // 清理数据 | ||||||
| func (e *WmTransfer) ClearAll() error { | func (e *WmTransfer) ClearAll() error { | ||||||
| 	err := e.Orm.Transaction(func(tx *gorm.DB) error { | 	err := e.Orm.Transaction(func(tx *gorm.DB) error { | ||||||
| 		if err1 := tx.Exec("truncate table wm_transfer_item").Error; err1 != nil { | 		if err1 := tx.Exec("delete from wm_transfer_item where is_auto = 2").Error; err1 != nil { | ||||||
| 			return err1 | 			return err1 | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if err2 := tx.Exec("truncate table wm_transfer").Error; err2 != nil { | 		if err2 := tx.Exec("delete from wm_transfer ").Error; err2 != nil { | ||||||
| 			return err2 | 			return err2 | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | |||||||
| @ -21,9 +21,10 @@ type WmTransferItem struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| // GetPage 获取WmTransferItem列表 | // GetPage 获取WmTransferItem列表 | ||||||
| func (e *WmTransferItem) GetPage(c *dto.WmTransferItemGetPageReq, p *actions.DataPermission, list *[]models.WmTransferItem, count *int64) error { | func (e *WmTransferItem) GetPage(c *dto.WmTransferItemGetPageReq, p *actions.DataPermission, list *[]dto.WmTransferItemResp, count *int64) error { | ||||||
| 	var err error | 	var err error | ||||||
| 	var data models.WmTransferItem | 	var data models.WmTransferItem | ||||||
|  | 	var datas []models.WmTransferItem | ||||||
|  |  | ||||||
| 	err = e.Orm.Model(&data). | 	err = e.Orm.Model(&data). | ||||||
| 		Scopes( | 		Scopes( | ||||||
| @ -31,15 +32,48 @@ func (e *WmTransferItem) GetPage(c *dto.WmTransferItemGetPageReq, p *actions.Dat | |||||||
| 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | ||||||
| 			actions.Permission(data.TableName(), p), | 			actions.Permission(data.TableName(), p), | ||||||
| 		). | 		). | ||||||
| 		Find(list).Limit(-1).Offset(-1). | 		Find(&datas).Limit(-1).Offset(-1). | ||||||
| 		Count(count).Error | 		Count(count).Error | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		e.Log.Errorf("WmTransferItemService GetPage error:%s \r\n", err) | 		e.Log.Errorf("WmTransferItemService GetPage error:%s \r\n", err) | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for i := 0; i < len(*list); i++ { | 	networkService := WmNetwork{Service: e.Service} | ||||||
| 		(*list)[i].PrivateKey = stringhelper.DesensitizeWalletAddress(aeshelper.AesEcbDecrypt((*list)[i].PrivateKey)) | 	networks, _ := networkService.GetAll() | ||||||
|  | 	tokenService := WmToken{Service: e.Service} | ||||||
|  | 	tokens, _ := tokenService.GetAll() | ||||||
|  |  | ||||||
|  | 	for i := 0; i < len(datas); i++ { | ||||||
|  | 		item := dto.WmTransferItemResp{} | ||||||
|  | 		item.Id = datas[i].Id | ||||||
|  | 		item.PrivateKey = stringhelper.DesensitizeWalletAddress(aeshelper.AesEcbDecrypt(datas[i].PrivateKey)) | ||||||
|  | 		item.FromAddress = datas[i].FromAddress | ||||||
|  | 		item.ToAddress = datas[i].ToAddress | ||||||
|  | 		item.TokenAddress = datas[i].TokenAddress | ||||||
|  | 		item.Amount = datas[i].Amount | ||||||
|  | 		item.Status = datas[i].Status | ||||||
|  | 		item.Remark = datas[i].Remark | ||||||
|  | 		item.Type = datas[i].Type | ||||||
|  | 		item.TypeValue = datas[i].TypeValue | ||||||
|  | 		item.Hash = datas[i].Hash | ||||||
|  | 		item.CreateAt = datas[i].CreatedAt | ||||||
|  |  | ||||||
|  | 		for _, network := range networks { | ||||||
|  | 			if network.Id == datas[i].NetworkId { | ||||||
|  | 				item.NetworkName = network.NetworkName | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		for _, token := range tokens { | ||||||
|  | 			if token.NetworkId == datas[i].NetworkId && token.TokenAddress == datas[i].TokenAddress { | ||||||
|  | 				item.TokenName = token.TokenName | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		*list = append(*list, item) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| @ -50,9 +84,22 @@ func (e *WmTransferItem) GetAutoTransferLogPage(c *dto.WmTransferItemAutoLogPage | |||||||
| 	var err error | 	var err error | ||||||
| 	var data models.WmTransferItem | 	var data models.WmTransferItem | ||||||
| 	var datas []models.WmTransferItem | 	var datas []models.WmTransferItem | ||||||
|  | 	query := e.Orm.Model(&data). | ||||||
|  | 		Where("is_auto = 1") | ||||||
|  |  | ||||||
| 	err = e.Orm.Model(&data). | 	if c.StartAmount >= 0 { | ||||||
| 		Where("is_auto = 1"). | 		query.Where("amount >=?", c.StartAmount) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if c.EndAmount > 0 { | ||||||
|  | 		query.Where("amount <=?", c.EndAmount) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if c.Status > 0 { | ||||||
|  | 		query.Where("status =?", c.Status) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = query. | ||||||
| 		Scopes( | 		Scopes( | ||||||
| 			cDto.MakeCondition(c.GetNeedSearch()), | 			cDto.MakeCondition(c.GetNeedSearch()), | ||||||
| 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | ||||||
| @ -111,8 +158,21 @@ func (e *WmTransferItem) ExportAutoLog(req *dto.WmTransferItemAutoLogPageReq, c | |||||||
| 	var err error | 	var err error | ||||||
| 	var data models.WmTransferItem | 	var data models.WmTransferItem | ||||||
| 	exportDatas := make([]dto.WmTransferItemResp, 0) | 	exportDatas := make([]dto.WmTransferItemResp, 0) | ||||||
|  | 	query := e.Orm.Model(&data) | ||||||
|  |  | ||||||
| 	err = e.Orm.Model(&data). | 	if req.StartAmount >= 0 { | ||||||
|  | 		query.Where("amount >=?", req.StartAmount) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if req.EndAmount > 0 { | ||||||
|  | 		query.Where("amount <=?", req.EndAmount) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if req.Status > 0 { | ||||||
|  | 		query.Where("status =?", req.Status) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	err = query. | ||||||
| 		Where("is_auto = 1"). | 		Where("is_auto = 1"). | ||||||
| 		Scopes( | 		Scopes( | ||||||
| 			cDto.MakeCondition(req.GetNeedSearch()), | 			cDto.MakeCondition(req.GetNeedSearch()), | ||||||
| @ -259,6 +319,11 @@ func (e *WmTransferItem) ExportExcel(req *dto.WmTransferItemExportReq, p *action | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	networkService := WmNetwork{Service: e.Service} | ||||||
|  | 	networks, _ := networkService.GetAll() | ||||||
|  | 	tokenService := WmToken{Service: e.Service} | ||||||
|  | 	tokens, _ := tokenService.GetAll() | ||||||
|  |  | ||||||
| 	for i := 0; i < len(datas); i++ { | 	for i := 0; i < len(datas); i++ { | ||||||
| 		(datas)[i].PrivateKey = stringhelper.DesensitizeWalletAddress(aeshelper.AesEcbDecrypt((datas)[i].PrivateKey)) | 		(datas)[i].PrivateKey = stringhelper.DesensitizeWalletAddress(aeshelper.AesEcbDecrypt((datas)[i].PrivateKey)) | ||||||
| 		exportData := dto.WmTransferItemExportData{ | 		exportData := dto.WmTransferItemExportData{ | ||||||
| @ -281,6 +346,21 @@ func (e *WmTransferItem) ExportExcel(req *dto.WmTransferItemExportReq, p *action | |||||||
| 		default: | 		default: | ||||||
| 			exportData.Status = "默认" | 			exportData.Status = "默认" | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		for _, network := range networks { | ||||||
|  | 			if network.Id == datas[i].NetworkId { | ||||||
|  | 				exportData.NetworkName = network.NetworkName | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		for _, token := range tokens { | ||||||
|  | 			if token.NetworkId == datas[i].NetworkId && token.TokenAddress == datas[i].TokenAddress { | ||||||
|  | 				exportData.TokenName = token.TokenName | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		exportDatas = append(exportDatas, exportData) | 		exportDatas = append(exportDatas, exportData) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @ -290,3 +370,13 @@ func (e *WmTransferItem) ExportExcel(req *dto.WmTransferItemExportReq, p *action | |||||||
|  |  | ||||||
| 	return excelhelper.ExportExcel(c, "转账明细", exportDatas, []string{}) | 	return excelhelper.ExportExcel(c, "转账明细", exportDatas, []string{}) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // 批量删除自动转账日志 | ||||||
|  | func (e *WmTransferItem) ClearAutoLog() error { | ||||||
|  | 	if err := e.Orm.Where("is_auto=1").Unscoped().Delete(&models.WmTransferItem{}).Error; err != nil { | ||||||
|  | 		e.Log.Errorf("Service ClearAutoLog error:%s \r\n", err) | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ import ( | |||||||
| 	"errors" | 	"errors" | ||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
|  | 	"github.com/gin-gonic/gin" | ||||||
| 	"github.com/go-admin-team/go-admin-core/sdk/service" | 	"github.com/go-admin-team/go-admin-core/sdk/service" | ||||||
| 	"github.com/shopspring/decimal" | 	"github.com/shopspring/decimal" | ||||||
| 	"gorm.io/gorm" | 	"gorm.io/gorm" | ||||||
| @ -16,6 +17,7 @@ import ( | |||||||
| 	"go-admin/utils/aeshelper" | 	"go-admin/utils/aeshelper" | ||||||
| 	"go-admin/utils/ethbalanceofhelper" | 	"go-admin/utils/ethbalanceofhelper" | ||||||
| 	"go-admin/utils/ethtransferhelper" | 	"go-admin/utils/ethtransferhelper" | ||||||
|  | 	"go-admin/utils/excelhelper" | ||||||
| 	"go-admin/utils/stringhelper" | 	"go-admin/utils/stringhelper" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @ -27,8 +29,13 @@ type WmWalletInfo struct { | |||||||
| func (e *WmWalletInfo) GetPage(c *dto.WmWalletInfoGetPageReq, p *actions.DataPermission, list *[]models.WmWalletInfo, count *int64) error { | func (e *WmWalletInfo) GetPage(c *dto.WmWalletInfoGetPageReq, p *actions.DataPermission, list *[]models.WmWalletInfo, count *int64) error { | ||||||
| 	var err error | 	var err error | ||||||
| 	var data models.WmWalletInfo | 	var data models.WmWalletInfo | ||||||
|  | 	query := e.Orm.Model(&data) | ||||||
|  | 	if c.PrivateKey != "" { | ||||||
|  | 		key := aeshelper.AesEcbDecrypt(c.PrivateKey) | ||||||
|  | 		query.Where("private_key =?", key) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	err = e.Orm.Model(&data). | 	err = query. | ||||||
| 		Scopes( | 		Scopes( | ||||||
| 			cDto.MakeCondition(c.GetNeedSearch()), | 			cDto.MakeCondition(c.GetNeedSearch()), | ||||||
| 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | ||||||
| @ -174,7 +181,7 @@ func (e *WmWalletInfo) ScheduledTask() error { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		for i := range datas { | 		for i := range datas { | ||||||
| 			amount, err := ethbalanceofhelper.GetERC20Balance(client, token.TokenAddress, datas[i].Address, token.Decimals) | 			amount, err := ethbalanceofhelper.GetBalance(client, token.TokenAddress, datas[i].Address, token.Decimals) | ||||||
|  |  | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				e.Log.Errorf("GetERC20Balance error:%s", err) | 				e.Log.Errorf("GetERC20Balance error:%s", err) | ||||||
| @ -245,3 +252,65 @@ func (e *WmWalletInfo) ClearAll() error { | |||||||
|  |  | ||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // 根据excel导入数据 | ||||||
|  | func (e *WmWalletInfo) ExcelImport(c *gin.Context) []string { | ||||||
|  | 	dataRows, headers, err := excelhelper.GetExcelContent(c) | ||||||
|  | 	errors := []string{} | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		errors = append(errors, err.Error()) | ||||||
|  | 		return errors | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	datas, err := excelhelper.MapExcelToStruct[dto.WmWalletExcelImportReq](dataRows, headers) | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		errors = append(errors, err.Error()) | ||||||
|  | 		return errors | ||||||
|  | 	} | ||||||
|  | 	// entitys := make([]models.WmWalletInfo, 0) | ||||||
|  | 	var count int64 | ||||||
|  | 	for _, data := range datas { | ||||||
|  | 		privateKey := strings.ReplaceAll(data.PrivateKey, " ", "") | ||||||
|  | 		if privateKey == "" { | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		_, address, _ := ethtransferhelper.GetAddressFromPrivateKey(privateKey) | ||||||
|  | 		entity := models.WmWalletInfo{ | ||||||
|  | 			PrivateKey: aeshelper.AesEcbEncrypt(privateKey), | ||||||
|  | 			Address:    address.String(), | ||||||
|  | 			Remark:     data.Remark, | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if err := e.Orm.Model(entity).Where("private_key =?", entity.PrivateKey).Count(&count).Error; err != nil { | ||||||
|  | 			e.Log.Errorf("db error:%s", err) | ||||||
|  | 		} | ||||||
|  | 		if count == 0 { | ||||||
|  | 			if err := e.Orm.Create(&entity).Error; err != nil { | ||||||
|  | 				e.Log.Errorf("db error:%s", err) | ||||||
|  | 				errors = append(errors, err.Error()) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		// entitys = append(entitys, entity) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// if len(entitys) > 0 { | ||||||
|  | 	// 	if err := e.Orm.CreateInBatches(entitys, 100).Error; err != nil { | ||||||
|  | 	// 		e.Log.Errorf("定时转账保存数据库失败 error:%s", err) | ||||||
|  | 	// 		return err | ||||||
|  | 	// 	} | ||||||
|  | 	// } | ||||||
|  |  | ||||||
|  | 	return errors | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 批量修改备注 | ||||||
|  | func (e *WmWalletInfo) BatchUpdateRemark(req *dto.WmWalletInfoBatchUpdateReq) error { | ||||||
|  | 	if err := e.Orm.Model(&models.WmWalletInfo{}).Where("id in ?", req.Ids).Update("remark", req.Remark).Error; err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								static/excel/钱包导入模板.xlsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								static/excel/钱包导入模板.xlsx
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -36,6 +36,30 @@ const erc20ABI = `[ | |||||||
|     } |     } | ||||||
| ]` | ]` | ||||||
| 
 | 
 | ||||||
|  | // GetBalance 查询  余额并转换为正常单位 (使用 decimal) | ||||||
|  | func GetBalance(client *ethclient.Client, tokenAddress, accountAddress string, decimals int) (decimal.Decimal, error) { | ||||||
|  | 	switch tokenAddress { | ||||||
|  | 	case "0": | ||||||
|  | 		return GetEthBalance(client, accountAddress, decimals) | ||||||
|  | 	default: | ||||||
|  | 		return GetERC20Balance(client, tokenAddress, accountAddress, decimals) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GetEthBalance 查询以太坊余额并转换为正常单位 (使用 decimal) | ||||||
|  | func GetEthBalance(client *ethclient.Client, accountAddress string, decimals int) (decimal.Decimal, error) { | ||||||
|  | 	account := common.HexToAddress(accountAddress) | ||||||
|  | 	balance, err := client.BalanceAt(context.Background(), account, nil) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return decimal.Zero, fmt.Errorf("查询余额失败 err:%v", err) | ||||||
|  | 	} | ||||||
|  | 	balanceDecimal := decimal.NewFromBigInt(balance, 0) // Create decimal from big.Int | ||||||
|  | 	decimalFactor := decimal.NewFromInt(10).Pow(decimal.NewFromInt(int64(decimals))) | ||||||
|  | 	readableBalance := balanceDecimal.Div(decimalFactor) | ||||||
|  | 
 | ||||||
|  | 	return readableBalance, nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // GetERC20Balance 查询 ERC-20 代币余额并转换为正常单位 (使用 decimal) | // GetERC20Balance 查询 ERC-20 代币余额并转换为正常单位 (使用 decimal) | ||||||
| // tokenAddress: 代币合约地址 | // tokenAddress: 代币合约地址 | ||||||
| // accountAddress: 账户地址 | // accountAddress: 账户地址 | ||||||
							
								
								
									
										25
									
								
								utils/ethbalanceofhelper/balanceof_helper_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								utils/ethbalanceofhelper/balanceof_helper_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | package ethbalanceofhelper | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | func TestBalanceOfHelper(t *testing.T) { | ||||||
|  | 	api := "https://stylish-cool-fire.ethereum-sepolia.quiknode.pro/17572db4c091accfa5dc6faa0c60a805e5173459" | ||||||
|  | 	proxy := "http://127.0.0.1:7890" | ||||||
|  | 	client, err := EthClientWithProxy(api, proxy) | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Error(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	address := "0x5079a681a2a2344f4da79a21e187d6ed075ba90a" | ||||||
|  | 	balance, err := GetBalance(client, "0", address, 18) | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Error(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	fmt.Println("余额:", balance) | ||||||
|  | } | ||||||
| @ -28,7 +28,7 @@ func TransferErc20( | |||||||
| 	tokenAmount decimal.Decimal, | 	tokenAmount decimal.Decimal, | ||||||
| 	tokenDecimals uint8) (*types.Transaction, error) { | 	tokenDecimals uint8) (*types.Transaction, error) { | ||||||
| 	switch tokenAddress { | 	switch tokenAddress { | ||||||
| 	case "": | 	case "0": | ||||||
| 		return TransferEth(client, fromPrivateKey, toAddress, tokenAmount) | 		return TransferEth(client, fromPrivateKey, toAddress, tokenAmount) | ||||||
| 	default: | 	default: | ||||||
| 		return TransferErc20Token(client, fromPrivateKey, tokenAddress, toAddress, tokenAmount, tokenDecimals) | 		return TransferErc20Token(client, fromPrivateKey, tokenAddress, toAddress, tokenAmount, tokenDecimals) | ||||||
| @ -81,7 +81,7 @@ func TransferEth(client *ethclient.Client, fromPrivateKey string, toAddress stri | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// 9. (预估gas+基础费用)*1.1 作为 GasLimit | 	// 9. (预估gas+基础费用)*1.1 作为 GasLimit | ||||||
| 	gasLimit = (gasLimit + 21000) * 12 / 10 // 增加 20% | 	gasLimit = (gasLimit + 21000) * 19 / 10 // 增加 90% | ||||||
| 	if gasLimit < 23000 { | 	if gasLimit < 23000 { | ||||||
| 		gasLimit = 23000 // 最小 Gas 限制 | 		gasLimit = 23000 // 最小 Gas 限制 | ||||||
| 	} | 	} | ||||||
| @ -182,7 +182,7 @@ func TransferErc20Token( | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// 9. (预估gas+基础费用)*1.1 作为 GasLimit | 	// 9. (预估gas+基础费用)*1.1 作为 GasLimit | ||||||
| 	gasLimit = (gasLimit + 21000) * 12 / 10 // 增加 20% | 	gasLimit = (gasLimit + 21000) * 19 / 10 // 增加 90% | ||||||
| 	if gasLimit < 23000 { | 	if gasLimit < 23000 { | ||||||
| 		gasLimit = 23000 // 最小 Gas 限制 | 		gasLimit = 23000 // 最小 Gas 限制 | ||||||
| 	} | 	} | ||||||
| @ -274,5 +274,5 @@ func IsValidAddress(address string) bool { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	checksumAddress := common.HexToAddress(address).String() | 	checksumAddress := common.HexToAddress(address).String() | ||||||
| 	return address == checksumAddress | 	return strings.EqualFold(address, checksumAddress) | ||||||
| } | } | ||||||
|  | |||||||
| @ -167,3 +167,46 @@ func MapExcelToStruct[T any](rows [][]string, headers []string) ([]T, error) { | |||||||
|  |  | ||||||
| 	return results, nil | 	return results, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // 获取上传文件的数据 | ||||||
|  | func GetExcelContent(c *gin.Context) (dataRows [][]string, headers []string, err error) { | ||||||
|  | 	// 获取上传的文件 | ||||||
|  | 	file, err := c.FormFile("file") | ||||||
|  | 	if err != nil { | ||||||
|  | 		err = errors.New("文件上传失败") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// 打开上传的文件 | ||||||
|  | 	src, err := file.Open() | ||||||
|  | 	if err != nil { | ||||||
|  | 		err = errors.New("文件打开失败") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	defer src.Close() | ||||||
|  |  | ||||||
|  | 	// 使用 excelize 读取 Excel 文件 | ||||||
|  | 	xlFile, err := excelize.OpenReader(src) | ||||||
|  | 	if err != nil { | ||||||
|  | 		err = errors.New("读取 Excel 文件失败") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	sheetName := xlFile.GetSheetName(0) | ||||||
|  |  | ||||||
|  | 	// 假设读取第一个工作表中的数据 | ||||||
|  | 	rows, err := xlFile.GetRows(sheetName) | ||||||
|  | 	if err != nil { | ||||||
|  | 		err = errors.New("读取 Excel 行数据失败") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if len(rows) < 1 { | ||||||
|  | 		err = errors.New("没有数据内容") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	headers = rows[0] // First row is the header | ||||||
|  | 	dataRows = rows[1:] | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user