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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,9 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +31,7 @@ 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