Skip to content

Commit

Permalink
feat: extend drep list sql to support drep types, searching and sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
MSzalowski committed Oct 28, 2024
1 parent 119883f commit dd31dcb
Show file tree
Hide file tree
Showing 8 changed files with 663 additions and 403 deletions.
252 changes: 157 additions & 95 deletions backend/package-lock.json

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion backend/src/ada-holder/ada-holder.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ export class AdaHolderService {
}

async getVotingPower(stakeKey: string) {
console.log('stakeKey', stakeKey);
try {
const sqlFilePath = path.join(
__dirname,
Expand Down
3 changes: 1 addition & 2 deletions backend/src/drep/drep.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ export class DRepListParamsDto {
@IsString()
@ApiPropertyOptional({
type: String,
description:
'Search by DRep view or raw id',
description: 'Search by DRep view or raw id',
})
search?: string;
}
60 changes: 29 additions & 31 deletions backend/src/drep/drep.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@ import * as fs from 'fs';
import { DataSource } from 'typeorm';

import { DRepListParamsDto, DRepSort } from './drep.dto';
import {
DRepListItemType,
DRepStatus,
DRepType,
RawQueryDRepListItemType,
} from 'src/types/drep';
import { DRepListItemType, RawQueryDRepListItemType } from 'src/types/drep';

@Injectable()
export class DrepService {
Expand Down Expand Up @@ -44,7 +39,6 @@ export class DrepService {
async listDReps(query: DRepListParamsDto) {
const sqlFilePath = path.join(__dirname, '../sql', 'list-dreps.sql');
const sql = fs.readFileSync(sqlFilePath, 'utf8');

const {
page = 1,
pageSize = 10,
Expand All @@ -57,14 +51,20 @@ export class DrepService {

const totalResult = await this.dataSource.query<{ count: string }[]>(
countQuery,
[],
[search, sort, status.length ? status : null],
);

const total = parseInt(totalResult[0].count, 10);

const result = await this.dataSource.query<RawQueryDRepListItemType[]>(
`${sql} LIMIT $2 OFFSET $1`,
[(page - 1) * pageSize, pageSize],
`${sql} LIMIT $5 OFFSET $4`,
[
search,
sort,
status.length ? status : null,
Number((page - 1) * pageSize),
Number(pageSize),
],
);

const elements = result.map(this.mapDRepListItem);
Expand All @@ -79,31 +79,29 @@ export class DrepService {

private mapDRepListItem(dRep: RawQueryDRepListItemType): DRepListItemType {
return {
drepId: dRep.drep_id,
view: dRep.view,
dRepHash: dRep.drep_id,
dRepView: dRep.view,
isScriptBased: dRep.has_script,
type:
+dRep.latest_deposit >= 0
? dRep.url
? DRepType.DRep
: DRepType.DirectVoter
: dRep.has_non_deregister_voting_anchor
? DRepType.DRep
: DRepType.DirectVoter,
status:
+dRep.deposit >= 0
? dRep.active
? DRepStatus.Active
: DRepStatus.Inactive
: DRepStatus.Retired,
url: dRep.url,
dataHash: dRep.data_hash,
deposit: +dRep.deposit,
votingPower: dRep.voting_power ? +dRep.voting_power : null,
latestRegistrationDate: dRep.latest_registration_date,
latestTxHash: dRep.latest_tx_hash,
metadataError: dRep.metadata_error,
metadataHash: dRep.metadata_hash,
isActive: dRep.active,
txHash: dRep.tx_hash,
date: dRep.last_register_time,
latestNonDeregisterVotingAnchorWasNotNull:
dRep.has_non_deregister_voting_anchor,
metadataError: dRep.fetch_error,
paymentAddress: dRep.payment_address,
givenName: dRep.given_name,
url: dRep.url,
objectives: dRep.objectives,
motivations: dRep.motivations,
qualifications: dRep.qualifications,
imageUrl: dRep.image_url,
imageHash: dRep.image_hash,
type: dRep.type,
status: dRep.status,
latestDeposit: +dRep.latest_deposit,
};
}
}
4 changes: 3 additions & 1 deletion backend/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);

app.enableCors();

const config = new DocumentBuilder()
.setTitle('GovTool Delegation Pillar API')
.setDescription('API for the GovTool Delegation Pillar')
Expand All @@ -15,6 +17,6 @@ async function bootstrap() {
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);

await app.listen(3001);
await app.listen(process.env.PORT || 3000);
}
bootstrap();
135 changes: 109 additions & 26 deletions backend/src/sql/list-dreps.sql
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,72 @@ DRepActivity AS (
ORDER BY
epoch_no DESC
LIMIT 1
),
DRepStatus AS (
SELECT
dh.id AS drep_hash_id,
CASE
WHEN dr_deposit.deposit < 0 THEN 'Retired'
WHEN dr_deposit.deposit >= 0 AND (DRepActivity.epoch_no - MAX(COALESCE(block.epoch_no, block_first_register.epoch_no))) <= DRepActivity.drep_activity THEN 'Active'
ELSE 'Inactive'
END AS status
FROM
drep_hash dh
LEFT JOIN (
SELECT
dr.id,
dr.drep_hash_id,
dr.deposit,
ROW_NUMBER() OVER (PARTITION BY dr.drep_hash_id ORDER BY dr.tx_id DESC) AS rn
FROM
drep_registration dr
WHERE
dr.deposit IS NOT NULL
) AS dr_deposit ON dr_deposit.drep_hash_id = dh.id
AND dr_deposit.rn = 1
LEFT JOIN tx ON tx.id = dr_deposit.id
LEFT JOIN block ON block.id = tx.block_id
LEFT JOIN block AS block_first_register ON block_first_register.id = tx.block_id
CROSS JOIN DRepActivity
GROUP BY dh.id, dr_deposit.deposit, DRepActivity.epoch_no, DRepActivity.drep_activity
)
SELECT
encode(dh.raw, 'hex'),
encode(dh.raw, 'hex') as drep_id,
dh.view,
dh.has_script,
va.url,
encode(va.data_hash, 'hex'),
encode(va.data_hash, 'hex') as data_hash,
dr_deposit.deposit,
DRepDistr.amount,
(DRepActivity.epoch_no - Max(coalesce(block.epoch_no, block_first_register.epoch_no))) <= DRepActivity.drep_activity AS active,
DRepDistr.amount as voting_power,
DRepStatus.status,
(DRepActivity.epoch_no - MAX(COALESCE(block.epoch_no, block_first_register.epoch_no))) <= DRepActivity.drep_activity AS active,
encode(dr_voting_anchor.tx_hash, 'hex') AS tx_hash,
newestRegister.time AS last_register_time,
COALESCE(latestDeposit.deposit, 0),
COALESCE(latestDeposit.deposit, 0) as latest_deposit,
non_deregister_voting_anchor.url IS NOT NULL AS has_non_deregister_voting_anchor,
fetch_error.message,
fetch_error.message as fetch_error,
off_chain_vote_drep_data.payment_address,
off_chain_vote_drep_data.given_name,
off_chain_vote_drep_data.objectives,
off_chain_vote_drep_data.motivations,
off_chain_vote_drep_data.qualifications,
off_chain_vote_drep_data.image_url,
off_chain_vote_drep_data.image_hash
off_chain_vote_drep_data.image_hash,
CASE
WHEN COALESCE(latestDeposit.deposit, 0) >= 0 THEN
CASE
WHEN va.url IS NOT NULL THEN 'DRep'
ELSE 'DirectVoter'
END
ELSE
CASE
WHEN non_deregister_voting_anchor.url IS NOT NULL THEN 'DRep'
ELSE 'DirectVoter'
END
END AS type
FROM
drep_hash dh
JOIN DRepStatus ON DRepStatus.drep_hash_id = dh.id
JOIN (
SELECT
dr.id,
Expand All @@ -50,16 +92,18 @@ FROM
FROM
drep_registration dr
WHERE
dr.deposit IS NOT NULL) AS dr_deposit ON dr_deposit.drep_hash_id = dh.id
dr.deposit IS NOT NULL
) AS dr_deposit ON dr_deposit.drep_hash_id = dh.id
AND dr_deposit.rn = 1
JOIN (
JOIN (
SELECT
dr.id,
dr.drep_hash_id,
dr.deposit,
ROW_NUMBER() OVER (PARTITION BY dr.drep_hash_id ORDER BY dr.tx_id DESC) AS rn
FROM
drep_registration dr) AS latestDeposit ON latestDeposit.drep_hash_id = dh.id
drep_registration dr
) AS latestDeposit ON latestDeposit.drep_hash_id = dh.id
AND latestDeposit.rn = 1
LEFT JOIN (
SELECT
Expand All @@ -70,9 +114,10 @@ FROM
tx.hash AS tx_hash
FROM
drep_registration dr
JOIN tx ON tx.id = dr.tx_id) AS dr_voting_anchor ON dr_voting_anchor.drep_hash_id = dh.id
AND dr_voting_anchor.rn = 1
LEFT JOIN (
JOIN tx ON tx.id = dr.tx_id
) AS dr_voting_anchor ON dr_voting_anchor.drep_hash_id = dh.id
AND dr_voting_anchor.rn = 1
LEFT JOIN (
SELECT
dr.id,
dr.drep_hash_id,
Expand All @@ -82,32 +127,35 @@ FROM
FROM
drep_registration dr
JOIN tx ON tx.id = dr.tx_id
WHERE dr.deposit is not null
AND dr.deposit >= 0) AS dr_non_deregister_voting_anchor ON dr_non_deregister_voting_anchor.drep_hash_id = dh.id
AND dr_non_deregister_voting_anchor.rn = 1
WHERE dr.deposit IS NOT NULL
AND dr.deposit >= 0
) AS dr_non_deregister_voting_anchor ON dr_non_deregister_voting_anchor.drep_hash_id = dh.id
AND dr_non_deregister_voting_anchor.rn = 1
LEFT JOIN (
SELECT
dr.id,
dr.drep_hash_id,
dr.voting_anchor_id,
ROW_NUMBER() OVER (PARTITION BY dr.drep_hash_id ORDER BY dr.tx_id DESC) AS rn
FROM
drep_registration dr) AS second_to_newest_drep_registration ON second_to_newest_drep_registration.drep_hash_id = dh.id
AND second_to_newest_drep_registration.rn = 2
drep_registration dr
) AS second_to_newest_drep_registration ON second_to_newest_drep_registration.drep_hash_id = dh.id
AND second_to_newest_drep_registration.rn = 2
LEFT JOIN DRepDistr ON DRepDistr.hash_id = dh.id
AND DRepDistr.rn = 1
AND DRepDistr.rn = 1
LEFT JOIN voting_anchor va ON va.id = dr_voting_anchor.voting_anchor_id
LEFT JOIN voting_anchor non_deregister_voting_anchor ON non_deregister_voting_anchor.id = dr_non_deregister_voting_anchor.voting_anchor_id
LEFT JOIN (
SELECT fetch_error as message, voting_anchor_id
SELECT fetch_error AS message, voting_anchor_id
FROM off_chain_vote_fetch_error
WHERE fetch_time = (
SELECT max(fetch_time)
FROM off_chain_vote_fetch_error)
SELECT MAX(fetch_time)
FROM off_chain_vote_fetch_error
)
GROUP BY fetch_error, voting_anchor_id
) AS fetch_error ON fetch_error.voting_anchor_id = va.id
LEFT JOIN off_chain_vote_data ON off_chain_vote_data.voting_anchor_id = va.id
LEFT JOIN off_chain_vote_drep_data on off_chain_vote_drep_data.off_chain_vote_data_id = off_chain_vote_data.id
LEFT JOIN off_chain_vote_drep_data ON off_chain_vote_drep_data.off_chain_vote_data_id = off_chain_vote_data.id
CROSS JOIN DRepActivity
LEFT JOIN voting_procedure AS voting_procedure ON voting_procedure.drep_voter = dh.id
LEFT JOIN tx AS tx ON tx.id = voting_procedure.tx_id
Expand All @@ -122,18 +170,40 @@ FROM
JOIN tx ON tx.id = dr.tx_id
JOIN block ON block.id = tx.block_id
WHERE
NOT (dr.deposit < 0)) AS newestRegister ON newestRegister.drep_hash_id = dh.id
NOT (dr.deposit < 0)
) AS newestRegister ON newestRegister.drep_hash_id = dh.id
AND newestRegister.rn = 1
LEFT JOIN (
SELECT
dr.tx_id,
dr.drep_hash_id,
ROW_NUMBER() OVER (PARTITION BY dr.drep_hash_id ORDER BY dr.tx_id ASC) AS rn
FROM
drep_registration dr) AS dr_first_register ON dr_first_register.drep_hash_id = dh.id
AND dr_first_register.rn = 1
drep_registration dr
) AS dr_first_register ON dr_first_register.drep_hash_id = dh.id
AND dr_first_register.rn = 1
LEFT JOIN tx AS tx_first_register ON tx_first_register.id = dr_first_register.tx_id
LEFT JOIN block AS block_first_register ON block_first_register.id = tx_first_register.block_id
WHERE
(array_length($3::text[], 1) IS NULL OR DRepStatus.status = ANY($3::text[]))
AND (
(
COALESCE($1, '') = ''
OR dh.view ILIKE $1
OR off_chain_vote_drep_data.given_name ILIKE $1
)
AND (
CASE
WHEN
(
COALESCE(latestDeposit.deposit, 0) >= 0 AND va.url IS NULL
OR COALESCE(latestDeposit.deposit, 0) < 0 AND non_deregister_voting_anchor.url IS NULL
)
THEN dh.view ILIKE $1
ELSE TRUE
END
)
)
GROUP BY
dh.raw,
second_to_newest_drep_registration.voting_anchor_id,
Expand All @@ -143,6 +213,7 @@ GROUP BY
va.data_hash,
dr_deposit.deposit,
DRepDistr.amount,
DRepStatus.status,
DRepActivity.epoch_no,
DRepActivity.drep_activity,
dr_voting_anchor.tx_hash,
Expand All @@ -157,3 +228,15 @@ GROUP BY
off_chain_vote_drep_data.qualifications,
off_chain_vote_drep_data.image_url,
off_chain_vote_drep_data.image_hash
ORDER BY
CASE
WHEN $2 = 'Random' THEN RANDOM()
WHEN $2 = 'VotingPower' THEN DRepDistr.amount
WHEN $2 = 'RegistrationDate' THEN EXTRACT(EPOCH FROM newestRegister.time)
WHEN $2 = 'Status' THEN
CASE
WHEN DRepStatus.status = 'Retired' THEN 1
WHEN DRepStatus.status = 'Active' THEN 2
ELSE 3
END
END
Loading

0 comments on commit dd31dcb

Please sign in to comment.