Merge pull request #1 from ranchimall/master

This commit is contained in:
Sai Raj 2023-07-07 04:39:58 +05:30 committed by GitHub
commit c97969c605
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 138 additions and 553 deletions

View File

@ -453,24 +453,6 @@ ul {
align-content: flex-start; align-content: flex-start;
} }
.logo {
display: grid;
align-items: center;
grid-template-columns: auto 1fr;
gap: 0 0.3rem;
margin-right: auto;
}
.logo h4 {
text-transform: capitalize;
font-weight: 600;
}
.logo .main-logo {
height: 1.4rem;
width: 1.4rem;
fill: rgba(var(--text-color), 1);
stroke: none;
}
details:not(:last-of-type) { details:not(:last-of-type) {
border-bottom: thin solid rgba(var(--text-color), 0.3); border-bottom: thin solid rgba(var(--text-color), 0.3);
} }
@ -683,6 +665,22 @@ sm-checkbox {
align-items: center; align-items: center;
} }
.app-brand {
display: flex;
gap: 0.3rem;
align-items: center;
}
.app-brand .icon {
height: 1.7rem;
width: 1.7rem;
}
.app-name__company {
font-size: 0.8rem;
font-weight: 500;
color: rgba(var(--text-color), 0.8);
}
#user_popup_button { #user_popup_button {
background-color: rgba(var(--text-color), 0.06); background-color: rgba(var(--text-color), 0.06);
border-radius: 2rem; border-radius: 2rem;
@ -745,7 +743,7 @@ sm-checkbox {
user-select: none; user-select: none;
color: inherit; color: inherit;
grid-template-columns: auto 1fr auto auto; grid-template-columns: auto 1fr auto auto;
grid-template-areas: "icon name rate right-arrow" "icon name countdown right-arrow"; grid-template-areas: "icon name rate right-arrow";
} }
.listed-asset__icon { .listed-asset__icon {
grid-area: icon; grid-area: icon;
@ -766,28 +764,6 @@ sm-checkbox {
.listed-asset__rate { .listed-asset__rate {
grid-area: rate; grid-area: rate;
} }
.listed-asset__countdown {
display: flex;
align-items: center;
grid-area: countdown;
justify-self: flex-end;
font-size: 0.8rem;
color: var(--accent-color);
}
.listed-asset__countdown .icon {
margin-left: 0.3rem;
overflow: visible;
stroke-width: 3;
fill: none;
}
.listed-asset__countdown .icon .path-a {
stroke: var(--accent-color);
stroke-dashoffset: var(--path-length, 0);
stroke-dasharray: 63;
}
.listed-asset__countdown .icon .path-b {
stroke: rgba(var(--text-color), 0.2);
}
.listed-asset__right-arrow { .listed-asset__right-arrow {
grid-area: right-arrow; grid-area: right-arrow;
background-color: rgba(var(--text-color), 0.1); background-color: rgba(var(--text-color), 0.1);

File diff suppressed because one or more lines are too long

View File

@ -427,24 +427,6 @@ ul {
align-content: flex-start; align-content: flex-start;
} }
} }
.logo {
display: grid;
align-items: center;
grid-template-columns: auto 1fr;
gap: 0 0.3rem;
margin-right: auto;
h4 {
text-transform: capitalize;
font-weight: 600;
}
.main-logo {
height: 1.4rem;
width: 1.4rem;
fill: rgba(var(--text-color), 1);
stroke: none;
}
}
details { details {
&:not(:last-of-type) { &:not(:last-of-type) {
border-bottom: thin solid rgba(var(--text-color), 0.3); border-bottom: thin solid rgba(var(--text-color), 0.3);
@ -643,6 +625,22 @@ sm-checkbox {
width: 100%; width: 100%;
align-items: center; align-items: center;
} }
.app-brand{
display: flex;
gap: 0.3rem;
align-items: center;
.icon{
height: 1.7rem;
width: 1.7rem;
}
}
.app-name{
&__company{
font-size: 0.8rem;
font-weight: 500;
color: rgba(var(--text-color), 0.8);
}
}
#user_popup_button { #user_popup_button {
background-color: rgba(var(--text-color), 0.06); background-color: rgba(var(--text-color), 0.06);
border-radius: 2rem; border-radius: 2rem;
@ -702,7 +700,7 @@ sm-checkbox {
user-select: none; user-select: none;
color: inherit; color: inherit;
grid-template-columns: auto 1fr auto auto; grid-template-columns: auto 1fr auto auto;
grid-template-areas: "icon name rate right-arrow" "icon name countdown right-arrow"; grid-template-areas: "icon name rate right-arrow";
&__icon { &__icon {
grid-area: icon; grid-area: icon;
padding: 0.5rem; padding: 0.5rem;
@ -722,28 +720,6 @@ sm-checkbox {
&__rate { &__rate {
grid-area: rate; grid-area: rate;
} }
&__countdown {
display: flex;
align-items: center;
grid-area: countdown;
justify-self: flex-end;
font-size: 0.8rem;
color: var(--accent-color);
.icon {
margin-left: 0.3rem;
overflow: visible;
stroke-width: 3;
fill: none;
.path-a {
stroke: var(--accent-color);
stroke-dashoffset: var(--path-length, 0);
stroke-dasharray: 63;
}
.path-b {
stroke: rgba(var(--text-color), 0.2);
}
}
}
&__right-arrow { &__right-arrow {
grid-area: right-arrow; grid-area: right-arrow;
background-color: rgba(var(--text-color), 0.1); background-color: rgba(var(--text-color), 0.1);

View File

@ -5,7 +5,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RanchiMall Exchange</title> <title>RanchiMall BitFlo</title>
<meta name="description" content="Trade FLO and FLO based RanchiMall tokens."> <meta name="description" content="Trade FLO and FLO based RanchiMall tokens.">
<meta name="theme-color" content="#516beb" /> <meta name="theme-color" content="#516beb" />
<script src="scripts/components.js" defer></script> <script src="scripts/components.js" defer></script>
@ -62,7 +62,7 @@
</path> </path>
</svg> </svg>
<div class="grid gap-0-5"> <div class="grid gap-0-5">
<h4>RanchiMall Exchange</h4> <h4>RanchiMall BitFlo</h4>
<p>Getting everything ready</p> <p>Getting everything ready</p>
</div> </div>
<line-loader></line-loader> <line-loader></line-loader>
@ -71,14 +71,16 @@
</div> </div>
<article id="home" class="page hidden"> <article id="home" class="page hidden">
<header id="main_header"> <header id="main_header">
<div class="logo"> <div class="app-brand margin-right-auto">
<svg class="main-logo" viewBox="0 0 27.25 32"> <svg id="main_logo" class="icon" viewBox="0 0 27.25 32">
<title>RanchiMall</title> <title>RanchiMall</title>
<path <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"></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> </svg>
<div class="grid"> <div class="app-name">
<h4>RanchiMall Exchange</h4> <div class="app-name__company">RanchiMall</div>
<h4 class="app-name__title">
BitFlo
</h4>
</div> </div>
</div> </div>
<theme-toggle id="theme_toggle"></theme-toggle> <theme-toggle id="theme_toggle"></theme-toggle>
@ -103,11 +105,6 @@
<sm-input type="password" id="login_form__priv_key" placeholder="Private key" <sm-input type="password" id="login_form__priv_key" placeholder="Private key"
error-text="Invalid private key" data-private-key autofocus animate required> error-text="Invalid private key" data-private-key autofocus animate required>
</sm-input> </sm-input>
<!-- <sm-checkbox id="remember_me" checked>
<span class="margin-left-0-5">
Remember me
</span>
</sm-checkbox> -->
<div class="loader-button-wrapper"> <div class="loader-button-wrapper">
<button id="login_button" class="button button--primary" onclick="UI_evt.login('login');" <button id="login_button" class="button button--primary" onclick="UI_evt.login('login');"
type="submit">Log type="submit">Log
@ -163,14 +160,24 @@
</div> </div>
<section id="exchange_wrapper" class="hidden user-content"> <section id="exchange_wrapper" class="hidden user-content">
<div id="asset_list_wrapper" class="grid gap-1 align-start"> <div id="asset_list_wrapper" class="grid gap-1 align-start">
<div class="grid gap-0-3"> <div class="flex align-center space-between">
<div class="flex align-center space-between"> <h5>ASSETS</h5>
<h5>ASSETS</h5> <h5>PRICE</h5>
<h5>PRICE</h5>
</div>
<p>Countdown shows est. time until asset prices are updated</p>
</div> </div>
<ul id="listed_assets" class="user-content hidden"></ul> <ul id="listed_assets" class="user-content hidden">
<li>
<a href="#/exchange?asset=FLO" class="listed-asset grid align-center">
<div class="listed-asset__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>
<h4 class="listed-asset__name">FLO</h4>
<b id="flo_exchange_rate" class="listed-asset__rate">0</b>
</a>
</li>
</ul>
</div> </div>
<div id="asset_page" class="hide-on-mobile"> <div id="asset_page" class="hide-on-mobile">
<nav id="asset_page__header" class="hide-on-desktop"> <nav id="asset_page__header" class="hide-on-desktop">
@ -209,7 +216,7 @@
required animate> required animate>
</sm-input> </sm-input>
</sm-input> </sm-input>
<sm-input id="get_total" placeholder="Locked amount (₹)" type="number" min="0.00000001" <sm-input id="set_price" placeholder="Price" type="number" min="0.00000001"
step="0.00000001" required animate> step="0.00000001" required animate>
</sm-input> </sm-input>
<div class="grid gap-0-5"> <div class="grid gap-0-5">
@ -349,7 +356,6 @@
</div> </div>
<div id="market_orders_wrapper"> <div id="market_orders_wrapper">
<div class="grid gap-1"> <div class="grid gap-1">
<p>Order placement denotes priority at which orders will get executed.</p>
<div class="flex text-center"> <div class="flex text-center">
<b class="flex-1" style="color: var(--green);">Buy</b> <b class="flex-1" style="color: var(--green);">Buy</b>
<b class="flex-1" style="color: var(--danger-color);">Sell</b> <b class="flex-1" style="color: var(--danger-color);">Sell</b>
@ -422,13 +428,13 @@
</div> </div>
</div> </div>
</div> </div>
<p>Deposit rupee from your FLO ID to exchange to purchase assets.</p> <p>Deposit BTC to exchange to purchase assets.</p>
<div class="grid gap-1"> <div class="grid gap-1">
<div id="exchange_rupee_balance"></div> <div id="exchange_btc_balance"></div>
<div class="grid"> <div class="grid">
<div class="flex align-center space-between"> <div class="flex align-center space-between">
<span class="label">Tradable assets</span> <span class="label">Tradable assets</span>
<span class="label">Quantity | value</span> <span class="label">Quantity</span>
</div> </div>
<fieldset id="my_assets" class="grid"></fieldset> <fieldset id="my_assets" class="grid"></fieldset>
</div> </div>
@ -446,44 +452,11 @@
d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" /> d="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z" />
</svg> </svg>
<p class="banner"> <p class="banner">
You need to have rupee tokens in your FLO ID to purchase assets, which then can You need to have BTC in your portfolio to purchase assets.
be
deposited
to your exchange account.
</p> </p>
</div> </div>
</div> </div>
<div id="portfolio_cards_wrapper"> <div id="portfolio_cards_wrapper">
<div class="grid gap-0-5 personal-asset-balance">
<div class="flex align-center">
<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>
<path
d="M13.66,7C13.1,5.82,11.9,5,10.5,5L6,5V3h12v2l-3.26,0c0.48,0.58,0.84,1.26,1.05,2L18,7v2l-2.02,0c-0.25,2.8-2.61,5-5.48,5 H9.77l6.73,7h-2.77L7,14v-2h3.5c1.76,0,3.22-1.3,3.46-3L6,9V7L13.66,7z" />
</g>
</g>
</svg>
<h5>Rupee token</h5>
</div>
<h1 class="h1" id="personal_rupee_balance"></h1>
<a href="https://ranchimall.github.io/flopay/#/home" target="_blank"
class="button 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 0h24v24H0z" fill="none"></path>
<path
d="M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z">
</path>
</svg>
Top-up
</a>
</div>
<div class="grid gap-0-5 personal-asset-balance"> <div class="grid gap-0-5 personal-asset-balance">
<div class="flex align-center"> <div class="flex align-center">
<svg class="icon flo-icon" width="64" height="64" viewBox="0 0 64 64" <svg class="icon flo-icon" width="64" height="64" viewBox="0 0 64 64"
@ -557,166 +530,6 @@
<p>No exchange transactions</p> <p>No exchange transactions</p>
</div> </div>
</div> </div>
<div id="help" class="mobile-page hidden grid gap-2">
<h1>Hey there! How can we help you today?</h1>
<div class="grid gap-0-5">
<h5>F.A.Qs</h5>
<div class="grid gap-0-5">
<details>
<summary class="interact">
<h4>
What are the rules of the exchange that I must know?
</h4>
<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="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z" />
</svg>
</summary>
<ul>
<li>Only the buyers of a token are permitted to sell that token</li>
<li>The maximum quantity of a token that can be sold is capped by the number of tokens
purchased for each token </li>
<li>You need sell-chips in order to sell. Sell-chips are given against each purchase
when current token prices are at least 10% higher</li>
<li><strong>Sell side priority</strong>: The first to buy gets the first priority to
sell no matter when
that person enters the order</li>
<li><strong>Buy side priority</strong>: the first to order gets the first priority to
buy</li>
<li>Launch sellers can sell without sell-chips in order to provide initial inventory
</li>
</ul>
</details>
<details>
<summary class="interact">
<h4>
What are rupee tokens?
</h4>
<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="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z" />
</svg>
</summary>
<p>
Rupee tokens are a digital asset which has value equal to 1 INR. Which can be used with
RanchiMall exchange and other RanchiMall products.
</p>
</details>
<details>
<summary class="interact">
<h4>
Where can I get rupee tokens?
</h4>
<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="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z" />
</svg>
</summary>
<p>
Rupee tokens can be acquired by paying equivalent amount of rupees using our <strong>
<a href="https://ranchimall.github.io/flopay/" target="_blank">FLO Pay</a>
</strong>
app.
</p>
</details>
<details>
<summary class="interact">
<h4>
Why is there a difference between current asset prices and prices shown as
buying/selling price?
</h4>
<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="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z" />
</svg>
</summary>
<p>
Contrary to other exchanges, the price you see as buying/selling price works as a upper
bound for buying and lower bound for selling. you order will bne executed at
best price determined by the exchange algorithm.
</p>
</details>
<details>
<summary class="interact">
<h4>
Why my order hasn't been filled yet?
</h4>
<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="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z" />
</svg>
</summary>
<p>
Our Exchange works a little differently than other exchanges. You can only buy or
sell at
the
market price.
If you have placed an order at lower/higher price than current price, your order will
not be
executed until the market price matches your order price.
</p>
</details>
<details>
<summary class="interact">
<h4>
Why am I not able to sell my assets?
</h4>
<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="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z" />
</svg>
</summary>
<p>
We only allows selling of assets that were bought in this exchange.
Assets bought in other exchanges can not be sold here.
</p>
</details>
<details>
<summary class="interact">
<h4>
I have rupee tokens in FLO ID, so why can't I see them in my portfolio?
</h4>
<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="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z" />
</svg>
</summary>
<p>
In order to user your rupee tokens in exchange, you have to deposit them in exchange
first.
Assets owned by a FLO ID are different than assets you own in exchange.
</p>
</details>
<details>
<summary class="interact">
<h4>
Why don't prices fluctuate often?
</h4>
<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="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z" />
</svg>
</summary>
<p>
Our exchange has a different pricing model than other exchanges. We have an algorithm
based
pricing model which updates prices every hour
based on predefined rules. This prevents rapid fluctuations in price and ensures that
you
can always buy or sell at the best price.
</p>
</details>
</div>
</div>
</div>
</section> </section>
<nav id="main_navbar" class="flex align-center"> <nav id="main_navbar" class="flex align-center">
<a href="#/exchange" class="main_navbar__item main_navbar__item--active interact"> <a href="#/exchange" class="main_navbar__item main_navbar__item--active interact">
@ -767,15 +580,6 @@
</svg> </svg>
<div class="item__title">Portfolio</div> <div class="item__title">Portfolio</div>
</a> </a>
<a href="#/help" class="main_navbar__item 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="M11 18h2v-2h-2v2zm1-16C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm0-14c-2.21 0-4 1.79-4 4h2c0-1.1.9-2 2-2s2 .9 2 2c0 2-3 1.75-3 5h2c0-2.25 3-2.5 3-5 0-2.21-1.79-4-4-4z" />
</svg>
<div class="item__title">Help</div>
</a>
</nav> </nav>
</article> </article>
<!-- <!--
@ -894,27 +698,6 @@
</sm-popup> </sm-popup>
<!-- templates --> <!-- 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>
<b class="listed-asset__rate"></b>
<div class="listed-asset__countdown">
timer
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 24">
<path class="path-a" d="M11.5,2a10,10,0,1,1-10,10,10,10,0,0,1,10-10" />
<path class="path-b" d="M11.5,2a10,10,0,1,1-10,10,10,10,0,0,1,10-10" />
</svg>
</div>
<svg class="icon listed-asset__right-arrow hide-on-desktop" xmlns="http://www.w3.org/2000/svg"
height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
<path d="M0 0h24v24H0z" fill="none"></path>
<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path>
</svg>
</a>
</li>
</template>
<template id="asset_balance_card_template"> <template id="asset_balance_card_template">
<a class="balance-card interact"> <a class="balance-card interact">
<div class="balance-card__icon"></div> <div class="balance-card__icon"></div>
@ -994,7 +777,7 @@
</div> </div>
<div class="flex gap-0-5"> <div class="flex gap-0-5">
<div class="grid flex-1"> <div class="grid flex-1">
<span class="label">Valid upto</span> <span class="label">Price</span>
<b class="transaction-card__price wrap-around"></b> <b class="transaction-card__price wrap-around"></b>
</div> </div>
<div class="grid flex-1"> <div class="grid flex-1">
@ -1021,7 +804,7 @@
</button> </button>
</div> </div>
<div class="grid price-block"> <div class="grid price-block">
<span class="label">Unit price</span> <span class="label">Price</span>
<b class="completed-trade__price"></b> <b class="completed-trade__price"></b>
</div> </div>
<div class="grid amount-block"> <div class="grid amount-block">
@ -1400,7 +1183,7 @@
const urlSearchParams = new URLSearchParams('?' + searchParams); const urlSearchParams = new URLSearchParams('?' + searchParams);
params = Object.fromEntries(urlSearchParams.entries()); params = Object.fromEntries(urlSearchParams.entries());
} }
if (typeof proxy.userID === "undefined" && !['exchange', 'market', 'help'].includes(pageId)) { if (typeof proxy.userID === "undefined" && !['exchange', 'market'].includes(pageId)) {
pageId = 'exchange' pageId = 'exchange'
history.replaceState(null, null, '#/exchange') history.replaceState(null, null, '#/exchange')
} }
@ -1410,6 +1193,7 @@
case 'exchange': case 'exchange':
if (document.body.classList.contains('is-signed-in')) { if (document.body.classList.contains('is-signed-in')) {
getRef('login_section').classList.add('hidden') getRef('login_section').classList.add('hidden')
if (!isMobileView && !params.hasOwnProperty('asset') || params.asset === '') { if (!isMobileView && !params.hasOwnProperty('asset') || params.asset === '') {
if (getRef('listed_assets').querySelector(`[href="#/exchange?asset=FLO"]`)) if (getRef('listed_assets').querySelector(`[href="#/exchange?asset=FLO"]`))
getRef('listed_assets').querySelector(`[href="#/exchange?asset=FLO"]`).click() getRef('listed_assets').querySelector(`[href="#/exchange?asset=FLO"]`).click()
@ -1419,10 +1203,9 @@
getRef('listed_assets').querySelector('.listed-asset--active').classList.remove('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('listed_assets').querySelector(`[href="#/exchange?asset=${params.asset}"]`).classList.add('listed-asset--active')
getRef('chart_asset').textContent = `${params.asset}/INR` getRef('chart_asset').textContent = `${params.asset}/INR`
showSuggestedPrice(params.asset)
getRef('traded_asset').textContent = `Trade ${params.asset}` getRef('traded_asset').textContent = `Trade ${params.asset}`
getRef('trade_button').textContent = `${tradeType} ${params.asset}` getRef('trade_button').textContent = `${tradeType} ${params.asset}`
getRef('quantity_type').textContent = tradeType === 'buy' ? formatAmount(allTokens.rupee.net, true) : `${parseFloat(allTokens[params.asset].net.toFixed(4))} ${params.asset}` getRef('quantity_type').textContent = `${parseFloat(allTokens[tradeType === 'buy' ? 'BTC' : params.asset].net.toFixed(4))} ${tradeType === 'buy' ? 'BTC' : params.asset}`
updateTooltip(params.asset, tradeType) updateTooltip(params.asset, tradeType)
} }
const animOptions = { const animOptions = {
@ -1476,6 +1259,11 @@
getRef('asset_list_wrapper').classList.remove('hide-on-mobile') getRef('asset_list_wrapper').classList.remove('hide-on-mobile')
} }
} }
getLastTradePrice().then(price => {
getRef('set_price').value = price
}).catch(err => {
console.error(err)
})
} else { } else {
getRef('login_section').classList.remove('hidden') getRef('login_section').classList.remove('hidden')
if (subPageId1 === 'generate') { if (subPageId1 === 'generate') {
@ -1499,7 +1287,7 @@
if (params.asset) { if (params.asset) {
getRef('portfolio_asset__name').textContent = params.asset getRef('portfolio_asset__name').textContent = params.asset
const { net, locked } = allTokens[params.asset] const { net, locked } = allTokens[params.asset]
const lockedBalance = params.asset === 'rupee' ? formatAmount(locked, true) : toFixed(locked) const lockedBalance = params.asset === 'rupee' ? formatAmount(locked) : toFixed(locked)
showChildElement('portfolio', 1, { showChildElement('portfolio', 1, {
entry: slideInLeft, entry: slideInLeft,
exit: slideOutLeft, exit: slideOutLeft,
@ -1507,8 +1295,8 @@
renderElem(getRef('portfolio_asset__balance'), html` renderElem(getRef('portfolio_asset__balance'), html`
<div class="grid"> <div class="grid">
<span class="label">Available</span> <span class="label">Available</span>
<b style="font-size:2rem">${params.asset === 'rupee' ? formatAmount(net, true) : toFixed(net)}</b> <b style="font-size:2rem">${params.asset === 'rupee' ? formatAmount(net) : toFixed(net)}</b>
${params.asset !== 'rupee' ? html`<span style="font-size: 1rem; opacity:0.8">₹${toFixed(net * floGlobals.exchangeRates[params.asset], 2)}</span>` : ''} ${params.asset !== 'rupee' ? html`<span style="font-size: 1rem; opacity:0.8">₹${toFixed(net, 2)}</span>` : ''}
</div> </div>
${locked ? html` ${locked ? html`
<div class="grid"> <div class="grid">
@ -1800,6 +1588,9 @@
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.0861 14.6534C22.3924 14.3472 22.7898 14.1486 23.2186 14.0876L44.6946 11.0319C45.2676 10.9504 45.8455 11.1432 46.2547 11.5524C47.2381 12.5358 46.8168 14.2128 45.4853 14.6146L28.6869 19.6843C28.3711 19.7796 28.0838 19.9515 27.8505 20.1848L27.0092 21.0261L28.3236 22.3404C29.0306 23.0475 29.0976 24.1522 28.5245 24.9346L52.2562 48.6662C53.0372 49.4473 53.0372 50.7136 52.2562 51.4946L51.4947 52.2561C50.7137 53.0372 49.4473 53.0372 48.6663 52.2561L24.9346 28.5245C24.1522 29.0976 23.0475 29.0306 22.3404 28.3236L21.0261 27.0092L20.1848 27.8505C19.9515 28.0838 19.7796 28.3711 19.6843 28.6869L14.6146 45.4853C14.2128 46.8168 12.5358 47.2381 11.5524 46.2547C11.1432 45.8455 10.9504 45.2675 11.0319 44.6946L14.0876 23.2186C14.1486 22.7898 14.3472 22.3924 14.6534 22.0861L15.3949 21.3447C14.8777 20.6386 14.8818 19.67 15.4072 18.9681C14.8209 18.1848 14.8837 17.0693 15.5958 16.3572L16.3573 15.5958C17.0694 14.8837 18.1848 14.8208 18.9681 15.4072C19.6701 14.8818 20.6386 14.8777 21.3447 15.3949L22.0861 14.6534Z"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M22.0861 14.6534C22.3924 14.3472 22.7898 14.1486 23.2186 14.0876L44.6946 11.0319C45.2676 10.9504 45.8455 11.1432 46.2547 11.5524C47.2381 12.5358 46.8168 14.2128 45.4853 14.6146L28.6869 19.6843C28.3711 19.7796 28.0838 19.9515 27.8505 20.1848L27.0092 21.0261L28.3236 22.3404C29.0306 23.0475 29.0976 24.1522 28.5245 24.9346L52.2562 48.6662C53.0372 49.4473 53.0372 50.7136 52.2562 51.4946L51.4947 52.2561C50.7137 53.0372 49.4473 53.0372 48.6663 52.2561L24.9346 28.5245C24.1522 29.0976 23.0475 29.0306 22.3404 28.3236L21.0261 27.0092L20.1848 27.8505C19.9515 28.0838 19.7796 28.3711 19.6843 28.6869L14.6146 45.4853C14.2128 46.8168 12.5358 47.2381 11.5524 46.2547C11.1432 45.8455 10.9504 45.2675 11.0319 44.6946L14.0876 23.2186C14.1486 22.7898 14.3472 22.3924 14.6534 22.0861L15.3949 21.3447C14.8777 20.6386 14.8818 19.67 15.4072 18.9681C14.8209 18.1848 14.8837 17.0693 15.5958 16.3572L16.3573 15.5958C17.0694 14.8837 18.1848 14.8208 18.9681 15.4072C19.6701 14.8818 20.6386 14.8777 21.3447 15.3949L22.0861 14.6534Z"/>
</svg>` </svg>`
}, },
BTC: {
icon: `<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><rect fill="none" height="24" width="24"/></g><g><path d="M17.06,11.57C17.65,10.88,18,9.98,18,9c0-1.86-1.27-3.43-3-3.87L15,3h-2v2h-2V3H9v2H6v2h2v10H6v2h3v2h2v-2h2v2h2v-2 c2.21,0,4-1.79,4-4C19,13.55,18.22,12.27,17.06,11.57z M10,7h4c1.1,0,2,0.9,2,2s-0.9,2-2,2h-4V7z M15,17h-5v-4h5c1.1,0,2,0.9,2,2 S16.1,17,15,17z"/></g></svg>`
},
default: { default: {
icon: `<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="M15 4c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zM3 12c0-2.61 1.67-4.83 4-5.65V4.26C3.55 5.15 1 8.27 1 12s2.55 6.85 6 7.74v-2.09c-2.33-.82-4-3.04-4-5.65z"/></svg>` icon: `<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="M15 4c-4.42 0-8 3.58-8 8s3.58 8 8 8 8-3.58 8-8-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6s2.69-6 6-6 6 2.69 6 6-2.69 6-6 6zM3 12c0-2.61 1.67-4.83 4-5.65V4.26C3.55 5.15 1 8.27 1 12s2.55 6.85 6 7.74v-2.09c-2.33-.82-4-3.04-4-5.65z"/></svg>`
} }
@ -1808,15 +1599,8 @@
return listedAssets.hasOwnProperty(asset) ? listedAssets[asset].icon : listedAssets.default.icon; return listedAssets.hasOwnProperty(asset) ? listedAssets[asset].icon : listedAssets.default.icon;
} }
function formatAmount(amount = 0, shorten = false) { function formatAmount(amount = 0, currency = 'BTC') {
return amount.toLocaleString(`en-IN`, { style: 'currency', currency: 'INR', maximumFractionDigits: shorten ? 2 : 8 }) return amount.toLocaleString(`en-US`, { style: 'currency', currency, minimumFractionDigits: 0, maximumFractionDigits: 8 })
}
// Convert milliseconds to time left in HH:MM:SS format
function getTimeLeft(milliseconds) {
const diff = milliseconds - Date.now()
const minutes = Math.floor((diff % 3600000) / 60000)
const seconds = Math.floor(((diff % 3600000) % 60000) / 1000)
return [`${minutes < 10 ? '0' : ''}${minutes}:${seconds < 10 ? '0' : ''}${seconds}`, ((diff % 3600000) / 60000).toFixed(2)]
} }
// remove digitals after specified decimal places without rounding // remove digitals after specified decimal places without rounding
@ -1829,35 +1613,6 @@
return parseFloat(match[0]); return parseFloat(match[0]);
} }
function getSuggestedPrice(asset = pagesData.params.asset || 'FLO') {
return toFixed(parseFloat(floGlobals.exchangeRates[asset]) * deviation[tradeType])
}
function showSuggestedPrice(asset = pagesData.params.asset || 'FLO') {
renderElem(
getRef('get_price'),
html`
<div class="grid">
<div style="font-size: 0.8rem; font-weight: 500; margin-bottom: 0.3rem;">Current price</div>
<h3>${formatAmount(floGlobals.exchangeRates[asset])}</h3>
</div>
<div class="grid">
<div style="font-size: 0.8rem; font-weight: 500; margin-bottom: 0.3rem;">Valid ${tradeType === 'buy' ? 'upto' : 'until'}</div>
<h3>${formatAmount(getSuggestedPrice(asset))}</h3>
</div>
<div class="tooltip">
<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="M11 7h2v2h-2zm0 4h2v6h-2zm1-9C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/></svg>
<p class="banner">
${tradeType === 'buy' ?
html`<b>Valid upto</b> is the max price upto which your order can be executed, which is <b>${DEFAULT_TRADE_PRICE_DEVIATION_BUY * 100}%</b> higher than current price.` :
html`<b>Valid until</b> is the min price until which your order can be executed, which is <b>${DEFAULT_TRADE_PRICE_DEVIATION_SELL * 100}%</b> lower than current price.`
} System will always try to execute your order at the <b>nearest price possible to current price</b>.
</p>
</div>`
)
}
const chartDimensions = { const chartDimensions = {
height: 0, height: 0,
width: 0 width: 0
@ -1875,37 +1630,20 @@
let historyLazyLoader let historyLazyLoader
let portfolioAssetHistoryLazyLoader let portfolioAssetHistoryLazyLoader
const render = { const render = {
listedAsset(asset, rate, countDown) {
const clone = getRef('listed_asset_template').content.cloneNode(true).firstElementChild
clone.firstElementChild.href = `#/exchange?asset=${asset}`
clone.firstElementChild.dataset.listedAsset = asset
clone.querySelector('.listed-asset__icon').innerHTML = getIcon(asset)
clone.querySelector('.listed-asset__rate').textContent = formatAmount(rate)
clone.querySelector('.listed-asset__name').textContent = asset
floGlobals.countDowns.intervals[asset] = setInterval(() => {
const [timeLeft, minutes] = getTimeLeft(countDown)
clone.querySelector('.listed-asset__countdown').firstChild.textContent = timeLeft;
const pathLength = 63 - Math.ceil((minutes / 60) * 63)
clone.querySelector('.listed-asset__countdown').style.setProperty('--path-length', pathLength)
}, 1000);
floGlobals.countDowns.timeouts[asset] = setTimeout(() => {
updateRate().catch(console.error)
delete floGlobals.countDowns.timeouts[asset]
}, countDown - Date.now());
return clone
},
orderCard(orderDetails = {}) { orderCard(orderDetails = {}) {
const { id, asset, quantity, price, time, type } = orderDetails console.log(orderDetails)
const { id, asset, quantity, price, time_placed, type, maxPrice } = orderDetails
const card = getRef('order_template').content.cloneNode(true).firstElementChild const card = getRef('order_template').content.cloneNode(true).firstElementChild
const unitValue = price || maxPrice
card.dataset.id = id card.dataset.id = id
card.dataset.type = type card.dataset.type = type
card.querySelector('.order-card__type').textContent = type card.querySelector('.order-card__type').textContent = type
card.querySelector('.order-card__quantity').textContent = `${quantity} ${asset}` card.querySelector('.order-card__quantity').textContent = `${quantity} ${asset}`
card.querySelector('.order-card__price-type').textContent = type === 'buy' ? 'Valid upto' : 'Valid until' card.querySelector('.order-card__price-type').textContent = 'Price'
card.querySelector('.order-card__price').textContent = formatAmount(price) card.querySelector('.order-card__price').textContent = formatAmount(unitValue)
card.querySelector('.order-card__amount-type').textContent = type === 'buy' ? 'Locked amount' : 'Min amount' card.querySelector('.order-card__amount-type').textContent = 'Amount'
card.querySelector('.order-card__amount').textContent = formatAmount(price * quantity, true) card.querySelector('.order-card__amount').textContent = formatAmount(unitValue * quantity)
card.querySelector('.order-card__time').textContent = relativeTime.from(new Date(time).getTime()) card.querySelector('.order-card__time').textContent = relativeTime.from(new Date(time_placed))
return card return card
}, },
transactionCard(transactionDetails = {}) { transactionCard(transactionDetails = {}) {
@ -1916,21 +1654,20 @@
card.querySelector('.completed-trade__quantity').textContent = `${quantity} ${asset}` card.querySelector('.completed-trade__quantity').textContent = `${quantity} ${asset}`
card.querySelector('.completed-trade__time').textContent = getFormattedTime(time) card.querySelector('.completed-trade__time').textContent = getFormattedTime(time)
card.querySelector('.completed-trade__price').textContent = formatAmount(unitValue) card.querySelector('.completed-trade__price').textContent = formatAmount(unitValue)
card.querySelector('.completed-trade__total').textContent = formatAmount(parseFloat(unitValue * quantity), true) card.querySelector('.completed-trade__total').textContent = formatAmount(parseFloat(unitValue * quantity))
card.querySelector('.more-info').dataset.buyer = buyer card.querySelector('.more-info').dataset.buyer = buyer
card.querySelector('.more-info').dataset.seller = seller card.querySelector('.more-info').dataset.seller = seller
card.querySelector('.more-info').dataset.other = other card.querySelector('.more-info').dataset.other = other
return card return card
}, },
marketOrderCard(orderDetails = {}) { marketOrderCard(orderDetails = {}) {
const { floID, asset, quantity, minPrice, maxPrice, time_placed, type } = orderDetails const { floID, asset, quantity, price, time_placed, type } = orderDetails
const card = getRef('market_order_template').content.cloneNode(true).firstElementChild const card = getRef('market_order_template').content.cloneNode(true).firstElementChild
const unitValue = minPrice || maxPrice;
card.dataset.type = type card.dataset.type = type
card.classList.add(`transaction-card--${type}`) card.classList.add(`transaction-card--${type}`)
card.querySelector('.transaction-card__quantity').textContent = `${quantity} ${asset}` card.querySelector('.transaction-card__quantity').textContent = `${quantity} ${asset}`
card.querySelector('.transaction-card__price').textContent = formatAmount(unitValue) card.querySelector('.transaction-card__price').textContent = formatAmount(price)
card.querySelector('.transaction-card__total').textContent = formatAmount(parseFloat(unitValue * quantity), true) card.querySelector('.transaction-card__total').textContent = formatAmount(parseFloat(price * quantity))
card.querySelector('.more-info').dataset.time = time_placed card.querySelector('.more-info').dataset.time = time_placed
card.querySelector('.more-info').dataset.buyer = type === 'buy' ? floID : undefined card.querySelector('.more-info').dataset.buyer = type === 'buy' ? floID : undefined
card.querySelector('.more-info').dataset.seller = type === 'sell' ? floID : undefined card.querySelector('.more-info').dataset.seller = type === 'sell' ? floID : undefined
@ -1943,7 +1680,7 @@
card.querySelector('.completed-trade__quantity').textContent = `${quantity} ${asset}` card.querySelector('.completed-trade__quantity').textContent = `${quantity} ${asset}`
card.querySelector('.completed-trade__time').textContent = getFormattedTime(time) card.querySelector('.completed-trade__time').textContent = getFormattedTime(time)
card.querySelector('.completed-trade__price').textContent = `₹${unitValue}` card.querySelector('.completed-trade__price').textContent = `₹${unitValue}`
card.querySelector('.completed-trade__total').textContent = formatAmount(parseFloat(unitValue * quantity), true) card.querySelector('.completed-trade__total').textContent = formatAmount(parseFloat(unitValue * quantity))
card.querySelector('.more-info').dataset.buyer = buyer card.querySelector('.more-info').dataset.buyer = buyer
card.querySelector('.more-info').dataset.seller = seller card.querySelector('.more-info').dataset.seller = seller
return card return card
@ -1957,8 +1694,8 @@
card.querySelector('.balance-card__icon').innerHTML = getIcon(asset) card.querySelector('.balance-card__icon').innerHTML = getIcon(asset)
const templateToClone = locked ? 'locked_balance_template' : 'net_balance_template'; const templateToClone = locked ? 'locked_balance_template' : 'net_balance_template';
const assetBalance = getRef(templateToClone).content.cloneNode(true) const assetBalance = getRef(templateToClone).content.cloneNode(true)
const availableBalance = asset === 'rupee' ? formatAmount(net, true) : `${toFixed(net)} | <span style="font-size: 0.8rem">₹${toFixed(net * floGlobals.exchangeRates[asset], 2)}</span>` const availableBalance = asset === 'rupee' ? formatAmount(net) : `${toFixed(net)}`
const lockedBalance = asset === 'rupee' ? formatAmount(locked, true) : toFixed(locked) const lockedBalance = asset === 'rupee' ? formatAmount(locked) : toFixed(locked)
assetBalance.querySelector('.available-balance').innerHTML = availableBalance assetBalance.querySelector('.available-balance').innerHTML = availableBalance
if (locked) { if (locked) {
assetBalance.querySelector('.locked-balance').textContent = lockedBalance assetBalance.querySelector('.locked-balance').textContent = lockedBalance
@ -1994,19 +1731,12 @@
const frag = document.createDocumentFragment() const frag = document.createDocumentFragment()
const ordersType = getRef('my_orders_category_selector').value const ordersType = getRef('my_orders_category_selector').value
if (ordersType === 'open') { if (ordersType === 'open') {
getRef('my_orders__title').textContent = 'My orders' getRef('my_orders__title').textContent = 'My orders';
buyOrders = buyOrders.map(order => ({ ...order, type: 'buy' }))
sellOrders = sellOrders.map(order => ({ ...order, type: 'sell' }))
const allOpenOrders = [...buyOrders, ...sellOrders].sort((a, b) => new Date(b.time_placed).getTime() - new Date(a.time_placed).getTime()) const allOpenOrders = [...buyOrders, ...sellOrders].sort((a, b) => new Date(b.time_placed).getTime() - new Date(a.time_placed).getTime())
allOpenOrders.forEach(order => { allOpenOrders.forEach(order => {
const { id, asset, quantity, minPrice = undefined, maxPrice = undefined, time_placed } = order frag.append(render.orderCard(order))
const orderDetails = {
id,
asset,
quantity,
type: minPrice ? 'sell' : 'buy',
price: minPrice || maxPrice,
time: time_placed
}
frag.append(render.orderCard(orderDetails))
}) })
} else { } else {
getRef('my_orders__title').textContent = 'My trades' getRef('my_orders__title').textContent = 'My trades'
@ -2181,7 +1911,7 @@
function updateTooltip(asset, tradeType) { function updateTooltip(asset, tradeType) {
getRef('quantity_selector').querySelectorAll('.button').forEach(button => { getRef('quantity_selector').querySelectorAll('.button').forEach(button => {
if (tradeType === 'buy') { if (tradeType === 'buy') {
button.title = `Buy ${asset} worth ${button.textContent} of total rupee` button.title = `Buy ${asset} worth ${button.textContent} of total ${floGlobals.currency}`
} else { } else {
button.title = `Sell ${button.textContent} of total ${asset}` button.title = `Sell ${button.textContent} of total ${asset}`
} }
@ -2204,20 +1934,27 @@
getRef('trade_type_selector').addEventListener('change', e => { getRef('trade_type_selector').addEventListener('change', e => {
tradeType = e.target.value tradeType = e.target.value
const selectedAsset = pagesData.params.asset const selectedAsset = pagesData.params.asset
showSuggestedPrice()
getRef('get_total').setAttribute('placeholder', tradeType === 'buy' ? `Locked amount (₹)` : `Min amount received (₹)`)
getRef('trade_button').textContent = `${tradeType} ${selectedAsset}` getRef('trade_button').textContent = `${tradeType} ${selectedAsset}`
getRef('quantity_type').textContent = tradeType === 'buy' ? formatAmount(allTokens.rupee.net, true) : `${parseFloat(allTokens[selectedAsset].net.toFixed(4))} ${selectedAsset}` getRef('quantity_type').textContent = `${parseFloat(allTokens[tradeType === 'buy' ? 'BTC' : selectedAsset].net.toFixed(4))} ${tradeType === 'buy' ? 'BTC' : selectedAsset}`
updateTooltip(selectedAsset, tradeType) updateTooltip(selectedAsset, tradeType)
}) })
getRef('price_duration_selector').addEventListener('change', e => { getRef('price_duration_selector').addEventListener('change', e => {
render.chart(pagesData.params.asset) render.chart(pagesData.params.asset)
}) })
function getLastTradePrice() {
return new Promise((resolve, reject) => {
floTradeAPI.getTradeList().then(tradeList => {
floGlobals.lastTradePrice = tradeList[0].unitValue || 0;
getRef('flo_exchange_rate').textContent = `${floGlobals.lastTradePrice} ${floGlobals.currency}`
resolve(floGlobals.lastTradePrice)
}).catch(reject)
})
}
async function tradeAsset() { async function tradeAsset() {
closePopup() closePopup()
const asset = pagesData.params.asset; const asset = pagesData.params.asset;
const quantity = parseFloat(getRef('get_quantity').value) const quantity = parseFloat(getRef('get_quantity').value)
const price = getSuggestedPrice() const price = getLastTradePrice()
if (tradeType === 'buy' && accountDetails.sellOrders.some(order => order.asset === asset)) { if (tradeType === 'buy' && accountDetails.sellOrders.some(order => order.asset === asset)) {
closePopup() closePopup()
return notify('You have an open sell order for this asset. Please close it before buying.', 'error') return notify('You have an open sell order for this asset. Please close it before buying.', 'error')
@ -2226,6 +1963,7 @@
return notify('You have an open buy order for this asset. Please close it before selling.', 'error') return notify('You have an open buy order for this asset. Please close it before selling.', 'error')
} }
buttonLoader('trade_button', true) buttonLoader('trade_button', true)
console.log(asset, quantity, price, proxy.userID, await proxy.secret)
try { try {
if (tradeType === 'buy') { if (tradeType === 'buy') {
await floTradeAPI.buy(asset, quantity, price, proxy.userID, await proxy.secret) await floTradeAPI.buy(asset, quantity, price, proxy.userID, await proxy.secret)
@ -2247,7 +1985,7 @@
finally { finally {
updateRate() updateRate()
getRef('get_quantity').value = 0 getRef('get_quantity').value = 0
getRef('get_total').value = 0 getRef('set_price').value = 0
setTimeout(() => { setTimeout(() => {
buttonLoader('trade_button', false) buttonLoader('trade_button', false)
getRef('trade_button').disabled = true getRef('trade_button').disabled = true
@ -2259,42 +1997,14 @@
} }
getRef('quantity_selector').addEventListener('click', e => { getRef('quantity_selector').addEventListener('click', e => {
if (e.target.closest('button')) { if (e.target.closest('button')) {
const selectedAsset = pagesData.params.asset const selectedAsset = pagesData.params.asset;
if (!selectedAsset) return notify('Please select an asset to trade', 'error')
const target = e.target.closest('button') const target = e.target.closest('button')
const unitValue = getSuggestedPrice()
const fraction = parseFloat(target.value) const fraction = parseFloat(target.value)
if (tradeType === 'buy') { const price = parseFloat(getRef('set_price').value.trim()) || floGlobals.lastTradePrice || 0
getRef('get_total').value = toFixed(fraction * allTokens['rupee'].net) getRef('get_quantity').value = toFixed((allTokens[selectedAsset].net / price) * fraction)
getRef('get_quantity').value = toFixed((allTokens['rupee'].net * fraction) / getSuggestedPrice())
} else {
getRef('get_total').value = toFixed(fraction * allTokens[selectedAsset].net * getSuggestedPrice())
getRef('get_quantity').value = toFixed(allTokens[selectedAsset].net * fraction)
}
} }
}) })
getRef('get_quantity').addEventListener('focusin', e => {
if (tradeType === 'buy') {
getRef('quantity_selector_tip').innerHTML = `<b>Locked amount</b> is highest total amount you'll be charged for buying specified quantity, most likely you'll charged less than locked amount.`
} else {
getRef('quantity_selector_tip').innerHTML = `<b>Min amount</b> received is lowest total amount you'll get by selling specified quantity, most likely you will get more than this amount. `
}
})
getRef('get_total').addEventListener('focusin', e => {
if (tradeType === 'buy') {
getRef('quantity_selector_tip').innerHTML = `<b>Locked amount</b> is highest total amount you'll be charged for buying specified quantity, most likely you'll charged less than locked amount.`
} else {
getRef('quantity_selector_tip').innerHTML = `<b>Min amount</b> received is lowest total amount you'll get by selling specified quantity, most likely you will get more than this amount. `
}
})
getRef('get_quantity').addEventListener('keyup', e => {
const unitValue = getSuggestedPrice()
getRef('get_total').value = toFixed(parseFloat(e.target.value) * unitValue)
})
getRef('get_total').addEventListener('keyup', e => {
const unitValue = getSuggestedPrice()
getRef('get_quantity').value = toFixed(parseFloat(e.target.value) / unitValue)
})
getRef('portfolio_pages_selector').addEventListener('change', e => { getRef('portfolio_pages_selector').addEventListener('change', e => {
if (e.target.value === 'exchange') { if (e.target.value === 'exchange') {
@ -2310,7 +2020,7 @@
const type = target.value const type = target.value
const asset = pagesData.params.asset const asset = pagesData.params.asset
getRef('portfolio_quantity_type').textContent = getRef('quantity_type').textContent = asset === 'rupee' ? formatAmount(allTokens.rupee.net, true) : `${toFixed(allTokens[asset].net)} ${asset}` getRef('portfolio_quantity_type').textContent = getRef('quantity_type').textContent = `${toFixed(allTokens[type === 'buy' ? 'BTC' : asset].net)} ${asset}`
getRef('portfolio_popup__cta').textContent = `${type} ${asset}` getRef('portfolio_popup__cta').textContent = `${type} ${asset}`
getRef('portfolio_popup__cta').setAttribute('value', type) getRef('portfolio_popup__cta').setAttribute('value', type)
getRef('portfolio_popup__title').textContent = `${type} ${asset}` getRef('portfolio_popup__title').textContent = `${type} ${asset}`
@ -2416,7 +2126,7 @@
case 'deposit': case 'deposit':
const privKey = getRef('get_private_key').value; const privKey = getRef('get_private_key').value;
if (asset === 'FLO') { if (asset === 'FLO') {
response = await floTradeAPI.depositFLO(quantity, proxy.userID, proxy.sinkID, privKey, proxySecret) response = await floTradeAPI.depositFLO(quantity, proxy.userID, await proxy.sinkID, privKey, proxySecret)
} else { } else {
response = await floTradeAPI.depositToken(asset, quantity, proxy.userID, proxy.sinkID, privKey, proxySecret) response = await floTradeAPI.depositToken(asset, quantity, proxy.userID, proxy.sinkID, privKey, proxySecret)
} }
@ -2672,10 +2382,7 @@
case 'confirm_trade_popup': case 'confirm_trade_popup':
const asset = pagesData.params.asset; const asset = pagesData.params.asset;
const quantity = parseFloat(getRef('get_quantity').value) const quantity = parseFloat(getRef('get_quantity').value)
const currentPrice = toFixed(floGlobals.exchangeRates[asset]); const setPrice = formatAmount(parseFloat(getRef('set_price').value))
const price = toFixed(getSuggestedPrice());
const total = formatAmount(parseFloat(getRef('get_total').value))
const minTotal = formatAmount(toFixed(currentPrice * quantity))
getRef('confirm_trade__title').textContent = `${tradeType} ${asset}` getRef('confirm_trade__title').textContent = `${tradeType} ${asset}`
getRef('confirm_trade__details').innerHTML = ` getRef('confirm_trade__details').innerHTML = `
<div class="grid"> <div class="grid">
@ -2683,20 +2390,9 @@
<b>${quantity} ${asset}</b> <b>${quantity} ${asset}</b>
</div> </div>
<div class="grid"> <div class="grid">
<p>${tradeType === 'buy' ? 'Min cost' : 'Max earned'}</p> <p>At price</p>
<div> <b>${setPrice}</b>
<b>${minTotal}</b><span> @ ${currentPrice}/${asset}</span>
</div>
</div> </div>
<div class="grid gap-0-3">
<p>${tradeType === 'buy' ? 'Max cost (Amount locked)' : 'Min earned'}</p>
<div>
<b>${total}</b><span> @ ${price}/${asset}</span>
</div>
</div>
<p>
<strong>All trades will be executed at current price.</strong>
</p>
`; `;
break; break;
} }
@ -2717,62 +2413,8 @@
function updateRate(init = false) { function updateRate(init = false) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
floTradeAPI.getRates().then(({ rates, countDown }) => { render.chart(pagesData.params.asset)
console.debug(rates); resolve();
floGlobals.exchangeRates = rates
if (init) {
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
}
}
// dynamically render listed assets if not already rendered
getRef('listed_assets').append(render.listedAsset(asset, formatAmount(parseFloat(rate)), countDown[asset]));
getRef('market_asset_rates').append(createElement('li', {
className: 'listed-asset grid align-center',
innerHTML: `
<div class="listed-asset__icon">${getIcon(asset)}</div>
<h4 class="listed-asset__name">${asset}</h4>
<b class="listed-asset__rate">${formatAmount(rate)}</b>
`
}))
})
resolve();
} else {
// update rates in UI
for (const asset in rates) {
const listedAsset = getRef(`listed_assets`).querySelector(`[data-listed-asset="${asset}"]`)
if (listedAsset) {
listedAsset.querySelector('.listed-asset__rate').textContent = formatAmount(parseFloat(rates[asset]))
if (floGlobals.countDowns.intervals.hasOwnProperty(asset)) {
clearInterval(floGlobals.countDowns.intervals[asset]);
}
floGlobals.countDowns.intervals[asset] = setInterval(() => {
const [timeLeft, minutes] = getTimeLeft(countDown[asset])
listedAsset.querySelector('.listed-asset__countdown').firstChild.textContent = timeLeft;
const pathLength = 63 - Math.ceil((minutes / 60) * 63)
listedAsset.querySelector('.listed-asset__countdown').style.setProperty('--path-length', pathLength)
}, 1000)
if (floGlobals.countDowns.timeouts.hasOwnProperty(asset)) {
clearTimeout(floGlobals.countDowns.timeouts[asset]);
delete floGlobals.countDowns.timeouts[asset]
}
floGlobals.countDowns.timeouts[asset] = setTimeout(() => {
updateRate()
}, countDown[asset] - Date.now());
}
}
resolve();
}
render.chart(pagesData.params.asset)
showSuggestedPrice()
}).catch(error => {
notify(error.message, 'error');
reject(error)
})
}).catch(error => console.error(error)) }).catch(error => console.error(error))
} }
@ -2810,8 +2452,8 @@
async function account() { async function account() {
floTradeAPI.getAccount(proxy.userID, await proxy.secret).then(async acc => { floTradeAPI.getAccount(proxy.userID, await proxy.secret).then(async acc => {
document.body.classList.add('is-signed-in'); document.body.classList.add('is-signed-in');
getRef('market_asset_rates').parentNode.remove() if (getRef('market_asset_rates'))
location.hash = `#/exchange` getRef('market_asset_rates').parentNode.remove()
getRef('user_popup_button').addEventListener('click', () => openPopup('user_popup')); getRef('user_popup_button').addEventListener('click', () => openPopup('user_popup'));
getRef('trade_button').addEventListener('click', () => openPopup('confirm_trade_popup')); getRef('trade_button').addEventListener('click', () => openPopup('confirm_trade_popup'));
accountDetails = acc accountDetails = acc
@ -2824,15 +2466,15 @@
if (acc.subAdmin) if (acc.subAdmin)
console.info("logged in as subAdmin"); console.info("logged in as subAdmin");
// rupee balance init // FLO balance init
allTokens[floGlobals.currency] = { allTokens[floGlobals.currency] = {
total: 0, total: 0,
locked: 0, locked: 0,
net: 0 net: 0
} }
// token balance // token balance
acc.tokenBalance.forEach(({ token, quantity }) => { acc.tokenBalance.forEach(({ asset, quantity }) => {
allTokens[token] = { allTokens[asset] = {
total: quantity, total: quantity,
locked: 0, locked: 0,
net: 0 net: 0
@ -2845,27 +2487,22 @@
for (const token in allTokens) { for (const token in allTokens) {
allTokens[token].net = allTokens[token].total - allTokens[token].locked allTokens[token].net = allTokens[token].total - allTokens[token].locked
} }
console.debug("FLO", allTokens['FLO']);
console.log(await floTradeAPI.getBalance(acc.floID))
console.debug("RUPEE", allTokens['rupee']);
// render all assets in portfolio // render all assets in portfolio
const frag = document.createDocumentFragment(); const frag = document.createDocumentFragment();
let totalPortfolio = 0; let totalPortfolio = 0;
Object.entries(allTokens).sort((a, b) => b[1].net - a[1].net).forEach(([asset], index) => { Object.entries(allTokens).sort((a, b) => b[1].net - a[1].net).forEach(([asset], index) => {
if (asset !== floGlobals.currency) { if (asset !== floGlobals.currency) {
totalPortfolio += allTokens[asset].net * floGlobals.exchangeRates[asset] totalPortfolio += allTokens[asset].net
frag.append(render.assetBalanceCard(asset)) frag.append(render.assetBalanceCard(asset))
} }
else { else {
getRef('exchange_rupee_balance').innerHTML = `` getRef('exchange_btc_balance').innerHTML = ``
getRef('exchange_rupee_balance').append(render.assetBalanceCard(asset)) getRef('exchange_btc_balance').append(render.assetBalanceCard(asset))
} }
}) })
getRef('my_assets').innerHTML = '' getRef('my_assets').innerHTML = ''
getRef('my_assets').append(frag) getRef('my_assets').append(frag)
getRef('portfolio_value').textContent = formatAmount(toFixed(totalPortfolio, 2), true) getRef('portfolio_value').textContent = formatAmount(toFixed(totalPortfolio, 2))
//My orders //My orders
render.userOrders(); render.userOrders();
@ -2874,10 +2511,6 @@
const [beforeDecimal, afterDecimal = '00'] = String(balance).split('.') const [beforeDecimal, afterDecimal = '00'] = String(balance).split('.')
getRef('personal_flo_balance').innerHTML = `<span><b>${beforeDecimal}</b></span>.<span>${afterDecimal}</span>` getRef('personal_flo_balance').innerHTML = `<span><b>${beforeDecimal}</b></span>.<span>${afterDecimal}</span>`
}) })
floTokenAPI.getBalance(accountDetails.floID, 'rupee').then(balance => {
const [beforeDecimal, afterDecimal] = formatAmount(balance, true).split('₹')[1].split('.')
getRef('personal_rupee_balance').innerHTML = `<span><b>${beforeDecimal}</b></span>.<span>${afterDecimal}</span>`
})
proxy.secret.then(_ => null).catch(_ => null); proxy.secret.then(_ => null).catch(_ => null);
routeTo(window.location.hash); routeTo(window.location.hash);
}).catch(error => { }).catch(error => {