aboutsummaryrefslogtreecommitdiffstats
path: root/packages/subproviders
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2018-07-13 05:13:47 +0800
committerFabio Berger <me@fabioberger.com>2018-07-13 05:13:47 +0800
commit49f1a6933cc22d1e703d631d5b861b8601ca2231 (patch)
tree3af6e0f9e84f09124d93b176c2cbfdd2a8edcaff /packages/subproviders
parenta45a29432e722b71fcfc63a8545fa43ffc29b92d (diff)
downloaddexon-0x-contracts-49f1a6933cc22d1e703d631d5b861b8601ca2231.tar.gz
dexon-0x-contracts-49f1a6933cc22d1e703d631d5b861b8601ca2231.tar.zst
dexon-0x-contracts-49f1a6933cc22d1e703d631d5b861b8601ca2231.zip
Add fetchAsync util and RPCSubprovider
Diffstat (limited to 'packages/subproviders')
-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
5 files changed, 105 insertions, 13 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;
}