Skip to content

Commit f9db3ec

Browse files
committed
Update API
1 parent 9b30370 commit f9db3ec

File tree

7 files changed

+231
-37
lines changed

7 files changed

+231
-37
lines changed

src/abi/Token.json

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,19 @@
284284
"stateMutability": "nonpayable",
285285
"type": "function"
286286
},
287+
{
288+
"inputs": [],
289+
"name": "contractURI",
290+
"outputs": [
291+
{
292+
"internalType": "string",
293+
"name": "",
294+
"type": "string"
295+
}
296+
],
297+
"stateMutability": "view",
298+
"type": "function"
299+
},
287300
{
288301
"inputs": [],
289302
"name": "decimals",
@@ -308,6 +321,16 @@
308321
"internalType": "string",
309322
"name": "symbol",
310323
"type": "string"
324+
},
325+
{
326+
"internalType": "string",
327+
"name": "_uri",
328+
"type": "string"
329+
},
330+
{
331+
"internalType": "address",
332+
"name": "_owner",
333+
"type": "address"
311334
}
312335
],
313336
"name": "initialize",
@@ -457,5 +480,18 @@
457480
"outputs": [],
458481
"stateMutability": "nonpayable",
459482
"type": "function"
483+
},
484+
{
485+
"inputs": [],
486+
"name": "uri",
487+
"outputs": [
488+
{
489+
"internalType": "string",
490+
"name": "",
491+
"type": "string"
492+
}
493+
],
494+
"stateMutability": "view",
495+
"type": "function"
460496
}
461497
]

src/abi/TokenFactory.json

Lines changed: 115 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,15 +79,53 @@
7979
"type": "error"
8080
},
8181
{
82+
"anonymous": false,
8283
"inputs": [
8384
{
85+
"indexed": true,
86+
"internalType": "address",
87+
"name": "sender",
88+
"type": "address"
89+
},
90+
{
91+
"indexed": true,
8492
"internalType": "address",
8593
"name": "token",
8694
"type": "address"
95+
},
96+
{
97+
"indexed": true,
98+
"internalType": "address",
99+
"name": "winnerToken",
100+
"type": "address"
101+
},
102+
{
103+
"indexed": false,
104+
"internalType": "uint256",
105+
"name": "burnedAmount",
106+
"type": "uint256"
107+
},
108+
{
109+
"indexed": false,
110+
"internalType": "uint256",
111+
"name": "receivedETH",
112+
"type": "uint256"
113+
},
114+
{
115+
"indexed": false,
116+
"internalType": "uint256",
117+
"name": "mintedAmount",
118+
"type": "uint256"
119+
},
120+
{
121+
"indexed": false,
122+
"internalType": "uint256",
123+
"name": "timestamp",
124+
"type": "uint256"
87125
}
88126
],
89-
"name": "SafeERC20FailedOperation",
90-
"type": "error"
127+
"name": "BurnTokenAndMintWinner",
128+
"type": "event"
91129
},
92130
{
93131
"anonymous": false,
@@ -108,6 +146,25 @@
108146
"name": "OwnershipTransferred",
109147
"type": "event"
110148
},
149+
{
150+
"anonymous": false,
151+
"inputs": [
152+
{
153+
"indexed": true,
154+
"internalType": "address",
155+
"name": "winner",
156+
"type": "address"
157+
},
158+
{
159+
"indexed": false,
160+
"internalType": "uint256",
161+
"name": "timestamp",
162+
"type": "uint256"
163+
}
164+
],
165+
"name": "SetWinner",
166+
"type": "event"
167+
},
111168
{
112169
"anonymous": false,
113170
"inputs": [
@@ -154,6 +211,30 @@
154211
"name": "token",
155212
"type": "address"
156213
},
214+
{
215+
"indexed": false,
216+
"internalType": "string",
217+
"name": "name",
218+
"type": "string"
219+
},
220+
{
221+
"indexed": false,
222+
"internalType": "string",
223+
"name": "symbol",
224+
"type": "string"
225+
},
226+
{
227+
"indexed": false,
228+
"internalType": "string",
229+
"name": "uri",
230+
"type": "string"
231+
},
232+
{
233+
"indexed": false,
234+
"internalType": "address",
235+
"name": "creator",
236+
"type": "address"
237+
},
157238
{
158239
"indexed": false,
159240
"internalType": "uint256",
@@ -306,7 +387,7 @@
306387
"type": "address"
307388
}
308389
],
309-
"name": "burnAllAndReleaseWinner",
390+
"name": "burnTokenAndMintWinner",
310391
"outputs": [],
311392
"stateMutability": "nonpayable",
312393
"type": "function"
@@ -361,6 +442,11 @@
361442
"internalType": "string",
362443
"name": "symbol",
363444
"type": "string"
445+
},
446+
{
447+
"internalType": "string",
448+
"name": "uri",
449+
"type": "string"
364450
}
365451
],
366452
"name": "createToken",
@@ -464,6 +550,19 @@
464550
"stateMutability": "nonpayable",
465551
"type": "function"
466552
},
553+
{
554+
"inputs": [
555+
{
556+
"internalType": "address",
557+
"name": "winnerAddress",
558+
"type": "address"
559+
}
560+
],
561+
"name": "setWinner",
562+
"outputs": [],
563+
"stateMutability": "nonpayable",
564+
"type": "function"
565+
},
467566
{
468567
"inputs": [],
469568
"name": "tokenImplementation",
@@ -534,5 +633,18 @@
534633
],
535634
"stateMutability": "view",
536635
"type": "function"
636+
},
637+
{
638+
"inputs": [],
639+
"name": "winnerToken",
640+
"outputs": [
641+
{
642+
"internalType": "address",
643+
"name": "",
644+
"type": "address"
645+
}
646+
],
647+
"stateMutability": "view",
648+
"type": "function"
537649
}
538650
]

