aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/subproviders/package.json1
-rw-r--r--packages/subproviders/src/globals.d.ts2
-rw-r--r--packages/subproviders/src/index.ts1
-rw-r--r--packages/subproviders/src/subproviders/rpc_subprovider.ts88
-rw-r--r--packages/subproviders/src/subproviders/subprovider.ts26
-rw-r--r--packages/types/src/index.ts12
-rw-r--r--packages/utils/package.json4
-rw-r--r--packages/utils/src/fetchAsync.ts29
-rw-r--r--packages/utils/src/index.ts2
-rw-r--r--yarn.lock8
10 files changed, 154 insertions, 19 deletions
diff --git a/packages/subproviders/package.json b/packages/subproviders/package.json
index bdc846e6b..796d87cf4 100644
--- a/packages/subproviders/package.json
+++ b/packages/subproviders/package.json
@@ -55,6 +55,7 @@
"ethereumjs-util": "^5.1.1",
"ganache-core": "0xProject/ganache-core",
"hdkey": "^0.7.1",
+ "json-rpc-error": "2.0.0",
"lodash": "^4.17.4",
"semaphore-async-await": "^1.5.1",
"web3-provider-engine": "14.0.6"
diff --git a/packages/subproviders/src/globals.d.ts b/packages/subproviders/src/globals.d.ts
index 94e63a32d..6af4c7980 100644
--- a/packages/subproviders/src/globals.d.ts
+++ b/packages/subproviders/src/globals.d.ts
@@ -4,3 +4,5 @@ declare module '*.json' {
export default json;
/* tslint:enable */
}
+
+declare module 'json-rpc-error';
diff --git a/packages/subproviders/src/index.ts b/packages/subproviders/src/index.ts
index 71d643f14..9a5597a06 100644
--- a/packages/subproviders/src/index.ts
+++ b/packages/subproviders/src/index.ts
@@ -10,6 +10,7 @@ export { FakeGasEstimateSubprovider } from './subproviders/fake_gas_estimate_sub
export { SignerSubprovider } from './subproviders/signer';
export { RedundantSubprovider } from './subproviders/redundant_subprovider';
export { LedgerSubprovider } from './subproviders/ledger';
+export { RPCSubprovider } from './subproviders/rpc_subprovider';
export { GanacheSubprovider } from './subproviders/ganache';
export { Subprovider } from './subproviders/subprovider';
export { NonceTrackerSubprovider } from './subproviders/nonce_tracker';
diff --git a/packages/subproviders/src/subproviders/rpc_subprovider.ts b/packages/subproviders/src/subproviders/rpc_subprovider.ts
new file mode 100644
index 000000000..87c522271
--- /dev/null
+++ b/packages/subproviders/src/subproviders/rpc_subprovider.ts
@@ -0,0 +1,88 @@
+import { assert } from '@0xproject/assert';
+import { StatusCodes } from '@0xproject/types';
+import { fetchAsync } from '@0xproject/utils';
+import { JSONRPCRequestPayload } from 'ethereum-types';
+import JsonRpcError = require('json-rpc-error');
+
+import { Callback, ErrorCallback } from '../types';
+
+import { Subprovider } from './subprovider';
+
+/**
+ * This class implements the [web3-provider-engine](https://github.com/MetaMask/provider-engine) subprovider interface.
+ * It forwards on JSON RPC requests to the supplied `rpcUrl` endpoint
+ */
+export class RPCSubprovider extends Subprovider {
+ private _rpcUrl: string;
+ constructor(rpcUrl: string) {
+ super();
+ assert.isString('rpcUrl', rpcUrl);
+ this._rpcUrl = rpcUrl;
+ }
+ /**
+ * This method conforms to the web3-provider-engine interface.
+ * It is called internally by the ProviderEngine when it is this subproviders
+ * turn to handle a JSON RPC request.
+ * @param payload JSON RPC payload
+ * @param next Callback to call if this subprovider decides not to handle the request
+ * @param end Callback to call if subprovider handled the request and wants to pass back the request.
+ */
+ // tslint:disable-next-line:prefer-function-over-method async-suffix
+ public async handleRequest(payload: JSONRPCRequestPayload, next: Callback, end: ErrorCallback): Promise<void> {
+ const finalPayload = Subprovider.createFinalPayload(payload);
+ const headers = new Headers({
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ });
+ const timeoutMs = 1000;
+
+ let response;
+ try {
+ response = await fetchAsync(
+ this._rpcUrl,
+ {
+ method: 'POST',
+ headers,
+ body: JSON.stringify(finalPayload),
+ },
+ timeoutMs,
+ );
+ } catch (err) {
+ end(new JsonRpcError.InternalError(err));
+ return;
+ }
+
+ const text = await response.text();
+ if (!response.ok) {
+ const statusCode = response.status;
+ switch (statusCode) {
+ case StatusCodes.MethodNotAllowed:
+ end(new JsonRpcError.MethodNotFound());
+ return;
+ case StatusCodes.GatewayTimeout:
+ const errMsg =
+ 'Gateway timeout. The request took too long to process. This can happen when querying logs over too wide a block range.';
+ const err = new Error(errMsg);
+ end(new JsonRpcError.InternalError(err));
+ return;
+ default:
+ end(new JsonRpcError.InternalError(text));
+ return;
+ }
+ }
+
+ let data;
+ try {
+ data = JSON.parse(text);
+ } catch (err) {
+ end(new JsonRpcError.InternalError(err));
+ return;
+ }
+
+ if (data.error) {
+ end(data.error);
+ return;
+ }
+ end(null, data.result);
+ }
+}
diff --git a/packages/subproviders/src/subproviders/subprovider.ts b/packages/subproviders/src/subproviders/subprovider.ts
index ff8378c4e..6f4a8f99e 100644
--- a/packages/subproviders/src/subproviders/subprovider.ts
+++ b/packages/subproviders/src/subproviders/subprovider.ts
@@ -9,18 +9,7 @@ import { Callback, ErrorCallback, JSONRPCRequestPayloadWithMethod } from '../typ
export abstract class Subprovider {
// tslint:disable-next-line:underscore-private-and-protected
private engine!: Provider;
- // Ported from: https://github.com/MetaMask/provider-engine/blob/master/util/random-id.js
- private static _getRandomId(): number {
- const extraDigits = 3;
- const baseTen = 10;
- // 13 time digits
- const datePart = new Date().getTime() * Math.pow(baseTen, extraDigits);
- // 3 random digits
- const extraPart = Math.floor(Math.random() * Math.pow(baseTen, extraDigits));
- // 16 digits
- return datePart + extraPart;
- }
- private static _createFinalPayload(
+ public static createFinalPayload(
payload: Partial<JSONRPCRequestPayloadWithMethod>,
): Partial<JSONRPCRequestPayloadWithMethod> {
const finalPayload = {
@@ -32,6 +21,17 @@ export abstract class Subprovider {
};
return finalPayload;
}
+ // Ported from: https://github.com/MetaMask/provider-engine/blob/master/util/random-id.js
+ private static _getRandomId(): number {
+ const extraDigits = 3;
+ const baseTen = 10;
+ // 13 time digits
+ const datePart = new Date().getTime() * Math.pow(baseTen, extraDigits);
+ // 3 random digits
+ const extraPart = Math.floor(Math.random() * Math.pow(baseTen, extraDigits));
+ // 16 digits
+ return datePart + extraPart;
+ }
// tslint:disable-next-line:async-suffix
public abstract async handleRequest(
payload: JSONRPCRequestPayload,
@@ -47,7 +47,7 @@ export abstract class Subprovider {
* @returns JSON RPC response payload
*/
public async emitPayloadAsync(payload: Partial<JSONRPCRequestPayloadWithMethod>): Promise<JSONRPCResponsePayload> {
- const finalPayload = Subprovider._createFinalPayload(payload);
+ const finalPayload = Subprovider.createFinalPayload(payload);
const response = await promisify<JSONRPCResponsePayload>(this.engine.sendAsync, this.engine)(finalPayload);
return response;
}
diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts
index 03fa2fe8a..9b1731b9d 100644
--- a/packages/types/src/index.ts
+++ b/packages/types/src/index.ts
@@ -221,3 +221,15 @@ export enum RevertReason {
ValueGreaterThanZero = 'VALUE_GREATER_THAN_ZERO',
InvalidMsgValue = 'INVALID_MSG_VALUE',
}
+
+export enum StatusCodes {
+ Success = 200,
+ NotFound = 404,
+ InternalError = 500,
+ MethodNotAllowed = 405,
+ GatewayTimeout = 504,
+}
+
+export interface FetchRequest extends RequestInit {
+ timeout?: number;
+}
diff --git a/packages/utils/package.json b/packages/utils/package.json
index 9168a3538..cb0989836 100644
--- a/packages/utils/package.json
+++ b/packages/utils/package.json
@@ -35,14 +35,14 @@
"typescript": "2.7.1"
},
"dependencies": {
- "ethereum-types": "^0.0.2",
+ "@0xproject/types": "^1.0.0",
"@0xproject/typescript-typings": "^0.4.2",
"@types/node": "^8.0.53",
- "ethereumjs-util": "^5.1.1",
"bignumber.js": "~4.1.0",
"ethereum-types": "^0.0.2",
"ethereumjs-util": "^5.1.1",
"ethers": "3.0.22",
+ "isomorphic-fetch": "^2.2.1",
"js-sha3": "^0.7.0",
"lodash": "^4.17.4"
},
diff --git a/packages/utils/src/fetchAsync.ts b/packages/utils/src/fetchAsync.ts
new file mode 100644
index 000000000..7cb2c1759
--- /dev/null
+++ b/packages/utils/src/fetchAsync.ts
@@ -0,0 +1,29 @@
+import { FetchRequest } from '@0xproject/types';
+import 'isomorphic-fetch';
+
+export const fetchAsync = async (
+ endpoint: string,
+ options: FetchRequest,
+ timeoutMs: number = 20000,
+): Promise<Response> => {
+ let finalOptions;
+ if ((process as any).browser === true) {
+ const controller = new AbortController();
+ const signal = controller.signal;
+ setTimeout(() => {
+ controller.abort();
+ }, timeoutMs);
+ finalOptions = {
+ signal,
+ ...options,
+ };
+ } else {
+ finalOptions = {
+ timeout: timeoutMs,
+ ...options,
+ };
+ }
+
+ const response = await fetch(endpoint, finalOptions);
+ return response;
+};
diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts
index fd102cecb..48fd6152e 100644
--- a/packages/utils/src/index.ts
+++ b/packages/utils/src/index.ts
@@ -8,3 +8,5 @@ export { logUtils } from './log_utils';
export { abiUtils } from './abi_utils';
export { NULL_BYTES } from './constants';
export { errorUtils } from './error_utils';
+export { fetchAsync } from './fetchAsync';
+export { FetchRequest } from '@0xproject/types';
diff --git a/yarn.lock b/yarn.lock
index a8a897511..f6b6a32e0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4481,9 +4481,9 @@ ethereumjs-wallet@~0.6.0:
utf8 "^2.1.1"
uuid "^2.0.1"
-ethers@3.0.22:
- version "3.0.22"
- resolved "https://registry.yarnpkg.com/ethers/-/ethers-3.0.22.tgz#7fab1ea16521705837aa43c15831877b2716b436"
+ethers@0xproject/ethers.js#eip-838-reasons, ethers@3.0.22:
+ version "3.0.18"
+ resolved "https://codeload.github.com/0xproject/ethers.js/tar.gz/b91342bd200d142af0165d6befddf783c8ae8447"
dependencies:
aes-js "3.0.0"
bn.js "^4.4.0"
@@ -6899,7 +6899,7 @@ json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0:
json-rpc-error "^2.0.0"
promise-to-callback "^1.0.0"
-json-rpc-error@^2.0.0:
+json-rpc-error@2.0.0, json-rpc-error@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02"
dependencies: