Added wallet deposit/withdraw UI
This commit is contained in:
parent
75879ca2f5
commit
5a67beb249
@ -1,11 +0,0 @@
|
||||
{
|
||||
"secret": "Secret_For_Session__Enter_A_Strong_String(Text/Password)",
|
||||
"blockchain_id": "FLO_ID_of_the_admin",
|
||||
"blockchain_private": "Private_Key_of_the_Admin",
|
||||
"port": "8080",
|
||||
|
||||
"sql_user": "mySQL_user",
|
||||
"sql_pwd": "mySQL_password",
|
||||
"sql_db": "supernode",
|
||||
"sql_host": "localhost"
|
||||
}
|
||||
@ -418,7 +418,7 @@ input{
|
||||
color: var(--accent-color)
|
||||
}
|
||||
:host([variant="outlined"]) .input {
|
||||
box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 0.4) inset;
|
||||
box-shadow: 0 0 0 0.1rem var(--border-color, rgba(var(--text-color), 0.4)) inset;
|
||||
background: rgba(var(--background-color), 1);
|
||||
}
|
||||
:host([variant="outlined"]) .label {
|
||||
@ -2207,3 +2207,405 @@ class SlideButton extends HTMLElement {
|
||||
|
||||
window.customElements.define('slide-button', SlideButton);
|
||||
|
||||
const smSelect = document.createElement('template')
|
||||
smSelect.innerHTML = `
|
||||
<style>
|
||||
*{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
:host{
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
--accent-color: #4d2588;
|
||||
--text-color: 17, 17, 17;
|
||||
--background-color: 255, 255, 255;
|
||||
--max-height: auto;
|
||||
--min-width: 100%;
|
||||
}
|
||||
:host([disabled]) .select{
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.hide{
|
||||
display: none !important;
|
||||
}
|
||||
.select{
|
||||
position: relative;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
.icon {
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
fill: rgba(var(--text-color), 0.7);
|
||||
}
|
||||
.selected-option-text{
|
||||
font-size: 0.9rem;
|
||||
overflow: hidden;
|
||||
-o-text-overflow: ellipsis;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.selection{
|
||||
border-radius: 0.3rem;
|
||||
display: -ms-grid;
|
||||
display: grid;
|
||||
-ms-grid-columns: 1fr auto;
|
||||
grid-template-columns: 1fr auto;
|
||||
grid-template-areas: 'heading heading' '. .';
|
||||
padding: 0.4rem 1rem;
|
||||
background: rgba(var(--text-color), 0.06);
|
||||
border: solid 1px rgba(var(--text-color), 0.2);
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
outline: none;
|
||||
}
|
||||
.selection:focus{
|
||||
-webkit-box-shadow: 0 0 0 0.1rem var(--accent-color);
|
||||
box-shadow: 0 0 0 0.1rem var(--accent-color)
|
||||
}
|
||||
.icon{
|
||||
margin-left: 1rem;
|
||||
}
|
||||
:host([align-select="left"]) .options{
|
||||
left: 0;
|
||||
}
|
||||
:host([align-select="right"]) .options{
|
||||
right: 0;
|
||||
}
|
||||
.options{
|
||||
top: 100%;
|
||||
margin-top: 0.2rem;
|
||||
overflow: hidden auto;
|
||||
position: absolute;
|
||||
grid-area: options;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
min-width: var(--min-width);
|
||||
max-height: var(--max-height);
|
||||
background: rgba(var(--background-color), 1);
|
||||
border: solid 1px rgba(var(--text-color), 0.2);
|
||||
border-radius: 0.3rem;
|
||||
z-index: 2;
|
||||
-webkit-box-shadow: 0.4rem 0.8rem 1.2rem #00000030;
|
||||
box-shadow: 0.4rem 0.8rem 1.2rem #00000030;
|
||||
}
|
||||
.rotate{
|
||||
-webkit-transform: rotate(180deg);
|
||||
-ms-transform: rotate(180deg);
|
||||
transform: rotate(180deg)
|
||||
}
|
||||
@media (any-hover: hover){
|
||||
::-webkit-scrollbar{
|
||||
width: 0.5rem;
|
||||
height: 0.5rem;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb{
|
||||
background: rgba(var(--text-color), 0.3);
|
||||
border-radius: 1rem;
|
||||
&:hover{
|
||||
background: rgba(var(--text-color), 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div class="select" >
|
||||
<div class="selection">
|
||||
<div class="selected-option-text"></div>
|
||||
<svg class="icon toggle" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M12 13.172l4.95-4.95 1.414 1.414L12 16 5.636 9.636 7.05 8.222z"/></svg>
|
||||
</div>
|
||||
<div part="options" class="options hide">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>`;
|
||||
customElements.define('sm-select', class extends HTMLElement {
|
||||
constructor() {
|
||||
super()
|
||||
this.attachShadow({
|
||||
mode: 'open'
|
||||
}).append(smSelect.content.cloneNode(true))
|
||||
|
||||
this.reset = this.reset.bind(this)
|
||||
this.open = this.open.bind(this)
|
||||
this.collapse = this.collapse.bind(this)
|
||||
this.toggle = this.toggle.bind(this)
|
||||
this.handleOptionsNavigation = this.handleOptionsNavigation.bind(this)
|
||||
this.handleOptionSelection = this.handleOptionSelection.bind(this)
|
||||
this.handleKeydown = this.handleKeydown.bind(this)
|
||||
this.handleClickOutside = this.handleClickOutside.bind(this)
|
||||
|
||||
this.availableOptions
|
||||
this.previousOption
|
||||
this.isOpen = false;
|
||||
this.slideDown = [{
|
||||
transform: `translateY(-0.5rem)`,
|
||||
opacity: 0
|
||||
},
|
||||
{
|
||||
transform: `translateY(0)`,
|
||||
opacity: 1
|
||||
}
|
||||
]
|
||||
this.slideUp = [{
|
||||
transform: `translateY(0)`,
|
||||
opacity: 1
|
||||
},
|
||||
{
|
||||
transform: `translateY(-0.5rem)`,
|
||||
opacity: 0
|
||||
}
|
||||
]
|
||||
this.animationOptions = {
|
||||
duration: 300,
|
||||
fill: "forwards",
|
||||
easing: 'ease'
|
||||
}
|
||||
|
||||
this.optionList = this.shadowRoot.querySelector('.options')
|
||||
this.chevron = this.shadowRoot.querySelector('.toggle')
|
||||
this.selection = this.shadowRoot.querySelector('.selection')
|
||||
this.selectedOptionText = this.shadowRoot.querySelector('.selected-option-text')
|
||||
}
|
||||
static get observedAttributes() {
|
||||
return ['value', 'disabled']
|
||||
}
|
||||
get value() {
|
||||
return this.getAttribute('value')
|
||||
}
|
||||
set value(val) {
|
||||
this.setAttribute('value', val)
|
||||
}
|
||||
|
||||
reset(fire = true) {
|
||||
if (this.availableOptions[0] && this.previousOption !== this.availableOptions[0]) {
|
||||
const firstElement = this.availableOptions[0];
|
||||
if (this.previousOption) {
|
||||
this.previousOption.classList.remove('check-selected')
|
||||
}
|
||||
firstElement.classList.add('check-selected')
|
||||
this.value = firstElement.getAttribute('value')
|
||||
this.selectedOptionText.textContent = firstElement.textContent
|
||||
this.previousOption = firstElement;
|
||||
if (fire) {
|
||||
this.fireEvent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open() {
|
||||
this.optionList.classList.remove('hide')
|
||||
this.optionList.animate(this.slideDown, this.animationOptions)
|
||||
this.chevron.classList.add('rotate')
|
||||
this.isOpen = true
|
||||
}
|
||||
collapse() {
|
||||
this.chevron.classList.remove('rotate')
|
||||
this.optionList.animate(this.slideUp, this.animationOptions)
|
||||
.onfinish = () => {
|
||||
this.optionList.classList.add('hide')
|
||||
this.isOpen = false
|
||||
}
|
||||
}
|
||||
toggle() {
|
||||
if (!this.isOpen && !this.hasAttribute('disabled')) {
|
||||
this.open()
|
||||
} else {
|
||||
this.collapse()
|
||||
}
|
||||
}
|
||||
|
||||
fireEvent() {
|
||||
this.dispatchEvent(new CustomEvent('change', {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
detail: {
|
||||
value: this.value
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
handleOptionsNavigation(e) {
|
||||
if (e.code === 'ArrowUp') {
|
||||
e.preventDefault()
|
||||
if (document.activeElement.previousElementSibling) {
|
||||
document.activeElement.previousElementSibling.focus()
|
||||
} else {
|
||||
this.availableOptions[this.availableOptions.length - 1].focus()
|
||||
}
|
||||
}
|
||||
else if (e.code === 'ArrowDown') {
|
||||
e.preventDefault()
|
||||
if (document.activeElement.nextElementSibling) {
|
||||
document.activeElement.nextElementSibling.focus()
|
||||
} else {
|
||||
this.availableOptions[0].focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
handleOptionSelection(e) {
|
||||
if (this.previousOption !== document.activeElement) {
|
||||
this.value = document.activeElement.getAttribute('value')
|
||||
this.selectedOptionText.textContent = document.activeElement.textContent;
|
||||
this.fireEvent()
|
||||
if (this.previousOption) {
|
||||
this.previousOption.classList.remove('check-selected')
|
||||
}
|
||||
document.activeElement.classList.add('check-selected')
|
||||
this.previousOption = document.activeElement
|
||||
}
|
||||
}
|
||||
handleClick(e) {
|
||||
if (e.target === this) {
|
||||
this.toggle()
|
||||
}
|
||||
else {
|
||||
this.handleOptionSelection()
|
||||
this.collapse()
|
||||
}
|
||||
}
|
||||
handleKeydown(e) {
|
||||
if (e.target === this) {
|
||||
if (this.isOpen && e.code === 'ArrowDown') {
|
||||
e.preventDefault()
|
||||
this.availableOptions[0].focus()
|
||||
this.handleOptionSelection(e)
|
||||
}
|
||||
else if (e.code === 'Enter' || e.code === 'Space') {
|
||||
e.preventDefault()
|
||||
this.toggle()
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.handleOptionsNavigation(e)
|
||||
this.handleOptionSelection(e)
|
||||
if (e.code === 'Enter' || e.code === 'Space') {
|
||||
e.preventDefault()
|
||||
this.collapse()
|
||||
}
|
||||
}
|
||||
}
|
||||
handleClickOutside(e) {
|
||||
if (this.isOpen && !this.contains(e.target)) {
|
||||
this.collapse()
|
||||
}
|
||||
}
|
||||
connectedCallback() {
|
||||
this.setAttribute('role', 'listbox')
|
||||
if (!this.hasAttribute('disabled')) {
|
||||
this.selection.setAttribute('tabindex', '0')
|
||||
}
|
||||
let slot = this.shadowRoot.querySelector('slot')
|
||||
slot.addEventListener('slotchange', e => {
|
||||
this.availableOptions = slot.assignedElements()
|
||||
this.reset(false)
|
||||
});
|
||||
this.addEventListener('click', this.handleClick)
|
||||
this.addEventListener('keydown', this.handleKeydown)
|
||||
document.addEventListener('mousedown', this.handleClickOutside)
|
||||
}
|
||||
disconnectedCallback() {
|
||||
this.removeEventListener('click', this.toggle)
|
||||
this.removeEventListener('keydown', this.handleKeydown)
|
||||
document.removeEventListener('mousedown', this.handleClickOutside)
|
||||
}
|
||||
attributeChangedCallback(name) {
|
||||
if (name === "disabled") {
|
||||
if (this.hasAttribute('disabled')) {
|
||||
this.selection.removeAttribute('tabindex')
|
||||
} else {
|
||||
this.selection.setAttribute('tabindex', '0')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// option
|
||||
const smOption = document.createElement('template')
|
||||
smOption.innerHTML = `
|
||||
<style>
|
||||
*{
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
:host{
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
}
|
||||
.option{
|
||||
display: grid;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
min-width: 100%;
|
||||
gap: 0.5rem;
|
||||
grid-template-columns: max-content minmax(0, 1fr);
|
||||
padding: 0.8rem 1.2rem;
|
||||
cursor: pointer;
|
||||
overflow-wrap: break-word;
|
||||
outline: none;
|
||||
user-select: none;
|
||||
}
|
||||
:host(:focus){
|
||||
outline: none;
|
||||
background: rgba(var(--text-color), 0.1);
|
||||
}
|
||||
.icon {
|
||||
opacity: 0;
|
||||
height: 1.2rem;
|
||||
width: 1.2rem;
|
||||
fill: rgba(var(--text-color), 0.8);
|
||||
}
|
||||
:host(:focus) .option .icon{
|
||||
opacity: 0.4
|
||||
}
|
||||
:host(.check-selected) .icon{
|
||||
opacity: 1
|
||||
}
|
||||
@media (hover: hover){
|
||||
.option:hover{
|
||||
background: rgba(var(--text-color), 0.1);
|
||||
}
|
||||
:host(:not(.check-selected):hover) .icon{
|
||||
opacity: 0.4
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<div class="option">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10 15.172l9.192-9.193 1.415 1.414L10 18l-6.364-6.364 1.414-1.414z"/></svg>
|
||||
<slot></slot>
|
||||
</div>`;
|
||||
customElements.define('sm-option', class extends HTMLElement {
|
||||
constructor() {
|
||||
super()
|
||||
this.attachShadow({
|
||||
mode: 'open'
|
||||
}).append(smOption.content.cloneNode(true))
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
this.setAttribute('role', 'option')
|
||||
this.setAttribute('tabindex', '0')
|
||||
}
|
||||
})
|
||||
|
||||
@ -376,24 +376,29 @@ ul {
|
||||
fill: var(--accent-color);
|
||||
}
|
||||
|
||||
#confirmation_popup {
|
||||
#confirmation_popup,
|
||||
#prompt_popup {
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
}
|
||||
#confirmation_popup h4 {
|
||||
#confirmation_popup h4,
|
||||
#prompt_popup h4 {
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
#confirmation_popup sm-button {
|
||||
#confirmation_popup sm-button,
|
||||
#prompt_popup sm-button {
|
||||
margin: 0;
|
||||
}
|
||||
#confirmation_popup .flex {
|
||||
#confirmation_popup .flex,
|
||||
#prompt_popup .flex {
|
||||
padding: 0;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
#confirmation_popup .flex sm-button:first-of-type {
|
||||
#confirmation_popup .flex sm-button:first-of-type,
|
||||
#prompt_popup .flex sm-button:first-of-type {
|
||||
margin-right: 0.6rem;
|
||||
margin-left: auto;
|
||||
}
|
||||
@ -405,6 +410,22 @@ button:active,
|
||||
transform: scale(0.96);
|
||||
}
|
||||
|
||||
.popup__header {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
padding: 0 1.5rem 0 0.5rem;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
}
|
||||
|
||||
.popup__header__close {
|
||||
padding: 0.5rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#main_page {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
@ -571,12 +592,11 @@ strip-option:last-of-type {
|
||||
#home {
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr auto;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
#main_header {
|
||||
padding: 1.5rem;
|
||||
padding: 1.8rem 1.5rem;
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
-webkit-box-align: center;
|
||||
@ -589,7 +609,7 @@ strip-option:last-of-type {
|
||||
--width: min(24rem, 100%);
|
||||
-ms-flex-item-align: start;
|
||||
align-self: flex-start;
|
||||
padding: 0 1.5rem;
|
||||
padding: 1rem 1.5rem;
|
||||
}
|
||||
|
||||
#quantity_selector .button {
|
||||
@ -611,22 +631,48 @@ strip-option:last-of-type {
|
||||
min-width: 8ch;
|
||||
}
|
||||
|
||||
#orders_section {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
#user_section {
|
||||
gap: 1.5rem;
|
||||
padding: 0 1.5rem;
|
||||
padding: 1.5rem;
|
||||
-ms-flex-line-pack: start;
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
.wallet_actions__wrapper {
|
||||
grid-column: span 3;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.wallet_actions__wrapper .button {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.balance-card {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
gap: 0.3rem 1rem;
|
||||
padding: 0.5rem 0;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
.balance-card.is-locked {
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
.balance-card.is-locked .label {
|
||||
font-size: 0.8rem;
|
||||
color: rgba(var(--text-color), 0.8);
|
||||
}
|
||||
.balance-card:not(.is-locked) {
|
||||
grid-template-columns: auto 1fr auto;
|
||||
}
|
||||
.balance-card__icon {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
@ -649,27 +695,58 @@ strip-option:last-of-type {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
.balance-card__amount {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
.balance-card__amount-wrapper {
|
||||
grid-column: span 2;
|
||||
gap: 0.3rem 1rem;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
.balance-card__actions {
|
||||
grid-column: span 3;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.balance-card__actions .button {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex: 1;
|
||||
flex: 1;
|
||||
.balance-card__amount-wrapper > :nth-child(even) {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 640px) {
|
||||
.loader-button-wrapper {
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
position: relative;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
.loader-button-wrapper sm-button,
|
||||
.loader-button-wrapper slide-button {
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
-webkit-transition: -webkit-clip-path 0.3s;
|
||||
transition: -webkit-clip-path 0.3s;
|
||||
transition: clip-path 0.3s;
|
||||
transition: clip-path 0.3s, -webkit-clip-path 0.3s;
|
||||
-webkit-clip-path: circle(100%);
|
||||
clip-path: circle(100%);
|
||||
}
|
||||
.loader-button-wrapper sm-button.clip,
|
||||
.loader-button-wrapper slide-button.clip {
|
||||
pointer-events: none;
|
||||
-webkit-clip-path: circle(0);
|
||||
clip-path: circle(0);
|
||||
}
|
||||
.loader-button-wrapper sm-spinner {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 40rem) {
|
||||
sm-button {
|
||||
--padding: 0.9rem 1.6rem;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 640px) {
|
||||
@media screen and (min-width: 40rem) {
|
||||
sm-popup {
|
||||
--width: 24rem;
|
||||
}
|
||||
|
||||
.h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
@ -686,6 +763,10 @@ strip-option:last-of-type {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.popup__header {
|
||||
padding: 1rem 1.5rem 0 0.5rem;
|
||||
}
|
||||
|
||||
#confirmation_popup {
|
||||
--width: 24rem;
|
||||
}
|
||||
@ -694,25 +775,30 @@ strip-option:last-of-type {
|
||||
grid-template-columns: 1fr 90vw 1fr;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 1024px) {
|
||||
@media screen and (min-width: 64rem) {
|
||||
.page-layout {
|
||||
grid-template-columns: 1fr 80vw 1fr;
|
||||
}
|
||||
|
||||
#home {
|
||||
-webkit-box-align: start;
|
||||
-ms-flex-align: start;
|
||||
align-items: flex-start;
|
||||
padding: 1.5vmax 3vmax;
|
||||
grid-template-columns: 24rem minmax(0, 1fr) 20rem;
|
||||
grid-template-rows: auto 1fr;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
#main_header {
|
||||
grid-column: span 3;
|
||||
#home > * {
|
||||
border-radius: 0.5rem;
|
||||
background-color: var(--foreground-color);
|
||||
border: solid thin rgba(var(--text-color), 0.1);
|
||||
}
|
||||
|
||||
.hide-on-desktop {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 1920px) {
|
||||
@media screen and (min-width: 120rem) {
|
||||
.page-layout {
|
||||
grid-template-columns: 1fr 70vw 1fr;
|
||||
}
|
||||
|
||||
2
public/css/main.min.css
vendored
2
public/css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -341,22 +341,19 @@ ul {
|
||||
fill: var(--accent-color);
|
||||
}
|
||||
}
|
||||
#confirmation_popup {
|
||||
#confirmation_popup,
|
||||
#prompt_popup {
|
||||
flex-direction: column;
|
||||
|
||||
h4 {
|
||||
font-weight: 500;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
sm-button {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.flex {
|
||||
padding: 0;
|
||||
margin-top: 1rem;
|
||||
|
||||
sm-button:first-of-type {
|
||||
margin-right: 0.6rem;
|
||||
margin-left: auto;
|
||||
@ -370,6 +367,20 @@ button:active,
|
||||
transform: scale(0.96);
|
||||
}
|
||||
|
||||
.popup__header {
|
||||
display: grid;
|
||||
gap: 0.5rem;
|
||||
width: 100%;
|
||||
padding: 0 1.5rem 0 0.5rem;
|
||||
align-items: center;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
}
|
||||
|
||||
.popup__header__close {
|
||||
padding: 0.5rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#main_page {
|
||||
padding: 1.5rem;
|
||||
|
||||
@ -517,12 +528,11 @@ strip-option {
|
||||
#home {
|
||||
height: 100%;
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr auto;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
#main_header {
|
||||
padding: 1.5rem;
|
||||
padding: 1.8rem 1.5rem;
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
align-items: center;
|
||||
@ -532,7 +542,7 @@ strip-option {
|
||||
#trade_form {
|
||||
--width: min(24rem, 100%);
|
||||
align-self: flex-start;
|
||||
padding: 0 1.5rem;
|
||||
padding: 1rem 1.5rem;
|
||||
}
|
||||
#quantity_selector {
|
||||
.button {
|
||||
@ -551,19 +561,41 @@ strip-option {
|
||||
font-weight: 500;
|
||||
min-width: 8ch;
|
||||
}
|
||||
#orders_section {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
#user_section {
|
||||
gap: 1.5rem;
|
||||
padding: 0 1.5rem;
|
||||
padding: 1.5rem;
|
||||
align-content: flex-start;
|
||||
}
|
||||
.user_section__header {
|
||||
}
|
||||
.wallet_actions__wrapper {
|
||||
grid-column: span 3;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
.button {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
.balance-card {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr auto;
|
||||
align-items: center;
|
||||
gap: 0.3rem 1rem;
|
||||
padding: 0.5rem 0;
|
||||
border-radius: 0.5rem;
|
||||
&.is-locked {
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 1rem;
|
||||
.label {
|
||||
font-size: 0.8rem;
|
||||
color: rgba(var(--text-color), 0.8);
|
||||
}
|
||||
}
|
||||
&:not(.is-locked) {
|
||||
grid-template-columns: auto 1fr auto;
|
||||
}
|
||||
&__icon {
|
||||
display: flex;
|
||||
align-content: center;
|
||||
@ -581,25 +613,44 @@ strip-option {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
&__amount {
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
&__actions {
|
||||
grid-column: span 3;
|
||||
gap: 0.5rem;
|
||||
margin-top: 0.5rem;
|
||||
.button {
|
||||
flex: 1;
|
||||
&__amount-wrapper {
|
||||
grid-column: span 2;
|
||||
gap: 0.3rem 1rem;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
& > :nth-child(even) {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 640px) {
|
||||
.loader-button-wrapper {
|
||||
display: flex;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
sm-button,
|
||||
slide-button {
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
transition: clip-path 0.3s;
|
||||
clip-path: circle(100%);
|
||||
&.clip {
|
||||
pointer-events: none;
|
||||
clip-path: circle(0);
|
||||
}
|
||||
}
|
||||
sm-spinner {
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 40rem) {
|
||||
sm-button {
|
||||
--padding: 0.9rem 1.6rem;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 640px) {
|
||||
@media screen and (min-width: 40rem) {
|
||||
sm-popup {
|
||||
--width: 24rem;
|
||||
}
|
||||
.h1 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
@ -615,6 +666,9 @@ strip-option {
|
||||
.h4 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.popup__header {
|
||||
padding: 1rem 1.5rem 0 0.5rem;
|
||||
}
|
||||
#confirmation_popup {
|
||||
--width: 24rem;
|
||||
}
|
||||
@ -622,24 +676,28 @@ strip-option {
|
||||
grid-template-columns: 1fr 90vw 1fr;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 1024px) {
|
||||
@media screen and (max-width: 64rem) {
|
||||
}
|
||||
@media screen and (min-width: 1024px) {
|
||||
@media screen and (min-width: 64rem) {
|
||||
.page-layout {
|
||||
grid-template-columns: 1fr 80vw 1fr;
|
||||
}
|
||||
#home {
|
||||
align-items: flex-start;
|
||||
padding: 1.5vmax 3vmax;
|
||||
grid-template-columns: 24rem minmax(0, 1fr) 20rem;
|
||||
grid-template-rows: auto 1fr;
|
||||
gap: 1rem;
|
||||
& > * {
|
||||
border-radius: 0.5rem;
|
||||
background-color: var(--foreground-color);
|
||||
border: solid thin rgba(var(--text-color), 0.1);
|
||||
}
|
||||
#main_header {
|
||||
grid-column: span 3;
|
||||
}
|
||||
.hide-on-desktop {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@media screen and (min-width: 1920px) {
|
||||
@media screen and (min-width: 120rem) {
|
||||
.page-layout {
|
||||
grid-template-columns: 1fr 70vw 1fr;
|
||||
}
|
||||
|
||||
@ -50,6 +50,15 @@
|
||||
<sm-button variant="no-outline" class="submit-btn">OK</sm-button>
|
||||
</div>
|
||||
</sm-popup>
|
||||
<sm-popup id="prompt_popup">
|
||||
<h4 id="prompt_title"></h4>
|
||||
<p id="prompt_message"></p>
|
||||
<sm-input id="prompt_input"></sm-input>
|
||||
<div class="flex align-center">
|
||||
<sm-button variant="no-outline" class="cancel-btn">Cancel</sm-button>
|
||||
<sm-button variant="no-outline" class="submit-btn" type="submit">OK</sm-button>
|
||||
</div>
|
||||
</sm-popup>
|
||||
<article id="landing" class="page page-layout hide-completely">
|
||||
<header class="flex space-between">
|
||||
<div class="logo">
|
||||
@ -139,6 +148,7 @@
|
||||
<h4>Loading RanchiMall Market</h4>
|
||||
</article>
|
||||
<article id="home" class="page">
|
||||
<section>
|
||||
<header id="main_header">
|
||||
<div class="logo">
|
||||
<svg class="main-logo" viewBox="0 0 27.25 32">
|
||||
@ -160,9 +170,11 @@
|
||||
<strip-option value="sell">Sell</strip-option>
|
||||
</strip-select>
|
||||
</div>
|
||||
<sm-input id="get_price" placeholder="Max price" type="number" step="0.00000001" required hiderequired>
|
||||
<sm-input id="get_price" variant="outlined" placeholder="Max price" type="number" step="0.00000001"
|
||||
required hiderequired animate>
|
||||
</sm-input>
|
||||
<sm-input id="get_quantity" placeholder="Quantity" type="number" step="0.0001" required hiderequired>
|
||||
<sm-input id="get_quantity" variant="outlined" placeholder="Quantity" type="number" step="0.00000001"
|
||||
required hiderequired animate>
|
||||
</sm-input>
|
||||
<div id="quantity_selector" class="flex align-center">
|
||||
<span id="quantity_type">Rupee</span>
|
||||
@ -173,14 +185,21 @@
|
||||
</div>
|
||||
<sm-button id="trade_button" class="uppercase" variant="primary" onclick="tradeFlo()">BUY</sm-button>
|
||||
</sm-form>
|
||||
<section>
|
||||
</section>
|
||||
<section id="orders_section" class="grid gap-1-5">
|
||||
<div class="flex space-between align-center">
|
||||
<h4>My orders</h4>
|
||||
<strip-select id="orders_scope_selector">
|
||||
<strip-option value="active" selected>Open</strip-option>
|
||||
<strip-option value="completed">Completed</strip-option>
|
||||
</strip-select>
|
||||
</div>
|
||||
<div class="table" style="--table-columns: 4;">
|
||||
<div class="table__header table__row">
|
||||
<div></div>
|
||||
<div>Quantity</div>
|
||||
<div>At price</div>
|
||||
<div>Order Placed</div>
|
||||
<div>Order placed</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@ -195,6 +214,23 @@
|
||||
</svg>
|
||||
My wallet
|
||||
</h4>
|
||||
<div id="wallet_actions">
|
||||
<p>Select asset</p>
|
||||
<sm-select id="wallet_asset_selector">
|
||||
<sm-option value="FLO">FLO</sm-option>
|
||||
<sm-option value="Rupee">Rupee</sm-option>
|
||||
</sm-select>
|
||||
<div class="flex wallet_actions__wrapper">
|
||||
<button class="button" value="deposit">
|
||||
Deposit
|
||||
</button>
|
||||
<button class="button" value="withdraw">
|
||||
Withdraw
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid gap-0-5">
|
||||
<h4>Balance</h4>
|
||||
<div class="balance-card">
|
||||
<div class="balance-card__icon">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||
@ -203,15 +239,7 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div class="balance-card__token">FLO</div>
|
||||
<div id="flo_balance" class="balance-card__amount"></div>
|
||||
<div class="flex balance-card__actions">
|
||||
<button class="button" onclick="UI_evt.depositFLO();">
|
||||
Deposit
|
||||
</button>
|
||||
<button class="button" onclick="UI_evt.withdrawFLO()">
|
||||
Withdraw
|
||||
</button>
|
||||
</div>
|
||||
<div id="flo_balance"></div>
|
||||
</div>
|
||||
<div class="balance-card">
|
||||
<div class="balance-card__icon">
|
||||
@ -221,18 +249,34 @@
|
||||
</svg>
|
||||
</div>
|
||||
<div class="balance-card__token">Rupee</div>
|
||||
<div id="rupee_balance" class="balance-card__amount">₹15402</div>
|
||||
<div class="flex balance-card__actions">
|
||||
<button class="button" onclick="UI_evt.depositRupee()">
|
||||
Deposit
|
||||
</button>
|
||||
<button class="button" onclick="UI_evt.withdrawRupee()">
|
||||
Withdraw
|
||||
</button>
|
||||
<div id="rupee_balance"></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</article>
|
||||
<sm-popup id="wallet_popup">
|
||||
<header slot="header" class="popup__header">
|
||||
<button class="popup__header__close" onclick="hidePopup()">
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
||||
<path fill="none" d="M0 0h24v24H0z" />
|
||||
<path
|
||||
d="M12 10.586l4.95-4.95 1.414 1.414-4.95 4.95 4.95 4.95-1.414 1.414-4.95-4.95-4.95 4.95-1.414-1.414 4.95-4.95-4.95-4.95L7.05 5.636z" />
|
||||
</svg>
|
||||
</button>
|
||||
<h4 id="wallet_popup__title" class="capitalize"></h4>
|
||||
</header>
|
||||
<sm-form id="wallet_form">
|
||||
<sm-input id="get_user_amount" variant="outlined" placeholder="Quantity" type="number" step="0.00000001"
|
||||
required hiderequired animate>
|
||||
</sm-input>
|
||||
<sm-input id="get_private_key" variant="outlined" placeholder="FLO private key" type="password" required
|
||||
error-text="Invalid private key" hiderequired animate>
|
||||
</sm-input>
|
||||
<div id="wallet_popup__cta_wrapper" class="loader-button-wrapper">
|
||||
<sm-button id="wallet_popup__cta" variant="primary"></sm-button>
|
||||
</div>
|
||||
</sm-form>
|
||||
</sm-popup>
|
||||
<form id="login-form">
|
||||
<fieldset>
|
||||
<legend>Login</legend>
|
||||
@ -247,8 +291,6 @@
|
||||
<fieldset>
|
||||
<legend>Profile</legend>
|
||||
<span id="user_id"></span><br />
|
||||
FLO: <span id="flo_bal"></span><br />
|
||||
Rupee: <span id="rupee_bal"></span><br />
|
||||
<button onclick="proxy.lock();">Add password lock</button><br />
|
||||
<button onclick="UI_evt.logout();">logout</button>
|
||||
<button onclick="toggle_view('my-profile');">Toggle</button>
|
||||
@ -278,7 +320,7 @@
|
||||
<th>Select</th>
|
||||
<th>Quantity</th>
|
||||
<th>Min Price</th>
|
||||
<th>Order Placed</th>
|
||||
<th>Order placed</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-type="sell"></tbody>
|
||||
@ -360,6 +402,19 @@
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<template id="net_balance_template">
|
||||
<span class="available-balance"></span>
|
||||
</template>
|
||||
<template id="locked_balance_template">
|
||||
<div>
|
||||
<span class="label">Locked</span>
|
||||
<span class="locked-balance"></span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">Available</span>
|
||||
<span class="available-balance"></span>
|
||||
</div>
|
||||
</template>
|
||||
<script id="ui_utils">
|
||||
// Global variables
|
||||
const domRefs = {};
|
||||
@ -503,6 +558,34 @@
|
||||
})
|
||||
}
|
||||
|
||||
// displays a popup for asking user input. Use this instead of JS prompt
|
||||
async function getPromptInput(title, message = '', options = {}) {
|
||||
const { isPassword = true, cancelText = 'Cancel', confirmText = 'OK' } = options
|
||||
showPopup('prompt_popup', true)
|
||||
getRef('prompt_title').textContent = title;
|
||||
let input = getRef('prompt_input');
|
||||
input.setAttribute("placeholder", message)
|
||||
let buttons = getRef('prompt_popup').querySelectorAll("sm-button");
|
||||
if (isPassword)
|
||||
input.setAttribute("type", "text")
|
||||
else
|
||||
input.setAttribute("type", "password")
|
||||
input.focusIn()
|
||||
buttons[0].textContent = cancelText;
|
||||
buttons[1].textContent = confirmText;
|
||||
return new Promise((resolve, reject) => {
|
||||
buttons[0].onclick = () => {
|
||||
hidePopup()
|
||||
return;
|
||||
}
|
||||
buttons[1].onclick = () => {
|
||||
let value = input.value;
|
||||
hidePopup()
|
||||
resolve(value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//Function for displaying toast notifications. pass in error for mode param if you want to show an error.
|
||||
function notify(message, mode, options = {}) {
|
||||
const { pinned = false, sound = false } = options
|
||||
@ -742,23 +825,23 @@
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
var user_id; //container for user ID and proxy private-key
|
||||
let user_id; //container for user ID and proxy private-key
|
||||
|
||||
const proxy = {
|
||||
private: null,
|
||||
public: null,
|
||||
lock() {
|
||||
async lock() {
|
||||
if (!this.private)
|
||||
throw "No proxy key found!";
|
||||
let pwd = prompt("Enter password: ");
|
||||
let pwd = await getPromptInput("Enter password", '', { isPassword: true });
|
||||
if (!pwd)
|
||||
alert("Password cannot be empty");
|
||||
notify("Password cannot be empty", 'error');
|
||||
else if (pwd.length < 4)
|
||||
alert("Password minimum length is 4");
|
||||
notify("Password minimum length is 4", 'error');
|
||||
else {
|
||||
let tmp = Crypto.AES.encrypt(this.private, pwd);
|
||||
localStorage.setItem("proxy_secret", "?" + tmp);
|
||||
alert("Successfully locked with Password");
|
||||
notify("Successfully locked with Password", 'success');
|
||||
}
|
||||
},
|
||||
clear() {
|
||||
@ -777,7 +860,7 @@
|
||||
try {
|
||||
let tmp = localStorage.getItem("proxy_secret");
|
||||
if (typeof tmp === "string" && tmp.startsWith("?")) {
|
||||
let pwd = prompt("Enter password: ");
|
||||
getPromptInput("Enter password", '', { isPassword: true }).then(pwd => {
|
||||
if (!pwd)
|
||||
throw "Password Required for making transactions";
|
||||
else {
|
||||
@ -788,6 +871,7 @@
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
this.private = tmp;
|
||||
this.public = floCrypto.getPubKeyHex(tmp);
|
||||
@ -865,6 +949,19 @@
|
||||
account();
|
||||
}
|
||||
|
||||
function showBalance(containerId, availableBalance = 0, lockedBalance = 0) {
|
||||
getRef(containerId).innerHTML = ''
|
||||
const templateToClone = lockedBalance ? 'locked_balance_template' : 'net_balance_template';
|
||||
const card = getRef(templateToClone).content.cloneNode(true).firstElementChild
|
||||
card.querySelector('.available-balance').textContent = availableBalance
|
||||
if (lockedBalance) {
|
||||
card.querySelector('.locked-balance').textContent = lockedBalance
|
||||
}
|
||||
getRef(containerId).className = lockedBalance ? 'grid balance-card__amount-wrapper' : ''
|
||||
getRef(containerId).parentNode.className = `balance-card ${lockedBalance ? 'is-locked' : ''}`
|
||||
getRef(containerId).append(card)
|
||||
}
|
||||
|
||||
function account() {
|
||||
getAccount().then(acc => {
|
||||
console.debug(acc);
|
||||
@ -878,13 +975,14 @@
|
||||
let flo_locked = acc.sellOrders.reduce((a, x) => a + x.quantity, 0);
|
||||
let flo_net = flo_total - flo_locked;
|
||||
console.debug("FLO", flo_total, flo_locked, flo_net);
|
||||
document.getElementById("flo_bal").textContent = flo_net + "(+" + flo_locked + ")";
|
||||
|
||||
showBalance("flo_balance", flo_net, flo_locked)
|
||||
//Rupee Balance
|
||||
let rupee_total = acc.rupee_total;
|
||||
let rupee_locked = acc.buyOrders.reduce((a, x) => a + x.quantity * x.maxPrice, 0);
|
||||
let rupee_net = rupee_total - rupee_locked;
|
||||
console.debug("RUPEE", rupee_total, rupee_locked, rupee_net);
|
||||
document.getElementById("rupee_bal").textContent = rupee_net + "(+" + rupee_locked + ")";
|
||||
showBalance("rupee_balance", rupee_net, rupee_locked)
|
||||
//My buy orders
|
||||
let container = document.getElementById("my-buy-orders").getElementsByTagName("tbody")[0];
|
||||
container.innerHTML = '';
|
||||
@ -948,16 +1046,17 @@
|
||||
|
||||
const UI_evt = {};
|
||||
|
||||
UI_evt.signup = function () {
|
||||
UI_evt.signup = async function () {
|
||||
let sid = document.forms['login-form']['sid'].value;
|
||||
let privKey = prompt("Enter Private Key of floID to register: ");
|
||||
let privKey = await getPromptInput("Register private key", "Enter the private key of floID you want to register", { isPassword: true });
|
||||
if (privKey) {
|
||||
signUp(privKey, sid).then(result => {
|
||||
console.info(result);
|
||||
alert("Account registered!")
|
||||
notify("Account registered!", 'success')
|
||||
}).catch(error => {
|
||||
console.error(error)
|
||||
alert(error);
|
||||
notify(error, 'error');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
UI_evt.logout = function () {
|
||||
@ -981,83 +1080,40 @@
|
||||
}).catch(error => console.error(error));
|
||||
};
|
||||
|
||||
UI_evt.sell = function () {
|
||||
let formInputs = document.forms['sell-form'];
|
||||
sell(parseFloat(formInputs["quantity"].value), parseFloat(formInputs["min-price"].value), proxy.secret)
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error))
|
||||
.finally(_ => formInputs.reset());
|
||||
};
|
||||
|
||||
UI_evt.buy = function () {
|
||||
let formInputs = document.forms['buy-form'];
|
||||
buy(parseFloat(formInputs["quantity"].value), parseFloat(formInputs["max-price"].value), proxy.secret)
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error))
|
||||
.finally(_ => formInputs.reset());
|
||||
};
|
||||
|
||||
UI_evt.cancelOrders = function () {
|
||||
let container = document.getElementById('my-orders');
|
||||
let cancel = [];
|
||||
let inputs = container.getElementsByTagName('input')
|
||||
let inputs = container.querySelectorAll('input[checked]')
|
||||
for (let i = 0; i < inputs.length; i++) {
|
||||
if (inputs[i].type === "checkbox" && inputs[i].checked) {
|
||||
let row = inputs[i].parentElement.parentElement
|
||||
let id = row.dataset['id'];
|
||||
let type = row.parentElement.dataset['type'];
|
||||
cancel.push([type, id]);
|
||||
}
|
||||
}
|
||||
cancel.forEach(o => cancelOrder(o[0], o[1], proxy.secret)
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(o, error)))
|
||||
};
|
||||
|
||||
UI_evt.depositFLO = function () {
|
||||
let formInputs = document.forms['deposit-withdraw-form'];
|
||||
let privKey = prompt("Enter private key");
|
||||
depositFLO(parseFloat(formInputs["quantity"].value), user_id, privKey, proxy.secret)
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error))
|
||||
.finally(_ => formInputs.reset());
|
||||
}
|
||||
|
||||
UI_evt.depositRupee = function () {
|
||||
let formInputs = document.forms['deposit-withdraw-form'];
|
||||
let privKey = prompt("Enter private key");
|
||||
depositRupee(parseFloat(formInputs["quantity"].value), user_id, privKey, proxy.secret)
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error))
|
||||
.finally(_ => formInputs.reset());
|
||||
}
|
||||
|
||||
UI_evt.withdrawFLO = function () {
|
||||
let formInputs = document.forms['deposit-withdraw-form'];
|
||||
withdrawFLO(parseFloat(formInputs["quantity"].value), proxy.secret)
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error))
|
||||
.finally(_ => formInputs.reset());
|
||||
}
|
||||
|
||||
UI_evt.withdrawRupee = function () {
|
||||
let formInputs = document.forms['deposit-withdraw-form'];
|
||||
withdrawRupee(parseFloat(formInputs["quantity"].value), proxy.secret)
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error))
|
||||
.finally(_ => formInputs.reset());
|
||||
}
|
||||
|
||||
refresh(true);
|
||||
</script>
|
||||
<script>
|
||||
function showProcess(id) {
|
||||
getRef(id).children[0].classList.add('clip')
|
||||
getRef(id).append(document.createElement('sm-spinner'))
|
||||
}
|
||||
function hideProcess(id) {
|
||||
getRef(id).children[0].classList.remove('clip')
|
||||
getRef(id).querySelector('sm-spinner')?.remove()
|
||||
}
|
||||
let tradeType = 'buy'
|
||||
getRef('trade_type_selector').addEventListener('change', e => {
|
||||
getRef('get_price').setAttribute('placeholder', e.detail.value === 'buy' ? 'Max price' : 'Min price')
|
||||
getRef('trade_button').textContent = e.detail.value
|
||||
getRef('quantity_type').textContent = e.detail.value === 'buy' ? `Rupee` : `FLO`
|
||||
tradeType = e.detail.value
|
||||
getRef('get_price').setAttribute('placeholder', tradeType === 'buy' ? 'Max price' : 'Min price')
|
||||
getRef('trade_button').textContent = tradeType
|
||||
getRef('quantity_type').textContent = tradeType === 'buy' ? `Rupee` : `FLO`
|
||||
})
|
||||
async function tradeFlo() {
|
||||
const tradeType = getRef('trade_type_selector').value
|
||||
const quantity = parseFloat(getRef('get_quantity').value)
|
||||
const price = parseFloat(getRef('get_price').value)
|
||||
try {
|
||||
@ -1075,6 +1131,77 @@
|
||||
getRef('trade_form').reset()
|
||||
}
|
||||
}
|
||||
const balance = {
|
||||
flo: 5.1245,
|
||||
rupee: 457.2
|
||||
}
|
||||
const rate = {
|
||||
flo: 1.487
|
||||
}
|
||||
getRef('quantity_selector').addEventListener('click', e => {
|
||||
// Get latest balance and exchange rate
|
||||
if (e.target.closest('button')) {
|
||||
const target = e.target.closest('button')
|
||||
const fraction = parseInt(target.value) / 100
|
||||
if (tradeType === 'buy') {
|
||||
getRef('get_quantity').value = parseFloat(((balance.rupee * fraction) / rate.flo).toFixed(8))
|
||||
} else {
|
||||
getRef('get_quantity').value = parseFloat((balance.flo * fraction).toFixed(8))
|
||||
}
|
||||
}
|
||||
})
|
||||
getRef('wallet_actions').addEventListener('click', e => {
|
||||
if (e.target.closest('.button')) {
|
||||
const target = e.target.closest('.button')
|
||||
showPopup('wallet_popup')
|
||||
const type = target.value
|
||||
const asset = getRef('wallet_asset_selector').value
|
||||
getRef('wallet_popup__cta').textContent = `${type}`
|
||||
getRef('wallet_popup__cta').setAttribute('value', type)
|
||||
getRef('wallet_popup__title').textContent = `${type} ${asset}`
|
||||
if (type === 'withdraw') {
|
||||
getRef('get_private_key').classList.add('hide-completely')
|
||||
getRef('get_private_key').removeAttribute('required')
|
||||
getRef('get_private_key').removeAttribute('hiderequired')
|
||||
} else {
|
||||
getRef('get_private_key').setAttribute('required', '')
|
||||
getRef('get_private_key').setAttribute('hiderequired', '')
|
||||
getRef('get_private_key').classList.remove('hide-completely')
|
||||
}
|
||||
getRef('wallet_form').elementsChanged()
|
||||
}
|
||||
})
|
||||
getRef('wallet_popup__cta').addEventListener('click', async e => {
|
||||
const asset = getRef('wallet_asset_selector').value
|
||||
const type = e.target.getAttribute('value')
|
||||
const quantity = parseFloat(getRef('get_quantity').value)
|
||||
console.log(type, asset)
|
||||
try {
|
||||
showProcess('wallet_popup__cta_wrapper')
|
||||
if (type === 'deposit') {
|
||||
const privKey = getRef('get_private_key').value;
|
||||
if (asset === 'FLO') {
|
||||
await depositFLO(quantity, user_id, privKey, proxy.secret)
|
||||
} else {
|
||||
await depositRupee(quantity, user_id, privKey, proxy.secret)
|
||||
}
|
||||
notify(`Deposited ${asset} successfully`)
|
||||
} else {
|
||||
if (asset === 'FLO') {
|
||||
await withdrawFLO(quantity, proxy.secret)
|
||||
} else {
|
||||
await withdrawRupee(quantity, proxy.secret)
|
||||
}
|
||||
notify(`Withdrawn ${asset} successfully`)
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
notify(err, 'error')
|
||||
}
|
||||
finally {
|
||||
hideProcess('wallet_popup__cta_wrapper')
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user