Skip to content

Commit

Permalink
feat: migrate voting power related endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
MSzalowski committed Oct 9, 2024
1 parent fe76570 commit 5016eff
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 0 deletions.
23 changes: 23 additions & 0 deletions backend/src/ada-holder/ada-holder.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Controller, Get, Query } from '@nestjs/common';
import { ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger';
import { AdaHolderService } from './ada-holder.service';

@ApiTags('ada-holder')
@Controller('ada-holder')
export class AdaHolderController {
constructor(private adaHolderService: AdaHolderService) {}

@Get('get-current-delegation/:stakeKey')
@ApiOperation({ summary: 'Get current delegation of a stake key' })
@ApiQuery({ name: 'stakeKey', type: 'string', required: true })
async getCurrentDelegation(@Query('stakeKey') stakeKey: string) {
return this.adaHolderService.getCurrentDelegation(stakeKey);
}

@Get('get-voting-power/:stakeKey')
@ApiOperation({ summary: 'Get voting power of a stake key' })
@ApiQuery({ name: 'stakeKey', type: 'string', required: true })
async getVotingPower(@Query('stakeKey') stakeKey: string) {
return this.adaHolderService.getVotingPower(stakeKey);
}
}
9 changes: 9 additions & 0 deletions backend/src/ada-holder/ada-holder.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { AdaHolderController } from './ada-holder.controller';
import { AdaHolderService } from './ada-holder.service';

@Module({
controllers: [AdaHolderController],
providers: [AdaHolderService],
})
export class AdaHolderModule {}
63 changes: 63 additions & 0 deletions backend/src/ada-holder/ada-holder.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Injectable } from '@nestjs/common';
import { InjectDataSource } from '@nestjs/typeorm';
import path from 'path';
import * as fs from 'fs';
import { DataSource } from 'typeorm';

@Injectable()
export class AdaHolderService {
constructor(
@InjectDataSource()
private readonly dataSource: DataSource,
) {}

async getCurrentDelegation(stakeKey: string) {
try {
const sqlFilePath = path.join(
__dirname,
'../sql',
'get-current-delegation.sql',
);
const sql = fs.readFileSync(sqlFilePath, 'utf8');

const result = await this.dataSource.query(sql, [stakeKey]);
if (result.length === 0) {
return null;
}

const [mDRepHash, dRepView, txHash] = result[0];

return {
dRepHash: mDRepHash,
dRepView,
txHash,
};
} catch (error) {
console.error(error);
return null;
}
}

async getVotingPower(stakeKey: string) {
console.log('stakeKey', stakeKey);
try {
const sqlFilePath = path.join(
__dirname,
'../sql',
'get-voting-power.sql',
);
const sql = fs.readFileSync(sqlFilePath, 'utf8');

const result = await this.dataSource.query(sql, [stakeKey]);

if (result.length === 0) {
return 0;
}

return result[0];
} catch (error) {
console.error(error);
return null;
}
}
}
4 changes: 4 additions & 0 deletions backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';

import { ProposalModule } from './proposal/proposal.module';
import { AdaHolderModule } from './ada-holder/ada-holder.module';
import { DrepModule } from './drep/drep.module';

@Module({
imports: [
Expand Down Expand Up @@ -30,6 +32,8 @@ import { ProposalModule } from './proposal/proposal.module';
}),
}),
ProposalModule,
AdaHolderModule,
DrepModule,
],
controllers: [],
providers: [],
Expand Down
16 changes: 16 additions & 0 deletions backend/src/drep/drep.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Controller, Get, Query } from '@nestjs/common';
import { ApiOperation, ApiQuery, ApiTags } from '@nestjs/swagger';
import { DrepService } from './drep.service';

