mirror of https://github.com/embarklabs/embark.git
Attempting to fix tests
Tests are not working currently, however given the current changes, the non-test functionality of the proxy is still working correctly.
This commit is contained in:
parent
b5aa508992
commit
9239c91492
|
@ -52,6 +52,7 @@ export interface Config {
|
||||||
rpcCorsDomain: string;
|
rpcCorsDomain: string;
|
||||||
wsRPC: boolean;
|
wsRPC: boolean;
|
||||||
isDev: boolean;
|
isDev: boolean;
|
||||||
|
client: string;
|
||||||
};
|
};
|
||||||
webServerConfig: {
|
webServerConfig: {
|
||||||
certOptions: {
|
certOptions: {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class Ganache {
|
class Ganache {
|
||||||
constructor(embark) {
|
constructor(embark) {
|
||||||
embark.events.request('proxy:vm:register', () => {
|
embark.events.request('blockchain:vm:register', () => {
|
||||||
const ganache = require('ganache-cli');
|
const ganache = require('ganache-cli');
|
||||||
return ganache.provider();
|
return ganache.provider();
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,7 +12,7 @@ export default class EthSubscribe extends RpcModifier {
|
||||||
|
|
||||||
private async ethSubscribeRequest(params: any, callback: Callback<any>) {
|
private async ethSubscribeRequest(params: any, callback: Callback<any>) {
|
||||||
// check for eth_subscribe and websockets
|
// check for eth_subscribe and websockets
|
||||||
if (params.isWs && params.request.method.includes("eth_subscribe")) {
|
if (params.isWs && params.request.method === "eth_subscribe") {
|
||||||
// indicate that we do not want this call to go to the node
|
// indicate that we do not want this call to go to the node
|
||||||
params.sendToNode = false;
|
params.sendToNode = false;
|
||||||
return callback(null, params);
|
return callback(null, params);
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
import { Callback, Embark, Events } /* supplied by @types/embark in packages/embark-typings */ from "embark";
|
import { Callback, Embark, Events } /* supplied by @types/embark in packages/embark-typings */ from "embark";
|
||||||
import Web3RequestManager from "web3-core-requestmanager";
|
|
||||||
import { __ } from "embark-i18n";
|
import { __ } from "embark-i18n";
|
||||||
import Web3 from "web3";
|
|
||||||
import RpcModifier from "./rpcModifier";
|
import RpcModifier from "./rpcModifier";
|
||||||
|
|
||||||
export default class EthUnsubscribe extends RpcModifier {
|
export default class EthUnsubscribe extends RpcModifier {
|
||||||
|
|
||||||
private nodeSubscriptions: object = {};
|
|
||||||
constructor(embark: Embark, rpcModifierEvents: Events) {
|
constructor(embark: Embark, rpcModifierEvents: Events) {
|
||||||
super(embark, rpcModifierEvents);
|
super(embark, rpcModifierEvents);
|
||||||
|
|
||||||
|
@ -16,7 +13,7 @@ export default class EthUnsubscribe extends RpcModifier {
|
||||||
|
|
||||||
private async ethUnsubscribeRequest(params: any, callback: Callback<any>) {
|
private async ethUnsubscribeRequest(params: any, callback: Callback<any>) {
|
||||||
// check for eth_subscribe and websockets
|
// check for eth_subscribe and websockets
|
||||||
if (params.isWs && params.request.method.includes("eth_unsubscribe")) {
|
if (params.isWs && params.request.method === "eth_unsubscribe") {
|
||||||
// indicate that we do not want this call to go to the node
|
// indicate that we do not want this call to go to the node
|
||||||
params.sendToNode = false;
|
params.sendToNode = false;
|
||||||
return callback(null, params);
|
return callback(null, params);
|
||||||
|
|
|
@ -9,30 +9,42 @@ class BlockchainClient {
|
||||||
|
|
||||||
this.blockchainClients = {};
|
this.blockchainClients = {};
|
||||||
this.client = null;
|
this.client = null;
|
||||||
|
this.vms = [];
|
||||||
this.events.setCommandHandler("blockchain:client:register", (clientName, blockchainClient) => {
|
this.events.setCommandHandler("blockchain:client:register", (clientName, blockchainClient) => {
|
||||||
this.blockchainClients[clientName] = blockchainClient;
|
this.blockchainClients[clientName] = blockchainClient;
|
||||||
this.client = blockchainClient;
|
this.client = blockchainClient;
|
||||||
});
|
});
|
||||||
|
this.events.setCommandHandler("blockchain:vm:register", (handler) => {
|
||||||
|
this.vms.push(handler);
|
||||||
|
});
|
||||||
|
|
||||||
// TODO: unclear currently if this belongs here so it's a bit hardcoded for now
|
// TODO: unclear currently if this belongs here so it's a bit hardcoded for now
|
||||||
this.events.setCommandHandler("blockchain:client:provider", (clientName, cb) => {
|
this.events.setCommandHandler("blockchain:client:nodeProvider", async (clientName, endpoint, cb) => {
|
||||||
this.events.request("proxy:endpoint:get", (err, endpoint) => {
|
if (!cb) {
|
||||||
if (err) {
|
cb = endpoint;
|
||||||
return cb(err);
|
endpoint = null;
|
||||||
}
|
}
|
||||||
if (endpoint.startsWith('ws')) {
|
if (clientName === constants.blockchain.vm) {
|
||||||
return cb(null, new Web3.providers.WebsocketProvider(endpoint, {
|
return cb(null, this.vms[this.vms.length - 1]());
|
||||||
headers: {Origin: constants.embarkResourceOrigin},
|
}
|
||||||
// TODO remove this when Geth fixes this: https://github.com/ethereum/go-ethereum/issues/16846
|
let provider;
|
||||||
// Edit: This has been fixed in Geth 1.9, but we don't support 1.9 yet and still support 1.8
|
try {
|
||||||
clientConfig: {
|
provider = await this._getProvider(clientName, endpoint);
|
||||||
fragmentationThreshold: 81920
|
}
|
||||||
}
|
catch (err) {
|
||||||
}));
|
return cb(`Error getting provider: ${err.message || err}`);
|
||||||
}
|
}
|
||||||
const web3 = new Web3(endpoint);
|
cb(null, provider);
|
||||||
cb(null, web3.currentProvider);
|
});
|
||||||
});
|
this.events.setCommandHandler("blockchain:client:provider", async (clientName, cb) => {
|
||||||
|
let provider;
|
||||||
|
try {
|
||||||
|
provider = await this._getProvider(clientName);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
return cb(`Error getting provider: ${err.message || err}`);
|
||||||
|
}
|
||||||
|
cb(null, provider);
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: maybe not the ideal event to listen to?
|
// TODO: maybe not the ideal event to listen to?
|
||||||
|
@ -46,7 +58,28 @@ class BlockchainClient {
|
||||||
// set default account
|
// set default account
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
async _getProvider(clientName, endpoint) {
|
||||||
|
// Passing in an endpoint allows us to customise which URL the provider connects to.
|
||||||
|
// If no endpoint is providing, the provider will connect to the proxy.
|
||||||
|
// Explicity setting an endpoint is useful for cases where we want to connect directly
|
||||||
|
// to the node (ie in the proxy).
|
||||||
|
if (!endpoint) {
|
||||||
|
// will return the proxy URL
|
||||||
|
endpoint = await this.events.request2("proxy:endpoint:get");
|
||||||
|
}
|
||||||
|
if (endpoint.startsWith('ws')) {
|
||||||
|
return new Web3.providers.WebsocketProvider(endpoint, {
|
||||||
|
headers: { Origin: constants.embarkResourceOrigin },
|
||||||
|
// TODO remove this when Geth fixes this: https://github.com/ethereum/go-ethereum/issues/16846
|
||||||
|
// Edit: This has been fixed in Geth 1.9, but we don't support 1.9 yet and still support 1.8
|
||||||
|
clientConfig: {
|
||||||
|
fragmentationThreshold: 81920
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const web3 = new Web3(endpoint);
|
||||||
|
return web3.currentProvider;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = BlockchainClient;
|
module.exports = BlockchainClient;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {Embark, Events } /* supplied by @types/embark in packages/embark-typings */ from "embark";
|
import { Embark, Events } /* supplied by @types/embark in packages/embark-typings */ from "embark";
|
||||||
import {__} from "embark-i18n";
|
import { __ } from "embark-i18n";
|
||||||
import { buildUrl, findNextPort } from "embark-utils";
|
import { buildUrl, findNextPort } from "embark-utils";
|
||||||
import { Logger } from 'embark-logger';
|
import { Logger } from 'embark-logger';
|
||||||
import { Proxy } from "./proxy";
|
import { Proxy } from "./proxy";
|
||||||
|
@ -18,6 +18,8 @@ export default class ProxyManager {
|
||||||
private ready = false;
|
private ready = false;
|
||||||
private isWs = false;
|
private isWs = false;
|
||||||
private vms: any[];
|
private vms: any[];
|
||||||
|
private _endpoint: string = "";
|
||||||
|
private portsSetup: boolean = false;
|
||||||
|
|
||||||
constructor(private embark: Embark, options: any) {
|
constructor(private embark: Embark, options: any) {
|
||||||
this.logger = embark.logger;
|
this.logger = embark.logger;
|
||||||
|
@ -50,19 +52,28 @@ export default class ProxyManager {
|
||||||
|
|
||||||
this.events.setCommandHandler("proxy:endpoint:get", async (cb) => {
|
this.events.setCommandHandler("proxy:endpoint:get", async (cb) => {
|
||||||
await this.onReady();
|
await this.onReady();
|
||||||
if (!this.embark.config.blockchainConfig.proxy) {
|
cb(null, (await this.endpoint));
|
||||||
return cb(null, this.embark.config.blockchainConfig.endpoint);
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private get endpoint() {
|
||||||
|
return (async () => {
|
||||||
|
if (this._endpoint) {
|
||||||
|
return this._endpoint;
|
||||||
}
|
}
|
||||||
|
if (!this.embark.config.blockchainConfig.proxy) {
|
||||||
|
this._endpoint = this.embark.config.blockchainConfig.endpoint;
|
||||||
|
return this._endpoint;
|
||||||
|
}
|
||||||
|
await this.setupPorts();
|
||||||
// TODO Check if the proxy can support HTTPS, though it probably doesn't matter since it's local
|
// TODO Check if the proxy can support HTTPS, though it probably doesn't matter since it's local
|
||||||
if (this.isWs) {
|
if (this.isWs) {
|
||||||
return cb(null, buildUrl("ws", this.host, this.wsPort, "ws"));
|
this._endpoint = buildUrl("ws", this.host, this.wsPort, "ws");
|
||||||
|
return this._endpoint;
|
||||||
}
|
}
|
||||||
cb(null, buildUrl("http", this.host, this.rpcPort, "rpc"));
|
this._endpoint = buildUrl("http", this.host, this.rpcPort, "rpc");
|
||||||
});
|
return this._endpoint;
|
||||||
|
})();
|
||||||
this.events.setCommandHandler("proxy:vm:register", (handler: any) => {
|
|
||||||
this.vms.push(handler);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public onReady() {
|
public onReady() {
|
||||||
|
@ -76,50 +87,65 @@ export default class ProxyManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async setupPorts() {
|
||||||
|
if (this.portsSetup) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const port = await findNextPort(this.embark.config.blockchainConfig.rpcPort + constants.blockchain.servicePortOnProxy);
|
||||||
|
this.portsSetup = true;
|
||||||
|
|
||||||
|
this.rpcPort = port;
|
||||||
|
this.wsPort = port + 1;
|
||||||
|
this.isWs = this.embark.config.blockchainConfig.client === constants.blockchain.vm || (/wss?/).test(this.embark.config.blockchainConfig.endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
private async setupProxy(clientName: string) {
|
private async setupProxy(clientName: string) {
|
||||||
|
await this.setupPorts();
|
||||||
if (!this.embark.config.blockchainConfig.proxy) {
|
if (!this.embark.config.blockchainConfig.proxy) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.httpProxy || this.wsProxy) {
|
if (this.httpProxy || this.wsProxy) {
|
||||||
throw new Error("Proxy is already started");
|
throw new Error("Proxy is already started");
|
||||||
}
|
}
|
||||||
const port = await findNextPort(this.embark.config.blockchainConfig.rpcPort + constants.blockchain.servicePortOnProxy);
|
|
||||||
|
|
||||||
this.rpcPort = port;
|
const endpoint = this.embark.config.blockchainConfig.endpoint;
|
||||||
this.wsPort = port + 1;
|
let isVm = false;
|
||||||
this.isWs = clientName === constants.blockchain.vm || (/wss?/).test(this.embark.config.blockchainConfig.endpoint);
|
|
||||||
|
// using simulator, ie tests
|
||||||
|
if (clientName === constants.blockchain.vm) {
|
||||||
|
this.isWs = true;
|
||||||
|
isVm = true;
|
||||||
|
}
|
||||||
|
|
||||||
// HTTP
|
// HTTP
|
||||||
if (clientName !== constants.blockchain.vm) {
|
if (clientName !== constants.blockchain.vm) {
|
||||||
this.httpProxy = await new Proxy({
|
this.httpProxy = await new Proxy({
|
||||||
endpoint: this.embark.config.blockchainConfig.endpoint,
|
endpoint,
|
||||||
events: this.events,
|
events: this.events,
|
||||||
isWs: false,
|
isWs: false,
|
||||||
logger: this.logger,
|
logger: this.logger,
|
||||||
plugins: this.plugins,
|
plugins: this.plugins
|
||||||
vms: this.vms,
|
|
||||||
})
|
})
|
||||||
.serve(
|
.serve(
|
||||||
this.host,
|
this.host,
|
||||||
this.rpcPort,
|
this.rpcPort,
|
||||||
);
|
);
|
||||||
this.logger.info(`HTTP Proxy for node endpoint ${this.embark.config.blockchainConfig.endpoint} listening on ${buildUrl("http", this.host, this.rpcPort, "rpc")}`);
|
this.logger.info(`HTTP Proxy for node endpoint ${this.embark.config.blockchainConfig.endpoint} listening on ${buildUrl("http", this.host, this.rpcPort, "rpc")}`);
|
||||||
}
|
}
|
||||||
if (this.isWs) {
|
if (this.isWs) {
|
||||||
const endpoint = clientName === constants.blockchain.vm ? constants.blockchain.vm : this.embark.config.blockchainConfig.endpoint;
|
|
||||||
this.wsProxy = await new Proxy({
|
this.wsProxy = await new Proxy({
|
||||||
endpoint,
|
endpoint,
|
||||||
events: this.events,
|
events: this.events,
|
||||||
isWs: true,
|
isWs: true,
|
||||||
logger: this.logger,
|
logger: this.logger,
|
||||||
plugins: this.plugins,
|
plugins: this.plugins,
|
||||||
vms: this.vms,
|
clientName
|
||||||
})
|
})
|
||||||
.serve(
|
.serve(
|
||||||
this.host,
|
this.host,
|
||||||
this.wsPort,
|
this.wsPort,
|
||||||
);
|
);
|
||||||
this.logger.info(`WS Proxy for node endpoint ${endpoint} listening on ${buildUrl("ws", this.host, this.wsPort, "ws")}`);
|
this.logger.info(`WS Proxy for node endpoint ${isVm ? 'vm' : endpoint} listening on ${buildUrl("ws", this.host, this.wsPort, "ws")}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private stopProxy() {
|
private stopProxy() {
|
||||||
|
|
|
@ -17,41 +17,35 @@ export class Proxy {
|
||||||
this.timeouts = {};
|
this.timeouts = {};
|
||||||
this.plugins = options.plugins;
|
this.plugins = options.plugins;
|
||||||
this.logger = options.logger;
|
this.logger = options.logger;
|
||||||
this.vms = options.vms;
|
|
||||||
this.app = null;
|
this.app = null;
|
||||||
this.endpoint = options.endpoint;
|
this.endpoint = options.endpoint;
|
||||||
this.events = options.events;
|
this.events = options.events;
|
||||||
|
|
||||||
if (options.endpoint === constants.blockchain.vm) {
|
|
||||||
this.endpoint = this.vms[this.vms.length - 1]();
|
|
||||||
}
|
|
||||||
|
|
||||||
let provider = null;
|
|
||||||
|
|
||||||
if (typeof this.endpoint === 'string' && this.endpoint.startsWith('ws')) {
|
|
||||||
provider = this._createWebSocketProvider();
|
|
||||||
} else {
|
|
||||||
provider = this.endpoint;
|
|
||||||
}
|
|
||||||
this.isWs = options.isWs;
|
this.isWs = options.isWs;
|
||||||
// used to service all non-long-living WS connections, including any
|
this.clientName = options.clientName;
|
||||||
// request that is not WS and any WS request that is not an `eth_subscribe`
|
|
||||||
// RPC request
|
|
||||||
this.requestManager = this._createWeb3RequestManager(provider);
|
|
||||||
this.nodeSubscriptions = {};
|
this.nodeSubscriptions = {};
|
||||||
|
this._requestManager = null;
|
||||||
|
|
||||||
this.events.setCommandHandler("proxy:websocket:subscribe", this.handleSubscribe.bind(this));
|
this.events.setCommandHandler("proxy:websocket:subscribe", this.handleSubscribe.bind(this));
|
||||||
this.events.setCommandHandler("proxy:websocket:unsubscribe", this.handleUnsubscribe.bind(this));
|
this.events.setCommandHandler("proxy:websocket:unsubscribe", this.handleUnsubscribe.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
_createWebSocketProvider() {
|
// used to service all non-long-living WS connections, including any
|
||||||
return new Web3WsProvider(this.endpoint, {
|
// request that is not WS and any WS request that is not an `eth_subscribe`
|
||||||
headers: { Origin: constants.embarkResourceOrigin },
|
// RPC request
|
||||||
// TODO remove this when Geth fixes this: https://github.com/ethereum/go-ethereum/issues/16846
|
get requestManager() {
|
||||||
// Edit: This has been fixed in Geth 1.9, but we don't support 1.9 yet and still support 1.8
|
return (async () => {
|
||||||
clientConfig: {
|
if (!this._requestManager) {
|
||||||
fragmentationThreshold: 81920
|
const provider = await this._createWebSocketProvider(this.endpoint);
|
||||||
|
this._requestManager = this._createWeb3RequestManager(provider);
|
||||||
}
|
}
|
||||||
});
|
return this._requestManager;
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
async _createWebSocketProvider(endpoint) {
|
||||||
|
// pass in endpoint to ensure we get a provider with a connection to the node
|
||||||
|
// this may return a VM provider during tests, in which case endpoint will be ignored
|
||||||
|
return this.events.request2("blockchain:client:nodeProvider", this.clientName /* TODO: test that this returns "vm" or "ethereum" */, endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
_createWeb3RequestManager(provider) {
|
_createWeb3RequestManager(provider) {
|
||||||
|
@ -60,7 +54,8 @@ export class Proxy {
|
||||||
|
|
||||||
async nodeReady() {
|
async nodeReady() {
|
||||||
try {
|
try {
|
||||||
await this.requestManager.send({ method: 'eth_accounts' });
|
const reqMgr = await this.requestManager;
|
||||||
|
await reqMgr.send({ method: 'eth_accounts' });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(__(`Unable to connect to the blockchain endpoint on ${this.endpoint}`));
|
throw new Error(__(`Unable to connect to the blockchain endpoint on ${this.endpoint}`));
|
||||||
}
|
}
|
||||||
|
@ -169,8 +164,9 @@ export class Proxy {
|
||||||
}
|
}
|
||||||
|
|
||||||
forwardRequestToNode(request) {
|
forwardRequestToNode(request) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
this.requestManager.send(request, (fwdReqErr, result) => {
|
const reqMgr = await this.requestManager;
|
||||||
|
reqMgr.send(request, (fwdReqErr, result) => {
|
||||||
if (fwdReqErr) {
|
if (fwdReqErr) {
|
||||||
return reject(fwdReqErr);
|
return reject(fwdReqErr);
|
||||||
}
|
}
|
||||||
|
@ -180,8 +176,9 @@ export class Proxy {
|
||||||
}
|
}
|
||||||
|
|
||||||
async handleSubscribe(clientSocket, request, response, cb) {
|
async handleSubscribe(clientSocket, request, response, cb) {
|
||||||
|
const provider = await this._createWebSocketProvider(this.endpoint);
|
||||||
// creates a new long-living connection to the node
|
// creates a new long-living connection to the node
|
||||||
const currentReqManager = this._createWeb3RequestManager(this._createWebSocketProvider());
|
const currentReqManager = this._createWeb3RequestManager(provider);
|
||||||
|
|
||||||
// kill WS connetion to the node when the client connection closes
|
// kill WS connetion to the node when the client connection closes
|
||||||
clientSocket.on('close', () => currentReqManager.provider.disconnect());
|
clientSocket.on('close', () => currentReqManager.provider.disconnect());
|
||||||
|
|
|
@ -224,9 +224,9 @@ class TestRunner {
|
||||||
const ogAccounts = this.simOptions.accounts;
|
const ogAccounts = this.simOptions.accounts;
|
||||||
Object.assign(this.simOptions, {host, port, type, protocol, accounts, client: config.blockchain && config.blockchain.client});
|
Object.assign(this.simOptions, {host, port, type, protocol, accounts, client: config.blockchain && config.blockchain.client});
|
||||||
|
|
||||||
if (!resetServices && !deepEqual(accounts, ogAccounts)) {
|
// if (!resetServices && !deepEqual(accounts, ogAccounts)) {
|
||||||
return this.plugins.emitAndRunActionsForEvent("accounts:reseted", {accounts}, cb);
|
// return this.plugins.emitAndRunActionsForEvent("accounts:reseted", {accounts}, cb);
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (!resetServices) {
|
if (!resetServices) {
|
||||||
return cb();
|
return cb();
|
||||||
|
|
Loading…
Reference in New Issue