50 Commits

Author SHA1 Message Date
tecnovert
c945e267e7 Merge pull request #239 from nahuhh/pr/filters
offers: align filters
2025-01-21 19:12:20 +00:00
tecnovert
ef65420978 Merge pull request #235 from nahuhh/pr/wallet
wallet: resposive ui & cleanup
2025-01-21 19:11:56 +00:00
tecnovert
6da4bf6aaf Merge pull request #225 from nahuhh/cores
help: add --upgradecores
2025-01-21 19:11:29 +00:00
tecnovert
6e56b7f421 Merge pull request #224 from nahuhh/pr/minbid
ui: reword min bid -> min purchase
2025-01-21 19:11:13 +00:00
Gerlof van Ek
f084c6f538 JS/UI: Fix scrolling lag / tooltips + Various fixes and cleanup. (#236)
* JS/UI: Fix scrolling lag + Various fixes and cleanup.

* Fix clear button

* JS: Fix when page is hidden, reconnect and proper pause/resume logic.

* JS: Fix tooltips bugs.

* JS: Various fixes.

* JS: Fix fetch system.

* JS: Cleanup
2025-01-21 19:10:52 +00:00
nahuhh
443bd6917f prepare: fix mweb wallet generation (#238)
* prepare: fix mweb wallet generation

* Restore interface_type on LTC MWEB and send it through initialiseWallet.

---------

Co-authored-by: tecnovert <tecnovert@tecnovert.net>
2025-01-21 19:09:04 +00:00
nahuhh
b55d126a0a ui: reword min bid -> min purchase 2025-01-21 13:23:31 +00:00
nahuhh
586ff3288f offers: align filters 2025-01-21 11:53:38 +00:00
nahuhh
0398fce5a8 wallet: responsive 2025-01-20 22:50:35 +00:00
nahuhh
ef082ff7be xmr: remove inaccurate fee rate, hide sweep all checkbox 2025-01-20 22:50:35 +00:00
nahuhh
168284ce25 wallet: cleanup, deduplicate, djlints 2025-01-20 22:50:27 +00:00
Gerlof van Ek
e797e23625 Merge pull request #234 from gerlofvanek/decimals
JS: Decimals
2025-01-18 22:22:28 +01:00
gerlofvanek
d3fcdc8052 JS: Decimals 2025-01-18 22:21:24 +01:00
Gerlof van Ek
2c176a8c86 Merge pull request #232 from gerlofvanek/cleanup-4
JS: Final tweaks 429
2025-01-18 21:06:54 +01:00
gerlofvanek
e92d5560af JS: Final tweaks 429 2025-01-18 20:53:13 +01:00
Gerlof van Ek
0171ad6889 Merge pull request #231 from gerlofvanek/eslint
Fix: Eslint.
2025-01-18 20:38:02 +01:00
gerlofvanek
5d381d4b73 Fix: Eslint. 2025-01-18 20:22:51 +01:00
Gerlof van Ek
9e24d9a12a Merge pull request #230 from nahuhh/pr/overflow
ui: missing character
2025-01-18 18:58:19 +01:00
nahuhh
21ef6f3129 ui: missing character 2025-01-18 17:31:40 +00:00
Gerlof van Ek
67d808cbe4 JS: Enhanced 429 fix + better error handle. Updated refresh button. (#229)
* JS: Enhanced 429 fix + better error handle. Updated refresh button.

* Update offerstable.js
2025-01-18 18:14:49 +01:00
Gerlof van Ek
5d1bed6423 Merge pull request #228 from nahuhh/pr/overflow
ui: responsive offers page
2025-01-18 18:13:47 +01:00
nahuhh
edc11b4c96 ui: offers responsive ui
ui: offers avoid squishing tiles
2025-01-18 16:55:48 +00:00
Gerlof van Ek
5daf591985 Merge pull request #226 from gerlofvanek/cleanup-2
JS: Fix HTTP Error 429
2025-01-17 22:50:39 +01:00
Gerlof van Ek
aee66712b8 Update pricechart.js 2025-01-17 22:14:19 +01:00
Gerlof van Ek
8de365f9d3 Update offerstable.js 2025-01-17 22:13:37 +01:00
gerlofvanek
765ef9571a JS: Fix HTTP Error 429 2025-01-17 20:15:58 +01:00
nahuhh
c575625097 help: add --upgradecores 2025-01-17 14:54:56 +00:00
tecnovert
fe02441619 Merge pull request #223 from gerlofvanek/cleanup-1
JS: Cleanup + Fixes
2025-01-17 10:46:07 +00:00
gerlofvanek
c992ef571a JS: Cleanup + Fixes 2025-01-17 11:34:28 +01:00
tecnovert
5f275132de Merge pull request #218 from basicswap/dependabot/pip/dev/python-gnupg-0.5.4
build(deps): bump python-gnupg from 0.5.3 to 0.5.4
2025-01-17 07:42:13 +00:00
tecnovert
64151f4203 Merge pull request #216 from nahuhh/bch
bch: v28.0.1
2025-01-17 07:39:51 +00:00
tecnovert
734214af53 Merge pull request #222 from nahuhh/pr/overflow
offers: fix overflow bar
2025-01-17 07:39:09 +00:00
tecnovert
1cb8ffb632 Merge pull request #220 from nahuhh/pr/eslint
lint: eslinting suggestions
2025-01-17 07:34:36 +00:00
nahuhh
40d06df325 offers: fix overflow bar 2025-01-17 02:55:20 +00:00
nahuhh
62031173f5 lint: manual eslint 2025-01-16 21:36:08 +00:00
nahuhh
f473d66de5 lint: auto eslint 2025-01-16 21:26:20 +00:00
tecnovert
e548cf2b3b Merge pull request #219 from gerlofvanek/memory
Fix potential sources of mem leaks + Various related fixes.
2025-01-16 19:28:13 +00:00
gerlofvanek
d1baf4bc10 Improve identity fetching + hor/ver bar fix. 2025-01-16 19:14:58 +01:00
gerlofvanek
3b8e084b2e Simplified API requests and remove debug. 2025-01-16 16:34:36 +01:00
gerlofvanek
0a697c61e8 Fix scroll up / down memory increase bug. 2025-01-16 16:26:48 +01:00
gerlofvanek
5af59dd8da Pricechart fix potential mem leaks. 2025-01-16 14:17:46 +01:00
gerlofvanek
a75cd28995 Reduced retry delay. 2025-01-16 13:23:18 +01:00
gerlofvanek
f40d98ef23 Fix API issue with Firo and various small fixes. 2025-01-16 13:08:52 +01:00
gerlofvanek
b14fba0e1f Fix small API bug and better status feedback. 2025-01-16 12:00:50 +01:00
gerlofvanek
4d928dc98e Better error handling API / Tooltips: Rate, Market. 2025-01-16 11:38:02 +01:00
gerlofvanek
1845f802a2 Update cleanup. 2025-01-16 10:25:25 +01:00
gerlofvanek
7ec9dfa35a Fix manual refresh button. 2025-01-16 01:28:10 +01:00
gerlofvanek
b70e46ffc1 Fix potential sources of mem leaks. 2025-01-16 01:17:23 +01:00
dependabot[bot]
07de2d61af build(deps): bump python-gnupg from 0.5.3 to 0.5.4
Bumps [python-gnupg](https://github.com/vsajip/python-gnupg) from 0.5.3 to 0.5.4.
- [Release notes](https://github.com/vsajip/python-gnupg/releases)
- [Changelog](https://github.com/vsajip/python-gnupg/blob/master/release)
- [Commits](https://github.com/vsajip/python-gnupg/compare/0.5.3...0.5.4)

---
updated-dependencies:
- dependency-name: python-gnupg
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-15 16:59:52 +00:00
nahuhh
b87e034719 bch: v28.0.1 2025-01-14 12:49:31 +00:00
23 changed files with 2441 additions and 1438 deletions

View File

@@ -1303,16 +1303,16 @@ class BasicSwap(BaseApp):
legacy_root_hash = ci.getSeedHash(root_key, 20)
self.setStringKV(key_str, legacy_root_hash.hex(), cursor)
def initialiseWallet(self, coin_type, raise_errors: bool = False) -> None:
if coin_type == Coins.PART:
def initialiseWallet(self, interface_type, raise_errors: bool = False) -> None:
if interface_type == Coins.PART:
return
ci = self.ci(coin_type)
ci = self.ci(interface_type)
db_key_coin_name = ci.coin_name().lower()
self.log.info("Initialising {} wallet.".format(ci.coin_name()))
if coin_type in (Coins.XMR, Coins.WOW):
key_view = self.getWalletKey(coin_type, 1, for_ed25519=True)
key_spend = self.getWalletKey(coin_type, 2, for_ed25519=True)
if interface_type in (Coins.XMR, Coins.WOW):
key_view = self.getWalletKey(interface_type, 1, for_ed25519=True)
key_spend = self.getWalletKey(interface_type, 2, for_ed25519=True)
ci.initialiseWallet(key_view, key_spend)
root_address = ci.getAddressFromKeys(key_view, key_spend)
@@ -1320,7 +1320,7 @@ class BasicSwap(BaseApp):
self.setStringKV(key_str, root_address)
return
root_key = self.getWalletKey(coin_type, 1)
root_key = self.getWalletKey(interface_type, 1)
try:
ci.initialiseWallet(root_key)
except Exception as e:
@@ -1334,13 +1334,13 @@ class BasicSwap(BaseApp):
try:
cursor = self.openDB()
self.storeSeedIDForCoin(root_key, coin_type, cursor)
self.storeSeedIDForCoin(root_key, interface_type, cursor)
# Clear any saved addresses
self.clearStringKV("receive_addr_" + db_key_coin_name, cursor)
self.clearStringKV("stealth_addr_" + db_key_coin_name, cursor)
coin_id = int(coin_type)
coin_id = int(interface_type)
info_type = 1 # wallet
query_str = "DELETE FROM wallets WHERE coin_id = ? AND balance_type = ?"
cursor.execute(query_str, (coin_id, info_type))

View File

@@ -84,7 +84,7 @@ NAV_VERSION_TAG = os.getenv("NAV_VERSION_TAG", "")
DCR_VERSION = os.getenv("DCR_VERSION", "1.8.1")
DCR_VERSION_TAG = os.getenv("DCR_VERSION_TAG", "")
BITCOINCASH_VERSION = os.getenv("BITCOINCASH_VERSION", "27.1.0")
BITCOINCASH_VERSION = os.getenv("BITCOINCASH_VERSION", "28.0.1")
BITCOINCASH_VERSION_TAG = os.getenv("BITCOINCASH_VERSION_TAG", "")
DOGECOIN_VERSION = os.getenv("DOGECOIN_VERSION", "23.2.1")
@@ -268,10 +268,18 @@ TOR_PROXY_HOST = os.getenv("TOR_PROXY_HOST", "127.0.0.1")
TOR_PROXY_PORT = int(os.getenv("TOR_PROXY_PORT", 9050))
TOR_CONTROL_PORT = int(os.getenv("TOR_CONTROL_PORT", 9051))
TOR_DNS_PORT = int(os.getenv("TOR_DNS_PORT", 5353))
TOR_CONTROL_LISTEN_INTERFACE = os.getenv("TOR_CONTROL_LISTEN_INTERFACE", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0")
TORRC_PROXY_HOST = os.getenv("TORRC_PROXY_HOST", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0")
TORRC_CONTROL_HOST = os.getenv("TORRC_CONTROL_HOST", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0")
TORRC_DNS_HOST = os.getenv("TORRC_DNS_HOST", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0")
TOR_CONTROL_LISTEN_INTERFACE = os.getenv(
"TOR_CONTROL_LISTEN_INTERFACE", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0"
)
TORRC_PROXY_HOST = os.getenv(
"TORRC_PROXY_HOST", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0"
)
TORRC_CONTROL_HOST = os.getenv(
"TORRC_CONTROL_HOST", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0"
)
TORRC_DNS_HOST = os.getenv(
"TORRC_DNS_HOST", "127.0.0.1" if BSX_LOCAL_TOR else "0.0.0.0"
)
TEST_TOR_PROXY = toBool(
os.getenv("TEST_TOR_PROXY", "true")
@@ -1593,6 +1601,9 @@ def printHelp():
print("--withoutcoin= Do not prepare system to run daemon for coin.")
print("--addcoin= Add coin to existing setup.")
print("--disablecoin= Make coin inactive.")
print(
"--upgradecores Upgrade all coin cores present in basicswap.json. Optionally use alongside --withcoin= or --withoutcoin="
)
print("--preparebinonly Don't prepare settings or datadirs.")
print("--nocores Don't download and extract any coin clients.")
print("--usecontainers Expect each core to run in a unique container.")

View File

@@ -137,7 +137,7 @@ class LTCInterfaceMWEB(LTCInterface):
self.rpc_wallet("walletpassphrase", [password, 100000000])
if self.getWalletSeedID() == "Not found":
self._sc.initialiseWallet(self.coin_type())
self._sc.initialiseWallet(self.interface_type())
# Workaround to trigger mweb_spk_man->LoadMWEBKeychain()
self.rpc("unloadwallet", ["mweb"])

View File

@@ -14,7 +14,7 @@ document.addEventListener('DOMContentLoaded', () => {
const image = selectedOption.getAttribute('data-image') || '';
const name = selectedOption.textContent.trim();
select.style.backgroundImage = image ? `url(${image}?${new Date().getTime()})` : '';
const selectImage = select.nextElementSibling.querySelector('.select-image');
if (selectImage) {
selectImage.src = image;

View File

@@ -0,0 +1,190 @@
(function(window) {
'use strict';
function positionElement(targetEl, triggerEl, placement = 'bottom', offsetDistance = 8) {
targetEl.style.visibility = 'hidden';
targetEl.style.display = 'block';
const triggerRect = triggerEl.getBoundingClientRect();
const targetRect = targetEl.getBoundingClientRect();
const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
let top, left;
top = triggerRect.bottom + offsetDistance;
left = triggerRect.left + (triggerRect.width - targetRect.width) / 2;
switch (placement) {
case 'bottom-start':
left = triggerRect.left;
break;
case 'bottom-end':
left = triggerRect.right - targetRect.width;
break;
}
const viewport = {
width: window.innerWidth,
height: window.innerHeight
};
if (left < 10) left = 10;
if (left + targetRect.width > viewport.width - 10) {
left = viewport.width - targetRect.width - 10;
}
targetEl.style.position = 'fixed';
targetEl.style.top = `${Math.round(top)}px`;
targetEl.style.left = `${Math.round(left)}px`;
targetEl.style.margin = '0';
targetEl.style.maxHeight = `${viewport.height - top - 10}px`;
targetEl.style.overflow = 'auto';
targetEl.style.visibility = 'visible';
}
class Dropdown {
constructor(targetEl, triggerEl, options = {}) {
this._targetEl = targetEl;
this._triggerEl = triggerEl;
this._options = {
placement: options.placement || 'bottom',
offset: options.offset || 5,
onShow: options.onShow || function() {},
onHide: options.onHide || function() {}
};
this._visible = false;
this._initialized = false;
this._handleScroll = this._handleScroll.bind(this);
this._handleResize = this._handleResize.bind(this);
this._handleOutsideClick = this._handleOutsideClick.bind(this);
this.init();
}
init() {
if (!this._initialized) {
this._targetEl.style.margin = '0';
this._targetEl.style.display = 'none';
this._targetEl.style.position = 'fixed';
this._targetEl.style.zIndex = '50';
this._setupEventListeners();
this._initialized = true;
}
}
_setupEventListeners() {
this._triggerEl.addEventListener('click', (e) => {
e.stopPropagation();
this.toggle();
});
document.addEventListener('click', this._handleOutsideClick);
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') this.hide();
});
window.addEventListener('scroll', this._handleScroll, true);
window.addEventListener('resize', this._handleResize);
}
_handleScroll() {
if (this._visible) {
requestAnimationFrame(() => {
positionElement(
this._targetEl,
this._triggerEl,
this._options.placement,
this._options.offset
);
});
}
}
_handleResize() {
if (this._visible) {
requestAnimationFrame(() => {
positionElement(
this._targetEl,
this._triggerEl,
this._options.placement,
this._options.offset
);
});
}
}
_handleOutsideClick(e) {
if (this._visible &&
!this._targetEl.contains(e.target) &&
!this._triggerEl.contains(e.target)) {
this.hide();
}
}
show() {
if (!this._visible) {
this._targetEl.style.display = 'block';
this._targetEl.style.visibility = 'hidden';
requestAnimationFrame(() => {
positionElement(
this._targetEl,
this._triggerEl,
this._options.placement,
this._options.offset
);
this._visible = true;
this._options.onShow();
});
}
}
hide() {
if (this._visible) {
this._targetEl.style.display = 'none';
this._visible = false;
this._options.onHide();
}
}
toggle() {
if (this._visible) {
this.hide();
} else {
this.show();
}
}
destroy() {
document.removeEventListener('click', this._handleOutsideClick);
window.removeEventListener('scroll', this._handleScroll, true);
window.removeEventListener('resize', this._handleResize);
this._initialized = false;
}
}
function initDropdowns() {
document.querySelectorAll('[data-dropdown-toggle]').forEach(triggerEl => {
const targetId = triggerEl.getAttribute('data-dropdown-toggle');
const targetEl = document.getElementById(targetId);
if (targetEl) {
const placement = triggerEl.getAttribute('data-dropdown-placement');
new Dropdown(targetEl, triggerEl, {
placement: placement || 'bottom-start'
});
}
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initDropdowns);
} else {
initDropdowns();
}
window.Dropdown = Dropdown;
window.initDropdowns = initDropdowns;
})(window);

File diff suppressed because one or more lines are too long

View File

@@ -19,8 +19,8 @@ document.addEventListener('DOMContentLoaded', function() {
const backdrop = document.querySelectorAll('.navbar-backdrop');
if (close.length) {
for (var i = 0; i < close.length; i++) {
close[i].addEventListener('click', function() {
for (var k = 0; k < close.length; k++) {
close[k].addEventListener('click', function() {
for (var j = 0; j < menu.length; j++) {
menu[j].classList.toggle('hidden');
}
@@ -29,12 +29,12 @@ document.addEventListener('DOMContentLoaded', function() {
}
if (backdrop.length) {
for (var i = 0; i < backdrop.length; i++) {
backdrop[i].addEventListener('click', function() {
for (var l = 0; l < backdrop.length; l++) {
backdrop[l].addEventListener('click', function() {
for (var j = 0; j < menu.length; j++) {
menu[j].classList.toggle('hidden');
}
});
}
}
});
});

View File

@@ -1,5 +1,5 @@
window.addEventListener('DOMContentLoaded', (event) => {
let err_msgs = document.querySelectorAll('p.error_msg');
window.addEventListener('DOMContentLoaded', () => {
const err_msgs = document.querySelectorAll('p.error_msg');
for (let i = 0; i < err_msgs.length; i++) {
err_msg = err_msgs[i].innerText;
if (err_msg.indexOf('coin_to') >= 0 || err_msg.indexOf('Coin To') >= 0) {
@@ -29,9 +29,9 @@ window.addEventListener('DOMContentLoaded', (event) => {
}
// remove error class on input or select focus
let inputs = document.querySelectorAll('input.error');
let selects = document.querySelectorAll('select.error');
let elements = [...inputs, ...selects];
const inputs = document.querySelectorAll('input.error');
const selects = document.querySelectorAll('select.error');
const elements = [...inputs, ...selects];
elements.forEach((element) => {
element.addEventListener('focus', (event) => {
event.target.classList.remove('error');

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

115
basicswap/static/js/tabs.js Normal file
View File

@@ -0,0 +1,115 @@
(function(window) {
'use strict';
class Tabs {
constructor(tabsEl, items = [], options = {}) {
this._tabsEl = tabsEl;
this._items = items;
this._activeTab = options.defaultTabId ? this.getTab(options.defaultTabId) : null;
this._options = {
defaultTabId: options.defaultTabId || null,
activeClasses: options.activeClasses || 'text-blue-600 hover:text-blue-600 dark:text-blue-500 dark:hover:text-blue-500 border-blue-600 dark:border-blue-500',
inactiveClasses: options.inactiveClasses || 'dark:border-transparent text-gray-500 hover:text-gray-600 dark:text-gray-400 border-gray-100 hover:border-gray-300 dark:border-gray-700 dark:hover:text-gray-300',
onShow: options.onShow || function() {}
};
this._initialized = false;
this.init();
}
init() {
if (this._items.length && !this._initialized) {
if (!this._activeTab) {
this.setActiveTab(this._items[0]);
}
this.show(this._activeTab.id, true);
this._items.forEach(tab => {
tab.triggerEl.addEventListener('click', () => {
this.show(tab.id);
});
});
this._initialized = true;
}
}
show(tabId, force = false) {
const tab = this.getTab(tabId);
if ((tab !== this._activeTab) || force) {
this._items.forEach(t => {
if (t !== tab) {
t.triggerEl.classList.remove(...this._options.activeClasses.split(' '));
t.triggerEl.classList.add(...this._options.inactiveClasses.split(' '));
t.targetEl.classList.add('hidden');
t.triggerEl.setAttribute('aria-selected', false);
}
});
tab.triggerEl.classList.add(...this._options.activeClasses.split(' '));
tab.triggerEl.classList.remove(...this._options.inactiveClasses.split(' '));
tab.triggerEl.setAttribute('aria-selected', true);
tab.targetEl.classList.remove('hidden');
this.setActiveTab(tab);
this._options.onShow(this, tab);
}
}
getTab(id) {
return this._items.find(t => t.id === id);
}
getActiveTab() {
return this._activeTab;
}
setActiveTab(tab) {
this._activeTab = tab;
}
}
function initTabs() {
document.querySelectorAll('[data-tabs-toggle]').forEach(tabsEl => {
const items = [];
let defaultTabId = null;
tabsEl.querySelectorAll('[role="tab"]').forEach(triggerEl => {
const isActive = triggerEl.getAttribute('aria-selected') === 'true';
const tab = {
id: triggerEl.getAttribute('data-tabs-target'),
triggerEl: triggerEl,
targetEl: document.querySelector(triggerEl.getAttribute('data-tabs-target'))
};
items.push(tab);
if (isActive) {
defaultTabId = tab.id;
}
});
new Tabs(tabsEl, items, {
defaultTabId: defaultTabId
});
});
}
const style = document.createElement('style');
style.textContent = `
[data-tabs-toggle] [role="tab"] {
cursor: pointer;
}
`;
document.head.appendChild(style);
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initTabs);
} else {
initTabs();
}
window.Tabs = Tabs;
window.initTabs = initTabs;
})(window);

View File

@@ -0,0 +1,309 @@
(function(window) {
'use strict';
const tooltipContainer = document.createElement('div');
tooltipContainer.className = 'tooltip-container';
const style = document.createElement('style');
style.textContent = `
[role="tooltip"] {
position: absolute;
z-index: 9999;
transition: opacity 0.2s ease-in-out;
pointer-events: auto;
opacity: 0;
visibility: hidden;
}
.tooltip-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 0;
overflow: visible;
pointer-events: none;
z-index: 9999;
}
`;
function ensureContainerExists() {
if (!document.body.contains(tooltipContainer)) {
document.body.appendChild(tooltipContainer);
}
}
function rafThrottle(callback) {
let requestId = null;
let lastArgs = null;
const later = (context) => {
requestId = null;
callback.apply(context, lastArgs);
};
return function(...args) {
lastArgs = args;
if (requestId === null) {
requestId = requestAnimationFrame(() => later(this));
}
};
}
function positionElement(targetEl, triggerEl, placement = 'top', offsetDistance = 8) {
const triggerRect = triggerEl.getBoundingClientRect();
const targetRect = targetEl.getBoundingClientRect();
let top, left;
switch (placement) {
case 'top':
top = triggerRect.top - targetRect.height - offsetDistance;
left = triggerRect.left + (triggerRect.width - targetRect.width) / 2;
break;
case 'bottom':
top = triggerRect.bottom + offsetDistance;
left = triggerRect.left + (triggerRect.width - targetRect.width) / 2;
break;
case 'left':
top = triggerRect.top + (triggerRect.height - targetRect.height) / 2;
left = triggerRect.left - targetRect.width - offsetDistance;
break;
case 'right':
top = triggerRect.top + (triggerRect.height - targetRect.height) / 2;
left = triggerRect.right + offsetDistance;
break;
}
const viewport = {
width: window.innerWidth,
height: window.innerHeight
};
if (left < 0) left = 0;
if (top < 0) top = 0;
if (left + targetRect.width > viewport.width)
left = viewport.width - targetRect.width;
if (top + targetRect.height > viewport.height)
top = viewport.height - targetRect.height;
targetEl.style.transform = `translate(${Math.round(left)}px, ${Math.round(top)}px)`;
}
const tooltips = new WeakMap();
class Tooltip {
constructor(targetEl, triggerEl, options = {}) {
ensureContainerExists();
this._targetEl = targetEl;
this._triggerEl = triggerEl;
this._options = {
placement: options.placement || 'top',
triggerType: options.triggerType || 'hover',
offset: options.offset || 8,
onShow: options.onShow || function() {},
onHide: options.onHide || function() {}
};
this._visible = false;
this._initialized = false;
this._hideTimeout = null;
this._showTimeout = null;
if (this._targetEl.parentNode !== tooltipContainer) {
tooltipContainer.appendChild(this._targetEl);
}
this._targetEl.style.visibility = 'hidden';
this._targetEl.style.opacity = '0';
this._showHandler = this.show.bind(this);
this._hideHandler = this._handleHide.bind(this);
this._updatePosition = rafThrottle(() => {
if (this._visible) {
positionElement(
this._targetEl,
this._triggerEl,
this._options.placement,
this._options.offset
);
}
});
this.init();
}
init() {
if (!this._initialized) {
this._setupEventListeners();
this._initialized = true;
positionElement(
this._targetEl,
this._triggerEl,
this._options.placement,
this._options.offset
);
}
}
_setupEventListeners() {
this._triggerEl.addEventListener('mouseenter', this._showHandler);
this._triggerEl.addEventListener('mouseleave', this._hideHandler);
this._triggerEl.addEventListener('focus', this._showHandler);
this._triggerEl.addEventListener('blur', this._hideHandler);
this._targetEl.addEventListener('mouseenter', () => {
clearTimeout(this._hideTimeout);
clearTimeout(this._showTimeout);
this._visible = true;
this._targetEl.style.visibility = 'visible';
this._targetEl.style.opacity = '1';
});
this._targetEl.addEventListener('mouseleave', this._hideHandler);
if (this._options.triggerType === 'click') {
this._triggerEl.addEventListener('click', this._showHandler);
}
window.addEventListener('scroll', this._updatePosition, { passive: true });
document.addEventListener('scroll', this._updatePosition, { passive: true, capture: true });
window.addEventListener('resize', this._updatePosition, { passive: true });
let rafId;
const smoothUpdate = () => {
if (this._visible) {
this._updatePosition();
rafId = requestAnimationFrame(smoothUpdate);
}
};
this._startSmoothUpdate = () => {
if (!rafId) rafId = requestAnimationFrame(smoothUpdate);
};
this._stopSmoothUpdate = () => {
if (rafId) {
cancelAnimationFrame(rafId);
rafId = null;
}
};
}
_handleHide() {
clearTimeout(this._hideTimeout);
clearTimeout(this._showTimeout);
this._hideTimeout = setTimeout(() => {
if (this._visible) {
this.hide();
}
}, 100);
}
show() {
clearTimeout(this._hideTimeout);
clearTimeout(this._showTimeout);
this._showTimeout = setTimeout(() => {
if (!this._visible) {
positionElement(
this._targetEl,
this._triggerEl,
this._options.placement,
this._options.offset
);
this._targetEl.style.visibility = 'visible';
this._targetEl.style.opacity = '1';
this._visible = true;
this._startSmoothUpdate();
this._options.onShow();
}
}, 20);
}
hide() {
this._targetEl.style.opacity = '0';
this._targetEl.style.visibility = 'hidden';
this._visible = false;
this._stopSmoothUpdate();
this._options.onHide();
}
destroy() {
clearTimeout(this._hideTimeout);
clearTimeout(this._showTimeout);
this._stopSmoothUpdate();
this._triggerEl.removeEventListener('mouseenter', this._showHandler);
this._triggerEl.removeEventListener('mouseleave', this._hideHandler);
this._triggerEl.removeEventListener('focus', this._showHandler);
this._triggerEl.removeEventListener('blur', this._hideHandler);
this._targetEl.removeEventListener('mouseenter', this._showHandler);
this._targetEl.removeEventListener('mouseleave', this._hideHandler);
if (this._options.triggerType === 'click') {
this._triggerEl.removeEventListener('click', this._showHandler);
}
window.removeEventListener('scroll', this._updatePosition);
document.removeEventListener('scroll', this._updatePosition, true);
window.removeEventListener('resize', this._updatePosition);
this._targetEl.style.visibility = '';
this._targetEl.style.opacity = '';
this._targetEl.style.transform = '';
if (this._targetEl.parentNode === tooltipContainer) {
document.body.appendChild(this._targetEl);
}
this._initialized = false;
}
toggle() {
if (this._visible) {
this.hide();
} else {
this.show();
}
}
}
document.head.appendChild(style);
function initTooltips() {
ensureContainerExists();
document.querySelectorAll('[data-tooltip-target]').forEach(triggerEl => {
if (tooltips.has(triggerEl)) return;
const targetId = triggerEl.getAttribute('data-tooltip-target');
const targetEl = document.getElementById(targetId);
if (targetEl) {
const placement = triggerEl.getAttribute('data-tooltip-placement');
const triggerType = triggerEl.getAttribute('data-tooltip-trigger');
const tooltip = new Tooltip(targetEl, triggerEl, {
placement: placement || 'top',
triggerType: triggerType || 'hover',
offset: 8
});
tooltips.set(triggerEl, tooltip);
}
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initTooltips);
} else {
initTooltips();
}
window.Tooltip = Tooltip;
window.initTooltips = initTooltips;
})(window);

View File

@@ -8,13 +8,18 @@
{% endif %}
<script src="/static/js/libs/chart.js"></script>
<script src="/static/js/libs/chartjs-adapter-date-fns.bundle.min.js"></script>
<link type="text/css" media="all" href="/static/css/libs/flowbite.min.css" rel="stylesheet" />
<link type="text/css" media="all" href="/static/css/libs/tailwind.min.css" rel="stylesheet">
<link type="text/css" media="all" href="/static/css/style.css" rel="stylesheet">
<script src="/static/js/main.js"></script>
<script src="/static/js/libs/flowbite.js"></script>
<script>
<script src="/static/js/main.js"></script>
<script src="/static/js/tabs.js"></script>
<script src="/static/js/dropdown.js"></script>
<script src="/static/js/tooltips.js"></script>
<script>
const isDarkMode =
localStorage.getItem('color-theme') === 'dark' ||
(!localStorage.getItem('color-theme') &&
@@ -451,7 +456,6 @@ document.addEventListener('DOMContentLoaded', function() {
<div id="tooltip-your-offers" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
<p><b>Total:</b> {{ summary.num_sent_offers }}</p>
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
</li>
@@ -468,7 +472,7 @@ document.addEventListener('DOMContentLoaded', function() {
<div id="tooltip-bids-received" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
<p><b>Total:</b> {{ summary.num_recv_bids }}</p>
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
<li>
<a data-tooltip-target="tooltip-bids-sent" class="flex mr-10 items-center text-sm text-gray-400 hover:text-gray-600 dark:text-gray-100 dark:hover:text-gray-100" href="/sentbids">
@@ -476,7 +480,7 @@ document.addEventListener('DOMContentLoaded', function() {
<span>Bids Sent</span><span class="inline-flex justify-center items-center text-xs font-semibold ml-3 mr-2 px-2.5 py-1 font-small text-white bg-blue-500 rounded-full">{{ summary.num_sent_active_bids }}</span></a>
<div id="tooltip-bids-sent" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
<p><b>Total:</b> {{ summary.num_sent_bids }}</p>
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
</li>

View File

@@ -137,7 +137,7 @@
<td class="py-3 px-6 bold">{{ data.amt_to }} {{ data.tla_to }}</td>
</tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
<td class="py-3 px-6 bold">Minimum Bid Amount</td>
<td class="py-3 px-6 bold">Minimum Purchase</td>
<td class="py-3 px-6">{{ data.amt_bid_min }} {{ data.tla_from }}</td>
</tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
@@ -747,40 +747,24 @@ function resetForm() {
const bidAmountInput = document.getElementById('bid_amount');
const bidRateInput = document.getElementById('bid_rate');
const validMinsInput = document.querySelector('input[name="validmins"]');
const addrFromSelect = document.querySelector('select[name="addr_from"]');
const amtVar = document.getElementById('amt_var')?.value === 'True';
if (bidAmountSendInput) {
const defaultSendAmount = bidAmountSendInput.getAttribute('max');
bidAmountSendInput.value = defaultSendAmount;
bidAmountSendInput.value = amtVar ? '' : bidAmountSendInput.getAttribute('max');
}
if (bidAmountInput) {
const defaultReceiveAmount = bidAmountInput.getAttribute('max');
bidAmountInput.value = defaultReceiveAmount;
bidAmountInput.value = amtVar ? '' : bidAmountInput.getAttribute('max');
}
if (bidRateInput && !bidRateInput.disabled) {
const defaultRate = document.getElementById('offer_rate')?.value || '';
bidRateInput.value = defaultRate;
}
if (validMinsInput) {
validMinsInput.value = "60";
}
if (addrFromSelect) {
if (addrFromSelect.options.length > 1) {
addrFromSelect.selectedIndex = 1;
} else {
addrFromSelect.selectedIndex = 0;
}
const selectedOption = addrFromSelect.options[addrFromSelect.selectedIndex];
saveAddress(selectedOption.value, selectedOption.text);
if (!amtVar) {
updateBidParams('rate');
}
updateBidParams('rate');
updateModalValues();
const errorMessages = document.querySelectorAll('.error-message');
errorMessages.forEach(msg => msg.remove());

View File

@@ -293,7 +293,7 @@
<div class="w-full md:flex-1 p-3">
<div class="flex flex-wrap -m-3">
<div class="w-full md:w-1/2 p-3">
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Minimum Bid Amount</p>
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Minimum Purchase</p>
<div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_bid_amount_svg | safe }}

View File

@@ -274,7 +274,7 @@ if (document.readyState === 'loading') {
<div class="w-full md:flex-1 p-3">
<div class="flex flex-wrap -m-3">
<div class="w-full md:w-1/2 p-3">
<p class="mb-1.5 font-medium text-base dark:text-white text-coolGray-800">Minimum Bid Amount</p>
<p class="mb-1.5 font-medium text-base dark:text-white text-coolGray-800">Minimum Purchase</p>
<div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_bid_amount_svg | safe }}

View File

@@ -279,7 +279,7 @@
<div class="w-full md:flex-1 p-3">
<div class="flex flex-wrap -m-3">
<div class="w-full md:w-1/2 p-3">
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Minimum Bid Amount</p>
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Minimum Purchase</p>
<div class="relative">
<div class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none">
{{ select_bid_amount_svg | safe }}

View File

@@ -25,11 +25,11 @@ function getWebSocketConfig() {
</script>
{% if sent_offers %}
<div class="container mx-auto">
<section class="p-5 mt-5">
<div class="flex flex-wrap items-center -m-2">
<div class="w-full md:w-1/2 p-2">
<ul class="flex flex-wrap items-center gap-x-3 mb-2">
<div class="lg:container mx-auto">
<section class="p-3 mt-2">
<div class="flex items-center">
<div class="w-full">
<ul class="flex items-center gap-x-2 mb-1">
<li><a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/">Home</a></li>
<li>{{ breadcrumb_line_svg | safe }}</li>
<li>
@@ -44,82 +44,74 @@ function getWebSocketConfig() {
</section>
</div>
{% endif %}
{% if sent_offers %}
<section class="py-5">
<section class="py-3">
{% else %}
<section class="py-5 mt-5">
<section class="py-3 px-4 mt-3">
{% endif %}
<div class="container px-4 mx-auto">
<div class="relative py-11 px-16 bg-coolGray-900 dark:bg-gray-500 rounded-md overflow-hidden">
<img class="absolute z-10 left-4 top-4 right-4 bottom-4" src="/static/images/elements/dots-red.svg" alt="dots-red">
<img class="absolute h-64 left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 object-cover" src="/static/images/elements/wave.svg" alt="wave">
<div class="relative z-20 flex flex-wrap items-center -m-3">
<div class="w-full md:w-1/2 p-3">
<h2 class="mb-6 text-4xl font-bold text-white tracking-tighter">{{ page_type }}</h2>
<p class="font-normal text-coolGray-200 dark:text-white">{{ page_type_description }}</p>
</div>
<div class="rounded-full{{ page_button }} w-full md:w-1/2 p-3 p-6 container flex flex-wrap items-center justify-end items-center mx-auto">
<a id="refresh" href="/newoffer" class="rounded-full flex flex-wrap justify-center px-5 py-3 bg-blue-500 hover:bg-green-600 hover:border-green-600 font-medium text-sm text-white border border-blue-500 rounded-md focus:ring-0 focus:outline-none">{{ place_new_offer_svg | safe }}<span>Place new Offer</span></a>
</div>
<div class="lg:container mx-auto">
<div class="relative py-6 px-8 bg-coolGray-900 dark:bg-gray-500 rounded-md overflow-hidden">
<img class="absolute h-48 left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 object-cover" src="/static/images/elements/wave.svg" alt="wave">
<div class="relative z-20 flex flex-wrap items-center -m-2">
<div class="w-full md:w-1/2 p-2">
<h2 class="mb-3 text-3xl font-bold text-white tracking-tighter">{{ page_type }}</h2>
<p class="font-normal text-coolGray-200 dark:text-white">{{ page_type_description }}</p>
</div>
<div class="rounded-full{{ page_button }} w-full md:w-1/2 p-2 lg:container flex flex-wrap items-center justify-end mx-auto">
<a id="refresh" href="/newoffer" class="rounded-full flex flex-wrap justify-center px-4 py-2 bg-blue-500 hover:bg-green-600 hover:border-green-600 font-medium text-sm text-white border border-blue-500 rounded-md focus:ring-0 focus:outline-none">{{ place_new_offer_svg | safe }}<span>Place new Offer</span></a>
</div>
</div>
</div>
</section>
</div>
</section>
{% include 'inc_messages.html' %}
{% if show_chart %}
<section class="relative hidden md:block">
<div class="pl-6 pr-6 pt-0 pb-0 mt-5 h-full overflow-hidden">
<div class="px-6 py-0 mt-5 h-full overflow-hidden">
<div class="pb-6 border-coolGray-100">
<div class="flex flex-wrap items-center justify-between -m-2">
<div class="flex flex-wrap items-center justify-between">
<div class="w-full pt-2">
<div class="container px-4 mx-auto">
<div class="lg:container mx-auto">
<div class="pt-6 pb-8 bg-coolGray-100 dark:bg-gray-500 rounded-xl container-to-blur">
<div class="flex justify-between items-center mb-4 mr-10 ml-10">
<div class="flex items-center justify-between">
<h2 class="text-xl font-bold dark:text-white" id="chart-title">Price Chart</h2>
<div class="flex items-center space-x-4">
<button id="resolution-year" class="ml-5 resolution-button">1Y</button>
<button id="resolution-sixMonths" class="resolution-button">6M</button>
<button id="resolution-day" class="resolution-button">24H</button>
<button id="resolution-year" class="ml-5 resolution-button">1Y</button>
<button id="resolution-sixMonths" class="resolution-button">6M</button>
<button id="resolution-day" class="resolution-button">24H</button>
</div>
</div>
<div class="flex items-center">
<span id="load-time hidden" class="mr-2 text-sm text-gray-600 dark:text-gray-300"></span>
<span id="last-refreshed-time hidden" class="mr-2 text-sm text-gray-600 dark:text-gray-300"></span>
<span id="cache-status hidden" class="mr-4 text-sm text-gray-600 dark:text-gray-300"></span>
<span id="tor-status" class="mr-4 text-sm hidden {% if tor_established %}text-green-500{% else %}text-red-500{% endif %}"> Tor {% if tor_established %}ON{% else %}OFF{% endif %}
<span id="tor-status" class="mr-4 text-sm hidden {% if tor_established %}text-green-500{% else %}text-red-500{% endif %}">
Tor {% if tor_established %}ON{% else %}OFF{% endif %}
<a href="https://academy.particl.io/en/latest/basicswap-guides/basicswapguides_tor.html" target="_blank" rel="noopener noreferrer" class="underline">(?)</a>
</span>
</span>
<span id="next-refresh-time" class="mr-4 text-sm text-gray-600 dark:text-gray-300">
<span id="next-refresh-label"></span>
<span id="next-refresh-value"></span>
</span>
<div id="tooltip-volume" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
Toggle Coin Volume
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
<div id="tooltip-volume" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">Toggle Coin Volume</div>
<button id="toggle-volume" data-tooltip-target="tooltip-volume" class="text-white font-bold py-2 px-4 rounded mr-2 focus:outline-none focus:ring-0 transition-colors duration-200" title="Toggle Volume">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path d="M2 11a1 1 0 011-1h2a1 1 0 011 1v5a1 1 0 01-1 1H3a1 1 0 01-1-1v-5zM8 7a1 1 0 011-1h2a1 1 0 011 1v9a1 1 0 01-1 1H9a1 1 0 01-1-1V7zM14 4a1 1 0 011-1h2a1 1 0 011 1v12a1 1 0 01-1 1h-2a1 1 0 01-1-1V4z" />
</svg>
</button>
<div id="tooltip-refresh" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
Refresh Charts/Prices & Clear Cache
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
<div id="tooltip-refresh" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">Refresh Charts/Prices & Clear Cache</div>
<button id="refresh-all" data-tooltip-target="tooltip-refresh" class="text-gray-600 dark:text-gray-400 font-bold py-2 px-4 rounded mr-2 focus:outline-none focus:ring-0 transition-colors duration-200" title="Refresh Data & Clear Cache">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
<circle cx="12" cy="12" r="3" />
</svg>
</button>
<div id="tooltip-auto" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
Auto Refresh Enable/Disable
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
<div id="tooltip-auto" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">Auto Refresh Enable/Disable</div>
<button id="toggle-auto-refresh" data-enabled="false" data-tooltip-target="tooltip-auto" class="text-white font-bold py-2 px-4 rounded mr-2 focus:outline-none focus:ring-0 transition-colors duration-200" title="Enable Auto-Refresh">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm.008 9.057a1 1 0 011.276.61A5.002 5.002 0 0014.001 13H11a1 1 0 110-2h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 01.61-1.276z" clip-rule="evenodd" />
@@ -137,18 +129,25 @@ function getWebSocketConfig() {
</div>
</div>
</div>
<div id="error-overlay" class="error-overlay hidden absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center">
<div id="error-content" class="error-content bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-2xl mx-4 relative">
<button id="close-error" class="absolute top-3 right-3 bg-red-500 text-white rounded-full p-2 hover:bg-red-600 focus:outline-none">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<div id="error-overlay" class="notice-overlay hidden absolute inset-0 bg-opacity-30 backdrop-blur-sm flex items-center justify-center">
<div id="error-content" class="notice-content bg-white dark:bg-gray-800 rounded-xl p-6 w-full max-w-2xl mx-4 relative shadow-lg">
<div class="absolute top-0 left-0 right-0 h-1 bg-gradient-to-r from-blue-400 via-blue-500 to-blue-600"></div>
<button id="close-error" class="absolute top-3 right-3 text-gray-400 hover:text-gray-500 dark:text-gray-500 dark:hover:text-white rounded-full p-2 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors focus:outline-none">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
<p class="text-red-600 font-semibold text-xl mb-4">Error</p>
<p id="error-message" class="text-gray-700 dark:text-gray-300 text-lg mb-6"></p>
<p class="text-sm text-gray-600 dark:text-gray-400">To review or update your Chart API Key(s), navigate to<a href="/settings" class="text-blue-500 hover:underline">Settings & Tools > Settings > General (TAB)</a>.
</p>
<div class="flex items-center gap-3 mb-4">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-blue-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
</svg>
<p class="text-lg font-medium text-gray-900 dark:text-gray-100">Notice</p>
</div>
<p id="error-message" class="text-gray-600 dark:text-gray-300 text-base mb-6"></p>
<div class="text-sm text-gray-500 dark:text-gray-400">
Need to update your (API) settings?
<a href="/settings" class="text-blue-500 hover:text-blue-600 dark:hover:text-blue-400 font-medium ml-1 hover:underline">Go to Settings -> General</a>
</div>
</div>
</div>
</div>
@@ -157,9 +156,9 @@ function getWebSocketConfig() {
</div>
</section>
<section class="py-4 flex flex-wrap justify-center overflow-hidden container-to-blur">
<div class="container px-4 mx-auto">
<div class="flex flex-wrap justify-center -m-3" id="coin-container">
<section class="py-4 px-3 flex flex-wrap overflow-hidden container-to-blur">
<div class="lg:container mx-auto">
<div class="flex flex-wrap justify-center lg:justify-start xl:justify-center" id="coin-container">
{% set coin_data = {
'BTC': {'name': 'Bitcoin', 'symbol': 'BTC', 'image': 'Bitcoin.png', 'show': true},
'XMR': {'name': 'Monero', 'symbol': 'XMR', 'image': 'Monero.png', 'show': true},
@@ -192,9 +191,9 @@ function getWebSocketConfig() {
{% for coin_symbol in custom_order %}
{% if coin_symbol in display_coins and coin_data[coin_symbol]['show'] %}
<div class="w-full sm:w-1/2 lg:w-1/6 p-3" id="{{ coin_symbol.lower() }}-container">
<div class="w-full sm:w-1/2 md:w-1/4 lg:w-1/5 xl:w-1/6 p-3" id="{{ coin_symbol.lower() }}-container">
<div class="px-5 py-3 h-full bg-coolGray-100 dark:bg-gray-500 rounded-2xl dark:text-white {% if coin_symbol == 'BTC' %}active-container{% endif %}" style="min-height: 180px;">
<div class="flex items-center">
<div class="flex items-center h-10">
<img src="/static/images/coins/{{ coin_data[coin_symbol]['image'] }}" class="rounded-xl" style="width: 28px; height: 28px; object-fit: contain;" alt="{{ coin_data[coin_symbol]['name'] }}">
<p class="ml-1 text-black text-sm dark:text-white">
{{ coin_data[coin_symbol]['name'] }} {% if coin_data[coin_symbol]['symbol'] != coin_data[coin_symbol]['name'] %}({{ coin_data[coin_symbol]['symbol'] }}){% endif %}
@@ -213,12 +212,13 @@ function getWebSocketConfig() {
</div>
{% if coin_symbol != 'BTC' %}
<div id="{{ coin_symbol.lower() }}-btc-price-div" class="flex items-center text-xs text-gray-600 dark:text-gray-300 mt-2 {% if coin_symbol == 'WOW' %}hidden{% endif %}">
<span class="bold mr-2">BTC:</span> <span id="{{ coin_symbol.lower() }}-price-btc"></span>
<span class="bold mr-2 ml-1">BTC:</span>
<span id="{{ coin_symbol.lower() }}-price-btc"></span>
</div>
{% endif %}
<div id="{{ coin_symbol.lower() }}-volume-div" class="flex items-center text-xs text-gray-600 dark:text-gray-300 mt-2">
<span class="bold mr-2">VOL:</span>
<div id="{{ coin_symbol.lower() }}-volume-24h"></div>
<span class="bold mr-2 ml-1">VOL:</span>
<span id="{{ coin_symbol.lower() }}-volume-24h"></span>
</div>
</div>
</div>
@@ -233,17 +233,17 @@ function getWebSocketConfig() {
<script src="/static/js/pricechart.js"></script>
<section>
<div class="pl-6 pr-6 pt-0 pb-0 mt-5 h-full overflow-hidden">
<div class="px-6 py-0 mt-5 h-full overflow-hidden">
<div class="border-coolGray-100">
<div class="flex flex-wrap items-center justify-between -m-2">
<div class="flex flex-wrap items-center justify-between">
<div class="w-full mx-auto pt-2">
<form method="post" id="filterForm">
<div class="flex items-center justify-center pb-4 dark:text-white">
<div class="rounded-b-md">
<div class="w-full md:w-0/12">
<div class="container flex flex-wrap">
<div class="md:w-auto hover-container justify-center">
<div class="flex flex-wrap justify-center">
<div class="lg:container flex flex-wrap justify-center">
<div class="md:w-auto hover-container">
<div class="flex flex-wrap">
<div class="pt-3 px-3 md:w-auto hover-container">
<div class="flex">
<button id="coin_to_button" class="bg-gray-50 text-gray-900 appearance-none w-10 dark:bg-gray-500 dark:text-white border-l border-t border-b border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-50 text-sm rounded-l-lg flex items-center" disabled></button>
@@ -302,14 +302,14 @@ function getWebSocketConfig() {
</div>
</div>
</div>
<div class="w-full md:w-auto pt-3 px-3">
<div class="w-full lg:w-auto pt-3 px-3">
<div class="relative">
<button type="button" id="clearFilters" class="transition-opacity duration-200 flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm hover:text-white dark:text-white dark:bg-gray-500 bg-coolGray-200 hover:bg-green-600 hover:border-green-600 rounded-lg transition duration-200 border border-coolGray-200 dark:border-gray-400 rounded-md shadow-button focus:ring-0 focus:outline-none" disabled>
<span>Clear Filters</span>
</button>
</div>
</div>
<div class="w-full md:w-auto pt-3 px-3">
<div class="w-full lg:w-auto pt-3 px-3">
<div class="relative">
<button type="button" id="refreshOffers" class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-white bg-blue-600 hover:bg-green-600 hover:border-green-600 rounded-lg transition duration-200 border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none">
<svg id="refreshIcon" class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
@@ -334,10 +334,10 @@ function getWebSocketConfig() {
<div id="jsonView" class="hidden mb-4">
<pre id="jsonContent" class="bg-gray-100 p-4 rounded overflow-auto" style="max-height: 300px;"></pre>
</div>
<div class="container mt-5 mx-auto px-4">
<div class="mt-5 lg:container mx-auto lg:px-0 px-6">
<div class="pt-0 pb-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="px-0">
<div class="w-auto mt-6 overflow-x-auto">
<div class="w-auto mt-6 overflow-auto lg:overflow-hidden">
<table class="w-full min-w-max">
<thead class="uppercase">
<tr>

View File

@@ -1,36 +1,37 @@
{% include 'header.html' %}
{% from 'style.html' import select_box_arrow_svg, select_box_class, circular_arrows_svg, circular_error_svg, circular_info_svg, cross_close_svg, breadcrumb_line_svg, withdraw_svg, utxo_groups_svg, create_utxo_svg, red_cross_close_svg, blue_cross_close_svg, circular_update_messages_svg, circular_error_messages_svg %}
<script src="/static/js/libs//qrcode.js"></script>
<div class="container mx-auto">
<section class="p-5 mt-5">
<div class="container mx-auto">
<div class="flex flex-wrap items-center -m-2">
<div class="w-full md:w-1/2 p-2">
<ul class="flex flex-wrap items-center gap-x-3 mb-2">
<li><a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/">Home</a></li>
<li><a class="flex font-medium text-md lg:text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/">Home</a></li>
<li>{{ breadcrumb_line_svg | safe }}</li>
<li><a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/wallets">Wallets</a></li>
<li><a class="flex font-medium text-md lg:text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/wallets">Wallets</a></li>
<li>{{ breadcrumb_line_svg | safe }}</li>
<li><a class="flex font-medium text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/wallet/{{ w.ticker }}">{{ w.ticker }}</a></li>
<li><a class="flex font-medium text-md lg:text-xs text-coolGray-500 dark:text-gray-300 hover:text-coolGray-700" href="/wallet/{{ w.ticker }}">{{ w.ticker }}</a></li>
</ul>
</div>
</div>
</div>
</section>
<section class="py-4">
<div class="container px-4 mx-auto">
<section class="py-4 px-6">
<div class="lg:container mx-auto">
<div class="relative py-11 px-16 bg-coolGray-900 dark:bg-blue-500 rounded-md overflow-hidden"> <img class="absolute z-10 left-4 top-4 right-4 bottom-4" src="/static/images/elements/dots-red.svg" alt="dots-red"> <img class="absolute h-64 left-1/2 top-1/2 transform -translate-x-1/2 -translate-y-1/2 object-cover" src="/static/images/elements/wave.svg" alt="wave">
<div class="relative z-20 flex flex-wrap items-center -m-3">
<div class="w-full md:w-1/2">
<h2 class="text-3xl font-bold text-white"> <span class="inline-block align-middle"><img class="mr-2 h-16" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }}"></span>({{ w.ticker }}) {{ w.name }} Wallet </h2>
</div>
<div class="w-full md:w-1/2 p-3 p-6 container flex flex-wrap items-center justify-end items-center mx-auto"> <a class="rounded-full mr-5 flex flex-wrap justify-center px-5 py-3 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border dark:bg-gray-500 dark:hover:bg-gray-700 border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" id="refresh" href="/wallet/{{ w.ticker }}"> {{ circular_arrows_svg | safe }}<span>Refresh</span> </a> </div>
<div class="w-full md:w-1/2 p-3 p-6 container flex flex-wrap items-center justify-end items-center mx-auto"> <a class="rounded-full mr-5 flex flex-wrap justify-center px-5 py-3 bg-blue-500 hover:bg-blue-600 font-medium text-lg lg:text-sm text-white border dark:bg-gray-500 dark:hover:bg-gray-700 border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" id="refresh" href="/wallet/{{ w.ticker }}"> {{ circular_arrows_svg | safe }}<span>Refresh</span> </a> </div>
</div>
</div>
</div>
</section>
{% include 'inc_messages.html' %}
{% if w.updating %}
<section class="py-4" id="messages_updating" role="alert">
<div class="container px-4 mx-auto">
<section class="py-4 px-6" id="messages_updating" role="alert">
<div class="lg:container mx-auto">
<div class="p-6 text-green-800 rounded-lg bg-blue-50 border border-blue-500 dark:bg-gray-500 dark:text-blue-400 rounded-md">
<div class="flex flex-wrap justify-between items-center -m-2">
<div class="flex-1 p-2">
@@ -39,8 +40,8 @@
{{ circular_update_messages_svg | safe }}
</div>
<ul class="ml-4 mt-1">
<li class="font-semibold text-sm text-blue-500 error_msg"><span class="bold">UPDATING:</span></li>
<li class="font-medium text-sm text-blue-500">Please wait...</li>
<li class="font-semibold text-lg lg:text-sm text-blue-500 error_msg"><span class="bold">UPDATING:</span></li>
<li class="font-medium text-lg lg:text-sm text-blue-500">Please wait...</li>
</ul>
</div>
</div>
@@ -56,8 +57,8 @@
{% endif %}
{% if w.havedata %}
{% if w.error %}
<section class="py-4" id="messages_error" role="alert">
<div class="container px-4 mx-auto">
<section class="py-4 px-6" id="messages_error" role="alert">
<div class="lg:container mx-auto">
<div class="p-6 text-green-800 rounded-lg bg-red-50 border border-red-400 dark:bg-gray-500 dark:text-red-400 rounded-md">
<div class="flex flex-wrap justify-between items-center -m-2">
<div class="flex-1 p-2">
@@ -66,8 +67,8 @@
{{ circular_error_messages_svg | safe }}
</div>
<ul class="ml-4 mt-1">
<li class="font-semibold text-sm text-red-500 error_msg"><span class="bold">ERROR:</span></li>
<li class="font-medium text-sm text-red-500 error_msg">{{ w.error }}</li>
<li class="font-semibold text-lg lg:text-sm text-red-500 error_msg"><span class="bold">ERROR:</span></li>
<li class="font-medium text-lg lg:text-sm text-red-500 error_msg">{{ w.error }}</li>
</ul>
</div>
</div>
@@ -83,8 +84,8 @@
</section>
{% else %}
{% if w.cid == '18' %} {# DOGE #}
<section class="py-4" id="messages_notice">
<div class="container px-4 mx-auto">
<section class="py-4 px-6" id="messages_notice">
<div class="lg:container mx-auto">
<div class="p-6 rounded-lg bg-coolGray-100 dark:bg-gray-500 shadow-sm">
<div class="flex items-start">
<svg class="w-6 h-6 text-blue-500 mt-1 mr-3 flex-shrink-0" fill="none" stroke="currentColor" stroke-width="1.5" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z"></path></svg>
@@ -101,24 +102,24 @@
</div>
</section>
{% endif %}
<form method="post" autocomplete="off">
<section>
<div class="pl-6 pr-6 pt-0 pb-0 mt-5 h-full overflow-hidden">
<section>
<form method="post" autocomplete="off">
<div class="px-6 py-0 mt-5 h-full overflow-hidden">
<div class="pb-6 border-coolGray-100">
<div class="flex flex-wrap items-center justify-between -m-2">
<div class="w-full pt-2">
<div class="container mt-5 mx-auto">
<div class="lg:container mt-5 mx-auto">
<div class="pt-6 pb-8 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="px-6">
<div class="w-full mt-6 pb-6 overflow-x-auto">
<table class="w-full min-w-max text-sm">
<div class="w-full pb-6 overflow-x-auto">
<table class="w-full text-lg lg:text-sm">
<thead class="uppercase">
<tr class="text-left">
<th class="p-0">
<div class="py-3 px-6 rounded-tl-xl bg-coolGray-200 dark:bg-gray-600"> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Wallet</span> </div>
<div class="py-3 px-6 rounded-tl-xl bg-coolGray-200 dark:bg-gray-600"> <span class="text-md lg:text-xs text-gray-600 dark:text-gray-300 font-semibold">Wallet</span> </div>
</th>
<th class="p-0">
<div class="py-3 px-6 rounded-tr-xl bg-coolGray-200 dark:bg-gray-600"> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Details</span> </div>
<div class="py-3 px-6 rounded-tr-xl bg-coolGray-200 dark:bg-gray-600"> <span class="text-md lg:text-xs text-gray-600 dark:text-gray-300 font-semibold">Details</span> </div>
</th>
</tr>
</thead>
@@ -129,7 +130,8 @@
<span class="inline-block py-1 px-2 rounded-full bg-green-100 text-green-500 dark:bg-gray-500 dark:text-green-500">Pending: +{{ w.pending }} {{ w.ticker }} </span>
{% endif %}
</td>
</tr> {% if w.cid == '1' %} {# PART #}
</tr>
{% if w.cid == '1' %} {# PART #}
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
<td class="py-3 px-6 bold"> <span class="inline-flex align-middle items-center justify-center w-9 h-10 bg-white-50 rounded"> <img class="h-7" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }} Blind"> </span>Blind Balance: </td>
<td class="py-3 px-6 bold coinname-value" data-coinname="{{ w.name }}">{{ w.blind_balance }} {{ w.ticker }} (<span class="usd-value"></span>)
@@ -147,11 +149,10 @@
</td>
<td class="usd-value"></td>
</tr>
{% endif %}
{# / PART #}
{% if w.cid == '3' %} {# LTC #}
{% elif w.cid == '3' %} {# LTC #}
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
<td class="py-3 px-6 bold"> <span class="pr-3 inline-flex align-middle items-center justify-center w-9 h-10 bg-white-50 rounded"> <img class="h-7" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }} MWEB"> </span>MWEB Balance: </td>
<td class="py-3 px-6 bold"> <span class="inline-flex align-middle items-center justify-center w-9 h-10 bg-white-50 rounded"> <img class="h-7" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }} MWEB"> </span>MWEB Balance: </td>
<td class="py-3 px-6 bold coinname-value" data-coinname="{{ w.name }}">{{ w.mweb_balance }} {{ w.ticker }} (<span class="usd-value"></span>)
{% if w.mweb_pending %}
<span class="inline-block py-1 px-2 rounded-full bg-green-100 text-green-500 dark:bg-gray-500 dark:text-green-500">Pending: +{{ w.mweb_pending }} {{ w.ticker }} </span>
@@ -163,7 +164,7 @@
{% if w.locked_utxos %}
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
<td class="py-3 px-6 bold">Locked Outputs:</td>
<td id='locked_utxos' class="py-3 px-6">{{ w.locked_utxos }}</td>
<td id="locked_utxos" class="py-3 px-6">{{ w.locked_utxos }}</td>
</tr>
{% endif %}
{# / locked_utxos #}
@@ -176,7 +177,7 @@
<td class="py-3 px-6">{{ w.version }}</td>
</tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
<td class="py-3 px-6 bold">Blocks:</td>
<td class="py-3 px-6 bold">Blockheight:</td>
<td class="py-3 px-6">{{ w.blocks }}
{% if w.known_block_count %} / {{ w.known_block_count }}
{% endif %}
@@ -206,10 +207,12 @@
</tr>
{% endif %}
{# / encrypted #}
{% if w.expected_seed != true %}
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
<td class="py-3 px-6 bold">Expected Seed:</td>
<td class="py-3 px-6">{{ w.expected_seed }}</td>
</tr>
{% endif %}
</table>
</div>
</div>
@@ -219,18 +222,19 @@
</div>
</div>
</div>
</section>
</form>
</section>
{% if block_unknown_seeds and w.expected_seed != true %} {# Only show addresses if wallet seed is correct #}
<section class="pl-6 pr-6 pt-0 pb-0 h-full overflow-hidden">
<section class="px-6 py-0 h-full overflow-hidden">
<div class="pb-6 border-coolGray-100">
<div class="flex flex-wrap items-center justify-between -m-2">
<div class="w-full pt-2">
<div class="container mt-5 mx-auto">
<div class="pt-6 pb-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="lg:container mt-5 mx-auto">
<div class="py-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="px-6">
{% if w.cid != '4' %} {# DCR #}
<div class="flex flex-wrap justify-end">
<div class="w-full md:w-auto p-1.5"> <input class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-sm text-white hover:text-red border border-red-500 hover:border-red-500 hover:bg-red-600 bg-red-500 rounded-md shadow-button focus:ring-0 focus:outline-none cursor-pointer" type="submit" name="reseed_{{ w.cid }}" value="Reseed wallet" onclick="return confirmReseed();"> </div>
<div class="w-full md:w-auto p-1.5"> <input class="flex flex-wrap justify-center w-full px-4 py-2.5 font-medium text-lg lg:text-sm text-white hover:text-red border border-red-500 hover:border-red-500 hover:bg-red-600 bg-red-500 rounded-md shadow-button focus:ring-0 focus:outline-none cursor-pointer" type="submit" name="reseed_{{ w.cid }}" value="Reseed wallet" onclick="return confirmReseed();"> </div>
</div>
{% endif %}
</div>
@@ -242,90 +246,53 @@
</section>
{% else %}
<section class="p-6">
<div class="lg:container mx-auto">
<div class="flex items-center">
<h4 class="font-semibold text-2xl text-black dark:text-white">Deposit</h4>
</div>
</div>
</section>
<form method="post" autocomplete="off">
<section>
<div class="pl-6 pr-6 pt-0 pb-0 overflow-hidden">
<div class="px-6 py-0 overflow-hidden">
<div class="pb-6 border-coolGray-100">
<div class="flex flex-wrap items-center justify-between -m-2">
<div class="w-full pt-2">
<div class="container mt-5 mx-auto">
<div class="lg:container mt-5 mx-auto">
<div class="pb-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="px-6">
<div class="container mx-auto">
<div class="flex flex-wrap max-w-7xl mx-auto justify-center -m-3">
{% if w.cid in '6, 9' %}
{# XMR | WOW #}
<div class="w-full md:w-1/2 p-3 flex justify-center items-center">
<div class="h-full">
<div class="flex flex-wrap -m-3">
<div class="w-full p-3">
<div class="mb-2 qrcode-container flex h-60 justify-center items-center">
<div class="qrcode-border flex">
<div class="flex flex-wrap max-w-7xl mx-auto justify-center -m-3">
<div class="w-full md:w-1/2 p-3 flex justify-center items-center">
<div class="h-full">
<div class="flex flex-wrap -m-3">
<div class="w-full p-3">
<div class="mb-2 qrcode-container flex h-60 justify-center items-center">
<div class="qrcode-border flex">
{% if w.cid in '6, 9' %}
{# XMR | WOW #}
<div id="qrcode-monero-main" class="qrcode"></div>
</div>
</div>
<div class="font-normal bold text-gray-500 text-center dark:text-white mb-5">{{ w.name }} Main Address: </div>
<div class="font-normal bold text-gray-500 text-center dark:text-white mb-5">Main Address: </div>
<div class="relative flex justify-center items-center">
<div data-tooltip-target="tooltip-copy-monero-main" class="input-like-container hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full focus:ring-0" id="monero_main_address">{{ w.main_address }}</div>
<div data-tooltip-target="tooltip-copy-monero-main" class="input-like-container hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-lg lg:text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full focus:ring-0" id="monero_main_address">{{ w.main_address }}</div>
</div>
<div id="tooltip-copy-monero-main" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
<p>Copy to clipboard</p>
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
</div>
</div>
</div>
</div>
<div class="w-full md:w-1/2 p-3 flex justify-center items-center">
<div class="h-full">
<div class="flex flex-wrap -m-3">
<div class="w-full p-3">
<div class="mb-2 qrcode-container flex h-60 justify-center items-center">
<div class="qrcode-border flex">
<div id="qrcode-monero-sub" class="qrcode"> </div>
</div>
</div>
<div class="font-normal bold text-gray-500 text-center dark:text-white mb-5">{{ w.name }} Sub Address: </div>
<div class="relative flex justify-center items-center">
<div data-tooltip-target="tooltip-copy-monero-sub" class="input-like-container hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full focus:ring-0" id="monero_sub_address">{{ w.deposit_address }}</div>
</div>
<div class="opacity-100 text-gray-500 dark:text-gray-100 flex justify-center items-center">
<div class="py-3 px-6 bold mt-5">
<button type="submit" class="flex justify-center py-2 px-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" name="newaddr_{{ w.cid }}" value="New Subaddress"> {{ circular_arrows_svg }} New {{ w.name }} Deposit Address</button>
</div>
</div>
<div id="tooltip-copy-monero-sub" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
<p>Copy to clipboard</p>
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
</div>
</div>
</div>
</div>
{% else %}
<div class="w-full md:w-1/2 p-3 flex justify-center items-center">
<div class="h-full">
<div class="flex flex-wrap -m-3">
<div class="w-full p-3">
<div class="mb-2 qrcode-container flex h-60 justify-center items-center">
<div class="qrcode-border flex">
<div id="tooltip-copy-monero-main" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-lg lg:text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
{% else %}
<div id="qrcode-deposit" class="qrcode"> </div>
</div>
</div>
<div class="font-normal bold text-gray-500 text-center dark:text-white mb-5">{{ w.name }} Deposit Address: </div>
<div class="font-normal bold text-gray-500 text-center dark:text-white mb-5">Deposit Address: </div>
<div class="relative flex justify-center items-center">
<div data-tooltip-target="tooltip-copy-default" class="input-like-container hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full focus:ring-0" id="main_deposit_address">{{ w.deposit_address }}</div>
<div data-tooltip-target="tooltip-copy-default" class="input-like-container hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-lg lg:text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full focus:ring-0" id="main_deposit_address">{{ w.deposit_address }}</div>
</div>
<div class="opacity-100 text-gray-500 dark:text-gray-100 flex justify-center items-center">
<div class="py-3 px-6 bold mt-5">
<button type="submit" class="flex justify-center py-2 px-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" name="newaddr_{{ w.cid }}" value="New Deposit Address"> {{ circular_arrows_svg }} New {{ w.name }} Deposit Address </button>
</div>
</div>
<div id="tooltip-copy-default" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
<div id="tooltip-copy-default" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-lg lg:text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
{% endif %}
<p>Copy to clipboard</p>
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
@@ -333,62 +300,67 @@
</div>
</div>
</div>
{% endif %}
{% if w.cid == '1' %} {# PART #}
{% if w.cid in '1, 3, 6, 9' %}
{# PART | LTC | XMR | WOW | #}
<div class="w-full md:w-1/2 p-3 flex justify-center items-center">
<div class="h-full">
<div class="flex flex-wrap -m-3">
<div class="w-full p-3">
<div class="mb-2 qrcode-container flex h-60 justify-center items-center">
<div class="qrcode-border flex">
{% if w.cid in '6, 9' %}
{# XMR | WOW #}
<div id="qrcode-monero-sub" class="qrcode"> </div>
</div>
</div>
<div class="font-normal bold text-gray-500 text-center dark:text-white mb-5">Subaddress: </div>
<div class="relative flex justify-center items-center">
<div data-tooltip-target="tooltip-copy-monero-sub" class="input-like-container hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-lg lg:text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full focus:ring-0" id="monero_sub_address">{{ w.deposit_address }}</div>
</div>
<div class="opacity-100 text-gray-500 dark:text-gray-100 flex justify-center items-center">
<div class="py-3 px-6 bold mt-5">
<button type="submit" class="flex justify-center py-2 px-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" name="newaddr_{{ w.cid }}" value="New Subaddress"> {{ circular_arrows_svg }} New {{ w.name }} Deposit Address</button>
</div>
</div>
<div id="tooltip-copy-monero-sub" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-lg lg:text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
{% elif w.cid == '1' %}
{# PART #}
<div id="qrcode-stealth" class="qrcode"> </div>
</div>
</div>
<div class="font-normal bold text-gray-500 text-center dark:text-white mb-5">{{ w.name }} Stealth Address: </div>
<div class="font-normal bold text-gray-500 text-center dark:text-white mb-5">Stealth Address: </div>
<div class="relative flex justify-center items-center">
<div data-tooltip-target="tooltip-copy-particl-stealth" class="input-like-container hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-10 focus:ring-0" id="stealth_address"> {{ w.stealth_address }}
<div data-tooltip-target="tooltip-copy-particl-stealth" class="input-like-container hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-lg lg:text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-10 focus:ring-0" id="stealth_address"> {{ w.stealth_address }}
</div>
</div>
<div id="tooltip-copy-particl-stealth" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
<p>Copy to clipboard</p>
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
</div>
</div>
</div>
</div>
{# / PART #}
{% elif w.cid == '3' %}
{# LTC #}
<div class="w-full md:w-1/2 p-3 flex justify-center items-center">
<div class="h-full">
<div class="flex flex-wrap -m-3">
<div class="w-full p-3">
<div class="mb-2 qrcode-container flex h-60 justify-center items-center">
<div class="qrcode-border flex">
<div id="tooltip-copy-particl-stealth" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-lg lg:text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
{# / PART #}
{% elif w.cid == '3' %}
{# LTC #}
<div id="qrcode-mweb" class="qrcode"> </div>
</div>
</div>
<div class="font-normal bold text-gray-500 text-center dark:text-white mb-5">{{ w.name }} MWEB Address: </div>
<div class="font-normal bold text-gray-500 text-center dark:text-white mb-5">MWEB Address: </div>
<div class="text-center relative">
<div data-tooltip-target="tooltip-copy-litecoin-mweb" class="input-like-container hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" id="stealth_address">{{ w.mweb_address }}</div>
<div data-tooltip-target="tooltip-copy-litecoin-mweb" class="input-like-container hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-lg lg:text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" id="stealth_address">{{ w.mweb_address }}</div>
<span class="absolute inset-y-0 right-0 flex items-center pr-3 cursor-pointer" id="copyIcon"></span>
</div>
<div class="opacity-100 text-gray-500 dark:text-gray-100 flex justify-center items-center">
<div class="py-3 px-6 bold mt-5">
<button type="submit" class="flex justify-center py-2 px-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" name="newmwebaddr_{{ w.cid }}" value="New MWEB Address"> {{ circular_arrows_svg }} New MWEB Address </button>
</div>
<div id="tooltip-copy-litecoin-mweb" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
</div>
<div id="tooltip-copy-litecoin-mweb" role="tooltip" class="inline-block absolute invisible z-10 py-2 px-3 text-lg lg:text-sm font-medium text-white bg-blue-500 rounded-lg shadow-sm opacity-0 transition-opacity duration-300 tooltip">
{# / LTC #}
{% endif %}
<p>Copy to clipboard</p>
<div class="tooltip-arrow" data-popper-arrow></div>
</div>
</div>
</div>
</div>
</div>
{% endif %}
{# / LTC #}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endif %}
</div>
</div>
</div>
@@ -410,8 +382,7 @@
correctLevel: QRCode.CorrectLevel.L
});
</script>
{% endif %}
{% if w.cid == '3' %}
{% elif w.cid == '3' %}
{# LTC #}
<script>
// Litecoin MWEB
@@ -529,61 +500,67 @@ document.addEventListener('DOMContentLoaded', function() {
});
</script>
<section class="p-6">
<div class="lg:container mx-auto">
<div class="flex items-center">
<h4 class="font-semibold text-2xl text-black dark:text-white">Withdraw</h4>
</div>
</section>
</div>
</section>
<section>
<div class="pl-6 pr-6 pt-0 pb-0 h-full overflow-hidden">
<div class="px-6 py-0 h-full overflow-hidden">
<div class="border-coolGray-100">
<div class="flex flex-wrap items-center justify-between -m-2">
<div class="w-full pt-2">
<div class="container mt-5 mx-auto">
<div class="pt-6 pb-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="lg:container mt-5 mx-auto">
<div class="py-6 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="px-6">
<div class="w-full mt-6 pb-6 overflow-x-auto">
<table class="w-full min-w-max text-sm">
<div class="w-full pb-6 overflow-x-auto">
<table class="w-full text-lg lg:text-sm">
<thead class="uppercase">
<tr class="text-left">
<th class="p-0">
<div class="py-3 px-6 rounded-tl-xl bg-coolGray-200 dark:bg-gray-600"> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Options</span> </div>
<div class="py-3 px-6 rounded-tl-xl bg-coolGray-200 dark:bg-gray-600"> <span class="text-md lg:text-xs text-gray-600 dark:text-gray-300 font-semibold">Options</span> </div>
</th>
<th class="p-0">
<div class="py-3 px-6 rounded-tr-xl bg-coolGray-200 dark:bg-gray-600"> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Input</span> </div>
<div class="py-3 px-6 rounded-tr-xl bg-coolGray-200 dark:bg-gray-600"> <span class="text-md lg:text-xs text-gray-600 dark:text-gray-300 font-semibold">Input</span> </div>
</th>
</tr>
</thead>
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-4 pl-6 bold"> <span class="inline-flex align-middle items-center justify-center w-9 h-10 bg-white-50 rounded"> <img class="h-7" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }}"> </span> {{ w.name }} Balance: </td>
<td class="py-4 pl-6 bold"> <span class="inline-flex align-middle items-center justify-center w-9 h-10 bg-white-50 rounded"> <img class="h-7" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }}"> </span>Balance: </td>
<td class="py-3 px-6" data-coinname="{{ w.name }}">{{ w.balance }} {{ w.ticker }} </td>
</tr>
{% if w.cid == '3' %}
{# LTC #}
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-4 pl-6 bold w-1/4"> <span class="inline-flex align-middle items-center justify-center w-9 h-10 bg-white-50 rounded"> <img class="h-7" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }}"> </span> {{ w.name }} MWEB Balance: </td>
<td class="py-4 pl-6 bold w-1/4"> <span class="inline-flex align-middle items-center justify-center w-9 h-10 bg-white-50 rounded"> <img class="h-7" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }}"> </span>MWEB Balance: </td>
<td class="py-3 px-6" data-coinname="{{ w.name }}">{{ w.mweb_balance }} {{ w.ticker }} </td>
{% endif %}
{% if w.cid == '1' %}
</tr>
{% elif w.cid == '1' %}
{# PART #}
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-4 pl-6 bold"> <span class="inline-flex align-middle items-center justify-center w-9 h-10 bg-white-50 rounded"> <img class="h-7" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }}"> </span> {{ w.name }} Blind Balance: </td>
<td class="py-4 pl-6 bold"> <span class="inline-flex align-middle items-center justify-center w-9 h-10 bg-white-50 rounded"> <img class="h-7" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }}"> </span>Blind Balance: </td>
<td class="py-3 px-6" data-coinname="{{ w.name }}">{{ w.blind_balance }} {{ w.ticker }} </td>
</tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-4 pl-6 bold"> <span class="inline-flex align-middle items-center justify-center w-9 h-10 bg-white-50 rounded"> <img class="h-7" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }}"> </span> {{ w.name }} Anon Balance: </td>
<td class="py-3 px-6" data-coinname="{{ w.name }}">{{ w.anon_balance }} {{ w.ticker }} </td> {% endif %}
<td class="py-4 pl-6 bold"> <span class="inline-flex align-middle items-center justify-center w-9 h-10 bg-white-50 rounded"> <img class="h-7" src="/static/images/coins/{{ w.name }}.png" alt="{{ w.name }}"> </span>Anon Balance: </td>
<td class="py-3 px-6" data-coinname="{{ w.name }}">{{ w.anon_balance }} {{ w.ticker }} </td>
</tr>
{% endif %}
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-4 pl-6 bold"> {{ w.name }} Address: </td>
<td class="py-3 px-6"> <input placeholder="{{ w.ticker }} Address" class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="text" name="to_{{ w.cid }}" value="{{ w.wd_address }}"> </td>
<td class="py-3 px-6"> <input placeholder="{{ w.ticker }} Address" class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-lg lg:text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="text" name="to_{{ w.cid }}" value="{{ w.wd_address }}"> </td>
</tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-4 pl-6 bold"> {{ w.name }} Amount:
<td class="py-3 px-6">
<div class="flex"> <input placeholder="{{ w.ticker }} Amount" class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="text" id="amount" name="amt_{{ w.cid }}" value="{{ w.wd_value }}">
<div class="flex"> <input placeholder="{{ w.ticker }} Amount" class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-lg lg:text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="text" id="amount" name="amt_{{ w.cid }}" value="{{ w.wd_value }}">
<div class="ml-2 flex">
{% if w.cid == '1' %}
{# PART #}
<button type="button" class="py-1 px-2 bg-blue-500 text-white text-sm rounded-md focus:outline-none" onclick="setAmount(0.25, '{{ w.balance }}', {{ w.cid }}, '{{ w.blind_balance }}', '{{ w.anon_balance }}')">25%</button>
<button type="button" class="ml-2 py-1 px-2 bg-blue-500 text-white text-sm rounded-md focus:outline-none" onclick="setAmount(0.5, '{{ w.balance }}', {{ w.cid }}, '{{ w.blind_balance }}', '{{ w.anon_balance }}')">50%</button>
<button type="button" class="ml-2 py-1 px-2 bg-blue-500 text-white text-sm rounded-md focus:outline-none" onclick="setAmount(1, '{{ w.balance }}', {{ w.cid }}, '{{ w.blind_balance }}', '{{ w.anon_balance }}')">100%</button>
<button type="button" class="hidden md:block py-1 px-2 bg-blue-500 text-white text-lg lg:text-sm rounded-md focus:outline-none" onclick="setAmount(0.25, '{{ w.balance }}', {{ w.cid }}, '{{ w.blind_balance }}', '{{ w.anon_balance }}')">25%</button>
<button type="button" class="hidden md:block ml-2 py-1 px-2 bg-blue-500 text-white text-lg lg:text-sm rounded-md focus:outline-none" onclick="setAmount(0.5, '{{ w.balance }}', {{ w.cid }}, '{{ w.blind_balance }}', '{{ w.anon_balance }}')">50%</button>
<button type="button" class="ml-2 py-1 px-2 bg-blue-500 text-white text-lg lg:text-sm rounded-md focus:outline-none" onclick="setAmount(1, '{{ w.balance }}', {{ w.cid }}, '{{ w.blind_balance }}', '{{ w.anon_balance }}')">100%</button>
<script>
function setAmount(percent, balance, cid, blindBalance, anonBalance) {
var amountInput = document.getElementById('amount');
@@ -618,9 +595,9 @@ document.addEventListener('DOMContentLoaded', function() {
{# / PART #}
{% elif w.cid == '3' %}
{# LTC #}
<button type="button" class="py-1 px-2 bg-blue-500 text-white text-sm rounded-md focus:outline-none" onclick="setAmount(0.25, '{{ w.balance }}', {{ w.cid }}, '{{ w.mweb_balance }}')">25%</button>
<button type="button" class="ml-2 py-1 px-2 bg-blue-500 text-white text-sm rounded-md focus:outline-none" onclick="setAmount(0.5, '{{ w.balance }}', {{ w.cid }}, '{{ w.mweb_balance }}')">50%</button>
<button type="button" class="ml-2 py-1 px-2 bg-blue-500 text-white text-sm rounded-md focus:outline-none" onclick="setAmount(1, '{{ w.balance }}', {{ w.cid }}, '{{ w.mweb_balance }}')">100%</button>
<button type="button" class="hidden md:block py-1 px-2 bg-blue-500 text-white text-lg lg:text-sm rounded-md focus:outline-none" onclick="setAmount(0.25, '{{ w.balance }}', {{ w.cid }}, '{{ w.mweb_balance }}')">25%</button>
<button type="button" class="hidden md:block ml-2 py-1 px-2 bg-blue-500 text-white text-lg lg:text-sm rounded-md focus:outline-none" onclick="setAmount(0.5, '{{ w.balance }}', {{ w.cid }}, '{{ w.mweb_balance }}')">50%</button>
<button type="button" class="ml-2 py-1 px-2 bg-blue-500 text-white text-lg lg:text-sm rounded-md focus:outline-none" onclick="setAmount(1, '{{ w.balance }}', {{ w.cid }}, '{{ w.mweb_balance }}')">100%</button>
<script>
function setAmount(percent, balance, cid, mwebBalance) {
var amountInput = document.getElementById('amount');
@@ -651,9 +628,9 @@ document.addEventListener('DOMContentLoaded', function() {
</script>
{# / LTC #}
{% else %}
<button type="button" class="py-1 px-2 bg-blue-500 text-white text-sm rounded-md focus:outline-none" onclick="setAmount(0.25, '{{ w.balance }}', {{ w.cid }})">25%</button>
<button type="button" class="ml-2 py-1 px-2 bg-blue-500 text-white text-sm rounded-md focus:outline-none" onclick="setAmount(0.5, '{{ w.balance }}', {{ w.cid }})">50%</button>
<button type="button" class="ml-2 py-1 px-2 bg-blue-500 text-white text-sm rounded-md focus:outline-none" onclick="setAmount(1, '{{ w.balance }}', {{ w.cid }})">100%</button>
<button type="button" class="hidden md:block py-1 px-2 bg-blue-500 text-white text-lg lg:text-sm rounded-md focus:outline-none" onclick="setAmount(0.25, '{{ w.balance }}', {{ w.cid }})">25%</button>
<button type="button" class="hidden md:block ml-2 py-1 px-2 bg-blue-500 text-white text-lg lg:text-sm rounded-md focus:outline-none" onclick="setAmount(0.5, '{{ w.balance }}', {{ w.cid }})">50%</button>
<button type="button" class="ml-2 py-1 px-2 bg-blue-500 text-white text-lg lg:text-sm rounded-md focus:outline-none" onclick="setAmount(1, '{{ w.balance }}', {{ w.cid }})">100%</button>
<script>
function setAmount(percent, balance, cid) {
var amountInput = document.getElementById('amount');
@@ -700,19 +677,21 @@ document.addEventListener('DOMContentLoaded', function() {
</script>
{% endif %}
</div>
</div>
</div>
</td>
</td>
</tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
{% if w.cid in '6, 9' %} {# XMR | WOW #}
<td class="py-3 px-6 bold">Sweep All:</td>
<td class="py-3 px-6">
<input class="hover:border-blue-500 w-5 h-5 form-check-input text-blue-600 bg-gray-50 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-1 dark:bg-gray-500 dark:border-gray-400" type="checkbox" id="sweepall" name="sweepall_{{ w.cid }}" {% if w.wd_sweepall==true %} checked=checked{% endif %}>
<td class="hidden py-3 px-6 bold">Sweep All:</td>
<td class="hidden py-3 px-6">
<input class="hover:border-blue-500 w-5 h-5 form-check-input text-blue-600 bg-gray-50 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-1 dark:bg-gray-500 dark:border-gray-400" type="checkbox" id="sweepall" name="sweepall_{{ w.cid }}" {% if w.wd_sweepall==true %} checked="checked"{% endif %}>
</td>
{% else %}
<td class="py-3 px-6 bold">Subtract Fee:</td>
<td class="py-3 px-6">
<input class="hover:border-blue-500 w-5 h-5 form-check-input text-blue-600 bg-gray-50 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-1 dark:bg-gray-500 dark:border-gray-400" type="checkbox" name="subfee_{{ w.cid }}" {% if w.wd_subfee==true %} checked=checked{% endif %}>
<input class="hover:border-blue-500 w-5 h-5 form-check-input text-blue-600 bg-gray-50 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-1 dark:bg-gray-500 dark:border-gray-400" type="checkbox" name="subfee_{{ w.cid }}" {% if w.wd_subfee==true %} checked="checked"{% endif %}>
</td>
{% endif %}
<td>
@@ -746,9 +725,8 @@ document.addEventListener('DOMContentLoaded', function() {
</div>
</td>
</tr>
{% endif %}
{# / PART #}
{% if w.cid == '3' %} {# LTC #}
{% elif w.cid == '3' %} {# LTC #}
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 bold">Type From:</td>
<td class="py-3 px-6">
@@ -762,14 +740,16 @@ document.addEventListener('DOMContentLoaded', function() {
</tr>
{% endif %}
{# / LTC #}
{% if w.cid not in '6,9' %} {# Not XMR WOW #}
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 bold">Fee Rate:</td>
<td class="py-3 px-6">{{ w.fee_rate }}</td>
</tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 bold">Estimate Fee:</td>
<td class="py-3 px-6 bold">Fee Estimate:</td>
<td class="py-3 px-6"> {{ w.est_fee }} </td>
</tr>
{% endif %}
</table>
</div>
</div>
@@ -781,25 +761,23 @@ document.addEventListener('DOMContentLoaded', function() {
</div>
</section>
<section>
<div class="pl-6 pr-6 pt-0 pb-0 h-full overflow-hidden ">
<div class="px-6 py-0 h-full overflow-hidden">
<div class="pb-6 ">
<div class="flex flex-wrap items-center justify-between -m-2">
<div class="w-full pt-2">
<div class="container mx-auto">
<div class="pt-6 pb-6 bg-coolGray-100 border-t border-gray-100 dark:border-gray-400 dark:bg-gray-500 rounded-bl-xl rounded-br-xl">
<div class="lg:container mx-auto">
<div class="py-6 bg-coolGray-100 border-t border-gray-100 dark:border-gray-400 dark:bg-gray-500 rounded-bl-xl rounded-br-xl">
<div class="px-6">
<div class="flex flex-wrap justify-end">
{% if w.cid not in '6, 9' %}
{# !XMR | WOW #}
{% if w.show_utxo_groups %}
{% else %}
<div class="w-full md:w-auto p-1.5"> <button type="submit" class="flex flex-wrap justify-center px-4 py-2.5 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" id="showutxogroups" name="showutxogroups" value="Show UTXO Groups"> {{ utxo_groups_svg | safe }} Show UTXO Groups </button> </div>
{% endif %} {% endif %}
{% if w.cid in '6, 9' %}
{# XMR | WOW #}
<div class="w-full md:w-auto p-1.5 ml-2"> <button type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" name="estfee_{{ w.cid }}" value="Estimate Fee">Estimate {{ w.ticker }} Fee </button> </div>
<div class="w-full md:w-auto p-1.5 mx-1"> <button type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 bg-blue-500 hover:bg-blue-600 font-medium text-lg lg:text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" name="estfee_{{ w.cid }}" value="Estimate Fee">Estimate {{ w.ticker }} Fee </button> </div>
{# / XMR | WOW #}
{% elif w.show_utxo_groups %}
{% else %}
<div class="w-full md:w-auto p-1.5 mx-1"> <button type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 bg-blue-500 hover:bg-blue-600 font-medium text-lg lg:text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" id="showutxogroups" name="showutxogroups" value="Show UTXO Groups"> {{ utxo_groups_svg | safe }} Show UTXO Groups </button> </div>
{% endif %}
{# / XMR | WOW #} <div class="w-full md:w-auto p-1.5 ml-2"> <button type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" name="withdraw_{{ w.cid }}" value="Withdraw" onclick="return confirmWithdrawal();">{{ withdraw_svg | safe }} Withdraw {{ w.ticker }} </div>
<div class="w-full md:w-auto p-1.5 mx-1"> <button type="submit" class="flex flex-wrap justify-center w-full px-4 py-2.5 bg-blue-500 hover:bg-blue-600 font-medium text-lg lg:text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" name="withdraw_{{ w.cid }}" value="Withdraw" onclick="return confirmWithdrawal();">{{ withdraw_svg | safe }} Withdraw {{ w.ticker }} </button></div>
</div>
</div>
</div>
@@ -807,42 +785,43 @@ document.addEventListener('DOMContentLoaded', function() {
</div>
</div>
</div>
</div>
</section>
{% if w.cid not in '6, 9' %}
{# !XMR | WOW #}
{% if w.show_utxo_groups %}
<section class="p-6">
<div class="lg:container mx-auto">
<div class="flex items-center">
<h4 class="font-semibold text-2xl text-black dark:text-white">UTXO Groups</h4>
</div>
</div>
</section>
<section>
<div class="pl-6 pr-6 pt-0 pb-0 h-full overflow-hidden">
<div class="px-6 py-0 h-full overflow-hidden">
<div class="border-coolGray-100">
<div class="flex flex-wrap items-center justify-between -m-2">
<div class="w-full pt-2">
<div class="container mt-5 mx-auto">
<div class="lg:container mt-5 mx-auto">
<div class="pt-6 pb-8 bg-coolGray-100 dark:bg-gray-500 rounded-xl">
<div class="px-6">
<div class="w-full mt-6 pb-6 overflow-x-auto">
<table class="w-full min-w-max text-sm">
<div class="w-full pb-6 overflow-x-auto">
<table class="w-full text-lg lg:text-sm">
<thead class="uppercase">
<tr class="text-left">
<th class="p-0">
<div class="py-3 px-6 rounded-tl-xl bg-coolGray-200 dark:bg-gray-600"> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold">Options</span> </div>
<div class="py-3 px-6 rounded-tl-xl bg-coolGray-200 dark:bg-gray-600"> <span class="text-md lg:text-xs text-gray-600 dark:text-gray-300 font-semibold">Options</span> </div>
</th>
<th class="p-0">
<div class="py-3 px-6 rounded-tr-xl bg-coolGray-200 dark:bg-gray-600"> <span class="text-xs text-gray-600 dark:text-gray-300 font-semibold p-10"></span> </div>
<div class="py-3 px-6 rounded-tr-xl bg-coolGray-200 dark:bg-gray-600"> <span class="text-md lg:text-xs text-gray-600 dark:text-gray-300 font-semibold p-10"></span> </div>
</th>
</tr>
</thead>
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6 w-1/4 bold">UTXO Groups:</td>
<td class="py-3 px-6"> <textarea class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-50 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" id="tx_view" rows="10" readonly>{{ w.utxo_groups }} </textarea> </td>
<td class="py-3 px-6"> <textarea class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-50 text-lg lg:text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" id="tx_view" rows="10" readonly>{{ w.utxo_groups }} </textarea> </td>
</tr>
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
<td class="py-3 px-6"> <button type="submit" class="flex flex-wrap justify-center px-4 py-2 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" id="create_utxo" name="create_utxo" value="Create UTXO" onclick="return confirmUTXOResize();"> {{ create_utxo_svg | safe }}Create UTXO </button> </td>
<td class="py-3 px-6"> <input placeholder="Amount" class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="text" name="utxo_value" value="{{ w.utxo_value }}"> </td>
<td class="py-3 px-6"> <button type="submit" class="flex flex-wrap justify-center px-4 py-2 bg-blue-500 hover:bg-blue-600 font-medium text-lg lg:text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" id="create_utxo" name="create_utxo" value="Create UTXO" onclick="return confirmUTXOResize();"> {{ create_utxo_svg | safe }}Create UTXO </button> </td>
<td class="py-3 px-6"> <input placeholder="Amount" class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-lg lg:text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" type="text" name="utxo_value" value="{{ w.utxo_value }}"> </td>
</tr>
</table>
</div>
@@ -855,14 +834,14 @@ document.addEventListener('DOMContentLoaded', function() {
</div>
</section>
<section>
<div class="pl-6 pr-6 pt-0 pb-0 h-full overflow-hidden ">
<div class="px-6 py-0 h-full overflow-hidden ">
<div class="pb-6 ">
<div class="flex flex-wrap items-center justify-between -m-2">
<div class="w-full pt-2">
<div class="container mx-auto">
<div class="pt-6 pb-6 bg-coolGray-100 border-t border-gray-100 dark:border-gray-400 dark:bg-gray-500 rounded-bl-xl rounded-br-xl">
<div class="lg:container mx-auto">
<div class="py-6 bg-coolGray-100 border-t border-gray-100 dark:border-gray-400 dark:bg-gray-500 rounded-bl-xl rounded-br-xl">
<div class="px-6">
<div class="flex flex-wrap justify-end"> <button type="submit" class="flex flex-wrap justify-center px-4 py-2.5 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" id="closeutxogroups" name="closeutxogroups" value="Close UTXO Groups"> {{ utxo_groups_svg | safe }} Close UTXO Groups </button> </div>
<div class="flex flex-wrap justify-end"> <button type="submit" class="flex flex-wrap justify-center px-4 py-2.5 bg-blue-500 hover:bg-blue-600 font-medium text-lg lg:text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" id="closeutxogroups" name="closeutxogroups" value="Close UTXO Groups"> {{ utxo_groups_svg | safe }} Close UTXO Groups </button> </div>
</div>
</div>
</div>
@@ -876,7 +855,6 @@ document.addEventListener('DOMContentLoaded', function() {
{% endif %}
{% endif %}
{% endif %}
{% endif %}
<input type="hidden" name="formid" value="{{ form_id }}">
</form>
<script>

View File

@@ -131,9 +131,9 @@ def parseOfferFormData(swap_client, form_data, page_data, options={}):
parsed_data["amt_bid_min"] < 0
or parsed_data["amt_bid_min"] > parsed_data["amt_from"]
):
errors.append("Minimum Bid Amount out of range")
errors.append("Minimum Purchase Quantity out of range")
except Exception:
errors.append("Minimum Bid Amount")
errors.append("Minimum Purchase Quantity")
if have_data_entry(form_data, "rate") and not have_data_entry(form_data, "amt_to"):
parsed_data["rate"] = ci_to.make_int(form_data["rate"], r=1)

View File

@@ -1,5 +1,5 @@
pyzmq==26.2.0
python-gnupg==0.5.3
python-gnupg==0.5.4
Jinja2==3.1.5
pycryptodome==3.21.0
PySocks==1.7.1

View File

@@ -190,9 +190,9 @@ pysocks==1.7.1 \
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0
# via -r requirements.in
python-gnupg==0.5.3 \
--hash=sha256:290d8ddb9cd63df96cfe9284b9b265f19fd6e145e5582dc58fd7271f026d0a47 \
--hash=sha256:2f8a4c6f63766feca6cc1416408f8b84e1b914fe7b54514e570fc5cbe92e9248
python-gnupg==0.5.4 \
--hash=sha256:40ce25cde9df29af91fe931ce9df3ce544e14a37f62b13ca878c897217b2de6c \
--hash=sha256:f2fdb5fb29615c77c2743e1cb3d9314353a6e87b10c37d238d91ae1c6feae086
# via -r requirements.in
pyzmq==26.2.0 \
--hash=sha256:007137c9ac9ad5ea21e6ad97d3489af654381324d5d3ba614c323f60dab8fae6 \

View File

@@ -31,7 +31,7 @@ Create offers
# Optional
"enabled": Set to false to ignore offer template.
"swap_type": Type of swap, defaults to "adaptor_sig"
"min_swap_amount": Sets "amt_bid_min" on the offer, minimum valid bid when offer amount is variable.
"min_swap_amount": Sets "amt_bid_min" on the offer, minimum purchase quantity when offer amount is variable.
"amount_step": If set offers will be created for amount values between "amount" and "min_coin_from_amt" in decrements of "amount_step".
},
...