From deaf239ddf69f5848e22b17a8150bf4bef32c9d8 Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Wed, 13 Jan 2021 18:53:15 +0300 Subject: [PATCH 01/36] feat: waitForStateTransitionResult endpoint --- .../drive/DriveStateRepository.js | 19 ++ lib/externalApis/tenderdash/WsClient.js | 205 ++++++++++++++++ .../platform/platformHandlersFactory.js | 29 +++ ...tForStateTransitionResultHandlerFactory.js | 110 +++++++++ package-lock.json | 225 +++++++++--------- package.json | 7 +- scripts/api.js | 29 +++ .../drive/DriveStateRepository.js | 35 +++ 8 files changed, 547 insertions(+), 112 deletions(-) create mode 100644 lib/externalApis/tenderdash/WsClient.js create mode 100644 lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js diff --git a/lib/externalApis/drive/DriveStateRepository.js b/lib/externalApis/drive/DriveStateRepository.js index 327523393..225fa99ce 100644 --- a/lib/externalApis/drive/DriveStateRepository.js +++ b/lib/externalApis/drive/DriveStateRepository.js @@ -160,6 +160,25 @@ class DriveStateRepository { prove, ); } + + /** + * Fetch proofs by ids + * + * @param {Buffer[]} [documentIds] + * @param {Buffer[]} [identityIds] + * @param {Buffer[]} [dataContractIds] + * @return {Promise<{data: Buffer}>} + */ + async fetchProofs({ documentIds, identityIds, dataContractIds }) { + return this.request( + '/proofs', + { + documentIds, + identityIds, + dataContractIds, + }, + ); + } } module.exports = DriveStateRepository; diff --git a/lib/externalApis/tenderdash/WsClient.js b/lib/externalApis/tenderdash/WsClient.js new file mode 100644 index 000000000..4cfa29229 --- /dev/null +++ b/lib/externalApis/tenderdash/WsClient.js @@ -0,0 +1,205 @@ +const { EventEmitter } = require('events'); +const WebSocket = require('ws'); + +class WsClient extends EventEmitter { + constructor(options = {}) { + super(); + + const protocol = (options && options.protocol) ? options.protocol.toString() : 'ws'; + const host = (options && options.host) ? options.host.toString() : '0.0.0.0'; + const port = (options && options.port) ? options.port.toString() : '26657'; + const path = (options && options.path) ? options.path.toString() : 'websocket'; + + this.url = `${protocol}://${host}:${port}/${path}`; + this.isConnected = false; + this.autoReconnectInterval = 1000; + this.subscribedQueries = new Map(); + } + + /** + * @private + * @return + */ + open() { + if (this.ws) { + this.disconnect(); + } + + this.ws = new WebSocket(this.url); + + const reconnect = () => { + if (this.connectionRetries <= this.maxRetries || this.maxRetries === -1) { + if (this.maxRetries !== -1) { + this.connectionRetries += 1; + } + + setTimeout(this.open.bind(this), this.autoReconnectInterval); + } else { + this.disconnect(); + + const event = { + type: 'connect:max_retry_exceeded', + address: this.url, + }; + + this.emit(event.type, event); + } + }; + + const onOpenListener = () => { + this.isConnected = true; + + const event = { + type: 'connect', + address: this.url, + }; + + this.emit(event.type, event); + + for (const query of this.subscribedQueries.keys()) { + this.subscribe(query); + } + }; + + const onCloseListener = (e) => { + if (e.code === 1000) { // close normal + this.disconnect(); + + return; + } + + reconnect(); + }; + + const onErrorListener = (e) => { + switch (e.code) { + case 'ECONNREFUSED': + reconnect(); + break; + default: + this.disconnect(); + this.emit('error', e); + break; + } + }; + + const onMessageListener = (rawData) => { + const { result } = JSON.parse(rawData); + + if (result !== undefined && Object.keys(result).length > 0) { + this.emit(result.query, result); + } + }; + + this.ws.on('open', onOpenListener); + this.ws.on('close', onCloseListener); + this.ws.on('error', onErrorListener); + this.ws.on('message', onMessageListener); + } + + /** + * + * @param {object} connectionOptions + * @param {number} connectionOptions.maxRetries + * @return {Promise} + */ + async connect(connectionOptions = {}) { + // by default, we don't set any max number of retries + this.maxRetries = connectionOptions.maxRetries || -1; + this.connectionRetries = 0; + this.subscribedQueries.clear(); + + return new Promise(async (resolve, reject) => { + // If a max number of retries is set, we reject when exceeding retry number + if (this.maxRetries !== -1) { + this.on('connect:max_retry_exceeded', async () => reject(new Error('Connection dropped. Max retries exceeded.'))); + } + + this.open(); + + // We only return socket when we actually established a connection + this.on('connect', () => resolve()); + }); + } + + /** + * + * @return {boolean} + */ + close() { + if (this.ws) { + if (this.isConnected) { + this.disconnect(); + } + + this.ws = null; + this.subscribedQueries.clear(); + + return true; + } + + return false; + } + + disconnect() { + this.ws.removeAllListeners(); + try { + this.ws.terminate(); + } catch (e) { + // do nothing + } + + this.isConnected = false; + } + + /** + * + * @param {string} query + */ + subscribe(query) { + const id = 0; + + const request = { + jsonrpc: '2.0', + method: 'subscribe', + id, + params: { + query, + }, + }; + + this.ws.send(JSON.stringify(request)); + + const count = this.subscribedQueries.get(query) || 0; + this.subscribedQueries.set(query, count + 1); + } + + /** + * + * @param {string} query + */ + unsubscribe(query) { + const count = this.subscribedQueries.get(query) - 1; + + if (count > 0) { + this.subscribedQueries.set(query, count); + } else { + const id = 0; + + const request = { + jsonrpc: '2.0', + method: 'unsubscribe', + id, + params: { + query, + }, + }; + + this.ws.send(JSON.stringify(request)); + + this.subscribedQueries.delete(query); + } + } +} + +module.exports = WsClient; diff --git a/lib/grpcServer/handlers/platform/platformHandlersFactory.js b/lib/grpcServer/handlers/platform/platformHandlersFactory.js index 4cb889d1c..cd4399924 100644 --- a/lib/grpcServer/handlers/platform/platformHandlersFactory.js +++ b/lib/grpcServer/handlers/platform/platformHandlersFactory.js @@ -21,6 +21,7 @@ const { GetDocumentsRequest, GetIdentitiesByPublicKeyHashesRequest, GetIdentityIdsByPublicKeyHashesRequest, + StateTransitionResultsRequest, pbjs: { BroadcastStateTransitionRequest: PBJSBroadcastStateTransitionRequest, BroadcastStateTransitionResponse: PBJSBroadcastStateTransitionResponse, @@ -34,6 +35,8 @@ const { GetIdentitiesByPublicKeyHashesRequest: PBJSGetIdentitiesByPublicKeyHashesRequest, GetIdentityIdsByPublicKeyHashesResponse: PBJSGetIdentityIdsByPublicKeyHashesResponse, GetIdentityIdsByPublicKeyHashesRequest: PBJSGetIdentityIdsByPublicKeyHashesRequest, + StateTransitionResultsRequest: PBJSStateTransitionResultsRequest, + StateTransitionResultsResponse: PBJSStateTransitionResultsResponse, }, }, } = require('@dashevo/dapi-grpc'); @@ -60,16 +63,23 @@ const getIdentitiesByPublicKeyHashesHandlerFactory = require( const getIdentityIdsByPublicKeyHashesHandlerFactory = require( './getIdentityIdsByPublicKeyHashesHandlerFactory', ); +const waitForStateTransitionResultHandlerFactory = require( + './waitForStateTransitionResultHandlerFactory', +); /** * @param {jaysonClient} rpcClient + * @param {WsClient} tenderDashWsClient * @param {DriveStateRepository} driveStateRepository + * @param {DashPlatformProtocol} dpp * @param {boolean} isProductionEnvironment * @returns {Object} */ function platformHandlersFactory( rpcClient, + tenderDashWsClient, driveStateRepository, + dpp, isProductionEnvironment, ) { const wrapInErrorHandler = wrapInErrorHandlerFactory(log, isProductionEnvironment); @@ -171,6 +181,24 @@ function platformHandlersFactory( wrapInErrorHandler(getIdentityIdsByPublicKeyHashesHandler), ); + // waitForStateTransitionResult + const waitForStateTransitionResultHandler = waitForStateTransitionResultHandlerFactory( + driveStateRepository, + tenderDashWsClient, + dpp, + ); + + const wrappedWaitForStateTransitionResult = jsonToProtobufHandlerWrapper( + jsonToProtobufFactory( + StateTransitionResultsRequest, + PBJSStateTransitionResultsRequest, + ), + protobufToJsonFactory( + PBJSStateTransitionResultsResponse, + ), + wrapInErrorHandler(waitForStateTransitionResultHandler), + ); + return { broadcastStateTransition: wrappedBroadcastStateTransition, getIdentity: wrappedGetIdentity, @@ -178,6 +206,7 @@ function platformHandlersFactory( getDataContract: wrappedGetDataContract, getIdentitiesByPublicKeyHashes: wrappedGetIdentitiesByPublicKeyHashes, getIdentityIdsByPublicKeyHashes: wrappedGetIdentityIdsByPublicKeyHashes, + waitForStateTransitionResult: wrappedWaitForStateTransitionResult, }; } diff --git a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js new file mode 100644 index 000000000..37b3bc812 --- /dev/null +++ b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -0,0 +1,110 @@ +const { + v0: { + WaitForStateTransitionResultResponse, + StateTransitionBroadcastError, + Proof, + }, +} = require('@dashevo/dapi-grpc'); + +const cbor = require('cbor'); + +/** + * + * @param {DriveStateRepository} driveStateRepository + * @param {WsClient} tenderDashWsClient + * @param {DashPlatformProtocol} dpp + * @return {waitForStateTransitionResultHandler} + */ +function waitForStateTransitionResultHandlerFactory( + driveStateRepository, + tenderDashWsClient, + dpp, +) { + /** + * + * @param {AbstractStateTransition} stateTransition + * @return {Promise} + */ + async function fetchProof(stateTransition) { + const modifiedIds = stateTransition.getModifiedDataIds(); + + let proof; + const params = {}; + if (stateTransition.isDocumentStateTransition()) { + ({ documentsProof: proof } = await driveStateRepository.fetchProofs( + { documentIds: modifiedIds }, + )); + } else if (stateTransition.isIdentityStateTransition()) { + ({ identitiesProof: proof } = await driveStateRepository.fetchProofs( + { identityIds: modifiedIds }, + )); + params.identityIds = modifiedIds; + } else if (stateTransition.isDataContractStateTransition()) { + ({ dataContractsProof: proof } = await driveStateRepository.fetchProofs( + { dataContractIds: modifiedIds }, + )); + } + + return proof; + } + + + /** + * @typedef waitForStateTransitionResultHandler + * @param {Object} call + * @return {Promise} + */ + + async function waitForStateTransitionResultHandler(call) { + const { request } = call; + + const stateTransitionHash = request.getStateTransitionHash(); + const prove = request.getProve(); + + const query = `tm.event = 'Tx' AND tx.hash = '${Buffer.from(stateTransitionHash).toString('hex')}'`; + + const data = await new Promise((resolve) => { + tenderDashWsClient.once(query, (message) => { + resolve(message); + }); + }); + + const response = new WaitForStateTransitionResultResponse(); + + const { result, tx } = data.data.value.TxResult; + + if (result && result.code !== undefined && result.code !== 0) { + const { error: abciError } = JSON.parse(result.log); + + const error = new StateTransitionBroadcastError(); + + error.setCode(result.code); + error.setMessage(abciError.message); + error.setData(cbor.encode(abciError.data)); + + response.setError(error); + + return response; + } + + if (prove) { + const stateTransition = await dpp.stateTransition.createFromBuffer( + Buffer.from(tx, 'base64'), + { skipValidation: true }, + ); + const proofObject = await fetchProof(stateTransition); + + const proof = new Proof(); + proof.setRootTreeProof(proofObject.rootTreeProof); + proof.setStoreTreeProof(proofObject.storeTreeProof); + + response.setProof(proof); + } + + return response; + } + + return waitForStateTransitionResultHandler; +} + +module.exports = waitForStateTransitionResultHandlerFactory; diff --git a/package-lock.json b/package-lock.json index 1a0afd1da..5f2704683 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,6 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-8.0.0.tgz", "integrity": "sha512-n4YBtwQhdpLto1BaUCyAeflizmIbaloGShsPyRtFf5qdFJxfssj+GgLavczgKJFa3Bq+3St2CKcpRJdjtB4EBw==", - "dev": true, "requires": { "@jsdevtools/ono": "^7.1.0", "call-me-maybe": "^1.0.1", @@ -99,17 +98,17 @@ } }, "@babel/traverse": { - "version": "7.12.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.10.tgz", - "integrity": "sha512-6aEtf0IeRgbYWzta29lePeYSk+YAFIC3kyqESeft8o5CkFlYIMX+EQDDWEiAQ9LHOA3d0oHdgrSsID/CKqXJlg==", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.12.tgz", + "integrity": "sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w==", "dev": true, "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.12.10", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.12.10", - "@babel/types": "^7.12.10", + "@babel/code-frame": "^7.12.11", + "@babel/generator": "^7.12.11", + "@babel/helper-function-name": "^7.12.11", + "@babel/helper-split-export-declaration": "^7.12.11", + "@babel/parser": "^7.12.11", + "@babel/types": "^7.12.12", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.19" @@ -133,9 +132,9 @@ } }, "@babel/types": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.11.tgz", - "integrity": "sha512-ukA9SQtKThINm++CX1CwmliMrE54J6nIYB5XTwL5f/CLFW9owfls+YSU8tVW15RQ2w+a3fSbPjC6HdQNtWZkiA==", + "version": "7.12.12", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.12.tgz", + "integrity": "sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ==", "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.12.11", @@ -144,34 +143,47 @@ } }, "@dashevo/dapi-client": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@dashevo/dapi-client/-/dapi-client-0.17.0.tgz", - "integrity": "sha512-gjZ8vnuyP2M1vtseDxzamYTKO8SRxi9DV8ujeX2W5nkKeNSawLSMqkkEBa+CE4wMJJPQ048K+tQfAQwYlzJphw==", + "version": "0.17.2", + "resolved": "https://registry.npmjs.org/@dashevo/dapi-client/-/dapi-client-0.17.2.tgz", + "integrity": "sha512-lWaAXNwf1yVtI9fccgu2wYjNlkKsOgdvmIAEkSN45ALrg3sEMjY2p4QiEJV55IZVzC3j6+nC+iG3QO6dY7ZGcQ==", "dev": true, "requires": { "@dashevo/dapi-grpc": "~0.17.0", - "@dashevo/dashcore-lib": "~0.19.18", + "@dashevo/dashcore-lib": "~0.19.19", "axios": "^0.19.2", "cbor": "^5.0.1", "lodash.sample": "^4.2.1" }, "dependencies": { + "@dashevo/dapi-grpc": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@dashevo/dapi-grpc/-/dapi-grpc-0.17.0.tgz", + "integrity": "sha512-Sd4N5Zqyq6h5ZQ1EpnWZeFYFV80RHiXnQ1DHE2xdX0npHIhj0R9kKsultwnkgB9oIp/roQtSpCL7t9iTsVKerA==", + "dev": true, + "requires": { + "@dashevo/grpc-common": "^0.3.0", + "google-protobuf": "^3.12.2", + "grpc": "^1.24.3", + "grpc-web": "^1.2.0", + "protobufjs": "github:jawid-h/protobuf.js#fix/buffer-conversion" + } + }, "cbor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-5.1.0.tgz", - "integrity": "sha512-qzEc7kUShdMbWTaUH7X+aHW8owvBU3FS0dfYR1lGYpoZr0mGJhhojLlZJH653x/DfeMZ56h315FRNBUIG1R7qg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-5.2.0.tgz", + "integrity": "sha512-5IMhi9e1QU76ppa5/ajP1BmMWZ2FHkhAhjeVKQ/EFCgYSEaeVaoGtL7cxJskf9oCCk+XjzaIdc3IuU/dbA/o2A==", "dev": true, "requires": { - "bignumber.js": "^9.0.0", + "bignumber.js": "^9.0.1", "nofilter": "^1.0.4" } } } }, "@dashevo/dapi-grpc": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@dashevo/dapi-grpc/-/dapi-grpc-0.17.0.tgz", - "integrity": "sha512-Sd4N5Zqyq6h5ZQ1EpnWZeFYFV80RHiXnQ1DHE2xdX0npHIhj0R9kKsultwnkgB9oIp/roQtSpCL7t9iTsVKerA==", + "version": "0.18.0-dev.1", + "resolved": "https://registry.npmjs.org/@dashevo/dapi-grpc/-/dapi-grpc-0.18.0-dev.1.tgz", + "integrity": "sha512-0F9vaIoS/lMgg3izzMV5n5chLEsVaqrUP5th8UOQwzaHBgkF592tGeYhhG3ItBd5AzgpXAkFlX7SVmHT7s6gZQ==", "requires": { "@dashevo/grpc-common": "^0.3.0", "google-protobuf": "^3.12.2", @@ -181,9 +193,9 @@ } }, "@dashevo/dashcore-lib": { - "version": "0.19.18", - "resolved": "https://registry.npmjs.org/@dashevo/dashcore-lib/-/dashcore-lib-0.19.18.tgz", - "integrity": "sha512-1+a175qKIl4XgOipulZbacQnc7amvmP1a3qyDoEVkKXEloHwn21Xk4tzd8ZArReceSe90AGkYTaMmqo2r/NXhg==", + "version": "0.19.19", + "resolved": "https://registry.npmjs.org/@dashevo/dashcore-lib/-/dashcore-lib-0.19.19.tgz", + "integrity": "sha512-ekt0l8fnwsGc1MP1cPzJhkTQ7+Ek4zIhzSt/491HOjxRJZaf+XC/WZNrDEjQgFb/oZYLnfDXlq4CdNkDk/CDow==", "requires": { "@dashevo/x11-hash-js": "^1.0.2", "@types/node": "^12.12.47", @@ -198,9 +210,9 @@ }, "dependencies": { "@types/node": { - "version": "12.19.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.11.tgz", - "integrity": "sha512-bwVfNTFZOrGXyiQ6t4B9sZerMSShWNsGRw8tC5DY1qImUNczS9SjT4G6PnzjCnxsu5Ubj6xjL2lgwddkxtQl5w==" + "version": "12.19.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.12.tgz", + "integrity": "sha512-UwfL2uIU9arX/+/PRcIkT08/iBadGN2z6ExOROA2Dh5mAuWTBj6iJbQX4nekiV5H8cTrEG569LeX+HRco9Cbxw==" }, "inherits": { "version": "2.0.1", @@ -252,12 +264,12 @@ }, "dependencies": { "cbor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-5.1.0.tgz", - "integrity": "sha512-qzEc7kUShdMbWTaUH7X+aHW8owvBU3FS0dfYR1lGYpoZr0mGJhhojLlZJH653x/DfeMZ56h315FRNBUIG1R7qg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-5.2.0.tgz", + "integrity": "sha512-5IMhi9e1QU76ppa5/ajP1BmMWZ2FHkhAhjeVKQ/EFCgYSEaeVaoGtL7cxJskf9oCCk+XjzaIdc3IuU/dbA/o2A==", "dev": true, "requires": { - "bignumber.js": "^9.0.0", + "bignumber.js": "^9.0.1", "nofilter": "^1.0.4" } } @@ -295,9 +307,9 @@ } }, "@types/node": { - "version": "12.19.9", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.9.tgz", - "integrity": "sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q==", + "version": "12.19.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.12.tgz", + "integrity": "sha512-UwfL2uIU9arX/+/PRcIkT08/iBadGN2z6ExOROA2Dh5mAuWTBj6iJbQX4nekiV5H8cTrEG569LeX+HRco9Cbxw==", "dev": true }, "inherits": { @@ -312,7 +324,6 @@ "version": "0.17.0", "resolved": "https://registry.npmjs.org/@dashevo/dpp/-/dpp-0.17.0.tgz", "integrity": "sha512-rt6uZZsBgv0oqwGENHTwWBzqy0w0ek2BP7N7gBlK34Y2MAkyVVwYYwNuS3oFibYzjYNaKl61Tl7noIOrhZDWGg==", - "dev": true, "requires": { "@apidevtools/json-schema-ref-parser": "^8.0.0", "@dashevo/dashcore-lib": "~0.19.18", @@ -327,12 +338,11 @@ }, "dependencies": { "cbor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-5.1.0.tgz", - "integrity": "sha512-qzEc7kUShdMbWTaUH7X+aHW8owvBU3FS0dfYR1lGYpoZr0mGJhhojLlZJH653x/DfeMZ56h315FRNBUIG1R7qg==", - "dev": true, + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-5.2.0.tgz", + "integrity": "sha512-5IMhi9e1QU76ppa5/ajP1BmMWZ2FHkhAhjeVKQ/EFCgYSEaeVaoGtL7cxJskf9oCCk+XjzaIdc3IuU/dbA/o2A==", "requires": { - "bignumber.js": "^9.0.0", + "bignumber.js": "^9.0.1", "nofilter": "^1.0.4" } } @@ -367,8 +377,7 @@ "@jsdevtools/ono": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", - "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", - "dev": true + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==" }, "@protobufjs/aspromise": { "version": "1.1.2", @@ -481,9 +490,9 @@ "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" }, "@types/node": { - "version": "13.13.36", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.36.tgz", - "integrity": "sha512-ctzZJ+XsmHQwe3xp07gFUq4JxBaRSYzKHPgblR76//UanGST7vfFNF0+ty5eEbgTqsENopzoDK090xlha9dccQ==" + "version": "13.13.39", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.39.tgz", + "integrity": "sha512-wct+WgRTTkBm2R3vbrFOqyZM5w0g+D8KnhstG9463CJBVC3UVZHMToge7iMBR1vDl/I+NWFHUeK9X+JcF0rWKw==" }, "@ungap/promise-all-settled": { "version": "1.1.2", @@ -597,7 +606,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -683,9 +691,9 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "aws-sdk": { - "version": "2.814.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.814.0.tgz", - "integrity": "sha512-empd1m/J/MAkL6d9OeRpmg9thobULu0wk4v8W3JToaxGi2TD7PIdvE6yliZKyOVAdJINhBWEBhxR4OUIHhcGbQ==", + "version": "2.825.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.825.0.tgz", + "integrity": "sha512-b49nvaETm7uVRLf0FJ1CMmwCRVlLaxHtptVFuxX+2L4FR9VB0sLdgsxhtL3RVFbQlgVFNRV7fJUVK27mC++H+A==", "dev": true, "requires": { "buffer": "4.9.2", @@ -781,9 +789,9 @@ "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" }, "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, "bitset": { @@ -942,20 +950,19 @@ } }, "call-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.0.tgz", - "integrity": "sha512-AEXsYIyyDY3MCzbwdhzG3Jx1R0J2wetQyUynn6dYHAO+bg8l1k7jwZtRv4ryryFs7EP+NDlikJlVe59jr0cM2w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", "dev": true, "requires": { "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.0" + "get-intrinsic": "^1.0.2" } }, "call-me-maybe": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", - "dev": true + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" }, "callsites": { "version": "3.1.0", @@ -1316,9 +1323,9 @@ "integrity": "sha1-m4MZR3wOX4rrPONXrjBfwl6hzSs=" }, "denque": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", - "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.0.tgz", + "integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ==", "dev": true }, "detect-libc": { @@ -1828,8 +1835,7 @@ "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { "version": "1.3.1", @@ -2848,9 +2854,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.49", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.49.tgz", - "integrity": "sha512-PGaJNs5IZz5XgzwJvL/1zRfZB7iaJ5BydZ8/Picm+lUNYoNO9iVTQkVy5eUh0dZDrx3rBOIs3GCbCRmMuYyqwg==" + "version": "10.17.50", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.50.tgz", + "integrity": "sha512-vwX+/ija9xKc/z9VqMCdbf4WYcMTGsI0I/L/6shIF3qXURxZOhPQlPRHtjTpiNhAwn0paMJzlOQqw6mAGEQnTA==" }, "commander": { "version": "2.20.3", @@ -2875,7 +2881,6 @@ "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -3042,14 +3047,12 @@ "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" }, "lodash.clonedeepwith": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeepwith/-/lodash.clonedeepwith-4.5.0.tgz", - "integrity": "sha1-buMFc6A6GmDWcKYu8zwQzxr9vdQ=", - "dev": true + "integrity": "sha1-buMFc6A6GmDWcKYu8zwQzxr9vdQ=" }, "lodash.flattendeep": { "version": "4.4.0", @@ -3071,8 +3074,7 @@ "lodash.mergewith": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", - "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", - "dev": true + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==" }, "lodash.sample": { "version": "4.2.1", @@ -3083,8 +3085,7 @@ "lodash.set": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=", - "dev": true + "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" }, "log-symbols": { "version": "4.0.0", @@ -3232,16 +3233,16 @@ } }, "mime-db": { - "version": "1.44.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", - "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==" }, "mime-types": { - "version": "2.1.27", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", - "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "version": "2.1.28", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz", + "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==", "requires": { - "mime-db": "1.44.0" + "mime-db": "1.45.0" } }, "mimic-fn": { @@ -3654,9 +3655,9 @@ } }, "needle": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", - "integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", + "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", "requires": { "debug": "^3.2.6", "iconv-lite": "^0.4.4", @@ -4313,7 +4314,7 @@ "dev": true }, "protobufjs": { - "version": "github:jawid-h/protobuf.js#264b99b2ab6e097ff5350a57055d754d44d8e703", + "version": "github:jawid-h/protobuf.js#8b91c72dca68fd6c418078fd2358c4969425dcdc", "from": "github:jawid-h/protobuf.js#fix/buffer-conversion", "requires": { "@protobufjs/aspromise": "^1.1.2", @@ -4823,8 +4824,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { "version": "1.16.1", @@ -5049,9 +5049,9 @@ } }, "tar-stream": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.4.tgz", - "integrity": "sha512-o3pS2zlG4gxr67GmFYBLlq+dM8gyRGUOvsrHclSkvtVtQbjV0s/+ZE8OpICbaj8clrX3tjeHngYGP7rweaBnuw==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "requires": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", @@ -5338,9 +5338,9 @@ "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==" }, "uri-js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", - "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "requires": { "punycode": "^2.1.0" } @@ -5421,6 +5421,19 @@ "safe-buffer": "^5.1.2", "ws": "^3.2.0", "xtend": "^4.0.0" + }, + "dependencies": { + "ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + } } }, "which": { @@ -5503,15 +5516,9 @@ } }, "ws": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", - "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0", - "ultron": "~1.1.0" - } + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.2.tgz", + "integrity": "sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA==" }, "xml2js": { "version": "0.4.19", @@ -5536,9 +5543,9 @@ "dev": true }, "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" }, "yallist": { "version": "3.1.1", diff --git a/package.json b/package.json index ff30e4c40..2946d45b8 100644 --- a/package.json +++ b/package.json @@ -30,9 +30,10 @@ "all": true }, "dependencies": { - "@dashevo/dapi-grpc": "~0.17.0", - "@dashevo/dashcore-lib": "~0.19.18", + "@dashevo/dapi-grpc": "~0.18.0-dev.1", + "@dashevo/dashcore-lib": "~0.19.19", "@dashevo/dashd-rpc": "^2.0.2", + "@dashevo/dpp": "~0.17.0", "@dashevo/grpc-common": "~0.3.2", "ajv": "^6.4.0", "bs58": "^4.0.1", @@ -45,12 +46,12 @@ "lodash": "^4.17.19", "request": "^2.87.0", "request-promise-native": "^1.0.5", + "ws": "^7.4.2", "zeromq": "^5.2.0" }, "devDependencies": { "@dashevo/dapi-client": "~0.17.0", "@dashevo/dp-services-ctl": "~0.14.0", - "@dashevo/dpp": "~0.17.0", "chai": "^4.2.0", "chai-as-promised": "^7.1.1", "dirty-chai": "^2.0.1", diff --git a/scripts/api.js b/scripts/api.js index 6d7065e5a..65d3312bb 100644 --- a/scripts/api.js +++ b/scripts/api.js @@ -13,8 +13,12 @@ const { getPlatformDefinition, } = require('@dashevo/dapi-grpc'); +const DashPlatformProtocol = require('@dashevo/dpp'); + const { client: RpcClient } = require('jayson/promise'); +const WsClient = require('../lib/externalApis/tenderdash/WsClient'); + // Load config from .env dotenv.config(); @@ -55,6 +59,27 @@ async function main() { port: config.tendermintCore.port, }); + const tenderDashWsClient = new WsClient({ + host: config.tendermintCore.host, + port: config.tendermintCore.port, + }); + + log.info(`Connecting to tenderdash WebSocket on ${config.tendermintCore.host}:${config.tendermintCore.port}`); + + tenderDashWsClient.on('error', (e) => { + log.error('WebSocket error', e); + + process.exit(1); + }); + + await tenderDashWsClient.connect(); + + const wsQuery = 'tm.event = \'Tx\''; + + tenderDashWsClient.subscribe(wsQuery); + + log.info('Connection to WebSocket established.'); + // Start JSON RPC server log.info('Starting JSON RPC server'); rpcServer.start({ @@ -65,6 +90,8 @@ async function main() { }); log.info(`JSON RPC server is listening on port ${config.rpcServer.port}`); + const dpp = new DashPlatformProtocol(); + // Start GRPC server log.info('Starting GRPC server'); @@ -74,7 +101,9 @@ async function main() { ); const platformHandlers = platformHandlersFactory( rpcClient, + tenderDashWsClient, driveStateRepository, + dpp, isProductionEnvironment, ); diff --git a/test/unit/externalApis/drive/DriveStateRepository.js b/test/unit/externalApis/drive/DriveStateRepository.js index 50011b435..5dbaeddb7 100644 --- a/test/unit/externalApis/drive/DriveStateRepository.js +++ b/test/unit/externalApis/drive/DriveStateRepository.js @@ -230,4 +230,39 @@ describe('DriveStateRepository', () => { }); }); }); + + describe('#fetchProofs', () => { + it('should call \'fetchProofs\' RPC with the given parameters', async () => { + const drive = new DriveStateRepository({ host: '127.0.0.1', port: 3000 }); + + const documentIds = undefined; + const identityIds = [Buffer.from('id')]; + const dataContractIds = [Buffer.from('anotherId')]; + + const proof = Buffer.from('proof'); + const buffer = cbor.encode({ data: proof }); + + sinon.stub(drive.client, 'request') + .resolves({ + result: { + response: { code: 0, value: buffer }, + }, + }); + + const result = await drive.fetchProofs({ documentIds, identityIds, dataContractIds }); + + expect(drive.client.request).to.have.been.calledOnceWithExactly('abci_query', { + path: '/proofs', + data: cbor.encode({ + documentIds, + identityIds, + dataContractIds, + }).toString('hex'), + }); + + expect(result).to.be.deep.equal({ + data: proof, + }); + }); + }); }); From 74a6d3fae7a564011aef48272b5ba1507273d99e Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Wed, 13 Jan 2021 19:28:01 +0300 Subject: [PATCH 02/36] bugfix --- .../waitForStateTransitionResultHandlerFactory.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 37b3bc812..e29079051 100644 --- a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -61,11 +61,14 @@ function waitForStateTransitionResultHandlerFactory( const stateTransitionHash = request.getStateTransitionHash(); const prove = request.getProve(); - const query = `tm.event = 'Tx' AND tx.hash = '${Buffer.from(stateTransitionHash).toString('hex')}'`; + const query = 'tm.event = \'Tx\''; + const hash = Buffer.from(stateTransitionHash).toString('hex'); const data = await new Promise((resolve) => { - tenderDashWsClient.once(query, (message) => { - resolve(message); + tenderDashWsClient.on(query, (message) => { + if (message.events['tx.hash'] === hash) { + resolve(message); + } }); }); From 3aaa596011f903f2c134fd04fd227ac6d4d8c65d Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Thu, 14 Jan 2021 18:35:11 +0300 Subject: [PATCH 03/36] test: add unit tests --- ...tForStateTransitionResultHandlerFactory.js | 20 +- package-lock.json | 594 +++++++++++++++++- package.json | 5 +- ...tForStateTransitionResultHandlerFactory.js | 203 ++++++ 4 files changed, 812 insertions(+), 10 deletions(-) create mode 100644 test/unit/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js diff --git a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index e29079051..5dfed5258 100644 --- a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -1,3 +1,10 @@ +const { + server: { + error: { + InvalidArgumentGrpcError, + }, + }, +} = require('@dashevo/grpc-common'); const { v0: { WaitForStateTransitionResultResponse, @@ -61,12 +68,16 @@ function waitForStateTransitionResultHandlerFactory( const stateTransitionHash = request.getStateTransitionHash(); const prove = request.getProve(); + if (stateTransitionHash === null) { + throw new InvalidArgumentGrpcError('state transition hash is not specified'); + } + const query = 'tm.event = \'Tx\''; const hash = Buffer.from(stateTransitionHash).toString('hex'); const data = await new Promise((resolve) => { tenderDashWsClient.on(query, (message) => { - if (message.events['tx.hash'] === hash) { + if (message.events['tx.hash'].includes(hash.toUpperCase())) { resolve(message); } }); @@ -79,11 +90,16 @@ function waitForStateTransitionResultHandlerFactory( if (result && result.code !== undefined && result.code !== 0) { const { error: abciError } = JSON.parse(result.log); + let errorData; + if (abciError.data) { + errorData = cbor.encode(abciError.data); + } + const error = new StateTransitionBroadcastError(); error.setCode(result.code); error.setMessage(abciError.message); - error.setData(cbor.encode(abciError.data)); + error.setData(errorData); response.setError(error); diff --git a/package-lock.json b/package-lock.json index 5f2704683..0e7d15e46 100644 --- a/package-lock.json +++ b/package-lock.json @@ -181,9 +181,9 @@ } }, "@dashevo/dapi-grpc": { - "version": "0.18.0-dev.1", - "resolved": "https://registry.npmjs.org/@dashevo/dapi-grpc/-/dapi-grpc-0.18.0-dev.1.tgz", - "integrity": "sha512-0F9vaIoS/lMgg3izzMV5n5chLEsVaqrUP5th8UOQwzaHBgkF592tGeYhhG3ItBd5AzgpXAkFlX7SVmHT7s6gZQ==", + "version": "0.18.0-dev.2", + "resolved": "https://registry.npmjs.org/@dashevo/dapi-grpc/-/dapi-grpc-0.18.0-dev.2.tgz", + "integrity": "sha512-0/530EWRMFLj1QBvfY+0CXHbuJjnWMDvCI+6GcFVzYprerIayQe9Wgr1l4gmplQjI06WJd+GXdk4W+mEpxImYQ==", "requires": { "@dashevo/grpc-common": "^0.3.0", "google-protobuf": "^3.12.2", @@ -321,9 +321,9 @@ } }, "@dashevo/dpp": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@dashevo/dpp/-/dpp-0.17.0.tgz", - "integrity": "sha512-rt6uZZsBgv0oqwGENHTwWBzqy0w0ek2BP7N7gBlK34Y2MAkyVVwYYwNuS3oFibYzjYNaKl61Tl7noIOrhZDWGg==", + "version": "0.18.0-dev.1", + "resolved": "https://registry.npmjs.org/@dashevo/dpp/-/dpp-0.18.0-dev.1.tgz", + "integrity": "sha512-2q4xQFJCXpQi61fn1wg4y+DIGD4g4VUcCEa7XIjjW20ellfQI5mKPOI0M9ziZQVu4dTqNxVpc6mXy2qpubMKHw==", "requires": { "@apidevtools/json-schema-ref-parser": "^8.0.0", "@dashevo/dashcore-lib": "~0.19.18", @@ -657,6 +657,45 @@ "safer-buffer": "~2.1.0" } }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -757,6 +796,16 @@ "follow-redirects": "1.5.10" } }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -871,6 +920,112 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "requires": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + } + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "bn.js": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, "bs58": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", @@ -922,6 +1077,18 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, "bytebuffer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", @@ -1137,6 +1304,12 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, + "compare-module-exports": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/compare-module-exports/-/compare-module-exports-2.1.0.tgz", + "integrity": "sha512-3Lc0sTIuX1jmY2K2RrXRJOND6KsRTX2D4v3+eu1PDptsuJZVK4LZc852eZa9I+avj0NrUKlTNgqvccNOH6mbGg==", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1160,11 +1333,23 @@ "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", "dev": true }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, "contains-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", @@ -1180,6 +1365,12 @@ "safe-buffer": "~5.1.1" } }, + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -1206,6 +1397,16 @@ } } }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, "create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", @@ -1219,6 +1420,20 @@ "sha.js": "^2.4.0" } }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -1240,6 +1455,25 @@ } } }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -1328,6 +1562,16 @@ "integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ==", "dev": true }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, "detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -1339,6 +1583,17 @@ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, "dirty-chai": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/dirty-chai/-/dirty-chai-2.0.1.tgz", @@ -1462,6 +1717,12 @@ "esutils": "^2.0.2" } }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, "dotenv": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", @@ -1889,6 +2150,16 @@ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", "dev": true }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, "expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -2451,6 +2722,12 @@ "sshpk": "^1.7.0" } }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -3034,6 +3311,12 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, "lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -3087,6 +3370,31 @@ "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" }, + "lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", + "dev": true + }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, "log-symbols": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", @@ -3232,6 +3540,16 @@ } } }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + } + }, "mime-db": { "version": "1.45.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", @@ -3715,6 +4033,80 @@ } } }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "events": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + } + } + }, "node-pre-gyp": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.16.0.tgz", @@ -4106,6 +4498,12 @@ "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -4169,6 +4567,12 @@ "release-zalgo": "^1.0.0" } }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4178,6 +4582,19 @@ "callsites": "^3.0.0" } }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -4187,6 +4604,12 @@ "error-ex": "^1.2.0" } }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -4248,6 +4671,19 @@ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", "dev": true }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -4302,6 +4738,12 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -4343,6 +4785,20 @@ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -4391,6 +4847,12 @@ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", "dev": true }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -4400,6 +4862,16 @@ "safe-buffer": "^5.1.0" } }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -4455,6 +4927,12 @@ "picomatch": "^2.2.1" } }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", @@ -4571,6 +5049,22 @@ "signal-exit": "^3.0.2" } }, + "rewiremock": { + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/rewiremock/-/rewiremock-3.14.3.tgz", + "integrity": "sha512-6BaUGfp7NtxBjisxcGN73nNiA2fS2AwhEk/9DMUqxfv5v0aDM1wpOYpj5GSArqsJi07YCfLhkD8C74LAN7+FkQ==", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "compare-module-exports": "^2.1.0", + "lodash.some": "^4.6.0", + "lodash.template": "^4.4.0", + "node-libs-browser": "^2.1.0", + "path-parse": "^1.0.5", + "wipe-node-cache": "^2.1.2", + "wipe-webpack-cache": "^2.1.0" + } + }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -4651,6 +5145,12 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, "sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", @@ -4847,6 +5347,29 @@ "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, "stream-shift": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", @@ -5235,6 +5758,15 @@ "xtend": "~4.0.1" } }, + "timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -5244,6 +5776,12 @@ "os-tmpdir": "~1.0.2" } }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, "to-buffer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", @@ -5292,6 +5830,12 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -5363,6 +5907,23 @@ } } }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -5409,6 +5970,12 @@ "extsprintf": "^1.2.0" } }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, "websocket-stream": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/websocket-stream/-/websocket-stream-5.5.2.tgz", @@ -5469,6 +6036,21 @@ "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" }, + "wipe-node-cache": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/wipe-node-cache/-/wipe-node-cache-2.1.2.tgz", + "integrity": "sha512-m7NXa8qSxBGMtdQilOu53ctMaIBXy93FOP04EC1Uf4bpsE+r+adfLKwIMIvGbABsznaSNxK/ErD4xXDyY5og9w==", + "dev": true + }, + "wipe-webpack-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wipe-webpack-cache/-/wipe-webpack-cache-2.1.0.tgz", + "integrity": "sha512-OXzQMGpA7MnQQ8AG+uMl5mWR2ezy6fw1+DMHY+wzYP1qkF1jrek87psLBmhZEj+er4efO/GD4R8jXWFierobaA==", + "dev": true, + "requires": { + "wipe-node-cache": "^2.1.0" + } + }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", diff --git a/package.json b/package.json index 2946d45b8..aa718ac0a 100644 --- a/package.json +++ b/package.json @@ -30,10 +30,10 @@ "all": true }, "dependencies": { - "@dashevo/dapi-grpc": "~0.18.0-dev.1", + "@dashevo/dapi-grpc": "~0.18.0-dev.2", "@dashevo/dashcore-lib": "~0.19.19", "@dashevo/dashd-rpc": "^2.0.2", - "@dashevo/dpp": "~0.17.0", + "@dashevo/dpp": "~0.18.0-dev.1", "@dashevo/grpc-common": "~0.3.2", "ajv": "^6.4.0", "bs58": "^4.0.1", @@ -61,6 +61,7 @@ "mocha": "^8.1.3", "mocha-sinon": "^2.1.0", "nyc": "^14.0.0", + "rewiremock": "^3.14.3", "semver": "^7.3.2", "sinon": "^7.5.0", "sinon-chai": "^3.4.0", diff --git a/test/unit/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/test/unit/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js new file mode 100644 index 000000000..0df52794d --- /dev/null +++ b/test/unit/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -0,0 +1,203 @@ +const { + server: { + error: { + InvalidArgumentGrpcError, + }, + }, +} = require('@dashevo/grpc-common'); + +const { + v0: { + WaitForStateTransitionResultResponse, + StateTransitionBroadcastError, + Proof, + }, +} = require('@dashevo/dapi-grpc'); +const createDPPMock = require('@dashevo/dpp/lib/test/mocks/createDPPMock'); +const getIdentityCreateTransitionFixture = require('@dashevo/dpp/lib/test/fixtures/getIdentityCreateTransitionFixture'); + +const { EventEmitter } = require('events'); + +const cbor = require('cbor'); + +const GrpcCallMock = require('../../../../../lib/test/mock/GrpcCallMock'); +const waitForStateTransitionResultHandlerFactory = require('../../../../../lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory'); + +describe('WaitForStateTransitionResultResponse', () => { + let call; + let waitForStateTransitionResultHandler; + let driveStateRepositoryMock; + let tenderDashWsClientMock; + let dppMock; + let hash; + let proofFixture; + let wsMessagesFixture; + let stateTransitionFixture; + + beforeEach(function beforeEach() { + hash = Buffer.from('56458F2D8A8617EA322931B72C103CDD93820004E534295183A6EF215B93C76E', 'hex'); + + wsMessagesFixture = { + success: { + query: "tm.event = 'Tx'", + data: { + type: 'tendermint/event/Tx', + value: { + TxResult: { + height: '145', + tx: 'pWR0eXBlA2lhc3NldExvY2ujZXByb29momR0eXBlAGtpbnN0YW50TG9ja1ilAR272lhhsS11I/IKpeDUL1LePc0tXC/pGbpntZ8FDSBuAAAAAHvUKCicVybMXMiWz60mTKDN2H7HesE1zhNhy9w+zKjYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa291dHB1dEluZGV4AGt0cmFuc2FjdGlvbljfAwAAAAFft1DH/7MLyiiZTQ0v9kxxx5IO+g3OowKiGXGr/gzTXAEAAABrSDBFAiEA9zBXt5ZbkZ0miGrXtJPF9abrNUHafXIGRHXeritMEZECIBO0nrmvNv/jff27bDehIf3kD+WHQACWj5UvryJNQvyAASECG117xwKATG95Jur1SvBo/vAjYHx5AnYYOwsN3zL8Wyf/////AgEAAAAAAAAAFmoU7MiTGZFsxDcto0FsSOKqkcWmk/5OiAAAAAAAABl2qRTk6MFuEOFzT3vBIbU1Hio2UuiDzYisAAAAAGlzaWduYXR1cmVYQSANwCdg67KHh/OiSv9FW8qNFj+8OBvwnm3Ybg2Ju0tGNmkw3jAkdOgHLqAkmHCtiSvqZ7IhGDXhU5YtHCk6PIOIamlkZW50aXR5SWRYIJmUCrEaSl7bW6UkE3rBhlQjTBhJ4v1m0ORUXh434DTDb3Byb3RvY29sVmVyc2lvbgA=', + result: {}, + }, + }, + }, + events: { + 'tx.hash': [ + '56458F2D8A8617EA322931B72C103CDD93820004E534295183A6EF215B93C76E', + ], + 'tx.height': [ + '145', + ], + 'tm.event': [ + 'Tx', + ], + }, + }, + error: { + query: "tm.event = 'Tx'", + data: { + type: 'tendermint/event/Tx', + value: { + TxResult: { + height: '135', + tx: 'pWR0eXBlAmlhc3NldExvY2ujZXByb29momR0eXBlAGtpbnN0YW50TG9ja1ilAR272lhhsS11I/IKpeDUL1LePc0tXC/pGbpntZ8FDSBuAAAAAMfKlZZZ3oAHaxO0bEIYXCSEpwTuR/baTwASqjgFgDAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa291dHB1dEluZGV4AGt0cmFuc2FjdGlvbljfAwAAAAFl5SQeBBDkK7Us9JcOU+Gp1oi4NIl/01A+5GAKeHi2JwEAAABrSDBFAiEAq9XMPgtU9J0imH6YJ/RtbxwJsavuhIpECU5Lw9h0xpoCIEgkU1njDQCe06YqRyeVYc6wK8G7Y/M5X+XicfJKo5P6ASEDK3jwtdIToEQAgTPMXxpjon4geQaNbbRNT/Xz50UgdHH/////AgEAAAAAAAAAFmoU8HHK+aRqNJOWXjNlOO3iWwvV45CDkAAAAAAAABl2qRTFVGzrfaB6ZhmvE8h2unBNgcJIMIisAAAAAGlzaWduYXR1cmVYQR/OHDEQUcSxczLBvMP9Z0HmRaDoCS6tTyFLbWhn7bAfJTlPF9hIbh13260WSCiDceJjWaYB0JuOGsqu2ZB5F0dDanB1YmxpY0tleXOBo2JpZABkZGF0YVghA85GJWE321+kW0HIwl3M6wO9BIHDxY80HlQgc1wRalT5ZHR5cGUAb3Byb3RvY29sVmVyc2lvbgA=', + result: { + code: 2, + log: '{"error":{"message":"Invalid state transition","data":{"errors":[{"name":"IdentityPublicKeyAlreadyExistsError","message":"Identity public key already exists","publicKeyHash":{"type":"Buffer","data":[216,100,221,206,173,76,253,13,66,247,118,172,153,161,161,189,154,91,240,205]}}]}}}', + }, + }, + }, + }, + events: { + 'tm.event': [ + 'Tx', + ], + 'tx.hash': [ + '56458F2D8A8617EA322931B72C103CDD93820004E534295183A6EF215B93C76E', + ], + 'tx.height': [ + '135', + ], + }, + }, + }; + + proofFixture = { + rootTreeProof: Buffer.alloc(1, 1), + storeTreeProof: Buffer.alloc(1, 2), + }; + + call = new GrpcCallMock(this.sinon, { + getStateTransitionHash: this.sinon.stub().returns(hash), + getProve: this.sinon.stub().returns(false), + }); + + tenderDashWsClientMock = new EventEmitter(); + + stateTransitionFixture = getIdentityCreateTransitionFixture(); + + dppMock = createDPPMock(this.sinon); + dppMock.stateTransition.createFromBuffer.resolves(stateTransitionFixture); + + driveStateRepositoryMock = { + fetchProofs: this.sinon.stub().resolves({ identitiesProof: proofFixture }), + }; + + waitForStateTransitionResultHandler = waitForStateTransitionResultHandlerFactory( + driveStateRepositoryMock, + tenderDashWsClientMock, + dppMock, + ); + }); + + it('should wait for state transition result', (done) => { + waitForStateTransitionResultHandler(call).then((result) => { + expect(result).to.be.an.instanceOf(WaitForStateTransitionResultResponse); + expect(result.getProof()).to.be.undefined(); + expect(result.getError()).to.be.undefined(); + + done(); + }); + + process.nextTick(() => { + tenderDashWsClientMock.emit('tm.event = \'Tx\'', wsMessagesFixture.success); + }); + }); + + it('should wait for state transition and return proof', (done) => { + call.request.getProve.returns(true); + + waitForStateTransitionResultHandler(call).then((result) => { + expect(result).to.be.an.instanceOf(WaitForStateTransitionResultResponse); + expect(result.getError()).to.be.undefined(); + const proof = result.getProof(); + + expect(proof).to.be.an.instanceOf(Proof); + const rootTreeProof = proof.getRootTreeProof(); + const storeTreeProof = proof.getStoreTreeProof(); + + expect(rootTreeProof).to.deep.equal(proofFixture.rootTreeProof); + expect(storeTreeProof).to.deep.equal(proofFixture.storeTreeProof); + + expect(driveStateRepositoryMock.fetchProofs).to.be.calledOnceWithExactly({ + identityIds: stateTransitionFixture.getModifiedDataIds(), + }); + + done(); + }); + + process.nextTick(() => { + tenderDashWsClientMock.emit('tm.event = \'Tx\'', wsMessagesFixture.success); + }); + }); + + it('should wait for state transition and return error', (done) => { + waitForStateTransitionResultHandler(call).then((result) => { + expect(result).to.be.an.instanceOf(WaitForStateTransitionResultResponse); + expect(result.getProof()).to.be.undefined(); + + const error = result.getError(); + expect(error).to.be.an.instanceOf(StateTransitionBroadcastError); + + const errorData = error.getData(); + const errorCode = error.getCode(); + const errorMessage = error.getMessage(); + + const { error: abciError } = JSON.parse( + wsMessagesFixture.error.data.value.TxResult.result.log, + ); + + expect(errorCode).to.equal(wsMessagesFixture.error.data.value.TxResult.result.code); + expect(errorData).to.deep.equal(cbor.encode(abciError.data)); + expect(errorMessage).to.equal(abciError.message); + + done(); + }); + + process.nextTick(() => { + tenderDashWsClientMock.emit('tm.event = \'Tx\'', wsMessagesFixture.error); + }); + }); + + it('should throw an InvalidArgumentGrpcError if state transition hash is not specified', async () => { + call.request.getStateTransitionHash.returns(null); + + try { + await waitForStateTransitionResultHandler(call); + + expect.fail('should throw an error'); + } catch (e) { + expect(e).to.be.instanceOf(InvalidArgumentGrpcError); + expect(e.getMessage()).to.equal('state transition hash is not specified'); + } + }); +}); From 807159722b847da66bb40112c08bf3f30ee08a64 Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Thu, 14 Jan 2021 19:48:40 +0300 Subject: [PATCH 04/36] bugfix --- .../platform/platformHandlersFactory.js | 12 +++++----- package-lock.json | 24 +++++++++---------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/lib/grpcServer/handlers/platform/platformHandlersFactory.js b/lib/grpcServer/handlers/platform/platformHandlersFactory.js index cd4399924..b2642fbfa 100644 --- a/lib/grpcServer/handlers/platform/platformHandlersFactory.js +++ b/lib/grpcServer/handlers/platform/platformHandlersFactory.js @@ -21,7 +21,7 @@ const { GetDocumentsRequest, GetIdentitiesByPublicKeyHashesRequest, GetIdentityIdsByPublicKeyHashesRequest, - StateTransitionResultsRequest, + WaitForStateTransitionResultRequest, pbjs: { BroadcastStateTransitionRequest: PBJSBroadcastStateTransitionRequest, BroadcastStateTransitionResponse: PBJSBroadcastStateTransitionResponse, @@ -35,8 +35,8 @@ const { GetIdentitiesByPublicKeyHashesRequest: PBJSGetIdentitiesByPublicKeyHashesRequest, GetIdentityIdsByPublicKeyHashesResponse: PBJSGetIdentityIdsByPublicKeyHashesResponse, GetIdentityIdsByPublicKeyHashesRequest: PBJSGetIdentityIdsByPublicKeyHashesRequest, - StateTransitionResultsRequest: PBJSStateTransitionResultsRequest, - StateTransitionResultsResponse: PBJSStateTransitionResultsResponse, + WaitForStateTransitionResultRequest: PBJSWaitForStateTransitionResultRequest, + WaitForStateTransitionResultResponse: PBJSWaitForStateTransitionResultResponse, }, }, } = require('@dashevo/dapi-grpc'); @@ -190,11 +190,11 @@ function platformHandlersFactory( const wrappedWaitForStateTransitionResult = jsonToProtobufHandlerWrapper( jsonToProtobufFactory( - StateTransitionResultsRequest, - PBJSStateTransitionResultsRequest, + WaitForStateTransitionResultRequest, + PBJSWaitForStateTransitionResultRequest, ), protobufToJsonFactory( - PBJSStateTransitionResultsResponse, + PBJSWaitForStateTransitionResultResponse, ), wrapInErrorHandler(waitForStateTransitionResultHandler), ); diff --git a/package-lock.json b/package-lock.json index 0e7d15e46..81b5ead75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -210,9 +210,9 @@ }, "dependencies": { "@types/node": { - "version": "12.19.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.12.tgz", - "integrity": "sha512-UwfL2uIU9arX/+/PRcIkT08/iBadGN2z6ExOROA2Dh5mAuWTBj6iJbQX4nekiV5H8cTrEG569LeX+HRco9Cbxw==" + "version": "12.19.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.13.tgz", + "integrity": "sha512-qdixo2f0U7z6m0UJUugTJqVF94GNDkdgQhfBtMs8t5898JE7G/D2kJYw4rc1nzjIPLVAsDkY2MdABnLAP5lM1w==" }, "inherits": { "version": "2.0.1", @@ -307,9 +307,9 @@ } }, "@types/node": { - "version": "12.19.12", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.12.tgz", - "integrity": "sha512-UwfL2uIU9arX/+/PRcIkT08/iBadGN2z6ExOROA2Dh5mAuWTBj6iJbQX4nekiV5H8cTrEG569LeX+HRco9Cbxw==", + "version": "12.19.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.13.tgz", + "integrity": "sha512-qdixo2f0U7z6m0UJUugTJqVF94GNDkdgQhfBtMs8t5898JE7G/D2kJYw4rc1nzjIPLVAsDkY2MdABnLAP5lM1w==", "dev": true }, "inherits": { @@ -434,9 +434,9 @@ "integrity": "sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA=" }, "@sinonjs/commons": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", - "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz", + "integrity": "sha512-sruwd86RJHdsVf/AtBoijDmUqJp3B6hF/DGC23C+JaegnDHaZyewCjoVGTdg3J0uz3Zs7NnIT05OBOmML72lQw==", "dev": true, "requires": { "type-detect": "4.0.8" @@ -730,9 +730,9 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "aws-sdk": { - "version": "2.825.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.825.0.tgz", - "integrity": "sha512-b49nvaETm7uVRLf0FJ1CMmwCRVlLaxHtptVFuxX+2L4FR9VB0sLdgsxhtL3RVFbQlgVFNRV7fJUVK27mC++H+A==", + "version": "2.827.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.827.0.tgz", + "integrity": "sha512-71PWS1dqJ65/SeNgDQWEgbJ6oKCuB+Ypq30TM3EyzbAHaxl69WjQRK71oJ2bjhdIHfGQJtOV0G9wg4zpge4Erg==", "dev": true, "requires": { "buffer": "4.9.2", From 3fd9b7ed656d7af28be5eca479efa01db9b9a321 Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Fri, 15 Jan 2021 18:58:02 +0300 Subject: [PATCH 05/36] Bugfix --- .../platform/waitForStateTransitionResultHandlerFactory.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 5dfed5258..79f92cff7 100644 --- a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -73,11 +73,11 @@ function waitForStateTransitionResultHandlerFactory( } const query = 'tm.event = \'Tx\''; - const hash = Buffer.from(stateTransitionHash).toString('hex'); + const hashString = Buffer.from(stateTransitionHash).toString('hex').toUpperCase(); const data = await new Promise((resolve) => { tenderDashWsClient.on(query, (message) => { - if (message.events['tx.hash'].includes(hash.toUpperCase())) { + if (message.events['tx.hash'].includes(hashString)) { resolve(message); } }); From edca7eba747620e0500265943cad016c2ddaadd3 Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Fri, 15 Jan 2021 19:07:22 +0300 Subject: [PATCH 06/36] remove rewiremock --- package-lock.json | 582 ---------------------------------------------- package.json | 1 - 2 files changed, 583 deletions(-) diff --git a/package-lock.json b/package-lock.json index 81b5ead75..d4af5b527 100644 --- a/package-lock.json +++ b/package-lock.json @@ -657,45 +657,6 @@ "safer-buffer": "~2.1.0" } }, - "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" - } - }, - "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", - "dev": true, - "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", - "dev": true - }, - "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", - "dev": true, - "requires": { - "inherits": "2.0.1" - } - } - } - }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -796,16 +757,6 @@ "follow-redirects": "1.5.10" } }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -920,112 +871,6 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "dev": true, - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "browserify-cipher": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", - "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", - "dev": true, - "requires": { - "browserify-aes": "^1.0.4", - "browserify-des": "^1.0.0", - "evp_bytestokey": "^1.0.0" - } - }, - "browserify-des": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", - "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", - "dev": true, - "requires": { - "cipher-base": "^1.0.1", - "des.js": "^1.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "browserify-rsa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", - "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", - "dev": true, - "requires": { - "bn.js": "^5.0.0", - "randombytes": "^2.0.1" - }, - "dependencies": { - "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", - "dev": true - } - } - }, - "browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", - "dev": true, - "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", - "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "bn.js": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", - "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", - "dev": true - }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - } - } - }, - "browserify-zlib": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", - "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", - "dev": true, - "requires": { - "pako": "~1.0.5" - } - }, "bs58": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", @@ -1077,18 +922,6 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", - "dev": true - }, - "builtin-status-codes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", - "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", - "dev": true - }, "bytebuffer": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/bytebuffer/-/bytebuffer-5.0.1.tgz", @@ -1304,12 +1137,6 @@ "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", "dev": true }, - "compare-module-exports": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/compare-module-exports/-/compare-module-exports-2.1.0.tgz", - "integrity": "sha512-3Lc0sTIuX1jmY2K2RrXRJOND6KsRTX2D4v3+eu1PDptsuJZVK4LZc852eZa9I+avj0NrUKlTNgqvccNOH6mbGg==", - "dev": true - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1333,23 +1160,11 @@ "integrity": "sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA==", "dev": true }, - "console-browserify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", - "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", - "dev": true - }, "console-control-strings": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" }, - "constants-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", - "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", - "dev": true - }, "contains-path": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", @@ -1365,12 +1180,6 @@ "safe-buffer": "~5.1.1" } }, - "core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "dev": true - }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -1397,16 +1206,6 @@ } } }, - "create-ecdh": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", - "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "elliptic": "^6.5.3" - } - }, "create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", @@ -1420,20 +1219,6 @@ "sha.js": "^2.4.0" } }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "dev": true, - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -1455,25 +1240,6 @@ } } }, - "crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", - "dev": true, - "requires": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" - } - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -1562,16 +1328,6 @@ "integrity": "sha512-CYiCSgIF1p6EUByQPlGkKnP1M9g0ZV3qMIrqMqZqdwazygIA/YP2vrbcyl1h/WppKJTdl1F85cXIle+394iDAQ==", "dev": true }, - "des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" - } - }, "detect-libc": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", @@ -1583,17 +1339,6 @@ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, - "diffie-hellman": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", - "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "miller-rabin": "^4.0.0", - "randombytes": "^2.0.0" - } - }, "dirty-chai": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/dirty-chai/-/dirty-chai-2.0.1.tgz", @@ -1717,12 +1462,6 @@ "esutils": "^2.0.2" } }, - "domain-browser": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", - "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", - "dev": true - }, "dotenv": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", @@ -2150,16 +1889,6 @@ "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", "dev": true }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "dev": true, - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, "expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -2722,12 +2451,6 @@ "sshpk": "^1.7.0" } }, - "https-browserify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", - "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", - "dev": true - }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -3311,12 +3034,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, "lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -3370,31 +3087,6 @@ "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" }, - "lodash.some": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", - "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=", - "dev": true - }, - "lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0" - } - }, "log-symbols": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", @@ -3540,16 +3232,6 @@ } } }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - } - }, "mime-db": { "version": "1.45.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", @@ -4033,80 +3715,6 @@ } } }, - "node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", - "dev": true, - "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" - }, - "dependencies": { - "buffer": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", - "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, - "events": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", - "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", - "dev": true - }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, - "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", - "dev": true, - "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" - }, - "dependencies": { - "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", - "dev": true - } - } - } - } - }, "node-pre-gyp": { "version": "0.16.0", "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.16.0.tgz", @@ -4498,12 +4106,6 @@ "resolved": "https://registry.npmjs.org/optjs/-/optjs-3.2.2.tgz", "integrity": "sha1-aabOicRCpEQDFBrS+bNwvVu29O4=" }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -4567,12 +4169,6 @@ "release-zalgo": "^1.0.0" } }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true - }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4582,19 +4178,6 @@ "callsites": "^3.0.0" } }, - "parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", - "dev": true, - "requires": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" - } - }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -4604,12 +4187,6 @@ "error-ex": "^1.2.0" } }, - "path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", - "dev": true - }, "path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", @@ -4671,19 +4248,6 @@ "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", "dev": true }, - "pbkdf2": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", - "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", - "dev": true, - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", @@ -4738,12 +4302,6 @@ "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "dev": true }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", - "dev": true - }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -4785,20 +4343,6 @@ "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, "pump": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", @@ -4847,12 +4391,6 @@ "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", "dev": true }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -4862,16 +4400,6 @@ "safe-buffer": "^5.1.0" } }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" - } - }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -4927,12 +4455,6 @@ "picomatch": "^2.2.1" } }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, "regexpp": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", @@ -5049,22 +4571,6 @@ "signal-exit": "^3.0.2" } }, - "rewiremock": { - "version": "3.14.3", - "resolved": "https://registry.npmjs.org/rewiremock/-/rewiremock-3.14.3.tgz", - "integrity": "sha512-6BaUGfp7NtxBjisxcGN73nNiA2fS2AwhEk/9DMUqxfv5v0aDM1wpOYpj5GSArqsJi07YCfLhkD8C74LAN7+FkQ==", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "compare-module-exports": "^2.1.0", - "lodash.some": "^4.6.0", - "lodash.template": "^4.4.0", - "node-libs-browser": "^2.1.0", - "path-parse": "^1.0.5", - "wipe-node-cache": "^2.1.2", - "wipe-webpack-cache": "^2.1.0" - } - }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -5145,12 +4651,6 @@ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", - "dev": true - }, "sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", @@ -5347,29 +4847,6 @@ "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=" }, - "stream-browserify": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", - "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", - "dev": true, - "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" - } - }, - "stream-http": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", - "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", - "dev": true, - "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" - } - }, "stream-shift": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", @@ -5758,15 +5235,6 @@ "xtend": "~4.0.1" } }, - "timers-browserify": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", - "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", - "dev": true, - "requires": { - "setimmediate": "^1.0.4" - } - }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -5776,12 +5244,6 @@ "os-tmpdir": "~1.0.2" } }, - "to-arraybuffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", - "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", - "dev": true - }, "to-buffer": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", @@ -5830,12 +5292,6 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, - "tty-browserify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", - "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", - "dev": true - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -5907,23 +5363,6 @@ } } }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -5970,12 +5409,6 @@ "extsprintf": "^1.2.0" } }, - "vm-browserify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", - "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", - "dev": true - }, "websocket-stream": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/websocket-stream/-/websocket-stream-5.5.2.tgz", @@ -6036,21 +5469,6 @@ "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" }, - "wipe-node-cache": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/wipe-node-cache/-/wipe-node-cache-2.1.2.tgz", - "integrity": "sha512-m7NXa8qSxBGMtdQilOu53ctMaIBXy93FOP04EC1Uf4bpsE+r+adfLKwIMIvGbABsznaSNxK/ErD4xXDyY5og9w==", - "dev": true - }, - "wipe-webpack-cache": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wipe-webpack-cache/-/wipe-webpack-cache-2.1.0.tgz", - "integrity": "sha512-OXzQMGpA7MnQQ8AG+uMl5mWR2ezy6fw1+DMHY+wzYP1qkF1jrek87psLBmhZEj+er4efO/GD4R8jXWFierobaA==", - "dev": true, - "requires": { - "wipe-node-cache": "^2.1.0" - } - }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", diff --git a/package.json b/package.json index aa718ac0a..259f50da5 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,6 @@ "mocha": "^8.1.3", "mocha-sinon": "^2.1.0", "nyc": "^14.0.0", - "rewiremock": "^3.14.3", "semver": "^7.3.2", "sinon": "^7.5.0", "sinon-chai": "^3.4.0", From 70cdd37ba4a6a5c58ab907b9b48c60c177ecf56a Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Tue, 19 Jan 2021 12:22:46 +0300 Subject: [PATCH 07/36] fix test name --- package.json | 2 +- .../platform/waitForStateTransitionResultHandlerFactory.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 259f50da5..658063990 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "api": "node scripts/api.js", "tx-filter-stream": "node scripts/tx-filter-stream.js", "test": "(EXIT_CODE=0; npm run test:coverage || EXIT_CODE=$?; npm run test:functional || EXIT_CODE=$?; exit $EXIT_CODE)", - "test:coverage": "nyc --check-coverage --lines=51 --branches=27 --functions=50 mocha --recursive test/unit test/integration", + "test:coverage": "nyc --check-coverage --lines=51 --branches=27 --functions=48 mocha --recursive test/unit test/integration", "test:unit": "mocha --recursive test/unit", "test:integration": "mocha --recursive test/integration", "test:functional": "mocha --recursive test/functional", diff --git a/test/unit/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/test/unit/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 0df52794d..20dcfb2d9 100644 --- a/test/unit/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/test/unit/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -23,7 +23,7 @@ const cbor = require('cbor'); const GrpcCallMock = require('../../../../../lib/test/mock/GrpcCallMock'); const waitForStateTransitionResultHandlerFactory = require('../../../../../lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory'); -describe('WaitForStateTransitionResultResponse', () => { +describe('waitForStateTransitionResultHandlerFactory', () => { let call; let waitForStateTransitionResultHandler; let driveStateRepositoryMock; From f227a71b9a5c9f79398abaa265e7bbf3395675d3 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Tue, 19 Jan 2021 17:10:18 +0300 Subject: [PATCH 08/36] add waitForTransactionHash to the WS client --- lib/externalApis/tenderdash/WsClient.js | 48 +++++++++++++++++++ ...tForStateTransitionResultHandlerFactory.js | 16 +++---- scripts/api.js | 4 +- ...tForStateTransitionResultHandlerFactory.js | 34 +++++++++++++ 4 files changed, 90 insertions(+), 12 deletions(-) diff --git a/lib/externalApis/tenderdash/WsClient.js b/lib/externalApis/tenderdash/WsClient.js index 4cfa29229..4384efeac 100644 --- a/lib/externalApis/tenderdash/WsClient.js +++ b/lib/externalApis/tenderdash/WsClient.js @@ -97,6 +97,10 @@ class WsClient extends EventEmitter { this.ws.on('message', onMessageListener); } + static getTxHashTopic(hash) { + return `txhash:${hash}`; + } + /** * * @param {object} connectionOptions @@ -174,6 +178,50 @@ class WsClient extends EventEmitter { this.subscribedQueries.set(query, count + 1); } + createPromiseHandler(topic, resolve) { + const handler = (data) => { + this.off(topic, handler); + resolve(data); + }; + + return handler; + } + + subscribeToTransactions() { + const query = 'tm.event = \'Tx\''; + this.subscribe(query); + this.on(query, (message) => { + this.emitTransactionHash(message); + }); + } + + emitTransactionHash(message) { + const hashString = message && message.events ? message.events['tx.hash'] : null; + if (!hashString) { + return; + } + + this.emit(WsClient.getTxHashTopic(hashString), message); + } + + waitForTransactionHash(hashString, timeout = 60000) { + const topic = WsClient.getTxHashTopic(hashString); + let handler; + + return Promise.race([ + new Promise((resolve) => { + handler = this.createPromiseHandler(topic, resolve); + this.on(topic, handler); + }), + new Promise((resolve, reject) => { + setTimeout(() => { + this.off(topic, handler); + reject(new Error(`ST waiting period for transaction ${hashString} timed out`)); + }, timeout); + }), + ]); + } + /** * * @param {string} query diff --git a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 79f92cff7..0dd4b503c 100644 --- a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -68,20 +68,18 @@ function waitForStateTransitionResultHandlerFactory( const stateTransitionHash = request.getStateTransitionHash(); const prove = request.getProve(); - if (stateTransitionHash === null) { + if (!stateTransitionHash) { throw new InvalidArgumentGrpcError('state transition hash is not specified'); } - const query = 'tm.event = \'Tx\''; const hashString = Buffer.from(stateTransitionHash).toString('hex').toUpperCase(); + let data; - const data = await new Promise((resolve) => { - tenderDashWsClient.on(query, (message) => { - if (message.events['tx.hash'].includes(hashString)) { - resolve(message); - } - }); - }); + try { + data = tenderDashWsClient.waitForTransactionHash(hashString); + } catch (e) { + // TODO: handle timeout error + } const response = new WaitForStateTransitionResultResponse(); diff --git a/scripts/api.js b/scripts/api.js index 65d3312bb..c9d5114dc 100644 --- a/scripts/api.js +++ b/scripts/api.js @@ -74,9 +74,7 @@ async function main() { await tenderDashWsClient.connect(); - const wsQuery = 'tm.event = \'Tx\''; - - tenderDashWsClient.subscribe(wsQuery); + tenderDashWsClient.subscribeToTransactions(); log.info('Connection to WebSocket established.'); diff --git a/test/unit/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/test/unit/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 20dcfb2d9..84b8931ac 100644 --- a/test/unit/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/test/unit/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -9,6 +9,7 @@ const { const { v0: { WaitForStateTransitionResultResponse, + WaitForStateTransitionResultRequest, StateTransitionBroadcastError, Proof, }, @@ -33,6 +34,7 @@ describe('waitForStateTransitionResultHandlerFactory', () => { let proofFixture; let wsMessagesFixture; let stateTransitionFixture; + let request; beforeEach(function beforeEach() { hash = Buffer.from('56458F2D8A8617EA322931B72C103CDD93820004E534295183A6EF215B93C76E', 'hex'); @@ -200,4 +202,36 @@ describe('waitForStateTransitionResultHandlerFactory', () => { expect(e.getMessage()).to.equal('state transition hash is not specified'); } }); + + it('should throw an InvalidArgumentGrpcError if stateTransitionHash wasn\'t set', async () => { + request = new WaitForStateTransitionResultRequest(); + + call.request = WaitForStateTransitionResultRequest.deserializeBinary(request.serializeBinary()); + + try { + await waitForStateTransitionResultHandler(call); + + expect.fail('should throw an error'); + } catch (e) { + expect(e).to.be.instanceOf(InvalidArgumentGrpcError); + expect(e.getMessage()).to.equal('state transition hash is not specified'); + } + }); + + it('should throw after the timeout', async () => { + request = new WaitForStateTransitionResultRequest(); + const stHash = Buffer.from('abff', 'hex'); + request.setStateTransitionHash(stHash); + + call.request = WaitForStateTransitionResultRequest.deserializeBinary(request.serializeBinary()); + + try { + await waitForStateTransitionResultHandler(call); + + expect.fail('should throw an error'); + } catch (e) { + expect(e).to.be.instanceOf(InvalidArgumentGrpcError); + expect(e.getMessage()).to.equal('kek timeout'); + } + }); }); From 296d18bf69b1b9f4dc34c8716b748f58b41d80c9 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 16:23:31 +0300 Subject: [PATCH 09/36] add TransactionsClient.js to subscribe to tendermint transactions more efficiently --- .../TransactionWaitPeriodExceededError.js | 25 ++++ .../tenderdash/TransactionsClient.js | 83 ++++++++++++ lib/externalApis/tenderdash/WsClient.js | 44 ------- .../platform/platformHandlersFactory.js | 6 +- ...tForStateTransitionResultHandlerFactory.js | 6 +- scripts/api.js | 5 +- .../tenderdash/TransactionsClient.spec.js | 122 ++++++++++++++++++ 7 files changed, 239 insertions(+), 52 deletions(-) create mode 100644 lib/errors/TransactionWaitPeriodExceededError.js create mode 100644 lib/externalApis/tenderdash/TransactionsClient.js create mode 100644 test/integration/externalApis/tenderdash/TransactionsClient.spec.js diff --git a/lib/errors/TransactionWaitPeriodExceededError.js b/lib/errors/TransactionWaitPeriodExceededError.js new file mode 100644 index 000000000..4713e5995 --- /dev/null +++ b/lib/errors/TransactionWaitPeriodExceededError.js @@ -0,0 +1,25 @@ +class TransactionWaitPeriodExceededError extends Error { + /** + * @param {string} transactionHash + * @param originalStack + */ + constructor(transactionHash, originalStack) { + const message = `Transaction waiting period for ${transactionHash} exceeded`; + super(message); + if (originalStack) { + this.stack = originalStack; + } + + this.transactionHash = transactionHash; + } + + /** + * Returns transaction hash + * @return {string} + */ + getTransactionHash() { + return this.transactionHash; + } +} + +module.exports = TransactionWaitPeriodExceededError; diff --git a/lib/externalApis/tenderdash/TransactionsClient.js b/lib/externalApis/tenderdash/TransactionsClient.js new file mode 100644 index 000000000..641a8685f --- /dev/null +++ b/lib/externalApis/tenderdash/TransactionsClient.js @@ -0,0 +1,83 @@ +const EventEmitter = require('events'); +const TransactionWaitPeriodExceededError = require('../../errors/TransactionWaitPeriodExceededError'); + +const TX_QUERY = 'tm.event = \'Tx\''; + +class TransactionsClient extends EventEmitter { + /** + * @param {WsClient} tenderdashWsClient + */ + constructor(tenderdashWsClient) { + super(); + this.wsClient = tenderdashWsClient; + this.wsClient.subscribe(TX_QUERY); + this.wsClient.on(TX_QUERY, (message) => { + this.emitTransaction(message); + }); + } + + /** + * Returns an event name for a specific hash + * @param {string} transactionHashString + * @return {string} + */ + static getTransactionEventName(transactionHashString) { + return `transaction:${transactionHashString}`; + } + + /** + * Creates promisified event handler + * @param {string} eventName + * @param {function} resolve + * @return {function} + */ + createPromiseHandler(eventName, resolve) { + const handler = (data) => { + this.off(eventName, handler); + resolve(data); + }; + + return handler; + } + + /** + * Emits transaction:%tx_hash% if there's a transaction in the message + * @param {Object} message + */ + emitTransaction(message) { + const hashString = message && message.events ? message.events['tx.hash'] : null; + if (!hashString) { + return; + } + + this.emit(TransactionsClient.getTransactionEventName(hashString), message); + } + + /** + * Returns data for a transaction or rejects after a timeout + * @param {string} hashString - transaction hash to resolve data for + * @param {number} [timeout] - timeout to reject after + * @return {Promise} + */ + waitForTransaction(hashString, timeout = 60000) { + const topic = TransactionsClient.getTransactionEventName(hashString); + let handler; + + return Promise.race([ + new Promise((resolve) => { + handler = this.createPromiseHandler(topic, resolve); + this.on(topic, handler); + }), + new Promise((resolve, reject) => { + setTimeout(() => { + this.off(topic, handler); + reject(new TransactionWaitPeriodExceededError(hashString)); + }, timeout); + }), + ]); + } +} + +TransactionsClient.TX_QUERY = TX_QUERY; + +module.exports = TransactionsClient; diff --git a/lib/externalApis/tenderdash/WsClient.js b/lib/externalApis/tenderdash/WsClient.js index 4384efeac..b0389700b 100644 --- a/lib/externalApis/tenderdash/WsClient.js +++ b/lib/externalApis/tenderdash/WsClient.js @@ -178,50 +178,6 @@ class WsClient extends EventEmitter { this.subscribedQueries.set(query, count + 1); } - createPromiseHandler(topic, resolve) { - const handler = (data) => { - this.off(topic, handler); - resolve(data); - }; - - return handler; - } - - subscribeToTransactions() { - const query = 'tm.event = \'Tx\''; - this.subscribe(query); - this.on(query, (message) => { - this.emitTransactionHash(message); - }); - } - - emitTransactionHash(message) { - const hashString = message && message.events ? message.events['tx.hash'] : null; - if (!hashString) { - return; - } - - this.emit(WsClient.getTxHashTopic(hashString), message); - } - - waitForTransactionHash(hashString, timeout = 60000) { - const topic = WsClient.getTxHashTopic(hashString); - let handler; - - return Promise.race([ - new Promise((resolve) => { - handler = this.createPromiseHandler(topic, resolve); - this.on(topic, handler); - }), - new Promise((resolve, reject) => { - setTimeout(() => { - this.off(topic, handler); - reject(new Error(`ST waiting period for transaction ${hashString} timed out`)); - }, timeout); - }), - ]); - } - /** * * @param {string} query diff --git a/lib/grpcServer/handlers/platform/platformHandlersFactory.js b/lib/grpcServer/handlers/platform/platformHandlersFactory.js index b2642fbfa..16172c752 100644 --- a/lib/grpcServer/handlers/platform/platformHandlersFactory.js +++ b/lib/grpcServer/handlers/platform/platformHandlersFactory.js @@ -69,7 +69,7 @@ const waitForStateTransitionResultHandlerFactory = require( /** * @param {jaysonClient} rpcClient - * @param {WsClient} tenderDashWsClient + * @param {TransactionsClient} transactionsClient * @param {DriveStateRepository} driveStateRepository * @param {DashPlatformProtocol} dpp * @param {boolean} isProductionEnvironment @@ -77,7 +77,7 @@ const waitForStateTransitionResultHandlerFactory = require( */ function platformHandlersFactory( rpcClient, - tenderDashWsClient, + transactionsClient, driveStateRepository, dpp, isProductionEnvironment, @@ -184,7 +184,7 @@ function platformHandlersFactory( // waitForStateTransitionResult const waitForStateTransitionResultHandler = waitForStateTransitionResultHandlerFactory( driveStateRepository, - tenderDashWsClient, + transactionsClient, dpp, ); diff --git a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 0dd4b503c..7e899a006 100644 --- a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -18,13 +18,13 @@ const cbor = require('cbor'); /** * * @param {DriveStateRepository} driveStateRepository - * @param {WsClient} tenderDashWsClient + * @param {TransactionsClient} transactionsClient * @param {DashPlatformProtocol} dpp * @return {waitForStateTransitionResultHandler} */ function waitForStateTransitionResultHandlerFactory( driveStateRepository, - tenderDashWsClient, + transactionsClient, dpp, ) { /** @@ -76,7 +76,7 @@ function waitForStateTransitionResultHandlerFactory( let data; try { - data = tenderDashWsClient.waitForTransactionHash(hashString); + data = transactionsClient.waitForTransaction(hashString); } catch (e) { // TODO: handle timeout error } diff --git a/scripts/api.js b/scripts/api.js index c9d5114dc..e0bae051f 100644 --- a/scripts/api.js +++ b/scripts/api.js @@ -29,6 +29,7 @@ const rpcServer = require('../lib/rpcServer/server'); const DriveStateRepository = require('../lib/externalApis/drive/DriveStateRepository'); const insightAPI = require('../lib/externalApis/insight'); const dashCoreRpcClient = require('../lib/externalApis/dashcore/rpc'); +const TransactionsClient = require('../lib/externalApis/tenderdash/TransactionsClient'); const coreHandlersFactory = require( '../lib/grpcServer/handlers/core/coreHandlersFactory', @@ -74,7 +75,7 @@ async function main() { await tenderDashWsClient.connect(); - tenderDashWsClient.subscribeToTransactions(); + const transactionsClient = new TransactionsClient(tenderDashWsClient); log.info('Connection to WebSocket established.'); @@ -99,7 +100,7 @@ async function main() { ); const platformHandlers = platformHandlersFactory( rpcClient, - tenderDashWsClient, + transactionsClient, driveStateRepository, dpp, isProductionEnvironment, diff --git a/test/integration/externalApis/tenderdash/TransactionsClient.spec.js b/test/integration/externalApis/tenderdash/TransactionsClient.spec.js new file mode 100644 index 000000000..c7506983d --- /dev/null +++ b/test/integration/externalApis/tenderdash/TransactionsClient.spec.js @@ -0,0 +1,122 @@ +const EventEmitter = require('events'); +const TransactionsClient = require('../../../../lib/externalApis/tenderdash/TransactionsClient'); +const TransactionWaitPeriodExceededError = require('../../../../lib/errors/TransactionWaitPeriodExceededError'); + +describe('TransactionClient', () => { + let sinon; + let wsClientMock; + let transactionsClient; + let txDataMock; + + beforeEach(function beforeEach() { + ({ sinon } = this); + wsClientMock = new EventEmitter(); + wsClientMock.subscribe = sinon.stub(); + transactionsClient = new TransactionsClient(wsClientMock); + + txDataMock = { + events: { + 'tx.hash': '123', + }, + }; + + sinon.spy(transactionsClient, 'on'); + sinon.spy(transactionsClient, 'off'); + sinon.spy(transactionsClient, 'emit'); + }); + + describe('constructor', () => { + it('should subscribe to transaction events from WS client', () => { + expect(wsClientMock.subscribe).to.be.calledOnce(); + expect(wsClientMock.subscribe).to.be.calledWithExactly(TransactionsClient.TX_QUERY); + }); + }); + + describe('.getTransactionEventName', () => { + it('should return transaction event name', () => { + const eventName = TransactionsClient.getTransactionEventName('123'); + expect(eventName).to.be.equal('transaction:123'); + }); + }); + + describe('#waitForTransaction', () => { + it('should remove listener after transaction resolves', async () => { + const eventName = TransactionsClient.getTransactionEventName('123'); + const txPromise = transactionsClient.waitForTransaction('123', 2000); + + expect(transactionsClient.listenerCount(eventName)).to.be.equal(1); + + setTimeout(() => { + wsClientMock.emit(TransactionsClient.TX_QUERY, Object.assign({}, txDataMock)); + }, 10); + + const txData = await txPromise; + + // Check that event listener was properly attached + expect(transactionsClient.on).to.be.calledOnce(); + // Check that transaction data was emitted + expect(transactionsClient.emit).to.be.calledOnce(); + // Check that the event listener was properly removed + expect(transactionsClient.off).to.be.calledOnce(); + expect(transactionsClient.listenerCount(eventName)).to.be.equal(0); + + expect(txData).to.be.deep.equal(txDataMock); + }); + + it('should not emit transaction event if event data has no transaction', async () => { + const eventName = TransactionsClient.getTransactionEventName('123'); + txDataMock = {}; + + let error; + try { + const txPromise = transactionsClient.waitForTransaction('123', 1000); + + expect(transactionsClient.listenerCount(eventName)).to.be.equal(1); + + setTimeout(() => { + wsClientMock.emit(TransactionsClient.TX_QUERY, Object.assign({}, txDataMock)); + }, 10); + + await txPromise; + } catch (e) { + error = e; + } + + // Check that the error is correct + expect(error).to.be.instanceOf(TransactionWaitPeriodExceededError); + expect(error.message).to.be.equal('Transaction waiting period for 123 exceeded'); + expect(error.getTransactionHash()).to.be.equal('123'); + + // Check that event listener was properly attached + expect(transactionsClient.on).to.be.calledOnce(); + // Check that event listener was properly removed + expect(transactionsClient.off).to.be.calledOnce(); + expect(transactionsClient.listenerCount(eventName)).to.be.equal(0); + // Check that no transaction data was emitted + expect(transactionsClient.emit).to.not.be.called(); + }); + + it('should remove listener after timeout has been exceeded', async () => { + const eventName = TransactionsClient.getTransactionEventName('123'); + let error; + try { + await transactionsClient.waitForTransaction('123', 100); + } catch (e) { + error = e; + } + + // Check that the error is correct + expect(error).to.be.instanceOf(TransactionWaitPeriodExceededError); + expect(error.message).to.be.equal('Transaction waiting period for 123 exceeded'); + expect(error.getTransactionHash()).to.be.equal('123'); + + // Check that event listener was properly attached + expect(transactionsClient.on).to.be.calledOnce(); + // Check that event listener was properly removed + expect(transactionsClient.off).to.be.calledOnce(); + expect(transactionsClient.listenerCount(eventName)).to.be.equal(0); + // Check that no transaction data was emitted + expect(transactionsClient.emit).to.not.be.called(); + }); + }); +}); From c4f3ed1c39fd9af55d42afbf52eada1218379236 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 16:47:38 +0300 Subject: [PATCH 10/36] move init logic from constructor to `start` method in TransactionsClient.js --- lib/externalApis/tenderdash/TransactionsClient.js | 11 +++++++---- scripts/api.js | 1 + .../tenderdash/TransactionsClient.spec.js | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/externalApis/tenderdash/TransactionsClient.js b/lib/externalApis/tenderdash/TransactionsClient.js index 641a8685f..f02ca8da7 100644 --- a/lib/externalApis/tenderdash/TransactionsClient.js +++ b/lib/externalApis/tenderdash/TransactionsClient.js @@ -10,10 +10,6 @@ class TransactionsClient extends EventEmitter { constructor(tenderdashWsClient) { super(); this.wsClient = tenderdashWsClient; - this.wsClient.subscribe(TX_QUERY); - this.wsClient.on(TX_QUERY, (message) => { - this.emitTransaction(message); - }); } /** @@ -25,6 +21,13 @@ class TransactionsClient extends EventEmitter { return `transaction:${transactionHashString}`; } + start() { + this.wsClient.subscribe(TX_QUERY); + this.wsClient.on(TX_QUERY, (message) => { + this.emitTransaction(message); + }); + } + /** * Creates promisified event handler * @param {string} eventName diff --git a/scripts/api.js b/scripts/api.js index e0bae051f..0e0e23fc5 100644 --- a/scripts/api.js +++ b/scripts/api.js @@ -76,6 +76,7 @@ async function main() { await tenderDashWsClient.connect(); const transactionsClient = new TransactionsClient(tenderDashWsClient); + transactionsClient.start(); log.info('Connection to WebSocket established.'); diff --git a/test/integration/externalApis/tenderdash/TransactionsClient.spec.js b/test/integration/externalApis/tenderdash/TransactionsClient.spec.js index c7506983d..37e44453e 100644 --- a/test/integration/externalApis/tenderdash/TransactionsClient.spec.js +++ b/test/integration/externalApis/tenderdash/TransactionsClient.spec.js @@ -13,6 +13,7 @@ describe('TransactionClient', () => { wsClientMock = new EventEmitter(); wsClientMock.subscribe = sinon.stub(); transactionsClient = new TransactionsClient(wsClientMock); + transactionsClient.start(); txDataMock = { events: { From 735d184f4395c4a8b238c48fe3e35743ef6a5813 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 16:57:10 +0300 Subject: [PATCH 11/36] marked private methods as private in jsdoc --- lib/externalApis/tenderdash/TransactionsClient.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/externalApis/tenderdash/TransactionsClient.js b/lib/externalApis/tenderdash/TransactionsClient.js index f02ca8da7..3c860d4c4 100644 --- a/lib/externalApis/tenderdash/TransactionsClient.js +++ b/lib/externalApis/tenderdash/TransactionsClient.js @@ -14,6 +14,7 @@ class TransactionsClient extends EventEmitter { /** * Returns an event name for a specific hash + * @private * @param {string} transactionHashString * @return {string} */ @@ -30,6 +31,7 @@ class TransactionsClient extends EventEmitter { /** * Creates promisified event handler + * @private * @param {string} eventName * @param {function} resolve * @return {function} @@ -45,6 +47,7 @@ class TransactionsClient extends EventEmitter { /** * Emits transaction:%tx_hash% if there's a transaction in the message + * @private * @param {Object} message */ emitTransaction(message) { From fbd27ce5fa8dbd33fb88390b48eeb3044864c585 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 17:00:10 +0300 Subject: [PATCH 12/36] add jsdoc for TransactionsClient.js start method --- lib/externalApis/tenderdash/TransactionsClient.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/externalApis/tenderdash/TransactionsClient.js b/lib/externalApis/tenderdash/TransactionsClient.js index 3c860d4c4..dc5583ea2 100644 --- a/lib/externalApis/tenderdash/TransactionsClient.js +++ b/lib/externalApis/tenderdash/TransactionsClient.js @@ -22,6 +22,9 @@ class TransactionsClient extends EventEmitter { return `transaction:${transactionHashString}`; } + /** + * Subscribe to transactions and attach transaction event handler + */ start() { this.wsClient.subscribe(TX_QUERY); this.wsClient.on(TX_QUERY, (message) => { From 44044e114dc71a49246a682f7c149353a2e8c961 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 17:01:25 +0300 Subject: [PATCH 13/36] shortened start method --- lib/externalApis/tenderdash/TransactionsClient.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/externalApis/tenderdash/TransactionsClient.js b/lib/externalApis/tenderdash/TransactionsClient.js index dc5583ea2..d85e6f550 100644 --- a/lib/externalApis/tenderdash/TransactionsClient.js +++ b/lib/externalApis/tenderdash/TransactionsClient.js @@ -27,9 +27,7 @@ class TransactionsClient extends EventEmitter { */ start() { this.wsClient.subscribe(TX_QUERY); - this.wsClient.on(TX_QUERY, (message) => { - this.emitTransaction(message); - }); + this.wsClient.on(TX_QUERY, this.emitTransaction.bind(this)); } /** From ac425528a96fc9bc4501a6a7c40f934eb7ac02ed Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 17:04:16 +0300 Subject: [PATCH 14/36] remove unused method from WsClient.js --- lib/externalApis/tenderdash/WsClient.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/externalApis/tenderdash/WsClient.js b/lib/externalApis/tenderdash/WsClient.js index b0389700b..4cfa29229 100644 --- a/lib/externalApis/tenderdash/WsClient.js +++ b/lib/externalApis/tenderdash/WsClient.js @@ -97,10 +97,6 @@ class WsClient extends EventEmitter { this.ws.on('message', onMessageListener); } - static getTxHashTopic(hash) { - return `txhash:${hash}`; - } - /** * * @param {object} connectionOptions From ff04df5c9f72d5c078c8d11b0fbc95ad1467c2a5 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 17:39:18 +0300 Subject: [PATCH 15/36] add handling of the st timeout in waitForStateTransitionResultHandlerFactory.js --- .../waitForStateTransitionResultHandlerFactory.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 7e899a006..d87a1f381 100644 --- a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -2,6 +2,7 @@ const { server: { error: { InvalidArgumentGrpcError, + DeadlineExceededGrpcError, }, }, } = require('@dashevo/grpc-common'); @@ -14,6 +15,7 @@ const { } = require('@dashevo/dapi-grpc'); const cbor = require('cbor'); +const TransactionWaitPeriodExceededError = require('../../../errors/TransactionWaitPeriodExceededError'); /** * @@ -78,7 +80,16 @@ function waitForStateTransitionResultHandlerFactory( try { data = transactionsClient.waitForTransaction(hashString); } catch (e) { - // TODO: handle timeout error + if (e instanceof TransactionWaitPeriodExceededError) { + throw new DeadlineExceededGrpcError( + `Waiting period for state transition ${e.getTransactionHash()} exceeded`, + { + stateTransitionHash: e.getTransactionHash(), + }, + ); + } else { + throw e; + } } const response = new WaitForStateTransitionResultResponse(); From 2638966e9ad1e65af530ca87181f6f6bdfaa999d Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 19:01:54 +0300 Subject: [PATCH 16/36] fixed old waitForStateTransitionResultHandlerFactory tests --- .../tenderdash/TransactionsClient.js | 3 ++- ...aitForStateTransitionResultHandlerFactory.js | 4 +++- ...aitForStateTransitionResultHandlerFactory.js | 17 ++++++++++++++--- 3 files changed, 19 insertions(+), 5 deletions(-) rename test/{unit => integration}/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js (93%) diff --git a/lib/externalApis/tenderdash/TransactionsClient.js b/lib/externalApis/tenderdash/TransactionsClient.js index d85e6f550..114f05d7d 100644 --- a/lib/externalApis/tenderdash/TransactionsClient.js +++ b/lib/externalApis/tenderdash/TransactionsClient.js @@ -52,7 +52,8 @@ class TransactionsClient extends EventEmitter { * @param {Object} message */ emitTransaction(message) { - const hashString = message && message.events ? message.events['tx.hash'] : null; + const hashArray = message && message.events ? message.events['tx.hash'] : null; + const hashString = Array.isArray(hashArray) && hashArray[0]; if (!hashString) { return; } diff --git a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index d87a1f381..b93de2a4f 100644 --- a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -22,12 +22,14 @@ const TransactionWaitPeriodExceededError = require('../../../errors/TransactionW * @param {DriveStateRepository} driveStateRepository * @param {TransactionsClient} transactionsClient * @param {DashPlatformProtocol} dpp + * @param {number} stateTransitionWaitTimeout * @return {waitForStateTransitionResultHandler} */ function waitForStateTransitionResultHandlerFactory( driveStateRepository, transactionsClient, dpp, + stateTransitionWaitTimeout = 60000, ) { /** * @@ -78,7 +80,7 @@ function waitForStateTransitionResultHandlerFactory( let data; try { - data = transactionsClient.waitForTransaction(hashString); + data = await transactionsClient.waitForTransaction(hashString, stateTransitionWaitTimeout); } catch (e) { if (e instanceof TransactionWaitPeriodExceededError) { throw new DeadlineExceededGrpcError( diff --git a/test/unit/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js similarity index 93% rename from test/unit/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js rename to test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 84b8931ac..cf7a9a1f1 100644 --- a/test/unit/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -2,6 +2,7 @@ const { server: { error: { InvalidArgumentGrpcError, + DeadlineExceededGrpcError, }, }, } = require('@dashevo/grpc-common'); @@ -20,6 +21,7 @@ const getIdentityCreateTransitionFixture = require('@dashevo/dpp/lib/test/fixtur const { EventEmitter } = require('events'); const cbor = require('cbor'); +const TransactionClient = require('../../../../../lib/externalApis/tenderdash/TransactionsClient'); const GrpcCallMock = require('../../../../../lib/test/mock/GrpcCallMock'); const waitForStateTransitionResultHandlerFactory = require('../../../../../lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory'); @@ -29,6 +31,7 @@ describe('waitForStateTransitionResultHandlerFactory', () => { let waitForStateTransitionResultHandler; let driveStateRepositoryMock; let tenderDashWsClientMock; + let transactionClient; let dppMock; let hash; let proofFixture; @@ -104,6 +107,7 @@ describe('waitForStateTransitionResultHandlerFactory', () => { }); tenderDashWsClientMock = new EventEmitter(); + tenderDashWsClientMock.subscribe = this.sinon.stub(); stateTransitionFixture = getIdentityCreateTransitionFixture(); @@ -114,10 +118,14 @@ describe('waitForStateTransitionResultHandlerFactory', () => { fetchProofs: this.sinon.stub().resolves({ identitiesProof: proofFixture }), }; + transactionClient = new TransactionClient(tenderDashWsClientMock); + transactionClient.start(); + waitForStateTransitionResultHandler = waitForStateTransitionResultHandlerFactory( driveStateRepositoryMock, - tenderDashWsClientMock, + transactionClient, dppMock, + 1000, ); }); @@ -230,8 +238,11 @@ describe('waitForStateTransitionResultHandlerFactory', () => { expect.fail('should throw an error'); } catch (e) { - expect(e).to.be.instanceOf(InvalidArgumentGrpcError); - expect(e.getMessage()).to.equal('kek timeout'); + expect(e).to.be.instanceOf(DeadlineExceededGrpcError); + expect(e.getMessage()).to.equal('Waiting period for state transition ABFF exceeded'); + expect(e.getRawMetadata()).to.be.deep.equal({ + stateTransitionHash: 'ABFF', + }); } }); }); From 08f8373c4383a62da3c59da7b5f698ff3fa634cb Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 19:06:58 +0300 Subject: [PATCH 17/36] fix TransactionsClient.spec.js --- .../externalApis/tenderdash/TransactionsClient.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/externalApis/tenderdash/TransactionsClient.spec.js b/test/integration/externalApis/tenderdash/TransactionsClient.spec.js index 37e44453e..c66439800 100644 --- a/test/integration/externalApis/tenderdash/TransactionsClient.spec.js +++ b/test/integration/externalApis/tenderdash/TransactionsClient.spec.js @@ -17,7 +17,7 @@ describe('TransactionClient', () => { txDataMock = { events: { - 'tx.hash': '123', + 'tx.hash': ['123'], }, }; @@ -26,7 +26,7 @@ describe('TransactionClient', () => { sinon.spy(transactionsClient, 'emit'); }); - describe('constructor', () => { + describe('#start', () => { it('should subscribe to transaction events from WS client', () => { expect(wsClientMock.subscribe).to.be.calledOnce(); expect(wsClientMock.subscribe).to.be.calledWithExactly(TransactionsClient.TX_QUERY); From 0199bf1b1e2f6624259424486d7e2989b499f25f Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 19:29:11 +0300 Subject: [PATCH 18/36] remove unnecessary condition --- .../platform/waitForStateTransitionResultHandlerFactory.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index b93de2a4f..32590ddd1 100644 --- a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -89,9 +89,8 @@ function waitForStateTransitionResultHandlerFactory( stateTransitionHash: e.getTransactionHash(), }, ); - } else { - throw e; } + throw e; } const response = new WaitForStateTransitionResultResponse(); From a3bcd591af195c88ee5c87f49897eba047ca757b Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 19:32:07 +0300 Subject: [PATCH 19/36] Update scripts/api.js Co-authored-by: Ivan Shumkov --- scripts/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/api.js b/scripts/api.js index 0e0e23fc5..c558c9b04 100644 --- a/scripts/api.js +++ b/scripts/api.js @@ -68,7 +68,7 @@ async function main() { log.info(`Connecting to tenderdash WebSocket on ${config.tendermintCore.host}:${config.tendermintCore.port}`); tenderDashWsClient.on('error', (e) => { - log.error('WebSocket error', e); + log.error('Tenderdash connection error', e); process.exit(1); }); From 6879af72a565ea51c882e822515a5d3be7e2c679 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 19:32:20 +0300 Subject: [PATCH 20/36] Update scripts/api.js Co-authored-by: Ivan Shumkov --- scripts/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/api.js b/scripts/api.js index c558c9b04..91bb052be 100644 --- a/scripts/api.js +++ b/scripts/api.js @@ -78,7 +78,7 @@ async function main() { const transactionsClient = new TransactionsClient(tenderDashWsClient); transactionsClient.start(); - log.info('Connection to WebSocket established.'); + log.info('Connection to Tenderdash established.'); // Start JSON RPC server log.info('Starting JSON RPC server'); From 08a59eec0261ecd34803bbaa7dad1bfd72c238af Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 19:34:04 +0300 Subject: [PATCH 21/36] Update scripts/api.js Co-authored-by: Ivan Shumkov --- scripts/api.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/api.js b/scripts/api.js index 91bb052be..4b6b4a7cb 100644 --- a/scripts/api.js +++ b/scripts/api.js @@ -65,7 +65,7 @@ async function main() { port: config.tendermintCore.port, }); - log.info(`Connecting to tenderdash WebSocket on ${config.tendermintCore.host}:${config.tendermintCore.port}`); + log.info(`Connecting to Tenderdash on ${config.tendermintCore.host}:${config.tendermintCore.port}`); tenderDashWsClient.on('error', (e) => { log.error('Tenderdash connection error', e); From 9544a496d07d2704f020569d18d6dcb43e108e7b Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 19:36:07 +0300 Subject: [PATCH 22/36] Update test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js Co-authored-by: Ivan Shumkov --- .../platform/waitForStateTransitionResultHandlerFactory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index cf7a9a1f1..90b401ce5 100644 --- a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -226,7 +226,7 @@ describe('waitForStateTransitionResultHandlerFactory', () => { } }); - it('should throw after the timeout', async () => { + it('should throw DeadlineExceededGrpcError after the timeout', async () => { request = new WaitForStateTransitionResultRequest(); const stHash = Buffer.from('abff', 'hex'); request.setStateTransitionHash(stHash); From 6d8f0bc392a50f8190ad546c276a8e08ebe68557 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 19:36:35 +0300 Subject: [PATCH 23/36] Update test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js Co-authored-by: Ivan Shumkov --- .../platform/waitForStateTransitionResultHandlerFactory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 90b401ce5..5d74eca6a 100644 --- a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -170,7 +170,7 @@ describe('waitForStateTransitionResultHandlerFactory', () => { }); }); - it('should wait for state transition and return error', (done) => { + it('should wait for state transition and return result with error', (done) => { waitForStateTransitionResultHandler(call).then((result) => { expect(result).to.be.an.instanceOf(WaitForStateTransitionResultResponse); expect(result.getProof()).to.be.undefined(); From 2ded36aeefabf794ebfc71bfb97ec69d5f989751 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 19:43:26 +0300 Subject: [PATCH 24/36] Update test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js Co-authored-by: Ivan Shumkov --- .../platform/waitForStateTransitionResultHandlerFactory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 5d74eca6a..a8be60575 100644 --- a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -143,7 +143,7 @@ describe('waitForStateTransitionResultHandlerFactory', () => { }); }); - it('should wait for state transition and return proof', (done) => { + it('should wait for state transition and return result with proof', (done) => { call.request.getProve.returns(true); waitForStateTransitionResultHandler(call).then((result) => { From 32e0ae945f37e8de9a7a3a8bad91b80454e513d6 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 19:45:38 +0300 Subject: [PATCH 25/36] Update test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js Co-authored-by: Ivan Shumkov --- .../platform/waitForStateTransitionResultHandlerFactory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index a8be60575..13166c71f 100644 --- a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -129,7 +129,7 @@ describe('waitForStateTransitionResultHandlerFactory', () => { ); }); - it('should wait for state transition result', (done) => { + it('should wait for state transition empty result', (done) => { waitForStateTransitionResultHandler(call).then((result) => { expect(result).to.be.an.instanceOf(WaitForStateTransitionResultResponse); expect(result.getProof()).to.be.undefined(); From 907548f0f67ac9e281178efd8433f789bda64c88 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Wed, 20 Jan 2021 19:47:07 +0300 Subject: [PATCH 26/36] remove duplicated test --- .../waitForStateTransitionResultHandlerFactory.js | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index cf7a9a1f1..aabf83499 100644 --- a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -198,19 +198,6 @@ describe('waitForStateTransitionResultHandlerFactory', () => { }); }); - it('should throw an InvalidArgumentGrpcError if state transition hash is not specified', async () => { - call.request.getStateTransitionHash.returns(null); - - try { - await waitForStateTransitionResultHandler(call); - - expect.fail('should throw an error'); - } catch (e) { - expect(e).to.be.instanceOf(InvalidArgumentGrpcError); - expect(e.getMessage()).to.equal('state transition hash is not specified'); - } - }); - it('should throw an InvalidArgumentGrpcError if stateTransitionHash wasn\'t set', async () => { request = new WaitForStateTransitionResultRequest(); From f89c546ea53805623731296f7afd0a1a3b39dd05 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Fri, 22 Jan 2021 13:18:12 +0300 Subject: [PATCH 27/36] add dpp/DriveStateRepository.js and renamed old class with this name into DriveClient.js; Add waiting interval to waitForStateTransitionResultHandlerFactory.js --- lib/dpp/DriveStateRepository.js | 29 +++++++++++++++++++ ...DriveStateRepository.js => DriveClient.js} | 4 +-- .../tenderdash/TransactionsClient.js | 25 ++++++++++++++++ .../platform/getDataContractHandlerFactory.js | 6 ++-- .../platform/getDocumentsHandlerFactory.js | 6 ++-- ...entitiesByPublicKeyHashesHandlerFactory.js | 6 ++-- .../platform/getIdentityHandlerFactory.js | 6 ++-- ...ntityIdsByPublicKeyHashesHandlerFactory.js | 6 ++-- .../platform/platformHandlersFactory.js | 16 +++++----- ...tForStateTransitionResultHandlerFactory.js | 16 +++++----- scripts/api.js | 13 ++++++--- test/mocks/driveFixture.js | 13 --------- ...DriveStateRepository.js => DriveClient.js} | 22 +++++++------- 13 files changed, 108 insertions(+), 60 deletions(-) create mode 100644 lib/dpp/DriveStateRepository.js rename lib/externalApis/drive/{DriveStateRepository.js => DriveClient.js} (98%) delete mode 100644 test/mocks/driveFixture.js rename test/unit/externalApis/drive/{DriveStateRepository.js => DriveClient.js} (89%) diff --git a/lib/dpp/DriveStateRepository.js b/lib/dpp/DriveStateRepository.js new file mode 100644 index 000000000..5c5ce530e --- /dev/null +++ b/lib/dpp/DriveStateRepository.js @@ -0,0 +1,29 @@ +const DataContract = require('@dashevo/dpp/lib/dataContract/DataContract'); +const { decode } = require('@dashevo/dpp/lib/util/serializer'); + +/** + * @implements StateRepository + */ +class DriveStateRepository { + /** + * @param {DriveClient} driveClient + */ + constructor(driveClient) { + this.driveClient = driveClient; + } + + /** + * Fetches data contract from Drive + * @param {Identifier} contractIdentifier + * @return {Promise} + */ + async fetchDataContract(contractIdentifier) { + const driveResponse = await this.driveClient.fetchDataContract( + contractIdentifier, false, + ); + + return new DataContract(decode(driveResponse.data)); + } +} + +module.exports = DriveStateRepository; diff --git a/lib/externalApis/drive/DriveStateRepository.js b/lib/externalApis/drive/DriveClient.js similarity index 98% rename from lib/externalApis/drive/DriveStateRepository.js rename to lib/externalApis/drive/DriveClient.js index 225fa99ce..a28893211 100644 --- a/lib/externalApis/drive/DriveStateRepository.js +++ b/lib/externalApis/drive/DriveClient.js @@ -5,7 +5,7 @@ const cbor = require('cbor'); const RPCError = require('../../rpcServer/RPCError'); const AbciResponseError = require('../../errors/AbciResponseError'); -class DriveStateRepository { +class DriveClient { /** * @param options * @param {string} options.host @@ -181,4 +181,4 @@ class DriveStateRepository { } } -module.exports = DriveStateRepository; +module.exports = DriveClient; diff --git a/lib/externalApis/tenderdash/TransactionsClient.js b/lib/externalApis/tenderdash/TransactionsClient.js index 114f05d7d..58b672fa5 100644 --- a/lib/externalApis/tenderdash/TransactionsClient.js +++ b/lib/externalApis/tenderdash/TransactionsClient.js @@ -2,6 +2,10 @@ const EventEmitter = require('events'); const TransactionWaitPeriodExceededError = require('../../errors/TransactionWaitPeriodExceededError'); const TX_QUERY = 'tm.event = \'Tx\''; +const BLOCK_QUERY = 'tm.event = \'NewBlock\''; +const events = { + NEW_BLOCK: 'block', +}; class TransactionsClient extends EventEmitter { /** @@ -28,6 +32,11 @@ class TransactionsClient extends EventEmitter { start() { this.wsClient.subscribe(TX_QUERY); this.wsClient.on(TX_QUERY, this.emitTransaction.bind(this)); + + this.wsClient.subscribe(BLOCK_QUERY); + this.wsClient.on(BLOCK_QUERY, (message) => { + this.emit(events.NEW_BLOCK, message); + }); } /** @@ -84,8 +93,24 @@ class TransactionsClient extends EventEmitter { }), ]); } + + waitForNextBlock() { + return new Promise((resolve) => { + this.once(events.NEW_BLOCK, resolve); + }); + } + + async waitForBlocks(countToWait = 1) { + let blocksSeen = 0; + while (blocksSeen !== countToWait) { + await this.waitForNextBlock(); + blocksSeen += 1; + } + } } TransactionsClient.TX_QUERY = TX_QUERY; +TransactionsClient.BLOCK_QUERY = BLOCK_QUERY; +TransactionsClient.events = events; module.exports = TransactionsClient; diff --git a/lib/grpcServer/handlers/platform/getDataContractHandlerFactory.js b/lib/grpcServer/handlers/platform/getDataContractHandlerFactory.js index a25764ee9..8b9620e5b 100644 --- a/lib/grpcServer/handlers/platform/getDataContractHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/getDataContractHandlerFactory.js @@ -16,12 +16,12 @@ const { const AbciResponseError = require('../../../errors/AbciResponseError'); /** - * @param {DriveStateRepository} driveStateRepository + * @param {DriveClient} driveClient * @param {handleAbciResponseError} handleAbciResponseError * * @returns {getDataContractHandler} */ -function getDataContractHandlerFactory(driveStateRepository, handleAbciResponseError) { +function getDataContractHandlerFactory(driveClient, handleAbciResponseError) { /** * @typedef getDataContractHandler * @@ -41,7 +41,7 @@ function getDataContractHandlerFactory(driveStateRepository, handleAbciResponseE let dataContractBuffer; let proofObject; try { - ({ data: dataContractBuffer, proof: proofObject } = await driveStateRepository + ({ data: dataContractBuffer, proof: proofObject } = await driveClient .fetchDataContract(id, prove)); } catch (e) { if (e instanceof AbciResponseError) { diff --git a/lib/grpcServer/handlers/platform/getDocumentsHandlerFactory.js b/lib/grpcServer/handlers/platform/getDocumentsHandlerFactory.js index de0246c97..3550987c8 100644 --- a/lib/grpcServer/handlers/platform/getDocumentsHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/getDocumentsHandlerFactory.js @@ -19,12 +19,12 @@ const AbciResponseError = require('../../../errors/AbciResponseError'); /** * - * @param {DriveStateRepository} driveStateRepository + * @param {DriveClient} driveClient * @param {handleAbciResponseError} handleAbciResponseError * * @returns {getDocumentsHandler} */ -function getDocumentsHandlerFactory(driveStateRepository, handleAbciResponseError) { +function getDocumentsHandlerFactory(driveClient, handleAbciResponseError) { /** * @typedef getDocumentsHandler * @@ -114,7 +114,7 @@ function getDocumentsHandlerFactory(driveStateRepository, handleAbciResponseErro let documentBuffers; let proofObject; try { - ({ data: documentBuffers, proof: proofObject } = await driveStateRepository.fetchDocuments( + ({ data: documentBuffers, proof: proofObject } = await driveClient.fetchDocuments( dataContractId, documentType, options, prove, )); } catch (e) { diff --git a/lib/grpcServer/handlers/platform/getIdentitiesByPublicKeyHashesHandlerFactory.js b/lib/grpcServer/handlers/platform/getIdentitiesByPublicKeyHashesHandlerFactory.js index 382254477..669942d43 100644 --- a/lib/grpcServer/handlers/platform/getIdentitiesByPublicKeyHashesHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/getIdentitiesByPublicKeyHashesHandlerFactory.js @@ -17,12 +17,12 @@ const AbciResponseError = require('../../../errors/AbciResponseError'); /** * - * @param {DriveStateRepository} driveStateRepository + * @param {DriveClient} driveClient * @param {handleAbciResponseError} handleAbciResponseError * @return {getIdentitiesByPublicKeyHashesHandler} */ function getIdentitiesByPublicKeyHashesHandlerFactory( - driveStateRepository, handleAbciResponseError, + driveClient, handleAbciResponseError, ) { /** * @typedef getIdentitiesByPublicKeyHashesHandler @@ -43,7 +43,7 @@ function getIdentitiesByPublicKeyHashesHandlerFactory( let identities; let proofObject; try { - ({ data: identities, proof: proofObject } = await driveStateRepository + ({ data: identities, proof: proofObject } = await driveClient .fetchIdentitiesByPublicKeyHashes(publicKeyHashes, prove)); } catch (e) { if (e instanceof AbciResponseError) { diff --git a/lib/grpcServer/handlers/platform/getIdentityHandlerFactory.js b/lib/grpcServer/handlers/platform/getIdentityHandlerFactory.js index 137fddbfa..c95380a69 100644 --- a/lib/grpcServer/handlers/platform/getIdentityHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/getIdentityHandlerFactory.js @@ -16,12 +16,12 @@ const { const AbciResponseError = require('../../../errors/AbciResponseError'); /** - * @param {DriveStateRepository} driveStateRepository + * @param {DriveClient} driveClient * @param {handleAbciResponseError} handleAbciResponseError * * @returns {getIdentityHandler} */ -function getIdentityHandlerFactory(driveStateRepository, handleAbciResponseError) { +function getIdentityHandlerFactory(driveClient, handleAbciResponseError) { /** * @typedef getIdentityHandler * @@ -44,7 +44,7 @@ function getIdentityHandlerFactory(driveStateRepository, handleAbciResponseError let proofObject; try { - ({ data: identityBuffer, proof: proofObject } = await driveStateRepository + ({ data: identityBuffer, proof: proofObject } = await driveClient .fetchIdentity(id, prove)); } catch (e) { if (e instanceof AbciResponseError) { diff --git a/lib/grpcServer/handlers/platform/getIdentityIdsByPublicKeyHashesHandlerFactory.js b/lib/grpcServer/handlers/platform/getIdentityIdsByPublicKeyHashesHandlerFactory.js index a24ed6cd2..8a7e1d934 100644 --- a/lib/grpcServer/handlers/platform/getIdentityIdsByPublicKeyHashesHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/getIdentityIdsByPublicKeyHashesHandlerFactory.js @@ -17,12 +17,12 @@ const AbciResponseError = require('../../../errors/AbciResponseError'); /** * - * @param {DriveStateRepository} driveStateRepository + * @param {DriveClient} driveClient * @param {handleAbciResponseError} handleAbciResponseError * @return {getIdentityIdsByPublicKeyHashesHandler} */ function getIdentityIdsByPublicKeyHashesHandlerFactory( - driveStateRepository, handleAbciResponseError, + driveClient, handleAbciResponseError, ) { /** * @typedef getIdentityIdsByPublicKeyHashesHandler @@ -44,7 +44,7 @@ function getIdentityIdsByPublicKeyHashesHandlerFactory( let proofObject; try { - ({ data: identityIds, proof: proofObject } = await driveStateRepository + ({ data: identityIds, proof: proofObject } = await driveClient .fetchIdentityIdsByPublicKeyHashes( publicKeyHashes, prove, diff --git a/lib/grpcServer/handlers/platform/platformHandlersFactory.js b/lib/grpcServer/handlers/platform/platformHandlersFactory.js index 16172c752..a88d7be59 100644 --- a/lib/grpcServer/handlers/platform/platformHandlersFactory.js +++ b/lib/grpcServer/handlers/platform/platformHandlersFactory.js @@ -70,7 +70,7 @@ const waitForStateTransitionResultHandlerFactory = require( /** * @param {jaysonClient} rpcClient * @param {TransactionsClient} transactionsClient - * @param {DriveStateRepository} driveStateRepository + * @param {DriveClient} driveClient * @param {DashPlatformProtocol} dpp * @param {boolean} isProductionEnvironment * @returns {Object} @@ -78,7 +78,7 @@ const waitForStateTransitionResultHandlerFactory = require( function platformHandlersFactory( rpcClient, transactionsClient, - driveStateRepository, + driveClient, dpp, isProductionEnvironment, ) { @@ -103,7 +103,7 @@ function platformHandlersFactory( // getIdentity const getIdentityHandler = getIdentityHandlerFactory( - driveStateRepository, handleAbciResponseError, + driveClient, handleAbciResponseError, ); const wrappedGetIdentity = jsonToProtobufHandlerWrapper( @@ -119,7 +119,7 @@ function platformHandlersFactory( // getDocuments const getDocumentsHandler = getDocumentsHandlerFactory( - driveStateRepository, handleAbciResponseError, + driveClient, handleAbciResponseError, ); const wrappedGetDocuments = jsonToProtobufHandlerWrapper( @@ -135,7 +135,7 @@ function platformHandlersFactory( // getDataContract const getDataContractHandler = getDataContractHandlerFactory( - driveStateRepository, handleAbciResponseError, + driveClient, handleAbciResponseError, ); const wrappedGetDataContract = jsonToProtobufHandlerWrapper( @@ -151,7 +151,7 @@ function platformHandlersFactory( // getIdentitiesByPublicKeyHashes const getIdentitiesByPublicKeyHashesHandler = getIdentitiesByPublicKeyHashesHandlerFactory( - driveStateRepository, handleAbciResponseError, + driveClient, handleAbciResponseError, ); const wrappedGetIdentitiesByPublicKeyHashes = jsonToProtobufHandlerWrapper( @@ -167,7 +167,7 @@ function platformHandlersFactory( // getIdentityIdsByPublicKeyHashes const getIdentityIdsByPublicKeyHashesHandler = getIdentityIdsByPublicKeyHashesHandlerFactory( - driveStateRepository, handleAbciResponseError, + driveClient, handleAbciResponseError, ); const wrappedGetIdentityIdsByPublicKeyHashes = jsonToProtobufHandlerWrapper( @@ -183,7 +183,7 @@ function platformHandlersFactory( // waitForStateTransitionResult const waitForStateTransitionResultHandler = waitForStateTransitionResultHandlerFactory( - driveStateRepository, + driveClient, transactionsClient, dpp, ); diff --git a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 32590ddd1..dc3cd7753 100644 --- a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -19,14 +19,14 @@ const TransactionWaitPeriodExceededError = require('../../../errors/TransactionW /** * - * @param {DriveStateRepository} driveStateRepository + * @param {DriveClient} driveClient * @param {TransactionsClient} transactionsClient * @param {DashPlatformProtocol} dpp * @param {number} stateTransitionWaitTimeout * @return {waitForStateTransitionResultHandler} */ function waitForStateTransitionResultHandlerFactory( - driveStateRepository, + driveClient, transactionsClient, dpp, stateTransitionWaitTimeout = 60000, @@ -40,18 +40,16 @@ function waitForStateTransitionResultHandlerFactory( const modifiedIds = stateTransition.getModifiedDataIds(); let proof; - const params = {}; if (stateTransition.isDocumentStateTransition()) { - ({ documentsProof: proof } = await driveStateRepository.fetchProofs( + ({ documentsProof: proof } = await driveClient.fetchProofs( { documentIds: modifiedIds }, )); } else if (stateTransition.isIdentityStateTransition()) { - ({ identitiesProof: proof } = await driveStateRepository.fetchProofs( + ({ identitiesProof: proof } = await driveClient.fetchProofs( { identityIds: modifiedIds }, )); - params.identityIds = modifiedIds; } else if (stateTransition.isDataContractStateTransition()) { - ({ dataContractsProof: proof } = await driveStateRepository.fetchProofs( + ({ dataContractsProof: proof } = await driveClient.fetchProofs( { dataContractIds: modifiedIds }, )); } @@ -116,6 +114,10 @@ function waitForStateTransitionResultHandlerFactory( return response; } + // The first block is the one with the current ST, second block is the + // block in which st result will be included in the proof + await transactionsClient.waitForBlocks(2); + if (prove) { const stateTransition = await dpp.stateTransition.createFromBuffer( Buffer.from(tx, 'base64'), diff --git a/scripts/api.js b/scripts/api.js index 4b6b4a7cb..803ca4181 100644 --- a/scripts/api.js +++ b/scripts/api.js @@ -26,10 +26,11 @@ const config = require('../lib/config'); const { validateConfig } = require('../lib/config/validator'); const log = require('../lib/log'); const rpcServer = require('../lib/rpcServer/server'); -const DriveStateRepository = require('../lib/externalApis/drive/DriveStateRepository'); +const DriveClient = require('../lib/externalApis/drive/DriveClient'); const insightAPI = require('../lib/externalApis/insight'); const dashCoreRpcClient = require('../lib/externalApis/dashcore/rpc'); const TransactionsClient = require('../lib/externalApis/tenderdash/TransactionsClient'); +const DriveStateRepository = require('../lib/dpp/DriveStateRepository'); const coreHandlersFactory = require( '../lib/grpcServer/handlers/core/coreHandlersFactory', @@ -50,7 +51,7 @@ async function main() { const isProductionEnvironment = process.env.NODE_ENV === 'production'; log.info('Connecting to Drive'); - const driveStateRepository = new DriveStateRepository({ + const driveClient = new DriveClient({ host: config.tendermintCore.host, port: config.tendermintCore.port, }); @@ -65,6 +66,8 @@ async function main() { port: config.tendermintCore.port, }); + const driveStateRepository = new DriveStateRepository(driveClient); + log.info(`Connecting to Tenderdash on ${config.tendermintCore.host}:${config.tendermintCore.port}`); tenderDashWsClient.on('error', (e) => { @@ -90,7 +93,9 @@ async function main() { }); log.info(`JSON RPC server is listening on port ${config.rpcServer.port}`); - const dpp = new DashPlatformProtocol(); + const dpp = new DashPlatformProtocol({ + stateRepository: driveStateRepository, + }); // Start GRPC server log.info('Starting GRPC server'); @@ -102,7 +107,7 @@ async function main() { const platformHandlers = platformHandlersFactory( rpcClient, transactionsClient, - driveStateRepository, + driveClient, dpp, isProductionEnvironment, ); diff --git a/test/mocks/driveFixture.js b/test/mocks/driveFixture.js deleted file mode 100644 index 36aeba0c6..000000000 --- a/test/mocks/driveFixture.js +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint class-methods-use-this: off */ -/* eslint-disable no-unused-vars */ -// Unused variables represent signatures for clarity -const DriveStateRepository = require('../../lib/externalApis/drive/DriveStateRepository'); - -// Create a class, so JSDoc would work properly in our tests -class DriveFixture extends DriveStateRepository { - addSTPacket(rawStateTransition, rawSTPacket) { return Promise.resolve(); } - - fetchContract(contractId) { return Promise.resolve({}); } -} - -module.exports = new DriveFixture({}); diff --git a/test/unit/externalApis/drive/DriveStateRepository.js b/test/unit/externalApis/drive/DriveClient.js similarity index 89% rename from test/unit/externalApis/drive/DriveStateRepository.js rename to test/unit/externalApis/drive/DriveClient.js index 5dbaeddb7..c85f5a456 100644 --- a/test/unit/externalApis/drive/DriveStateRepository.js +++ b/test/unit/externalApis/drive/DriveClient.js @@ -7,7 +7,7 @@ const dirtyChai = require('dirty-chai'); const generateRandomIdentifier = require('@dashevo/dpp/lib/test/utils/generateRandomIdentifier'); const getIdentityFixture = require('@dashevo/dpp/lib/test/fixtures/getIdentityFixture'); -const DriveStateRepository = require('../../../../lib/externalApis/drive/DriveStateRepository'); +const DriveClient = require('../../../../lib/externalApis/drive/DriveClient'); const RPCError = require('../../../../lib/rpcServer/RPCError'); const AbciResponseError = require('../../../../lib/errors/AbciResponseError'); @@ -18,10 +18,10 @@ chai.use(dirtyChai); const { expect } = chai; -describe('DriveStateRepository', () => { +describe('DriveClient', () => { describe('constructor', () => { it('Should create drive client with given options', () => { - const drive = new DriveStateRepository({ host: '127.0.0.1', port: 3000 }); + const drive = new DriveClient({ host: '127.0.0.1', port: 3000 }); expect(drive.client.options.host).to.be.equal('127.0.0.1'); expect(drive.client.options.port).to.be.equal(3000); @@ -29,7 +29,7 @@ describe('DriveStateRepository', () => { }); it('should throw RPCError if JSON RPC call failed', async () => { - const drive = new DriveStateRepository({ host: '127.0.0.1', port: 3000 }); + const drive = new DriveClient({ host: '127.0.0.1', port: 3000 }); const error = new Error('Some RPC error'); @@ -46,7 +46,7 @@ describe('DriveStateRepository', () => { }); it('should throw ABCI error response have one', async () => { - const drive = new DriveStateRepository({ host: '127.0.0.1', port: 3000 }); + const drive = new DriveClient({ host: '127.0.0.1', port: 3000 }); const abciError = { message: 'Some ABCI error', @@ -81,7 +81,7 @@ describe('DriveStateRepository', () => { describe('#fetchDataContract', () => { it('Should call \'fetchContract\' RPC with the given parameters', async () => { - const drive = new DriveStateRepository({ host: '127.0.0.1', port: 3000 }); + const drive = new DriveClient({ host: '127.0.0.1', port: 3000 }); const contractId = 'someId'; const data = Buffer.from('someData'); @@ -112,7 +112,7 @@ describe('DriveStateRepository', () => { describe('#fetchDocuments', () => { it('Should call \'fetchDocuments\' RPC with the given parameters', async () => { - const drive = new DriveStateRepository({ host: '127.0.0.1', port: 3000 }); + const drive = new DriveClient({ host: '127.0.0.1', port: 3000 }); const contractId = 'someId'; const type = 'object'; @@ -147,7 +147,7 @@ describe('DriveStateRepository', () => { describe('#fetchIdentity', () => { it('Should call \'fetchIdentity\' RPC with the given parameters', async () => { - const drive = new DriveStateRepository({ host: '127.0.0.1', port: 3000 }); + const drive = new DriveClient({ host: '127.0.0.1', port: 3000 }); const identityId = 'someId'; const data = Buffer.from('someData'); @@ -172,7 +172,7 @@ describe('DriveStateRepository', () => { describe('#fetchIdentitiesByPublicKeyHashes', () => { it('Should call \'fetchIdentitiesByPublicKeyHashes\' RPC with the given parameters', async () => { - const drive = new DriveStateRepository({ host: '127.0.0.1', port: 3000 }); + const drive = new DriveClient({ host: '127.0.0.1', port: 3000 }); const identity = getIdentityFixture(); const proof = Buffer.from('proof'); @@ -203,7 +203,7 @@ describe('DriveStateRepository', () => { describe('#fetchIdentityIdsByPublicKeyHashes', () => { it('Should call \'fetchIdentityIdsByPublicKeyHashes\' RPC with the given parameters', async () => { - const drive = new DriveStateRepository({ host: '127.0.0.1', port: 3000 }); + const drive = new DriveClient({ host: '127.0.0.1', port: 3000 }); const identityId = generateRandomIdentifier(); const publicKeyHashes = [Buffer.alloc(1)]; @@ -233,7 +233,7 @@ describe('DriveStateRepository', () => { describe('#fetchProofs', () => { it('should call \'fetchProofs\' RPC with the given parameters', async () => { - const drive = new DriveStateRepository({ host: '127.0.0.1', port: 3000 }); + const drive = new DriveClient({ host: '127.0.0.1', port: 3000 }); const documentIds = undefined; const identityIds = [Buffer.from('id')]; From ad45925351c1a323ecbc5df73973472a29dcbe56 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Fri, 22 Jan 2021 13:33:48 +0300 Subject: [PATCH 28/36] add test for waiting for blocks --- .../tenderdash/TransactionsClient.js | 8 ++--- .../tenderdash/TransactionsClient.spec.js | 34 +++++++++++++++++-- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/lib/externalApis/tenderdash/TransactionsClient.js b/lib/externalApis/tenderdash/TransactionsClient.js index 58b672fa5..fcf91a7a2 100644 --- a/lib/externalApis/tenderdash/TransactionsClient.js +++ b/lib/externalApis/tenderdash/TransactionsClient.js @@ -2,7 +2,7 @@ const EventEmitter = require('events'); const TransactionWaitPeriodExceededError = require('../../errors/TransactionWaitPeriodExceededError'); const TX_QUERY = 'tm.event = \'Tx\''; -const BLOCK_QUERY = 'tm.event = \'NewBlock\''; +const NEW_BLOCK_QUERY = 'tm.event = \'NewBlock\''; const events = { NEW_BLOCK: 'block', }; @@ -33,8 +33,8 @@ class TransactionsClient extends EventEmitter { this.wsClient.subscribe(TX_QUERY); this.wsClient.on(TX_QUERY, this.emitTransaction.bind(this)); - this.wsClient.subscribe(BLOCK_QUERY); - this.wsClient.on(BLOCK_QUERY, (message) => { + this.wsClient.subscribe(NEW_BLOCK_QUERY); + this.wsClient.on(NEW_BLOCK_QUERY, (message) => { this.emit(events.NEW_BLOCK, message); }); } @@ -110,7 +110,7 @@ class TransactionsClient extends EventEmitter { } TransactionsClient.TX_QUERY = TX_QUERY; -TransactionsClient.BLOCK_QUERY = BLOCK_QUERY; +TransactionsClient.NEW_BLOCK_QUERY = NEW_BLOCK_QUERY; TransactionsClient.events = events; module.exports = TransactionsClient; diff --git a/test/integration/externalApis/tenderdash/TransactionsClient.spec.js b/test/integration/externalApis/tenderdash/TransactionsClient.spec.js index c66439800..dcb0d3daa 100644 --- a/test/integration/externalApis/tenderdash/TransactionsClient.spec.js +++ b/test/integration/externalApis/tenderdash/TransactionsClient.spec.js @@ -28,8 +28,13 @@ describe('TransactionClient', () => { describe('#start', () => { it('should subscribe to transaction events from WS client', () => { - expect(wsClientMock.subscribe).to.be.calledOnce(); - expect(wsClientMock.subscribe).to.be.calledWithExactly(TransactionsClient.TX_QUERY); + expect(wsClientMock.subscribe).to.be.calledTwice(); + expect(wsClientMock.subscribe.firstCall).to.be.calledWithExactly( + TransactionsClient.TX_QUERY, + ); + expect(wsClientMock.subscribe.secondCall).to.be.calledWithExactly( + TransactionsClient.BLOCK_QUERY, + ); }); }); @@ -120,4 +125,29 @@ describe('TransactionClient', () => { expect(transactionsClient.emit).to.not.be.called(); }); }); + + describe('#waitForBlocks', () => { + it('should wait for n blocks and remove listeners afterwards', async () => { + const newBlockEvent = TransactionsClient.events.NEW_BLOCK; + const blockPromise = transactionsClient.waitForBlocks(2); + + expect(transactionsClient.listenerCount(newBlockEvent)).to.be.equal(1); + + setTimeout(() => { + wsClientMock.emit(TransactionsClient.NEW_BLOCK_QUERY, Object.assign({}, txDataMock)); + }, 10); + setTimeout(() => { + wsClientMock.emit(TransactionsClient.NEW_BLOCK_QUERY, Object.assign({}, txDataMock)); + }, 10); + + await blockPromise; + + // Check that event listener was properly attached + expect(transactionsClient.on).to.be.calledTwice(); + // Check that transaction data was emitted + expect(transactionsClient.emit).to.be.calledTwice(); + // Check that the event listener was properly removed + expect(transactionsClient.listenerCount(newBlockEvent)).to.be.equal(0); + }); + }); }); From 9f9e39c4b54c99908196bde556953464528f03b8 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Fri, 22 Jan 2021 13:44:50 +0300 Subject: [PATCH 29/36] fix waitForStateTransitionResultHandlerFactory.js tests --- .../tenderdash/TransactionsClient.spec.js | 2 +- ...tForStateTransitionResultHandlerFactory.js | 66 +++++++++++-------- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/test/integration/externalApis/tenderdash/TransactionsClient.spec.js b/test/integration/externalApis/tenderdash/TransactionsClient.spec.js index dcb0d3daa..57ca3cd8d 100644 --- a/test/integration/externalApis/tenderdash/TransactionsClient.spec.js +++ b/test/integration/externalApis/tenderdash/TransactionsClient.spec.js @@ -33,7 +33,7 @@ describe('TransactionClient', () => { TransactionsClient.TX_QUERY, ); expect(wsClientMock.subscribe.secondCall).to.be.calledWithExactly( - TransactionsClient.BLOCK_QUERY, + TransactionsClient.NEW_BLOCK_QUERY, ); }); }); diff --git a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 13cc9d219..5749b2d77 100644 --- a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -129,44 +129,56 @@ describe('waitForStateTransitionResultHandlerFactory', () => { ); }); - it('should wait for state transition empty result', (done) => { - waitForStateTransitionResultHandler(call).then((result) => { - expect(result).to.be.an.instanceOf(WaitForStateTransitionResultResponse); - expect(result.getProof()).to.be.undefined(); - expect(result.getError()).to.be.undefined(); + it('should wait for state transition empty result', async () => { + const promise = waitForStateTransitionResultHandler(call); - done(); - }); - - process.nextTick(() => { + setTimeout(() => { tenderDashWsClientMock.emit('tm.event = \'Tx\'', wsMessagesFixture.success); - }); + }, 10); + setTimeout(() => { + tenderDashWsClientMock.emit(TransactionClient.NEW_BLOCK_QUERY, wsMessagesFixture.success); + }, 10); + setTimeout(() => { + tenderDashWsClientMock.emit(TransactionClient.NEW_BLOCK_QUERY, wsMessagesFixture.success); + }, 10); + + const result = await promise; + + expect(result).to.be.an.instanceOf(WaitForStateTransitionResultResponse); + expect(result.getProof()).to.be.undefined(); + expect(result.getError()).to.be.undefined(); }); - it('should wait for state transition and return result with proof', (done) => { + it('should wait for state transition and return result with proof', async () => { call.request.getProve.returns(true); - waitForStateTransitionResultHandler(call).then((result) => { - expect(result).to.be.an.instanceOf(WaitForStateTransitionResultResponse); - expect(result.getError()).to.be.undefined(); - const proof = result.getProof(); + const promise = waitForStateTransitionResultHandler(call); - expect(proof).to.be.an.instanceOf(Proof); - const rootTreeProof = proof.getRootTreeProof(); - const storeTreeProof = proof.getStoreTreeProof(); + setTimeout(() => { + tenderDashWsClientMock.emit('tm.event = \'Tx\'', wsMessagesFixture.success); + }, 10); + setTimeout(() => { + tenderDashWsClientMock.emit(TransactionClient.NEW_BLOCK_QUERY, wsMessagesFixture.success); + }, 10); + setTimeout(() => { + tenderDashWsClientMock.emit(TransactionClient.NEW_BLOCK_QUERY, wsMessagesFixture.success); + }, 10); - expect(rootTreeProof).to.deep.equal(proofFixture.rootTreeProof); - expect(storeTreeProof).to.deep.equal(proofFixture.storeTreeProof); + const result = await promise; - expect(driveStateRepositoryMock.fetchProofs).to.be.calledOnceWithExactly({ - identityIds: stateTransitionFixture.getModifiedDataIds(), - }); + expect(result).to.be.an.instanceOf(WaitForStateTransitionResultResponse); + expect(result.getError()).to.be.undefined(); + const proof = result.getProof(); - done(); - }); + expect(proof).to.be.an.instanceOf(Proof); + const rootTreeProof = proof.getRootTreeProof(); + const storeTreeProof = proof.getStoreTreeProof(); - process.nextTick(() => { - tenderDashWsClientMock.emit('tm.event = \'Tx\'', wsMessagesFixture.success); + expect(rootTreeProof).to.deep.equal(proofFixture.rootTreeProof); + expect(storeTreeProof).to.deep.equal(proofFixture.storeTreeProof); + + expect(driveStateRepositoryMock.fetchProofs).to.be.calledOnceWithExactly({ + identityIds: stateTransitionFixture.getModifiedDataIds(), }); }); From a3cdb3cceaa07eed39ccbdf317cb6bac8109921d Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Thu, 28 Jan 2021 16:10:04 +0300 Subject: [PATCH 30/36] add handling of checTx errors in broadcastStateTransition --- .../broadcastStateTransitionHandlerFactory.js | 17 +++++++++++++++-- ...aitForStateTransitionResultHandlerFactory.js | 2 +- .../subscribeToNewTransactions.js | 4 ++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js b/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js index b7d7d2c8d..0515d0b99 100644 --- a/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js @@ -13,12 +13,15 @@ const { }, } = require('@dashevo/dapi-grpc'); +const AbciResponseError = require('../../../errors/AbciResponseError'); + /** * @param {jaysonClient} rpcClient + * @param {handleAbciResponseError} handleAbciResponseError * * @returns {broadcastStateTransitionHandler} */ -function broadcastStateTransitionHandlerFactory(rpcClient) { +function broadcastStateTransitionHandlerFactory(rpcClient, handleAbciResponseError) { /** * @typedef broadcastStateTransitionHandler * @@ -36,7 +39,9 @@ function broadcastStateTransitionHandlerFactory(rpcClient) { const tx = Buffer.from(stByteArray).toString('base64'); - const { error: jsonRpcError } = await rpcClient.request('broadcast_tx_async', { tx }); + const { result } = await rpcClient.request('broadcast_tx_sync', { tx }); + + const { error: jsonRpcError } = result; if (jsonRpcError) { if (jsonRpcError.data === 'tx already exists in cache') { @@ -49,6 +54,14 @@ function broadcastStateTransitionHandlerFactory(rpcClient) { throw error; } + if (result.code !== undefined && result.code !== 0) { + const { error: abciError } = JSON.parse(result.log); + + handleAbciResponseError( + new AbciResponseError(result.code, abciError), + ); + } + return new BroadcastStateTransitionResponse(); } diff --git a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index dc3cd7753..7fc87934a 100644 --- a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -29,7 +29,7 @@ function waitForStateTransitionResultHandlerFactory( driveClient, transactionsClient, dpp, - stateTransitionWaitTimeout = 60000, + stateTransitionWaitTimeout = 80000, ) { /** * diff --git a/lib/transactionsFilter/subscribeToNewTransactions.js b/lib/transactionsFilter/subscribeToNewTransactions.js index 1410dd491..ba794d344 100644 --- a/lib/transactionsFilter/subscribeToNewTransactions.js +++ b/lib/transactionsFilter/subscribeToNewTransactions.js @@ -85,6 +85,10 @@ function subscribeToNewTransactions( mediator.once(ProcessMediator.EVENTS.CLIENT_DISCONNECTED, () => { isClientConnected = false; + + mediator.removeAllListeners(); + filterEmitter.removeAllListeners(); + bloomFilterEmitterCollection.remove(filterEmitter); }); } From 72690076af97d90a070482f7da72a0e14376aa05 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Fri, 29 Jan 2021 13:07:30 +0300 Subject: [PATCH 31/36] rename TransactionsClient to BlockchainListener.js --- ...actionsClient.js => BlockchainListener.js} | 14 ++-- .../platform/platformHandlersFactory.js | 6 +- ...tForStateTransitionResultHandlerFactory.js | 8 +- scripts/api.js | 8 +- ...ent.spec.js => BlockchainListener.spec.js} | 80 +++++++++---------- ...tForStateTransitionResultHandlerFactory.js | 2 +- .../broadcastStateTransitionHandlerFactory.js | 2 +- 7 files changed, 60 insertions(+), 60 deletions(-) rename lib/externalApis/tenderdash/{TransactionsClient.js => BlockchainListener.js} (88%) rename test/integration/externalApis/tenderdash/{TransactionsClient.spec.js => BlockchainListener.spec.js} (59%) diff --git a/lib/externalApis/tenderdash/TransactionsClient.js b/lib/externalApis/tenderdash/BlockchainListener.js similarity index 88% rename from lib/externalApis/tenderdash/TransactionsClient.js rename to lib/externalApis/tenderdash/BlockchainListener.js index fcf91a7a2..40ab9c360 100644 --- a/lib/externalApis/tenderdash/TransactionsClient.js +++ b/lib/externalApis/tenderdash/BlockchainListener.js @@ -7,7 +7,7 @@ const events = { NEW_BLOCK: 'block', }; -class TransactionsClient extends EventEmitter { +class BlockchainListener extends EventEmitter { /** * @param {WsClient} tenderdashWsClient */ @@ -67,7 +67,7 @@ class TransactionsClient extends EventEmitter { return; } - this.emit(TransactionsClient.getTransactionEventName(hashString), message); + this.emit(BlockchainListener.getTransactionEventName(hashString), message); } /** @@ -77,7 +77,7 @@ class TransactionsClient extends EventEmitter { * @return {Promise} */ waitForTransaction(hashString, timeout = 60000) { - const topic = TransactionsClient.getTransactionEventName(hashString); + const topic = BlockchainListener.getTransactionEventName(hashString); let handler; return Promise.race([ @@ -109,8 +109,8 @@ class TransactionsClient extends EventEmitter { } } -TransactionsClient.TX_QUERY = TX_QUERY; -TransactionsClient.NEW_BLOCK_QUERY = NEW_BLOCK_QUERY; -TransactionsClient.events = events; +BlockchainListener.TX_QUERY = TX_QUERY; +BlockchainListener.NEW_BLOCK_QUERY = NEW_BLOCK_QUERY; +BlockchainListener.events = events; -module.exports = TransactionsClient; +module.exports = BlockchainListener; diff --git a/lib/grpcServer/handlers/platform/platformHandlersFactory.js b/lib/grpcServer/handlers/platform/platformHandlersFactory.js index a88d7be59..ab502ba04 100644 --- a/lib/grpcServer/handlers/platform/platformHandlersFactory.js +++ b/lib/grpcServer/handlers/platform/platformHandlersFactory.js @@ -69,7 +69,7 @@ const waitForStateTransitionResultHandlerFactory = require( /** * @param {jaysonClient} rpcClient - * @param {TransactionsClient} transactionsClient + * @param {BlockchainListener} blockchainListener * @param {DriveClient} driveClient * @param {DashPlatformProtocol} dpp * @param {boolean} isProductionEnvironment @@ -77,7 +77,7 @@ const waitForStateTransitionResultHandlerFactory = require( */ function platformHandlersFactory( rpcClient, - transactionsClient, + blockchainListener, driveClient, dpp, isProductionEnvironment, @@ -184,7 +184,7 @@ function platformHandlersFactory( // waitForStateTransitionResult const waitForStateTransitionResultHandler = waitForStateTransitionResultHandlerFactory( driveClient, - transactionsClient, + blockchainListener, dpp, ); diff --git a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 7fc87934a..fd8e7739c 100644 --- a/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -20,14 +20,14 @@ const TransactionWaitPeriodExceededError = require('../../../errors/TransactionW /** * * @param {DriveClient} driveClient - * @param {TransactionsClient} transactionsClient + * @param {BlockchainListener} blockchainListener * @param {DashPlatformProtocol} dpp * @param {number} stateTransitionWaitTimeout * @return {waitForStateTransitionResultHandler} */ function waitForStateTransitionResultHandlerFactory( driveClient, - transactionsClient, + blockchainListener, dpp, stateTransitionWaitTimeout = 80000, ) { @@ -78,7 +78,7 @@ function waitForStateTransitionResultHandlerFactory( let data; try { - data = await transactionsClient.waitForTransaction(hashString, stateTransitionWaitTimeout); + data = await blockchainListener.waitForTransaction(hashString, stateTransitionWaitTimeout); } catch (e) { if (e instanceof TransactionWaitPeriodExceededError) { throw new DeadlineExceededGrpcError( @@ -116,7 +116,7 @@ function waitForStateTransitionResultHandlerFactory( // The first block is the one with the current ST, second block is the // block in which st result will be included in the proof - await transactionsClient.waitForBlocks(2); + await blockchainListener.waitForBlocks(2); if (prove) { const stateTransition = await dpp.stateTransition.createFromBuffer( diff --git a/scripts/api.js b/scripts/api.js index 803ca4181..0ee39423f 100644 --- a/scripts/api.js +++ b/scripts/api.js @@ -29,7 +29,7 @@ const rpcServer = require('../lib/rpcServer/server'); const DriveClient = require('../lib/externalApis/drive/DriveClient'); const insightAPI = require('../lib/externalApis/insight'); const dashCoreRpcClient = require('../lib/externalApis/dashcore/rpc'); -const TransactionsClient = require('../lib/externalApis/tenderdash/TransactionsClient'); +const BlockchainListener = require('../lib/externalApis/tenderdash/BlockchainListener'); const DriveStateRepository = require('../lib/dpp/DriveStateRepository'); const coreHandlersFactory = require( @@ -78,8 +78,8 @@ async function main() { await tenderDashWsClient.connect(); - const transactionsClient = new TransactionsClient(tenderDashWsClient); - transactionsClient.start(); + const blockchainListener = new BlockchainListener(tenderDashWsClient); + blockchainListener.start(); log.info('Connection to Tenderdash established.'); @@ -106,7 +106,7 @@ async function main() { ); const platformHandlers = platformHandlersFactory( rpcClient, - transactionsClient, + blockchainListener, driveClient, dpp, isProductionEnvironment, diff --git a/test/integration/externalApis/tenderdash/TransactionsClient.spec.js b/test/integration/externalApis/tenderdash/BlockchainListener.spec.js similarity index 59% rename from test/integration/externalApis/tenderdash/TransactionsClient.spec.js rename to test/integration/externalApis/tenderdash/BlockchainListener.spec.js index 57ca3cd8d..c1ec8d25e 100644 --- a/test/integration/externalApis/tenderdash/TransactionsClient.spec.js +++ b/test/integration/externalApis/tenderdash/BlockchainListener.spec.js @@ -1,19 +1,19 @@ const EventEmitter = require('events'); -const TransactionsClient = require('../../../../lib/externalApis/tenderdash/TransactionsClient'); +const BlockchainListener = require('../../../../lib/externalApis/tenderdash/BlockchainListener'); const TransactionWaitPeriodExceededError = require('../../../../lib/errors/TransactionWaitPeriodExceededError'); describe('TransactionClient', () => { let sinon; let wsClientMock; - let transactionsClient; + let blockchainListener; let txDataMock; beforeEach(function beforeEach() { ({ sinon } = this); wsClientMock = new EventEmitter(); wsClientMock.subscribe = sinon.stub(); - transactionsClient = new TransactionsClient(wsClientMock); - transactionsClient.start(); + blockchainListener = new BlockchainListener(wsClientMock); + blockchainListener.start(); txDataMock = { events: { @@ -21,66 +21,66 @@ describe('TransactionClient', () => { }, }; - sinon.spy(transactionsClient, 'on'); - sinon.spy(transactionsClient, 'off'); - sinon.spy(transactionsClient, 'emit'); + sinon.spy(blockchainListener, 'on'); + sinon.spy(blockchainListener, 'off'); + sinon.spy(blockchainListener, 'emit'); }); describe('#start', () => { it('should subscribe to transaction events from WS client', () => { expect(wsClientMock.subscribe).to.be.calledTwice(); expect(wsClientMock.subscribe.firstCall).to.be.calledWithExactly( - TransactionsClient.TX_QUERY, + BlockchainListener.TX_QUERY, ); expect(wsClientMock.subscribe.secondCall).to.be.calledWithExactly( - TransactionsClient.NEW_BLOCK_QUERY, + BlockchainListener.NEW_BLOCK_QUERY, ); }); }); describe('.getTransactionEventName', () => { it('should return transaction event name', () => { - const eventName = TransactionsClient.getTransactionEventName('123'); + const eventName = BlockchainListener.getTransactionEventName('123'); expect(eventName).to.be.equal('transaction:123'); }); }); describe('#waitForTransaction', () => { it('should remove listener after transaction resolves', async () => { - const eventName = TransactionsClient.getTransactionEventName('123'); - const txPromise = transactionsClient.waitForTransaction('123', 2000); + const eventName = BlockchainListener.getTransactionEventName('123'); + const txPromise = blockchainListener.waitForTransaction('123', 2000); - expect(transactionsClient.listenerCount(eventName)).to.be.equal(1); + expect(blockchainListener.listenerCount(eventName)).to.be.equal(1); setTimeout(() => { - wsClientMock.emit(TransactionsClient.TX_QUERY, Object.assign({}, txDataMock)); + wsClientMock.emit(BlockchainListener.TX_QUERY, Object.assign({}, txDataMock)); }, 10); const txData = await txPromise; // Check that event listener was properly attached - expect(transactionsClient.on).to.be.calledOnce(); + expect(blockchainListener.on).to.be.calledOnce(); // Check that transaction data was emitted - expect(transactionsClient.emit).to.be.calledOnce(); + expect(blockchainListener.emit).to.be.calledOnce(); // Check that the event listener was properly removed - expect(transactionsClient.off).to.be.calledOnce(); - expect(transactionsClient.listenerCount(eventName)).to.be.equal(0); + expect(blockchainListener.off).to.be.calledOnce(); + expect(blockchainListener.listenerCount(eventName)).to.be.equal(0); expect(txData).to.be.deep.equal(txDataMock); }); it('should not emit transaction event if event data has no transaction', async () => { - const eventName = TransactionsClient.getTransactionEventName('123'); + const eventName = BlockchainListener.getTransactionEventName('123'); txDataMock = {}; let error; try { - const txPromise = transactionsClient.waitForTransaction('123', 1000); + const txPromise = blockchainListener.waitForTransaction('123', 1000); - expect(transactionsClient.listenerCount(eventName)).to.be.equal(1); + expect(blockchainListener.listenerCount(eventName)).to.be.equal(1); setTimeout(() => { - wsClientMock.emit(TransactionsClient.TX_QUERY, Object.assign({}, txDataMock)); + wsClientMock.emit(BlockchainListener.TX_QUERY, Object.assign({}, txDataMock)); }, 10); await txPromise; @@ -94,19 +94,19 @@ describe('TransactionClient', () => { expect(error.getTransactionHash()).to.be.equal('123'); // Check that event listener was properly attached - expect(transactionsClient.on).to.be.calledOnce(); + expect(blockchainListener.on).to.be.calledOnce(); // Check that event listener was properly removed - expect(transactionsClient.off).to.be.calledOnce(); - expect(transactionsClient.listenerCount(eventName)).to.be.equal(0); + expect(blockchainListener.off).to.be.calledOnce(); + expect(blockchainListener.listenerCount(eventName)).to.be.equal(0); // Check that no transaction data was emitted - expect(transactionsClient.emit).to.not.be.called(); + expect(blockchainListener.emit).to.not.be.called(); }); it('should remove listener after timeout has been exceeded', async () => { - const eventName = TransactionsClient.getTransactionEventName('123'); + const eventName = BlockchainListener.getTransactionEventName('123'); let error; try { - await transactionsClient.waitForTransaction('123', 100); + await blockchainListener.waitForTransaction('123', 100); } catch (e) { error = e; } @@ -117,37 +117,37 @@ describe('TransactionClient', () => { expect(error.getTransactionHash()).to.be.equal('123'); // Check that event listener was properly attached - expect(transactionsClient.on).to.be.calledOnce(); + expect(blockchainListener.on).to.be.calledOnce(); // Check that event listener was properly removed - expect(transactionsClient.off).to.be.calledOnce(); - expect(transactionsClient.listenerCount(eventName)).to.be.equal(0); + expect(blockchainListener.off).to.be.calledOnce(); + expect(blockchainListener.listenerCount(eventName)).to.be.equal(0); // Check that no transaction data was emitted - expect(transactionsClient.emit).to.not.be.called(); + expect(blockchainListener.emit).to.not.be.called(); }); }); describe('#waitForBlocks', () => { it('should wait for n blocks and remove listeners afterwards', async () => { - const newBlockEvent = TransactionsClient.events.NEW_BLOCK; - const blockPromise = transactionsClient.waitForBlocks(2); + const newBlockEvent = BlockchainListener.events.NEW_BLOCK; + const blockPromise = blockchainListener.waitForBlocks(2); - expect(transactionsClient.listenerCount(newBlockEvent)).to.be.equal(1); + expect(blockchainListener.listenerCount(newBlockEvent)).to.be.equal(1); setTimeout(() => { - wsClientMock.emit(TransactionsClient.NEW_BLOCK_QUERY, Object.assign({}, txDataMock)); + wsClientMock.emit(BlockchainListener.NEW_BLOCK_QUERY, Object.assign({}, txDataMock)); }, 10); setTimeout(() => { - wsClientMock.emit(TransactionsClient.NEW_BLOCK_QUERY, Object.assign({}, txDataMock)); + wsClientMock.emit(BlockchainListener.NEW_BLOCK_QUERY, Object.assign({}, txDataMock)); }, 10); await blockPromise; // Check that event listener was properly attached - expect(transactionsClient.on).to.be.calledTwice(); + expect(blockchainListener.on).to.be.calledTwice(); // Check that transaction data was emitted - expect(transactionsClient.emit).to.be.calledTwice(); + expect(blockchainListener.emit).to.be.calledTwice(); // Check that the event listener was properly removed - expect(transactionsClient.listenerCount(newBlockEvent)).to.be.equal(0); + expect(blockchainListener.listenerCount(newBlockEvent)).to.be.equal(0); }); }); }); diff --git a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js index 5749b2d77..5bed8cdf6 100644 --- a/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js +++ b/test/integration/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory.js @@ -21,7 +21,7 @@ const getIdentityCreateTransitionFixture = require('@dashevo/dpp/lib/test/fixtur const { EventEmitter } = require('events'); const cbor = require('cbor'); -const TransactionClient = require('../../../../../lib/externalApis/tenderdash/TransactionsClient'); +const TransactionClient = require('../../../../../lib/externalApis/tenderdash/BlockchainListener'); const GrpcCallMock = require('../../../../../lib/test/mock/GrpcCallMock'); const waitForStateTransitionResultHandlerFactory = require('../../../../../lib/grpcServer/handlers/platform/waitForStateTransitionResultHandlerFactory'); diff --git a/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js b/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js index 82f0dad14..0686a02e3 100644 --- a/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js +++ b/test/unit/grpcServer/handlers/platform/broadcastStateTransitionHandlerFactory.js @@ -98,7 +98,7 @@ describe('broadcastStateTransitionHandlerFactory', () => { const tx = stateTransitionFixture.toBuffer().toString('base64'); expect(result).to.be.an.instanceOf(BroadcastStateTransitionResponse); - expect(rpcClientMock.request).to.be.calledOnceWith('broadcast_tx_async', { tx }); + expect(rpcClientMock.request).to.be.calledOnceWith('broadcast_tx_sync', { tx }); }); it('should throw an error if transaction broadcast returns error', async () => { From 9399de01ef798d767fcd727c5feab21d729ad55d Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Fri, 29 Jan 2021 15:09:38 +0300 Subject: [PATCH 32/36] add dpp to DriveStateRepository and added a test --- lib/dpp/DriveStateRepository.js | 6 +- scripts/api.js | 3 +- .../dpp/DriveStateRepository.spec.js | 55 +++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 test/integration/dpp/DriveStateRepository.spec.js diff --git a/lib/dpp/DriveStateRepository.js b/lib/dpp/DriveStateRepository.js index 5c5ce530e..0966a7156 100644 --- a/lib/dpp/DriveStateRepository.js +++ b/lib/dpp/DriveStateRepository.js @@ -7,9 +7,11 @@ const { decode } = require('@dashevo/dpp/lib/util/serializer'); class DriveStateRepository { /** * @param {DriveClient} driveClient + * @param {DashPlatformProtocol} dpp */ - constructor(driveClient) { + constructor(driveClient, dpp) { this.driveClient = driveClient; + this.dpp = dpp; } /** @@ -22,7 +24,7 @@ class DriveStateRepository { contractIdentifier, false, ); - return new DataContract(decode(driveResponse.data)); + return this.dpp.dataContract.createFromBuffer(driveResponse.data); } } diff --git a/scripts/api.js b/scripts/api.js index 0ee39423f..beea01f1e 100644 --- a/scripts/api.js +++ b/scripts/api.js @@ -66,7 +66,8 @@ async function main() { port: config.tendermintCore.port, }); - const driveStateRepository = new DriveStateRepository(driveClient); + const dppForParsingContracts = new DashPlatformProtocol(); + const driveStateRepository = new DriveStateRepository(driveClient, dppForParsingContracts); log.info(`Connecting to Tenderdash on ${config.tendermintCore.host}:${config.tendermintCore.port}`); diff --git a/test/integration/dpp/DriveStateRepository.spec.js b/test/integration/dpp/DriveStateRepository.spec.js new file mode 100644 index 000000000..380ca6d0f --- /dev/null +++ b/test/integration/dpp/DriveStateRepository.spec.js @@ -0,0 +1,55 @@ +const chai = require('chai'); +const sinon = require('sinon'); + +const chaiAsPromised = require('chai-as-promised'); +const dirtyChai = require('dirty-chai'); + +const DashPlatformProtocol = require('@dashevo/dpp'); + +const generateRandomIdentifier = require('@dashevo/dpp/lib/test/utils/generateRandomIdentifier'); +const getDataContractFixture = require('@dashevo/dpp/lib/test/fixtures/getDataContractFixture'); +const DriveStateRepository = require('../../../lib/dpp/DriveStateRepository'); + + +chai.use(chaiAsPromised); +chai.use(dirtyChai); + +const { expect } = chai; + +describe('DriveStateRepository', () => { + let dpp; + let driveClientMock; + let stateRepository; + let dataContractFixture; + + beforeEach(function before() { + dataContractFixture = getDataContractFixture(); + + dpp = new DashPlatformProtocol(); + sinon.spy(dpp.dataContract, 'createFromBuffer'); + + driveClientMock = sinon.stub(); + driveClientMock.fetchDataContract = this.sinon.stub().resolves({ + data: dataContractFixture.toBuffer(), + }); + + stateRepository = new DriveStateRepository(driveClientMock, dpp); + }); + + describe('#fetchDataContract', () => { + it('should fetch and parse data contract', async () => { + const contractId = generateRandomIdentifier(); + const result = await stateRepository.fetchDataContract(contractId); + + expect(result.toObject()).to.be.deep.equal(dataContractFixture.toObject()); + + expect(dpp.dataContract.createFromBuffer).to.be.calledOnce(); + expect(dpp.dataContract.createFromBuffer).to.be.calledWithExactly( + dataContractFixture.toBuffer(), + ); + + expect(driveClientMock.fetchDataContract).to.be.calledOnce(); + expect(driveClientMock.fetchDataContract).to.be.calledWithExactly(contractId, false); + }); + }); +}); From 36074e21dbdf634197012a46d7ed2015055f24f0 Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Fri, 29 Jan 2021 15:17:35 +0300 Subject: [PATCH 33/36] remove unused imports from state repository --- lib/dpp/DriveStateRepository.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/dpp/DriveStateRepository.js b/lib/dpp/DriveStateRepository.js index 0966a7156..87a5784e1 100644 --- a/lib/dpp/DriveStateRepository.js +++ b/lib/dpp/DriveStateRepository.js @@ -1,6 +1,3 @@ -const DataContract = require('@dashevo/dpp/lib/dataContract/DataContract'); -const { decode } = require('@dashevo/dpp/lib/util/serializer'); - /** * @implements StateRepository */ From fb59e20706d6b65ff60c5bb4665d52029756a76e Mon Sep 17 00:00:00 2001 From: Ivan Shumkov Date: Fri, 29 Jan 2021 20:45:23 +0800 Subject: [PATCH 34/36] Update test/integration/externalApis/tenderdash/BlockchainListener.spec.js --- .../externalApis/tenderdash/BlockchainListener.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/externalApis/tenderdash/BlockchainListener.spec.js b/test/integration/externalApis/tenderdash/BlockchainListener.spec.js index c1ec8d25e..533661c35 100644 --- a/test/integration/externalApis/tenderdash/BlockchainListener.spec.js +++ b/test/integration/externalApis/tenderdash/BlockchainListener.spec.js @@ -2,7 +2,7 @@ const EventEmitter = require('events'); const BlockchainListener = require('../../../../lib/externalApis/tenderdash/BlockchainListener'); const TransactionWaitPeriodExceededError = require('../../../../lib/errors/TransactionWaitPeriodExceededError'); -describe('TransactionClient', () => { +describe('BlockchainListener', () => { let sinon; let wsClientMock; let blockchainListener; From 2f4a527d482c8ac75c46bf114ad3ca7aa6bd1b9b Mon Sep 17 00:00:00 2001 From: Anton Suprunchuk Date: Mon, 1 Feb 2021 18:03:26 +0300 Subject: [PATCH 35/36] update lock --- package-lock.json | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 01c5a6efc..6d7e41333 100644 --- a/package-lock.json +++ b/package-lock.json @@ -177,6 +177,26 @@ "bignumber.js": "^9.0.1", "nofilter": "^1.0.4" } + }, + "protobufjs": { + "version": "github:jawid-h/protobuf.js#8b91c72dca68fd6c418078fd2358c4969425dcdc", + "from": "github:jawid-h/protobuf.js#fix/buffer-conversion", + "dev": true, + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": "^13.7.0", + "long": "^4.0.0" + } } } }, @@ -190,6 +210,27 @@ "grpc": "^1.24.3", "grpc-web": "^1.2.0", "protobufjs": "github:jawid-h/protobuf.js#fix/buffer-conversion" + }, + "dependencies": { + "protobufjs": { + "version": "github:jawid-h/protobuf.js#8b91c72dca68fd6c418078fd2358c4969425dcdc", + "from": "github:jawid-h/protobuf.js#fix/buffer-conversion", + "requires": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": "^13.7.0", + "long": "^4.0.0" + } + } } }, "@dashevo/dashcore-lib": { @@ -4314,8 +4355,9 @@ "dev": true }, "protobufjs": { - "version": "github:jawid-h/protobuf.js#8b91c72dca68fd6c418078fd2358c4969425dcdc", - "from": "github:jawid-h/protobuf.js#fix/buffer-conversion", + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.10.1.tgz", + "integrity": "sha512-pb8kTchL+1Ceg4lFd5XUpK8PdWacbvV5SK2ULH2ebrYtl4GjJmS24m6CKME67jzV53tbJxHlnNOSqQHbTsR9JQ==", "requires": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", From d729dc2605e0b4e9ef7c5084085d0983fd90fa93 Mon Sep 17 00:00:00 2001 From: Konstantin Shuplenkov Date: Tue, 2 Feb 2021 15:28:12 +0300 Subject: [PATCH 36/36] feat: update dapi-grpc to 0.18.0-dev.3 --- package-lock.json | 137 +++++++++++++++++----------------------------- package.json | 2 +- 2 files changed, 50 insertions(+), 89 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6d7e41333..522bb91a5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -177,60 +177,19 @@ "bignumber.js": "^9.0.1", "nofilter": "^1.0.4" } - }, - "protobufjs": { - "version": "github:jawid-h/protobuf.js#8b91c72dca68fd6c418078fd2358c4969425dcdc", - "from": "github:jawid-h/protobuf.js#fix/buffer-conversion", - "dev": true, - "requires": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.1", - "@types/node": "^13.7.0", - "long": "^4.0.0" - } } } }, "@dashevo/dapi-grpc": { - "version": "0.18.0-dev.2", - "resolved": "https://registry.npmjs.org/@dashevo/dapi-grpc/-/dapi-grpc-0.18.0-dev.2.tgz", - "integrity": "sha512-0/530EWRMFLj1QBvfY+0CXHbuJjnWMDvCI+6GcFVzYprerIayQe9Wgr1l4gmplQjI06WJd+GXdk4W+mEpxImYQ==", + "version": "0.18.0-dev.3", + "resolved": "https://registry.npmjs.org/@dashevo/dapi-grpc/-/dapi-grpc-0.18.0-dev.3.tgz", + "integrity": "sha512-SX3ENFDV86ZuVDoB3VP7+GPbMcd0TMXDJih5/keOd5LMNX7DWgth1nmSPPVSLtr+EPTdRWqfV8AfbbYweOo/YQ==", "requires": { "@dashevo/grpc-common": "^0.3.0", "google-protobuf": "^3.12.2", "grpc": "^1.24.3", "grpc-web": "^1.2.0", "protobufjs": "github:jawid-h/protobuf.js#fix/buffer-conversion" - }, - "dependencies": { - "protobufjs": { - "version": "github:jawid-h/protobuf.js#8b91c72dca68fd6c418078fd2358c4969425dcdc", - "from": "github:jawid-h/protobuf.js#fix/buffer-conversion", - "requires": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/long": "^4.0.1", - "@types/node": "^13.7.0", - "long": "^4.0.0" - } - } } }, "@dashevo/dashcore-lib": { @@ -251,9 +210,9 @@ }, "dependencies": { "@types/node": { - "version": "12.19.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.13.tgz", - "integrity": "sha512-qdixo2f0U7z6m0UJUugTJqVF94GNDkdgQhfBtMs8t5898JE7G/D2kJYw4rc1nzjIPLVAsDkY2MdABnLAP5lM1w==" + "version": "12.19.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.15.tgz", + "integrity": "sha512-lowukE3GUI+VSYSu6VcBXl14d61Rp5hA1D+61r16qnwC0lYNSqdxcvRh0pswejorHfS+HgwBasM8jLXz0/aOsw==" }, "inherits": { "version": "2.0.1", @@ -263,9 +222,9 @@ } }, "@dashevo/dashd-rpc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@dashevo/dashd-rpc/-/dashd-rpc-2.0.2.tgz", - "integrity": "sha512-fbD+40fzVLHGliRoNd8kGqkoUkGeEKZOo2X5OhEkrUxDoGXTWRL4u0R/e72l57Oj8Aqfwh2S4dQ5gB7zu3AFhA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@dashevo/dashd-rpc/-/dashd-rpc-2.1.0.tgz", + "integrity": "sha512-5+cKTL0JC5irQjr479ovucZ5KS5Zv4+0nIATnKDnU3giHAVQlIDqrLnHbs/8TNEk9XXx4ZtUafhMOxXgwo2W2Q==", "requires": { "async": "^3.2.0", "bluebird": "^3.7.2" @@ -348,9 +307,9 @@ } }, "@types/node": { - "version": "12.19.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.13.tgz", - "integrity": "sha512-qdixo2f0U7z6m0UJUugTJqVF94GNDkdgQhfBtMs8t5898JE7G/D2kJYw4rc1nzjIPLVAsDkY2MdABnLAP5lM1w==", + "version": "12.19.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.19.15.tgz", + "integrity": "sha512-lowukE3GUI+VSYSu6VcBXl14d61Rp5hA1D+61r16qnwC0lYNSqdxcvRh0pswejorHfS+HgwBasM8jLXz0/aOsw==", "dev": true }, "inherits": { @@ -407,9 +366,9 @@ "integrity": "sha512-3vvnZweBca4URBXHF+FTrM4sdTpp3IMt73G1zUKQEdYm/kJkIKN94qpFai7YZDl87k64RCH+ckRZk6ruQPz5KQ==" }, "@grpc/proto-loader": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.5.tgz", - "integrity": "sha512-WwN9jVNdHRQoOBo9FDH7qU+mgfjPc8GygPYms3M+y3fbQLfnCe/Kv/E01t7JRgnrsOHH8euvSbed3mIalXhwqQ==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.5.6.tgz", + "integrity": "sha512-DT14xgw3PSzPxwS13auTEwxhMMOoz33DPUKNtmYK/QYbBSpLXJy78FGGs5yVoxVobEqPm4iW9MOIoz0A3bLTRQ==", "requires": { "lodash.camelcase": "^4.3.0", "protobufjs": "^6.8.6" @@ -531,9 +490,9 @@ "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" }, "@types/node": { - "version": "13.13.39", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.39.tgz", - "integrity": "sha512-wct+WgRTTkBm2R3vbrFOqyZM5w0g+D8KnhstG9463CJBVC3UVZHMToge7iMBR1vDl/I+NWFHUeK9X+JcF0rWKw==" + "version": "13.13.40", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.40.tgz", + "integrity": "sha512-eKaRo87lu1yAXrzEJl0zcJxfUMDT5/mZalFyOkT44rnQps41eS2pfWzbaulSPpQLFNy29bFqn+Y5lOTL8ATlEQ==" }, "@ungap/promise-all-settled": { "version": "1.1.2", @@ -732,9 +691,9 @@ "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, "aws-sdk": { - "version": "2.827.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.827.0.tgz", - "integrity": "sha512-71PWS1dqJ65/SeNgDQWEgbJ6oKCuB+Ypq30TM3EyzbAHaxl69WjQRK71oJ2bjhdIHfGQJtOV0G9wg4zpge4Erg==", + "version": "2.834.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.834.0.tgz", + "integrity": "sha512-9WRULrn4qAmgXI+tEW/IG5s/6ixJGZqjPOrmJsFZQev7/WRkxAZmJAjcwd4Ifm/jsJbXx2FSwO76gOPEvu2LqA==", "dev": true, "requires": { "buffer": "4.9.2", @@ -1587,23 +1546,25 @@ } }, "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", + "version": "1.18.0-next.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.2.tgz", + "integrity": "sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw==", "dev": true, "requires": { + "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2", "has": "^1.0.3", "has-symbols": "^1.0.1", "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", + "is-negative-zero": "^2.0.1", "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", + "object-inspect": "^1.9.0", "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.3", + "string.prototype.trimstart": "^1.0.3" } }, "es-to-primitive": { @@ -2256,9 +2217,9 @@ "dev": true }, "get-intrinsic": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.0.2.tgz", - "integrity": "sha512-aeX0vrFm21ILl3+JpFFRNe9aUvp6VFZb2/CTbgLb8j75kOhvoNYjt9d8KA/tJG4gSo8nzEDedRl0h7vDmBYRVg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.0.tgz", + "integrity": "sha512-M11rgtQp5GZMZzDL7jLTNxbDfurpzuau5uqRWDPvlHjfvg3TdScAZo96GLvhMjImrmR8uAt0FS2RLoMrfWGKlg==", "dev": true, "requires": { "function-bind": "^1.1.1", @@ -2662,9 +2623,9 @@ } }, "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", "dev": true }, "is-core-module": { @@ -2724,11 +2685,12 @@ "dev": true }, "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.2.tgz", + "integrity": "sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg==", "dev": true, "requires": { + "call-bind": "^1.0.2", "has-symbols": "^1.0.1" } }, @@ -2895,9 +2857,9 @@ }, "dependencies": { "@types/node": { - "version": "10.17.50", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.50.tgz", - "integrity": "sha512-vwX+/ija9xKc/z9VqMCdbf4WYcMTGsI0I/L/6shIF3qXURxZOhPQlPRHtjTpiNhAwn0paMJzlOQqw6mAGEQnTA==" + "version": "10.17.51", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.51.tgz", + "integrity": "sha512-KANw+MkL626tq90l++hGelbl67irOJzGhUJk6a1Bt8QHOeh9tztJx+L0AqttraWKinmZn7Qi5lJZJzx45Gq0dg==" }, "commander": { "version": "2.20.3", @@ -4284,9 +4246,9 @@ } }, "pathval": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", - "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true }, "performance-now": { @@ -4355,9 +4317,8 @@ "dev": true }, "protobufjs": { - "version": "6.10.1", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.10.1.tgz", - "integrity": "sha512-pb8kTchL+1Ceg4lFd5XUpK8PdWacbvV5SK2ULH2ebrYtl4GjJmS24m6CKME67jzV53tbJxHlnNOSqQHbTsR9JQ==", + "version": "github:jawid-h/protobuf.js#8b91c72dca68fd6c418078fd2358c4969425dcdc", + "from": "github:jawid-h/protobuf.js#fix/buffer-conversion", "requires": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", diff --git a/package.json b/package.json index d8fcf147c..91bbaee5b 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "all": true }, "dependencies": { - "@dashevo/dapi-grpc": "~0.18.0-dev.2", + "@dashevo/dapi-grpc": "~0.18.0-dev.3", "@dashevo/dashcore-lib": "~0.19.19", "@dashevo/dashd-rpc": "^2.0.2", "@dashevo/dpp": "~0.18.0-dev.1",