Skip to content

Commit 860398e

Browse files
committed
GET /token/winners
1 parent 1baf798 commit 860398e

File tree

6 files changed

+116
-8
lines changed

6 files changed

+116
-8
lines changed

src/app.controller.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { ConfigService } from '@nestjs/config';
1515
import {SkipThrottle} from "@nestjs/throttler";
1616
import {AddCommentDto, GetCommentsDto} from "./dto/comment.dto";
1717
import {AppService} from "./app.service";
18-
import {GetTokenBalancesDto, GetTokensDto} from "./dto/token.dto";
18+
import {GetTokenBalancesDto, GetTokensDto, GetTokenWinnersDto} from "./dto/token.dto";
1919
import {GetTradesDto} from "./dto/trade.dto";
2020
import {AddUserDto} from "./dto/user.dto";
2121
import {UserService} from "./user/user.service";
@@ -55,6 +55,11 @@ export class AppController {
5555
return this.appService.getTokenBalances(dto)
5656
}
5757

58+
@Get('/token/winners')
59+
getWinners(@Query() dto: GetTokenWinnersDto) {
60+
return this.appService.getTokenWinners(dto)
61+
}
62+
5863
@Get('/comments')
5964
getComments(@Query() dto: GetCommentsDto) {
6065
return this.appService.getComments(dto)

src/app.service.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import {Injectable, Logger} from '@nestjs/common';
22
import {Between, DataSource} from "typeorm";
3-
import {Comment, Token, TokenBalance, UserAccount} from "./entities";
3+
import {Comment, Token, TokenBalance, TokenWinner, UserAccount} from "./entities";
44
import {AddCommentDto, GetCommentsDto} from "./dto/comment.dto";
5-
import {GetTokenBalancesDto, GetTokensDto} from "./dto/token.dto";
5+
import {GetTokenBalancesDto, GetTokensDto, GetTokenWinnersDto} from "./dto/token.dto";
66
import {Trade} from "./entities";
77
import {GetTradesDto} from "./dto/trade.dto";
88
import {UserService} from "./user/user.service";
@@ -54,7 +54,6 @@ export class AppService {
5454

5555
async getTokenBalances(dto: GetTokenBalancesDto){
5656
const { offset = 0, limit = 100 } = dto
57-
5857
return this.dataSource.manager.find(TokenBalance, {
5958
where: {
6059
token: {
@@ -69,6 +68,16 @@ export class AppService {
6968
})
7069
}
7170

71+
async getTokenWinners(dto: GetTokenWinnersDto) {
72+
return await this.dataSource.manager.find(TokenWinner, {
73+
order: {
74+
timestamp: 'desc'
75+
},
76+
take: dto.limit,
77+
skip: dto.offset,
78+
})
79+
}
80+
7281
async getTrades(dto: GetTradesDto){
7382
return await this.dataSource.manager.find(Trade, {
7483
where: {

src/dto/token.dto.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,17 @@ export class GetTokenBalancesDto {
3939
@IsString()
4040
offset: number;
4141
}
42+
43+
export class GetTokenWinnersDto {
44+
@ApiProperty({ type: Number, required: false, default: '100' })
45+
// @Transform((limit) => limit.value.toNumber())
46+
@Type(() => String)
47+
@IsString()
48+
limit: number;
49+
50+
@ApiProperty({ type: Number, required: false, default: '0' })
51+
// @Transform((offset) => offset.value.toNumber())
52+
@Type(() => String)
53+
@IsString()
54+
offset: number;
55+
}

src/entities/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,17 @@ import { IndexerState } from './indexer.state.entity';
44
import { Trade } from './trade.entity';
55
import { Comment } from './comment.entity';
66
import { TokenBalance } from './token.balances.entity';
7+
import { TokenWinner } from './token.winner.entity';
78

89
const entities = [
910
UserAccount,
1011
Token,
1112
IndexerState,
1213
Trade,
1314
Comment,
14-
TokenBalance
15+
TokenBalance,
16+
TokenWinner
1517
];
1618

17-
export { UserAccount, Token, IndexerState, Trade, Comment, TokenBalance };
19+
export { UserAccount, Token, IndexerState, Trade, Comment, TokenBalance, TokenWinner };
1820
export default entities;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import {
2+
Column,
3+
CreateDateColumn,
4+
Entity,
5+
PrimaryGeneratedColumn,
6+
ManyToOne
7+
} from 'typeorm';
8+
import { ApiProperty } from '@nestjs/swagger';
9+
import {Token} from "./token.entity";
10+
11+
@Entity({ name: 'token_winners' })
12+
export class TokenWinner {
13+
@ApiProperty()
14+
@PrimaryGeneratedColumn('uuid')
15+
id: string;
16+
17+
@ManyToOne(() => Token, {
18+
eager: true
19+
})
20+
token: Token
21+
22+
@ApiProperty()
23+
@Column({ type: 'decimal', default: 0 })
24+
timestamp: string;
25+
26+
@ApiProperty()
27+
@Column()
28+
txnHash: string;
29+
30+
@ApiProperty()
31+
@Column({ type: 'integer' })
32+
blockNumber: number;
33+
34+
@ApiProperty()
35+
@CreateDateColumn({ name: 'createdAt' })
36+
createdAt: Date;
37+
}

src/indexer/indexer.service.ts

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {Contract, ContractAbi, EventLog, Web3} from "web3";
33
import {TokenMetadata, TradeEventLog, TradeType} from "../types";
44
import axios from "axios";
55
import process from "process";
6-
import {IndexerState, Token, TokenBalance, Trade} from "../entities";
6+
import {IndexerState, Token, TokenBalance, TokenWinner, Trade} from "../entities";
77
import {ConfigService} from "@nestjs/config";
88
import {UserService} from "../user/user.service";
99
import {DataSource} from "typeorm";
@@ -83,6 +83,42 @@ export class IndexerService {
8383
}
8484
}
8585

86+
private async processSetWinnerEvents(events: EventLog[]) {
87+
for(const event of events) {
88+
const txnHash = event.transactionHash.toLowerCase()
89+
const blockNumber = Number(event.blockNumber)
90+
const values = event.returnValues
91+
const winnerAddress = (values['winner'] as string).toLowerCase()
92+
const timestamp = String(values['timestamp'] as bigint)
93+
94+
const existedWinner = await this.dataSource.manager.findOne(TokenWinner, {
95+
where: {
96+
token: {
97+
address: winnerAddress
98+
},
99+
timestamp
100+
}
101+
})
102+
103+
if(!existedWinner) {
104+
const token = await this.appService.getTokenByAddress(winnerAddress)
105+
if(!token) {
106+
this.logger.error(`Winner token entry not found in database, winnerAddress=${winnerAddress} , exit`)
107+
process.exit(1)
108+
}
109+
await this.dataSource.manager.insert(TokenWinner, {
110+
token,
111+
timestamp,
112+
txnHash,
113+
blockNumber
114+
})
115+
this.logger.log(`Added new token winner=${winnerAddress}, timestamp=${timestamp}`)
116+
} else {
117+
this.logger.warn(`Token winner=${winnerAddress}, timestamp=${timestamp} already exists, skip`)
118+
}
119+
}
120+
}
121+
86122
private async processTradeEvents(events: TradeEventLog[]) {
87123
for(const event of events) {
88124
const { type, data } = event
@@ -208,6 +244,10 @@ export class IndexerService {
208244
}
209245

210246
if(toBlock - fromBlock >= 1) {
247+
const setWinnerEvents = await this.tokenFactoryContract.getPastEvents('allEvents', {
248+
fromBlock, toBlock, topics: [ this.web3.utils.sha3('SetWinner(address,uint256)')],
249+
}) as EventLog[];
250+
211251
const tokenCreatedEvents = await this.tokenFactoryContract.getPastEvents('allEvents', {
212252
fromBlock,
213253
toBlock,
@@ -289,9 +329,10 @@ export class IndexerService {
289329
this.logger.log(`Create token: address=${tokenAddress}, name=${name}, symbol=${symbol}, uri=${uri}, creator=${creatorAddress}, txnHash=${txnHash}`);
290330
}
291331

332+
await this.processSetWinnerEvents(setWinnerEvents)
292333
await this.processTradeEvents(tradeEvents)
293334

294-
this.logger.log(`[${fromBlock}-${toBlock}] (${((toBlock - fromBlock + 1))} blocks), new tokens=${tokenCreatedEvents.length}, trade=${[...buyEvents, ...sellEvents].length} (buy=${buyEvents.length}, sell=${sellEvents.length})`)
335+
this.logger.log(`[${fromBlock}-${toBlock}] (${((toBlock - fromBlock + 1))} blocks), new tokens=${tokenCreatedEvents.length}, trade=${[...buyEvents, ...sellEvents].length} (buy=${buyEvents.length}, sell=${sellEvents.length}), setWinner=${setWinnerEvents.length}`)
295336
} else {
296337
// Wait for blockchain
297338
toBlock = fromBlockParam - 1

0 commit comments

Comments
 (0)