diff --git a/packages/node/src/api.ts b/packages/node/src/api.ts index 0dc18e344..1d0c7e10f 100644 --- a/packages/node/src/api.ts +++ b/packages/node/src/api.ts @@ -90,9 +90,3 @@ export const methodNameToImplementation = controllers.reduce( export const createRpcRouter = (requestHandler: RequestHandler) => new RpcRouter({ controllers, requestHandler }); - -export const eventNameToImplementation = { - [NODE_EVENTS.PROTOCOL_MESSAGE_EVENT]: handleReceivedProtocolMessage, - [NODE_EVENTS.REJECT_INSTALL]: handleRejectProposalMessage, - [NODE_EVENTS.REJECT_INSTALL_VIRTUAL]: handleRejectProposalMessage -}; diff --git a/packages/node/src/methods/state-channel/deposit/controller.ts b/packages/node/src/methods/state-channel/deposit/controller.ts index 1e0aeae6c..db766b399 100644 --- a/packages/node/src/methods/state-channel/deposit/controller.ts +++ b/packages/node/src/methods/state-channel/deposit/controller.ts @@ -78,7 +78,7 @@ export default class DepositController extends NodeController { requestHandler: RequestHandler, params: Node.DepositParams ): Promise { - const { outgoing, provider } = requestHandler; + const { outgoing, provider, publicIdentifier } = requestHandler; const { multisigAddress, tokenAddress } = params; params.tokenAddress = tokenAddress || CONVENTION_FOR_ETH_TOKEN_ADDRESS; @@ -87,25 +87,11 @@ export default class DepositController extends NodeController { await makeDeposit(requestHandler, params); await uninstallBalanceRefundApp(requestHandler, params); - // send deposit confirmation to counter party _after_ the balance refund - // app is installed so as to prevent needing to handle the case of - // the counter party hitting the issue of - // "Cannot deposit while another deposit is occurring in the channel." - const { messagingService, publicIdentifier, store } = requestHandler; - const [counterpartyAddress] = await StateChannel.getPeersAddressFromChannel( - publicIdentifier, - store, - multisigAddress - ); - - const payload: DepositConfirmationMessage = { + outgoing.emit(NODE_EVENTS.DEPOSIT_CONFIRMED, { from: publicIdentifier, type: NODE_EVENTS.DEPOSIT_CONFIRMED, data: params - }; - - await messagingService.send(counterpartyAddress, payload); - outgoing.emit(NODE_EVENTS.DEPOSIT_CONFIRMED, payload); + }); return { multisigBalance: await provider.getBalance(multisigAddress) diff --git a/packages/node/src/node.ts b/packages/node/src/node.ts index 21f340f24..a416c2465 100644 --- a/packages/node/src/node.ts +++ b/packages/node/src/node.ts @@ -362,8 +362,8 @@ export class Node { * solely to the deffered promise's resolve callback. */ private async handleReceivedMessage(msg: NodeTypes.NodeMessage) { - if (!this.requestHandler.isLegacyEvent(msg.type)) { - throw new Error(`Received message with unknown event type: ${msg.type}`); + if (!this.requestHandler.hasMessageHandler(msg.type)) { + throw new Error(`Received message with unknown type: ${msg.type}.}`); } const isProtocolMessage = (msg: NodeTypes.NodeMessage) => @@ -381,7 +381,7 @@ export class Node { ); } - return await this.requestHandler.callEvent(msg.type, msg); + return await this.requestHandler.callMessageHandler(msg); } private async handleIoSendDeferral(msg: NodeMessageWrappedProtocolMessage) { diff --git a/packages/node/src/request-handler.ts b/packages/node/src/request-handler.ts index 109ae58e1..08bb4b37d 100644 --- a/packages/node/src/request-handler.ts +++ b/packages/node/src/request-handler.ts @@ -2,14 +2,28 @@ import { NetworkContext, Node } from "@counterfactual/types"; import { Signer } from "ethers"; import { BaseProvider, JsonRpcProvider } from "ethers/providers"; import EventEmitter from "eventemitter3"; -import log from "loglevel"; -import { eventNameToImplementation, methodNameToImplementation } from "./api"; +import { methodNameToImplementation } from "./api"; import { ProtocolRunner } from "./machine"; +import { + handleReceivedProposalMessage, + handleReceivedProposeVirtualMessage, + handleRejectProposalMessage +} from "./message-handling/handle-node-message"; +import { handleReceivedProtocolMessage } from "./message-handling/handle-protocol-message"; import ProcessQueue from "./process-queue"; import RpcRouter from "./rpc-router"; import { Store } from "./store"; -import { NODE_EVENTS, NodeEvents } from "./types"; +import { + InstallMessage, + InstallVirtualMessage, + NODE_EVENTS, + NodeEvents, + NodeMessageWrappedProtocolMessage, + ProposeMessage, + ProposeVirtualMessage, + RejectProposalMessage +} from "./types"; import { prettyPrintObject } from "./utils"; /** @@ -18,7 +32,7 @@ import { prettyPrintObject } from "./utils"; */ export class RequestHandler { private readonly methods = new Map(); - private readonly events = new Map(); + public readonly processQueue = new ProcessQueue(); router!: RpcRouter; @@ -39,7 +53,6 @@ export class RequestHandler { injectRouter(router: RpcRouter) { this.router = router; this.mapPublicApiMethods(); - this.mapEventHandlers(); } /** @@ -82,51 +95,51 @@ export class RequestHandler { } } - /** - * This maps the Node event names to their respective handlers. - * - * These are the events being listened on to detect requests from peer Nodes. - * https://github.com/counterfactual/monorepo/blob/master/packages/cf.js/API_REFERENCE.md#events - */ - private mapEventHandlers() { - for (const eventName of Object.values(NODE_EVENTS)) { - this.events.set(eventName, eventNameToImplementation[eventName]); - } - } + public async callMessageHandler(msg: Node.NodeMessage) { + switch (msg.type) { + case NODE_EVENTS.PROTOCOL_MESSAGE_EVENT: + await handleReceivedProtocolMessage( + this, + // TODO: Replace type cast with input validation + msg as NodeMessageWrappedProtocolMessage + ); + break; - /** - * This is internally called when an event is received from a peer Node. - * Node consumers can separately setup their own callbacks for incoming events. - * @param event - * @param msg - */ - public async callEvent(event: NodeEvents, msg: Node.NodeMessage) { - const controllerExecutionMethod = this.events.get(event); - const controllerCount = this.router.eventListenerCount(event); - - if (!controllerExecutionMethod && controllerCount === 0) { - if (event === NODE_EVENTS.DEPOSIT_CONFIRMED) { - log.info( - `No event handler for counter depositing into channel: ${JSON.stringify( - msg, - undefined, - 4 - )}` + case NODE_EVENTS.PROPOSE_INSTALL: + // TODO: Replace type cast with input validation + await handleReceivedProposalMessage(this, msg as ProposeMessage); + break; + + case NODE_EVENTS.PROPOSE_INSTALL_VIRTUAL: + await handleReceivedProposeVirtualMessage( + this, + msg as ProposeVirtualMessage ); - } else { - throw Error(`Recent ${event} which has no event handler`); - } - } + break; + + case NODE_EVENTS.REJECT_INSTALL: + case NODE_EVENTS.REJECT_INSTALL_VIRTUAL: + // TODO: Replace type cast with input validation + await handleRejectProposalMessage(this, msg as RejectProposalMessage); + break; - if (controllerExecutionMethod) { - await controllerExecutionMethod(this, msg); + default: + throw new Error(`Received unknown message ${msg.type}`); } - this.router.emit(event, msg); + this.router.emit(msg.type, msg); } - public async isLegacyEvent(event: NodeEvents) { - return this.events.has(event); + public async hasMessageHandler(event: NodeEvents) { + return [ + NODE_EVENTS.PROTOCOL_MESSAGE_EVENT, + NODE_EVENTS.PROPOSE_INSTALL, + NODE_EVENTS.PROPOSE_INSTALL_VIRTUAL, + NODE_EVENTS.REJECT_INSTALL, + NODE_EVENTS.REJECT_INSTALL_VIRTUAL, + NODE_EVENTS.INSTALL, + NODE_EVENTS.INSTALL_VIRTUAL + ].includes(event); } public async getSigner(): Promise {