Skip to content
This repository has been archived by the owner on Dec 16, 2021. It is now read-only.

Commit

Permalink
feat: waitForStateTransactionResult checks existing result (#341)
Browse files Browse the repository at this point in the history
  • Loading branch information
shumkov committed Feb 25, 2021
1 parent 8fed086 commit 18eb575
Show file tree
Hide file tree
Showing 21 changed files with 595 additions and 527 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const crypto = require('crypto');

const EventEmitter = require('events');

const TX_QUERY = 'tm.event = \'Tx\'';
Expand Down Expand Up @@ -27,15 +25,6 @@ class BlockchainListener extends EventEmitter {
return `transaction:${transactionHashString}`;
}

/**
*
* @param transactionHashString
* @return {string}
*/
static getTransactionAddedToTheBlockEventName(transactionHashString) {
return `blockTransactionAdded:${transactionHashString}`;
}

/**
* Subscribe to blocks and transaction results
*/
Expand All @@ -54,23 +43,7 @@ class BlockchainListener extends EventEmitter {

// Emit blocks and contained transactions
this.wsClient.subscribe(NEW_BLOCK_QUERY);
this.wsClient.on(NEW_BLOCK_QUERY, (message) => {
this.emit(EVENTS.NEW_BLOCK, message);

// Emit transaction hashes from block
message.data.value.block.data.txs.forEach((base64tx) => {
const transaction = Buffer.from(base64tx, 'base64');
const hashString = crypto.createHash('sha256')
.update(transaction)
.digest()
.toString('hex');

this.emit(
BlockchainListener.getTransactionAddedToTheBlockEventName(hashString),
transaction,
);
});
});
this.wsClient.on(NEW_BLOCK_QUERY, message => this.emit(EVENTS.NEW_BLOCK, message));
}
}

Expand Down

This file was deleted.

This file was deleted.

41 changes: 41 additions & 0 deletions lib/externalApis/tenderdash/waitForHeightFactory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const BlockchainListener = require('./BlockchainListener');

/**
* @param {BlockchainListener} blockchainListener
*/
function waitForHeightFactory(blockchainListener) {
let currentHeight = 0;

blockchainListener.on(BlockchainListener.EVENTS.NEW_BLOCK, (message) => {
currentHeight = parseInt(message.data.value.block.header.height, 10);
});

/**
* @typedef {waitForHeight}
* @param {number} height
* @return {Promise<void>}
*/
function waitForHeight(height) {
return new Promise((resolve) => {
if (currentHeight >= height) {
resolve();

return;
}

const handler = () => {
if (currentHeight >= height) {
blockchainListener.off(BlockchainListener.EVENTS.NEW_BLOCK, handler);

resolve();
}
};

blockchainListener.on(BlockchainListener.EVENTS.NEW_BLOCK, handler);
});
}

return waitForHeight;
}

module.exports = waitForHeightFactory;
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const TransactionOkResult = require('./transactionResult/TransactionOkResult');
const TransactionErrorResult = require('./transactionResult/TransactionErrorResult');
const RPCError = require('../../../rpcServer/RPCError');

/**
* @param {RpcClient} rpcClient
* @return {getExistingTransactionResult}
*/
function getExistingTransactionResultFactory(rpcClient) {
/**
* @typedef {getExistingTransactionResult}
* @param {string} hashString
* @return {Promise<TransactionOkResult|TransactionErrorResult>}
*/
async function getExistingTransactionResult(hashString) {
const hash = Buffer.from(hashString, 'hex');

const params = { hash: hash.toString('base64') };

const { result, error } = await rpcClient.request('tx', params);

// Handle JSON RPC error
if (error) {
throw new RPCError(
error.code || -32602,
error.message || 'Internal error',
error.data,
);
}

const TransactionResultClass = result.tx_result.code === 0
? TransactionOkResult
: TransactionErrorResult;

return new TransactionResultClass(
result.tx_result,
parseInt(result.height, 10),
Buffer.from(result.tx, 'base64'),
);
}

return getExistingTransactionResult;
}

module.exports = getExistingTransactionResultFactory;
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
class AbstractTransactionResult {
/**
* @param {Object} deliverResult
* @param {Object} result
* @param {number} height
* @param {Buffer} transaction
*/
constructor(deliverResult, transaction) {
this.deliverResult = deliverResult;
constructor(result, height, transaction) {
this.deliverResult = result;
this.height = height;
this.transaction = transaction;
}

Expand All @@ -13,10 +15,19 @@ class AbstractTransactionResult {
*
* @return {Object}
*/
getDeliverResult() {
getResult() {
return this.deliverResult;
}

/**
* Get transaction block height
*
* @return {number}
*/
getHeight() {
return this.height;
}

/**
* Get transaction
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,25 @@ function waitForTransactionResult(blockchainListener, hashString) {

let handler;

const promise = new Promise((resolve, reject) => {
const promise = new Promise((resolve) => {
handler = ({ data: { value: { TxResult: txResult } } }) => {
blockchainListener.off(topic, handler);

const { result: deliverResult, tx } = txResult;
const { result: deliverResult, tx, height } = txResult;

const txBuffer = Buffer.from(tx, 'base64');

let TransactionResultClass = TransactionOkResult;
if (deliverResult && deliverResult.code !== undefined && deliverResult.code !== 0) {
// If a transaction result is error we don't need to wait for next block
return reject(
new TransactionErrorResult(deliverResult, txBuffer),
);
TransactionResultClass = TransactionErrorResult;
}

return resolve(
new TransactionOkResult(deliverResult, txBuffer),
resolve(
new TransactionResultClass(
deliverResult,
parseInt(height, 10),
txBuffer,
),
);
};

Expand Down
Loading

0 comments on commit 18eb575

Please sign in to comment.