From 822f026c65ff16814890eea44fe1fb1e4af53a2e Mon Sep 17 00:00:00 2001
From: void-57
Date: Tue, 6 Jan 2026 21:29:29 +0530
Subject: [PATCH] feat: Implement multi-chain address recovery from private key
and enhance transaction history retrieval with pagination and improved error
handling
---
README.md | 3 +
css/main.css | 458 ++++++++++++++++--
css/main.min.css | 308 ------------
index.html | 1025 ++++++++++++++++++++--------------------
scripts/bscOperator.js | 583 ++++++++++++-----------
5 files changed, 1257 insertions(+), 1120 deletions(-)
diff --git a/README.md b/README.md
index 5291adc..f6f436e 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,5 @@
# bscwallet
Binance Chain Wallet linked with FLO blockchain address
+# RanchiMall-bsc-wallet
+# RanchiMall-bsc-wallet
+# RanchiMall-bsc-wallet
diff --git a/css/main.css b/css/main.css
index f3293e1..7424383 100644
--- a/css/main.css
+++ b/css/main.css
@@ -28,7 +28,7 @@ body {
background-color: rgba(var(--foreground-color), 1);
}
-body[data-theme=dark] {
+body[data-theme="dark"] {
--accent-color: #92a2ff;
--accent-color-rgb: 160, 182, 255;
--secondary-color: #d60739;
@@ -39,7 +39,7 @@ body[data-theme=dark] {
--green: #00e676;
--yellow: rgb(255, 213, 5);
}
-body[data-theme=dark] ::-webkit-calendar-picker-indicator {
+body[data-theme="dark"] ::-webkit-calendar-picker-indicator {
filter: invert(1);
}
@@ -63,7 +63,7 @@ strong {
img {
-o-object-fit: cover;
- object-fit: cover;
+ object-fit: cover;
}
a:where([class]) {
@@ -90,7 +90,7 @@ a:any-link:focus-visible {
outline: rgba(var(--text-color), 1) 0.1rem solid;
}
-input[type=datetime-local] {
+input[type="datetime-local"] {
width: 100%;
padding: 0.8rem 0.6rem;
border: none;
@@ -101,7 +101,7 @@ input[type=datetime-local] {
color: inherit;
background-color: rgba(var(--text-color), 0.06);
}
-input[type=datetime-local]:focus {
+input[type="datetime-local"]:focus {
outline: none;
box-shadow: 0 0 0 0.1rem var(--accent-color);
}
@@ -109,8 +109,8 @@ input[type=datetime-local]:focus {
button,
.button {
-webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
+ -moz-user-select: none;
+ user-select: none;
position: relative;
display: inline-flex;
border: none;
@@ -224,8 +224,8 @@ a:any-link:focus-visible {
details summary {
display: flex;
-webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
+ -moz-user-select: none;
+ user-select: none;
cursor: pointer;
align-items: center;
gap: 1rem;
@@ -264,8 +264,8 @@ sm-chip {
--padding: 0.5rem 0.8rem;
--background: rgba(var(--text-color), 0.06);
-webkit-user-select: none;
- -moz-user-select: none;
- user-select: none;
+ -moz-user-select: none;
+ user-select: none;
font-weight: 500;
}
sm-chip[selected] {
@@ -604,7 +604,11 @@ ul {
position: absolute;
border-radius: 50%;
transform: scale(0);
- background: radial-gradient(circle, rgba(var(--text-color), 0.3) 0%, rgba(0, 0, 0, 0) 50%);
+ background: radial-gradient(
+ circle,
+ rgba(var(--text-color), 0.3) 0%,
+ rgba(0, 0, 0, 0) 50%
+ );
pointer-events: none;
}
@@ -699,17 +703,17 @@ ul {
justify-self: flex-start;
}
-ul[type=circle],
-menu[type=circle] {
+ul[type="circle"],
+menu[type="circle"] {
padding: 1.5rem 2.5rem;
list-style: circle;
}
-ul[type=circle] li,
-menu[type=circle] li {
+ul[type="circle"] li,
+menu[type="circle"] li {
margin-bottom: 1rem;
}
-ul[type=circle] li:last-of-type,
-menu[type=circle] li:last-of-type {
+ul[type="circle"] li:last-of-type,
+menu[type="circle"] li:last-of-type {
margin-bottom: 0;
}
ul,
@@ -773,13 +777,13 @@ menu {
#meta_mask_status_button .icon-wrapper > * {
grid-area: 1/1;
}
-#meta_mask_status_button[data-status=connected] {
+#meta_mask_status_button[data-status="connected"] {
pointer-events: none;
}
-#meta_mask_status_button[data-status=connected] .icon-wrapper::after {
+#meta_mask_status_button[data-status="connected"] .icon-wrapper::after {
background-color: var(--green);
}
-#meta_mask_status_button[data-status=disconnected] .icon-wrapper::after {
+#meta_mask_status_button[data-status="disconnected"] .icon-wrapper::after {
background-color: var(--danger-color);
}
@@ -847,7 +851,8 @@ main {
transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.nav-item__title {
- transition: opacity 0.2s, transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ transition: opacity 0.2s,
+ transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.nav-item--active {
color: var(--accent-color);
@@ -870,17 +875,17 @@ main {
overflow: auto;
grid-area: pages;
}
-#page_container[data-page=home] > :nth-child(2) {
+#page_container[data-page="home"] > :nth-child(2) {
flex: 1;
}
-#page_container[data-page=send] {
+#page_container[data-page="send"] {
align-items: flex-start;
}
-#page_container[data-page=send] > * {
+#page_container[data-page="send"] > * {
padding: 1rem;
margin: 0 auto;
}
-#page_container[data-page=create] {
+#page_container[data-page="create"] {
margin: 0 auto;
padding: 4vw 1rem;
gap: 2rem;
@@ -940,17 +945,30 @@ aside h4 {
gap: 0.5rem;
}
-#bsc_balance_wrapper {
+#eth_balance_wrapper {
background-color: rgba(var(--text-color), 0.06);
padding: max(1rem, 1.5vw);
border-radius: 0.5rem;
width: 100%;
}
-#bsc_balance_wrapper li:not(:last-of-type) {
+#eth_balance_wrapper li:not(:last-of-type) {
border-bottom: solid thin rgba(var(--text-color), 0.3);
padding-bottom: 0.5rem;
}
+#address_transactions {
+ width: 100%;
+ max-width: 32rem;
+}
+
+.transaction {
+ width: 100%;
+}
+
+#transactions_list {
+ width: 100%;
+}
+
#error_section {
display: grid;
height: 100%;
@@ -978,6 +996,7 @@ aside h4 {
position: relative;
margin-bottom: 2rem;
}
+
.transaction__phase:not(:last-of-type)::after {
content: "";
position: absolute;
@@ -1004,7 +1023,7 @@ aside h4 {
width: 4rem;
border-radius: 5rem;
-webkit-animation: popup 1s;
- animation: popup 1s;
+ animation: popup 1s;
padding: 1rem;
}
.user-action-result__icon.pending {
@@ -1068,17 +1087,24 @@ aside h4 {
padding-bottom: 1rem;
border-bottom: solid thin rgba(var(--text-color), 0.3);
}
-
+.create-buttons {
+ display: flex;
+ max-width: 400px;
+ gap: 1rem;
+}
@media only screen and (max-width: 640px) {
.hide-on-small {
display: none;
}
- #page_container[data-page=home] {
+ #page_container[data-page="home"] {
flex-direction: column;
}
- #page_container[data-page=home] > :first-child {
+ #page_container[data-page="home"] > :first-child {
order: 1;
}
+ .create-buttons {
+ display: grid;
+ }
}
@media only screen and (min-width: 640px) {
sm-popup {
@@ -1166,9 +1192,369 @@ aside h4 {
}
@media (prefers-reduced-motion) {
::view-transition-group(*),
-::view-transition-old(*),
-::view-transition-new(*) {
+ ::view-transition-old(*),
+ ::view-transition-new(*) {
-webkit-animation: none !important;
- animation: none !important;
+ animation: none !important;
}
-}
\ No newline at end of file
+}
+
+.tx-details-container {
+ max-width: 800px;
+ margin: 1rem auto;
+ padding: 1rem;
+ font-family: inherit;
+}
+
+/* Header styling */
+.tx-header {
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 0.5rem;
+ margin-bottom: 1.5rem;
+ padding-bottom: 1rem;
+ border-bottom: 1px solid rgba(var(--text-color), 0.1);
+}
+
+.tx-title {
+ font-size: 1.5rem;
+ font-weight: 600;
+ color: rgba(var(--text-color), 0.95);
+ margin: 0;
+}
+
+.tx-card {
+ background-color: rgba(var(--foreground-color), 1);
+ border-radius: 0.75rem;
+ overflow: hidden;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
+ border: 1px solid rgba(var(--text-color), 0.1);
+ margin-top: 1rem;
+}
+
+.tx-status-header {
+ display: flex;
+ align-items: center;
+ gap: 1rem;
+ padding: 1.25rem;
+ background-color: rgba(var(--text-color), 0.03);
+ border-bottom: 1px solid rgba(var(--text-color), 0.1);
+}
+
+.status-indicator {
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+ flex-shrink: 0;
+}
+
+.status-indicator.confirmed {
+ background-color: var(--color-success);
+ box-shadow: 0 0 0 4px rgba(var(--color-success-rgb), 0.2);
+}
+
+.status-indicator.pending {
+ background-color: var(--color-warning);
+ box-shadow: 0 0 0 4px rgba(var(--color-warning-rgb), 0.2);
+}
+
+.status-details {
+ flex-grow: 1;
+}
+
+.status-title {
+ font-size: 1.15rem;
+ font-weight: 600;
+ color: rgba(var(--text-color), 0.95);
+ margin: 0;
+}
+
+.status-subtext {
+ font-size: 0.85rem;
+ color: rgba(var(--text-color), 0.7);
+ margin: 0.25rem 0 0;
+}
+
+.tx-info-grid {
+ padding: 1.25rem;
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
+}
+
+.tx-address-section {
+ display: flex;
+ align-items: stretch;
+ gap: 1rem;
+ background: rgba(var(--text-color), 0.02);
+ padding: 1rem;
+ border-radius: 0.5rem;
+}
+
+.address-card {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.address-label {
+ font-size: 0.75rem;
+ font-weight: 500;
+ color: rgba(var(--text-color), 0.6);
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.address-value {
+ font-family: "Roboto Mono", monospace;
+ font-size: 0.85rem;
+ color: rgba(var(--text-color), 0.9);
+ word-break: break-all;
+ background: rgba(var(--text-color), 0.05);
+ padding: 0.5rem 0.75rem;
+ border-radius: 0.25rem;
+}
+
+.tx-arrow {
+ font-size: 1.5rem;
+ color: rgba(var(--text-color), 0.4);
+ display: flex;
+ align-items: center;
+ padding: 0 0.5rem;
+}
+
+.tx-hash-section {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+}
+
+.section-label {
+ font-size: 0.75rem;
+ font-weight: 500;
+ color: rgba(var(--text-color), 0.6);
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+
+.hash-value {
+ background-color: rgba(var(--text-color), 0.05);
+ padding: 0.75rem;
+ border-radius: 0.25rem;
+ font-family: "Roboto Mono", monospace;
+ font-size: 0.85rem;
+ color: rgba(var(--text-color), 0.9);
+ word-break: break-all;
+}
+
+.tx-metrics-grid {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
+ gap: 1rem;
+}
+
+.metric-card {
+ background-color: rgba(var(--text-color), 0.03);
+ padding: 1rem;
+ border-radius: 0.5rem;
+ text-align: center;
+ border: 1px solid rgba(var(--text-color), 0.08);
+ transition: background-color 0.2s ease, transform 0.2s ease;
+}
+
+.metric-card:hover {
+ background-color: rgba(var(--text-color), 0.06);
+ transform: translateY(-2px);
+}
+
+.metric-label {
+ font-size: 0.75rem;
+ font-weight: 500;
+ color: rgba(var(--text-color), 0.6);
+ margin-bottom: 0.5rem;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+ display: block;
+}
+
+.metric-value {
+ font-size: 0.95rem;
+ font-weight: 500;
+ color: rgba(var(--text-color), 0.95);
+ word-break: break-word;
+}
+
+.tx-actions {
+ display: flex;
+ justify-content: space-between;
+ gap: 1rem;
+ padding: 1.25rem;
+ border-top: 1px solid rgba(var(--text-color), 0.1);
+ background-color: rgba(var(--text-color), 0.03);
+}
+
+.tx-actions .button {
+ flex: 1;
+}
+
+@media (max-width: 768px) {
+ .tx-address-section {
+ flex-direction: column;
+ gap: 0.75rem;
+ align-items: stretch;
+ }
+
+ .tx-arrow {
+ transform: rotate(90deg);
+ margin: 0.5rem auto;
+ padding: 0;
+ }
+
+ .tx-metrics-grid {
+ grid-template-columns: 1fr 1fr;
+ }
+}
+
+@media (max-width: 576px) {
+ .tx-header {
+ padding-bottom: 0.75rem;
+ }
+
+ .tx-status-header {
+ padding: 1rem;
+ gap: 0.75rem;
+ }
+
+ .status-title {
+ font-size: 1.1rem;
+ }
+
+ .tx-info-grid {
+ padding: 1rem;
+ gap: 1.25rem;
+ }
+
+ .tx-address-section {
+ padding: 0.75rem;
+ }
+
+ .tx-metrics-grid {
+ grid-template-columns: 1fr;
+ }
+
+ .tx-actions {
+ flex-direction: column;
+ padding: 1rem;
+ }
+}
+
+/* Valuation toggle styles */
+.valuation-toggle {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ font-size: 0.85rem;
+ color: rgba(var(--text-color), 0.8);
+ margin-top: 0.5rem;
+ margin-right: 0.5rem;
+}
+
+.toggle-switch {
+ position: relative;
+ display: inline-block;
+ width: 3rem;
+ height: 1.5rem;
+}
+
+.toggle-switch input {
+ opacity: 0;
+ width: 0;
+ height: 0;
+}
+
+.toggle-slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(var(--text-color), 0.2);
+ transition: 0.4s;
+ border-radius: 1.5rem;
+}
+
+.toggle-slider:before {
+ position: absolute;
+ content: "";
+ height: 1.1rem;
+ width: 1.1rem;
+ left: 0.2rem;
+ bottom: 0.2rem;
+ background-color: white;
+ transition: 0.4s;
+ border-radius: 50%;
+}
+
+input:checked + .toggle-slider {
+ background-color: var(--accent-color);
+}
+
+input:checked + .toggle-slider:before {
+ transform: translateX(1.5rem);
+}
+
+.transaction-controls {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 1rem;
+ margin-bottom: 1rem;
+ padding: 0.5rem;
+ background-color: rgba(var(--text-color), 0.03);
+ border-radius: 0.5rem;
+ border: 1px solid rgba(var(--text-color), 0.08);
+}
+
+.filter-control {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+}
+
+.filter-control label {
+ font-size: 0.9rem;
+ color: rgba(var(--text-color), 0.8);
+ font-weight: 500;
+}
+
+.filter-control select {
+ padding: 0.4rem 0.6rem;
+ border-radius: 0.4rem;
+ border: 1px solid rgba(var(--text-color), 0.1);
+ background-color: rgba(var(--foreground-color), 1);
+ color: rgba(var(--text-color), 0.9);
+ font-size: 0.9rem;
+ cursor: pointer;
+ outline: none;
+}
+.margin-left-auto + .margin-left-auto {
+ display: none !important;
+}
+
+.filter-control select:focus {
+ border-color: var(--accent-color);
+}
+
+#bsc_balance_wrapper {
+ background-color: rgba(var(--text-color), 0.06);
+ padding: max(1rem, 1.5vw);
+ border-radius: 0.5rem;
+ width: 100%;
+}
+#bsc_balance_wrapper li:not(:last-of-type) {
+ border-bottom: solid thin rgba(var(--text-color), 0.3);
+ padding-bottom: 0.5rem;
+}
diff --git a/css/main.min.css b/css/main.min.css
index 4810aa0..4a527d3 100644
--- a/css/main.min.css
+++ b/css/main.min.css
@@ -1050,311 +1050,3 @@ aside h4 {
animation: none !important;
}
}
-.tx-details-container {
- max-width: 800px;
- margin: 1rem auto;
- padding: 1rem;
- font-family: inherit;
-}
-.tx-header {
- display: flex;
- flex-direction: column;
- align-items: flex-start;
- gap: 0.5rem;
- margin-bottom: 1.5rem;
- padding-bottom: 1rem;
- border-bottom: 1px solid rgba(var(--text-color), 0.1);
-}
-.tx-title {
- font-size: 1.5rem;
- font-weight: 600;
- color: rgba(var(--text-color), 0.95);
- margin: 0;
-}
-.tx-card {
- background-color: rgba(var(--foreground-color), 1);
- border-radius: 0.75rem;
- overflow: hidden;
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
- border: 1px solid rgba(var(--text-color), 0.1);
- margin-top: 1rem;
-}
-.tx-status-header {
- display: flex;
- align-items: center;
- gap: 1rem;
- padding: 1.25rem;
- background-color: rgba(var(--text-color), 0.03);
- border-bottom: 1px solid rgba(var(--text-color), 0.1);
-}
-.status-indicator {
- width: 12px;
- height: 12px;
- border-radius: 50%;
- flex-shrink: 0;
-}
-.status-indicator.confirmed {
- background-color: var(--color-success);
- box-shadow: 0 0 0 4px rgba(var(--color-success-rgb), 0.2);
-}
-.status-indicator.pending {
- background-color: var(--color-warning);
- box-shadow: 0 0 0 4px rgba(var(--color-warning-rgb), 0.2);
-}
-.status-details {
- flex-grow: 1;
-}
-.status-title {
- font-size: 1.15rem;
- font-weight: 600;
- color: rgba(var(--text-color), 0.95);
- margin: 0;
-}
-.status-subtext {
- font-size: 0.85rem;
- color: rgba(var(--text-color), 0.7);
- margin: 0.25rem 0 0;
-}
-.tx-info-grid {
- padding: 1.25rem;
- display: flex;
- flex-direction: column;
- gap: 1.5rem;
-}
-.tx-address-section {
- display: flex;
- align-items: stretch;
- gap: 1rem;
- background: rgba(var(--text-color), 0.02);
- padding: 1rem;
- border-radius: 0.5rem;
-}
-.address-card {
- flex: 1;
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-}
-.address-label {
- font-size: 0.75rem;
- font-weight: 500;
- color: rgba(var(--text-color), 0.6);
- text-transform: uppercase;
- letter-spacing: 0.5px;
-}
-.address-value {
- font-family: "Roboto Mono", monospace;
- font-size: 0.85rem;
- color: rgba(var(--text-color), 0.9);
- word-break: break-all;
- background: rgba(var(--text-color), 0.05);
- padding: 0.5rem 0.75rem;
- border-radius: 0.25rem;
-}
-.tx-arrow {
- font-size: 1.5rem;
- color: rgba(var(--text-color), 0.4);
- display: flex;
- align-items: center;
- padding: 0 0.5rem;
-}
-.tx-hash-section {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
-}
-.section-label {
- font-size: 0.75rem;
- font-weight: 500;
- color: rgba(var(--text-color), 0.6);
- text-transform: uppercase;
- letter-spacing: 0.5px;
-}
-.hash-value {
- background-color: rgba(var(--text-color), 0.05);
- padding: 0.75rem;
- border-radius: 0.25rem;
- font-family: "Roboto Mono", monospace;
- font-size: 0.85rem;
- color: rgba(var(--text-color), 0.9);
- word-break: break-all;
-}
-.tx-metrics-grid {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
- gap: 1rem;
-}
-.metric-card {
- background-color: rgba(var(--text-color), 0.03);
- padding: 1rem;
- border-radius: 0.5rem;
- text-align: center;
- border: 1px solid rgba(var(--text-color), 0.08);
- transition: background-color 0.2s ease, transform 0.2s ease;
-}
-.metric-card:hover {
- background-color: rgba(var(--text-color), 0.06);
- transform: translateY(-2px);
-}
-.metric-label {
- font-size: 0.75rem;
- font-weight: 500;
- color: rgba(var(--text-color), 0.6);
- margin-bottom: 0.5rem;
- text-transform: uppercase;
- letter-spacing: 0.5px;
- display: block;
-}
-.metric-value {
- font-size: 0.95rem;
- font-weight: 500;
- color: rgba(var(--text-color), 0.95);
- word-break: break-word;
-}
-.tx-actions {
- display: flex;
- justify-content: space-between;
- gap: 1rem;
- padding: 1.25rem;
- border-top: 1px solid rgba(var(--text-color), 0.1);
- background-color: rgba(var(--text-color), 0.03);
-}
-.tx-actions .button {
- flex: 1;
-}
-@media (max-width: 768px) {
- .tx-address-section {
- flex-direction: column;
- gap: 0.75rem;
- align-items: stretch;
- }
- .tx-arrow {
- transform: rotate(90deg);
- margin: 0.5rem auto;
- padding: 0;
- }
- .tx-metrics-grid {
- grid-template-columns: 1fr 1fr;
- }
-}
-@media (max-width: 576px) {
- .tx-header {
- padding-bottom: 0.75rem;
- }
- .tx-status-header {
- padding: 1rem;
- gap: 0.75rem;
- }
- .status-title {
- font-size: 1.1rem;
- }
- .tx-info-grid {
- padding: 1rem;
- gap: 1.25rem;
- }
- .tx-address-section {
- padding: 0.75rem;
- }
- .tx-metrics-grid {
- grid-template-columns: 1fr;
- }
- .tx-actions {
- flex-direction: column;
- padding: 1rem;
- }
-}
-.valuation-toggle {
- display: flex;
- align-items: center;
- gap: 0.5rem;
- font-size: 0.85rem;
- color: rgba(var(--text-color), 0.8);
- margin-top: 0.5rem;
- margin-right: 0.5rem;
-}
-.toggle-switch {
- position: relative;
- display: inline-block;
- width: 3rem;
- height: 1.5rem;
-}
-.toggle-switch input {
- opacity: 0;
- width: 0;
- height: 0;
-}
-.toggle-slider {
- position: absolute;
- cursor: pointer;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background-color: rgba(var(--text-color), 0.2);
- transition: 0.4s;
- border-radius: 1.5rem;
-}
-.toggle-slider:before {
- position: absolute;
- content: "";
- height: 1.1rem;
- width: 1.1rem;
- left: 0.2rem;
- bottom: 0.2rem;
- background-color: white;
- transition: 0.4s;
- border-radius: 50%;
-}
-input:checked + .toggle-slider {
- background-color: var(--accent-color);
-}
-input:checked + .toggle-slider:before {
- transform: translateX(1.5rem);
-}
-.transaction-controls {
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 1rem;
- margin-bottom: 1rem;
- padding: 0.5rem;
- background-color: rgba(var(--text-color), 0.03);
- border-radius: 0.5rem;
- border: 1px solid rgba(var(--text-color), 0.08);
-}
-.filter-control {
- display: flex;
- align-items: center;
- gap: 0.5rem;
-}
-.filter-control label {
- font-size: 0.9rem;
- color: rgba(var(--text-color), 0.8);
- font-weight: 500;
-}
-.filter-control select {
- padding: 0.4rem 0.6rem;
- border-radius: 0.4rem;
- border: 1px solid rgba(var(--text-color), 0.1);
- background-color: rgba(var(--foreground-color), 1);
- color: rgba(var(--text-color), 0.9);
- font-size: 0.9rem;
- cursor: pointer;
- outline: none;
-}
-.margin-left-auto + .margin-left-auto {
- display: none !important;
-}
-.filter-control select:focus {
- border-color: var(--accent-color);
-}
-#bsc_balance_wrapper {
- background-color: rgba(var(--text-color), 0.06);
- padding: max(1rem, 1.5vw);
- border-radius: 0.5rem;
- width: 100%;
-}
-#bsc_balance_wrapper li:not(:last-of-type) {
- border-bottom: solid thin rgba(var(--text-color), 0.3);
- padding-bottom: 0.5rem;
-}
diff --git a/index.html b/index.html
index f706c8f..e2b3ec7 100644
--- a/index.html
+++ b/index.html
@@ -1,11 +1,11 @@
-
Binance Smart Chain
-
+
+
Cancel
- Ok
+
+ Ok
+
@@ -260,17 +262,13 @@
-
Did you forget your Binance Address?
+
Did you forget your addresses?
- If you have your BSC/BTC/FLO Private Key, enter it here and recover
- your Binance Address.
+ If you have your BSC/BTC/FLO Private Key, enter it here to recover
+ all your addresses and private keys.
-
-
Recovered Binance Address
-
-
+
-
+
@@ -354,13 +353,11 @@
-
+
+
-
\ No newline at end of file
diff --git a/scripts/bscOperator.js b/scripts/bscOperator.js
index 29e3df4..4e9a892 100644
--- a/scripts/bscOperator.js
+++ b/scripts/bscOperator.js
@@ -1,305 +1,330 @@
-
-(function (EXPORTS) { //bscOperator v1.0.2
+(function (EXPORTS) {
+ //bscOperator v1.0.2
/* ETH Crypto and API Operator */
- if (!window.ethers)
- return console.error('ethers.js not found')
+ if (!window.ethers) return console.error("ethers.js not found");
const bscOperator = EXPORTS;
- const isValidAddress = bscOperator.isValidAddress = (address) => {
+ const isValidAddress = (bscOperator.isValidAddress = (address) => {
try {
// Check if the address is a valid checksum address
const isValidChecksum = ethers.utils.isAddress(address);
// Check if the address is a valid non-checksum address
- const isValidNonChecksum = ethers.utils.getAddress(address) === address.toLowerCase();
+ const isValidNonChecksum =
+ ethers.utils.getAddress(address) === address.toLowerCase();
return isValidChecksum || isValidNonChecksum;
} catch (error) {
return false;
}
- }
+ });
const BEP20ABI = [
{
- "constant": true,
- "inputs": [],
- "name": "name",
- "outputs": [
+ constant: true,
+ inputs: [],
+ name: "name",
+ outputs: [
{
- "name": "",
- "type": "string"
- }
+ name: "",
+ type: "string",
+ },
],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
+ payable: false,
+ stateMutability: "view",
+ type: "function",
},
{
- "constant": false,
- "inputs": [
+ constant: false,
+ inputs: [
{
- "name": "_spender",
- "type": "address"
+ name: "_spender",
+ type: "address",
},
{
- "name": "_value",
- "type": "uint256"
- }
+ name: "_value",
+ type: "uint256",
+ },
],
- "name": "approve",
- "outputs": [
+ name: "approve",
+ outputs: [
{
- "name": "",
- "type": "bool"
- }
+ name: "",
+ type: "bool",
+ },
],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
+ payable: false,
+ stateMutability: "nonpayable",
+ type: "function",
},
{
- "constant": true,
- "inputs": [],
- "name": "totalSupply",
- "outputs": [
+ constant: true,
+ inputs: [],
+ name: "totalSupply",
+ outputs: [
{
- "name": "",
- "type": "uint256"
- }
+ name: "",
+ type: "uint256",
+ },
],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
+ payable: false,
+ stateMutability: "view",
+ type: "function",
},
{
- "constant": false,
- "inputs": [
+ constant: false,
+ inputs: [
{
- "name": "_from",
- "type": "address"
+ name: "_from",
+ type: "address",
},
{
- "name": "_to",
- "type": "address"
+ name: "_to",
+ type: "address",
},
{
- "name": "_value",
- "type": "uint256"
- }
+ name: "_value",
+ type: "uint256",
+ },
],
- "name": "transferFrom",
- "outputs": [
+ name: "transferFrom",
+ outputs: [
{
- "name": "",
- "type": "bool"
- }
+ name: "",
+ type: "bool",
+ },
],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
+ payable: false,
+ stateMutability: "nonpayable",
+ type: "function",
},
{
- "constant": true,
- "inputs": [],
- "name": "decimals",
- "outputs": [
+ constant: true,
+ inputs: [],
+ name: "decimals",
+ outputs: [
{
- "name": "",
- "type": "uint8"
- }
+ name: "",
+ type: "uint8",
+ },
],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
+ payable: false,
+ stateMutability: "view",
+ type: "function",
},
{
- "constant": true,
- "inputs": [
+ constant: true,
+ inputs: [
{
- "name": "_owner",
- "type": "address"
- }
+ name: "_owner",
+ type: "address",
+ },
],
- "name": "balanceOf",
- "outputs": [
+ name: "balanceOf",
+ outputs: [
{
- "name": "balance",
- "type": "uint256"
- }
+ name: "balance",
+ type: "uint256",
+ },
],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
+ payable: false,
+ stateMutability: "view",
+ type: "function",
},
{
- "constant": true,
- "inputs": [],
- "name": "symbol",
- "outputs": [
+ constant: true,
+ inputs: [],
+ name: "symbol",
+ outputs: [
{
- "name": "",
- "type": "string"
- }
+ name: "",
+ type: "string",
+ },
],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
+ payable: false,
+ stateMutability: "view",
+ type: "function",
},
{
- "constant": false,
- "inputs": [
+ constant: false,
+ inputs: [
{
- "name": "_to",
- "type": "address"
+ name: "_to",
+ type: "address",
},
{
- "name": "_value",
- "type": "uint256"
- }
+ name: "_value",
+ type: "uint256",
+ },
],
- "name": "transfer",
- "outputs": [
+ name: "transfer",
+ outputs: [
{
- "name": "",
- "type": "bool"
- }
+ name: "",
+ type: "bool",
+ },
],
- "payable": false,
- "stateMutability": "nonpayable",
- "type": "function"
+ payable: false,
+ stateMutability: "nonpayable",
+ type: "function",
},
{
- "constant": true,
- "inputs": [
+ constant: true,
+ inputs: [
{
- "name": "_owner",
- "type": "address"
+ name: "_owner",
+ type: "address",
},
{
- "name": "_spender",
- "type": "address"
- }
+ name: "_spender",
+ type: "address",
+ },
],
- "name": "allowance",
- "outputs": [
+ name: "allowance",
+ outputs: [
{
- "name": "",
- "type": "uint256"
- }
+ name: "",
+ type: "uint256",
+ },
],
- "payable": false,
- "stateMutability": "view",
- "type": "function"
+ payable: false,
+ stateMutability: "view",
+ type: "function",
},
{
- "payable": true,
- "stateMutability": "payable",
- "type": "fallback"
+ payable: true,
+ stateMutability: "payable",
+ type: "fallback",
},
{
- "anonymous": false,
- "inputs": [
+ anonymous: false,
+ inputs: [
{
- "indexed": true,
- "name": "owner",
- "type": "address"
+ indexed: true,
+ name: "owner",
+ type: "address",
},
{
- "indexed": true,
- "name": "spender",
- "type": "address"
+ indexed: true,
+ name: "spender",
+ type: "address",
},
{
- "indexed": false,
- "name": "value",
- "type": "uint256"
- }
+ indexed: false,
+ name: "value",
+ type: "uint256",
+ },
],
- "name": "Approval",
- "type": "event"
+ name: "Approval",
+ type: "event",
},
{
- "anonymous": false,
- "inputs": [
+ anonymous: false,
+ inputs: [
{
- "indexed": true,
- "name": "from",
- "type": "address"
+ indexed: true,
+ name: "from",
+ type: "address",
},
{
- "indexed": true,
- "name": "to",
- "type": "address"
+ indexed: true,
+ name: "to",
+ type: "address",
},
{
- "indexed": false,
- "name": "value",
- "type": "uint256"
- }
+ indexed: false,
+ name: "value",
+ type: "uint256",
+ },
],
- "name": "Transfer",
- "type": "event"
- }
- ]
+ name: "Transfer",
+ type: "event",
+ },
+ ];
const CONTRACT_ADDRESSES = {
usdc: "0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d",
- usdt: "0x55d398326f99059ff775485246999027b3197955"
- }
+ usdt: "0x55d398326f99059ff775485246999027b3197955",
+ };
function getProvider() {
// switches provider based on whether the user is using MetaMask or not
const bscMainnet = {
chainId: 56,
- name: 'binance',
- rpc: 'https://bsc-dataseed.binance.org/',
- explorer: 'https://bscscan.com'
+ name: "binance",
+ rpc: "https://bsc-dataseed.binance.org/",
+ explorer: "https://bscscan.com",
};
-
-
+
if (window.ethereum) {
return new ethers.providers.Web3Provider(window.ethereum);
} else {
- return new ethers.providers.JsonRpcProvider(bscMainnet.rpc, bscMainnet)
+ return new ethers.providers.JsonRpcProvider(bscMainnet.rpc, bscMainnet);
}
}
function connectToMetaMask() {
return new Promise((resolve, reject) => {
// if (typeof window.ethereum === "undefined")
// return reject("MetaMask not installed");
- return resolve(true)
+ return resolve(true);
ethereum
- .request({ method: 'eth_requestAccounts' })
+ .request({ method: "eth_requestAccounts" })
.then((accounts) => {
- console.log('Connected to MetaMask')
- return resolve(accounts)
+ console.log("Connected to MetaMask");
+ return resolve(accounts);
})
.catch((err) => {
- console.log(err)
- return reject(err)
- })
- })
+ console.log(err);
+ return reject(err);
+ });
+ });
}
const getTransactionHistory = (bscOperator.getTransactionHistory = async (
- address
+ address,
+ cursor = null
) => {
try {
if (!address || !isValidAddress(address))
return new Error("Invalid address");
- const url = `https://api.bscscan.com/api?module=account&action=txlist&address=${address}&startblock=0&endblock=99999999&sort=desc&apikey=N7BFDPT7X927YVKWW4XT7VWI6RP2CH38RR`;
+
+ // Moralis API endpoint for BSC transactions
+ const MORALIS_API_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJub25jZSI6IjQyZWNiMjk0LTBiMGItNDg4Yy1hNjUwLTE4NmJhMjFjNjNhYyIsIm9yZ0lkIjoiNDg4NzAzIiwidXNlcklkIjoiNTAyODExIiwidHlwZUlkIjoiZjE5ZmZjYTYtNDllMS00NTdlLTllNjgtMGI1MDIyODU2N2Q4IiwidHlwZSI6IlBST0pFQ1QiLCJpYXQiOjE3Njc1NDkxNDQsImV4cCI6NDkyMzMwOTE0NH0.yr_jtBCrrid4Y5d48iTwJ4PwgMOZn8mwWyiQ7dAmNvw";
+
+ // Fetch 10 transactions per page
+ const url = `https://deep-index.moralis.io/api/v2/${address}?chain=bsc&limit=10${cursor ? `&cursor=${cursor}` : ''}`;
- const response = await fetch(url);
+ const response = await fetch(url, {
+ headers: {
+ "Accept": "application/json",
+ "X-API-Key": MORALIS_API_KEY
+ }
+ });
const data = await response.json();
- if (data.status === "1") {
- return data.result.map((tx) => ({
+ if (data.result && Array.isArray(data.result)) {
+ // Get current block number to calculate confirmations
+ const provider = getProvider();
+ const currentBlockNumber = await provider.getBlockNumber();
+
+ const transactions = data.result.map((tx) => ({
hash: tx.hash,
- from: tx.from,
- to: tx.to,
+ from: tx.from_address,
+ to: tx.to_address,
value: tx.value,
- timeStamp: tx.timeStamp,
- blockNumber: tx.blockNumber,
- confirmations: tx.confirmations || 0,
- gasPrice: tx.gasPrice,
- gasUsed: tx.gasUsed,
+ timeStamp: Math.floor(new Date(tx.block_timestamp).getTime() / 1000),
+ blockNumber: tx.block_number,
+ confirmations: currentBlockNumber - parseInt(tx.block_number),
+ gasPrice: tx.gas_price,
+ gasUsed: tx.receipt_gas_used,
}));
+
+ // Return transactions along with cursor for next page
+ return {
+ transactions: transactions,
+ nextCursor: data.cursor || null,
+ hasMore: !!data.cursor
+ };
} else {
- console.error("Error fetching transaction history:", data.message);
- return [];
+ console.error("Error fetching transaction history:", data.message || "No results");
+ return {
+ transactions: [],
+ nextCursor: null,
+ hasMore: false
+ };
}
} catch (error) {
console.error("Error:", error.message);
@@ -319,9 +344,12 @@
const receipt = await provider.getTransactionReceipt(txHash);
let timestamp = null;
+ let confirmations = 0;
if (tx.blockNumber) {
const block = await provider.getBlock(tx.blockNumber);
timestamp = block.timestamp;
+ const currentBlockNumber = await provider.getBlockNumber();
+ confirmations = currentBlockNumber - tx.blockNumber;
}
return {
@@ -333,6 +361,7 @@
gasUsed: receipt ? receipt.gasUsed : null,
blockNumber: tx.blockNumber,
timeStamp: timestamp,
+ confirmations: confirmations,
status: receipt ? (receipt.status ? "success" : "failed") : "pending",
};
} catch (error) {
@@ -340,90 +369,80 @@
return null;
}
});
-
-
- const getBalance = bscOperator.getBalance = async (address) => {
+
+ const getBalance = (bscOperator.getBalance = async (address) => {
try {
- if (!address || !isValidAddress(address))
- return new Error('Invalid address');
- // Get the balance
+ if (!address || !isValidAddress(address)) {
+ return new Error("Invalid address");
+ }
+
const provider = getProvider();
const balanceWei = await provider.getBalance(address);
const balanceEth = parseFloat(ethers.utils.formatEther(balanceWei));
return balanceEth;
} catch (error) {
- console.error('Error:', error.message);
+ console.error("Error in getBalance:", error);
return error;
}
- }
+ });
-
-
-
-
-
-
-
- const getTokenBalance = bscOperator.getTokenBalance = async (address, token, { contractAddress } = {}) => {
+ const getTokenBalance = (bscOperator.getTokenBalance = async (
+ address,
+ token,
+ { contractAddress } = {}
+ ) => {
try {
if (!address) {
+
throw new Error("Address not specified");
}
if (!token) {
+
throw new Error("Token not specified");
}
if (!CONTRACT_ADDRESSES[token] && !contractAddress) {
+
throw new Error("Contract address of token not available");
}
-
- const provider = getProvider(); // Ensure this returns a valid provider for BSC
- const contract = new ethers.Contract(CONTRACT_ADDRESSES[token] || contractAddress, BEP20ABI, provider);
-
+
+ const provider = getProvider();
+ const contract = new ethers.Contract(
+ CONTRACT_ADDRESSES[token] || contractAddress,
+ BEP20ABI,
+ provider
+ );
+
let balance = await contract.balanceOf(address);
-
- // Assuming 18 decimals for most tokens like USDT and USDC*****************************************************
- // const decimals = 0.00;
+
const decimals = 18;
- const formattedDecimals = decimals.toFixed(1); // This will convert 18 to "18.00"
- console.log(formattedDecimals); // Outputs: "18.0"
+ balance = parseFloat(ethers.utils.formatUnits(balance, decimals));
- balance = parseFloat(ethers.utils.formatUnits(balance, decimals));
-
- // Format the balance to 2 decimal places for display
- balance = balance.toFixed(2);
-
return balance;
- }
- catch (e) {
- // console.error("Error getting token balance:", e.message);
- // throw new Error("Failed to get token balance");
+ } catch (e) {
+ console.error("Error in getTokenBalance:", e);
+ throw e;
}
- }
-
+ });
// Example usage:
// Ensure MetaMask is connected and BSC network is selected in MetaMask
- const address = '0xYourAddressHere'; // Replace with your actual address
+ const address = "0xYourAddressHere"; // Replace with your actual address
(async () => {
try {
- const usdtBalance = await getTokenBalance(address, 'USDT');
- const bnbBalance = await getTokenBalance(address, 'BNB');
- console.log('USDT Balance:', usdtBalance);
- console.log('BNB Balance:', bnbBalance);
+ const usdtBalance = await getTokenBalance(address, "USDT");
+ const bnbBalance = await getTokenBalance(address, "BNB");
+ console.log("USDT Balance:", usdtBalance);
+ console.log("BNB Balance:", bnbBalance);
} catch (error) {
- console.error('Error fetching balances:', error.message);
+ console.error("Error fetching balances:", error.message);
}
})();
-
-
-
-
-
-
-
-
- const estimateGas = bscOperator.estimateGas = async ({ privateKey, receiver, amount }) => {
+ const estimateGas = (bscOperator.estimateGas = async ({
+ privateKey,
+ receiver,
+ amount,
+ }) => {
try {
const provider = getProvider();
const signer = new ethers.Wallet(privateKey, provider);
@@ -433,61 +452,79 @@
value: ethers.utils.parseUnits(amount, "ether"),
});
} catch (e) {
- throw new Error(e)
+ throw new Error(e);
}
- }
+ });
- const sendTransaction = bscOperator.sendTransaction = async ({ privateKey, receiver, amount }) => {
+ const sendTransaction = (bscOperator.sendTransaction = async ({
+ privateKey,
+ receiver,
+ amount,
+ }) => {
try {
const provider = getProvider();
const signer = new ethers.Wallet(privateKey, provider);
- const limit = await estimateGas({ privateKey, receiver, amount })
- // Creating and sending the transaction object
- return signer.sendTransaction({
+
+ const limit = await estimateGas({ privateKey, receiver, amount });
+
+ const tx = await signer.sendTransaction({
to: receiver,
value: ethers.utils.parseUnits(amount, "ether"),
gasLimit: limit,
- nonce: signer.getTransactionCount(),
+ nonce: await signer.getTransactionCount(),
maxPriorityFeePerGas: ethers.utils.parseUnits("2", "gwei"),
- })
+ });
+
+ return tx;
} catch (e) {
- throw new Error(e)
+ console.error("Error in sendTransaction:", e);
+ throw e;
}
- };
-
+ });
- const sendToken = bscOperator.sendToken = async ({ token, privateKey, amount, receiver, contractAddress }) => {
- // Create a wallet using the private key
- const wallet = new ethers.Wallet(privateKey, getProvider());
+ const sendToken = (bscOperator.sendToken = async ({
+ token,
+ privateKey,
+ amount,
+ receiver,
+ contractAddress,
+ }) => {
+ try {
+ const wallet = new ethers.Wallet(privateKey, getProvider());
- // Contract interface
- const tokenContract = new ethers.Contract(CONTRACT_ADDRESSES[token] || contractAddress, BEP20ABI, wallet);
+ const tokenContract = new ethers.Contract(
+ CONTRACT_ADDRESSES[token] || contractAddress,
+ BEP20ABI,
+ wallet
+ );
- // Fetch the correct number of decimals for the token
- const decimals = await tokenContract.decimals();
+ const decimals = await tokenContract.decimals();
- // Convert the amount to the smallest unit of the token
- const amountWei = ethers.utils.parseUnits(amount.toString(), decimals);
+ const amountWei = ethers.utils.parseUnits(amount.toString(), decimals);
- // Estimate gas limit for the transaction
- const gasLimit = await tokenContract.estimateGas.transfer(receiver, amountWei);
+ const gasLimit = await tokenContract.estimateGas.transfer(
+ receiver,
+ amountWei
+ );
- // Get the current gas price
- const gasPrice = await wallet.provider.getGasPrice();
+ const gasPrice = await wallet.provider.getGasPrice();
- // Calculate the gas cost
- const gasCost = gasPrice.mul(gasLimit);
+ const gasCost = gasPrice.mul(gasLimit);
- console.log(`Gas cost: ${ethers.utils.formatEther(gasCost)} BNB`);
+ const balance = await wallet.getBalance();
- // Check if wallet has enough balance to cover gas fees
- const balance = await wallet.getBalance();
- if (balance.lt(gasCost)) {
- throw new Error("Insufficient funds for gas fee");
+ if (balance.lt(gasCost)) {
+ throw new Error("Insufficient funds for gas fee");
+ }
+
+ const tx = await tokenContract.transfer(receiver, amountWei, {
+ gasLimit,
+ gasPrice,
+ });
+ return tx;
+ } catch (e) {
+ console.error("Error in sendToken:", e);
+ throw e;
}
-
-
- // Call the transfer function on the USDC contract
- return tokenContract.transfer(receiver, amountWei, { gasLimit, gasPrice });
- }
-})('object' === typeof module ? module.exports : window.bscOperator = {});
\ No newline at end of file
+ });
+})("object" === typeof module ? module.exports : (window.bscOperator = {}));