diff --git a/packages/codegen/src/templates/fill-template.handlebars b/packages/codegen/src/templates/fill-template.handlebars index 15e634c2..5a6b1eab 100644 --- a/packages/codegen/src/templates/fill-template.handlebars +++ b/packages/codegen/src/templates/fill-template.handlebars @@ -8,11 +8,10 @@ import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import debug from 'debug'; import { PubSub } from 'apollo-server-express'; -import { getDefaultProvider } from 'ethers'; import { getCache } from '@vulcanize/cache'; import { EthClient } from '@vulcanize/ipld-eth-client'; -import { getConfig, fillBlocks, JobQueue, DEFAULT_CONFIG_PATH } from '@vulcanize/util'; +import { getConfig, fillBlocks, JobQueue, DEFAULT_CONFIG_PATH, getCustomProvider } from '@vulcanize/util'; import { Database } from './database'; import { Indexer } from './indexer'; @@ -71,7 +70,7 @@ export const main = async (): Promise => { cache }); - const ethProvider = getDefaultProvider(rpcProviderEndpoint); + const ethProvider = getCustomProvider(rpcProviderEndpoint); // Note: In-memory pubsub works fine for now, as each watcher is a single process anyway. // Later: https://www.apollographql.com/docs/apollo-server/data/subscriptions/#production-pubsub-libraries diff --git a/packages/codegen/src/templates/job-runner-template.handlebars b/packages/codegen/src/templates/job-runner-template.handlebars index c1f6c804..9fa01d76 100644 --- a/packages/codegen/src/templates/job-runner-template.handlebars +++ b/packages/codegen/src/templates/job-runner-template.handlebars @@ -7,7 +7,6 @@ import 'reflect-metadata'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import debug from 'debug'; -import { getDefaultProvider } from 'ethers'; import { getCache } from '@vulcanize/cache'; import { EthClient } from '@vulcanize/ipld-eth-client'; @@ -18,7 +17,8 @@ import { QUEUE_BLOCK_PROCESSING, QUEUE_EVENT_PROCESSING, JobQueueConfig, - DEFAULT_CONFIG_PATH + DEFAULT_CONFIG_PATH, + getCustomProvider } from '@vulcanize/util'; import { Indexer } from './indexer'; @@ -106,7 +106,7 @@ export const main = async (): Promise => { cache }); - const ethProvider = getDefaultProvider(rpcProviderEndpoint); + const ethProvider = getCustomProvider(rpcProviderEndpoint); const indexer = new Indexer(db, ethClient, postgraphileClient, ethProvider); assert(jobQueueConfig, 'Missing job queue config'); diff --git a/packages/codegen/src/templates/server-template.handlebars b/packages/codegen/src/templates/server-template.handlebars index ed588f74..80817762 100644 --- a/packages/codegen/src/templates/server-template.handlebars +++ b/packages/codegen/src/templates/server-template.handlebars @@ -13,11 +13,10 @@ import { hideBin } from 'yargs/helpers'; import debug from 'debug'; import 'graphql-import-node'; import { createServer } from 'http'; -import { getDefaultProvider } from 'ethers'; import { getCache } from '@vulcanize/cache'; import { EthClient } from '@vulcanize/ipld-eth-client'; -import { DEFAULT_CONFIG_PATH, getConfig, JobQueue, KIND_ACTIVE } from '@vulcanize/util'; +import { DEFAULT_CONFIG_PATH, getConfig, JobQueue, KIND_ACTIVE, getCustomProvider } from '@vulcanize/util'; import { createResolvers } from './resolvers'; import { Indexer } from './indexer'; @@ -68,7 +67,7 @@ export const main = async (): Promise => { cache }); - const ethProvider = getDefaultProvider(rpcProviderEndpoint); + const ethProvider = getCustomProvider(rpcProviderEndpoint); const indexer = new Indexer(db, ethClient, postgraphileClient, ethProvider); diff --git a/packages/erc20-watcher/src/fill.ts b/packages/erc20-watcher/src/fill.ts index 21ce258d..dbb098a7 100644 --- a/packages/erc20-watcher/src/fill.ts +++ b/packages/erc20-watcher/src/fill.ts @@ -8,11 +8,10 @@ import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import debug from 'debug'; import { PubSub } from 'apollo-server-express'; -import { getDefaultProvider } from 'ethers'; import { getCache } from '@vulcanize/cache'; import { EthClient } from '@vulcanize/ipld-eth-client'; -import { getConfig, fillBlocks, JobQueue, DEFAULT_CONFIG_PATH } from '@vulcanize/util'; +import { getConfig, fillBlocks, JobQueue, DEFAULT_CONFIG_PATH, getCustomProvider } from '@vulcanize/util'; import { Database } from './database'; import { Indexer } from './indexer'; @@ -68,7 +67,7 @@ export const main = async (): Promise => { cache }); - const ethProvider = getDefaultProvider(rpcProviderEndpoint); + const ethProvider = getCustomProvider(rpcProviderEndpoint); // Note: In-memory pubsub works fine for now, as each watcher is a single process anyway. // Later: https://www.apollographql.com/docs/apollo-server/data/subscriptions/#production-pubsub-libraries diff --git a/packages/erc20-watcher/src/indexer.ts b/packages/erc20-watcher/src/indexer.ts index ea195ea5..b4e4ce12 100644 --- a/packages/erc20-watcher/src/indexer.ts +++ b/packages/erc20-watcher/src/indexer.ts @@ -90,7 +90,7 @@ export class Indexer { let result: ValueResult; if (this._serverMode === ETH_CALL_MODE) { - const value = await fetchTokenTotalSupply(this._ethProvider, token); + const value = await fetchTokenTotalSupply(this._ethProvider, blockHash, token); result = { value }; } else { @@ -179,7 +179,7 @@ export class Indexer { let result: ValueResult; if (this._serverMode === ETH_CALL_MODE) { - const value = await fetchTokenName(this._ethProvider, token); + const value = await fetchTokenName(this._ethProvider, blockHash, token); result = { value }; } else { @@ -195,7 +195,7 @@ export class Indexer { let result: ValueResult; if (this._serverMode === ETH_CALL_MODE) { - const value = await fetchTokenSymbol(this._ethProvider, token); + const value = await fetchTokenSymbol(this._ethProvider, blockHash, token); result = { value }; } else { @@ -211,7 +211,7 @@ export class Indexer { let result: ValueResult; if (this._serverMode === ETH_CALL_MODE) { - const value = await fetchTokenDecimals(this._ethProvider, token); + const value = await fetchTokenDecimals(this._ethProvider, blockHash, token); result = { value }; } else { diff --git a/packages/erc20-watcher/src/job-runner.ts b/packages/erc20-watcher/src/job-runner.ts index aa68e8fd..4c272b63 100644 --- a/packages/erc20-watcher/src/job-runner.ts +++ b/packages/erc20-watcher/src/job-runner.ts @@ -7,7 +7,6 @@ import 'reflect-metadata'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import debug from 'debug'; -import { getDefaultProvider } from 'ethers'; import { getCache } from '@vulcanize/cache'; import { EthClient } from '@vulcanize/ipld-eth-client'; @@ -18,7 +17,8 @@ import { QUEUE_BLOCK_PROCESSING, QUEUE_EVENT_PROCESSING, JobQueueConfig, - DEFAULT_CONFIG_PATH + DEFAULT_CONFIG_PATH, + getCustomProvider } from '@vulcanize/util'; import { Indexer } from './indexer'; @@ -100,7 +100,7 @@ export const main = async (): Promise => { cache }); - const ethProvider = getDefaultProvider(rpcProviderEndpoint); + const ethProvider = getCustomProvider(rpcProviderEndpoint); const indexer = new Indexer(db, ethClient, ethProvider, mode); assert(jobQueueConfig, 'Missing job queue config'); diff --git a/packages/erc20-watcher/src/server.ts b/packages/erc20-watcher/src/server.ts index 9c9a992e..c4a6cd89 100644 --- a/packages/erc20-watcher/src/server.ts +++ b/packages/erc20-watcher/src/server.ts @@ -11,11 +11,10 @@ import { hideBin } from 'yargs/helpers'; import debug from 'debug'; import 'graphql-import-node'; import { createServer } from 'http'; -import { getDefaultProvider } from 'ethers'; import { getCache } from '@vulcanize/cache'; import { EthClient } from '@vulcanize/ipld-eth-client'; -import { DEFAULT_CONFIG_PATH, getConfig, JobQueue, KIND_ACTIVE } from '@vulcanize/util'; +import { DEFAULT_CONFIG_PATH, getConfig, getCustomProvider, JobQueue, KIND_ACTIVE } from '@vulcanize/util'; import typeDefs from './schema'; @@ -63,7 +62,7 @@ export const main = async (): Promise => { cache }); - const ethProvider = getDefaultProvider(rpcProviderEndpoint); + const ethProvider = getCustomProvider(rpcProviderEndpoint); // Note: In-memory pubsub works fine for now, as each watcher is a single process anyway. // Later: https://www.apollographql.com/docs/apollo-server/data/subscriptions/#production-pubsub-libraries diff --git a/packages/erc20-watcher/src/utils/index.ts b/packages/erc20-watcher/src/utils/index.ts index 16797629..7ca865b4 100644 --- a/packages/erc20-watcher/src/utils/index.ts +++ b/packages/erc20-watcher/src/utils/index.ts @@ -10,18 +10,18 @@ import ERC20SymbolBytesABI from '../artifacts/ERC20SymbolBytes.json'; import ERC20NameBytesABI from '../artifacts/ERC20NameBytes.json'; import { StaticTokenDefinition } from './static-token-definition'; -export const fetchTokenSymbol = async (ethProvider: BaseProvider, tokenAddress: string): Promise => { +export const fetchTokenSymbol = async (ethProvider: BaseProvider, blockHash: string, tokenAddress: string): Promise => { const contract = new Contract(tokenAddress, abi, ethProvider); const contractSymbolBytes = new Contract(tokenAddress, ERC20SymbolBytesABI, ethProvider); let symbolValue = 'unknown'; // Try types string and bytes32 for symbol. try { - const result = await contract.symbol(); + const result = await contract.symbol({ blockTag: blockHash }); symbolValue = result; } catch (error) { try { - const result = await contractSymbolBytes.symbol(); + const result = await contractSymbolBytes.symbol({ blockTag: blockHash }); // For broken pairs that have no symbol function exposed. if (!isNullEthValue(result)) { @@ -42,18 +42,18 @@ export const fetchTokenSymbol = async (ethProvider: BaseProvider, tokenAddress: return symbolValue; }; -export const fetchTokenName = async (ethProvider: BaseProvider, tokenAddress: string): Promise => { +export const fetchTokenName = async (ethProvider: BaseProvider, blockHash: string, tokenAddress: string): Promise => { const contract = new Contract(tokenAddress, abi, ethProvider); const contractNameBytes = new Contract(tokenAddress, ERC20NameBytesABI, ethProvider); let nameValue = 'unknown'; // Try types string and bytes32 for name. try { - const result = await contract.name(); + const result = await contract.name({ blockTag: blockHash }); nameValue = result; } catch (error) { try { - const result = await contractNameBytes.name(); + const result = await contractNameBytes.name({ blockTag: blockHash }); // For broken pairs that have no name function exposed. if (!isNullEthValue(result)) { @@ -74,12 +74,12 @@ export const fetchTokenName = async (ethProvider: BaseProvider, tokenAddress: st return nameValue; }; -export const fetchTokenTotalSupply = async (ethProvider: BaseProvider, tokenAddress: string): Promise => { +export const fetchTokenTotalSupply = async (ethProvider: BaseProvider, blockHash: string, tokenAddress: string): Promise => { const contract = new Contract(tokenAddress, abi, ethProvider); let totalSupplyValue = null; try { - const result = await contract.totalSupply(); + const result = await contract.totalSupply({ blockTag: blockHash }); totalSupplyValue = result.toString(); } catch (error) { totalSupplyValue = 0; @@ -88,14 +88,14 @@ export const fetchTokenTotalSupply = async (ethProvider: BaseProvider, tokenAddr return BigInt(totalSupplyValue); }; -export const fetchTokenDecimals = async (ethProvider: BaseProvider, tokenAddress: string): Promise => { +export const fetchTokenDecimals = async (ethProvider: BaseProvider, blockHash: string, tokenAddress: string): Promise => { const contract = new Contract(tokenAddress, abi, ethProvider); // Try types uint8 for decimals. let decimalValue = null; try { - const result = await contract.decimals(); + const result = await contract.decimals({ blockTag: blockHash }); decimalValue = result.toString(); } catch (error) { // Try with the static definition. diff --git a/packages/uni-info-watcher/src/fill.ts b/packages/uni-info-watcher/src/fill.ts index 2edc88cd..09cce804 100644 --- a/packages/uni-info-watcher/src/fill.ts +++ b/packages/uni-info-watcher/src/fill.ts @@ -7,11 +7,10 @@ import 'reflect-metadata'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import debug from 'debug'; -import { getDefaultProvider } from 'ethers'; import { getCache } from '@vulcanize/cache'; import { EthClient } from '@vulcanize/ipld-eth-client'; -import { getConfig, fillBlocks, JobQueue, DEFAULT_CONFIG_PATH } from '@vulcanize/util'; +import { getConfig, fillBlocks, JobQueue, DEFAULT_CONFIG_PATH, getCustomProvider } from '@vulcanize/util'; import { Client as UniClient } from '@vulcanize/uni-watcher'; import { Client as ERC20Client } from '@vulcanize/erc20-watcher'; @@ -72,7 +71,7 @@ export const main = async (): Promise => { const uniClient = new UniClient(uniWatcher); const erc20Client = new ERC20Client(tokenWatcher); - const ethProvider = getDefaultProvider(rpcProviderEndpoint); + const ethProvider = getCustomProvider(rpcProviderEndpoint); // Note: In-memory pubsub works fine for now, as each watcher is a single process anyway. // Later: https://www.apollographql.com/docs/apollo-server/data/subscriptions/#production-pubsub-libraries diff --git a/packages/uni-info-watcher/src/job-runner.ts b/packages/uni-info-watcher/src/job-runner.ts index 77149d3b..1c8d1e00 100644 --- a/packages/uni-info-watcher/src/job-runner.ts +++ b/packages/uni-info-watcher/src/job-runner.ts @@ -7,7 +7,6 @@ import 'reflect-metadata'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import debug from 'debug'; -import { getDefaultProvider } from 'ethers'; import { Client as ERC20Client } from '@vulcanize/erc20-watcher'; import { Client as UniClient } from '@vulcanize/uni-watcher'; @@ -20,7 +19,8 @@ import { QUEUE_EVENT_PROCESSING, JobRunner as BaseJobRunner, JobQueueConfig, - DEFAULT_CONFIG_PATH + DEFAULT_CONFIG_PATH, + getCustomProvider } from '@vulcanize/util'; import { Indexer } from './indexer'; @@ -122,7 +122,7 @@ export const main = async (): Promise => { }); const erc20Client = new ERC20Client(tokenWatcher); - const ethProvider = getDefaultProvider(rpcProviderEndpoint); + const ethProvider = getCustomProvider(rpcProviderEndpoint); const indexer = new Indexer(db, uniClient, erc20Client, ethClient, ethProvider, mode); diff --git a/packages/uni-info-watcher/src/server.ts b/packages/uni-info-watcher/src/server.ts index c15d38ea..f9c78808 100644 --- a/packages/uni-info-watcher/src/server.ts +++ b/packages/uni-info-watcher/src/server.ts @@ -11,12 +11,11 @@ import { hideBin } from 'yargs/helpers'; import debug from 'debug'; import 'graphql-import-node'; import { createServer } from 'http'; -import { getDefaultProvider } from 'ethers'; import { Client as ERC20Client } from '@vulcanize/erc20-watcher'; import { Client as UniClient } from '@vulcanize/uni-watcher'; import { EthClient } from '@vulcanize/ipld-eth-client'; -import { DEFAULT_CONFIG_PATH, getConfig, JobQueue } from '@vulcanize/util'; +import { DEFAULT_CONFIG_PATH, getConfig, getCustomProvider, JobQueue } from '@vulcanize/util'; import { getCache } from '@vulcanize/cache'; import typeDefs from './schema'; @@ -77,7 +76,7 @@ export const main = async (): Promise => { const uniClient = new UniClient(uniWatcher); const erc20Client = new ERC20Client(tokenWatcher); - const ethProvider = getDefaultProvider(rpcProviderEndpoint); + const ethProvider = getCustomProvider(rpcProviderEndpoint); const indexer = new Indexer(db, uniClient, erc20Client, ethClient, ethProvider, mode); assert(jobQueueConfig, 'Missing job queue config'); diff --git a/packages/uni-watcher/src/chain-pruning.test.ts b/packages/uni-watcher/src/chain-pruning.test.ts index 1400232b..95d1e8a2 100644 --- a/packages/uni-watcher/src/chain-pruning.test.ts +++ b/packages/uni-watcher/src/chain-pruning.test.ts @@ -6,9 +6,8 @@ import { expect, assert } from 'chai'; import { AssertionError } from 'assert'; import 'mocha'; import _ from 'lodash'; -import { getDefaultProvider } from 'ethers'; -import { getConfig, JobQueue, JobRunner, JOB_KIND_PRUNE } from '@vulcanize/util'; +import { getConfig, getCustomProvider, JobQueue, JobRunner, JOB_KIND_PRUNE } from '@vulcanize/util'; import { getCache } from '@vulcanize/cache'; import { EthClient } from '@vulcanize/ipld-eth-client'; import { insertNDummyBlocks, removeEntities } from '@vulcanize/util/test'; @@ -62,7 +61,7 @@ describe('chain pruning', () => { cache }); - const ethProvider = getDefaultProvider(rpcProviderEndpoint); + const ethProvider = getCustomProvider(rpcProviderEndpoint); indexer = new Indexer(db, ethClient, postgraphileClient, ethProvider); assert(indexer, 'Could not create indexer object.'); diff --git a/packages/uni-watcher/src/fill.ts b/packages/uni-watcher/src/fill.ts index 10f7e6b3..70b38fd5 100644 --- a/packages/uni-watcher/src/fill.ts +++ b/packages/uni-watcher/src/fill.ts @@ -8,11 +8,10 @@ import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import debug from 'debug'; import { PubSub } from 'apollo-server-express'; -import { getDefaultProvider } from 'ethers'; import { getCache } from '@vulcanize/cache'; import { EthClient } from '@vulcanize/ipld-eth-client'; -import { getConfig, fillBlocks, JobQueue, DEFAULT_CONFIG_PATH } from '@vulcanize/util'; +import { getConfig, fillBlocks, JobQueue, DEFAULT_CONFIG_PATH, getCustomProvider } from '@vulcanize/util'; import { Database } from './database'; import { Indexer } from './indexer'; @@ -73,7 +72,7 @@ export const main = async (): Promise => { cache }); - const ethProvider = getDefaultProvider(rpcProviderEndpoint); + const ethProvider = getCustomProvider(rpcProviderEndpoint); // Note: In-memory pubsub works fine for now, as each watcher is a single process anyway. // Later: https://www.apollographql.com/docs/apollo-server/data/subscriptions/#production-pubsub-libraries diff --git a/packages/uni-watcher/src/job-runner.ts b/packages/uni-watcher/src/job-runner.ts index 2a793ef0..9f4c2f80 100644 --- a/packages/uni-watcher/src/job-runner.ts +++ b/packages/uni-watcher/src/job-runner.ts @@ -7,7 +7,6 @@ import 'reflect-metadata'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; import debug from 'debug'; -import { getDefaultProvider } from 'ethers'; import { getCache } from '@vulcanize/cache'; import { EthClient } from '@vulcanize/ipld-eth-client'; @@ -18,7 +17,8 @@ import { QUEUE_BLOCK_PROCESSING, QUEUE_EVENT_PROCESSING, JobQueueConfig, - DEFAULT_CONFIG_PATH + DEFAULT_CONFIG_PATH, + getCustomProvider } from '@vulcanize/util'; import { Indexer } from './indexer'; @@ -122,7 +122,7 @@ export const main = async (): Promise => { cache }); - const ethProvider = getDefaultProvider(rpcProviderEndpoint); + const ethProvider = getCustomProvider(rpcProviderEndpoint); const indexer = new Indexer(db, ethClient, postgraphileClient, ethProvider); diff --git a/packages/uni-watcher/src/server.ts b/packages/uni-watcher/src/server.ts index 9b72972f..463591a2 100644 --- a/packages/uni-watcher/src/server.ts +++ b/packages/uni-watcher/src/server.ts @@ -11,11 +11,10 @@ import { hideBin } from 'yargs/helpers'; import debug from 'debug'; import 'graphql-import-node'; import { createServer } from 'http'; -import { getDefaultProvider } from 'ethers'; import { getCache } from '@vulcanize/cache'; import { EthClient } from '@vulcanize/ipld-eth-client'; -import { DEFAULT_CONFIG_PATH, getConfig, JobQueue } from '@vulcanize/util'; +import { DEFAULT_CONFIG_PATH, getConfig, getCustomProvider, JobQueue } from '@vulcanize/util'; import typeDefs from './schema'; @@ -68,7 +67,7 @@ export const main = async (): Promise => { cache }); - const ethProvider = getDefaultProvider(rpcProviderEndpoint); + const ethProvider = getCustomProvider(rpcProviderEndpoint); // Note: In-memory pubsub works fine for now, as each watcher is a single process anyway. // Later: https://www.apollographql.com/docs/apollo-server/data/subscriptions/#production-pubsub-libraries diff --git a/packages/util/src/config.ts b/packages/util/src/config.ts index 02146d7d..0dbdbbd5 100644 --- a/packages/util/src/config.ts +++ b/packages/util/src/config.ts @@ -8,12 +8,13 @@ import path from 'path'; import toml from 'toml'; import debug from 'debug'; import { ConnectionOptions } from 'typeorm'; -import { getDefaultProvider } from 'ethers'; import { BaseProvider } from '@ethersproject/providers'; import { Config as CacheConfig, getCache } from '@vulcanize/cache'; import { EthClient } from '@vulcanize/ipld-eth-client'; +import { getCustomProvider } from './index'; + const log = debug('vulcanize:config'); export interface JobQueueConfig { @@ -99,7 +100,7 @@ export const getResetConfig = async (config: Config): Promise<{ cache }); - const ethProvider = getDefaultProvider(rpcProviderEndpoint); + const ethProvider = getCustomProvider(rpcProviderEndpoint); return { dbConfig, diff --git a/packages/util/src/index.ts b/packages/util/src/index.ts index 5bf59da0..bab67ee7 100644 --- a/packages/util/src/index.ts +++ b/packages/util/src/index.ts @@ -7,6 +7,7 @@ import Decimal from 'decimal.js'; import { ValueTransformer } from 'typeorm'; import yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; +import { utils, getDefaultProvider, providers } from 'ethers'; import { DEFAULT_CONFIG_PATH } from './constants'; import { Config } from './config'; @@ -84,3 +85,32 @@ export const getResetYargs = (): yargs.Argv => { } }); }; + +export const getCustomProvider = (network?: providers.Network | string, options?: any): providers.BaseProvider => { + const provider = getDefaultProvider(network, options); + provider.formatter = new CustomFormatter(); + return provider; +}; + +class CustomFormatter extends providers.Formatter { + blockTag (blockTag: any): string { + if (blockTag == null) { return 'latest'; } + + if (blockTag === 'earliest') { return '0x0'; } + + if (blockTag === 'latest' || blockTag === 'pending') { + return blockTag; + } + + if (typeof (blockTag) === 'number' || utils.isHexString(blockTag)) { + // Return value if hex string is of block hash length. + if (utils.isHexString(blockTag) && utils.hexDataLength(blockTag) === 32) { + return blockTag; + } + + return utils.hexValue(blockTag); + } + + throw new Error('invalid blockTag'); + } +}