feat: implement collectible ownership status

This commit is contained in:
Dario Gabriel Lipicar 2023-09-14 18:52:49 -03:00 committed by dlipicar
parent e502ba82ce
commit e337ab4f13
2 changed files with 72 additions and 8 deletions

View File

@ -3,6 +3,7 @@ package collectibles
import ( import (
"context" "context"
"errors" "errors"
"sync/atomic"
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -27,16 +28,19 @@ type periodicRefreshOwnedCollectiblesCommand struct {
walletFeed *event.Feed walletFeed *event.Feed
group *async.Group group *async.Group
state atomic.Value
} }
func newPeriodicRefreshOwnedCollectiblesCommand(manager *Manager, ownershipDB *OwnershipDB, walletFeed *event.Feed, chainID walletCommon.ChainID, account common.Address) *periodicRefreshOwnedCollectiblesCommand { func newPeriodicRefreshOwnedCollectiblesCommand(manager *Manager, ownershipDB *OwnershipDB, walletFeed *event.Feed, chainID walletCommon.ChainID, account common.Address) *periodicRefreshOwnedCollectiblesCommand {
return &periodicRefreshOwnedCollectiblesCommand{ ret := &periodicRefreshOwnedCollectiblesCommand{
manager: manager, manager: manager,
ownershipDB: ownershipDB, ownershipDB: ownershipDB,
walletFeed: walletFeed, walletFeed: walletFeed,
chainID: chainID, chainID: chainID,
account: account, account: account,
} }
ret.state.Store(OwnershipStateIdle)
return ret
} }
func (c *periodicRefreshOwnedCollectiblesCommand) Command() async.Command { func (c *periodicRefreshOwnedCollectiblesCommand) Command() async.Command {
@ -50,6 +54,10 @@ func (c *periodicRefreshOwnedCollectiblesCommand) Run(ctx context.Context) (err
return c.loadOwnedCollectibles(ctx) return c.loadOwnedCollectibles(ctx)
} }
func (c *periodicRefreshOwnedCollectiblesCommand) GetState() OwnershipState {
return c.state.Load().(OwnershipState)
}
func (c *periodicRefreshOwnedCollectiblesCommand) Stop() { func (c *periodicRefreshOwnedCollectiblesCommand) Stop() {
if c.group != nil { if c.group != nil {
c.group.Stop() c.group.Stop()
@ -60,8 +68,17 @@ func (c *periodicRefreshOwnedCollectiblesCommand) Stop() {
func (c *periodicRefreshOwnedCollectiblesCommand) loadOwnedCollectibles(ctx context.Context) error { func (c *periodicRefreshOwnedCollectiblesCommand) loadOwnedCollectibles(ctx context.Context) error {
c.group = async.NewGroup(ctx) c.group = async.NewGroup(ctx)
command := newLoadOwnedCollectiblesCommand(c.manager, c.ownershipDB, c.walletFeed, c.chainID, c.account) command := newLoadOwnedCollectiblesCommand(c.manager, c.ownershipDB, c.walletFeed, c.chainID, c.account)
c.state.Store(OwnershipStateUpdating)
defer func() {
if command.err != nil {
c.state.Store(OwnershipStateError)
} else {
c.state.Store(OwnershipStateIdle)
}
}()
c.group.Add(command.Command()) c.group.Add(command.Command())
select { select {

View File

@ -84,13 +84,30 @@ const (
ErrorCodeFailed ErrorCodeFailed
) )
type OwnershipState = int
const (
OwnershipStateIdle OwnershipState = iota + 1
OwnershipStateUpdating
OwnershipStateError
)
type OwnershipStatus struct {
State OwnershipState `json:"state"`
Timestamp int64 `json:"timestamp"`
}
type OwnershipStatusPerChainID = map[walletCommon.ChainID]OwnershipStatus
type OwnershipStatusPerAddressAndChainID = map[common.Address]OwnershipStatusPerChainID
type FilterOwnedCollectiblesResponse struct { type FilterOwnedCollectiblesResponse struct {
Collectibles []CollectibleHeader `json:"collectibles"` Collectibles []CollectibleHeader `json:"collectibles"`
Offset int `json:"offset"` Offset int `json:"offset"`
// Used to indicate that there might be more collectibles that were not returned // Used to indicate that there might be more collectibles that were not returned
// based on a simple heuristic // based on a simple heuristic
HasMore bool `json:"hasMore"` HasMore bool `json:"hasMore"`
ErrorCode ErrorCode `json:"errorCode"` OwnershipStatus OwnershipStatusPerAddressAndChainID `json:"ownershipStatus"`
ErrorCode ErrorCode `json:"errorCode"`
} }
type GetCollectiblesDetailsResponse struct { type GetCollectiblesDetailsResponse struct {
@ -99,8 +116,9 @@ type GetCollectiblesDetailsResponse struct {
} }
type filterOwnedCollectiblesTaskReturnType struct { type filterOwnedCollectiblesTaskReturnType struct {
collectibles []CollectibleHeader collectibles []CollectibleHeader
hasMore bool hasMore bool
ownershipStatus OwnershipStatusPerAddressAndChainID
} }
// FilterOwnedCollectiblesResponse allows only one filter task to run at a time // FilterOwnedCollectiblesResponse allows only one filter task to run at a time
@ -116,10 +134,15 @@ func (s *Service) FilterOwnedCollectiblesAsync(requestID int32, chainIDs []walle
if err != nil { if err != nil {
return nil, err return nil, err
} }
ownershipStatus, err := s.GetOwnershipStatus(chainIDs, addresses)
if err != nil {
return nil, err
}
return filterOwnedCollectiblesTaskReturnType{ return filterOwnedCollectiblesTaskReturnType{
collectibles: fullCollectiblesDataToHeaders(data), collectibles: fullCollectiblesDataToHeaders(data),
hasMore: hasMore, hasMore: hasMore,
ownershipStatus: ownershipStatus,
}, err }, err
}, func(result interface{}, taskType async.TaskType, err error) { }, func(result interface{}, taskType async.TaskType, err error) {
res := FilterOwnedCollectiblesResponse{ res := FilterOwnedCollectiblesResponse{
@ -133,6 +156,7 @@ func (s *Service) FilterOwnedCollectiblesAsync(requestID int32, chainIDs []walle
res.Collectibles = fnRet.collectibles res.Collectibles = fnRet.collectibles
res.Offset = offset res.Offset = offset
res.HasMore = fnRet.hasMore res.HasMore = fnRet.hasMore
res.OwnershipStatus = fnRet.ownershipStatus
res.ErrorCode = ErrorCodeSuccess res.ErrorCode = ErrorCodeSuccess
} }
@ -355,3 +379,26 @@ func (s *Service) GetOwnedCollectibles(chainIDs []walletCommon.ChainID, owners [
func (s *Service) GetOwnedCollectible(chainID walletCommon.ChainID, owner common.Address, contractAddress common.Address, tokenID *big.Int) (*thirdparty.CollectibleUniqueID, error) { func (s *Service) GetOwnedCollectible(chainID walletCommon.ChainID, owner common.Address, contractAddress common.Address, tokenID *big.Int) (*thirdparty.CollectibleUniqueID, error) {
return s.ownershipDB.GetOwnedCollectible(chainID, owner, contractAddress, tokenID) return s.ownershipDB.GetOwnedCollectible(chainID, owner, contractAddress, tokenID)
} }
func (s *Service) GetOwnershipStatus(chainIDs []walletCommon.ChainID, owners []common.Address) (OwnershipStatusPerAddressAndChainID, error) {
ret := make(OwnershipStatusPerAddressAndChainID)
for _, address := range owners {
ret[address] = make(OwnershipStatusPerChainID)
for _, chainID := range chainIDs {
timestamp, err := s.ownershipDB.GetOwnershipUpdateTimestamp(address, chainID)
if err != nil {
return nil, err
}
state := OwnershipStateIdle
if s.commands[address] != nil && s.commands[address][chainID] != nil {
state = s.commands[address][chainID].GetState()
}
ret[address][chainID] = OwnershipStatus{
State: state,
Timestamp: timestamp,
}
}
}
return ret, nil
}