UNPKG

@bsv/wallet-toolbox-client

Version:
721 lines 33.6 kB
"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