chain balance query
This commit is contained in:
parent
0303dd302e
commit
e7da389340
@ -3,6 +3,8 @@ package system
|
|||||||
import (
|
import (
|
||||||
"f5"
|
"f5"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"main/mt"
|
||||||
|
"main/service"
|
||||||
|
|
||||||
"main/constant"
|
"main/constant"
|
||||||
"main/model/system"
|
"main/model/system"
|
||||||
@ -125,3 +127,68 @@ func (this *NFTApi) NFTQuery(c *gin.Context) {
|
|||||||
return p
|
return p
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *NFTApi) BalanceQuery(c *gin.Context) {
|
||||||
|
type BalanceQueryForm struct {
|
||||||
|
Account string `json:"account_address"`
|
||||||
|
}
|
||||||
|
|
||||||
|
reqJson := BalanceQueryForm{}
|
||||||
|
if !checkparam(&reqJson, c) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
selfaccount := false
|
||||||
|
if reqJson.Account != "" {
|
||||||
|
mt.Table.Chain.Traverse(func(item *mt.Chain) bool {
|
||||||
|
if item.GetAccountAddress() == reqJson.Account {
|
||||||
|
selfaccount = true
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type retitem struct {
|
||||||
|
Account string `json:"account_address"`
|
||||||
|
TokenName string `json:"token_name"`
|
||||||
|
ChainBalance string `json:"chain_balance"`
|
||||||
|
Recharge int64 `json:"recharge"`
|
||||||
|
NetId int32 `json:"net_id"`
|
||||||
|
TokenAddress string `json:"-"`
|
||||||
|
}
|
||||||
|
result := []retitem{}
|
||||||
|
|
||||||
|
mt.Table.Chain.Traverse(func(item *mt.Chain) bool {
|
||||||
|
account := item.GetAccountAddress()
|
||||||
|
if selfaccount && account != reqJson.Account {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if reqJson.Account != "" && !selfaccount {
|
||||||
|
account = reqJson.Account
|
||||||
|
}
|
||||||
|
|
||||||
|
p := q5.NewSliceElement(&result)
|
||||||
|
p.Account = account
|
||||||
|
p.NetId = item.GetNetId()
|
||||||
|
p.TokenName = item.GetTokenName()
|
||||||
|
p.TokenAddress = item.GetTokenAddress()
|
||||||
|
|
||||||
|
key := fmt.Sprintf("%d$%s", item.GetNetId(), item.GetTokenAddress())
|
||||||
|
if selfaccount || reqJson.Account == "" {
|
||||||
|
p.ChainBalance, p.Recharge = service.Balance.GetGlobalBalance(key)
|
||||||
|
} else {
|
||||||
|
p.ChainBalance, p.Recharge = service.Balance.GetAccoutBalance(key, account)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, gin.H{
|
||||||
|
"code": 0,
|
||||||
|
"message": "",
|
||||||
|
"data": result,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -18,6 +18,7 @@ const (
|
|||||||
APP_MODULE_IDX = iota
|
APP_MODULE_IDX = iota
|
||||||
ROUTER_MODULE_IDX
|
ROUTER_MODULE_IDX
|
||||||
SESSION_MGR_MODULE_IDX
|
SESSION_MGR_MODULE_IDX
|
||||||
|
SERVICE_MGR_MODULE_IDX
|
||||||
MAX_MODULE_IDX
|
MAX_MODULE_IDX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
package global
|
package global
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"q5"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"main/constant"
|
|
||||||
"main/common"
|
"main/common"
|
||||||
|
"main/constant"
|
||||||
|
"q5"
|
||||||
)
|
)
|
||||||
|
|
||||||
var modules [constant.MAX_MODULE_IDX]q5.Module
|
var modules [constant.MAX_MODULE_IDX]q5.Module
|
||||||
var initOrders = []int32 {
|
var initOrders = []int32 {
|
||||||
constant.ROUTER_MODULE_IDX,
|
constant.ROUTER_MODULE_IDX,
|
||||||
constant.SESSION_MGR_MODULE_IDX,
|
constant.SESSION_MGR_MODULE_IDX,
|
||||||
|
constant.SERVICE_MGR_MODULE_IDX,
|
||||||
}
|
}
|
||||||
|
|
||||||
var app common.App
|
var app common.App
|
||||||
@ -39,6 +40,10 @@ func RegModule(idx int32, m q5.Module) {
|
|||||||
{
|
{
|
||||||
sessionMgr = m.(common.SessionMgr)
|
sessionMgr = m.(common.SessionMgr)
|
||||||
}
|
}
|
||||||
|
case constant.SERVICE_MGR_MODULE_IDX:
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
panic("unknow module")
|
panic("unknow module")
|
||||||
|
14
server/adminserver/mt/Chain.go
Normal file
14
server/adminserver/mt/Chain.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package mt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"f5"
|
||||||
|
"main/mtb"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Chain struct {
|
||||||
|
mtb.Erc20
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChainTable struct {
|
||||||
|
f5.RawMetaTable[Chain]
|
||||||
|
}
|
@ -18,6 +18,7 @@ type table struct {
|
|||||||
ConfDb *ConfDbTable
|
ConfDb *ConfDbTable
|
||||||
Item *ItemTable
|
Item *ItemTable
|
||||||
Contract *ContractTable
|
Contract *ContractTable
|
||||||
|
Chain *ChainTable
|
||||||
}
|
}
|
||||||
|
|
||||||
var Table = f5.New(func(this *table) {
|
var Table = f5.New(func(this *table) {
|
||||||
@ -78,4 +79,8 @@ var Table = f5.New(func(this *table) {
|
|||||||
this.FileName = "../res/item@item.json"
|
this.FileName = "../res/item@item.json"
|
||||||
this.PrimKey = "id"
|
this.PrimKey = "id"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.Chain = f5.New(func(this *ChainTable) {
|
||||||
|
this.FileName = "../config/erc20.json"
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -129,6 +129,7 @@ type Item struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Erc20 struct {
|
type Erc20 struct {
|
||||||
|
token_name string
|
||||||
net_id int32
|
net_id int32
|
||||||
rpc_url string
|
rpc_url string
|
||||||
account_address string
|
account_address string
|
||||||
@ -602,6 +603,14 @@ func (this *Item) HasSubType() bool {
|
|||||||
return (this._flags1_ & (uint64(1) << 4)) > 0
|
return (this._flags1_ & (uint64(1) << 4)) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (this *Erc20) GetTokenName() string {
|
||||||
|
return this.token_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *Erc20) HasTokenName() bool {
|
||||||
|
return (this._flags1_ & (uint64(1) << 1)) > 0
|
||||||
|
}
|
||||||
|
|
||||||
func (this *Erc20) GetNetId() int32 {
|
func (this *Erc20) GetNetId() int32 {
|
||||||
return this.net_id
|
return this.net_id
|
||||||
}
|
}
|
||||||
@ -727,6 +736,7 @@ func (this *Item) LoadFromKv(kv map[string]interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (this *Erc20) LoadFromKv(kv map[string]interface{}) {
|
func (this *Erc20) LoadFromKv(kv map[string]interface{}) {
|
||||||
|
f5.ReadMetaTableField(&this.token_name, "token_name", &this._flags1_, 1, kv)
|
||||||
f5.ReadMetaTableField(&this.net_id, "net_id", &this._flags1_, 2, kv)
|
f5.ReadMetaTableField(&this.net_id, "net_id", &this._flags1_, 2, kv)
|
||||||
f5.ReadMetaTableField(&this.rpc_url, "rpc_url", &this._flags1_, 3, kv)
|
f5.ReadMetaTableField(&this.rpc_url, "rpc_url", &this._flags1_, 3, kv)
|
||||||
f5.ReadMetaTableField(&this.account_address, "account_address", &this._flags1_, 4, kv)
|
f5.ReadMetaTableField(&this.account_address, "account_address", &this._flags1_, 4, kv)
|
||||||
|
@ -106,6 +106,7 @@ message Item
|
|||||||
|
|
||||||
message Erc20
|
message Erc20
|
||||||
{
|
{
|
||||||
|
optional string token_name = 1;
|
||||||
optional int32 net_id = 2;
|
optional int32 net_id = 2;
|
||||||
optional string rpc_url = 3;
|
optional string rpc_url = 3;
|
||||||
optional string account_address = 4;
|
optional string account_address = 4;
|
||||||
|
@ -16,5 +16,6 @@ func (nr *NFTRouter) InitNFTRouter(priRouter *gin.RouterGroup) {
|
|||||||
group.POST("orderquery", middleware.Permission("api/v1/nft/orderquery", api.OrderQuery))
|
group.POST("orderquery", middleware.Permission("api/v1/nft/orderquery", api.OrderQuery))
|
||||||
group.POST("salequery", middleware.Permission("api/v1/nft/salequery", api.SaleQuery))
|
group.POST("salequery", middleware.Permission("api/v1/nft/salequery", api.SaleQuery))
|
||||||
group.POST("nftquery", middleware.Permission("api/v1/nft/nftquery", api.NFTQuery))
|
group.POST("nftquery", middleware.Permission("api/v1/nft/nftquery", api.NFTQuery))
|
||||||
|
group.POST("balancequery", middleware.Permission("api/v1/nft/balancequery", api.BalanceQuery))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
196
server/adminserver/service/balance.go
Normal file
196
server/adminserver/service/balance.go
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"adminserver/constant"
|
||||||
|
"f5"
|
||||||
|
"fmt"
|
||||||
|
"main/mt"
|
||||||
|
"q5"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type baseinfo struct {
|
||||||
|
recharge int64
|
||||||
|
balance string
|
||||||
|
}
|
||||||
|
|
||||||
|
type addressBalance struct {
|
||||||
|
gcTime int64
|
||||||
|
infoList q5.ConcurrentMap[string, *baseinfo] // <netid$toke_addr, baseinfo>
|
||||||
|
}
|
||||||
|
|
||||||
|
type chainbalance struct {
|
||||||
|
gcTime int64
|
||||||
|
|
||||||
|
infoList q5.ConcurrentMap[string, *baseinfo] // <netid$toke_addr, baseinfo>
|
||||||
|
addressBalanceList q5.ConcurrentMap[string, *addressBalance] // <account, addressBalance>
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *chainbalance) init() {
|
||||||
|
this.infoList = q5.ConcurrentMap[string, *baseinfo]{}
|
||||||
|
this.addressBalanceList = q5.ConcurrentMap[string, *addressBalance]{}
|
||||||
|
this.GetGlobalBalance("")
|
||||||
|
go this.checkBalanceList()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *chainbalance) unInit() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *chainbalance) GetAccoutBalance(netidtoken string, acc string) (string, int64) {
|
||||||
|
info, exist := this.addressBalanceList.Load(acc)
|
||||||
|
if !exist {
|
||||||
|
tmpinfo := new(addressBalance)
|
||||||
|
this.addressBalanceList.Store(acc, tmpinfo)
|
||||||
|
info = &tmpinfo
|
||||||
|
}
|
||||||
|
|
||||||
|
if nowseconds := f5.GetApp().GetRealSeconds(); (*info).gcTime+60 < nowseconds {
|
||||||
|
(*info).gcTime = nowseconds
|
||||||
|
this.getChainBalance(acc)
|
||||||
|
}
|
||||||
|
|
||||||
|
v, exist := (*info).infoList.Load(netidtoken)
|
||||||
|
if exist {
|
||||||
|
return (*v).balance, (*v).recharge
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *chainbalance) GetGlobalBalance(netidtoken string) (string, int64) {
|
||||||
|
if nowseconds := f5.GetApp().GetRealSeconds(); this.gcTime+60 < nowseconds {
|
||||||
|
this.gcTime = nowseconds
|
||||||
|
go this.getChainBalance("")
|
||||||
|
}
|
||||||
|
|
||||||
|
v, exist := this.infoList.Load(netidtoken)
|
||||||
|
if exist {
|
||||||
|
return (*v).balance, (*v).recharge
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *chainbalance) getChainBalance(acc string) {
|
||||||
|
tmpmap := q5.ConcurrentMap[string, int32]{}
|
||||||
|
url := mt.Table.Web3ServiceCluster.RandElement().GetUrl() + "/webapp/index.php"
|
||||||
|
mt.Table.Chain.Traverse(func(item *mt.Chain) bool {
|
||||||
|
var info *baseinfo
|
||||||
|
key := fmt.Sprintf("%d$%s", item.GetNetId(), item.GetTokenAddress())
|
||||||
|
if acc == "" {
|
||||||
|
tmp, exist := this.infoList.Load(key)
|
||||||
|
if !exist {
|
||||||
|
info = new(baseinfo)
|
||||||
|
this.infoList.Store(key, info)
|
||||||
|
tmp = &info
|
||||||
|
} else {
|
||||||
|
info = *tmp
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
accinfo, exist := this.addressBalanceList.Load(acc)
|
||||||
|
if !exist {
|
||||||
|
tmp := new(addressBalance)
|
||||||
|
this.addressBalanceList.Store(acc, tmp)
|
||||||
|
accinfo = &tmp
|
||||||
|
info = new(baseinfo)
|
||||||
|
tmp.infoList.Store(key, info)
|
||||||
|
} else {
|
||||||
|
keyinfo, exist := (*accinfo).infoList.Load(key)
|
||||||
|
if !exist {
|
||||||
|
info = new(baseinfo)
|
||||||
|
(*accinfo).infoList.Store(key, info)
|
||||||
|
} else {
|
||||||
|
info = *keyinfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
sql := fmt.Sprintf(`SELECT sum(diamond) FROM t_recharge_order WHERE idx > 0 AND pay_status = 1 AND net_id = %d AND currency_name = '%s'`, item.GetNetId(), strings.ToLower(item.GetTokenAddress()))
|
||||||
|
if acc != "" {
|
||||||
|
sql = fmt.Sprintf(`%s AND account_address = '%s'`, sql, strings.ToLower(acc))
|
||||||
|
}
|
||||||
|
|
||||||
|
f5.GetGoStyleDb().RawQuery(
|
||||||
|
constant.BCNFT_DB,
|
||||||
|
sql,
|
||||||
|
[]string{},
|
||||||
|
func(err error, ds *f5.DataSet) {
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if ds.Next() {
|
||||||
|
info.recharge = q5.SafeToInt64(ds.GetByIndex(0)) / 100
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
rpcurl := item.GetRpcUrl()
|
||||||
|
|
||||||
|
tmpmap.Store(key, 1)
|
||||||
|
doquery := func(account string, tokeaddr string, balance *string) {
|
||||||
|
f5.GetHttpCliMgr().SendGoStyleRequest(
|
||||||
|
url,
|
||||||
|
map[string]string{
|
||||||
|
"c": "Erc20",
|
||||||
|
"a": "getBalance",
|
||||||
|
"rpc_url": rpcurl,
|
||||||
|
"account_address": account,
|
||||||
|
"token_address": tokeaddr,
|
||||||
|
},
|
||||||
|
func(rsp f5.HttpCliResponse) {
|
||||||
|
tmpmap.Delete(key)
|
||||||
|
if rsp.GetErr() != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
rspJson := struct {
|
||||||
|
ErrCode int32 `json:"errcode"`
|
||||||
|
ErrMsg string `json:"errmsg"`
|
||||||
|
Balance string `json:"balance"`
|
||||||
|
}{}
|
||||||
|
if q5.DecodeJson(rsp.GetRawData(), &rspJson) != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
*balance = rspJson.Balance
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
queryAcc := item.GetAccountAddress()
|
||||||
|
if acc != "" {
|
||||||
|
queryAcc = acc
|
||||||
|
}
|
||||||
|
go doquery(queryAcc, item.GetTokenAddress(), &info.balance)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
for tmpmap.GetSize() > 0 {
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *chainbalance) checkBalanceList() {
|
||||||
|
fmt.Println("checkBalanceList start")
|
||||||
|
for {
|
||||||
|
if time.Now().UTC().Hour() == 0 && time.Now().UTC().Minute() == 0 {
|
||||||
|
nowseconds := f5.GetApp().GetRealSeconds()
|
||||||
|
deletelist := []string{}
|
||||||
|
this.addressBalanceList.Range(func(key string, value *addressBalance) bool {
|
||||||
|
if value.gcTime+86400 < nowseconds {
|
||||||
|
deletelist = append(deletelist, key)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, account := range deletelist {
|
||||||
|
this.addressBalanceList.Delete(account)
|
||||||
|
}
|
||||||
|
|
||||||
|
f5.GetSysLog().Info("delete chainbalance address cache count:%d", len(deletelist))
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep((time.Second * 60))
|
||||||
|
}
|
||||||
|
}
|
13
server/adminserver/service/export.go
Normal file
13
server/adminserver/service/export.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"main/constant"
|
||||||
|
"main/global"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Balance = new(chainbalance)
|
||||||
|
var _serviceMgr = new(serviceMgr)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
global.RegModule(constant.SERVICE_MGR_MODULE_IDX, _serviceMgr)
|
||||||
|
}
|
12
server/adminserver/service/servicemgr.go
Normal file
12
server/adminserver/service/servicemgr.go
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
type serviceMgr struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *serviceMgr) Init() {
|
||||||
|
Balance.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *serviceMgr) UnInit() {
|
||||||
|
Balance.unInit()
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user