UNPKG

foundation-server

Version:

An extremely efficient, highly scalable, all-in-one, easy to setup cryptocurrency mining pool

1,009 lines (939 loc) 93.2 kB
/* * * Payments (Updated) * */ const MockDate = require('mockdate'); const redis = require('redis-mock'); jest.mock('redis', () => jest.requireActual('redis-mock')); const nock = require('nock'); const mockDaemon = require('./daemon.mock.js'); const mockPayments = require('./payments.mock.js'); const PoolLogger = require('../main/logger'); const PoolPayments = require('../main/payments'); const Stratum = require('foundation-stratum'); const poolConfig = require('../../configs/pools/example.js'); const portalConfig = require('../../configs/main/example.js'); poolConfig.primary.address = 'tb1qcc0lzt4fftzmpxuye6q8vnfngu03yuwpasu0dw'; poolConfig.primary.recipients[0].address = 'tb1qcc0lzt4fftzmpxuye6q8vnfngu03yuwpasu0dw'; poolConfig.p2p.enabled = false; const client = redis.createClient({ 'port': portalConfig.redis.port, 'host': portalConfig.redis.host, }); client._maxListeners = 0; client._redisMock._maxListeners = 0; nock.disableNetConnect(); nock.enableNetConnect('127.0.0.1'); process.env.poolConfigs = JSON.stringify({ Pool1: poolConfig }); process.env.portalConfig = JSON.stringify(portalConfig); const logger = new PoolLogger(portalConfig); //////////////////////////////////////////////////////////////////////////////// function mockBuildBlock(height, hash, reward, transaction, difficulty, worker, solo) { return JSON.stringify({ height: height, hash: hash, reward: reward, transaction: transaction, difficulty: difficulty, worker: worker, solo: solo, }); } function mockSetupClient(client, commands, coin, callback) { client.multi(commands).exec(() => callback()); } //////////////////////////////////////////////////////////////////////////////// /* eslint-disable no-unused-vars */ describe('Test payments functionality', () => { beforeEach((done) => { client.flushall(() => done()); }); test('Test initialization of payments', () => { const poolPayments = new PoolPayments(logger, client); expect(typeof poolPayments.portalConfig).toBe('object'); expect(typeof poolPayments.handleManagement).toBe('function'); expect(typeof poolPayments.handleIntervals).toBe('function'); }); test('Test round shares if deleteable [1]', () => { const poolPayments = new PoolPayments(logger, client); const rounds = [ { height: 180, category: 'immature', serialized: 'test' }, { height: 181, category: 'immature', serialized: 'test' }, { height: 182, category: 'immature', serialized: 'test' }]; expect(poolPayments.checkShares(rounds, {})).toBe(true); }); test('Test round shares if deleteable [2]', () => { const poolPayments = new PoolPayments(logger, client); const rounds = [ { height: 180, category: 'immature', serialized: 'test' }, { height: 181, category: 'immature', serialized: 'test' }, { height: 182, category: 'immature', serialized: 'test' }]; const round = { height: 180, category: 'immature', serialized: 'hmm' }; expect(poolPayments.checkShares(rounds, round)).toBe(false); }); test('Test address validation functionality [1]', (done) => { mockDaemon.mockValidateAddress(); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.checkAddress(daemon, 'test', 'validateaddress', (error, results) => { expect(error).toBe(true); expect(results).toBe('The daemon does not own the pool address listed'); nock.cleanAll(); done(); }); }); test('Test address validation functionality [2]', (done) => { mockDaemon.mockValidateAddressError(); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.checkAddress(daemon, 'test', 'validateaddress', (error, results) => { expect(error).toBe(true); expect(results).toBe('{"error":true}'); nock.cleanAll(); done(); }); }); test('Test address validation functionality [3]', (done) => { mockDaemon.mockValidateAddressSecondary(); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.checkAddress(daemon, 'test', 'validateaddress', (error, results) => { expect(error).toBe(null); expect(typeof results).toBe('undefined'); nock.cleanAll(); done(); }); }); test('Test address validation functionality [4]', (done) => { mockDaemon.mockGetAddressInfo(); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.handleAddress(daemon, 'test', 'Bitcoin', (error, results) => { expect(error).toBe(null); expect(results).toStrictEqual([]); nock.cleanAll(); done(); }); }); test('Test address validation functionality [5]', (done) => { mockDaemon.mockValidateAddressSecondary(); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.handleAddress(daemon, 'test', 'Bitcoin', (error, results) => { expect(error).toBe(null); expect(results).toStrictEqual([]); nock.cleanAll(); done(); }); }); test('Test address validation functionality [6]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.handleAddress(daemon, 'test', 'Bitcoin', (error, results) => { expect(error).toBe(true); expect(results).toStrictEqual([]); console.log.mockClear(); nock.cleanAll(); done(); }); }); test('Test balance retrieval from daemon [1]', (done) => { mockDaemon.mockGetBalance(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.handleBalance(daemon, poolConfig, 'Bitcoin', 'primary', (error, results) => { expect(error).toBe(null); expect(results[0]).toBe(100000000); expect(results[1]).toBe(500000); expect(results[2]).toBe(8); console.log.mockClear(); nock.cleanAll(); done(); }); }); test('Test balance retrieval from daemon [2]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.handleBalance(daemon, poolConfig, 'Bitcoin', 'primary', (error, results) => { expect(error).toBe(true); expect(results).toStrictEqual([]); console.log.mockClear(); nock.cleanAll(); done(); }); }); test('Test balance retrieval from daemon [3]', (done) => { mockDaemon.mockGetBalanceInvalid(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.handleBalance(daemon, poolConfig, 'Bitcoin', 'primary', (error, results) => { expect(error).toBe(true); expect(results).toStrictEqual([]); console.log.mockClear(); nock.cleanAll(); done(); }); }); test('Test balance retrieval from daemon [4]', (done) => { mockDaemon.mockGetBalanceInvalid(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.handleBalance(daemon, poolConfig, 'Bitcoin', 'auxiliary', (error, results) => { expect(error).toBe(true); expect(results).toStrictEqual([]); console.log.mockClear(); nock.cleanAll(); done(); }); }); test('Test handling of orphan shares/times [1]', (done) => { MockDate.set(1637878085886); const poolPayments = new PoolPayments(logger, client); const round = { orphanShares: { 'example': 8 }, orphanTimes: { 'example': 1 }}; const expected = [ ['hincrby', 'Pool1:rounds:primary:current:shared:counts', 'valid', 1], ['hset', 'Pool1:rounds:primary:current:shared:shares', 'example', '{"time":1637878085886,"effort":0,"identifier":null,"round":"orphan","solo":false,"times":1,"types":{"valid":1,"invalid":0,"stale":0},"work":8,"worker":"example"}']]; poolPayments.handleOrphans(round, 'Pool1', 'primary', (error, results) => { expect(error).toBe(null); expect(results).toStrictEqual(expected); done(); }); }); test('Test handling of orphan shares/times [2]', (done) => { MockDate.set(1637878085886); const poolPayments = new PoolPayments(logger, client); const round = { orphanShares: { 'example': 8 }, orphanTimes: {}}; const expected = [ ['hincrby', 'Pool1:rounds:primary:current:shared:counts', 'valid', 1], ['hset', 'Pool1:rounds:primary:current:shared:shares', 'example', '{"time":1637878085886,"effort":0,"identifier":null,"round":"orphan","solo":false,"times":0,"types":{"valid":1,"invalid":0,"stale":0},"work":8,"worker":"example"}']]; poolPayments.handleOrphans(round, 'Pool1', 'primary', (error, results) => { expect(error).toBe(null); expect(results).toStrictEqual(expected); done(); }); }); test('Test handling of orphan shares/times [3]', (done) => { const poolPayments = new PoolPayments(logger, client); poolPayments.handleOrphans({}, 'Bitcoin', 'primary', (error, results) => { expect(error).toBe(null); expect(results).toStrictEqual([]); done(); }); }); test('Test calculation of unspent inputs in daemon [1]', (done) => { mockDaemon.mockListUnspent(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); const config = poolPayments.poolConfigs['Pool1']; poolPayments.handleUnspent(daemon, config, 'checks', 'Bitcoin', 'primary', (error, results) => { expect(results[0]).toBe(2375000000); console.log.mockClear(); nock.cleanAll(); done(); }); }); test('Test calculation of unspent inputs in daemon [2]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); const config = poolPayments.poolConfigs['Pool1']; poolPayments.handleUnspent(daemon, config, 'checks', 'Bitcoin', 'primary', (error, results) => { expect(error).toBe(true); expect(results.length).toBe(0); console.log.mockClear(); nock.cleanAll(); done(); }); }); test('Test calculation of unspent inputs in daemon [3]', (done) => { mockDaemon.mockListUnspentEmpty(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); const config = poolPayments.poolConfigs['Pool1']; poolPayments.handleUnspent(daemon, config, 'checks', 'Bitcoin', 'primary', (error, results) => { expect(error).toBe(null); expect(results[0]).toBe(0); console.log.mockClear(); nock.cleanAll(); done(); }); }); test('Test calculation of unspent inputs in daemon [4]', (done) => { mockDaemon.mockListUnspentInvalid(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); const config = poolPayments.poolConfigs['Pool1']; poolPayments.handleUnspent(daemon, config, 'checks', 'Bitcoin', 'primary', (error, results) => { expect(error).toBe(null); expect(results[0]).toBe(0); console.log.mockClear(); nock.cleanAll(); done(); }); }); test('Test calculation of unspent inputs in daemon [5]', (done) => { mockDaemon.mockListUnspent(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); const config = poolPayments.poolConfigs['Pool1']; poolPayments.handleUnspent(daemon, config, 'start', 'Bitcoin', 'primary', (error, results) => { expect(error).toBe(null); expect(consoleSpy).toHaveBeenCalledWith(expect.stringMatching('Bitcoin wallet has a balance of 23.75 BTC')); expect(results[0]).toBe(2375000000); console.log.mockClear(); nock.cleanAll(); done(); }); }); test('Test calculation of unspent inputs in daemon [5]', (done) => { mockDaemon.mockListUnspent(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].auxiliary = { coin: { name: 'Bitcoin', symbol: 'BTC' }, payments: {} }; poolPayments.poolConfigs['Pool1'].auxiliary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].auxiliary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].auxiliary.payments.coinPrecision = 8; const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); const config = poolPayments.poolConfigs['Pool1']; poolPayments.handleUnspent(daemon, config, 'start', 'Bitcoin', 'auxiliary', (error, results) => { expect(error).toBe(null); expect(consoleSpy).toHaveBeenCalledWith(expect.stringMatching('Bitcoin wallet has a balance of 23.75 BTC')); expect(results[0]).toBe(2375000000); console.log.mockClear(); nock.cleanAll(); done(); }); }); test('Test handling of duplicate rounds [1]', (done) => { mockDaemon.mockDuplicateRounds(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); const rounds = [ { hash: 'abcd', height: 180, duplicate: true }, { hash: 'abce', height: 180, duplicate: true }, { hash: 'abcf', height: 181, duplicate: false }]; poolPayments.handleDuplicates(daemon, rounds, 'Bitcoin', 'primary', (error, results) => { expect(error).toBe(null); expect(results[0].length).toBe(1); expect(results[0][0].hash).toBe('abcf'); expect(results[0][0].duplicate).toBe(false); console.log.mockClear(); nock.cleanAll(); done(); }); }); test('Test handling of duplicate rounds [2]', (done) => { const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.handleDuplicates(daemon, [], 'Bitcoin', 'primary', (error, results) => { expect(error).toBe(true); expect(results).toStrictEqual([]); done(); }); }); test('Test handling of duplicate rounds [3]', (done) => { mockDaemon.mockDuplicateBlocks(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); const rounds = [ { hash: 'abcd', height: 180, duplicate: true }, { hash: 'abcd', height: 180, duplicate: true }, { hash: 'abcf', height: 181, duplicate: false }]; poolPayments.handleDuplicates(daemon, rounds, 'Bitcoin', 'primary', (error, results) => { expect(error).toBe(null); expect(results[0].length).toBe(1); expect(results[0][0].hash).toBe('abcf'); expect(results[0][0].duplicate).toBe(false); console.log.mockClear(); nock.cleanAll(); done(); }); }); test('Test handling of duplicate rounds [4]', (done) => { mockDaemon.mockDuplicateBlocks(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); const rounds = [ { hash: 'abcd', height: 180, duplicate: true }, { hash: 'abce', height: 181, duplicate: true }, { hash: 'abcf', height: 182, duplicate: false }]; poolPayments.handleDuplicates(daemon, rounds, 'Bitcoin', 'primary', (error, results) => { expect(error).toBe(null); expect(results[0].length).toBe(1); expect(results[0][0].hash).toBe('abcf'); expect(results[0][0].duplicate).toBe(false); console.log.mockClear(); nock.cleanAll(); done(); }); }); test('Test handling of immature blocks [1]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.payments.processingFee = parseFloat(0.0004); const config = poolPayments.poolConfigs['Pool1']; const round = { reward: 12.50, solo: false, worker: 'example' }; poolPayments.handleImmature(config, round, {}, { 'example': 20.15 }, 20.15, {}, { 'example': 8 }, 'primary', (error, results) => { expect(error).toBe(null); expect(results[0]['example'].immature).toBe(1249960000); expect(results[0]['example'].shares.round).toBe(8); console.log.mockClear(); done(); }); }); test('Test handling of immature blocks [2]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.payments.processingFee = parseFloat(0.0004); const config = poolPayments.poolConfigs['Pool1']; const round = { reward: 12.50, solo: false, worker: 'example' }; poolPayments.handleImmature(config, round, {}, { 'example': 20.15 }, 20.15, {}, {}, 'primary', (error, results) => { expect(error).toBe(null); expect(results[0]).toStrictEqual({}); console.log.mockClear(); done(); }); }); test('Test handling of immature blocks [3]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.payments.processingFee = parseFloat(0.0004); const config = poolPayments.poolConfigs['Pool1']; const round = { reward: 12.50, solo: true, worker: 'example' }; poolPayments.handleImmature(config, round, {}, { 'example': 20.15 }, 20.15, { 'example': 8 }, {}, 'primary', (error, results) => { expect(error).toBe(null); expect(results[0]['example'].immature).toBe(1249960000); expect(results[0]['example'].shares.round).toBe(8); console.log.mockClear(); done(); }); }); test('Test handling of immature blocks [4]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.payments.processingFee = parseFloat(0.0004); const config = poolPayments.poolConfigs['Pool1']; const round = { reward: 12.50, solo: true, worker: 'example' }; poolPayments.handleImmature(config, round, {}, { 'example': 20.15 }, 20.15, {}, {}, 'primary', (error, results) => { expect(error).toBe(null); expect(results[0]['example'].immature).toBe(1249960000); expect(results[0]['example'].shares.round).toBe(1); console.log.mockClear(); done(); }); }); test('Test handling of immature blocks [5]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.payments.processingFee = parseFloat(0.0004); const config = poolPayments.poolConfigs['Pool1']; const round = { reward: 12.50, solo: false, worker: 'example' }; poolPayments.handleImmature(config, round, {}, { 'example': 8.2 }, 20.15, {}, { 'example': 8 }, 'primary', (error, results) => { expect(error).toBe(null); expect(results[0]['example'].immature).toBe(1249960000); expect(results[0]['example'].shares.round).toBe(3.28); console.log.mockClear(); done(); }); }); test('Test handling of immature blocks [6]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.payments.processingFee = parseFloat(0.0004); const config = poolPayments.poolConfigs['Pool1']; const round = { reward: 12.50, solo: false, worker: 'example' }; poolPayments.handleImmature(config, round, {}, {}, 20.15, {}, { 'example': 8 }, 'primary', (error, results) => { expect(error).toBe(null); expect(results[0]['example'].immature).toBe(1249960000); expect(results[0]['example'].shares.round).toBe(8); console.log.mockClear(); done(); }); }); test('Test handling of immature blocks [6]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].auxiliary = { payments: {} }; poolPayments.poolConfigs['Pool1'].auxiliary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].auxiliary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].auxiliary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].auxiliary.payments.processingFee = parseFloat(0.0004); const config = poolPayments.poolConfigs['Pool1']; const round = { reward: 12.50, solo: false, worker: 'example' }; poolPayments.handleImmature(config, round, {}, {}, 20.15, {}, { 'example': 8 }, 'auxiliary', (error, results) => { expect(error).toBe(null); expect(results[0]['example'].immature).toBe(1249960000); expect(results[0]['example'].shares.round).toBe(8); console.log.mockClear(); done(); }); }); test('Test handling of generate blocks [1]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.payments.processingFee = parseFloat(0.0004); const config = poolPayments.poolConfigs['Pool1']; const round = { reward: 12.50, height: 180, solo: false, worker: 'example' }; poolPayments.handleGenerate(config, round, {}, { 'example': 20.15 }, 20.15, {}, { 'example': 8 }, 'primary', (error, results) => { expect(error).toBe(null); expect(results[0]['example'].generate).toBe(1249960000); expect(results[0]['example'].shares.round).toBe(8); expect(results[0]['example'].shares.total).toBe(8); console.log.mockClear(); done(); }); }); test('Test handling of generate blocks [2]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.payments.processingFee = parseFloat(0.0004); const config = poolPayments.poolConfigs['Pool1']; const round = { reward: 12.50, height: 180, solo: false, worker: 'example' }; poolPayments.handleGenerate(config, round, {}, { 'example': 20.15 }, 20.15, {}, {}, 'primary', (error, results) => { expect(error).toBe(null); expect(results[0]).toStrictEqual({}); console.log.mockClear(); done(); }); }); test('Test handling of generate blocks [3]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.payments.processingFee = parseFloat(0.0004); const config = poolPayments.poolConfigs['Pool1']; const round = { reward: 12.50, height: 180, solo: true, worker: 'example' }; poolPayments.handleGenerate(config, round, {}, { 'example': 20.15 }, 20.15, { 'example': 8 }, {}, 'primary', (error, results) => { expect(error).toBe(null); expect(results[0]['example'].generate).toBe(1249960000); expect(results[0]['example'].shares.round).toBe(8); expect(results[0]['example'].shares.total).toBe(8); console.log.mockClear(); done(); }); }); test('Test handling of generate blocks [4]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.payments.processingFee = parseFloat(0.0004); const config = poolPayments.poolConfigs['Pool1']; const round = { reward: 12.50, height: 180, solo: true, worker: 'example' }; poolPayments.handleGenerate(config, round, {}, { 'example': 20.15 }, 20.15, {}, {}, 'primary', (error, results) => { expect(error).toBe(null); expect(results[0]['example'].generate).toBe(1249960000); expect(results[0]['example'].shares.round).toBe(1); expect(results[0]['example'].shares.total).toBe(1); console.log.mockClear(); done(); }); }); test('Test handling of generate blocks [5]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.payments.processingFee = parseFloat(0.0004); const config = poolPayments.poolConfigs['Pool1']; const round = { reward: 12.50, height: 180, solo: false, worker: 'example' }; poolPayments.handleGenerate(config, round, {}, { 'example': 8.2 }, 20.15, {}, { 'example': 8 }, 'primary', (error, results) => { expect(error).toBe(null); expect(results[0]['example'].generate).toBe(1249960000); expect(results[0]['example'].shares.round).toBe(3.28); expect(results[0]['example'].shares.total).toBe(3.28); console.log.mockClear(); done(); }); }); test('Test handling of generate blocks [6]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.payments.processingFee = parseFloat(0.0004); const config = poolPayments.poolConfigs['Pool1']; const round = { reward: 12.50, height: 180, solo: false, worker: 'example' }; poolPayments.handleGenerate(config, round, {}, {}, 20.15, {}, { 'example': 8 }, 'primary', (error, results) => { expect(error).toBe(null); expect(results[0]['example'].generate).toBe(1249960000); expect(results[0]['example'].shares.round).toBe(8); expect(results[0]['example'].shares.total).toBe(8); console.log.mockClear(); done(); }); }); test('Test handling of generate blocks [7]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].auxiliary = { payments: {} }; poolPayments.poolConfigs['Pool1'].auxiliary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].auxiliary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].auxiliary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].auxiliary.payments.processingFee = parseFloat(0.0004); const config = poolPayments.poolConfigs['Pool1']; const round = { reward: 12.50, height: 180, solo: false, worker: 'example' }; poolPayments.handleGenerate(config, round, {}, {}, 20.15, {}, { 'example': 8 }, 'auxiliary', (error, results) => { expect(error).toBe(null); expect(results[0]['example'].generate).toBe(1249960000); expect(results[0]['example'].shares.round).toBe(8); expect(results[0]['example'].shares.total).toBe(8); console.log.mockClear(); done(); }); }); test('Test main block/round handling [1]', (done) => { const commands = [ ['sadd', 'Pool1:blocks:primary:pending', mockBuildBlock(180, 'hash', 12.5, 'txid', 8, 'worker', false)], ['sadd', 'Pool1:blocks:primary:pending', mockBuildBlock(181, 'hash', 12.5, 'txid', 8, 'worker', false)], ['sadd', 'Pool1:blocks:primary:pending', mockBuildBlock(182, 'hash', 12.5, 'txid', 8, 'worker', false)], ['sadd', 'Pool1:blocks:primary:pending', mockBuildBlock(183, 'hash', 12.5, 'txid', 8, 'worker', false)]]; mockSetupClient(client, commands, 'Bitcoin', () => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); const config = poolPayments.poolConfigs['Pool1']; poolPayments.handleBlocks(daemon, config, 'primary', (error, results) => { expect(error).toBe(null); expect(results[0].length).toBe(4); expect(results[0][0].difficulty).toBe(8); expect(results[0][1].height).toBe(181); expect(results[0][2].reward).toBe(12.5); expect(results[0][3].transaction).toBe('txid'); console.log.mockClear(); done(); }); }); }); test('Test main block/round handling [2]', (done) => { const commands = [ ['sadd', 'Pool1:blocks:primary:pending', mockBuildBlock(180, 'hash', 12.5, 'txid', 8, 'worker', false)], ['sadd', 'Pool1:blocks:primary:pending', mockBuildBlock(180, 'hash2', 12.5, 'txid2', 8, 'worker2', false)], ['sadd', 'Pool1:blocks:primary:pending', mockBuildBlock(182, 'hash', 12.5, 'txid', 8, 'worker', false)], ['sadd', 'Pool1:blocks:primary:pending', mockBuildBlock(183, 'hash', 12.5, 'txid', 8, 'worker', false)]]; mockSetupClient(client, commands, 'Bitcoin', () => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); const config = poolPayments.poolConfigs['Pool1']; poolPayments.handleBlocks(daemon, config, 'primary', (error, results) => { expect(error).toBe(true); expect(results).toStrictEqual([]); console.log.mockClear(); done(); }); }); }); test('Test main worker handling [1]', (done) => { const commands = [ ['hincrbyfloat', 'Pool1:payments:primary:balances', 'worker1', 672.21], ['hincrbyfloat', 'Pool1:payments:primary:balances', 'worker2', 391.15]]; mockSetupClient(client, commands, 'Bitcoin', () => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; const config = poolPayments.poolConfigs['Pool1']; poolPayments.handleWorkers(config, 'primary', [[]], (error, results) => { expect(error).toBe(null); expect(Object.keys(results[1]).length).toBe(2); expect(results[1]['worker1'].balance).toBe(67221000000); expect(results[1]['worker2'].balance).toBe(39115000000); console.log.mockClear(); done(); }); }); }); test('Test main worker handling [2]', (done) => { const commands = [ ['hincrbyfloat', 'Pool1:payments:auxiliary:balances', 'worker1', 672.21], ['hincrbyfloat', 'Pool1:payments:auxiliary:balances', 'worker2', 391.15]]; mockSetupClient(client, commands, 'Bitcoin', () => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); poolPayments.poolConfigs['Pool1'].auxiliary = { payments: {} }; poolPayments.poolConfigs['Pool1'].auxiliary.payments.magnitude = 100000000; const config = poolPayments.poolConfigs['Pool1']; poolPayments.handleWorkers(config, 'auxiliary', [[]], (error, results) => { expect(error).toBe(null); expect(Object.keys(results[1]).length).toBe(2); expect(results[1]['worker1'].balance).toBe(67221000000); expect(results[1]['worker2'].balance).toBe(39115000000); console.log.mockClear(); done(); }); }); }); test('Test main transaction handling [1]', (done) => { mockDaemon.mockGetTransactionsGenerate(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.address = 'tltc1qa0z9fsraqpvasgfj6c72a59ztx0xh9vfv9ccwd'; const config = poolPayments.poolConfigs['Pool1']; const rounds = [{ transaction: 'efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c' }]; poolPayments.handleTransactions(daemon, config, 'primary', [rounds, [], []], (error, results) => { expect(error).toBe(null); expect(results[0][0].category).toBe('generate'); expect(results[0][0].reward).toBe(11.87510021); expect(results[0][0].transaction).toBe('efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c'); nock.cleanAll(); console.log.mockClear(); done(); }); }); test('Test main transaction handling [2]', (done) => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); const config = poolPayments.poolConfigs['Pool1']; const rounds = [{ transaction: 'efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c' }]; poolPayments.handleTransactions(daemon, config, 'primary', [rounds, [], []], (error, results) => { expect(error).toBe(true); expect(consoleSpy).toHaveBeenCalledWith(expect.stringMatching('Could not get transactions from daemon')); expect(results).toStrictEqual([]); console.log.mockClear(); done(); }); }); test('Test main transaction handling [3]', (done) => { mockDaemon.mockGetTransactionsImmature(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.address = 'tltc1qa0z9fsraqpvasgfj6c72a59ztx0xh9vfv9ccwd'; const config = poolPayments.poolConfigs['Pool1']; const rounds = [{ transaction: 'efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c' }]; poolPayments.handleTransactions(daemon, config, 'primary', [rounds, [], []], (error, results) => { expect(error).toBe(null); expect(results[0][0].category).toBe('immature'); expect(results[0][0].reward).toBe(11.87510021); expect(results[0][0].transaction).toBe('efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c'); nock.cleanAll(); console.log.mockClear(); done(); }); }); test('Test main transaction handling [4]', (done) => { mockDaemon.mockGetTransactionsSplit(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.address = 'tltc1qa0z9fsraqpvasgfj6c72a59ztx0xh9vfv9ccwd'; const config = poolPayments.poolConfigs['Pool1']; const rounds = [{ transaction: 'efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c' }]; poolPayments.handleTransactions(daemon, config, 'primary', [rounds, [], []], (error, results) => { expect(error).toBe(null); expect(results[0][0].category).toBe('generate'); expect(results[0][0].reward).toBe(11.87510021); expect(results[0][0].transaction).toBe('efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c'); nock.cleanAll(); console.log.mockClear(); done(); }); }); test('Test main transaction handling [5]', (done) => { mockDaemon.mockGetTransactionsOrphan(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.poolConfigs['Pool1'].primary.address = 'tltc1qa0z9fsraqpvasgfj6c72a59ztx0xh9vfv9ccwd'; const config = poolPayments.poolConfigs['Pool1']; const rounds = [{ transaction: 'efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c' }]; poolPayments.handleTransactions(daemon, config, 'primary', [rounds, [], []], (error, results) => { expect(error).toBe(null); expect(results[0][0].category).toBe('orphan'); expect(results[0][0].delete).toBe(true); expect(results[0][0].transaction).toBe('efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c'); nock.cleanAll(); console.log.mockClear(); done(); }); }); test('Test main transaction handling [6]', (done) => { mockDaemon.mockGetTransactionsSingle(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; const config = poolPayments.poolConfigs['Pool1']; const rounds = [{ transaction: 'efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c' }]; poolPayments.handleTransactions(daemon, config, 'primary', [rounds, [], []], (error, results) => { expect(error).toBe(null); expect(results[0][0].category).toBe('generate'); expect(results[0][0].reward).toBe(11.87510021); expect(results[0][0].transaction).toBe('efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c'); nock.cleanAll(); console.log.mockClear(); done(); }); }); test('Test main transaction handling [7]', (done) => { mockDaemon.mockGetTransactionsValue(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.poolConfigs['Pool1'].primary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].primary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].primary.payments.coinPrecision = 8; poolPayments.poolConfigs['Pool1'].primary.address = 'tltc1qa0z9fsraqpvasgfj6c72a59ztx0xh9vfv9ccwd'; const config = poolPayments.poolConfigs['Pool1']; const rounds = [{ transaction: 'efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c' }]; poolPayments.handleTransactions(daemon, config, 'primary', [rounds, [], []], (error, results) => { expect(error).toBe(null); expect(results[0][0].category).toBe('generate'); expect(results[0][0].reward).toBe(11.87510021); expect(results[0][0].transaction).toBe('efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c'); nock.cleanAll(); console.log.mockClear(); done(); }); }); test('Test main transaction handling [8]', (done) => { mockDaemon.mockGetTransactionsError1(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); const config = poolPayments.poolConfigs['Pool1']; const rounds = [{ transaction: 'efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c' }]; poolPayments.handleTransactions(daemon, config, 'primary', [rounds, [], []], (error, results) => { expect(error).toBe(null); expect(consoleSpy).toHaveBeenCalledWith(expect.stringMatching('Daemon reports invalid transaction')); expect(results[0][0].category).toBe('kicked'); expect(results[0][0].delete).toBe(true); expect(results[0][0].transaction).toBe('efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c'); nock.cleanAll(); console.log.mockClear(); done(); }); }); test('Test main transaction handling [9]', (done) => { mockDaemon.mockGetTransactionsError2(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); const config = poolPayments.poolConfigs['Pool1']; const rounds = [{ transaction: 'efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c' }]; poolPayments.handleTransactions(daemon, config, 'primary', [rounds, [], []], (error, results) => { expect(error).toBe(null); expect(consoleSpy).toHaveBeenCalledWith(expect.stringMatching('Daemon reports no details for transaction')); expect(results[0][0].category).toBe('kicked'); expect(results[0][0].delete).toBe(true); expect(results[0][0].transaction).toBe('efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c'); nock.cleanAll(); console.log.mockClear(); done(); }); }); test('Test main transaction handling [10]', (done) => { mockDaemon.mockGetTransactionsError3(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); const config = poolPayments.poolConfigs['Pool1']; const rounds = [{ transaction: 'efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c' }]; poolPayments.handleTransactions(daemon, config, 'primary', [rounds, [], []], (error, results) => { expect(error).toBe(null); expect(consoleSpy).toHaveBeenCalledWith(expect.stringMatching('Unable to load transaction')); expect(results).toStrictEqual([[], []]); nock.cleanAll(); console.log.mockClear(); done(); }); }); test('Test main transaction handling [11]', (done) => { mockDaemon.mockGetTransactionsValue(); const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const daemon = new Stratum.daemon([poolConfig.primary.payments.daemon], () => {}); poolPayments.poolConfigs['Pool1'].auxiliary = { payments: {} }; poolPayments.poolConfigs['Pool1'].auxiliary.payments.magnitude = 100000000; poolPayments.poolConfigs['Pool1'].auxiliary.payments.minPaymentSatoshis = 500000; poolPayments.poolConfigs['Pool1'].auxiliary.payments.coinPrecision = 8; const config = poolPayments.poolConfigs['Pool1']; const rounds = [{ transaction: 'efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c' }]; poolPayments.handleTransactions(daemon, config, 'auxiliary', [rounds, [], []], (error, results) => { expect(error).toBe(null); expect(results[0][0].category).toBe('generate'); expect(results[0][0].reward).toBe(11.87510021); expect(results[0][0].transaction).toBe('efaab94af3973b6d1148d030a75abbea6b5e2af4e4c989738393a55e1d44fd2c'); nock.cleanAll(); console.log.mockClear(); done(); }); }); test('Test main shares handling [1]', (done) => { const commands = [ ['hset', 'Pool1:rounds:primary:round-180:shares', 'worker1', JSON.stringify({ time: 0, work: 8, worker: 'worker1', times: 20, solo: true })], ['hset', 'Pool1:rounds:primary:round-180:shares', 'worker2', JSON.stringify({ time: 0, work: 28, worker: 'worker2', times: 40, solo: false })]]; mockSetupClient(client, commands, 'Bitcoin', () => { const consoleSpy = jest.spyOn(console, 'log').mockImplementation(() => {}); const poolPayments = new PoolPayments(logger, client); const config = poolPayments.poolConfigs['Pool1']; const rounds = [{ height: 180 }]; poolPayments.handleShares(config, 'primary', [rounds, [], []], (error, results) => { expec