Skip to content

Commit

Permalink
feat:get game credit stored locally
Browse files Browse the repository at this point in the history
  • Loading branch information
zhouop0 committed Jun 23, 2024
1 parent 22271c8 commit d34443e
Show file tree
Hide file tree
Showing 14 changed files with 238 additions and 137 deletions.
18 changes: 17 additions & 1 deletion deploy/postgres.sql
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,20 @@ CREATE TABLE IF NOT EXISTS game_claim_data
claim varchar(64) NOT NULL,
position bigint NOT NULL,
clock bigint NOT NULL
)
);

--------------------------------------------------------
alter table dispute_game add column computed bool default false;

-- Table structure for game_claim_data
-- ----------------------------
DROP TABLE if exists game_credit;
CREATE TABLE IF NOT EXISTS game_credit
(
id SERIAL PRIMARY KEY,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
game_contract varchar(42) NOT NULL,
address varchar(64) NOT NULL,
credit numeric NOT NULL
);
121 changes: 0 additions & 121 deletions docs/sql/listener.sql

This file was deleted.

17 changes: 16 additions & 1 deletion docs/sql/postgres.sql
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ CREATE TABLE IF NOT EXISTS dispute_game
game_contract varchar(42) NOT NULL,
game_type int NOT NULL,
l2_block_number bigint NOT NULL,
status int NOT NULL
status int NOT NULL,
computed boolean default false
);
CREATE INDEX if not exists dispute_game_index ON dispute_game (contract_address, game_contract);

Expand All @@ -94,3 +95,17 @@ CREATE TABLE IF NOT EXISTS game_claim_data
clock bigint NOT NULL
);
CREATE INDEX if not exists dispute_game_data_index ON game_claim_data (game_contract, data_index);

-- Table structure for game_claim_data
-- ----------------------------
DROP TABLE if exists game_credit;
CREATE TABLE IF NOT EXISTS game_credit
(
id SERIAL PRIMARY KEY,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
game_contract varchar(42) NOT NULL,
address varchar(64) NOT NULL,
credit numeric NOT NULL
);

36 changes: 36 additions & 0 deletions internal/api/dispute_game_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package api
import (
"net/http"

"github.com/spf13/cast"

"github.com/gin-gonic/gin"
"github.com/optimism-java/dispute-explorer/internal/schema"
"github.com/optimism-java/dispute-explorer/pkg/util"
Expand Down Expand Up @@ -43,3 +45,37 @@ func (h DisputeGameHandler) GetClaimData(c *gin.Context) {
"data": claimData,
})
}

type CreditRank struct {
Amount string `json:"amount"`
Address string `json:"address"`
}

func (h DisputeGameHandler) GetCreditRank(c *gin.Context) {
limit := cast.ToInt(c.Query("limit"))
if limit == 0 || limit > 100 {
limit = 10
}
var res []CreditRank
h.DB.Table("game_credit").Select("sum(credit) amount, address").Group("address").Order("amount desc").Limit(limit).Scan(&res)
c.JSON(http.StatusOK, gin.H{
"data": res,
})
}

func (h DisputeGameHandler) GetCreditDetails(c *gin.Context) {
address := c.Param("address")
games := make([]schema.GameCredit, 0)
p := util.NewPagination(c)
results := h.DB.Where(" address = ? ", address).Order("created_at desc").Find(&games)
totalRows := results.RowsAffected
results.Scopes(p.GormPaginate()).Find(&games)
totalPage := totalRows/p.Size + 1
c.JSON(http.StatusOK, gin.H{
"currentPage": p.Page,
"pageSize": p.Size,
"totalCounts": totalRows,
"totalPage": totalPage,
"records": games,
})
}
80 changes: 77 additions & 3 deletions internal/handler/disputeGame.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"math/big"
"strings"

"github.com/pkg/errors"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/optimism-java/dispute-explorer/pkg/log"
Expand All @@ -21,8 +23,9 @@ import (
)

type RetryDisputeGameClient struct {
Client *contract.RateAndRetryDisputeGameClient
DB *gorm.DB
Client *contract.RateAndRetryDisputeGameClient
DB *gorm.DB
DisputeGameAddress common.Address
}

func NewRetryDisputeGameClient(db *gorm.DB, address common.Address, rpc *ethclient.Client, limit rate.Limit,
Expand All @@ -33,7 +36,7 @@ func NewRetryDisputeGameClient(db *gorm.DB, address common.Address, rpc *ethclie
return nil, err
}
retryLimitGame := contract.NewRateAndRetryDisputeGameClient(newDisputeGame, limit, burst)
return &RetryDisputeGameClient{Client: retryLimitGame, DB: db}, nil
return &RetryDisputeGameClient{Client: retryLimitGame, DB: db, DisputeGameAddress: address}, nil
}

func (r *RetryDisputeGameClient) ProcessDisputeGameCreated(ctx context.Context, evt schema.SyncEvent) error {
Expand Down Expand Up @@ -189,3 +192,74 @@ func (r *RetryDisputeGameClient) addDisputeGame(ctx context.Context, evt *schema
}
return nil
}

