feat: implement collectible ownership status
This commit is contained in:
parent
e502ba82ce
commit
e337ab4f13
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue