Added BTC multisig transaction fee increase process
This commit is contained in:
parent
0d6c9f5fbe
commit
31d8be6aa7
@ -708,6 +708,10 @@ ol li::before {
|
|||||||
#prompt_popup .flex {
|
#prompt_popup .flex {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
#confirmation_popup sm-input,
|
||||||
|
#prompt_popup sm-input {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
.popup__header {
|
.popup__header {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
2
css/main.min.css
vendored
2
css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -725,6 +725,9 @@ ol {
|
|||||||
.flex {
|
.flex {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
sm-input {
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.popup__header {
|
.popup__header {
|
||||||
|
|||||||
131
index.html
131
index.html
@ -85,7 +85,7 @@
|
|||||||
<h4 id="prompt_title"></h4>
|
<h4 id="prompt_title"></h4>
|
||||||
<p id="prompt_message"></p>
|
<p id="prompt_message"></p>
|
||||||
<sm-form>
|
<sm-form>
|
||||||
<sm-input id="prompt_input"></sm-input>
|
<sm-input id="prompt_input" required></sm-input>
|
||||||
<div class="flex align-center gap-0-5 margin-left-auto">
|
<div class="flex align-center gap-0-5 margin-left-auto">
|
||||||
<button class="button cancel-button">Cancel</button>
|
<button class="button cancel-button">Cancel</button>
|
||||||
<button class="button confirm-button button--primary" type="submit">OK</button>
|
<button class="button confirm-button button--primary" type="submit">OK</button>
|
||||||
@ -1111,7 +1111,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script src="scripts/components.js"></script>
|
<script src="scripts/components.min.js"></script>
|
||||||
<script type="module" src="https://cdn.jsdelivr.net/npm/emoji-picker-element@^1/index.js"></script>
|
<script type="module" src="https://cdn.jsdelivr.net/npm/emoji-picker-element@^1/index.js"></script>
|
||||||
<script>
|
<script>
|
||||||
/*jshint esversion: 8 */
|
/*jshint esversion: 8 */
|
||||||
@ -1526,15 +1526,22 @@
|
|||||||
}
|
}
|
||||||
// displays a popup for asking user input. Use this instead of JS prompt
|
// displays a popup for asking user input. Use this instead of JS prompt
|
||||||
function getPromptInput(title, message = '', options = {}) {
|
function getPromptInput(title, message = '', options = {}) {
|
||||||
let { placeholder = '', isPassword = false, cancelText = 'Cancel', confirmText = 'OK' } = options
|
let { placeholder = '', isPassword = false, cancelText = 'Cancel', confirmText = 'OK', attributes = {} } = options
|
||||||
getRef('prompt_title').innerText = title;
|
getRef('prompt_title').innerText = title;
|
||||||
getRef('prompt_message').innerText = message;
|
getRef('prompt_message').innerText = message;
|
||||||
const cancelButton = getRef('prompt_popup').querySelector('.cancel-button');
|
const cancelButton = getRef('prompt_popup').querySelector('.cancel-button');
|
||||||
const confirmButton = getRef('prompt_popup').querySelector('.confirm-button')
|
const confirmButton = getRef('prompt_popup').querySelector('.confirm-button')
|
||||||
|
// remove all attribute except id
|
||||||
|
while (getRef('prompt_input').attributes.length > 0 && getRef('prompt_input').attributes[0].name !== 'id') {
|
||||||
|
getRef('prompt_input').removeAttribute(getRef('prompt_input').attributes[0].name)
|
||||||
|
}
|
||||||
if (isPassword) {
|
if (isPassword) {
|
||||||
placeholder = 'Password'
|
placeholder = 'Password'
|
||||||
getRef('prompt_input').setAttribute("type", "password")
|
getRef('prompt_input').setAttribute("type", "password")
|
||||||
}
|
}
|
||||||
|
for (const attr in attributes) {
|
||||||
|
getRef('prompt_input').setAttribute(attr, attributes[attr])
|
||||||
|
}
|
||||||
getRef('prompt_input').setAttribute("placeholder", placeholder)
|
getRef('prompt_input').setAttribute("placeholder", placeholder)
|
||||||
getRef('prompt_input').focusIn()
|
getRef('prompt_input').focusIn()
|
||||||
cancelButton.textContent = cancelText;
|
cancelButton.textContent = cancelText;
|
||||||
@ -1543,7 +1550,7 @@
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
cancelButton.addEventListener('click', () => {
|
cancelButton.addEventListener('click', () => {
|
||||||
closePopup()
|
closePopup()
|
||||||
return null
|
resolve(null)
|
||||||
}, { once: true })
|
}, { once: true })
|
||||||
confirmButton.addEventListener('click', () => {
|
confirmButton.addEventListener('click', () => {
|
||||||
closePopup()
|
closePopup()
|
||||||
@ -1633,7 +1640,13 @@
|
|||||||
window.addEventListener('hashchange', e => routeTo(window.location.hash))
|
window.addEventListener('hashchange', e => routeTo(window.location.hash))
|
||||||
window.addEventListener("load", () => {
|
window.addEventListener("load", () => {
|
||||||
document.body.classList.remove('hidden')
|
document.body.classList.remove('hidden')
|
||||||
document.querySelectorAll('sm-input[data-flo-address]').forEach(input => input.customValidation = floCrypto.validateAddr)
|
document.querySelectorAll('sm-input[data-flo-address]').forEach(input => input.customValidation = (value) => {
|
||||||
|
if (!value) return { isValid: false, errorText: 'Please enter a FLO address' }
|
||||||
|
return {
|
||||||
|
isValid: floCrypto.validateAddr(value),
|
||||||
|
errorText: `Invalid FLO address.<br> It usually starts with "F"`
|
||||||
|
}
|
||||||
|
})
|
||||||
document.addEventListener('keyup', (e) => {
|
document.addEventListener('keyup', (e) => {
|
||||||
if (e.key === 'Escape') {
|
if (e.key === 'Escape') {
|
||||||
closePopup()
|
closePopup()
|
||||||
@ -2301,7 +2314,13 @@
|
|||||||
floGlobals.isPrivKeySecured = false;
|
floGlobals.isPrivKeySecured = false;
|
||||||
getRef('private_key_field').dataset.privateKey = ''
|
getRef('private_key_field').dataset.privateKey = ''
|
||||||
getRef('private_key_field').setAttribute('placeholder', 'FLO/BTC private key');
|
getRef('private_key_field').setAttribute('placeholder', 'FLO/BTC private key');
|
||||||
getRef('private_key_field').customValidation = floCrypto.getPubKeyHex;
|
getRef('private_key_field').customValidation = (value) => {
|
||||||
|
if (!value) return { isValid: false, errorText: 'Please enter a private key' }
|
||||||
|
return {
|
||||||
|
isValid: floCrypto.getPubKeyHex(value),
|
||||||
|
errorText: `Invalid private key.<br> It's a long string of random characters usually starting with 'R'.`
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
if (!generalPages.find(page => window.location.hash.includes(page))) {
|
if (!generalPages.find(page => window.location.hash.includes(page))) {
|
||||||
location.hash = floGlobals.isPrivKeySecured ? '#/sign_in' : `#/landing`;
|
location.hash = floGlobals.isPrivKeySecured ? '#/sign_in' : `#/landing`;
|
||||||
@ -3861,6 +3880,32 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
async function initFeeIncrease(parsedTx, currentPipeID, e) {
|
||||||
|
const button = e.target.closest('button')
|
||||||
|
const { fee } = parsedTx;
|
||||||
|
try {
|
||||||
|
const newFee = await getPromptInput('Increase transaction fee', `Current fee: ${fee} BTC.\n *This will create a new group and disable current one.`, {
|
||||||
|
confirmText: 'Increase',
|
||||||
|
placeholder: 'New BTC transaction fee',
|
||||||
|
attributes: {
|
||||||
|
type: 'number',
|
||||||
|
min: fee,
|
||||||
|
step: '0.00000001',
|
||||||
|
'error-text': `New fee should be greater than ${fee} BTC`,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (newFee <= fee)
|
||||||
|
return notify('New fee should be greater than current fee', 'error')
|
||||||
|
buttonLoader(button, true)
|
||||||
|
const newPipeID = await messenger.editFee(parsedTx, newFee)
|
||||||
|
highlightNewGroup(newPipeID)
|
||||||
|
await messenger.disablePipeline(currentPipeID)
|
||||||
|
notify('Created a new multisig group. Please collect required signs again.', 'success')
|
||||||
|
} catch (error) {
|
||||||
|
notify(error, 'error')
|
||||||
|
buttonLoader(button, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let chatLazyLoader
|
let chatLazyLoader
|
||||||
function renderMessages(floID) {
|
function renderMessages(floID) {
|
||||||
@ -3971,21 +4016,45 @@
|
|||||||
}
|
}
|
||||||
if (floGlobals.pipelineTxHex) {
|
if (floGlobals.pipelineTxHex) {
|
||||||
try {
|
try {
|
||||||
let details, currency
|
let parsedTx, currency
|
||||||
switch (messenger.pipeline[floID].model) {
|
switch (messenger.pipeline[floID].model) {
|
||||||
case 'flo_multisig':
|
case 'flo_multisig':
|
||||||
currency = 'FLO'
|
currency = 'FLO'
|
||||||
details = await floBlockchainAPI.parseTransaction(floGlobals.pipelineTxHex)
|
parsedTx = await floBlockchainAPI.parseTransaction(floGlobals.pipelineTxHex)
|
||||||
break;
|
break;
|
||||||
case 'btc_multisig':
|
case 'btc_multisig':
|
||||||
currency = 'BTC'
|
currency = 'BTC'
|
||||||
details = await btcOperator.parseTransaction(floGlobals.pipelineTxHex)
|
parsedTx = await btcOperator.parseTransaction(floGlobals.pipelineTxHex)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const { inputs, outputs, fee, floData } = details
|
const { inputs, outputs, fee, floData } = parsedTx
|
||||||
const { s: signsDone, r: minSignsRequired, t: totalMembers } = inputs[0]?.signed || {}
|
const { s: signsDone, r: minSignsRequired, t: totalMembers } = inputs[0]?.signed || {}
|
||||||
const pendingSigns = minSignsRequired - signsDone || 0;
|
const pendingSigns = minSignsRequired - signsDone || 0;
|
||||||
if ($('#transaction_details')) $('#transaction_details').remove()
|
if ($('#transaction_details')) $('#transaction_details').remove()
|
||||||
|
let retrySection = ''
|
||||||
|
if (pendingSigns === 0 && !messenger.pipeline[floID].disabled) {
|
||||||
|
switch (messenger.pipeline[floID].model) {
|
||||||
|
case 'flo_multisig':
|
||||||
|
retrySection = html`
|
||||||
|
<div class="grid gap-0-5 margin-top-1">
|
||||||
|
<strong> The transaction was not completed. Retry the transaction by clicking the button below.</strong>
|
||||||
|
<div class="multi-state-button margin-right-auto">
|
||||||
|
<button class="button button--primary cta" onclick="${(e) => broadcastTx(floID, e)}">Retry</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
break;
|
||||||
|
case 'btc_multisig':
|
||||||
|
retrySection = html`
|
||||||
|
<div class="grid gap-0-5 margin-top-1">
|
||||||
|
<strong> If transaction is taking too long to confirm, increase transaction fee.</strong>
|
||||||
|
<div class="multi-state-button margin-right-auto">
|
||||||
|
<button class="button button--primary cta" onclick="${(e) => initFeeIncrease(parsedTx, floID, e)}">Increase fee</button>
|
||||||
|
</div>
|
||||||
|
</div>`
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
getRef('messages_container').prepend(html.node`
|
getRef('messages_container').prepend(html.node`
|
||||||
<details id="transaction_details" class="grid gap-1 card" open>
|
<details id="transaction_details" class="grid gap-1 card" open>
|
||||||
<summary>
|
<summary>
|
||||||
@ -4018,16 +4087,9 @@
|
|||||||
<div class="grid">
|
<div class="grid">
|
||||||
<h5>FLO data</h5>
|
<h5>FLO data</h5>
|
||||||
<p>${floData}</p>
|
<p>${floData}</p>
|
||||||
</div>`: ''
|
|
||||||
}
|
|
||||||
${messenger.pipeline[floID].model === 'flo_multisig' && pendingSigns === 0 && !messenger.pipeline[floID].disabled ? html`
|
|
||||||
<div class="grid gap-0-5 margin-top-1">
|
|
||||||
<strong> The transaction was not completed. Retry the transaction by clicking the button below.</strong>
|
|
||||||
<div class="multi-state-button margin-right-auto">
|
|
||||||
<button class="button button--primary cta" onclick="${(e) => broadcastTx(floID, e)}">Retry</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
`: ''}
|
`: ''}
|
||||||
|
${retrySection}
|
||||||
</details>
|
</details>
|
||||||
`)
|
`)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -4787,12 +4849,24 @@
|
|||||||
if (multisigMode === 'flo') {
|
if (multisigMode === 'flo') {
|
||||||
getRef('receiver_container').querySelectorAll('.receiver-input').forEach(input => {
|
getRef('receiver_container').querySelectorAll('.receiver-input').forEach(input => {
|
||||||
input.setAttribute('error-text', 'Invalid FLO address')
|
input.setAttribute('error-text', 'Invalid FLO address')
|
||||||
input.customValidation = floCrypto.validateFloID
|
input.customValidation = (value) => {
|
||||||
|
if (!value) return { isValid: false, errorText: 'Please enter a FLO address' }
|
||||||
|
return {
|
||||||
|
isValid: floCrypto.validateFloID(value),
|
||||||
|
errorText: `Invalid FLO address.<br> It usually starts with "F"`
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
} else if (multisigMode === 'btc') {
|
} else if (multisigMode === 'btc') {
|
||||||
getRef('receiver_container').querySelectorAll('.receiver-input').forEach(input => {
|
getRef('receiver_container').querySelectorAll('.receiver-input').forEach(input => {
|
||||||
input.setAttribute('error-text', 'Invalid BTC address')
|
input.setAttribute('error-text', 'Invalid BTC address')
|
||||||
input.customValidation = btcOperator.validateAddress
|
input.customValidation = (value) => {
|
||||||
|
if (!value) return { isValid: false, errorText: 'Please enter a BTC address' }
|
||||||
|
return {
|
||||||
|
isValid: btcOperator.validateAddr(value),
|
||||||
|
errorText: `Invalid BTC address.<br> It usually starts with '1', '3' or 'bc1'`
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4938,19 +5012,22 @@
|
|||||||
notify('New multisig group created', 'success')
|
notify('New multisig group created', 'success')
|
||||||
closePopup();
|
closePopup();
|
||||||
getRef('send_tx').reset()
|
getRef('send_tx').reset()
|
||||||
getRef('feature_mode').firstElementChild.click();
|
highlightNewGroup(result)
|
||||||
const createdPipelineCard = getRef('chats_list').querySelector(`[data-flo-address="${result}"]`)
|
|
||||||
if (createdPipelineCard) {
|
|
||||||
createdPipelineCard.scrollIntoView({ behavior: 'smooth' })
|
|
||||||
createdPipelineCard.classList.add('highlight')
|
|
||||||
setTimeout(_ => createdPipelineCard.classList.remove('highlight'), 2000)
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
notify(`Error intiating transaction \n ${err}`, 'error');
|
notify(`Error intiating transaction \n ${err}`, 'error');
|
||||||
} finally {
|
} finally {
|
||||||
buttonLoader('initiate_transaction', false)
|
buttonLoader('initiate_transaction', false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function highlightNewGroup(address) {
|
||||||
|
getRef('feature_mode').firstElementChild.click();
|
||||||
|
const createdPipelineCard = getRef('chats_list').querySelector(`[data-flo-address="${address}"]`)
|
||||||
|
if (createdPipelineCard) {
|
||||||
|
createdPipelineCard.scrollIntoView({ behavior: 'smooth' })
|
||||||
|
createdPipelineCard.classList.add('highlight')
|
||||||
|
setTimeout(_ => createdPipelineCard.classList.remove('highlight'), 2000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function signTransaction(pipeID) {
|
function signTransaction(pipeID) {
|
||||||
getConfirmation('Sign transaction', { message: 'Are you sure you want to sign this transaction?', confirmText: 'Sign' }).then(async (res) => {
|
getConfirmation('Sign transaction', { message: 'Are you sure you want to sign this transaction?', confirmText: 'Sign' }).then(async (res) => {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
1
scripts/components.min.js
vendored
Normal file
1
scripts/components.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1409,18 +1409,26 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
messenger.editFee = function(tx_id, new_fee, private_key, change_only = true) {
|
messenger.editFee = function (tx_id, new_fee, private_key, change_only = true) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
//1. FIND REDEEMSCRIPT
|
//? what to do about private_key param? It's not used in anywhere in the function
|
||||||
//2. CHANGE OUTPUT VALUES
|
//1. FIND REDEEMSCRIPT
|
||||||
//3. Call modified version of MultiSig.createTx_BTC_1 where the input taken is txhex rather than senders etc
|
//2. CHANGE OUTPUT VALUES
|
||||||
//4. MultiSig.createTx_BTC_1 will in turn call btcOperator.createMultiSigTx_1(tx_hex). Check that Redeemscript information is present
|
//3. Call modified version of MultiSig.createTx_BTC_1 where the input taken is txhex rather than senders etc
|
||||||
var address;
|
//4. MultiSig.createTx_BTC_1 will in turn call btcOperator.createMultiSigTx_1(tx_hex). Check that Redeemscript information is present
|
||||||
|
var address;
|
||||||
|
|
||||||
if (!Array.isArray(private_keys))
|
if (!Array.isArray(private_keys))
|
||||||
private_keys = [private_keys];
|
private_keys = [private_keys];
|
||||||
btcOperator.tx_fetch_for_editing(tx_id).then(tx => {
|
try {
|
||||||
btcOperator.parseTransaction(tx).then(tx_parsed => {
|
let tx, tx_parsed;
|
||||||
|
|
||||||
|
if (typeof tx_id === 'string') {
|
||||||
|
tx = await btcOperator.tx_fetch_for_editing(tx_id)
|
||||||
|
tx_parsed = await btcOperator.parseTransaction(tx)
|
||||||
|
} else if (tx_id.inputs) {
|
||||||
|
tx_parsed = tx_id
|
||||||
|
}
|
||||||
if (tx_parsed.fee >= new_fee)
|
if (tx_parsed.fee >= new_fee)
|
||||||
return reject("Fees can only be increased");
|
return reject("Fees can only be increased");
|
||||||
|
|
||||||
@ -1486,7 +1494,7 @@
|
|||||||
script = Crypto.util.bytesToHex(s.buffer);
|
script = Crypto.util.bytesToHex(s.buffer);
|
||||||
} else if (((rs.match(/^00/) && rs.length == 44)) || (rs.length == 40 && rs.match(/^[a-f0-9]+$/gi))) {
|
} else if (((rs.match(/^00/) && rs.length == 44)) || (rs.length == 40 && rs.match(/^[a-f0-9]+$/gi))) {
|
||||||
//redeemScript for segwit/bech32
|
//redeemScript for segwit/bech32
|
||||||
if (addr_decode == "bech32") {witness_position = witness_position + 1;} //bech32 has witness
|
if (addr_decode == "bech32") { witness_position = witness_position + 1; } //bech32 has witness
|
||||||
let s = coinjs.script();
|
let s = coinjs.script();
|
||||||
s.writeBytes(Crypto.util.hexToBytes(rs));
|
s.writeBytes(Crypto.util.hexToBytes(rs));
|
||||||
s.writeOp(0);
|
s.writeOp(0);
|
||||||
@ -1499,7 +1507,7 @@
|
|||||||
rs_array = btcOperator.extractLastHexStrings(tx.witness);
|
rs_array = btcOperator.extractLastHexStrings(tx.witness);
|
||||||
let redeemScript = rs_array[witness_position];
|
let redeemScript = rs_array[witness_position];
|
||||||
witness_position = witness_position + 1; //this permits mixing witness and non witness based inputs
|
witness_position = witness_position + 1; //this permits mixing witness and non witness based inputs
|
||||||
|
|
||||||
let s = coinjs.script();
|
let s = coinjs.script();
|
||||||
s.writeBytes(Crypto.util.hexToBytes(redeemScript));
|
s.writeBytes(Crypto.util.hexToBytes(redeemScript));
|
||||||
s.writeOp(0);
|
s.writeOp(0);
|
||||||
@ -1512,7 +1520,7 @@
|
|||||||
tx.witness = false; //remove all witness signatures
|
tx.witness = false; //remove all witness signatures
|
||||||
console.debug("Unsigned:", tx.serialize());
|
console.debug("Unsigned:", tx.serialize());
|
||||||
//re-sign the transaction
|
//re-sign the transaction
|
||||||
new Set(wif_keys).forEach(key => tx.sign(key, 1 /*sighashtype*/ )); //Sign the tx using private key WIF
|
new Set(wif_keys).forEach(key => tx.sign(key, 1 /*sighashtype*/)); //Sign the tx using private key WIF
|
||||||
let tx_hex = tx.serialize();
|
let tx_hex = tx.serialize();
|
||||||
|
|
||||||
//Call MultiSig.createTx_BTC_editFee(tx.serialize());
|
//Call MultiSig.createTx_BTC_editFee(tx.serialize());
|
||||||
@ -1531,24 +1539,21 @@
|
|||||||
//let privateKey = await floDapps.user.private;
|
//let privateKey = await floDapps.user.private;
|
||||||
|
|
||||||
// let tx_hex = btcOperator.signTx_1(tx, privateKey);
|
// let tx_hex = btcOperator.signTx_1(tx, privateKey);
|
||||||
|
|
||||||
createPipeline(TYPE_BTC_MULTISIG, co_owners, 32, decode.pubkeys).then(pipeline => {
|
createPipeline(TYPE_BTC_MULTISIG, co_owners, 32, decode.pubkeys).then(pipeline => {
|
||||||
let message = encrypt(tx_hex, pipeline.eKey);
|
let message = encrypt(tx_hex, pipeline.eKey);
|
||||||
sendRaw(message, pipeline.id, "TRANSACTION", false)
|
sendRaw(message, pipeline.id, "TRANSACTION", false)
|
||||||
.then(result => resolve(pipeline.id))
|
.then(result => resolve(pipeline.id))
|
||||||
.catch(error => reject(error)) //SENDRAW
|
.catch(error => reject(error)) //SENDRAW
|
||||||
}).catch(error => reject(error)) //CREATE PIPELINE
|
}).catch(error => reject(error)) //CREATE PIPELINE
|
||||||
|
// resolve(tx.serialize()); //CHECK THIS -- NOT NEEDED
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// resolve(tx.serialize()); //CHECK THIS -- NOT NEEDED
|
|
||||||
}).catch(error => reject(error)) //PARSETRANSACTION
|
|
||||||
}).catch(error => reject(error)) //TX_FETCH_FOR_EDITING
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
processData.pipeline = {};
|
processData.pipeline = {};
|
||||||
|
|
||||||
//pipeline model for btc multisig
|
//pipeline model for btc multisig
|
||||||
|
|||||||
1
scripts/messenger.min.js
vendored
Normal file
1
scripts/messenger.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user