change method for config of event catcher

This commit is contained in:
CounterFire2023 2024-01-12 19:31:42 +08:00
parent def646bc21
commit ba4d63b185
28 changed files with 292 additions and 271 deletions

View File

@ -0,0 +1,25 @@
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
}

View File

@ -0,0 +1,25 @@
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
}

View File

@ -0,0 +1,46 @@
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "user",
"type": "address"
},
{
"components": [
{
"internalType": "address",
"name": "user",
"type": "address"
},
{
"internalType": "address",
"name": "nft",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "uint64",
"name": "start",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "stakeTime",
"type": "uint64"
}
],
"indexed": false,
"internalType": "struct ERC721Staking.Staker[]",
"name": "infos",
"type": "tuple[]"
}
],
"name": "Redeem",
"type": "event"
}

View File

@ -0,0 +1,46 @@
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "user",
"type": "address"
},
{
"components": [
{
"internalType": "address",
"name": "user",
"type": "address"
},
{
"internalType": "address",
"name": "nft",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "uint64",
"name": "start",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "stakeTime",
"type": "uint64"
}
],
"indexed": false,
"internalType": "struct ERC721Staking.Staker[]",
"name": "infos",
"type": "tuple[]"
}
],
"name": "Staked",
"type": "event"
}

50
config/event_list.json Normal file
View File

@ -0,0 +1,50 @@
[
{
"chain": 421614,
"address": "0xCD4bb3402f1a444a1AF10F31946Ed37DaC0eaC4d",
"event": "Transfer",
"abi": "ERC721_Transfer",
"fromBlock": 3549077,
"eventProcesser": "NftHolder"
},
{
"chain": 421614,
"address": "0x6a673D946a976776fd5F163d9d831b2fEB600015",
"event": "Transfer",
"abi": "ERC721_Transfer",
"fromBlock": 5814045,
"eventProcesser": "NftHolder"
},
{
"chain": 421614,
"address": "0x7b6399DFbed8Bc46F6A498C6B1040E80c2B5C4bc",
"event": "Transfer",
"abi": "ERC721_Transfer",
"fromBlock": 5814491,
"eventProcesser": "NftHolder"
},
{
"chain": 421614,
"address": "0xe2E4D5a4045fBFcbCBECAf5b8A94303712d2FA97",
"event": "Transfer",
"abi": "ERC721_Transfer",
"fromBlock": 3549613,
"eventProcesser": "NftHolder"
},
{
"chain": 421614,
"address": "0xd46fA2E72BA0F54092D0eF6a6e0D1d5660259C7a",
"event": "Staked",
"abi": "NFT_Stake",
"fromBlock": 3549891,
"eventProcesser": "NftStake"
},
{
"chain": 421614,
"address": "0xd46fA2E72BA0F54092D0eF6a6e0D1d5660259C7a",
"event": "Staked",
"abi": "NFT_Redeem",
"fromBlock": 3549891,
"eventProcesser": "NftStake"
}
]

View File

@ -1,3 +1,3 @@
pm2 start npm --name "chain-client" --log-date-format "YYYY-MM-DD HH:mm:ss" -- run "dev:api"
pm2 start npm --name "chain-scription" --log-date-format "YYYY-MM-DD HH:mm:ss" -- run "dev:scription"
pm2 start npm --name "chain-event" --log-date-format "YYYY-MM-DD HH:mm:ss" -- run "dev:event"
pm2 start ts-node --name "chain:api" --log-date-format "YYYY-MM-DD HH:mm:ss" -- -r ./node_modules/tsconfig-paths/register ./src/api.ts
pm2 start ts-node --name "chain:scriptions" --log-date-format "YYYY-MM-DD HH:mm:ss" -- -r ./node_modules/tsconfig-paths/register ./src/scriptions.ts
pm2 start ts-node --name "chain:event" --log-date-format "YYYY-MM-DD HH:mm:ss" -- -r ./node_modules/tsconfig-paths/register ./src/events.ts

View File

