major UI changes

This commit is contained in:
sairaj mote 2022-03-29 18:37:26 +05:30
parent fa46e1132f
commit 1e2971ac8e
6 changed files with 1292 additions and 1614 deletions

1
args/app-config.json Normal file
View File

@ -0,0 +1 @@
{"secret":"9qWGMLljSaHWGfm4tfXMxukjig43fBtafjZ","port":"8080","sql_user":"user","sql_pwd":"Qwerty@123","sql_db":"exchange","sql_host":"localhost","backup-port":"8081","backup-floIDs":[]}

File diff suppressed because it is too large Load Diff

View File

@ -16,38 +16,29 @@ body {
}
body {
color: rgba(var(--text-color), 1);
background: rgba(var(--background-color), 1);
}
body,
body * {
--accent-color: #504dff;
--accent-color--light: #eeeeff;
--text-color: 36, 36, 36;
--background-color: 255, 255, 255;
--foreground-color: rgb(250, 252, 255);
--text-color: 20, 20, 20;
--background-color: 240, 240, 240;
--foreground-color: 250, 250, 250;
--danger-color: rgb(255, 75, 75);
--green: #1cad59;
--yellow: #f3a600;
--loan-color: rgb(255, 171, 93);
scrollbar-width: thin;
scrollbar-gutter: stable;
color: rgba(var(--text-color), 1);
background-color: rgba(var(--background-color), 1);
transition: background-color 0.3s;
}
body[data-theme=dark],
body[data-theme=dark] * {
body[data-theme=dark] {
--accent-color: #a3a1ff;
--accent-color--light: rgba(142, 140, 255, 0.06);
--text-color: 230, 230, 230;
--text-color-light: 170, 170, 170;
--text-color: 220, 220, 220;
--background-color: 10, 10, 10;
--foreground-color: rgb(24, 24, 24);
--foreground-color: 24, 24, 24;
--danger-color: rgb(255, 106, 106);
--green: #00e676;
--yellow: #ffd13a;
--loan-color: rgb(255, 232, 170);
}
body[data-theme=dark] sm-popup::part(popup) {
background-color: var(--foreground-color);
background-color: rgba(var(--foreground-color), 1);
}
p,
@ -128,7 +119,6 @@ a:any-link:focus-visible {
sm-input {
font-size: 0.9rem;
--border-radius: 0.3rem;
--background: var(--accent-color--light);
}
sm-button {
@ -149,6 +139,10 @@ sm-button.danger {
color: rgba(var(--background-color), 1);
}
sm-form {
--gap: 1rem;
}
ul {
list-style: none;
}
@ -166,7 +160,7 @@ ul {
pointer-events: none;
}
.hide-completely {
.hide {
display: none !important;
}
@ -313,11 +307,21 @@ ul {
.interact {
position: relative;
overflow: hidden;
cursor: pointer;
transition: transform 0.3s;
-webkit-tap-highlight-color: transparent;
}
.ripple {
height: 8rem;
width: 8rem;
position: absolute;
border-radius: 50%;
transform: scale(0);
background: radial-gradient(circle, rgba(var(--text-color), 0.3) 0%, rgba(0, 0, 0, 0) 50%);
pointer-events: none;
}
.empty-state {
display: grid;
justify-content: center;
@ -336,15 +340,11 @@ ul {
}
.icon {
width: 1.5rem;
height: 1.5rem;
width: 1.2rem;
height: 1.2rem;
fill: rgba(var(--text-color), 0.8);
}
.button__icon {
height: 1.2rem;
width: 1.2rem;
}
.button__icon--left {
margin-right: 0.5rem;
}
@ -392,12 +392,6 @@ ul {
margin-bottom: 1.5rem;
}
button:active,
.button:active,
.interact:active {
transform: scale(0.96);
}
.popup__header {
display: grid;
gap: 0.5rem;
@ -506,6 +500,10 @@ sm-checkbox {
height: 100%;
}
.mobile-page {
align-items: flex-start;
}
#landing {
grid-template-rows: auto 1fr;
}
@ -547,10 +545,10 @@ sm-checkbox {
#home {
height: 100%;
display: grid;
display: flex;
flex-direction: column;
align-items: flex-start;
align-content: flex-start;
grid-template-columns: minmax(0, 1fr);
}
#login_form__priv_key {
@ -558,34 +556,90 @@ sm-checkbox {
}
#main_header {
margin-top: 1.5rem;
margin-bottom: 1rem;
display: grid;
gap: 1rem;
padding: 1.5rem;
width: 100%;
align-items: center;
grid-template-columns: 1fr auto auto;
grid-column: 1/-1;
}
#flo_exchange_rate {
#main_navbar {
width: 100%;
}
.main_navbar__item {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
padding: 0.5rem 0;
}
.main_navbar__item .item__title,
.main_navbar__item .icon {
transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0.3s;
}
.main_navbar__item .item__title {
color: rgba(var(--text-color), 0.8);
font-size: 0.8rem;
font-weight: 500;
}
.main_navbar__item .icon {
height: 1.2rem;
margin-bottom: 0.3rem;
}
.main_navbar__item--active .item__title {
color: var(--accent-color);
}
.main_navbar__item--active .icon {
fill: var(--accent-color);
}
#pages_container {
display: flex;
flex: 1;
width: 100%;
justify-content: center;
overflow-y: auto;
padding: 0 1.5rem;
}
#pages_container > * {
width: min(42rem, 100%);
}
#exchange {
display: grid;
gap: 1.5rem;
}
.listed-asset {
position: relative;
grid-template-columns: auto 1fr auto;
gap: 0.5rem;
padding: 1rem;
border-radius: 0.5rem;
border: solid rgba(var(--text-color), 0.2) thin;
background-color: rgba(var(--background-color), 1);
opacity: 0.8;
font-weight: 400;
transition: background-color 0.3s;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
color: inherit;
}
.listed-asset__icon {
display: flex;
}
.listed-asset__icon .icon {
height: 1.5rem;
width: 1.5rem;
}
#flo_rate {
font-weight: 700;
}
#trade_form,
#login_form {
align-self: flex-start;
padding: 1rem 1.5rem 1.5rem 1.5rem;
}
.quantity-selector .button {
flex: 1;
padding: 0.5rem 0.6rem;
@ -604,24 +658,17 @@ sm-checkbox {
min-width: 8ch;
}
#my_orders_section,
#market_orders_section {
padding-top: 1rem;
#my_orders,
#market {
width: min(42rem, 100%);
grid-template-rows: auto 1fr;
}
#my_orders_section .icon,
#market_orders_section .icon {
#my_orders .icon,
#market .icon {
height: 1.2rem;
width: 1.2rem;
}
.orders_section__header {
padding: 0 1.5rem;
}
#my_orders_section__header {
height: 2.4rem;
}
#orders_section__header--primary sm-tab-header {
--gap: 1.5rem;
}
@ -631,7 +678,7 @@ sm-checkbox {
}
.list__item {
padding: 0.5rem 1.5rem;
padding: 0.5rem 0;
display: grid;
}
@ -720,13 +767,11 @@ sm-checkbox {
}
#market_orders_list .list__header {
margin-bottom: 0.5rem;
padding: 0 1.5rem;
grid-template-columns: repeat(3, 1fr) 2rem;
}
#user_section {
#wallet {
gap: 1.5rem;
padding: 1.5rem;
align-content: flex-start;
}
@ -943,53 +988,16 @@ sm-checkbox {
}
}
@media screen and (max-width: 40rem) {
#main_header {
padding: 0 1.5rem;
}
sm-button {
--padding: 0.9rem 1.6rem;
}
#home > :last-child {
padding-bottom: 5rem;
}
#bottom_nav {
position: fixed;
bottom: 0;
background-color: var(--foreground-color);
width: 100%;
}
.bottom_nav__item {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
padding: 0.5rem 0;
}
.bottom_nav__item .item__title,
.bottom_nav__item .icon {
transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.bottom_nav__item .item__title {
color: rgba(var(--text-color), 0.8);
font-size: 0.8rem;
font-weight: 500;
}
.bottom_nav__item .icon {
height: 1.2rem;
margin-bottom: 0.3rem;
}
.bottom_nav__item--active .item__title {
color: var(--accent-color);
.main_navbar__item--active .item__title {
transform: translateY(100%);
opacity: 0;
}
.bottom_nav__item--active .icon {
.main_navbar__item--active .icon {
transform: translateY(50%) scale(1.2);
fill: var(--accent-color);
}
.hide-on-mobile {
@ -1029,45 +1037,69 @@ sm-checkbox {
grid-template-columns: 1fr 90vw 1fr;
}
#home {
padding: 0 4vmax;
gap: 1rem;
}
.hide-on-desktop {
display: none;
}
.card {
border-radius: 0.5rem;
background-color: var(--foreground-color);
border: solid thin rgba(var(--text-color), 0.1);
}
}
@media screen and (min-width: 48rem) {
#home {
grid-template-rows: -webkit-min-content 1fr;
grid-template-rows: min-content 1fr;
grid-template-columns: 24rem minmax(0, 1fr);
}
#home.signed-in #orders_list,
#home.signed-in #market_orders_list {
height: 32vmin;
overflow-y: auto;
display: grid;
grid-template-columns: 12rem 1fr;
grid-template-rows: auto 1fr;
grid-template-areas: "header header" "nav .";
}
#orders_section {
grid-row: span 2;
#main_header {
grid-area: header;
}
#main_navbar {
grid-area: nav;
flex-direction: column;
height: 100%;
padding: 0 0.5rem;
}
.main_navbar__item {
padding: 1.5rem 1rem;
width: 100%;
flex: 0;
flex-direction: row;
border-radius: 0.5rem;
transition: background-color 0.3s;
}
.main_navbar__item .icon {
margin-bottom: 0;
margin-right: 0.5rem;
}
.main_navbar__item .item__title {
font-size: 0.9rem;
}
.main_navbar__item--active {
background-color: rgba(var(--text-color), 0.06);
}
#exchange {
display: grid;
grid-template-columns: 16rem 1fr;
}
.listed-asset--active {
opacity: 1;
background-color: rgba(var(--text-color), 0.06);
}
.listed-asset--active::before {
content: "";
position: absolute;
width: 0.25rem;
border-radius: 0 0.2rem 0.2rem 0;
height: 50%;
background-color: var(--accent-color);
}
}
@media screen and (min-width: 72rem) {
.page-layout {
grid-template-columns: 1fr 80vw 1fr;
}
#home.signed-in {
grid-template-columns: 24rem minmax(0, 1fr) 20rem;
}
}
@media screen and (min-width: 120rem) {
.page-layout {
@ -1088,15 +1120,6 @@ sm-checkbox {
background: rgba(var(--text-color), 0.5);
}
.interact,
button {
transition: background-color 0.3s, transform 0.3s;
}
.interact:hover,
button:hover {
background-color: var(--accent-color--light);
}
.order-card .cancel-order {
justify-self: flex-end;
overflow: hidden;

File diff suppressed because one or more lines are too long

View File

@ -16,40 +16,28 @@ body {
}
body {
&,
* {
--accent-color: #504dff;
--accent-color--light: #eeeeff;
--text-color: 36, 36, 36;
--background-color: 255, 255, 255;
--foreground-color: rgb(250, 252, 255);
--danger-color: rgb(255, 75, 75);
--green: #1cad59;
--yellow: #f3a600;
--loan-color: rgb(255, 171, 93);
scrollbar-width: thin;
}
--accent-color: #504dff;
--text-color: 20, 20, 20;
--background-color: 240, 240, 240;
--foreground-color: 250, 250, 250;
--danger-color: rgb(255, 75, 75);
--green: #1cad59;
scrollbar-width: thin;
scrollbar-gutter: stable;
color: rgba(var(--text-color), 1);
background: rgba(var(--background-color), 1);
background-color: rgba(var(--background-color), 1);
transition: background-color 0.3s;
}
body[data-theme="dark"] {
&,
* {
--accent-color: #a3a1ff;
--accent-color--light: rgba(142, 140, 255, 0.06);
--text-color: 230, 230, 230;
--text-color-light: 170, 170, 170;
--background-color: 10, 10, 10;
--foreground-color: rgb(24, 24, 24);
--danger-color: rgb(255, 106, 106);
--green: #00e676;
--yellow: #ffd13a;
--loan-color: rgb(255, 232, 170);
}
--accent-color: #a3a1ff;
--text-color: 220, 220, 220;
--background-color: 10, 10, 10;
--foreground-color: 24, 24, 24;
--danger-color: rgb(255, 106, 106);
--green: #00e676;
sm-popup::part(popup) {
background-color: var(--foreground-color);
background-color: rgba(var(--foreground-color), 1);
}
}
@ -119,7 +107,6 @@ a:any-link:focus-visible {
sm-input {
font-size: 0.9rem;
--border-radius: 0.3rem;
--background: var(--accent-color--light);
}
sm-button {
text-transform: uppercase;
@ -143,6 +130,9 @@ sm-button {
color: rgba(var(--background-color), 1);
}
}
sm-form {
--gap: 1rem;
}
ul {
list-style: none;
}
@ -160,7 +150,7 @@ ul {
pointer-events: none;
}
.hide-completely {
.hide {
display: none !important;
}
@ -308,10 +298,23 @@ ul {
.interact {
position: relative;
overflow: hidden;
cursor: pointer;
transition: transform 0.3s;
-webkit-tap-highlight-color: transparent;
}
.ripple {
height: 8rem;
width: 8rem;
position: absolute;
border-radius: 50%;
transform: scale(0);
background: radial-gradient(
circle,
rgba(var(--text-color), 0.3) 0%,
rgba(0, 0, 0, 0) 50%
);
pointer-events: none;
}
.empty-state {
display: grid;
justify-content: center;
@ -330,15 +333,12 @@ ul {
}
.icon {
width: 1.5rem;
height: 1.5rem;
width: 1.2rem;
height: 1.2rem;
fill: rgba(var(--text-color), 0.8);
}
.button__icon {
height: 1.2rem;
width: 1.2rem;
&--left {
margin-right: 0.5rem;
}
@ -379,13 +379,6 @@ ul {
#prompt_message {
margin-bottom: 1.5rem;
}
button:active,
.button:active,
.interact:active {
transform: scale(0.96);
}
.popup__header {
display: grid;
gap: 0.5rem;
@ -487,6 +480,9 @@ sm-checkbox {
.page {
height: 100%;
}
.mobile-page {
align-items: flex-start;
}
#landing {
grid-template-rows: auto 1fr;
header {
@ -527,42 +523,94 @@ sm-checkbox {
}
#home {
height: 100%;
display: grid;
display: flex;
flex-direction: column;
align-items: flex-start;
align-content: flex-start;
grid-template-columns: minmax(0, 1fr);
}
#login_form__priv_key {
margin-top: 1rem;
}
#main_header {
margin-top: 1.5rem;
margin-bottom: 1rem;
display: grid;
gap: 1rem;
padding: 1.5rem;
width: 100%;
align-items: center;
grid-template-columns: 1fr auto auto;
grid-column: 1/-1;
}
#main_navbar {
width: 100%;
}
.main_navbar__item {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
padding: 0.5rem 0;
.item__title,
.icon {
transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275),
opacity 0.3s;
}
.item__title {
color: rgba(var(--text-color), 0.8);
font-size: 0.8rem;
font-weight: 500;
}
.icon {
height: 1.2rem;
margin-bottom: 0.3rem;
}
&--active {
.item__title {
color: var(--accent-color);
}
.icon {
fill: var(--accent-color);
}
}
}
#pages_container {
display: flex;
flex: 1;
width: 100%;
justify-content: center;
overflow-y: auto;
padding: 0 1.5rem;
& > * {
width: min(42rem, 100%);
}
}
#flo_exchange_rate {
#exchange {
display: grid;
gap: 1.5rem;
}
.listed-asset {
position: relative;
grid-template-columns: auto 1fr auto;
gap: 0.5rem;
padding: 1rem;
border-radius: 0.5rem;
border: solid rgba(var(--text-color), 0.2) thin;
background-color: rgba(var(--background-color), 1);
opacity: 0.8;
font-weight: 400;
transition: background-color 0.3s;
user-select: none;
color: inherit;
&__icon {
display: flex;
.icon {
height: 1.5rem;
width: 1.5rem;
}
}
}
#flo_rate {
font-weight: 700;
}
#trade_form,
#login_form {
align-self: flex-start;
padding: 1rem 1.5rem 1.5rem 1.5rem;
}
.quantity-selector {
.button {
flex: 1;
@ -581,20 +629,15 @@ sm-checkbox {
font-weight: 500;
min-width: 8ch;
}
#my_orders_section,
#market_orders_section {
padding-top: 1rem;
#my_orders,
#market {
width: min(42rem, 100%);
grid-template-rows: auto 1fr;
.icon {
height: 1.2rem;
width: 1.2rem;
}
}
.orders_section__header {
padding: 0 1.5rem;
}
#my_orders_section__header {
height: 2.4rem;
}
#orders_section__header--primary {
sm-tab-header {
--gap: 1.5rem;
@ -606,7 +649,7 @@ sm-checkbox {
}
.list__item {
padding: 0.5rem 1.5rem;
padding: 0.5rem 0;
display: grid;
}
.order-card {
@ -697,13 +740,11 @@ sm-checkbox {
}
.list__header {
margin-bottom: 0.5rem;
padding: 0 1.5rem;
grid-template-columns: repeat(3, 1fr) 2rem;
}
}
#user_section {
#wallet {
gap: 1.5rem;
padding: 1.5rem;
align-content: flex-start;
}
.wallet_actions__wrapper {
@ -879,52 +920,16 @@ sm-checkbox {
}
}
@media screen and (max-width: 40rem) {
#main_header {
padding: 0 1.5rem;
}
sm-button {
--padding: 0.9rem 1.6rem;
}
#home {
& > :last-child {
padding-bottom: 5rem;
}
}
#bottom_nav {
position: fixed;
bottom: 0;
background-color: var(--foreground-color);
width: 100%;
}
.bottom_nav__item {
display: flex;
flex-direction: column;
align-items: center;
flex: 1;
padding: 0.5rem 0;
.item__title,
.icon {
transition: 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.main_navbar__item--active {
.item__title {
color: rgba(var(--text-color), 0.8);
font-size: 0.8rem;
font-weight: 500;
transform: translateY(100%);
opacity: 0;
}
.icon {
height: 1.2rem;
margin-bottom: 0.3rem;
}
&--active {
.item__title {
color: var(--accent-color);
transform: translateY(100%);
opacity: 0;
}
.icon {
transform: translateY(50%) scale(1.2);
fill: var(--accent-color);
}
transform: translateY(50%) scale(1.2);
}
}
.hide-on-mobile {
@ -959,33 +964,59 @@ sm-checkbox {
.page-layout {
grid-template-columns: 1fr 90vw 1fr;
}
#home {
padding: 0 4vmax;
gap: 1rem;
}
.hide-on-desktop {
display: none;
}
.card {
border-radius: 0.5rem;
background-color: var(--foreground-color);
border: solid thin rgba(var(--text-color), 0.1);
}
}
@media screen and (min-width: 48rem) {
#home {
grid-template-rows: min-content 1fr;
grid-template-columns: 24rem minmax(0, 1fr);
&.signed-in {
#orders_list,
#market_orders_list {
height: 32vmin;
overflow-y: auto;
}
display: grid;
grid-template-columns: 12rem 1fr;
grid-template-rows: auto 1fr;
grid-template-areas: "header header" "nav .";
}
#main_header {
grid-area: header;
}
#main_navbar {
grid-area: nav;
flex-direction: column;
height: 100%;
padding: 0 0.5rem;
}
.main_navbar__item {
padding: 1.5rem 1rem;
width: 100%;
flex: 0;
flex-direction: row;
border-radius: 0.5rem;
transition: background-color 0.3s;
.icon {
margin-bottom: 0;
margin-right: 0.5rem;
}
.item__title {
font-size: 0.9rem;
}
&--active {
background-color: rgba(var(--text-color), 0.06);
}
}
#orders_section {
grid-row: span 2;
#exchange {
display: grid;
grid-template-columns: 16rem 1fr;
}
.listed-asset {
&--active {
opacity: 1;
background-color: rgba(var(--text-color), 0.06);
&::before {
content: "";
position: absolute;
width: 0.25rem;
border-radius: 0 0.2rem 0.2rem 0;
height: 50%;
background-color: var(--accent-color);
}
}
}
}
@media screen and (max-width: 64rem) {
@ -994,9 +1025,6 @@ sm-checkbox {
.page-layout {
grid-template-columns: 1fr 80vw 1fr;
}
#home.signed-in {
grid-template-columns: 24rem minmax(0, 1fr) 20rem;
}
}
@media screen and (min-width: 120rem) {
.page-layout {
@ -1017,13 +1045,6 @@ sm-checkbox {
background: rgba(var(--text-color), 0.5);
}
}
.interact,
button {
transition: background-color 0.3s, transform 0.3s;
&:hover {
background-color: var(--accent-color--light);
}
}
.order-card {
.cancel-order {
justify-self: flex-end;

View File

@ -21,12 +21,8 @@
<script>console.debug(floExchangeAPI);</script>
</head>
<body class="hide-completely">
<body class="hide">
<sm-notifications id="notification_drawer"></sm-notifications>
<audio id="notification_sound">
<source src="https://rmservices.duckdns.org/files/notification-sound.mp3" type="audio/mpeg">
<source src="https://rmservices.duckdns.org/files/notification-sound.ogg" type="audio/ogg">
</audio>
<sm-popup id="confirmation_popup">
<h4 id="confirm_title"></h4>
<p id="confirm_message"></p>
@ -59,7 +55,7 @@
</div>
</div>
<theme-toggle></theme-toggle>
<button id="user_popup_button" class="hide-completely" onclick="showPopup('user_popup')">
<button id="user_popup_button" class="hide" onclick="showPopup('user_popup')">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" height="24px" viewBox="0 0 24 24" width="24px"
fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none" />
@ -68,71 +64,70 @@
</svg>
</button>
</header>
<section id="dashboard" class="card mobile-page">
<sm-form id="login_form" class="hide-">
<div class="grid gap-0-5">
<h4>Login</h4>
<p>Please login for trading and accessing your account.</p>
<section id="pages_container">
<section id="exchange" class="mobile-page">
<sm-form id="login_form">
<div class="grid gap-0-5">
<h4>Login</h4>
<p>Please login for exchange.</p>
</div>
<sm-input type="password" id="login_form__priv_key" placeholder="Private key" animate required>
</sm-input>
</sm-input>
<sm-checkbox id="remember_me" checked>
<span class="button__icon--right">
Remember me
</span>
</sm-checkbox>
<input type="text" id="sign_in_code" style="display: none;" hidden />
<input type="text" id="sign_in_hash" style="display: none;" hidden />
<div id="login_button_wrapper" class="stateful-button-wrapper">
<sm-button variant="primary" onclick="UI_evt.login();">Log in</sm-button>
</div>
<sm-button onclick="showPopup('registration_popup')" style="display: none;" disabled>Not registered?
click here!</sm-button>
<div class="grid gap-0-5">
<p>Don't have FLO credentials?</p>
<sm-button onclick="showPopup('sign_up_popup')">Generate FLO credentials</sm-button>
</div>
<sm-button onclick="floExchangeAPI.clearAllLocalData()">clear local data</sm-button>
</sm-form>
<div class="grid gap-1 align-start hide user-content">
<h4>Assets</h4>
<ul id="listed_assets" class="user-content hide"></ul>
</div>
<sm-input type="password" id="login_form__priv_key" placeholder="Private key" variant="outlined" animate
required hiderequired></sm-input>
<sm-checkbox id="remember_me" checked>
<span class="button__icon--right">
Remember me
</span>
</sm-checkbox>
<input type="text" id="sign_in_code" style="display: none;" hidden />
<input type="text" id="sign_in_hash" style="display: none;" hidden />
<div id="login_button_wrapper" class="stateful-button-wrapper">
<sm-button variant="primary" onclick="UI_evt.login();">Log in</sm-button>
</div>
<sm-button onclick="showPopup('registration_popup')" style="display: none;" disabled>Not registered? click here!</sm-button>
<div class="grid gap-0-5">
<p>Don't have FLO credentials?</p>
<sm-button onclick="showPopup('sign_up_popup')">Generate FLO credentials</sm-button>
</div>
<sm-button onclick="floExchangeAPI.clearAllLocalData()">clear local data</sm-button>
</sm-form>
<sm-form id="trade_form" class="user-content hide-completely">
<div id="flo_exchange_rate" class="grid align-center">
<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>
<p><b>FLO</b>/INR</p>
<span id="flo_rate"></span>
</div>
<div class="flex space-between align-center">
<h4>Trade FLO</h4>
<strip-select id="trade_type_selector" class="tab">
<strip-option value="buy" selected>Buy</strip-option>
<strip-option value="sell">Sell</strip-option>
</strip-select>
</div>
<sm-select id="get_asset"></sm-select>
<sm-input id="get_price" variant="outlined" placeholder="Max price (₹)" type="number" step="0.01"
required hiderequired animate>
</sm-input>
<sm-input id="get_quantity" variant="outlined" placeholder="Quantity (FLO)" type="number" step="0.0001"
required hiderequired animate></sm-input>
<sm-input id="get_total" variant="outlined" placeholder="Total (₹)" type="number" min="0.01" step="0.01"
required hiderequired animate>
</sm-input>
<div id="quantity_selector" class="flex align-center quantity-selector">
<span id="quantity_type">Rupee</span>
<button class="button" value="0.25">25%</button>
<button class="button" value="0.5">50%</button>
<button class="button" value="0.75">75%</button>
<button class="button" value="1">100%</button>
</div>
<div id="trade_button_wrapper" class="stateful-button-wrapper flex align-center justify-center">
<sm-button id="trade_button" class="uppercase w-100" variant="primary" onclick="tradeFlo()">BUY FLO
</sm-button>
</div>
</sm-form>
</section>
<section id="orders_section" class="grid gap-1">
<section id="my_orders_section" class="grid gap-1 card user-content mobile-page hide-on-mobile">
<sm-form id="trade_form" class="user-content hide hide-on-mobile">
<div class="flex space-between align-center">
<h4 id="traded_asset">Trade FLO</h4>
<strip-select id="trade_type_selector" class="tab">
<strip-option value="buy" selected>Buy</strip-option>
<strip-option value="sell">Sell</strip-option>
</strip-select>
</div>
<sm-input id="get_price" placeholder="Max price (₹)" type="number" step="0.01" required animate>
</sm-input>
<sm-input id="get_quantity" placeholder="Quantity" type="number" step="0.0001" required animate>
</sm-input>
</sm-input>
<sm-input id="get_total" placeholder="Total (₹)" type="number" min="0.01" step="0.01" required
animate>
</sm-input>
<div id="quantity_selector" class="flex align-center quantity-selector">
<span id="quantity_type">Rupee</span>
<button class="button" value="0.25" title="Buy FLO worth 25% of total rupee">25%</button>
<button class="button" value="0.5" title="Buy FLO worth 50% of total rupee">50%</button>
<button class="button" value="0.75" title="Buy FLO worth 75% of total rupee">75%</button>
<button class="button" value="1" title="Buy FLO worth 100% of total rupee">100%</button>
</div>
<div id="trade_button_wrapper" class="stateful-button-wrapper flex align-center justify-center">
<sm-button id="trade_button" class="uppercase w-100" variant="primary" onclick="tradeFlo()">
BUY
FLO
</sm-button>
</div>
</sm-form>
</section>
<section id="my_orders" class="grid gap-1 hide mobile-page">
<div id="my_orders_section__header" class="orders_section__header flex">
<div id="orders_section__header--primary" class="flex w-100 align-center space-between">
<h4>
@ -143,8 +138,7 @@
<strip-option value="completed">History</strip-option>
</strip-select>
</div>
<div id="orders_section__header--secondary"
class="flex w-100 align-center space-between hide-completely">
<div id="orders_section__header--secondary" class="flex w-100 align-center space-between hide">
<button class="" onclick="clearSelection()" title="Clear all selection">
<svg xmlns="http://www.w3.org/2000/svg" class="icon button__icon--left" height="24px"
viewBox="0 0 24 24" width="24px">
@ -166,7 +160,7 @@
No orders placed
</p>
</section>
<section id="market_orders_section" class="grid gap-1 card mobile-page hide-on-mobile">
<section id="market" class="grid gap-1 hide mobile-page">
<div class="orders_section__header flex align-center space-between">
<h4 class="flex align-center">
Market orders
@ -189,110 +183,109 @@
No orders placed
</p>
</section>
<section id="wallet" class="grid mobile-page hide">
<h4 class="flex align-center user_section__header">
<svg xmlns="http://www.w3.org/2000/svg" class="icon button__icon--left" height="24px"
viewBox="0 0 24 24" width="24px">
<path d="M0 0h24v24H0V0z" fill="none" />
<path
d="M21 7.28V5c0-1.1-.9-2-2-2H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-2.28c.59-.35 1-.98 1-1.72V9c0-.74-.41-1.37-1-1.72zM20 9v6h-7V9h7zM5 19V5h14v2h-6c-1.1 0-2 .9-2 2v6c0 1.1.9 2 2 2h6v2H5z" />
<circle cx="16" cy="12" r="1.5" />
</svg>
My wallet
</h4>
<div id="wallet_actions">
<p class="label">Select asset</p>
<sm-select id="wallet_asset_selector"></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="grid gap-1">
<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">
<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>
</div>
</section>
</section>
<section id="user_section" class="grid card user-content mobile-page hide-completely hide-on-mobile">
<h4 class="flex align-center user_section__header">
<svg xmlns="http://www.w3.org/2000/svg" class="icon button__icon--left" height="24px"
viewBox="0 0 24 24" width="24px">
<nav id="main_navbar" class="flex align-center">
<a href="#/exchange" class="main_navbar__item main_navbar__item--active interact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px"
viewBox="0 0 24 24" width="24px" fill="#000000">
<rect fill="none" height="24" width="24" />
<path
d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M5,19V5h6v14H5z M19,19h-6v-7h6V19z M19,10h-6V5h6V10z" />
</svg>
<div class="item__title">Exchange</div>
</a>
<a href="#/my_orders" class="main_navbar__item user-content hide interact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px"
viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0,0h24v24H0V0z" fill="none" />
<g>
<path
d="M19.5,3.5L18,2l-1.5,1.5L15,2l-1.5,1.5L12,2l-1.5,1.5L9,2L7.5,3.5L6,2v14H3v3c0,1.66,1.34,3,3,3h12c1.66,0,3-1.34,3-3V2 L19.5,3.5z M15,20H6c-0.55,0-1-0.45-1-1v-1h10V20z M19,19c0,0.55-0.45,1-1,1s-1-0.45-1-1v-3H8V5h11V19z" />
<rect height="2" width="6" x="9" y="7" />
<rect height="2" width="2" x="16" y="7" />
<rect height="2" width="6" x="9" y="10" />
<rect height="2" width="2" x="16" y="10" />
</g>
</svg>
<div class="item__title">My orders</div>
</a>
<a href="#/market" class="main_navbar__item interact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px"
viewBox="0 0 24 24" width="24px" fill="#000000">
<g>
<rect fill="none" height="24" width="24" />
</g>
<g>
<g />
<g>
<path
d="M21.9,8.89l-1.05-4.37c-0.22-0.9-1-1.52-1.91-1.52H5.05C4.15,3,3.36,3.63,3.15,4.52L2.1,8.89 c-0.24,1.02-0.02,2.06,0.62,2.88C2.8,11.88,2.91,11.96,3,12.06V19c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2v-6.94 c0.09-0.09,0.2-0.18,0.28-0.28C21.92,10.96,22.15,9.91,21.9,8.89z M18.91,4.99l1.05,4.37c0.1,0.42,0.01,0.84-0.25,1.17 C19.57,10.71,19.27,11,18.77,11c-0.61,0-1.14-0.49-1.21-1.14L16.98,5L18.91,4.99z M13,5h1.96l0.54,4.52 c0.05,0.39-0.07,0.78-0.33,1.07C14.95,10.85,14.63,11,14.22,11C13.55,11,13,10.41,13,9.69V5z M8.49,9.52L9.04,5H11v4.69 C11,10.41,10.45,11,9.71,11c-0.34,0-0.65-0.15-0.89-0.41C8.57,10.3,8.45,9.91,8.49,9.52z M4.04,9.36L5.05,5h1.97L6.44,9.86 C6.36,10.51,5.84,11,5.23,11c-0.49,0-0.8-0.29-0.93-0.47C4.03,10.21,3.94,9.78,4.04,9.36z M5,19v-6.03C5.08,12.98,5.15,13,5.23,13 c0.87,0,1.66-0.36,2.24-0.95c0.6,0.6,1.4,0.95,2.31,0.95c0.87,0,1.65-0.36,2.23-0.93c0.59,0.57,1.39,0.93,2.29,0.93 c0.84,0,1.64-0.35,2.24-0.95c0.58,0.59,1.37,0.95,2.24,0.95c0.08,0,0.15-0.02,0.23-0.03V19H5z" />
</g>
</g>
</svg>
<div class="item__title">Market</div>
</a>
<a href="#/wallet" class="main_navbar__item user-content hide interact">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none" />
<path
d="M21 7.28V5c0-1.1-.9-2-2-2H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-2.28c.59-.35 1-.98 1-1.72V9c0-.74-.41-1.37-1-1.72zM20 9v6h-7V9h7zM5 19V5h14v2h-6c-1.1 0-2 .9-2 2v6c0 1.1.9 2 2 2h6v2H5z" />
<circle cx="16" cy="12" r="1.5" />
</svg>
My wallet
</h4>
<div id="wallet_actions">
<p class="label">Select asset</p>
<sm-select id="wallet_asset_selector">
</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="grid gap-1">
<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">
<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>
</div>
</section>
<div class="item__title">Wallet</div>
</a>
</nav>
</article>
<footer id="bottom_nav" class="flex align-center hide-on-desktop">
<a href="#/dashboard" class="bottom_nav__item bottom_nav__item--active">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px"
viewBox="0 0 24 24" width="24px" fill="#000000">
<rect fill="none" height="24" width="24" />
<path
d="M19,3H5C3.9,3,3,3.9,3,5v14c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5C21,3.9,20.1,3,19,3z M5,19V5h6v14H5z M19,19h-6v-7h6V19z M19,10h-6V5h6V10z" />
</svg>
<div class="item__title">Dashboard</div>
</a>
<a href="#/my_orders" class="bottom_nav__item user-content hide-completely">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px"
viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0,0h24v24H0V0z" fill="none" />
<g>
<path
d="M19.5,3.5L18,2l-1.5,1.5L15,2l-1.5,1.5L12,2l-1.5,1.5L9,2L7.5,3.5L6,2v14H3v3c0,1.66,1.34,3,3,3h12c1.66,0,3-1.34,3-3V2 L19.5,3.5z M15,20H6c-0.55,0-1-0.45-1-1v-1h10V20z M19,19c0,0.55-0.45,1-1,1s-1-0.45-1-1v-3H8V5h11V19z" />
<rect height="2" width="6" x="9" y="7" />
<rect height="2" width="2" x="16" y="7" />
<rect height="2" width="6" x="9" y="10" />
<rect height="2" width="2" x="16" y="10" />
</g>
</svg>
<div class="item__title">My orders</div>
</a>
<a href="#/market" class="bottom_nav__item">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px"
viewBox="0 0 24 24" width="24px" fill="#000000">
<g>
<rect fill="none" height="24" width="24" />
</g>
<g>
<g />
<g>
<path
d="M21.9,8.89l-1.05-4.37c-0.22-0.9-1-1.52-1.91-1.52H5.05C4.15,3,3.36,3.63,3.15,4.52L2.1,8.89 c-0.24,1.02-0.02,2.06,0.62,2.88C2.8,11.88,2.91,11.96,3,12.06V19c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2v-6.94 c0.09-0.09,0.2-0.18,0.28-0.28C21.92,10.96,22.15,9.91,21.9,8.89z M18.91,4.99l1.05,4.37c0.1,0.42,0.01,0.84-0.25,1.17 C19.57,10.71,19.27,11,18.77,11c-0.61,0-1.14-0.49-1.21-1.14L16.98,5L18.91,4.99z M13,5h1.96l0.54,4.52 c0.05,0.39-0.07,0.78-0.33,1.07C14.95,10.85,14.63,11,14.22,11C13.55,11,13,10.41,13,9.69V5z M8.49,9.52L9.04,5H11v4.69 C11,10.41,10.45,11,9.71,11c-0.34,0-0.65-0.15-0.89-0.41C8.57,10.3,8.45,9.91,8.49,9.52z M4.04,9.36L5.05,5h1.97L6.44,9.86 C6.36,10.51,5.84,11,5.23,11c-0.49,0-0.8-0.29-0.93-0.47C4.03,10.21,3.94,9.78,4.04,9.36z M5,19v-6.03C5.08,12.98,5.15,13,5.23,13 c0.87,0,1.66-0.36,2.24-0.95c0.6,0.6,1.4,0.95,2.31,0.95c0.87,0,1.65-0.36,2.23-0.93c0.59,0.57,1.39,0.93,2.29,0.93 c0.84,0,1.64-0.35,2.24-0.95c0.58,0.59,1.37,0.95,2.24,0.95c0.08,0,0.15-0.02,0.23-0.03V19H5z" />
</g>
</g>
</svg>
<div class="item__title">Market</div>
</a>
<a href="#/wallet" class="bottom_nav__item user-content hide-completely">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
fill="#000000">
<path d="M0 0h24v24H0V0z" fill="none" />
<path
d="M21 7.28V5c0-1.1-.9-2-2-2H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-2.28c.59-.35 1-.98 1-1.72V9c0-.74-.41-1.37-1-1.72zM20 9v6h-7V9h7zM5 19V5h14v2h-6c-1.1 0-2 .9-2 2v6c0 1.1.9 2 2 2h6v2H5z" />
<circle cx="16" cy="12" r="1.5" />
</svg>
<div class="item__title">Wallet</div>
</a>
</footer>
<sm-popup id="user_popup">
<header slot="header" class="popup__header">
<button class="popup__header__close" onclick="hidePopup()">
@ -336,8 +329,8 @@
<div class="grid gap-1-5">
<sm-form id="register_section">
<p>Enter the private key of FLO ID you want to register.</p>
<sm-input id="get_registration_key" variant="outlined" placeholder="Private key" type="password"
required hiderequired></sm-input>
<sm-input id="get_registration_key" placeholder="Private key" type="password" required>
</sm-input>
<sm-button variant="primary" onclick="UI_evt.signup()" disabled>Register</sm-button>
</sm-form>
</div>
@ -364,7 +357,8 @@
<sm-copy id="generated_private_key"></sm-copy>
</div>
</div>
<sm-button id="sign_up_button" variant="primary" onclick="registerID()" style="display: none;" disabled>Register these credentials
<sm-button id="sign_up_button" variant="primary" onclick="registerID()" style="display: none;" disabled>
Register these credentials
</sm-button>
<strong class="warning">
Keep your private key secure and don't share with anyone.
@ -385,8 +379,8 @@
</header>
<sm-form id="wallet_form">
<input type="text" id="sink_id" style="display: none;" hidden />
<sm-input id="get_user_amount" variant="outlined" placeholder="Quantity" type="number" min="0.01"
step="0.00001" required hiderequired animate>
<sm-input id="get_user_amount" placeholder="Quantity" type="number" min="0.01" step="0.00001" required
animate>
</sm-input>
<div id="wallet_quantity_selector" class="flex align-center quantity-selector">
<span id="wallet_quantity_type">Rupee</span>
@ -395,14 +389,14 @@
<button class="button" value="0.75">75%</button>
<button class="button" value="1">100%</button>
</div>
<sm-input id="get_private_key" variant="outlined" placeholder="FLO private key" type="password" required
error-text="Invalid private key" hiderequired animate>
<sm-input id="get_private_key" placeholder="FLO private key" type="password" required
error-text="Invalid private key" animate>
</sm-input>
<div id="wallet_popup__cta_wrapper" class="stateful-button-wrapper">
<sm-button id="wallet_popup__cta" class="uppercase" variant="primary"></sm-button>
</div>
</sm-form>
<div id="wallet_result" class="grid gap-2 hide-completely">
<div id="wallet_result" class="grid gap-2 hide">
<div id="wallet_result__icon"></div>
<div class="grid gap-0-5">
<h4 id="wallet_result__title"></h4>
@ -437,6 +431,18 @@
</div>
</div>
</sm-popup>
<!-- templates -->
<template id="listed_asset_template">
<li>
<a class="listed-asset interact grid align-center">
<div class="listed-asset__icon"></div>
<h4 class="listed-asset__name"></h4>
<strong class="listed-asset__rate"></strong>
</a>
</li>
</template>
<template id="net_balance_template">
<span class="available-balance"></span>
</template>
@ -724,10 +730,6 @@
break;
}
getRef("notification_drawer").push(message, { pinned, icon });
if (navigator.onLine && sound) {
getRef("notification_sound").currentTime = 0;
getRef("notification_sound").play();
}
if (mode === 'error') {
console.error(message)
}
@ -784,8 +786,7 @@
window.addEventListener('hashchange', e => showPage(window.location.hash))
window.addEventListener("load", () => {
showPage(window.location.hash)
document.body.classList.remove('hide-completely')
document.body.classList.remove('hide')
document.querySelectorAll('sm-input[data-private-key]').forEach(input => input.customValidation = floCrypto.getPubKeyHex)
document.addEventListener('keyup', (e) => {
if (e.key === 'Escape') {
@ -795,17 +796,51 @@
document.addEventListener('copy', () => {
notify('copied', 'success')
})
document.addEventListener("pointerdown", (e) => {
if (e.target.closest("button:not([disabled]), sm-button:not([disabled]), .interact")) {
createRipple(e, e.target.closest("button, sm-button, .interact"));
}
});
});
function createRipple(event, target) {
const circle = document.createElement("span");
const diameter = Math.max(target.clientWidth, target.clientHeight);
const radius = diameter / 2;
const targetDimensions = target.getBoundingClientRect();
circle.style.width = circle.style.height = `${diameter}px`;
circle.style.left = `${event.clientX - (targetDimensions.left + radius)}px`;
circle.style.top = `${event.clientY - (targetDimensions.top + radius)}px`;
circle.classList.add("ripple");
const rippleAnimation = circle.animate(
[
{
transform: "scale(4)",
opacity: 0,
},
],
{
duration: 600,
fill: "forwards",
easing: "ease-out",
}
);
target.append(circle);
rippleAnimation.onfinish = () => {
circle.remove();
};
}
const pagesData = {
openedPages: [],
lastPage: '',
params: {}
}
async function showPage(targetPage, options = {}) {
const { firstLoad, hashChange } = options
let pageId
let params
let subPageId
let params = {}
let searchParams
if (targetPage === '') {
if (typeof proxy.userID === "undefined") {
pageId = 'landing'
@ -814,53 +849,72 @@
}
} else {
if (targetPage.includes('/')) {
const pages = targetPage.split('/')
pageId = pages[1]
if (targetPage.includes('?')) {
const splitAddress = targetPage.split('?')
searchParams = splitAddress.pop()
const pages = splitAddress.pop().split('/')
pageId = pages[1]
subPageId = pages[2]
} else {
const pages = targetPage.split('/')
pageId = pages[1]
subPageId = pages[2]
}
} else {
pageId = targetPage
}
}
if (pagesData.lastPage !== pageId) {
let target
switch (pageId) {
case 'dashboard':
target = 'dashboard'
break;
case 'my_orders':
target = 'my_orders_section'
break;
case 'market':
target = 'market_orders_section'
break;
case 'wallet':
target = 'user_section'
break;
}
if (target) {
document.querySelectorAll('.mobile-page').forEach(elem => elem.classList.add('hide-on-mobile'))
getRef(target).classList.remove('hide-on-mobile')
document.querySelectorAll('.bottom_nav__item').forEach(elem => elem.classList.remove('bottom_nav__item--active'))
document.querySelector(`.bottom_nav__item[href="#/${pageId}"]`).classList.add('bottom_nav__item--active')
getRef(target)?.animate([
{
transform: 'translateY(1rem)',
opacity: 0,
},
{
transform: 'none',
opacity: 1,
},
],
{
duration: 300,
easing: 'ease'
})
pagesData.lastPage = target
if (!pagesData.openedPages.includes(target)) {
pagesData.openedPages.push(target)
}
}
if (searchParams) {
const urlSearchParams = new URLSearchParams('?' + searchParams);
params = Object.fromEntries(urlSearchParams.entries());
}
switch (pageId) {
case 'exchange':
if (!params.hasOwnProperty('asset') || params.asset === '') {
params.asset = 'FLO'
}
if (getRef('listed_assets').querySelector('.listed-asset--active'))
getRef('listed_assets').querySelector('.listed-asset--active').classList.remove('listed-asset--active')
getRef('listed_assets').querySelector(`[href="#/exchange?asset=${params.asset}"]`).classList.add('listed-asset--active')
getRef('get_price').value = parseFloat(floGlobals.exchangeRates[params.asset].toFixed(2))
getRef('traded_asset').textContent = `Trade ${params.asset}`
getRef('trade_button').textContent = `${tradeType} ${params.asset}`
getRef('quantity_type').textContent = tradeType === 'buy' ? formatAmount(allTokens.rupee.net) : `${parseFloat(allTokens[params.asset].net.toFixed(3))} ${params.asset}`
getRef('quantity_selector').querySelectorAll('.button').forEach(button => {
if (tradeType === 'buy') {
button.title = `Buy ${params.asset} worth ${button.textContent} of total rupee`
} else {
button.title = `Sell ${button.textContent} of total ${params.asset}`
}
})
break;
case 'my_orders':
break;
case 'market':
break;
case 'wallet':
break;
}
if (pagesData.lastPage !== pageId) {
document.querySelectorAll('.mobile-page').forEach(elem => elem.classList.add('hide'))
getRef(pageId).classList.remove('hide')
document.querySelectorAll('.main_navbar__item').forEach(elem => elem.classList.remove('main_navbar__item--active'))
document.querySelector(`.main_navbar__item[href="#/${pageId}"]`).classList.add('main_navbar__item--active')
getRef(pageId)?.animate([
{
opacity: 0,
},
{
opacity: 1,
},
],
{
duration: 150,
easing: 'ease'
})
pagesData.lastPage = pageId
}
pagesData.params = params
}
// class based lazy loading
class LazyLoader {
@ -939,10 +993,27 @@
}
</script>
<script>
const listedAssets = {
FLO: {
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>`
},
}
function formatAmount(amount) {
return amount.toLocaleString(`en-IN`, { style: 'currency', currency: 'INR' })
}
const render = {
listedAsset(name, rate) {
const clone = getRef('listed_asset_template').content.cloneNode(true).firstElementChild.firstElementChild
clone.href = `#/exchange?asset=${name}`
clone.querySelector('.listed-asset__icon').innerHTML = listedAssets[name] ? listedAssets[name].icon : ''
clone.querySelector('.listed-asset__rate').textContent = rate
clone.querySelector('.listed-asset__name').textContent = name
return clone
},
orderCard(orderDetails = {}) {
const { id, asset, quantity, price, time, type } = orderDetails
const card = getRef('order_template').content.cloneNode(true).firstElementChild
@ -1010,12 +1081,21 @@
let tradeType = 'buy'
getRef('trade_type_selector').addEventListener('change', e => {
tradeType = e.detail.value
const selectedAsset = pagesData.params.asset
getRef('get_price').setAttribute('placeholder', tradeType === 'buy' ? 'Max price' : 'Min price')
getRef('trade_button').textContent = `${tradeType} FLO`
getRef('quantity_type').textContent = tradeType === 'buy' ? `Rupee` : `FLO`
getRef('trade_button').textContent = `${tradeType} ${selectedAsset}`
getRef('quantity_type').textContent = tradeType === 'buy' ? formatAmount(allTokens.rupee.net) : `${parseFloat(allTokens[selectedAsset].net.toFixed(3))} ${selectedAsset}`
getRef('quantity_selector').querySelectorAll('.button').forEach(button => {
if (tradeType === 'buy') {
button.title = `Buy ${selectedAsset} worth ${button.textContent} of total rupee`
} else {
button.title = `Sell ${button.textContent} of total ${selectedAsset}`
}
})
})
async function tradeFlo() {
const asset = getRef('get_asset').value;
const asset = pagesData.params.asset;
const quantity = parseFloat(getRef('get_quantity').value)
const price = parseFloat(getRef('get_price').value)
showProcess('trade_button_wrapper')
@ -1052,18 +1132,19 @@
const target = e.target.closest('button')
const unitValue = parseFloat(getRef('get_price').value)
const fraction = parseFloat(target.value)
const selectedAsset = pagesData.params.asset
if (tradeType === 'buy') {
getRef('get_total').value = parseFloat((fraction * balance.rupee).toFixed(2))
getRef('get_quantity').value = parseFloat(((balance.rupee * fraction) / unitValue).toFixed(4))
console.log(parseFloat((fraction * allTokens['rupee'].net).toFixed(2)), parseFloat(((allTokens['rupee'].net * fraction) / unitValue).toFixed(4)))
getRef('get_total').value = parseFloat((fraction * allTokens['rupee'].net).toFixed(2))
getRef('get_quantity').value = parseFloat(((allTokens['rupee'].net * fraction) / unitValue).toFixed(4))
} else {
console.log(fraction, balance.flo, floExchangeRate)
getRef('get_total').value = parseFloat((fraction * balance.flo * floExchangeRate).toFixed(2))
getRef('get_quantity').value = parseFloat((balance.flo * fraction).toFixed(4))
getRef('get_total').value = parseFloat((fraction * allTokens[selectedAsset].net * floGlobals.exchangeRates[selectedAsset]).toFixed(2))
getRef('get_quantity').value = parseFloat((allTokens[selectedAsset].net * fraction).toFixed(4))
}
}
})
getRef('get_price').addEventListener('keyup', e => {
const unitValue = parseFloat(getRef('get_price').value) || floExchangeRate
const unitValue = parseFloat(getRef('get_price').value) || floGlobals.exchangeRates[pagesData.params.asset]
const quantity = parseFloat(getRef('get_quantity').value) || 0
getRef('get_total').value = parseFloat((quantity * unitValue).toFixed(2)) || 0
})
@ -1089,16 +1170,14 @@
getRef('get_user_amount').setAttribute('step', asset === 'FLO' ? '0.0001' : '0.01')
getRef('get_user_amount').setAttribute('min', asset === 'FLO' ? '0.0001' : '0.01')
if (type === 'withdraw') {
getRef('get_private_key').classList.add('hide-completely')
getRef('wallet_quantity_selector').classList.remove('hide-completely')
getRef('get_private_key').classList.add('hide')
getRef('wallet_quantity_selector').classList.remove('hide')
getRef('get_private_key').removeAttribute('required')
getRef('get_private_key').removeAttribute('hiderequired')
} else {
getRef('get_private_key').setAttribute('required', '')
getRef('wallet_quantity_selector').classList.add('hide-completely')
getRef('get_private_key').setAttribute('hiderequired', '')
getRef('get_private_key').classList.remove('hide-completely')
getRef('wallet_quantity_selector').classList.add('hide')
getRef('get_private_key').classList.remove('hide')
}
getRef('wallet_form').elementsChanged()
}
@ -1128,8 +1207,8 @@
getRef('wallet_result__description').textContent = description
getRef('wallet_form').animate(slideOutLeft, animOptions)
.onfinish = () => {
getRef('wallet_form').classList.add('hide-completely')
getRef('wallet_result').classList.remove('hide-completely')
getRef('wallet_form').classList.add('hide')
getRef('wallet_result').classList.remove('hide')
getRef('wallet_result').animate(slideInLeft, animOptions)
}
}
@ -1141,8 +1220,8 @@
}
getRef('wallet_result').animate(slideOutRight, animOptions)
.onfinish = () => {
getRef('wallet_result').classList.add('hide-completely')
getRef('wallet_form').classList.remove('hide-completely')
getRef('wallet_result').classList.add('hide')
getRef('wallet_form').classList.remove('hide')
getRef('wallet_form').animate(slideInRight, animOptions)
}
}
@ -1150,9 +1229,9 @@
// Get latest balance and exchange rate
if (e.target.closest('button')) {
const target = e.target.closest('button')
const asset = getRef('wallet_asset_selector').value.toLowerCase()
const asset = getRef('wallet_asset_selector').value
const fraction = parseFloat(target.value)
getRef('get_user_amount').value = parseFloat((balance[asset] * fraction).toFixed(asset === "flo" ? 4 : 2))
getRef('get_user_amount').value = parseFloat((allTokens[asset].net * fraction).toFixed(asset === "rupee" ? 2 : 4))
}
})
getRef('wallet_popup__cta').addEventListener('click', async e => {
@ -1263,14 +1342,14 @@
selectedOrders.delete(target.dataset.id)
}
getRef('selected_orders').textContent = `${selectedOrders.size} selected`
if (selectedOrders.size === 1 && !getRef('my_orders_section__header').children[0].classList.contains('hide-completely')) {
if (selectedOrders.size === 1 && !getRef('my_orders_section__header').children[0].classList.contains('hide')) {
getRef('my_orders_section__header').children[0].animate(slideOutLeft, animOptions)
.onfinish = () => {
getRef('my_orders_section__header').children[0].classList.add('hide-completely')
getRef('my_orders_section__header').children[1].classList.remove('hide-completely')
getRef('my_orders_section__header').children[0].classList.add('hide')
getRef('my_orders_section__header').children[1].classList.remove('hide')
getRef('my_orders_section__header').children[1].animate(slideInLeft, animOptions)
}
} else if (selectedOrders.size === 0 && getRef('my_orders_section__header').children[0].classList.contains('hide-completely')) {
} else if (selectedOrders.size === 0 && getRef('my_orders_section__header').children[0].classList.contains('hide')) {
hideMyOrdersOptions()
}
})
@ -1282,8 +1361,8 @@
}
getRef('my_orders_section__header').children[1].animate(slideOutRight, animOptions)
.onfinish = () => {
getRef('my_orders_section__header').children[1].classList.add('hide-completely')
getRef('my_orders_section__header').children[0].classList.remove('hide-completely')
getRef('my_orders_section__header').children[1].classList.add('hide')
getRef('my_orders_section__header').children[0].classList.remove('hide')
getRef('my_orders_section__header').children[0].animate(slideInRight, animOptions)
}
}
@ -1295,16 +1374,16 @@
const target = e.target.closest('.more-info')
showPopup('transaction_info_popup')
if (target.dataset.buyer !== 'undefined') {
getRef('transaction__buyer_wrapper').classList.remove('hide-completely')
getRef('transaction__buyer_wrapper').classList.remove('hide')
getRef('transaction__buyer').value = target.dataset.buyer
} else {
getRef('transaction__buyer_wrapper').classList.add('hide-completely')
getRef('transaction__buyer_wrapper').classList.add('hide')
}
if (target.dataset.seller !== 'undefined') {
getRef('transaction__seller_wrapper').classList.remove('hide-completely')
getRef('transaction__seller_wrapper').classList.remove('hide')
getRef('transaction__seller').value = target.dataset.seller
} else {
getRef('transaction__seller_wrapper').classList.add('hide-completely')
getRef('transaction__seller_wrapper').classList.add('hide')
}
getRef('transaction_time__label').textContent = target.dataset.pending === 'true' ? 'Placed on' : 'Completed on'
getRef('transaction_time').textContent = getFormattedTime(target.dataset.time)
@ -1601,30 +1680,33 @@
})
}
}
let floExchangeRate = 0
function updateRate(init = false) {
floExchangeAPI.getRates().then(rates => {
console.debug(rates);
if (init) {
let assetList = getRef('get_asset');
let walletList = getRef('wallet_asset_selector');
let c = document.createElement('sm-option');
c.setAttribute('value', floGlobals.currency);
c.innerText = floGlobals.currency;
walletList.appendChild(c);
for (let asset in rates) {
let e = document.createElement('sm-option');
e.setAttribute('value', asset);
e.innerText = asset;
assetList.appendChild(e);
walletList.appendChild(e.cloneNode(true));
}
floGlobals.exchangeRates = rates
getRef('wallet_asset_selector').append(
createElement('sm-option', {
textContent: floGlobals.currency,
attributes: { value: floGlobals.currency },
})
);
Object.entries(rates).sort((a, b) => a[1] < b[1] ? 1 : -1).forEach(([asset, rate]) => {
if (!allTokens.hasOwnProperty(asset)) {
allTokens[asset] = {
total: 0,
locked: 0,
net: 0
}
}
getRef('listed_assets').append(render.listedAsset(asset, formatAmount(parseFloat(rate))));
getRef('wallet_asset_selector').append(createElement('sm-option', {
textContent: asset,
attributes: { value: asset },
}));
})
}
let flo_rate = rates["FLO"];
floExchangeRate = parseFloat(flo_rate)
getRef('flo_rate').textContent = formatAmount(parseFloat(flo_rate))
getRef('get_price').value = parseFloat(parseFloat(flo_rate).toFixed(2))
getRef('get_price').value = parseFloat(parseFloat(rates["FLO"]).toFixed(2))
}).catch(error => console.error(error))
}
@ -1632,10 +1714,9 @@
if (init) {
console.info("init");
if (!proxy.userID) {
getRef('home').classList.remove('signed-in');
floExchangeAPI.getLoginCode().then(response => {
getRef("login_form").classList.remove('hide-completely');
document.querySelectorAll(".user-content").forEach(elem => elem.classList.add('hide-completely'))
getRef("login_form").classList.remove('hide');
document.querySelectorAll(".user-content").forEach(elem => elem.classList.add('hide'))
getRef('sign_in_code').value = response.code;
getRef('sign_in_hash').value = response.hash;
proxy.clear();
@ -1662,40 +1743,51 @@
getRef(`${type}_balance`).append(card)
}
const balance = {}
let accountDetails = {}
const allTokens = {}
async function account() {
floExchangeAPI.getAccount(proxy.userID, await proxy.secret).then(acc => {
getRef("login_form").classList.add('hide-completely')
getRef('home').classList.add('signed-in')
getRef('user_popup_button').classList.remove('hide-completely')
floExchangeAPI.getAccount(proxy.userID, await proxy.secret).then(async acc => {
getRef("login_form").classList.add('hide')
getRef('user_popup_button').classList.remove('hide')
accountDetails = acc
console.debug(acc);
//Element display
document.querySelectorAll(".user-content").forEach(elem => elem.classList.remove('hide-completely'))
getRef('trade_form').classList.remove('hide-completely')
document.querySelectorAll(".user-content").forEach(elem => elem.classList.remove('hide'))
getRef("user_id").value = acc.floID;
getRef("sink_id").value = acc.sinkID;
//FLO Balance
console.debug(acc.vault);
let flo_total = acc.vault.reduce((a, x) => a + (x.asset === "FLO" ? x.quantity : 0), 0);
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);
balance.flo = flo_net
// token balance
acc.vault.forEach(({ asset, quantity }) => {
if (!allTokens.hasOwnProperty(asset)) {
allTokens[asset] = {
total: 0,
locked: 0,
net: 0
}
}
allTokens[asset].total += quantity
})
acc.sellOrders.forEach(({ quantity }) => {
allTokens[asset].locked += quantity
})
for (const asset in allTokens) {
allTokens[asset].net = allTokens[asset].total - allTokens[asset].locked
}
console.debug("FLO", allTokens['FLO']);
showBalance("flo", allTokens['FLO'].net, allTokens['FLO'].locked)
console.log(await floExchangeAPI.getBalance(acc.floID))
showBalance("flo", flo_net, flo_locked,)
//Rupee Balance
let rupee_total = acc.cash;
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);
balance.rupee = rupee_net
showBalance("rupee", rupee_net, rupee_locked)
allTokens['rupee'] = {
total: acc.cash,
locked: acc.buyOrders.reduce((a, x) => a + x.quantity * x.maxPrice, 0),
}
allTokens['rupee'].net = allTokens['rupee'].total - allTokens['rupee'].locked
console.debug("RUPEE", allTokens['rupee']);
showBalance("rupee", allTokens['rupee'].net, allTokens['rupee'].locked)
//My orders
renderUserOrders();
proxy.secret.then(_ => null).catch(_ => null);
showPage(window.location.hash)
}).catch(error => console.error(error))
};