Skip to content

Commit

Permalink
Merge pull request #112 from klayrHQ/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
Theezr authored Oct 9, 2024
2 parents 20d6de5 + 7e1a92d commit 494d40d
Show file tree
Hide file tree
Showing 18 changed files with 444 additions and 93 deletions.
81 changes: 76 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@
"fastq": "^1.17.1",
"nestjs-loki-logger": "^0.1.0",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1"
"rxjs": "^7.8.1",
"ws": "^8.18.0"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
Expand All @@ -54,6 +55,7 @@
"@types/jest": "^29.5.2",
"@types/node": "^20.3.1",
"@types/supertest": "^6.0.0",
"@types/ws": "^8.5.12",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"eslint": "^8.42.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ CREATE TABLE "Transaction" (
"signatures" TEXT[],
"index" INTEGER NOT NULL,
"senderAddress" TEXT NOT NULL,
"receivingChainID" TEXT,
"recipientAddress" TEXT,
"executionStatus" TEXT DEFAULT 'pending',

Expand Down
1 change: 1 addition & 0 deletions prisma/schema/transaction.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ model Transaction {
signatures String[]
index Int
senderAddress String
receivingChainID String?
recipientAddress String?
executionStatus String? @default("pending")
sender Account @relation("sender", fields: [senderAddress], references: [address])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,20 @@ export class IndexTransactionHandler implements ICommandHandler<IndexTransaction

if (recipientAddress && !accounts.get(recipientAddress)) accounts.set(recipientAddress, {});

// TODO: this is not complete because validators are added after all txs, but decent quick solution which covers 80% +
if (`${tx.module}:${tx.command}` === TxEvents.POS_STAKE) {
await this.handlePosStake(txParams);
let receivingChainID = null;

switch (`${tx.module}:${tx.command}`) {
case TxEvents.POS_STAKE:
// TODO: this is not complete because validators are added after all txs, but decent quick solution which covers 80% +
await this.handlePosStake(txParams);
break;

case TxEvents.TOKEN_TRANSFER_CROSS_CHAIN:
receivingChainID = this.handleTransferCrossChain(txParams);
break;

default:
break;
}

return {
Expand All @@ -107,6 +118,7 @@ export class IndexTransactionHandler implements ICommandHandler<IndexTransaction
senderAddress: senderAddress,
recipientAddress,
index,
receivingChainID,
params: txParams,
};
}
Expand Down Expand Up @@ -161,4 +173,13 @@ export class IndexTransactionHandler implements ICommandHandler<IndexTransaction
),
);
}

// ! Dont know if it works, will check on deployment
private handleTransferCrossChain(txParams: any): string {
this.logger.debug('Handling cross chain transfer');
this.logger.debug(`Params: ${txParams}`);
const receivingChainID = txParams.receivingChainID;
this.logger.debug(`Receiving chain ID: ${receivingChainID}`);
return receivingChainID;
}
}
65 changes: 28 additions & 37 deletions src/modules/indexer/indexer.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { IndexAssetCommand } from './block/block-commands/asset-index.command';
import { ChainEvent } from './interfaces/chain-event.interface';
import { IndexKnownAccountsCommand } from './startup/known-accounts.command';
import { UpdateValidatorRanks } from './event/commands/update-validator-ranks.command';
import { OnEvent } from '@nestjs/event-emitter';

// Sets `genesisHeight` as `nextBlockToSync`
// `SYNCING`: Will send new block events to queue from `nextBlockToSync` to current `nodeHeight`
Expand All @@ -48,19 +49,10 @@ export class IndexerService {
this.state.set(Modules.INDEXER, IndexerState.START_UP);
}

async onModuleInit() {
await this.nodeApi.getAndSetNodeInfo();
}

async onApplicationBootstrap() {
await this.nodeApi.getAndSetNodeInfo();
await this.setNextBlockandState();
await this.executeStartUpCommands();

setImmediate(() => {
this.subscribeToNewBlock().catch((error) => {
this.logger.error('Error syncing with node', error);
});
});
}

private async executeStartUpCommands() {
Expand Down Expand Up @@ -191,41 +183,40 @@ export class IndexerService {
}
}

