wallet-storage-client
Version:
Client only Wallet Storage
94 lines • 4.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.internalizeAction = internalizeAction;
const sdk_1 = require("@bsv/sdk");
const index_client_1 = require("../../index.client");
/**
* Internalize Action allows a wallet to take ownership of outputs in a pre-existing transaction.
* The transaction may, or may not already be known to both the storage and user.
*
* Two types of outputs are handled: "wallet payments" and "basket insertions".
*
* A "basket insertion" output is considered a custom output and has no effect on the wallet's "balance".
*
* A "wallet payment" adds an outputs value to the wallet's change "balance". These outputs are assigned to the "default" basket.
*
* Processing starts with simple validation and then checks for a pre-existing transaction.
* If the transaction is already known to the user, then the outputs are reviewed against the existing outputs treatment,
* and merge rules are added to the arguments passed to the storage layer.
* The existing transaction must be in the 'unproven' or 'completed' status. Any other status is an error.
*
* When the transaction already exists, the description is updated. The isOutgoing sense is not changed.
*
* "basket insertion" Merge Rules:
* 1. The "default" basket may not be specified as the insertion basket.
* 2. A change output in the "default" basket may not be target of an insertion into a different basket.
* 3. These baskets do not affect the wallet's balance and are typed "custom".
*
* "wallet payment" Merge Rules:
* 1. Targetting an existing change "default" basket output results in a no-op. No error. No alterations made.
* 2. Targetting a previously "custom" non-change output converts it into a change output. This alters the transaction's `amount`, and the wallet balance.
*
*/
async function internalizeAction(wallet, auth, args) {
const vargs = index_client_1.sdk.validateInternalizeActionArgs(args);
const { ab, tx, txid } = await validateAtomicBeef();
const brc29ProtocolID = [2, '3241645161d8'];
for (const o of vargs.outputs) {
if (o.outputIndex < 0 || o.outputIndex >= tx.outputs.length)
throw new index_client_1.sdk.WERR_INVALID_PARAMETER('outputIndex', `a valid output index in range 0 to ${tx.outputs.length - 1}`);
switch (o.protocol) {
case 'basket insertion':
setupBasketInsertionForOutput(o, vargs);
break;
case 'wallet payment':
setupWalletPaymentForOutput(o, vargs);
break;
default: throw new index_client_1.sdk.WERR_INTERNAL(`unexpected protocol ${o.protocol}`);
}
}
const r = await wallet.storage.internalizeAction(args);
return r;
function setupWalletPaymentForOutput(o, dargs) {
const p = o.paymentRemittance;
const output = tx.outputs[o.outputIndex];
if (!p)
throw new index_client_1.sdk.WERR_INVALID_PARAMETER('paymentRemitance', `valid for protocol ${o.protocol}`);
const keyID = `${p.derivationPrefix} ${p.derivationSuffix}`;
const privKey = wallet.keyDeriver.derivePrivateKey(brc29ProtocolID, keyID, p.senderIdentityKey);
const expectedLockScript = new sdk_1.P2PKH().lock(privKey.toAddress());
if (output.lockingScript.toHex() !== expectedLockScript.toHex())
throw new index_client_1.sdk.WERR_INVALID_PARAMETER('paymentRemitance', `locked by script conforming to BRC-29`);
}
function setupBasketInsertionForOutput(o, dargs) {
/*
No additional validations...
*/
}
async function validateAtomicBeef() {
const ab = sdk_1.Beef.fromBinary(vargs.tx);
// TODO: Add support for known txids...
const txValid = await ab.verify(await wallet.getServices().getChainTracker(), false);
if (!txValid || !ab.atomicTxid)
throw new index_client_1.sdk.WERR_INVALID_PARAMETER('tx', 'valid AtomicBEEF');
const txid = ab.atomicTxid;
const btx = ab.findTxid(txid);
if (!btx)
throw new index_client_1.sdk.WERR_INVALID_PARAMETER('tx', `valid AtomicBEEF with newest txid of ${txid}`);
const tx = btx.tx;
/*
for (const i of tx.inputs) {
if (!i.sourceTXID)
throw new sdk.WERR_INTERNAL('beef Transactions must have sourceTXIDs')
if (!i.sourceTransaction) {
const btx = ab.findTxid(i.sourceTXID)
if (!btx)
throw new sdk.WERR_INVALID_PARAMETER('tx', `valid AtomicBEEF and contain input transaction with txid ${i.sourceTXID}`);
i.sourceTransaction = btx.tx
}
}
*/
return { ab, tx, txid };
}
}
//# sourceMappingURL=internalizeAction.js.map