Fix eth_calls with blockHash (#287)

* Fix eth_calls with blockHash

* Use blockHash in erc20 eth_calls
This commit is contained in:
nikugogoi 2021-10-25 19:51:16 +05:30 committed by GitHub
parent 737d9a9b6e
commit 137f7d1a21
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 77 additions and 55 deletions

View File

@ -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<any> => {
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

View File

@ -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<any> => {
cache
});
const ethProvider = getDefaultProvider(rpcProviderEndpoint);
const ethProvider = getCustomProvider(rpcProviderEndpoint);
const indexer = new Indexer(db, ethClient, postgraphileClient, ethProvider);
assert(jobQueueConfig, 'Missing job queue config');

View File

@ -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<any> => {
cache
});
const ethProvider = getDefaultProvider(rpcProviderEndpoint);
const ethProvider = getCustomProvider(rpcProviderEndpoint);
const indexer = new Indexer(db, ethClient, postgraphileClient, ethProvider);

View File

@ -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<any> => {
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

View File

@ -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 {

View File

@ -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<any> => {
cache
});
const ethProvider = getDefaultProvider(rpcProviderEndpoint);
const ethProvider = getCustomProvider(rpcProviderEndpoint);
const indexer = new Indexer(db, ethClient, ethProvider, mode);
assert(jobQueueConfig, 'Missing job queue config');

View File

@ -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<any> => {
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

View File

@ -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<string> => {
export const fetchTokenSymbol = async (ethProvider: BaseProvider, blockHash: string, tokenAddress: string): Promise<string> => {
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<string> => {
export const fetchTokenName = async (ethProvider: BaseProvider, blockHash: string, tokenAddress: string): Promise<string> => {
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<bigint> => {
export const fetchTokenTotalSupply = async (ethProvider: BaseProvider, blockHash: string, tokenAddress: string): Promise<bigint> => {
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<bigint> => {
export const fetchTokenDecimals = async (ethProvider: BaseProvider, blockHash: string, tokenAddress: string): Promise<bigint> => {
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.

View File

@ -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<any> => {
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

View File

@ -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<any> => {
});
const erc20Client = new ERC20Client(tokenWatcher);
const ethProvider = getDefaultProvider(rpcProviderEndpoint);
const ethProvider = getCustomProvider(rpcProviderEndpoint);
const indexer = new Indexer(db, uniClient, erc20Client, ethClient, ethProvider, mode);

View File

@ -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<any> => {
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');

View File

@ -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.');

View File

@ -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<any> => {
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

View File

@ -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<any> => {
cache
});
const ethProvider = getDefaultProvider(rpcProviderEndpoint);
const ethProvider = getCustomProvider(rpcProviderEndpoint);
const indexer = new Indexer(db, ethClient, postgraphileClient, ethProvider);

View File

@ -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<any> => {
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

View File

@ -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,

View File

@ -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(<number | string>blockTag);
}
throw new Error('invalid blockTag');
}
}