Skip to content

Commit

Permalink
Add token burn entity
Browse files Browse the repository at this point in the history
  • Loading branch information
ArtemKolodko committed Nov 21, 2024
1 parent c49464c commit 6940dec
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/app.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class AppService {
balance: MoreThan('0')
},
order: {
createdAt: 'desc'
balance: 'desc'
},
take: limit,
skip: offset
Expand Down
6 changes: 4 additions & 2 deletions src/entities/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Comment } from './comment.entity';
import { TokenBalance } from './token.balances.entity';
import { TokenWinner } from './token.winner.entity';
import { SignInRequestEntity } from './signin.entity';
import { TokenBurn } from './token.burn.entity';

const entities = [
UserAccount,
Expand All @@ -15,8 +16,9 @@ const entities = [
Comment,
TokenBalance,
TokenWinner,
SignInRequestEntity
SignInRequestEntity,
TokenBurn
];

export { UserAccount, Token, IndexerState, Trade, Comment, TokenBalance, TokenWinner, SignInRequestEntity };
export { UserAccount, Token, IndexerState, Trade, Comment, TokenBalance, TokenWinner, SignInRequestEntity, TokenBurn };
export default entities;
54 changes: 54 additions & 0 deletions src/entities/token.burn.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {
Column,
CreateDateColumn,
Entity,
PrimaryGeneratedColumn,
ManyToOne
} from 'typeorm';
import { ApiProperty } from '@nestjs/swagger';
import {Token} from "./token.entity";
import {UserAccount} from "./user-account.entity";

@Entity({ name: 'token_burns' })
export class TokenBurn {
@ApiProperty()
@PrimaryGeneratedColumn('uuid')
id: string;

@ApiProperty()
@Column({ unique: true })
txnHash: string;

@ApiProperty()
@Column({ type: 'integer' })
blockNumber: number;

@ManyToOne(() => UserAccount)
sender: UserAccount;

@ManyToOne(() => Token)
token: Token;

@ManyToOne(() => Token)
winnerToken: Token;

@ApiProperty()
@Column({ type: 'decimal' })
burnedAmount: string;

@ApiProperty()
@Column({ type: 'decimal' })
receivedETH: string;

@ApiProperty()
@Column({ type: 'decimal' })
mintedAmount: string;

@ApiProperty()
@Column({ type: 'bigint' })
timestamp: number;

@ApiProperty()
@CreateDateColumn({ name: 'createdAt' })
createdAt: Date;
}
4 changes: 4 additions & 0 deletions src/entities/token.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ export class Token {
@Column({ type: 'double precision', default: 0, transformer: new ColumnNumericTransformer() })
price: string;

@ApiProperty()
@Column('bool', { default: false })
isWinner: boolean;

protected marketCap: String;

@ApiProperty()
Expand Down
63 changes: 62 additions & 1 deletion src/indexer/indexer.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {Contract, ContractAbi, EventLog, Web3} from "web3";
import {TokenMetadata, TradeType} from "../types";
import axios from "axios";
import process from "process";
import {IndexerState, Token, TokenBalance, TokenWinner, Trade} from "../entities";
import {IndexerState, Token, TokenBalance, TokenBurn, TokenWinner, Trade} from "../entities";
import {ConfigService} from "@nestjs/config";
import {UserService} from "../user/user.service";
import {DataSource, EntityManager} from "typeorm";
Expand Down Expand Up @@ -114,6 +114,10 @@ export class IndexerService {
this.logger.error(`Failed to add winner: winner token not found in database, winnerAddress=${winnerAddress}, exit`)
process.exit(1)
}

token.isWinner = true

await transactionalEntityManager.save(token)
await transactionalEntityManager.insert(TokenWinner, {
token,
timestamp,
Expand Down Expand Up @@ -266,6 +270,50 @@ export class IndexerService {
}
}

private async processBurnTokenAndSetWinnerEvent(event: EventLog, transactionalEntityManager: EntityManager) {
const txnHash = event.transactionHash.toLowerCase()
const values = event.returnValues
const senderAddress = (values['sender'] as string).toLowerCase()
const tokenAddress = (values['token'] as string).toLowerCase()
const winnerTokenAddress = (values['winnerToken'] as string).toLowerCase()
const burnedAmount = values['burnedAmount'] as bigint
const receivedETH = values['receivedETH'] as bigint
const mintedAmount = values['mintedAmount'] as bigint
const timestamp = Number(values['timestamp'] as bigint)

let sender = await this.userService.getUserByAddress(senderAddress, transactionalEntityManager)
if(!sender) {
this.logger.warn(`Sender ${senderAddress} is missing, adding new user...`)
await this.userService.createUser({ address: senderAddress }, transactionalEntityManager)
sender = await this.userService.getUserByAddress(senderAddress, transactionalEntityManager)
}

const token = await this.appService.getTokenByAddress(tokenAddress, transactionalEntityManager)
if(!token) {
this.logger.error(`Token ${tokenAddress} not found in database, exit`)
process.exit(1)
}

const winnerToken = await this.appService.getTokenByAddress(winnerTokenAddress, transactionalEntityManager)
if(!winnerToken) {
this.logger.error(`Winner token ${winnerTokenAddress} not found in database, exit`)
process.exit(1)
}

await transactionalEntityManager.insert(TokenBurn, {
txnHash,
blockNumber: Number(event.blockNumber),
sender,
token,
winnerToken,
timestamp,
burnedAmount: String(burnedAmount),
receivedETH: String(receivedETH),
mintedAmount: String(mintedAmount),
});
this.logger.log(`BurnTokenAndMintWinner: senderAddress=${senderAddress}, tokenAddress=${tokenAddress}, winnerTokenAddress=${winnerTokenAddress}, burnedAmount=${burnedAmount}, receivedETH=${receivedETH}, mintedAmount=${mintedAmount}, txnHash=${txnHash}`);
}

private async getLatestIndexedBlockNumber() {
const indexerState = await this.dataSource.manager.findOne(IndexerState, {
where: {},
Expand Down Expand Up @@ -328,12 +376,21 @@ export class IndexerService {
],
}) as EventLog[];

const burnAndSetWinnerEvents = await this.tokenFactoryContract.getPastEvents('allEvents', {
fromBlock,
toBlock,
topics: [
this.web3.utils.sha3('BurnTokenAndMintWinner(address,address,address,uint256,uint256,uint256,uint256)'),
],
}) as EventLog[];

// concat and sort all events by block number and transaction index
const protocolEvents: { data: EventLog; type: string }[] = tokenCreatedEvents
.map(data => ({ type: 'create_token', data }))
.concat(...buyEvents.map(data => ({ type: 'buy', data })))
.concat(...sellEvents.map(data => ({ type: 'sell', data })))
.concat(...setWinnerEvents.map(data => ({ type: 'set_winner', data })))
.concat(...burnAndSetWinnerEvents.map(data => ({ type: 'burn_token_and_set_winner', data })))
.sort((a, b) => {
const blockNumberDiff = Number(a.data.blockNumber) - Number(b.data.blockNumber)
if(blockNumberDiff !== 0) {
Expand Down Expand Up @@ -362,6 +419,10 @@ export class IndexerService {
await this.processSetWinnerEvent(data, transactionalEntityManager)
break;
}
case 'burn_token_and_set_winner': {
await this.processBurnTokenAndSetWinnerEvent(data, transactionalEntityManager)
break;
}
}
}
})
Expand Down
14 changes: 10 additions & 4 deletions src/user/user.controller.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import {
BadRequestException,
Body,
Controller, Get,
Controller,
Get,
HttpCode,
HttpStatus,
Logger, NotFoundException, Param,
Post, UnauthorizedException,
Logger,
NotFoundException,
Param,
Post,
UnauthorizedException,
UsePipes,
ValidationPipe,
Request, UseGuards, InternalServerErrorException
Request,
UseGuards,
InternalServerErrorException
} from '@nestjs/common';
import {ApiBearerAuth, ApiOkResponse, ApiOperation, ApiTags} from "@nestjs/swagger";
import {validationCfg} from "../common/validation.cfg";
Expand Down

0 comments on commit 6940dec

Please sign in to comment.