diff --git a/package-lock.json b/package-lock.json index 63894b3e..20bb69b8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2816,7 +2816,7 @@ }, "node_modules/chainsauce": { "version": "1.0.20", - "resolved": "git+ssh://git@github.com/gitcoinco/chainsauce.git#c9af5345ba7f40b7c3c857b329875a137ad34497", + "resolved": "git+ssh://git@github.com/gitcoinco/chainsauce.git#f40578663011a924d269626d14231d19aaa3d25c", "license": "MIT", "dependencies": { "@types/pg": "^8.10.9", @@ -10529,7 +10529,7 @@ } }, "chainsauce": { - "version": "git+ssh://git@github.com/gitcoinco/chainsauce.git#c9af5345ba7f40b7c3c857b329875a137ad34497", + "version": "git+ssh://git@github.com/gitcoinco/chainsauce.git#f40578663011a924d269626d14231d19aaa3d25c", "from": "chainsauce@github:gitcoinco/chainsauce#main", "requires": { "@types/pg": "^8.10.9", diff --git a/src/database/migrate.ts b/src/database/migrate.ts index 50679263..9f86d5c3 100644 --- a/src/database/migrate.ts +++ b/src/database/migrate.ts @@ -10,14 +10,25 @@ const PENDING_ROLE_TYPE = "text"; export async function migrate(db: Kysely, schemaName: string) { const ref = (name: string) => sql.table(`${schemaName}.${name}`); - const schema = db.withSchema(schemaName).schema; + const cacheSchema = db.withSchema("cache").schema; + const chainDataSchema = db.withSchema(schemaName).schema; - await schema + await db.schema.createSchema("cache").ifNotExists().execute(); + + await cacheSchema + .createTable("blocks") + .addColumn("chainId", CHAIN_ID_TYPE) + .addColumn("number", BIGINT_TYPE) + .addColumn("timestamp", "timestamptz") + .ifNotExists() + .execute(); + + await chainDataSchema .createType("project_type") .asEnum(["canonical", "linked"]) .execute(); - await schema + await chainDataSchema .createTable("projects") .addColumn("id", "text") .addColumn("name", "text") @@ -37,7 +48,7 @@ export async function migrate(db: Kysely, schemaName: string) { .addPrimaryKeyConstraint("projects_pkey", ["id", "chainId"]) .execute(); - await schema + await chainDataSchema .createTable("pending_project_roles") .addColumn("id", "serial", (col) => col.primaryKey()) .addColumn("chainId", CHAIN_ID_TYPE) @@ -46,12 +57,12 @@ export async function migrate(db: Kysely, schemaName: string) { .addColumn("createdAtBlock", BIGINT_TYPE) .execute(); - await schema + await chainDataSchema .createType("project_role_name") .asEnum(["owner", "member"]) .execute(); - await schema + await chainDataSchema .createTable("project_roles") .addColumn("chainId", CHAIN_ID_TYPE) .addColumn("projectId", "text") @@ -72,7 +83,7 @@ export async function migrate(db: Kysely, schemaName: string) { ) .execute(); - await schema + await chainDataSchema .createTable("rounds") .addColumn("id", "text") .addColumn("chainId", CHAIN_ID_TYPE) @@ -130,19 +141,19 @@ export async function migrate(db: Kysely, schemaName: string) { .addPrimaryKeyConstraint("rounds_pkey", ["id", "chainId"]) .execute(); - await schema + await chainDataSchema .createIndex("idx_rounds_manager_role") .on("rounds") .columns(["managerRole"]) .execute(); - await schema + await chainDataSchema .createIndex("idx_rounds_admin_role") .on("rounds") .columns(["adminRole"]) .execute(); - await schema + await chainDataSchema .createTable("pending_round_roles") .addColumn("id", "serial", (col) => col.primaryKey()) .addColumn("chainId", CHAIN_ID_TYPE) @@ -151,12 +162,12 @@ export async function migrate(db: Kysely, schemaName: string) { .addColumn("createdAtBlock", BIGINT_TYPE) .execute(); - await schema + await chainDataSchema .createType("round_role_name") .asEnum(["admin", "manager"]) .execute(); - await schema + await chainDataSchema .createTable("round_roles") .addColumn("chainId", CHAIN_ID_TYPE) .addColumn("roundId", "text") @@ -177,12 +188,12 @@ export async function migrate(db: Kysely, schemaName: string) { ) .execute(); - await schema + await chainDataSchema .createType("application_status") .asEnum(["PENDING", "APPROVED", "REJECTED", "CANCELLED", "IN_REVIEW"]) .execute(); - await schema + await chainDataSchema .createTable("applications") .addColumn("id", "text") .addColumn("chainId", CHAIN_ID_TYPE) @@ -218,7 +229,7 @@ export async function migrate(db: Kysely, schemaName: string) { .execute(); - await schema + await chainDataSchema .createTable("applications_payouts") .addColumn("id", "serial", (col) => col.primaryKey()) .addColumn("chainId", CHAIN_ID_TYPE) @@ -238,7 +249,7 @@ export async function migrate(db: Kysely, schemaName: string) { ) .execute(); - await schema + await chainDataSchema .createTable("donations") .addColumn("id", "text") @@ -252,6 +263,8 @@ export async function migrate(db: Kysely, schemaName: string) { .addColumn("blockNumber", BIGINT_TYPE) .addColumn("tokenAddress", ADDRESS_TYPE) + .addColumn("timestamp", "timestamptz") + .addColumn("amount", BIGINT_TYPE) .addColumn("amountInUSD", "real") .addColumn("amountInRoundMatchToken", BIGINT_TYPE) @@ -260,25 +273,25 @@ export async function migrate(db: Kysely, schemaName: string) { .execute(); - await schema + await chainDataSchema .createIndex("idx_donations_donor_chain") .on("donations") .columns(["donorAddress"]) .execute(); - await schema + await chainDataSchema .createIndex("idx_donations_chain_round") .on("donations") .columns(["chainId", "roundId"]) .execute(); - await schema + await chainDataSchema .createIndex("idx_donations_chain_round_app") .on("donations") .columns(["chainId", "roundId", "applicationId"]) .execute(); - await schema + await chainDataSchema .createTable("prices") .addColumn("id", "serial", (cb) => cb.primaryKey()) .addColumn("chainId", CHAIN_ID_TYPE) @@ -294,7 +307,7 @@ export async function migrate(db: Kysely, schemaName: string) { .expression(sql`chain_id, token_address, block_number DESC`) .execute(); - await schema + await chainDataSchema .createTable("legacy_projects") .addColumn("id", "serial", (col) => col.primaryKey()) .addColumn("v1ProjectId", "text") diff --git a/src/database/schema.ts b/src/database/schema.ts index d78855fb..ef5a4ccd 100644 --- a/src/database/schema.ts +++ b/src/database/schema.ts @@ -209,6 +209,7 @@ export type DonationTable = { amount: bigint; amountInUsd: number; amountInRoundMatchToken: bigint; + timestamp: Date; }; export type NewDonation = Insertable; diff --git a/src/index.ts b/src/index.ts index 6c6f19e1..822a874e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ import { createIndexer, - createSqliteCache, + createPostgresCache, createPostgresSubscriptionStore, createHttpRpcClient, SubscriptionStore, @@ -120,9 +120,10 @@ async function main(): Promise { }); // the chainsauce cache is used to cache events and contract reads - const chainsauceCache = config.cacheDir - ? createSqliteCache(path.join(config.cacheDir, "chainsauceCache.db")) - : null; + const chainsauceCache = createPostgresCache({ + connectionPool: databaseConnectionPool, + schemaName: "chainsauce_cache", + }); const priceProvider = createPriceProvider({ db, diff --git a/src/indexer/allo/v1/handleEvent.ts b/src/indexer/allo/v1/handleEvent.ts index bc30b9fe..994dc3e5 100644 --- a/src/indexer/allo/v1/handleEvent.ts +++ b/src/indexer/allo/v1/handleEvent.ts @@ -712,6 +712,7 @@ export async function handleEvent( amount: event.params.amount, amountInUsd: amountInUsd, amountInRoundMatchToken, + timestamp: conversionToUSD.timestamp, }; return [ diff --git a/src/indexer/allo/v2/handleEvent.ts b/src/indexer/allo/v2/handleEvent.ts index 7ef087a1..65b6422d 100644 --- a/src/indexer/allo/v2/handleEvent.ts +++ b/src/indexer/allo/v2/handleEvent.ts @@ -994,15 +994,15 @@ export async function handleEvent( [`${event.blockNumber}-${event.logIndex}`] ); - const amountInUsd = ( - await convertToUSD( - priceProvider, - chainId, - token, - event.params.amount, - event.blockNumber - ) - ).amount; + const conversionToUSD = await convertToUSD( + priceProvider, + chainId, + token, + event.params.amount, + event.blockNumber + ); + + const amountInUsd = conversionToUSD.amount; let amountInRoundMatchToken: bigint | null = null; try { @@ -1058,6 +1058,7 @@ export async function handleEvent( amount: amount, amountInUsd, amountInRoundMatchToken, + timestamp: conversionToUSD.timestamp, }; return [ diff --git a/src/prices/provider.ts b/src/prices/provider.ts index 9abc68f5..01f75656 100644 --- a/src/prices/provider.ts +++ b/src/prices/provider.ts @@ -25,7 +25,7 @@ export async function convertFromUSD( token: Address, amountInUSD: number, blockNumber: bigint | "latest" -): Promise<{ amount: bigint; price: number }> { +): Promise<{ amount: bigint; price: number; timestamp: Date }> { const closestPrice = await priceProvider.getUSDConversionRate( chainId, token, @@ -39,6 +39,7 @@ export async function convertFromUSD( tokenPriceDecimals: 8, tokenDecimals: closestPrice.tokenDecimals, }), + timestamp: closestPrice.timestamp, price: 1 / closestPrice.priceInUsd, // price is the token price in USD, we return the inverse }; } @@ -49,7 +50,7 @@ export async function convertToUSD( token: Address, amount: bigint, blockNumber: bigint | "latest" -): Promise<{ amount: number; price: number }> { +): Promise<{ amount: number; price: number; timestamp: Date }> { const closestPrice = await priceProvider.getUSDConversionRate( chainId, token, @@ -63,6 +64,7 @@ export async function convertToUSD( tokenPrice: closestPrice.priceInUsd, tokenPriceDecimals: 8, }), + timestamp: closestPrice.timestamp, price: closestPrice.priceInUsd, }; }