From 6d03f662a329e29aeeed70257919dae42fdfc1a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?U=C4=9Fur=20Eren?= Date: Thu, 19 Sep 2024 14:53:21 +0300 Subject: [PATCH] feat: revolut liquidity indexers --- backend/drizzle/0001_dusty_microbe.sql | 65 ++ backend/drizzle/meta/0001_snapshot.json | 758 ++++++++++++++++++ backend/drizzle/meta/_journal.json | 7 + backend/src/db/schema.ts | 67 ++ indexers/docker-compose.yml | 36 + indexers/src/escrow-locked.indexer.ts | 4 +- indexers/src/escrow-unlocked.indexer.ts | 4 +- .../src/revolut-liquidity-added.indexer.ts | 60 ++ .../src/revolut-liquidity-locked.indexer.ts | 53 ++ .../revolut-liquidity-retrieved.indexer.ts | 60 ++ indexers/src/utils/constants.ts | 10 +- 11 files changed, 1119 insertions(+), 5 deletions(-) create mode 100644 backend/drizzle/0001_dusty_microbe.sql create mode 100644 backend/drizzle/meta/0001_snapshot.json create mode 100644 indexers/src/revolut-liquidity-added.indexer.ts create mode 100644 indexers/src/revolut-liquidity-locked.indexer.ts create mode 100644 indexers/src/revolut-liquidity-retrieved.indexer.ts diff --git a/backend/drizzle/0001_dusty_microbe.sql b/backend/drizzle/0001_dusty_microbe.sql new file mode 100644 index 0000000..3b1b8d9 --- /dev/null +++ b/backend/drizzle/0001_dusty_microbe.sql @@ -0,0 +1,65 @@ +DO $$ BEGIN + CREATE TYPE "public"."ramp_type" AS ENUM('Revolut'); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "indexer_liquidity_added" ( + "_cursor" bigint, + "created_at" timestamp, + "network" "network_type", + "block_hash" text, + "block_number" bigint, + "block_timestamp" timestamp, + "transaction_hash" text, + "index_in_block" bigint, + "id" text PRIMARY KEY NOT NULL, + "ramp" "ramp_type", + "owner_address" text, + "offchain_id" text, + "amount" text +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "indexer_liquidity_locked" ( + "_cursor" bigint, + "created_at" timestamp, + "network" "network_type", + "block_hash" text, + "block_number" bigint, + "block_timestamp" timestamp, + "transaction_hash" text, + "index_in_block" bigint, + "id" text PRIMARY KEY NOT NULL, + "ramp" "ramp_type", + "owner_address" text, + "offchain_id" text +); +--> statement-breakpoint +CREATE TABLE IF NOT EXISTS "indexer_liquidity_retrieved" ( + "_cursor" bigint, + "created_at" timestamp, + "network" "network_type", + "block_hash" text, + "block_number" bigint, + "block_timestamp" timestamp, + "transaction_hash" text, + "index_in_block" bigint, + "id" text PRIMARY KEY NOT NULL, + "ramp" "ramp_type", + "owner_address" text, + "offchain_id" text, + "amount" text +); +--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "liquidity_added_cursor_idx" ON "indexer_liquidity_added" USING btree ("_cursor");--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "liquidity_added_token_idx" ON "indexer_liquidity_added" USING btree ("ramp");--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "liquidity_added_owner_idx" ON "indexer_liquidity_added" USING btree ("owner_address");--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "liquidity_added_offchain_id_idx" ON "indexer_liquidity_added" USING btree ("offchain_id");--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "liquidity_locked_cursor_idx" ON "indexer_liquidity_locked" USING btree ("_cursor");--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "liquidity_locked_token_idx" ON "indexer_liquidity_locked" USING btree ("ramp");--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "liquidity_locked_owner_idx" ON "indexer_liquidity_locked" USING btree ("owner_address");--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "liquidity_locked_offchain_id_idx" ON "indexer_liquidity_locked" USING btree ("offchain_id");--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "liquidity_retrieved_cursor_idx" ON "indexer_liquidity_retrieved" USING btree ("_cursor");--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "liquidity_retrieved_token_idx" ON "indexer_liquidity_retrieved" USING btree ("ramp");--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "liquidity_retrieved_owner_idx" ON "indexer_liquidity_retrieved" USING btree ("owner_address");--> statement-breakpoint +CREATE INDEX IF NOT EXISTS "liquidity_retrieved_offchain_id_idx" ON "indexer_liquidity_retrieved" USING btree ("offchain_id"); \ No newline at end of file diff --git a/backend/drizzle/meta/0001_snapshot.json b/backend/drizzle/meta/0001_snapshot.json new file mode 100644 index 0000000..efa55f6 --- /dev/null +++ b/backend/drizzle/meta/0001_snapshot.json @@ -0,0 +1,758 @@ +{ + "id": "98ec95bb-ade2-4d5b-bac0-178f8e38a81a", + "prevId": "d5a50aa7-acac-4a5f-8d1f-e537c7e92d09", + "version": "7", + "dialect": "postgresql", + "tables": { + "public.indexer_liquidity_added": { + "name": "indexer_liquidity_added", + "schema": "", + "columns": { + "_cursor": { + "name": "_cursor", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "network": { + "name": "network", + "type": "network_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "block_hash": { + "name": "block_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "block_number": { + "name": "block_number", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "block_timestamp": { + "name": "block_timestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "transaction_hash": { + "name": "transaction_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "index_in_block": { + "name": "index_in_block", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ramp": { + "name": "ramp", + "type": "ramp_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "owner_address": { + "name": "owner_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "offchain_id": { + "name": "offchain_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "amount": { + "name": "amount", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "liquidity_added_cursor_idx": { + "name": "liquidity_added_cursor_idx", + "columns": [ + { + "expression": "_cursor", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "liquidity_added_token_idx": { + "name": "liquidity_added_token_idx", + "columns": [ + { + "expression": "ramp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "liquidity_added_owner_idx": { + "name": "liquidity_added_owner_idx", + "columns": [ + { + "expression": "owner_address", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "liquidity_added_offchain_id_idx": { + "name": "liquidity_added_offchain_id_idx", + "columns": [ + { + "expression": "offchain_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.indexer_liquidity_locked": { + "name": "indexer_liquidity_locked", + "schema": "", + "columns": { + "_cursor": { + "name": "_cursor", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "network": { + "name": "network", + "type": "network_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "block_hash": { + "name": "block_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "block_number": { + "name": "block_number", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "block_timestamp": { + "name": "block_timestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "transaction_hash": { + "name": "transaction_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "index_in_block": { + "name": "index_in_block", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ramp": { + "name": "ramp", + "type": "ramp_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "owner_address": { + "name": "owner_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "offchain_id": { + "name": "offchain_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "liquidity_locked_cursor_idx": { + "name": "liquidity_locked_cursor_idx", + "columns": [ + { + "expression": "_cursor", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "liquidity_locked_token_idx": { + "name": "liquidity_locked_token_idx", + "columns": [ + { + "expression": "ramp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "liquidity_locked_owner_idx": { + "name": "liquidity_locked_owner_idx", + "columns": [ + { + "expression": "owner_address", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "liquidity_locked_offchain_id_idx": { + "name": "liquidity_locked_offchain_id_idx", + "columns": [ + { + "expression": "offchain_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.indexer_liquidity_retrieved": { + "name": "indexer_liquidity_retrieved", + "schema": "", + "columns": { + "_cursor": { + "name": "_cursor", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "network": { + "name": "network", + "type": "network_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "block_hash": { + "name": "block_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "block_number": { + "name": "block_number", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "block_timestamp": { + "name": "block_timestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "transaction_hash": { + "name": "transaction_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "index_in_block": { + "name": "index_in_block", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "ramp": { + "name": "ramp", + "type": "ramp_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "owner_address": { + "name": "owner_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "offchain_id": { + "name": "offchain_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "amount": { + "name": "amount", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "liquidity_retrieved_cursor_idx": { + "name": "liquidity_retrieved_cursor_idx", + "columns": [ + { + "expression": "_cursor", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "liquidity_retrieved_token_idx": { + "name": "liquidity_retrieved_token_idx", + "columns": [ + { + "expression": "ramp", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "liquidity_retrieved_owner_idx": { + "name": "liquidity_retrieved_owner_idx", + "columns": [ + { + "expression": "owner_address", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "liquidity_retrieved_offchain_id_idx": { + "name": "liquidity_retrieved_offchain_id_idx", + "columns": [ + { + "expression": "offchain_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.indexer_locked": { + "name": "indexer_locked", + "schema": "", + "columns": { + "_cursor": { + "name": "_cursor", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "network": { + "name": "network", + "type": "network_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "block_hash": { + "name": "block_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "block_number": { + "name": "block_number", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "block_timestamp": { + "name": "block_timestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "transaction_hash": { + "name": "transaction_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "index_in_block": { + "name": "index_in_block", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "token_address": { + "name": "token_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "from_address": { + "name": "from_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "amount": { + "name": "amount", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "locked_cursor_idx": { + "name": "locked_cursor_idx", + "columns": [ + { + "expression": "_cursor", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "locked_token_idx": { + "name": "locked_token_idx", + "columns": [ + { + "expression": "token_address", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "locked_from_idx": { + "name": "locked_from_idx", + "columns": [ + { + "expression": "from_address", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + }, + "public.indexer_unlocked": { + "name": "indexer_unlocked", + "schema": "", + "columns": { + "_cursor": { + "name": "_cursor", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "network": { + "name": "network", + "type": "network_type", + "typeSchema": "public", + "primaryKey": false, + "notNull": false + }, + "block_hash": { + "name": "block_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "block_number": { + "name": "block_number", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "block_timestamp": { + "name": "block_timestamp", + "type": "timestamp", + "primaryKey": false, + "notNull": false + }, + "transaction_hash": { + "name": "transaction_hash", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "index_in_block": { + "name": "index_in_block", + "type": "bigint", + "primaryKey": false, + "notNull": false + }, + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "token_address": { + "name": "token_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "from_address": { + "name": "from_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "to_address": { + "name": "to_address", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "amount": { + "name": "amount", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": { + "unlocked_cursor_idx": { + "name": "unlocked_cursor_idx", + "columns": [ + { + "expression": "_cursor", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "unlocked_token_idx": { + "name": "unlocked_token_idx", + "columns": [ + { + "expression": "token_address", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "unlocked_from_idx": { + "name": "unlocked_from_idx", + "columns": [ + { + "expression": "from_address", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "unlocked_to_idx": { + "name": "unlocked_to_idx", + "columns": [ + { + "expression": "to_address", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {} + } + }, + "enums": { + "public.network_type": { + "name": "network_type", + "schema": "public", + "values": [ + "mainnet", + "sepolia" + ] + }, + "public.ramp_type": { + "name": "ramp_type", + "schema": "public", + "values": [ + "Revolut" + ] + } + }, + "schemas": {}, + "sequences": {}, + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + } +} \ No newline at end of file diff --git a/backend/drizzle/meta/_journal.json b/backend/drizzle/meta/_journal.json index 6a1742e..eef0414 100644 --- a/backend/drizzle/meta/_journal.json +++ b/backend/drizzle/meta/_journal.json @@ -8,6 +8,13 @@ "when": 1725556971568, "tag": "0000_damp_typhoid_mary", "breakpoints": true + }, + { + "idx": 1, + "version": "7", + "when": 1726746693178, + "tag": "0001_dusty_microbe", + "breakpoints": true } ] } \ No newline at end of file diff --git a/backend/src/db/schema.ts b/backend/src/db/schema.ts index 746a960..cc60816 100644 --- a/backend/src/db/schema.ts +++ b/backend/src/db/schema.ts @@ -2,6 +2,8 @@ import { bigint, index, pgEnum, pgTable, text, timestamp } from 'drizzle-orm/pg- export const networkEnum = pgEnum('network_type', ['mainnet', 'sepolia']) +export const rampEnum = pgEnum('ramp_type', ['Revolut']) + // eslint-disable-next-line @typescript-eslint/no-unused-vars const indexerCommonSchema = { cursor: bigint('_cursor', { mode: 'number' }), @@ -59,3 +61,68 @@ export const unlocked = pgTable( } }, ) + +export const liquidityAdded = pgTable( + 'indexer_liquidity_added', + { + ...indexerCommonSchema, + + id: text('id').primaryKey(), + + ramp: rampEnum('ramp'), + owner: text('owner_address'), + offchainId: text('offchain_id'), + amount: text('amount'), + }, + (table) => { + return { + cursorIdx: index('liquidity_added_cursor_idx').on(table.cursor), + rampIdx: index('liquidity_added_token_idx').on(table.ramp), + ownerIdx: index('liquidity_added_owner_idx').on(table.owner), + offchainIdIdx: index('liquidity_added_offchain_id_idx').on(table.offchainId), + } + }, +) + +export const liquidityLocked = pgTable( + 'indexer_liquidity_locked', + { + ...indexerCommonSchema, + + id: text('id').primaryKey(), + + ramp: rampEnum('ramp'), + owner: text('owner_address'), + offchainId: text('offchain_id'), + }, + (table) => { + return { + cursorIdx: index('liquidity_locked_cursor_idx').on(table.cursor), + rampIdx: index('liquidity_locked_token_idx').on(table.ramp), + ownerIdx: index('liquidity_locked_owner_idx').on(table.owner), + offchainIdIdx: index('liquidity_locked_offchain_id_idx').on(table.offchainId), + } + }, +) + +export const liquidityRetrieved = pgTable( + 'indexer_liquidity_retrieved', + { + ...indexerCommonSchema, + + id: text('id').primaryKey(), + + ramp: rampEnum('ramp'), + owner: text('owner_address'), + offchainId: text('offchain_id'), + amount: text('amount'), + }, + (table) => { + return { + cursorIdx: index('liquidity_retrieved_cursor_idx').on(table.cursor), + rampIdx: index('liquidity_retrieved_token_idx').on(table.ramp), + ownerIdx: index('liquidity_retrieved_owner_idx').on(table.owner), + offchainIdIdx: index('liquidity_retrieved_offchain_id_idx').on(table.offchainId), + } + }, +) diff --git a/indexers/docker-compose.yml b/indexers/docker-compose.yml index 60a4d35..a69bbb7 100644 --- a/indexers/docker-compose.yml +++ b/indexers/docker-compose.yml @@ -25,6 +25,42 @@ services: - indexer restart: on-failure + revolut-liquidity-added-indexer: + environment: + - AUTH_TOKEN=${AUTH_TOKEN} + - POSTGRES_CONNECTION_STRING=${POSTGRES_CONNECTION_STRING} + image: quay.io/apibara/sink-postgres:latest + command: 'run ./indexer/revolut-liquidity-added.indexer.ts --connection-string ${POSTGRES_CONNECTION_STRING} -A ${AUTH_TOKEN}' + volumes: + - ./src:/indexer + networks: + - indexer + restart: on-failure + + revolut-liquidity-locked-indexer: + environment: + - AUTH_TOKEN=${AUTH_TOKEN} + - POSTGRES_CONNECTION_STRING=${POSTGRES_CONNECTION_STRING} + image: quay.io/apibara/sink-postgres:latest + command: 'run ./indexer/revolut-liquidity-locked.indexer.ts --connection-string ${POSTGRES_CONNECTION_STRING} -A ${AUTH_TOKEN}' + volumes: + - ./src:/indexer + networks: + - indexer + restart: on-failure + + revolut-liquidity-retrieved-indexer: + environment: + - AUTH_TOKEN=${AUTH_TOKEN} + - POSTGRES_CONNECTION_STRING=${POSTGRES_CONNECTION_STRING} + image: quay.io/apibara/sink-postgres:latest + command: 'run ./indexer/revolut-liquidity-retrieved.indexer.ts --connection-string ${POSTGRES_CONNECTION_STRING} -A ${AUTH_TOKEN}' + volumes: + - ./src:/indexer + networks: + - indexer + restart: on-failure + networks: indexer: driver: bridge diff --git a/indexers/src/escrow-locked.indexer.ts b/indexers/src/escrow-locked.indexer.ts index 6daef89..e561d56 100644 --- a/indexers/src/escrow-locked.indexer.ts +++ b/indexers/src/escrow-locked.indexer.ts @@ -1,5 +1,5 @@ import { apibara, starknet } from './utils/deps.ts' -import { ESCROW_ADDRESS, STARTING_BLOCK } from './utils/constants.ts' +import { ESCROW_ADDRESS, ESCROW_STARTING_BLOCK } from './utils/constants.ts' import { getCommonValues } from './utils/helpers.ts' const filter = { @@ -17,7 +17,7 @@ const filter = { export const config = { streamUrl: 'https://mainnet.starknet.a5a.ch', - startingBlock: STARTING_BLOCK, + startingBlock: ESCROW_STARTING_BLOCK, network: 'starknet', finality: 'DATA_STATUS_ACCEPTED', filter, diff --git a/indexers/src/escrow-unlocked.indexer.ts b/indexers/src/escrow-unlocked.indexer.ts index 7fa55e7..877a7fa 100644 --- a/indexers/src/escrow-unlocked.indexer.ts +++ b/indexers/src/escrow-unlocked.indexer.ts @@ -1,5 +1,5 @@ import { apibara, starknet } from './utils/deps.ts' -import { ESCROW_ADDRESS, STARTING_BLOCK } from './utils/constants.ts' +import { ESCROW_ADDRESS, ESCROW_STARTING_BLOCK } from './utils/constants.ts' import { getCommonValues } from './utils/helpers.ts' const filter = { @@ -17,7 +17,7 @@ const filter = { export const config = { streamUrl: 'https://mainnet.starknet.a5a.ch', - startingBlock: STARTING_BLOCK, + startingBlock: ESCROW_STARTING_BLOCK, network: 'starknet', finality: 'DATA_STATUS_ACCEPTED', filter, diff --git a/indexers/src/revolut-liquidity-added.indexer.ts b/indexers/src/revolut-liquidity-added.indexer.ts new file mode 100644 index 0000000..e878556 --- /dev/null +++ b/indexers/src/revolut-liquidity-added.indexer.ts @@ -0,0 +1,60 @@ +import { apibara, starknet } from './utils/deps.ts' +import { RAMPS, REVOLUT_ADDRESS, REVOLUT_STARTING_BLOCK } from './utils/constants.ts' +import { getCommonValues } from './utils/helpers.ts' + +const filter = { + header: { + weak: true, + }, + events: [ + { + fromAddress: REVOLUT_ADDRESS, + keys: [starknet.hash.getSelectorFromName('LiquidityAdded')], + includeReceipt: false, + }, + ], +} + +export const config = { + streamUrl: 'https://mainnet.starknet.a5a.ch', + startingBlock: REVOLUT_STARTING_BLOCK, + network: 'starknet', + finality: 'DATA_STATUS_ACCEPTED', + filter, + sinkType: 'postgres', + sinkOptions: { + tableName: 'indexer_liquidity_added', + }, +} + +export default function transform({ header, events }: apibara.Block) { + return (events ?? []) + .map(({ event, transaction }) => { + if (!event.data || !event.keys) return null + + const eventId = `${transaction.meta.hash}_${event.index ?? 0}` + + const [, owner, ramp_idx, offchain_id] = event.keys + const [amountLow, amountHigh] = event.data + + const ramp = Object.values(RAMPS)[Number(ramp_idx)] + if (!ramp) return null + + const amount = starknet.uint256.uint256ToBN({ + low: amountLow, + high: amountHigh, + }) + + return { + ...getCommonValues(header!, event, transaction), + + id: eventId, + + ramp, + owner_address: owner, + offchain_id, + amount: amount.toString(), + } + }) + .filter(Boolean) +} diff --git a/indexers/src/revolut-liquidity-locked.indexer.ts b/indexers/src/revolut-liquidity-locked.indexer.ts new file mode 100644 index 0000000..87fb5d8 --- /dev/null +++ b/indexers/src/revolut-liquidity-locked.indexer.ts @@ -0,0 +1,53 @@ +import { apibara, starknet } from './utils/deps.ts' +import { RAMPS, REVOLUT_ADDRESS, REVOLUT_STARTING_BLOCK } from './utils/constants.ts' +import { getCommonValues } from './utils/helpers.ts' + +const filter = { + header: { + weak: true, + }, + events: [ + { + fromAddress: REVOLUT_ADDRESS, + keys: [starknet.hash.getSelectorFromName('LiquidityLocked')], + includeReceipt: false, + }, + ], +} + +export const config = { + streamUrl: 'https://mainnet.starknet.a5a.ch', + startingBlock: REVOLUT_STARTING_BLOCK, + network: 'starknet', + finality: 'DATA_STATUS_ACCEPTED', + filter, + sinkType: 'postgres', + sinkOptions: { + tableName: 'indexer_liquidity_locked', + }, +} + +export default function transform({ header, events }: apibara.Block) { + return (events ?? []) + .map(({ event, transaction }) => { + if (!event.data || !event.keys) return null + + const eventId = `${transaction.meta.hash}_${event.index ?? 0}` + + const [, owner, ramp_idx, offchain_id] = event.keys + + const ramp = Object.values(RAMPS)[Number(ramp_idx)] + if (!ramp) return null + + return { + ...getCommonValues(header!, event, transaction), + + id: eventId, + + ramp, + owner_address: owner, + offchain_id, + } + }) + .filter(Boolean) +} diff --git a/indexers/src/revolut-liquidity-retrieved.indexer.ts b/indexers/src/revolut-liquidity-retrieved.indexer.ts new file mode 100644 index 0000000..6f29cff --- /dev/null +++ b/indexers/src/revolut-liquidity-retrieved.indexer.ts @@ -0,0 +1,60 @@ +import { apibara, starknet } from './utils/deps.ts' +import { RAMPS, REVOLUT_ADDRESS, REVOLUT_STARTING_BLOCK } from './utils/constants.ts' +import { getCommonValues } from './utils/helpers.ts' + +const filter = { + header: { + weak: true, + }, + events: [ + { + fromAddress: REVOLUT_ADDRESS, + keys: [starknet.hash.getSelectorFromName('LiquidityRetrieved')], + includeReceipt: false, + }, + ], +} + +export const config = { + streamUrl: 'https://mainnet.starknet.a5a.ch', + startingBlock: REVOLUT_STARTING_BLOCK, + network: 'starknet', + finality: 'DATA_STATUS_ACCEPTED', + filter, + sinkType: 'postgres', + sinkOptions: { + tableName: 'indexer_liquidity_retrieved', + }, +} + +export default function transform({ header, events }: apibara.Block) { + return (events ?? []) + .map(({ event, transaction }) => { + if (!event.data || !event.keys) return null + + const eventId = `${transaction.meta.hash}_${event.index ?? 0}` + + const [, owner, ramp_idx, offchain_id] = event.keys + const [amountLow, amountHigh] = event.data + + const ramp = Object.values(RAMPS)[Number(ramp_idx)] + if (!ramp) return null + + const amount = starknet.uint256.uint256ToBN({ + low: amountLow, + high: amountHigh, + }) + + return { + ...getCommonValues(header!, event, transaction), + + id: eventId, + + ramp, + owner_address: owner, + offchain_id, + amount: amount.toString(), + } + }) + .filter(Boolean) +} diff --git a/indexers/src/utils/constants.ts b/indexers/src/utils/constants.ts index 4f17e8b..cfe4e8f 100644 --- a/indexers/src/utils/constants.ts +++ b/indexers/src/utils/constants.ts @@ -1,2 +1,10 @@ +// Order should match the order in the contract +export enum RAMPS { + Revolut, +} + export const ESCROW_ADDRESS = '0x0' -export const STARTING_BLOCK = 0 +export const ESCROW_STARTING_BLOCK = 0 + +export const REVOLUT_ADDRESS = '0x0' +export const REVOLUT_STARTING_BLOCK = 0