Skip to content

Commit 1ad6f85

Browse files
committed
fix: backend & abi migration
1 parent 86329a5 commit 1ad6f85

File tree

8 files changed

+88
-40
lines changed

8 files changed

+88
-40
lines changed

Makefile

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,29 @@ test:
4646

4747
# Run Slither static analysis
4848
slither-check:
49-
slither .
49+
slither ./src
5050

5151
# Export TaskManager ABI to backend/src/listener/abi
5252
export-task-manager-abi:
53-
forge inspect src/TaskManager.sol:TaskManager abi --json > backend/src/listener/abi/TaskManagerAbi.json
53+
forge inspect src/TaskManager.sol:TaskManager abi --json > ./abi/TaskManagerAbi.json
5454

5555
# Initialize the task_board_db database (database has to be created!)
5656
init-db:
5757
psql -h localhost -U app -d task_board_db -p 5432 -a -f ./backend/src/db/init_db.sql
5858

5959
# Delete tables from task_board_db database
6060
delete-db:
61-
psql -h localhost -U app -d task_board_db -p 5432 -a -f ./backend/src/db/delete_db.sql
61+
psql -h localhost -U app -d task_board_db -p 5432 -a -f ./backend/src/db/delete_db.sql
62+
63+
64+
local-be-test:
65+
make delete_db
66+
make init_db
67+
make deploy-local
68+
make add-creator-local
69+
add-task-local
70+
add-task-local
71+
add-task-local
72+
add-task-local
73+
add-task-local
74+
add-task-local

