@gnolang/tm2-js-client
Version:
Tendermint2 JS / TS Client
649 lines (648 loc) • 26.4 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var crypto_1 = require("@cosmjs/crypto");
var jest_websocket_mock_1 = __importDefault(require("jest-websocket-mock"));
var long_1 = __importDefault(require("long"));
var proto_1 = require("../../proto");
var endpoints_1 = require("../endpoints");
var messages_1 = require("../errors/messages");
var types_1 = require("../types");
var utility_1 = require("../utility");
var ws_1 = require("./ws");
describe('WS Provider', function () {
var wsPort = 8545;
var wsHost = 'localhost';
var wsURL = "ws://".concat(wsHost, ":").concat(wsPort);
var server;
var wsProvider;
var mockABCIResponse = function (response) {
return {
response: {
ResponseBase: {
Log: '',
Info: '',
Data: (0, utility_1.stringToBase64)(response),
Error: null,
Events: null,
},
Key: null,
Value: null,
Proof: null,
Height: '',
},
};
};
/**
* Sets up the test response handler (single-response)
* @param {WebSocketServer} wss the websocket server returning data
* @param {Type} testData the test data being returned to the client
*/
var setHandler = function (testData) { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
server.on('connection', function (socket) {
socket.on('message', function (data) {
var request = JSON.parse(data.toString());
var response = (0, utility_1.newResponse)(testData);
response.id = request.id;
socket.send(JSON.stringify(response));
});
});
return [4 /*yield*/, server.connected];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); };
beforeEach(function () {
server = new jest_websocket_mock_1.default(wsURL);
wsProvider = new ws_1.WSProvider(wsURL);
});
afterEach(function () {
wsProvider.closeConnection();
jest_websocket_mock_1.default.clean();
});
test('estimateGas', function () { return __awaiter(void 0, void 0, void 0, function () {
var tx, expectedEstimation, mockSimulateResponseVale, mockABCIResponse, estimation;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
tx = proto_1.Tx.fromJSON({
signatures: [],
fee: {
gasFee: '',
gasWanted: new long_1.default(0),
},
messages: [],
memo: '',
});
expectedEstimation = 44900;
mockSimulateResponseVale = 'CiMiIW1zZzowLHN1Y2Nlc3M6dHJ1ZSxsb2c6LGV2ZW50czpbXRCAiXoYyL0F';
mockABCIResponse = {
response: {
Height: '',
Key: '',
Proof: null,
Value: mockSimulateResponseVale,
ResponseBase: {
Log: '',
Info: '',
Error: null,
Events: null,
Data: '',
},
},
};
// Set the response
return [4 /*yield*/, setHandler(mockABCIResponse)];
case 1:
// Set the response
_a.sent();
return [4 /*yield*/, wsProvider.estimateGas(tx)];
case 2:
estimation = _a.sent();
expect(estimation).toEqual(expectedEstimation);
return [2 /*return*/];
}
});
}); });
test('getNetwork', function () { return __awaiter(void 0, void 0, void 0, function () {
var mockInfo, info;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
mockInfo = {
listening: false,
listeners: [],
n_peers: '0',
peers: [],
};
// Set the response
return [4 /*yield*/, setHandler(mockInfo)];
case 1:
// Set the response
_a.sent();
return [4 /*yield*/, wsProvider.getNetwork()];
case 2:
info = _a.sent();
expect(info).toEqual(mockInfo);
return [2 /*return*/];
}
});
}); });
var getEmptyStatus = function () {
return {
node_info: {
version_set: [],
net_address: '',
network: '',
software: '',
version: '',
channels: '',
monkier: '',
other: {
tx_index: '',
rpc_address: '',
},
},
sync_info: {
latest_block_hash: '',
latest_app_hash: '',
latest_block_height: '',
latest_block_time: '',
catching_up: false,
},
validator_info: {
address: '',
pub_key: {
type: '',
value: '',
},
voting_power: '',
},
};
};
test('getStatus', function () { return __awaiter(void 0, void 0, void 0, function () {
var mockStatus, status;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
mockStatus = getEmptyStatus();
mockStatus.validator_info.address = 'address';
// Set the response
return [4 /*yield*/, setHandler(mockStatus)];
case 1:
// Set the response
_a.sent();
return [4 /*yield*/, wsProvider.getStatus()];
case 2:
status = _a.sent();
expect(status).toEqual(status);
return [2 /*return*/];
}
});
}); });
test('getConsensusParams', function () { return __awaiter(void 0, void 0, void 0, function () {
var mockParams, params;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
mockParams = {
block_height: '',
consensus_params: {
Block: {
MaxTxBytes: '',
MaxDataBytes: '',
MaxBlockBytes: '',
MaxGas: '',
TimeIotaMS: '',
},
Validator: {
PubKeyTypeURLs: [],
},
},
};
// Set the response
return [4 /*yield*/, setHandler(mockParams)];
case 1:
// Set the response
_a.sent();
return [4 /*yield*/, wsProvider.getConsensusParams(1)];
case 2:
params = _a.sent();
expect(params).toEqual(mockParams);
return [2 /*return*/];
}
});
}); });
describe('getSequence', function () {
var validAccount = {
BaseAccount: {
address: 'random address',
coins: '',
public_key: null,
account_number: '0',
sequence: '10',
},
};
test.each([
[
JSON.stringify(validAccount),
parseInt(validAccount.BaseAccount.sequence, 10),
], // account exists
['null', 0], // account doesn't exist
])('case %#', function (response, expected) { return __awaiter(void 0, void 0, void 0, function () {
var mockResponse, sequence;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
mockResponse = mockABCIResponse(response);
// Set the response
return [4 /*yield*/, setHandler(mockResponse)];
case 1:
// Set the response
_a.sent();
return [4 /*yield*/, wsProvider.getAccountSequence('address')];
case 2:
sequence = _a.sent();
expect(sequence).toBe(expected);
return [2 /*return*/];
}
});
}); });
});
describe('getAccountNumber', function () {
var validAccount = {
BaseAccount: {
address: 'random address',
coins: '',
public_key: null,
account_number: '10',
sequence: '0',
},
};
test.each([
[
JSON.stringify(validAccount),
parseInt(validAccount.BaseAccount.account_number, 10),
], // account exists
['null', 0], // account doesn't exist
])('case %#', function (response, expected) { return __awaiter(void 0, void 0, void 0, function () {
var mockResponse, accountNumber, e_1;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
mockResponse = mockABCIResponse(response);
// Set the response
return [4 /*yield*/, setHandler(mockResponse)];
case 1:
// Set the response
_a.sent();
_a.label = 2;
case 2:
_a.trys.push([2, 4, , 5]);
return [4 /*yield*/, wsProvider.getAccountNumber('address')];
case 3:
accountNumber = _a.sent();
expect(accountNumber).toBe(expected);
return [3 /*break*/, 5];
case 4:
e_1 = _a.sent();
expect(e_1.message).toContain('account is not initialized');
return [3 /*break*/, 5];
case 5: return [2 /*return*/];
}
});
}); });
});
describe('getAccount', function () {
var validAccount = {
BaseAccount: {
address: 'random address',
coins: '',
public_key: null,
account_number: '10',
sequence: '0',
},
};
test.each([
[JSON.stringify(validAccount), validAccount], // account exists
['null', null], // account doesn't exist
])('case %#', function (response, expected) { return __awaiter(void 0, void 0, void 0, function () {
var mockResponse, account, e_2;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
mockResponse = mockABCIResponse(response);
// Set the response
return [4 /*yield*/, setHandler(mockResponse)];
case 1:
// Set the response
_a.sent();
_a.label = 2;
case 2:
_a.trys.push([2, 4, , 5]);
return [4 /*yield*/, wsProvider.getAccount('address')];
case 3:
account = _a.sent();
expect(account).toStrictEqual(expected);
return [3 /*break*/, 5];
case 4:
e_2 = _a.sent();
expect(e_2.message).toContain('account is not initialized');
return [3 /*break*/, 5];
case 5: return [2 /*return*/];
}
});
}); });
});
describe('getBalance', function () {
var denomination = 'atom';
test.each([
['"5gnot,100atom"', 100], // balance found
['"5universe"', 0], // balance not found
['""', 0], // account doesn't exist
])('case %#', function (existing, expected) { return __awaiter(void 0, void 0, void 0, function () {
var mockResponse, balance;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
mockResponse = mockABCIResponse(existing);
// Set the response
return [4 /*yield*/, setHandler(mockResponse)];
case 1:
// Set the response
_a.sent();
return [4 /*yield*/, wsProvider.getBalance('address', denomination)];
case 2:
balance = _a.sent();
expect(balance).toBe(expected);
return [2 /*return*/];
}
});
}); });
});
test('getBlockNumber', function () { return __awaiter(void 0, void 0, void 0, function () {
var expectedBlockNumber, mockStatus, blockNumber;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
expectedBlockNumber = 10;
mockStatus = getEmptyStatus();
mockStatus.sync_info.latest_block_height = "".concat(expectedBlockNumber);
// Set the response
return [4 /*yield*/, setHandler(mockStatus)];
case 1:
// Set the response
_a.sent();
return [4 /*yield*/, wsProvider.getBlockNumber()];
case 2:
blockNumber = _a.sent();
expect(blockNumber).toBe(expectedBlockNumber);
return [2 /*return*/];
}
});
}); });
describe('sendTransaction', function () {
var _a;
var validResult = {
error: null,
data: null,
Log: '',
hash: 'hash123',
};
var mockError = '/std.UnauthorizedError';
var mockLog = 'random error message';
var invalidResult = {
error: (_a = {},
_a[types_1.ABCIErrorKey] = mockError,
_a),
data: null,
Log: mockLog,
hash: '',
};
test.each([
[validResult, validResult.hash, '', ''], // no error
[invalidResult, invalidResult.hash, messages_1.UnauthorizedErrorMessage, mockLog], // error out
])('case %#', function (response, expectedHash, expectedErr, expectedLog) { return __awaiter(void 0, void 0, void 0, function () {
var tx, e_3;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, setHandler(response)];
case 1:
_a.sent();
_a.label = 2;
case 2:
_a.trys.push([2, 4, , 5]);
return [4 /*yield*/, wsProvider.sendTransaction('encoded tx', endpoints_1.TransactionEndpoint.BROADCAST_TX_SYNC)];
case 3:
tx = _a.sent();
expect(tx.hash).toEqual(expectedHash);
if (expectedErr != '') {
fail('expected error');
}
return [3 /*break*/, 5];
case 4:
e_3 = _a.sent();
expect(e_3.message).toBe(expectedErr);
expect(e_3.log).toBe(expectedLog);
return [3 /*break*/, 5];
case 5: return [2 /*return*/];
}
});
}); });
});
var getEmptyBlockInfo = function () {
var emptyHeader = {
version: '',
chain_id: '',
height: '',
time: '',
num_txs: '',
total_txs: '',
app_version: '',
last_block_id: {
hash: null,
parts: {
total: '',
hash: null,
},
},
last_commit_hash: '',
data_hash: '',
validators_hash: '',
consensus_hash: '',
app_hash: '',
last_results_hash: '',
proposer_address: '',
};
var emptyBlockID = {
hash: null,
parts: {
total: '',
hash: null,
},
};
return {
block_meta: {
block_id: emptyBlockID,
header: emptyHeader,
},
block: {
header: emptyHeader,
data: {
txs: null,
},
last_commit: {
block_id: emptyBlockID,
precommits: null,
},
},
};
};
test('getBlock', function () { return __awaiter(void 0, void 0, void 0, function () {
var mockInfo, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
mockInfo = getEmptyBlockInfo();
// Set the response
return [4 /*yield*/, setHandler(mockInfo)];
case 1:
// Set the response
_a.sent();
return [4 /*yield*/, wsProvider.getBlock(0)];
case 2:
result = _a.sent();
expect(result).toEqual(mockInfo);
return [2 /*return*/];
}
});
}); });
var getEmptyBlockResult = function () {
var emptyResponseBase = {
Error: null,
Data: null,
Events: null,
Log: '',
Info: '',
};
var emptyEndBlock = {
ResponseBase: emptyResponseBase,
ValidatorUpdates: null,
ConsensusParams: null,
Events: null,
};
var emptyStartBlock = {
ResponseBase: emptyResponseBase,
};
return {
height: '',
results: {
deliver_tx: null,
end_block: emptyEndBlock,
begin_block: emptyStartBlock,
},
};
};
test('getBlockResult', function () { return __awaiter(void 0, void 0, void 0, function () {
var mockResult, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
mockResult = getEmptyBlockResult();
// Set the response
return [4 /*yield*/, setHandler(mockResult)];
case 1:
// Set the response
_a.sent();
return [4 /*yield*/, wsProvider.getBlockResult(0)];
case 2:
result = _a.sent();
expect(result).toEqual(mockResult);
return [2 /*return*/];
}
});
}); });
test('waitForTransaction', function () { return __awaiter(void 0, void 0, void 0, function () {
var emptyBlock, tx, encodedTx, txHash, filledBlock, latestBlock, startBlock, mockStatus, responseMap, receivedTx;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
emptyBlock = getEmptyBlockInfo();
emptyBlock.block.data = {
txs: [],
};
tx = {
messages: [],
signatures: [],
memo: 'tx memo',
};
encodedTx = proto_1.Tx.encode(tx).finish();
txHash = (0, crypto_1.sha256)(encodedTx);
filledBlock = getEmptyBlockInfo();
filledBlock.block.data = {
txs: [(0, utility_1.uint8ArrayToBase64)(encodedTx)],
};
latestBlock = 5;
startBlock = latestBlock - 2;
mockStatus = getEmptyStatus();
mockStatus.sync_info.latest_block_height = "".concat(latestBlock);
responseMap = new Map([
[latestBlock, filledBlock],
[latestBlock - 1, emptyBlock],
[startBlock, emptyBlock],
]);
// Set the response
server.on('connection', function (socket) {
socket.on('message', function (data) {
var request = JSON.parse(data.toString());
if (request.method == endpoints_1.CommonEndpoint.STATUS) {
var response_1 = (0, utility_1.newResponse)(mockStatus);
response_1.id = request.id;
socket.send(JSON.stringify(response_1));
return;
}
if (!request.params) {
return;
}
var blockNum = +request.params[0];
var info = responseMap.get(blockNum);
var response = (0, utility_1.newResponse)(info);
response.id = request.id;
socket.send(JSON.stringify(response));
});
});
return [4 /*yield*/, server.connected];
case 1:
_a.sent();
return [4 /*yield*/, wsProvider.waitForTransaction((0, utility_1.uint8ArrayToBase64)(txHash), startBlock)];
case 2:
receivedTx = _a.sent();
expect(receivedTx).toEqual(tx);
return [2 /*return*/];
}
});
}); });
});