diff --git a/index.html b/index.html
index 27f22ba..8e565f5 100644
--- a/index.html
+++ b/index.html
@@ -501,7 +501,7 @@
.then(() => {
selectedCurrency = localStorage.getItem('taproot-wallet-currency') || 'btc'
setTimeout(() => {
- document.getElementById('currency_selector').value = selectedCurrency
+ getRef('currency_selector').value = selectedCurrency
}, 100)
})
.catch(e => {
@@ -2105,15 +2105,13 @@
-
-
- ${finalScriptWitness.length > 3 ? html`
-
- ` : html`
-
- `}
*The generated signature will be used as one of the solutions.
+ ${finalScriptWitness.length > 3 ? html`
+
+ ` : html`
+
+ `}
` : ''}
-
+
`)
@@ -2174,12 +2172,12 @@
-
+
`)
}
- document.getElementById('new_fee').querySelector('.currency-symbol').innerHTML = currencyIcons[selectedCurrency]
+ getRef('new_fee').querySelector('.currency-symbol').innerHTML = currencyIcons[selectedCurrency]
openPopup('increase_fee_popup')
} catch (e) {
console.error(e)
@@ -2187,39 +2185,54 @@
buttonLoader(button, false)
}
}
- async function increaseFee() {
- buttonLoader(document.getElementById('increase_fee'), true)
- const newFee = parseFloat((parseFloat(document.getElementById('new_fee').value.trim()) / (globalExchangeRate[selectedCurrency] || 1)).toFixed(8))
- const privateKeys = []
- document.querySelectorAll('.increase-fee-sender').forEach(sender => {
- const address = sender.querySelector('.sender__address').textContent.trim()
- const privateKey = sender.querySelector('.sender__private-key').value.trim()
- if (!btcOperator.verifyKey(address, privateKey))
- return notify(`Invalid private key for address ${address}`, 'error')
- if (privateKey) {
- privateKeys.push(privateKey)
- }
- })
- console.log(changingFeeOf, newFee, privateKeys)
+ async function increaseFee(type = 'key-path') {
try {
- let signedTxHex = await taprootEditFee({
- txId: changingFeeOf,
- new_fee: newFee,
- private_keys: privateKeys
- })
- btcOperator.broadcastTx(signedTxHex).then(txId => {
+ buttonLoader(getRef('increase_fee'), true)
+ const newFee = parseFloat((parseFloat(getRef('new_fee').value.trim()) / (globalExchangeRate[selectedCurrency] || 1)).toFixed(8))
+ let txHex
+ if (type === 'key-path') {
+ const privateKeys = []
+ document.querySelectorAll('.increase-fee-sender').forEach(sender => {
+ const address = sender.querySelector('.sender__address').textContent.trim()
+ const privateKey = sender.querySelector('.sender__private-key').value.trim()
+ if (!btcOperator.verifyKey(address, privateKey))
+ return notify(`Invalid private key for address ${address}`, 'error')
+ if (privateKey) {
+ privateKeys.push(privateKey)
+ }
+ })
+ txHex = await taprootEditFee({
+ txId: changingFeeOf,
+ newFee: newFee,
+ privateKeys
+ })
+ } else {
+ const providedSolutions = [...document.querySelectorAll('.solution-input')].map(input => input.value.trim())
+ const signaturePlace = parseInt(getRef('signature_place_input').value.trim())
+ const signerPrivateKey = getRef('signer_input') ? getRef('signer_input').value.trim() : null;
+ const editParams = {
+ txId: changingFeeOf,
+ newFee,
+ providedSolutions,
+ signaturePlace,
+ }
+ if (signerPrivateKey)
+ editParams.signerSecretKey = hex.decode(coinjs.wif2privkey(signerPrivateKey).privkey)
+ txHex = await taprootEditFee(editParams)
+ }
+ btcOperator.broadcastTx(txHex).then(txId => {
console.log(txId)
closePopup()
showTransactionResult('success', txId)
}).catch(e => {
notify(e, 'error')
}).finally(_ => {
- buttonLoader(document.getElementById('increase_fee'), false)
+ buttonLoader(getRef('increase_fee'), false)
changingFeeOf = null
})
} catch (err) {
notify(e, 'error')
- buttonLoader(document.getElementById('increase_fee'), false)
+ buttonLoader(getRef('increase_fee'), false)
}
}
router.addRoute('create', state => {
@@ -2487,29 +2500,27 @@
})
}
- const taprootEditFee = function ({ txId, new_fee, private_keys, change_only = true }) {
+ const taprootEditFee = function ({ txId, newFee, privateKeys, changeOnly = true, signerSecretKey, providedSolutions, signaturePlace }) {
return new Promise((resolve, reject) => {
- if (!Array.isArray(private_keys))
- private_keys = [private_keys];
getTaprootTx(txId).then(({ tx, rawTx }) => {
const isScriptPath = tx.inputs[0].finalScriptWitness && tx.inputs[0].finalScriptWitness.length > 1;
const parsedTx = parseTransaction(rawTx)
- if (parsedTx.fee >= new_fee)
+ if (parsedTx.fee >= newFee)
return reject("Fees can only be increased");
//editable addresses in output values (for fee increase)
- parsedTx edit_output_address = new Set();
- if (change_only === true) //allow only change values (ie, sender address) to be edited to inc fee
+ const edit_output_address = new Set();
+ if (changeOnly === true) //allow only change values (ie, sender address) to be edited to inc fee
parsedTx.inputs.forEach(inp => edit_output_address.add(inp.address));
- else if (change_only === false) //allow all output values to be edited
+ else if (changeOnly === false) //allow all output values to be edited
parsedTx.outputs.forEach(out => edit_output_address.add(out.address));
- else if (typeof change_only == 'string') // allow only given receiver id output to be edited
- edit_output_address.add(change_only);
- else if (Array.isArray(change_only)) //allow only given set of receiver id outputs to be edited
- change_only.forEach(id => edit_output_address.add(id));
+ else if (typeof changeOnly == 'string') // allow only given receiver id output to be edited
+ edit_output_address.add(changeOnly);
+ else if (Array.isArray(changeOnly)) //allow only given set of receiver id outputs to be edited
+ changeOnly.forEach(id => edit_output_address.add(id));
//edit output values to increase fee
- let inc_fee = btcOperator.util.BTC_to_Sat(new_fee - parsedTx.fee);
+ let inc_fee = btcOperator.util.BTC_to_Sat(newFee - parsedTx.fee);
if (inc_fee < MIN_FEE_UPDATE)
return reject(`Insufficient additional fee. Minimum increment: ${MIN_FEE_UPDATE}`);
for (let i = tx.outs.length - 1; i >= 0 && inc_fee > 0; i--) //reduce in reverse order
@@ -2527,19 +2538,36 @@
}
}
if (inc_fee > 0) {
- let max_possible_fee = btcOperator.util.BTC_to_Sat(new_fee) - inc_fee; //in satoshi
+ let max_possible_fee = btcOperator.util.BTC_to_Sat(newFee) - inc_fee; //in satoshi
return reject(`Insufficient output values to increase fee. Maximum fee possible: ${btcOperator.util.Sat_to_BTC(max_possible_fee)}`);
}
tx.outs = tx.outs.filter(o => o.value >= DUST_AMT); //remove all output with value less than DUST amount
if (isScriptPath) {
-
+ tx.inputs.forEach((input, index) => {
+ // remove every element from the finalScriptWitness except the last two
+ const scriptWitness = input.finalScriptWitness.slice(-2)
+ const [userScript, controlBlock] = scriptWitness;
+ const controlBlockVersion = taproot.TaprootControlBlock.decode(controlBlock).version
+ const providedSolutions = scriptWitness.slice(0, -1)
+ if (providedSolutions && providedSolutions.length)
+ scriptWitness.unshift(...providedSolutions)
+ if (signerSecretKey) {
+ const { amount } = consumedUtxos[index]
+ const hash = tx.preimageWitnessV1(index, [script], 0, [amount], undefined, userScript, controlBlockVersion)
+ const sig = secp.schnorr.signSync(hash, signerSecretKey, new Uint8Array(32))
+ scriptWitness.splice((signaturePlace - 1), 0, sig)
+ }
+ input.finalScriptWitness = scriptWitness
+ })
} else {
//remove existing signatures and reset the scripts
+ if (!Array.isArray(privateKeys))
+ privateKeys = [privateKeys];
let wif_keys = [];
for (let i in tx.ins) {
const addr = parsedTx.inputs[i].address;
//find the correct key for addr
- const privKey = private_keys.find(pk => btcOperator.verifyKey(addr, pk));
+ const privKey = privateKeys.find(pk => btcOperator.verifyKey(addr, pk));
if (!privKey)
return reject(`Private key missing for ${addr}`);
}