@bsv/wallet-toolbox-client
Version:
Client only Wallet Storage
721 lines • 33.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Wallet = void 0;
const sdk_1 = require("@bsv/sdk");
const acquireDirectCertificate_1 = require("./signer/methods/acquireDirectCertificate");
const proveCertificate_1 = require("./signer/methods/proveCertificate");
const createAction_1 = require("./signer/methods/createAction");
const signAction_1 = require("./signer/methods/signAction");
const internalizeAction_1 = require("./signer/methods/internalizeAction");
const WalletSettingsManager_1 = require("./WalletSettingsManager");
const identityUtils_1 = require("./utility/identityUtils");
const generateChange_1 = require("./storage/methods/generateChange");
const utilityHelpers_1 = require("./utility/utilityHelpers");
const ScriptTemplateBRC29_1 = require("./utility/ScriptTemplateBRC29");
const types_1 = require("./sdk/types");
const WERR_errors_1 = require("./sdk/WERR_errors");
const validationHelpers_1 = require("./sdk/validationHelpers");
const WalletError_1 = require("./sdk/WalletError");
function isWalletSigner(args) {
return args['isWalletSigner'];
}
class Wallet {
constructor(argsOrSigner, services, monitor, privilegedKeyManager) {
/**
* If true, signableTransactions will include sourceTransaction for each input,
* including those that do not require signature and those that were also contained
* in the inputBEEF.
*/
this.includeAllSourceTransactions = true;
/**
* If true, txids that are known to the wallet's party beef do not need to be returned from storage.
*/
this.autoKnownTxids = false;
/**
* If true, beefs returned to the user may contain txidOnly transactions.
*/
this.returnTxidOnly = false;
/**
* For repeatability testing, set to an array of random numbers from [0..1).
*/
this.randomVals = undefined;
const args = !isWalletSigner(argsOrSigner)
? argsOrSigner
: {
chain: argsOrSigner.chain,
keyDeriver: argsOrSigner.keyDeriver,
storage: argsOrSigner.storage,
services,
monitor,
privilegedKeyManager
};
if (args.storage._authId.identityKey != args.keyDeriver.identityKey)
throw new WERR_errors_1.WERR_INVALID_PARAMETER('storage', `authenticated as the same identityKey (${args.storage._authId.identityKey}) as the keyDeriver (${args.keyDeriver.identityKey}).`);
this.settingsManager = args.settingsManager || new WalletSettingsManager_1.WalletSettingsManager(this);
this.chain = args.chain;
this.lookupResolver =
args.lookupResolver ||
new sdk_1.LookupResolver({
networkPreset: (0, utilityHelpers_1.toWalletNetwork)(this.chain)
});
this.keyDeriver = args.keyDeriver;
this.storage = args.storage;
this.proto = new sdk_1.ProtoWallet(args.keyDeriver);
this.services = args.services;
this.monitor = args.monitor;
this.privilegedKeyManager = args.privilegedKeyManager;
this.identityKey = this.keyDeriver.identityKey;
this.pendingSignActions = {};
this.userParty = `user ${this.getClientChangeKeyPair().publicKey}`;
this.beef = new sdk_1.BeefParty([this.userParty]);
this.trustSelf = 'known';
if (this.services) {
this.storage.setServices(this.services);
}
}
async destroy() {
await this.storage.destroy();
if (this.privilegedKeyManager)
await this.privilegedKeyManager.destroyKey();
}
getClientChangeKeyPair() {
const kp = {
privateKey: this.keyDeriver.rootKey.toString(),
publicKey: this.keyDeriver.rootKey.toPublicKey().toString()
};
return kp;
}
async getIdentityKey() {
return (await this.getPublicKey({ identityKey: true })).publicKey;
}
getPublicKey(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.getPublicKey(args);
}
return this.proto.getPublicKey(args);
}
revealCounterpartyKeyLinkage(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.revealCounterpartyKeyLinkage(args);
}
return this.proto.revealCounterpartyKeyLinkage(args);
}
revealSpecificKeyLinkage(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.revealSpecificKeyLinkage(args);
}
return this.proto.revealSpecificKeyLinkage(args);
}
encrypt(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.encrypt(args);
}
return this.proto.encrypt(args);
}
decrypt(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.decrypt(args);
}
return this.proto.decrypt(args);
}
createHmac(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.createHmac(args);
}
return this.proto.createHmac(args);
}
verifyHmac(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.verifyHmac(args);
}
return this.proto.verifyHmac(args);
}
createSignature(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.createSignature(args);
}
return this.proto.createSignature(args);
}
verifySignature(args, originator) {
if (args.privileged) {
if (!this.privilegedKeyManager) {
throw new Error('Privileged operations require the Wallet to be configured with a privileged key manager.');
}
return this.privilegedKeyManager.verifySignature(args);
}
return this.proto.verifySignature(args);
}
getServices() {
if (!this.services)
throw new WERR_errors_1.WERR_INVALID_PARAMETER('services', 'valid in constructor arguments to be retreived here.');
return this.services;
}
/**
* @returns the full list of txids whose validity this wallet claims to know.
*
* @param newKnownTxids Optional. Additional new txids known to be valid by the caller to be merged.
*/
getKnownTxids(newKnownTxids) {
if (newKnownTxids) {
for (const txid of newKnownTxids)
this.beef.mergeTxidOnly(txid);
}
const r = this.beef.sortTxs();
const knownTxids = r.valid;
return knownTxids;
}
getStorageIdentity() {
const s = this.storage.getSettings();
return {
storageIdentityKey: s.storageIdentityKey,
storageName: s.storageName
};
}
validateAuthAndArgs(args, validate) {
const vargs = validate(args);
const auth = { identityKey: this.identityKey };
return { vargs, auth };
}
//////////////////
// List Methods
//////////////////
async listActions(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
const { vargs } = this.validateAuthAndArgs(args, validationHelpers_1.validateListActionsArgs);
const r = await this.storage.listActions(vargs);
return r;
}
get storageParty() {
return `storage ${this.getStorageIdentity().storageIdentityKey}`;
}
async listOutputs(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
const { vargs } = this.validateAuthAndArgs(args, validationHelpers_1.validateListOutputsArgs);
if (this.autoKnownTxids && !vargs.knownTxids) {
vargs.knownTxids = this.getKnownTxids();
}
const r = await this.storage.listOutputs(vargs);
if (r.BEEF) {
this.beef.mergeBeefFromParty(this.storageParty, r.BEEF);
r.BEEF = this.verifyReturnedTxidOnlyBEEF(r.BEEF);
}
return r;
}
async listCertificates(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
const { vargs } = this.validateAuthAndArgs(args, validationHelpers_1.validateListCertificatesArgs);
const r = await this.storage.listCertificates(vargs);
return r;
}
//////////////////
// Certificates
//////////////////
async acquireCertificate(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
if (args.acquisitionProtocol === 'direct') {
const { auth, vargs } = this.validateAuthAndArgs(args, validationHelpers_1.validateAcquireDirectCertificateArgs);
vargs.subject = (await this.getPublicKey({
identityKey: true,
privileged: args.privileged,
privilegedReason: args.privilegedReason
})).publicKey;
try {
// Confirm that the information received adds up to a usable certificate...
// TODO: Clean up MasterCertificate to support decrypt on instance
const cert = new sdk_1.MasterCertificate(vargs.type, vargs.serialNumber, vargs.subject, vargs.certifier, vargs.revocationOutpoint, vargs.fields, vargs.keyringForSubject, vargs.signature);
await cert.verify();
// Verify certificate details
await sdk_1.MasterCertificate.decryptFields(this, vargs.keyringForSubject, vargs.fields, vargs.certifier, vargs.privileged, vargs.privilegedReason);
}
catch (eu) {
const e = WalletError_1.WalletError.fromUnknown(eu);
throw new WERR_errors_1.WERR_INVALID_PARAMETER('args', `valid encrypted and signed certificate and keyring from revealer. ${e.name}: ${e.message}`);
}
const r = await (0, acquireDirectCertificate_1.acquireDirectCertificate)(this, auth, vargs);
return r;
}
if (args.acquisitionProtocol === 'issuance') {
const { auth, vargs } = this.validateAuthAndArgs(args, validationHelpers_1.validateAcquireIssuanceCertificateArgs);
// Create a random nonce that the server can verify
const clientNonce = await (0, sdk_1.createNonce)(this, vargs.certifier);
// TODO: Consider adding support to request certificates from a certifier before acquiring a certificate.
const authClient = new sdk_1.AuthFetch(this);
// Create a certificate master keyring
// The certifier is able to decrypt these fields as they are the counterparty
const { certificateFields, masterKeyring } = await sdk_1.MasterCertificate.createCertificateFields(this, vargs.certifier, vargs.fields);
// Make a Certificate Signing Request (CSR) to the certifier
const response = await authClient.fetch(`${vargs.certifierUrl}/signCertificate`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
clientNonce,
type: vargs.type,
fields: certificateFields,
masterKeyring
})
});
if (response.headers.get('x-bsv-auth-identity-key') !== vargs.certifier) {
throw new Error(`Invalid certifier! Expected: ${vargs.certifier}, Received: ${response.headers.get('x-bsv-auth-identity-key')}`);
}
const { certificate, serverNonce } = await response.json();
// Validate the server response
if (!certificate) {
throw new Error('No certificate received from certifier!');
}
if (!serverNonce) {
throw new Error('No serverNonce received from certifier!');
}
const signedCertificate = new sdk_1.Certificate(certificate.type, certificate.serialNumber, certificate.subject, certificate.certifier, certificate.revocationOutpoint, certificate.fields, certificate.signature);
// Validate server nonce
await (0, sdk_1.verifyNonce)(serverNonce, this, vargs.certifier);
// Verify the server included our nonce
const { valid } = await this.verifyHmac({
hmac: sdk_1.Utils.toArray(signedCertificate.serialNumber, 'base64'),
data: sdk_1.Utils.toArray(clientNonce + serverNonce, 'base64'),
protocolID: [2, 'certificate issuance'],
keyID: serverNonce + clientNonce,
counterparty: vargs.certifier
});
if (!valid)
throw new Error('Invalid serialNumber');
// Validate the certificate received
if (signedCertificate.type !== vargs.type) {
throw new Error(`Invalid certificate type! Expected: ${vargs.type}, Received: ${signedCertificate.type}`);
}
if (signedCertificate.subject !== this.identityKey) {
throw new Error(`Invalid certificate subject! Expected: ${this.identityKey}, Received: ${signedCertificate.subject}`);
}
if (signedCertificate.certifier !== vargs.certifier) {
throw new Error(`Invalid certifier! Expected: ${vargs.certifier}, Received: ${signedCertificate.certifier}`);
}
if (!signedCertificate.revocationOutpoint) {
throw new Error(`Invalid revocationOutpoint!`);
}
if (Object.keys(signedCertificate.fields).length !== Object.keys(certificateFields).length) {
throw new Error(`Fields mismatch! Objects have different numbers of keys.`);
}
for (const field of Object.keys(certificateFields)) {
if (!(field in signedCertificate.fields)) {
throw new Error(`Missing field: ${field} in certificate.fields`);
}
if (signedCertificate.fields[field] !== certificateFields[field]) {
throw new Error(`Invalid field! Expected: ${certificateFields[field]}, Received: ${signedCertificate.fields[field]}`);
}
}
await signedCertificate.verify();
// Test decryption works
await sdk_1.MasterCertificate.decryptFields(this, masterKeyring, certificate.fields, vargs.certifier);
// Store the newly issued certificate
return await (0, acquireDirectCertificate_1.acquireDirectCertificate)(this, auth, {
...certificate,
keyringRevealer: 'certifier',
keyringForSubject: masterKeyring,
privileged: vargs.privileged
});
}
throw new WERR_errors_1.WERR_INVALID_PARAMETER('acquisitionProtocol', `valid.${args.acquisitionProtocol} is unrecognized.`);
}
async relinquishCertificate(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
this.validateAuthAndArgs(args, validationHelpers_1.validateRelinquishCertificateArgs);
const r = await this.storage.relinquishCertificate(args);
return { relinquished: true };
}
async proveCertificate(args, originator) {
originator = (0, validationHelpers_1.validateOriginator)(originator);
const { auth, vargs } = this.validateAuthAndArgs(args, validationHelpers_1.validateProveCertificateArgs);
const r = await (0, proveCertificate_1.proveCertificate)(this, auth, vargs);
return r;
}
async discoverByIdentityKey(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
this.validateAuthAndArgs(args, validationHelpers_1.validateDiscoverByIdentityKeyArgs);
const trustSettings = (await this.settingsManager.get()).trustSettings;
const results = await (0, identityUtils_1.queryOverlay)({
identityKey: args.identityKey,
certifiers: trustSettings.trustedCertifiers.map(certifier => certifier.identityKey)
}, this.lookupResolver);
if (!results) {
return {
totalCertificates: 0,
certificates: []
};
}
return (0, identityUtils_1.transformVerifiableCertificatesWithTrust)(trustSettings, results);
}
async discoverByAttributes(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
this.validateAuthAndArgs(args, validationHelpers_1.validateDiscoverByAttributesArgs);
const trustSettings = (await this.settingsManager.get()).trustSettings;
const results = await (0, identityUtils_1.queryOverlay)({
attributes: args.attributes,
certifiers: trustSettings.trustedCertifiers.map(certifier => certifier.identityKey)
}, this.lookupResolver);
if (!results) {
return {
totalCertificates: 0,
certificates: []
};
}
return (0, identityUtils_1.transformVerifiableCertificatesWithTrust)(trustSettings, results);
}
verifyReturnedTxidOnly(beef, knownTxids) {
if (this.returnTxidOnly)
return beef;
const onlyTxids = beef.txs.filter(btx => btx.isTxidOnly).map(btx => btx.txid);
for (const txid of onlyTxids) {
if (knownTxids && knownTxids.indexOf(txid) >= 0)
continue;
const btx = beef.findTxid(txid);
const tx = this.beef.findAtomicTransaction(txid);
if (!tx)
throw new WERR_errors_1.WERR_INTERNAL(`unable to merge txid ${txid} into beef`);
beef.mergeTransaction(tx);
}
for (const btx of beef.txs) {
if (knownTxids && knownTxids.indexOf(btx.txid) >= 0)
continue;
if (btx.isTxidOnly)
throw new WERR_errors_1.WERR_INTERNAL(`remaining txidOnly ${btx.txid} is not known`);
}
return beef;
}
verifyReturnedTxidOnlyAtomicBEEF(beef, knownTxids) {
if (this.returnTxidOnly)
return beef;
const b = sdk_1.Beef.fromBinary(beef);
if (!b.atomicTxid)
throw new WERR_errors_1.WERR_INTERNAL();
return this.verifyReturnedTxidOnly(b, knownTxids).toBinaryAtomic(b.atomicTxid);
}
verifyReturnedTxidOnlyBEEF(beef) {
if (this.returnTxidOnly)
return beef;
const b = sdk_1.Beef.fromBinary(beef);
return this.verifyReturnedTxidOnly(b).toBinary();
}
//////////////////
// Actions
//////////////////
async createAction(args, originator) {
var _a;
var _b;
(0, validationHelpers_1.validateOriginator)(originator);
if (!args.options)
args.options = {};
(_b = args.options).trustSelf || (_b.trustSelf = this.trustSelf);
if (this.autoKnownTxids && !args.options.knownTxids) {
args.options.knownTxids = this.getKnownTxids(args.options.knownTxids);
}
const { auth, vargs } = this.validateAuthAndArgs(args, validationHelpers_1.validateCreateActionArgs);
if (vargs.labels.indexOf(types_1.specOpThrowReviewActions) >= 0)
throwDummyReviewActions();
vargs.includeAllSourceTransactions = this.includeAllSourceTransactions;
if (this.randomVals && this.randomVals.length > 1) {
vargs.randomVals = [...this.randomVals];
}
const r = await (0, createAction_1.createAction)(this, auth, vargs);
if (r.tx) {
this.beef.mergeBeefFromParty(this.storageParty, r.tx);
}
if (r.tx)
r.tx = this.verifyReturnedTxidOnlyAtomicBEEF(r.tx, (_a = args.options) === null || _a === void 0 ? void 0 : _a.knownTxids);
if (!vargs.isDelayed)
throwIfAnyUnsuccessfulCreateActions(r);
return r;
}
async signAction(args, originator) {
var _a;
(0, validationHelpers_1.validateOriginator)(originator);
const { auth, vargs } = this.validateAuthAndArgs(args, validationHelpers_1.validateSignActionArgs);
// createAction options are merged with undefined signAction options before validation...
const r = await (0, signAction_1.signAction)(this, auth, args);
if (!vargs.isDelayed)
throwIfAnyUnsuccessfulSignActions(r);
const prior = this.pendingSignActions[args.reference];
if (r.tx)
r.tx = this.verifyReturnedTxidOnlyAtomicBEEF(r.tx, (_a = prior.args.options) === null || _a === void 0 ? void 0 : _a.knownTxids);
return r;
}
async internalizeAction(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
const { auth, vargs } = this.validateAuthAndArgs(args, validationHelpers_1.validateInternalizeActionArgs);
if (vargs.labels.indexOf(types_1.specOpThrowReviewActions) >= 0)
throwDummyReviewActions();
const r = await (0, internalizeAction_1.internalizeAction)(this, auth, args);
throwIfUnsuccessfulInternalizeAction(r);
return r;
}
async abortAction(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
const { auth } = this.validateAuthAndArgs(args, validationHelpers_1.validateAbortActionArgs);
const r = await this.storage.abortAction(args);
return r;
}
async relinquishOutput(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
const { vargs } = this.validateAuthAndArgs(args, validationHelpers_1.validateRelinquishOutputArgs);
const r = await this.storage.relinquishOutput(args);
return { relinquished: true };
}
async isAuthenticated(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
const r = {
authenticated: true
};
return r;
}
async waitForAuthentication(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
return { authenticated: true };
}
async getHeight(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
const height = await this.getServices().getHeight();
return { height };
}
async getHeaderForHeight(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
const serializedHeader = await this.getServices().getHeaderForHeight(args.height);
return { header: sdk_1.Utils.toHex(serializedHeader) };
}
async getNetwork(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
return { network: (0, utilityHelpers_1.toWalletNetwork)(this.chain) };
}
async getVersion(args, originator) {
(0, validationHelpers_1.validateOriginator)(originator);
return { version: 'wallet-brc100-1.0.0' };
}
/**
* Transfer all possible satoshis held by this wallet to `toWallet`.
*
* @param toWallet wallet which will receive this wallet's satoshis.
*/
async sweepTo(toWallet) {
const derivationPrefix = (0, utilityHelpers_1.randomBytesBase64)(8);
const derivationSuffix = (0, utilityHelpers_1.randomBytesBase64)(8);
const keyDeriver = this.keyDeriver;
const t = new ScriptTemplateBRC29_1.ScriptTemplateBRC29({
derivationPrefix,
derivationSuffix,
keyDeriver
});
const label = 'sweep';
const satoshis = generateChange_1.maxPossibleSatoshis;
const car = await this.createAction({
outputs: [
{
lockingScript: t.lock(keyDeriver.rootKey.toString(), toWallet.identityKey).toHex(),
satoshis,
outputDescription: label,
tags: ['relinquish'],
customInstructions: JSON.stringify({
derivationPrefix,
derivationSuffix,
type: 'BRC29'
})
}
],
options: {
randomizeOutputs: false,
acceptDelayedBroadcast: false
},
labels: [label],
description: label
});
const iar = await toWallet.internalizeAction({
tx: car.tx,
outputs: [
{
outputIndex: 0,
protocol: 'wallet payment',
paymentRemittance: {
derivationPrefix,
derivationSuffix,
senderIdentityKey: this.identityKey
}
}
],
description: label,
labels: [label]
});
}
/**
* Uses `listOutputs` to iterate over chunks of up to 1000 outputs to
* compute the sum of output satoshis.
*
* @param {string} basket - Optional. Defaults to 'default', the wallet change basket.
* @returns {WalletBalance} total sum of output satoshis and utxo details (satoshis and outpoints)
*/
async balanceAndUtxos(basket = 'default') {
const r = { total: 0, utxos: [] };
let offset = 0;
for (;;) {
const change = await this.listOutputs({
basket,
limit: 1000,
offset
});
if (change.totalOutputs === 0)
break;
for (const o of change.outputs) {
r.total += o.satoshis;
r.utxos.push({ satoshis: o.satoshis, outpoint: o.outpoint });
}
offset += change.outputs.length;
}
return r;
}
/**
* Uses `listOutputs` special operation to compute the total value (of satoshis) for
* all spendable outputs in the 'default' basket.
*
* @returns {number} sum of output satoshis
*/
async balance() {
const args = {
basket: types_1.specOpWalletBalance
};
const r = await this.listOutputs(args);
return r.totalOutputs;
}
/**
* Uses `listOutputs` special operation to review the spendability via `Services` of
* outputs currently considered spendable. Returns the outputs that fail to verify.
*
* Ignores the `limit` and `offset` properties.
*
* @param all Defaults to false. If false, only change outputs ('default' basket) are reviewed. If true, all spendable outputs are reviewed.
* @param release Defaults to false. If true, sets outputs that fail to verify to un-spendable (spendable: false)
* @param optionalArgs Optional. Additional tags will constrain the outputs processed.
* @returns outputs which are/where considered spendable but currently fail to verify as spendable.
*/
async reviewSpendableOutputs(all = false, release = false, optionalArgs) {
const args = {
...(optionalArgs || {}),
basket: types_1.specOpInvalidChange
};
args.tags || (args.tags = []);
if (all)
args.tags.push('all');
if (release)
args.tags.push('release');
const r = await this.listOutputs(args);
return r;
}
/**
* Uses `listOutputs` special operation to update the 'default' basket's automatic
* change generation parameters.
*
* @param count target number of change UTXOs to maintain.
* @param satoshis target value for new change outputs.
*/
async setWalletChangeParams(count, satoshis) {
const args = {
basket: types_1.specOpSetWalletChangeParams,
tags: [count.toString(), satoshis.toString()]
};
await this.listOutputs(args);
}
/**
* Uses `listActions` special operation to return only actions with status 'nosend'.
*
* @param abort Defaults to false. If true, runs `abortAction` on each 'nosend' action.
* @returns {ListActionsResult} start `listActions` result restricted to 'nosend' (or 'failed' if aborted) actions.
*/
async listNoSendActions(args, abort = false) {
const { vargs } = this.validateAuthAndArgs(args, validationHelpers_1.validateListActionsArgs);
vargs.labels.push(types_1.specOpNoSendActions);
if (abort)
vargs.labels.push('abort');
const r = await this.storage.listActions(vargs);
return r;
}
/**
* Uses `listActions` special operation to return only actions with status 'failed'.
*
* @param unfail Defaults to false. If true, queues the action for attempted recovery.
* @returns {ListActionsResult} start `listActions` result restricted to 'failed' status actions.
*/
async listFailedActions(args, unfail = false) {
const { vargs } = this.validateAuthAndArgs(args, validationHelpers_1.validateListActionsArgs);
vargs.labels.push(types_1.specOpFailedActions);
if (unfail)
vargs.labels.push('unfail');
const r = await this.storage.listActions(vargs);
return r;
}
}
exports.Wallet = Wallet;
function throwIfAnyUnsuccessfulCreateActions(r) {
const ndrs = r.notDelayedResults;
const swrs = r.sendWithResults;
if (!ndrs || !swrs || swrs.every(r => r.status === 'unproven'))
return;
throw new WERR_errors_1.WERR_REVIEW_ACTIONS(ndrs, swrs, r.txid, r.tx, r.noSendChange);
}
function throwIfAnyUnsuccessfulSignActions(r) {
const ndrs = r.notDelayedResults;
const swrs = r.sendWithResults;
if (!ndrs || !swrs || swrs.every(r => r.status === 'unproven'))
return;
throw new WERR_errors_1.WERR_REVIEW_ACTIONS(ndrs, swrs, r.txid, r.tx);
}
function throwIfUnsuccessfulInternalizeAction(r) {
const ndrs = r.notDelayedResults;
const swrs = r.sendWithResults;
if (!ndrs || !swrs || swrs.every(r => r.status === 'unproven'))
return;
throw new WERR_errors_1.WERR_REVIEW_ACTIONS(ndrs, swrs, r.txid);
}
/**
* Throws a WERR_REVIEW_ACTIONS with a full set of properties to test data formats and propagation.
*/
function throwDummyReviewActions() {
const b58Beef = 'gno9MC7VXii1KoCkc2nsVyYJpqzN3dhBzYATETJcys62emMKfpBof4R7GozwYEaSapUtnNvqQ57aaYYjm3U2dv9eUJ1sV46boHkQgppYmAz9YH8FdZduV8aJayPViaKcyPmbDhEw6UW8TM5iFZLXNs7HBnJHUKCeTdNK4FUEL7vAugxAV9WUUZ43BZjJk2SmSeps9TCXjt1Ci9fKWp3d9QSoYvTpxwzyUFHjRKtbUgwq55ZfkBp5bV2Bpz9qSuKywKewW7Hh4S1nCUScwwzpKDozb3zic1V9p2k8rQxoPsRxjUJ8bjhNDdsN8d7KukFuc3n47fXzdWttvnxwsujLJRGnQbgJuknQqx3KLf5kJXHzwjG6TzigZk2t24qeB6d3hbYiaDr2fFkUJBL3tukTHhfNkQYRXuz3kucVDzvejHyqJaF51mXG8BjMN5aQj91ZJXCaPVqkMWCzmvyaqmXMdRiJdSAynhXbQK91xf6RwdNhz1tg5f9B6oJJMhsi9UYSVymmax8VLKD9AKzBCBDcfyD83m3jyS1VgKGZn3SkQmr6bsoWq88L3GsMnnmYUGogvdAYarTqg3pzkjCMxHzmJBMN6ofnUk8c1sRTXQue7BbyUaN5uZu3KW6CmFsEfpuqVvnqFW93TU1jrPP2S8yz8AexAnARPCKE8Yz7RfVaT6RCavwQKL3u5iookwRWEZXW1QWmM37yJWHD87SjVynyg327a1CLwcBxmE2CB48QeNVGyQki4CTQMqw2o8TMhDPJej1g68oniAjBcxBLSCs7KGvK3k7AfrHbCMULX9CTibYhCjdFjbsbBoocqJpxxcvkMo1fEEiAzZuiBVZQDYktDdTVbhKHvYkW25HcYX75NJrpNAhm7AjFeKLzEVxqAQkMfvTufpESNRZF4kQqg2Rg8h2ajcKTd5cpEPwXCrZLHm4EaZEmZVbg3QNfGhn7BJu1bHMtLqPD4y8eJxm2uGrW6saf6qKYmmu64F8A667NbD4yskPRQ1S863VzwGpxxmgLc1Ta3R46jEqsAoRDoZVUaCgBBZG3Yg1CTgi1EVBMXU7qvY4n3h8o2FLCEMWY4KadnV3iD4FbcdCmg4yxBosNAZgbPjhgGjCimjh4YsLd9zymGLmivmz2ZBg5m3xaiXT9NN81X9C1JUujd';
const beef = sdk_1.Beef.fromBinary(sdk_1.Utils.fromBase58(b58Beef));
const btx = beef.txs.slice(-1)[0];
const txid = btx.txid;
debugger;
throw new WERR_errors_1.WERR_REVIEW_ACTIONS([
{
txid, // only care that it is syntactically a txid
status: 'doubleSpend',
competingTxs: [txid], // a txid in the beef
competingBeef: beef.toBinary()
}
], [
{
txid,
status: 'failed'
}
], txid, beef.toBinaryAtomic(txid), [`${txid}.0`]);
}
//# sourceMappingURL=Wallet.js.map