wallet-storage
Version:
BRC100 conforming wallet, wallet storage and wallet signer components
298 lines • 18 kB
JavaScript
"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