@bsv/wallet-toolbox
Version:
BRC100 conforming wallet, wallet storage and wallet signer components
142 lines • 5.63 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getListOutputsSpecOp = getListOutputsSpecOp;
const types_1 = require("../../sdk/types");
const utilityHelpers_1 = require("../../utility/utilityHelpers");
const WERR_errors_1 = require("../../sdk/WERR_errors");
const INVALID_CHANGE_MAX_CONCURRENCY = 12;
async function runWithConcurrency(values, maxConcurrency, worker) {
const active = [];
for (const value of values) {
const task = worker(value).finally(() => {
const i = active.indexOf(task);
if (i >= 0)
active.splice(i, 1);
});
active.push(task);
if (active.length >= maxConcurrency) {
await Promise.race(active);
}
}
await Promise.all(active);
}
const getBasketToSpecOp = () => {
return {
[types_1.specOpWalletBalance]: {
name: 'totalOutputsIsWalletBalance',
useBasket: 'default',
ignoreLimit: true,
totalOutputsIsSumOfSatoshis: true,
resultFromOutputs: async (s, auth, vargs, specOpTags, outputs) => {
let totalOutputs = 0;
for (const o of outputs)
totalOutputs += o.satoshis;
return { totalOutputs, outputs: [] };
}
},
[types_1.specOpInvalidChange]: {
name: 'invalidChangeOutputs',
useBasket: 'default',
ignoreLimit: true,
includeOutputScripts: true,
includeSpent: false,
tagsToIntercept: ['release', 'all'],
filterOutputs: async (s, auth, vargs, specOpTags, outputs) => {
const invalidOutputIds = new Set();
const services = s.getServices();
await runWithConcurrency(outputs, INVALID_CHANGE_MAX_CONCURRENCY, async (o) => {
if (!o.basketId)
return; // only care about outputs assigned to baskets.
await s.validateOutputScript(o);
let ok = false;
if (o.lockingScript && o.lockingScript.length > 0) {
ok = await services.isUtxo(o);
}
else {
ok = undefined;
}
if (ok === false) {
invalidOutputIds.add(o.outputId);
}
});
const filteredOutputs = outputs.filter(o => invalidOutputIds.has(o.outputId));
if (specOpTags.indexOf('release') >= 0) {
await runWithConcurrency(filteredOutputs, INVALID_CHANGE_MAX_CONCURRENCY, async (o) => {
await s.updateOutput(o.outputId, { spendable: false });
o.spendable = false;
});
}
return filteredOutputs;
}
},
[types_1.specOpSetWalletChangeParams]: {
name: 'setWalletChangeParams',
tagsParamsCount: 2,
resultFromTags: async (s, auth, vargs, specOpTags) => {
if (specOpTags.length !== 2)
throw new WERR_errors_1.WERR_INVALID_PARAMETER('numberOfDesiredUTXOs and minimumDesiredUTXOValue', 'valid');
const numberOfDesiredUTXOs = (0, utilityHelpers_1.verifyInteger)(Number(specOpTags[0]));
const minimumDesiredUTXOValue = (0, utilityHelpers_1.verifyInteger)(Number(specOpTags[1]));
const basket = (0, utilityHelpers_1.verifyOne)(await s.findOutputBaskets({
partial: { userId: (0, utilityHelpers_1.verifyId)(auth.userId), name: 'default' }
}));
await s.updateOutputBasket(basket.basketId, {
numberOfDesiredUTXOs,
minimumDesiredUTXOValue
});
return { totalOutputs: 0, outputs: [] };
}
}
};
};
const getTagToSpecOp = () => {
return {
[types_1.specOpWalletBalance]: {
name: 'totalOutputsIsWalletBalance',
useBasket: 'default',
ignoreLimit: true,
totalOutputsIsSumOfSatoshis: true,
resultFromOutputs: async (s, auth, vargs, specOpTags, outputs) => {
let totalOutputs = 0;
for (const o of outputs)
totalOutputs += o.satoshis;
return { totalOutputs, outputs: [] };
}
}
};
};
let _basketSpecOps = undefined;
let _tagSpecOps = undefined;
/**
* Check basket and tags arguments passed to listOutputs to determine if they trigger a special operation execution mode.
* @param basket
* @param tags
* @returns
*/
function getListOutputsSpecOp(basket, tags) {
let specOp;
if (basket) {
if (_basketSpecOps === undefined) {
_basketSpecOps = getBasketToSpecOp();
}
specOp = _basketSpecOps[basket];
if (specOp) {
return { specOp, basket: specOp.useBasket, tags: tags || [] };
}
}
if (tags) {
if (_tagSpecOps === undefined) {
_tagSpecOps = getTagToSpecOp();
}
for (const tag of tags) {
specOp = _tagSpecOps[tag];
if (specOp) {
if (!basket && specOp.useBasket)
basket = specOp.useBasket;
return { specOp, basket, tags: tags.filter(t => t !== tag) };
}
}
}
return { specOp: undefined, basket, tags };
}
//# sourceMappingURL=ListOutputsSpecOp.js.map