Merge branch 'master' into dev
This commit is contained in:
commit
5c2ce4f03e
238
css/main.css
238
css/main.css
@ -112,7 +112,6 @@ button,
|
|||||||
padding: 0.8rem;
|
padding: 0.8rem;
|
||||||
border-radius: 0.3rem;
|
border-radius: 0.3rem;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
}
|
||||||
button:focus-visible,
|
button:focus-visible,
|
||||||
.button:focus-visible {
|
.button:focus-visible {
|
||||||
@ -497,7 +496,7 @@ h3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.observe-empty-state:empty {
|
.observe-empty-state:empty {
|
||||||
display: none;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.observe-empty-state:not(:empty) + .empty-state {
|
.observe-empty-state:not(:empty) + .empty-state {
|
||||||
@ -709,13 +708,10 @@ h3 {
|
|||||||
margin-bottom: 0.3rem;
|
margin-bottom: 0.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#home {
|
#contacts > :first-child {
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
#home > :first-child {
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
padding: 0.5rem 1.5rem 4rem 1.5rem;
|
padding-bottom: 4rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#primary_actions_wrapper {
|
#primary_actions_wrapper {
|
||||||
@ -738,6 +734,67 @@ h3 {
|
|||||||
fill: var(--accent-color);
|
fill: var(--accent-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#search {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#queried_flo_address h4 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
#queried_flo_address > sm-copy {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#token_list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.token-item {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
background-color: rgba(var(--text-color), 0.06);
|
||||||
|
border-radius: 0.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.transaction {
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: rgba(var(--text-color), 0.03);
|
||||||
|
border-radius: 0.3rem;
|
||||||
|
}
|
||||||
|
.transaction:not(:last-of-type) {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
.transaction .icon {
|
||||||
|
fill: var(--accent-color);
|
||||||
|
}
|
||||||
|
.transaction__time, .transaction__link, .transaction__receiver {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
.transaction__receiver {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
color: rgba(var(--text-color), 0.8);
|
||||||
|
}
|
||||||
|
.transaction p {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
max-width: unset;
|
||||||
|
}
|
||||||
|
.transaction__time {
|
||||||
|
justify-self: flex-end;
|
||||||
|
color: rgba(var(--text-color), 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#search_wrapper {
|
||||||
|
width: min(100%, 36rem);
|
||||||
|
}
|
||||||
|
|
||||||
|
#search_query_input {
|
||||||
|
justify-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
#saved_ids_list {
|
#saved_ids_list {
|
||||||
position: relative;
|
position: relative;
|
||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
@ -803,79 +860,10 @@ h3 {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
padding: 0 1.5rem;
|
padding: 0 1rem;
|
||||||
padding-bottom: 3rem;
|
padding-bottom: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#transactions {
|
|
||||||
position: relative;
|
|
||||||
height: 100%;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
#transactions header {
|
|
||||||
padding: 1rem 0.7rem;
|
|
||||||
}
|
|
||||||
#transactions header .grid {
|
|
||||||
grid-template-columns: auto 1fr auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#queried_flo_address {
|
|
||||||
margin: 0.5rem 0;
|
|
||||||
margin-left: 0.7rem;
|
|
||||||
}
|
|
||||||
#queried_flo_address h4 {
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
#queried_flo_address > sm-copy {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#token_list {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.token-item {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
padding: 0.5rem 1rem;
|
|
||||||
background-color: rgba(var(--text-color), 0.06);
|
|
||||||
border-radius: 0.3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
#transactions_list {
|
|
||||||
flex-direction: column;
|
|
||||||
padding-bottom: 4rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.transaction {
|
|
||||||
gap: 1rem;
|
|
||||||
padding: 1rem;
|
|
||||||
background-color: rgba(var(--text-color), 0.03);
|
|
||||||
border-radius: 0.3rem;
|
|
||||||
}
|
|
||||||
.transaction:not(:last-of-type) {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
.transaction .icon {
|
|
||||||
fill: var(--accent-color);
|
|
||||||
}
|
|
||||||
.transaction__time, .transaction__link, .transaction__receiver {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
}
|
|
||||||
.transaction__receiver {
|
|
||||||
margin-left: 0.5rem;
|
|
||||||
color: rgba(var(--text-color), 0.8);
|
|
||||||
}
|
|
||||||
.transaction p {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
max-width: unset;
|
|
||||||
}
|
|
||||||
.transaction__time {
|
|
||||||
justify-self: flex-end;
|
|
||||||
color: rgba(var(--text-color), 0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.fab {
|
.fab {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
@ -885,11 +873,6 @@ h3 {
|
|||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
#scroll_to_top {
|
|
||||||
border-radius: 3rem;
|
|
||||||
background-color: rgba(var(--foreground-color), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#add_address_button {
|
#add_address_button {
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
color: rgba(var(--background-color), 1);
|
color: rgba(var(--background-color), 1);
|
||||||
@ -912,6 +895,9 @@ h3 {
|
|||||||
#balance_card form {
|
#balance_card form {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
#balance_card fieldset {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
.token-balance {
|
.token-balance {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -932,6 +918,25 @@ h3 {
|
|||||||
accent-color: var(--accent-color);
|
accent-color: var(--accent-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.token-receiver-combo {
|
||||||
|
border: solid thin rgba(var(--text-color), 0.2);
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-radius: 0.8rem;
|
||||||
|
}
|
||||||
|
.token-receiver-combo--removable {
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
|
grid-template-areas: "receiver receiver" "amount remove";
|
||||||
|
}
|
||||||
|
.token-receiver-combo--removable .token-receiver {
|
||||||
|
grid-area: receiver;
|
||||||
|
}
|
||||||
|
.token-receiver-combo--removable .token-amount {
|
||||||
|
grid-area: amount;
|
||||||
|
}
|
||||||
|
.token-receiver-combo--removable .remove-token-receiver {
|
||||||
|
grid-area: remove;
|
||||||
|
}
|
||||||
|
|
||||||
#transaction_result {
|
#transaction_result {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
@ -1009,6 +1014,41 @@ h3 {
|
|||||||
transform: scale(1) translateY(0);
|
transform: scale(1) translateY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#queried_address_transactions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pagination_wrapper {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0.5rem;
|
||||||
|
background-color: rgba(var(--foreground-color), 1);
|
||||||
|
z-index: 5;
|
||||||
|
border-radius: 0.7rem;
|
||||||
|
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.2);
|
||||||
|
margin: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination__item {
|
||||||
|
display: flex;
|
||||||
|
padding: 0.2rem 0.5rem;
|
||||||
|
border-radius: 0.3rem;
|
||||||
|
}
|
||||||
|
.pagination__item--active {
|
||||||
|
background-color: var(--accent-color);
|
||||||
|
color: rgba(var(--background-color), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
legend,
|
||||||
|
.label {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: rgba(var(--text-color), 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
#smartcontracts {
|
#smartcontracts {
|
||||||
display: grid;
|
display: grid;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
@ -1025,11 +1065,6 @@ h3 {
|
|||||||
#smartcontracts fieldset legend {
|
#smartcontracts fieldset legend {
|
||||||
padding: 0 0.5rem;
|
padding: 0 0.5rem;
|
||||||
}
|
}
|
||||||
#smartcontracts legend,
|
|
||||||
#smartcontracts .label {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
color: rgba(var(--text-color), 0.8);
|
|
||||||
}
|
|
||||||
#smartcontracts label {
|
#smartcontracts label {
|
||||||
padding: 0.3rem 0.5rem;
|
padding: 0.3rem 0.5rem;
|
||||||
}
|
}
|
||||||
@ -1174,6 +1209,13 @@ h3 {
|
|||||||
transform: translateY(100%);
|
transform: translateY(100%);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
#pagination_wrapper {
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 4.8rem;
|
||||||
|
left: 50%;
|
||||||
|
right: auto;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@media screen and (min-width: 40rem) {
|
@media screen and (min-width: 40rem) {
|
||||||
sm-popup {
|
sm-popup {
|
||||||
@ -1200,6 +1242,9 @@ h3 {
|
|||||||
#pages_container {
|
#pages_container {
|
||||||
grid-area: main;
|
grid-area: main;
|
||||||
}
|
}
|
||||||
|
.page {
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
}
|
||||||
#main_navbar {
|
#main_navbar {
|
||||||
grid-area: nav;
|
grid-area: nav;
|
||||||
border-top: none;
|
border-top: none;
|
||||||
@ -1235,9 +1280,12 @@ h3 {
|
|||||||
#retrieve_flo_id_popup {
|
#retrieve_flo_id_popup {
|
||||||
--width: 26rem;
|
--width: 26rem;
|
||||||
}
|
}
|
||||||
#send sm-form::part(form) {
|
#send {
|
||||||
align-items: flex-start;
|
padding: 0 6vw;
|
||||||
grid-template-columns: 45% 1fr;
|
}
|
||||||
|
#send sm-form {
|
||||||
|
width: min(56rem, 100%);
|
||||||
|
margin: auto;
|
||||||
}
|
}
|
||||||
#smart_contract_creation_templates {
|
#smart_contract_creation_templates {
|
||||||
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
|
||||||
@ -1271,9 +1319,15 @@ h3 {
|
|||||||
grid-template-areas: "address share button";
|
grid-template-areas: "address share button";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@media screen and (min-width: 56rem) {
|
||||||
|
#send sm-form::part(form) {
|
||||||
|
align-items: flex-start;
|
||||||
|
grid-template-columns: 1fr 1.5fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
@media screen and (min-width: 64rem) {
|
@media screen and (min-width: 64rem) {
|
||||||
#transactions_scroller {
|
#address_details_wrapper {
|
||||||
grid-template-columns: 22rem 1fr;
|
grid-template-columns: auto 1fr;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
#transactions_hero_section {
|
#transactions_hero_section {
|
||||||
|
|||||||
2
css/main.min.css
vendored
2
css/main.min.css
vendored
File diff suppressed because one or more lines are too long
224
css/main.scss
224
css/main.scss
@ -111,7 +111,6 @@ button,
|
|||||||
padding: 0.8rem;
|
padding: 0.8rem;
|
||||||
border-radius: 0.3rem;
|
border-radius: 0.3rem;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
text-transform: capitalize;
|
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
outline: var(--accent-color) solid medium;
|
outline: var(--accent-color) solid medium;
|
||||||
}
|
}
|
||||||
@ -472,7 +471,7 @@ h3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.observe-empty-state:empty {
|
.observe-empty-state:empty {
|
||||||
display: none;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.observe-empty-state:not(:empty) + .empty-state {
|
.observe-empty-state:not(:empty) + .empty-state {
|
||||||
@ -677,12 +676,11 @@ h3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#home {
|
#contacts {
|
||||||
padding: 0;
|
|
||||||
& > :first-child {
|
& > :first-child {
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
padding: 0.5rem 1.5rem 4rem 1.5rem;
|
padding-bottom: 4rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#primary_actions_wrapper {
|
#primary_actions_wrapper {
|
||||||
@ -703,6 +701,64 @@ h3 {
|
|||||||
fill: var(--accent-color);
|
fill: var(--accent-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#search {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
#queried_flo_address {
|
||||||
|
h4 {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
& > sm-copy {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#token_list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.5rem;
|
||||||
|
}
|
||||||
|
.token-item {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
background-color: rgba(var(--text-color), 0.06);
|
||||||
|
border-radius: 0.3rem;
|
||||||
|
}
|
||||||
|
.transaction {
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background-color: rgba(var(--text-color), 0.03);
|
||||||
|
border-radius: 0.3rem;
|
||||||
|
&:not(:last-of-type) {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
.icon {
|
||||||
|
fill: var(--accent-color);
|
||||||
|
}
|
||||||
|
&__time,
|
||||||
|
&__link,
|
||||||
|
&__receiver {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
&__receiver {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
color: rgba(var(--text-color), 0.8);
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
max-width: unset;
|
||||||
|
}
|
||||||
|
&__time {
|
||||||
|
justify-self: flex-end;
|
||||||
|
color: rgba(var(--text-color), 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#search_wrapper {
|
||||||
|
width: min(100%, 36rem);
|
||||||
|
}
|
||||||
|
#search_query_input {
|
||||||
|
justify-self: center;
|
||||||
|
}
|
||||||
#saved_ids_list {
|
#saved_ids_list {
|
||||||
position: relative;
|
position: relative;
|
||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
@ -765,75 +821,9 @@ h3 {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
align-content: flex-start;
|
align-content: flex-start;
|
||||||
padding: 0 1.5rem;
|
padding: 0 1rem;
|
||||||
padding-bottom: 3rem;
|
padding-bottom: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
#transactions {
|
|
||||||
position: relative;
|
|
||||||
height: 100%;
|
|
||||||
padding: 0;
|
|
||||||
header {
|
|
||||||
padding: 1rem 0.7rem;
|
|
||||||
.grid {
|
|
||||||
grid-template-columns: auto 1fr auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#queried_flo_address {
|
|
||||||
margin: 0.5rem 0;
|
|
||||||
margin-left: 0.7rem;
|
|
||||||
h4 {
|
|
||||||
font-size: 1.1rem;
|
|
||||||
}
|
|
||||||
& > sm-copy {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#token_list {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 0.5rem;
|
|
||||||
}
|
|
||||||
.token-item {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
padding: 0.5rem 1rem;
|
|
||||||
background-color: rgba(var(--text-color), 0.06);
|
|
||||||
border-radius: 0.3rem;
|
|
||||||
}
|
|
||||||
#transactions_list {
|
|
||||||
flex-direction: column;
|
|
||||||
padding-bottom: 4rem;
|
|
||||||
}
|
|
||||||
.transaction {
|
|
||||||
gap: 1rem;
|
|
||||||
padding: 1rem;
|
|
||||||
background-color: rgba(var(--text-color), 0.03);
|
|
||||||
border-radius: 0.3rem;
|
|
||||||
&:not(:last-of-type) {
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
.icon {
|
|
||||||
fill: var(--accent-color);
|
|
||||||
}
|
|
||||||
&__time,
|
|
||||||
&__link,
|
|
||||||
&__receiver {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
}
|
|
||||||
&__receiver {
|
|
||||||
margin-left: 0.5rem;
|
|
||||||
color: rgba(var(--text-color), 0.8);
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
max-width: unset;
|
|
||||||
}
|
|
||||||
&__time {
|
|
||||||
justify-self: flex-end;
|
|
||||||
color: rgba(var(--text-color), 0.8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.fab {
|
.fab {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
@ -842,10 +832,6 @@ h3 {
|
|||||||
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.2);
|
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.2);
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
#scroll_to_top {
|
|
||||||
border-radius: 3rem;
|
|
||||||
background-color: rgba(var(--foreground-color), 1);
|
|
||||||
}
|
|
||||||
#add_address_button {
|
#add_address_button {
|
||||||
border-radius: 0.5rem;
|
border-radius: 0.5rem;
|
||||||
color: rgba(var(--background-color), 1);
|
color: rgba(var(--background-color), 1);
|
||||||
@ -866,6 +852,9 @@ h3 {
|
|||||||
form {
|
form {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
|
fieldset {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.token-balance {
|
.token-balance {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -887,6 +876,24 @@ h3 {
|
|||||||
accent-color: var(--accent-color);
|
accent-color: var(--accent-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.token-receiver-combo {
|
||||||
|
border: solid thin rgba(var(--text-color), 0.2);
|
||||||
|
padding: 0.5rem;
|
||||||
|
border-radius: 0.8rem;
|
||||||
|
&--removable {
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
|
grid-template-areas: "receiver receiver" "amount remove";
|
||||||
|
.token-receiver {
|
||||||
|
grid-area: receiver;
|
||||||
|
}
|
||||||
|
.token-amount {
|
||||||
|
grid-area: amount;
|
||||||
|
}
|
||||||
|
.remove-token-receiver {
|
||||||
|
grid-area: remove;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#transaction_result {
|
#transaction_result {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
@ -942,7 +949,38 @@ h3 {
|
|||||||
transform: scale(1) translateY(0);
|
transform: scale(1) translateY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#queried_address_transactions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
#pagination_wrapper {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0.5rem;
|
||||||
|
background-color: rgba(var(--foreground-color), 1);
|
||||||
|
z-index: 5;
|
||||||
|
border-radius: 0.7rem;
|
||||||
|
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.2);
|
||||||
|
margin: 0.5rem;
|
||||||
|
}
|
||||||
|
.pagination__item {
|
||||||
|
display: flex;
|
||||||
|
padding: 0.2rem 0.5rem;
|
||||||
|
border-radius: 0.3rem;
|
||||||
|
&--active {
|
||||||
|
background-color: var(--accent-color);
|
||||||
|
color: rgba(var(--background-color), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
legend,
|
||||||
|
.label {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: rgba(var(--text-color), 0.8);
|
||||||
|
}
|
||||||
#smartcontracts {
|
#smartcontracts {
|
||||||
display: grid;
|
display: grid;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
@ -958,11 +996,6 @@ h3 {
|
|||||||
padding: 0 0.5rem;
|
padding: 0 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
legend,
|
|
||||||
.label {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
color: rgba(var(--text-color), 0.8);
|
|
||||||
}
|
|
||||||
label {
|
label {
|
||||||
padding: 0.3rem 0.5rem;
|
padding: 0.3rem 0.5rem;
|
||||||
&:has(input:not(:disabled):not(:checked)) {
|
&:has(input:not(:disabled):not(:checked)) {
|
||||||
@ -1110,6 +1143,13 @@ h3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#pagination_wrapper {
|
||||||
|
margin: 0;
|
||||||
|
margin-bottom: 4.8rem;
|
||||||
|
left: 50%;
|
||||||
|
right: auto;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@media screen and (min-width: 40rem) {
|
@media screen and (min-width: 40rem) {
|
||||||
sm-popup {
|
sm-popup {
|
||||||
@ -1138,6 +1178,9 @@ h3 {
|
|||||||
#pages_container {
|
#pages_container {
|
||||||
grid-area: main;
|
grid-area: main;
|
||||||
}
|
}
|
||||||
|
.page {
|
||||||
|
padding: 0 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
#main_navbar {
|
#main_navbar {
|
||||||
grid-area: nav;
|
grid-area: nav;
|
||||||
@ -1175,9 +1218,10 @@ h3 {
|
|||||||
--width: 26rem;
|
--width: 26rem;
|
||||||
}
|
}
|
||||||
#send {
|
#send {
|
||||||
sm-form::part(form) {
|
padding: 0 6vw;
|
||||||
align-items: flex-start;
|
sm-form {
|
||||||
grid-template-columns: 45% 1fr;
|
width: min(56rem, 100%);
|
||||||
|
margin: auto;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#smart_contract_creation_templates {
|
#smart_contract_creation_templates {
|
||||||
@ -1213,9 +1257,17 @@ h3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@media screen and (min-width: 56rem) {
|
||||||
|
#send {
|
||||||
|
sm-form::part(form) {
|
||||||
|
align-items: flex-start;
|
||||||
|
grid-template-columns: 1fr 1.5fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@media screen and (min-width: 64rem) {
|
@media screen and (min-width: 64rem) {
|
||||||
#transactions_scroller {
|
#address_details_wrapper {
|
||||||
grid-template-columns: 22rem 1fr;
|
grid-template-columns: auto 1fr;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
#transactions_hero_section {
|
#transactions_hero_section {
|
||||||
|
|||||||
715
index.html
715
index.html
@ -7,6 +7,8 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="description"
|
<meta name="description"
|
||||||
content="This webapp allows monitoring FLO addresses and performing transactions based on FLO blockchain.">
|
content="This webapp allows monitoring FLO addresses and performing transactions based on FLO blockchain.">
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap"
|
||||||
rel="stylesheet">
|
rel="stylesheet">
|
||||||
@ -45,7 +47,6 @@
|
|||||||
floGlobals.scMap = new Map()
|
floGlobals.scMap = new Map()
|
||||||
floGlobals.tokens = tokens.sort((a, b) => a.localeCompare(b))
|
floGlobals.tokens = tokens.sort((a, b) => a.localeCompare(b))
|
||||||
floGlobals.smartContracts = smartContracts
|
floGlobals.smartContracts = smartContracts
|
||||||
.filter(sc => sc.status === 'active')
|
|
||||||
.sort((a, b) => a.contractName.localeCompare(b.contractName))
|
.sort((a, b) => a.contractName.localeCompare(b.contractName))
|
||||||
floGlobals.smartContracts.forEach((sc, index) => {
|
floGlobals.smartContracts.forEach((sc, index) => {
|
||||||
floGlobals.scMap.set(`${sc.contractName}_${sc.contractAddress}`, index)
|
floGlobals.scMap.set(`${sc.contractName}_${sc.contractAddress}`, index)
|
||||||
@ -53,7 +54,11 @@
|
|||||||
routeTo(window.location.hash, { firstLoad: true })
|
routeTo(window.location.hash, { firstLoad: true })
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
notify('Error fetching tokens', 'error')
|
if (window.location.hash.includes('smartcontracts'))
|
||||||
|
routeTo('', { firstLoad: true })
|
||||||
|
else
|
||||||
|
routeTo(window.location.hash, { firstLoad: true })
|
||||||
|
getRef('smart_contract_link').classList.add('hidden')
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
loader(false)
|
loader(false)
|
||||||
})
|
})
|
||||||
@ -118,8 +123,7 @@
|
|||||||
<theme-toggle></theme-toggle>
|
<theme-toggle></theme-toggle>
|
||||||
</header>
|
</header>
|
||||||
<div id="pages_container">
|
<div id="pages_container">
|
||||||
<div id="home" class="page flex h-100">
|
<div id="search" class="page flex h-100 gap-1-5">
|
||||||
<div class="flex direction-column gap-2 h-100">
|
|
||||||
<section id="primary_actions_wrapper">
|
<section id="primary_actions_wrapper">
|
||||||
<button id="gen_new_addr_btn" class="button primary-action interact">
|
<button id="gen_new_addr_btn" class="button primary-action interact">
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24"
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24"
|
||||||
@ -146,16 +150,84 @@
|
|||||||
</svg>
|
</svg>
|
||||||
Retrieve FLO address
|
Retrieve FLO address
|
||||||
</button>
|
</button>
|
||||||
<button class="button primary-action interact" onclick="openPopup('check_balance_popup')">
|
|
||||||
<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
|
|
||||||
d="M21 18v1c0 1.1-.9 2-2 2H5c-1.11 0-2-.9-2-2V5c0-1.1.89-2 2-2h14c1.1 0 2 .9 2 2v1h-9c-1.11 0-2 .9-2 2v8c0 1.1.89 2 2 2h9zm-9-2h10V8H12v8zm4-2.5c-.83 0-1.5-.67-1.5-1.5s.67-1.5 1.5-1.5 1.5.67 1.5 1.5-.67 1.5-1.5 1.5z" />
|
|
||||||
</svg>
|
|
||||||
Check balance
|
|
||||||
</button>
|
|
||||||
</section>
|
</section>
|
||||||
|
<sm-form id="search_wrapper" class="flex margin-bottom-2" style="--gap: 0.5rem;">
|
||||||
|
<sm-input type="search" id="search_query_input" class="flex-1" placeholder="Search FLO address"
|
||||||
|
required>
|
||||||
|
<svg slot="icon" 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.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />
|
||||||
|
</svg>
|
||||||
|
</sm-input>
|
||||||
|
<button id="process_query" class="button button--primary cta" style="height: 3.2rem;"
|
||||||
|
onclick="processQuery()" type="submit" disabled>Search</button>
|
||||||
|
</sm-form>
|
||||||
|
<div id="address_details_wrapper" class="grid gap-1-5 hidden">
|
||||||
|
<div id="transactions_hero_section" class="grid gap-2"
|
||||||
|
style="background-color: rgba(var(--text-color), 0.03); padding: 1.5rem 1rem; border-radius: 0.5rem;">
|
||||||
|
<div id="queried_flo_address"></div>
|
||||||
|
<div class="flex align-center">
|
||||||
|
<svg class="icon margin-right-0-5" viewBox="0 0 48 48"
|
||||||
|
style="enable-background:new 0 0 107.65 47.07;" xml:space="preserve">
|
||||||
|
<path class="flo-logo"
|
||||||
|
d="M34.2,32.4c0,0,3.75-0.18,7.41-3.86c2.96-2.98,3.65-6.66,3.99-8.52c-11.04-0.63-12.36,0.99-13.71,1.68
|
||||||
|
c-1.19,0.61-5.33,4.55-5.33,4.55s3.06-3.13,3.2-9.94c0.09-4.54-1.02-7.39-2.72-10.64C25.29,2.33,22.79,0,22.79,0l0.01,4.97
|
||||||
|
c0,0,4.35,2.84,4.35,11.84c0,6.52-4.35,11.02-4.35,11.02s-4.35-4.5-4.35-11.02c0-9.01,4.35-11.84,4.35-11.84L22.79,0
|
||||||
|
c0,0-2.48,2.33-4.23,5.67c-1.7,3.25-2.81,6.1-2.72,10.64c0.13,6.81,3.2,9.94,3.2,9.94s-4.14-3.95-5.33-4.55
|
||||||
|
c-1.35-0.69-2.67-2.31-13.71-1.68c0.34,1.86,1.03,5.54,3.99,8.52c3.66,3.68,7.41,3.86,7.41,3.86s-5.05-2.03-7.15-9.45
|
||||||
|
c0,0,5.76-0.7,9.63,1.87c2.52,1.67,4.86,4.26,6.79,6.01c0,0-2.58-0.04-6.81,1.88c-2.54,1.15-3.92,2.84-4.44,4.38
|
||||||
|
c-0.36,1.06-0.2,2.27-0.2,2.27s3.31,0.31,5.94,0c1.99-0.23,3.42-2.16,3.42-2.16s-2,0.78-3.95,0.78c-2.06,0-2.67-0.66-2.67-0.66
|
||||||
|
c0.98-3.64,8.68-5.19,8.68-5.19s-1.34,2.6-1.42,6.5c-0.1,4.79,3.57,8.52,3.57,8.45c0,0.07,3.67-3.66,3.57-8.45
|
||||||
|
c-0.08-3.9-1.42-6.5-1.42-6.5s7.71,1.55,8.68,5.19c0,0-0.61,0.66-2.67,0.66c-1.95,0-3.95-0.78-3.95-0.78s1.43,1.93,3.42,2.16
|
||||||
|
c2.63,0.31,5.94,0,5.94,0s0.16-1.21-0.2-2.27c-0.52-1.54-1.9-3.23-4.44-4.38c-4.23-1.92-6.81-1.88-6.81-1.88
|
||||||
|
c1.93-1.76,4.27-4.34,6.79-6.01c3.87-2.57,9.63-1.87,9.63-1.87C39.26,30.38,34.2,32.4,34.2,32.4z M22.8,43.06
|
||||||
|
c-0.95-1.37-1.47-2.13-1.47-4.26c0-2.4,1.12-4.61,1.47-5.14c0.35,0.52,1.47,2.74,1.47,5.14C24.27,40.92,23.75,41.69,22.8,43.06z">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
<div class="grid gap-0-5">
|
||||||
|
<h5>FLO balance</h5>
|
||||||
|
<span id="flo_balance"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="token_list_wrapper" class="grid gap-0-5 hidden">
|
||||||
|
<div class="flex align-center">
|
||||||
|
<svg class="icon margin-right-0-5" xmlns="http://www.w3.org/2000/svg" height="24px"
|
||||||
|
viewBox="0 0 24 24" width="24px" fill="#000000">
|
||||||
|
<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 6z" />
|
||||||
|
<path
|
||||||
|
d="M3 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>
|
||||||
|
<h5>Tokens owned</h5>
|
||||||
|
</div>
|
||||||
|
<ul id="token_list"></ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<section class="grid gap-1">
|
||||||
|
<div class="flex align-center space-between sticky top-0"
|
||||||
|
style="background-color: rgba(var(--foreground-color), 1);">
|
||||||
|
<h4>Transactions</h4>
|
||||||
|
<sm-chips id="filter_selector" class="hidden">
|
||||||
|
<sm-chip value="sent" selected>Sent</sm-chip>
|
||||||
|
<sm-chip value="received">Received</sm-chip>
|
||||||
|
<sm-chip value="all">All</sm-chip>
|
||||||
|
</sm-chips>
|
||||||
|
</div>
|
||||||
|
<ul id="queried_address_transactions" class="observe-empty-state"></ul>
|
||||||
|
<div class="empty-state">
|
||||||
|
<h4>
|
||||||
|
Looks a bit empty here, no transactions yet.
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<div id="pagination_wrapper" class="flex gap-0-3 align-center"> </div>
|
||||||
|
</div>
|
||||||
|
<div id="contacts" class="page flex h-100">
|
||||||
|
<div class="flex direction-column gap-2 h-100">
|
||||||
<section class="flex direction-column h-100">
|
<section class="flex direction-column h-100">
|
||||||
<div class="grid align-center gap-0-5">
|
<div class="grid align-center gap-0-5">
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
@ -235,108 +307,6 @@
|
|||||||
Add FLO address
|
Add FLO address
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="transactions" class="hidden page">
|
|
||||||
<header class="grid">
|
|
||||||
<div class="grid align-center w-100">
|
|
||||||
<a href="#/home" class="flex interact icon-only">
|
|
||||||
<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 d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" />
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
<button class="icon-only" style="margin-left:auto" onclick="render.transactions()"
|
|
||||||
title="Refresh">
|
|
||||||
<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
|
|
||||||
d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div id="queried_flo_address"></div>
|
|
||||||
</header>
|
|
||||||
<section id="transactions_scroller" class="grid gap-2" style="overflow-y: auto;padding: 0 1rem;">
|
|
||||||
<div id="transactions_hero_section" class="grid gap-2"
|
|
||||||
style="background-color: rgba(var(--text-color), 0.03); padding: 1.5rem 1rem; border-radius: 0.5rem;">
|
|
||||||
<div class="flex align-center">
|
|
||||||
<svg class="icon margin-right-0-5" viewBox="0 0 48 48"
|
|
||||||
style="enable-background:new 0 0 107.65 47.07;" xml:space="preserve">
|
|
||||||
<path class="flo-logo"
|
|
||||||
d="M34.2,32.4c0,0,3.75-0.18,7.41-3.86c2.96-2.98,3.65-6.66,3.99-8.52c-11.04-0.63-12.36,0.99-13.71,1.68
|
|
||||||
c-1.19,0.61-5.33,4.55-5.33,4.55s3.06-3.13,3.2-9.94c0.09-4.54-1.02-7.39-2.72-10.64C25.29,2.33,22.79,0,22.79,0l0.01,4.97
|
|
||||||
c0,0,4.35,2.84,4.35,11.84c0,6.52-4.35,11.02-4.35,11.02s-4.35-4.5-4.35-11.02c0-9.01,4.35-11.84,4.35-11.84L22.79,0
|
|
||||||
c0,0-2.48,2.33-4.23,5.67c-1.7,3.25-2.81,6.1-2.72,10.64c0.13,6.81,3.2,9.94,3.2,9.94s-4.14-3.95-5.33-4.55
|
|
||||||
c-1.35-0.69-2.67-2.31-13.71-1.68c0.34,1.86,1.03,5.54,3.99,8.52c3.66,3.68,7.41,3.86,7.41,3.86s-5.05-2.03-7.15-9.45
|
|
||||||
c0,0,5.76-0.7,9.63,1.87c2.52,1.67,4.86,4.26,6.79,6.01c0,0-2.58-0.04-6.81,1.88c-2.54,1.15-3.92,2.84-4.44,4.38
|
|
||||||
c-0.36,1.06-0.2,2.27-0.2,2.27s3.31,0.31,5.94,0c1.99-0.23,3.42-2.16,3.42-2.16s-2,0.78-3.95,0.78c-2.06,0-2.67-0.66-2.67-0.66
|
|
||||||
c0.98-3.64,8.68-5.19,8.68-5.19s-1.34,2.6-1.42,6.5c-0.1,4.79,3.57,8.52,3.57,8.45c0,0.07,3.67-3.66,3.57-8.45
|
|
||||||
c-0.08-3.9-1.42-6.5-1.42-6.5s7.71,1.55,8.68,5.19c0,0-0.61,0.66-2.67,0.66c-1.95,0-3.95-0.78-3.95-0.78s1.43,1.93,3.42,2.16
|
|
||||||
c2.63,0.31,5.94,0,5.94,0s0.16-1.21-0.2-2.27c-0.52-1.54-1.9-3.23-4.44-4.38c-4.23-1.92-6.81-1.88-6.81-1.88
|
|
||||||
c1.93-1.76,4.27-4.34,6.79-6.01c3.87-2.57,9.63-1.87,9.63-1.87C39.26,30.38,34.2,32.4,34.2,32.4z M22.8,43.06
|
|
||||||
c-0.95-1.37-1.47-2.13-1.47-4.26c0-2.4,1.12-4.61,1.47-5.14c0.35,0.52,1.47,2.74,1.47,5.14C24.27,40.92,23.75,41.69,22.8,43.06z">
|
|
||||||
</path>
|
|
||||||
</svg>
|
|
||||||
<div class="grid gap-0-5">
|
|
||||||
<h5>FLO balance</h5>
|
|
||||||
<span id="flo_balance"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="tokens" class="grid gap-0-5 hidden">
|
|
||||||
<div class="flex align-center">
|
|
||||||
<svg class="icon margin-right-0-5" xmlns="http://www.w3.org/2000/svg" height="24px"
|
|
||||||
viewBox="0 0 24 24" width="24px" fill="#000000">
|
|
||||||
<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 6z" />
|
|
||||||
<path
|
|
||||||
d="M3 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>
|
|
||||||
<h5>Tokens owned</h5>
|
|
||||||
</div>
|
|
||||||
<ul id="token_list"></ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="grid gap-0-5">
|
|
||||||
<div id="transactions_header" class="flex align-center space-between sticky top-0"
|
|
||||||
style="background-color: rgba(var(--foreground-color),1); padding-bottom: 0.5rem;">
|
|
||||||
<div class="flex">
|
|
||||||
<svg class="icon margin-right-0-5" xmlns="http://www.w3.org/2000/svg" height="24px"
|
|
||||||
viewBox="0 0 24 24" width="24px" fill="#000000">
|
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
|
||||||
<path d="M16 17.01V10h-2v7.01h-3L15 21l4-3.99h-3zM9 3L5 6.99h3V14h2V6.99h3L9 3z" />
|
|
||||||
</svg>
|
|
||||||
<h5>Transactions</h5>
|
|
||||||
</div>
|
|
||||||
<sm-chips id="filter_selector">
|
|
||||||
<sm-chip value="sent" selected>Sent</sm-chip>
|
|
||||||
<sm-chip value="received">Received</sm-chip>
|
|
||||||
<sm-chip value="all">All</sm-chip>
|
|
||||||
</sm-chips>
|
|
||||||
</div>
|
|
||||||
<ul id="transactions_list" class="flex observe-empty-state"></ul>
|
|
||||||
<div class="empty-state">
|
|
||||||
<h4>
|
|
||||||
Looks a bit empty here, no transactions yet.
|
|
||||||
</h4>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<div class="empty-state justify-center align-center h-100">
|
|
||||||
<div class="grid justify-center text-center gap-1">
|
|
||||||
<sm-spinner class="justify-self-center"></sm-spinner>
|
|
||||||
<span>Loading transactions</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button id="scroll_to_top" class="fab hidden" onclick="backToTop()">
|
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px"
|
|
||||||
fill="#000000">
|
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
|
||||||
<path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div id="send" class="page hidden gap-1">
|
<div id="send" class="page hidden gap-1">
|
||||||
<div class="grid full-bleed">
|
<div class="grid full-bleed">
|
||||||
<h3>Send</h3>
|
<h3>Send</h3>
|
||||||
@ -352,6 +322,8 @@
|
|||||||
Sender balance will be shown once you enter sender private key
|
Sender balance will be shown once you enter sender private key
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="grid gap-1">
|
||||||
<sm-input id="get_private_key_field" placeholder="Sender's private key" class="password-field"
|
<sm-input id="get_private_key_field" placeholder="Sender's private key" class="password-field"
|
||||||
type="password" error-text="Invalid private key" data-private-key required autofocus>
|
type="password" error-text="Invalid private key" data-private-key required autofocus>
|
||||||
<label slot="right" class="interact">
|
<label slot="right" class="interact">
|
||||||
@ -373,12 +345,14 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</label>
|
</label>
|
||||||
</sm-input>
|
</sm-input>
|
||||||
<sm-input id="receiver" class="w-100" placeholder="Receiver's FLO address"
|
<div class="grid gap-1">
|
||||||
|
<div id="tx_receiver_wrapper" class="grid gap-1">
|
||||||
|
<sm-input id="tx_receiver" class="w-100" placeholder="Receiver's FLO address"
|
||||||
error-text="Invalid FLO address" data-flo-address="" animate required>
|
error-text="Invalid FLO address" data-flo-address="" animate required>
|
||||||
<button slot="right" class="icon-only" onclick="openPopup('saved_ids_popup')"
|
<button slot="right" class="icon-only" onclick="openPopup('saved_ids_popup')"
|
||||||
title="Select from saved IDs">
|
title="Select from saved IDs">
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24"
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px"
|
||||||
width="24px" fill="#000000">
|
viewBox="0 0 24 24" width="24px" fill="#000000">
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
<path
|
<path
|
||||||
d="M21 5v14h2V5h-2zm-4 14h2V5h-2v14zM14 5H2c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V6c0-.55-.45-1-1-1zM8 7.75c1.24 0 2.25 1.01 2.25 2.25S9.24 12.25 8 12.25 5.75 11.24 5.75 10 6.76 7.75 8 7.75zM12.5 17h-9v-.75c0-1.5 3-2.25 4.5-2.25s4.5.75 4.5 2.25V17z" />
|
d="M21 5v14h2V5h-2zm-4 14h2V5h-2v14zM14 5H2c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V6c0-.55-.45-1-1-1zM8 7.75c1.24 0 2.25 1.01 2.25 2.25S9.24 12.25 8 12.25 5.75 11.24 5.75 10 6.76 7.75 8 7.75zM12.5 17h-9v-.75c0-1.5 3-2.25 4.5-2.25s4.5.75 4.5 2.25V17z" />
|
||||||
@ -386,13 +360,20 @@
|
|||||||
</button>
|
</button>
|
||||||
</sm-input>
|
</sm-input>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid gap-1">
|
<button id="add_token_receiver"
|
||||||
|
class="button button--small gap-0-5 justify-self-start hidden"
|
||||||
|
onclick="addTokenReceiver()">
|
||||||
|
<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 d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
|
||||||
|
</svg>
|
||||||
|
<span>Add token receiver</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<sm-input id="tx_flo_amount" type="number" placeholder="FLO amount" step="0.00000001"
|
<sm-input id="tx_flo_amount" type="number" placeholder="FLO amount" step="0.00000001"
|
||||||
min="0.00000001" error-text="Invalid amount" animate required>
|
min="0.00000001" error-text="Invalid amount" animate required>
|
||||||
</sm-input>
|
</sm-input>
|
||||||
<sm-input id="tx_token_amount" type="number" class="hidden" placeholder="Token amount"
|
|
||||||
step="0.00000001" min="0.00000001" error-text="Invalid amount" animate required disabled>
|
|
||||||
</sm-input>
|
|
||||||
<div id="flo_data_wrapper" class="grid gap-0-5">
|
<div id="flo_data_wrapper" class="grid gap-0-5">
|
||||||
<sm-textarea id="flo_data_textarea" placeholder="FLO data" rows="8" maxlength="1040"
|
<sm-textarea id="flo_data_textarea" placeholder="FLO data" rows="8" maxlength="1040"
|
||||||
animate>
|
animate>
|
||||||
@ -613,13 +594,25 @@
|
|||||||
<nav id="main_navbar">
|
<nav id="main_navbar">
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
<a href="#/home" class="nav-item interact">
|
<a href="#/search" class="nav-item interact">
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24"
|
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24"
|
||||||
width="24px" fill="#000000">
|
width="24px" fill="#000000">
|
||||||
<path d="M0 0h24v24H0z" fill="none" />
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
<path d="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" />
|
<path
|
||||||
|
d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" />
|
||||||
</svg>
|
</svg>
|
||||||
<span class="nav-item__title">Home</span>
|
<span class="nav-item__title">Search</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#/contacts" class="nav-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 0h24v24H0zm0 0h24v24H0zm0 0h24v24H0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M20 0H4v2h16V0zM4 24h16v-2H4v2zM20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 2.75c1.24 0 2.25 1.01 2.25 2.25s-1.01 2.25-2.25 2.25S9.75 10.24 9.75 9 10.76 6.75 12 6.75zM17 17H7v-1.5c0-1.67 3.33-2.5 5-2.5s5 .83 5 2.5V17z" />
|
||||||
|
</svg>
|
||||||
|
<span class="nav-item__title">Contacts</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
@ -633,7 +626,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#/smartcontracts" class="nav-item interact" title='Send FLO data'>
|
<a id="smart_contract_link" href="#/smartcontracts" class="nav-item interact" title='Send FLO data'>
|
||||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24"
|
<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">
|
height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
|
||||||
<path d="M0,0h24v24H0V0z" fill="none" />
|
<path d="M0,0h24v24H0V0z" fill="none" />
|
||||||
@ -789,30 +782,6 @@
|
|||||||
</sm-form>
|
</sm-form>
|
||||||
</section>
|
</section>
|
||||||
</sm-popup>
|
</sm-popup>
|
||||||
<sm-popup id="check_balance_popup">
|
|
||||||
<header slot="header" class="popup__header">
|
|
||||||
<button class="popup__header__close justify-self-start" onclick="closePopup()">
|
|
||||||
<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="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<h3>Check balance</h3>
|
|
||||||
</header>
|
|
||||||
<sm-form id="check_balance_form">
|
|
||||||
<sm-input id="check_balance_field" type="text" error-text="Invalid FLO address" placeholder="FLO address"
|
|
||||||
data-flo-address="" required autofocus>
|
|
||||||
</sm-input>
|
|
||||||
<div class="multi-state-button">
|
|
||||||
<button id="check_balance_button" class="button button--primary cta" type="submit"
|
|
||||||
onclick="checkBalance()" disabled>Check</button>
|
|
||||||
</div>
|
|
||||||
</sm-form>
|
|
||||||
<div id="balance_wrapper" class="hidden grid gap-0-5" style="margin-top: 2rem">
|
|
||||||
</div>
|
|
||||||
</sm-popup>
|
|
||||||
<sm-popup id="saved_ids_popup">
|
<sm-popup id="saved_ids_popup">
|
||||||
<header slot="header" class="popup__header">
|
<header slot="header" class="popup__header">
|
||||||
<button class="popup__header__close justify-self-start" onclick="closePopup()">
|
<button class="popup__header__close justify-self-start" onclick="closePopup()">
|
||||||
@ -876,7 +845,7 @@
|
|||||||
<li class="transaction grid">
|
<li class="transaction grid">
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
<div class="transaction__icon"></div>
|
<div class="transaction__icon"></div>
|
||||||
<div class="transaction__receiver"></div>
|
<div class="transaction__receiver breakable"></div>
|
||||||
</div>
|
</div>
|
||||||
<p class="transaction__flo-data breakable"></p>
|
<p class="transaction__flo-data breakable"></p>
|
||||||
<div class="flex align-center space-between">
|
<div class="flex align-center space-between">
|
||||||
@ -1010,10 +979,6 @@
|
|||||||
case 'retrieve_flo_id_popup':
|
case 'retrieve_flo_id_popup':
|
||||||
getRef('recovered_flo_id_wrapper').classList.add('hidden')
|
getRef('recovered_flo_id_wrapper').classList.add('hidden')
|
||||||
break;
|
break;
|
||||||
case 'check_balance_popup':
|
|
||||||
getRef('balance_wrapper').classList.add('hidden')
|
|
||||||
getRef('check_balance_form')._checkValidity()
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1232,7 +1197,7 @@
|
|||||||
let searchParams
|
let searchParams
|
||||||
let wildcards
|
let wildcards
|
||||||
if (targetPage === '') {
|
if (targetPage === '') {
|
||||||
pageId = 'home'
|
pageId = 'search'
|
||||||
} else {
|
} else {
|
||||||
if (targetPage.includes('/')) {
|
if (targetPage.includes('/')) {
|
||||||
let path;
|
let path;
|
||||||
@ -1252,19 +1217,34 @@
|
|||||||
if (params)
|
if (params)
|
||||||
pagesData.params = params
|
pagesData.params = params
|
||||||
switch (pageId) {
|
switch (pageId) {
|
||||||
case 'transactions':
|
case 'search': {
|
||||||
const floId = wildcards[0]
|
const { type, query, page = 1 } = params
|
||||||
if (floId && floCrypto.validateFloID(floId)) {
|
switch (type) {
|
||||||
render.transactions(floId).then(() => {
|
case 'address':
|
||||||
if (getRef('transactions_list').firstElementChild) {
|
try {
|
||||||
scrollToTopObserver.observe(getRef('transactions_list').firstElementChild)
|
if (floGlobals.query.string !== query) {
|
||||||
getRef('filter_selector').classList.remove('hidden')
|
checkBalance(query)
|
||||||
} else {
|
renderElem(getRef('queried_address_transactions'), html`
|
||||||
getRef('filter_selector').classList.add('hidden')
|
<div class="grid gap-1 justify-items-center text-center" style="margin: 3rem 0">
|
||||||
}
|
<sm-spinner></sm-spinner>
|
||||||
|
<span>Loading transactions...</span>
|
||||||
|
</div>
|
||||||
|
`)
|
||||||
|
fetchTransactions(query).then(() => {
|
||||||
|
filterFetchedTransactions()
|
||||||
|
render.paginatedTransactions(parseInt(page))
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
notify('Invalid Flo ID', 'error')
|
render.paginatedTransactions(parseInt(page))
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
notify(err, 'error')
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'txid':
|
||||||
|
// location.href = `#/tx/${query}`
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'smartcontracts':
|
case 'smartcontracts':
|
||||||
@ -1537,9 +1517,6 @@
|
|||||||
renderElem(getRef('smart_contract_creation_form'), html``)
|
renderElem(getRef('smart_contract_creation_form'), html``)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
default:
|
|
||||||
getRef('transactions_list').innerHTML = ''
|
|
||||||
scrollToTopObserver.disconnect()
|
|
||||||
}
|
}
|
||||||
const animOptions = {
|
const animOptions = {
|
||||||
duration: 100,
|
duration: 100,
|
||||||
@ -1921,7 +1898,7 @@
|
|||||||
},
|
},
|
||||||
transactionCard(details) {
|
transactionCard(details) {
|
||||||
const { sender, receiver, floData, time, txid } = details
|
const { sender, receiver, floData, time, txid } = details
|
||||||
const queriedFloId = pagesData.wildcards[0]
|
const { query: queriedFloId } = pagesData.params
|
||||||
const clone = getRef('transaction_template').content.cloneNode(true).firstElementChild;
|
const clone = getRef('transaction_template').content.cloneNode(true).firstElementChild;
|
||||||
if (sender === receiver) {
|
if (sender === receiver) {
|
||||||
clone.querySelector('.transaction__icon').innerHTML = `<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><title>sender and receiver is same</title><path d="M.01 0h24v24h-24V0z" fill="none"/><path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"/></svg>`;
|
clone.querySelector('.transaction__icon').innerHTML = `<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><title>sender and receiver is same</title><path d="M.01 0h24v24h-24V0z" fill="none"/><path d="M12 4V1L8 5l4 4V6c3.31 0 6 2.69 6 6 0 1.01-.25 1.97-.7 2.8l1.46 1.46C19.54 15.03 20 13.57 20 12c0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-1.01.25-1.97.7-2.8L5.24 7.74C4.46 8.97 4 10.43 4 12c0 4.42 3.58 8 8 8v3l4-4-4-4v3z"/></svg>`;
|
||||||
@ -1936,66 +1913,52 @@
|
|||||||
clone.querySelector('.transaction__time').textContent = getFormattedTime(time * 1000)
|
clone.querySelector('.transaction__time').textContent = getFormattedTime(time * 1000)
|
||||||
return clone
|
return clone
|
||||||
},
|
},
|
||||||
async transactions(queriedFloId = pagesData.wildcards[0]) {
|
paginatedTransactions(page = 1) {
|
||||||
try {
|
const startingIndex = ((page - 1) * 20)
|
||||||
scrollToTopObserver.disconnect()
|
const endingIndex = startingIndex + 20
|
||||||
// retrieve tokens and render them
|
const { transactions, string: address } = floGlobals.query
|
||||||
getRef('tokens').classList.add('hidden')
|
const renderedTransactions = transactions
|
||||||
fetchJSON(`${floGlobals.tokenApiUrl}/api/v2/floAddressBalance/${queriedFloId}`).then(({ floAddressBalances }) => {
|
.slice(startingIndex, endingIndex)
|
||||||
let ownedTokens = []
|
.map(transaction => render.transactionCard(transaction))
|
||||||
for (const token in floAddressBalances) {
|
renderElem(getRef('queried_address_transactions'), html`${renderedTransactions}`)
|
||||||
ownedTokens.push(html`
|
getRef('transactions_hero_section').scrollIntoView({
|
||||||
<li class="token-item">
|
behavior: 'smooth',
|
||||||
<span>${token}: </span><span>${parseFloat((floAddressBalances[token].balance || 0).toFixed(8))}</span>
|
block: 'start'
|
||||||
</li>
|
})
|
||||||
|
if (renderedTransactions.length) {
|
||||||
|
getRef('filter_selector').classList.remove('hidden')
|
||||||
|
} else {
|
||||||
|
getRef('filter_selector').classList.add('hidden')
|
||||||
|
}
|
||||||
|
const paginationSegments = transactions ? Math.ceil(transactions.length / renderTransactions) : 0;
|
||||||
|
let pagination = []
|
||||||
|
let startingPage = page - 2;
|
||||||
|
let showTill = page + 2;
|
||||||
|
if (startingPage < 1) {
|
||||||
|
showTill += Math.abs(startingPage) + 1;
|
||||||
|
startingPage = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showTill > paginationSegments) {
|
||||||
|
startingPage -= showTill - paginationSegments;
|
||||||
|
showTill = paginationSegments;
|
||||||
|
}
|
||||||
|
if (paginationSegments > 1) {
|
||||||
|
for (let i = 1; i <= paginationSegments; i++) {
|
||||||
|
if (startingPage <= i && i <= showTill) {
|
||||||
|
pagination.push(html`
|
||||||
|
<a href=${`#/search?type=address&query=${address}&page=${i}`} class=${`pagination__item ${i === page ? 'pagination__item--active' : ''}`}>
|
||||||
|
${i}
|
||||||
|
</a>
|
||||||
`)
|
`)
|
||||||
|
} else if (i === showTill + 1 && i < paginationSegments) {
|
||||||
|
pagination.push(html` <div class="pagination__item">...</div> `)
|
||||||
|
} else if (i == paginationSegments) {
|
||||||
|
pagination.push(html` <a href=${`#/search?type=address&query=${address}&page=${i}`} class="pagination__item">${i}</a> `)
|
||||||
}
|
}
|
||||||
if (ownedTokens.length) {
|
|
||||||
renderElem(getRef('token_list'), html`${ownedTokens}`)
|
|
||||||
getRef('tokens').classList.remove('hidden')
|
|
||||||
}
|
}
|
||||||
}).catch(e => {
|
|
||||||
console.error(e)
|
|
||||||
})
|
|
||||||
// retrieve FLO balance
|
|
||||||
getRef('flo_balance').innerHTML = `<sm-spinner></sm-spinner>`;
|
|
||||||
floWebWallet.getBalance(queriedFloId).then((retrievedBal) => {
|
|
||||||
getRef('flo_balance').textContent = `${parseFloat(retrievedBal.toFixed(3))} FLO`;
|
|
||||||
}).catch((error) => {
|
|
||||||
notify(error, 'error');
|
|
||||||
})
|
|
||||||
floWebWallet.getLabels().then(allLabels => {
|
|
||||||
if (allLabels[queriedFloId]) {
|
|
||||||
renderElem(getRef('queried_flo_address'), html`<h4>${allLabels[queriedFloId]}</h4> <sm-copy clip-text value=${queriedFloId}></sm-copy>`)
|
|
||||||
} else {
|
|
||||||
renderElem(getRef('queried_flo_address'), html`<h4><sm-copy clip-text value=${queriedFloId}></sm-copy></h4>`)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
// show spinner
|
|
||||||
getRef('transactions_scroller').nextElementSibling.classList.remove('hidden')
|
|
||||||
getRef('transactions_scroller').classList.add('hidden')
|
|
||||||
getRef('transactions_list').innerHTML = '';
|
|
||||||
await floWebWallet.syncTransactions(queriedFloId);
|
|
||||||
let allTransactions = (await floWebWallet.readTransactions(queriedFloId)).reverse();
|
|
||||||
const filter = getRef('filter_selector').value;
|
|
||||||
if (filter !== 'all') {
|
|
||||||
allTransactions = allTransactions.filter(t => filter === 'sent' ? t.sender === queriedFloId : t.receiver === queriedFloId)
|
|
||||||
}
|
|
||||||
// render transactions
|
|
||||||
if (transactionsLazyLoader) {
|
|
||||||
transactionsLazyLoader.update(allTransactions)
|
|
||||||
} else {
|
|
||||||
transactionsLazyLoader = new LazyLoader('#transactions_list', allTransactions, render.transactionCard)
|
|
||||||
transactionsLazyLoader.init()
|
|
||||||
}
|
|
||||||
getRef('transactions_scroller').classList.remove('hidden')
|
|
||||||
getRef('transactions_scroller').nextElementSibling.classList.add('hidden')
|
|
||||||
getRef('transactions_scroller').scroll({
|
|
||||||
top: 0
|
|
||||||
})
|
|
||||||
} catch (err) {
|
|
||||||
notify(err, 'error');
|
|
||||||
}
|
}
|
||||||
|
renderElem(getRef('pagination_wrapper'), html`${pagination}`)
|
||||||
},
|
},
|
||||||
availableAssetOptions() {
|
availableAssetOptions() {
|
||||||
return (floGlobals.tokens || []).map(token => html` <sm-option value=${token}>${token}</sm-option> `)
|
return (floGlobals.tokens || []).map(token => html` <sm-option value=${token}>${token}</sm-option> `)
|
||||||
@ -2171,24 +2134,20 @@
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const target = e.target.closest('.saved-id');
|
const target = e.target.closest('.saved-id');
|
||||||
window.location.hash = `#/transactions/${target.dataset.floAddress}`
|
window.location.hash = `#/search?type=address&query=${target.dataset.floAddress}&page=1`
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
delegate(getRef('saved_ids_picker_list'), 'click', '.saved-id', e => {
|
delegate(getRef('saved_ids_picker_list'), 'click', '.saved-id', e => {
|
||||||
const target = e.target.closest('.saved-id');
|
const target = e.target.closest('.saved-id');
|
||||||
getRef('receiver').value = target.dataset.floAddress
|
document.getElementById('tx_receiver').value = target.dataset.floAddress
|
||||||
getRef('receiver').focusIn()
|
document.getElementById('tx_receiver').focusIn()
|
||||||
closePopup()
|
closePopup()
|
||||||
})
|
})
|
||||||
|
|
||||||
getRef('filter_selector').addEventListener('change', async e => {
|
getRef('filter_selector').addEventListener('change', async e => {
|
||||||
const queriedFloId = pagesData.wildcards[0]
|
floGlobals.query.transactions = (await floWebWallet.readTransactions(floGlobals.query.string)).reverse();
|
||||||
const filter = e.target.value
|
filterFetchedTransactions()
|
||||||
let allTransactions = (await floWebWallet.readTransactions(queriedFloId)).reverse()
|
render.paginatedTransactions()
|
||||||
if (filter !== 'all') {
|
|
||||||
allTransactions = allTransactions.filter(t => filter === 'sent' ? t.sender === queriedFloId : t.receiver === queriedFloId)
|
|
||||||
}
|
|
||||||
transactionsLazyLoader.update(allTransactions)
|
|
||||||
})
|
})
|
||||||
const scrollToTopObserver = new IntersectionObserver(entries => {
|
const scrollToTopObserver = new IntersectionObserver(entries => {
|
||||||
entries.forEach(entry => {
|
entries.forEach(entry => {
|
||||||
@ -2355,13 +2314,15 @@
|
|||||||
</label>
|
</label>
|
||||||
`)
|
`)
|
||||||
renderElem(document.getElementById('sender_tokens_wrapper'), html.for(document.getElementById('sender_tokens_wrapper'), senderFloAddr)`
|
renderElem(document.getElementById('sender_tokens_wrapper'), html.for(document.getElementById('sender_tokens_wrapper'), senderFloAddr)`
|
||||||
|
<div class="grid">
|
||||||
<h5>Tokens</h5>
|
<h5>Tokens</h5>
|
||||||
<p>Select a token, if you want to send a token.</p>
|
<p>Select a token, if you want to send a token.</p>
|
||||||
<form onsubmit="event.preventDefault()" onchange=${handleTokenSelection} class="grid gap-1">
|
</div>
|
||||||
|
<fieldset onchange=${handleTokenSelection} class="grid gap-1">
|
||||||
<div class="grid gap-0-5">
|
<div class="grid gap-0-5">
|
||||||
${ownedTokens}
|
${ownedTokens}
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</fieldset>
|
||||||
`)
|
`)
|
||||||
document.getElementById('sender_tokens_wrapper').classList.remove('hidden')
|
document.getElementById('sender_tokens_wrapper').classList.remove('hidden')
|
||||||
handleTokenSelection()
|
handleTokenSelection()
|
||||||
@ -2374,13 +2335,21 @@
|
|||||||
resetBalance()
|
resetBalance()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
floGlobals.sendType = 'flo'
|
||||||
function clearSelection() {
|
function clearSelection() {
|
||||||
getRef('tx_token_amount').disabled = true
|
|
||||||
getRef('tx_token_amount').classList.add('hidden')
|
|
||||||
getRef('tx_token_amount').value = ''
|
|
||||||
getRef('flo_data_wrapper').classList.remove('hidden')
|
getRef('flo_data_wrapper').classList.remove('hidden')
|
||||||
getRef('flo_data_textarea').value = ''
|
getRef('flo_data_textarea').value = ''
|
||||||
getRef('tx_flo_amount').value = ''
|
getRef('tx_flo_amount').value = ''
|
||||||
|
getRef('tx_flo_amount').classList.remove('hidden')
|
||||||
|
renderElem(getRef('tx_receiver_wrapper'), html`
|
||||||
|
<sm-input id="tx_receiver" class="w-100" placeholder="Receiver's FLO address" error-text="Invalid FLO address" data-flo-address animate required>
|
||||||
|
<button slot="right" class="icon-only" onclick="openPopup('saved_ids_popup')" title="Select from saved IDs">
|
||||||
|
<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 d="M21 5v14h2V5h-2zm-4 14h2V5h-2v14zM14 5H2c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V6c0-.55-.45-1-1-1zM8 7.75c1.24 0 2.25 1.01 2.25 2.25S9.24 12.25 8 12.25 5.75 11.24 5.75 10 6.76 7.75 8 7.75zM12.5 17h-9v-.75c0-1.5 3-2.25 4.5-2.25s4.5.75 4.5 2.25V17z" /> </svg>
|
||||||
|
</button>
|
||||||
|
</sm-input>
|
||||||
|
`)
|
||||||
|
getRef('add_token_receiver').classList.add('hidden')
|
||||||
|
floGlobals.sendType = 'flo'
|
||||||
}
|
}
|
||||||
function handleTokenSelection() {
|
function handleTokenSelection() {
|
||||||
const selectedToken = document.getElementById('sender_tokens_wrapper').querySelector('input[type="radio"]:checked')
|
const selectedToken = document.getElementById('sender_tokens_wrapper').querySelector('input[type="radio"]:checked')
|
||||||
@ -2389,24 +2358,46 @@
|
|||||||
const tokenName = selectedToken.value
|
const tokenName = selectedToken.value
|
||||||
const tokenBalance = parseFloat(selectedToken.dataset.balance)
|
const tokenBalance = parseFloat(selectedToken.dataset.balance)
|
||||||
getRef('flo_data_wrapper').classList.add('hidden')
|
getRef('flo_data_wrapper').classList.add('hidden')
|
||||||
getRef('tx_token_amount').disabled = false
|
|
||||||
getRef('tx_token_amount').classList.remove('hidden')
|
|
||||||
getRef('tx_token_amount').placeholder = `${tokenName.charAt(0).toUpperCase() + tokenName.slice(1)} amount`
|
|
||||||
getRef('tx_token_amount').setAttribute('max', tokenBalance)
|
|
||||||
getRef('tx_flo_amount').value = '0.001'
|
getRef('tx_flo_amount').value = '0.001'
|
||||||
|
getRef('tx_flo_amount').classList.add('hidden')
|
||||||
|
renderElem(getRef('tx_receiver_wrapper'), html``)
|
||||||
|
addTokenReceiver()
|
||||||
|
getRef('add_token_receiver').classList.remove('hidden')
|
||||||
|
floGlobals.sendType = 'token'
|
||||||
}
|
}
|
||||||
getRef('tx_token_amount').addEventListener('input', e => {
|
function addTokenReceiver() {
|
||||||
const tokenAmount = parseFloat(e.target.value.trim())
|
|
||||||
const selectedToken = document.getElementById('sender_tokens_wrapper').querySelector('input[type="radio"]:checked')
|
const selectedToken = document.getElementById('sender_tokens_wrapper').querySelector('input[type="radio"]:checked')
|
||||||
const tokenName = selectedToken.value
|
const tokenName = selectedToken.value;
|
||||||
const tokenBalance = parseFloat(selectedToken.dataset.balance)
|
const isFirst = getRef('tx_receiver_wrapper').children.length === 0
|
||||||
const { rangeOverflow, rangeUnderflow } = e.target.validity;
|
getRef('tx_receiver_wrapper').append(html.node`
|
||||||
if (rangeUnderflow)
|
<div class=${`token-receiver-combo ${isFirst ? '' : 'token-receiver-combo--removable'} grid gap-0-5`}>
|
||||||
e.target.setAttribute('error-text', `Minimum 0.00000001 ${tokenName} allowed`)
|
<sm-input class="token-receiver" class="w-100" placeholder="Receiver's FLO address" error-text="Invalid FLO address" data-flo-address animate required>
|
||||||
if (rangeOverflow)
|
<button slot="right" class="icon-only" onclick="openPopup('saved_ids_popup')" title="Select from saved IDs">
|
||||||
e.target.setAttribute('error-text', `You can send ${tokenName} upto ${tokenBalance} only`)
|
<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 d="M21 5v14h2V5h-2zm-4 14h2V5h-2v14zM14 5H2c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h12c.55 0 1-.45 1-1V6c0-.55-.45-1-1-1zM8 7.75c1.24 0 2.25 1.01 2.25 2.25S9.24 12.25 8 12.25 5.75 11.24 5.75 10 6.76 7.75 8 7.75zM12.5 17h-9v-.75c0-1.5 3-2.25 4.5-2.25s4.5.75 4.5 2.25V17z" /> </svg>
|
||||||
getRef('flo_data_textarea').value = `send ${tokenAmount} ${tokenName}#`
|
</button>
|
||||||
})
|
</sm-input>
|
||||||
|
<sm-input class="token-amount" type="number" placeholder=${`${tokenName.charAt(0).toUpperCase() + tokenName.slice(1)} amount`}
|
||||||
|
step="0.00000001" min="0.00000001" error-text="Min. amount is 0.00000001" animate required>
|
||||||
|
</sm-input>
|
||||||
|
${!isFirst ? html.node`
|
||||||
|
<button class="button icon-only remove-token-receiver" onclick="removeTokenReceiver(this)" title="Remove">
|
||||||
|
<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 d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></svg>
|
||||||
|
</button>
|
||||||
|
` : ''}
|
||||||
|
</div>
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
function removeTokenReceiver(elem) {
|
||||||
|
elem.closest('.grid').remove()
|
||||||
|
}
|
||||||
|
|
||||||
|
// getRef('tx_token_amount').addEventListener('input', e => {
|
||||||
|
// const tokenAmount = parseFloat(e.target.value.trim())
|
||||||
|
// const selectedToken = document.getElementById('sender_tokens_wrapper').querySelector('input[type="radio"]:checked')
|
||||||
|
// const tokenName = selectedToken.value
|
||||||
|
// const tokenBalance = parseFloat(selectedToken.dataset.balance)
|
||||||
|
// getRef('flo_data_textarea').value = `send ${tokenAmount} ${tokenName}#`
|
||||||
|
// })
|
||||||
getRef('tx_flo_amount').addEventListener('input', e => {
|
getRef('tx_flo_amount').addEventListener('input', e => {
|
||||||
const floAmount = parseFloat(e.target.value.trim())
|
const floAmount = parseFloat(e.target.value.trim())
|
||||||
const { rangeOverflow, rangeUnderflow } = e.target.validity;
|
const { rangeOverflow, rangeUnderflow } = e.target.validity;
|
||||||
@ -2435,7 +2426,7 @@
|
|||||||
</p>
|
</p>
|
||||||
` : ''}
|
` : ''}
|
||||||
</div>
|
</div>
|
||||||
<div id="sender_tokens_wrapper" class="grid hidden"></div>
|
<div id="sender_tokens_wrapper" class="grid gap-1 hidden"></div>
|
||||||
`)
|
`)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2501,64 +2492,168 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkBalance() {
|
async function checkBalance(address) {
|
||||||
getRef('balance_wrapper').classList.add('hidden')
|
try {
|
||||||
const floID = getRef('check_balance_field').value.trim()
|
getRef('address_details_wrapper').classList.remove('hidden')
|
||||||
buttonLoader(getRef('check_balance_button'), true)
|
floWebWallet.getLabels().then(allLabels => {
|
||||||
Promise.all([
|
if (allLabels[queriedFloId]) {
|
||||||
floWebWallet.getBalance(floID),
|
renderElem(getRef('queried_flo_address'), html`<h4>${allLabels[queriedFloId]}</h4> <sm-copy clip-text value=${queriedFloId}></sm-copy>`)
|
||||||
fetchJSON(`${floGlobals.tokenApiUrl}/api/v2/floAddressBalance/${floID}`)
|
} else {
|
||||||
]).then(([retrievedBal, { floAddressBalances }]) => {
|
renderElem(getRef('queried_flo_address'), html`
|
||||||
console.log(floAddressBalances)
|
<p class="label">FLO Address </p>
|
||||||
renderElem(getRef('balance_wrapper'), html`
|
<h4><sm-copy clip-text value=${queriedFloId}></sm-copy></h4>
|
||||||
<h4>Balance</h4>
|
|
||||||
<div class="flex gap-0-5 align-center space-between">
|
|
||||||
<span>FLO:</span>
|
|
||||||
<strong style="font-size: 1.1rem">${retrievedBal}</strong>
|
|
||||||
</div>
|
|
||||||
${floAddressBalances ? Object.keys(floAddressBalances).map(token => html`
|
|
||||||
<div class="flex gap-0-5 align-center space-between">
|
|
||||||
<span>${token}:</span>
|
|
||||||
<strong style="font-size: 1.1rem">${parseFloat((floAddressBalances[token].balance || 0).toFixed(8))}</strong>
|
|
||||||
</div>
|
|
||||||
`) : ''}
|
|
||||||
`)
|
`)
|
||||||
getRef('balance_wrapper').classList.remove('hidden')
|
}
|
||||||
|
})
|
||||||
|
const queriedFloId = address || getRef('search_query_input').value.trim()
|
||||||
|
getRef('token_list_wrapper').classList.add('hidden')
|
||||||
|
getRef('flo_balance').innerHTML = `<sm-spinner></sm-spinner>`;
|
||||||
|
const [floBalance, tokenBalances] = await Promise.all([
|
||||||
|
floWebWallet.getBalance(queriedFloId),
|
||||||
|
fetchJSON(`${floGlobals.tokenApiUrl}/api/v2/floAddressBalance/${queriedFloId}`).then(({ floAddressBalances }) => floAddressBalances)
|
||||||
|
])
|
||||||
|
let ownedTokens = []
|
||||||
|
for (const token in tokenBalances) {
|
||||||
|
ownedTokens.push(html`
|
||||||
|
<li class="token-item">
|
||||||
|
<span>${token}: </span><span>${parseFloat((tokenBalances[token].balance || 0).toFixed(8))}</span>
|
||||||
|
</li>
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
if (ownedTokens.length) {
|
||||||
|
renderElem(getRef('token_list'), html`${ownedTokens}`)
|
||||||
|
getRef('token_list_wrapper').classList.remove('hidden')
|
||||||
|
}
|
||||||
|
// retrieve FLO balance
|
||||||
|
getRef('flo_balance').textContent = `${parseFloat(floBalance.toFixed(3))} FLO`;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function categorizeText(text) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (text.length == 34 && floCrypto.validateFloID(text)) {
|
||||||
|
//console.log('data entered is a FLO address');
|
||||||
|
resolve('address')
|
||||||
|
} else if (text.length == 64 && returnHexNumber(text)) {
|
||||||
|
fetchJson(`${floGlobals.tokenApiUrl}/api/v2/categoriseString/` + text)
|
||||||
|
.then(function (myJson) {
|
||||||
|
resolve(myJson['type'])
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
notify(err, 'error')
|
reject(err)
|
||||||
}).finally(() => {
|
})
|
||||||
buttonLoader(getRef('check_balance_button'), false)
|
} else {
|
||||||
|
resolve('unknown')
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function initTransaction() {
|
let renderTransactions = 20;
|
||||||
|
floGlobals.query = {
|
||||||
|
transactions: [],
|
||||||
|
string: '',
|
||||||
|
}
|
||||||
|
async function fetchTransactions(address) {
|
||||||
|
try {
|
||||||
|
floGlobals.query.transactions = [];
|
||||||
|
await floWebWallet.syncTransactions(address);
|
||||||
|
floGlobals.query.transactions = (await floWebWallet.readTransactions(address)).reverse();
|
||||||
|
floGlobals.query.string = address;
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function filterFetchedTransactions() {
|
||||||
|
const filter = getRef('filter_selector').value;
|
||||||
|
if (filter !== 'all') {
|
||||||
|
floGlobals.query.transactions = floGlobals.query.transactions.filter(t => filter === 'sent' ? t.sender === floGlobals.query.string : t.receiver === floGlobals.query.string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function processQuery() {
|
||||||
|
const query = getRef('search_query_input').value.trim()
|
||||||
|
categorizeText(query).then(async type => {
|
||||||
|
window.location.hash = `#/search?type=${type}&query=${query}&page=1`
|
||||||
|
}).catch(err => {
|
||||||
|
notify(err, 'error')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function initTransaction() {
|
||||||
|
try {
|
||||||
const privKey = getRef('get_private_key_field').value.trim();
|
const privKey = getRef('get_private_key_field').value.trim();
|
||||||
const sender = floCrypto.getFloID(privKey)
|
const sender = floCrypto.getFloID(privKey)
|
||||||
const floAmount = parseFloat(getRef('tx_flo_amount').value.trim());
|
const floAmount = parseFloat(getRef('tx_flo_amount').value.trim());
|
||||||
const receiver = getRef('receiver').value.trim();
|
|
||||||
const floData = getRef('flo_data_textarea').value.trim();
|
const floData = getRef('flo_data_textarea').value.trim();
|
||||||
const selectedToken = document.getElementById('sender_tokens_wrapper').querySelector('input[type="radio"]:checked')
|
const selectedToken = document.getElementById('sender_tokens_wrapper').querySelector('input[type="radio"]:checked')
|
||||||
const tokenAmount = parseFloat(getRef('tx_token_amount').value.trim())
|
let transactionId
|
||||||
getConfirmation(`Confirm transaction`, {
|
if (floGlobals.sendType === 'flo') {
|
||||||
message: `
|
const receiver = document.getElementById('tx_receiver').value.trim();
|
||||||
Sending ${floAmount} FLO ${selectedToken && selectedToken.value !== 'none' ? ` and ${tokenAmount} ${selectedToken.value}` : ''} to ${receiver}
|
const consent = await getConfirmation(`Confirm transaction`, {
|
||||||
`,
|
message: ` Sending ${floAmount} FLO to ${receiver} `,
|
||||||
confirmText: 'Send',
|
confirmText: 'Send',
|
||||||
}).then(res => {
|
|
||||||
if (res) {
|
|
||||||
buttonLoader('send_button', true)
|
|
||||||
floWebWallet.sendTransaction(sender, receiver, floAmount, floData, privKey).then((transactionId) => {
|
|
||||||
showTransactionResult(true, transactionId);
|
|
||||||
getRef('send_form').reset();
|
|
||||||
getRef('send_button').disabled = true;
|
|
||||||
resetBalance()
|
|
||||||
}).catch((error) => {
|
|
||||||
showTransactionResult(false, error);
|
|
||||||
}).finally(() => {
|
|
||||||
buttonLoader('send_button', false)
|
|
||||||
})
|
})
|
||||||
|
if (!consent) return;
|
||||||
|
buttonLoader('send_button', true)
|
||||||
|
transactionId = await floWebWallet.sendTransaction(sender, receiver, floAmount, floData, privKey)
|
||||||
|
showTransactionResult(true, transactionId);
|
||||||
|
} else {
|
||||||
|
const bulkTokenReceivers = {}
|
||||||
|
getRef('tx_receiver_wrapper').querySelectorAll('.token-receiver-combo').forEach(elem => {
|
||||||
|
const receiverFloAddress = elem.querySelector('.token-receiver').value.trim()
|
||||||
|
const receiverTokenAmount = parseFloat(elem.querySelector('.token-amount').value.trim())
|
||||||
|
if (receiverFloAddress !== '' && receiverTokenAmount) {
|
||||||
|
if (!bulkTokenReceivers[receiverFloAddress])
|
||||||
|
bulkTokenReceivers[receiverFloAddress] = 0
|
||||||
|
bulkTokenReceivers[receiverFloAddress] += receiverTokenAmount
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const tokenReceivers = Object.keys(bulkTokenReceivers)
|
||||||
|
if (tokenReceivers.length) {
|
||||||
|
const consent = await getConfirmation(`Confirm transaction`, {
|
||||||
|
message: `
|
||||||
|
Sending ${selectedToken.value} tokens to \n\n ${tokenReceivers.map(r => `${r}: ${bulkTokenReceivers[r]} ${selectedToken.value}`).join('\n')}
|
||||||
|
`,
|
||||||
|
confirmText: 'Send',
|
||||||
|
})
|
||||||
|
if (!consent) return;
|
||||||
|
buttonLoader('send_button', true)
|
||||||
|
if (tokenReceivers.length > 1) {
|
||||||
|
// transfer tokens to multiple addresses
|
||||||
|
transactionIds = await floWebWallet.bulkTransferTokens(sender, privKey, selectedToken.value, bulkTokenReceivers)
|
||||||
|
showTransactionResult(true, null, {
|
||||||
|
title: `Multiple transactions have been initiated`,
|
||||||
|
description: html`
|
||||||
|
<ul class="grid gap-0-5">
|
||||||
|
${tokenReceivers.map((receiver, index) => html`
|
||||||
|
<li>
|
||||||
|
<a href=${`${floBlockchainAPI.current_server}tx/${transactionIds[receiver]}`} target="_blank">
|
||||||
|
Check ${receiver} (${bulkTokenReceivers[receiver]} ${selectedToken.value}) transaction
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
`)}
|
||||||
|
</ul>
|
||||||
|
`
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const floData = `send ${bulkTokenReceivers[tokenReceivers[0]]} ${selectedToken.value}#`
|
||||||
|
transactionId = await floBlockchainAPI.writeData(sender, floData, privKey, tokenReceivers[0])
|
||||||
|
showTransactionResult(true, transactionId);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
notify('Please enter at least one receiver', 'error')
|
||||||
|
buttonLoader('send_button', false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getRef('send_form').reset();
|
||||||
|
buttonLoader('send_button', false)
|
||||||
|
getRef('send_button').disabled = true;
|
||||||
|
resetBalance()
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
showTransactionResult(false, e);
|
||||||
|
buttonLoader('send_button', false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function showTransactionResult(success, result, options = {}) {
|
function showTransactionResult(success, result, options = {}) {
|
||||||
@ -2577,7 +2672,7 @@
|
|||||||
` : ''}
|
` : ''}
|
||||||
<h3 id="transaction_result__title">${title}</h3>
|
<h3 id="transaction_result__title">${title}</h3>
|
||||||
<p id="transaction_result__description"> ${description} </p>
|
<p id="transaction_result__description"> ${description} </p>
|
||||||
${success ? html`
|
${success && result ? html`
|
||||||
<div class="grid gap-1">
|
<div class="grid gap-1">
|
||||||
<a id="transaction_link" href=${`${floBlockchainAPI.current_server}tx/${result}`} style="margin-top: 1.5rem;" target="_blank">See transaction on blockchain</a>
|
<a id="transaction_link" href=${`${floBlockchainAPI.current_server}tx/${result}`} style="margin-top: 1.5rem;" target="_blank">See transaction on blockchain</a>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
@ -2604,13 +2699,6 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function backToTop() {
|
|
||||||
getRef('transactions_scroller').scroll({
|
|
||||||
top: 0,
|
|
||||||
behavior: 'smooth'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
getRef('flo_data_textarea').addEventListener('keydown', e => {
|
getRef('flo_data_textarea').addEventListener('keydown', e => {
|
||||||
if (e.target.value.length > 1040)
|
if (e.target.value.length > 1040)
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
@ -2735,7 +2823,8 @@
|
|||||||
|
|
||||||
function filterSmartContracts(options) {
|
function filterSmartContracts(options) {
|
||||||
const { type, subType, dynamic = false } = options || {}
|
const { type, subType, dynamic = false } = options || {}
|
||||||
let filteredSmartContracts = (floGlobals.smartContracts || []);
|
let filteredSmartContracts = (floGlobals.smartContracts || [])
|
||||||
|
.filter(sc => sc.status === 'active')
|
||||||
if (type) {
|
if (type) {
|
||||||
filteredSmartContracts = filteredSmartContracts.filter(sc => sc.contractType === type)
|
filteredSmartContracts = filteredSmartContracts.filter(sc => sc.contractType === type)
|
||||||
if (type === 'continuos-event' && dynamic)
|
if (type === 'continuos-event' && dynamic)
|
||||||
@ -2837,7 +2926,7 @@
|
|||||||
}
|
}
|
||||||
console.log(floData)
|
console.log(floData)
|
||||||
buttonLoader('participate_button', true)
|
buttonLoader('participate_button', true)
|
||||||
floTokenAPI.getBalance(participantAddress, acceptingToken).then(balance => {
|
floTokenAPI.getBalance(participantAddress, acceptingToken || tokenIdentification).then(balance => {
|
||||||
if (balance < participationAmount) {
|
if (balance < participationAmount) {
|
||||||
buttonLoader('participate_button', false)
|
buttonLoader('participate_button', false)
|
||||||
return notify(`Insufficient balance. You have ${balance} ${acceptingToken || tokenIdentification}`, 'error')
|
return notify(`Insufficient balance. You have ${balance} ${acceptingToken || tokenIdentification}`, 'error')
|
||||||
@ -2958,6 +3047,8 @@
|
|||||||
const creatorAddress = floCrypto.getFloID(creatorPrivateKey)
|
const creatorAddress = floCrypto.getFloID(creatorPrivateKey)
|
||||||
let floData
|
let floData
|
||||||
let confirmationMessage = ''
|
let confirmationMessage = ''
|
||||||
|
if (floGlobals.scMap.has(`${contractName}_${creatorAddress}`))
|
||||||
|
return notify(`Contract with name: ${contractName} and address: ${creatorAddress} already exists`, 'error')
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'one-time-event':
|
case 'one-time-event':
|
||||||
const contractAsset = document.getElementById('contract_asset').value;
|
const contractAsset = document.getElementById('contract_asset').value;
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user