diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..8499a6ea --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +src/abi +src/model + diff --git a/.prettierrc b/.prettierrc index 1a68d900..6253f707 100644 --- a/.prettierrc +++ b/.prettierrc @@ -3,9 +3,18 @@ "trailingComma": "all", "tabWidth": 2, "semi": false, - "importOrder": ["^@core/(.*)$", "^@server/(.*)$", "^@ui/(.*)$", "^[./]"], + "importOrder": [ + "", + "^@", + "^[./]" + ], "importOrderSeparation": true, "importOrderSortSpecifiers": true, - "importOrderParserPlugins": ["typescript", "decorators-legacy"], - "plugins": ["@trivago/prettier-plugin-sort-imports"] + "importOrderParserPlugins": [ + "typescript", + "decorators-legacy" + ], + "plugins": [ + "@trivago/prettier-plugin-sort-imports" + ] } diff --git a/README.md b/README.md index cbfda715..d096a1d3 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ sqd down # Bring down squid container sqd up # Bring up squid container sqd process:oeth # Run OETH processor sqd process:ousd # Run OUSD processor -sqd process:other # Run misc processor +sqd process:mainnet # Run misc processor sqd migration:generate # Generate migration (sqd down && sqd up first) ``` diff --git a/commands.json b/commands.json index 4a263a9c..b7c85b2a 100644 --- a/commands.json +++ b/commands.json @@ -97,6 +97,7 @@ "cmd": [ "node", "--require=dotenv/config", + "--require=tsconfig-paths/register", "lib/main.js" ] }, @@ -108,6 +109,7 @@ "cmd": [ "node", "--require=dotenv/config", + "--require=tsconfig-paths/register", "lib/main-arbitrum.js" ] }, @@ -119,6 +121,7 @@ "cmd": [ "node", "--require=dotenv/config", + "--require=tsconfig-paths/register", "lib/main-oeth.js" ] }, @@ -130,6 +133,7 @@ "cmd": [ "node", "--require=dotenv/config", + "--require=tsconfig-paths/register", "lib/main-ousd.js" ] }, @@ -141,10 +145,11 @@ "cmd": [ "node", "--require=dotenv/config", + "--require=tsconfig-paths/register", "lib/main-ogv.js" ] }, - "process:other": { + "process:mainnet": { "description": "Load .env and start the squid processor", "deps": [ "build" @@ -152,7 +157,8 @@ "cmd": [ "node", "--require=dotenv/config", - "lib/main-other.js" + "--require=tsconfig-paths/register", + "lib/main-mainnet.js" ] }, "process:arbitrum:prod": { @@ -162,6 +168,7 @@ ], "cmd": [ "node", + "--require=tsconfig-paths/register", "lib/main-arbitrum.js" ], "hidden": true @@ -173,6 +180,7 @@ ], "cmd": [ "node", + "--require=tsconfig-paths/register", "lib/main-oeth.js" ], "hidden": true @@ -184,6 +192,7 @@ ], "cmd": [ "node", + "--require=tsconfig-paths/register", "lib/main-ousd.js" ], "hidden": true @@ -195,18 +204,20 @@ ], "cmd": [ "node", + "--require=tsconfig-paths/register", "lib/main-ogv.js" ], "hidden": true }, - "process:other:prod": { + "process:mainnet:prod": { "description": "Start the squid processor", "deps": [ "migration:apply" ], "cmd": [ "node", - "lib/main-other.js" + "--require=tsconfig-paths/register", + "lib/main-mainnet.js" ], "hidden": true }, diff --git a/db/migrations/1712281391762-Data.js b/db/migrations/1713570460723-Data.js similarity index 92% rename from db/migrations/1712281391762-Data.js rename to db/migrations/1713570460723-Data.js index fca5972d..09c25ae7 100644 --- a/db/migrations/1712281391762-Data.js +++ b/db/migrations/1713570460723-Data.js @@ -1,5 +1,5 @@ -module.exports = class Data1712281391762 { - name = 'Data1712281391762' +module.exports = class Data1713570460723 { + name = 'Data1713570460723' async up(db) { await db.query(`CREATE TABLE "processing_status" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, CONSTRAINT "PK_85f5e2467b74fb70fac1a053021" PRIMARY KEY ("id"))`) @@ -18,14 +18,24 @@ module.exports = class Data1712281391762 { await db.query(`CREATE TABLE "native_balance" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "account" text NOT NULL, "balance" numeric NOT NULL, CONSTRAINT "PK_62f6bdfe058e52d1914d0c2c1ce" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_45fb48f831ccadcf29f404824a" ON "native_balance" ("timestamp") `) await db.query(`CREATE INDEX "IDX_82d827c3b96fb3c5ab43068502" ON "native_balance" ("block_number") `) - await db.query(`CREATE TABLE "erc20" ("id" character varying NOT NULL, "address" text NOT NULL, "name" text NOT NULL, "decimals" integer NOT NULL, "symbol" text NOT NULL, CONSTRAINT "PK_8d43ce15401ba044c55a72a8ceb" PRIMARY KEY ("id"))`) - await db.query(`CREATE TABLE "erc20_holder" ("id" character varying NOT NULL, "address" text NOT NULL, "account" text NOT NULL, CONSTRAINT "PK_3adce7edbac4bcb03c662c3a1ac" PRIMARY KEY ("id"))`) - await db.query(`CREATE TABLE "erc20_state" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "address" text NOT NULL, "total_supply" numeric NOT NULL, "holder_count" integer NOT NULL, CONSTRAINT "PK_eac1124b07bbdedafd4fff2f7b7" PRIMARY KEY ("id"))`) + await db.query(`CREATE TABLE "erc20" ("id" character varying NOT NULL, "chain_id" integer NOT NULL, "address" text NOT NULL, "name" text NOT NULL, "decimals" integer NOT NULL, "symbol" text NOT NULL, CONSTRAINT "PK_8d43ce15401ba044c55a72a8ceb" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_905ff854e6782fc32dc4268a25" ON "erc20" ("chain_id") `) + await db.query(`CREATE INDEX "IDX_40fd11c1a0d0f2562824894e85" ON "erc20" ("address") `) + await db.query(`CREATE TABLE "erc20_holder" ("id" character varying NOT NULL, "chain_id" integer NOT NULL, "address" text NOT NULL, "account" text NOT NULL, CONSTRAINT "PK_3adce7edbac4bcb03c662c3a1ac" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_51b9e7c44702ef3a6f05d3702e" ON "erc20_holder" ("chain_id") `) + await db.query(`CREATE TABLE "erc20_state" ("id" character varying NOT NULL, "chain_id" integer NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "address" text NOT NULL, "total_supply" numeric NOT NULL, "holder_count" integer NOT NULL, CONSTRAINT "PK_eac1124b07bbdedafd4fff2f7b7" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_2b69abb250c647c7a4b5a5a715" ON "erc20_state" ("chain_id") `) await db.query(`CREATE INDEX "IDX_c3d08eb2dafe4b5b188924d835" ON "erc20_state" ("timestamp") `) await db.query(`CREATE INDEX "IDX_29e8edc6ba8cc37c0c16ff0baf" ON "erc20_state" ("block_number") `) - await db.query(`CREATE TABLE "erc20_balance" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "address" text NOT NULL, "account" text NOT NULL, "balance" numeric NOT NULL, CONSTRAINT "PK_069b6549e7a9938cc89f32063a6" PRIMARY KEY ("id"))`) + await db.query(`CREATE TABLE "erc20_balance" ("id" character varying NOT NULL, "chain_id" integer NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "address" text NOT NULL, "account" text NOT NULL, "balance" numeric NOT NULL, CONSTRAINT "PK_069b6549e7a9938cc89f32063a6" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_bb6a884e702f2887037d5a7eec" ON "erc20_balance" ("chain_id") `) await db.query(`CREATE INDEX "IDX_c9fbe21a3411d93ea586af2a4c" ON "erc20_balance" ("timestamp") `) await db.query(`CREATE INDEX "IDX_d1f50dc39003331b76fad8a640" ON "erc20_balance" ("block_number") `) + await db.query(`CREATE TABLE "erc20_transfer" ("id" character varying NOT NULL, "chain_id" integer NOT NULL, "tx_hash" text NOT NULL, "block_number" integer NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "address" text NOT NULL, "from" text NOT NULL, "to" text NOT NULL, "value" numeric NOT NULL, CONSTRAINT "PK_12764843146818a31e3d28fc577" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_f914d2e140eb88375a5a2ef6c7" ON "erc20_transfer" ("chain_id") `) + await db.query(`CREATE INDEX "IDX_6350ddb2def19c1e3a06d8b3ec" ON "erc20_transfer" ("address") `) + await db.query(`CREATE INDEX "IDX_eca70565083880d00e9110b000" ON "erc20_transfer" ("from") `) + await db.query(`CREATE INDEX "IDX_9fdc9d58b6ae0cb13b9c7f8226" ON "erc20_transfer" ("to") `) await db.query(`CREATE TABLE "curve_pool" ("id" character varying NOT NULL, "address" text NOT NULL, "name" text NOT NULL, "token_count" integer NOT NULL, "token0" text NOT NULL, "token1" text NOT NULL, "token2" text, CONSTRAINT "PK_c04bba36a8aa877d6efa4eafd6c" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_76c9202c1160ce818f7a29d131" ON "curve_pool" ("address") `) await db.query(`CREATE TABLE "curve_pool_balance" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "address" text NOT NULL, "balance0" numeric NOT NULL, "balance1" numeric NOT NULL, "balance2" numeric NOT NULL, CONSTRAINT "PK_40412750bb910ca560aa084dd88" PRIMARY KEY ("id"))`) @@ -51,18 +61,18 @@ module.exports = class Data1712281391762 { await db.query(`CREATE TABLE "liquidity_daily_balance" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "address" text NOT NULL, "token" text NOT NULL, "balance" numeric NOT NULL, CONSTRAINT "PK_bf1de97f9815d851f7b4abca9ca" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_c5116bd4f5406fc2848552f0ba" ON "liquidity_daily_balance" ("timestamp") `) await db.query(`CREATE INDEX "IDX_58d14205a5e9ad1d05f94d7bb6" ON "liquidity_daily_balance" ("block_number") `) - await db.query(`CREATE TABLE "bridge_transfer" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "tx_hash" text NOT NULL, "message_id" text NOT NULL, "bridge" text NOT NULL, "sender" text NOT NULL, "receiver" text NOT NULL, "chain_in" integer NOT NULL, "chain_out" integer NOT NULL, "token_in" text NOT NULL, "token_out" text NOT NULL, "amount_in" numeric NOT NULL, "amount_out" numeric NOT NULL, CONSTRAINT "PK_fab0727701656a3e6c320fca6e9" PRIMARY KEY ("id"))`) + await db.query(`CREATE TABLE "bridge_transfer" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "tx_hash_in" text NOT NULL, "tx_hash_out" text, "message_id" text NOT NULL, "bridge" text NOT NULL, "sender" text NOT NULL, "receiver" text NOT NULL, "chain_in" integer NOT NULL, "chain_out" integer NOT NULL, "token_in" text NOT NULL, "token_out" text NOT NULL, "amount_in" numeric NOT NULL, "amount_out" numeric NOT NULL, "state" integer NOT NULL, CONSTRAINT "PK_fab0727701656a3e6c320fca6e9" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_aaedc42eda914e44a21e8eac72" ON "bridge_transfer" ("timestamp") `) await db.query(`CREATE INDEX "IDX_f8d8d410f058f0bae15eefbc81" ON "bridge_transfer" ("block_number") `) - await db.query(`CREATE INDEX "IDX_312166d6942ae27bf8459775ce" ON "bridge_transfer" ("tx_hash") `) await db.query(`CREATE INDEX "IDX_85994c1ee045b713bbcbcccc8b" ON "bridge_transfer" ("message_id") `) await db.query(`CREATE INDEX "IDX_7ff6ab2147f80a465d3752e79f" ON "bridge_transfer" ("bridge") `) await db.query(`CREATE INDEX "IDX_3cbd3eea30bc62ebc91c276e73" ON "bridge_transfer" ("sender") `) await db.query(`CREATE INDEX "IDX_54f4abe8f2eb80204637ce328e" ON "bridge_transfer" ("receiver") `) await db.query(`CREATE INDEX "IDX_12fa326ec2496a964493f2a7bc" ON "bridge_transfer" ("chain_in") `) - await db.query(`CREATE TABLE "bridge_transfer_state" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "state" integer NOT NULL, CONSTRAINT "PK_00ca26906171755e6fc01882c68" PRIMARY KEY ("id"))`) + await db.query(`CREATE TABLE "bridge_transfer_state" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "tx_hash" text NOT NULL, "state" integer NOT NULL, CONSTRAINT "PK_00ca26906171755e6fc01882c68" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_374659ae3bd149042388e132be" ON "bridge_transfer_state" ("timestamp") `) await db.query(`CREATE INDEX "IDX_74f93b10ec560e63792dcc877e" ON "bridge_transfer_state" ("block_number") `) + await db.query(`CREATE INDEX "IDX_df99bdbf11d4ed57bec0e6c511" ON "bridge_transfer_state" ("tx_hash") `) await db.query(`CREATE TABLE "oeth" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "total_supply" numeric NOT NULL, "rebasing_supply" numeric NOT NULL, "non_rebasing_supply" numeric NOT NULL, CONSTRAINT "PK_de1d885501070dbd1ab6f8577ba" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_5b81a67229bac2d68e0dc92cc4" ON "oeth" ("timestamp") `) await db.query(`CREATE INDEX "IDX_408e5f79f83093aa5cf2b0ea32" ON "oeth" ("block_number") `) @@ -73,10 +83,6 @@ module.exports = class Data1712281391762 { await db.query(`CREATE INDEX "IDX_96956b1c8d29eb7066a97d5ea7" ON "oeth_history" ("block_number") `) await db.query(`CREATE INDEX "IDX_b14170bdb7fbc0775bf55df15d" ON "oeth_history" ("tx_hash") `) await db.query(`CREATE TABLE "oeth_address" ("id" character varying NOT NULL, "is_contract" boolean NOT NULL, "rebasing_option" character varying(6) NOT NULL, "balance" numeric NOT NULL, "earned" numeric NOT NULL, "credits" numeric NOT NULL, "last_updated" TIMESTAMP WITH TIME ZONE NOT NULL, CONSTRAINT "PK_92a966afe47d584af73ce77a1cd" PRIMARY KEY ("id"))`) - await db.query(`CREATE TABLE "woeth_history" ("id" character varying NOT NULL, "address" text NOT NULL, "value" numeric NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "tx_hash" text NOT NULL, "type" character varying(8) NOT NULL, CONSTRAINT "PK_078ca80778522886c3ce9dcf1cf" PRIMARY KEY ("id"))`) - await db.query(`CREATE INDEX "IDX_2b694747dde9f6915fc2106862" ON "woeth_history" ("address") `) - await db.query(`CREATE INDEX "IDX_a5642ab77eff35d76c2a9584e7" ON "woeth_history" ("block_number") `) - await db.query(`CREATE INDEX "IDX_49c09d8924e121e762ba96e5f3" ON "woeth_history" ("tx_hash") `) await db.query(`CREATE TABLE "oethapy" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "tx_hash" text NOT NULL, "apr" numeric NOT NULL, "apy" numeric NOT NULL, "apy7_day_avg" numeric NOT NULL, "apy14_day_avg" numeric NOT NULL, "apy30_day_avg" numeric NOT NULL, "rebasing_credits_per_token" numeric NOT NULL, CONSTRAINT "PK_8dbb4d04591848361200f18f62a" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_b1a448045d1ed9d655b679a371" ON "oethapy" ("timestamp") `) await db.query(`CREATE INDEX "IDX_6b8a7a706a0701e659a7d81508" ON "oethapy" ("block_number") `) @@ -145,6 +151,11 @@ module.exports = class Data1712281391762 { await db.query(`CREATE TABLE "ogv_daily_stat" ("id" character varying NOT NULL, "block_number" integer NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "total_supply" numeric NOT NULL, "total_supply_usd" numeric NOT NULL, "total_staked" numeric NOT NULL, "trading_volume_usd" numeric NOT NULL, "market_cap_usd" numeric NOT NULL, "price_usd" numeric NOT NULL, "holders_over_threshold" integer NOT NULL, CONSTRAINT "PK_69bc6d866711151e2712481794c" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_c974bde87107cacae6d3654972" ON "ogv_daily_stat" ("block_number") `) await db.query(`CREATE INDEX "IDX_b62fa80951183bb0acf8a5e8b9" ON "ogv_daily_stat" ("timestamp") `) + await db.query(`CREATE TABLE "o_token_vault" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "chain_id" integer NOT NULL, "address" text NOT NULL, "total_value" numeric NOT NULL, CONSTRAINT "PK_90bb3a4df699017439cd6a44a0c" PRIMARY KEY ("id"))`) + await db.query(`CREATE INDEX "IDX_091cfbe0d977006e05144bd1fe" ON "o_token_vault" ("timestamp") `) + await db.query(`CREATE INDEX "IDX_fa92b36d011441a02d9a231860" ON "o_token_vault" ("block_number") `) + await db.query(`CREATE INDEX "IDX_6990f4cd71ea8db6d9d27a0db5" ON "o_token_vault" ("chain_id") `) + await db.query(`CREATE INDEX "IDX_3a2bfb2808c1d7cbb0a568910c" ON "o_token_vault" ("address") `) await db.query(`CREATE TABLE "ousd" ("id" character varying NOT NULL, "timestamp" TIMESTAMP WITH TIME ZONE NOT NULL, "block_number" integer NOT NULL, "total_supply" numeric NOT NULL, "rebasing_supply" numeric NOT NULL, "non_rebasing_supply" numeric NOT NULL, CONSTRAINT "PK_acecae4a20bc14b22d9f6738d8d" PRIMARY KEY ("id"))`) await db.query(`CREATE INDEX "IDX_c8d1e285213b445b088805ac7c" ON "ousd" ("timestamp") `) await db.query(`CREATE INDEX "IDX_806949dd853b7e8acab5d03b81" ON "ousd" ("block_number") `) @@ -251,13 +262,23 @@ module.exports = class Data1712281391762 { await db.query(`DROP INDEX "public"."IDX_45fb48f831ccadcf29f404824a"`) await db.query(`DROP INDEX "public"."IDX_82d827c3b96fb3c5ab43068502"`) await db.query(`DROP TABLE "erc20"`) + await db.query(`DROP INDEX "public"."IDX_905ff854e6782fc32dc4268a25"`) + await db.query(`DROP INDEX "public"."IDX_40fd11c1a0d0f2562824894e85"`) await db.query(`DROP TABLE "erc20_holder"`) + await db.query(`DROP INDEX "public"."IDX_51b9e7c44702ef3a6f05d3702e"`) await db.query(`DROP TABLE "erc20_state"`) + await db.query(`DROP INDEX "public"."IDX_2b69abb250c647c7a4b5a5a715"`) await db.query(`DROP INDEX "public"."IDX_c3d08eb2dafe4b5b188924d835"`) await db.query(`DROP INDEX "public"."IDX_29e8edc6ba8cc37c0c16ff0baf"`) await db.query(`DROP TABLE "erc20_balance"`) + await db.query(`DROP INDEX "public"."IDX_bb6a884e702f2887037d5a7eec"`) await db.query(`DROP INDEX "public"."IDX_c9fbe21a3411d93ea586af2a4c"`) await db.query(`DROP INDEX "public"."IDX_d1f50dc39003331b76fad8a640"`) + await db.query(`DROP TABLE "erc20_transfer"`) + await db.query(`DROP INDEX "public"."IDX_f914d2e140eb88375a5a2ef6c7"`) + await db.query(`DROP INDEX "public"."IDX_6350ddb2def19c1e3a06d8b3ec"`) + await db.query(`DROP INDEX "public"."IDX_eca70565083880d00e9110b000"`) + await db.query(`DROP INDEX "public"."IDX_9fdc9d58b6ae0cb13b9c7f8226"`) await db.query(`DROP TABLE "curve_pool"`) await db.query(`DROP INDEX "public"."IDX_76c9202c1160ce818f7a29d131"`) await db.query(`DROP TABLE "curve_pool_balance"`) @@ -286,7 +307,6 @@ module.exports = class Data1712281391762 { await db.query(`DROP TABLE "bridge_transfer"`) await db.query(`DROP INDEX "public"."IDX_aaedc42eda914e44a21e8eac72"`) await db.query(`DROP INDEX "public"."IDX_f8d8d410f058f0bae15eefbc81"`) - await db.query(`DROP INDEX "public"."IDX_312166d6942ae27bf8459775ce"`) await db.query(`DROP INDEX "public"."IDX_85994c1ee045b713bbcbcccc8b"`) await db.query(`DROP INDEX "public"."IDX_7ff6ab2147f80a465d3752e79f"`) await db.query(`DROP INDEX "public"."IDX_3cbd3eea30bc62ebc91c276e73"`) @@ -295,6 +315,7 @@ module.exports = class Data1712281391762 { await db.query(`DROP TABLE "bridge_transfer_state"`) await db.query(`DROP INDEX "public"."IDX_374659ae3bd149042388e132be"`) await db.query(`DROP INDEX "public"."IDX_74f93b10ec560e63792dcc877e"`) + await db.query(`DROP INDEX "public"."IDX_df99bdbf11d4ed57bec0e6c511"`) await db.query(`DROP TABLE "oeth"`) await db.query(`DROP INDEX "public"."IDX_5b81a67229bac2d68e0dc92cc4"`) await db.query(`DROP INDEX "public"."IDX_408e5f79f83093aa5cf2b0ea32"`) @@ -305,10 +326,6 @@ module.exports = class Data1712281391762 { await db.query(`DROP INDEX "public"."IDX_96956b1c8d29eb7066a97d5ea7"`) await db.query(`DROP INDEX "public"."IDX_b14170bdb7fbc0775bf55df15d"`) await db.query(`DROP TABLE "oeth_address"`) - await db.query(`DROP TABLE "woeth_history"`) - await db.query(`DROP INDEX "public"."IDX_2b694747dde9f6915fc2106862"`) - await db.query(`DROP INDEX "public"."IDX_a5642ab77eff35d76c2a9584e7"`) - await db.query(`DROP INDEX "public"."IDX_49c09d8924e121e762ba96e5f3"`) await db.query(`DROP TABLE "oethapy"`) await db.query(`DROP INDEX "public"."IDX_b1a448045d1ed9d655b679a371"`) await db.query(`DROP INDEX "public"."IDX_6b8a7a706a0701e659a7d81508"`) @@ -377,6 +394,11 @@ module.exports = class Data1712281391762 { await db.query(`DROP TABLE "ogv_daily_stat"`) await db.query(`DROP INDEX "public"."IDX_c974bde87107cacae6d3654972"`) await db.query(`DROP INDEX "public"."IDX_b62fa80951183bb0acf8a5e8b9"`) + await db.query(`DROP TABLE "o_token_vault"`) + await db.query(`DROP INDEX "public"."IDX_091cfbe0d977006e05144bd1fe"`) + await db.query(`DROP INDEX "public"."IDX_fa92b36d011441a02d9a231860"`) + await db.query(`DROP INDEX "public"."IDX_6990f4cd71ea8db6d9d27a0db5"`) + await db.query(`DROP INDEX "public"."IDX_3a2bfb2808c1d7cbb0a568910c"`) await db.query(`DROP TABLE "ousd"`) await db.query(`DROP INDEX "public"."IDX_c8d1e285213b445b088805ac7c"`) await db.query(`DROP INDEX "public"."IDX_806949dd853b7e8acab5d03b81"`) diff --git a/dev.env b/dev.env index 7fa52100..6c1a68d4 100644 --- a/dev.env +++ b/dev.env @@ -1,3 +1,4 @@ +TS_NODE_BASEURL=./lib DB_NAME=squid DB_PORT=23798 GQL_PORT=4350 diff --git a/graphql.config.yml b/graphql.config.yml index 54059e8c..c6964b92 100644 --- a/graphql.config.yml +++ b/graphql.config.yml @@ -5,6 +5,11 @@ projects: schema: schema-general.graphql include: - types.graphql + otoken: + schema: schema-otoken.graphql + include: + - schema-general.graphql + - types.graphql oeth: schema: schema-oeth.graphql include: diff --git a/package-lock.json b/package-lock.json index 22efe451..840c5b7b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,6 +36,7 @@ "@types/uuid": "^9.0.2", "npm-run-all": "^4.1.5", "prettier": "^3.0.3", + "tsconfig-paths": "^4.2.0", "typescript": "~5.1.3" } }, @@ -233,14 +234,13 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.2.tgz", + "integrity": "sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.2", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" @@ -251,7 +251,6 @@ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.17.0", "jsesc": "^2.5.1", @@ -262,24 +261,36 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", - "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", - "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/template": "^7.22.5", - "@babel/types": "^7.22.5" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name/node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" @@ -290,7 +301,6 @@ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.22.5" }, @@ -298,12 +308,25 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-hoist-variables/node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-split-export-declaration": { "version": "7.22.6", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, - "license": "MIT", "dependencies": { "@babel/types": "^7.22.5" }, @@ -311,47 +334,58 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-split-export-declaration/node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz", + "integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.19", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.19.tgz", - "integrity": "sha512-Tinq7ybnEPFFXhlYOYFiSjespWQk0dq2dRNAiMdRTOYQzEGqnnNyrTxPYHP5r6wGjlF1rFgABdDV0g8EwD6Qbg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz", - "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==", + "version": "7.24.2", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.2.tgz", + "integrity": "sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.22.16", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", - "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz", + "integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==", "dev": true, - "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -372,35 +406,47 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.0.tgz", + "integrity": "sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.23.5", + "@babel/parser": "^7.24.0", + "@babel/types": "^7.24.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template/node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.17.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", - "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.16.7", - "@babel/generator": "^7.17.3", - "@babel/helper-environment-visitor": "^7.16.7", - "@babel/helper-function-name": "^7.16.7", - "@babel/helper-hoist-variables": "^7.16.7", - "@babel/helper-split-export-declaration": "^7.16.7", - "@babel/parser": "^7.17.3", - "@babel/types": "^7.17.0", + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -409,27 +455,39 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/generator": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz", - "integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==", + "version": "7.24.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz", + "integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/types": "^7.22.15", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/@babel/types": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz", + "integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.23.4", + "@babel/helper-validator-identifier": "^7.22.20", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/traverse/node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, - "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -446,18 +504,15 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@babel/types": { - "version": "7.22.19", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.19.tgz", - "integrity": "sha512-P7LAw/LbojPzkgp5oznjE6tQEIWbp4PkkfrZDINTro9zgBRtI324/EYsiSI7lhPbpIQ+DCeR2NNmMWANGGfZsg==", + "version": "7.17.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", + "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.19", + "@babel/helper-validator-identifier": "^7.16.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -915,36 +970,33 @@ "integrity": "sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg==" }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, - "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, - "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -953,15 +1005,13 @@ "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, - "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -1543,15 +1593,14 @@ "integrity": "sha512-DVUnuiWAX7/4ZvbzuHENUShEEV4G0M38mQ/+R8DpHxwpCSrtEaSRaUMwdyUSn/WVqR7wo9+jkLCxFjE5feCURQ==" }, "node_modules/@trivago/prettier-plugin-sort-imports": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.2.0.tgz", - "integrity": "sha512-YBepjbt+ZNBVmN3ev1amQH3lWCmHyt5qTbLCp/syXJRu/Kw2koXh44qayB1gMRxcL/gV8egmjN5xWSrYyfUtyw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.3.0.tgz", + "integrity": "sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==", "dev": true, - "license": "Apache-2.0", "dependencies": { "@babel/generator": "7.17.7", "@babel/parser": "^7.20.5", - "@babel/traverse": "7.17.3", + "@babel/traverse": "7.23.2", "@babel/types": "7.17.0", "javascript-natural-sort": "0.7.1", "lodash": "^4.17.21" @@ -1566,20 +1615,6 @@ } } }, - "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/types": { - "version": "7.17.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", - "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.16.7", - "to-fast-properties": "^2.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@types/accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.7.tgz", @@ -3372,7 +3407,6 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -4036,15 +4070,13 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" + "dev": true }, "node_modules/js-yaml": { "version": "4.1.0", @@ -4062,7 +4094,6 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, - "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -4082,6 +4113,18 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -4244,6 +4287,15 @@ "node": ">=10" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/mkdirp": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", @@ -4703,6 +4755,12 @@ "split2": "^4.1.0" } }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, "node_modules/pidtree": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz", @@ -5163,7 +5221,6 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", "dev": true, - "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -5413,7 +5470,6 @@ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -5432,6 +5488,20 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", diff --git a/package.json b/package.json index 4dfb3e8f..ea4dee0e 100644 --- a/package.json +++ b/package.json @@ -3,18 +3,19 @@ "private": true, "scripts": { "codegen": "echo '# GENERATED, DO NOT MODIFY\n' > schema.graphql && cat schema-*.graphql >> schema.graphql && sqd codegen && git add src/model/generated/*", - "migration:generate": "sqd down && sqd up && sqd migration:generate", + "migration:generate": "sqd down && sqd up && sqd migration:generate && git add db/migrations/*", + "generate": "npm-run-all codegen migration:generate", "build": "rm -rf lib && tsc", - "prettier-check": "prettier --check **/*.ts **/*.json", - "prettier-fix": "prettier --write **/*.ts **/*.json", + "prettier-check": "prettier --check src", + "prettier-fix": "prettier --write src", "setup": "sqd down && sqd up && sleep 2 && sqd migration:apply", "serve": "sqd serve", "process:arbitrum": "sqd process:arbitrum", "process:oeth": "sqd process:oeth", "process:ousd": "sqd process:ousd", "process:ogv": "sqd process:ogv", - "process:other": "sqd process:other", - "process": "npm-run-all --parallel process:arbitrum process:oeth process:ousd process:ogv process:other" + "process:mainnet": "sqd process:mainnet", + "process": "sqd process" }, "dependencies": { "@subsquid/archive-registry": "^3.3.0", @@ -47,6 +48,7 @@ "@types/uuid": "^9.0.2", "npm-run-all": "^4.1.5", "prettier": "^3.0.3", + "tsconfig-paths": "^4.2.0", "typescript": "~5.1.3" } } diff --git a/schema-general.graphql b/schema-general.graphql index ad74035a..bd16f2b5 100644 --- a/schema-general.graphql +++ b/schema-general.graphql @@ -93,7 +93,8 @@ type ERC20 @entity { Format: 'address' """ id: ID! - address: String! + chainId: Int! @index + address: String! @index name: String! decimals: Int! symbol: String! @@ -104,6 +105,7 @@ type ERC20Holder @entity { Format: 'address:account' """ id: ID! + chainId: Int! @index address: String! account: String! } @@ -113,6 +115,7 @@ type ERC20State @entity { Format: 'address:blockNumber' """ id: ID! + chainId: Int! @index timestamp: DateTime! @index blockNumber: Int! @index address: String! @@ -125,6 +128,7 @@ type ERC20Balance @entity { Format: 'address:account:blockNumber' """ id: ID! + chainId: Int! @index timestamp: DateTime! @index blockNumber: Int! @index address: String! @@ -132,6 +136,18 @@ type ERC20Balance @entity { balance: BigInt! } +type ERC20Transfer @entity { + id: ID! + chainId: Int! @index + txHash: String! + blockNumber: Int! + timestamp: DateTime! + address: String! @index + from: String! @index + to: String! @index + value: BigInt! +} + type CurvePool @entity { id: ID! address: String! @index @@ -240,7 +256,8 @@ type BridgeTransfer @entity { id: ID! # chain + log id timestamp: DateTime! @index blockNumber: Int! @index - txHash: String! @index + txHashIn: String! + txHashOut: String # Initially null messageId: String! @index bridge: String! @index sender: String! @index @@ -251,11 +268,13 @@ type BridgeTransfer @entity { tokenOut: String! amountIn: BigInt! amountOut: BigInt! + state: Int! } type BridgeTransferState @entity { id: ID! timestamp: DateTime! @index blockNumber: Int! @index + txHash: String! @index state: Int! -} \ No newline at end of file +} diff --git a/schema-oeth.graphql b/schema-oeth.graphql index 95bffdae..344d01fb 100644 --- a/schema-oeth.graphql +++ b/schema-oeth.graphql @@ -44,19 +44,6 @@ type OETHHistory @entity { type: HistoryType! } -""" -The History entity tracks events that change the balance of OETH for an address. -""" -type WOETHHistory @entity { - id: ID! - address: String! @index - value: BigInt! - timestamp: DateTime! - blockNumber: Int! @index - txHash: String! @index - type: HistoryType! -} - """ The Rebase entity tracks historical rebase events on the OETH contract. """ @@ -308,4 +295,4 @@ type OETHActivity @entity { fromSymbol: String toSymbol: String amount: BigInt -} \ No newline at end of file +} diff --git a/schema-ogv.graphql b/schema-ogv.graphql index 8a37fdba..fc39ed88 100644 --- a/schema-ogv.graphql +++ b/schema-ogv.graphql @@ -115,4 +115,4 @@ type OGVDailyStat @entity { marketCapUSD: Float! priceUSD: Float! holdersOverThreshold: Int! -} \ No newline at end of file +} diff --git a/schema-otoken.graphql b/schema-otoken.graphql new file mode 100644 index 00000000..74d6f95d --- /dev/null +++ b/schema-otoken.graphql @@ -0,0 +1,8 @@ +type OTokenVault @entity { + id: ID! + timestamp: DateTime! @index + blockNumber: Int! @index + chainId: Int! @index + address: String! @index + totalValue: BigInt! +} diff --git a/schema.graphql b/schema.graphql index 0634314b..330fcd34 100644 --- a/schema.graphql +++ b/schema.graphql @@ -95,7 +95,8 @@ type ERC20 @entity { Format: 'address' """ id: ID! - address: String! + chainId: Int! @index + address: String! @index name: String! decimals: Int! symbol: String! @@ -106,6 +107,7 @@ type ERC20Holder @entity { Format: 'address:account' """ id: ID! + chainId: Int! @index address: String! account: String! } @@ -115,6 +117,7 @@ type ERC20State @entity { Format: 'address:blockNumber' """ id: ID! + chainId: Int! @index timestamp: DateTime! @index blockNumber: Int! @index address: String! @@ -127,6 +130,7 @@ type ERC20Balance @entity { Format: 'address:account:blockNumber' """ id: ID! + chainId: Int! @index timestamp: DateTime! @index blockNumber: Int! @index address: String! @@ -134,6 +138,18 @@ type ERC20Balance @entity { balance: BigInt! } +type ERC20Transfer @entity { + id: ID! + chainId: Int! @index + txHash: String! + blockNumber: Int! + timestamp: DateTime! + address: String! @index + from: String! @index + to: String! @index + value: BigInt! +} + type CurvePool @entity { id: ID! address: String! @index @@ -242,7 +258,8 @@ type BridgeTransfer @entity { id: ID! # chain + log id timestamp: DateTime! @index blockNumber: Int! @index - txHash: String! @index + txHashIn: String! + txHashOut: String # Initially null messageId: String! @index bridge: String! @index sender: String! @index @@ -253,14 +270,17 @@ type BridgeTransfer @entity { tokenOut: String! amountIn: BigInt! amountOut: BigInt! + state: Int! } type BridgeTransferState @entity { id: ID! timestamp: DateTime! @index blockNumber: Int! @index + txHash: String! @index state: Int! -}""" +} +""" The OETH entity tracks the change in total supply of OETH over time. """ type OETH @entity { @@ -306,19 +326,6 @@ type OETHHistory @entity { type: HistoryType! } -""" -The History entity tracks events that change the balance of OETH for an address. -""" -type WOETHHistory @entity { - id: ID! - address: String! @index - value: BigInt! - timestamp: DateTime! - blockNumber: Int! @index - txHash: String! @index - type: HistoryType! -} - """ The Rebase entity tracks historical rebase events on the OETH contract. """ @@ -570,7 +577,8 @@ type OETHActivity @entity { fromSymbol: String toSymbol: String amount: BigInt -}type OGV @entity { +} +type OGV @entity { id: ID! timestamp: DateTime! @index blockNumber: Int! @index @@ -687,7 +695,16 @@ type OGVDailyStat @entity { marketCapUSD: Float! priceUSD: Float! holdersOverThreshold: Int! -}""" +} +type OTokenVault @entity { + id: ID! + timestamp: DateTime! @index + blockNumber: Int! @index + chainId: Int! @index + address: String! @index + totalValue: BigInt! +} +""" The OUSD entity tracks the change in total supply of OUSD over time. """ type OUSD @entity { diff --git a/squid-ousd.yaml b/squid-ousd.yaml new file mode 100644 index 00000000..5fc2e7dc --- /dev/null +++ b/squid-ousd.yaml @@ -0,0 +1,41 @@ +manifestVersion: subsquid.io/v0.1 +name: origin-ousd +version: 999 +description: 'Origin OUSD 🦑' +build: +deploy: + addons: + postgres: + secrets: + - RPC_ENDPOINT + - RPC_ENDPOINT_999 + - RPC_ENDPOINT_RETH + - RPC_BACKUP + - RPC_ARBITRUM_ENDPOINT + - RPC_ARBITRUM_ENV + processor: + - name: ousd-processor + cmd: [ "sqd", "process:ousd:prod" ] + env: + RPC_ENV: RPC_ENDPOINT_RETH + TS_NODE_BASEURL: './lib' + api: + env: + TS_NODE_BASEURL: './lib' + cmd: + - npx + - squid-graphql-server + - '--dumb-cache' + - in-memory + - '--dumb-cache-ttl' + - '1000' + - '--dumb-cache-size' + - '100' + - '--dumb-cache-max-age' + - '1000' +scale: + dedicated: true + addons: + postgres: + storage: 20G + profile: medium diff --git a/squid.yaml b/squid.yaml index bde7258b..e92b9221 100644 --- a/squid.yaml +++ b/squid.yaml @@ -14,31 +14,34 @@ deploy: - RPC_ARBITRUM_ENDPOINT - RPC_ARBITRUM_ENV processor: - # cmd: [ "node", "lib/main" ] - # env: - # RPC_ENV: RPC_ENDPOINT_999 - ################################ + - name: mainnet-processor + cmd: [ "sqd", "process:mainnet:prod" ] + env: + RPC_ENV: RPC_ENDPOINT_RETH + TS_NODE_BASEURL: './lib' - name: arbitrum-processor cmd: [ "sqd", "process:arbitrum:prod" ] env: RPC_ENV: RPC_ENDPOINT_RETH + TS_NODE_BASEURL: './lib' - name: oeth-processor cmd: [ "sqd", "process:oeth:prod" ] env: RPC_ENV: RPC_ENDPOINT_RETH - - name: ousd-processor - cmd: [ "sqd", "process:ousd:prod" ] - env: - RPC_ENV: RPC_ENDPOINT_RETH + TS_NODE_BASEURL: './lib' - name: ogv-processor cmd: [ "sqd", "process:ogv:prod" ] env: RPC_ENV: RPC_ENDPOINT_RETH - - name: other-processor - cmd: [ "sqd", "process:other:prod" ] + TS_NODE_BASEURL: './lib' + - name: ousd-processor + cmd: [ "sqd", "process:ousd:prod" ] env: RPC_ENV: RPC_ENDPOINT_RETH + TS_NODE_BASEURL: './lib' api: + env: + TS_NODE_BASEURL: './lib' cmd: - npx - squid-graphql-server diff --git a/src/arbitrum/erc20.ts b/src/arbitrum/erc20.ts new file mode 100644 index 00000000..73cd287e --- /dev/null +++ b/src/arbitrum/erc20.ts @@ -0,0 +1,11 @@ +import { createERC20Tracker } from '@templates/erc20' +import { WOETH_ARBITRUM_ADDRESS } from '@utils/addresses' + +const woethTransferProcessor = createERC20Tracker({ + from: 178662968, + address: WOETH_ARBITRUM_ADDRESS, +}) + +export const from = woethTransferProcessor.from +export const setup = woethTransferProcessor.setup +export const process = woethTransferProcessor.process diff --git a/src/arbitrum/index.ts b/src/arbitrum/index.ts new file mode 100644 index 00000000..de35cab2 --- /dev/null +++ b/src/arbitrum/index.ts @@ -0,0 +1 @@ +export * as erc20 from './erc20' diff --git a/src/main-arbitrum.ts b/src/main-arbitrum.ts index 33264d46..b9c72ad3 100644 --- a/src/main-arbitrum.ts +++ b/src/main-arbitrum.ts @@ -1,13 +1,15 @@ -import { KnownArchives } from '@subsquid/archive-registry/lib/chains' +import 'tsconfig-paths/register' +import { arbitrum } from 'viem/chains' +import { run } from '@processor' + +import { erc20 } from './arbitrum' import { ccip } from './oeth/processors/ccip' -import { run } from './processor' export const processor = { - archive: 'arbitrum' as KnownArchives, - rpcEnv: process.env.RPC_ARBITRUM_ENV, + chainId: arbitrum.id, stateSchema: 'arbitrum-processor', - processors: [ccip({ chainId: 42161 })], + processors: [erc20, ccip({ chainId: arbitrum.id })], postProcessors: [], validators: [], } diff --git a/src/main-mainnet.ts b/src/main-mainnet.ts new file mode 100644 index 00000000..9effac7d --- /dev/null +++ b/src/main-mainnet.ts @@ -0,0 +1,21 @@ +import 'tsconfig-paths/register' + +import { run } from '@processor' +import * as exchangeRates from '@shared/post-processors/exchange-rates' +import { processStatus } from '@templates/processor-status' + +import * as curve from './mainnet/processors/curve' +import { erc20s } from './mainnet/processors/erc20s' +import * as validate from './mainnet/validators/validate-mainnet' + +export const processor = { + stateSchema: 'mainnet-processor', + processors: [curve, ...erc20s()], + postProcessors: [exchangeRates, processStatus('other')], + validators: [validate], +} +export default processor + +if (require.main === module) { + run(processor) +} diff --git a/src/main-oeth.ts b/src/main-oeth.ts index e916ca2d..5aebb80d 100644 --- a/src/main-oeth.ts +++ b/src/main-oeth.ts @@ -1,3 +1,9 @@ +import 'tsconfig-paths/register' + +import { run } from '@processor' +import * as exchangeRatesPostProcessor from '@shared/post-processors/exchange-rates' +import { processStatus } from '@templates/processor-status' + import * as dailyStats from './oeth/post-processors/daily-stats' import * as oeth from './oeth/processors' import * as balancerMetaPoolStrategy from './oeth/processors/balancer-meta-pool' @@ -10,9 +16,6 @@ import * as morphoAave from './oeth/processors/morpho-aave' import * as strategies from './oeth/processors/strategies' import * as vault from './oeth/processors/vault' import * as validateOeth from './oeth/validators/validate-oeth' -import { run } from './processor' -import * as exchangeRatesPostProcessor from './shared/post-processors/exchange-rates' -import { processStatus } from './shared/processor-templates/processor-status' export const processor = { stateSchema: 'oeth-processor', diff --git a/src/main-ogv.ts b/src/main-ogv.ts index 753d66b7..18968b79 100644 --- a/src/main-ogv.ts +++ b/src/main-ogv.ts @@ -1,9 +1,12 @@ +import 'tsconfig-paths/register' + +import { run } from '@processor' +import { processStatus } from '@templates/processor-status' + import * as dailyStats from './ogv/post-processors/daily-stats' import * as governance from './ogv/post-processors/governance' import * as ogv from './ogv/processors/ogv' import * as ogvSupply from './ogv/processors/ogv-supply' -import { run } from './processor' -import { processStatus } from './shared/processor-templates/processor-status' export const processor = { stateSchema: 'ogv-processor', diff --git a/src/main-other.ts b/src/main-other.ts deleted file mode 100644 index 865ab8a6..00000000 --- a/src/main-other.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { run } from './processor' -import * as exchangeRates from './shared/post-processors/exchange-rates' -import * as liquidity from './shared/post-processors/liquidity' -import { processStatus } from './shared/processor-templates/processor-status' -import * as balancer from './shared/processors/balancer' -import * as curve from './shared/processors/curve' -import { erc20s } from './shared/processors/erc20s' -import * as liquiditySources from './shared/processors/liquidity-sources' -import * as maverick from './shared/processors/maverick' -import * as native from './shared/processors/native' -import * as sushiswap from './shared/processors/sushiswap' -import * as uniswap from './shared/processors/uniswap' -import * as validate from './shared/validators/validate-shared' - -sushiswap.initialize() -uniswap.initialize() - -export const processor = { - stateSchema: 'other-processor', - processors: [ - balancer, - curve, - maverick, - native, - ...erc20s(), - liquiditySources, - ], - postProcessors: [exchangeRates, liquidity, processStatus('other')], - validators: [validate], -} -export default processor - -if (require.main === module) { - run(processor) -} diff --git a/src/main-ousd.ts b/src/main-ousd.ts index 1b3edac6..d2a1ca32 100644 --- a/src/main-ousd.ts +++ b/src/main-ousd.ts @@ -1,14 +1,19 @@ +import 'tsconfig-paths/register' + +import { run } from '@processor' +import * as exchangeRates from '@shared/post-processors/exchange-rates' +import { processStatus } from '@templates/processor-status' + import * as dailyStats from './ousd/post-processors/daily-stats' +import * as curve from './ousd/processors/curve' +import { erc20s } from './ousd/processors/erc20s' import * as ousd from './ousd/processors/ousd' import * as strategies from './ousd/processors/strategies/strategies' import * as validateOusd from './ousd/validators/validate-ousd' -import { run } from './processor' -import * as exchangeRates from './shared/post-processors/exchange-rates' -import { processStatus } from './shared/processor-templates/processor-status' export const processor = { stateSchema: 'ousd-processor', - processors: [ousd, strategies], + processors: [ousd, strategies, curve, ...erc20s], postProcessors: [exchangeRates, dailyStats, processStatus('ousd')], validators: [validateOusd], } diff --git a/src/main.ts b/src/main.ts index d912d582..6a10002e 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,28 +1,16 @@ -import { uniq } from 'lodash' +import 'tsconfig-paths/register' +import { run } from '@processor' + +import arbitrum from './main-arbitrum' +import mainnet from './main-mainnet' import oeth from './main-oeth' import ogv from './main-ogv' -import other from './main-other' -import ousd from './main-ousd' -import { run } from './processor' -run({ - processors: uniq([ - ...oeth.processors, - ...ousd.processors, - ...ogv.processors, - ...other.processors, - ]), - postProcessors: uniq([ - ...oeth.postProcessors, - ...ousd.postProcessors, - ...ogv.postProcessors, - ...other.postProcessors, - ]), - validators: uniq([ - ...oeth.validators, - ...ousd.validators, - ...ogv.validators, - ...other.validators, - ]), -}) +// import ousd from './main-ousd' + +run(mainnet) +run(arbitrum) +run(oeth) +// run(ogv) +// run(ousd) diff --git a/src/mainnet/processors/balancer/balancer.ts b/src/mainnet/processors/balancer/balancer.ts new file mode 100644 index 00000000..1039d6a0 --- /dev/null +++ b/src/mainnet/processors/balancer/balancer.ts @@ -0,0 +1,114 @@ +import { Context } from '@processor' +import { CurrencyAddress } from '@shared/post-processors/exchange-rates/currencies' +import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { + createBalancerInitializer, + createBalancerProcessor, + createBalancerSetup, +} from '@templates/balancer' + +const ousdResetFrom = 11585978 +const oethDeployFrom = 16933090 + +const pools: { + name: string + poolSymbol: string + poolType: 'MetaStable' | 'ComposableStable' | 'Weighted' | 'Gyroscope' + poolAddress: string + poolId: string + from: number + tokens: + | [string, string] + | [string, string, string] + | [string, string, string, string] + rates?: [CurrencyAddress, CurrencyAddress][] +}[] = [ + // { + // name: 'Balancer rETH Stable Pool', + // poolSymbol: 'B-rETH-STABLE', + // poolType: 'MetaStable', + // poolAddress: '0x1e19cf2d73a72ef1332c882f20534b6519be0276', + // poolId: + // '0x1e19cf2d73a72ef1332c882f20534b6519be0276000200000000000000000112', + // tokens: [tokens.rETH, tokens.WETH], + // from: Math.max(13850000, oethDeployFrom), + // }, + // { + // name: 'wstETH-rETH-sfrxETH-BPT', + // poolSymbol: 'wstETH-rETH-sfrxETH-BPT', + // poolType: 'ComposableStable', + // poolAddress: '0x42ed016f826165c2e5976fe5bc3df540c5ad0af7', + // poolId: + // '0x42ed016f826165c2e5976fe5bc3df540c5ad0af700000000000000000000058b', + // tokens: [ + // '0x42ed016f826165c2e5976fe5bc3df540c5ad0af7', + // tokens.wstETH, + // tokens.sfrxETH, + // tokens.rETH, + // ], + // from: Math.max(17680000, oethDeployFrom), + // }, + // { + // name: 'Balancer wstETH-WETH Stable Pool', + // poolSymbol: 'wstETH-WETH-BPT', + // poolType: 'ComposableStable', + // poolAddress: '0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd', + // poolId: + // '0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2', + // tokens: [ + // tokens.wstETH, + // '0x93d199263632a4EF4Bb438F1feB99e57b4b5f0BD', + // tokens.WETH, + // ], + // from: Math.max(17920000, oethDeployFrom), + // }, + // { + // name: 'Balancer 80 BAL 20 WETH', + // poolSymbol: 'B-80BAL-20WETH', + // poolType: 'Weighted', + // poolAddress: '0x5c6ee304399dbdb9c8ef030ab642b10820db8f56', + // poolId: + // '0x5c6ee304399dbdb9c8ef030ab642b10820db8f56000200000000000000000014', + // from: Math.max(12370000, oethDeployFrom), + // tokens: [tokens.BAL, tokens.WETH], + // rates: [[tokens.BAL, tokens.ETH] as [CurrencyAddress, CurrencyAddress]], + // }, + // { + // name: 'Gyroscope ECLP wstETH/wETH', + // poolSymbol: 'ECLP-wstETH-wETH', + // poolAddress: '0xf01b0684c98cd7ada480bfdf6e43876422fa1fc1', + // poolId: + // '0xf01b0684c98cd7ada480bfdf6e43876422fa1fc10002000000000000000005de', + // poolType: 'Gyroscope', + // from: Math.max(18015100, oethDeployFrom), + // tokens: [tokens.wstETH, tokens.WETH], + // }, +] + +export const from = Math.min(...pools.map((p) => p.from)) + +export const setup = (processor: EvmBatchProcessor) => { + for (const pool of pools) { + createBalancerSetup(pool.from, processor) + } +} + +const initializers = pools.map((pool) => createBalancerInitializer(pool)) + +export const initialize = async (ctx: Context) => { + await Promise.all(initializers.map((p) => p(ctx))) +} + +const processors = pools.map((pool) => + createBalancerProcessor( + pool.poolAddress.toLowerCase(), + pool.poolId.toLowerCase(), + pool.poolType, + pool.from, + pool.rates, + ), +) + +export const process = async (ctx: Context) => { + await Promise.all(processors.map((p) => p(ctx))) +} diff --git a/src/shared/processor-templates/balancer/index.ts b/src/mainnet/processors/balancer/index.ts similarity index 100% rename from src/shared/processor-templates/balancer/index.ts rename to src/mainnet/processors/balancer/index.ts diff --git a/src/mainnet/processors/curve/curve.ts b/src/mainnet/processors/curve/curve.ts new file mode 100644 index 00000000..ca6d84c3 --- /dev/null +++ b/src/mainnet/processors/curve/curve.ts @@ -0,0 +1,103 @@ +import { Context } from '@processor' +import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { + createCurveInitializer, + createCurveProcessor, + createCurveSetup, +} from '@templates/curve' +import { tokens } from '@utils/addresses' + +const ousdResetFrom = 11585978 +const oethDeployFrom = 16933090 + +export const from = Math.min(ousdResetFrom, oethDeployFrom) + +const pools: (Parameters['0'] & + Parameters['0'])[] = [ + // Curve (OETH) + { + name: 'factory-v2-298: ETH/OETH', + address: '0x94B17476A93b3262d87B9a326965D1E91f9c13E7'.toLowerCase(), + from: Math.max(17130500, oethDeployFrom), + tokens: [tokens.ETH, tokens.OETH], + ratesToPull: [{ i: 1n, j: 0n, dx: 1000000000000000000n }], + }, + // { + // name: 'factory-crvusd-15: WETH/frxETH', + // address: '0x9c3b46c0ceb5b9e304fcd6d88fc50f7dd24b31bc', + // from: Math.max(17922938, oethDeployFrom), + // tokens: [tokens.WETH, tokens.frxETH], + // }, + // { + // name: 'steth: ETH/stETH', + // address: '0xdc24316b9ae028f1497c275eb9192a3ea0f67022', + // from: Math.max(11592551, oethDeployFrom), + // tokens: [tokens.ETH, tokens.stETH], + // }, + // { + // name: 'stETH-ng: ETH/stETH', + // address: '0x21e27a5e5513d6e65c4f830167390997aa84843a', + // from: Math.max(17272519, oethDeployFrom), + // tokens: [tokens.ETH, tokens.stETH], + // }, + // { + // name: 'frxeth: ETH/frxETH', + // address: '0xa1f8a6807c402e4a15ef4eba36528a3fed24e577', + // from: Math.max(15741010, oethDeployFrom), + // tokens: [tokens.ETH, tokens.frxETH], + // }, + // { + // name: 'factory-crypto-210: ETH/rETH', + // address: '0x0f3159811670c117c372428d4e69ac32325e4d0f', + // from: Math.max(16615906, oethDeployFrom), + // tokens: [tokens.ETH, tokens.rETH], + // }, + // { + // name: 'factory-v2-274: stETH/frxETH', + // address: '0x4d9f9d15101eec665f77210cb999639f760f831e', + // from: Math.max(16683219, oethDeployFrom), + // tokens: [tokens.stETH, tokens.frxETH], + // }, + // { + // name: 'factory-v2-117: WETH/stETH', + // address: '0x828b154032950c8ff7cf8085d841723db2696056', + // from: Math.max(14759666, oethDeployFrom), + // tokens: [tokens.WETH, tokens.stETH], + // }, + // { + // name: 'factory-v2-89: rETH/wstETH', + // address: '0x447ddd4960d9fdbf6af9a790560d0af76795cb08', + // from: Math.max(14258216, oethDeployFrom), + // tokens: [tokens.rETH, tokens.wstETH], + // }, + // { + // name: 'factory-crypto-218: rETH/frxETH', + // address: '0xe7c6e0a739021cdba7aac21b4b728779eef974d9', + // from: Math.max(16684327, oethDeployFrom), + // tokens: [tokens.rETH, tokens.frxETH], + // }, + // { + // name: 'factory-tricrypto-14: wstETH/rETH/sfrxETH', + // address: '0x2570f1bd5d2735314fc102eb12fc1afe9e6e7193', + // from: Math.max(18084222, oethDeployFrom), + // tokens: [tokens.wstETH, tokens.rETH, tokens.sfrxETH], + // }, +] + +export const setup = (processor: EvmBatchProcessor) => { + for (const pool of pools) { + createCurveSetup(pool.from, processor) + } +} + +const initializers = pools.map((pool) => createCurveInitializer(pool)) + +export const initialize = async (ctx: Context) => { + await Promise.all(initializers.map((p) => p(ctx))) +} + +const processors = pools.map((pool) => createCurveProcessor(pool)) + +export const process = async (ctx: Context) => { + await Promise.all(processors.map((p) => p(ctx))) +} diff --git a/src/shared/processor-templates/curve/index.ts b/src/mainnet/processors/curve/index.ts similarity index 100% rename from src/shared/processor-templates/curve/index.ts rename to src/mainnet/processors/curve/index.ts diff --git a/src/mainnet/processors/erc20s.ts b/src/mainnet/processors/erc20s.ts new file mode 100644 index 00000000..d1111cf6 --- /dev/null +++ b/src/mainnet/processors/erc20s.ts @@ -0,0 +1,124 @@ +import * as otoken from '@abi/otoken' +import { createERC20Tracker } from '@templates/erc20' +import { + OETH_ADDRESS, + OETH_DRIPPER_ADDRESS, + OETH_VAULT_ADDRESS, + OUSD_VAULT_ADDRESS, + TokenSymbol, + WOETH_ADDRESS, + oethStrategyArray, + ousdStrategyArray, + tokens, +} from '@utils/addresses' +import { logFilter } from '@utils/logFilter' + +// TODO: Would be nice if interested parties could register their desires here from other parts of the code, +// allowing multiple declarations of need without issue. + +let initialized = false + +const tracks: Record[0]> = { + // Origin Specific + OGN: { + // from: 15350225, // 6436154, + from: 16933090, // oeth deploy date + address: tokens.OGN, + accountFilter: [ + '0x2eae0cae2323167abf78462e0c0686865c67a655', // Origin: Team Distribution (starts at block 15350225) + '0xfe730b3cf80ca7b31905f70241f7c786baf443e3', // Origin: Investor Wallet + ], + intervalTracking: true, + }, + OGV: { + // from: 15350225, // 14439231, + from: 16933090, // oeth deploy date + address: tokens.OGV, + accountFilter: [ + '0x2eae0cae2323167abf78462e0c0686865c67a655', // Origin: Team Distribution (starts at block 15350225) + '0xfe730b3cf80ca7b31905f70241f7c786baf443e3', // Origin: Investor Wallet + ], + intervalTracking: true, + }, + OETH: { + from: 16935276, + address: tokens.OETH, + rebaseFilters: [ + logFilter({ + address: [OETH_ADDRESS], + topic0: [otoken.events.TotalSupplyUpdatedHighres.topic], + transaction: true, + range: { from: 16935276 }, + }), + ], + }, + wOETH: { + from: 16933090, + address: WOETH_ADDRESS, + }, + // OETH Related + WETH: { + from: 16933090, // oeth deploy date + address: tokens.WETH, + accountFilter: [ + ...oethStrategyArray, + OETH_VAULT_ADDRESS, + OETH_DRIPPER_ADDRESS, + // '0xa4e0faA58465A2D369aa21B3e42d43374c6F9613', // Uniswap wstETH/WETH + // '0x109830a1aaad605bbf02a9dfa7b0b92ec2fb7daa', // Uniswap rETH/WETH + ], + intervalTracking: true, + }, + // rETH: { + // from: 16933090, // oeth deploy date + // address: tokens.rETH, + // accountFilter: [ + // ...oethStrategyArray, + // OETH_VAULT_ADDRESS, + // '0xa4e0faA58465A2D369aa21B3e42d43374c6F9613', // Uniswap rETH/WETH + // '0x553e9c493678d8606d6a5ba284643db2110df823', // Uniswap rETH/WETH + // ], + // intervalTracking: true, + // }, + // wstETH: { + // from: 16933090, // oeth deploy date + // address: tokens.wstETH, + // accountFilter: [ + // ...oethStrategyArray, + // OETH_VAULT_ADDRESS, + // '0x109830a1aaad605bbf02a9dfa7b0b92ec2fb7daa', // Uniswap wstETH/WETH + // ], + // intervalTracking: true, + // }, + // stETH: { + // from: 16933090, // oeth deploy date + // address: tokens.stETH, + // accountFilter: [...oethStrategyArray, OETH_VAULT_ADDRESS], + // intervalTracking: true, + // }, + // frxETH: { + // from: 16933090, // oeth deploy date + // address: tokens.frxETH, + // accountFilter: [...oethStrategyArray, OETH_VAULT_ADDRESS], + // intervalTracking: true, + // }, +} + +// This is a function to allow others to subscribe to balance tracking +export const erc20s = () => { + initialized = true + return Object.values(tracks).map(createERC20Tracker) +} + +export const addERC20Processing = (symbol: TokenSymbol, account: string) => { + if (initialized) { + throw new Error('erc20s already initialized, check load order') + } + const track = tracks[symbol] + if (track) { + // If there is no `accountFilter` then it is OK to have this as a noop. (we already want everything) + track.accountFilter?.push(account) + } else { + throw new Error(`Symbol ${symbol} not added to \`tracks\``) + } +} diff --git a/src/shared/processors/liquidity-sources.ts b/src/mainnet/processors/liquidity-sources.ts similarity index 93% rename from src/shared/processors/liquidity-sources.ts rename to src/mainnet/processors/liquidity-sources.ts index a1761ea9..3737b9a1 100644 --- a/src/shared/processors/liquidity-sources.ts +++ b/src/mainnet/processors/liquidity-sources.ts @@ -1,5 +1,5 @@ -import { LiquiditySource, LiquiditySourceType } from '../../model' -import { Context } from '../../processor' +import { LiquiditySource, LiquiditySourceType } from '@model' +import { Context } from '@processor' const sources = new Map() diff --git a/src/shared/processors/maverick.ts b/src/mainnet/processors/maverick.ts similarity index 56% rename from src/shared/processors/maverick.ts rename to src/mainnet/processors/maverick.ts index d6fbee79..51f08a7f 100644 --- a/src/shared/processors/maverick.ts +++ b/src/mainnet/processors/maverick.ts @@ -1,12 +1,10 @@ +import { Context } from '@processor' import { EvmBatchProcessor } from '@subsquid/evm-processor' - -import { Context } from '../../processor' -import { tokens } from '../../utils/addresses' import { createMaverickInitializer, createMaverickProcessor, createMaverickSetup, -} from '../processor-templates/maverick' +} from '@templates/maverick' const oethDeployFrom = 16933090 @@ -14,24 +12,24 @@ export const from = Math.min(oethDeployFrom) const pools: (Parameters['0'] & Parameters['0'])[] = [ - { - name: 'wstETH-ETH', - address: '0x0eb1c92f9f5ec9d817968afddb4b46c564cdedbe', - from: Math.max(17216724, oethDeployFrom), - tokens: [tokens.wstETH, tokens.ETH], - }, - { - name: 'rETH-ETH', - address: '0xeb061a4e1ad3f1983655281cb8019ebbf8b30b29', - from: Math.max(17216790, oethDeployFrom), - tokens: [tokens.rETH, tokens.ETH], - }, - { - name: 'OETH-ETH', - address: '0xa51822839bfa4685b27ad60305264a37eae28a68', - from: Math.max(17444830, oethDeployFrom), - tokens: [tokens.OETH, tokens.ETH], - }, + // { + // name: 'wstETH-ETH', + // address: '0x0eb1c92f9f5ec9d817968afddb4b46c564cdedbe', + // from: Math.max(17216724, oethDeployFrom), + // tokens: [tokens.wstETH, tokens.ETH], + // }, + // { + // name: 'rETH-ETH', + // address: '0xeb061a4e1ad3f1983655281cb8019ebbf8b30b29', + // from: Math.max(17216790, oethDeployFrom), + // tokens: [tokens.rETH, tokens.ETH], + // }, + // { + // name: 'OETH-ETH', + // address: '0xa51822839bfa4685b27ad60305264a37eae28a68', + // from: Math.max(17444830, oethDeployFrom), + // tokens: [tokens.OETH, tokens.ETH], + // }, ] export const setup = (processor: EvmBatchProcessor) => { diff --git a/src/shared/processors/native.ts b/src/mainnet/processors/native.ts similarity index 84% rename from src/shared/processors/native.ts rename to src/mainnet/processors/native.ts index 70be1433..c68c258c 100644 --- a/src/shared/processors/native.ts +++ b/src/mainnet/processors/native.ts @@ -1,16 +1,16 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' import { minBy } from 'lodash' -import { NativeBalance } from '../../model' -import { Context } from '../../processor' +import { NativeBalance } from '@model' +import { Context } from '@processor' +import { EvmBatchProcessor } from '@subsquid/evm-processor' import { OETH_VAULT_ADDRESS, OUSD_VAULT_ADDRESS, oethStrategyArray, ousdStrategyArray, -} from '../../utils/addresses' -import { blockFrequencyUpdater } from '../../utils/blockFrequencyUpdater' -import { getNativeBalances } from '../../utils/nativeBalance' +} from '@utils/addresses' +import { blockFrequencyUpdater } from '@utils/blockFrequencyUpdater' +import { getNativeBalances } from '@utils/nativeBalance' /** * We end up with a lot of initial 0 balance entities. @@ -32,11 +32,13 @@ const tracks = [ export const from = minBy(tracks, 'from')?.from ?? 19072024 export const setup = (processor: EvmBatchProcessor) => { + if (!tracks.length) return processor.includeAllBlocks({ from }) } const updater = blockFrequencyUpdater({ from }) export const process = async (ctx: Context) => { + if (!tracks.length) return const results: NativeBalance[] = [] await updater(ctx, async (ctx: Context, block: Context['blocks'][number]) => { const addresses = tracks diff --git a/src/shared/processors/sushiswap.ts b/src/mainnet/processors/sushiswap.ts similarity index 84% rename from src/shared/processors/sushiswap.ts rename to src/mainnet/processors/sushiswap.ts index d2536831..d5168aed 100644 --- a/src/shared/processors/sushiswap.ts +++ b/src/mainnet/processors/sushiswap.ts @@ -1,5 +1,6 @@ -import { LiquiditySourceType } from '../../model' -import { addresses } from '../../utils/addresses' +import { LiquiditySourceType } from '@model' +import { addresses } from '@utils/addresses' + import { addERC20Processing } from './erc20s' import { registerLiquiditySource } from './liquidity-sources' diff --git a/src/shared/processors/uniswap.ts b/src/mainnet/processors/uniswap.ts similarity index 89% rename from src/shared/processors/uniswap.ts rename to src/mainnet/processors/uniswap.ts index 74b2a79c..3c7d2ccd 100644 --- a/src/shared/processors/uniswap.ts +++ b/src/mainnet/processors/uniswap.ts @@ -1,5 +1,6 @@ -import { LiquiditySourceType } from '../../model' -import { addresses } from '../../utils/addresses' +import { LiquiditySourceType } from '@model' +import { addresses } from '@utils/addresses' + import { addERC20Processing } from './erc20s' import { registerLiquiditySource } from './liquidity-sources' diff --git a/src/mainnet/validators/validate-mainnet.ts b/src/mainnet/validators/validate-mainnet.ts new file mode 100644 index 00000000..64ff5c93 --- /dev/null +++ b/src/mainnet/validators/validate-mainnet.ts @@ -0,0 +1,97 @@ +import assert from 'assert' +import { sortBy } from 'lodash' + +import { ERC20Balance, ERC20State } from '@model' +import { Block, Context } from '@processor' +import { Entity, EntityClass } from '@subsquid/typeorm-store' +import { env } from '@utils/env' +import { jsonify } from '@utils/jsonify' + +export const name = 'validate-shared' + +let firstBlock = true + +export const process = async (ctx: Context) => { + if (env.BLOCK_FROM) return + for (const block of ctx.blocks) { + await validateExpectations(ctx, block, ERC20State, expectations.erc20States) + await validateExpectations( + ctx, + block, + ERC20Balance, + expectations.erc20Balances, + ) + firstBlock = false + } +} + +const validateExpectations = async < + T extends Entity & { + timestamp: string + blockNumber: number + }, +>( + ctx: Context, + block: Block, + Class: EntityClass, + expectations?: T[], +) => { + if (!expectations) return + if (firstBlock) { + while (expectations[0]?.blockNumber < block.header.height) { + const entity = expectations.shift()! + await validateExpectation(ctx, Class, entity) + } + } + assert( + !expectations.length || expectations[0]?.blockNumber >= block.header.height, + 'Something is missing', + ) + while (expectations[0]?.blockNumber === block.header.height) { + const entity = expectations.shift()! + await validateExpectation(ctx, Class, entity) + } +} + +const validateExpectation = async < + T extends Entity & { + timestamp: string + blockNumber: number + }, +>( + ctx: Context, + Class: EntityClass, + expectation: T, +) => { + const actual = await ctx.store.findOne(Class, { + where: { id: expectation.id }, + }) + assert( + actual, + `Expected entity does not exist: Entity=${Class.name} id=${expectation.id}`, + ) + expectation.timestamp = new Date(expectation.timestamp).toJSON() + // We decide to only care about float decimal accuracy to the 8th. + assert.deepEqual( + JSON.parse( + jsonify(actual, (_key, value) => + typeof value === 'number' ? Number(value.toFixed(8)) : value, + ), + ), + JSON.parse( + jsonify(expectation, (_key, value) => + typeof value === 'number' ? Number(value.toFixed(8)) : value, + ), + ), + ) + ctx.log.info(`Validated entity: Entity=${Class.name} id=${expectation.id}`) +} + +const e = (arr: any[]) => { + return sortBy(arr, (v) => v.blockNumber) +} + +const expectations = { + erc20States: e([]), // TODO: Fill me up? + erc20Balances: e([]), +} as const diff --git a/src/model/generated/bridgeTransfer.model.ts b/src/model/generated/bridgeTransfer.model.ts index 0afbd902..bd17c25a 100644 --- a/src/model/generated/bridgeTransfer.model.ts +++ b/src/model/generated/bridgeTransfer.model.ts @@ -18,9 +18,11 @@ export class BridgeTransfer { @Column_("int4", {nullable: false}) blockNumber!: number - @Index_() @Column_("text", {nullable: false}) - txHash!: string + txHashIn!: string + + @Column_("text", {nullable: true}) + txHashOut!: string | undefined | null @Index_() @Column_("text", {nullable: false}) @@ -56,4 +58,7 @@ export class BridgeTransfer { @Column_("numeric", {transformer: marshal.bigintTransformer, nullable: false}) amountOut!: bigint + + @Column_("int4", {nullable: false}) + state!: number } diff --git a/src/model/generated/bridgeTransferState.model.ts b/src/model/generated/bridgeTransferState.model.ts index 933b4663..a9c7a829 100644 --- a/src/model/generated/bridgeTransferState.model.ts +++ b/src/model/generated/bridgeTransferState.model.ts @@ -17,6 +17,10 @@ export class BridgeTransferState { @Column_("int4", {nullable: false}) blockNumber!: number + @Index_() + @Column_("text", {nullable: false}) + txHash!: string + @Column_("int4", {nullable: false}) state!: number } diff --git a/src/model/generated/erc20.model.ts b/src/model/generated/erc20.model.ts index 35530660..37998202 100644 --- a/src/model/generated/erc20.model.ts +++ b/src/model/generated/erc20.model.ts @@ -1,4 +1,4 @@ -import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_} from "typeorm" +import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, Index as Index_} from "typeorm" @Entity_() export class ERC20 { @@ -12,6 +12,11 @@ export class ERC20 { @PrimaryColumn_() id!: string + @Index_() + @Column_("int4", {nullable: false}) + chainId!: number + + @Index_() @Column_("text", {nullable: false}) address!: string diff --git a/src/model/generated/erc20Balance.model.ts b/src/model/generated/erc20Balance.model.ts index f78a6524..cba53f3d 100644 --- a/src/model/generated/erc20Balance.model.ts +++ b/src/model/generated/erc20Balance.model.ts @@ -13,6 +13,10 @@ export class ERC20Balance { @PrimaryColumn_() id!: string + @Index_() + @Column_("int4", {nullable: false}) + chainId!: number + @Index_() @Column_("timestamp with time zone", {nullable: false}) timestamp!: Date diff --git a/src/model/generated/erc20Holder.model.ts b/src/model/generated/erc20Holder.model.ts index c39d5612..8515f6f7 100644 --- a/src/model/generated/erc20Holder.model.ts +++ b/src/model/generated/erc20Holder.model.ts @@ -1,4 +1,4 @@ -import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_} from "typeorm" +import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, Index as Index_} from "typeorm" @Entity_() export class ERC20Holder { @@ -12,6 +12,10 @@ export class ERC20Holder { @PrimaryColumn_() id!: string + @Index_() + @Column_("int4", {nullable: false}) + chainId!: number + @Column_("text", {nullable: false}) address!: string diff --git a/src/model/generated/erc20State.model.ts b/src/model/generated/erc20State.model.ts index 3d2dd72d..8e1ac6b5 100644 --- a/src/model/generated/erc20State.model.ts +++ b/src/model/generated/erc20State.model.ts @@ -13,6 +13,10 @@ export class ERC20State { @PrimaryColumn_() id!: string + @Index_() + @Column_("int4", {nullable: false}) + chainId!: number + @Index_() @Column_("timestamp with time zone", {nullable: false}) timestamp!: Date diff --git a/src/model/generated/woethHistory.model.ts b/src/model/generated/erc20Transfer.model.ts similarity index 69% rename from src/model/generated/woethHistory.model.ts rename to src/model/generated/erc20Transfer.model.ts index 2686e34c..268efbcd 100644 --- a/src/model/generated/woethHistory.model.ts +++ b/src/model/generated/erc20Transfer.model.ts @@ -1,13 +1,9 @@ import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, Index as Index_} from "typeorm" import * as marshal from "./marshal" -import {HistoryType} from "./_historyType" -/** - * The History entity tracks events that change the balance of OETH for an address. - */ @Entity_() -export class WOETHHistory { - constructor(props?: Partial) { +export class ERC20Transfer { + constructor(props?: Partial) { Object.assign(this, props) } @@ -15,23 +11,30 @@ export class WOETHHistory { id!: string @Index_() + @Column_("int4", {nullable: false}) + chainId!: number + @Column_("text", {nullable: false}) - address!: string + txHash!: string - @Column_("numeric", {transformer: marshal.bigintTransformer, nullable: false}) - value!: bigint + @Column_("int4", {nullable: false}) + blockNumber!: number @Column_("timestamp with time zone", {nullable: false}) timestamp!: Date @Index_() - @Column_("int4", {nullable: false}) - blockNumber!: number + @Column_("text", {nullable: false}) + address!: string @Index_() @Column_("text", {nullable: false}) - txHash!: string + from!: string - @Column_("varchar", {length: 8, nullable: false}) - type!: HistoryType + @Index_() + @Column_("text", {nullable: false}) + to!: string + + @Column_("numeric", {transformer: marshal.bigintTransformer, nullable: false}) + value!: bigint } diff --git a/src/model/generated/index.ts b/src/model/generated/index.ts index 59bf54e3..a52ee4c9 100644 --- a/src/model/generated/index.ts +++ b/src/model/generated/index.ts @@ -8,6 +8,7 @@ export * from "./erc20.model" export * from "./erc20Holder.model" export * from "./erc20State.model" export * from "./erc20Balance.model" +export * from "./erc20Transfer.model" export * from "./curvePool.model" export * from "./curvePoolBalance.model" export * from "./curvePoolRate.model" @@ -27,7 +28,6 @@ export * from "./oethAddress.model" export * from "./_rebasingOption" export * from "./oethHistory.model" export * from "./_historyType" -export * from "./woethHistory.model" export * from "./oethRebase.model" export * from "./oethRebaseOption.model" export * from "./oethapy.model" @@ -55,6 +55,7 @@ export * from "./_ogvProposalState" export * from "./ogvProposalVote.model" export * from "./_ogvVoteType" export * from "./ogvDailyStat.model" +export * from "./oTokenVault.model" export * from "./ousd.model" export * from "./ousdAsset.model" export * from "./ousdAddress.model" diff --git a/src/model/generated/oTokenVault.model.ts b/src/model/generated/oTokenVault.model.ts new file mode 100644 index 00000000..9f45ec80 --- /dev/null +++ b/src/model/generated/oTokenVault.model.ts @@ -0,0 +1,31 @@ +import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, Index as Index_} from "typeorm" +import * as marshal from "./marshal" + +@Entity_() +export class OTokenVault { + constructor(props?: Partial) { + Object.assign(this, props) + } + + @PrimaryColumn_() + id!: string + + @Index_() + @Column_("timestamp with time zone", {nullable: false}) + timestamp!: Date + + @Index_() + @Column_("int4", {nullable: false}) + blockNumber!: number + + @Index_() + @Column_("int4", {nullable: false}) + chainId!: number + + @Index_() + @Column_("text", {nullable: false}) + address!: string + + @Column_("numeric", {transformer: marshal.bigintTransformer, nullable: false}) + totalValue!: bigint +} diff --git a/src/oeth/post-processors/daily-stats/daily-stats.ts b/src/oeth/post-processors/daily-stats/daily-stats.ts index 9cb62063..729417fe 100644 --- a/src/oeth/post-processors/daily-stats/daily-stats.ts +++ b/src/oeth/post-processors/daily-stats/daily-stats.ts @@ -1,4 +1,3 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' import dayjs from 'dayjs' import utc from 'dayjs/plugin/utc' import { @@ -24,9 +23,10 @@ import { OETHStrategyDailyStat, OETHStrategyHoldingDailyStat, OETHVault, -} from '../../../model' -import { Context } from '../../../processor' -import { applyCoingeckoData } from '../../../utils/coingecko' +} from '@model' +import { Context } from '@processor' +import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { applyCoingeckoData } from '@utils/coingecko' dayjs.extend(utc) diff --git a/src/oeth/processors/balancer-meta-pool.ts b/src/oeth/processors/balancer-meta-pool.ts index cc501b75..0df9c87b 100644 --- a/src/oeth/processors/balancer-meta-pool.ts +++ b/src/oeth/processors/balancer-meta-pool.ts @@ -1,14 +1,14 @@ +import * as balancerMetaPoolStrategy from '@abi/balancer-meta-pool-strategy' +import * as metaStablePool from '@abi/balancer-meta-stable-pool' +import * as baseRewardPool4626 from '@abi/base-reward-pool-4626' +import { OETHBalancerMetaPoolStrategy } from '@model' +import { Context } from '@processor' +import { ensureExchangeRates } from '@shared/post-processors/exchange-rates' import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { getBalancerStrategyHoldings } from '@templates/strategy/strategy-balancer' +import { RETH_ADDRESS, WETH_ADDRESS } from '@utils/addresses' +import { getLatestEntity } from '@utils/utils' -import * as balancerMetaPoolStrategy from '../../abi/balancer-meta-pool-strategy' -import * as metaStablePool from '../../abi/balancer-meta-stable-pool' -import * as baseRewardPool4626 from '../../abi/base-reward-pool-4626' -import { OETHBalancerMetaPoolStrategy } from '../../model' -import { Context } from '../../processor' -import { ensureExchangeRates } from '../../shared/post-processors/exchange-rates' -import { getBalancerStrategyHoldings } from '../../shared/processor-templates/strategy/strategy-balancer' -import { RETH_ADDRESS, WETH_ADDRESS } from '../../utils/addresses' -import { getLatestEntity } from '../../utils/utils' import { oethStrategies } from './strategies' const strategyDeployBlock = 18156219 diff --git a/src/oeth/processors/ccip.ts b/src/oeth/processors/ccip.ts index c0897e86..35c6895b 100644 --- a/src/oeth/processors/ccip.ts +++ b/src/oeth/processors/ccip.ts @@ -1,12 +1,11 @@ +import * as ccipOffRampAbi from '@abi/ccip-evm2evmofframp' +import * as ccipOnRampAbi from '@abi/ccip-evm2evmonramp' +import * as ccipRouter from '@abi/ccip-router' +import * as erc20Abi from '@abi/erc20' +import { BridgeTransfer, BridgeTransferState } from '@model' +import { Context } from '@processor' import { EvmBatchProcessor } from '@subsquid/evm-processor' - -import * as ccipOffRampAbi from '../../abi/ccip-evm2evmofframp' -import * as ccipOnRampAbi from '../../abi/ccip-evm2evmonramp' -import * as ccipRouter from '../../abi/ccip-router' -import * as erc20Abi from '../../abi/erc20' -import { BridgeTransfer, BridgeTransferState } from '../../model' -import { Context } from '../../processor' -import { logFilter } from '../../utils/logFilter' +import { logFilter } from '@utils/logFilter' // Code Reference: https://github.com/smartcontractkit/smart-contract-examples/tree/main/ccip-offchain // https://github.com/smartcontractkit/smart-contract-examples/blob/main/ccip-offchain/typescript/src/get-status.ts @@ -105,20 +104,31 @@ export const ccip = (params: { chainId: 1 | 42161 }) => { id: data.messageId, blockNumber: block.header.height, timestamp: new Date(block.header.timestamp), + txHash: log.transactionHash, state: data.state, }) result.bridgeTransferStates.set(state.id, state) - console.log(state) + + // A `BridgeTransfer` may already exist. If so, we should update it. + const bridgeTransfer = await ctx.store.findOneBy(BridgeTransfer, { + messageId: data.messageId, + }) + if (bridgeTransfer) { + bridgeTransfer.txHashOut = log.transactionHash + bridgeTransfer.state = data.state + result.transfers.set(state.id, bridgeTransfer) + } + // console.log(state) } if (transfersToLockReleasePool.matches(log)) { - console.log('match transfersToOnramp') + // console.log('match transfersToOnramp') const logSendRequested = block.logs.find( (l) => log.transactionHash === l.transactionHash && ccipSendRequested.matches(l), ) if (logSendRequested) { - console.log('match ccipSendRequested') + // console.log('match ccipSendRequested') const data = ccipOnRampAbi.events.CCIPSendRequested.decode(logSendRequested) const message = data.message @@ -126,12 +136,21 @@ export const ccip = (params: { chainId: 1 | 42161 }) => { logSendRequested.transaction!.input, ) - for (const tokenAmount of message.tokenAmounts) { + // A `BridgeTransferState` may already exist. + // If so, we should pull the `state` for it. + const bridgeTransferState = await ctx.store.get( + BridgeTransferState, + message.messageId, + ) + + for (let i = 0; i < message.tokenAmounts.length; i++) { + const tokenAmount = message.tokenAmounts[i] const transfer = new BridgeTransfer({ - id: `${params.chainId}-${log.id}`, + id: `${message.messageId}-${i}`, blockNumber: block.header.height, timestamp: new Date(block.header.timestamp), - txHash: log.transactionHash, + txHashIn: log.transactionHash, + txHashOut: null, messageId: message.messageId, bridge: 'ccip', chainIn: params.chainId, @@ -145,8 +164,9 @@ export const ccip = (params: { chainId: 1 | 42161 }) => { amountOut: tokenAmount.amount, sender: message.sender.toLowerCase(), receiver: message.receiver.toLowerCase(), + state: bridgeTransferState?.state ?? 0, }) - console.log(transfer) + // console.log(transfer) result.transfers.set(transfer.id, transfer) } } @@ -154,7 +174,7 @@ export const ccip = (params: { chainId: 1 | 42161 }) => { } } - await ctx.store.insert([...result.transfers.values()]) + await ctx.store.upsert([...result.transfers.values()]) await ctx.store.upsert([...result.bridgeTransferStates.values()]) } diff --git a/src/oeth/processors/curve-lp.ts b/src/oeth/processors/curve-lp.ts index 06920a24..019ea1d9 100644 --- a/src/oeth/processors/curve-lp.ts +++ b/src/oeth/processors/curve-lp.ts @@ -1,16 +1,16 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' import { pad } from 'viem' -import * as baseRewardPool from '../../abi/base-reward-pool' -import * as curveLpToken from '../../abi/curve-lp-token' -import { OETHCurveLP } from '../../model' -import { Context } from '../../processor' +import * as baseRewardPool from '@abi/base-reward-pool' +import * as curveLpToken from '@abi/curve-lp-token' +import { OETHCurveLP } from '@model' +import { Context } from '@processor' +import { EvmBatchProcessor } from '@subsquid/evm-processor' import { OETH_CONVEX_ADDRESS, OETH_CURVE_LP_ADDRESS, OETH_CURVE_REWARD_LP_ADDRESS, -} from '../../utils/addresses' -import { getLatestEntity } from '../../utils/utils' +} from '@utils/addresses' +import { getLatestEntity } from '@utils/utils' interface ProcessResult { curveLPs: OETHCurveLP[] diff --git a/src/oeth/processors/dripper.ts b/src/oeth/processors/dripper.ts index 871cd257..68e3d74d 100644 --- a/src/oeth/processors/dripper.ts +++ b/src/oeth/processors/dripper.ts @@ -1,13 +1,13 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' import { pad } from 'viem' -import * as dripperAbi from '../../abi/dripper' -import * as erc20 from '../../abi/erc20' -import { OETHDripper } from '../../model' -import { Context } from '../../processor' -import { ensureExchangeRate } from '../../shared/post-processors/exchange-rates' -import { OETH_DRIPPER_ADDRESS, WETH_ADDRESS } from '../../utils/addresses' -import { getLatestEntity, trackAddressBalances } from '../../utils/utils' +import * as dripperAbi from '@abi/dripper' +import * as erc20 from '@abi/erc20' +import { OETHDripper } from '@model' +import { Context } from '@processor' +import { ensureExchangeRate } from '@shared/post-processors/exchange-rates' +import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { OETH_DRIPPER_ADDRESS, WETH_ADDRESS } from '@utils/addresses' +import { getLatestEntity, trackAddressBalances } from '@utils/utils' interface ProcessResult { drippers: OETHDripper[] diff --git a/src/oeth/processors/exchange-rates.ts b/src/oeth/processors/exchange-rates.ts index 3750a5c3..39a22dd3 100644 --- a/src/oeth/processors/exchange-rates.ts +++ b/src/oeth/processors/exchange-rates.ts @@ -1,8 +1,7 @@ +import { Context } from '@processor' +import { ensureExchangeRates } from '@shared/post-processors/exchange-rates' import { EvmBatchProcessor } from '@subsquid/evm-processor' - -import { Context } from '../../processor' -import { ensureExchangeRates } from '../../shared/post-processors/exchange-rates' -import { blockFrequencyUpdater } from '../../utils/blockFrequencyUpdater' +import { blockFrequencyUpdater } from '@utils/blockFrequencyUpdater' export const from = 16933090 // OETH Deploy diff --git a/src/oeth/processors/frax-staking.ts b/src/oeth/processors/frax-staking.ts index 9ad73378..a37fd685 100644 --- a/src/oeth/processors/frax-staking.ts +++ b/src/oeth/processors/frax-staking.ts @@ -1,14 +1,11 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' import { pad } from 'viem' -import * as sfrxETH from '../../abi/sfrx-eth' -import { OETHFraxStaking } from '../../model' -import { Context } from '../../processor' -import { ensureExchangeRate } from '../../shared/post-processors/exchange-rates' -import { - OETH_FRAX_STAKING_ADDRESS, - SFRXETH_ADDRESS, -} from '../../utils/addresses' +import * as sfrxETH from '@abi/sfrx-eth' +import { OETHFraxStaking } from '@model' +import { Context } from '@processor' +import { ensureExchangeRate } from '@shared/post-processors/exchange-rates' +import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { OETH_FRAX_STAKING_ADDRESS, SFRXETH_ADDRESS } from '@utils/addresses' interface ProcessResult { fraxStakings: OETHFraxStaking[] diff --git a/src/oeth/processors/morpho-aave.ts b/src/oeth/processors/morpho-aave.ts index 41a1d8c8..0c77cca2 100644 --- a/src/oeth/processors/morpho-aave.ts +++ b/src/oeth/processors/morpho-aave.ts @@ -1,12 +1,12 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' import { pad } from 'viem' -import * as erc20 from '../../abi/erc20' -import * as initializableAbstractStrategy from '../../abi/initializable-abstract-strategy' -import { OETHMorphoAave } from '../../model' -import { Context } from '../../processor' -import { ensureExchangeRate } from '../../shared/post-processors/exchange-rates' -import { OETH_MORPHO_AAVE_ADDRESS, WETH_ADDRESS } from '../../utils/addresses' +import * as erc20 from '@abi/erc20' +import * as initializableAbstractStrategy from '@abi/initializable-abstract-strategy' +import { OETHMorphoAave } from '@model' +import { Context } from '@processor' +import { ensureExchangeRate } from '@shared/post-processors/exchange-rates' +import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { OETH_MORPHO_AAVE_ADDRESS, WETH_ADDRESS } from '@utils/addresses' interface ProcessResult { morphoAaves: OETHMorphoAave[] diff --git a/src/oeth/processors/oeth.ts b/src/oeth/processors/oeth.ts index 60fa8a6d..f42e2218 100644 --- a/src/oeth/processors/oeth.ts +++ b/src/oeth/processors/oeth.ts @@ -7,12 +7,8 @@ import { OETHHistory, OETHRebase, OETHRebaseOption, - WOETHHistory, -} from '../../model' -import { - createOTokenProcessor, - createOTokenSetup, -} from '../../shared/processor-templates/otoken' +} from '@model' +import { createOTokenProcessor, createOTokenSetup } from '@templates/otoken' import { ETH_ADDRESS, FRXETH_ADDRESS, @@ -24,7 +20,7 @@ import { WETH_ADDRESS, WOETH_ADDRESS, WSTETH_ADDRESS, -} from '../../utils/addresses' +} from '@utils/addresses' export const from = 16933090 // https://etherscan.io/tx/0x3b4ece4f5fef04bf7ceaec4f6c6edf700540d7597589f8da0e3a8c94264a3b50 @@ -39,6 +35,8 @@ export const setup = createOTokenSetup({ }) export const process = createOTokenProcessor({ + from, + vaultFrom: 17084107, OTOKEN_ADDRESS: OETH_ADDRESS, WOTOKEN_ADDRESS: WOETH_ADDRESS, OTOKEN_VAULT_ADDRESS: OETH_VAULT_ADDRESS, @@ -56,7 +54,6 @@ export const process = createOTokenProcessor({ OTokenAsset: OETHAsset, OTokenAddress: OETHAddress, OTokenHistory: OETHHistory, - WOTokenHistory: WOETHHistory, OTokenAPY: OETHAPY, OTokenRebase: OETHRebase, OTokenRebaseOption: OETHRebaseOption, diff --git a/src/oeth/processors/strategies/strategies.ts b/src/oeth/processors/strategies/strategies.ts index 843b66ec..21ab7f0d 100644 --- a/src/oeth/processors/strategies/strategies.ts +++ b/src/oeth/processors/strategies/strategies.ts @@ -1,17 +1,16 @@ +import { OETHRewardTokenCollected } from '@model' +import { Context } from '@processor' +import { currencies } from '@shared/post-processors/exchange-rates/currencies' import { EvmBatchProcessor } from '@subsquid/evm-processor' - -import { OETHRewardTokenCollected } from '../../../model' -import { Context } from '../../../processor' -import { currencies } from '../../../shared/post-processors/exchange-rates/currencies' import { IStrategyData, createStrategyProcessor, createStrategySetup, -} from '../../../shared/processor-templates/strategy' +} from '@templates/strategy' import { createStrategyRewardProcessor, createStrategyRewardSetup, -} from '../../../shared/processor-templates/strategy-rewards' +} from '@templates/strategy-rewards' import { ETH_ADDRESS, FRXETH_ADDRESS, @@ -21,7 +20,7 @@ import { STETH_ADDRESS, WETH_ADDRESS, addresses, -} from '../../../utils/addresses' +} from '@utils/addresses' export const oethStrategies: readonly IStrategyData[] = [ { diff --git a/src/oeth/processors/vault.ts b/src/oeth/processors/vault.ts index d5be4be4..51405e84 100644 --- a/src/oeth/processors/vault.ts +++ b/src/oeth/processors/vault.ts @@ -1,11 +1,11 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' import { pad } from 'viem' -import * as erc20 from '../../abi/erc20' -import * as lido from '../../abi/lido' -import { OETHVault } from '../../model' -import { Context } from '../../processor' -import { ensureExchangeRates } from '../../shared/post-processors/exchange-rates' +import * as erc20 from '@abi/erc20' +import * as lido from '@abi/lido' +import { OETHVault } from '@model' +import { Context } from '@processor' +import { ensureExchangeRates } from '@shared/post-processors/exchange-rates' +import { EvmBatchProcessor } from '@subsquid/evm-processor' import { FRXETH_ADDRESS, OETH_VAULT_ADDRESS, @@ -13,8 +13,8 @@ import { RETH_ADDRESS, STETH_ADDRESS, WETH_ADDRESS, -} from '../../utils/addresses' -import { getLatestEntity, trackAddressBalances } from '../../utils/utils' +} from '@utils/addresses' +import { getLatestEntity, trackAddressBalances } from '@utils/utils' interface ProcessResult { vaults: OETHVault[] diff --git a/src/oeth/validators/validate-oeth/validate-oeth.ts b/src/oeth/validators/validate-oeth/validate-oeth.ts index f7c118ba..1f647350 100644 --- a/src/oeth/validators/validate-oeth/validate-oeth.ts +++ b/src/oeth/validators/validate-oeth/validate-oeth.ts @@ -1,4 +1,3 @@ -import { Entity, EntityClass } from '@subsquid/typeorm-store' import assert from 'assert' import { sortBy } from 'lodash' @@ -9,10 +8,11 @@ import { OETHRebase, OETHVault, StrategyBalance, -} from '../../../model' -import { Block, Context } from '../../../processor' -import { env } from '../../../utils/env' -import { jsonify } from '../../../utils/jsonify' +} from '@model' +import { Block, Context } from '@processor' +import { Entity, EntityClass } from '@subsquid/typeorm-store' +import { env } from '@utils/env' +import { jsonify } from '@utils/jsonify' export const name = 'validate-oeth' diff --git a/src/ogv/post-processors/daily-stats.ts b/src/ogv/post-processors/daily-stats.ts index 57328330..e201c4bd 100644 --- a/src/ogv/post-processors/daily-stats.ts +++ b/src/ogv/post-processors/daily-stats.ts @@ -1,4 +1,3 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' import dayjs from 'dayjs' import utc from 'dayjs/plugin/utc' import { @@ -7,9 +6,10 @@ import { MoreThanOrEqual, } from 'typeorm' -import { OGV, OGVAddress, OGVDailyStat } from '../../model' -import { Context } from '../../processor' -import { applyCoingeckoData } from '../../utils/coingecko' +import { OGV, OGVAddress, OGVDailyStat } from '@model' +import { Context } from '@processor' +import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { applyCoingeckoData } from '@utils/coingecko' dayjs.extend(utc) diff --git a/src/ogv/post-processors/governance.ts b/src/ogv/post-processors/governance.ts index c6183057..cedb970b 100644 --- a/src/ogv/post-processors/governance.ts +++ b/src/ogv/post-processors/governance.ts @@ -1,7 +1,6 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' import { formatEther } from 'viem' -import * as governanceAbi from '../../abi/governance' +import * as governanceAbi from '@abi/governance' import { OGVAddress, OGVProposal, @@ -10,10 +9,11 @@ import { OGVProposalTxLog, OGVProposalVote, OGVVoteType, -} from '../../model' -import { Block, Context, Log } from '../../processor' -import { GOVERNANCE_ADDRESS } from '../../utils/addresses' -import { env } from '../../utils/env' +} from '@model' +import { Block, Context, Log } from '@processor' +import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { GOVERNANCE_ADDRESS } from '@utils/addresses' +import { env } from '@utils/env' export const from = 15491391 // https://etherscan.io/tx/0x0e04e429248c384e6b36229edf8eb5a77bec7023c58808c21b702edfcbc0e0d6 diff --git a/src/ogv/processors/ogv-supply.ts b/src/ogv/processors/ogv-supply.ts index a8796bef..3a6fc182 100644 --- a/src/ogv/processors/ogv-supply.ts +++ b/src/ogv/processors/ogv-supply.ts @@ -1,10 +1,9 @@ +import * as erc20Abi from '@abi/erc20' +import { OGV } from '@model' +import { Context } from '@processor' import { EvmBatchProcessor } from '@subsquid/evm-processor' - -import * as erc20Abi from '../../abi/erc20' -import { OGV } from '../../model' -import { Context } from '../../processor' -import { OGV_ADDRESS, VEOGV_ADDRESS } from '../../utils/addresses' -import { blockFrequencyUpdater } from '../../utils/blockFrequencyUpdater' +import { OGV_ADDRESS, VEOGV_ADDRESS } from '@utils/addresses' +import { blockFrequencyUpdater } from '@utils/blockFrequencyUpdater' export const from = 14439231 // https://etherscan.io/tx/0x9295cac246169f06a3d4ec33fdbd87fced7a9e19ea61177cae75034e45ae66f4 diff --git a/src/ogv/processors/ogv.ts b/src/ogv/processors/ogv.ts index e0b2a456..2f71bcae 100644 --- a/src/ogv/processors/ogv.ts +++ b/src/ogv/processors/ogv.ts @@ -1,15 +1,14 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' - -import * as erc20Abi from '../../abi/erc20' -import * as veogvAbi from '../../abi/veogv' +import * as erc20Abi from '@abi/erc20' +import * as veogvAbi from '@abi/veogv' import { OGVAddress, OGVLockup, OGVLockupEventType, OGVLockupTxLog, -} from '../../model' -import { Block, Context, Log } from '../../processor' -import { ADDRESS_ZERO, OGV_ADDRESS, VEOGV_ADDRESS } from '../../utils/addresses' +} from '@model' +import { Block, Context, Log } from '@processor' +import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { ADDRESS_ZERO, OGV_ADDRESS, VEOGV_ADDRESS } from '@utils/addresses' export const from = 14439231 // https://etherscan.io/tx/0x9295cac246169f06a3d4ec33fdbd87fced7a9e19ea61177cae75034e45ae66f4 export const veogvFrom = 15089597 // https://etherscan.io/tx/0x70c582e56ea1c49b7e9df70a0b40ddbfac9362b8b172cb527c329c2302d7d48a diff --git a/src/ousd/post-processors/daily-stats/daily-stats.ts b/src/ousd/post-processors/daily-stats/daily-stats.ts index c2413b3f..d2c689b2 100644 --- a/src/ousd/post-processors/daily-stats/daily-stats.ts +++ b/src/ousd/post-processors/daily-stats/daily-stats.ts @@ -1,4 +1,3 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' import dayjs from 'dayjs' import utc from 'dayjs/plugin/utc' import { @@ -19,9 +18,10 @@ import { OUSDStrategyDailyStat, OUSDStrategyHoldingDailyStat, OUSDVault, -} from '../../../model' -import { Context } from '../../../processor' -import { applyCoingeckoData } from '../../../utils/coingecko' +} from '@model' +import { Context } from '@processor' +import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { applyCoingeckoData } from '@utils/coingecko' dayjs.extend(utc) diff --git a/src/ousd/processors/curve/curve.ts b/src/ousd/processors/curve/curve.ts new file mode 100644 index 00000000..18b48e0a --- /dev/null +++ b/src/ousd/processors/curve/curve.ts @@ -0,0 +1,54 @@ +import { Context } from '@processor' +import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { + createCurveInitializer, + createCurveProcessor, + createCurveSetup, +} from '@templates/curve' +import { tokens } from '@utils/addresses' + +const ousdResetFrom = 11585978 +const oethDeployFrom = 16933090 + +export const from = Math.min(ousdResetFrom, oethDeployFrom) + +const pools: (Parameters['0'] & + Parameters['0'])[] = [ + // Curve (OUSD) + { + name: 'ThreePool', + address: '0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7'.toLowerCase(), + from: Math.max(10809473, ousdResetFrom), + tokens: [tokens.DAI, tokens.USDC, tokens.USDT], + }, + { + name: 'OUSDMetapool', + address: '0x87650d7bbfc3a9f10587d7778206671719d9910d'.toLowerCase(), + from: Math.max(12860905, ousdResetFrom), + tokens: [tokens.OUSD, tokens.CRV3], + }, + { + name: 'LUSDMetapool', + address: '0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca'.toLowerCase(), + from: Math.max(12184843, ousdResetFrom), + tokens: [tokens.LUSD, tokens.CRV3], + }, +] + +export const setup = (processor: EvmBatchProcessor) => { + for (const pool of pools) { + createCurveSetup(pool.from, processor) + } +} + +const initializers = pools.map((pool) => createCurveInitializer(pool)) + +export const initialize = async (ctx: Context) => { + await Promise.all(initializers.map((p) => p(ctx))) +} + +const processors = pools.map((pool) => createCurveProcessor(pool)) + +export const process = async (ctx: Context) => { + await Promise.all(processors.map((p) => p(ctx))) +} diff --git a/src/shared/processors/curve/index.ts b/src/ousd/processors/curve/index.ts similarity index 100% rename from src/shared/processors/curve/index.ts rename to src/ousd/processors/curve/index.ts diff --git a/src/ousd/processors/erc20s.ts b/src/ousd/processors/erc20s.ts new file mode 100644 index 00000000..de74dbf3 --- /dev/null +++ b/src/ousd/processors/erc20s.ts @@ -0,0 +1,45 @@ +import { createERC20Tracker } from '@templates/erc20' +import { OUSD_VAULT_ADDRESS, ousdStrategyArray, tokens } from '@utils/addresses' + +const tracks: Record[0]> = { + // OUSD Related + USDT: { + // from: 11362821, + from: 16933090, // oeth deploy date + address: tokens.USDT, + accountFilter: [ + ...ousdStrategyArray, + OUSD_VAULT_ADDRESS, + '0x3ed3b47dd13ec9a98b44e6204a523e766b225811', // aUSDT + '0xf650c3d88d12db855b8bf7d11be6c55a4e07dcc9', // cUSDT + ], + intervalTracking: true, + }, + USDC: { + // from: 11367200, + from: 16933090, // oeth deploy date + address: tokens.USDC, + accountFilter: [ + ...ousdStrategyArray, + OUSD_VAULT_ADDRESS, + '0xbcca60bb61934080951369a648fb03df4f96263c', // aUSDC + '0x39aa39c021dfbae8fac545936693ac917d5e7563', // cUSDC + ], + intervalTracking: true, + }, + DAI: { + // from: 11367184, + from: 16933090, // oeth deploy date + address: tokens.DAI, + accountFilter: [ + ...ousdStrategyArray, + OUSD_VAULT_ADDRESS, + '0x028171bca77440897b824ca71d1c56cac55b68a3', // aDAI + '0x5d3a536e4d6dbd6114cc1ead35777bab948e3643', // cDAI + ], + intervalTracking: true, + }, +} + +// This is a function to allow others to subscribe to balance tracking +export const erc20s = Object.values(tracks).map(createERC20Tracker) diff --git a/src/ousd/processors/ousd/ousd.ts b/src/ousd/processors/ousd/ousd.ts index 86caeded..0c852798 100644 --- a/src/ousd/processors/ousd/ousd.ts +++ b/src/ousd/processors/ousd/ousd.ts @@ -7,18 +7,15 @@ import { OUSDHistory, OUSDRebase, OUSDRebaseOption, -} from '../../../model' -import { - createOTokenProcessor, - createOTokenSetup, -} from '../../../shared/processor-templates/otoken' +} from '@model' +import { createOTokenProcessor, createOTokenSetup } from '@templates/otoken' import { DAI_ADDRESS, OUSD_ADDRESS, OUSD_VAULT_ADDRESS, USDC_ADDRESS, USDT_ADDRESS, -} from '../../../utils/addresses' +} from '@utils/addresses' // export const from = 10884563 // https://etherscan.io/tx/0x9141921f5ebf072e58c00fe56332b6bee0c02f0ae4f54c42999b8a3a88662681 export const from = 11585978 // OUSDReset @@ -31,6 +28,8 @@ export const setup = createOTokenSetup({ }) export const process = createOTokenProcessor({ + from, + vaultFrom: 11596942, Upgrade_CreditsBalanceOfHighRes: 13533937, // https://etherscan.io/tx/0xc9b6fc6a4fad18dad197ff7d0636f74bf066671d75656849a1c45122e00d54cf OTOKEN_ADDRESS: OUSD_ADDRESS, OTOKEN_VAULT_ADDRESS: OUSD_VAULT_ADDRESS, diff --git a/src/ousd/processors/strategies/aave-strategy.ts b/src/ousd/processors/strategies/aave-strategy.ts index 2e490571..cbdd3876 100644 --- a/src/ousd/processors/strategies/aave-strategy.ts +++ b/src/ousd/processors/strategies/aave-strategy.ts @@ -1,10 +1,11 @@ import { pad as viemPad } from 'viem' -import * as aaveLendingPool from '../../../abi/aave-lending-pool' -import { currencies } from '../../../shared/post-processors/exchange-rates/currencies' -import { IStrategyData } from '../../../shared/processor-templates/strategy' -import { OUSD_ADDRESS } from '../../../utils/addresses' -import { logFilter } from '../../../utils/logFilter' +import * as aaveLendingPool from '@abi/aave-lending-pool' +import { currencies } from '@shared/post-processors/exchange-rates/currencies' +import { IStrategyData } from '@templates/strategy' +import { OUSD_ADDRESS } from '@utils/addresses' +import { logFilter } from '@utils/logFilter' + import { DAI, USDT } from './const' export const aaveStrategy: IStrategyData = { diff --git a/src/ousd/processors/strategies/convex-meta-strategy.ts b/src/ousd/processors/strategies/convex-meta-strategy.ts index 4f2dd8ee..0db880d4 100644 --- a/src/ousd/processors/strategies/convex-meta-strategy.ts +++ b/src/ousd/processors/strategies/convex-meta-strategy.ts @@ -1,10 +1,9 @@ -import * as erc20 from '../../../abi/erc20' -import * as abstractStrategyAbi from '../../../abi/initializable-abstract-strategy' -import { currencies } from '../../../shared/post-processors/exchange-rates/currencies' -import { IStrategyData } from '../../../shared/processor-templates/strategy' -import { OUSD_ADDRESS } from '../../../utils/addresses' -import { logFilter } from '../../../utils/logFilter' -import { traceFilter } from '../../../utils/traceFilter' +import * as abstractStrategyAbi from '@abi/initializable-abstract-strategy' +import { currencies } from '@shared/post-processors/exchange-rates/currencies' +import { IStrategyData } from '@templates/strategy' +import { OUSD_ADDRESS } from '@utils/addresses' +import { traceFilter } from '@utils/traceFilter' + import { DAI, USDC, USDT } from './const' const from = 15896478 diff --git a/src/ousd/processors/strategies/flux-strategy.ts b/src/ousd/processors/strategies/flux-strategy.ts index 6fcad6b0..898b340a 100644 --- a/src/ousd/processors/strategies/flux-strategy.ts +++ b/src/ousd/processors/strategies/flux-strategy.ts @@ -1,6 +1,7 @@ -import { currencies } from '../../../shared/post-processors/exchange-rates/currencies' -import { IStrategyData } from '../../../shared/processor-templates/strategy' -import { OUSD_ADDRESS } from '../../../utils/addresses' +import { currencies } from '@shared/post-processors/exchange-rates/currencies' +import { IStrategyData } from '@templates/strategy' +import { OUSD_ADDRESS } from '@utils/addresses' + import { DAI, USDC, USDT } from './const' export const fluxStrategy: IStrategyData = { diff --git a/src/ousd/processors/strategies/maker-dsr-strategy.ts b/src/ousd/processors/strategies/maker-dsr-strategy.ts index 94b75c6e..ac4bc463 100644 --- a/src/ousd/processors/strategies/maker-dsr-strategy.ts +++ b/src/ousd/processors/strategies/maker-dsr-strategy.ts @@ -1,6 +1,7 @@ -import { currencies } from '../../../shared/post-processors/exchange-rates/currencies' -import { IStrategyData } from '../../../shared/processor-templates/strategy' -import { OUSD_ADDRESS } from '../../../utils/addresses' +import { currencies } from '@shared/post-processors/exchange-rates/currencies' +import { IStrategyData } from '@templates/strategy' +import { OUSD_ADDRESS } from '@utils/addresses' + import { DAI, USDC, USDT } from './const' export const makerDsrStrategy: IStrategyData = { diff --git a/src/ousd/processors/strategies/morpho-aave.ts b/src/ousd/processors/strategies/morpho-aave.ts index 4c0d3863..ca843be7 100644 --- a/src/ousd/processors/strategies/morpho-aave.ts +++ b/src/ousd/processors/strategies/morpho-aave.ts @@ -1,6 +1,7 @@ -import { currencies } from '../../../shared/post-processors/exchange-rates/currencies' -import { IStrategyData } from '../../../shared/processor-templates/strategy' -import { OUSD_ADDRESS } from '../../../utils/addresses' +import { currencies } from '@shared/post-processors/exchange-rates/currencies' +import { IStrategyData } from '@templates/strategy' +import { OUSD_ADDRESS } from '@utils/addresses' + import { DAI, USDC, USDT } from './const' export const morphoAave: IStrategyData = { diff --git a/src/ousd/processors/strategies/morpho-compound.ts b/src/ousd/processors/strategies/morpho-compound.ts index c21e6809..7463a998 100644 --- a/src/ousd/processors/strategies/morpho-compound.ts +++ b/src/ousd/processors/strategies/morpho-compound.ts @@ -1,6 +1,7 @@ -import { currencies } from '../../../shared/post-processors/exchange-rates/currencies' -import { IStrategyData } from '../../../shared/processor-templates/strategy' -import { OUSD_ADDRESS } from '../../../utils/addresses' +import { currencies } from '@shared/post-processors/exchange-rates/currencies' +import { IStrategyData } from '@templates/strategy' +import { OUSD_ADDRESS } from '@utils/addresses' + import { DAI, USDC, USDT } from './const' export const morphoCompound: IStrategyData = { diff --git a/src/ousd/processors/strategies/strategies.ts b/src/ousd/processors/strategies/strategies.ts index dd04f90f..20354902 100644 --- a/src/ousd/processors/strategies/strategies.ts +++ b/src/ousd/processors/strategies/strategies.ts @@ -1,16 +1,16 @@ +import { OETHRewardTokenCollected } from '@model' +import { Context } from '@processor' import { EvmBatchProcessor } from '@subsquid/evm-processor' - -import { OETHRewardTokenCollected } from '../../../model' -import { Context } from '../../../processor' import { IStrategyData, createStrategyProcessor, createStrategySetup, -} from '../../../shared/processor-templates/strategy' +} from '@templates/strategy' import { createStrategyRewardProcessor, createStrategyRewardSetup, -} from '../../../shared/processor-templates/strategy-rewards' +} from '@templates/strategy-rewards' + import { aaveStrategy } from './aave-strategy' import { convexMetaStrategy } from './convex-meta-strategy' import { fluxStrategy } from './flux-strategy' diff --git a/src/ousd/processors/vault.ts b/src/ousd/processors/vault.ts index 4c9737f4..72b7675b 100644 --- a/src/ousd/processors/vault.ts +++ b/src/ousd/processors/vault.ts @@ -1,17 +1,17 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' import { pad } from 'viem' -import * as erc20 from '../../abi/erc20' -import { OUSDVault } from '../../model' -import { Context } from '../../processor' +import * as erc20 from '@abi/erc20' +import { OUSDVault } from '@model' +import { Context } from '@processor' +import { EvmBatchProcessor } from '@subsquid/evm-processor' import { DAI_ADDRESS, OUSD_VAULT_ADDRESS, OUSD_VAULT_ERC20_ADDRESSES, USDC_ADDRESS, USDT_ADDRESS, -} from '../../utils/addresses' -import { getLatestEntity, trackAddressBalances } from '../../utils/utils' +} from '@utils/addresses' +import { getLatestEntity, trackAddressBalances } from '@utils/utils' interface ProcessResult { vaults: OUSDVault[] diff --git a/src/ousd/validators/validate-ousd/validate-ousd.ts b/src/ousd/validators/validate-ousd/validate-ousd.ts index df84071a..9377e7c7 100644 --- a/src/ousd/validators/validate-ousd/validate-ousd.ts +++ b/src/ousd/validators/validate-ousd/validate-ousd.ts @@ -1,11 +1,11 @@ -import { Entity, EntityClass } from '@subsquid/typeorm-store' import assert from 'assert' import { sortBy } from 'lodash' -import { StrategyYield } from '../../../model' -import { Block, Context } from '../../../processor' -import { env } from '../../../utils/env' -import { jsonify } from '../../../utils/jsonify' +import { StrategyYield } from '@model' +import { Block, Context } from '@processor' +import { Entity, EntityClass } from '@subsquid/typeorm-store' +import { env } from '@utils/env' +import { jsonify } from '@utils/jsonify' export const name = 'validate-ousd' diff --git a/src/processor.ts b/src/processor.ts index eda2e939..09898261 100644 --- a/src/processor.ts +++ b/src/processor.ts @@ -1,3 +1,10 @@ +import assert from 'assert' +import dayjs from 'dayjs' +import duration from 'dayjs/plugin/duration' +import utc from 'dayjs/plugin/utc' +import { Chain } from 'viem' +import { arbitrum, mainnet } from 'viem/chains' + import { lookupArchive } from '@subsquid/archive-registry' import { KnownArchives } from '@subsquid/archive-registry/lib/chains' import { @@ -6,12 +13,7 @@ import { EvmBatchProcessorFields, } from '@subsquid/evm-processor' import { Store, TypeormDatabase } from '@subsquid/typeorm-store' -import assert from 'assert' -import dayjs from 'dayjs' -import duration from 'dayjs/plugin/duration' -import utc from 'dayjs/plugin/utc' - -import { calculateBPS } from './utils/calculateBPS' +import { calculateBlockRate } from '@utils/calculateBlockRate' dayjs.extend(duration) dayjs.extend(utc) @@ -23,23 +25,14 @@ export const createSquidProcessor = ( const url = process.env[rpc_env] || 'http://localhost:8545' console.log(`RPC URL: ${url}`) return new EvmBatchProcessor() - .setDataSource({ - // Change the Archive endpoints for run the squid - // against the other EVM networks - // For a full list of supported networks and config options - // see https://docs.subsquid.io/evm-indexing/ - archive: lookupArchive(archive), - - // Must be set for RPC ingestion (https://docs.subsquid.io/evm-indexing/evm-processor/) - // OR to enable contract state queries (https://docs.subsquid.io/evm-indexing/query-state/) - // chain: 'https://rpc.ankr.com/eth', - // chain: "https://mainnet.infura.io/v3/03b96dfbb4904c5c89c04680dd480064", - chain: { - url, - // Alchemy is deprecating `eth_getBlockReceipts` https://docs.alchemy.com/reference/eth-getblockreceipts - // so we need to set `maxBatchCallSize` 1 to avoid using this method - maxBatchCallSize: url.includes('alchemy.com') ? 1 : 10, - }, + .setGateway(lookupArchive(archive)) + .setRpcEndpoint({ + url, + maxBatchCallSize: url.includes('alchemy.com') ? 1 : 10, + }) + .setRpcDataIngestionSettings({ + disabled: archive === 'arbitrum', + headPollInterval: 30000, }) .setFinalityConfirmation(10) .setFields({ @@ -74,22 +67,36 @@ interface Processor { name?: string from?: number initialize?: (ctx: Context) => Promise // To only be run once per `sqd process`. - setup?: (p: ReturnType) => void + setup?: (p: ReturnType, chain: Chain) => void process: (ctx: Context) => Promise } let initialized = false +const chainConfigs: Record< + number, + { chain: Chain; archive: KnownArchives; rpcEnv: string } | undefined +> = { + [mainnet.id]: { + chain: mainnet, + archive: 'eth-mainnet', + rpcEnv: process.env.RPC_ENV ?? 'RPC_ENDPOINT', + }, + [arbitrum.id]: { + chain: arbitrum, + archive: 'arbitrum', + rpcEnv: process.env.RPC_ARBITRUM_ENV ?? 'RPC_ARBITRUM_ENDPOINT', + }, +} + export const run = ({ - archive, - rpcEnv, + chainId = 1, stateSchema, processors, postProcessors, validators, }: { - archive?: KnownArchives - rpcEnv?: string + chainId?: number stateSchema?: string processors: Processor[] postProcessors?: Processor[] @@ -100,7 +107,9 @@ export const run = ({ 'All processors must have a `from` defined', ) - const processor = createSquidProcessor(archive, rpcEnv) + const config = chainConfigs[chainId] + if (!config) throw new Error('No chain configuration found.') + const processor = createSquidProcessor(config.archive, config.rpcEnv) processor.setBlockRange({ from: process.env.BLOCK_FROM @@ -113,8 +122,8 @@ export const run = ({ ), to: process.env.BLOCK_TO ? Number(process.env.BLOCK_TO) : undefined, }) - processors.forEach((p) => p.setup?.(processor)) - postProcessors?.forEach((p) => p.setup?.(processor)) + processors.forEach((p) => p.setup?.(processor, config.chain)) + postProcessors?.forEach((p) => p.setup?.(processor, config.chain)) processor.run( new TypeormDatabase({ stateSchema, @@ -124,9 +133,10 @@ export const run = ({ async (_ctx) => { const ctx = _ctx as Context try { + ctx.chain = config.chain ctx.__state = new Map() - if (ctx.blocks.length > 1) { - ctx.bps = await calculateBPS(ctx) + if (ctx.blocks.length >= 1) { + ctx.blockRate = await calculateBlockRate(ctx) // ctx.log.info({ bps: ctx.bps, length: ctx.blocks.length }) } @@ -223,7 +233,8 @@ export type Fields = EvmBatchProcessorFields< ReturnType > export type Context = DataHandlerContext & { - bps: number + chain: Chain + blockRate: number __state: Map } export type Block = Context['blocks']['0'] diff --git a/src/server-extension/ogn-stats.ts b/src/server-extension/ogn-stats.ts index e35b985d..b78694a4 100644 --- a/src/server-extension/ogn-stats.ts +++ b/src/server-extension/ogn-stats.ts @@ -1,4 +1,3 @@ -import './fetch-polyfill' import { GraphQLResolveInfo } from 'graphql' import 'reflect-metadata' import { Field, Info, ObjectType, Query, Resolver } from 'type-graphql' @@ -13,8 +12,10 @@ import { } from 'viem' import { mainnet } from 'viem/chains' -import * as Erc20ABI from '../abi/erc20.abi' -import { OGN_ADDRESS } from '../utils/addresses' +import * as Erc20ABI from '@abi/erc20.abi' +import { OGN_ADDRESS } from '@utils/addresses' + +import './fetch-polyfill' const publicClient = createPublicClient({ chain: mainnet, diff --git a/src/server-extension/resolvers/index.ts b/src/server-extension/resolvers/index.ts index 725de5e1..88561fe4 100644 --- a/src/server-extension/resolvers/index.ts +++ b/src/server-extension/resolvers/index.ts @@ -1 +1,3 @@ +import 'tsconfig-paths/register' + export { OGNStatsResolver } from '../ogn-stats' diff --git a/src/shared/post-processors/exchange-rates/currencies.ts b/src/shared/post-processors/exchange-rates/currencies.ts index a502743d..f22801fa 100644 --- a/src/shared/post-processors/exchange-rates/currencies.ts +++ b/src/shared/post-processors/exchange-rates/currencies.ts @@ -1,6 +1,6 @@ import { invert, mapKeys } from 'lodash' -import { ExchangeRate } from '../../../model' +import { ExchangeRate } from '@model' export const currencies = { USD: '0x0000000000000000000000000000000000000348', // Chainlink Denominations.USD diff --git a/src/shared/post-processors/exchange-rates/exchange-rates.ts b/src/shared/post-processors/exchange-rates/exchange-rates.ts index c1a547cc..6ece7568 100644 --- a/src/shared/post-processors/exchange-rates/exchange-rates.ts +++ b/src/shared/post-processors/exchange-rates/exchange-rates.ts @@ -1,9 +1,10 @@ import { compact } from 'lodash' import { Between } from 'typeorm' -import { ExchangeRate } from '../../../model' -import { Block, Context } from '../../../processor' -import { useProcessorState } from '../../../utils/state' +import { ExchangeRate } from '@model' +import { Block, Context } from '@processor' +import { useProcessorState } from '@utils/state' + import { Currency, currenciesByAddress } from './currencies' import { getPrice } from './price-routing' diff --git a/src/shared/post-processors/exchange-rates/price-routing.ts b/src/shared/post-processors/exchange-rates/price-routing.ts index 3b1141ba..0789d1d8 100644 --- a/src/shared/post-processors/exchange-rates/price-routing.ts +++ b/src/shared/post-processors/exchange-rates/price-routing.ts @@ -1,14 +1,15 @@ import { memoize } from 'lodash' -import * as balancerMetaStablePoolAbi from '../../../abi/balancer-meta-stable-pool' -import * as balancerRateProvider from '../../../abi/balancer-rate-provider' -import * as chainlinkFeedRegistry from '../../../abi/chainlink-feed-registry' -import * as frxEthFraxOracle from '../../../abi/frx-eth-frax-oracle' -import * as oethOracleRouter from '../../../abi/oeth-oracle-router' -import * as stakedFraxEth from '../../../abi/sfrx-eth' -import * as woethAbi from '../../../abi/woeth' -import { Context } from '../../../processor' -import { STETH_ADDRESS } from '../../../utils/addresses' +import * as balancerMetaStablePoolAbi from '@abi/balancer-meta-stable-pool' +import * as balancerRateProvider from '@abi/balancer-rate-provider' +import * as chainlinkFeedRegistry from '@abi/chainlink-feed-registry' +import * as frxEthFraxOracle from '@abi/frx-eth-frax-oracle' +import * as oethOracleRouter from '@abi/oeth-oracle-router' +import * as stakedFraxEth from '@abi/sfrx-eth' +import * as woethAbi from '@abi/woeth' +import { Context } from '@processor' +import { STETH_ADDRESS } from '@utils/addresses' + import { Currency, CurrencySymbol, currencies } from './currencies' export const getPrice = async ( diff --git a/src/shared/post-processors/liquidity.ts b/src/shared/post-processors/liquidity.ts index 8bdde1eb..4f9e62f8 100644 --- a/src/shared/post-processors/liquidity.ts +++ b/src/shared/post-processors/liquidity.ts @@ -1,8 +1,8 @@ import dayjs from 'dayjs' -import { LiquidityDailyBalance } from '../../model' -import { Context } from '../../processor' -import { useProcessorState } from '../../utils/state' +import { LiquidityDailyBalance } from '@model' +import { Context } from '@processor' +import { useProcessorState } from '@utils/state' const useLiquidityDailyBalance = (ctx: Context) => useProcessorState( diff --git a/src/shared/processors/balancer/balancer.ts b/src/shared/processors/balancer/balancer.ts deleted file mode 100644 index 45e3f18d..00000000 --- a/src/shared/processors/balancer/balancer.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' - -import { Context } from '../../../processor' -import { tokens } from '../../../utils/addresses' -import { CurrencyAddress } from '../../post-processors/exchange-rates/currencies' -import { - createBalancerInitializer, - createBalancerProcessor, - createBalancerSetup, -} from '../../processor-templates/balancer' - -const ousdResetFrom = 11585978 -const oethDeployFrom = 16933090 - -const pools: { - name: string - poolSymbol: string - poolType: 'MetaStable' | 'ComposableStable' | 'Weighted' | 'Gyroscope' - poolAddress: string - poolId: string - from: number - tokens: - | [string, string] - | [string, string, string] - | [string, string, string, string] - rates?: [CurrencyAddress, CurrencyAddress][] -}[] = [ - { - name: 'Balancer rETH Stable Pool', - poolSymbol: 'B-rETH-STABLE', - poolType: 'MetaStable', - poolAddress: '0x1e19cf2d73a72ef1332c882f20534b6519be0276', - poolId: - '0x1e19cf2d73a72ef1332c882f20534b6519be0276000200000000000000000112', - tokens: [tokens.rETH, tokens.WETH], - from: Math.max(13850000, oethDeployFrom), - }, - { - name: 'wstETH-rETH-sfrxETH-BPT', - poolSymbol: 'wstETH-rETH-sfrxETH-BPT', - poolType: 'ComposableStable', - poolAddress: '0x42ed016f826165c2e5976fe5bc3df540c5ad0af7', - poolId: - '0x42ed016f826165c2e5976fe5bc3df540c5ad0af700000000000000000000058b', - tokens: [ - '0x42ed016f826165c2e5976fe5bc3df540c5ad0af7', - tokens.wstETH, - tokens.sfrxETH, - tokens.rETH, - ], - from: Math.max(17680000, oethDeployFrom), - }, - { - name: 'Balancer wstETH-WETH Stable Pool', - poolSymbol: 'wstETH-WETH-BPT', - poolType: 'ComposableStable', - poolAddress: '0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd', - poolId: - '0x93d199263632a4ef4bb438f1feb99e57b4b5f0bd0000000000000000000005c2', - tokens: [ - tokens.wstETH, - '0x93d199263632a4EF4Bb438F1feB99e57b4b5f0BD', - tokens.WETH, - ], - from: Math.max(17920000, oethDeployFrom), - }, - { - name: 'Balancer 80 BAL 20 WETH', - poolSymbol: 'B-80BAL-20WETH', - poolType: 'Weighted', - poolAddress: '0x5c6ee304399dbdb9c8ef030ab642b10820db8f56', - poolId: - '0x5c6ee304399dbdb9c8ef030ab642b10820db8f56000200000000000000000014', - from: Math.max(12370000, oethDeployFrom), - tokens: [tokens.BAL, tokens.WETH], - rates: [[tokens.BAL, tokens.ETH] as [CurrencyAddress, CurrencyAddress]], - }, - { - name: 'Gyroscope ECLP wstETH/wETH', - poolSymbol: 'ECLP-wstETH-wETH', - poolAddress: '0xf01b0684c98cd7ada480bfdf6e43876422fa1fc1', - poolId: - '0xf01b0684c98cd7ada480bfdf6e43876422fa1fc10002000000000000000005de', - poolType: 'Gyroscope', - from: Math.max(18015100, oethDeployFrom), - tokens: [tokens.wstETH, tokens.WETH], - }, -] - -export const from = Math.min(...pools.map((p) => p.from)) - -export const setup = (processor: EvmBatchProcessor) => { - for (const pool of pools) { - createBalancerSetup(pool.from, processor) - } -} - -const initializers = pools.map((pool) => createBalancerInitializer(pool)) - -export const initialize = async (ctx: Context) => { - await Promise.all(initializers.map((p) => p(ctx))) -} - -const processors = pools.map((pool) => - createBalancerProcessor( - pool.poolAddress.toLowerCase(), - pool.poolId.toLowerCase(), - pool.poolType, - pool.from, - pool.rates, - ), -) - -export const process = async (ctx: Context) => { - await Promise.all(processors.map((p) => p(ctx))) -} diff --git a/src/shared/processors/curve/curve.ts b/src/shared/processors/curve/curve.ts deleted file mode 100644 index b85ee935..00000000 --- a/src/shared/processors/curve/curve.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' - -import { Context } from '../../../processor' -import { tokens } from '../../../utils/addresses' -import { - createCurveInitializer, - createCurveProcessor, - createCurveSetup, -} from '../../processor-templates/curve' - -const ousdResetFrom = 11585978 -const oethDeployFrom = 16933090 - -export const from = Math.min(ousdResetFrom, oethDeployFrom) - -const pools: (Parameters['0'] & - Parameters['0'])[] = [ - // Curve (OUSD) - { - name: 'ThreePool', - address: '0xbebc44782c7db0a1a60cb6fe97d0b483032ff1c7'.toLowerCase(), - from: Math.max(10809473, ousdResetFrom), - tokens: [tokens.DAI, tokens.USDC, tokens.USDT], - }, - { - name: 'OUSDMetapool', - address: '0x87650d7bbfc3a9f10587d7778206671719d9910d'.toLowerCase(), - from: Math.max(12860905, ousdResetFrom), - tokens: [tokens.OUSD, tokens.CRV3], - }, - { - name: 'LUSDMetapool', - address: '0xed279fdd11ca84beef15af5d39bb4d4bee23f0ca'.toLowerCase(), - from: Math.max(12184843, ousdResetFrom), - tokens: [tokens.LUSD, tokens.CRV3], - }, - - // Curve (OETH) - { - name: 'factory-v2-298: ETH/OETH', - address: '0x94B17476A93b3262d87B9a326965D1E91f9c13E7'.toLowerCase(), - from: Math.max(17130500, oethDeployFrom), - tokens: [tokens.ETH, tokens.OETH], - ratesToPull: [{ i: 1n, j: 0n, dx: 1000000000000000000n }], - }, - { - name: 'factory-crvusd-15: WETH/frxETH', - address: '0x9c3b46c0ceb5b9e304fcd6d88fc50f7dd24b31bc', - from: Math.max(17922938, oethDeployFrom), - tokens: [tokens.WETH, tokens.frxETH], - }, - { - name: 'steth: ETH/stETH', - address: '0xdc24316b9ae028f1497c275eb9192a3ea0f67022', - from: Math.max(11592551, oethDeployFrom), - tokens: [tokens.ETH, tokens.stETH], - }, - { - name: 'stETH-ng: ETH/stETH', - address: '0x21e27a5e5513d6e65c4f830167390997aa84843a', - from: Math.max(17272519, oethDeployFrom), - tokens: [tokens.ETH, tokens.stETH], - }, - { - name: 'frxeth: ETH/frxETH', - address: '0xa1f8a6807c402e4a15ef4eba36528a3fed24e577', - from: Math.max(15741010, oethDeployFrom), - tokens: [tokens.ETH, tokens.frxETH], - }, - { - name: 'factory-crypto-210: ETH/rETH', - address: '0x0f3159811670c117c372428d4e69ac32325e4d0f', - from: Math.max(16615906, oethDeployFrom), - tokens: [tokens.ETH, tokens.rETH], - }, - { - name: 'factory-v2-274: stETH/frxETH', - address: '0x4d9f9d15101eec665f77210cb999639f760f831e', - from: Math.max(16683219, oethDeployFrom), - tokens: [tokens.stETH, tokens.frxETH], - }, - { - name: 'factory-v2-117: WETH/stETH', - address: '0x828b154032950c8ff7cf8085d841723db2696056', - from: Math.max(14759666, oethDeployFrom), - tokens: [tokens.WETH, tokens.stETH], - }, - { - name: 'factory-v2-89: rETH/wstETH', - address: '0x447ddd4960d9fdbf6af9a790560d0af76795cb08', - from: Math.max(14258216, oethDeployFrom), - tokens: [tokens.rETH, tokens.wstETH], - }, - { - name: 'factory-crypto-218: rETH/frxETH', - address: '0xe7c6e0a739021cdba7aac21b4b728779eef974d9', - from: Math.max(16684327, oethDeployFrom), - tokens: [tokens.rETH, tokens.frxETH], - }, - { - name: 'factory-tricrypto-14: wstETH/rETH/sfrxETH', - address: '0x2570f1bd5d2735314fc102eb12fc1afe9e6e7193', - from: Math.max(18084222, oethDeployFrom), - tokens: [tokens.wstETH, tokens.rETH, tokens.sfrxETH], - }, -] - -export const setup = (processor: EvmBatchProcessor) => { - for (const pool of pools) { - createCurveSetup(pool.from, processor) - } -} - -const initializers = pools.map((pool) => createCurveInitializer(pool)) - -export const initialize = async (ctx: Context) => { - await Promise.all(initializers.map((p) => p(ctx))) -} - -const processors = pools.map((pool) => createCurveProcessor(pool)) - -export const process = async (ctx: Context) => { - await Promise.all(processors.map((p) => p(ctx))) -} diff --git a/src/shared/processors/erc20s.ts b/src/shared/processors/erc20s.ts deleted file mode 100644 index cebfe76d..00000000 --- a/src/shared/processors/erc20s.ts +++ /dev/null @@ -1,149 +0,0 @@ -import * as otoken from '../../abi/otoken' -import { - OETH_ADDRESS, - OETH_DRIPPER_ADDRESS, - OETH_VAULT_ADDRESS, - OUSD_VAULT_ADDRESS, - TokenSymbol, - oethStrategyArray, - ousdStrategyArray, - tokens, -} from '../../utils/addresses' -import { logFilter } from '../../utils/logFilter' -import { createERC20Tracker } from '../processor-templates/erc20' - -// TODO: Would be nice if interested parties could register their desires here from other parts of the code, -// allowing multiple declarations of need without issue. - -let initialized = false - -const tracks: Record[0]> = { - // Origin Specific - OGN: { - from: 15350225, // 6436154, - address: tokens.OGN, - accountFilter: [ - '0x2eae0cae2323167abf78462e0c0686865c67a655', // Origin: Team Distribution (starts at block 15350225) - ], - intervalTracking: true, - }, - OGV: { - from: 15350225, // 14439231, - address: tokens.OGV, - accountFilter: [ - '0x2eae0cae2323167abf78462e0c0686865c67a655', // Origin: Team Distribution (starts at block 15350225) - ], - intervalTracking: true, - }, - OETH: { - from: 16935276, - address: tokens.OETH, - rebaseFilters: [ - logFilter({ - address: [OETH_ADDRESS], - topic0: [otoken.events.TotalSupplyUpdatedHighres.topic], - transaction: true, - range: { from: 16935276 }, - }), - ], - }, - // OUSD Related - USDT: { - from: 11362821, - address: tokens.USDT, - accountFilter: [ - ...ousdStrategyArray, - OUSD_VAULT_ADDRESS, - '0x3ed3b47dd13ec9a98b44e6204a523e766b225811', // aUSDT - '0xf650c3d88d12db855b8bf7d11be6c55a4e07dcc9', // cUSDT - ], - intervalTracking: true, - }, - USDC: { - from: 11367200, - address: tokens.USDC, - accountFilter: [ - ...ousdStrategyArray, - OUSD_VAULT_ADDRESS, - '0xbcca60bb61934080951369a648fb03df4f96263c', // aUSDC - '0x39aa39c021dfbae8fac545936693ac917d5e7563', // cUSDC - ], - intervalTracking: true, - }, - DAI: { - from: 11367184, - address: tokens.DAI, - accountFilter: [ - ...ousdStrategyArray, - OUSD_VAULT_ADDRESS, - '0x028171bca77440897b824ca71d1c56cac55b68a3', // aDAI - '0x5d3a536e4d6dbd6114cc1ead35777bab948e3643', // cDAI - ], - intervalTracking: true, - }, - // OETH Related - WETH: { - from: 16933090, // oeth deploy date - address: tokens.WETH, - accountFilter: [ - ...oethStrategyArray, - OETH_VAULT_ADDRESS, - OETH_DRIPPER_ADDRESS, - '0xa4e0faA58465A2D369aa21B3e42d43374c6F9613', // Uniswap wstETH/WETH - '0x109830a1aaad605bbf02a9dfa7b0b92ec2fb7daa', // Uniswap rETH/WETH - ], - intervalTracking: true, - }, - rETH: { - from: 16933090, // oeth deploy date - address: tokens.rETH, - accountFilter: [ - ...oethStrategyArray, - OETH_VAULT_ADDRESS, - '0xa4e0faA58465A2D369aa21B3e42d43374c6F9613', // Uniswap rETH/WETH - '0x553e9c493678d8606d6a5ba284643db2110df823', // Uniswap rETH/WETH - ], - intervalTracking: true, - }, - wstETH: { - from: 16933090, // oeth deploy date - address: tokens.wstETH, - accountFilter: [ - ...oethStrategyArray, - OETH_VAULT_ADDRESS, - '0x109830a1aaad605bbf02a9dfa7b0b92ec2fb7daa', // Uniswap wstETH/WETH - ], - intervalTracking: true, - }, - stETH: { - from: 16933090, // oeth deploy date - address: tokens.stETH, - accountFilter: [...oethStrategyArray, OETH_VAULT_ADDRESS], - intervalTracking: true, - }, - frxETH: { - from: 16933090, // oeth deploy date - address: tokens.frxETH, - accountFilter: [...oethStrategyArray, OETH_VAULT_ADDRESS], - intervalTracking: true, - }, -} - -// This is a function to allow others to subscribe to balance tracking -export const erc20s = () => { - initialized = true - return Object.values(tracks).map(createERC20Tracker) -} - -export const addERC20Processing = (symbol: TokenSymbol, account: string) => { - if (initialized) { - throw new Error('erc20s already initialized, check load order') - } - const track = tracks[symbol] - if (track) { - // If there is no `accountFilter` then it is OK to have this as a noop. (we already want everything) - track.accountFilter?.push(account) - } else { - throw new Error(`Symbol ${symbol} not added to \`tracks\``) - } -} diff --git a/src/shared/validators/validate-shared.ts b/src/shared/validators/validate-shared.ts deleted file mode 100644 index 1f7cc0f3..00000000 --- a/src/shared/validators/validate-shared.ts +++ /dev/null @@ -1,259 +0,0 @@ -import { Entity, EntityClass } from '@subsquid/typeorm-store' -import assert from 'assert' -import { sortBy } from 'lodash' - -import { ERC20Balance, ERC20State } from '../../model' -import { Block, Context } from '../../processor' -import { env } from '../../utils/env' -import { jsonify } from '../../utils/jsonify' - -export const name = 'validate-shared' - -let firstBlock = true - -export const process = async (ctx: Context) => { - if (env.BLOCK_FROM) return - for (const block of ctx.blocks) { - await validateExpectations(ctx, block, ERC20State, expectations.erc20States) - await validateExpectations( - ctx, - block, - ERC20Balance, - expectations.erc20Balances, - ) - firstBlock = false - } -} - -const validateExpectations = async < - T extends Entity & { - timestamp: string - blockNumber: number - }, ->( - ctx: Context, - block: Block, - Class: EntityClass, - expectations?: T[], -) => { - if (!expectations) return - if (firstBlock) { - while (expectations[0]?.blockNumber < block.header.height) { - const entity = expectations.shift()! - await validateExpectation(ctx, Class, entity) - } - } - assert( - !expectations.length || expectations[0]?.blockNumber >= block.header.height, - 'Something is missing', - ) - while (expectations[0]?.blockNumber === block.header.height) { - const entity = expectations.shift()! - await validateExpectation(ctx, Class, entity) - } -} - -const validateExpectation = async < - T extends Entity & { - timestamp: string - blockNumber: number - }, ->( - ctx: Context, - Class: EntityClass, - expectation: T, -) => { - const actual = await ctx.store.findOne(Class, { - where: { id: expectation.id }, - }) - assert( - actual, - `Expected entity does not exist: Entity=${Class.name} id=${expectation.id}`, - ) - expectation.timestamp = new Date(expectation.timestamp).toJSON() - // We decide to only care about float decimal accuracy to the 8th. - assert.deepEqual( - JSON.parse( - jsonify(actual, (_key, value) => - typeof value === 'number' ? Number(value.toFixed(8)) : value, - ), - ), - JSON.parse( - jsonify(expectation, (_key, value) => - typeof value === 'number' ? Number(value.toFixed(8)) : value, - ), - ), - ) - ctx.log.info(`Validated entity: Entity=${Class.name} id=${expectation.id}`) -} - -const e = (arr: any[]) => { - return sortBy(arr, (v) => v.blockNumber) -} - -const expectations = { - erc20States: e([ - { - address: '0x6b175474e89094c44da98b954eedeac495271d0f', - blockNumber: 11367184, - holderCount: 0, - id: '11367184:0x6b175474e89094c44da98b954eedeac495271d0f', - timestamp: '2020-12-01T14:22:02.000000Z', - totalSupply: '692399822445745145525155198', - }, - { - address: '0xdac17f958d2ee523a2206206994597c13d831ec7', - blockNumber: 11401000, - holderCount: 2, - id: '11401000:0xdac17f958d2ee523a2206206994597c13d831ec7', - timestamp: '2020-12-06T19:20:45.000000Z', - totalSupply: '12442213561495551', - }, - { - address: '0x6b175474e89094c44da98b954eedeac495271d0f', - blockNumber: 12964450, - holderCount: 3, - id: '12964450:0x6b175474e89094c44da98b954eedeac495271d0f', - timestamp: '2021-08-05T10:27:01.000000Z', - totalSupply: '5445306543169379254918394333', - }, - { - address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - blockNumber: 12964450, - holderCount: 3, - id: '12964450:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', - timestamp: '2021-08-05T10:27:01.000000Z', - totalSupply: '26720553335039550', - }, - { - address: '0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3', - blockNumber: 17296080, - holderCount: 90, - id: '17296080:0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3', - timestamp: '2023-05-19T21:05:35.000000Z', - totalSupply: '3528560797966319884732', - }, - { - address: '0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3', - blockNumber: 17296257, - holderCount: 90, - id: '17296257:0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3', - timestamp: '2023-05-19T21:40:59.000000Z', - totalSupply: '3529563347644033413431', - }, - { - address: '0x5e8422345238f34275888049021821e8e08caa1f', - blockNumber: 17979735, - holderCount: 0, - id: '17979735:0x5e8422345238f34275888049021821e8e08caa1f', - timestamp: '2023-08-23T20:16:11.000000Z', - totalSupply: '254108641082873082034663', - }, - { - address: '0x5e8422345238f34275888049021821e8e08caa1f', - blockNumber: 17986884, - holderCount: 0, - id: '17986884:0x5e8422345238f34275888049021821e8e08caa1f', - timestamp: '2023-08-24T20:16:59.000000Z', - totalSupply: '254331703007023082033663', - }, - { - address: '0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3', - blockNumber: 18388340, - holderCount: 499, - id: '18388340:0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3', - timestamp: '2023-10-20T01:44:59.000000Z', - totalSupply: '38214229823673500371847', - }, - { - address: '0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3', - blockNumber: 18389908, - holderCount: 499, - id: '18389908:0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3', - timestamp: '2023-10-20T06:59:47.000000Z', - totalSupply: '38217047513690199318528', - }, - ]), - erc20Balances: e([ - { - id: '11362821:0xdac17f958d2ee523a2206206994597c13d831ec7:0xf650c3d88d12db855b8bf7d11be6c55a4e07dcc9', - timestamp: '2020-11-30T22:20:30.000000Z', - blockNumber: 11362821, - balance: '11457161992607', - address: '0xdac17f958d2ee523a2206206994597c13d831ec7', - account: '0xf650c3d88d12db855b8bf7d11be6c55a4e07dcc9', - }, - { - id: '11367184:0x6b175474e89094c44da98b954eedeac495271d0f:0x89eb88fedc50fc77ae8a18aad1ca0ac27f777a90', - timestamp: '2020-12-01T14:22:02.000000Z', - blockNumber: 11367184, - balance: '0', - address: '0x6b175474e89094c44da98b954eedeac495271d0f', - account: '0x89eb88fedc50fc77ae8a18aad1ca0ac27f777a90', - }, - { - id: '11367184:0x6b175474e89094c44da98b954eedeac495271d0f:0x5e3646a1db86993f73e6b74a57d8640b69f7e259', - timestamp: '2020-12-01T14:22:02.000000Z', - blockNumber: 11367184, - balance: '0', - address: '0x6b175474e89094c44da98b954eedeac495271d0f', - account: '0x5e3646a1db86993f73e6b74a57d8640b69f7e259', - }, - { - id: '17149230:0x6b175474e89094c44da98b954eedeac495271d0f:0x7a192dd9cc4ea9bdedec9992df74f1da55e60a19', - timestamp: '2023-04-29T03:58:35.000000Z', - blockNumber: 17149230, - balance: '0', - address: '0x6b175474e89094c44da98b954eedeac495271d0f', - account: '0x7a192dd9cc4ea9bdedec9992df74f1da55e60a19', - }, - { - id: '17149230:0x6b175474e89094c44da98b954eedeac495271d0f:0xe75d77b1865ae93c7eaa3040b038d7aa7bc02f70', - timestamp: '2023-04-29T03:58:35.000000Z', - blockNumber: 17149230, - balance: '556620480436222718976', - address: '0x6b175474e89094c44da98b954eedeac495271d0f', - account: '0xe75d77b1865ae93c7eaa3040b038d7aa7bc02f70', - }, - { - id: '17149230:0x6b175474e89094c44da98b954eedeac495271d0f:0x028171bca77440897b824ca71d1c56cac55b68a3', - timestamp: '2023-04-29T03:58:35.000000Z', - blockNumber: 17149230, - balance: '29859949254086282250927323', - address: '0x6b175474e89094c44da98b954eedeac495271d0f', - account: '0x028171bca77440897b824ca71d1c56cac55b68a3', - }, - { - id: '17149230:0x6b175474e89094c44da98b954eedeac495271d0f:0x5d3a536e4d6dbd6114cc1ead35777bab948e3643', - timestamp: '2023-04-29T03:58:35.000000Z', - blockNumber: 17149230, - balance: '175900582068662134551795199', - address: '0x6b175474e89094c44da98b954eedeac495271d0f', - account: '0x5d3a536e4d6dbd6114cc1ead35777bab948e3643', - }, - { - id: '17156244:0x6b175474e89094c44da98b954eedeac495271d0f:0x89eb88fedc50fc77ae8a18aad1ca0ac27f777a90', - timestamp: '2023-04-30T03:38:59.000000Z', - blockNumber: 17156244, - balance: '0', - address: '0x6b175474e89094c44da98b954eedeac495271d0f', - account: '0x89eb88fedc50fc77ae8a18aad1ca0ac27f777a90', - }, - { - id: '17904321:0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3:0x9283099a29556fcf8fff5b2cea2d4f67cb7a7a8b', - timestamp: '2023-08-13T07:02:47.000000Z', - blockNumber: 17904321, - balance: '4081205214585785457', - address: '0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3', - account: '0x9283099a29556fcf8fff5b2cea2d4f67cb7a7a8b', - }, - { - id: '17904321:0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3:0x46d13d72db5d05bd2671312e321867ab8b30d9f6', - timestamp: '2023-08-13T07:02:47.000000Z', - blockNumber: 17904321, - balance: '4081198559585393770', - address: '0x856c4efb76c1d1ae02e20ceb03a2a6a08b0b8dc3', - account: '0x46d13d72db5d05bd2671312e321867ab8b30d9f6', - }, - ]), -} as const diff --git a/src/shared/processor-templates/balancer/balancer.ts b/src/templates/balancer/balancer.ts similarity index 85% rename from src/shared/processor-templates/balancer/balancer.ts rename to src/templates/balancer/balancer.ts index 9ea91ca5..be58447f 100644 --- a/src/shared/processor-templates/balancer/balancer.ts +++ b/src/templates/balancer/balancer.ts @@ -1,24 +1,23 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' - -import * as balancerComposableStablePool from '../../../abi/balancer-composable-stable-pool' -import * as balancerMetaStablePoolAbi from '../../../abi/balancer-meta-stable-pool' -import * as balancerRateProvider from '../../../abi/balancer-rate-provider' -import * as balancerVaultAbi from '../../../abi/balancer-vault' -import * as balancerWeightedPool from '../../../abi/balancer-weighted-pool-2-token' +import * as balancerComposableStablePool from '@abi/balancer-composable-stable-pool' +import * as balancerMetaStablePoolAbi from '@abi/balancer-meta-stable-pool' +import * as balancerRateProvider from '@abi/balancer-rate-provider' +import * as balancerVaultAbi from '@abi/balancer-vault' +import * as balancerWeightedPool from '@abi/balancer-weighted-pool-2-token' import { BalancerPool, BalancerPoolBalance, BalancerPoolRate, - LiquiditySource, LiquiditySourceType, -} from '../../../model' -import { Context } from '../../../processor' -import { ADDRESS_ZERO, BALANCER_VAULT } from '../../../utils/addresses' -import { blockFrequencyUpdater } from '../../../utils/blockFrequencyUpdater' -import { ensureExchangeRates } from '../../post-processors/exchange-rates' -import { Currency } from '../../post-processors/exchange-rates/currencies' -import { updateLiquidityBalances } from '../../post-processors/liquidity' -import { registerLiquiditySource } from '../../processors/liquidity-sources' +} from '@model' +import { Context } from '@processor' +import { ensureExchangeRates } from '@shared/post-processors/exchange-rates' +import { Currency } from '@shared/post-processors/exchange-rates/currencies' +import { updateLiquidityBalances } from '@shared/post-processors/liquidity' +import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { ADDRESS_ZERO, BALANCER_VAULT } from '@utils/addresses' +import { blockFrequencyUpdater } from '@utils/blockFrequencyUpdater' + +import { registerLiquiditySource } from '../../mainnet/processors/liquidity-sources' const eth1 = BigInt('1000000000000000000') diff --git a/src/shared/processors/balancer/index.ts b/src/templates/balancer/index.ts similarity index 100% rename from src/shared/processors/balancer/index.ts rename to src/templates/balancer/index.ts diff --git a/src/shared/processor-templates/curve/curve.ts b/src/templates/curve/curve.ts similarity index 88% rename from src/shared/processor-templates/curve/curve.ts rename to src/templates/curve/curve.ts index 913efc60..d995af74 100644 --- a/src/shared/processor-templates/curve/curve.ts +++ b/src/templates/curve/curve.ts @@ -1,17 +1,17 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' - -import * as curveLpToken from '../../../abi/curve-lp-token' +import * as curveLpToken from '@abi/curve-lp-token' import { CurvePool, CurvePoolBalance, CurvePoolRate, LiquiditySourceType, -} from '../../../model' -import { Context } from '../../../processor' -import { blockFrequencyUpdater } from '../../../utils/blockFrequencyUpdater' -import { range } from '../../../utils/range' -import { updateLiquidityBalances } from '../../post-processors/liquidity' -import { registerLiquiditySource } from '../../processors/liquidity-sources' +} from '@model' +import { Context } from '@processor' +import { updateLiquidityBalances } from '@shared/post-processors/liquidity' +import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { blockFrequencyUpdater } from '@utils/blockFrequencyUpdater' +import { range } from '@utils/range' + +import { registerLiquiditySource } from '../../mainnet/processors/liquidity-sources' interface ProcessResult { curvePoolBalances: CurvePoolBalance[] diff --git a/src/templates/curve/index.ts b/src/templates/curve/index.ts new file mode 100644 index 00000000..e039a951 --- /dev/null +++ b/src/templates/curve/index.ts @@ -0,0 +1 @@ +export * from './curve' diff --git a/src/shared/processor-templates/erc20/erc20.ts b/src/templates/erc20/erc20.ts similarity index 77% rename from src/shared/processor-templates/erc20/erc20.ts rename to src/templates/erc20/erc20.ts index bace1848..cc48c81b 100644 --- a/src/shared/processor-templates/erc20/erc20.ts +++ b/src/templates/erc20/erc20.ts @@ -1,12 +1,17 @@ +import * as abi from '@abi/erc20' +import { + ERC20, + ERC20Balance, + ERC20Holder, + ERC20State, + ERC20Transfer, +} from '@model' +import { Context } from '@processor' import { EvmBatchProcessor } from '@subsquid/evm-processor' - -import * as abi from '../../../abi/erc20' -import { ERC20, ERC20Balance, ERC20Holder, ERC20State } from '../../../model' -import { Context } from '../../../processor' -import { ADDRESS_ZERO, TokenAddress } from '../../../utils/addresses' -import { blockFrequencyTracker } from '../../../utils/blockFrequencyUpdater' -import { LogFilter, logFilter } from '../../../utils/logFilter' -import { multicall } from '../../../utils/multicall' +import { ADDRESS_ZERO, TokenAddress } from '@utils/addresses' +import { blockFrequencyTracker } from '@utils/blockFrequencyUpdater' +import { LogFilter, logFilter } from '@utils/logFilter' +import { multicall } from '@utils/multicall' const duplicateTracker = new Set() @@ -69,7 +74,8 @@ export const createERC20Tracker = ({ contract.decimals(), ]) erc20 = new ERC20({ - id: address, + id: `${ctx.chain.id}-${address}`, + chainId: ctx.chain.id, address, name, symbol, @@ -106,6 +112,7 @@ export const createERC20Tracker = ({ const result = { states: new Map(), balances: new Map(), + transfers: new Map(), newHolders: new Map(), removedHolders: new Set(), } @@ -113,10 +120,11 @@ export const createERC20Tracker = ({ if (block.header.height < from) continue const contract = new abi.Contract(ctx, block.header, address) const updateState = async () => { - const id = `${block.header.height}:${address}` + const id = `${ctx.chain.id}-${block.header.height}-${address}` const totalSupply = await contract.totalSupply() const state = new ERC20State({ id, + chainId: ctx.chain.id, address, timestamp: new Date(block.header.timestamp), blockNumber: block.header.height, @@ -143,9 +151,10 @@ export const createERC20Tracker = ({ accounts.forEach((account, i) => { if (account === ADDRESS_ZERO) return account = account.toLowerCase() - const id = `${block.header.height}:${address}:${account}` + const id = `${ctx.chain.id}-${block.header.height}-${address}-${account}` const balance = new ERC20Balance({ id, + chainId: ctx.chain.id, timestamp: new Date(block.header.timestamp), blockNumber: block.header.height, address, @@ -156,11 +165,12 @@ export const createERC20Tracker = ({ if (balance.balance === 0n) { doStateUpdate = true holders.delete(account) - result.newHolders.delete(`${address}:${account}`) - result.removedHolders.add(`${address}:${account}`) + result.newHolders.delete(account) + result.removedHolders.add(account) } else if (!holders.has(account)) { const newHolder = new ERC20Holder({ - id: `${address}:${account}`, + id: `${ctx.chain.id}-${address}-${account}`, + chainId: ctx.chain.id, address, account, }) @@ -168,8 +178,8 @@ export const createERC20Tracker = ({ doStateUpdate = true holders.add(account) } - result.newHolders.set(`${address}:${account}`, newHolder) - result.removedHolders.delete(`${address}:${account}`) + result.newHolders.set(newHolder.account, newHolder) + result.removedHolders.delete(newHolder.account) } }) } @@ -186,9 +196,21 @@ export const createERC20Tracker = ({ for (const log of block.logs) { const isTransferLog = transferLogFilters.find((l) => l.matches(log)) if (isTransferLog) { - const transfer = abi.events.Transfer.decode(log) - accounts.add(transfer.from.toLowerCase()) - accounts.add(transfer.to.toLowerCase()) + const data = abi.events.Transfer.decode(log) + accounts.add(data.from.toLowerCase()) + accounts.add(data.to.toLowerCase()) + const transfer = new ERC20Transfer({ + id: `${ctx.chain.id}-${log.id}`, + chainId: ctx.chain.id, + txHash: log.transactionHash, + blockNumber: block.header.height, + timestamp: new Date(block.header.timestamp), + address: log.address, + from: data.from.toLowerCase(), + to: data.to.toLowerCase(), + value: data.value, + }) + result.transfers.set(transfer.id, transfer) } const isRebaseLog = rebaseFilters.find((l) => l.matches(log)) if (isRebaseLog) { @@ -207,6 +229,7 @@ export const createERC20Tracker = ({ ctx.store.upsert([...result.newHolders.values()]), ctx.store.insert([...result.states.values()]), ctx.store.insert([...result.balances.values()]), + ctx.store.insert([...result.transfers.values()]), ctx.store.remove( [...result.removedHolders.values()].map( (id) => new ERC20Holder({ id }), diff --git a/src/shared/processor-templates/erc20/index.ts b/src/templates/erc20/index.ts similarity index 100% rename from src/shared/processor-templates/erc20/index.ts rename to src/templates/erc20/index.ts diff --git a/src/shared/processor-templates/maverick/index.ts b/src/templates/maverick/index.ts similarity index 100% rename from src/shared/processor-templates/maverick/index.ts rename to src/templates/maverick/index.ts diff --git a/src/shared/processor-templates/maverick/maverick.ts b/src/templates/maverick/maverick.ts similarity index 82% rename from src/shared/processor-templates/maverick/maverick.ts rename to src/templates/maverick/maverick.ts index 94beb1fb..49c49608 100644 --- a/src/shared/processor-templates/maverick/maverick.ts +++ b/src/templates/maverick/maverick.ts @@ -1,17 +1,11 @@ +import * as maverickPool from '@abi/maverick-pool' +import { LiquiditySourceType, MaverickPool, MaverickPoolBalance } from '@model' +import { Context } from '@processor' +import { updateLiquidityBalances } from '@shared/post-processors/liquidity' import { EvmBatchProcessor } from '@subsquid/evm-processor' -import { add } from 'lodash' +import { blockFrequencyUpdater } from '@utils/blockFrequencyUpdater' -import * as maverickPool from '../../../abi/maverick-pool' -import { - LiquiditySource, - LiquiditySourceType, - MaverickPool, - MaverickPoolBalance, -} from '../../../model' -import { Context } from '../../../processor' -import { blockFrequencyUpdater } from '../../../utils/blockFrequencyUpdater' -import { updateLiquidityBalances } from '../../post-processors/liquidity' -import { registerLiquiditySource } from '../../processors/liquidity-sources' +import { registerLiquiditySource } from '../../mainnet/processors/liquidity-sources' // Maverick Pool Reference: https://docs.mav.xyz/guides/technical-reference/pool diff --git a/src/shared/processor-templates/otoken/index.ts b/src/templates/otoken/index.ts similarity index 100% rename from src/shared/processor-templates/otoken/index.ts rename to src/templates/otoken/index.ts diff --git a/src/shared/processor-templates/otoken/otoken.ts b/src/templates/otoken/otoken.ts similarity index 89% rename from src/shared/processor-templates/otoken/otoken.ts rename to src/templates/otoken/otoken.ts index 8469f82c..0a60a6c3 100644 --- a/src/shared/processor-templates/otoken/otoken.ts +++ b/src/templates/otoken/otoken.ts @@ -1,10 +1,9 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' import { groupBy } from 'lodash' import { GetTransactionReceiptReturnType } from 'viem' -import * as erc20 from '../../../abi/erc20' -import * as otoken from '../../../abi/otoken' -import * as otokenVault from '../../../abi/otoken-vault' +import * as erc20 from '@abi/erc20' +import * as otoken from '@abi/otoken' +import * as otokenVault from '@abi/otoken-vault' import { HistoryType, OETH, @@ -15,6 +14,7 @@ import { OETHHistory, OETHRebase, OETHRebaseOption, + OTokenVault, OUSD, OUSDAPY, OUSDActivity, @@ -24,20 +24,22 @@ import { OUSDRebase, OUSDRebaseOption, RebasingOption, - WOETHHistory, -} from '../../../model' -import { Context } from '../../../processor' -import { type Transaction, activityFromTx } from '../../../utils/activityFromTx' -import { ADDRESS_ZERO } from '../../../utils/addresses' -import { DECIMALS_18 } from '../../../utils/constants' -import { multicall } from '../../../utils/multicall' -import { EntityClassT, InstanceTypeOfConstructor } from '../../../utils/type' -import { getLatestEntity } from '../../../utils/utils' -import { ensureExchangeRate } from '../../post-processors/exchange-rates' +} from '@model' +import { Context } from '@processor' +import { ensureExchangeRate } from '@shared/post-processors/exchange-rates' import { CurrencyAddress, CurrencySymbol, -} from '../../post-processors/exchange-rates/currencies' +} from '@shared/post-processors/exchange-rates/currencies' +import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { type Transaction, activityFromTx } from '@utils/activityFromTx' +import { ADDRESS_ZERO } from '@utils/addresses' +import { blockFrequencyUpdater } from '@utils/blockFrequencyUpdater' +import { DECIMALS_18 } from '@utils/constants' +import { multicall } from '@utils/multicall' +import { EntityClassT, InstanceTypeOfConstructor } from '@utils/type' +import { getLatestEntity } from '@utils/utils' + import { createAddress, createRebaseAPY } from './utils' type OToken = EntityClassT | EntityClassT @@ -46,7 +48,6 @@ type OTokenAPY = EntityClassT | EntityClassT type OTokenActivity = EntityClassT | EntityClassT type OTokenAddress = EntityClassT | EntityClassT type OTokenHistory = EntityClassT | EntityClassT -type WOTokenHistory = EntityClassT type OTokenRebase = EntityClassT | EntityClassT type OTokenRebaseOption = | EntityClassT @@ -105,6 +106,8 @@ export const createOTokenSetup = } export const createOTokenProcessor = (params: { + from: number + vaultFrom: number Upgrade_CreditsBalanceOfHighRes?: number OTOKEN_ADDRESS: string WOTOKEN_ADDRESS?: string @@ -115,7 +118,6 @@ export const createOTokenProcessor = (params: { OTokenAPY: OTokenAPY OTokenAddress: OTokenAddress OTokenHistory: OTokenHistory - WOTokenHistory?: WOTokenHistory OTokenActivity: OTokenActivity OTokenRebase: OTokenRebase OTokenRebaseOption: OTokenRebaseOption @@ -126,11 +128,11 @@ export const createOTokenProcessor = (params: { otokens: InstanceTypeOfConstructor[] assets: InstanceTypeOfConstructor[] history: InstanceTypeOfConstructor[] - wrappedHistory: InstanceTypeOfConstructor[] rebases: InstanceTypeOfConstructor[] rebaseOptions: InstanceTypeOfConstructor[] apies: InstanceTypeOfConstructor[] activity: InstanceTypeOfConstructor[] + vaults: OTokenVault[] lastYieldDistributionEvent?: { fee: bigint yield: bigint @@ -147,6 +149,7 @@ export const createOTokenProcessor = (params: { idMap.set(partialId, nextId) return `${partialId}-${nextId}` } + const frequencyUpdate = blockFrequencyUpdater({ from: params.vaultFrom }) const process = async (ctx: Context) => { idMap = new Map() @@ -184,11 +187,11 @@ export const createOTokenProcessor = (params: { otokens: [], assets: [], history: [], - wrappedHistory: [], rebases: [], rebaseOptions: [], apies: [], activity: [], + vaults: [], } for (const block of ctx.blocks) { @@ -197,7 +200,6 @@ export const createOTokenProcessor = (params: { } for (const log of block.logs) { await processTransfer(ctx, result, block, log) - await processTransferWOETH(ctx, result, block, log) await processYieldDistribution(ctx, result, block, log) await processTotalSupplyUpdatedHighres(ctx, result, block, log) await processRebaseOptEvent(ctx, result, block, log) @@ -205,18 +207,36 @@ export const createOTokenProcessor = (params: { await processActivity(ctx, result, block) } + await frequencyUpdate(ctx, async (ctx, block) => { + const vaultContract = new otokenVault.Contract( + ctx, + block.header, + params.OTOKEN_VAULT_ADDRESS, + ) + result.vaults.push( + new OTokenVault({ + id: `${ctx.chain.id}-${block.header.height}-${params.OTOKEN_VAULT_ADDRESS}`, + blockNumber: block.header.height, + timestamp: new Date(block.header.timestamp), + chainId: ctx.chain.id, + address: params.OTOKEN_VAULT_ADDRESS, + totalValue: await vaultContract.totalValue(), + }), + ) + }) + if (owners) { await ctx.store.upsert([...owners.values()]) } + await ctx.store.upsert(result.apies) await Promise.all([ - ctx.store.upsert(result.apies), ctx.store.insert(result.otokens), ctx.store.insert(result.assets), ctx.store.insert(result.history), - ctx.store.insert(result.wrappedHistory), ctx.store.insert(result.rebases), ctx.store.insert(result.rebaseOptions), ctx.store.insert(result.activity), + ctx.store.insert(result.vaults), ]) } @@ -360,45 +380,6 @@ export const createOTokenProcessor = (params: { } } - const processTransferWOETH = async ( - ctx: Context, - result: ProcessResult, - block: Context['blocks']['0'], - log: Context['blocks']['0']['logs']['0'], - ) => { - if (!params.WOTokenHistory) return - if (log.address !== params.WOTOKEN_ADDRESS) return - if (log.topics[0] === otoken.events.Transfer.topic) { - const dataRaw = otoken.events.Transfer.decode(log) - const data = { - from: dataRaw.from.toLowerCase(), - to: dataRaw.to.toLowerCase(), - value: dataRaw.value, - } - - result.wrappedHistory.push( - new params.WOTokenHistory({ - id: getUniqueId(`${log.id}-${params.WOTOKEN_ADDRESS}`), - address: data.from, - value: -data.value, - timestamp: new Date(block.header.timestamp), - blockNumber: block.header.height, - txHash: log.transactionHash, - type: HistoryType.Sent, - }), - new params.WOTokenHistory({ - id: getUniqueId(`${log.id}-${params.WOTOKEN_ADDRESS}`), - address: data.to, - value: data.value, - timestamp: new Date(block.header.timestamp), - blockNumber: block.header.height, - txHash: log.transactionHash, - type: HistoryType.Received, - }), - ) - } - } - const processActivity = async ( ctx: Context, result: ProcessResult, @@ -470,7 +451,7 @@ export const createOTokenProcessor = (params: { } // Rebase events - let rebase = createRebaseAPY( + const rebase = createRebaseAPY( params.OTokenAPY, params.OTokenRebase, ctx, @@ -563,7 +544,7 @@ export const createOTokenProcessor = (params: { owners!.set(address, owner) } - let rebaseOption = new params.OTokenRebaseOption({ + const rebaseOption = new params.OTokenRebaseOption({ id: getUniqueId(`${trace.transaction?.hash!}-${owner.id}`), timestamp, blockNumber, @@ -634,7 +615,7 @@ export const createOTokenProcessor = (params: { owners!.set(address, owner) } - let rebaseOption = new params.OTokenRebaseOption({ + const rebaseOption = new params.OTokenRebaseOption({ id: getUniqueId(`${log.transactionHash!}-${owner.id}`), timestamp, blockNumber, diff --git a/src/shared/processor-templates/otoken/utils.ts b/src/templates/otoken/utils.ts similarity index 96% rename from src/shared/processor-templates/otoken/utils.ts rename to src/templates/otoken/utils.ts index 272525ad..5ae18578 100644 --- a/src/shared/processor-templates/otoken/utils.ts +++ b/src/templates/otoken/utils.ts @@ -2,7 +2,7 @@ import dayjs from 'dayjs' import utc from 'dayjs/plugin/utc' import { LessThan, MoreThanOrEqual } from 'typeorm' -import * as otoken from '../../../abi/otoken' +import * as otoken from '@abi/otoken' import { ExchangeRate, OETHAPY, @@ -12,9 +12,9 @@ import { OUSDAddress, OUSDRebase, RebasingOption, -} from '../../../model' -import { Context } from '../../../processor' -import { calculateAPY } from '../../../utils/calculateAPY' +} from '@model' +import { Context } from '@processor' +import { calculateAPY } from '@utils/calculateAPY' dayjs.extend(utc) diff --git a/src/shared/processor-templates/processor-status/index.ts b/src/templates/processor-status/index.ts similarity index 100% rename from src/shared/processor-templates/processor-status/index.ts rename to src/templates/processor-status/index.ts diff --git a/src/shared/processor-templates/processor-status/processor-status.ts b/src/templates/processor-status/processor-status.ts similarity index 85% rename from src/shared/processor-templates/processor-status/processor-status.ts rename to src/templates/processor-status/processor-status.ts index dec2abd2..a078eb89 100644 --- a/src/shared/processor-templates/processor-status/processor-status.ts +++ b/src/templates/processor-status/processor-status.ts @@ -1,5 +1,5 @@ -import { ProcessingStatus } from '../../../model' -import { Context } from '../../../processor' +import { ProcessingStatus } from '@model' +import { Context } from '@processor' const processorIds = new Set() diff --git a/src/shared/processor-templates/strategy-rewards/index.ts b/src/templates/strategy-rewards/index.ts similarity index 100% rename from src/shared/processor-templates/strategy-rewards/index.ts rename to src/templates/strategy-rewards/index.ts diff --git a/src/shared/processor-templates/strategy-rewards/strategy-rewards.ts b/src/templates/strategy-rewards/strategy-rewards.ts similarity index 87% rename from src/shared/processor-templates/strategy-rewards/strategy-rewards.ts rename to src/templates/strategy-rewards/strategy-rewards.ts index 7b655253..c40fab4c 100644 --- a/src/shared/processor-templates/strategy-rewards/strategy-rewards.ts +++ b/src/templates/strategy-rewards/strategy-rewards.ts @@ -1,9 +1,8 @@ +import * as iat from '@abi/initializable-abstract-strategy' +import { OETHRewardTokenCollected } from '@model' +import { Context } from '@processor' import { EvmBatchProcessor } from '@subsquid/evm-processor' - -import * as iat from '../../../abi/initializable-abstract-strategy' -import { OETHRewardTokenCollected } from '../../../model' -import { Context } from '../../../processor' -import { EntityClassT } from '../../../utils/type' +import { EntityClassT } from '@utils/type' export const createStrategyRewardSetup = ({ address, diff --git a/src/shared/processor-templates/strategy/index.ts b/src/templates/strategy/index.ts similarity index 100% rename from src/shared/processor-templates/strategy/index.ts rename to src/templates/strategy/index.ts diff --git a/src/shared/processor-templates/strategy/strategy-balancer.ts b/src/templates/strategy/strategy-balancer.ts similarity index 85% rename from src/shared/processor-templates/strategy/strategy-balancer.ts rename to src/templates/strategy/strategy-balancer.ts index 09334248..0eb0aace 100644 --- a/src/shared/processor-templates/strategy/strategy-balancer.ts +++ b/src/templates/strategy/strategy-balancer.ts @@ -1,18 +1,18 @@ +import * as balancerMetaStablePoolStrategyAbi from '@abi/balancer-meta-pool-strategy' +import * as balancerRateProvider from '@abi/balancer-rate-provider' +import * as balancerVaultAbi from '@abi/balancer-vault' +import { StrategyBalance } from '@model' +import { Context } from '@processor' +import { getBalancePoolRateProviders } from '@shared/post-processors/exchange-rates/price-routing' import { EvmBatchProcessor } from '@subsquid/evm-processor' - -import * as balancerMetaStablePoolStrategyAbi from '../../../abi/balancer-meta-pool-strategy' -import * as balancerRateProvider from '../../../abi/balancer-rate-provider' -import * as balancerVaultAbi from '../../../abi/balancer-vault' -import { StrategyBalance } from '../../../model' -import { Context } from '../../../processor' import { ADDRESS_ZERO, BALANCER_VAULT, ETH_ADDRESS, WETH_ADDRESS, -} from '../../../utils/addresses' -import { blockFrequencyUpdater } from '../../../utils/blockFrequencyUpdater' -import { getBalancePoolRateProviders } from '../../post-processors/exchange-rates/price-routing' +} from '@utils/addresses' +import { blockFrequencyUpdater } from '@utils/blockFrequencyUpdater' + import { IStrategyData } from './index' import { processStrategyEarnings, @@ -104,7 +104,7 @@ export const getBalancerStrategyHoldings = async ( block, BALANCER_VAULT, ) - let [poolAssets, balances] = await balancerVault.getPoolTokens(poolId) + const [poolAssets, balances] = await balancerVault.getPoolTokens(poolId) const totalStrategyBalance = await strategy['checkBalance()']() // in WETH const eth1 = BigInt('1000000000000000000') diff --git a/src/shared/processor-templates/strategy/strategy-curve-amo.ts b/src/templates/strategy/strategy-curve-amo.ts similarity index 90% rename from src/shared/processor-templates/strategy/strategy-curve-amo.ts rename to src/templates/strategy/strategy-curve-amo.ts index 073161cc..3b684327 100644 --- a/src/shared/processor-templates/strategy/strategy-curve-amo.ts +++ b/src/templates/strategy/strategy-curve-amo.ts @@ -1,12 +1,12 @@ +import * as curvePool from '@abi/curve-lp-token' +import * as erc20 from '@abi/erc20' +import * as abstractStrategyAbi from '@abi/initializable-abstract-strategy' +import { StrategyBalance } from '@model' +import { Block, Context } from '@processor' import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { ETH_ADDRESS, WETH_ADDRESS } from '@utils/addresses' +import { blockFrequencyUpdater } from '@utils/blockFrequencyUpdater' -import * as curvePool from '../../../abi/curve-lp-token' -import * as erc20 from '../../../abi/erc20' -import * as abstractStrategyAbi from '../../../abi/initializable-abstract-strategy' -import { StrategyBalance } from '../../../model' -import { Block, Context } from '../../../processor' -import { ETH_ADDRESS, WETH_ADDRESS } from '../../../utils/addresses' -import { blockFrequencyUpdater } from '../../../utils/blockFrequencyUpdater' import { IStrategyData } from './index' import { processStrategyEarnings, diff --git a/src/shared/processor-templates/strategy/strategy-daily-earnings.ts b/src/templates/strategy/strategy-daily-earnings.ts similarity index 95% rename from src/shared/processor-templates/strategy/strategy-daily-earnings.ts rename to src/templates/strategy/strategy-daily-earnings.ts index b136541e..c8bcc78f 100644 --- a/src/shared/processor-templates/strategy/strategy-daily-earnings.ts +++ b/src/templates/strategy/strategy-daily-earnings.ts @@ -2,10 +2,11 @@ import dayjs from 'dayjs' import { Between, LessThan, LessThanOrEqual } from 'typeorm' import { parseEther } from 'viem' -import { StrategyDailyYield, StrategyYield } from '../../../model' -import { Block, Context } from '../../../processor' -import { calculateAPY } from '../../../utils/calculateAPY' -import { lastExcept, max } from '../../../utils/utils' +import { StrategyDailyYield, StrategyYield } from '@model' +import { Block, Context } from '@processor' +import { calculateAPY } from '@utils/calculateAPY' +import { lastExcept, max } from '@utils/utils' + import { IStrategyData } from './strategy' const eth1 = 1000000000000000000n diff --git a/src/shared/processor-templates/strategy/strategy-earnings.ts b/src/templates/strategy/strategy-earnings.ts similarity index 94% rename from src/shared/processor-templates/strategy/strategy-earnings.ts rename to src/templates/strategy/strategy-earnings.ts index 0470c965..a7267931 100644 --- a/src/shared/processor-templates/strategy/strategy-earnings.ts +++ b/src/templates/strategy/strategy-earnings.ts @@ -1,15 +1,19 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' import dayjs from 'dayjs' import { LessThan } from 'typeorm' -import { formatEther, pad } from 'viem' - -import * as baseRewardPool from '../../../abi/base-reward-pool' -import * as erc20 from '../../../abi/erc20' -import * as abstractStrategyAbi from '../../../abi/initializable-abstract-strategy' -import { StrategyYield } from '../../../model' -import { Block, Context } from '../../../processor' +import { formatEther } from 'viem' + +import * as baseRewardPool from '@abi/base-reward-pool' +import * as erc20 from '@abi/erc20' +import * as abstractStrategyAbi from '@abi/initializable-abstract-strategy' +import { StrategyYield } from '@model' +import { Block, Context } from '@processor' +import { ensureExchangeRates } from '@shared/post-processors/exchange-rates' +import { + Currency, + convertRate, +} from '@shared/post-processors/exchange-rates/currencies' +import { EvmBatchProcessor } from '@subsquid/evm-processor' import { - AURA_REWARDS_POOL_ADDRESS, OETH_ADDRESS, OETH_DRIPPER_ADDRESS, OETH_HARVESTER_ADDRESS, @@ -18,15 +22,11 @@ import { OUSD_HARVESTER_ADDRESS, USDT_ADDRESS, WETH_ADDRESS, -} from '../../../utils/addresses' -import { blockFrequencyTracker } from '../../../utils/blockFrequencyUpdater' -import { logFilter } from '../../../utils/logFilter' -import { convertDecimals, lastExcept } from '../../../utils/utils' -import { ensureExchangeRates } from '../../post-processors/exchange-rates' -import { - Currency, - convertRate, -} from '../../post-processors/exchange-rates/currencies' +} from '@utils/addresses' +import { blockFrequencyTracker } from '@utils/blockFrequencyUpdater' +import { logFilter } from '@utils/logFilter' +import { convertDecimals, lastExcept } from '@utils/utils' + import { IStrategyData } from './strategy' import { processStrategyDailyEarnings } from './strategy-daily-earnings' @@ -500,7 +500,7 @@ const getLatest = async ( results = [] resultMap.set(asset, results) } - let latest = + const latest = lastExcept(resultMap.get(asset), id) ?? (await ctx.store.findOne(StrategyYield, { order: { blockNumber: 'desc' }, @@ -510,6 +510,6 @@ const getLatest = async ( asset, }, })) - let current = resultMap.get(asset)?.find((l) => l.id === id) + const current = resultMap.get(asset)?.find((l) => l.id === id) return { latest, current, results } } diff --git a/src/shared/processor-templates/strategy/strategy-generic.ts b/src/templates/strategy/strategy-generic.ts similarity index 85% rename from src/shared/processor-templates/strategy/strategy-generic.ts rename to src/templates/strategy/strategy-generic.ts index d5132ca3..9676094f 100644 --- a/src/shared/processor-templates/strategy/strategy-generic.ts +++ b/src/templates/strategy/strategy-generic.ts @@ -1,11 +1,11 @@ +import * as abstractStrategyAbi from '@abi/initializable-abstract-strategy' +import { StrategyBalance } from '@model' +import { Block, Context } from '@processor' +import { ensureExchangeRates } from '@shared/post-processors/exchange-rates' +import { CurrencyAddress } from '@shared/post-processors/exchange-rates/currencies' import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { blockFrequencyUpdater } from '@utils/blockFrequencyUpdater' -import * as abstractStrategyAbi from '../../../abi/initializable-abstract-strategy' -import { StrategyBalance } from '../../../model' -import { Block, Context } from '../../../processor' -import { blockFrequencyUpdater } from '../../../utils/blockFrequencyUpdater' -import { ensureExchangeRates } from '../../post-processors/exchange-rates' -import { CurrencyAddress } from '../../post-processors/exchange-rates/currencies' import { IStrategyData } from './index' import { processStrategyEarnings, diff --git a/src/shared/processor-templates/strategy/strategy-vault.ts b/src/templates/strategy/strategy-vault.ts similarity index 89% rename from src/shared/processor-templates/strategy/strategy-vault.ts rename to src/templates/strategy/strategy-vault.ts index 5e4416a8..b7e7c50c 100644 --- a/src/shared/processor-templates/strategy/strategy-vault.ts +++ b/src/templates/strategy/strategy-vault.ts @@ -1,10 +1,10 @@ +import * as erc20 from '@abi/erc20' +import { StrategyBalance } from '@model' +import { Block, Context } from '@processor' import { EvmBatchProcessor } from '@subsquid/evm-processor' +import { blockFrequencyUpdater } from '@utils/blockFrequencyUpdater' +import { convertDecimals } from '@utils/utils' -import * as erc20 from '../../../abi/erc20' -import { StrategyBalance } from '../../../model' -import { Block, Context } from '../../../processor' -import { blockFrequencyUpdater } from '../../../utils/blockFrequencyUpdater' -import { convertDecimals } from '../../../utils/utils' import { IStrategyData } from './index' import { processStrategyEarnings, diff --git a/src/shared/processor-templates/strategy/strategy.ts b/src/templates/strategy/strategy.ts similarity index 85% rename from src/shared/processor-templates/strategy/strategy.ts rename to src/templates/strategy/strategy.ts index 5cdc8a9f..53d715f3 100644 --- a/src/shared/processor-templates/strategy/strategy.ts +++ b/src/templates/strategy/strategy.ts @@ -1,13 +1,12 @@ +import { Context } from '@processor' +import { ensureExchangeRates } from '@shared/post-processors/exchange-rates' +import { CurrencyAddress } from '@shared/post-processors/exchange-rates/currencies' import { EvmBatchProcessor } from '@subsquid/evm-processor' -import durationPlugin from 'dayjs/plugin/duration' +import { OETH_ADDRESS, OUSD_ADDRESS } from '@utils/addresses' +import { blockFrequencyUpdater } from '@utils/blockFrequencyUpdater' +import { LogFilter } from '@utils/logFilter' +import { TraceFilter } from '@utils/traceFilter' -import { Context } from '../../../processor' -import { OETH_ADDRESS, OUSD_ADDRESS } from '../../../utils/addresses' -import { blockFrequencyUpdater } from '../../../utils/blockFrequencyUpdater' -import { LogFilter } from '../../../utils/logFilter' -import { TraceFilter } from '../../../utils/traceFilter' -import { ensureExchangeRates } from '../../post-processors/exchange-rates' -import { CurrencyAddress } from '../../post-processors/exchange-rates/currencies' import * as strategyBalancer from './strategy-balancer' import * as strategyCurveAMO from './strategy-curve-amo' import * as strategyGeneric from './strategy-generic' diff --git a/src/types.d.ts b/src/types.d.ts new file mode 100644 index 00000000..b20f78e2 --- /dev/null +++ b/src/types.d.ts @@ -0,0 +1 @@ +declare module 'tsconfig-paths/register' diff --git a/src/utils/activityFromTx.ts b/src/utils/activityFromTx.ts index 21141d14..3eaafdb1 100644 --- a/src/utils/activityFromTx.ts +++ b/src/utils/activityFromTx.ts @@ -1,16 +1,11 @@ import { compact } from 'lodash' -import { - GetTransactionReceiptReturnType, - decodeEventLog, - decodeFunctionData, - parseAbi, -} from 'viem' - -import * as balancerVaultAbi from '../abi/balancer-vault.abi' -import * as curveLpAbi from '../abi/curve-lp-token.abi' -import * as oethZapperAbi from '../abi/oeth-zapper.abi' -import * as oethAbi from '../abi/oeth.abi' -import * as oethVaultAbi from '../abi/otoken-vault.abi' +import { GetTransactionReceiptReturnType, decodeEventLog, parseAbi } from 'viem' + +import * as balancerVaultAbi from '@abi/balancer-vault.abi' +import * as curveLpAbi from '@abi/curve-lp-token.abi' +import * as oethAbi from '@abi/oeth.abi' +import * as oethVaultAbi from '@abi/otoken-vault.abi' + import { OETH_ADDRESS, OETH_VAULT_ADDRESS, diff --git a/src/utils/addresses.ts b/src/utils/addresses.ts index 99ba0fbb..5a752de5 100644 --- a/src/utils/addresses.ts +++ b/src/utils/addresses.ts @@ -21,6 +21,8 @@ export const OETH_HARVESTER_ADDRESS = `0x0d017afa83eace9f10a8ec5b6e13941664a6785 export const OETH_ZAPPER_ADDRESS = '0x9858e47bcbbe6fbac040519b02d7cd4b2c470c66' export const OETH_DRIPPER_ADDRESS = '0xc0f42f73b8f01849a2dd99753524d4ba14317eb3' export const WOETH_ADDRESS = '0xdcee70654261af21c44c093c300ed3bb97b78192' +export const WOETH_ARBITRUM_ADDRESS = + '0xd8724322f44e5c58d7a815f542036fb17dbbf839' export const WETH_ADDRESS = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' export const STETH_ADDRESS = '0xae7ab96520de3a18e5e111b5eaab095312d7fe84' @@ -84,6 +86,7 @@ export const tokens = { OETH: OETH_ADDRESS, OUSD: OUSD_ADDRESS, wOETH: WOETH_ADDRESS, + wOETH_arbitrum: WOETH_ARBITRUM_ADDRESS, // Dollar DAI: DAI_ADDRESS, diff --git a/src/utils/blockFrequencyUpdater.ts b/src/utils/blockFrequencyUpdater.ts index 4912294b..b73134ea 100644 --- a/src/utils/blockFrequencyUpdater.ts +++ b/src/utils/blockFrequencyUpdater.ts @@ -2,7 +2,7 @@ import dayjs from 'dayjs' import duration from 'dayjs/plugin/duration' import utc from 'dayjs/plugin/utc' -import { Block, Context } from '../processor' +import { Block, Context } from '@processor' dayjs.extend(duration) dayjs.extend(utc) @@ -17,63 +17,69 @@ const oneMonthAgo = dayjs.utc().subtract(1, 'month').valueOf() const oneWeekAgo = dayjs.utc().subtract(1, 'week').valueOf() const oneDayAgo = dayjs.utc().subtract(1, 'day').valueOf() const oneHourAgo = dayjs.utc().subtract(1, 'hour').valueOf() +const fifteenMinutesAgo = dayjs.utc().subtract(15, 'minutes').valueOf() -const getFrequency = (bps: number, timestamp: number) => { - let frequency = 1 +const getFrequency = (blockRate: number, timestamp: number) => { if (timestamp < oneYearAgo) { - frequency = (SECONDS_PER_WEEK / bps) ^ 0 // Older than one year ago + return (SECONDS_PER_WEEK / blockRate) ^ 0 // Older than one year ago } else if (timestamp < oneMonthAgo) { - frequency = (SECONDS_PER_DAY / bps) ^ 0 // Older than one month ago + return (SECONDS_PER_DAY / blockRate) ^ 0 // Older than one month ago } else if (timestamp < oneWeekAgo) { - frequency = (SECONDS_PER_DAY / bps / 4) ^ 0 // Older than one week ago + return (SECONDS_PER_DAY / blockRate / 4) ^ 0 // Older than one week ago } else if (timestamp < oneDayAgo) { - frequency = (SECONDS_PER_DAY / bps / 24) ^ 0 // Older than one day ago + return (SECONDS_PER_DAY / blockRate / 12) ^ 0 // Older than one day ago } else if (timestamp < oneHourAgo) { - frequency = ((SECONDS_PER_MINUTE * 5) / bps) ^ 0 // Older than one hour ago + return ((SECONDS_PER_MINUTE * 30) / blockRate) ^ 0 // Older than one hour ago + } else if (timestamp < fifteenMinutesAgo) { + return ((SECONDS_PER_MINUTE * 5) / blockRate) ^ 0 // Older than 15 minutes ago } else { - frequency = (SECONDS_PER_MINUTE / bps) ^ 0 + return (SECONDS_PER_MINUTE / blockRate) ^ 0 } - return frequency || 1 } export const blockFrequencyTracker = (params: { from: number }) => { - let nextBlockToProcess = params.from - const shouldProcess = (b: Block, frequency: number) => { - let result = b.header.height >= nextBlockToProcess - if (result) { - nextBlockToProcess = - Math.floor((b.header.height + frequency) / frequency) * frequency - } - return result - } return (ctx: Context, block: Block) => { if (block.header.height < params.from) return - const { bps } = ctx - const frequency: number = getFrequency(bps, block.header.timestamp) - return shouldProcess(block, frequency) + const frequency: number = getFrequency( + ctx.blockRate, + block.header.timestamp, + ) + return block.header.height % frequency === 0 } } export const blockFrequencyUpdater = (params: { from: number }) => { - let nextBlockToProcess = params.from - const shouldProcess = (b: Block) => { - return b.header.height >= nextBlockToProcess - } return async ( ctx: Context, fn: (ctx: Context, block: Block) => Promise, ) => { if (!ctx.blocks.length) return - // If we're not at head, determine our frequency and then process. - const { bps } = ctx - let frequency: number = getFrequency(bps, ctx.blocks[0].header.timestamp) - for (let i = 0; i < ctx.blocks.length; i += frequency) { + if (ctx.blocks[ctx.blocks.length - 1].header.height < params.from) { + // No applicable blocks in current context. + return + } + let frequency: number = getFrequency( + ctx.blockRate, + ctx.blocks[0].header.timestamp, + ) + for ( + let i = ctx.blocks.findIndex( + (b) => + b.header.height % frequency === 0 && b.header.height >= params.from, + ); + i < ctx.blocks.length; + i += frequency + ) { const block = ctx.blocks[i] - if (!shouldProcess(block)) continue + if (!block) break + if (block.header.height % frequency !== 0) { + throw new Error( + 'This should never happen. Ensure you are passing all blocks through here.', + ) + } await fn(ctx, block) - nextBlockToProcess = - Math.floor((block.header.height + frequency) / frequency) * frequency - frequency = getFrequency(bps, block.header.timestamp) + frequency = getFrequency(ctx.blockRate, block.header.timestamp) + i -= ctx.blocks[i].header.height % frequency } } } diff --git a/src/utils/calculateBPS.ts b/src/utils/calculateBPS.ts deleted file mode 100644 index 1ad14b1f..00000000 --- a/src/utils/calculateBPS.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { hexToNumber, numberToHex } from 'viem' - -import { Context } from '../processor' - -let lastBpsFrom = 0 -let lastResult = 0 - -export const calculateBPS = async (ctx: Context) => { - const lastBlockNumber = ctx.blocks[ctx.blocks.length - 1].header.height - const bpsTestRange = 100_000 - const bpsFrom = Math.max( - 1, - Math.floor(lastBlockNumber / bpsTestRange) * bpsTestRange - bpsTestRange, - ) - if (bpsFrom === lastBpsFrom) { - return lastResult - } - const bpsTo = bpsFrom + bpsTestRange - const [bpsBlockFrom, bpsBlockTo] = (await ctx._chain.client.batchCall([ - { - method: 'eth_getBlockByNumber', - params: [numberToHex(bpsFrom), false], - }, - { - method: 'eth_getBlockByNumber', - params: [numberToHex(bpsTo), false], - }, - ])) as { timestamp: `0x${string}` }[] - - const seconds = - hexToNumber(bpsBlockTo.timestamp) - hexToNumber(bpsBlockFrom.timestamp) - const result = seconds / bpsTestRange - lastResult = result - return result -} diff --git a/src/utils/calculateBlockRate.ts b/src/utils/calculateBlockRate.ts new file mode 100644 index 00000000..9f053863 --- /dev/null +++ b/src/utils/calculateBlockRate.ts @@ -0,0 +1,44 @@ +import { hexToNumber, numberToHex } from 'viem' +import { arbitrum, mainnet } from 'viem/chains' + +import { Context } from '@processor' + +let lastRateFrom = 0 +let lastResult = 0 + +const blockRates: Record = { + [mainnet.id]: 12, + [arbitrum.id]: 0.26, +} + +export const calculateBlockRate = async (ctx: Context) => { + if (ctx.isHead && blockRates[ctx.chain.id]) { + return blockRates[ctx.chain.id] + } + const lastBlockNumber = ctx.blocks[ctx.blocks.length - 1].header.height + const rateTestRange = 100_000 + const rateFrom = Math.max( + 1, + Math.floor(lastBlockNumber / rateTestRange) * rateTestRange - rateTestRange, + ) + if (rateFrom === lastRateFrom) { + return lastResult + } + const rateTo = Math.min(rateFrom + rateTestRange, lastBlockNumber) + const [rateBlockFrom, rateBlockTo] = (await ctx._chain.client.batchCall([ + { + method: 'eth_getBlockByNumber', + params: [numberToHex(rateFrom), false], + }, + { + method: 'eth_getBlockByNumber', + params: [numberToHex(rateTo), false], + }, + ])) as { timestamp: `0x${string}` }[] + + const seconds = + hexToNumber(rateBlockTo.timestamp) - hexToNumber(rateBlockFrom.timestamp) + const result = seconds / rateTestRange + lastResult = result + return result +} diff --git a/src/utils/coingecko.ts b/src/utils/coingecko.ts index 0936f2d7..c2f73a7a 100644 --- a/src/utils/coingecko.ts +++ b/src/utils/coingecko.ts @@ -1,9 +1,9 @@ import { Between, LessThanOrEqual } from 'typeorm' import { parseEther } from 'viem' -import { OETHDailyStat, OGVDailyStat, OUSDDailyStat } from '../model' -import { Context } from '../processor' -import { EntityClassT } from '../utils/type' +import { OETHDailyStat, OGVDailyStat, OUSDDailyStat } from '@model' +import { Context } from '@processor' +import { EntityClassT } from '@utils/type' type DailyStat = | EntityClassT diff --git a/src/utils/logFilter.ts b/src/utils/logFilter.ts index bb57657f..83b1df99 100644 --- a/src/utils/logFilter.ts +++ b/src/utils/logFilter.ts @@ -1,7 +1,7 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' import { pad as viemPad } from 'viem' -import { Log } from '../processor' +import { Log } from '@processor' +import { EvmBatchProcessor } from '@subsquid/evm-processor' const pad = (hex: string) => viemPad(hex as `0x${string}`) const lower = (hex: string) => hex.toLowerCase() diff --git a/src/utils/multicall.ts b/src/utils/multicall.ts index eaa6b5c0..704f8c1d 100644 --- a/src/utils/multicall.ts +++ b/src/utils/multicall.ts @@ -1,12 +1,23 @@ import { toHex } from 'viem' +import { arbitrum, mainnet } from 'viem/chains' -import { Func } from '../abi/abi.support' -import { Multicall } from '../abi/multicall' -import { Block, Context } from '../processor' - -const MULTICALL_CONTRACT = '0x5ba1e12693dc8f9c48aad8770482f4739beed696' -const from = 12336033 +import { Func } from '@abi/abi.support' +import { Multicall } from '@abi/multicall' +import { Block, Context } from '@processor' +const MULTICALL_CONTRACTS: Record< + number, + undefined | { from: number; address: string } +> = { + [mainnet.id]: { + from: 12336033, + address: '0x5ba1e12693dc8f9c48aad8770482f4739beed696', + }, + [arbitrum.id]: { + from: 821923, + address: '0x842ec2c7d803033edf55e478f461fc547bc54eb2', + }, +} export const multicall = async ( ctx: Context, header: Block['header'], @@ -14,8 +25,9 @@ export const multicall = async ( address: string, calls: Args[], ) => { - if (header.height >= from) { - const multicall = new Multicall(ctx, header, MULTICALL_CONTRACT) + const multicallContract = MULTICALL_CONTRACTS[ctx.chain.id] + if (multicallContract && header.height >= multicallContract.from) { + const multicall = new Multicall(ctx, header, multicallContract.address) return multicall.aggregate(func, address, calls) } const batchCalls = calls.map((fnParams) => ({ diff --git a/src/utils/nativeBalance.ts b/src/utils/nativeBalance.ts index df1c63d8..06f8ec72 100644 --- a/src/utils/nativeBalance.ts +++ b/src/utils/nativeBalance.ts @@ -1,6 +1,6 @@ import { hexToBigInt } from 'viem' -import { Context } from '../processor' +import { Context } from '@processor' export const getNativeBalance = async ( ctx: Context, diff --git a/src/utils/state.ts b/src/utils/state.ts index 1c8fd35a..ac257565 100644 --- a/src/utils/state.ts +++ b/src/utils/state.ts @@ -1,4 +1,4 @@ -import { Context } from '../processor' +import { Context } from '@processor' export const useProcessorState = ( ctx: Context, diff --git a/src/utils/traceFilter.ts b/src/utils/traceFilter.ts index 7ecb17a5..f4789d2e 100644 --- a/src/utils/traceFilter.ts +++ b/src/utils/traceFilter.ts @@ -1,7 +1,7 @@ -import { EvmBatchProcessor } from '@subsquid/evm-processor' import { pad as viemPad } from 'viem' -import { Trace } from '../processor' +import { Trace } from '@processor' +import { EvmBatchProcessor } from '@subsquid/evm-processor' const pad = (hex: string) => viemPad(hex as `0x${string}`) const lower = (hex: string) => hex.toLowerCase() diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 0a1aed23..6103fd1b 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,9 +1,9 @@ -import { Entity, EntityClass } from '@subsquid/typeorm-store' import { LessThanOrEqual } from 'typeorm' import { pad } from 'viem' -import * as erc20 from '../abi/erc20' -import { Context } from '../processor' +import * as erc20 from '@abi/erc20' +import { Context } from '@processor' +import { Entity, EntityClass } from '@subsquid/typeorm-store' export const max = (values: bigint[], start = 0n) => { return values.reduce((max, v) => (max > v ? max : v), start) diff --git a/tsconfig.json b/tsconfig.json index e59d8d66..2cb91563 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,28 @@ "experimentalDecorators": true, "emitDecoratorMetadata": true, "skipLibCheck": true, - "resolveJsonModule": true + "resolveJsonModule": true, + "baseUrl": "./src/", + "paths": { + "@abi/*": [ + "abi/*" + ], + "@model": [ + "model" + ], + "@processor": [ + "processor" + ], + "@shared/*": [ + "shared/*" + ], + "@templates/*": [ + "templates/*" + ], + "@utils/*": [ + "utils/*" + ] + } }, "include": [ "src"