Skip to content

Commit 79bdf09

Browse files
IDubuquefarhanW3
andauthored
Feature: Contract Events (#431)
* added table schema * add trigger for new indexed contracts * delete migrations * update schema * add migration for indexer tables * add migration for indexer triggers * adding db util functions * adding indexer routes * remove indexer trigger migration * update db contract log getter * add getLogs route * save contract indexer listener * add indexer listener cron schedule * adding indexer config * updating the db layer * updating routes * updating prisma schema * updating indexer worker * add failure message * estimate blocktime, add route * cleanup * remove relations and fk constraints * remove fk constraints migration * removing get logs endpoint * update indexer * remove test routes * cleaning up migration history * add contract indexer migration * fix for edge case * redo the migration and update schema * table rename * updating naming to events and subscriptions * fix import * automatically delete logs on subscribe * add logging * use lowercase contract address * adding error handling * all log values toString * adding new getContractLogs route * adding event name to get logs response * remove export, this feels dirty imo * lint fix * add deletedAt to contract subscriptions * add update endpoints * add contract log indexes * add default max blocks to index * remove logs * added query limits * remove debug log * remove performance logging * remove debug log * fix lint * move chain indexer * clean migration history * minor fix * use unon insted of prevalidation handler * added default indexer schedule * fix block time error * minor fix * fixing subscribe / unsubscribe bug with deletedAt * minor fix: update contractSubscrition query with id * adding base64 package * updating schema * adding pagination endpoint * clean up migrations * add comment * minor fix: duplicate indexed transactions * fixing chainIndexer * add last block indexed * Feature/contract tx indexer (#446) * update docs * add ContractTransactionReceipts data model * helper for contractId * update ContractTransactionReceipts with create / update time * crud db apis for ContractTransactionReceipts * adding examples for docs * lowercase all str fields * reorg contract subscriptions * remove console.logs * add transactionReceiptSchema * update db apis * add routes for getting tx receipts * update imports for routes * add Contract Transaction routes * update prisma model with transaction value and receipt * update transaction value and receipt * delete transaction receipts on unsubscribe * add migration for transaction receipts * update endpoint * update endpoints * add value / data to transaction receipt response * transaction status bug fix * cleanup * parallelize transaction receipts and event logs * remove log * bug fix: transaction receipt timestamp * variable max blocks to index * parallelize block receipts + perf logging * update blocks to estimate 100 and parallelize * Added chainIndexerListener to restart on config DB changes * remove perf logs * adding decode failed warning back in --------- Co-authored-by: farhanW3 <farhan@thirdweb.com>
1 parent c8521f9 commit 79bdf09

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2814
-1
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
"@thirdweb-dev/sdk": "^4.0.46-nightly-3e7f9cb94-20240314012159",
4747
"@thirdweb-dev/service-utils": "0.4.17",
4848
"@thirdweb-dev/wallets": "^2.1.5",
49+
"@types/base-64": "^1.0.2",
50+
"base-64": "^1.0.0",
4951
"body-parser": "^1.20.2",
5052
"cookie": "^0.5.0",
5153
"cookie-parser": "^1.4.6",
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { PrismaTransaction } from "../../schema/prisma";
2+
import { getPrismaWithPostgresTx } from "../client";
3+
4+
interface GetLastIndexedBlockParams {
5+
chainId: number;
6+
pgtx?: PrismaTransaction;
7+
}
8+
9+
export const getLastIndexedBlock = async ({
10+
chainId,
11+
pgtx,
12+
}: GetLastIndexedBlockParams) => {
13+
const prisma = getPrismaWithPostgresTx(pgtx);
14+
15+
const indexedChain = await prisma.chainIndexers.findUnique({
16+
where: {
17+
chainId,
18+
},
19+
});
20+
21+
if (indexedChain) {
22+
return indexedChain.lastIndexedBlock;
23+
}
24+
};
25+
26+
interface GetBlockForIndexingParams {
27+
chainId: number;
28+
pgtx?: PrismaTransaction;
29+
}
30+
31+
export const getBlockForIndexing = async ({
32+
chainId,
33+
pgtx,
34+
}: GetBlockForIndexingParams) => {
35+
const prisma = getPrismaWithPostgresTx(pgtx);
36+
37+
const lastIndexedBlock = await prisma.$queryRaw<
38+
{ lastIndexedBlock: number }[]
39+
>`
40+
SELECT
41+
"lastIndexedBlock"
42+
FROM
43+
"chain_indexers"
44+
WHERE
45+
"chainId"=${chainId}
46+
FOR UPDATE NOWAIT
47+
`;
48+
return lastIndexedBlock[0]["lastIndexedBlock"];
49+
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { PrismaTransaction } from "../../schema/prisma";
2+
import { getPrismaWithPostgresTx } from "../client";
3+
4+
interface UpsertChainIndexerParams {
5+
chainId: number;
6+
currentBlockNumber: number;
7+
pgtx?: PrismaTransaction;
8+
}
9+
10+
export const upsertChainIndexer = async ({
11+
chainId,
12+
currentBlockNumber,
13+
pgtx,
14+
}: UpsertChainIndexerParams) => {
15+
const prisma = getPrismaWithPostgresTx(pgtx);
16+
return prisma.chainIndexers.upsert({
17+
where: {
18+
chainId,
19+
},
20+
update: {
21+
chainId,
22+
lastIndexedBlock: currentBlockNumber,
23+
},
24+
create: {
25+
chainId,
26+
lastIndexedBlock: currentBlockNumber,
27+
},
28+
});
29+
};

src/db/configuration/getConfiguration.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ export const getConfiguration = async (): Promise<Config> => {
179179
minedTxListenerCronSchedule: "*/5 * * * * *",
180180
maxTxsToUpdate: 50,
181181
retryTxListenerCronSchedule: "*/15 * * * * *",
182+
indexerListenerCronSchedule: "*/5 * * * * *",
183+
maxBlocksToIndex: 25,
184+
cursorDelaySeconds: 2,
182185
minEllapsedBlocksBeforeRetry: 12,
183186
maxFeePerGasForRetries: ethers.utils
184187
.parseUnits("10000", "gwei")
@@ -205,6 +208,10 @@ export const getConfiguration = async (): Promise<Config> => {
205208
config = await updateConfiguration({
206209
accessControlAllowOrigin: mandatoryAllowedCorsUrls.join(","),
207210
});
211+
} else if (!config.indexerListenerCronSchedule) {
212+
config = await updateConfiguration({
213+
indexerListenerCronSchedule: "*/5 * * * * *",
214+
});
208215
}
209216

210217
return withWalletConfig(config);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { PrismaTransaction } from "../../schema/prisma";
2+
import { getPrismaWithPostgresTx } from "../client";
3+
4+
interface ContractEventLogEntry {
5+
chainId: number;
6+
blockNumber: number;
7+
contractAddress: string;
8+
transactionHash: string;
9+
topic0?: string;
10+
topic1?: string;
11+
topic2?: string;
12+
topic3?: string;
13+
data: string;
14+
decodedLog?: any; // Assuming JSON object for decodedLog
15+
eventName?: string;
16+
timestamp: Date;
17+
transactionIndex: number;
18+
logIndex: number;
19+
}
20+
21+
export interface BulkInsertContractLogsParams {
22+
pgtx?: PrismaTransaction;
23+
logs: ContractEventLogEntry[];
24+
}
25+
26+
export const bulkInsertContractEventLogs = async ({
27+
pgtx,
28+
logs,
29+
}: BulkInsertContractLogsParams) => {
30+
const prisma = getPrismaWithPostgresTx(pgtx);
31+
return await prisma.contractEventLogs.createMany({
32+
data: logs,
33+
skipDuplicates: true,
34+
});
35+
};
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { prisma } from "../client";
2+
3+
interface DeleteContractEventLogsParams {
4+
chainId: number;
5+
contractAddress: string;
6+
}
7+
8+
export const deleteContractEventLogs = async ({
9+
chainId,
10+
contractAddress,
11+
}: DeleteContractEventLogsParams) => {
12+
return prisma.contractEventLogs.deleteMany({
13+
where: {
14+
chainId,
15+
contractAddress,
16+
},
17+
});
18+
};

0 commit comments

Comments
 (0)