UNPKG

wallet-storage

Version:

BRC100 conforming wallet, wallet storage and wallet signer components

298 lines 18 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const sdk_1 = require("@bsv/sdk"); const index_client_1 = require("../../src/index.client"); const TaskCheckForProofs_1 = require("../../src/monitor/tasks/TaskCheckForProofs"); const TaskClock_1 = require("../../src/monitor/tasks/TaskClock"); const TaskNewHeader_1 = require("../../src/monitor/tasks/TaskNewHeader"); const TaskPurge_1 = require("../../src/monitor/tasks/TaskPurge"); const TaskSendWaiting_1 = require("../../src/monitor/tasks/TaskSendWaiting"); const TestUtilsWalletStorage_1 = require("../utils/TestUtilsWalletStorage"); const TaskReviewStatus_1 = require("../../src/monitor/tasks/TaskReviewStatus"); describe('Monitor tests', () => { jest.setTimeout(99999999); const env = TestUtilsWalletStorage_1._tu.getEnv('test'); const ctxs = []; beforeAll(async () => { ctxs.push(await TestUtilsWalletStorage_1._tu.createSQLiteTestSetup1Wallet({ databaseName: 'walletMonitorMain', chain: 'main', rootKeyHex: '3'.repeat(64) })); //ctxs.push(await _tu.createSQLiteTestSetup1Wallet({ databaseName: 'walletMonitorTest', chain: 'test', rootKeyHex: '3'.repeat(64)})) }); afterAll(async () => { for (const ctx of ctxs) { await ctx.storage.destroy(); } }); test('0 TaskClock', async () => { if (!env.runSlowTests) return; // This test takes a bit over a minute to run... un-skip it to work on it. for (const { chain, wallet, services, monitor } of ctxs) { if (!monitor) throw new index_client_1.sdk.WERR_INTERNAL('test requires setup with monitor'); { // The clock attempts to update nextMinute to msecs for each minute. // Starting the clock and waiting a bit over a minute should see the value // increase by one minute's worth of msecs. const task = new TaskClock_1.TaskClock(monitor); monitor._tasks.push(task); const msecsFirst = task.nextMinute; const startTasksPromise = monitor.startTasks(); await (0, index_client_1.wait)(monitor.oneMinute * 1.1); const msecsNext = task.nextMinute; monitor.stopTasks(); const elapsed = (msecsNext - msecsFirst) / monitor.oneMinute; expect(elapsed === 1 || elapsed === 2).toBe(true); await startTasksPromise; } } }); test('1 TaskNewHeader', async () => { if (!env.runSlowTests) return; // This test takes 10+ seconds to run... un-skip it to work on it. for (const { chain, wallet, services, monitor } of ctxs) { if (!monitor) throw new index_client_1.sdk.WERR_INTERNAL('test requires setup with monitor'); { // The new header task polls chaintracks for latest header and if new sets flag to check for proofs. // Starting the clock and waiting a bit should cause first header to be fetched and flag to be set. const task = new TaskNewHeader_1.TaskNewHeader(monitor); monitor._tasks.push(task); expect(TaskCheckForProofs_1.TaskCheckForProofs.checkNow).toBe(false); const startTasksPromise = monitor.startTasks(); await (0, index_client_1.wait)(monitor.oneSecond * 10); expect(task.header).toBeTruthy(); expect(TaskCheckForProofs_1.TaskCheckForProofs.checkNow).toBe(true); monitor.stopTasks(); await startTasksPromise; } } }); test.skip('2 TaskPurge', async () => { /* ** The following code is to test against un-purged data copied from staging-dojo: const ctxs: TestWallet<{}>[] = [] const env = _tu.getEnv('test') const identityKeyTone = '03ac2d10bdb0023f4145cc2eba2fcd2ad3070cb2107b0b48170c46a9440e4cc3fe' const rootKeyHex = env.devKeys[identityKeyTone] ctxs.push(await _tu.createMySQLTestWallet({ databaseName: 'stagingdojotone', chain: 'test', rootKeyHex, dropAll: false })) */ for (const { chain, wallet, services, monitor } of ctxs) { if (!monitor) throw new index_client_1.sdk.WERR_INTERNAL('test requires setup with monitor'); { const task = new TaskPurge_1.TaskPurge(monitor, { purgeCompleted: true, purgeFailed: true, purgeSpent: true, purgeCompletedAge: 1, purgeFailedAge: 1, purgeSpentAge: 1, }); TaskPurge_1.TaskPurge.checkNow = true; monitor._tasks.push(task); await monitor.runTask('Purge'); } } for (const ctx of ctxs) { await ctx.storage.destroy(); } }); test('3 TaskSendWaiting success', async () => { await runMockedSendWaiting('success', 'monitorTest3'); }); test('4 TaskSendWaiting error', async () => { await runMockedSendWaiting('error', 'monitorTest4'); }); test('5 TaskCheckForProofs success', async () => { const ctxs = []; ctxs.push(await TestUtilsWalletStorage_1._tu.createLegacyWalletSQLiteCopy('monitorTest5')); let txidsPosted = []; let mockResultIndex = 0; const expectedTxids = [ "c099c52277426abb863dc902d0389b008ddf2301d6b40ac718746ac16ca59136", "6935ce33b9e3b9ee60360ce0606aa0a0970b4840203f457b5559212676dc33ab", "67ca2475886b3fc2edd76a2eb8c32bd0bc308176c7dff463e0507942aeebcbec", "3fa94b62a3b10d8c18bada527a9b68c4e70db67140719df16c44fb0328782532", "519675259eff036c6597e4a497d37c132e718171dde4ea2257e84c947ecf656b", ]; TestUtilsWalletStorage_1._tu.mockMerklePathServicesAsCallback(ctxs, async (txid) => { expect(expectedTxids).toContain(txid); const r = mockGetMerklePathResults[mockResultIndex++]; return r; }); for (const { activeStorage: storage, monitor } of ctxs) { if (!monitor) throw new index_client_1.sdk.WERR_INTERNAL('test requires setup with monitor'); { for (const txid of expectedTxids) { // no matching ProvenTx exists. expect((await storage.findProvenTxs({ partial: { txid } })).length).toBe(0); const req = (0, index_client_1.verifyTruthy)(await index_client_1.entity.ProvenTxReq.fromStorageTxid(storage, txid)); expect(req.status).toBe('unmined'); } const task = new TaskCheckForProofs_1.TaskCheckForProofs(monitor, 1); monitor._tasks.push(task); await monitor.runTask('CheckForProofs'); for (const txid of expectedTxids) { const proven = (0, index_client_1.verifyOne)(await storage.findProvenTxs({ partial: { txid } })); expect(proven.merklePath).toBeTruthy(); const req = (0, index_client_1.verifyTruthy)(await index_client_1.entity.ProvenTxReq.fromStorageTxid(storage, txid)); expect(req.status).toBe('completed'); expect(req.provenTxId).toBe(proven.provenTxId); } } } for (const ctx of ctxs) { await ctx.storage.destroy(); } }); test('6 TaskCheckForProofs fail', async () => { const ctxs = []; ctxs.push(await TestUtilsWalletStorage_1._tu.createLegacyWalletSQLiteCopy('monitorTest6')); let txidsPosted = []; let mockResultIndex = 0; const expectedTxids = [ "c099c52277426abb863dc902d0389b008ddf2301d6b40ac718746ac16ca59136", "6935ce33b9e3b9ee60360ce0606aa0a0970b4840203f457b5559212676dc33ab", "67ca2475886b3fc2edd76a2eb8c32bd0bc308176c7dff463e0507942aeebcbec", "3fa94b62a3b10d8c18bada527a9b68c4e70db67140719df16c44fb0328782532", "519675259eff036c6597e4a497d37c132e718171dde4ea2257e84c947ecf656b", ]; TestUtilsWalletStorage_1._tu.mockMerklePathServicesAsCallback(ctxs, async (txid) => { expect(expectedTxids).toContain(txid); const r = {}; return r; }); for (const { activeStorage: storage, monitor } of ctxs) { if (!monitor) throw new index_client_1.sdk.WERR_INTERNAL('test requires setup with monitor'); { const attempts = []; for (const txid of expectedTxids) { // no matching ProvenTx exists. expect((await storage.findProvenTxs({ partial: { txid } })).length).toBe(0); const req = (0, index_client_1.verifyTruthy)(await index_client_1.entity.ProvenTxReq.fromStorageTxid(storage, txid)); expect(req.status).toBe('unmined'); attempts.push(req.attempts); } const task = new TaskCheckForProofs_1.TaskCheckForProofs(monitor, 1); monitor._tasks.push(task); await monitor.runTask('CheckForProofs'); let i = -1; for (const txid of expectedTxids) { i++; // no matching ProvenTx exists. expect((await storage.findProvenTxs({ partial: { txid } })).length).toBe(0); const req = (0, index_client_1.verifyTruthy)(await index_client_1.entity.ProvenTxReq.fromStorageTxid(storage, txid)); expect(req.status).toBe('unmined'); expect(req.attempts).toBeGreaterThanOrEqual(attempts[i]); } } } for (const ctx of ctxs) { await ctx.storage.destroy(); } }); const mockGetMerklePathResults = [ { name: "WoCTsc", merklePath: new sdk_1.MerklePath(1652142, [[{ offset: 2, hash: "74c55a15a08ea491e02c41a6934c4177666c0dbda2781d0cf9743d3ad68a4623" }, { offset: 3, hash: "c099c52277426abb863dc902d0389b008ddf2301d6b40ac718746ac16ca59136", txid: true }], [{ offset: 0, hash: "2574544a253c91e69c7d5b4478af95d39420ad2c8e44c78b280f1bd5e7a11849" }], [{ offset: 1, hash: "8903289601da1910820c3471d41ae9187a7d46d6e39e636840b176519bdc5d00" }]]), header: { version: 536870912, previousHash: "0000000039f1c7dc943d50883e531022825bf5c15a40db2cedde7d203ca3d644", merkleRoot: "68bde58600fbd2c716871356cc2ad34b43ac67ac8d7a879dd966429d5a6935b2", time: 1734530373, bits: 474103450, nonce: 3894752803, height: 1652142, hash: "000000000d9419a409f83f16e2c162b4e44266986d6b9ee02d1b97d9556d9a3a" }, }, { name: "WoCTsc", merklePath: new sdk_1.MerklePath(1652142, [[{ offset: 4, hash: "6935ce33b9e3b9ee60360ce0606aa0a0970b4840203f457b5559212676dc33ab", txid: true }, { offset: 5, duplicate: true }], [{ offset: 3, hash: "65b5a77f61ca87af5766546e4a22129da89f3378322ef29aac6cdc94c1f637f3" }], [{ offset: 0, hash: "0aeaa5c76cba5495f922ae0b52805c0d12c2ffa54d2829d250c958d67c7c5073" }]]), header: { version: 536870912, previousHash: "0000000039f1c7dc943d50883e531022825bf5c15a40db2cedde7d203ca3d644", merkleRoot: "68bde58600fbd2c716871356cc2ad34b43ac67ac8d7a879dd966429d5a6935b2", time: 1734530373, bits: 474103450, nonce: 3894752803, height: 1652142, hash: "000000000d9419a409f83f16e2c162b4e44266986d6b9ee02d1b97d9556d9a3a" }, }, { name: "WoCTsc", merklePath: new sdk_1.MerklePath(1652145, [[{ offset: 0, hash: "c160acfce1c29c648614b722f1c490473fd7aea0c60d21be95ae981eb0c9c4f0" }, { offset: 1, hash: "67ca2475886b3fc2edd76a2eb8c32bd0bc308176c7dff463e0507942aeebcbec", txid: true }], [{ offset: 1, hash: "c0eb049e4d3872d63bd3402dd4d6bc8022a170155493a994e1da692f08b2f2d0" }]]), header: { version: 536870912, previousHash: "000000001888ff57f4848f181f9f69cab27f2388d7c2edd99b8c004ae482cca7", merkleRoot: "f990936bc3267ba4911acc490107ed1841eedbd2c5017e1074891285df30f255", time: 1734532172, bits: 474081547, nonce: 740519774, height: 1652145, hash: "0000000003ea4ecae9254b992f292137fde1de66cc809d1a81cfd60cab4ba160" } }, { name: "WoCTsc", merklePath: new sdk_1.MerklePath(1652145, [[{ offset: 2, hash: "3fa94b62a3b10d8c18bada527a9b68c4e70db67140719df16c44fb0328782532", txid: true }, { offset: 3, duplicate: true }], [{ offset: 0, hash: "5eec838112f0eabc45e68c8ec14f76e74b0ea636180d91ccf034f5f3c5114edf" }]]), header: { version: 536870912, previousHash: "000000001888ff57f4848f181f9f69cab27f2388d7c2edd99b8c004ae482cca7", merkleRoot: "f990936bc3267ba4911acc490107ed1841eedbd2c5017e1074891285df30f255", time: 1734532172, bits: 474081547, nonce: 740519774, height: 1652145, hash: "0000000003ea4ecae9254b992f292137fde1de66cc809d1a81cfd60cab4ba160" } }, { name: "WoCTsc", merklePath: new sdk_1.MerklePath(1652160, [[{ offset: 0, hash: "ee8d57d6c3f5be3238709f539dc224c44c2c848414cb5969bfa8c81c2768ad6b" }, { offset: 1, hash: "519675259eff036c6597e4a497d37c132e718171dde4ea2257e84c947ecf656b", txid: true }]]), header: { version: 536870912, previousHash: "0000000012dbd406fef49503c545bafd940ba2f2c9b05ef351177b71fe96e7d8", merkleRoot: "c2714feeccc7db8ea4235799e6490271867008dd39e3cf8a6e9aa20fd47f3222", time: 1734538772, bits: 474045917, nonce: 2431702809, height: 1652160, hash: "000000001c5d2b3beb2e1f1f21f69f77cb979ed92f99d2cdd1a2618349b575ca" } } ]; async function runMockedSendWaiting(postBeefMockStatus, database) { const ctxs = []; ctxs.push(await TestUtilsWalletStorage_1._tu.createLegacyWalletSQLiteCopy(database)); let txidsPosted = []; TestUtilsWalletStorage_1._tu.mockPostServicesAsCallback(ctxs, (beef, txids) => { txidsPosted.push(...txids); return postBeefMockStatus; }); for (const { activeStorage: storage, monitor } of ctxs) { if (!monitor) throw new index_client_1.sdk.WERR_INTERNAL('test requires setup with monitor'); { const task = new TaskSendWaiting_1.TaskSendWaiting(monitor, 1, 1); monitor._tasks.push(task); txidsPosted = []; const expectedTxids = [ "d9ec73b2e0f06e0f482d2d1db9ceccf2f212f0b24afbe10846ac907567be571f", "b7634f08d8c7f3c6244050bebf73a79f40e672aba7d5232663609a58b123b816", "3d2ea64ee584a1f6eb161dbedf3a8d299e3e4497ac7a203d23c044c998c6aa08", "a3a8fe7f541c1383ff7b975af49b27284ae720af5f2705d8409baaf519190d26", "6d68cc6fa7363e59aaccbaa65f0ca613a6ae8af718453ab5d3a2b022c59b5cc6", ]; for (const txid of expectedTxids) { const req = (0, index_client_1.verifyOne)(await storage.findProvenTxReqs({ partial: { txid } })); expect(req.status).toBe('unsent'); const notifyIds = new index_client_1.entity.ProvenTxReq(req).notify.transactionIds || []; for (const transactionId of notifyIds) { const tx = (0, index_client_1.verifyTruthy)(await storage.findTransactionById(transactionId)); expect(['nosend', 'unprocessed', 'sending']).toContain(tx.status); } } await monitor.runTask('SendWaiting'); expect(txidsPosted).toEqual(expectedTxids); for (const txid of expectedTxids) { const req = (0, index_client_1.verifyOne)(await storage.findProvenTxReqs({ partial: { txid } })); if (env.logTests) console.log(new index_client_1.entity.ProvenTxReq(req).historyPretty()); const notifyIds = new index_client_1.entity.ProvenTxReq(req).notify.transactionIds || []; switch (postBeefMockStatus) { case 'success': { expect(req.status).toBe('unmined'); for (const transactionId of notifyIds) { const tx = (0, index_client_1.verifyTruthy)(await storage.findTransactionById(transactionId)); expect(['unproven']).toContain(tx.status); } } break; case 'error': { expect(req.status).toBe('unsent'); } } } } } for (const ctx of ctxs) { await ctx.storage.destroy(); } } test('7 TaskReviewStatus', async () => { const ctxs = []; ctxs.push(await TestUtilsWalletStorage_1._tu.createLegacyWalletSQLiteCopy('monitorTest7')); //ctxs.push(await _tu.createLegacyWalletMySQLCopy('monitorTest7')) for (const { activeStorage: storage, monitor } of ctxs) { const reqs = await storage.findProvenTxReqs({ partial: { status: 'unmined' } }); const crus = await storage.updateProvenTxReq(reqs[0].provenTxReqId, { status: 'invalid' }); const ctus = await storage.updateTransaction(23, { provenTxId: undefined }); const task = new TaskReviewStatus_1.TaskReviewStatus(monitor, 1, 1000 * 5); monitor._tasks.push(task); const log = await monitor.runTask('ReviewStatus'); //console.log(log) } for (const ctx of ctxs) { await ctx.storage.destroy(); } }); }); //# sourceMappingURL=Monitor.test.js.map