bitcore-node
Version:
A blockchain indexing node with extended capabilities using bitcore
303 lines • 12.4 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = require("chai");
const sinon_1 = __importDefault(require("sinon"));
const io = __importStar(require("socket.io-client"));
const config_1 = __importDefault(require("../../src/config"));
const p2p_1 = require("../../src/modules/bitcoin/p2p");
const rpc_1 = require("../../src/rpc");
const api_1 = require("../../src/services/api");
const event_1 = require("../../src/services/event");
const helpers_1 = require("../helpers");
const { PrivateKey } = require('bitcore-lib');
const chain = 'BTC';
const network = 'regtest';
const chainConfig = config_1.default.chains[chain][network];
const creds = chainConfig.rpc;
const rpc = new rpc_1.AsyncRPC(creds.username, creds.password, creds.host, creds.port);
const bitcore_client_1 = require("bitcore-client");
const wallet_1 = require("../../src/models/wallet");
const walletAddress_1 = require("../../src/models/walletAddress");
const socket_1 = require("../../src/services/socket");
const utils_1 = require("../../src/utils");
const integration_1 = require("../helpers/integration");
function getSocket() {
const socket = io.connect('http://localhost:3000', { transports: ['websocket'] });
return socket;
}
let p2pWorker;
let socket = getSocket();
const bwsPrivKey = new PrivateKey();
const bwsKey = bwsPrivKey.publicKey.toString('hex');
const authKey = new PrivateKey();
const pubKey = authKey.publicKey.toString('hex');
const address = '2MuYKLUaKCenkEpwPkWUwYpBoDBNA2dgY3t';
const sandbox = sinon_1.default.createSandbox();
describe('Websockets', function () {
const suite = this;
this.timeout(60000);
before(async () => {
(0, integration_1.intBeforeHelper)();
sandbox.stub(socket_1.Socket.serviceConfig, 'bwsKeys').value([bwsKey]);
await (0, helpers_1.resetDatabase)();
await event_1.Event.start();
await api_1.Api.start();
const inserted = await wallet_1.WalletStorage.collection.insertOne({
chain,
network,
name: 'WalletSocketTest',
singleAddress: false,
pubKey,
path: ''
});
await walletAddress_1.WalletAddressStorage.collection.insertOne({
address,
chain,
network,
processed: true,
wallet: inserted.insertedId
});
});
after(async () => {
await event_1.Event.stop();
await api_1.Api.stop();
await (0, helpers_1.resetDatabase)();
await (0, integration_1.intAfterHelper)(suite);
});
beforeEach(async () => {
socket = getSocket();
const connected = new Promise(r => {
socket.on('connect', () => {
console.log('Socket connected');
r();
});
});
await connected;
p2pWorker = new p2p_1.BitcoinP2PWorker({
chain,
network,
chainConfig
});
console.log('Starting p2p worker');
p2pWorker.start();
if (p2pWorker.isSyncing) {
console.log('Worker is syncing. Waiting til done');
await p2pWorker.syncDone();
}
console.log('Waiting til p2p done');
await p2pWorker.waitTilSync();
console.log('P2P done');
});
afterEach(async () => {
try {
console.log('Stopping p2p worker');
await p2pWorker.stop();
console.log('Disconnecting socket');
await socket.disconnect();
}
catch (e) {
console.log('Error stopping p2p worker');
}
});
it('should get websocket events', async () => {
socket.emit('room', '/BTC/regtest/inv');
let hasSeenTxEvent = false;
let hasSeenBlockEvent = false;
let hasSeenCoinEvent = false;
const anAddress = await rpc.getnewaddress('');
let sawEvents = new Promise(async (resolve) => {
socket.on('block', () => {
hasSeenBlockEvent = true;
console.log('Block event received');
if (hasSeenTxEvent && hasSeenCoinEvent && hasSeenBlockEvent) {
resolve();
}
});
socket.on('tx', () => {
hasSeenTxEvent = true;
console.log('Transaction event received');
if (hasSeenTxEvent && hasSeenCoinEvent && hasSeenBlockEvent) {
resolve();
}
});
socket.on('coin', () => {
hasSeenCoinEvent = true;
console.log('Coin event received');
if (hasSeenTxEvent && hasSeenCoinEvent && hasSeenBlockEvent) {
resolve();
}
});
while (!hasSeenBlockEvent) {
console.log('WAITING FOR BLOCK EVENT ON SOCKET');
if (hasSeenTxEvent && hasSeenCoinEvent && hasSeenBlockEvent) {
return resolve();
}
await (0, utils_1.wait)(1000);
}
});
console.log('Generating 100 blocks');
await rpc.call('generatetoaddress', [101, anAddress]);
await p2pWorker.syncDone();
console.log('Sync done, generating new block');
await rpc.call('generatetoaddress', [1, anAddress]);
console.log('Sending bitcoin');
await rpc.sendtoaddress(address, 0.1);
await sawEvents;
(0, chai_1.expect)(hasSeenBlockEvent).to.equal(true);
(0, chai_1.expect)(hasSeenTxEvent).to.equal(true);
(0, chai_1.expect)(hasSeenCoinEvent).to.equal(true);
});
it('should get wallet events', async () => {
const authClient = new bitcore_client_1.Client({ apiUrl: 'http://localhost:3000/api', authKey });
const payload = { method: 'socket', url: 'http://localhost:3000/api' };
const authPayload = { pubKey, message: authClient.getMessage(payload), signature: authClient.sign(payload) };
const chain = 'BTC';
const network = 'regtest';
const roomPrefix = `/${chain}/${network}/`;
socket.emit('room', roomPrefix + 'wallet', authPayload);
let hasSeenTxEvent = false;
let hasSeenCoinEvent = false;
let sawEvents = new Promise(async (resolve) => {
socket.on('tx', () => {
hasSeenTxEvent = true;
console.log('Transaction event received');
if (hasSeenTxEvent && hasSeenCoinEvent) {
resolve();
}
});
socket.on('coin', () => {
hasSeenCoinEvent = true;
console.log('Coin event received');
if (hasSeenTxEvent && hasSeenCoinEvent) {
resolve();
}
});
while (!hasSeenTxEvent) {
console.log('WAITING FOR TX EVENT ON SOCKET');
if (hasSeenTxEvent && hasSeenCoinEvent) {
return resolve();
}
await (0, utils_1.wait)(1000);
}
});
await rpc.sendtoaddress(address, 0.1);
await sawEvents;
(0, chai_1.expect)(hasSeenTxEvent).to.equal(true);
(0, chai_1.expect)(hasSeenCoinEvent).to.equal(true);
});
it('should get all wallet events', async () => {
const authClient = new bitcore_client_1.Client({ apiUrl: 'http://localhost:3000/api', authKey: bwsPrivKey });
const payload = { method: 'socket', url: 'http://localhost:3000/api' };
const authPayload = {
pubKey: bwsKey,
message: authClient.getMessage(payload),
signature: authClient.sign(payload)
};
const chain = 'BTC';
const network = 'regtest';
const roomPrefix = `/${chain}/${network}/`;
socket.emit('room', roomPrefix + 'wallets', authPayload);
let hasSeenTxEvent = false;
let hasSeenCoinEvent = false;
let sawEvents = new Promise(async (resolve) => {
socket.on('tx', () => {
hasSeenTxEvent = true;
console.log('Transaction event received');
if (hasSeenTxEvent && hasSeenCoinEvent) {
resolve();
}
});
socket.on('coin', () => {
hasSeenCoinEvent = true;
console.log('Coin event received');
if (hasSeenTxEvent && hasSeenCoinEvent) {
resolve();
}
});
while (!hasSeenTxEvent) {
console.log('WAITING FOR Wallet-TX EVENT ON SOCKET');
if (hasSeenTxEvent && hasSeenCoinEvent) {
return resolve();
}
await (0, utils_1.wait)(1000);
}
});
await rpc.sendtoaddress(address, 0.1);
await sawEvents;
(0, chai_1.expect)(hasSeenTxEvent).to.equal(true);
(0, chai_1.expect)(hasSeenCoinEvent).to.equal(true);
sandbox.restore();
});
it('should get an error when the key does not match the bwsKey', async () => {
const pubKey = authKey.publicKey.toString('hex');
const wrongKey = new PrivateKey();
const authClient = new bitcore_client_1.Client({ apiUrl: 'http://localhost:3000/api', authKey: wrongKey });
const payload = { method: 'socket', url: 'http://localhost:3000/api' };
const authPayload = { pubKey, message: authClient.getMessage(payload), signature: authClient.sign(payload) };
const chain = 'BTC';
const network = 'regtest';
const roomPrefix = `/${chain}/${network}/`;
let failed = new Promise(resolve => {
socket.on('failure', e => {
(0, chai_1.expect)(e.message).to.include('Authentication failed');
resolve();
});
});
socket.emit('room', roomPrefix + 'wallets', authPayload);
await failed;
});
it('should get an error when the signature is invalid', async () => {
const wrongKey = new PrivateKey();
const authClient = new bitcore_client_1.Client({ apiUrl: 'http://localhost:3000/api', authKey: wrongKey });
const payload = { method: 'socket', url: 'http://localhost:3000/api' };
const authPayload = { pubKey, message: authClient.getMessage(payload), signature: 'invalid' };
const chain = 'BTC';
const network = 'regtest';
const roomPrefix = `/${chain}/${network}/`;
let failed = new Promise(resolve => {
socket.on('failure', e => {
(0, chai_1.expect)(e.message).to.include('Authentication failed');
resolve();
});
});
socket.emit('room', roomPrefix + 'wallet', authPayload);
await failed;
});
});
//# sourceMappingURL=websocket.spec.js.map