Added default provider support for Ethereum classic (#351).

This commit is contained in:
Richard Moore 2018-11-20 15:41:12 -05:00
parent 09208fa8fe
commit bffc557be1
No known key found for this signature in database
GPG Key ID: 525F70A6FCABC295
4 changed files with 84 additions and 29 deletions

@ -33,10 +33,9 @@ import { ContractFunction, ContractTransaction, Event, EventFilter } from './con
// Helper Functions // Helper Functions
function getDefaultProvider(network?: utils.Network | string): providers.BaseProvider { function getDefaultProvider(network?: utils.Network | string): providers.BaseProvider {
return new providers.FallbackProvider([ let n = utils.getNetwork(network || 'homestead');
new providers.InfuraProvider(network), if (!n || !n._defaultProvider) { return null; }
new providers.EtherscanProvider(network), return n._defaultProvider(providers);
]);
} }

@ -82,10 +82,14 @@ function arrayOf(check: CheckFunc): CheckFunc {
}); });
} }
function checkHash(hash: any): string { function checkHash(hash: any, requirePrefix?: boolean): string {
if (typeof(hash) === 'string' && hexDataLength(hash) === 32) { if (typeof(hash) === 'string') {
// geth-etc does add a "0x" prefix on receipt.root
if (!requirePrefix && hash.substring(0, 2) !== '0x') { hash = '0x' + hash; }
if (hexDataLength(hash) === 32) {
return hash.toLowerCase(); return hash.toLowerCase();
} }
}
errors.throwError('invalid hash', errors.INVALID_ARGUMENT, { arg: 'hash', value: hash }); errors.throwError('invalid hash', errors.INVALID_ARGUMENT, { arg: 'hash', value: hash });
return null; return null;
} }
@ -220,11 +224,15 @@ function checkTransactionResponse(transaction: any): TransactionResponse {
} }
} }
let result = check(formatTransaction, transaction); let result = check(formatTransaction, transaction);
let networkId = transaction.networkId; let networkId = transaction.networkId;
// geth-etc returns chainId
if (transaction.chainId != null && networkId == null && result.v == null) {
networkId = transaction.chainId;
}
if (isHexString(networkId)) { if (isHexString(networkId)) {
networkId = bigNumberify(networkId).toNumber(); networkId = bigNumberify(networkId).toNumber();
} }
@ -979,7 +987,7 @@ export class BaseProvider extends Provider {
getTransaction(transactionHash: string): Promise<TransactionResponse> { getTransaction(transactionHash: string): Promise<TransactionResponse> {
return this.ready.then(() => { return this.ready.then(() => {
return resolveProperties({ transactionHash: transactionHash }).then(({ transactionHash }) => { return resolveProperties({ transactionHash: transactionHash }).then(({ transactionHash }) => {
let params = { transactionHash: checkHash(transactionHash) }; let params = { transactionHash: checkHash(transactionHash, true) };
return poll(() => { return poll(() => {
return this.perform('getTransaction', params).then((result) => { return this.perform('getTransaction', params).then((result) => {
if (result == null) { if (result == null) {
@ -1016,7 +1024,7 @@ export class BaseProvider extends Provider {
getTransactionReceipt(transactionHash: string): Promise<TransactionReceipt> { getTransactionReceipt(transactionHash: string): Promise<TransactionReceipt> {
return this.ready.then(() => { return this.ready.then(() => {
return resolveProperties({ transactionHash: transactionHash }).then(({ transactionHash }) => { return resolveProperties({ transactionHash: transactionHash }).then(({ transactionHash }) => {
let params = { transactionHash: checkHash(transactionHash) }; let params = { transactionHash: checkHash(transactionHash, true) };
return poll(() => { return poll(() => {
return this.perform('getTransactionReceipt', params).then((result) => { return this.perform('getTransactionReceipt', params).then((result) => {
if (result == null) { if (result == null) {

@ -32,7 +32,8 @@ function checkNetworks(networks: Array<Network>): boolean {
// Matches! // Matches!
if (check.name === network.name && if (check.name === network.name &&
check.chainId === network.chainId && check.chainId === network.chainId &&
check.ensAddress === network.ensAddress) { return; } ((check.ensAddress === network.ensAddress) ||
(check.ensAddress == null && network.ensAddress == null))) { return; }
errors.throwError( errors.throwError(
'provider mismatch', 'provider mismatch',

@ -7,33 +7,69 @@ export type Network = {
name: string, name: string,
chainId: number, chainId: number,
ensAddress?: string, ensAddress?: string,
_defaultProvider?: (providers: any) => any
} }
export type Networkish = Network | string | number; export type Networkish = Network | string | number;
function ethDefaultProvider(network: string): (providers: any) => any {
return function(providers: any): any {
let providerList: Array<any> = [];
if (providers.InfuraProvider) {
providerList.push(new providers.InfuraProvider(network));
}
if (providers.EtherscanProvider) {
providerList.push(new providers.EtherscanProvider(network));
}
if (providerList.length === 0) { return null; }
if (providers.FallbackProvider) {
return new providers.FallbackProvider(providerList);;
}
return providerList[0];
}
}
function etcDefaultProvider(url: string, network: string): (providers: any) => any {
return function(providers: any): any {
if (providers.JsonRpcProvider) {
return new providers.JsonRpcProvider(url, network);
}
return null;
}
}
const homestead: Network = { const homestead: Network = {
chainId: 1, chainId: 1,
ensAddress: "0x314159265dd8dbb310642f98f50c066173c1259b", ensAddress: "0x314159265dd8dbb310642f98f50c066173c1259b",
name: "homestead" name: "homestead",
_defaultProvider: ethDefaultProvider('homestead')
}; };
const ropsten: Network = { const ropsten: Network = {
chainId: 3, chainId: 3,
ensAddress: "0x112234455c3a32fd11230c42e7bccd4a84e02010", ensAddress: "0x112234455c3a32fd11230c42e7bccd4a84e02010",
name: "ropsten" name: "ropsten",
_defaultProvider: ethDefaultProvider('ropsten')
}; };
const networks: { [name: string]: { chainId: number, ensAddress?: string } } = { const networks: { [name: string]: Network } = {
unspecified: { unspecified: {
chainId: 0 chainId: 0,
name: 'unspecified'
}, },
homestead: homestead, homestead: homestead,
mainnet: homestead, mainnet: homestead,
morden: { morden: {
chainId: 2 chainId: 2,
name: 'morden'
}, },
ropsten: ropsten, ropsten: ropsten,
@ -41,19 +77,27 @@ const networks: { [name: string]: { chainId: number, ensAddress?: string } } = {
rinkeby: { rinkeby: {
chainId: 4, chainId: 4,
ensAddress: "0xe7410170f87102DF0055eB195163A03B7F2Bff4A" ensAddress: "0xe7410170f87102DF0055eB195163A03B7F2Bff4A",
name: 'rinkeby',
_defaultProvider: ethDefaultProvider('rinkeby')
}, },
kovan: { kovan: {
chainId: 42 chainId: 42,
name: 'kovan',
_defaultProvider: ethDefaultProvider('kovan')
}, },
classic: { classic: {
chainId: 61 chainId: 61,
name: 'classic',
_defaultProvider: etcDefaultProvider('https://web3.gastracker.io', 'classic')
}, },
classicTestnet: { classicTestnet: {
chainId: 62 chainId: 62,
name: 'classicTestnet',
_defaultProvider: etcDefaultProvider('https://web3.gastracker.io/morden', 'classicTestnet')
} }
} }
@ -64,17 +108,18 @@ const networks: { [name: string]: { chainId: number, ensAddress?: string } } = {
* and verifies a network is a valid Network.. * and verifies a network is a valid Network..
*/ */
export function getNetwork(network: Networkish): Network { export function getNetwork(network: Networkish): Network {
// No network (null) or unspecified (chainId = 0) // No network (null)
if (!network) { return null; } if (network == null) { return null; }
if (typeof(network) === 'number') { if (typeof(network) === 'number') {
for (var name in networks) { for (let name in networks) {
let n = networks[name]; let n = networks[name];
if (n.chainId === network) { if (n.chainId === network) {
return { return {
name: name, name: n.name,
chainId: n.chainId, chainId: n.chainId,
ensAddress: n.ensAddress ensAddress: (n.ensAddress || null),
_defaultProvider: (n._defaultProvider || null)
}; };
} }
} }
@ -89,9 +134,10 @@ export function getNetwork(network: Networkish): Network {
let n = networks[network]; let n = networks[network];
if (n == null) { return null; } if (n == null) { return null; }
return { return {
name: network, name: n.name,
chainId: n.chainId, chainId: n.chainId,
ensAddress: n.ensAddress ensAddress: n.ensAddress,
_defaultProvider: (n._defaultProvider || null)
}; };
} }
@ -110,10 +156,11 @@ export function getNetwork(network: Networkish): Network {
errors.throwError('network chainId mismatch', errors.INVALID_ARGUMENT, { arg: 'network', value: network }); errors.throwError('network chainId mismatch', errors.INVALID_ARGUMENT, { arg: 'network', value: network });
} }
// Standard Network // Standard Network (allow overriding the ENS address)
return { return {
name: network.name, name: network.name,
chainId: n.chainId, chainId: n.chainId,
ensAddress: n.ensAddress ensAddress: (network.ensAddress || n.ensAddress || null),
_defaultProvider: (network._defaultProvider || n._defaultProvider || null)
}; };
} }