@ -1,145 +0,0 @@
export const FT_TRANSFER_EVENT_ABI = {
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "value",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
}
export const NFT_TRANSFER_EVENT_ABI = {
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "from",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "to",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
}
],
"name": "Transfer",
"type": "event"
}
export const NFT_STAKE_EVENT_ABI = {
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "user",
"type": "address"
},
{
"components": [
{
"internalType": "address",
"name": "user",
"type": "address"
},
{
"internalType": "address",
"name": "nft",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "uint64",
"name": "start",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "stakeTime",
"type": "uint64"
}
],
"indexed": false,
"internalType": "struct ERC721Staking.Staker[]",
"name": "infos",
"type": "tuple[]"
}
],
"name": "Staked",
"type": "event"
}
export const NFT_REDEEM_EVENT_ABI = {
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "user",
"type": "address"
},
{
"components": [
{
"internalType": "address",
"name": "user",
"type": "address"
},
{
"internalType": "address",
"name": "nft",
"type": "address"
},
{
"internalType": "uint256",
"name": "tokenId",
"type": "uint256"
},
{
"internalType": "uint64",
"name": "start",
"type": "uint64"
},
{
"internalType": "uint64",
"name": "stakeTime",
"type": "uint64"
}
],
"indexed": false,
"internalType": "struct ERC721Staking.Staker[]",
"name": "infos",
"type": "tuple[]"
}
],
"name": "Redeem",
"type": "event"
}

View File