@ApiTags('drep')
@Controller('drep')
export class DrepController {
constructor(private drepService: DrepService) {}

@Get('get-voting-power/:drepId')
@ApiOperation({ summary: 'Get voting power of a drep id' })
@ApiQuery({ name: 'drepId', type: 'string', required: true })
async getVotingPower(@Query('drepId') drepId: string) {
return this.drepService.getVotingPower(drepId);
}
}
9 changes: 9 additions & 0 deletions backend/src/drep/drep.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common';
import { DrepController } from './drep.controller';
import { DrepService } from './drep.service';

@Module({
controllers: [DrepController],
providers: [DrepService],
})
export class DrepModule {}
35 changes: 35 additions & 0 deletions backend/src/drep/drep.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Injectable } from '@nestjs/common';
import { InjectDataSource } from '@nestjs/typeorm';
import path from 'path';
import * as fs from 'fs';
import { DataSource } from 'typeorm';

@Injectable()
export class DrepService {
constructor(
@InjectDataSource()
private readonly dataSource: DataSource,
) {}

async getVotingPower(drepId: string) {
try {
const sqlFilePath = path.join(
__dirname,
'../sql',
'get-voting-power.sql',
);
const sql = fs.readFileSync(sqlFilePath, 'utf8');

const result = await this.dataSource.query(sql, [drepId]);

if (result.length === 0) {
return 0;
}

return result[0];
} catch (error) {
console.error(error);
return null;
}
}
}
19 changes: 19 additions & 0 deletions backend/src/sql/get-current-delegation.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
SELECT
CASE
WHEN drep_hash.raw IS NULL THEN NULL
ELSE encode(drep_hash.raw, 'hex')
END AS drep_raw,
drep_hash.view AS drep_view,
encode(tx.hash, 'hex')
FROM delegation_vote
JOIN tx ON tx.id = delegation_vote.tx_id
JOIN drep_hash ON drep_hash.id = delegation_vote.drep_hash_id
JOIN stake_address ON stake_address.id = delegation_vote.addr_id
WHERE stake_address.hash_raw = decode($1, 'hex')
AND NOT EXISTS (
SELECT *
FROM delegation_vote AS dv2
WHERE dv2.addr_id = delegation_vote.addr_id
AND dv2.tx_id > delegation_vote.tx_id
)
LIMIT 1;
19 changes: 19 additions & 0 deletions backend/src/sql/get-votes.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
SELECT DISTINCT ON (voting_procedure.gov_action_proposal_id, voting_procedure.drep_voter)
voting_procedure.gov_action_proposal_id,
CONCAT(encode(gov_action_tx.hash, 'hex'), '#', gov_action_proposal.index),
encode(drep_hash.raw, 'hex'),
voting_procedure.vote::text,
voting_anchor.url,
encode(voting_anchor.data_hash, 'hex'),
block.epoch_no AS epoch_no,
block.time AS time,
encode(vote_tx.hash, 'hex') AS vote_tx_hash
FROM voting_procedure
JOIN gov_action_proposal ON gov_action_proposal.id = voting_procedure.gov_action_proposal_id
JOIN drep_hash ON drep_hash.id = voting_procedure.drep_voter
LEFT JOIN voting_anchor ON voting_anchor.id = voting_procedure.voting_anchor_id
JOIN tx AS gov_action_tx ON gov_action_tx.id = gov_action_proposal.tx_id
JOIN tx AS vote_tx ON vote_tx.id = voting_procedure.tx_id
JOIN block ON block.id = vote_tx.block_id
WHERE drep_hash.raw = decode($1, 'hex')
ORDER BY voting_procedure.gov_action_proposal_id, voting_procedure.drep_voter, voting_procedure.id DESC
6 changes: 6 additions & 0 deletions backend/src/sql/get-voting-power.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
SELECT COALESCE(drep_distr.amount, 0) AS amount
FROM drep_hash
LEFT JOIN drep_distr ON drep_hash.id = drep_distr.hash_id
WHERE drep_hash.raw = DECODE($1::text, 'hex')
ORDER BY epoch_no DESC
LIMIT 1;

0 comments on commit 5016eff

Please sign in to comment.