Added wallet deposit/withdraw UI

This commit is contained in:
sairaj mote 2021-10-04 19:12:31 +05:30
parent 75879ca2f5
commit 5a67beb249
6 changed files with 885 additions and 223 deletions

View File

@ -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"
}

View File

@ -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')
}
})

View File

@ -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;
}

File diff suppressed because one or more lines are too long

View File

@ -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;
}
#main_header {
grid-column: span 3;
gap: 1rem;
& > * {
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;
}

View File

@ -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,48 +148,58 @@
<h4>Loading RanchiMall Market</h4>
</article>
<article id="home" class="page">
<header id="main_header">
<div class="logo">
<svg class="main-logo" viewBox="0 0 27.25 32">
<title>RanchiMall</title>
<path
d="M27.14,30.86c-.74-2.48-3-4.36-8.25-6.94a20,20,0,0,1-4.2-2.49,6,6,0,0,1-1.25-1.67,4,4,0,0,1,0-2.26c.37-1.08.79-1.57,3.89-4.55a11.66,11.66,0,0,0,3.34-4.67,6.54,6.54,0,0,0,.05-2.82C20,3.6,18.58,2,16.16.49c-.89-.56-1.29-.64-1.3-.24a3,3,0,0,1-.3.72l-.3.55L13.42.94C13,.62,12.4.26,12.19.15c-.4-.2-.73-.18-.72.05a9.39,9.39,0,0,1-.61,1.33s-.14,0-.27-.13C8.76.09,8-.27,8,.23A11.73,11.73,0,0,1,6.76,2.6C4.81,5.87,2.83,7.49.77,7.49c-.89,0-.88,0-.61,1,.22.85.33.92,1.09.69A5.29,5.29,0,0,0,3,8.33c.23-.17.45-.29.49-.26a2,2,0,0,1,.22.63A1.31,1.31,0,0,0,4,9.34a5.62,5.62,0,0,0,2.27-.87L7,8l.13.55c.19.74.32.82,1,.65a7.06,7.06,0,0,0,3.46-2.47l.6-.71-.06.64c-.17,1.63-1.3,3.42-3.39,5.42L6.73,14c-3.21,3.06-3,5.59.6,8a46.77,46.77,0,0,0,4.6,2.41c.28.13,1,.52,1.59.87,3.31,2,4.95,3.92,4.95,5.93a2.49,2.49,0,0,0,.07.77h0c.09.09,0,.1.9-.14a2.61,2.61,0,0,0,.83-.32,3.69,3.69,0,0,0-.55-1.83A11.14,11.14,0,0,0,17,26.81a35.7,35.7,0,0,0-5.1-2.91C9.37,22.64,8.38,22,7.52,21.17a3.53,3.53,0,0,1-1.18-2.48c0-1.38.71-2.58,2.5-4.23,2.84-2.6,3.92-3.91,4.67-5.65a3.64,3.64,0,0,0,.42-2A3.37,3.37,0,0,0,13.61,5l-.32-.74.29-.48c.17-.27.37-.63.46-.8l.15-.3.44.64a5.92,5.92,0,0,1,1,2.81,5.86,5.86,0,0,1-.42,1.94c0,.12-.12.3-.15.4a9.49,9.49,0,0,1-.67,1.1,28,28,0,0,1-4,4.29C8.62,15.49,8.05,16.44,8,17.78a3.28,3.28,0,0,0,1.11,2.76c.95,1,2.07,1.74,5.25,3.32,3.64,1.82,5.22,2.9,6.41,4.38A4.78,4.78,0,0,1,21.94,31a3.21,3.21,0,0,0,.14.92,1.06,1.06,0,0,0,.43-.05l.83-.22.46-.12-.06-.46c-.21-1.53-1.62-3.25-3.94-4.8a37.57,37.57,0,0,0-5.22-2.82A13.36,13.36,0,0,1,11,21.19a3.36,3.36,0,0,1-.8-4.19c.41-.85.83-1.31,3.77-4.15,2.39-2.31,3.43-4.13,3.43-6a5.85,5.85,0,0,0-2.08-4.29c-.23-.21-.44-.43-.65-.65A2.5,2.5,0,0,1,15.27.69a10.6,10.6,0,0,1,2.91,2.78A4.16,4.16,0,0,1,19,6.16a4.91,4.91,0,0,1-.87,3c-.71,1.22-1.26,1.82-4.27,4.67a9.47,9.47,0,0,0-2.07,2.6,2.76,2.76,0,0,0-.33,1.54,2.76,2.76,0,0,0,.29,1.47c.57,1.21,2.23,2.55,4.65,3.73a32.41,32.41,0,0,1,5.82,3.24c2.16,1.6,3.2,3.16,3.2,4.8a1.94,1.94,0,0,0,.09.76,4.54,4.54,0,0,0,1.66-.4C27.29,31.42,27.29,31.37,27.14,30.86ZM6.1,7h0a3.77,3.77,0,0,1-1.46.45L4,7.51l.68-.83a25.09,25.09,0,0,0,3-4.82A12,12,0,0,1,8.28.76c.11-.12.77.32,1.53,1l.63.58-.57.84A10.34,10.34,0,0,1,6.1,7Zm5.71-1.78A9.77,9.77,0,0,1,9.24,7.18h0a5.25,5.25,0,0,1-1.17.28l-.58,0,.65-.78a21.29,21.29,0,0,0,2.1-3.12c.22-.41.42-.76.44-.79s.5.43.9,1.24L12,5ZM13.41,3a2.84,2.84,0,0,1-.45.64,11,11,0,0,1-.9-.91l-.84-.9.19-.45c.34-.79.39-.8,1-.31A9.4,9.4,0,0,1,13.8,2.33q-.18.34-.39.69Z" />
</svg>
<div class="grid">
<h4>RanchiMall Market</h4>
<section>
<header id="main_header">
<div class="logo">
<svg class="main-logo" viewBox="0 0 27.25 32">
<title>RanchiMall</title>
<path
d="M27.14,30.86c-.74-2.48-3-4.36-8.25-6.94a20,20,0,0,1-4.2-2.49,6,6,0,0,1-1.25-1.67,4,4,0,0,1,0-2.26c.37-1.08.79-1.57,3.89-4.55a11.66,11.66,0,0,0,3.34-4.67,6.54,6.54,0,0,0,.05-2.82C20,3.6,18.58,2,16.16.49c-.89-.56-1.29-.64-1.3-.24a3,3,0,0,1-.3.72l-.3.55L13.42.94C13,.62,12.4.26,12.19.15c-.4-.2-.73-.18-.72.05a9.39,9.39,0,0,1-.61,1.33s-.14,0-.27-.13C8.76.09,8-.27,8,.23A11.73,11.73,0,0,1,6.76,2.6C4.81,5.87,2.83,7.49.77,7.49c-.89,0-.88,0-.61,1,.22.85.33.92,1.09.69A5.29,5.29,0,0,0,3,8.33c.23-.17.45-.29.49-.26a2,2,0,0,1,.22.63A1.31,1.31,0,0,0,4,9.34a5.62,5.62,0,0,0,2.27-.87L7,8l.13.55c.19.74.32.82,1,.65a7.06,7.06,0,0,0,3.46-2.47l.6-.71-.06.64c-.17,1.63-1.3,3.42-3.39,5.42L6.73,14c-3.21,3.06-3,5.59.6,8a46.77,46.77,0,0,0,4.6,2.41c.28.13,1,.52,1.59.87,3.31,2,4.95,3.92,4.95,5.93a2.49,2.49,0,0,0,.07.77h0c.09.09,0,.1.9-.14a2.61,2.61,0,0,0,.83-.32,3.69,3.69,0,0,0-.55-1.83A11.14,11.14,0,0,0,17,26.81a35.7,35.7,0,0,0-5.1-2.91C9.37,22.64,8.38,22,7.52,21.17a3.53,3.53,0,0,1-1.18-2.48c0-1.38.71-2.58,2.5-4.23,2.84-2.6,3.92-3.91,4.67-5.65a3.64,3.64,0,0,0,.42-2A3.37,3.37,0,0,0,13.61,5l-.32-.74.29-.48c.17-.27.37-.63.46-.8l.15-.3.44.64a5.92,5.92,0,0,1,1,2.81,5.86,5.86,0,0,1-.42,1.94c0,.12-.12.3-.15.4a9.49,9.49,0,0,1-.67,1.1,28,28,0,0,1-4,4.29C8.62,15.49,8.05,16.44,8,17.78a3.28,3.28,0,0,0,1.11,2.76c.95,1,2.07,1.74,5.25,3.32,3.64,1.82,5.22,2.9,6.41,4.38A4.78,4.78,0,0,1,21.94,31a3.21,3.21,0,0,0,.14.92,1.06,1.06,0,0,0,.43-.05l.83-.22.46-.12-.06-.46c-.21-1.53-1.62-3.25-3.94-4.8a37.57,37.57,0,0,0-5.22-2.82A13.36,13.36,0,0,1,11,21.19a3.36,3.36,0,0,1-.8-4.19c.41-.85.83-1.31,3.77-4.15,2.39-2.31,3.43-4.13,3.43-6a5.85,5.85,0,0,0-2.08-4.29c-.23-.21-.44-.43-.65-.65A2.5,2.5,0,0,1,15.27.69a10.6,10.6,0,0,1,2.91,2.78A4.16,4.16,0,0,1,19,6.16a4.91,4.91,0,0,1-.87,3c-.71,1.22-1.26,1.82-4.27,4.67a9.47,9.47,0,0,0-2.07,2.6,2.76,2.76,0,0,0-.33,1.54,2.76,2.76,0,0,0,.29,1.47c.57,1.21,2.23,2.55,4.65,3.73a32.41,32.41,0,0,1,5.82,3.24c2.16,1.6,3.2,3.16,3.2,4.8a1.94,1.94,0,0,0,.09.76,4.54,4.54,0,0,0,1.66-.4C27.29,31.42,27.29,31.37,27.14,30.86ZM6.1,7h0a3.77,3.77,0,0,1-1.46.45L4,7.51l.68-.83a25.09,25.09,0,0,0,3-4.82A12,12,0,0,1,8.28.76c.11-.12.77.32,1.53,1l.63.58-.57.84A10.34,10.34,0,0,1,6.1,7Zm5.71-1.78A9.77,9.77,0,0,1,9.24,7.18h0a5.25,5.25,0,0,1-1.17.28l-.58,0,.65-.78a21.29,21.29,0,0,0,2.1-3.12c.22-.41.42-.76.44-.79s.5.43.9,1.24L12,5ZM13.41,3a2.84,2.84,0,0,1-.45.64,11,11,0,0,1-.9-.91l-.84-.9.19-.45c.34-.79.39-.8,1-.31A9.4,9.4,0,0,1,13.8,2.33q-.18.34-.39.69Z" />
</svg>
<div class="grid">
<h4>RanchiMall Market</h4>
</div>
</div>
</div>
<theme-toggle></theme-toggle>
</header>
<sm-form id="trade_form">
<theme-toggle></theme-toggle>
</header>
<sm-form id="trade_form">
<div class="flex space-between align-center">
<h4>Trade FLO</h4>
<strip-select id="trade_type_selector">
<strip-option value="buy" selected>Buy</strip-option>
<strip-option value="sell">Sell</strip-option>
</strip-select>
</div>
<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" 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>
<button class="button" value="25">25%</button>
<button class="button" value="50">50%</button>
<button class="button" value="75">75%</button>
<button class="button" value="100">100%</button>
</div>
<sm-button id="trade_button" class="uppercase" variant="primary" onclick="tradeFlo()">BUY</sm-button>
</sm-form>
</section>
<section id="orders_section" class="grid gap-1-5">
<div class="flex space-between align-center">
<h4>Trade FLO</h4>
<strip-select id="trade_type_selector">
<strip-option value="buy" selected>Buy</strip-option>
<strip-option value="sell">Sell</strip-option>
<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>
<sm-input id="get_price" placeholder="Max price" type="number" step="0.00000001" required hiderequired>
</sm-input>
<sm-input id="get_quantity" placeholder="Quantity" type="number" step="0.0001" required hiderequired>
</sm-input>
<div id="quantity_selector" class="flex align-center">
<span id="quantity_type">Rupee</span>
<button class="button" value="25">25%</button>
<button class="button" value="50">50%</button>
<button class="button" value="75">75%</button>
<button class="button" value="100">100%</button>
</div>
<sm-button id="trade_button" class="uppercase" variant="primary" onclick="tradeFlo()">BUY</sm-button>
</sm-form>
<section>
<h4>My orders</h4>
<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,44 +214,69 @@
</svg>
My wallet
</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">
<path
d="M16.36,15.39c1.83,0,4.26-2.49,4.36-4.74-5.65-.19-4.91.47-7.28,2.39,2.19-2.4,1.42-7.79-1.43-10V6.17c2.33,1.49,2.21,5.14,0,7.15-2.23-2-2.27-5.69,0-7.15V3c-2.83,2.26-3.62,7.66-1.44,10-2.36-1.93-1.63-2.58-7.28-2.39.1,2.26,2.55,4.73,4.36,4.74,0,0-1.93.22-2.74-2.62,2.38-.37,4.29-.14,6.28,2-.79-.11-4.89,1.13-4.38,3.26.53.06,3,.3,3.58-.83-.17.18-1.25.5-1.53.05.38-1.39,2.32-2,2.32-2-1,1.82-.48,4.63.82,5.72,1.31-1.08,1.8-3.95.82-5.72,0,0,1.95.6,2.32,2-.29.46-1.36.12-1.53-.05.58,1.14,3.06.88,3.58.83.49-2.17-3.58-3.36-4.38-3.26,2-2.17,3.92-2.39,6.28-2C18.3,15.62,16.36,15.39,16.36,15.39ZM12,19.46c-.91-.79-.5-3,0-3.59C12.5,16.45,12.91,18.66,12,19.46Z" />
</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();">
<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" onclick="UI_evt.withdrawFLO()">
<button class="button" value="withdraw">
Withdraw
</button>
</div>
</div>
<div class="balance-card">
<div class="balance-card__icon">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path
d="M15.3,4.91a4.78,4.78,0,0,0-.39-.5l3.14,0L18.75,2H6L5.25,4.6H9a4.22,4.22,0,0,1,3.06,1,3.16,3.16,0,0,1,.75,1.24H5.93L5.25,9.22h7.62a3.15,3.15,0,0,1-.34.82,3,3,0,0,1-1.37,1.17,5.34,5.34,0,0,1-2.2.4H5.5l0,1.9,7,8.49h3.56v-.17L9.68,14l.09,0a8.07,8.07,0,0,0,3.65-1,5,5,0,0,0,2-2.09A6.29,6.29,0,0,0,16,9.22h2.1l.69-2.42H15.93A5.93,5.93,0,0,0,15.3,4.91Z" />
</svg>
<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">
<path
d="M16.36,15.39c1.83,0,4.26-2.49,4.36-4.74-5.65-.19-4.91.47-7.28,2.39,2.19-2.4,1.42-7.79-1.43-10V6.17c2.33,1.49,2.21,5.14,0,7.15-2.23-2-2.27-5.69,0-7.15V3c-2.83,2.26-3.62,7.66-1.44,10-2.36-1.93-1.63-2.58-7.28-2.39.1,2.26,2.55,4.73,4.36,4.74,0,0-1.93.22-2.74-2.62,2.38-.37,4.29-.14,6.28,2-.79-.11-4.89,1.13-4.38,3.26.53.06,3,.3,3.58-.83-.17.18-1.25.5-1.53.05.38-1.39,2.32-2,2.32-2-1,1.82-.48,4.63.82,5.72,1.31-1.08,1.8-3.95.82-5.72,0,0,1.95.6,2.32,2-.29.46-1.36.12-1.53-.05.58,1.14,3.06.88,3.58.83.49-2.17-3.58-3.36-4.38-3.26,2-2.17,3.92-2.39,6.28-2C18.3,15.62,16.36,15.39,16.36,15.39ZM12,19.46c-.91-.79-.5-3,0-3.59C12.5,16.45,12.91,18.66,12,19.46Z" />
</svg>
</div>
<div class="balance-card__token">FLO</div>
<div id="flo_balance"></div>
</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 class="balance-card">
<div class="balance-card__icon">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path
d="M15.3,4.91a4.78,4.78,0,0,0-.39-.5l3.14,0L18.75,2H6L5.25,4.6H9a4.22,4.22,0,0,1,3.06,1,3.16,3.16,0,0,1,.75,1.24H5.93L5.25,9.22h7.62a3.15,3.15,0,0,1-.34.82,3,3,0,0,1-1.37,1.17,5.34,5.34,0,0,1-2.2.4H5.5l0,1.9,7,8.49h3.56v-.17L9.68,14l.09,0a8.07,8.07,0,0,0,3.65-1,5,5,0,0,0,2-2.09A6.29,6.29,0,0,0,16,9.22h2.1l.69-2.42H15.93A5.93,5.93,0,0,0,15.3,4.91Z" />
</svg>
</div>
<div class="balance-card__token">Rupee</div>
<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,17 +860,18 @@
try {
let tmp = localStorage.getItem("proxy_secret");
if (typeof tmp === "string" && tmp.startsWith("?")) {
let pwd = prompt("Enter password: ");
if (!pwd)
throw "Password Required for making transactions";
else {
try {
tmp = Crypto.AES.decrypt(tmp.substring(1), pwd);
} catch (error) {
throw "Incorrect Password! Password Required for making transactions";
}
getPromptInput("Enter password", '', { isPassword: true }).then(pwd => {
if (!pwd)
throw "Password Required for making transactions";
else {
try {
tmp = Crypto.AES.decrypt(tmp.substring(1), pwd);
} catch (error) {
throw "Incorrect Password! Password Required for making transactions";
}
}
}
});
}
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: ");
signUp(privKey, sid).then(result => {
console.info(result);
alert("Account registered!")
}).catch(error => {
console.error(error)
alert(error);
});
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);
notify("Account registered!", 'success')
}).catch(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]);
}
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>