Skip to content

Commit

Permalink
fix: retrieving data for special dreps drep_always_abstain and `dre…
Browse files Browse the repository at this point in the history
…p_always_no_confidence`
  • Loading branch information
slowbackspace committed Oct 2, 2024
1 parent 81af0db commit d5c2b55
Show file tree
Hide file tree
Showing 18 changed files with 169 additions and 70 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed

- Retrieving data for special dreps `drep_always_abstain` and `drep_always_no_confidence`

## [2.2.1] - 2024-09-24

### Fixed
Expand Down
16 changes: 11 additions & 5 deletions src/routes/governance/dreps/drep-id/delegators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { SQLQuery } from '../../../../sql/index.js';
import { getSchemaForEndpoint } from '@blockfrost/openapi';
import { isUnpaged } from '../../../../utils/routes.js';
import { handle400Custom } from '@blockfrost/blockfrost-utils/lib/fastify.js';
import { drepIdToRaw } from '../../../../utils/bech32.js';
import { validateDRepId } from '../../../../utils/validation.js';

async function route(fastify: FastifyInstance) {
fastify.route({
Expand All @@ -15,10 +15,10 @@ async function route(fastify: FastifyInstance) {
schema: getSchemaForEndpoint('/governance/dreps/{drep_id}/delegators'),

handler: async (request: FastifyRequest<QueryTypes.RequestParametersDRepID>, reply) => {
let drepHex;
let drepValidation;

try {
drepHex = drepIdToRaw(request.params.drep_id);
drepValidation = validateDRepId(request.params.drep_id);
} catch {
return handle400Custom(reply, 'Invalid or malformed drep id.');
}
Expand All @@ -30,11 +30,17 @@ async function route(fastify: FastifyInstance) {
const { rows }: { rows: ResponseTypes.DRepsDrepIDDelegators } = unpaged
? await clientDbSync.query<QueryTypes.DRepsDrepIDDelegators>(
SQLQuery.get('governance_dreps_drep_id_delegators_unpaged'),
[request.query.order],
[request.query.order, drepValidation.raw, drepValidation.id],
)
: await clientDbSync.query<QueryTypes.DRepsDrepIDDelegators>(
SQLQuery.get('governance_dreps_drep_id_delegators'),
[request.query.order, request.query.count, request.query.page, drepHex],
[
request.query.order,
request.query.count,
request.query.page,
drepValidation.raw,
drepValidation.id,
],
);

clientDbSync.release();
Expand Down
8 changes: 4 additions & 4 deletions src/routes/governance/dreps/drep-id/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { getDbSync } from '../../../../utils/database.js';
import { handle400Custom, handle404 } from '../../../../utils/error-handler.js';
import { SQLQuery } from '../../../../sql/index.js';
import { getSchemaForEndpoint } from '@blockfrost/openapi';
import { drepIdToRaw } from '../../../../utils/bech32.js';
import { validateDRepId } from '../../../../utils/validation.js';

async function route(fastify: FastifyInstance) {
fastify.route({
Expand All @@ -14,10 +14,10 @@ async function route(fastify: FastifyInstance) {
schema: getSchemaForEndpoint('/governance/dreps/{drep_id}'),

handler: async (request: FastifyRequest<QueryTypes.RequestDRepID>, reply) => {
let drepHex;
let drepValidation;

try {
drepHex = drepIdToRaw(request.params.drep_id);
drepValidation = validateDRepId(request.params.drep_id);
} catch {
return handle400Custom(reply, 'Invalid or malformed drep id.');
}
Expand All @@ -28,7 +28,7 @@ async function route(fastify: FastifyInstance) {
const { rows }: { rows: ResponseTypes.DRepsDrepID[] } =
await clientDbSync.query<QueryTypes.DRepsDrepID>(
SQLQuery.get('governance_dreps_drep_id'),
[drepHex],
[drepValidation.raw, drepValidation.id],
);

clientDbSync.release();
Expand Down
8 changes: 4 additions & 4 deletions src/routes/governance/dreps/drep-id/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { getDbSync } from '../../../../utils/database.js';
import { handle400Custom, handle404 } from '../../../../utils/error-handler.js';
import { SQLQuery } from '../../../../sql/index.js';
import { getSchemaForEndpoint } from '@blockfrost/openapi';
import { drepIdToRaw } from '../../../../utils/bech32.js';
import { validateDRepId } from '../../../../utils/validation.js';

async function route(fastify: FastifyInstance) {
fastify.route({
Expand All @@ -14,10 +14,10 @@ async function route(fastify: FastifyInstance) {
schema: getSchemaForEndpoint('/governance/dreps/{drep_id}/metadata'),

handler: async (request: FastifyRequest<QueryTypes.RequestDRepID>, reply) => {
let drepHex;
let drepValidation;

try {
drepHex = drepIdToRaw(request.params.drep_id);
drepValidation = validateDRepId(request.params.drep_id);
} catch {
return handle400Custom(reply, 'Invalid or malformed drep id.');
}
Expand All @@ -28,7 +28,7 @@ async function route(fastify: FastifyInstance) {
const { rows }: { rows: ResponseTypes.DRepsDrepIDMetadata[] } =
await clientDbSync.query<QueryTypes.DRepsDrepIDMetadata>(
SQLQuery.get('governance_dreps_drep_id_metadata'),
[drepHex],
[drepValidation.raw, drepValidation.id],
);

clientDbSync.release();
Expand Down
16 changes: 11 additions & 5 deletions src/routes/governance/dreps/drep-id/updates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { SQLQuery } from '../../../../sql/index.js';
import { getSchemaForEndpoint } from '@blockfrost/openapi';
import { isUnpaged } from '../../../../utils/routes.js';
import { handle400Custom } from '@blockfrost/blockfrost-utils/lib/fastify.js';
import { drepIdToRaw } from '../../../../utils/bech32.js';
import { validateDRepId } from '../../../../utils/validation.js';

async function route(fastify: FastifyInstance) {
fastify.route({
Expand All @@ -15,10 +15,10 @@ async function route(fastify: FastifyInstance) {
schema: getSchemaForEndpoint('/governance/dreps/{drep_id}/updates'),

handler: async (request: FastifyRequest<QueryTypes.RequestParametersDRepID>, reply) => {
let drepHex;
let drepValidation;

try {
drepHex = drepIdToRaw(request.params.drep_id);
drepValidation = validateDRepId(request.params.drep_id);
} catch {
return handle400Custom(reply, 'Invalid or malformed drep id.');
}
Expand All @@ -30,11 +30,17 @@ async function route(fastify: FastifyInstance) {
const { rows }: { rows: ResponseTypes.DRepsDrepIDUpdates } = unpaged
? await clientDbSync.query<QueryTypes.DRepsDrepIDUpdates>(
SQLQuery.get('governance_dreps_drep_id_updates_unpaged'),
[request.query.order, request.params.drep_id],
[request.query.order, drepValidation.raw, drepValidation.id],
)
: await clientDbSync.query<QueryTypes.DRepsDrepIDUpdates>(
SQLQuery.get('governance_dreps_drep_id_updates'),
[request.query.order, request.query.count, request.query.page, drepHex],
[
request.query.order,
request.query.count,
request.query.page,
drepValidation.raw,
drepValidation.id,
],
);

clientDbSync.release();
Expand Down
16 changes: 11 additions & 5 deletions src/routes/governance/dreps/drep-id/votes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { SQLQuery } from '../../../../sql/index.js';
import { getSchemaForEndpoint } from '@blockfrost/openapi';
import { isUnpaged } from '../../../../utils/routes.js';
import { handle400Custom } from '@blockfrost/blockfrost-utils/lib/fastify.js';
import { drepIdToRaw } from '../../../../utils/bech32.js';
import { validateDRepId } from '../../../../utils/validation.js';

async function route(fastify: FastifyInstance) {
fastify.route({
Expand All @@ -15,10 +15,10 @@ async function route(fastify: FastifyInstance) {
schema: getSchemaForEndpoint('/governance/dreps/{drep_id}/votes'),

handler: async (request: FastifyRequest<QueryTypes.RequestParametersDRepID>, reply) => {
let drepHex;
let drepValidation;

try {
drepHex = drepIdToRaw(request.params.drep_id);
drepValidation = validateDRepId(request.params.drep_id);
} catch {
return handle400Custom(reply, 'Invalid or malformed drep id.');
}
Expand All @@ -30,11 +30,17 @@ async function route(fastify: FastifyInstance) {
const { rows }: { rows: ResponseTypes.DRepsDrepIDUpdates } = unpaged
? await clientDbSync.query<QueryTypes.DRepsDrepIDUpdates>(
SQLQuery.get('governance_dreps_drep_id_votes_unpaged'),
[request.query.order, request.params.drep_id],
[request.query.order, drepValidation.raw, drepValidation.id],
)
: await clientDbSync.query<QueryTypes.DRepsDrepIDUpdates>(
SQLQuery.get('governance_dreps_drep_id_votes'),
[request.query.order, request.query.count, request.query.page, drepHex],
[
request.query.order,
request.query.count,
request.query.page,
drepValidation.raw,
drepValidation.id,
],
);

clientDbSync.release();
Expand Down
7 changes: 6 additions & 1 deletion src/sql/governance/dreps_drep_id.sql
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ FROM drep_hash dh
FROM queried_epoch
)
)
WHERE dh.raw = $1
WHERE (
CASE
WHEN $1::bytea IS NOT NULL THEN dh.raw = $1::bytea
ELSE dh.view = $2::text
END
)
ORDER BY (tx_id, cert_index) DESC
LIMIT 1
5 changes: 4 additions & 1 deletion src/sql/governance/dreps_drep_id_delegators.sql
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ FROM (
FROM delegation_vote dv
JOIN drep_hash dh ON (dh.id = dv.drep_hash_id)
JOIN stake_address sa ON (sa.id = dv.addr_id)
WHERE dh.raw = $4
WHERE (
($4 IS NOT NULL AND dh.raw = $4::bytea) OR
($4 IS NULL AND dh.view = $5)
)
AND dv.id = (
SELECT MAX(id)
FROM delegation_vote
Expand Down
5 changes: 4 additions & 1 deletion src/sql/governance/dreps_drep_id_metadata.sql
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ FROM drep_hash dh
JOIN drep_registration dr ON (dh.id = dr.drep_hash_id)
JOIN voting_anchor va ON (dr.voting_anchor_id = va.id)
JOIN off_chain_vote_data ocvd ON (ocvd.voting_anchor_id = va.id)
WHERE dh.raw = $1
WHERE (
($1 IS NOT NULL AND dh.raw = $1::bytea) OR
($1 IS NULL AND dh.view = $2)
)
ORDER BY (dr.tx_id, dr.cert_index) DESC
LIMIT 1
5 changes: 4 additions & 1 deletion src/sql/governance/dreps_drep_id_updates.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ SELECT encode(tx.hash, 'hex') AS "tx_hash",
FROM drep_hash dh
JOIN drep_registration dr ON (dh.id = dr.drep_hash_id)
JOIN tx ON (dr.tx_id = tx.id)
WHERE dh.raw = $4
WHERE (
($4 IS NOT NULL AND dh.raw = $4::bytea) OR
($4 IS NULL AND dh.view = $5)
)
ORDER BY CASE
WHEN LOWER($1) = 'desc' THEN dr.id
END DESC,
Expand Down
5 changes: 4 additions & 1 deletion src/sql/governance/dreps_drep_id_votes.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ SELECT encode(tx.hash, 'hex') AS "tx_hash",
FROM voting_procedure vp
JOIN drep_hash dh ON (vp.drep_voter = dh.id)
JOIN tx ON (vp.tx_id = tx.id)
WHERE dh.raw = $4
WHERE (
($4 IS NOT NULL AND dh.raw = $4::bytea) OR
($4 IS NULL AND dh.view = $5)
)
ORDER BY CASE
WHEN LOWER($1) = 'desc' THEN vp.id
END DESC,
Expand Down
5 changes: 4 additions & 1 deletion src/sql/governance/unpaged/dreps_drep_id_delegators.sql
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ FROM (
FROM delegation_vote dv
JOIN drep_hash dh ON (dh.id = dv.drep_hash_id)
JOIN stake_address sa ON (sa.id = dv.addr_id)
WHERE dh.view = $2
WHERE (
($2 IS NOT NULL AND dh.raw = $2::bytea) OR
($2 IS NULL AND dh.view = $3)
)
AND dv.id = (
SELECT MAX(id)
FROM delegation_vote
Expand Down
5 changes: 4 additions & 1 deletion src/sql/governance/unpaged/dreps_drep_id_updates.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ SELECT encode(tx.hash, 'hex') AS "tx_hash",
FROM drep_hash dh
JOIN drep_registration dr ON (dh.id = dr.drep_hash_id)
JOIN tx ON (dr.tx_id = tx.id)
WHERE dh.view = $2
WHERE (
($2 IS NOT NULL AND dh.raw = $2::bytea) OR
($2 IS NULL AND dh.view = $3)
)
ORDER BY CASE
WHEN LOWER($1) = 'desc' THEN dr.id
END DESC,
Expand Down
5 changes: 4 additions & 1 deletion src/sql/governance/unpaged/dreps_drep_id_votes.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ SELECT encode(tx.hash, 'hex') AS "tx_hash",
FROM voting_procedure vp
JOIN drep_hash dh ON (vp.drep_voter = dh.id)
JOIN tx ON (vp.tx_id = tx.id)
WHERE dh.view = $2
WHERE (
($2 IS NOT NULL AND dh.raw = $3::bytea) OR
($2 IS NULL AND dh.view = $3)
)
ORDER BY CASE
WHEN LOWER($1) = 'desc' THEN vp.id
END DESC,
Expand Down
14 changes: 0 additions & 14 deletions src/utils/bech32.ts

This file was deleted.

40 changes: 40 additions & 0 deletions src/utils/validation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { validation } from '@blockfrost/blockfrost-utils';
import { getConfig } from '../config.js';
import { bech32 } from 'bech32';

export const isNumber = validation.isNumber;
export const validateHex = validation.validateHex;
Expand Down Expand Up @@ -31,3 +32,42 @@ export const isTestnet = (): boolean => {

return network === 'mainnet' ? false : true;
};

/**
* Validates a DRep ID and returns both the ID and its raw format if applicable.
*
* @param {string} bechDrepId - The DRep ID in Bech32 format that needs to be validated.
* @returns {{ id: string, raw: string | null }} - An object containing the validated ID and its raw form.
* - `id`: The original DRep ID.
* - `raw`: The raw format of the DRep ID in hexadecimal if applicable, or `null` for special cases ()drep_always_abstain, drep_always_no_confidence).
*
* @throws {Error} If the DRep ID prefix is invalid, an error is thrown.
*/
export const validateDRepId = (
bechDrepId: string,
): {
id: string;
raw: string | null;
} => {
const SPECIAL_DREP_IDS = ['drep_always_abstain', 'drep_always_no_confidence'];

if (SPECIAL_DREP_IDS.includes(bechDrepId)) {
return {
id: bechDrepId,
raw: null,
};
}
const { prefix, words } = bech32.decode(bechDrepId);

if (prefix !== 'drep' && prefix !== 'drep_script') {
throw new Error('Invalid drep id prefix');
}

const hashBuf = Buffer.from(bech32.fromWords(words));
const drepIdRaw = `\\x${Buffer.from(hashBuf).toString('hex')}`;

return {
id: bechDrepId,
raw: drepIdRaw,
};
};
25 changes: 0 additions & 25 deletions test/unit/tests/utils/bech32.ts

This file was deleted.

Loading

0 comments on commit d5c2b55

Please sign in to comment.