func (r *RetryDisputeGameClient) ProcessDisputeGameCredit(ctx context.Context) error {
addresses, err := r.GetAllAddress(&r.DisputeGameAddress)
if err != nil {
return fmt.Errorf("[ProcessDisputeGameCredit] GetAllAddress err: %s", err)
}
credits := make([]*schema.GameCredit, 0)
for key := range addresses {
res, err := r.Client.RetryCredit(ctx, &bind.CallOpts{}, common.HexToAddress(key))
if err != nil {
return fmt.Errorf("[handler.SyncCredit] RetryCredit err: %s", err)
}
credit := &schema.GameCredit{
GameContract: r.DisputeGameAddress.String(),
Address: key,
Credit: res.String(),
}
credits = append(credits, credit)
}
disputeGame := &schema.DisputeGame{}
err = r.DB.Where("game_contract=?", strings.ToLower(r.DisputeGameAddress.String())).First(&disputeGame).Error
if err != nil {
return fmt.Errorf("[ProcessDisputeGameCredit] find dispute game err:%s", errors.WithStack(err))
}
err = r.DB.Transaction(func(tx *gorm.DB) error {
err = tx.Save(credits).Error
if err != nil {
return fmt.Errorf("[ProcessDisputeGameCredit] save game credit err: %s\n ", err)
}
disputeGame.Computed = true
err = tx.Save(disputeGame).Error
if err != nil {
return fmt.Errorf("[ProcessDisputeGameCredit] update dispute game computed err: %s\n ", err)
}
return nil
})
if err != nil {
panic(err)
}
return nil
}

func (r *RetryDisputeGameClient) GetCredit(ctx context.Context, address common.Address) (*big.Int, error) {
credit, err := r.Client.RetryCredit(ctx, &bind.CallOpts{}, address)
if err != nil {
return nil, fmt.Errorf("[GetCredit] GET address %s credit err: %s", address.String(), err)
}
return credit, nil
}

func (r *RetryDisputeGameClient) GetAllAddress(disputeGame *common.Address) (map[string]bool, error) {
claimDatas := make([]schema.GameClaimData, 0)
err := r.DB.Where("game_contract=?", strings.ToLower(disputeGame.String())).Order("data_index").Find(&claimDatas).Error
if err != nil {
return nil, fmt.Errorf("[GetAllAddress] %s find claim datas err: %s", disputeGame.String(), err)
}
addresses := map[string]bool{}
for _, claimData := range claimDatas {
if claimData.CounteredBy != common.HexToAddress("0").String() {
if !addresses[claimData.CounteredBy] {
addresses[claimData.CounteredBy] = true
}
}
if claimData.Claimant != common.HexToAddress("0").String() {
if !addresses[claimData.Claimant] {
addresses[claimData.Claimant] = true
}
}
}
return addresses, nil
}
16 changes: 9 additions & 7 deletions internal/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import (

func Run(ctx *svc.ServiceContext) {
// query last block number
go LatestBlackNumber(ctx)
// sync blocks
go SyncBlock(ctx)
// sync events
go SyncEvent(ctx)
// sync dispute game
go SyncDispute(ctx)
// go LatestBlackNumber(ctx)
//// sync blocks
// go SyncBlock(ctx)
//// sync events
// go SyncEvent(ctx)
//// sync dispute game
//go SyncDispute(ctx)

Check failure on line 15 in internal/handler/handler.go

View workflow job for this annotation

GitHub Actions / Run golangci-lint

commentFormatting: put a space between `//` and comment text (gocritic)

go SyncCredit(ctx)
}
39 changes: 39 additions & 0 deletions internal/handler/syncCredit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package handler

import (
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/optimism-java/dispute-explorer/internal/schema"
"github.com/optimism-java/dispute-explorer/internal/svc"
"github.com/optimism-java/dispute-explorer/pkg/log"
"github.com/pkg/errors"
"golang.org/x/time/rate"
)

func SyncCredit(ctx *svc.ServiceContext) {
for {
var disputeGames []schema.DisputeGame
err := ctx.DB.Where("status!=? and computed=?", schema.DisputeGameStatusInProgress, false).Order("block_number").Limit(20).Find(&disputeGames).Error
if err != nil {
log.Errorf("[Handler.SyncCredit] find dispute games for statistic err: %s", errors.WithStack(err))
time.Sleep(5 * time.Second)
continue
}
for _, disputeGame := range disputeGames {
game := common.HexToAddress(disputeGame.GameContract)
disputeClient, err := NewRetryDisputeGameClient(ctx.DB, game,
ctx.L1RPC, rate.Limit(ctx.Config.RPCRateLimit), ctx.Config.RPCRateBurst)
if err != nil {
log.Errorf("[Handler.SyncCredit] NewRetryDisputeGameClient err: %s", err)
time.Sleep(5 * time.Second)
continue
}
err = disputeClient.ProcessDisputeGameCredit(ctx.Context)
if err != nil {
log.Errorf("[Handler.SyncCredit] ProcessDisputeGameCredit err: %s", err)
}
}
time.Sleep(60 * time.Second)
}
}
1 change: 1 addition & 0 deletions internal/schema/dispute_game.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type DisputeGame struct {
GameType uint32 `json:"game_type"`
L2BlockNumber int64 `json:"l_2_block_number"`
Status uint8 `json:"status"`
Computed bool `json:"computed"`
}

func (DisputeGame) TableName() string {
Expand Down
Loading

0 comments on commit d34443e

Please sign in to comment.