@bsv/wallet-toolbox
Version:
BRC100 conforming wallet, wallet storage and wallet signer components
385 lines • 15.8 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;
};
})();
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