@ -7,9 +7,7 @@ import { IncomingMessage, Server, ServerResponse } from 'http'
import { RouterMap } from 'decorators/router'
import { mongoose } from '@typegoose/typegoose'
import logger from 'logger/logger'
import BlocknumSchedule from 'schedule/blocknum.schedule'
import { RedisClient } from 'redis/RedisClient'
import { restartAllUnFinishedTask } from 'service/chain.service'
import { PriceSvr } from 'service/price.service'
const zReqParserPlugin = require('plugins/zReqParser')
@ -159,7 +157,6 @@ export class ApiServer {
self.setErrHandler()
self.setFormatSend()
self.initSchedules()
restartAllUnFinishedTask()
this.server.listen(
{ port: parseInt(process.env.API_PORT), host: process.env.API_HOST },
(err: any, address: any) => {

View File

@ -1,7 +1,7 @@
import { Contract } from 'web3-eth-contract'
import Web3 from 'web3'
import { Account } from 'web3-core'
const abi = require('abis/NftDistributor.json').abi
const abi = require('../../config/abis/NftDistributor.json').abi
export class DistributorReactor {
private web3: Web3

View File

@ -7,7 +7,7 @@ import { AllChains } from './allchain'
import { HttpRetryProvider } from './HttpRetryProvider'
import { CHAIN_GAS_BOOST } from 'common/Constants'
const abiFt = require('abis/ERC20.json').abi
const abiFt = require('../../config/abis/ERC20.json').abi
export class ERC20Reactor {
private web3: Web3
private contract: Contract

View File

@ -11,7 +11,7 @@ export const ERC721_INTERFACE_ID = '0x80ac58cd'
export const ERC721_METADATA_INTERFACE_ID = '0x5b5e139f'
export const ERC721_ENUMERABLE_INTERFACE_ID = '0x780e9d63'
const abiNft = require('abis/BEBadge.json').abi
const abiNft = require('../../config/abis/BEBadge.json').abi
export class ERC721Reactor {
private web3: Web3

View File

@ -3,7 +3,7 @@ import Web3 from 'web3'
import { Account } from 'web3-core'
import { ZERO_BYTES32 } from 'common/Constants'
import { generateRandomBytes32 } from 'utils/wallet.util'
const abi = require('abis/BEMultiSigWallet.json').abi
const abi = require('../../config/abis/BEMultiSigWallet.json').abi
/**
* ["address", "uint256", "bytes", "uint256", "bytes32"],

View File

@ -35,7 +35,7 @@ export const ethGetBlockByNumber = async (rpc: string, blockNumber: string) => {
}
export const ethGetLogs = async (rpc: string, params: any) => {
return requestChain(rpc, "eth_getLogs", [params])
return requestChain(rpc, "eth_getLogs", params)
}
export const _batchEthBlocks = async (rpc: string, blockNumber: number, amount: number) => {

View File

@ -1,64 +0,0 @@
import { NFT_REDEEM_EVENT_ABI, NFT_STAKE_EVENT_ABI, NFT_TRANSFER_EVENT_ABI } from 'abis/Transfer'
import { NftStake } from 'models/NftStake'
import { NftHolder } from 'models/NftHolder'
export interface IEventCfg {
address: string,
event: string,
abi: any,
fromBlock: number,
eventProcesser?: string,
chain: number,
topic?: string,
}
export const EVENTS_CFG: IEventCfg[] = [
{ // hero
chain: 421614,
address: "0xCD4bb3402f1a444a1AF10F31946Ed37DaC0eaC4d",
event: "Transfer",
abi: NFT_TRANSFER_EVENT_ABI,
fromBlock: 3549077,
eventProcesser: NftHolder,
},
{ // candy
chain: 421614,
address: "0x6a673D946a976776fd5F163d9d831b2fEB600015",
event: "Transfer",
abi: NFT_TRANSFER_EVENT_ABI,
fromBlock: 5814045,
eventProcesser: NftHolder,
},
{ // Explorer
chain: 421614,
address: "0x7b6399DFbed8Bc46F6A498C6B1040E80c2B5C4bc",
event: "Transfer",
abi: NFT_TRANSFER_EVENT_ABI,
fromBlock: 5814491,
eventProcesser: NftHolder,
},
{ // Gacha
chain: 421614,
address: "0xe2E4D5a4045fBFcbCBECAf5b8A94303712d2FA97",
event: "Transfer",
abi: NFT_TRANSFER_EVENT_ABI,
fromBlock: 3549613,
eventProcesser: NftHolder,
},
{ // Stake
chain: 421614,
address: "0xd46fA2E72BA0F54092D0eF6a6e0D1d5660259C7a",
event: "Staked",
abi: NFT_STAKE_EVENT_ABI,
fromBlock: 3549891,
eventProcesser: NftStake,
},
{ // Stake
chain: 421614,
address: "0xd46fA2E72BA0F54092D0eF6a6e0D1d5660259C7a",
event: "Staked",
abi: NFT_REDEEM_EVENT_ABI,
fromBlock: 3549891,
eventProcesser: NftStake,
},
]

View File

@ -4,12 +4,12 @@ import { RedisClient } from 'redis/RedisClient'
const envFile = process.env.NODE_ENV && process.env.NODE_ENV === 'production' ? `.env.production` : '.env.development'
dotenv.config({ path: envFile })
const events = require('../config/event_list.json')
import 'common/Extend'
import { AllChains, IChain } from 'chain/allchain'
import { EVENTS_CFG, IEventCfg } from 'config/events_cfg'
import { EventBatchSvr } from 'service/event.batch.service'
import { IEventCfg } from 'interface/IEventCfg'
let svrs: any[] = []
let lock = false
@ -17,8 +17,9 @@ let lock = false
async function initEventSvrs() {
const cfgMap: Map<IChain, IEventCfg[]> = new Map();
for (let cfg of EVENTS_CFG) {
for (let cfg of events) {
cfg.address = cfg.address.toLowerCase()
cfg.abi = require(`../config/event_abis/${cfg.abi}.json`)
const chainCfg = AllChains.find((chain) => chain.id === cfg.chain)
if (!chainCfg) {
logger.error('chainCfg not found: ' + cfg.chain)

View File

@ -0,0 +1,9 @@
export interface IEventCfg {
address: string,
event: string,
abi: any,
fromBlock: number,
eventProcesser?: string,
chain: number,
topic?: string,
}

View File

@ -1,39 +0,0 @@
import { getModelForClass, index, modelOptions, prop } from '@typegoose/typegoose'
import { dbconn } from 'decorators/dbconn'
import { BaseModule } from './Base'
import { GeneralEvent } from './GeneralEvent'
@dbconn()
@index({ chain: 1, address: 1, user: 1 }, { unique: true })
@modelOptions({
schemaOptions: { collection: 'ft_holder', timestamps: true },
})
export class FtHolderClass extends BaseModule {
@prop({ required: true })
public address!: string
@prop({ required: true })
public chain: string
@prop({ required: true })
public amount: string
@prop()
public blockNumber: number
@prop()
public user: string
//TODO::
public static async parseEvent(event: typeof GeneralEvent) {
const address = event.address;
const chain = event.chain;
const amount = event.amount;
const blockNumer = event.blockNumber;
}
}
export const FtHolder = getModelForClass(FtHolderClass, {
existingConnection: FtHolderClass['db'],
})

View File

@ -1,7 +1,7 @@
import { getModelForClass, index, modelOptions, prop } from '@typegoose/typegoose'
import { dbconn } from 'decorators/dbconn'
import { BaseModule } from './Base'
import { FtHolder } from './FtHolder'
import { TokenHolder } from './TokenHolder'
@dbconn()
@index({ address: 1 }, { unique: false })
@ -61,7 +61,7 @@ export class FtTransferEventClass extends BaseModule {
}
let record = await FtTransferEvent.insertOrUpdate({ hash, logIndex, chain: event.chain }, data)
await FtHolder.saveData(record)
await TokenHolder.saveData(record)
}
}

60
src/models/TokenHolder.ts Normal file
View File

@ -0,0 +1,60 @@
import { getModelForClass, index, modelOptions, prop } from '@typegoose/typegoose'
import { dbconn } from 'decorators/dbconn'
import { BaseModule } from './Base'
import { GeneralEvent } from './GeneralEvent'
import { ZERO_ADDRESS } from 'common/Constants'
@dbconn()
@index({ chain: 1, address: 1, user: 1 }, { unique: true })
@modelOptions({
schemaOptions: { collection: 'token_holder', timestamps: true },
})
export class TokenHolderClass extends BaseModule {
@prop({ required: true })
public chain: string
@prop({ required: true })
public address!: string
@prop()
public user: string
@prop({ required: true })
public amount: string
@prop()
public blockNumber: number
public static async parseEvent(event: typeof GeneralEvent) {
const address = event.address.toLowerCase();
const chain = event.chain;
const blockNumber = event.blockNumber;
let { from, to, value } = event.decodedData
from = from.toLowerCase()
to = to.toLowerCase()
if (from !== ZERO_ADDRESS) {
let record = await TokenHolder.findOne({ address, chain, user: from })
if (record) {
record.amount = BigInt(record.amount) - BigInt(value)
record.blockNumber = blockNumber
}
await record.save();
}
if (to !== ZERO_ADDRESS) {
let record = await TokenHolder.findOne({ address, chain, user: to })
if (!record) {
record = new TokenHolder({ address, chain, user: to, amount: BigInt(value), blockNumber })
} else {
record.amount = BigInt(record.amount) + BigInt(value)
record.blockNumber = blockNumber
}
await record.save();
}
}
}
export const TokenHolder = getModelForClass(TokenHolderClass, {
existingConnection: TokenHolderClass['db'],
})

View File

@ -1,12 +1,22 @@
import { IChain } from "chain/allchain";
import { batchEthLogs, ethGetLogs } from "chain/chain.api";
import { IEventCfg } from "config/events_cfg";
import logger from "logger/logger";
import { GeneralEvent } from "models/GeneralEvent";
import { RedisClient } from "redis/RedisClient";
import { decodeEvent, getTopics } from "utils/event.util";
import { NftHolder } from 'models/NftHolder'
import { TokenHolder } from 'models/TokenHolder'
import { NftStake } from 'models/NftStake'
import { IEventCfg } from "interface/IEventCfg";
let eventProcessers = {
NftHolder: NftHolder,
TokenHolder: TokenHolder,
NftStake: NftStake
}
const MAX_TOPICS = 4
export class EventBatchSvr {
@ -77,7 +87,7 @@ export class EventBatchSvr {
}
} else if (uninParams.length == 1) {
logger.debug(`unin params length 1, use eth_getLogs`)
let result = await ethGetLogs(this.rpc, uninParams[0])
let result = await ethGetLogs(this.rpc, uninParams[0].params)
if (result.error) {
throw result.error
}
@ -157,9 +167,8 @@ export class EventBatchSvr {
event.decodedData = result
const record = await GeneralEvent.saveEvent(event)
blockNumber = Math.max(parseInt(event.blockNumber, 16), cfg.fromBlock)
if (cfg.eventProcesser) {
// @ts-ignore
await cfg.eventProcesser.parseEvent(record)
if (cfg.eventProcesser && eventProcessers[cfg.eventProcesser]) {
await eventProcessers[cfg.eventProcesser].parseEvent(record)
}
}
return blockNumber

View File

@ -1,7 +1,8 @@
import { IEventCfg } from "config/events_cfg";
//@ts-ignore
import { keccak256, _jsonInterfaceMethodToString, AbiInput } from "web3-utils";
import web3abi from 'web3-eth-abi';
import { IEventCfg } from "interface/IEventCfg";
export const getTopics = (cfg: IEventCfg) => {
// let abi = cfg.abi

View File

@ -4,7 +4,7 @@
"name": "chain-client",
"script": "npm",
"args": "run prod:api",
"cwd": "/data/apps/web_chain_client",
"cwd": "/root/code/web_chain_client",
"max_memory_restart": "1024M",
"log_date_format": "YYYY-MM-DD HH:mm Z",
"watch": false,