private async subscribeToNewBlock(): Promise<void> {
this.nodeApi.subscribeToNewBlock(async (newBlockData: NewBlockEvent) => {
const newBlockHeight = newBlockData.blockHeader.height;
const state = this.state.get(Modules.INDEXER);
@OnEvent(NodeApi.CHAIN_NEW_BLOCK)
private async subscribeToNewBlock(newBlockData: NewBlockEvent): Promise<void> {
const newBlockHeight = newBlockData.blockHeader.height;
const state = this.state.get(Modules.INDEXER);

if (state === IndexerState.SYNCING)
return this.logger.log(`Syncing: Current height ${this.nextBlockToSync}`);
if (state === IndexerState.SYNCING)
return this.logger.log(`Syncing: Current height ${this.nextBlockToSync}`);

if (this.processingBlocks)
return this.logger.log(`Already processing blocks: Current height ${this.nextBlockToSync}`);
if (this.processingBlocks)
return this.logger.log(`Already processing blocks: Current height ${this.nextBlockToSync}`);

// will go back to syncing state if received block is greather then `nextBlockToSync`
if (newBlockHeight > this.nextBlockToSync || state === IndexerState.RESTART) {
this.state.set(Modules.INDEXER, IndexerState.SYNCING);
// will go back to syncing state if received block is greather then `nextBlockToSync`
if (newBlockHeight > this.nextBlockToSync || state === IndexerState.RESTART) {
this.state.set(Modules.INDEXER, IndexerState.SYNCING);

setImmediate(() => {
this.syncWithNode().catch((error) => {
this.state.set(Modules.INDEXER, IndexerState.RESTART);
this.logger.error('Error syncing with node, will retry', error);
});
setImmediate(() => {
this.syncWithNode().catch((error) => {
this.state.set(Modules.INDEXER, IndexerState.RESTART);
this.logger.error('Error syncing with node, will retry', error);
});

return;
}

const block = await this.nodeApi.invokeApi<Block>(NodeApi.CHAIN_GET_BLOCK_BY_ID, {
id: newBlockData.blockHeader.id,
});

await Promise.all([
this.handleNewBlockEvent([block]),
this.nodeApi.cacheNodeApiOnNewBlock(block.header.height),
this.updateNextBlockToSync(newBlockHeight + 1),
]);
return;
}

const block = await this.nodeApi.invokeApi<Block>(NodeApi.CHAIN_GET_BLOCK_BY_ID, {
id: newBlockData.blockHeader.id,
});

await Promise.all([
this.handleNewBlockEvent([block]),
this.nodeApi.cacheNodeApiOnNewBlock(block.header.height),
this.updateNextBlockToSync(newBlockHeight + 1),
]);
}

private async updateNextBlockToSync(height: number): Promise<void> {
Expand Down
2 changes: 2 additions & 0 deletions src/modules/indexer/interfaces/transaction.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,7 @@ export enum TxEvents {
POS_STAKE = 'pos:stake',
POS_REGISTER_VALIDATOR = 'pos:registerValidator',
POS_CHANGE_COMMISSION = 'pos:changeCommission',

TOKEN_TRANSFER = 'token:transfer',
TOKEN_TRANSFER_CROSS_CHAIN = 'token:transferCrossChain',
}
2 changes: 2 additions & 0 deletions src/modules/indexer/startup/genesis-index.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ export class IndexGenesisBlockHandler implements ICommandHandler<IndexGenesisBlo
await this.prisma.account.createMany({
data: addresses,
});

if (process.env.NODE_ENV === 'dev') return;
for await (const user of addresses) {
await this.commandBus.execute(new UpdateAccountCommand(user.address, tokenID));
}
Expand Down
3 changes: 2 additions & 1 deletion src/modules/node-api/node-api.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Module } from '@nestjs/common';
import { NodeApiService } from './node-api.service';
import { NodeApiController } from './node-api.controller';
import { WebSocketClientService } from './websocket/websocket.service';

@Module({
providers: [NodeApiService],
providers: [WebSocketClientService, NodeApiService],
exports: [NodeApiService],
controllers: [NodeApiController],
})
Expand Down
Loading

0 comments on commit 494d40d

Please sign in to comment.