src/app.service.ts

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@ import {Injectable, Logger} from '@nestjs/common';
22
import {ConfigService} from "@nestjs/config";
33
import {Contract, ContractAbi, EventLog, Web3} from "web3";
44
import * as TokenFactoryABI from './abi/TokenFactory.json'
5-
import * as TokenABI from './abi/Token.json'
65
import {Between, DataSource} from "typeorm";
7-
import {IndexerState, Token, UserAccount} from "./entities";
6+
import {Comment, IndexerState, Token, UserAccount} from "./entities";
87
import {AddCommentDto, GetCommentsDto} from "./dto/comment.dto";
9-
import {Comment} from "./entities";
108
import {GetTokensDto} from "./dto/token.dto";
119
import * as process from "node:process";
12-
import {Trade, TradeType} from "./entities/trade.entity";
10+
import {Trade} from "./entities";
1311
import {Cron, CronExpression} from "@nestjs/schedule";
1412
import * as moment from "moment";
1513
import {GetTradesDto} from "./dto/trade.dto";
1614
import {UserService} from "./user/user.service";
15+
import axios from "axios";
16+
import {TokenMetadata, TradeEventLog, TradeType} from "./types";
1717

1818
@Injectable()
1919
export class AppService {
@@ -90,26 +90,27 @@ export class AppService {
9090
}
9191
}
9292

93-
private async processTradeEvents(events: EventLog[], tradeType: TradeType) {
93+
private async processTradeEvents(events: TradeEventLog[]) {
9494
for(const event of events) {
95-
const txnHash = event.transactionHash
96-
const blockNumber = Number(event.blockNumber)
97-
const values = event.returnValues
98-
const tokenAddress = values['token'] as string
95+
const { data, type } = event
96+
const txnHash = data.transactionHash.toLowerCase()
97+
const blockNumber = Number(data.blockNumber)
98+
const values = data.returnValues
99+
const tokenAddress = (values['token'] as string).toLowerCase()
99100
const amountIn = String(values['amount0In'] as bigint)
100101
const amountOut = String(values['amount0Out'] as bigint)
101102
const fee = String(values['fee'] as bigint)
102103
const timestamp = Number(values['timestamp'] as bigint)
103104

104105
const token = await this.getTokenByAddress(tokenAddress)
105106
if(!token) {
106-
this.logger.error(`swap event: failed to get token by address="${tokenAddress}", event tx hash="${event.transactionHash}", exit`)
107+
this.logger.error(`Trade event: failed to get token by address="${tokenAddress}", event tx hash="${data.transactionHash}", exit`)
107108
process.exit(1)
108109
}
109110

110111
try {
111112
await this.dataSource.manager.insert(Trade, {
112-
type: tradeType,
113+
type,
113114
txnHash,
114115
blockNumber,
115116
token,
@@ -118,9 +119,9 @@ export class AppService {
118119
fee,
119120
timestamp
120121
});
121-
this.logger.log(`Trade [${tradeType}]: token=${tokenAddress}, amountIn=${amountIn}, amountOut=${amountOut}, fee=${fee}`)
122+
this.logger.log(`Trade [${type}]: token=${tokenAddress}, amountIn=${amountIn}, amountOut=${amountOut}, fee=${fee}, timestamp=${timestamp}, txnHash=${txnHash}`)
122123
} catch (e) {
123-
this.logger.error(`Failed to process swap token=${tokenAddress} txnHash=${txnHash}`, e)
124+
this.logger.error(`Failed to process trade [${type}]: token=${tokenAddress} txnHash=${txnHash}`, e)
124125
throw new Error(e);
125126
}
126127
}
@@ -163,7 +164,7 @@ export class AppService {
163164
fromBlock,
164165
toBlock,
165166
topics: [
166-
this.web3.utils.sha3('TokenCreated(address,uint256)'),
167+
this.web3.utils.sha3('TokenCreated(address,string,string,string,address,uint256)'),
167168
],
168169
}) as EventLog[];
169170

@@ -183,38 +184,60 @@ export class AppService {
183184
],
184185
}) as EventLog[];
185186

