UNPKG

@bsv/wallet-toolbox

Version:

BRC100 conforming wallet, wallet storage and wallet signer components

385 lines 15.8 kB
"use strict"; 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; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); const sdk_1 = require("@bsv/sdk"); const src_1 = require("../../../src"); const TestUtilsWalletStorage_1 = require("../../utils/TestUtilsWalletStorage"); const Format_1 = require("../../../src/utility/Format"); const dotenv = __importStar(require("dotenv")); dotenv.config(); const chain = 'main'; const options = { setActiveClient: true, useMySQLConnectionForClient: true, useTestIdentityKey: false, useIdentityKey2: false }; describe('reqErrorReview.2025.05.06.man tests', () => { jest.setTimeout(99999999); // OVERWRITES EXISTING FILE CONTENTS!!!! test.skip('0 grab reqs history as local sqlite file', async () => { const { env, storage, services } = await TestUtilsWalletStorage_1._tu.createMainReviewSetup(); const { activeStorage: s2 } = await TestUtilsWalletStorage_1._tu.createSQLiteTestWallet({ filePath: `${__dirname}/reqhistory.sqlite`, databaseName: 'reqhistory', chain: 'main', rootKeyHex: '1'.repeat(64), dropAll: true }); await s2.makeAvailable(); const limit = 100; let offset = 0; for (;;) { const r = await storage.knex.raw(` select provenTxReqId as id, txid, status, history from proven_tx_reqs where history is not null limit ${limit} offset ${offset} `); const reqs = r[0]; for (const req of reqs) { const { id, history, status, txid } = req; await s2.insertProvenTxReq({ created_at: new Date(), updated_at: new Date(), provenTxReqId: id, status, attempts: 0, notified: false, txid, history, notify: '', rawTx: [] }); } if (reqs.length < limit) break; offset += limit; } await s2.destroy(); await storage.destroy(); }); test('1 review reqs history and final outcome', async () => { let undouble = []; let uninvalid = []; let uncompleted = []; let deunmined = []; let noSuccessCompleted = []; let successDouble = []; let internalizeDouble = []; let successInvalid = []; const { activeStorage: storage } = await TestUtilsWalletStorage_1._tu.createSQLiteTestWallet({ filePath: `${__dirname}/reqhistory.sqlite`, databaseName: 'reqhistory', chain: 'main', rootKeyHex: '1'.repeat(64), dropAll: false }); //const { env, storage, services } = await _tu.createMainReviewSetup() let limit = 100; let offset = 0; let aggSum = -1; const partial = {}; let log = ''; for (;;) { const reqs = await storage.findProvenTxReqs({ partial, status: undefined, paged: { limit, offset } }); for (const reqApi of reqs) { if (reqApi.provenTxReqId < 11312) continue; const r = reviewHistoryNotes(reqApi); if (!r) continue; if (r.isCompleted && r.wasDoubleSpend) { undouble.push(reqApi.provenTxReqId); let review = ''; if (r.doubleReview) { const rr = r.doubleReview; review = `0:${rr.status0},1:${rr.status1},2:${rr.status2},Txs:${rr.competingTxs}`; } //log += `undouble ${reqApi.provenTxReqId} arc:${r.brArc} woc:${r.brWoC} bit:${r.brBitails} ${review}\n` } if (r.isCompleted && r.wasInvalid) { uninvalid.push(reqApi.provenTxReqId); //log += `uninvalid ${reqApi.provenTxReqId} arc:${r.brArc} woc:${r.brWoC} bit:${r.brBitails}\n` } if ((r.isDoubleSpend || r.isInvalid) && r.wasCompleted) { uncompleted.push(reqApi.provenTxReqId); } if ((r.isDoubleSpend || r.isInvalid) && r.wasUnmined) { if (r.wasInternalize) internalizeDouble.push(reqApi.provenTxReqId); else { deunmined.push(reqApi.provenTxReqId); log += `deunmined ${reqApi.provenTxReqId} arc:${r.brArc} woc:${r.brWoC} bit:${r.brBitails}\n`; } } if (r.aggregate && r.aggregate.successCount === 0 && r.isCompleted) { noSuccessCompleted.push(reqApi.provenTxReqId); } if (r.aggregate && r.aggregate.successCount > 0 && r.isDoubleSpend) { successDouble.push(reqApi.provenTxReqId); } if (r.aggregate && r.aggregate.successCount > 0 && r.isInvalid) { successInvalid.push(reqApi.provenTxReqId); } if (r.aggregate && r.aggSum !== aggSum) { log += `aggSum changed ${aggSum} to ${r.aggSum} reqId=${reqApi.provenTxReqId}\n`; aggSum = r.aggSum; } } if (reqs.length < limit) break; offset += limit; } if (undouble.length > 0) log += `undouble: ${JSON.stringify(undouble)}\n`; if (uninvalid.length > 0) log += `uninvalid: ${JSON.stringify(uninvalid)}\n`; if (uncompleted.length > 0) log += `uncompleted: ${JSON.stringify(uncompleted)}\n`; if (deunmined.length > 0) log += `deunmined: ${JSON.stringify(deunmined)}\n`; if (internalizeDouble.length > 0) log += `internalizeDouble: ${JSON.stringify(internalizeDouble)}\n`; if (noSuccessCompleted.length > 0) log += `noSuccessCompleted: ${JSON.stringify(noSuccessCompleted)}\n`; if (successDouble.length > 0) log += `successDouble: ${JSON.stringify(successDouble)}\n`; if (successInvalid.length > 0) log += `successInvalid: ${JSON.stringify(successInvalid)}\n`; console.log(log); await storage.destroy(); }); const uninvalid = [ 10822, 12228, 14884, 14948, 1654, 1649, 2654, 2655, 2656, 2658, 2659, 2660, 2661, 2662, 2663, 2664, 2665, 2666, 2667, 2669, 2707, 2719, 2723, 2724, 2726 ]; const undouble = [ 10732, 12303, 12476, 14084, 14111, 14956, 14972, 14874, 14789, 14810, 14813, 14817, 14588, 14640, 14641, 14531, 2753, 2653, 2657, 2670, 2671, 2681, 2684, 2691, 2732, 4343, 4222, 4124, 4148, 3873, 3735, 3514, 3537, 5074, 5125, 4958, 4977, 4730, 4365 ]; const deunmined = [ 12304, 12305, 12306, 12307, 12480, 12483, 12484, 12488, 12489, 12490, 12497, 14085, 14086, 14087, 14814, 14816, 14821, 14953, 15170 ]; test('2 review deunmined reqs', async () => { const { env, storage, services } = await TestUtilsWalletStorage_1._tu.createMainReviewSetup(); const chaintracker = await services.getChainTracker(); let log = ''; for (const id of deunmined) { const reqApi = await storage.findProvenTxReqById(id); if (!reqApi) continue; const beef = new sdk_1.Beef(); beef.mergeRawTx(reqApi.rawTx); if (reqApi.inputBEEF) beef.mergeBeef(reqApi.inputBEEF); let tx = beef.findTxid(reqApi.txid).tx; let allInputsFound = true; let ilog = ''; for (const input of tx.inputs) { if (beef.findTxid(input.sourceTXID)) continue; try { const ib = await storage.getBeefForTransaction(input.sourceTXID, {}); if (ib) beef.mergeBeef(ib); } catch (e) { if (input.sourceTXID) { const r2 = (0, src_1.verifyOneOrNone)(await storage.findProvenTxReqs({ partial: { txid: input.sourceTXID } })); if (r2 && r2.rawTx) { const itx = sdk_1.Transaction.fromBinary(r2.rawTx); ilog += 'missing input ' + Format_1.Format.toLogStringTransaction(itx); } } allInputsFound = false; } } if (allInputsFound) { tx = beef.findAtomicTransaction(reqApi.txid); try { const ok = await tx.verify('scripts only'); log += `${reqApi.provenTxReqId} ${reqApi.txid} ${ok ? 'OK' : 'FAIL'}\n`; } catch (e) { log += `${reqApi.provenTxReqId} ${reqApi.txid} ${src_1.sdk.WalletError.fromUnknown(e).message}\n`; } } else { log += `${reqApi.provenTxReqId} FAILED `; log += Format_1.Format.toLogStringBeefTxid(beef, reqApi.txid); log += ilog; } } console.log(log); await storage.destroy(); }); }); function reviewHistoryNotes(reqApi) { var _a; const r = { req: new src_1.EntityProvenTxReq(reqApi), wasDoubleSpend: false, wasInvalid: false, wasCompleted: false, wasUnmined: false, wasInternalize: false, isDoubleSpend: false, isInvalid: false, isCompleted: false, aggSum: 0, aggregate: undefined }; if (!((_a = r.req.history) === null || _a === void 0 ? void 0 : _a.notes)) return undefined; for (const note of r.req.history.notes) { if (note.what === 'status') { const statusWas = note.status_was; const statusNow = note.status_now; if (statusNow === 'doubleSpend') { r.isDoubleSpend = r.wasDoubleSpend = true; r.isInvalid = false; r.isCompleted = false; } else if (statusNow === 'invalid') { r.isDoubleSpend = false; r.isInvalid = r.wasInvalid = true; r.isCompleted = false; } else if (statusNow === 'completed') { r.isDoubleSpend = false; r.isInvalid = false; r.isCompleted = r.wasCompleted = true; } else if (statusNow === 'unmined') { r.isDoubleSpend = false; r.isInvalid = false; r.wasUnmined = true; } } else if (note.what === 'aggregateResults') { r.aggregate = { successCount: note.successCount, doubleSpendCount: note.doubleSpendCount, statusErrorCount: note.statusErrorCount, serviceErrorCount: note.serviceErrorCount, newReqStatus: note.newReqStatus }; const a = r.aggregate; r.aggSum = a.doubleSpendCount + a.statusErrorCount + a.serviceErrorCount + a.successCount; } else if (note.what === 'confirmDoubleSpend') { r.doubleReview = { status0: note.getStatus0, status1: note.getStatus1, status2: note.getStatus2, competingTxs: note.competingTxs }; } else if (note.what === 'internalizeAction') { r.wasInternalize = true; } if (note.name === 'WoCpostRawTx') { if (note.what === 'postRawTxErrorMissingInputs') { r.brWoC = 'missingInputs'; } else if (note.what === 'postRawTxError') { if (note.status === 504) { r.brWoC = 'serviceError'; } } } else if (note.name === 'WoCpostBeef') { if (note.what === 'postBeefSuccess') { r.brWoC = 'success'; } else if (note.what === 'postBeefError' && r.brWoC === undefined) { r.brWoC = 'invalidTx'; } } else if (note.name === 'ARCpostBeef') { if (note.what === 'postBeefGetTxDataSuccess') { if (note.txStatus === 'STORED') r.brArc = 'success'; } } else if (note.name === 'ARCv1tx') { if (note.what === 'postRawTxDoubleSpend') { if (note.txStatus === 'DOUBLE_SPEND_ATTEMPTED') r.brArc = 'doubleSpend'; } else if (note.what === 'postRawTxError') { if (note.status === 469) r.brArc = 'badRoots'; else if (note.status === 463) r.brArc = 'badBump'; } else if (note.what === 'postRawTxSuccess') { if (note.txStatus === 'ANNOUNCED_TO_NETWORK') r.brArc = 'success'; else if (note.txStatus === 'SEEN_ON_NETWORK') r.brArc = 'success'; else if (note.txStatus === 'REQUESTED_BY_NETWORK') r.brArc = 'success'; } } else if (note.name === 'BitailsPostRawTx') { if (note.what === 'postRawsSuccess') { r.brBitails = 'success'; } else if (note.what === 'postRawsSuccessAlreadyInMempool') { r.brBitails = 'success'; } else if (note.what === 'postRawsErrorMissingInputs') { r.brBitails = 'invalidTx'; } else if (note.what === 'postRawsError') { if (note.code === -26) { r.brBitails = 'invalidTx'; } else if (note.code === -1) { r.brBitails = 'serviceError'; } else if (note.code === 'ESOCKETTIMEDOUT') { r.brBitails = 'serviceError'; } } } } return r; } //# sourceMappingURL=reqErrorReview.2025.05.06.man.test.js.map