From 776eca473024f42306f73637fee701fa00d01e88 Mon Sep 17 00:00:00 2001 From: huangzhiran Date: Thu, 26 Dec 2024 11:35:59 +0800 Subject: [PATCH] monitor erc721 transfer event --- cmd/server/main.go | 1 + db/device.go | 11 ++++++++++- monitor/monitor.go | 17 +++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index df0ae8a..a0d4bfd 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -47,6 +47,7 @@ func main() { UpsertScannedBlockNumber: db.UpsertScannedBlockNumber, UpsertProjectMetadata: db.UpsertApp, UpsertDevice: db.UpsertDevice, + UpdateDeviceOwner: db.UpdateOwner, }, &monitor.ContractAddr{ Project: common.HexToAddress(cfg.ProjectContractAddr), diff --git a/db/device.go b/db/device.go index 8b80f5c..3a23389 100644 --- a/db/device.go +++ b/db/device.go @@ -1,8 +1,10 @@ package db import ( + "math/big" "strings" + "github.com/ethereum/go-ethereum/common" "github.com/pkg/errors" "gorm.io/gorm" "gorm.io/gorm/clause" @@ -16,6 +18,7 @@ const ( type Device struct { ID string `gorm:"primary_key"` + NFTID string `gorm:"uniqueIndex:device_nft_id,not null"` Name string `gorm:"not null;default:''"` Owner string `gorm:"not null;default:''"` Address string `gorm:"not null;default:''"` @@ -56,11 +59,17 @@ func (d *DB) Device(id string) (*Device, error) { func (d *DB) UpsertDevice(t *Device) error { err := d.db.Clauses(clause.OnConflict{ Columns: []clause.Column{{Name: "id"}}, - DoUpdates: clause.AssignmentColumns([]string{"owner", "address", "status", "proposer", "updated_at"}), + DoUpdates: clause.AssignmentColumns([]string{"nftid", "owner", "address", "status", "proposer", "updated_at"}), }).Create(t).Error return errors.Wrap(err, "failed to upsert device") } +func (d *DB) UpdateOwner(nftid *big.Int, owner common.Address) error { + values := map[string]any{"owner": owner.String()} + err := d.db.Model(&Device{}).Where("nftid = ?", nftid.String()).Updates(values).Error + return errors.Wrap(err, "failed to update device owner") +} + func (d *DB) UpdateByID(id string, values map[string]any) error { err := d.db.Model(&Device{}).Where("id = ?", id).Updates(values).Error return errors.Wrap(err, "failed to update device") diff --git a/monitor/monitor.go b/monitor/monitor.go index da7049f..2a9d9a5 100644 --- a/monitor/monitor.go +++ b/monitor/monitor.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" "github.com/pkg/errors" + "gorm.io/gorm" "github.com/iotexproject/pebble-server/contract/ioid" "github.com/iotexproject/pebble-server/contract/project" @@ -25,6 +26,7 @@ type ( UpsertScannedBlockNumber func(uint64) error UpsertProjectMetadata func(projectID uint64, key [32]byte, value []byte) error UpsertDevice func(t *db.Device) error + UpdateDeviceOwner func(*big.Int, common.Address) error ) type Handler struct { @@ -32,6 +34,7 @@ type Handler struct { UpsertScannedBlockNumber UpsertProjectMetadata UpsertDevice + UpdateDeviceOwner } type ContractAddr struct { @@ -54,11 +57,13 @@ type contract struct { var ( projectAddMetadataTopic = crypto.Keccak256Hash([]byte("AddMetadata(uint256,string,bytes32,bytes)")) createIoIDTopic = crypto.Keccak256Hash([]byte("CreateIoID(address,uint256,address,string)")) + erc721TransferTopic = crypto.Keccak256Hash([]byte("Transfer(address,address,uint256)")) ) var allTopic = []common.Hash{ projectAddMetadataTopic, createIoIDTopic, + erc721TransferTopic, } func (c *contract) processLogs(logs []types.Log) error { @@ -98,6 +103,7 @@ func (c *contract) processLogs(logs []types.Log) error { if err := c.h.UpsertDevice(&db.Device{ ID: e.Did, + NFTID: e.Id.String(), Owner: e.Owner.String(), Address: address.String(), Status: db.CONFIRM, @@ -106,6 +112,17 @@ func (c *contract) processLogs(logs []types.Log) error { }); err != nil { return err } + case erc721TransferTopic: + e, err := c.ioidInstance.ParseTransfer(l) + if err != nil { + return errors.Wrap(err, "failed to parse erc721 transfer event") + } + if err := c.h.UpdateDeviceOwner(e.TokenId, e.To); err != nil { + if err == gorm.ErrRecordNotFound { + continue + } + return errors.Wrap(err, "failed to update device owner") + } } } return nil