-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c0a5214
commit 76838ac
Showing
7 changed files
with
198 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
116 changes: 116 additions & 0 deletions
116
apps/nestjs-indexer/src/indexer/name-service.indexer.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import { FieldElement, v1alpha2 as starknet } from '@apibara/starknet'; | ||
import { Inject, Injectable, Logger } from '@nestjs/common'; | ||
import { formatUnits } from 'viem'; | ||
import constants from 'src/common/constants'; | ||
import { uint256, validateAndParseAddress, hash, shortString } from 'starknet'; | ||
import { NameServiceService } from 'src/services/name-service/name-service.service'; | ||
import { IndexerService } from './indexer.service'; | ||
import { ContractAddress } from 'src/common/types'; | ||
|
||
@Injectable() | ||
export class NameServiceIndexer { | ||
private readonly logger = new Logger(NameServiceIndexer.name); | ||
private readonly eventKeys: string[]; | ||
|
||
constructor( | ||
@Inject(NameServiceService) | ||
private readonly nameServiceService: NameServiceService, | ||
|
||
@Inject(IndexerService) | ||
private readonly indexerService: IndexerService, | ||
) { | ||
this.eventKeys = [ | ||
validateAndParseAddress(hash.getSelectorFromName('UsernameClaimed')), | ||
]; | ||
} | ||
|
||
async onModuleInit() { | ||
this.indexerService.registerIndexer( | ||
this.eventKeys, | ||
this.handleEvents.bind(this), | ||
); | ||
} | ||
|
||
private async handleEvents( | ||
header: starknet.IBlockHeader, | ||
event: starknet.IEvent, | ||
transaction: starknet.ITransaction, | ||
) { | ||
this.logger.log('Received event'); | ||
const eventKey = validateAndParseAddress(FieldElement.toHex(event.keys[0])); | ||
|
||
switch (eventKey) { | ||
case validateAndParseAddress(hash.getSelectorFromName('UsernameClaimed')): | ||
this.logger.log('Event name: CreateLaunch'); | ||
this.handleUsernameClaimedEvent(header, event, transaction); | ||
break; | ||
default: | ||
this.logger.warn(`Unknown event type: ${eventKey}`); | ||
} | ||
} | ||
|
||
private async handleUsernameClaimedEvent( | ||
header: starknet.IBlockHeader, | ||
event: starknet.IEvent, | ||
transaction: starknet.ITransaction, | ||
) { | ||
const { | ||
blockNumber, | ||
blockHash: blockHashFelt, | ||
timestamp: blockTimestamp, | ||
} = header; | ||
|
||
const blockHash = validateAndParseAddress( | ||
`0x${FieldElement.toBigInt(blockHashFelt).toString(16)}`, | ||
) as ContractAddress; | ||
|
||
const transactionHashFelt = transaction.meta.hash; | ||
const transactionHash = validateAndParseAddress( | ||
`0x${FieldElement.toBigInt(transactionHashFelt).toString(16)}`, | ||
) as ContractAddress; | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
const [_, addressFelt] = event.keys; | ||
|
||
const address = validateAndParseAddress( | ||
`0x${FieldElement.toBigInt(addressFelt).toString(16)}`, | ||
) as ContractAddress; | ||
|
||
const [usernameFelt, expiryFelt, paidLow, paidHigh, quoteTokenFelt] = | ||
event.data; | ||
|
||
const username = usernameFelt | ||
? shortString.decodeShortString( | ||
FieldElement.toBigInt(usernameFelt).toString(), | ||
) | ||
: ''; | ||
|
||
const expiry = new Date(Number(FieldElement.toBigInt(expiryFelt)) * 1000); | ||
|
||
const paidRaw = uint256.uint256ToBN({ | ||
low: FieldElement.toBigInt(paidLow), | ||
high: FieldElement.toBigInt(paidHigh), | ||
}); | ||
const paid = formatUnits(paidRaw, constants.DECIMALS).toString(); | ||
|
||
const quoteToken = validateAndParseAddress( | ||
`0x${FieldElement.toBigInt(quoteTokenFelt).toString(16)}`, | ||
) as ContractAddress; | ||
|
||
const data = { | ||
transactionHash, | ||
network: 'starknet-sepolia', | ||
blockNumber: Number(blockNumber), | ||
blockHash, | ||
blockTimestamp: new Date(Number(blockTimestamp.seconds) * 1000), | ||
ownerAddress: address, | ||
expiry, | ||
name: username, | ||
username, | ||
paid, | ||
quoteToken: quoteToken, | ||
}; | ||
|
||
await this.nameServiceService.create(data); | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
apps/nestjs-indexer/src/services/name-service/interfaces/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './name-service.interface'; |
17 changes: 17 additions & 0 deletions
17
apps/nestjs-indexer/src/services/name-service/interfaces/name-service.interface.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
export interface NameService { | ||
transactionHash: string; | ||
network?: string; | ||
blockHash?: string; | ||
blockNumber?: number; | ||
blockTimestamp?: Date; | ||
ownerAddress?: string; | ||
expiry?: Date; | ||
username?: string; | ||
name?: string; | ||
symbol?: string; | ||
paid?: string; | ||
quoteAddress?: string; | ||
cursor?: number; | ||
timestamp?: Date; | ||
createdAt?: Date; | ||
} |
9 changes: 9 additions & 0 deletions
9
apps/nestjs-indexer/src/services/name-service/name-service.module.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { NameServiceService } from './name-service.service'; | ||
|
||
@Module({ | ||
imports: [], | ||
providers: [NameServiceService], | ||
exports: [NameServiceService], | ||
}) | ||
export class NameServiceModule {} |
47 changes: 47 additions & 0 deletions
47
apps/nestjs-indexer/src/services/name-service/name-service.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { Injectable, Logger } from '@nestjs/common'; | ||
import { PrismaService } from 'src/prisma/prisma.service'; | ||
import { NameService } from './interfaces'; | ||
|
||
@Injectable() | ||
export class NameServiceService { | ||
private readonly logger = new Logger(NameServiceService.name); | ||
constructor(private readonly prismaService: PrismaService) {} | ||
|
||
async create(data: NameService) { | ||
try { | ||
const nameServiceRecord = | ||
await this.prismaService.username_claimed.findUnique({ | ||
where: { transaction_hash: data.transactionHash }, | ||
}); | ||
|
||
if (nameServiceRecord) { | ||
this.logger.warn( | ||
`Record with transaction hash ${data.transactionHash} already exists`, | ||
); | ||
return; | ||
} | ||
|
||
await this.prismaService.username_claimed.create({ | ||
data: { | ||
transaction_hash: data.transactionHash, | ||
network: data.network, | ||
block_hash: data.blockHash, | ||
block_number: data.blockNumber, | ||
block_timestamp: data.blockTimestamp, | ||
owner_address: data.ownerAddress, | ||
expiry: data.expiry, | ||
username: data.username, | ||
symbol: data.symbol, | ||
paid: data.paid, | ||
quote_address: data.quoteAddress, | ||
time_stamp: data.timestamp, | ||
}, | ||
}); | ||
} catch (error) { | ||
this.logger.error( | ||
`Error creating name service record: ${error.message}`, | ||
error.stack, | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters