Added transaction Fee suggestion

This commit is contained in:
sairaj mote 2023-02-22 01:44:57 +05:30
parent 087ddd0ed8
commit d20381da36
5 changed files with 219 additions and 28 deletions

View File

@ -304,6 +304,10 @@ sm-chip[selected] {
--background: rgba(var(--text-color), 0.9);
}
sm-popup::part(popup) {
background-color: rgba(var(--foreground-color), 1);
}
ul,
ol {
list-style: none;
@ -1099,6 +1103,7 @@ ol li::before {
opacity: 0.9;
}
.contact .menu {
flex-shrink: 0;
justify-self: flex-end;
padding: 0.2rem;
fill: rgba(var(--text-color), 1);
@ -2237,6 +2242,31 @@ sm-chip .badge {
border-bottom: solid thin rgba(var(--text-color), 0.3);
}
#selected_fee_tip,
#error_section {
font-weight: 500;
}
.error {
color: var(--danger-color);
}
.error .icon {
fill: var(--danger-color);
}
#send_fee_wrapper {
display: grid;
}
#send_fee_wrapper > * {
grid-area: 1/1;
}
#send_fee_loader {
background-color: rgba(var(--foreground-color), 1);
z-index: 1;
width: 100%;
}
@media screen and (max-width: 640px) {
sm-popup {
--border-radius: 1rem 1rem 0 0;

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

View File

@ -310,6 +310,11 @@ sm-chip {
--background: rgba(var(--text-color), 0.9);
}
}
sm-popup {
&::part(popup) {
background-color: rgba(var(--foreground-color), 1);
}
}
ul,
ol {
@ -1121,6 +1126,7 @@ ol {
}
.menu {
flex-shrink: 0;
justify-self: flex-end;
padding: 0.2rem;
fill: rgba(var(--text-color), 1);
@ -2305,6 +2311,27 @@ sm-chip {
border-bottom: solid thin rgba(var(--text-color), 0.3);
}
}
#selected_fee_tip,
#error_section {
font-weight: 500;
}
.error {
color: var(--danger-color);
.icon {
fill: var(--danger-color);
}
}
#send_fee_wrapper {
display: grid;
& > * {
grid-area: 1/1;
}
}
#send_fee_loader {
background-color: rgba(var(--foreground-color), 1);
z-index: 1;
width: 100%;
}
@media screen and (max-width: 640px) {
sm-popup {

View File

@ -1044,32 +1044,39 @@
</svg>
Add receiver</button>
</div>
<div class="grid gap-0-5">
<div id="fees_section" class="grid gap-0-5">
<div class="flex align-center space-between">
<h4>Fees</h4>
<sm-chips id="fees_selector" class="hidden">
<sm-chips id="fees_selector">
<sm-chip value="suggested" selected>Suggested</sm-chip>
<sm-chip value="custom">Custom</sm-chip>
</sm-chips>
</div>
<p id="selected_fee_tip" class="hidden">Estimated time of confirmation is 1hr</p>
<sm-input type="number" id="send_fee" placeholder="Fee" min="0.00000001" step="0.00000001"
error-text="Please enter valid fees" animate required>
<div class="currency-symbol flex" slot="icon">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24"
height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<g>
<rect fill="none" height="24" width="24"></rect>
</g>
<g>
<path
d="M17.06,11.57C17.65,10.88,18,9.98,18,9c0-1.86-1.27-3.43-3-3.87L15,3h-2v2h-2V3H9v2H6v2h2v10H6v2h3v2h2v-2h2v2h2v-2 c2.21,0,4-1.79,4-4C19,13.55,18.22,12.27,17.06,11.57z M10,7h4c1.1,0,2,0.9,2,2s-0.9,2-2,2h-4V7z M15,17h-5v-4h5c1.1,0,2,0.9,2,2 S16.1,17,15,17z">
</path>
</g>
</svg>
<p id="selected_fee_tip"></p>
<div id="send_fee_wrapper">
<sm-input type="number" id="send_fee" placeholder="Fee" min="0.00000001" step="0.00000001"
error-text="Please enter valid fees" readonly animate required>
<div class="currency-symbol flex" slot="icon">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24"
height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<g>
<rect fill="none" height="24" width="24"></rect>
</g>
<g>
<path
d="M17.06,11.57C17.65,10.88,18,9.98,18,9c0-1.86-1.27-3.43-3-3.87L15,3h-2v2h-2V3H9v2H6v2h2v10H6v2h3v2h2v-2h2v2h2v-2 c2.21,0,4-1.79,4-4C19,13.55,18.22,12.27,17.06,11.57z M10,7h4c1.1,0,2,0.9,2,2s-0.9,2-2,2h-4V7z M15,17h-5v-4h5c1.1,0,2,0.9,2,2 S16.1,17,15,17z">
</path>
</g>
</svg>
</div>
</sm-input>
<div id="send_fee_loader" class="hidden flex align-center gap-0-5">
<sm-spinner></sm-spinner>
<span>Calculating fees...</span>
</div>
</sm-input>
</div>
</div>
<div id="error_section" class="hidden"></div>
<div class="multi-state-button margin-bottom-1-5">
<button id="initiate_transaction" type="submit" class="button button--primary cta w-100"
disabled>Initiate</button>
@ -1405,6 +1412,9 @@
renderCreationList()
break;
}
case 'multisig_tx_popup':
calculateFees()
break;
case 'compose_mail_popup':
const mailingContacts = []
for (const floID in floGlobals.contacts) {
@ -2199,6 +2209,22 @@
transform: 'translateY(-1.5rem)'
},
]
const fadeIn = [
{
opacity: 0
},
{
opacity: 1
}
]
const fadeOut = [
{
opacity: 1
},
{
opacity: 0
}
]
function showChildElement(id, index, options = {}) {
return new Promise((resolve) => {
@ -4422,7 +4448,7 @@
const widthDelta = changedWidth - originalWidth
const leftMove = -widthDelta / 2;
const rightMove = widthDelta / 2;
const scale = (changedWidth / originalWidth).toFixed(2);
const scale = (changedWidth / (originalWidth || 1)).toFixed(2) || 1;
getRef('receiver_name').textContent = originalName
getRef('pseudo_background').animate([
{
@ -4482,7 +4508,13 @@
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></svg>
</button>
`);
}).catch(err => notify(err, 'error'))
}).catch(err => {
console.error(err)
notify('Failed to check balance', 'error')
renderElem(multisig.querySelector('.multisig-option__balance'), html`
<button class="button button--small" onclick=${checkBalance}>Check balance</button>
`)
})
}
function initTransaction(e) {
@ -4547,6 +4579,108 @@
delegate(getRef('receiver_container'), 'click', '.remove-card', e => {
e.target.closest('.receiver-card').remove()
})
getRef('fees_selector').addEventListener('change', e => {
switch (e.target.value) {
case 'custom':
getRef('send_fee').readOnly = false;
getRef('send_fee').placeholder = 'Fee';
renderElem(getRef('selected_fee_tip'), html`Set custom fee`)
break;
case 'suggested':
calculateFees();
getRef('send_fee').readOnly = true;
break;
}
})
function calculateApproxFee() {
return new Promise((resolve, reject) => {
fetch('https://bitcoiner.live/api/fees/estimates/latest')
.then(res => {
res.json()
.then(data => {
const satPerByte = data.estimates['60'].sat_per_vbyte;
const legacyBytes = 200;
const segwitBytes = 77;
resolve((legacyBytes * satPerByte + (0.25 * satPerByte) * segwitBytes) / Math.pow(10, 8));
}).catch(e => {
reject(e)
})
}).catch(e => {
reject(e)
})
})
}
async function calculateBtcFees() {
const [senders, privKeys, receivers, amounts] = await getTransactionInputs().catch(e => {
console.error(e)
return
});
// if (!senders.length || !privKeys.length || !receivers.length || !amounts.length) return;
return btcOperator.createSignedTx(senders, privKeys, receivers, amounts)
}
async function getTransactionInputs() {
const privateKey = await floDapps.user.private.catch(err => console.log(err));
const privKeys = btcOperator.convert.wif(privateKey);
const senders = floGlobals.myBtcID;
const receivers = [...getRef('receiver_container').querySelectorAll('.receiver-input')].filter(input => input.value.trim() !== '').map(input => input.value.trim());
const amounts = [...getRef('receiver_container').querySelectorAll('.amount-input')].filter(input => input.value.trim() !== '').map(input => {
return parseFloat(input.value.trim())
});
return [senders, privKeys, receivers, amounts]
}
getRef('receiver_container').addEventListener('input', debounce(calculateFees, 300))
function calculateFees() {
getRef('fees_selector').children[0].click();
getRef('fees_selector').classList.remove('hidden')
getRef('initiate_transaction').disabled = true;
getRef('send_fee').value = '';
getRef('send_fee_loader').classList.remove('hidden')
const animOptions = {
duration: 200,
easing: 'ease',
fill: 'forwards'
}
getRef('send_fee_loader').animate(fadeIn, animOptions)
getRef('fees_section').classList.remove('hidden')
getRef('error_section').classList.add('hidden')
const allValid = [...getRef('receiver_container').querySelectorAll('sm-input')].every(input => input.isValid)
if (allValid) {
getRef('send_fee').placeholder = 'Fee'
calculateBtcFees().then(({ fee }) => {
getRef('send_fee').value = fee.toFixed(8);
renderElem(getRef('selected_fee_tip'), html``)
getRef('initiate_transaction').disabled = false;
}).catch(e => {
getRef('fees_section').classList.add('hidden')
getRef('error_section').classList.remove('hidden')
renderElem(getRef('error_section'), html`
<p class="error flex align-center gap-0-5">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M11 15h2v2h-2v-2zm0-8h2v6h-2V7zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></svg>
${e}
</p>
`)
console.error(e)
}).finally(_ => {
getRef('send_fee_loader').animate(fadeOut, animOptions).onfinish = _ =>
getRef('send_fee_loader').classList.add('hidden')
})
} else {
getRef('send_fee').placeholder = 'Approximate fee'
renderElem(getRef('selected_fee_tip'), html` <p style="opacity: 0.8;">*Fill out all fields for exact fee!</p> `)
calculateApproxFee().then(fee => {
getRef('send_fee').value = fee.toFixed(8);
}).catch(e => {
getRef('fees_selector').children[1].click();
getRef('fees_selector').classList.add('hidden')
}).finally(_ => {
getRef('send_fee_loader').animate(fadeOut, animOptions).onfinish = _ =>
getRef('send_fee_loader').classList.add('hidden')
})
}
}
getRef('initiate_transaction').onclick = async evt => {
buttonLoader('initiate_transaction', true)

File diff suppressed because one or more lines are too long