backend/src/listener/abi/TaskManagerAbi.json renamed to abi/TaskManagerAbi.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,13 @@
185185
{
186186
"name": "name",
187187
"type": "string",
188-
"indexed": true,
188+
"indexed": false,
189189
"internalType": "string"
190190
},
191191
{
192192
"name": "difficulty",
193193
"type": "string",
194-
"indexed": true,
194+
"indexed": false,
195195
"internalType": "string"
196196
},
197197
{

backend/src/app.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ async function buildApp() {
3636

3737
// Start smart contract event listener
3838
const el = new EventListener(db)
39-
el.startListener().catch(err => {
39+
el.startListener().catch(err => {
4040
app.log.error(err)
4141
})
4242

backend/src/controllers/taskController.ts

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* @author Michal Ľaš
77
*/
88

9-
import { type FastifyReply, type FastifyRequest } from 'fastify';
9+
import { type FastifyReply, type FastifyRequest } from 'fastify'
1010
import { type Static } from '@sinclair/typebox'
1111
import { TokenMetadataSchema } from '../schemas/taskSchema.ts'
1212
import TaskBoardIPFS from '../ipfs/TaskBoardIPFS.ts'
@@ -32,7 +32,10 @@ export function createTaskController(IPFS: TaskBoardIPFS) {
3232
}
3333

3434
export function getTasksController(IPFS: TaskBoardIPFS) {
35-
return async (request: FastifyRequest<{ Querystring: { limit?: number; offset?: number; difficulty?: string; name?: string } }>, reply: FastifyReply) => {
35+
return async (
36+
request: FastifyRequest<{ Querystring: { limit?: number; offset?: number; difficulty?: string; name?: string } }>,
37+
reply: FastifyReply
38+
) => {
3639
try {
3740
const { limit = 10, offset = 0, difficulty, name } = request.query
3841
const filters: any = {}
@@ -41,19 +44,22 @@ export function getTasksController(IPFS: TaskBoardIPFS) {
4144

4245
const tasks = await IPFS.getTasks(limit, offset, filters)
4346

44-
if (tasks.length === 0) {
45-
return reply.code(404).send({
46-
error: 'No tasks found',
47-
message: 'No tasks match the provided criteria.'
48-
})
49-
} else {
50-
reply.code(200).send(tasks.map(t => ({ ...t.toJSON(), createdAt: t.task.createdAt, ipfsCid: t.task.ipfsCid })))
51-
}
47+
const response = tasks.map((t) => ({
48+
...t.toJSON(),
49+
createdAt: t.task.createdAt,
50+
ipfsCid: t.task.ipfsCid,
51+
}))
52+
53+
return reply.code(200).send({
54+
tasks: response,
55+
nextOffset: tasks.length < limit ? undefined : offset + limit,
56+
})
5257
} catch (error) {
53-
reply.code(500).send({
58+
request.log.error(error)
59+
return reply.code(500).send({
5460
error: 'Failed to fetch tasks',
55-
message: 'Could not retrieve tasks. Please try again later.'
56-
})
61+
message: 'Could not retrieve tasks. Please try again later.',
62+
})
5763
}
5864
}
5965
}

backend/src/db/init_db.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ CREATE TABLE processed_blocks (
2020
id SERIAL PRIMARY KEY,
2121
last_processed_block BIGINT NOT NULL
2222
);
23+
24+
-- ensure one row exists
25+
INSERT INTO processed_blocks (last_processed_block) VALUES (0);

backend/src/listener/Listener.ts

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
import { ethers } from 'ethers';
1111
import dotenv from 'dotenv'
12-
import TaskManagerAbi from './abi/TaskManagerAbi.json' with {type: 'json'}; // compiled ABI
12+
import TaskManagerAbi from '../../../abi/TaskManagerAbi.json' with {type: 'json'}; // compiled ABI
1313
import Db from '../db/Db.js';
1414

1515
// Load env variables
@@ -95,15 +95,28 @@ private eventQueue: Map<number, { blockHash: string, handlers: (() => Promise<vo
9595
txHash: log.transactionHash,
9696
blockNumber: log.blockNumber
9797
})
98-
// Save to Postgres
99-
await this.db.saveTask({
100-
taskId: Number(taskId),
101-
name,
102-
difficulty,
103-
time: Number(time),
104-
uri: URI,
105-
txHash: log.transactionHash
106-
});
98+
// If log.blockNumber >= currentBlock - FINALITY_BLOCKS => Save to Postgres
99+
if ((log.blockNumber - this.FINALITY_BLOCKS) >= 0) {
100+
await this.db.saveTask({
101+
taskId: Number(taskId),
102+
name,
103+
difficulty,
104+
time: Number(time),
105+
uri: URI,
106+
txHash: log.transactionHash
107+
});
108+
} else { // Else add it to eventQueue
109+
this._queueEvent(log.blockNumber, log.blockHash, async () => {
110+
await this.db.saveTask({
111+
taskId: Number(taskId),
112+
name,
113+
difficulty,
114+
time: Number(time),
115+
uri: URI,
116+
txHash: log.transactionHash,
117+
});
118+
})
119+
}
107120
});
108121

109122
const filterDeactivated = this.contract.filters.TaskDeactivated!()
@@ -114,10 +127,16 @@ private eventQueue: Map<number, { blockHash: string, handlers: (() => Promise<vo
114127
taskId: taskId.toString(),
115128
txHash: log.transactionHash,
116129
})
117-
await this.db.deactivateTask(Number(taskId), log.transactionHash)
130+
if ((log.blockNumber - this.FINALITY_BLOCKS)) {
131+
await this.db.deactivateTask(Number(taskId), log.transactionHash)
132+
} else {
133+
this._queueEvent(log.blockNumber, log.blockHash, async () => {
134+
await this.db.deactivateTask(Number(taskId), log.transactionHash);
135+
});
136+
}
118137
})
119138

120-
await this.db.updateLastProcessedBlock(toBlock);
139+
await this.db.updateLastProcessedBlock(toBlock - this.FINALITY_BLOCKS);
121140
}
122141

123142
// Backfill past events from the deployed block to the latest block
@@ -126,7 +145,7 @@ private eventQueue: Map<number, { blockHash: string, handlers: (() => Promise<vo
126145
const currentBlock = await this.provider.getBlockNumber();
127146
let fromBlock = (await this.db.getLastProcessedBlock()) ?? this.START_BLOCK;
128147
if (fromBlock > currentBlock) fromBlock = currentBlock;
129-
await this._fetchPastEvents(fromBlock, currentBlock - this.FINALITY_BLOCKS);
148+
await this._fetchPastEvents(fromBlock, currentBlock);
130149
}
131150

132151
/// Adds emmited event into the processing queue - handler executes the action once after the blockNumber fill be considerd final

backend/src/routes/taskRoutes.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,20 @@ const taskRoutes: FastifyPluginAsync<{ ipfs: TaskBoardIPFS }> = async (app, opts
2222
limit: { type: 'integer', minimum: 1, maximum: 50 },
2323
offset: { type: 'integer', minimum: 0 },
2424
difficulty: { type: 'string' },
25-
name: { type: 'string' }
26-
}
25+
name: { type: 'string' },
26+
},
2727
},
2828
response: {
29-
200: { type: 'array', items: TokenMetadataSchema }
30-
}
29+
200: {
30+
type: 'object',
31+
properties: {
32+
tasks: { type: 'array', items: TokenMetadataSchema },
33+
nextOffset: { type: 'integer', nullable: true },
34+
},
35+
},
36+
},
3137
},
32-
handler: getTasksController(ipfs)
38+
handler: getTasksController(ipfs),
3339
})
3440

3541
app.post('/tasks', {

frontend/src/containers/TaskContainer.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@ type TasksResponse = {
1919
async function fetchTasks({ pageParam = 0, queryKey }: any) {
2020
const [_key, { search, difficulty }] = queryKey;
2121
const res = await fetch(
22-
`/api/tasks?search=${encodeURIComponent(search)}&difficulty=${difficulty}&offset=${pageParam}&limit=10`
22+
`/api/tasks?name=${encodeURIComponent(search)}&difficulty=${difficulty}&offset=${pageParam}&limit=10`
2323
);
24+
console.log("msg", res);
2425
if (!res.ok) throw new Error("Failed to fetch tasks");
25-
return res.json(); // expected: { tasks: TaskToken[], nextOffset?: number }
26+
return res.json(); // { tasks: [], nextOffset?: number }
2627
}
2728

28-
2929
function TaskContainer({ search, difficulty }: TaskContainerProps) {
3030
const [openTaskId, setOpenTaskId] = useState<string | null>(null);
3131
const { showLoading, hideLoading } = useLoadingScreen();
@@ -56,6 +56,7 @@ function TaskContainer({ search, difficulty }: TaskContainerProps) {
5656

5757
useEffect(() => {
5858
if (error) {
59+
console.error(`Error: ${error.name} (${error.cause}): ${error.message}`);
5960
showAlert("error", "Could not fetch tasks.");
6061
}
6162
}, [error, showAlert]);

0 commit comments

Comments
 (0)