1、调整gas费浮动比例为90%
This commit is contained in:
		| @ -43,7 +43,7 @@ func (e WmTransferItem) GetPage(c *gin.Context) { | ||||
| 	} | ||||
|  | ||||
| 	p := actions.GetPermissionFromContext(c) | ||||
| 	list := make([]models.WmTransferItem, 0) | ||||
| 	list := make([]dto.WmTransferItemResp, 0) | ||||
| 	var count int64 | ||||
|  | ||||
| 	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(), "查询成功") | ||||
| } | ||||
|  | ||||
| // 清除自动转账 | ||||
| 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, "清空成功") | ||||
| } | ||||
|  | ||||
| // 根据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:"-"` | ||||
| 	Fail         int    `json:"fail" gorm:"-"` | ||||
| 	Pending      int    `json:"pending" gorm:"-"` | ||||
| 	NetworkName  string `json:"networkName" gorm:"-"` | ||||
| 	TokenName    string `json:"tokenName" gorm:"-"` | ||||
| 	models.ModelTime | ||||
| 	models.ControlBy | ||||
| } | ||||
|  | ||||
| @ -12,6 +12,7 @@ type WmWalletInfo struct { | ||||
| 	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余额"` | ||||
| 	Remark     string          `json:"remark" gorm:"type:varchar(255);comment:备注信息"` | ||||
| 	models.ModelTime | ||||
| 	models.ControlBy | ||||
| } | ||||
|  | ||||
| @ -24,6 +24,7 @@ func registerWmTransferItemRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJW | ||||
| 		r.PUT("/:id", actions.PermissionAction(), api.Update) | ||||
| 		r.DELETE("", api.Delete) | ||||
|  | ||||
| 		r.DELETE("/clear", api.ClearAutoLog) | ||||
| 		r.GET("/export", actions.PermissionAction(), api.Export) | ||||
| 		r.GET("/export-auto-log", actions.PermissionAction(), api.ExportAutoLog) | ||||
| 		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.DELETE("", api.Delete) | ||||
| 		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:"-"` | ||||
| 	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:"代币名称"` | ||||
| 	TransType      int    `form:"transType"  search:"-" comment:"转账类型 1-百分比 2-实际金额"` | ||||
| 	WmTokenOrder | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -2,9 +2,11 @@ package dto | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"go-admin/app/admin/models" | ||||
| 	"go-admin/common/dto" | ||||
| 	common "go-admin/common/models" | ||||
| 	"go-admin/utils/ethtransferhelper" | ||||
| 	"strings" | ||||
|  | ||||
| 	"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 | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -18,6 +18,9 @@ type WmTransferItemGetPageReq struct { | ||||
| type WmTransferItemAutoLogPageReq struct { | ||||
| 	dto.Pagination `search:"-"` | ||||
| 	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 | ||||
| } | ||||
|  | ||||
| @ -146,6 +149,8 @@ type WmTransferItemExportReq struct { | ||||
| } | ||||
|  | ||||
| type WmTransferItemExportData struct { | ||||
| 	NetworkName  string          `json:"networkName" excel:"网络名称"` | ||||
| 	TokenName    string          `json:"tokenName" excel:"代币名称"` | ||||
| 	PrivateKey   string          `json:"privateKey" excel:"私钥"` | ||||
| 	TokenAddress string          `json:"tokenAddress" excel:"代币地址"` | ||||
| 	FromAddress  string          `json:"fromAddress" excel:"来源地址"` | ||||
|  | ||||
| @ -10,7 +10,7 @@ import ( | ||||
|  | ||||
| type WmWalletInfoGetPageReq struct { | ||||
| 	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 | ||||
| } | ||||
|  | ||||
| @ -31,6 +31,7 @@ func (m *WmWalletInfoGetPageReq) GetNeedSearch() interface{} { | ||||
|  | ||||
| type WmWalletInfoBatchInsertReq struct { | ||||
| 	Keys   string `json:"keys"` | ||||
| 	Remark string `json:"remark"` | ||||
| 	common.ControlBy | ||||
| } | ||||
|  | ||||
| @ -103,3 +104,14 @@ type WmWalletInfoDeleteReq struct { | ||||
| func (s *WmWalletInfoDeleteReq) GetId() interface{} { | ||||
| 	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 { | ||||
| 	var err error | ||||
| 	var data models.WmToken | ||||
|  | ||||
| 	err = e.Orm.Model(&data). | ||||
| 	query := e.Orm.Model(&data). | ||||
| 		Scopes( | ||||
| 			cDto.MakeCondition(c.GetNeedSearch()), | ||||
| 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | ||||
| 			actions.Permission(data.TableName(), p), | ||||
| 		). | ||||
| 		) | ||||
|  | ||||
| 	if c.TransType > 0 { | ||||
| 		query.Where("trans_type = ?", c.TransType) | ||||
| 	} | ||||
|  | ||||
| 	err = query. | ||||
| 		Find(list).Limit(-1).Offset(-1). | ||||
| 		Count(count).Error | ||||
| 	if err != nil { | ||||
|  | ||||
| @ -56,6 +56,10 @@ func (e *WmTransfer) GetPage(c *dto.WmTransferGetPageReq, p *actions.DataPermiss | ||||
| 	} | ||||
|  | ||||
| 	itemData, _ := e.GetItemData(transferIds) | ||||
| 	networkService := WmNetwork{Service: e.Service} | ||||
| 	networks, _ := networkService.GetAll() | ||||
| 	tokenService := WmToken{Service: e.Service} | ||||
| 	tokens, _ := tokenService.GetAll() | ||||
|  | ||||
| 	for i := range *list { | ||||
| 		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 | ||||
| 	} | ||||
|  | ||||
| @ -196,6 +214,7 @@ func (e *WmTransfer) Insert(c *dto.WmTransferInsertReq) error { | ||||
| 			caches[i].TransferId = data.Id | ||||
| 			caches[i].IsAuto = 2 | ||||
| 			caches[i].TokenAddress = c.TokenAddress | ||||
| 			caches[i].Decimals = token.Decimals | ||||
| 		} | ||||
|  | ||||
| 		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("连接区块链失败") | ||||
| 		} | ||||
|  | ||||
| 		amount, err = ethbalanceofhelper.GetERC20Balance(client, tokenAddress, accountAddress.String(), decimals) | ||||
| 		amount, err = ethbalanceofhelper.GetBalance(client, tokenAddress, accountAddress.String(), decimals) | ||||
|  | ||||
| 		if err != nil { | ||||
| 			return amount, errors.New("查询主账号余额失败") | ||||
| @ -372,11 +391,11 @@ func (e *WmTransfer) CheckHashStatus() error { | ||||
| // 清理数据 | ||||
| func (e *WmTransfer) ClearAll() error { | ||||
| 	err := e.Orm.Transaction(func(tx *gorm.DB) error { | ||||
| 		if err1 := tx.Exec("truncate table wm_transfer_item").Error; err1 != nil { | ||||
| 		if err1 := tx.Exec("delete from wm_transfer_item where is_auto = 2").Error; err1 != nil { | ||||
| 			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 | ||||
| 		} | ||||
|  | ||||
|  | ||||
| @ -21,9 +21,10 @@ type WmTransferItem struct { | ||||
| } | ||||
|  | ||||
| // 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 data models.WmTransferItem | ||||
| 	var datas []models.WmTransferItem | ||||
|  | ||||
| 	err = e.Orm.Model(&data). | ||||
| 		Scopes( | ||||
| @ -31,15 +32,48 @@ func (e *WmTransferItem) GetPage(c *dto.WmTransferItemGetPageReq, p *actions.Dat | ||||
| 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | ||||
| 			actions.Permission(data.TableName(), p), | ||||
| 		). | ||||
| 		Find(list).Limit(-1).Offset(-1). | ||||
| 		Find(&datas).Limit(-1).Offset(-1). | ||||
| 		Count(count).Error | ||||
| 	if err != nil { | ||||
| 		e.Log.Errorf("WmTransferItemService GetPage error:%s \r\n", err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	for i := 0; i < len(*list); i++ { | ||||
| 		(*list)[i].PrivateKey = stringhelper.DesensitizeWalletAddress(aeshelper.AesEcbDecrypt((*list)[i].PrivateKey)) | ||||
| 	networkService := WmNetwork{Service: e.Service} | ||||
| 	networks, _ := networkService.GetAll() | ||||
| 	tokenService := WmToken{Service: e.Service} | ||||
| 	tokens, _ := tokenService.GetAll() | ||||
|  | ||||
| 	for i := 0; i < len(datas); i++ { | ||||
| 		item := dto.WmTransferItemResp{} | ||||
| 		item.Id = datas[i].Id | ||||
| 		item.PrivateKey = stringhelper.DesensitizeWalletAddress(aeshelper.AesEcbDecrypt(datas[i].PrivateKey)) | ||||
| 		item.FromAddress = datas[i].FromAddress | ||||
| 		item.ToAddress = datas[i].ToAddress | ||||
| 		item.TokenAddress = datas[i].TokenAddress | ||||
| 		item.Amount = datas[i].Amount | ||||
| 		item.Status = datas[i].Status | ||||
| 		item.Remark = datas[i].Remark | ||||
| 		item.Type = datas[i].Type | ||||
| 		item.TypeValue = datas[i].TypeValue | ||||
| 		item.Hash = datas[i].Hash | ||||
| 		item.CreateAt = datas[i].CreatedAt | ||||
|  | ||||
| 		for _, network := range networks { | ||||
| 			if network.Id == datas[i].NetworkId { | ||||
| 				item.NetworkName = network.NetworkName | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		for _, token := range tokens { | ||||
| 			if token.NetworkId == datas[i].NetworkId && token.TokenAddress == datas[i].TokenAddress { | ||||
| 				item.TokenName = token.TokenName | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		*list = append(*list, item) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| @ -50,9 +84,22 @@ func (e *WmTransferItem) GetAutoTransferLogPage(c *dto.WmTransferItemAutoLogPage | ||||
| 	var err error | ||||
| 	var data models.WmTransferItem | ||||
| 	var datas []models.WmTransferItem | ||||
| 	query := e.Orm.Model(&data). | ||||
| 		Where("is_auto = 1") | ||||
|  | ||||
| 	err = e.Orm.Model(&data). | ||||
| 		Where("is_auto = 1"). | ||||
| 	if c.StartAmount >= 0 { | ||||
| 		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( | ||||
| 			cDto.MakeCondition(c.GetNeedSearch()), | ||||
| 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | ||||
| @ -111,8 +158,21 @@ func (e *WmTransferItem) ExportAutoLog(req *dto.WmTransferItemAutoLogPageReq, c | ||||
| 	var err error | ||||
| 	var data models.WmTransferItem | ||||
| 	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"). | ||||
| 		Scopes( | ||||
| 			cDto.MakeCondition(req.GetNeedSearch()), | ||||
| @ -259,6 +319,11 @@ func (e *WmTransferItem) ExportExcel(req *dto.WmTransferItemExportReq, p *action | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	networkService := WmNetwork{Service: e.Service} | ||||
| 	networks, _ := networkService.GetAll() | ||||
| 	tokenService := WmToken{Service: e.Service} | ||||
| 	tokens, _ := tokenService.GetAll() | ||||
|  | ||||
| 	for i := 0; i < len(datas); i++ { | ||||
| 		(datas)[i].PrivateKey = stringhelper.DesensitizeWalletAddress(aeshelper.AesEcbDecrypt((datas)[i].PrivateKey)) | ||||
| 		exportData := dto.WmTransferItemExportData{ | ||||
| @ -281,6 +346,21 @@ func (e *WmTransferItem) ExportExcel(req *dto.WmTransferItemExportReq, p *action | ||||
| 		default: | ||||
| 			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) | ||||
| 	} | ||||
|  | ||||
| @ -290,3 +370,13 @@ func (e *WmTransferItem) ExportExcel(req *dto.WmTransferItemExportReq, p *action | ||||
|  | ||||
| 	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" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"github.com/go-admin-team/go-admin-core/sdk/service" | ||||
| 	"github.com/shopspring/decimal" | ||||
| 	"gorm.io/gorm" | ||||
| @ -16,6 +17,7 @@ import ( | ||||
| 	"go-admin/utils/aeshelper" | ||||
| 	"go-admin/utils/ethbalanceofhelper" | ||||
| 	"go-admin/utils/ethtransferhelper" | ||||
| 	"go-admin/utils/excelhelper" | ||||
| 	"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 { | ||||
| 	var err error | ||||
| 	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( | ||||
| 			cDto.MakeCondition(c.GetNeedSearch()), | ||||
| 			cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), | ||||
| @ -174,7 +181,7 @@ func (e *WmWalletInfo) ScheduledTask() error { | ||||
| 		} | ||||
|  | ||||
| 		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 { | ||||
| 				e.Log.Errorf("GetERC20Balance error:%s", err) | ||||
| @ -245,3 +252,65 @@ func (e *WmWalletInfo) ClearAll() error { | ||||
|  | ||||
| 	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) | ||||
| // tokenAddress: 代币合约地址 | ||||
| // 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, | ||||
| 	tokenDecimals uint8) (*types.Transaction, error) { | ||||
| 	switch tokenAddress { | ||||
| 	case "": | ||||
| 	case "0": | ||||
| 		return TransferEth(client, fromPrivateKey, toAddress, tokenAmount) | ||||
| 	default: | ||||
| 		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 | ||||
| 	gasLimit = (gasLimit + 21000) * 12 / 10 // 增加 20% | ||||
| 	gasLimit = (gasLimit + 21000) * 19 / 10 // 增加 90% | ||||
| 	if gasLimit < 23000 { | ||||
| 		gasLimit = 23000 // 最小 Gas 限制 | ||||
| 	} | ||||
| @ -182,7 +182,7 @@ func TransferErc20Token( | ||||
| 	} | ||||
|  | ||||
| 	// 9. (预估gas+基础费用)*1.1 作为 GasLimit | ||||
| 	gasLimit = (gasLimit + 21000) * 12 / 10 // 增加 20% | ||||
| 	gasLimit = (gasLimit + 21000) * 19 / 10 // 增加 90% | ||||
| 	if gasLimit < 23000 { | ||||
| 		gasLimit = 23000 // 最小 Gas 限制 | ||||
| 	} | ||||
| @ -274,5 +274,5 @@ func IsValidAddress(address string) bool { | ||||
| 	} | ||||
|  | ||||
| 	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 | ||||
| } | ||||
|  | ||||
| // 获取上传文件的数据 | ||||
| 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