Commit 81815ab0 authored by duanjinfei's avatar duanjinfei

init commit

parent 4a784859
Pipeline #598 failed with stages
nft-event
.idea
\ No newline at end of file
package cache
import (
"fmt"
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
"github.com/garyburd/redigo/redis"
red "github.com/wuban/nft-event/cache/redis"
"time"
)
var Redis red.IRedis
var pool *redis.Pool
func init() {
conn := beego.AppConfig.String("cache::conn")
dbNum := beego.AppConfig.String("cache::dbNum")
password := beego.AppConfig.String("cache::password")
if err := NewPool(conn, dbNum, password); err != nil {
logs.Error(err)
return
}
Redis = red.NewStoreRedis(pool)
}
func NewPool(conn, dbNum, password string) error {
fmt.Println("redis连接池里的连接为空,重新创建连接池,starting...")
pool = &redis.Pool{
MaxIdle: 50, //最大空闲连接数
MaxActive: 0, //若为0,则活跃数没有限制
Wait: true,
IdleTimeout: 30 * time.Second, //最大空闲连接时间
Dial: func() (redis.Conn, error) {
c, err := redis.Dial("tcp", conn)
if err != nil {
panic(err)
return nil, err
}
// 设置密码
if _, err := c.Do("AUTH", password); err != nil {
panic(err)
return nil, err
}
// 选择db
c.Do("SELECT", dbNum)
return c, nil
},
}
return nil
}
package redis
type IRedis interface {
Set(key, value string) error
Get(key string) string
LpushByte(key string, value []byte) error
Close()
RPopByte(key string) ([]byte, error)
LLen(key string) (int64, error)
RPopLPushByte(key, key1 string) ([]byte, error)
}
package redis
import (
"fmt"
"github.com/garyburd/redigo/redis"
"reflect"
"strings"
"unsafe"
)
type StoreRedis struct {
pool *redis.Pool
}
func NewStoreRedis(pool *redis.Pool) IRedis {
sr := new(StoreRedis)
sr.pool = pool
return sr
}
/**
此方法没有使用
*/
func (s *StoreRedis) errorLogic(e error) {
i := strings.Index(e.Error(), "connect: connection refused")
if i == -1 {
fmt.Println(i, "不包含")
}
}
/**
设置key,value数据
*/
func (s *StoreRedis) Set(key, value string) error {
_, err := s.pool.Get().Do("SET", key, value)
defer s.Close()
if err != nil {
return err
}
return nil
}
/**
设置key,value数据
*/
func (s *StoreRedis) SetBytes(key string, value []byte) error {
_, err := s.pool.Get().Do("SET", key, value)
defer s.Close()
if err != nil {
return err
}
return nil
}
/**
设置key的过期时间
*/
func (s *StoreRedis) SetKvAndExp(key, value string, expire int) error {
_, err := s.pool.Get().Do("SET", key, value, "EX", expire)
defer s.Close()
if err != nil {
return err
}
return nil
}
func (s *StoreRedis) SetKvInt(key string, value int) error {
_, err := s.pool.Get().Do("SET", key, value)
defer s.Close()
if err != nil {
return err
}
return nil
}
/**
根据key获取对应数据
*/
func (s *StoreRedis) Get(key string) string {
value, err := redis.String(s.pool.Get().Do("GET", key))
defer s.Close()
if err != nil {
fmt.Println("redis get failed:", err)
}
return value
}
/**
根据key获取对应数据
*/
func (s *StoreRedis) GetBytes(key string) []byte {
value, err := s.pool.Get().Do("GET", key)
defer s.Close()
if err != nil {
fmt.Println("redis get failed:", err)
}
if value == nil {
return nil
}
return value.([]byte)
}
/**
判断key是否存在
*/
func (s *StoreRedis) IsKeyExists(key string) bool {
is_key_exit, _ := redis.Bool(s.pool.Get().Do("EXISTS", key))
defer s.Close()
return is_key_exit
}
/**
删除key
*/
func (s *StoreRedis) Del(key string) bool {
is_key_delete, err := redis.Bool(s.pool.Get().Do("DEL", key))
defer s.Close()
if err != nil {
fmt.Println("error:", err)
}
return is_key_delete
}
/**
删除key
*/
func (s *StoreRedis) HDel(key string, field string) bool {
is_key_delete, err := redis.Bool(s.pool.Get().Do("HDEL", key, field))
defer s.Close()
if err != nil {
fmt.Println("error:", err)
}
return is_key_delete
}
/**
对象转换成json后进行存储
*/
func (s *StoreRedis) Setnx(key string, value []byte) error {
_, err := s.pool.Get().Do("SETNX", key, value)
defer s.Close()
if err != nil {
return err
}
return nil
}
func (s *StoreRedis) LpushByte(key string, value []byte) error {
_, err := s.pool.Get().Do("lpush", key, value)
if err != nil {
defer s.Close()
return err
}
defer s.Close()
return nil
}
func (s *StoreRedis) RPopByte(key string) ([]byte, error) {
v, err := redis.Bytes(s.pool.Get().Do("rpop", key))
if err != nil {
defer s.Close()
return nil, err
}
defer s.Close()
return v, nil
}
func (s *StoreRedis) LPop(key string) (string, error) {
v, err := s.pool.Get().Do("lpop", key)
if err != nil {
defer s.Close()
return "", err
}
defer s.Close()
if v == nil {
return "", nil
}
vv := BytesToString(v.([]byte))
return vv, nil
}
func BytesToString(b []byte) string {
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
sh := reflect.StringHeader{bh.Data, bh.Len}
return *(*string)(unsafe.Pointer(&sh))
}
func (s *StoreRedis) LLen(key string) (int64, error) {
v, err := s.pool.Get().Do("llen", key)
if err != nil {
defer s.Close()
return 0, err
}
defer s.Close()
if v == nil {
return 0, nil
}
return v.(int64), nil
}
func (s *StoreRedis) Close() {
s.pool.Get().Close()
}
/**
Hincryby方法
*/
func (s *StoreRedis) HINCRBY(key, field string) {
s.pool.Get().Do("HINCRBY", key, field, 1)
defer s.Close()
}
/**
HGet方法
*/
func (s *StoreRedis) HGet(key, field string) (interface{}, error) {
value, err := s.pool.Get().Do("HGET", key, field)
defer s.Close()
return value, err
}
/**
HGetAll方法
*/
func (s *StoreRedis) HGetAll(key string) ([][]byte, error) {
inter, err := redis.ByteSlices(s.pool.Get().Do("HGetAll", key))
defer s.Close()
return inter, err
}
/**
Hset方法
*/
func (s *StoreRedis) HSet(key string, field string, value string) (interface{}, error) {
inter, err := s.pool.Get().Do("HSET", key, field, value)
defer s.Close()
return inter, err
}
/**
Hset方法
*/
func (s *StoreRedis) HSetByte(key string, field string, value []byte) (interface{}, error) {
inter, err := s.pool.Get().Do("HSET", key, field, value)
defer s.Close()
return inter, err
}
/**
SADD方法
*/
func (s *StoreRedis) SAdd(args []interface{}) (interface{}, error) {
inter, err := s.pool.Get().Do("SADD", args...)
defer s.Close()
return inter, err
}
/**
Scard方法
*/
func (s *StoreRedis) SCard(key string) (interface{}, error) {
inter, err := s.pool.Get().Do("SCARD", key)
defer s.Close()
return inter, err
}
/**
Spop方法
*/
func (s *StoreRedis) SPop(key string) (interface{}, error) {
inter, err := s.pool.Get().Do("SPOP", key)
defer s.Close()
vv := BytesToString(inter.([]byte))
return vv, err
}
func (s *StoreRedis) RPopLPushByte(key, key1 string) ([]byte, error) {
v, err := redis.Bytes(s.pool.Get().Do("RPOPLPUSH", key, key1))
if err != nil {
defer s.Close()
return nil, err
}
defer s.Close()
return v, nil
}
appname = nft-event
httpport = 9000
runmode = dev
mysql = root:mysql2022@/nftEvent?charset=utf8
rpcUrl = https://cloudflare-eth.com
deployedBlock = 17347500
isSyncLog = false
beforeEndReqUrl = https://meta.hapeprime.com/
httpUrlRegex = ^(http|https):\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}(\/\S*)?$
lotteryContract = 0x2Fc9Ba75f1c78ECc77D1a8fD3BDd6bA83eA68b7e
secret = 0x2Fc9Ba75f1c78ECc77D1a8fD3BDd6bA83eA68b7e
# redis config
[cache]
collectionName = redis
conn = 127.0.0.1:6379
dbNum = 1
password = 123456
package controllers
import (
"github.com/astaxie/beego"
"github.com/wuban/nft-event/utils"
)
type AuthController struct {
BaseController
}
func (c *AuthController) GetToken() {
secret := beego.AppConfig.String("secret")
res, err := utils.GenerateToken(secret)
if err != nil {
c.ResponseInfo(500, "Get token error", err.Error())
}
c.ResponseInfo(200, "success", res)
}
package controllers
import (
"github.com/astaxie/beego"
"github.com/astaxie/beego/logs"
)
type BaseController struct {
beego.Controller
}
func (d *BaseController) ResponseInfo(code int, msg interface{}, result interface{}) {
switch code {
case 500:
logs.Error(msg, result)
d.Data["json"] = map[string]interface{}{"code": "500", "msg": msg, "data": result}
case 200:
logs.Info(msg, result)
d.Data["json"] = map[string]interface{}{"code": "200", "msg": msg, "data": result}
}
d.ServeJSON()
}
package controllers
import (
"encoding/json"
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
"github.com/wuban/nft-event/models"
"github.com/wuban/nft-event/utils"
"io/ioutil"
"net/http"
"regexp"
)
type LotteryController struct {
BaseController
}
func (c *LotteryController) GetPeriodList() {
poolAddr := c.GetString("poolAddr")
if poolAddr == "" || !utils.IsAddress(poolAddr) {
c.ResponseInfo(500, models.PARAM_ERR, "")
}
o := orm.NewOrm()
var lotteries []*models.Lottery
_, err := o.QueryTable("lottery").Filter("pool_addr", poolAddr).All(&lotteries, "period")
if err != nil {
c.ResponseInfo(500, models.PERIOD_ERR, err.Error())
}
res := &models.LotteryPeriodListRes{
PoolAddr: poolAddr,
}
periodList := make([]int64, 0)
for i := 0; i < len(lotteries); i++ {
periodList = append(periodList, lotteries[i].Period)
}
res.PeriodList = periodList
c.ResponseInfo(200, models.SUCCESS, res)
}
func (c *LotteryController) GetUserList() {
poolAddr := c.GetString("poolAddr")
if poolAddr == "" || !utils.IsAddress(poolAddr) {
c.ResponseInfo(500, models.PARAM_ERR, "")
}
period, err := c.GetInt64("period")
if err != nil {
c.ResponseInfo(500, models.PARAM_ERR, err.Error())
}
o := orm.NewOrm()
var lotteries []*models.Lottery
_, err = o.QueryTable("lottery").Filter("pool_addr", poolAddr).Filter("period", period).OrderBy("-sort_by").All(&lotteries, "user", "value", "hash")
if err != nil {
c.ResponseInfo(500, models.USER_ERR, err.Error())
}
res := make([]*models.LotteryUserList, 0)
for i := 0; i < len(lotteries); i++ {
lottery := lotteries[i]
lotteryUserList := &models.LotteryUserList{
UserAddr: lottery.User,
Value: lottery.Value,
Hash: lottery.Hash,
}
res = append(res, lotteryUserList)
}
c.ResponseInfo(200, models.SUCCESS, res)
}
func (c *LotteryController) GetHashSortByCondition() {
poolAddr := c.GetString("poolAddr")
if poolAddr == "" || !utils.IsAddress(poolAddr) {
c.ResponseInfo(500, models.PARAM_ERR, "")
}
userAddr := c.GetString("user")
if userAddr == "" || !utils.IsAddress(poolAddr) {
c.ResponseInfo(500, models.PARAM_ERR, "")
}
period, err := c.GetInt64("period")
if err != nil {
c.ResponseInfo(500, models.PARAM_ERR, err.Error())
}
o := orm.NewOrm()
lottery := &models.Lottery{}
err = o.QueryTable("lottery").Filter("pool_addr", poolAddr).Filter("period", period).One(lottery)
if err != nil {
c.ResponseInfo(500, models.SORTBY_ERR, err.Error())
}
if lottery == nil {
c.ResponseInfo(200, models.DATA_NIL, nil)
}
lotteryHashLastSix := &models.LotteryHashLastSix{
Hash: lottery.Hash,
SortBy: lottery.SortBy,
}
c.ResponseInfo(200, models.SUCCESS, lotteryHashLastSix)
}
func (c *LotteryController) ForwardReq() {
id := c.GetString("id")
urlPattern := beego.AppConfig.String("httpUrlRegex")
// 编译正则表达式
regex, err := regexp.Compile(urlPattern)
if err != nil {
c.ResponseInfo(500, models.FAILED, err.Error())
}
if id == "" {
c.ResponseInfo(500, models.PARAM_ERR, nil)
}
if regex.MatchString(id) {
c.ResponseInfo(500, models.PARAM_ERR, nil)
}
url := beego.AppConfig.String("beforeEndReqUrl") + id
client := &http.Client{}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
c.ResponseInfo(500, models.FAILED, err.Error())
}
resp, err := client.Do(req)
if err != nil {
c.ResponseInfo(500, models.FAILED, err.Error())
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
c.ResponseInfo(500, models.FAILED, err.Error())
}
res := map[string]interface{}{}
json.Unmarshal(body, &res)
c.ResponseInfo(200, models.SUCCESS, res)
}
module github.com/wuban/nft-event
go 1.19
require github.com/astaxie/beego v1.12.1
require (
github.com/ethereum/go-ethereum v1.12.0
github.com/garyburd/redigo v1.6.4
github.com/go-sql-driver/mysql v1.7.1
github.com/sirupsen/logrus v1.9.2
github.com/smartystreets/goconvey v1.6.4
)
require (
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/deckarep/golang-set/v2 v2.1.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/go-ole/go-ole v1.2.1 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c // indirect
github.com/jtolds/gls v4.20.0+incompatible // indirect
github.com/shiena/ansicolor v0.0.0-20230509054315-a9deabde6e02 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d // indirect
github.com/tklauser/go-sysconf v0.3.5 // indirect
github.com/tklauser/numcpus v0.2.2 // indirect
golang.org/x/crypto v0.1.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/text v0.8.0 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
This diff is collapsed.
package main
import (
"github.com/astaxie/beego"
_ "github.com/wuban/nft-event/routers"
"github.com/wuban/nft-event/sync"
)
func main() {
isSyncLog, _ := beego.AppConfig.Bool("isSyncLog")
if isSyncLog {
go sync.SyncLogs()
}
beego.Run()
}
package models
import (
"github.com/astaxie/beego"
"github.com/astaxie/beego/orm"
_ "github.com/go-sql-driver/mysql"
)
func init() {
mysqlCfg := beego.AppConfig.String("mysql")
orm.RegisterDriver("mysql", orm.DRMySQL)
orm.RegisterDataBase("default", "mysql", mysqlCfg)
orm.RegisterModel(new(Lottery))
orm.RunSyncdb("default", false, true)
}
package models
type Lottery struct {
Id int64 `orm:"pk;auto"`
PoolAddr string `orm:"size(255)"`
Period int64
User string `orm:"size(255)"`
Value string `orm:"size(255)"`
Hash string `orm:"size(255)"`
SortBy string `orm:"size(255)"`
}
package models
const (
SUCCESS = "success"
FAILED = "failed"
PARAM_ERR = "Input param error"
DATA_NIL = "Get data is nil"
PERIOD_ERR = "Get period list err"
USER_ERR = "Get user list err"
SORTBY_ERR = "Get sort condition err"
)
package models
type LotteryPeriodListRes struct {
PoolAddr string `json:"poolAddr"`
PeriodList []int64 `json:"periodList"`
}
type LotteryUserList struct {
UserAddr string `json:"userAddr"`
Value string `json:"value"`
Hash string `json:"hash"`
}
type LotteryHashLastSix struct {
Hash string `json:"hash"`
SortBy string `json:"sortBy"`
}
type FilterRes struct {
Code int `json:"code"`
Msg interface{} `json:"msg"`
Data interface{} `json:"data"`
}
package routers
import (
"github.com/astaxie/beego"
"github.com/wuban/nft-event/controllers"
)
func init() {
beego.Router("/api/v1/event/get/periodList", &controllers.LotteryController{}, "get:GetPeriodList")
beego.Router("/api/v1/event/get/joinUserList", &controllers.LotteryController{}, "get:GetUserList")
beego.Router("/api/v1/event/get/sortCondition", &controllers.LotteryController{}, "get:GetHashSortByCondition")
beego.Router("/api/v1/event/get/param", &controllers.LotteryController{}, "get:ForwardReq")
beego.Router("/getToken", &controllers.AuthController{}, "get:GetToken")
// 添加鉴权过滤器
//beego.InsertFilter("/*", beego.BeforeRouter, utils.AuthFilter)
}
package sync
import (
"bufio"
"github.com/astaxie/beego/logs"
"github.com/astaxie/beego/orm"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
log "github.com/sirupsen/logrus"
"github.com/wuban/nft-event/models"
"github.com/wuban/nft-event/utils"
"math/big"
"os"
)
// LotteryTopic ERC721 transfer event topic
var LotteryTopic = crypto.Keccak256Hash([]byte("Lottery(address,uint256,address,uint256)")).Hex()
func LotteryContractHandler(vLog types.Log) error {
logs.Info("handler lottery contract logs")
file, err := os.Open("./sync/Lottery_Event.json")
if err != nil {
panic(err)
}
defer func(file *os.File) {
err := file.Close()
if err != nil {
log.Error("read file close failed:", err)
}
}(file)
lotteryAbiInfo, _ := abi.JSON(bufio.NewReader(file))
log.Info("LotteryTopic:", LotteryTopic)
{
txHash := vLog.TxHash.Hex()
method := vLog.Topics[0]
switch method.String() {
case LotteryTopic:
rp, err := lotteryAbiInfo.Unpack("Lottery", vLog.Data)
period, err := utils.HexToInt64(vLog.Topics[2].Hex())
if err != nil {
log.Error("HexToInt64 error:", err.Error())
return err
}
value := rp[0].(*big.Int)
log.Info("value:", value.String())
lottery := &models.Lottery{
PoolAddr: utils.HexToAddr(vLog.Topics[1].Hex()).String(),
Period: period,
User: utils.HexToAddr(vLog.Topics[3].Hex()).String(),
Value: value.String(),
Hash: txHash,
SortBy: txHash[len(txHash)-6:],
}
log.Info("Insert data lottery:", lottery)
o := orm.NewOrm()
lotteryVar := &models.Lottery{}
// todo 是否需要过滤每个用户只能参加一次抽奖的日志
o.QueryTable("lottery").Filter("pool_addr", lottery.PoolAddr).Filter("period", lottery.Period).Filter("User", lottery.User).All(lotteryVar)
if lotteryVar.PoolAddr != "" {
log.Warning("The lottery is exist", lotteryVar)
return nil
}
_, err = o.Insert(lottery)
if err != nil {
logs.Error("Insert lottery error:", err.Error())
return err
}
}
}
return nil
}
[
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "pool",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "period",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "user",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Lottery",
"type": "event"
}
]
\ No newline at end of file
package sync
import (
"context"
"fmt"
"github.com/astaxie/beego"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
log "github.com/sirupsen/logrus"
"github.com/wuban/nft-event/cache"
"math/big"
"time"
)
const (
LastSyncBlockKey = "lastSyncBlock"
)
var (
pullTask *PullEvent
bigOne = big.NewInt(1)
bigTen = big.NewInt(10)
bigHundred = big.NewInt(100)
bigEight = big.NewInt(700)
)
type logHandler func(log types.Log) error
type PullEvent struct {
ctx context.Context
client *ethclient.Client
lastBlock *big.Int
contractList []common.Address
contractHandler map[common.Address]logHandler
}
func SyncLogs() {
pullTask.GetLogs()
}
func init() {
var err error
rpc := beego.AppConfig.String("rpcUrl")
deployBlock := beego.AppConfig.String("deployedBlock")
fmt.Println("get rpc ", rpc)
pullTask = &PullEvent{contractHandler: make(map[common.Address]logHandler)}
client, err := ethclient.Dial(rpc)
if err != nil {
panic(fmt.Sprintf("ethclient dial failed, err:", err))
} else {
pullTask.client = client
lastBlock := cache.Redis.Get(LastSyncBlockKey)
if len(lastBlock) == 0 {
lastBlock = deployBlock
}
{
blockNumber, _ := new(big.Int).SetString(lastBlock, 10)
pullTask.lastBlock = blockNumber
}
}
pullTask.ctx = context.Background()
pullTask.contractList = make([]common.Address, 0)
{
lotteryAddr := beego.AppConfig.String("lotteryContract")
if lotteryAddr == "" {
return
}
addr := common.HexToAddress(lotteryAddr)
pullTask.contractList = append(pullTask.contractList, addr)
pullTask.contractHandler[addr] = LotteryContractHandler
}
}
func (p *PullEvent) GetLogs() {
query := ethereum.FilterQuery{}
query.FromBlock = p.lastBlock
query.ToBlock = new(big.Int).Add(p.lastBlock, big.NewInt(1))
query.Addresses = p.contractList
for {
query.FromBlock = p.lastBlock
log.Info("start fileter start at ", p.lastBlock.Text(10))
height, err := p.client.BlockNumber(p.ctx)
log.Info("current node height:", height)
if height <= p.lastBlock.Uint64() {
time.Sleep(time.Second)
continue
} else if (height - 700) >= p.lastBlock.Uint64() {
query.ToBlock = new(big.Int).Add(p.lastBlock, bigEight)
} else if (height - 100) >= p.lastBlock.Uint64() {
query.ToBlock = new(big.Int).Add(p.lastBlock, bigHundred)
} else if (height - 10) >= p.lastBlock.Uint64() {
query.ToBlock = new(big.Int).Add(p.lastBlock, bigTen)
} else {
query.ToBlock = new(big.Int).Add(p.lastBlock, bigOne)
}
allLogs, err := p.client.FilterLogs(p.ctx, query)
if err != nil {
log.Error("filter logs failed", err)
continue
}
if len(allLogs) > 0 {
for _, vlog := range allLogs {
handle, exist := p.contractHandler[vlog.Address]
if exist {
handle(vlog)
}
}
}
p.lastBlock = new(big.Int).Add(query.ToBlock, bigOne)
cache.Redis.Set(LastSyncBlockKey, p.lastBlock.Text(10))
}
}
package test
import (
"net/http"
"net/http/httptest"
"testing"
"runtime"
"path/filepath"
_ "nft-event/routers"
"github.com/astaxie/beego"
. "github.com/smartystreets/goconvey/convey"
)
func init() {
_, file, _, _ := runtime.Caller(0)
apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".." + string(filepath.Separator))))
beego.TestBeegoInit(apppath)
}
// TestBeego is a sample to run an endpoint test
func TestBeego(t *testing.T) {
r, _ := http.NewRequest("GET", "/", nil)
w := httptest.NewRecorder()
beego.BeeApp.Handlers.ServeHTTP(w, r)
beego.Trace("testing", "TestBeego", "Code[%d]\n%s", w.Code, w.Body.String())
Convey("Subject: Test Station Endpoint\n", t, func() {
Convey("Status Code Should Be 200", func() {
So(w.Code, ShouldEqual, 200)
})
Convey("The Result Should Not Be Empty", func() {
So(w.Body.Len(), ShouldBeGreaterThan, 0)
})
})
}
package utils
import (
"fmt"
"github.com/astaxie/beego"
"github.com/astaxie/beego/context"
"github.com/dgrijalva/jwt-go"
"github.com/wuban/nft-event/models"
"net/http"
"time"
)
// 定义 JWT 密钥
var jwtKey = []byte(beego.AppConfig.String("secret"))
// Claims 定义自定义声明
type Claims struct {
Address string `json:"address"`
jwt.StandardClaims
}
// GenerateToken 生成 JWT
func GenerateToken(address string) (string, error) {
// 设置过期时间
expirationTime := time.Now().Add(15 * time.Minute)
// 创建声明
claims := &Claims{
Address: address,
StandardClaims: jwt.StandardClaims{
ExpiresAt: expirationTime.Unix(),
IssuedAt: time.Now().Unix(),
},
}
// 创建令牌
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
// 签名令牌
tokenString, err := token.SignedString(jwtKey)
if err != nil {
return "", err
}
return tokenString, nil
}
// AuthFilter 鉴权过滤器
var AuthFilter = func(ctx *context.Context) {
// 判断路由是否需要鉴权
if ctx.Request.URL.Path == "/getToken" {
// 不进行鉴权校验,直接通过
return
}
filterRes := &models.FilterRes{
Data: "",
Code: http.StatusUnauthorized,
Msg: "Unauthorized",
}
authHeader := ctx.Input.Header("Authorization")
if authHeader == "" {
ctx.Output.SetStatus(http.StatusUnauthorized)
ctx.Output.JSON(filterRes, true, false)
return
}
// 解析 JWT
tokenString := authHeader[len("Bearer "):]
claims := &Claims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("UnExpected signing method")
}
return jwtKey, nil
})
if err != nil {
if err == jwt.ErrSignatureInvalid {
ctx.Output.SetStatus(http.StatusUnauthorized)
ctx.Output.JSON(filterRes, true, false)
return
}
filterRes.Code = http.StatusBadRequest
filterRes.Msg = "Bad Request"
ctx.Output.SetStatus(http.StatusBadRequest)
ctx.Output.JSON(filterRes, true, false)
return
}
if !token.Valid {
ctx.Output.SetStatus(http.StatusUnauthorized)
ctx.Output.JSON(filterRes, true, false)
return
}
if claims.Address != beego.AppConfig.String("secret") {
ctx.Output.SetStatus(http.StatusUnauthorized)
filterRes.Msg = "Error token"
ctx.Output.JSON(filterRes, true, false)
return
}
}
package utils
import (
"encoding/hex"
"fmt"
"github.com/astaxie/beego"
"github.com/dgrijalva/jwt-go"
"github.com/ethereum/go-ethereum/common"
log "github.com/sirupsen/logrus"
)
func IsAddress(val string) bool {
return common.IsHexAddress(val)
}
func HexToAddr(val string) common.Address {
return common.HexToAddress(val)
}
func HexToInt64(hexStr string) (int64, error) {
// 去除十六进制字符串的前缀 "0x"
if len(hexStr) > 2 && hexStr[0:2] == "0x" {
hexStr = hexStr[2:]
}
// 解码十六进制字符串
bytes, err := hex.DecodeString(hexStr)
if err != nil {
return 0, err
}
// 将解码后的字节切片转换为 int64 类型
value := int64(0)
for _, b := range bytes {
value = (value << 8) | int64(b)
}
return value, nil
}
func CheckToken(tokenString string) bool {
token, _ := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("UnExpected signing method")
}
return []byte(beego.AppConfig.String("secret")), nil
})
if token == nil {
return false
}
claims, _ := token.Claims.(jwt.MapClaims)
log.Info("claims:", claims)
return true
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment