Skip to content

Commit

Permalink
Add eth-query types
Browse files Browse the repository at this point in the history
  • Loading branch information
Gudahtt committed Apr 25, 2023
1 parent bd29cbc commit c8fa5bc
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 56 deletions.
13 changes: 10 additions & 3 deletions packages/assets-controllers/src/AccountTrackerController.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import EthQuery from 'eth-query';
import type { Provider } from 'eth-query';
import { Mutex } from 'async-mutex';
import {
BaseConfig,
Expand Down Expand Up @@ -30,7 +31,7 @@ export interface AccountInformation {
*/
export interface AccountTrackerConfig extends BaseConfig {
interval: number;
provider?: any;
provider?: Provider;
}

/**
Expand All @@ -50,7 +51,7 @@ export class AccountTrackerController extends BaseController<
AccountTrackerConfig,
AccountTrackerState
> {
private ethQuery: any;
private ethQuery?: EthQuery;

private mutex = new Mutex();

Expand Down Expand Up @@ -125,7 +126,7 @@ export class AccountTrackerController extends BaseController<
*
* @param provider - Provider used to create a new underlying EthQuery instance.
*/
set provider(provider: any) {
set provider(provider: Provider) {
this.ethQuery = new EthQuery(provider);
}

Expand Down Expand Up @@ -157,6 +158,9 @@ export class AccountTrackerController extends BaseController<
const accounts = { ...this.state.accounts };
for (const address in accounts) {
await safelyExecuteWithTimeout(async () => {
if (!this.ethQuery) {
throw new Error('Provider not set');
}
const balance = await query(this.ethQuery, 'getBalance', [address]);
accounts[address] = { balance: BNToHex(balance) };
});
Expand All @@ -176,6 +180,9 @@ export class AccountTrackerController extends BaseController<
return await Promise.all(
addresses.map((address): Promise<[string, string] | undefined> => {
return safelyExecuteWithTimeout(async () => {
if (!this.ethQuery) {
throw new Error('Provider not set');
}
const balance = await query(this.ethQuery, 'getBalance', [address]);
return [address, balance];
});
Expand Down
1 change: 1 addition & 0 deletions packages/controller-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"@metamask/utils": "^5.0.1",
"@spruceid/siwe-parser": "1.1.3",
"eth-ens-namehash": "^2.0.8",
"eth-query": "^2.1.2",
"eth-rpc-errors": "^4.0.2",
"ethereumjs-util": "^7.0.10",
"ethjs-unit": "^0.1.6",
Expand Down
20 changes: 11 additions & 9 deletions packages/controller-utils/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import {
toChecksumAddress,
stripHexPrefix,
} from 'ethereumjs-util';
import type EthQuery from 'eth-query';
import { fromWei, toWei } from 'ethjs-unit';
import ensNamehash from 'eth-ens-namehash';
import deepEqual from 'fast-deep-equal';
import type { Hex } from '@metamask/utils';
import { isStrictHexString } from '@metamask/utils';
import { hasProperty, isStrictHexString } from '@metamask/utils';
import type { Json } from './types';
import { MAX_SAFE_CHAIN_ID } from './constants';

Expand Down Expand Up @@ -426,20 +427,26 @@ export function normalizeEnsName(ensName: string): string | null {
* @returns Promise resolving the request.
*/
export function query(
ethQuery: any,
ethQuery: EthQuery,
method: string,
args: any[] = [],
): Promise<any> {
return new Promise((resolve, reject) => {
const cb = (error: Error, result: any) => {
const cb = (error: unknown, result: any) => {
if (error) {
reject(error);
return;
}
resolve(result);
};

if (typeof ethQuery[method] === 'function') {
if (
hasProperty(ethQuery, method) &&
typeof ethQuery[method] === 'function'
) {
// All of the generated method types have this signature, but our types don't support these yet
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
ethQuery[method](...args, cb);
} else {
ethQuery.sendAsync({ method, params: args }, cb);
Expand Down Expand Up @@ -475,11 +482,6 @@ export function isPlainObject(value: unknown): value is PlainObject {
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
}

export const hasProperty = (
object: PlainObject,
key: string | number | symbol,
) => Reflect.hasOwnProperty.call(object, key);

/**
* Like {@link Array}, but always non-empty.
*
Expand Down
2 changes: 1 addition & 1 deletion packages/gas-fee-controller/src/GasFeeController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ export class GasFeeController extends BaseControllerV2<

private currentChainId;

private ethQuery: any;
private ethQuery: EthQuery;

private clientId?: string;

Expand Down
58 changes: 42 additions & 16 deletions packages/network-controller/src/NetworkController.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type EventEmitter from 'events';
import EthQuery from 'eth-query';
import type { Provider as EthQueryProvider } from 'eth-query';
import Subprovider from 'web3-provider-engine/subproviders/provider';
import createInfuraProvider from 'eth-json-rpc-infura/src/createProvider';
import createMetamaskProvider from 'web3-provider-engine/zero';
Expand All @@ -20,7 +22,7 @@ import {
isNetworkType,
BUILT_IN_NETWORKS,
} from '@metamask/controller-utils';
import { assertIsStrictHexString } from '@metamask/utils';
import { assertIsStrictHexString, hasProperty } from '@metamask/utils';

import { NetworkStatus } from './constants';

Expand Down Expand Up @@ -123,16 +125,14 @@ const LOCALHOST_RPC_URL = 'http://localhost:8545';

const name = 'NetworkController';

export type EthQuery = any;

type Provider = any;

export type ProviderProxy = SwappableProxy<Provider>;

type BlockTracker = any;

export type BlockTrackerProxy = SwappableProxy<BlockTracker>;

export type Provider = EventEmitter & EthQueryProvider & { stop: () => void };

export type ProviderProxy = SwappableProxy<Provider>;

export type NetworkControllerStateChangeEvent = {
type: `NetworkController:stateChange`;
payload: [NetworkState, Patch[]];
Expand Down Expand Up @@ -211,7 +211,7 @@ export class NetworkController extends BaseControllerV2<
NetworkState,
NetworkControllerMessenger
> {
#ethQuery: EthQuery;
#ethQuery?: EthQuery;

#infuraProjectId: string | undefined;

Expand Down Expand Up @@ -272,6 +272,9 @@ export class NetworkController extends BaseControllerV2<
this.messagingSystem.registerActionHandler(
`${this.name}:getEthQuery`,
() => {
if (!this.#ethQuery) {
throw new Error('Provider has not been initialized');
}
return this.#ethQuery;
},
);
Expand Down Expand Up @@ -347,7 +350,11 @@ export class NetworkController extends BaseControllerV2<
pollingInterval: 12000,
},
};
this.#updateProvider(createMetamaskProvider(config));

// Cast needed because the `web3-provider-engine` type for `sendAsync`
// incorrectly suggests that an array is accepted as the first parameter
// of `sendAsync`.
this.#updateProvider(createMetamaskProvider(config) as Provider);
}

#setupStandardProvider(
Expand All @@ -363,11 +370,18 @@ export class NetworkController extends BaseControllerV2<
rpcUrl: rpcTarget,
ticker,
};
this.#updateProvider(createMetamaskProvider(config));

// Cast needed because the `web3-provider-engine` type for `sendAsync`
// incorrectly suggests that an array is accepted as the first parameter
// of `sendAsync`.
this.#updateProvider(createMetamaskProvider(config) as Provider);
}

#updateProvider(provider: Provider) {
this.#safelyStopProvider(this.#provider);
if (!hasProperty(provider, '_blockTracker')) {
throw new Error('Provider is missing block tracker');
}
this.#setProviderAndBlockTracker({
provider,
blockTracker: provider._blockTracker,
Expand All @@ -377,7 +391,13 @@ export class NetworkController extends BaseControllerV2<

#safelyStopProvider(provider: Provider | undefined) {
setTimeout(() => {
provider?.stop();
if (
provider &&
hasProperty(provider, 'stop') &&
typeof provider.stop === 'function'
) {
provider?.stop();
}
}, 500);
}

Expand All @@ -403,13 +423,16 @@ export class NetworkController extends BaseControllerV2<

async #getNetworkId(): Promise<NetworkId> {
const possibleNetworkId = await new Promise<string>((resolve, reject) => {
if (!this.#ethQuery) {
throw new Error('Provider has not been initialized');
}
this.#ethQuery.sendAsync(
{ method: 'net_version' },
(error: Error, result: string) => {
(error: unknown, result?: unknown) => {
if (error) {
reject(error);
} else {
resolve(result);
resolve(result as string);
}
},
);
Expand Down Expand Up @@ -532,15 +555,18 @@ export class NetworkController extends BaseControllerV2<
await this.#refreshNetwork();
}

#getLatestBlock(): Promise<Block> {
async #getLatestBlock(): Promise<Block> {
return new Promise((resolve, reject) => {
if (!this.#ethQuery) {
throw new Error('Provider has not been initialized');
}
this.#ethQuery.sendAsync(
{ method: 'eth_getBlockByNumber', params: ['latest', false] },
(error: Error, block: Block) => {
(error: unknown, block?: unknown) => {
if (error) {
reject(error);
} else {
resolve(block);
resolve(block as Block);
}
},
);
Expand Down
Loading

0 comments on commit c8fa5bc

Please sign in to comment.