187+
const tradeEvents: TradeEventLog[] = [...buyEvents].map(data => {
188+
return {
189+
type: TradeType.buy,
190+
data
191+
}
192+
}).concat([...sellEvents].map(data => {
193+
return {
194+
type: TradeType.sell,
195+
data
196+
}
197+
})).sort((a, b) => {
198+
return +(a.data.returnValues.timestamp.toString()) - +(b.data.returnValues.timestamp.toString())
199+
})
200+
186201
for(const tokenCreated of tokenCreatedEvents) {
187-
const txnHash = tokenCreated.transactionHash
202+
const txnHash = tokenCreated.transactionHash.toLowerCase()
188203
const values = tokenCreated.returnValues
189-
const tokenAddress = values['token'] as string
204+
const tokenAddress = (values['token'] as string).toLowerCase()
205+
const name = values['name'] as string
206+
const symbol = values['symbol'] as string
207+
const uri = values['uri'] as string
208+
const creatorAddress = (values['creator'] as string).toLowerCase()
190209
const timestamp = Number(values['timestamp'] as bigint)
191210

192-
const tx = await this.web3.eth.getTransaction(txnHash)
193-
const userAddress = tx.from
211+
let image = null
212+
let uriData = null
213+
try {
214+
const { data } = await axios.get<TokenMetadata>(uri)
215+
uriData = data
216+
} catch (e) {
217+
this.logger.error(`Failed to get token uri data, uri=${uri}, tokenAddress=${tokenAddress}`, e)
218+
}
219+
194220
const user = await this.dataSource.manager.findOne(UserAccount, {
195221
where: {
196-
address: userAddress.toLowerCase()
222+
address: creatorAddress
197223
}
198224
})
199225

200-
const tokenContract = new this.web3.eth.Contract(TokenABI, tokenAddress);
201-
const name = await tokenContract.methods.name().call() as string
202-
const symbol = await tokenContract.methods.symbol().call() as string
203-
204226
await this.dataSource.manager.insert(Token, {
205227
txnHash,
206228
address: tokenAddress,
207229
blockNumber: Number(tokenCreated.blockNumber),
208230
name,
209231
symbol,
210232
timestamp,
211-
user
233+
user,
234+
uri,
235+
uriData,
212236
});
213-
this.logger.log(`New token: address=${tokenAddress}, name=${name}, symbol=${symbol}, user=${userAddress}, txnHash=${txnHash}`);
237+
this.logger.log(`Create token: address=${tokenAddress}, name=${name}, symbol=${symbol}, uri=${uri}, creator=${creatorAddress}, txnHash=${txnHash}`);
214238
}
215239

216-
await this.processTradeEvents(buyEvents, TradeType.buy)
217-
await this.processTradeEvents(sellEvents, TradeType.sell)
240+
await this.processTradeEvents(tradeEvents)
218241

219242
this.logger.log(`[${fromBlock}-${toBlock}] (${((toBlock - fromBlock + 1))} blocks), new tokens=${tokenCreatedEvents.length}, trade=${[...buyEvents, ...sellEvents].length} (buy=${buyEvents.length}, sell=${sellEvents.length})`)
220243
} else {

src/dto/metadata.dto.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export class AddTokenMetadataDto {
1616
@ApiProperty({ type: String, required: true })
1717
@Type(() => String)
1818
@IsString()
19-
ticker: string;
19+
symbol: string;
2020

2121
@ApiProperty({ type: String, required: true })
2222
@Type(() => String)

0 commit comments

Comments
 (0)