Added better token transfer
This commit is contained in:
parent
d0ec0ee79c
commit
831b129cf8
33
css/main.css
33
css/main.css
@ -481,6 +481,10 @@ h3 {
|
|||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.margin-left-auto {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.icon-button {
|
.icon-button {
|
||||||
padding: 0.6rem;
|
padding: 0.6rem;
|
||||||
border-radius: 0.8rem;
|
border-radius: 0.8rem;
|
||||||
@ -863,13 +867,35 @@ h3 {
|
|||||||
#balance_card {
|
#balance_card {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 2rem;
|
||||||
padding: max(1rem, 2vw);
|
padding: max(1rem, 2vw);
|
||||||
background-color: rgba(var(--text-color), 0.06);
|
background-color: rgba(var(--text-color), 0.06);
|
||||||
aspect-ratio: 4/2;
|
aspect-ratio: 4/2;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
}
|
}
|
||||||
|
#balance_card form {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token-balance {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
gap: 0.5rem;
|
||||||
|
background-color: rgba(var(--text-color), 0.06);
|
||||||
|
padding: 0.8rem;
|
||||||
|
border-radius: 0.3rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
.token-balance span:first-of-type {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
.token-balance input {
|
||||||
|
height: 1rem;
|
||||||
|
width: 1rem;
|
||||||
|
accent-color: var(--accent-color);
|
||||||
|
}
|
||||||
|
|
||||||
#transaction_result {
|
#transaction_result {
|
||||||
display: grid;
|
display: grid;
|
||||||
@ -880,6 +906,9 @@ h3 {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
}
|
}
|
||||||
|
#transaction_result:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
#transaction_result h3 {
|
#transaction_result h3 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -1062,6 +1091,6 @@ h3 {
|
|||||||
overflow: overlay;
|
overflow: overlay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.hide {
|
.hidden {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
2
css/main.min.css
vendored
2
css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -460,6 +460,9 @@ h3 {
|
|||||||
.margin-left-0-5 {
|
.margin-left-0-5 {
|
||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
}
|
}
|
||||||
|
.margin-left-auto {
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.icon-button {
|
.icon-button {
|
||||||
padding: 0.6rem;
|
padding: 0.6rem;
|
||||||
@ -822,12 +825,33 @@ h3 {
|
|||||||
#balance_card {
|
#balance_card {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1rem;
|
gap: 2rem;
|
||||||
padding: max(1rem, 2vw);
|
padding: max(1rem, 2vw);
|
||||||
background-color: rgba(var(--text-color), 0.06);
|
background-color: rgba(var(--text-color), 0.06);
|
||||||
aspect-ratio: 4/2;
|
aspect-ratio: 4/2;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
|
form {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.token-balance {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
gap: 0.5rem;
|
||||||
|
background-color: rgba(var(--text-color), 0.06);
|
||||||
|
padding: 0.8rem;
|
||||||
|
border-radius: 0.3rem;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
span:first-of-type {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
height: 1rem;
|
||||||
|
width: 1rem;
|
||||||
|
accent-color: var(--accent-color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#transaction_result {
|
#transaction_result {
|
||||||
display: grid;
|
display: grid;
|
||||||
@ -837,6 +861,9 @@ h3 {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
|
&:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
h3 {
|
h3 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -1017,6 +1044,6 @@ h3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.hide {
|
.hidden {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|||||||
263
index.html
263
index.html
@ -42,7 +42,7 @@
|
|||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body onload="onLoadStartUp()" class="hide">
|
<body onload="onLoadStartUp()" class="hidden">
|
||||||
<sm-notifications id="notification_drawer"></sm-notifications>
|
<sm-notifications id="notification_drawer"></sm-notifications>
|
||||||
<sm-popup id="confirmation_popup">
|
<sm-popup id="confirmation_popup">
|
||||||
<h4 id="confirm_title"></h4>
|
<h4 id="confirm_title"></h4>
|
||||||
@ -198,7 +198,7 @@
|
|||||||
Add FLO address
|
Add FLO address
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="transactions" class="hide page">
|
<div id="transactions" class="hidden page">
|
||||||
<header class="grid">
|
<header class="grid">
|
||||||
<div class="grid align-center w-100">
|
<div class="grid align-center w-100">
|
||||||
<a href="#/home" class="flex interact icon-only">
|
<a href="#/home" class="flex interact icon-only">
|
||||||
@ -246,7 +246,7 @@
|
|||||||
<span id="flo_balance"></span>
|
<span id="flo_balance"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="tokens" class="grid gap-0-5 hide">
|
<div id="tokens" class="grid gap-0-5 hidden">
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<svg class="icon margin-right-0-5" xmlns="http://www.w3.org/2000/svg" height="24px"
|
<svg class="icon margin-right-0-5" xmlns="http://www.w3.org/2000/svg" height="24px"
|
||||||
viewBox="0 0 24 24" width="24px" fill="#000000">
|
viewBox="0 0 24 24" width="24px" fill="#000000">
|
||||||
@ -287,7 +287,7 @@
|
|||||||
<span>Loading transactions</span>
|
<span>Loading transactions</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button id="scroll_to_top" class="fab hide" onclick="backToTop()">
|
<button id="scroll_to_top" class="fab hidden" onclick="backToTop()">
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
||||||
fill="#000000">
|
fill="#000000">
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
@ -295,7 +295,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="send" class="page hide gap-1">
|
<div id="send" class="page hidden gap-1">
|
||||||
<div class="grid full-bleed">
|
<div class="grid full-bleed">
|
||||||
<h3>Send</h3>
|
<h3>Send</h3>
|
||||||
<p>Perform FLO blockchain transactions</p>
|
<p>Perform FLO blockchain transactions</p>
|
||||||
@ -310,7 +310,7 @@
|
|||||||
Sender balance will be shown once you enter a valid address
|
Sender balance will be shown once you enter a valid address
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<sm-input id="getBal_addr" class="w-100" placeholder="Sender FLO address"
|
<sm-input id="sender_flo_addr" class="w-100" placeholder="Sender FLO address"
|
||||||
error-text="Invalid FLO address" data-flo-id="" animate required>
|
error-text="Invalid FLO address" data-flo-id="" animate required>
|
||||||
<button slot="right" class="icon-only" onclick="showFloIdPicker('sender')"
|
<button slot="right" class="icon-only" onclick="showFloIdPicker('sender')"
|
||||||
title="Select from saved IDs">
|
title="Select from saved IDs">
|
||||||
@ -336,21 +336,27 @@
|
|||||||
</sm-input>
|
</sm-input>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid gap-1">
|
<div class="grid gap-1">
|
||||||
<sm-input id="amount" type="number" placeholder="Amount" step="0.00001" min="0.00001"
|
<sm-input id="tx_flo_amount" type="number" placeholder="FLO amount" step="0.00000001"
|
||||||
error-text="Invalid amount" animate required>
|
min="0.00000001" error-text="Invalid amount" animate required>
|
||||||
</sm-input>
|
</sm-input>
|
||||||
<sm-textarea id="flo_data_textarea" placeholder="FLO data" rows="8" maxlength="1040" animate>
|
<sm-input id="tx_token_amount" type="number" class="hidden" placeholder="Token amount"
|
||||||
</sm-textarea>
|
step="0.00000001" min="0.00000001" error-text="Invalid amount" animate required disabled>
|
||||||
<div id="show_character_count">1040/1040</div>
|
</sm-input>
|
||||||
<p id="flo_data_status"></p>
|
<div id="flo_data_wrapper" class="grid gap-0-5">
|
||||||
<button class="button button--primary hide" id="fix_invalid_button"
|
<sm-textarea id="flo_data_textarea" placeholder="FLO data" rows="8" maxlength="1040"
|
||||||
|
animate>
|
||||||
|
</sm-textarea>
|
||||||
|
<div id="show_character_count">1040/1040</div>
|
||||||
|
<p id="flo_data_status"></p>
|
||||||
|
</div>
|
||||||
|
<button class="button button--primary hidden" id="fix_invalid_button"
|
||||||
onclick="removeInvalid()">Fix</button>
|
onclick="removeInvalid()">Fix</button>
|
||||||
<button class="button button--primary cta" id="sendBtn" type="submit"
|
<button class="button button--primary cta" id="send_button" type="submit"
|
||||||
onclick="openPopup('get_private_key_popup')" disabled>Send</button>
|
onclick="openPopup('get_private_key_popup')" disabled>Send</button>
|
||||||
</div>
|
</div>
|
||||||
</sm-form>
|
</sm-form>
|
||||||
</div>
|
</div>
|
||||||
<div id="settings" class="page hide gap-2">
|
<div id="settings" class="page hidden gap-2">
|
||||||
<h3>Settings</h3>
|
<h3>Settings</h3>
|
||||||
<section class="grid gap-1">
|
<section class="grid gap-1">
|
||||||
<h4>Accent color</h4>
|
<h4>Accent color</h4>
|
||||||
@ -425,10 +431,10 @@
|
|||||||
<h3>Add address</h3>
|
<h3>Add address</h3>
|
||||||
</header>
|
</header>
|
||||||
<sm-form>
|
<sm-form>
|
||||||
<sm-input id="floAddr" placeholder="FLO address" error-text="Invalid FLO address" autofocus data-flo-id
|
<sm-input id="flo_addr_to_save" placeholder="FLO address" error-text="Invalid FLO address" autofocus
|
||||||
animate required>
|
data-flo-id animate required>
|
||||||
</sm-input>
|
</sm-input>
|
||||||
<sm-input id="addrLabel" placeholder="Name" animate></sm-input>
|
<sm-input id="label_to_save" placeholder="Name" animate></sm-input>
|
||||||
<button class="button button--primary cta" type="submit" onclick="saveFloId()" disabled>Add</button>
|
<button class="button button--primary cta" type="submit" onclick="saveFloId()" disabled>Add</button>
|
||||||
</sm-form>
|
</sm-form>
|
||||||
</sm-popup>
|
</sm-popup>
|
||||||
@ -450,7 +456,7 @@
|
|||||||
<sm-copy id="edit_saved_id"></sm-copy>
|
<sm-copy id="edit_saved_id"></sm-copy>
|
||||||
</div>
|
</div>
|
||||||
<sm-form>
|
<sm-form>
|
||||||
<sm-input id="newAddrLabel" placeholder="Name" autofocus animate required></sm-input>
|
<sm-input id="new_addr_label" placeholder="Name" autofocus animate required></sm-input>
|
||||||
<div class="flex align-center space-between">
|
<div class="flex align-center space-between">
|
||||||
<button class="button icon-only" title="Delete this FLO address?" onclick="deleteSaved()">
|
<button class="button icon-only" title="Delete this FLO address?" onclick="deleteSaved()">
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24"
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24"
|
||||||
@ -507,14 +513,14 @@
|
|||||||
it.</p>
|
it.</p>
|
||||||
</div>
|
</div>
|
||||||
<sm-form>
|
<sm-form>
|
||||||
<div id="recovered_flo_id_wrapper" class="hide">
|
<div id="recovered_flo_id_wrapper" class="hidden">
|
||||||
<h5>Recovered FLO address</h5>
|
<h5>Recovered FLO address</h5>
|
||||||
<sm-copy id="recovered_flo_id"></sm-copy>
|
<sm-copy id="recovered_flo_id"></sm-copy>
|
||||||
</div>
|
</div>
|
||||||
<sm-input id="retrieve_flo_id_field" type="password" error-text="Invalid private key"
|
<sm-input id="retrieve_flo_id_field" type="password" error-text="Invalid private key"
|
||||||
placeholder="Private key" class="password-field" required autofocus>
|
placeholder="Private key" class="password-field" required autofocus>
|
||||||
<label slot="right" class="interact">
|
<label slot="right" class="interact">
|
||||||
<input type="checkbox" class="hide" readonly onchange="togglePrivateKeyVisibility(this)">
|
<input type="checkbox" class="hidden" readonly onchange="togglePrivateKeyVisibility(this)">
|
||||||
<svg class="icon invisible" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24"
|
<svg class="icon invisible" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24"
|
||||||
width="24px" fill="#000000">
|
width="24px" fill="#000000">
|
||||||
<title>Hide password</title>
|
<title>Hide password</title>
|
||||||
@ -582,7 +588,7 @@
|
|||||||
<sm-form>
|
<sm-form>
|
||||||
<sm-input id="get_private_key_field" class="password-field " type="password" required autofocus>
|
<sm-input id="get_private_key_field" class="password-field " type="password" required autofocus>
|
||||||
<label slot="right" class="interact">
|
<label slot="right" class="interact">
|
||||||
<input type="checkbox" class="hide" readonly onchange="togglePrivateKeyVisibility(this)">
|
<input type="checkbox" class="hidden" readonly onchange="togglePrivateKeyVisibility(this)">
|
||||||
<svg class="icon invisible" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24"
|
<svg class="icon invisible" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24"
|
||||||
width="24px" fill="#000000">
|
width="24px" fill="#000000">
|
||||||
<title>Hide password</title>
|
<title>Hide password</title>
|
||||||
@ -767,11 +773,11 @@
|
|||||||
getRef('search_saved_ids_picker').value = ''
|
getRef('search_saved_ids_picker').value = ''
|
||||||
break;
|
break;
|
||||||
case 'get_private_key_popup':
|
case 'get_private_key_popup':
|
||||||
getRef('get_private_key').classList.remove('hide')
|
getRef('get_private_key').classList.remove('hidden')
|
||||||
renderElem(getRef('transaction_result'), html``)
|
renderElem(getRef('transaction_result'), html``)
|
||||||
break;
|
break;
|
||||||
case 'retrieve_flo_id_popup':
|
case 'retrieve_flo_id_popup':
|
||||||
getRef('recovered_flo_id_wrapper').classList.add('hide')
|
getRef('recovered_flo_id_wrapper').classList.add('hidden')
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -923,7 +929,7 @@
|
|||||||
} else {
|
} else {
|
||||||
notify('Browser is not fully compatible, some features may not work. for best experience please use Chrome, Edge, Firefox or Safari', 'error')
|
notify('Browser is not fully compatible, some features may not work. for best experience please use Chrome, Edge, Firefox or Safari', 'error')
|
||||||
}
|
}
|
||||||
document.body.classList.remove('hide')
|
document.body.classList.remove('hidden')
|
||||||
document.querySelectorAll('sm-input[data-flo-id]').forEach(input => input.customValidation = floCrypto.validateFloID)
|
document.querySelectorAll('sm-input[data-flo-id]').forEach(input => input.customValidation = floCrypto.validateFloID)
|
||||||
document.querySelectorAll('sm-input[data-private-key]').forEach(input => input.customValidation = floCrypto.getPubKeyHex)
|
document.querySelectorAll('sm-input[data-private-key]').forEach(input => input.customValidation = floCrypto.getPubKeyHex)
|
||||||
document.addEventListener('keyup', (e) => {
|
document.addEventListener('keyup', (e) => {
|
||||||
@ -1037,9 +1043,9 @@
|
|||||||
let previousActiveElement = getRef('main_navbar').querySelector('.nav-item--active')
|
let previousActiveElement = getRef('main_navbar').querySelector('.nav-item--active')
|
||||||
const currentActiveElement = document.querySelector(`.nav-item[href="#/${pageId}"]`)
|
const currentActiveElement = document.querySelector(`.nav-item[href="#/${pageId}"]`)
|
||||||
if (currentActiveElement) {
|
if (currentActiveElement) {
|
||||||
if (getRef('main_navbar').classList.contains('hide')) {
|
if (getRef('main_navbar').classList.contains('hidden')) {
|
||||||
getRef('main_navbar').classList.remove('hide-away')
|
getRef('main_navbar').classList.remove('hide-away')
|
||||||
getRef('main_navbar').classList.remove('hide')
|
getRef('main_navbar').classList.remove('hidden')
|
||||||
getRef('main_navbar').animate([
|
getRef('main_navbar').animate([
|
||||||
{
|
{
|
||||||
transform: isMobileView ? `translateY(100%)` : `translateX(-100%)`,
|
transform: isMobileView ? `translateY(100%)` : `translateX(-100%)`,
|
||||||
@ -1055,7 +1061,7 @@
|
|||||||
easing: 'ease'
|
easing: 'ease'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
getRef('main_header').classList.remove('hide')
|
getRef('main_header').classList.remove('hidden')
|
||||||
const previousActiveElementIndex = [...getRef('main_navbar').querySelectorAll('.nav-item')].indexOf(previousActiveElement)
|
const previousActiveElementIndex = [...getRef('main_navbar').querySelectorAll('.nav-item')].indexOf(previousActiveElement)
|
||||||
const currentActiveElementIndex = [...getRef('main_navbar').querySelectorAll('.nav-item')].indexOf(currentActiveElement)
|
const currentActiveElementIndex = [...getRef('main_navbar').querySelectorAll('.nav-item')].indexOf(currentActiveElement)
|
||||||
const isOnTop = previousActiveElementIndex < currentActiveElementIndex
|
const isOnTop = previousActiveElementIndex < currentActiveElementIndex
|
||||||
@ -1098,7 +1104,7 @@
|
|||||||
previousActiveElement.classList.remove('nav-item--active');
|
previousActiveElement.classList.remove('nav-item--active');
|
||||||
currentActiveElement.classList.add('nav-item--active')
|
currentActiveElement.classList.add('nav-item--active')
|
||||||
} else {
|
} else {
|
||||||
if (!getRef('main_navbar').classList.contains('hide')) {
|
if (!getRef('main_navbar').classList.contains('hidden')) {
|
||||||
getRef('main_navbar').classList.add('hide-away')
|
getRef('main_navbar').classList.add('hide-away')
|
||||||
getRef('main_navbar').animate([
|
getRef('main_navbar').animate([
|
||||||
{
|
{
|
||||||
@ -1114,13 +1120,13 @@
|
|||||||
fill: 'forwards',
|
fill: 'forwards',
|
||||||
easing: 'ease'
|
easing: 'ease'
|
||||||
}).onfinish = () => {
|
}).onfinish = () => {
|
||||||
getRef('main_navbar').classList.add('hide')
|
getRef('main_navbar').classList.add('hidden')
|
||||||
}
|
}
|
||||||
getRef('main_header').classList.add('hide')
|
getRef('main_header').classList.add('hidden')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
document.querySelectorAll('.page').forEach(page => page.classList.add('hide'))
|
document.querySelectorAll('.page').forEach(page => page.classList.add('hidden'))
|
||||||
getRef(pageId).classList.remove('hide')
|
getRef(pageId).classList.remove('hidden')
|
||||||
getRef(pageId).animate([{ opacity: 0 }, { opacity: 1 }], { duration: 300, fill: 'forwards', easing: 'ease' })
|
getRef(pageId).animate([{ opacity: 0 }, { opacity: 1 }], { duration: 300, fill: 'forwards', easing: 'ease' })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1240,6 +1246,16 @@
|
|||||||
mobileQuery.addEventListener('change', handleMobileChange)
|
mobileQuery.addEventListener('change', handleMobileChange)
|
||||||
|
|
||||||
handleMobileChange(mobileQuery)
|
handleMobileChange(mobileQuery)
|
||||||
|
|
||||||
|
// fetch with json response
|
||||||
|
async function fetchJSON(url, options) {
|
||||||
|
const response = await fetch(url, options)
|
||||||
|
if (response.ok) {
|
||||||
|
return await response.json()
|
||||||
|
} else {
|
||||||
|
throw new Error(response.statusText)
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
//UI for webWallet
|
//UI for webWallet
|
||||||
@ -1300,21 +1316,19 @@
|
|||||||
try {
|
try {
|
||||||
scrollToTopObserver.disconnect()
|
scrollToTopObserver.disconnect()
|
||||||
// retrieve tokens and render them
|
// retrieve tokens and render them
|
||||||
getRef('tokens').classList.add('hide')
|
getRef('tokens').classList.add('hidden')
|
||||||
fetch(`https://ranchimallflo.duckdns.org/api/v1.0/getFloAddressBalance?floAddress=${queriedFloId}`).then(res => res.json()).then(({ floAddressBalances }) => {
|
fetchJSON(`https://ranchimallflo.duckdns.org/api/v1.0/getFloAddressBalance?floAddress=${queriedFloId}`).then(({ floAddressBalances }) => {
|
||||||
const frag = document.createDocumentFragment()
|
let ownedTokens = []
|
||||||
getRef('token_list').innerHTML = ''
|
|
||||||
let hasTokens = false
|
|
||||||
for (const token in floAddressBalances) {
|
for (const token in floAddressBalances) {
|
||||||
hasTokens = true
|
ownedTokens.push(html`
|
||||||
frag.append(createElement('li', {
|
<li class="token-item">
|
||||||
className: 'token-item',
|
<span>${token}: </span><span>${parseFloat(floAddressBalances[token].balance.toFixed(8))}</span>
|
||||||
innerHTML: `<span>${token}: </span><span>${parseFloat(floAddressBalances[token].balance.toFixed(8))}</span>`
|
</li>
|
||||||
}))
|
`)
|
||||||
}
|
}
|
||||||
if (hasTokens) {
|
if (ownedTokens.length) {
|
||||||
getRef('token_list').append(frag)
|
renderElem(getRef('token_list'), html`${ownedTokens}`)
|
||||||
getRef('tokens').classList.remove('hide')
|
getRef('tokens').classList.remove('hidden')
|
||||||
}
|
}
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
@ -1334,8 +1348,8 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
// show spinner
|
// show spinner
|
||||||
getRef('transactions_scroller').nextElementSibling.classList.remove('hide')
|
getRef('transactions_scroller').nextElementSibling.classList.remove('hidden')
|
||||||
getRef('transactions_scroller').classList.add('hide')
|
getRef('transactions_scroller').classList.add('hidden')
|
||||||
getRef('transactions_list').innerHTML = '';
|
getRef('transactions_list').innerHTML = '';
|
||||||
await floWebWallet.syncTransactions(queriedFloId);
|
await floWebWallet.syncTransactions(queriedFloId);
|
||||||
let allTransactions = (await floWebWallet.readTransactions(queriedFloId)).reverse();
|
let allTransactions = (await floWebWallet.readTransactions(queriedFloId)).reverse();
|
||||||
@ -1350,8 +1364,8 @@
|
|||||||
transactionsLazyLoader = new LazyLoader('#transactions_list', allTransactions, render.transactionCard)
|
transactionsLazyLoader = new LazyLoader('#transactions_list', allTransactions, render.transactionCard)
|
||||||
transactionsLazyLoader.init()
|
transactionsLazyLoader.init()
|
||||||
}
|
}
|
||||||
getRef('transactions_scroller').classList.remove('hide')
|
getRef('transactions_scroller').classList.remove('hidden')
|
||||||
getRef('transactions_scroller').nextElementSibling.classList.add('hide')
|
getRef('transactions_scroller').nextElementSibling.classList.add('hidden')
|
||||||
getRef('transactions_scroller').scroll({
|
getRef('transactions_scroller').scroll({
|
||||||
top: 0
|
top: 0
|
||||||
})
|
})
|
||||||
@ -1372,7 +1386,7 @@
|
|||||||
if (e.target.closest('.edit-saved')) {
|
if (e.target.closest('.edit-saved')) {
|
||||||
const target = e.target.closest('.saved-id');
|
const target = e.target.closest('.saved-id');
|
||||||
getRef('edit_saved_id').setAttribute('value', target.dataset.floId)
|
getRef('edit_saved_id').setAttribute('value', target.dataset.floId)
|
||||||
getRef('newAddrLabel').value = target.dataset.name
|
getRef('new_addr_label').value = target.dataset.name
|
||||||
openPopup('edit_saved_popup')
|
openPopup('edit_saved_popup')
|
||||||
} else if (e.target.closest('.copy-saved-id')) {
|
} else if (e.target.closest('.copy-saved-id')) {
|
||||||
const target = e.target.closest('.saved-id');
|
const target = e.target.closest('.saved-id');
|
||||||
@ -1390,11 +1404,11 @@
|
|||||||
})
|
})
|
||||||
delegate(getRef('saved_ids_picker_list'), 'click', '.saved-id', e => {
|
delegate(getRef('saved_ids_picker_list'), 'click', '.saved-id', e => {
|
||||||
const target = e.target.closest('.saved-id');
|
const target = e.target.closest('.saved-id');
|
||||||
getRef(`${openSavedIdPopupFor === 'sender' ? 'getBal_addr' : 'receiver'}`).value = target.dataset.floId
|
getRef(`${openSavedIdPopupFor === 'sender' ? 'sender_flo_addr' : 'receiver'}`).value = target.dataset.floId
|
||||||
getRef(`${openSavedIdPopupFor === 'sender' ? 'getBal_addr' : 'receiver'}`).focusIn()
|
getRef(`${openSavedIdPopupFor === 'sender' ? 'sender_flo_addr' : 'receiver'}`).focusIn()
|
||||||
if (openSavedIdPopupFor === 'sender') {
|
if (openSavedIdPopupFor === 'sender') {
|
||||||
checkSenderBalance()
|
checkSenderBalance()
|
||||||
$('#refresh_balance_button').classList.remove('hide')
|
$('#refresh_balance_button').classList.remove('hidden')
|
||||||
}
|
}
|
||||||
closePopup()
|
closePopup()
|
||||||
})
|
})
|
||||||
@ -1422,10 +1436,10 @@
|
|||||||
duration: 150,
|
duration: 150,
|
||||||
easing: 'ease',
|
easing: 'ease',
|
||||||
}).onfinish = () => {
|
}).onfinish = () => {
|
||||||
getRef('scroll_to_top').classList.add('hide')
|
getRef('scroll_to_top').classList.add('hidden')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
getRef('scroll_to_top').classList.remove('hide')
|
getRef('scroll_to_top').classList.remove('hidden')
|
||||||
getRef('scroll_to_top').animate([
|
getRef('scroll_to_top').animate([
|
||||||
{
|
{
|
||||||
transform: 'scale(0)',
|
transform: 'scale(0)',
|
||||||
@ -1521,8 +1535,8 @@
|
|||||||
|
|
||||||
|
|
||||||
function saveFloId() {
|
function saveFloId() {
|
||||||
const floID = getRef('floAddr').value.trim()
|
const floID = getRef('flo_addr_to_save').value.trim()
|
||||||
let name = getRef('addrLabel').value.trim();
|
let name = getRef('label_to_save').value.trim();
|
||||||
if (name == '')
|
if (name == '')
|
||||||
name = 'Unknown'
|
name = 'Unknown'
|
||||||
compactIDB.addData('labels', name, floID).then((resolve) => {
|
compactIDB.addData('labels', name, floID).then((resolve) => {
|
||||||
@ -1545,7 +1559,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getRef('getBal_addr').addEventListener('input', debounce(e => {
|
getRef('sender_flo_addr').addEventListener('input', debounce(e => {
|
||||||
if (e.target.isValid) {
|
if (e.target.isValid) {
|
||||||
checkSenderBalance()
|
checkSenderBalance()
|
||||||
} else {
|
} else {
|
||||||
@ -1555,29 +1569,105 @@
|
|||||||
|
|
||||||
function checkSenderBalance() {
|
function checkSenderBalance() {
|
||||||
renderBalance(0, true)
|
renderBalance(0, true)
|
||||||
floWebWallet.getBalance(getRef('getBal_addr').value.trim()).then((retrievedBal) => {
|
const senderFloAddr = getRef('sender_flo_addr').value.trim()
|
||||||
|
Promise.all([
|
||||||
|
floWebWallet.getBalance(senderFloAddr),
|
||||||
|
fetchJSON(`https://ranchimallflo.duckdns.org/api/v1.0/getFloAddressBalance?floAddress=${senderFloAddr}`)
|
||||||
|
]).then(([retrievedBal, { floAddressBalances }]) => {
|
||||||
renderBalance(parseFloat(retrievedBal))
|
renderBalance(parseFloat(retrievedBal))
|
||||||
|
let ownedTokens = []
|
||||||
|
for (const token in floAddressBalances) {
|
||||||
|
ownedTokens.push(html`
|
||||||
|
<label class="token-balance">
|
||||||
|
<input type="radio" name="sender-token" data-balance=${floAddressBalances[token].balance.toFixed(8)} value=${token}/>
|
||||||
|
<span>${token} </span><b class="margin-left-auto">${parseFloat(floAddressBalances[token].balance.toFixed(8))}</b>
|
||||||
|
</label>
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
if (ownedTokens.length) {
|
||||||
|
ownedTokens.push(html`
|
||||||
|
<label class="token-balance">
|
||||||
|
<input type="radio" name="sender-token" value="none" checked/>
|
||||||
|
<span>Don't send a token</span>
|
||||||
|
</label>
|
||||||
|
`)
|
||||||
|
renderElem(document.getElementById('sender_tokens_wrapper'), html.for(document.getElementById('sender_tokens_wrapper'), senderFloAddr)`
|
||||||
|
<h5>Tokens</h5>
|
||||||
|
<p>Select a token, if you want to send a token.</p>
|
||||||
|
<form onsubmit="event.preventDefault()" onchange=${handleTokenSelection} class="grid gap-1">
|
||||||
|
<div class="grid gap-0-5">
|
||||||
|
${ownedTokens}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
`)
|
||||||
|
document.getElementById('sender_tokens_wrapper').classList.remove('hidden')
|
||||||
|
handleTokenSelection()
|
||||||
|
}
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
notify(error, 'error');
|
notify(error, 'error');
|
||||||
resetBalance()
|
resetBalance()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
function clearSelection() {
|
||||||
|
getRef('tx_token_amount').disabled = true
|
||||||
|
getRef('tx_token_amount').classList.add('hidden')
|
||||||
|
getRef('tx_token_amount').value = ''
|
||||||
|
getRef('flo_data_wrapper').classList.remove('hidden')
|
||||||
|
getRef('flo_data_textarea').value = ''
|
||||||
|
}
|
||||||
|
function handleTokenSelection() {
|
||||||
|
const selectedToken = document.getElementById('sender_tokens_wrapper').querySelector('input[type="radio"]:checked')
|
||||||
|
if (selectedToken.value === 'none')
|
||||||
|
return clearSelection(e)
|
||||||
|
const tokenName = selectedToken.value
|
||||||
|
const tokenBalance = parseFloat(selectedToken.dataset.balance)
|
||||||
|
getRef('flo_data_wrapper').classList.add('hidden')
|
||||||
|
getRef('tx_token_amount').disabled = false
|
||||||
|
getRef('tx_token_amount').classList.remove('hidden')
|
||||||
|
getRef('tx_token_amount').placeholder = `${tokenName.charAt(0).toUpperCase() + tokenName.slice(1)} amount`
|
||||||
|
getRef('tx_token_amount').setAttribute('max', tokenBalance)
|
||||||
|
}
|
||||||
|
getRef('tx_token_amount').addEventListener('input', e => {
|
||||||
|
const tokenAmount = parseFloat(e.target.value.trim())
|
||||||
|
const selectedToken = document.getElementById('sender_tokens_wrapper').querySelector('input[type="radio"]:checked')
|
||||||
|
const tokenName = selectedToken.value
|
||||||
|
const tokenBalance = parseFloat(selectedToken.dataset.balance)
|
||||||
|
const { rangeOverflow, rangeUnderflow } = e.target.validity;
|
||||||
|
if (rangeUnderflow)
|
||||||
|
e.target.setAttribute('error-text', `Minimum 0.00000001 ${tokenName} allowed`)
|
||||||
|
if (rangeOverflow)
|
||||||
|
e.target.setAttribute('error-text', `You can send ${tokenName} upto ${tokenBalance} only`)
|
||||||
|
getRef('flo_data_textarea').value = `send ${tokenAmount} ${tokenName}#`
|
||||||
|
})
|
||||||
|
getRef('tx_flo_amount').addEventListener('input', e => {
|
||||||
|
const floAmount = parseFloat(e.target.value.trim())
|
||||||
|
const { rangeOverflow, rangeUnderflow } = e.target.validity;
|
||||||
|
if (rangeUnderflow)
|
||||||
|
e.target.setAttribute('error-text', `Minimum 0.00000001 FLO allowed`)
|
||||||
|
if (rangeOverflow)
|
||||||
|
e.target.setAttribute('error-text', `You can send FLO upto ${getRef('sender_balance').textContent} only`)
|
||||||
|
})
|
||||||
|
|
||||||
function renderBalance(balance = 0, loading = false) {
|
function renderBalance(balance = 0, loading = false) {
|
||||||
|
getRef('tx_flo_amount').setAttribute('max', balance)
|
||||||
renderElem(getRef('balance_card'), html`
|
renderElem(getRef('balance_card'), html`
|
||||||
<div class="flex align-center space-between">
|
<div class="grid">
|
||||||
<h5>Balance</h5>
|
<div class="flex align-center space-between">
|
||||||
<button id="refresh_balance_button" class="button button--small button--colored hide"
|
<h5>Balance</h5>
|
||||||
onclick="checkSenderBalance()">Refresh</button>
|
<button id="refresh_balance_button" class="button button--small button--colored hidden"
|
||||||
</div>
|
onclick="checkSenderBalance()">Refresh</button>
|
||||||
<div class="flex align-end gap-0-3">
|
</div>
|
||||||
<b id="sender_balance" style="font-size: 2.5rem;line-height: 1;">${loading ? html`<sm-spinner></sm-spinner>` : balance}</b>
|
<div class="flex align-end gap-0-3">
|
||||||
<span>FLO</span>
|
<b id="sender_balance" style="font-size: 2.5rem;line-height: 1;">${loading ? html`<sm-spinner></sm-spinner>` : balance}</b>
|
||||||
|
<span>FLO</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="sender_tokens_wrapper" class="grid hidden"></div>
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetBalance() {
|
function resetBalance() {
|
||||||
|
clearSelection()
|
||||||
renderElem(getRef('balance_card'), html`
|
renderElem(getRef('balance_card'), html`
|
||||||
<div class="flex align-center space-between">
|
<div class="flex align-center space-between">
|
||||||
<h5>Balance</h5>
|
<h5>Balance</h5>
|
||||||
@ -1590,7 +1680,7 @@
|
|||||||
|
|
||||||
|
|
||||||
function saveChanges() {
|
function saveChanges() {
|
||||||
let name = getRef('newAddrLabel').value.trim();
|
let name = getRef('new_addr_label').value.trim();
|
||||||
if (name == '')
|
if (name == '')
|
||||||
name = 'Unknown';
|
name = 'Unknown';
|
||||||
compactIDB.writeData('labels', name, getRef('edit_saved_id').value).then((resolve) => {
|
compactIDB.writeData('labels', name, getRef('edit_saved_id').value).then((resolve) => {
|
||||||
@ -1633,22 +1723,22 @@
|
|||||||
function retrieveFloId() {
|
function retrieveFloId() {
|
||||||
const privKey = getRef('retrieve_flo_id_field').value.trim()
|
const privKey = getRef('retrieve_flo_id_field').value.trim()
|
||||||
floWebWallet.recoverAddr(privKey).then(({ floID }) => {
|
floWebWallet.recoverAddr(privKey).then(({ floID }) => {
|
||||||
getRef('recovered_flo_id_wrapper').classList.remove('hide')
|
getRef('recovered_flo_id_wrapper').classList.remove('hidden')
|
||||||
getRef('recovered_flo_id').value = floID
|
getRef('recovered_flo_id').value = floID
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendMessage() {
|
function sendMessage() {
|
||||||
const sender = getRef('getBal_addr').value.trim();
|
const sender = getRef('sender_flo_addr').value.trim();
|
||||||
const amount = parseFloat(getRef('amount').value.trim());
|
const floAmount = parseFloat(getRef('tx_flo_amount').value.trim());
|
||||||
const receiver = getRef('receiver').value.trim();
|
const receiver = getRef('receiver').value.trim();
|
||||||
const floData = getRef('flo_data_textarea').value.trim();
|
const floData = getRef('flo_data_textarea').value.trim();
|
||||||
const privKey = getRef('get_private_key_field').value.trim();
|
const privKey = getRef('get_private_key_field').value.trim();
|
||||||
buttonLoader('confirm_transaction_button', true)
|
buttonLoader('confirm_transaction_button', true)
|
||||||
floWebWallet.sendTransaction(sender, receiver, amount, floData, privKey).then((transactionId) => {
|
floWebWallet.sendTransaction(sender, receiver, floAmount, floData, privKey).then((transactionId) => {
|
||||||
showTransactionResult(true, transactionId);
|
showTransactionResult(true, transactionId);
|
||||||
getRef('send_form').reset();
|
getRef('send_form').reset();
|
||||||
getRef('sendBtn').disabled = true;
|
getRef('send_button').disabled = true;
|
||||||
resetBalance()
|
resetBalance()
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
showTransactionResult(false, error);
|
showTransactionResult(false, error);
|
||||||
@ -1658,7 +1748,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showTransactionResult(success, result) {
|
function showTransactionResult(success, result) {
|
||||||
getRef('get_private_key').classList.add('hide')
|
getRef('get_private_key').classList.add('hidden')
|
||||||
renderElem(getRef('transaction_result'), html`
|
renderElem(getRef('transaction_result'), html`
|
||||||
${success ? html`
|
${success ? html`
|
||||||
<svg class="icon icon--success" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <path d="M0 0h24v24H0z" fill="none" /> <path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z" /> </svg>
|
<svg class="icon icon--success" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"> <path d="M0 0h24v24H0z" fill="none" /> <path d="M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z" /> </svg>
|
||||||
@ -1700,12 +1790,12 @@
|
|||||||
|
|
||||||
getRef('flo_data_textarea').addEventListener('input', function (e) {
|
getRef('flo_data_textarea').addEventListener('input', function (e) {
|
||||||
if (this.value.trim() !== '') {
|
if (this.value.trim() !== '') {
|
||||||
getRef('sendBtn').classList.add('hide')
|
getRef('send_button').classList.add('hidden')
|
||||||
getRef('fix_invalid_button').classList.remove('hide')
|
getRef('fix_invalid_button').classList.remove('hidden')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
getRef('sendBtn').classList.remove('hide')
|
getRef('send_button').classList.remove('hidden')
|
||||||
getRef('fix_invalid_button').classList.add('hide')
|
getRef('fix_invalid_button').classList.add('hidden')
|
||||||
}
|
}
|
||||||
if (1040 - this.value.length) {
|
if (1040 - this.value.length) {
|
||||||
getRef('show_character_count').textContent = `${1040 - this.value.length} /1040`
|
getRef('show_character_count').textContent = `${1040 - this.value.length} /1040`
|
||||||
@ -1717,8 +1807,8 @@
|
|||||||
function checkFloData() {
|
function checkFloData() {
|
||||||
const floDataText = getRef('flo_data_textarea').value;
|
const floDataText = getRef('flo_data_textarea').value;
|
||||||
if (/^[\x20-\x7E]*$/.test(floDataText)) {
|
if (/^[\x20-\x7E]*$/.test(floDataText)) {
|
||||||
getRef('sendBtn').classList.remove('hide')
|
getRef('send_button').classList.remove('hidden')
|
||||||
getRef('fix_invalid_button').classList.add('hide')
|
getRef('fix_invalid_button').classList.add('hidden')
|
||||||
getRef('flo_data_status').textContent = ''
|
getRef('flo_data_status').textContent = ''
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -1731,17 +1821,6 @@
|
|||||||
checkFloData()
|
checkFloData()
|
||||||
}
|
}
|
||||||
|
|
||||||
// let preventUnconfirmedUTXO = true
|
|
||||||
// getRef('allow_utxo_switch').addEventListener('change', e => {
|
|
||||||
// preventUnconfirmedUTXO = !e.target.checked
|
|
||||||
// localStorage.preventUnconfirmedUTXO = preventUnconfirmedUTXO
|
|
||||||
// })
|
|
||||||
// if (localStorage.getItem('preventUnconfirmedUTXO') !== 'null') {
|
|
||||||
// const getBoolean = (localStorage.preventUnconfirmedUTXO === 'false')
|
|
||||||
// preventUnconfirmedUTXO = getBoolean
|
|
||||||
// getRef('allow_utxo_switch').checked = getBoolean
|
|
||||||
// }
|
|
||||||
|
|
||||||
const selectedColors = [
|
const selectedColors = [
|
||||||
'--dark-red',
|
'--dark-red',
|
||||||
'--red',
|
'--red',
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user