Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: retrieving data for special dreps drep_always_abstain and `dre… #210

Merged
merged 1 commit into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
2 changes: 1 addition & 1 deletion default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pkgs ? import nixpkgs {}
, blockfrost-tests ?
(builtins.fetchGit {
url = "ssh://git@github.com/blockfrost/blockfrost-tests.git";
rev = "3b7ca46b6528cfa8a64585b28dda2cee682707aa";
rev = "3f750379f3431a07bd4d802879043429108dfab2";
allRefs = true;
})
, system ? builtins.currentSystem
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
5 changes: 4 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,9 @@ FROM drep_hash dh
FROM queried_epoch
)
)
WHERE dh.raw = $1
WHERE (
($1::bytea IS NOT NULL AND dh.raw = $1) OR
($1 IS NULL AND dh.view = $2)
)
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::bytea IS NOT NULL AND dh.raw = $4) 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::bytea IS NOT NULL AND dh.raw = $1) 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::bytea IS NOT NULL AND dh.raw = $4) 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::bytea IS NOT NULL AND dh.raw = $4) 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::bytea IS NOT NULL AND dh.raw = $2) 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::bytea IS NOT NULL AND dh.raw = $2) 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::bytea IS NOT NULL AND dh.raw = $2) 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
Loading