Skip to content

Commit 3feb62d

Browse files
feat: make changes to DB + router (#11)
- add index with unique contraint - updated ApplicationEntity to have alloPoolId instead of poolId - updated Pool Entity to have customDistribution - add POST/ set-custom-distribution
1 parent 3de4355 commit 3feb62d

12 files changed

+278
-31
lines changed

src/controllers/applicationController.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@ export const createApplication = async (
6161
// Create application
6262
const [error, application] = await catchError(
6363
applicationService.createApplication({
64+
alloPoolId,
6465
chainId,
6566
alloApplicationId,
6667
pool,
67-
poolId: pool.id,
6868
})
6969
);
7070

src/controllers/poolController.ts

+87-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
import type { Request, Response } from 'express';
22
import poolService from '@/service/PoolService';
33
import applicationService from '@/service/ApplicationService';
4-
import { catchError, validateRequest } from '@/utils';
4+
import {
5+
catchError,
6+
isPoolFinalised,
7+
isPoolManager,
8+
validateRequest,
9+
} from '@/utils';
510
import { createLogger } from '@/logger';
611
import {
712
indexerClient,
813
type RoundWithApplications as IndexerRoundWithApplications,
914
} from '@/ext/indexer';
1015

1116
import {
17+
ActionNotAllowedError,
1218
BadRequestError,
1319
IsNullError,
1420
NotFoundError,
@@ -18,6 +24,8 @@ import { EligibilityType } from '@/entity/EligibilityCriteria';
1824
import { calculate } from '@/utils/calculate';
1925
import eligibilityCriteriaService from '@/service/EligibilityCriteriaService';
2026
import { type PoolIdChainId } from './types';
27+
import { type Distribution } from '@/entity/Pool';
28+
import { type Hex } from 'viem';
2129

2230
const logger = createLogger();
2331

@@ -32,6 +40,12 @@ interface EligibilityCriteriaRequest extends PoolIdChainId {
3240
data: object;
3341
}
3442

43+
interface SetCustomDistributionRequest extends PoolIdChainId {
44+
signature: Hex;
45+
sender: Hex;
46+
distribution: Distribution[];
47+
}
48+
3549
/**
3650
* Creates a pool
3751
*
@@ -237,3 +251,75 @@ export const updateEligibilityCriteria = async (req, res): Promise<void> => {
237251
message: 'Eligibility criteria updated successfully',
238252
});
239253
};
254+
255+
export const setCustomDistribution = async (req, res): Promise<void> => {
256+
const { alloPoolId, chainId, distribution, signature } =
257+
req.body as SetCustomDistributionRequest;
258+
259+
if (
260+
!(await isPoolManager(
261+
{ alloPoolId, chainId },
262+
signature,
263+
chainId,
264+
alloPoolId
265+
))
266+
) {
267+
res.status(401).json({ message: 'Not Authorzied' });
268+
throw new BadRequestError('Not Authorzied');
269+
}
270+
271+
if (await isPoolFinalised(alloPoolId, chainId)) {
272+
res.status(400).json({ message: 'Pool is finalised' });
273+
throw new ActionNotAllowedError('Pool is finalised');
274+
}
275+
276+
const [error] = await catchError(
277+
poolService.updateCustomDistribution(alloPoolId, chainId, distribution)
278+
);
279+
280+
if (error !== undefined) {
281+
res.status(500).json({
282+
message: 'Error setting custom distribution',
283+
error: error?.message,
284+
});
285+
throw new ServerError(`Error setting custom distribution`);
286+
}
287+
288+
res.status(201).json({ message: 'Custom distribution set successfully' });
289+
};
290+
291+
export const deleteCustomDistribution = async (req, res): Promise<void> => {
292+
const { alloPoolId, chainId, signature } =
293+
req.body as SetCustomDistributionRequest;
294+
295+
if (
296+
!(await isPoolManager(
297+
{ alloPoolId, chainId },
298+
signature,
299+
chainId,
300+
alloPoolId
301+
))
302+
) {
303+
res.status(401).json({ message: 'Not Authorzied' });
304+
throw new BadRequestError('Not Authorzied');
305+
}
306+
307+
if (await isPoolFinalised(alloPoolId, chainId)) {
308+
res.status(400).json({ message: 'Pool is finalised' });
309+
throw new ActionNotAllowedError('Pool is finalised');
310+
}
311+
312+
const [error] = await catchError(
313+
poolService.deleteCustomDistribution(alloPoolId, chainId)
314+
);
315+
316+
if (error !== undefined) {
317+
res.status(500).json({
318+
message: 'Error deleting custom distribution',
319+
error: error?.message,
320+
});
321+
throw new ServerError(`Error deleting custom distribution`);
322+
}
323+
324+
res.status(200).json({ message: 'Custom distribution deleted successfully' });
325+
};

src/entity/Application.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,27 @@ import {
33
Column,
44
Entity,
55
ManyToOne,
6-
Unique,
6+
Index,
77
} from 'typeorm';
88
import { Pool } from '@/entity/Pool';
99

1010
@Entity()
11-
@Unique(['alloApplicationId', 'poolId'])
11+
@Index(['alloPoolId', 'chainId', 'alloApplicationId'], { unique: true })
1212
export class Application {
1313
@PrimaryGeneratedColumn()
1414
id: number;
1515

1616
@Column()
1717
chainId: number;
1818

19+
@Column()
20+
alloPoolId: string;
21+
1922
@Column()
2023
alloApplicationId: string;
2124

2225
@ManyToOne(() => Pool, pool => pool.applications, {
2326
onDelete: 'CASCADE',
2427
})
2528
pool: Pool;
26-
27-
@Column() // Explicitly define the foreign key column for pool
28-
poolId: number;
2929
}

src/entity/EligibilityCriteria.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import { Entity, PrimaryGeneratedColumn, Column, Unique } from 'typeorm';
1+
import { Entity, PrimaryGeneratedColumn, Column, Index } from 'typeorm';
22

33
export enum EligibilityType {
44
Linear = 'linear',
55
// Weighted = 'weighted',
66
}
77

88
@Entity()
9-
@Unique(['chainId', 'alloPoolId'])
9+
@Index(['chainId', 'alloPoolId'], { unique: true })
1010
export class EligibilityCriteria {
1111
@PrimaryGeneratedColumn()
1212
id: number;

src/entity/Pool.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import {
33
Column,
44
Entity,
55
OneToMany,
6-
Unique,
76
OneToOne,
87
JoinColumn,
8+
Index,
99
} from 'typeorm';
1010
import { Application } from '@/entity/Application';
1111
import { EligibilityCriteria } from './EligibilityCriteria';
@@ -22,7 +22,7 @@ export interface Distribution {
2222
}
2323

2424
@Entity()
25-
@Unique(['chainId', 'alloPoolId'])
25+
@Index(['chainId', 'alloPoolId'], { unique: true })
2626
export class Pool {
2727
@PrimaryGeneratedColumn()
2828
id: number;
@@ -47,5 +47,8 @@ export class Pool {
4747
votes: Vote[];
4848

4949
@Column('simple-json', { nullable: true })
50-
distributionData: DistributionData;
50+
distributionData: DistributionData | null;
51+
52+
@Column('simple-json', { nullable: true })
53+
customDistributionData: DistributionData | null;
5154
}

src/entity/Vote.ts

+6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import {
22
Column,
33
Entity,
4+
Index,
45
ManyToOne,
56
PrimaryGeneratedColumn,
67
Unique,
8+
UpdateDateColumn,
79
} from 'typeorm';
810
import { Pool } from './Pool';
911

@@ -14,6 +16,7 @@ export interface Ballot {
1416

1517
@Entity()
1618
@Unique(['poolId', 'voter'])
19+
@Index(['alloPoolId', 'chainId', 'voter'], { unique: true })
1720
export class Vote {
1821
@PrimaryGeneratedColumn()
1922
id: number;
@@ -35,4 +38,7 @@ export class Vote {
3538

3639
@Column() // Explicitly define the foreign key column for pool
3740
poolId: number;
41+
42+
@UpdateDateColumn()
43+
updatedAt: Date;
3844
}

src/migration/1737626955612-InitMigration.ts src/migration/1738605183828-InitMigration.ts

+17-9
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,39 @@
11
import { type MigrationInterface, type QueryRunner } from "typeorm";
22

3-
export class InitMigration1737626955612 implements MigrationInterface {
4-
name = 'InitMigration1737626955612'
3+
export class InitMigration1738605183828 implements MigrationInterface {
4+
name = 'InitMigration1738605183828'
55

66
public async up(queryRunner: QueryRunner): Promise<void> {
7-
await queryRunner.query(`CREATE TABLE "application" ("id" SERIAL NOT NULL, "chainId" integer NOT NULL, "alloApplicationId" character varying NOT NULL, "poolId" integer NOT NULL, CONSTRAINT "UQ_8849159f2a2681f6be67ef84efb" UNIQUE ("alloApplicationId", "poolId"), CONSTRAINT "PK_569e0c3e863ebdf5f2408ee1670" PRIMARY KEY ("id"))`);
7+
await queryRunner.query(`CREATE TABLE "application" ("id" SERIAL NOT NULL, "chainId" integer NOT NULL, "alloPoolId" character varying NOT NULL, "alloApplicationId" character varying NOT NULL, "poolId" integer, CONSTRAINT "PK_569e0c3e863ebdf5f2408ee1670" PRIMARY KEY ("id"))`);
8+
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_32767cacf4bb8819b2c51e854e" ON "application" ("alloPoolId", "chainId", "alloApplicationId") `);
89
await queryRunner.query(`CREATE TYPE "public"."eligibility_criteria_eligibilitytype_enum" AS ENUM('linear')`);
9-
await queryRunner.query(`CREATE TABLE "eligibility_criteria" ("id" SERIAL NOT NULL, "chainId" integer NOT NULL, "alloPoolId" character varying NOT NULL, "eligibilityType" "public"."eligibility_criteria_eligibilitytype_enum" NOT NULL, "data" json NOT NULL, CONSTRAINT "UQ_cab3614863337cf5dba521b9b84" UNIQUE ("chainId", "alloPoolId"), CONSTRAINT "PK_231ea7a8a87bb6092eb3af1c5a8" PRIMARY KEY ("id"))`);
10-
await queryRunner.query(`CREATE TABLE "vote" ("id" SERIAL NOT NULL, "voter" character varying(42) NOT NULL, "alloPoolId" character varying NOT NULL, "chainId" integer NOT NULL, "ballot" text NOT NULL, "poolId" integer NOT NULL, CONSTRAINT "UQ_3940f20660f872bfe5386def7f1" UNIQUE ("poolId", "voter"), CONSTRAINT "PK_2d5932d46afe39c8176f9d4be72" PRIMARY KEY ("id"))`);
11-
await queryRunner.query(`CREATE TABLE "pool" ("id" SERIAL NOT NULL, "chainId" integer NOT NULL, "alloPoolId" character varying NOT NULL, "metricIdentifiers" text, "distributionData" text, "eligibilityCriteriaId" integer, CONSTRAINT "UQ_72fcaa655b2b7348f4feaf25ea3" UNIQUE ("chainId", "alloPoolId"), CONSTRAINT "REL_bb4a5f9f4367c3de6ccaf665cc" UNIQUE ("eligibilityCriteriaId"), CONSTRAINT "PK_db1bfe411e1516c01120b85f8fe" PRIMARY KEY ("id"))`);
10+
await queryRunner.query(`CREATE TABLE "eligibility_criteria" ("id" SERIAL NOT NULL, "chainId" integer NOT NULL, "alloPoolId" character varying NOT NULL, "eligibilityType" "public"."eligibility_criteria_eligibilitytype_enum" NOT NULL, "data" json NOT NULL, CONSTRAINT "PK_231ea7a8a87bb6092eb3af1c5a8" PRIMARY KEY ("id"))`);
11+
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_cab3614863337cf5dba521b9b8" ON "eligibility_criteria" ("chainId", "alloPoolId") `);
12+
await queryRunner.query(`CREATE TABLE "pool" ("id" SERIAL NOT NULL, "chainId" integer NOT NULL, "alloPoolId" character varying NOT NULL, "metricIdentifiers" text, "distributionData" text, "customDistributionData" text, "eligibilityCriteriaId" integer, CONSTRAINT "REL_bb4a5f9f4367c3de6ccaf665cc" UNIQUE ("eligibilityCriteriaId"), CONSTRAINT "PK_db1bfe411e1516c01120b85f8fe" PRIMARY KEY ("id"))`);
13+
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_72fcaa655b2b7348f4feaf25ea" ON "pool" ("chainId", "alloPoolId") `);
14+
await queryRunner.query(`CREATE TABLE "vote" ("id" SERIAL NOT NULL, "voter" character varying(42) NOT NULL, "alloPoolId" character varying NOT NULL, "chainId" integer NOT NULL, "ballot" text NOT NULL, "poolId" integer NOT NULL, "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "UQ_3940f20660f872bfe5386def7f1" UNIQUE ("poolId", "voter"), CONSTRAINT "PK_2d5932d46afe39c8176f9d4be72" PRIMARY KEY ("id"))`);
15+
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_4f0abff01b2f41e22cf23a215a" ON "vote" ("alloPoolId", "chainId", "voter") `);
1216
await queryRunner.query(`CREATE TYPE "public"."metric_orientation_enum" AS ENUM('increase', 'decrease')`);
1317
await queryRunner.query(`CREATE TABLE "metric" ("id" SERIAL NOT NULL, "identifier" character varying NOT NULL, "title" character varying NOT NULL, "description" character varying NOT NULL, "orientation" "public"."metric_orientation_enum" NOT NULL, "enabled" boolean NOT NULL DEFAULT false, CONSTRAINT "UQ_1136bb423acf02b4e7e5c909d0c" UNIQUE ("identifier"), CONSTRAINT "PK_7d24c075ea2926dd32bd1c534ce" PRIMARY KEY ("id"))`);
1418
await queryRunner.query(`ALTER TABLE "application" ADD CONSTRAINT "FK_a2d1c7a2c6ee681b42112d41284" FOREIGN KEY ("poolId") REFERENCES "pool"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
15-
await queryRunner.query(`ALTER TABLE "vote" ADD CONSTRAINT "FK_86b9c0ae3057aa451170728b2bb" FOREIGN KEY ("poolId") REFERENCES "pool"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
1619
await queryRunner.query(`ALTER TABLE "pool" ADD CONSTRAINT "FK_bb4a5f9f4367c3de6ccaf665cc2" FOREIGN KEY ("eligibilityCriteriaId") REFERENCES "eligibility_criteria"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
20+
await queryRunner.query(`ALTER TABLE "vote" ADD CONSTRAINT "FK_86b9c0ae3057aa451170728b2bb" FOREIGN KEY ("poolId") REFERENCES "pool"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`);
1721
}
1822

1923
public async down(queryRunner: QueryRunner): Promise<void> {
20-
await queryRunner.query(`ALTER TABLE "pool" DROP CONSTRAINT "FK_bb4a5f9f4367c3de6ccaf665cc2"`);
2124
await queryRunner.query(`ALTER TABLE "vote" DROP CONSTRAINT "FK_86b9c0ae3057aa451170728b2bb"`);
25+
await queryRunner.query(`ALTER TABLE "pool" DROP CONSTRAINT "FK_bb4a5f9f4367c3de6ccaf665cc2"`);
2226
await queryRunner.query(`ALTER TABLE "application" DROP CONSTRAINT "FK_a2d1c7a2c6ee681b42112d41284"`);
2327
await queryRunner.query(`DROP TABLE "metric"`);
2428
await queryRunner.query(`DROP TYPE "public"."metric_orientation_enum"`);
25-
await queryRunner.query(`DROP TABLE "pool"`);
29+
await queryRunner.query(`DROP INDEX "public"."IDX_4f0abff01b2f41e22cf23a215a"`);
2630
await queryRunner.query(`DROP TABLE "vote"`);
31+
await queryRunner.query(`DROP INDEX "public"."IDX_72fcaa655b2b7348f4feaf25ea"`);
32+
await queryRunner.query(`DROP TABLE "pool"`);
33+
await queryRunner.query(`DROP INDEX "public"."IDX_cab3614863337cf5dba521b9b8"`);
2734
await queryRunner.query(`DROP TABLE "eligibility_criteria"`);
2835
await queryRunner.query(`DROP TYPE "public"."eligibility_criteria_eligibilitytype_enum"`);
36+
await queryRunner.query(`DROP INDEX "public"."IDX_32767cacf4bb8819b2c51e854e"`);
2937
await queryRunner.query(`DROP TABLE "application"`);
3038
}
3139

src/routes/applicationRoutes.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const router = Router();
1919
* alloPoolId:
2020
* type: string
2121
* description: The ID of the pool to link the application to
22-
* example: "615" # Example of poolId
22+
* example: "673" # Example of poolId
2323
* chainId:
2424
* type: number
2525
* description: The chain ID associated with the pool

0 commit comments

Comments
 (0)